A.N.A.L.O.G. ISSUE 54 / MAY 1987 / PAGE 44

T:EDIT

A sweet little text editor.

by Bryan Schappel

Well, someone had to do it. Someone had to write a text editor for the 8-bit Atari, one you could type in and get a lot of use out of … and that someone was me.

In the last few years, quite a few compiled languages have become available for the 8-bit Atari. Some of these are Deep Blue C, Kyan Pascal, Draper Pascal, and DVC/65. All these programs require you to create your source code with a text editor, load the compiler, compile the source code, and go back to the editor to fix your mistakes. If you’re like me, the only text editor you have is AtariWriter. That means you have to plug in the cartridge, boot up, edit your text, save it, remove the cartridge, load the compiler, and so on. Not only is this process tedious and time consuming, it also puts plenty of wear and tear on your computer.

I bet you thought, “Gee, it sure would be nice to have a little text editor that you could binary load from DOS, do a little editing and, with the touch of two keys, pop back into DOS again. That would certainly make life a lot easier.”

Well, I thought so, too. And, as I thought these sick thoughts, my mind kept screaming, “Why don’t you write a text editor?” So I did. I now offer you T:EDIT (short for Text EDITor).

Some of the things my mind told me T:EDIT must do were… (1) this editor must be a full-scrolling screen editor like those other fancy editors; (2) it had better have a lot of commands, or else; and, finally, (3) it has to he easy to use. So, to appease my mind, I made T:EDIT do all these things and a little more.

Typing it in.

Listing 1 is the BASIC data used to create the TEDIT.COM file. For those of our readers interested in the assembly language source code of this program, the listing is available on the disk version of this magazine, or on the ANALOG Computing Atari Users’ Group SIG on the Delphi network.

Please refer to M/L Editor on page 10 for typing instructions. When you’ve typed the listing, the resultant file should be named TEDIT.COM.

To use T:EDIT, after creating the TEDIT.COM file, simply turn your computer off, remove all cartridges (on XL and XE computers, hold down OPTION while booting up) and follow these loading instructions.

If you’re using ATARI DOS 2.0S, type L and RETURN, then type TEDIT.COM and RETURN. T:EDIT will load and run automatically.

From OSS OS/A+ DOS or from SpartaDOS, simply type TEDIT and hit RETURN. The program will load and run automatically.

The program resides in cartridge slot A memory locations ($A000-$BFFF) and uses addresses $BC00-$BFFF as screen memory. This was done to allow the maximum amount of text space on a 48K Atari. The amount of free space varies on each computer and with each DOS. With SpartaDOS version 2.3e, you get 37120 bytes of text space.

Table 1.—The commands.

TEXT COMMANDS
KeyFunction
^LLoad a text file
^SSave a text file
^PPrint a text file
^MPrint to any device
^XDisk directory
^FGlobal search and replace
^CErase text in memory
^IToggle insert mode
^OShow “false” spaces
^EErase spaces
^KChange char case (^CAPS)
^RReverse two characters
^QQuit T:EDIT and enter DOS
^NCount w/ords in text
TABInsert five spaces
DSDelete back one character
^DSDelete one character
A>Insert one space
SH>Insert 255 spaces
SHDSDelete 1 screen line
CURSOR CONTROLS
KeyFunction
^+Move 1 character to left
^*Move 1 character to right
^-Move up one screen line
^=Move down one screen line
^TJump to top of text
^BJump to bottom of text
^AJump to beginning of line
^ZJump to end of line
^WJump one word to the right
^UJump up 1 screen of text
^DJump down 1 screen of text
^HHome cursor to upper left

The screen editor.

T:EDIT is a screen-oriented text editor, very much like AtariWriter. Because it’s screen oriented, T:EDIT gives you a very natural programming environment. The screen editor in T:EDIT uses a word-wrap routine, so that none of the words will be broken on the right margin. This method is similar to that of most word processing packages, and makes the screen much easier for the user to read and comprehend.

The editing screen is twenty lines high and thirty-eight characters across. There are three lines at the bottom of the screen used to display information and ask for input. The first of the three lines is the cursor line. It contains the row and column position of the cursor on the editing screen, and the number of free bytes left for new text. The two following lines are the input/output lines used to display messages.

You may enter almost any character you wish into your document, except a few. No control characters are permitted, as they’re reserved for commands; CTRL-COMMA, CTRL-PERIOD, CTRL-SEMICOLON and CTRL-CLEAR are not allowed. Uppercase, lowercase and all inverse video keys are allowed.

If you must insert any control characters into your text, you can do so by pressing SELECT and the key you want as a control. This method will only work for letters, such as CTRL-A. While in the editor, all control characters appear in a “tech-computer” font; these are larger and easy to distinguish from normal text.

Command description.

To use one of the commands in Table 1, simply type the correct key combination, given under the heading Key. In the table, the ^ character indicates that the CONTROL key is pressed with the letter after the ^. SH indicates that you press and hold SHIFT; DS stands for DELETE-BACKSPACE key; and < and > are the CLEAR and INSERT keys, respectively.

Before I describe all the commands, I’d like to tell you how to abort most. With any command that asks you for keyboard input, simply press the ESC key. The command will abort, and you can continue to edit your text. Some commands will ask you, Are you sure - Y/N? The only key that will give a yes response is Y key; any other key is taken as a no.

Load a text file (^L). This command allows you to load any standard ATASCII text file into memory. You’ll be prompted for a filename, and, after you enter this, the current text file will be erased and the new file loaded. Once the loading begins, all text in memory is lost forever. If the load was successful you can edit the file. Otherwise, the message LOAD FILE ERROR will appear, and you must press a key to continue.

Save a text file (^S). This command permits you to save the text in memory to disk. You’re asked for a filename, then the save begins. If the save is successful, you can continue to edit text; otherwise, the message SAVE FILE ERROR will appear, and you must press a key to continue to edit your text. This command will overwrite a disk file if it already exists, so be sure you’ve typed the correct filename.

Print a text file (^P). This command will print the file in memory to your printer, in 80-column format. If your printer’s not on-line, the message PRINTER ERROR will appear at the bottom of the screen, and you must press a key to continue editing. Pressing BREAK during printing will halt the printing and force a PRINTER ERROR. The print function will produce formatted output with no broken words on the right margin. It will skip the perforations between pages and number each page in the upper left-hand corner.

The print function will work on any 80-column printer, since it doesn’t send any control codes to the printer. Because of this, you must have the paper at the top of form before you start printing, or else the page breaks won’t be in the right places. If the end of text is reached before the end of a page, the print function will form feed to the top of the next page for you.

Since you can load any text file into T:EDIT, the print routine must be able to print anything. If you load a file from AtariWriter into T:EDIT it’s embedded with various control characters having some meaning to AtariWriter—but none to T:EDIT. So the print routine will simply print all control characters as inverse uppercase characters. On most printers, these characters will come out as italics.

Print to Device (^M). This function is exactly the same as the print command, except that the text may be sent to any Atari device (barring only the E: and S: devices). This is an extremely powerful feature, allowing one to make formatted disk files of text for uploading to the Delphi Atari User’s Group. These files can then be downloaded and printed to any 80-column printer, with the DOS copy function.

Disk Directory (^X). When you select this command, you are asked: DIRECTORY FOR DRIVE - [1-2-3-4-8]? Respond by typing one of the numbers in the brackets (pressing any other key will abort). Then the screen will clear, and the directory of the chosen drive will be printed to the screen in two-column format.

If the directory’s longer than one screen, the message DIRECTORY PAUSED - PRESS A KEY will appear. Simply press any key (ESC to abort), and the screen will clear. The remaining portion of the directory will be displayed.

When the end of the directory is reached, the message DIRECTORY FINISHED - PRESS A KEY will appear Just press a key to continue to edit your text.

If you attempt to get a directory from a drive that doesn’t exist—or you press BREAK while the directory’s being read, or you have no disk in the drive—you’ll get a DIRECTORY ERROR. When you get this error, simply press any key to continue editing your text.

Global Search and Replace (^F). When this is executed, you’re asked FIND WHAT? Respond with a string up to twenty-four characters in length and press RETURN. If the program finds the string, the screen will move to the beginning of the string, and the string’s first character will be highlighted in inverse video. Then you’re asked REPLACE STRING - Y/N? If you wish to do so, respond by pressing Y; otherwise, hit any other key to abort. If you pressed Y, you’re asked REP. WITH? Type in your replacement string, up to twenty-four characters, and press RETURN. The program will then begin to replace all occurrences of the search string. Once a replace starts, it can’t be stopped until it ends, so be careful. The search/replace will begin at the current cursor position and continue until the end of text is reached.

Erase text in memory (^C). This command will wipe out text currently in memory. You’re asked if you’re sure about the erase. If you say yes, the document in memory is erased and you may enter a new one. Once text is erased, you can’t recover it.

Toggle Insert Mode (^I). T:EDIT has two modes of operation, “replace” and “insert.” Replace is the default mode. The insert mode is useful, but can get very slow if you’re inserting at the top of a long document. To tell which mode you’re in, the cursor line will be blue for replace mode and red for insert mode.

Show “false” spaces (^O). Pressing this key will cause any space used to word wrap the screen to appear as a small dot. Pressing it again will make all “false” spaces blanks again. This is a very useful command. It shows you which spaces are yours and which are generated for the word wrap’s sake.

Erase spaces (^E). This function will erase all spaces, from the cursor to the next non-space character. You’ll see the use of this command later.

Change character case (^K or ^CAPS key). Pressing this key will cause the character under the cursor to be changed to uppercase if it was in lowercase, and vice versa. After this command executes, the cursor moves one character to the right.

Reverse two characters (^R). This command is for all the people out there who just love to make transposition errors. When you use it, the character under the cursor will be swapped with the character to the right of the cursor

Quit T:EDIT (^Q). This command will exit you back to DOS. It will also erase your text, so you’re asked if you’re sure. If you answer yes, you’ll go to DOS. To re-enter T:EDIT from Atari DOS 2.0S, you can either reload it or perform a RUN AT ADDRESS, with the address being 9FFD. From OSS OS/A+ or from SpartaDOS, typing RUN or RUN 9FFD at the D1: prompt will restart T:EDIT.

Count Words in text (^N). When you press ^N, T:EDIT will count all the words in your text and display the number on the first I/O line at the bottom of the screen. This is a true word count, not faked by counting spaces and dividing by two, hence it’s accurate to within one word of the actual number of words in memory. When the program is through counting, you’re asked to press a key. Do so and you may edit more text.

Insert five spaces (TAB). Pressing the TAB key will insert five spaces into the text at the cursor position (not tab across the screen). This can be useful if you’re in replace mode and want some space to insert a new word. The program can insert five spaces in the same amount of time it can insert one space, so this can be quite a time saver.

Delete back one character (DS). Pressing DELETE-BACKSPACE will delete the character to the left of the cursor and move the rest of the document up. Again, this can be slow with large documents.

Delete one character (^DS). This deletes the character under the cursor and moves the rest of the document up.

Insert one space (^>). This will move the document down and insert a space under the cursor.

Insert 255 spaces (SH-). If you must have a lot of room for new revisions, this is how you get it. The command will insert 255 spaces from the cursor’s position—in the time it takes to insert one space. If you find that you don’t need all this space, simply press ^E to remove the remaining spaces.

Delete one screen line (SHDS). This will delete text from the cursor position to the end of the line the cursor’s sitting on. Usually, this is anywhere between one and twenty characters.

A note about deleting text: text deleted is lost forever. Since the deletions are usually rather small, this doesn’t cause too many problems. However, care should be taken before deleting anything.

Cursor movement.

T:EDIT uses the arrow keys (^+, ^*, ^-, ^=) to move the cursor around the screen, much like the normal screen editor—with a few variations.

If you’re at the bottom of the screen and try to go further down, a new line of text will appear. The same goes for trying to cursor off the top of the screen. If you try to go past the left margin, you wind up on the last character of the previous line. If you cursor past the last character on a line, the cursor is placed on the first character of the next line. There are other ways to move the cursor around within the document.

Jump to TOP of text (^T). This will place the cursor at the top of your text. The cursor is also in the “home” position. (The home position is the upper left corner of the screen).

Jump to BOTTOM of text (^B). This will move the cursor to the end of the document. It’s placed after the last character in the document.

Moving on the line (^A, ^Z). ^A will place the cursor on the first character on the screen line. ^Z will place the cursor on the last.

Jump one word to the right (^W). This will move the cursor to the next word in the document. The command was included as a replacement for the TAB fimction.

Moving by screenfuls (^U, ^D). Pressing ^U will send the cursor home and move it back nineteen lines of text. Pressing ^D will move the cursor home, then bring it forward nineteen lines.

Homing the cursor (^H). ^H will move the cursor to the home position.

That finishes up the commands for T:EDIT. Now we’ll look at some of the program’s technical aspects.

Entering filenames.

T:EDIT allows you to load or save text from any disk drive or device. When you select either SAVE or LOAD, you’re asked for a filename. You can respond in many ways. Here are some examples:

  1. filename.ext RETURN
  2. d2:filename.ext RETURN
  3. C: RETURN
  4. E:filename.ext

In example (1), you simply enter a filename. T:EDIT will default to using drive 1 as the device. In (2), you specified drive number and filename; therefore, T:EDIT will use this device and name. In (3), we specified the device as the cassette drive. In (4), we tried to load/save text to the screen editor. If you try this to either the E: or S: devices, T:EDIT defaults to the D: device. This makes T:EDIT extremely powerful. So, if you want a simple rough text printout, just save it to the printer (P:). You won’t get any page breaks or page numbers, but it can be useful.

T:EDIT has a smart filename handler. If your filename has any lowercase, control or inverse characters, they’ll all be converted to normal video uppercase characters. Since you may enter up to twenty-four characters for a filename, the program can access text files stored in subdirectories with SpartaDOS or MYDOS version 4.0, thus making T:EDIT easier to use.

Technical notes.

The program uses a custom display list and display list interrupts (DLIs) to produce an attractive screen. The blinking underline used for the cursor was quite a little task to code.

The cursor works this way:

  1. We figure out which character’s under the cursor and copy its definition to another character (in this case, character 127).
  2. Then we replace the character under the cursor with character 127.
  3. Now, simply blink the eighth bit in character 127 with an EOR #$FF. By doing this, you get a nice little cursor that looks really neat on a character with a descender, like a y or g.

All the text is stored in memory in internal code, for speed. If we store all text in internal code, there’s no time needed to convert a screenful of text each time we redraw the screen. When text is saved, it’s saved in ATASCII.

You’ll notice that the DLIs don’t flicker during I/O operations. This is because the immediate mode vertical blank is used to copy the screen color shadow registers into their corresponding hardware registers.

I’ve found T:EDIT a very useful utility to have around. I hope you get as much use from it as I have.


Bryan Schappel is a Computer Science major at the University of Wisconsin. He’s been programming the Atari for four years. Besides writing programs, his main computer interests are word processing and data management.

Listing 1.
M/L Editor data.

1000 DATA 255,255,253,159,133,183,76,103,180,0,0,0,0,0,0,0,7899
1010 DATA 0,0,24,24,24,24,0,24,0,0,102,102,102,0,0,0,5306
1020 DATA 0,0,102,255,102,102,255,102,0,24,62,96,60,6,124,24,1251
1030 DATA 0,0,102,108,24,48,102,70,0,28,54,28,56,111,102,59,9416
1040 DATA 0,0,24,24,24,0,0,0,0,0,14,28,24,24,28,14,3110
1050 DATA 0,0,112,56,24,24,56,112,0,0,102,60,255,60,102,0,689
1060 DATA 0,0,24,24,126,24,24,0,0,0,0,0,0,0,24,24,2914
1070 DATA 48,0,0,0,126,0,0,0,0,0,0,0,0,0,24,24,2492
1080 DATA 0,0,6,12,24,48,96,64,0,0,60,102,110,118,102,60,194
1090 DATA 0,0,24,56,24,24,24,126,0,0,60,102,12,24,48,126,7938
1100 DATA 0,0,126,12,24,12,102,60,0,0,12,28,60,108,126,12,7754
1110 DATA 0,0,126,96,124,6,102,60,0,0,60,96,124,102,102,60,1064
1120 DATA 0,0,126,6,12,24,48,48,0,0,60,102,60,102,102,60,9028
1130 DATA 0,0,60,102,62,6,12,56,0,0,0,24,24,0,24,24,3940
1140 DATA 0,0,0,24,24,0,24,24,48,6,12,24,48,24,12,6,3864
1150 DATA 0,0,0,126,0,0,126,0,0,96,48,24,12,24,48,96,7060
1160 DATA 0,0,60,102,12,24,0,24,0,0,60,102,110,110,96,62,9430
1170 DATA 0,0,24,60,102,102,126,102,0,0,124,102,124,102,102,124,3444
1180 DATA 0,0,60,102,96,96,102,60,0,0,120,108,102,102,108,120,2928
1190 DATA 0,0,126,96,124,96,96,126,0,0,126,96,124,96,96,96,3298
1200 DATA 0,0,62,96,96,110,102,62,0,0,102,102,126,102,102,102,2694
1210 DATA 0,0,126,24,24,24,24,126,0,0,6,6,6,6,102,60,5914
1220 DATA 0,0,102,108,120,120,108,102,0,0,96,96,96,96,96,126,3106
1230 DATA 0,0,99,119,127,107,99,99,0,0,102,118,126,126,110,102,3987
1240 DATA 0,0,60,102,102,102,102,60,0,0,124,102,102,124,96,96,2770
1250 DATA 0,0,60,102,102,102,108,54,0,0,124,102,102,124,108,102,3050
1260 DATA 0,0,60,96,60,6,6,60,0,0,126,24,24,24,24,24,5748
1270 DATA 0,0,102,102,102,102,102,126,0,0,102,102,102,102,60,24,1212
1280 DATA 0,0,99,99,107,127,119,99,0,0,102,102,60,60,102,102,2023
1290 DATA 0,0,102,102,60,24,24,24,0,0,126,12,24,48,96,126,8778
1300 DATA 0,0,30,24,24,24,24,30,0,0,64,96,48,24,12,6,5250
1310 DATA 0,0,120,24,24,24,24,120,0,0,8,28,54,99,0,0,5670
1320 DATA 0,0,0,0,0,0,0,255,0,0,0,0,0,0,0,0,3360
1330 DATA 0,63,51,51,127,115,115,115,0,126,102,102,127,103,103,127,5139
1340 DATA 0,127,103,103,96,99,99,127,0,126,102,102,119,119,119,127,5734
1350 DATA 0,127,96,96,127,112,112,127,0,127,96,96,127,112,112,112,5552
1360 DATA 0,127,99,96,111,103,103,127,0,115,115,115,127,115,115,115,5826
1370 DATA 0,12,12,12,12,60,60,60,0,12,12,12,14,14,110,126,7238
1380 DATA 0,102,102,108,127,103,103,103,0,48,48,48,112,112,112,126,3424
1390 DATA 0,103,127,127,119,103,103,103,0,103,119,127,111,103,103,103,5184
1400 DATA 0,127,99,99,103,103,103,127,0,127,99,99,127,112,112,112,5455
1410 DATA 0,127,99,99,103,103,103,127,7,126,102,102,127,119,119,119,5902
1420 DATA 0,127,96,127,3,115,115,127,0,127,28,28,28,28,28,28,8534
1430 DATA 0,103,103,103,103,103,103,127,0,103,103,103,103,111,62,28,2897
1440 DATA 0,103,103,103,111,127,127,103,0,115,115,115,62,103,103,103,4633
1450 DATA 0,103,103,103,127,28,28,28,0,127,102,108,24,55,103,127,1947
1460 DATA 0,0,0,0,0,0,0,0,0,0,24,60,126,24,24,24,5162
1470 DATA 0,0,24,24,24,126,60,24,0,0,24,48,126,48,24,0,6636
1480 DATA 0,0,24,12,126,12,24,0,0,255,231,207,129,207,231,255,2165
1490 DATA 0,0,0,60,6,62,102,62,0,0,96,96,124,102,102,124,2104
1500 DATA 0,0,0,60,96,96,96,60,0,0,6,6,62,102,102,62,8842
1510 DATA 0,0,0,60,102,126,96,60,0,0,14,24,62,24,24,24,6496
1520 DATA 0,0,0,62,102,102,62,6,124,0,96,96,124,102,102,102,2898
1530 DATA 0,0,24,0,56,24,24,60,0,0,6,0,6,6,6,6,3088
1540 DATA 60,0,96,96,108,120,108,102,0,0,56,24,24,24,24,60,7976
1550 DATA 0,0,0,102,127,127,107,99,0,0,0,124,102,102,102,102,2300
1560 DATA 0,0,0,60,102,102,102,60,0,0,0,124,102,102,124,96,1754
1570 DATA 96,0,0,62,102,102,62,6,6,0,0,124,102,96,96,96,706
1580 DATA 0,0,0,62,96,60,6,124,0,0,24,126,24,24,24,14,6710
1590 DATA 0,0,0,102,102,102,102,62,0,0,0,102,102,102,60,24,9592
1600 DATA 0,0,0,99,107,127,62,54,0,0,0,102,60,24,60,102,9031
1610 DATA 0,0,0,102,102,102,62,12,120,0,0,126,12,24,48,126,9490
1620 DATA 0,0,0,0,0,0,0,0,0,24,24,24,24,24,24,24,3804
1630 DATA 24,0,96,112,124,124,112,96,0,0,0,0,0,0,0,0,5306
1640 DATA 0,0,0,0,0,0,0,0,0,112,112,112,66,0,188,2,9046
1650 DATA 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,1922
1660 DATA 2,2,176,194,35,164,16,2,2,65,0,164,0,0,0,0,6893
1670 DATA 35,47,44,26,0,16,18,0,0,0,50,47,55,26,0,16,4706
1680 DATA 16,0,0,0,38,50,37,37,26,0,16,16,16,16,16,0,4015
1690 DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1690
1700 DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1700
1710 DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1710
1720 DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1720
1730 DATA 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1730
1740 DATA 0,0,0,0,255,254,253,159,158,157,156,155,127,126,125,31,9936
1750 DATA 30,29,28,27,64,0,32,96,32,64,0,96,144,2,76,79,9726
1760 DATA 65,68,32,70,73,76,69,58,155,83,65,86,69,32,70,73,1640
1770 DATA 76,69,58,155,80,82,73,78,84,32,68,69,86,58,155,70,2832
1780 DATA 73,78,68,32,87,72,65,84,63,155,82,69,80,46,32,87,1738
1790 DATA 73,84,72,58,155,68,73,82,69,67,84,79,82,89,32,70,1904
1800 DATA 79,82,32,68,82,73,86,69,32,91,49,45,50,45,51,45,9455
1810 DATA 52,45,56,93,63,155,68,73,82,69,67,84,79,82,89,32,1992
1820 DATA 80,65,85,83,69,68,32,45,32,80,82,69,83,83,32,65,533
1830 DATA 32,75,69,89,155,68,73,82,69,67,84,79,82,89,32,70,2000
1840 DATA 73,78,73,83,72,69,68,32,45,32,80,82,69,83,83,32,531
1850 DATA 65,32,75,69,89,155,68,73,82,69,67,84,79,82,89,32,2110
1860 DATA 69,82,82,79,82,155,82,69,80,76,65,67,69,32,83,84,2054
1870 DATA 82,73,78,71,32,45,32,89,47,78,63,155,81,85,73,84,2420
1880 DATA 32,69,68,73,84,79,82,155,69,82,65,83,69,32,77,69,2010
1890 DATA 77,79,82,89,155,80,82,73,78,84,32,84,69,88,84,155,3911
1900 DATA 83,65,86,69,32,73,47,79,32,69,82,82,79,82,155,76,2786
1910 DATA 79,65,68,32,73,47,79,32,69,82,82,79,82,155,80,82,2946
1920 DATA 73,78,84,69,82,32,69,82,82,79,82,155,80,97,103,101,4267
1930 DATA 32,35,32,32,32,32,155,33,50,37,0,57,47,53,0,51,7630
1940 DATA 53,50,37,0,13,0,57,15,46,31,87,79,82,68,32,67,8987
1950 DATA 79,85,78,84,58,32,48,48,48,48,48,155,69,58,155,80,2585
1960 DATA 58,155,49,50,51,52,56,68,49,58,68,49,58,42,46,42,9239
1970 DATA 155,5,84,26,69,68,73,84,0,13,0,97,0,48,114,111,9879
1980 DATA 103,114,97,109,0,52,101,120,116,0,37,100,105,116,111,114,4146
1990 DATA 255,255,14,55,114,105,116,116,101,110,0,34,121,26,255,255,8216
2000 DATA 11,34,114,121,97,110,0,48,14,0,51,99,104,97,112,112,2491
2010 DATA 101,108,255,255,7,8,99,9,0,17,25,24,22,0,65,78,8202
2020 DATA 65,76,79,71,0,35,111,109,112,117,116,105,110,103,255,255,108
2030 DATA 12,13,0,48,114,101,115,115,0,97,0,43,101,121,0,13,9862
2040 DATA 253,0,96,123,125,12,19,20,2,21,4,3,16,17,126,28,7155
2050 DATA 29,30,31,254,255,1,23,26,18,157,127,15,8,9,156,5,857
2060 DATA 6,11,24,14,13,237,169,233,168,218,168,176,170,194,173,252,5955
2070 DATA 172,54,168,90,169,137,168,62,172,116,173,49,173,38,172,29,7577
2080 DATA 172,49,172,42,171,100,170,119,170,199,170,228,170,61,171,67,1458
2090 DATA 171,243,172,212,170,221,170,220,173,52,174,156,174,210,175,119,4831
2100 DATA 178,96,176,64,169,160,0,152,153,0,188,153,0,189,153,0,6497
2110 DATA 190,200,208,244,160,31,153,0,191,136,16,250,96,160,79,169,9989
2120 DATA 0,153,75,164,136,16,250,96,160,39,208,243,160,39,169,0,8796
2130 DATA 153,115,164,136,16,250,96,141,26,167,140,27,167,32,255,166,9797
2140 DATA 160,0,185,255,255,201,155,240,9,32,71,180,153,77,164,200,1430
2150 DATA 208,240,96,173,252,2,201,255,240,249,162,255,142,252,2,133,5561
2160 DATA 146,162,126,72,142,31,208,173,11,212,205,11,212,240,251,202,4751
2170 DATA 202,16,241,104,168,192,192,144,2,160,154,177,121,133,147,201,2323
2180 DATA 128,240,208,201,129,208,9,165,148,73,128,133,148,76,42,167,8848
2190 DATA 201,130,208,9,165,149,73,64,133,149,76,42,167,201,131,208,358
2200 DATA 6,169,64,133,149,208,172,201,132,208,5,169,11,133,147,96,9170
2210 DATA 201,133,240,159,165,146,201,64,176,19,165,147,201,97,144,13,9345
2220 DATA 201,123,176,9,165,149,240,5,5,146,76,75,167,162,15,189,7599
2230 DATA 155,164,197,147,240,3,202,16,246,240,4,165,147,69,148,133,515
2240 DATA 147,96,164,128,200,132,158,32,229,182,173,250,183,141,44,164,3158
2250 DATA 173,251,183,141,45,164,165,129,133,158,32,229,182,173,250,183,4777
2260 DATA 141,54,164,173,251,183,141,55,164,76,98,228,72,138,72,166,127
2270 DATA 151,208,8,165,175,240,4,169,66,208,3,189,179,164,141,10,9089
2280 DATA 212,141,24,208,230,151,104,170,104,64,169,0,133,151,160,3,7548
2290 DATA 185,196,2,153,22,208,136,16,247,165,170,208,31,230,138,165,2495
2300 DATA 138,201,16,208,12,173,255,163,73,255,141,255,163,169,0,133,2338
2310 DATA 138,165,172,240,7,164,171,169,63,153,88,164,76,95,228,165,1233
2320 DATA 141,240,12,169,127,160,165,32,14,167,32,97,168,144,1,96,5722
2330 DATA 160,0,132,141,132,144,200,132,129,132,128,32,220,166,172,232,3179
2340 DATA 2,200,132,145,32,244,170,76,244,166,32,3,167,160,18,185,9025
2350 DATA 206,165,153,117,164,136,16,247,32,42,167,41,127,201,91,144,8708
2360 DATA 3,56,233,32,201,89,240,5,32,244,166,56,96,32,244,166,9799
2370 DATA 24,96,169,115,160,165,32,14,167,32,97,168,144,3,76,244,7543
2380 DATA 166,104,104,169,7,160,98,162,228,32,92,228,169,6,160,95,9040
2390 DATA 162,228,32,92,228,169,64,141,14,212,162,0,169,12,141,66,6766
2400 DATA 3,32,86,228,162,0,169,3,141,66,3,169,12,141,74,3,2932
2410 DATA 142,75,3,169,243,141,68,3,169,165,141,69,3,32,86,228,6923
2420 DATA 108,10,0,165,144,133,139,133,152,165,145,133,140,133,153,76,165
2430 DATA 77,179,165,141,208,1,96,169,192,160,164,32,14,167,32,181,8406
2440 DATA 177,32,155,172,169,8,133,173,32,240,176,48,42,162,16,165,7936
2450 DATA 144,157,68,3,165,145,157,69,3,56,165,134,229,144,157,72,8980
2460 DATA 3,165,135,229,145,157,73,3,169,11,32,4,178,48,8,32,1965
2470 DATA 19,177,198,170,76,161,172,169,151,160,165,32,14,167,32,19,6481
2480 DATA 177,32,42,167,198,170,76,161,172,165,141,208,1,96,169,203,1730
2490 DATA 160,164,32,14,167,32,181,177,169,8,133,173,32,240,176,48,9164
2500 DATA 23,16,37,165,141,240,32,169,140,160,165,32,14,167,32,97,6658
2510 DATA 168,176,20,32,29,177,16,16,32,19,177,169,181,160,165,32,6698
2520 DATA 14,167,198,170,76,42,167,96,169,1,133,196,165,144,133,136,389
2530 DATA 165,145,133,137,32,75,178,48,223,165,196,133,158,32,229,182,2430
2540 DATA 173,252,183,24,105,32,141,202,165,173,250,183,24,105,32,141,9861
2550 DATA 203,165,173,251,183,24,105,32,141,204,165,160,0,132,157,185,863
2560 DATA 195,165,153,159,183,201,155,240,3,200,208,243,32,83,178,48,1553
2570 DATA 167,32,75,178,48,162,32,233,175,48,157,165,197,201,255,240,5840
2580 DATA 6,165,157,208,241,240,173,165,157,240,6,32,75,178,76,222,1817
2590 DATA 169,198,170,76,19,177,169,181,160,164,32,14,167,32,181,177,9523
2600 DATA 169,4,133,173,32,240,176,48,81,32,244,170,162,16,165,142,9934
2610 DATA 157,72,3,165,143,157,73,3,169,7,32,4,178,48,59,162,4226
2620 DATA 16,189,72,3,56,233,1,157,72,3,189,73,3,233,0,157,5629
2630 DATA 73,3,165,144,125,72,3,133,134,133,136,165,145,125,73,3,6712
2640 DATA 133,135,133,137,32,19,177,230,141,198,170,160,1,169,0,145,9081
2650 DATA 136,200,208,251,32,161,172,76,77,179,192,136,240,193,32,19,585
2660 DATA 177,169,166,160,165,32,14,167,198,170,76,42,167,166,128,202,1233
2670 DATA 134,130,165,139,56,229,130,133,139,165,140,233,0,133,140,96,478
2680 DATA 160,0,177,139,240,8,201,96,240,4,200,208,245,96,200,208,5103
2690 DATA 10,230,140,165,140,197,135,144,2,208,19,177,139,240,239,24,1786
2700 DATA 152,101,139,133,139,165,140,105,0,133,140,76,225,181,165,134,1368
2710 DATA 133,139,165,135,133,140,76,225,181,169,0,133,152,165,135,56,115
2720 DATA 233,4,197,145,176,2,165,145,133,153,32,77,179,76,165,170,9928
2730 DATA 32,100,170,166,129,189,133,183,168,136,76,150,170,165,152,133,2746
2740 DATA 139,165,153,133,140,96,165,175,73,1,133,175,96,160,0,177,8581
2750 DATA 139,72,200,177,139,136,145,139,200,104,145,139,96,165,144,133,1928
2760 DATA 136,133,152,133,139,133,134,165,145,133,137,133,153,133,140,133,1718
2770 DATA 135,56,169,159,229,145,133,143,170,169,0,133,142,160,255,198,4145
2780 DATA 137,145,136,200,230,137,145,136,200,208,251,230,137,202,208,246,9556
2790 DATA 145,136,96,169,1,133,176,169,0,133,177,32,101,171,169,0,7461
2800 DATA 168,145,139,76,225,181,169,255,133,176,208,15,169,5,133,176,1916
2810 DATA 32,82,171,177,139,208,1,200,76,150,170,169,0,133,177,32,8888
2820 DATA 101,171,169,0,168,166,176,145,139,200,202,208,250,96,24,165,3561
2830 DATA 134,101,176,165,135,101,177,201,159,144,3,104,104,96,24,165,8330
2840 DATA 139,133,178,101,176,133,180,165,140,133,179,101,177,133,181,56,1986
2850 DATA 165,134,229,178,133,182,165,135,229,179,133,183,32,164,171,24,1845
2860 DATA 165,134,101,176,133,134,165,135,101,177,133,135,96,165,183,170,2789
2870 DATA 5,182,208,1,96,24,138,101,179,141,207,171,165,178,141,206,3663
2880 DATA 171,24,138,101,181,141,210,171,165,180,141,209,171,232,164,182,6693
2890 DATA 208,4,240,13,160,255,185,255,255,153,255,255,136,192,255,208,842
2900 DATA 245,206,207,171,206,210,171,202,208,234,96,165,178,141,1,172,4268
2910 DATA 165,179,141,2,172,165,180,141,4,172,165,181,141,5,172,166,984
2920 DATA 183,240,30,169,0,133,184,160,0,185,255,255,153,255,255,200,8014
2930 DATA 196,184,208,245,238,2,172,238,5,172,224,0,240,7,202,208,3213
2940 DATA 226,165,182,208,224,96,230,139,208,2,230,140,76,225,181,165,4887
2950 DATA 139,208,2,198,140,198,139,76,225,181,32,29,172,32,71,172,8808
2960 DATA 32,38,172,32,98,172,96,32,71,172,32,38,172,76,98,172,6851
2970 DATA 56,165,139,229,144,133,130,165,140,229,145,5,130,208,3,104,9953
2980 DATA 104,96,165,139,133,178,165,140,133,179,96,56,165,139,133,180,2016
2990 DATA 73,255,101,178,133,188,165,140,133,181,73,255,101,179,133,189,4364
3000 DATA 56,165,134,229,180,133,182,165,135,229,181,133,183,230,182,208,7745
3010 DATA 2,230,183,32,226,171,165,134,56,229,188,133,134,165,135,229,4731
3020 DATA 189,133,135,96,169,0,133,190,240,4,169,128,133,190,165,144,2323
3030 DATA 133,136,165,145,133,137,56,165,135,229,137,170,232,160,0,177,2849
3040 DATA 136,72,165,190,240,23,104,201,155,208,4,169,96,208,34,201,1682
3050 DATA 127,208,4,169,125,208,26,32,71,180,76,232,172,104,201,96,894
3060 DATA 208,4,169,155,208,11,201,125,208,4,169,127,208,3,32,80,7717
3070 DATA 180,145,136,200,208,201,230,137,202,208,196,96,173,4,162,73,2809
3080 DATA 16,141,4,162,96,32,212,170,160,0,165,152,24,121,134,183,9577
3090 DATA 133,152,133,139,165,153,105,0,133,153,133,140,200,192,19,208,1731
3100 DATA 233,165,135,197,140,144,10,240,2,176,9,165,134,197,139,144,1156
3110 DATA 3,76,176,170,32,77,179,76,225,181,32,100,170,166,129,165,1452
3120 DATA 139,24,125,133,183,133,139,165,140,105,0,133,140,224,20,208,710
3130 DATA 30,138,72,165,128,72,165,152,24,109,134,183,133,152,165,153,1511
3140 DATA 105,0,133,153,32,77,179,104,133,128,104,133,129,162,19,189,9434
3150 DATA 134,183,197,128,144,2,165,128,168,136,76,150,170,32,100,170,50
3160 DATA 166,129,224,1,240,19,202,202,165,139,56,253,134,183,133,139,3654
3170 DATA 165,140,233,0,133,140,76,102,173,32,166,173,166,139,134,152,1492
3180 DATA 166,140,134,153,197,128,144,2,165,128,168,136,76,150,170,32,9812
3190 DATA 212,170,32,242,179,132,130,192,255,208,1,96,165,139,56,229,3072
3200 DATA 130,133,139,165,140,233,0,133,140,152,96,169,0,133,157,32,8428
3210 DATA 166,173,165,139,133,152,165,140,133,153,230,157,165,157,201,19,3428
3220 DATA 208,237,76,225,181,32,2,174,32,199,170,165,191,56,229,134,2507
3230 DATA 133,130,165,192,229,135,5,130,176,56,165,139,56,229,134,133,1615
3240 DATA 130,165,140,229,135,5,130,240,21,208,13,165,139,133,180,133,1460
3250 DATA 191,165,140,133,181,133,192,96,230,139,208,2,230,140,56,165,2740
3260 DATA 139,133,178,229,191,133,188,165,140,133,179,229,192,133,189,32,4516
3270 DATA 119,172,165,191,133,139,165,192,133,140,76,225,181,165,139,133,4191
3280 DATA 136,133,180,165,140,133,137,133,181,160,0,177,136,208,25,200,2011
3290 DATA 208,249,165,137,197,135,144,12,165,134,133,136,165,135,133,137,2080
3300 DATA 160,0,240,4,230,137,208,227,24,152,101,136,133,178,169,0,675
3310 DATA 101,137,133,179,56,165,134,229,180,133,182,165,135,229,181,133,5576
3320 DATA 183,56,165,178,229,180,133,188,165,179,229,181,133,189,230,182,8185
3330 DATA 208,2,230,183,32,226,171,56,165,134,229,188,133,134,165,135,3965
3340 DATA 229,189,133,135,96,169,214,160,164,32,14,167,32,46,177,144,9131
3350 DATA 1,96,165,171,133,193,160,44,185,159,183,153,253,183,136,16,3268
3360 DATA 247,32,234,174,201,255,240,24,169,93,160,165,32,14,167,32,9296
3370 DATA 111,168,176,12,169,225,160,164,32,14,167,32,46,177,144,1,6921
3380 DATA 96,32,234,174,165,195,201,255,240,246,32,91,175,32,225,181,5438
3390 DATA 76,216,174,165,139,133,136,165,140,133,137,160,0,162,0,189,154
3400 DATA 253,183,32,71,180,209,136,240,5,224,0,208,240,202,200,208,6482
3410 DATA 10,230,137,165,137,197,135,240,2,176,68,232,228,193,208,223,7347
3420 DATA 24,152,101,136,133,130,165,137,105,0,133,131,165,134,197,130,1327
3430 DATA 165,135,229,131,144,41,56,165,130,229,193,133,139,133,194,165,4152
3440 DATA 131,233,0,133,140,133,195,32,225,181,160,0,177,139,73,128,673
3450 DATA 145,139,32,77,179,160,0,177,139,73,128,145,139,152,96,169,756
3460 DATA 255,133,195,96,56,165,139,133,180,229,194,133,130,165,140,133,4125
3470 DATA 181,229,195,5,130,208,97,169,255,133,195,24,165,193,101,139,3287
3480 DATA 133,178,169,0,101,140,133,179,56,165,134,229,180,133,182,165,4132
3490 DATA 135,229,181,133,183,230,182,208,2,230,183,165,193,197,171,240,8374
3500 DATA 27,32,226,171,56,165,134,229,193,133,134,165,135,233,0,133,2659
3510 DATA 135,165,171,133,176,169,0,133,177,32,101,171,160,0,185,159,453
3520 DATA 183,32,71,180,145,139,200,196,171,208,243,24,165,139,101,171,4149
3530 DATA 133,139,165,140,105,0,133,140,76,225,181,160,0,177,139,41,9636
3540 DATA 63,201,33,144,10,201,59,176,6,177,139,73,64,145,139,76,8149
3550 DATA 29,172,32,119,182,160,0,177,136,201,96,240,25,153,163,183,2791
3560 DATA 200,192,70,144,242,132,197,177,136,240,11,136,208,249,164,197,6906
3570 DATA 200,177,136,240,1,136,132,197,152,56,101,136,133,136,165,137,1784
3580 DATA 105,0,133,137,160,0,185,163,183,32,80,180,72,41,127,201,9669
3590 DATA 32,176,13,24,105,192,170,104,138,201,192,208,2,169,155,72,1537
3600 DATA 104,153,163,183,200,196,197,208,221,169,155,153,163,183,32,83,4159
3610 DATA 178,48,21,56,165,136,229,134,133,130,165,137,229,135,5,130,1465
3620 DATA 144,4,169,255,133,197,169,0,96,165,144,133,136,165,145,133,2404
3630 DATA 137,169,0,133,166,133,167,169,225,160,165,32,14,167,32,165,250
3640 DATA 176,144,21,160,0,185,30,165,201,155,240,9,32,71,180,153,112
3650 DATA 95,164,200,208,240,76,42,167,230,166,208,2,230,167,32,171,3377
3660 DATA 182,160,4,185,245,183,153,89,164,136,16,247,48,208,160,0,932
3670 DATA 177,136,41,127,240,4,201,96,208,11,200,208,243,230,137,32,3773
3680 DATA 220,176,144,236,96,32,210,176,160,0,177,136,41,127,240,11,284
3690 DATA 201,96,240,7,200,208,243,230,137,208,239,152,24,101,136,133,4280
3700 DATA 136,144,2,230,137,165,136,56,229,134,133,130,165,137,229,135,4207
3710 DATA 5,130,144,2,240,1,96,24,96,32,19,177,230,170,162,16,8058
3720 DATA 169,3,157,66,3,169,42,157,68,3,169,184,157,69,3,165,7610
3730 DATA 173,157,74,3,169,0,157,75,3,76,86,228,162,16,169,12,6521
3740 DATA 157,66,3,76,86,228,160,2,185,246,165,153,42,184,136,16,470
3750 DATA 247,169,8,133,173,208,194,169,0,133,171,230,172,32,119,182,3066
3760 DATA 32,42,167,201,27,208,4,198,172,56,96,160,3,41,127,217,9250
3770 DATA 120,166,240,236,136,16,248,165,147,201,126,208,32,198,171,16,2942
3780 DATA 4,169,0,133,171,32,170,177,165,171,240,212,164,171,192,24,4476
3790 DATA 208,1,136,169,0,153,88,164,153,89,164,240,195,201,156,240,6410
3800 DATA 191,164,171,153,159,183,201,155,240,25,32,71,180,192,24,208,2314
3810 DATA 1,136,153,88,164,200,192,25,144,1,136,132,171,32,170,177,897
3820 DATA 76,55,177,173,159,183,201,155,240,141,169,0,153,88,164,133,3007
3830 DATA 172,24,96,165,171,208,6,141,88,164,141,89,164,96,32,46,8014
3840 DATA 177,144,5,104,104,76,244,166,162,0,173,160,183,201,58,240,3932
3850 DATA 22,173,161,183,201,58,240,15,160,2,185,254,165,153,42,184,2990
3860 DATA 136,16,247,160,3,208,2,160,0,189,159,183,32,22,178,153,9643
3870 DATA 42,184,201,155,240,6,200,232,224,25,208,237,173,42,184,201,6206
3880 DATA 69,240,4,201,83,208,5,169,68,141,42,184,96,162,16,157,9255
3890 DATA 66,3,165,144,157,68,3,165,145,157,69,3,76,86,228,201,65
3900 DATA 155,240,18,201,123,176,14,201,97,144,3,56,233,32,201,32,8792
3910 DATA 176,3,24,105,64,96,162,16,169,9,157,66,3,169,159,157,8174
3920 DATA 68,3,169,183,157,69,3,169,80,157,72,3,169,0,157,73,6643
3930 DATA 3,76,86,228,32,119,182,169,155,141,159,183,32,45,178,48,9989
3940 DATA 30,230,157,165,157,201,62,144,20,169,155,141,159,183,32,45,234
3950 DATA 178,32,45,178,32,45,178,230,196,169,0,133,157,169,0,96,9548
3960 DATA 169,236,160,164,32,14,167,32,42,167,160,4,217,249,165,240,3884
3970 DATA 4,136,16,248,96,141,2,166,160,6,185,1,166,153,42,184,9375
3980 DATA 136,16,247,169,6,133,173,32,19,177,32,240,176,16,15,169,8474
3990 DATA 77,160,165,32,14,167,32,19,177,198,170,76,42,167,32,220,9697
4000 DATA 166,169,2,24,105,0,133,154,169,188,105,0,133,155,169,0,8284
4010 DATA 133,198,133,157,32,47,179,48,77,160,0,185,159,183,201,155,2282
4020 DATA 240,8,32,71,180,145,154,200,208,241,230,198,165,198,201,2,6256
4030 DATA 144,12,169,0,133,198,230,157,165,157,201,20,240,16,165,154,3213
4040 DATA 24,105,20,133,154,165,155,105,0,133,155,76,203,178,169,13,372
4050 DATA 160,165,32,14,167,32,42,167,201,27,240,20,169,236,160,164,2833
4060 DATA 32,14,167,76,181,178,169,44,160,165,32,14,167,32,42,167,7964
4070 DATA 32,19,177,198,170,76,220,166,162,16,169,5,157,66,3,169,8888
4080 DATA 159,157,68,3,169,183,157,69,3,169,20,157,72,3,169,0,5697
4090 DATA 157,73,3,76,86,228,169,2,24,105,0,133,154,169,188,105,9433
4100 DATA 0,133,155,165,152,56,229,144,133,130,165,153,229,145,5,130,2652
4110 DATA 176,8,165,144,133,152,165,145,133,153,165,152,133,136,165,153,4187
4120 DATA 133,137,162,1,160,0,177,136,153,128,5,200,201,127,208,6,863
4130 DATA 134,129,132,128,165,174,41,127,201,96,240,25,192,38,208,230,4139
4140 DATA 136,177,136,41,127,201,127,208,2,165,174,201,0,240,5,136,1201
4150 DATA 208,239,160,37,200,132,130,160,0,185,128,5,145,154,200,196,2941
4160 DATA 130,208,246,24,152,101,136,133,136,165,137,105,0,133,137,152,912
4170 DATA 157,133,183,192,38,240,8,169,64,145,154,200,76,202,179,24,1953
4180 DATA 165,154,105,40,133,154,144,2,230,155,232,224,21,240,3,76,1495
4190 DATA 123,179,165,136,133,132,165,137,133,133,96,165,139,197,144,208,5034
4200 DATA 9,165,140,197,145,208,3,160,255,96,169,0,133,136,165,140,2483
4210 DATA 56,233,4,133,137,197,145,176,8,165,144,133,136,165,145,133,2849
4220 DATA 137,160,0,177,136,200,201,96,240,15,192,38,208,245,136,177,5324
4230 DATA 136,240,5,136,208,249,160,37,200,24,152,101,136,133,136,165,2589
4240 DATA 137,105,0,133,137,197,140,144,216,165,136,197,139,144,210,96,5081
4250 DATA 32,89,180,29,171,164,166,150,96,32,89,180,29,175,164,166,1583
4260 DATA 150,96,72,42,42,42,42,41,3,134,150,170,104,41,159,96,6974
4270 DATA 216,169,0,133,138,133,175,133,148,133,170,133,172,133,149,169,4298
4280 DATA 34,141,47,2,169,7,160,185,162,167,32,92,228,169,6,160,796
4290 DATA 1,162,168,32,92,228,169,227,141,0,2,169,167,141,1,2,7585
4300 DATA 169,192,141,14,212,169,4,141,198,2,169,0,141,48,2,169,7462
4310 DATA 164,141,49,2,32,71,168,165,121,5,122,208,6,169,254,133,1352
4320 DATA 121,133,122,169,160,141,244,2,32,44,183,160,0,132,185,177,1235
4330 DATA 139,133,174,16,2,198,185,41,127,133,186,132,187,6,186,38,158
4340 DATA 187,6,186,38,187,6,186,38,187,165,187,24,105,160,133,187,2096
4350 DATA 160,7,177,186,69,185,153,248,163,136,16,246,32,106,183,160,3469
4360 DATA 0,169,127,145,139,32,77,179,173,252,2,201,255,240,237,32,5770
4370 DATA 49,167,170,160,0,132,185,165,174,145,139,138,160,8,140,31,299
4380 DATA 208,172,31,208,192,5,208,36,138,16,4,160,128,132,185,41,8900
4390 DATA 127,201,97,144,7,201,123,176,3,56,233,32,201,65,144,12,8705
4400 DATA 201,91,176,8,56,233,64,69,185,76,159,181,160,31,138,41,9607
4410 DATA 127,201,28,144,1,138,217,124,166,240,5,136,16,248,48,31,9420
4420 DATA 152,10,168,185,156,166,141,103,181,185,157,166,141,104,181,32,3137
4430 DATA 255,255,169,0,133,172,32,244,166,32,77,179,76,194,180,165,3428
4440 DATA 141,208,2,230,141,165,147,201,155,240,21,41,127,160,3,217,2181
4450 DATA 120,166,240,5,136,16,248,48,3,76,194,180,201,32,144,249,2824
4460 DATA 165,147,201,155,208,2,169,96,72,160,0,177,139,201,96,240,3418
4470 DATA 4,165,175,240,3,32,42,171,104,32,71,180,160,0,145,139,8834
4480 DATA 32,77,179,56,165,139,229,134,133,130,165,140,229,135,5,130,2775
4490 DATA 144,12,165,139,105,0,133,134,165,140,105,0,133,135,230,139,1570
4500 DATA 208,2,230,140,32,225,181,76,194,180,32,47,182,56,165,139,1658
4510 DATA 229,152,165,140,229,153,176,24,56,165,152,229,144,133,130,229,5507
4520 DATA 145,5,130,240,11,165,139,133,152,165,140,133,153,32,77,179,1717
4530 DATA 56,165,132,229,139,133,136,165,133,229,140,133,137,5,136,240,4347
4540 DATA 2,176,20,24,165,152,109,134,183,133,152,165,153,105,0,133,838
4550 DATA 153,32,77,179,76,7,182,96,56,165,134,233,0,133,130,165,1054
4560 DATA 135,233,159,5,130,144,8,169,0,133,134,169,159,133,135,56,262
4570 DATA 165,139,229,144,133,130,165,140,229,145,5,130,176,9,165,144,2315
4580 DATA 133,139,165,145,133,140,96,56,165,139,229,134,133,130,165,140,3957
4590 DATA 229,135,5,130,176,1,96,165,134,133,139,165,135,133,140,96,1800
4600 DATA 160,84,169,32,153,159,183,136,16,250,96,165,166,133,160,165,4391
4610 DATA 167,133,161,169,0,133,162,133,163,133,164,133,165,248,160,16,3668
4620 DATA 6,160,38,161,162,3,181,162,117,162,149,162,202,208,247,136,6770
4630 DATA 208,238,216,96,32,130,182,160,0,162,0,185,163,0,32,216,9735
4640 DATA 182,165,168,157,244,183,165,169,157,245,183,232,232,200,192,3,8513
4650 DATA 208,233,160,5,185,244,183,24,105,16,153,244,183,136,16,244,3829
4660 DATA 96,72,41,15,133,169,104,74,74,74,74,133,168,96,165,158,429
4670 DATA 160,0,132,159,140,252,183,201,200,144,11,160,2,141,252,183,4952
4680 DATA 56,233,200,76,9,183,201,100,144,8,160,1,140,252,183,56,1593
4690 DATA 233,100,201,10,144,7,56,233,10,230,159,208,245,24,105,16,771
4700 DATA 141,251,183,165,159,24,105,16,141,250,183,173,252,183,24,105,4090
4710 DATA 16,141,252,183,96,162,2,169,234,157,191,180,202,16,250,169,6555
4720 DATA 40,133,154,169,188,133,155,232,189,8,166,168,201,255,240,17,6521
4730 DATA 232,189,8,166,201,255,240,9,201,253,240,20,145,154,200,208,7903
4740 DATA 239,165,154,24,105,40,133,154,165,155,105,0,133,155,208,215,3444
4750 DATA 76,42,167,169,0,56,229,134,133,166,169,159,229,135,133,167,5256
4760 DATA 32,171,182,160,4,185,245,183,153,65,164,136,16,247,96,226,4814
4770 DATA 2,227,2,253,159,0,0,0,0,0,0,0,0,0,0,0,7039

Listing 2.
TEDIT1.M65

;------------------------
;
;A Simple Text Editor
;
;By: Bryan Schappel
;
;Written for: DEEP BLUE C
;
;------------------------
EOLCHAR	=	96	;return char
TCOMS	=	31	;# of commands-1
ILEGS	=	3
TXTEND	=	$9F00
;
	*=	0
PASS	.=	PASS+1
	.IF	PASS=1
	.INCLUDE	#D:SYSEQU.M65
	.ENDIF
;
;PRINT macro
;
	.MACRO	PRINT 
	LDA	#<%1
	LDY	#>%1
	JSR	LNPRINT
	.ENDM
;
;BUMP macro
;
	.MACRO	BUMP 
	INC	%1
	BNE	@BMP
	INC	%1+1
@BMP
	.ENDM
;
;---------------
;Zero Page Usage
;---------------
;
	*=	$80
CURX	.DS	1	;cursor Xpos
CURY	.DS	1	;cursor Ypos
TEMP	.DS	2
BOTSCR	.DS	2
MEMPNT	.DS	2
TEXTP	.DS	2
CLOCK	.DS	1
CURMEM	.DS	2	;cur pos in mem
FILE?	.DS	1	;file flag
MEMMAX	.DS	2
MEMST	.DS	2	;memory start
OLDC	.DS	1	;keycode
OLDAC	.DS	1	;ascii convert
INVS	.DS	1	;inverse flag
CAPS	.DS	1	;caps flag
SAVXI	.DS	1	;X save
DLIDX	.DS	1	;DLI index
TOPLN	.DS	2	;upper lft scr
SCR	.DS	2	;screen adr
WLEN	.DS	1	;word length
LINES	.DS	1	;# lines
LO	.DS	1	;Work Variables
HI	.DS	1	;for INTEGER to
WORKL	.DS	1	;BCD conversion
WORKH	.DS	1
BCD	.DS	4
LO1	.DS	1
HI1	.DS	1
HNUM	.DS	2	;hex buffer
PAUSE?	.DS	1	;VB pause
CEND	.DS	1	;input length
IPUT	.DS	1	;input flag
IODIR	.DS	1	;i/o direction
CHARUNDR	.DS	1	;char save
INSMODE	.DS	1
INSLEN	.DS	2
FROM	.DS	2
DEST	.DS	2
MOVELEN	.DS	2
ENDPOS	.DS	1
INFLG	.DS	1
CBAS	.DS	2
GOBLEN	.DS	2
CONFLAG	.DS	1
SAVCUR	.DS	2
SLEN	.DS	1	;srch length
FPOS	.DS	2
PAGENUM	.DS	1
LPLEN	.DS	1
COLS	.DS	1
	.OPT	LIST
ENDZPG	=	*
	.OPT	NOLIST
;----------------
;Start of Program
;----------------
;
SCMEM	=	$BC00
;
	*=	$9FFD	;start of code
PSTART	=	*	;save addr.
;
	JMP	INIT
	.INCLUDE	#D:TEXT2.M65
;------------
;Display List
;------------
;
DLIST	.BYTE	$70,$70,$70,$42
	.WORD	SCMEM
	.BYTE	$02,$02,$02,$02,$02
	.BYTE	$02,$02,$02,$02,$02
	.BYTE	$02,$02,$02,$02,$02
	.BYTE	$02,$02,$02,$02,$B0
	.BYTE	$C2
	.WORD	MYMEM
	.BYTE	$10,$02,$02,$41
	.WORD	DLIST
;----------------
;My Screen Memory
;----------------
;
MYMEM	.SBYTE	"    COL: 02   ROW: 00   FREE: 00000     "
LN1	.SBYTE	"                                        "
LN2	.SBYTE	"                                        "
COMLN	=	LN1+13
;
;Special Key Codes
;
KEYS	.BYTE	$FF,$FE,$FD,$9F,$9E
	.BYTE	$9D,$9C,$9B,$7F,$7E
	.BYTE	$7D,$1F,$1E,$1D,$1C
	.BYTE	$1B
;
;Convert Tables
;
A2I	.BYTE	$40,$00,$20,$60
I2A	.BYTE	$20,$40,$00,$60
;
;DLI Colors
;
DLICL	.BYTE	$90,$02
;
;Text and Misc. Data
;
LOADM	.BYTE	"LOAD FILE:",EOL
SAVEM	.BYTE	"SAVE FILE:",EOL
PRNTM	.BYTE	"PRINT DEV:",EOL
FINDM	.BYTE	"FIND WHAT?",EOL
REPLW	.BYTE	"REP. WITH:",EOL
DIRMS	.BYTE	"DIRECTORY FOR DRIVE [1-2-3-4-8]?",EOL
DIRPS	.BYTE	"DIRECTORY PAUSED - PRESS A KEY",EOL
DIRFN	.BYTE	"DIRECTORY FINISHED - PRESS A KEY",EOL
DIRER	.BYTE	"DIRECTORY ERROR",EOL
REPLM	.BYTE	"REPLACE STRING - Y/N?",EOL
QTEXT	.BYTE	"QUIT EDITOR",EOL
ERASE	.BYTE	"ERASE MEMORY",EOL
PTEXT	.BYTE	"PRINT TEXT",EOL
SAVER	.BYTE	"SAVE I/O ERROR",EOL
LOADR	.BYTE	"LOAD I/O ERROR",EOL
PRTER	.BYTE	"PRINTER ERROR",EOL
PAGEN	.BYTE	"Page #    ",EOL
SURE?	.SBYTE	"ARE YOU SURE - Y/N?"
WORDTXT	.BYTE	"WORD COUNT: 00000",EOL
EADR	.BYTE	"E:",EOL
PDEV	.BYTE	"P:",EOL
DIRNUMS	.BYTE	"12348"
D1TXT	.BYTE	"D1:"
DIRTXT	.BYTE	"D1:*.*",EOL
;
;Intro Text
;
ITXT	.BYTE	5,"T",26,"EDIT"
	.SBYTE	" - a Program Text"
	.SBYTE	" Editor"
	.BYTE	$FF,$FF,14
	.SBYTE	"Written By:"
	.BYTE	$FF,$FF,11
	.SBYTE	"Bryan P. Schappel"
	.BYTE	$FF,$FF,7
	.SBYTE	"(c) 1986 "
	.BYTE	"ANALOG"
	.SBYTE	" Computing"
	.BYTE	$FF,$FF,12
	.SBYTE	"- Press a Key -"
	.BYTE	$FD	;end of text
;
;Illegal chars
;
ILLEG	.BYTE	0,96,123,125
;
;Command Text
;
CMDTXT	.BYTE	12,19,20,2,21,4
	.BYTE	3,16,17
	.BYTE	$7E,28,29,30,31
	.BYTE	$FE,$FF,1,23,26,18
	.BYTE	157,$7F,15,8,9,156
	.BYTE	5,6,11,24,14,13
;
;Command Addresses
;
COMADR	.WORD	LOAD	;^L
	.WORD	SAVE	;^S
	.WORD	TOP	;^T
	.WORD	BOTTOM	;^B
	.WORD	UPSC	;^U
	.WORD	DNSC	;^D
	.WORD	CLEAR	;^C
	.WORD	PRINT	;^P
	.WORD	QUIT	;^Q
	.WORD	CHRDEL	;DEL-BS
	.WORD	UPLN	;^-
	.WORD	DNLN	;^=
	.WORD	GOLEFT	;^*
	.WORD	GORIGHT	;^+
	.WORD	CTRLDEL	;^DEL-BS
	.WORD	INSCHAR	;^INS
	.WORD	BLINE	;^A
	.WORD	UPWORD	;^W
	.WORD	ENDLN	;^Z
	.WORD	REVERSE	;^R
	.WORD	ADD255	;SH-INS
	.WORD	ADDTAB	;TAB
	.WORD	PARSE	;^O
	.WORD	HOME	;^H
	.WORD	IMODE	;^I
	.WORD	DEL2CR	;SH-DEL
	.WORD	KSPACE	;^E
	.WORD	FIND	;^F
	.WORD	CONVERT	;^K or ^CAPS
	.WORD	DODIR	;^X
	.WORD	CNTWORD	;^N
	.WORD	MANUAL	;^M
;
;--------------------
;Start of Subroutines
;--------------------
;
;Clear Main Text Screen
;
CLRSCR	LDY	#0
	TYA
CLR1	STA	SCMEM,Y
	STA	SCMEM+$0100,Y
	STA	SCMEM+$0200,Y
	INY
	BNE	CLR1
	LDY	#$1F
CLR2	STA	SCMEM+$0300,Y
	DEY
	BPL	CLR2
	RTS
;
;Clear Entry Window
;
CLRWIN	LDY	#79
CLW	LDA	#0
CLRW	STA	LN1,Y
	DEY
	BPL	CLRW
	RTS
;
;Clear Other Line
;
CLRW1	LDY	#39
	BNE	CLW
;
;Clear Qline
;
CLRW2	LDY	#39
	LDA	#0
CL2	STA	LN2,Y
	DEY
	BPL	CL2
	RTS
;
;Print line routine
;
LNPRINT	STA	LNL+1
	STY	LNL+2
	JSR	CLRW1
	LDY	#0
LNL	LDA	$FFFF,Y
	CMP	#EOL
	BEQ	LNLV
	JSR	ASC2IC
	STA	LN1+2,Y
	INY
	BNE	LNL
LNLV	RTS
;
;Get Key Routine
;
GETKEY	LDA	CH
	CMP	#$FF
	BEQ	GETKEY
GETKEY1	LDX	#$FF
	STX	CH
	STA	OLDC
	LDX	#$7E
	PHA
CLKIT	STX	CONSOL
	LDA	VCOUNT
CLKWT	CMP	VCOUNT
	BEQ	CLKWT
	DEX
	DEX
	BPL	CLKIT
	PLA
K0	TAY
	CPY	#$C0
	BCC	K1
	LDY	#$9A
K1	LDA	(KEYDEF),Y
	STA	OLDAC
	CMP	#$80
	BEQ	GETKEY
	CMP	#$81
	BNE	K2
	LDA	INVS
	EOR	#$80
	STA	INVS
	JMP	GETKEY
K2	CMP	#$82
	BNE	K3
	LDA	CAPS
	EOR	#64
	STA	CAPS
	JMP	GETKEY
K3	CMP	#$83
	BNE	K4
	LDA	#64
	STA	CAPS
	BNE	GETKEY
K4	CMP	#$84
	BNE	K5
	LDA	#11
	STA	OLDAC
	RTS
K5	CMP	#$85
	BEQ	GETKEY
	LDA	OLDC
	CMP	#64
	BCS	K6
	LDA	OLDAC
	CMP	#97
	BCC	K6
	CMP	#123
	BCS	K6
	LDA	CAPS
	BEQ	K6
	ORA	OLDC
	JMP	K0
K6	LDX	#15
K7	LDA	KEYS,X
	CMP	OLDAC
	BEQ	K8
	DEX
	BPL	K7
K8	BEQ	K9
	LDA	OLDAC
	EOR	INVS
K9	STA	OLDAC
	RTS
;
;Vertical Blank Cursor Handler
;Deferred Mode
;
VBLANK1	LDY	CURX
	INY
	STY	LO
	JSR	CALCNM
	LDA	NBUF
	STA	MYMEM+9
	LDA	NBUF+1
	STA	MYMEM+10
	LDA	CURY
	STA	LO
	JSR	CALCNM
	LDA	NBUF
	STA	MYMEM+19
	LDA	NBUF+1
	STA	MYMEM+20
VB1.X	JMP	XITVBV
;
;Display List Interrupt
;
DLI	PHA
	TXA
	PHA
	LDX	DLIDX
	BNE	GDLIC
	LDA	INSMODE
	BEQ	GDLIC
	LDA	#$42
	BNE	DLIAD
GDLIC	LDA	DLICL,X
DLIAD	STA	WSYNC
	STA	COLPF2
	INC	DLIDX
	PLA
	TAX
	PLA
	RTI
;
;Immediate Mode VBLANK
;
VBLANK2	LDA	#0
	STA	DLIDX
	LDY	#3
VBL2.1	LDA	COLOR0,Y
	STA	COLPF0,Y
	DEY
	BPL	VBL2.1
	LDA	PAUSE?
	BNE	VBL2.X
	INC	CLOCK
	LDA	CLOCK
	CMP	#$10
	BNE	VBI2.2
	LDA	CURCHR+7
	EOR	#$FF
	STA	CURCHR+7
	LDA	#0
	STA	CLOCK
VBI2.2	LDA	IPUT
	BEQ	VBL2.X
	LDY	CEND
	LDA	#63
	STA	COMLN,Y
VBL2.X	JMP	SYSVBV
;
;Erase File
;
CLEAR	LDA	FILE?
	BEQ	CLL
		PRINT ERASE
	JSR	YESNO
	BCC	CLEAR2
CLL	RTS
CLEAR2	LDY	#0
	STY	FILE?
	STY	MEMST
	INY
	STY	CURY
	STY	CURX
	JSR	CLRSCR
;
	LDY	MEMLO+1
	INY
	STY	MEMST+1
;
	JSR	ERASEMEM
;
	JMP	CLRWIN
;
;YES/NO
;
YESNO	JSR	CLRW2
	LDY	#18
YN1	LDA	SURE?,Y
	STA	LN2+2,Y
	DEY
	BPL	YN1
YN2	JSR	GETKEY
	AND	#$7F
	CMP	#'[
	BCC	UPC
	SEC
	SBC	#32
UPC	CMP	#'Y
	BEQ	GOTY
	JSR	CLRWIN
	SEC
	RTS
GOTY	JSR	CLRWIN
	CLC
	RTS
;
;Quit Editor
;
QUIT		PRINT QTEXT
	JSR	YESNO
	BCC	DOQUIT
	JMP	CLRWIN
DOQUIT	PLA
	PLA
	LDA	#7
	LDY	#<XITVBV
	LDX	#>XITVBV
	JSR	SETVBV
	LDA	#6
	LDY	#<SYSVBV
	LDX	#>SYSVBV
	JSR	SETVBV
	LDA	#$40
	STA	NMIEN
	LDX	#$00
	LDA	#12
	STA	ICCOM
	JSR	CIOV
	LDX	#$00
	LDA	#3
	STA	ICCOM
	LDA	#12
	STA	AUX1
	STX	AUX2
	LDA	#<EADR
	STA	ICBAL
	LDA	#>EADR
	STA	ICBAH
	JSR	CIOV
	JMP	(DOSVEC)
;
;Go To TOP of text
;
TOP	LDA	MEMST
	STA	CURMEM
	STA	TOPLN
	LDA	MEMST+1
	STA	CURMEM+1
	STA	TOPLN+1
	JMP	SCRDRAW
;
;******************************
;INCLUDE Subroutines
;
	.INCLUDE	#D:TEXT3.M65
	.INCLUDE	#D:TEXT4.M65
;
;
;Convert ATASCII to ICODE
;
ASC2IC	JSR	BITER
	ORA	A2I,X
	LDX	SAVXI
	RTS
;
;Convert ICODE to ATASCII
;
IC2ASC	JSR	BITER
	ORA	I2A,X
	LDX	SAVXI
	RTS
;
;Ready Character
;
BITER	PHA
	ROL	A
	ROL	A
	ROL	A
	ROL	A
	AND	#3
	STX	SAVXI
	TAX
	PLA
	AND	#$9F
	RTS
;
;#############################
;Program Execution Starts Here
;#############################
;
INIT	CLD
	LDA	#0
	STA	CLOCK
	STA	INSMODE
	STA	INVS
	STA	PAUSE?
	STA	IPUT
	STA	CAPS
	LDA	#$22
	STA	SDMCTL
	LDA	#7
	LDY	#<VBLANK1
	LDX	#>VBLANK1
	JSR	SETVBV
	LDA	#6
	LDY	#<VBLANK2
	LDX	#>VBLANK2
	JSR	SETVBV
	LDA	#<DLI
	STA	VDSLST
	LDA	#>DLI
	STA	VDSLST+1
	LDA	#$C0
	STA	NMIEN
	LDA	#4
	STA	COLOR2
	LDA	#<DLIST
	STA	SDLSTL
	LDA	#>DLIST
	STA	SDLSTL+1
	JSR	CLEAR2
	LDA	KEYDEF
	ORA	KEYDEF+1
	BNE	INSET
	LDA	#$FE
	STA	KEYDEF
	STA	KEYDEF+1
;
INSET	LDA	#>MYSET
	STA	CHBAS
GOINT	JSR	INTRO	;call intro
;
MAIN	LDY	#0
	STY	INFLG
	LDA	(CURMEM),Y
	STA	CHARUNDR
	BPL	BLN
	DEC	INFLG
BLN	AND	#$7F
	STA	CBAS
	STY	CBAS+1
	ASL	CBAS
	ROL	CBAS+1
	ASL	CBAS
	ROL	CBAS+1
	ASL	CBAS
	ROL	CBAS+1
	LDA	CBAS+1
	CLC
	ADC	#>MYSET
	STA	CBAS+1
	LDY	#7
CCHRM	LDA	(CBAS),Y
	EOR	INFLG
	STA	CURCHR,Y
	DEY
	BPL	CCHRM
MAIN2	JSR	SHOFREE
	LDY	#0
	LDA	#$7F
	STA	(CURMEM),Y
	JSR	SCRDRAW
WAITM	LDA	CH
	CMP	#$FF
	BEQ	MAIN2
;
HAVKEY	JSR	GETKEY1
	TAX		;SAVE KEY
	LDY	#0
	STY	INFLG
	LDA	CHARUNDR
	STA	(CURMEM),Y
	TXA		;RESTORE KEY
	LDY	#8
	STY	CONSOL
	LDY	CONSOL
	CPY	#5
	BNE	HAVK1
	TXA
	BPL	CTRAND
	LDY	#$80
	STY	INFLG
CTRAND	AND	#$7F
	CMP	#'a
	BCC	CHKRN
	CMP	#'z+1
	BCS	CHKRN
	SEC
	SBC	#$20
CHKRN	CMP	#'A
	BCC	HAVK1
	CMP	#'Z+1
	BCS	HAVK1
	SEC
	SBC	#$40
	EOR	INFLG
	JMP	NOTEOL
HAVK1	LDY	#TCOMS	;# COMMANDS
	TXA
	AND	#$7F
	CMP	#28
	BCC	CMDCK
	TXA
CMDCK	CMP	CMDTXT,Y
	BEQ	GOTCOM
	DEY
	BPL	CMDCK
	BMI	JUSTCHR
GOTCOM	TYA
	ASL	A
	TAY
	LDA	COMADR,Y
	STA	CMDJSR+1
	LDA	COMADR+1,Y
	STA	CMDJSR+2
CMDJSR	JSR	$FFFF
	LDA	#0
	STA	IPUT
	JSR	CLRWIN
	JSR	SCRDRAW
	JMP	MAIN
;
JUSTCHR	LDA	FILE?
	BNE	JCHAR
	INC	FILE?
JCHAR	LDA	OLDAC
	CMP	#EOL
	BEQ	JCH2
	AND	#$7F
	LDY	#ILEGS
JCHT	CMP	ILLEG,Y
	BEQ	JCHI
	DEY
	BPL	JCHT
	BMI	JCHTST
JCHI	JMP	MAIN
JCHTST	CMP	#$20
	BCC	JCHI
JCH2	LDA	OLDAC
	CMP	#EOL
	BNE	NOTEOL
	LDA	#EOLCHAR
NOTEOL	PHA
	LDY	#0
	LDA	(CURMEM),Y
	CMP	#EOLCHAR
	BEQ	DOINS
	LDA	INSMODE
	BEQ	NOTINS
DOINS	JSR	INSCHAR
NOTINS	PLA
	JSR	ASC2IC
	LDY	#0
	STA	(CURMEM),Y
	JSR	SCRDRAW
	SEC
	LDA	CURMEM
	SBC	MEMPNT
	STA	TEMP
	LDA	CURMEM+1
	SBC	MEMPNT+1
	ORA	TEMP
	BCC	INCCUR
	LDA	CURMEM
	ADC	#0
	STA	MEMPNT
	LDA	CURMEM+1
	ADC	#0
	STA	MEMPNT+1
;
INCCUR		BUMP CURMEM
	JSR	CHECKMEM
	JMP	MAIN
;
;Check Memory Routine
;
CHECKMEM	JSR	CHECKM2
	SEC
	LDA	CURMEM
	SBC	TOPLN
	LDA	CURMEM+1
	SBC	TOPLN+1
	BCS	OK1
	SEC
	LDA	TOPLN
	SBC	MEMST
	STA	TEMP
	SBC	MEMST+1
	ORA	TEMP
	BEQ	OK1
	LDA	CURMEM
	STA	TOPLN
	LDA	CURMEM+1
	STA	TOPLN+1
	JSR	SCRDRAW
OK1	SEC
	LDA	BOTSCR
	SBC	CURMEM
	STA	TEXTP
	LDA	BOTSCR+1
	SBC	CURMEM+1
	STA	TEXTP+1
	ORA	TEXTP
	BEQ	EQA
	BCS	OK2
EQA	CLC
	LDA	TOPLN
	ADC	LENTABLE
	STA	TOPLN
	LDA	TOPLN+1
	ADC	#0
	STA	TOPLN+1
REF	JSR	SCRDRAW
	JMP	OK1
OK2	RTS
CHECKM2	SEC
	LDA	MEMPNT
	SBC	#<TXTEND
	STA	TEMP
	LDA	MEMPNT+1
	SBC	#>TXTEND
	ORA	TEMP
	BCC	CK3
	LDA	#<TXTEND
	STA	MEMPNT
	LDA	#>TXTEND
	STA	MEMPNT+1
CK3	SEC
	LDA	CURMEM
	SBC	MEMST
	STA	TEMP
	LDA	CURMEM+1
	SBC	MEMST+1
	ORA	TEMP
	BCS	INRANGE
	LDA	MEMST
	STA	CURMEM
	LDA	MEMST+1
	STA	CURMEM+1
	RTS
INRANGE	SEC
	LDA	CURMEM
	SBC	MEMPNT
	STA	TEMP
	LDA	CURMEM+1
	SBC	MEMPNT+1
	ORA	TEMP
	BCS	OUTRANGE
	RTS
OUTRANGE	LDA	MEMPNT
	STA	CURMEM
	LDA	MEMPNT+1
	STA	CURMEM+1
	RTS
;
;Erase Buffer
;
ERMYBF	LDY	#84
	LDA	#$20
ERMB	STA	MYBUF,Y
	DEY
	BPL	ERMB
	RTS
;
;2 BYTE BINARY INTEGER TO A
;4 BYTE BINARY CODED DECIMAL
;NUMBER.
;
INT2FP	LDA	LO1
	STA	WORKL
	LDA	HI1
	STA	WORKH
	LDA	#0
	STA	BCD
	STA	BCD+1
	STA	BCD+2
	STA	BCD+3
	SED
	LDY	#$10
IFP1	ASL	WORKL
	ROL	WORKH
	LDX	#$03
IFP2	LDA	BCD,X
	ADC	BCD,X
	STA	BCD,X
	DEX
	BNE	IFP2
	DEY
	BNE	IFP1
	CLD
	RTS
;
;Convert BCD to Internal Code
;
CONBCD	JSR	INT2FP
	LDY	#0
	LDX	#0
CONB	LDA	BCD+1,Y
	JSR	BIN2HEX
	LDA	HNUM
	STA	ABUF,X
	LDA	HNUM+1
	STA	ABUF+1,X
	INX
	INX
	INY
	CPY	#3
	BNE	CONB
	LDY	#5
CONB3	LDA	ABUF,Y
	CLC
	ADC	#16
	STA	ABUF,Y
	DEY
	BPL	CONB3
	RTS
;
;Convert BCD to 2 byte number
;
BIN2HEX	PHA
	AND	#$0F
	STA	HNUM+1
	PLA
	LSR	A
	LSR	A
	LSR	A
	LSR	A
	STA	HNUM
	RTS
;
;Convert 1 byte binary number
;to internal code
;
CALCNM	LDA	LO
	LDY	#0
	STY	HI
	STY	NBUF+2
	CMP	#200
	BCC	TRY100
	LDY	#2
	STA	NBUF+2
	SEC
	SBC	#200
	JMP	CLC1
TRY100	CMP	#100
	BCC	CLC1
	LDY	#1
	STY	NBUF+2
	SEC
	SBC	#100
CLC1	CMP	#10
	BCC	CLCDN
	SEC
	SBC	#10
	INC	HI
	BNE	CLC1
CLCDN	CLC
	ADC	#$10
	STA	NBUF+1
	LDA	HI
	CLC
	ADC	#$10
	STA	NBUF
	LDA	NBUF+2
	CLC
	ADC	#$10
	STA	NBUF+2
	RTS
;
;Introduction
;
INTRO	LDX	#2
	LDA	#$EA	;a NOP
INTRO1	STA	GOINT,X
	DEX
	BPL	INTRO1
	LDA	#<[SCMEM+40]
	STA	SCR
	LDA	#>[SCMEM+40]
	STA	SCR+1
PTITL	INX
	LDA	ITXT,X
	TAY
	CMP	#$FF
	BEQ	IADD40
P2	INX
	LDA	ITXT,X
	CMP	#$FF
	BEQ	IADD40
	CMP	#$FD
	BEQ	IPDN
	STA	(SCR),Y
	INY
	BNE	P2
IADD40	LDA	SCR
	CLC
	ADC	#40
	STA	SCR
	LDA	SCR+1
	ADC	#0
	STA	SCR+1
	BNE	PTITL
IPDN	JMP	GETKEY
;
;This routine shows the number
;of free bytes left in text
;memory, it puts the # of bytes
;on the MYMEM+30 line.
;
SHOFREE	LDA	#<TXTEND
	SEC
	SBC	MEMPNT
	STA	LO1
	LDA	#>TXTEND
	SBC	MEMPNT+1
	STA	HI1
	JSR	CONBCD
	LDY	#4
SHOFREE1	LDA	ABUF+1,Y
	STA	MYMEM+30,Y
	DEY
	BPL	SHOFREE1
	RTS
;
;Work Buffers
;
	.OPT	LIST
LENTABLE	.DS	25
MYBUF	.DS	85
ABUF	.DS	6
NBUF	.DS	3
SBUF	.DS	45
FILNAM	.DS	30
ENDMYPG	=	*-1
	.OPT	NOLIST
;
;Set Run Address
;
	*=	RUNAD
	.WORD	PSTART
	.END

Listing 3.
SYSEQU.M65

;------------------------
;SYSTEM EQUATES FILE FOR
;ATARI HOME COMPUTERS
;------------------------
;
;DISK I/O
;
DSKINV	=	$E453
SIOV	=	$E459
DDEVIC	=	$0300
DUNIT	=	$0301	;D: UNIT
DCOMND	=	$0302	;D: command
DSTATS	=	$0303
DBUFLO	=	$0304	;sector buffer
DBUFHI	=	$0305
DTIMLO	=	$0306
DBYTLO	=	$0308
DBYTHI	=	$0309
DSECLO	=	$030A	;sector #
DSECHI	=	$030B
;
;CIO ROUTINES
;
CIOV	=	$E456	;CIO vector
ICCOM	=	$0342	;command
ICBAL	=	$0344	;buffer address
ICBAH	=	$0345
ICBLL	=	$0348	;buffer len
ICBLH	=	$0349
AUX1	=	$034A
AUX2	=	$034B
RUNAD	=	$02E0
INITAD	=	$02E2
;
;SCREEN HANDLER/INTERRUPTS
;
VDSLST	=	$0200	;DLI vector
VBREAK	=	$0206	;BRK vector
VKEYBD	=	$0208	;keyboard vec
SRTIMR	=	$022B	;key repeat
SDMCTL	=	$022F	;DMA control
SDLSTL	=	$0230	;display list
PCOLR0	=	$02C0
PCOLR1	=	$02C1
PCOLR2	=	$02C2
PCOLR3	=	$02C3
COLOR0	=	$02C4
COLOR1	=	$02C5
COLOR2	=	$02C6
COLOR3	=	$02C7
COLOR4	=	$02C8
CHBAS	=	$02F4	;char set
SETVBV	=	$E45C
SYSVBV	=	$E45F
XITVBV	=	$E462
NMIEN	=	$D40E
VCOUNT	=	$D40B
CHBASE	=	$D409
WSYNC	=	$D40A
CHACT	=	$02F3
CHACTL	=	$D401
CRSINH	=	$02F0
CHRSET	=	$E000	;ROM characters
;
;MISC.
;
CONSOL	=	$D01F	;console keys
RTCLOK	=	$14
CH	=	$02FC
MEMLO	=	$02E7
SHFLOK	=	$02BE
WARMSV	=	$E474
COLDSV	=	$E477
LBUFF	=	$0580
EOL	=	$9B
;
;Device Vectors
;
HATABS	=	$031A
EDITRV	=	$E400
SCRENV	=	$E410
KEYBDV	=	$E420
PRINTV	=	$E430
CASETV	=	$E440
;
;PAGE ZERO LOCATIONS
;
CASINI	=	$02
TRAMSZ	=	$06
WARMST	=	$08
BOOT?	=	$09
DOSVEC	=	$0A
DOSINI	=	$0C
POKMSK	=	$10
BRKKEY	=	$11
SOUNDR	=	$41
CRITIC	=	$42
ATRACT	=	$4D
KEYDEF	=	$79
LMARGN	=	$52
RMARGN	=	$53
ROWCRS	=	$54
COLCRS	=	$55
SAVMSC	=	$58
RAMTOP	=	$6A
;
;FLOATING POINT
;
FR0	=	$D4
FRE	=	$DA
FR1	=	$E0
FR2	=	$E6
FRX	=	$EC
EEXP	=	$ED
NSIGN	=	$EE
ESIGN	=	$EF
FCHRFLG	=	$F0
DIGRT	=	$F1
CIX	=	$F2
INBUFF	=	$F3
RADFLG	=	$FB
AFP	=	$D800
FASC	=	$D8E6
IFP	=	$D9AA
FPI	=	$D9D2
ZFR0	=	$DA44
ZF1	=	$DA46
FSUB	=	$DA60
FADD	=	$DA66
FMUL	=	$DADB
FDIV	=	$DB28
PLYEVL	=	$DD40
FMOVE	=	$DDB6
EXP	=	$DDC0
EXP10	=	$DDCC
LOG	=	$DECD
LOG10	=	$DED1
;
;STICK, PADDLES, TRIGGERS
;
PADDL0	=	$0270
PADDL1	=	$0271
PADDL2	=	$0272
PADDL3	=	$0273
STICK0	=	$0278
STICK1	=	$0279
PTRIG0	=	$027C
PTRIG1	=	$027D
PTRIG2	=	$027E
PTRIG3	=	$027F
STRIG0	=	$0284
STRIG1	=	$0285
;
;AUDIO CONTROL
;
AUDF1	=	$D200
AUDC1	=	$D201
AUDF2	=	$D202
AUDC2	=	$D203
AUDF3	=	$D204
AUDC3	=	$D205
AUDF4	=	$D206
AUDC4	=	$D207
AUDCTL	=	$D208
SKCTL	=	$D20F
;
;P/M GRAPHICS
;
PMBASE	=	$D407
GPRIOR	=	$026F
HPOSP0	=	$D000
HPOSP1	=	$D001
HPOSP2	=	$D002
HPOSP3	=	$D003
M0PF	=	$D000
M1PF	=	$D001
M2PF	=	$D002
M3PF	=	$D003
HPOSM0	=	$D004
HPOSM1	=	$D005
HPOSM2	=	$D006
HPOSM3	=	$D007
P0PF	=	$D004
P1PF	=	$D005
P2PF	=	$D006
P3PF	=	$D007
SIZEP0	=	$D008
SIZEP1	=	$D009
SIZEP2	=	$D00A
SIZEP3	=	$D00B
M0PL	=	$D008
M1PL	=	$D009
M2PL	=	$D00A
M3PL	=	$D00B
SIZEM	=	$D00C	;missile size
P0PL	=	$D00C	;player/pf
P1PL	=	$D00D
P2PL	=	$D00E
P3PL	=	$D00F
COLPM0	=	$D012
COLPM1	=	$D013
COLPM2	=	$D014
COLPM3	=	$D015
COLPF0	=	$D016
COLPF1	=	$D017
COLPF2	=	$D018
COLPF3	=	$D019
COLBK	=	$D01A
GRACTL	=	$D01D
HITCLR	=	$D01E
	.OPT	NOLIST

Listing 4.
TEDIT2.M65

MYSET	.BYTE	$00,$00,$00,$00
	.BYTE	$00,$00,$00,$00
	.BYTE	$00,$18,$18,$18
	.BYTE	$18,$00,$18,$00
	.BYTE	$00,$66,$66,$66
	.BYTE	$00,$00,$00,$00
	.BYTE	$00,$66,$FF,$66
	.BYTE	$66,$FF,$66,$00
	.BYTE	$18,$3E,$60,$3C
	.BYTE	$06,$7C,$18,$00
	.BYTE	$00,$66,$6C,$18
	.BYTE	$30,$66,$46,$00
	.BYTE	$1C,$36,$1C,$38
	.BYTE	$6F,$66,$3B,$00
	.BYTE	$00,$18,$18,$18
	.BYTE	$00,$00,$00,$00
	.BYTE	$00,$0E,$1C,$18
	.BYTE	$18,$1C,$0E,$00
	.BYTE	$00,$70,$38,$18
	.BYTE	$18,$38,$70,$00
	.BYTE	$00,$66,$3C,$FF
	.BYTE	$3C,$66,$00,$00
	.BYTE	$00,$18,$18,$7E
	.BYTE	$18,$18,$00,$00
	.BYTE	$00,$00,$00,$00
	.BYTE	$00,$18,$18,$30
	.BYTE	$00,$00,$00,$7E
	.BYTE	$00,$00,$00,$00
	.BYTE	$00,$00,$00,$00
	.BYTE	$00,$18,$18,$00
	.BYTE	$00,$06,$0C,$18
	.BYTE	$30,$60,$40,$00
	.BYTE	$00,$3C,$66,$6E
	.BYTE	$76,$66,$3C,$00
	.BYTE	$00,$18,$38,$18
	.BYTE	$18,$18,$7E,$00
	.BYTE	$00,$3C,$66,$0C
	.BYTE	$18,$30,$7E,$00
	.BYTE	$00,$7E,$0C,$18
	.BYTE	$0C,$66,$3C,$00
	.BYTE	$00,$0C,$1C,$3C
	.BYTE	$6C,$7E,$0C,$00
	.BYTE	$00,$7E,$60,$7C
	.BYTE	$06,$66,$3C,$00
	.BYTE	$00,$3C,$60,$7C
	.BYTE	$66,$66,$3C,$00
	.BYTE	$00,$7E,$06,$0C
	.BYTE	$18,$30,$30,$00
	.BYTE	$00,$3C,$66,$3C
	.BYTE	$66,$66,$3C,$00
	.BYTE	$00,$3C,$66,$3E
	.BYTE	$06,$0C,$38,$00
	.BYTE	$00,$00,$18,$18
	.BYTE	$00,$18,$18,$00
	.BYTE	$00,$00,$18,$18
	.BYTE	$00,$18,$18,$30
	.BYTE	$06,$0C,$18,$30
	.BYTE	$18,$0C,$06,$00
	.BYTE	$00,$00,$7E,$00
	.BYTE	$00,$7E,$00,$00
	.BYTE	$60,$30,$18,$0C
	.BYTE	$18,$30,$60,$00
	.BYTE	$00,$3C,$66,$0C
	.BYTE	$18,$00,$18,$00
	.BYTE	$00,$3C,$66,$6E
	.BYTE	$6E,$60,$3E,$00
	.BYTE	$00,$18,$3C,$66
	.BYTE	$66,$7E,$66,$00
	.BYTE	$00,$7C,$66,$7C
	.BYTE	$66,$66,$7C,$00
	.BYTE	$00,$3C,$66,$60
	.BYTE	$60,$66,$3C,$00
	.BYTE	$00,$78,$6C,$66
	.BYTE	$66,$6C,$78,$00
	.BYTE	$00,$7E,$60,$7C
	.BYTE	$60,$60,$7E,$00
	.BYTE	$00,$7E,$60,$7C
	.BYTE	$60,$60,$60,$00
	.BYTE	$00,$3E,$60,$60
	.BYTE	$6E,$66,$3E,$00
	.BYTE	$00,$66,$66,$7E
	.BYTE	$66,$66,$66,$00
	.BYTE	$00,$7E,$18,$18
	.BYTE	$18,$18,$7E,$00
	.BYTE	$00,$06,$06,$06
	.BYTE	$06,$66,$3C,$00
	.BYTE	$00,$66,$6C,$78
	.BYTE	$78,$6C,$66,$00
	.BYTE	$00,$60,$60,$60
	.BYTE	$60,$60,$7E,$00
	.BYTE	$00,$63,$77,$7F
	.BYTE	$6B,$63,$63,$00
	.BYTE	$00,$66,$76,$7E
	.BYTE	$7E,$6E,$66,$00
	.BYTE	$00,$3C,$66,$66
	.BYTE	$66,$66,$3C,$00
	.BYTE	$00,$7C,$66,$66
	.BYTE	$7C,$60,$60,$00
	.BYTE	$00,$3C,$66,$66
	.BYTE	$66,$6C,$36,$00
	.BYTE	$00,$7C,$66,$66
	.BYTE	$7C,$6C,$66,$00
	.BYTE	$00,$3C,$60,$3C
	.BYTE	$06,$06,$3C,$00
	.BYTE	$00,$7E,$18,$18
	.BYTE	$18,$18,$18,$00
	.BYTE	$00,$66,$66,$66
	.BYTE	$66,$66,$7E,$00
	.BYTE	$00,$66,$66,$66
	.BYTE	$66,$3C,$18,$00
	.BYTE	$00,$63,$63,$6B
	.BYTE	$7F,$77,$63,$00
	.BYTE	$00,$66,$66,$3C
	.BYTE	$3C,$66,$66,$00
	.BYTE	$00,$66,$66,$3C
	.BYTE	$18,$18,$18,$00
	.BYTE	$00,$7E,$0C,$18
	.BYTE	$30,$60,$7E,$00
	.BYTE	$00,$1E,$18,$18
	.BYTE	$18,$18,$1E,$00
	.BYTE	$00,$40,$60,$30
	.BYTE	$18,$0C,$06,$00
	.BYTE	$00,$78,$18,$18
	.BYTE	$18,$18,$78,$00
	.BYTE	$00,$08,$1C,$36
	.BYTE	$63,$00,$00,$00
	.BYTE	$00,$00,$00,$00
	.BYTE	$00,$00,$FF,$00
	.BYTE	$00,$00,$00,$00
	.BYTE	$00,$00,$00,$00
	.BYTE	$3F,$33,$33,$7F
	.BYTE	$73,$73,$73,$00
	.BYTE	$7E,$66,$66,$7F
	.BYTE	$67,$67,$7F,$00
	.BYTE	$7F,$67,$67,$60
	.BYTE	$63,$63,$7F,$00
	.BYTE	$7E,$66,$66,$77
	.BYTE	$77,$77,$7F,$00
	.BYTE	$7F,$60,$60,$7F
	.BYTE	$70,$70,$7F,$00
	.BYTE	$7F,$60,$60,$7F
	.BYTE	$70,$70,$70,$00
	.BYTE	$7F,$63,$60,$6F
	.BYTE	$67,$67,$7F,$00
	.BYTE	$73,$73,$73,$7F
	.BYTE	$73,$73,$73,$00
	.BYTE	$0C,$0C,$0C,$0C
	.BYTE	$3C,$3C,$3C,$00
	.BYTE	$0C,$0C,$0C,$0E
	.BYTE	$0E,$6E,$7E,$00
	.BYTE	$66,$66,$6C,$7F
	.BYTE	$67,$67,$67,$00
	.BYTE	$30,$30,$30,$70
	.BYTE	$70,$70,$7E,$00
	.BYTE	$67,$7F,$7F,$77
	.BYTE	$67,$67,$67,$00
	.BYTE	$67,$77,$7F,$6F
	.BYTE	$67,$67,$67,$00
	.BYTE	$7F,$63,$63,$67
	.BYTE	$67,$67,$7F,$00
	.BYTE	$7F,$63,$63,$7F
	.BYTE	$70,$70,$70,$00
	.BYTE	$7F,$63,$63,$67
	.BYTE	$67,$67,$7F,$07
	.BYTE	$7E,$66,$66,$7F
	.BYTE	$77,$77,$77,$00
	.BYTE	$7F,$60,$7F,$03
	.BYTE	$73,$73,$7F,$00
	.BYTE	$7F,$1C,$1C,$1C
	.BYTE	$1C,$1C,$1C,$00
	.BYTE	$67,$67,$67,$67
	.BYTE	$67,$67,$7F,$00
	.BYTE	$67,$67,$67,$67
	.BYTE	$6F,$3E,$1C,$00
	.BYTE	$67,$67,$67,$6F
	.BYTE	$7F,$7F,$67,$00
	.BYTE	$73,$73,$73,$3E
	.BYTE	$67,$67,$67,$00
	.BYTE	$67,$67,$67,$7F
	.BYTE	$1C,$1C,$1C,$00
	.BYTE	$7F,$66,$6C,$18
	.BYTE	$37,$67,$7F,$00
	.BYTE	$00,$00,$00,$00
	.BYTE	$00,$00,$00,$00
	.BYTE	$00,$18,$3C,$7E
	.BYTE	$18,$18,$18,$00
	.BYTE	$00,$18,$18,$18
	.BYTE	$7E,$3C,$18,$00
	.BYTE	$00,$18,$30,$7E
	.BYTE	$30,$18,$00,$00
	.BYTE	$00,$18,$0C,$7E
	.BYTE	$0C,$18,$00,$00
	.BYTE	$FF,$E7,$CF,$81
	.BYTE	$CF,$E7,$FF,$00
	.BYTE	$00,$00,$3C,$06
	.BYTE	$3E,$66,$3E,$00
	.BYTE	$00,$60,$60,$7C
	.BYTE	$66,$66,$7C,$00
	.BYTE	$00,$00,$3C,$60
	.BYTE	$60,$60,$3C,$00
	.BYTE	$00,$06,$06,$3E
	.BYTE	$66,$66,$3E,$00
	.BYTE	$00,$00,$3C,$66
	.BYTE	$7E,$60,$3C,$00
	.BYTE	$00,$0E,$18,$3E
	.BYTE	$18,$18,$18,$00
	.BYTE	$00,$00,$3E,$66
	.BYTE	$66,$3E,$06,$7C
	.BYTE	$00,$60,$60,$7C
	.BYTE	$66,$66,$66,$00
	.BYTE	$00,$18,$00,$38
	.BYTE	$18,$18,$3C,$00
	.BYTE	$00,$06,$00,$06
	.BYTE	$06,$06,$06,$3C
	.BYTE	$00,$60,$60,$6C
	.BYTE	$78,$6C,$66,$00
	.BYTE	$00,$38,$18,$18
	.BYTE	$18,$18,$3C,$00
	.BYTE	$00,$00,$66,$7F
	.BYTE	$7F,$6B,$63,$00
	.BYTE	$00,$00,$7C,$66
	.BYTE	$66,$66,$66,$00
	.BYTE	$00,$00,$3C,$66
	.BYTE	$66,$66,$3C,$00
	.BYTE	$00,$00,$7C,$66
	.BYTE	$66,$7C,$60,$60
	.BYTE	$00,$00,$3E,$66
	.BYTE	$66,$3E,$06,$06
	.BYTE	$00,$00,$7C,$66
	.BYTE	$60,$60,$60,$00
	.BYTE	$00,$00,$3E,$60
	.BYTE	$3C,$06,$7C,$00
	.BYTE	$00,$18,$7E,$18
	.BYTE	$18,$18,$0E,$00
	.BYTE	$00,$00,$66,$66
	.BYTE	$66,$66,$3E,$00
	.BYTE	$00,$00,$66,$66
	.BYTE	$66,$3C,$18,$00
	.BYTE	$00,$00,$63,$6B
	.BYTE	$7F,$3E,$36,$00
	.BYTE	$00,$00,$66,$3C
	.BYTE	$18,$3C,$66,$00
	.BYTE	$00,$00,$66,$66
	.BYTE	$66,$3E,$0C,$78
	.BYTE	$00,$00,$7E,$0C
	.BYTE	$18,$30,$7E,$00
	.BYTE	$00,$00,$00,$00
	.BYTE	$00,$00,$00,$00
	.BYTE	$18,$18,$18,$18
	.BYTE	$18,$18,$18,$18
	.BYTE	$00,$60,$70,$7C
	.BYTE	$7C,$70,$60,$00
	.BYTE	$00,$00,$00,$00
	.BYTE	$00,$00,$00,$00
CURCHR	.BYTE	$00,$00,$00,$00
	.BYTE	$00,$00,$00,$00

Listing 5.
TEDIT3.M65

;-----------------------
;
;Text Editor Subroutines
;
;By: Bryan Schappel
;
;FILE: TXTSUB
;
;-----------------------
;
;SAVE a file
;
;This routine will SAVE a file
;to disk, if there is a file in
;memory at this time, if there
;is no file in memory, the
;command is aborted. The routine
;will over-write the disk file.
;it will not ask to replace it.
;
SAVE	LDA	FILE?
	BNE	DSV
	RTS
DSV		PRINT SAVEM
	JSR	COPFIL
	JSR	CONASC
	LDA	#8
	STA	IODIR
	JSR	OPENFIL	;open file
SV1	BMI	SVERR
	LDX	#$10
	LDA	MEMST
	STA	ICBAL,X
	LDA	MEMST+1
	STA	ICBAH,X
	SEC
	LDA	MEMPNT
	SBC	MEMST
	STA	ICBLL,X
	LDA	MEMPNT+1
	SBC	MEMST+1
	STA	ICBLH,X
	LDA	#11
	JSR	PERFIO
	BMI	SVERR
	JSR	CLOSE1
	DEC	PAUSE?
	JMP	CONINT
;
SVERR		PRINT SAVER
SCL	JSR	CLOSE1
	JSR	GETKEY
	DEC	PAUSE?
	JMP	CONINT
;
;This is the PRINT TO DISK, or
;MANUAL routine.  This justs
;asks for a disk filename, then
;branches to the proper place
;in the print routine to produce
;the output.
;
MANUAL	LDA	FILE?
	BNE	DMAN
	RTS
DMAN		PRINT PRNTM
	JSR	COPFIL
	LDA	#8
	STA	IODIR
	JSR	OPENFIL
	BMI	PERR
	BPL	PV2
;
;PRINT a file
;
;This routine will generate page
;formatted output to any line
;printer. The text is formatted
;for 80 columns by the routine
;LPLINE. The LINES location is
;used to keep track of where the
;page is being printed, if LINES
;=0 then we are at TOP of form,
;else some where else on the
;page. The program will number
;all pages (up to 255, if the
;page number exceeds 255, then
;the page number is set to 0)
;The message 'Page # xxx' is
;used at the top of each page.
;
PRINT	LDA	FILE?
	BEQ	PV0
		PRINT PTEXT
	JSR	YESNO
	BCS	PV0
	JSR	OPENP
	BPL	PV2
PERR	JSR	CLOSE1
		PRINT PRTER
	DEC	PAUSE?
	JMP	GETKEY
PV0	RTS
PV2	LDA	#1
	STA	PAGENUM
	LDA	MEMST
	STA	TEXTP
	LDA	MEMST+1
	STA	TEXTP+1
PRINTLP	JSR	LPCR
	BMI	PERR
	LDA	PAGENUM
	STA	LO
	JSR	CALCNM
	LDA	NBUF+2
	CLC
	ADC	#$20
	STA	PAGEN+7
	LDA	NBUF
	CLC
	ADC	#$20
	STA	PAGEN+8
	LDA	NBUF+1
	CLC
	ADC	#$20
	STA	PAGEN+9
	LDY	#0
	STY	LINES
PGNLP	LDA	PAGEN,Y
	STA	MYBUF,Y
	CMP	#EOL
	BEQ	PGNLP0
	INY
	BNE	PGNLP
PGNLP0	JSR	LPRINT	;line #1
	BMI	PERR
	JSR	LPCR	;line #2
	BMI	PERR
LPTEXT	JSR	LPLINE
	BMI	PERR
	LDA	LPLEN
	CMP	#$FF
	BEQ	LPDONE
	LDA	LINES
	BNE	LPTEXT
	BEQ	PRINTLP
LPDONE	LDA	LINES
	BEQ	LPDONE1
	JSR	LPCR
	JMP	LPDONE
LPDONE1	DEC	PAUSE?
	JMP	CLOSE1
;
;LOAD a file
;
;Here we LOAD a file into
;memory. If the LOAD is good
;we convert the file to ICODE
;by calling - CONINT. If the
;LOAD is bad we print the error
;message, and exit.
;
LOAD		PRINT LOADM
	JSR	COPFIL
	LDA	#4
	STA	IODIR
	JSR	OPENFIL
	BMI	LOERR
	JSR	ERASEMEM
	LDX	#$10
	LDA	MEMMAX
	STA	ICBLL,X
	LDA	MEMMAX+1
	STA	ICBLH,X
	LDA	#7
	JSR	PERFIO
	BMI	LOERR
LOAG	LDX	#$10
	LDA	ICBLL,X
	SEC
	SBC	#1
	STA	ICBLL,X
	LDA	ICBLH,X
	SBC	#0
	STA	ICBLH,X
	LDA	MEMST
	ADC	ICBLL,X
	STA	MEMPNT
	STA	TEXTP
	LDA	MEMST+1
	ADC	ICBLH,X
	STA	MEMPNT+1
	STA	TEXTP+1
	JSR	CLOSE1
	INC	FILE?
	DEC	PAUSE?
	LDY	#1
	LDA	#0
LOAL	STA	(TEXTP),Y
	INY
	BNE	LOAL
	JSR	CONINT
	JMP	SCRDRAW
;
LOERR	CPY	#136	;EOF?
	BEQ	LOAG
	JSR	CLOSE1
		PRINT LOADR
	DEC	PAUSE?
	JMP	GETKEY
;
;Jump to Beginning of Line
;
;We jump to the start of the
;line by taking the Xpos of the
;cursor, subtract 1 (since the
;actual Xpos is kept as 1 less
;than the number that is shown
;on the cursor line), then
;subtract this number from
;CURMEM.
;
BLINE	LDX	CURX
	DEX
	STX	TEMP
	LDA	CURMEM
	SEC
	SBC	TEMP
	STA	CURMEM
	LDA	CURMEM+1
	SBC	#0
	STA	CURMEM+1
BLOUT	RTS
;
;Advance ONE word
;
;Here we scan ahead for a SPACE
;or a RETURN to determine if we
;have found the end of a word
;then scan ahead for a non-
;space character.
;
UPWORD	LDY	#0
RLOOP	LDA	(CURMEM),Y
	BEQ	UPWRD1
	CMP	#EOLCHAR
	BEQ	UPWRD1
	INY
	BNE	RLOOP
	RTS
UPWRD1	INY
	BNE	UPWRD
	INC	CURMEM+1
	LDA	CURMEM+1
	CMP	MEMPNT+1
	BCC	UPWRD
	BNE	ENDTEXT
UPWRD	LDA	(CURMEM),Y
	BEQ	UPWRD1
;
;This routine adds the Y-reg
;to CURMEM, and then calls
;CHECKMEM to make sure we did
;not leave the screen.
;
ADDY2CP	CLC
	TYA
	ADC	CURMEM
	STA	CURMEM
	LDA	CURMEM+1
	ADC	#0
	STA	CURMEM+1
WRTN	JMP	CHECKMEM
ENDTEXT	LDA	MEMPNT
	STA	CURMEM
	LDA	MEMPNT+1
	STA	CURMEM+1
	JMP	CHECKMEM
;
;Goto bottom of text
;
;This routine is a little bit
;tricky. If the end of text is
;on the screen, we just call
;ENDTEXT, else we subtract
;1K from the EOT pointer and
;call CHECKMEM to scroll to the
;end of text.
;
BOTTOM	LDA	#0
	STA	TOPLN
	LDA	MEMPNT+1
	SEC
	SBC	#4
	CMP	MEMST+1
	BCS	BOTSAFE
	LDA	MEMST+1
BOTSAFE	STA	TOPLN+1
	JSR	SCRDRAW
	JMP	ENDTEXT
;
;Goto end of line
;
;To goto the EOL we move to the
;Begin of line, and then add
;line length-1 to the CURMEM
;pointer.
;
ENDLN	JSR	BLINE
	LDX	CURY
	LDA	LENTABLE-1,X
	TAY
	DEY
	JMP	ADDY2CP
;
;Home Cursor
;
;All we do here is move to ADR
;of TOPLN to the CURMEM
;pointer.
;
HOME	LDA	TOPLN
	STA	CURMEM
	LDA	TOPLN+1
	STA	CURMEM+1
	RTS
;
;Flip Insert mode
;
;All we do here is flip the
;INSMODE mode between 0 and 1.
;Then the DLI will change the
;CURSOR line color to reflect
;the mode change.
;
IMODE	LDA	INSMODE
	EOR	#$01
	STA	INSMODE
	RTS
;
;Reverse Characters
;
;This command was one I heard
;PAPERCLIP had so I had to
;include it here. As you can
;see it is not hard to do. If
;you move to the EOT and do a
;swap, the character is flipped
;with a blank space.
;
REVERSE	LDY	#0
	LDA	(CURMEM),Y
	PHA
	INY
	LDA	(CURMEM),Y
	DEY
	STA	(CURMEM),Y
	INY
	PLA
	STA	(CURMEM),Y
	RTS
;
;Erase all of Memory
;
;This is called only to ERASE
;the entire TEXTPT buffer. It
;also resets some of my
;pointers. It fills memory with
;zeroes.
;
ERASEMEM	LDA	MEMST
	STA	TEXTP
	STA	TOPLN
	STA	CURMEM
	STA	MEMPNT
	LDA	MEMST+1
	STA	TEXTP+1
	STA	TOPLN+1
	STA	CURMEM+1
	STA	MEMPNT+1
	SEC
	LDA	#>TXTEND
	SBC	MEMST+1
	STA	MEMMAX+1
	TAX
	LDA	#0
	STA	MEMMAX
ERMEMLP	LDY	#$FF
	DEC	TEXTP+1
	STA	(TEXTP),Y
	INY
	INC	TEXTP+1
ERMLP2	STA	(TEXTP),Y
	INY
	BNE	ERMLP2
	INC	TEXTP+1
	DEX
	BNE	ERMLP2
	STA	(TEXTP),Y
	RTS
;
;Insert One Space
;
;This sets the INSLEN location
;to 1 and calls the block
;insert routine. Then it puts
;a space under the cursor.
;
INSCHAR	LDA	#1
	STA	INSLEN
	LDA	#0
	STA	INSLEN+1
	JSR	INSBLOCK
	LDA	#0
	TAY
	STA	(CURMEM),Y
	JMP	CHECKMEM
;
;These are the block inserts
;
;This is the 255 char block
;insert routine. It works much
;the the 1 char insert routine
;it only sets INSLEN to 255.
;
ADD255	LDA	#$FF
	STA	INSLEN
	BNE	TAB2
;
;This routine inserts 5 spaces
;into the text.
;
ADDTAB	LDA	#5
	STA	INSLEN
	JSR	TAB2
	LDA	(CURMEM),Y
	BNE	NOINCY
	INY
NOINCY	JMP	ADDY2CP
TAB2	LDA	#0
	STA	INSLEN+1
	JSR	INSBLOCK
	LDA	#0
	TAY
	LDX	INSLEN
FILLSP	STA	(CURMEM),Y
	INY
	DEX
	BNE	FILLSP
	RTS
;
;Insert a block of text
;
;This is the actual INSERT code
;it sets up the pointers DEST
;and FROM, then moves the
;memory. There are checks made
;to make certain that you don't
;go past the EOT memory.
;
INSBLOCK	CLC
	LDA	MEMPNT
	ADC	INSLEN
	LDA	MEMPNT+1
	ADC	INSLEN+1
	CMP	#>TXTEND
	BCC	OKINS
	PLA
	PLA
	RTS
OKINS	CLC
	LDA	CURMEM
	STA	FROM
	ADC	INSLEN
	STA	DEST
	LDA	CURMEM+1
	STA	FROM+1
	ADC	INSLEN+1
	STA	DEST+1
	SEC
	LDA	MEMPNT
	SBC	FROM
	STA	MOVELEN
	LDA	MEMPNT+1
	SBC	FROM+1
	STA	MOVELEN+1
	JSR	DMOVE
	CLC
	LDA	MEMPNT
	ADC	INSLEN
	STA	MEMPNT
	LDA	MEMPNT+1
	ADC	INSLEN+1
	STA	MEMPNT+1
	RTS
;
;Move Memory Routines
;
;The next two routines are the
;memory move routines.
;They self-modify for a little
;extra speed.
;
DMOVE	LDA	MOVELEN+1
	TAX
	ORA	MOVELEN
	BNE	NOTNULL
	RTS
NOTNULL	CLC
	TXA
	ADC	FROM+1
	STA	DMVLP+2
	LDA	FROM
	STA	DMVLP+1
	CLC
	TXA
	ADC	DEST+1
	STA	DMVLP+5
	LDA	DEST
	STA	DMVLP+4
	INX
	LDY	MOVELEN
	BNE	DMVLP
	BEQ	SKIPDMV
DMV1	LDY	#$FF
DMVLP	LDA	$FFFF,Y
	STA	$FFFF,Y
	DEY
	CPY	#$FF
	BNE	DMVLP
SKIPDMV	DEC	DMVLP+2
	DEC	DMVLP+5
	DEX
	BNE	DMV1
	RTS
;
;Move memory up
;
UMOVE	LDA	FROM
	STA	UMVLP+1
	LDA	FROM+1
	STA	UMVLP+2
	LDA	DEST
	STA	UMVLP+4
	LDA	DEST+1
	STA	UMVLP+5
	LDX	MOVELEN+1
	BEQ	SKIPUMV
UMV1	LDA	#0
UMV2	STA	ENDPOS
	LDY	#0
UMVLP	LDA	$FFFF,Y
	STA	$FFFF,Y
	INY
	CPY	ENDPOS
	BNE	UMVLP
	INC	UMVLP+2
	INC	UMVLP+5
	CPX	#0
	BEQ	UMVOUT
	DEX
	BNE	UMV1
SKIPUMV	LDA	MOVELEN
	BNE	UMV2
UMVOUT	RTS
;
;Move cursor Right
;
;This simply adds one to the
;CURMEM pointer and calls the
;CHECKMEM routine to make sure
;we did not leave text memory.
;
GORIGHT		BUMP CURMEM
	JMP	CHECKMEM
;
;Move Cursor Left
;
;This just subtracts one from
;CURMEM and calls CHECKMEM. If
;you go left from the HOME posit
;the screen will only move one
;character up in the document.
;This can cause some minor
;cosmetic problems for the word
;wrap later on.
;
GOLEFT	LDA	CURMEM
	BNE	NODEC
	DEC	CURMEM+1
NODEC	DEC	CURMEM
	JMP	CHECKMEM
;
;CONTROL-DEL a char
;
;This moves the cursor forward,
;then saves its position, then
;moves it back again and calls
;the DELETE2 code to delete the
;text.
;
CTRLDEL	JSR	GORIGHT
	JSR	DELETE1
	JSR	GOLEFT
	JSR	DELETE2
	RTS
;
;Delete a char (BACK S)
;
;This save the CURMEM position
;then moves left and deletes
;the text.
;
CHRDEL	JSR	DELETE1
	JSR	GOLEFT
	JMP	DELETE2
;
;Actual delete code
;
;Here are the work-horse delete
;routines, that perform most
;of the text delete functions.
;
DELETE1	SEC
	LDA	CURMEM
	SBC	MEMST
	STA	TEMP
	LDA	CURMEM+1
	SBC	MEMST+1
	ORA	TEMP
	BNE	DELETE1.1
	PLA
	PLA
	RTS
DELETE1.1	LDA	CURMEM
	STA	FROM
	LDA	CURMEM+1
	STA	FROM+1
	RTS
DELETE2	SEC
	LDA	CURMEM
	STA	DEST
	EOR	#$FF
	ADC	FROM
	STA	GOBLEN
	LDA	CURMEM+1
	STA	DEST+1
	EOR	#$FF
	ADC	FROM+1
	STA	GOBLEN+1
DELMEM	SEC
	LDA	MEMPNT
	SBC	DEST
	STA	MOVELEN
	LDA	MEMPNT+1
	SBC	DEST+1
	STA	MOVELEN+1
		BUMP MOVELEN
	JSR	UMOVE
	LDA	MEMPNT
	SEC
	SBC	GOBLEN
	STA	MEMPNT
	LDA	MEMPNT+1
	SBC	GOBLEN+1
	STA	MEMPNT+1
	RTS
;
;These are the routines
;that convert the text into
;the internal form the program
;uses.
;
CONASC	LDA	#0
	STA	CONFLAG
	BEQ	DOCON
CONINT	LDA	#128
	STA	CONFLAG
DOCON	LDA	MEMST
	STA	TEXTP
	LDA	MEMST+1
	STA	TEXTP+1
	SEC
	LDA	MEMPNT+1
	SBC	TEXTP+1
	TAX
	INX
	LDY	#0
CVLOOP	LDA	(TEXTP),Y
	PHA
	LDA	CONFLAG
	BEQ	COTHER
	PLA
	CMP	#EOL
	BNE	NOTRTN
	LDA	#EOLCHAR
	BNE	OVEROTHER
NOTRTN	CMP	#$7F
	BNE	GOASCQ
	LDA	#125
	BNE	OVEROTHER
GOASCQ	JSR	ASC2IC
	JMP	OVEROTHER
COTHER	PLA
	CMP	#EOLCHAR
	BNE	NOTRC
	LDA	#EOL
	BNE	OVEROTHER
NOTRC	CMP	#125
	BNE	GOASCX
	LDA	#$7F
	BNE	OVEROTHER
GOASCX	JSR	IC2ASC
OVEROTHER	STA	(TEXTP),Y
	INY
	BNE	CVLOOP
	INC	TEXTP+1
	DEX
	BNE	CVLOOP
	RTS
;
;Show false spaces
;
;This simply flips the middle
;bit of the middle byte on one
;of the characters in my set.
;This produces a small dot on
;the screen where a word-wrap
;occured.
;
PARSE	LDA	MYSET+$0204
	EOR	#$10
	STA	MYSET+$0204
	RTS
;
;Move Down One Screen
;
;This will HOME the cursor and
;then move the screen down 19
;lines by simply adding the
;length of the line, stored in
;the table - LENTABLE. If we
;try to go past the EOT, then
;we call the BOTTOM routine.
;
DNSC	JSR	HOME
	LDY	#0
DNLOOP	LDA	TOPLN
	CLC
	ADC	LENTABLE,Y
	STA	TOPLN
	STA	CURMEM
	LDA	TOPLN+1
	ADC	#0
	STA	TOPLN+1
	STA	CURMEM+1
	INY
	CPY	#19
	BNE	DNLOOP
	LDA	MEMPNT+1
	CMP	CURMEM+1
	BCC	DNBT
	BEQ	DNCL
	BCS	DNSCO
DNCL	LDA	MEMPNT
	CMP	CURMEM
	BCC	DNSCO
DNBT	JMP	BOTTOM
DNSCO	JSR	SCRDRAW
	JMP	CHECKMEM
;
;Move Cursor Down a line
;
;This simply moves the cursor
;to the start of the line, then
;adds the length of the line to
;CURMEM. If the cursor is on
;the last line, we must first
;scroll the screen (to get the
;length of the next text line)
;and add this new length.
;
DNLN	JSR	BLINE
	LDX	CURY
	LDA	CURMEM
	CLC
	ADC	LENTABLE-1,X
	STA	CURMEM
	LDA	CURMEM+1
	ADC	#0
	STA	CURMEM+1
	CPX	#20
	BNE	DOVER
	TXA
	PHA
	LDA	CURX
	PHA
	LDA	TOPLN
	CLC
	ADC	LENTABLE
	STA	TOPLN
	LDA	TOPLN+1
	ADC	#0
	STA	TOPLN+1
	JSR	SCRDRAW
	PLA
	STA	CURX
	PLA
	STA	CURY
	LDX	#19
DOVER	LDA	LENTABLE,X
	CMP	CURX
	BCC	ADDONY
	LDA	CURX
ADDONY	TAY
	DEY
	JMP	ADDY2CP
;
;Move cursor Up a line
;
;This was the most difficult
;routine to write for T:EDIT.
;If the cursor is on any line
;but one, we simply goto the
;start of the line, subtract
;the length of the line before
;it and then check to see if
;the cursor Xpos is on the new
;line. If not we move to the
;end of the new line. If the
;cursor was on the TOP line, we
;run into the problem - How
;long is the line just off the
;top of the screen? - To figure
;this out I wrote a routine
;much like the BOTTOM routine +
;the SCRDRAW routine. It steps
;back 1K and 'draws the screen'
;until we find the cursor. When
;we are done with this, we know
;the length of the line just
;off the screen. Yeah! This
;little gem of an idea took
;weeks to form and a matter of
;hours to get to work. Enjoy.
;
UPLN	JSR	BLINE
	LDX	CURY
	CPX	#1
	BEQ	SCRLUP
	DEX
	DEX
	LDA	CURMEM
	SEC
	SBC	LENTABLE,X
	STA	CURMEM
	LDA	CURMEM+1
	SBC	#0
	STA	CURMEM+1
	JMP	DOVER
SCRLUP	JSR	MOVEUP
	LDX	CURMEM
	STX	TOPLN
	LDX	CURMEM+1
	STX	TOPLN+1
	CMP	CURX
	BCC	SCRLUY
	LDA	CURX
SCRLUY	TAY
	DEY
	JMP	ADDY2CP
;
;Move CURMEM up one line
;
;This routine HOME's the cursor
;then calls CUROFF, to calc.
;the length of the unseen line,
;If Y-reg = $FF, we are at the
;top of text and abort.
;
MOVEUP	JSR	HOME
	JSR	CUROFF
	STY	TEMP
	CPY	#$FF
	BNE	MVU
	RTS
MVU	LDA	CURMEM
	SEC
	SBC	TEMP
	STA	CURMEM
	LDA	CURMEM+1
	SBC	#0
	STA	CURMEM+1
	TYA
	RTS
;
;Move the cursor up one screen
;
;This simply calls MOVEUP 19
;times, and when we are done
;we call CHECKMEM to move the
;screen up.
;
UPSC	LDA	#0
	STA	LINES
UPSCL	JSR	MOVEUP
	LDA	CURMEM
	STA	TOPLN
	LDA	CURMEM+1
	STA	TOPLN+1
	INC	LINES
	LDA	LINES
	CMP	#19
	BNE	UPSCL
	JMP	CHECKMEM
;
;Delete to end of line
;
;This saves the CURMEM position
;moves to the EOL then deletes
;the text, very simple.
;
DEL2CR	JSR	ERAS1
	JSR	ENDLN
	LDA	SAVCUR
	SEC
	SBC	MEMPNT
	STA	TEMP
	LDA	SAVCUR+1
	SBC	MEMPNT+1
	ORA	TEMP
	BCS	DEL2CRLV
	LDA	CURMEM
	SEC
	SBC	MEMPNT
	STA	TEMP
	LDA	CURMEM+1
	SBC	MEMPNT+1
	ORA	TEMP
	BEQ	ERAS3
	BNE	ERAS2
;
;The following routines are the
;ones used to delete to the EOL.
;
ERAS1	LDA	CURMEM
	STA	DEST
	STA	SAVCUR
	LDA	CURMEM+1
	STA	DEST+1
	STA	SAVCUR+1
	RTS
;
ERAS2		BUMP CURMEM
ERAS3	SEC
	LDA	CURMEM
	STA	FROM
	SBC	SAVCUR
	STA	GOBLEN
	LDA	CURMEM+1
	STA	FROM+1
	SBC	SAVCUR+1
	STA	GOBLEN+1
	JSR	DELMEM
DEL2CRLV	LDA	SAVCUR
	STA	CURMEM
	LDA	SAVCUR+1
	STA	CURMEM+1
	JMP	CHECKMEM
;
;Delete all spaces from CURMEM
;to next non-space character.
;
;This simply moves the CURMEM
;to the next non-space char
;and deletes all chars between
;the original position and the
;new position.
;
KSPACE	LDA	CURMEM
	STA	TEXTP
	STA	DEST
	LDA	CURMEM+1
	STA	TEXTP+1
	STA	DEST+1
	LDY	#0
SPCFND	LDA	(TEXTP),Y
	BNE	OUTSPC
	INY
	BNE	SPCFND
	LDA	TEXTP+1
	CMP	MEMPNT+1
	BCC	GOINC
	LDA	MEMPNT
	STA	TEXTP
	LDA	MEMPNT+1
	STA	TEXTP+1
	LDY	#0
	BEQ	OUTSPC
GOINC	INC	TEXTP+1
	BNE	SPCFND
OUTSPC	CLC
	TYA
	ADC	TEXTP
	STA	FROM
	LDA	#0
	ADC	TEXTP+1
	STA	FROM+1
	SEC
	LDA	MEMPNT
	SBC	DEST
	STA	MOVELEN
	LDA	MEMPNT+1
	SBC	DEST+1
	STA	MOVELEN+1
	SEC
	LDA	FROM
	SBC	DEST
	STA	GOBLEN
	LDA	FROM+1
	SBC	DEST+1
	STA	GOBLEN+1
		BUMP MOVELEN
	JSR	UMOVE
	SEC
	LDA	MEMPNT
	SBC	GOBLEN
	STA	MEMPNT
	LDA	MEMPNT+1
	SBC	GOBLEN+1
	STA	MEMPNT+1
	RTS
;
;Find a string in memory
;
;These are the GLOBAL Search &
;REPLACE routines. If the
;Search string is equal in
;length to the Replace string
;the S&R goes very fast, else
;you might wait a little while
;
FIND		PRINT FINDM
	JSR	INPUT
	BCC	FINDOK
	RTS
FINDOK	LDA	CEND
	STA	SLEN
	LDY	#44
FNDMB	LDA	MYBUF,Y
	STA	SBUF,Y
	DEY
	BPL	FNDMB
GLOBL	JSR	CSRCH
	CMP	#$FF
	BEQ	NFND
		PRINT REPLM
	JSR	YN2
	BCS	NFND
GETREP		PRINT REPLW
	JSR	INPUT
	BCC	GLBREP
NFND	RTS
GLBREP	JSR	CSRCH
	LDA	FPOS+1
	CMP	#$FF
	BEQ	NFND
	JSR	REPL
	JSR	CHECKMEM
	JMP	GLBREP
CSRCH	LDA	CURMEM
	STA	TEXTP
	LDA	CURMEM+1
	STA	TEXTP+1
	LDY	#0
SRCH0	LDX	#0
SRCH1	LDA	SBUF,X
	JSR	ASC2IC
	CMP	(TEXTP),Y
	BEQ	CY
	CPX	#0
	BNE	SRCH0
	DEX
CY	INY
	BNE	NOVFL
	INC	TEXTP+1
	LDA	TEXTP+1
	CMP	MEMPNT+1
	BEQ	NOVFL
	BCS	NOTFOUND
NOVFL	INX
	CPX	SLEN
	BNE	SRCH1
	CLC
	TYA
	ADC	TEXTP
	STA	TEMP
	LDA	TEXTP+1
	ADC	#0
	STA	TEMP+1
	LDA	MEMPNT
	CMP	TEMP
	LDA	MEMPNT+1
	SBC	TEMP+1
	BCC	NOTFOUND
	SEC
	LDA	TEMP
	SBC	SLEN
	STA	CURMEM
	STA	FPOS
	LDA	TEMP+1
	SBC	#0
	STA	CURMEM+1
	STA	FPOS+1
	JSR	CHECKMEM
	LDY	#0
	LDA	(CURMEM),Y
	EOR	#$80
	STA	(CURMEM),Y
	JSR	SCRDRAW
	LDY	#0
	LDA	(CURMEM),Y
	EOR	#$80
	STA	(CURMEM),Y
	TYA
	RTS
NOTFOUND	LDA	#$FF
	STA	FPOS+1
	RTS
;
;This is the replace routine
;
REPL	SEC
	LDA	CURMEM
	STA	DEST
	SBC	FPOS
	STA	TEMP
	LDA	CURMEM+1
	STA	DEST+1
	SBC	FPOS+1
	ORA	TEMP
	BNE	NOREPL
	LDA	#$FF
	STA	FPOS+1
	CLC
	LDA	SLEN
	ADC	CURMEM
	STA	FROM
	LDA	#0
	ADC	CURMEM+1
	STA	FROM+1
	SEC
	LDA	MEMPNT
	SBC	DEST
	STA	MOVELEN
	LDA	MEMPNT+1
	SBC	DEST+1
	STA	MOVELEN+1
		BUMP MOVELEN
	LDA	SLEN
	CMP	CEND
	BEQ	DOREPC
	JSR	UMOVE
	SEC
	LDA	MEMPNT
	SBC	SLEN
	STA	MEMPNT
	LDA	MEMPNT+1
	SBC	#0
	STA	MEMPNT+1
	LDA	CEND
	STA	INSLEN
	LDA	#0
	STA	INSLEN+1
	JSR	INSBLOCK
DOREPC	LDY	#0
REPLOOP	LDA	MYBUF,Y
	JSR	ASC2IC
	STA	(CURMEM),Y
	INY
	CPY	CEND
	BNE	REPLOOP
	CLC
	LDA	CURMEM
	ADC	CEND
	STA	CURMEM
	LDA	CURMEM+1
	ADC	#0
	STA	CURMEM+1
NOREPL	JMP	CHECKMEM
;
;Convert char under cursor to
;UPPER if LOWER and LOWER if
;UPPER.
;
CONVERT	LDY	#0
	LDA	(CURMEM),Y
	AND	#63
	CMP	#33
	BCC	NOTALP
	CMP	#59
	BCS	NOTALP
	LDA	(CURMEM),Y
	EOR	#$40
	STA	(CURMEM),Y
NOTALP	JMP	GORIGHT
;
;This routine forms a line of
;text for the printer routine.
;If the end of text is reached
;it returns a $FF in LPLEN.
;else, it returns the CIO
;error code.
;
LPLINE	JSR	ERMYBF
	LDY	#0
PLOOP1	LDA	(TEXTP),Y
	CMP	#EOLCHAR
	BEQ	FOUNDSPACE
NOTRET	STA	MYBUF+4,Y	;LMARG=5
	INY
	CPY	#70	;70 chars?
	BCC	PLOOP1
	STY	LPLEN
FINDSPACE	LDA	(TEXTP),Y
	BEQ	FOUNDSPACE
	DEY
	BNE	FINDSPACE
	LDY	LPLEN
FSPACE	INY
	LDA	(TEXTP),Y
	BEQ	FOUNDSPACE
	DEY
FOUNDSPACE	STY	LPLEN
OVERSTOR	TYA
	SEC
	ADC	TEXTP
	STA	TEXTP
	LDA	TEXTP+1
	ADC	#0
	STA	TEXTP+1
	LDY	#0
MAKEASC	LDA	MYBUF+4,Y
	JSR	IC2ASC
	PHA
	AND	#$7F
	CMP	#$20
	BCS	CHR2BUF
	CLC
	ADC	#$C0
	TAX
	PLA
	TXA
	CMP	#$C0
	BNE	CHR2BUF1
	LDA	#EOL
CHR2BUF1	PHA
CHR2BUF	PLA
	STA	MYBUF+4,Y
	INY
	CPY	LPLEN
	BNE	MAKEASC
	LDA	#EOL
	STA	MYBUF+4,Y
	JSR	LPRINT
	BMI	LEAVELPL
	SEC
	LDA	TEXTP
	SBC	MEMPNT
	STA	TEMP
	LDA	TEXTP+1
	SBC	MEMPNT+1
	ORA	TEMP
	BCC	LEAVELP
	LDA	#$FF
	STA	LPLEN
LEAVELP	LDA	#0
LEAVELPL	RTS
;
;This routine counts the
;number of words in the text
;in memory. This is a true
;count, not faked by counting
;spaces and dividing by two.
;The count begins from the
;top of memory.
;
CNTWORD	LDA	MEMST
	STA	TEXTP
	LDA	MEMST+1
	STA	TEXTP+1
	LDA	#0
	STA	LO1
	STA	HI1
		PRINT WORDTXT
CNTWLP	JSR	GETWORD
	BCC	CNTOK
	LDY	#0
CNTDN	LDA	DIRPS+17,Y
	CMP	#EOL
	BEQ	CNTKEY
	JSR	ASC2IC
	STA	LN1+20,Y
	INY
	BNE	CNTDN
CNTKEY	JMP	GETKEY
CNTOK		BUMP LO1
	JSR	CONBCD
	LDY	#4
CNTCPY	LDA	ABUF+1,Y
	STA	LN1+14,Y
	DEY
	BPL	CNTCPY
	BMI	CNTWLP
;
;This routine finds a word in
;memory, it skips spaces until
;it hits a non-space, then
;looks for another space.
;Then we check if we are past
;the end of the text.
;
GETWORD	LDY	#0
GETW1	LDA	(TEXTP),Y
	AND	#$7F
	BEQ	GETUPL
	CMP	#EOLCHAR
	BNE	GOTWORD
GETUPL	INY
	BNE	GETW1
	INC	TEXTP+1
	JSR	WRDRTS
	BCC	GETW1
	RTS
GOTWORD	JSR	ENDWORD
	LDY	#0
GETWSPC	LDA	(TEXTP),Y
	AND	#$7F
	BEQ	ENDWORD
	CMP	#EOLCHAR
	BEQ	ENDWORD
	INY
	BNE	GETWSPC
	INC	TEXTP+1
	BNE	GETWSPC
ENDWORD	TYA
	CLC
	ADC	TEXTP
	STA	TEXTP
	BCC	WRDRTS
	INC	TEXTP+1
WRDRTS	LDA	TEXTP
	SEC
	SBC	MEMPNT
	STA	TEMP
	LDA	TEXTP+1
	SBC	MEMPNT+1
	ORA	TEMP
	BCC	WRDRTS2
	BEQ	WRDSET
WRDRTS2	RTS
WRDSET	CLC
	RTS

Listing 6.
TEDIT4.M65

;-------------------
;
;I/O Subroutines
;
;For the TEXT EDITOR
;
;FILE: IOSUB
;
;-------------------
;
;OPEN a file/device
;
;This routine will open whatever
;file or device is named in
;the string - FILNAM. It I/O
;mode is transfered in IODIR. It
;will also pause the VBI's.
;
OPENFIL	JSR	CLOSE1
	INC	PAUSE?
	LDX	#$10
	LDA	#3
	STA	ICCOM,X
	LDA	#<FILNAM
	STA	ICBAL,X
	LDA	#>FILNAM
	STA	ICBAH,X
	LDA	IODIR
	STA	AUX1,X
	LDA	#0
	STA	AUX2,X
	JMP	CIOV
;
;Close IOCB #1
;
CLOSE1	LDX	#$10
	LDA	#12
	STA	ICCOM,X
	JMP	CIOV
;
;Open Printer
;
OPENP	LDY	#2
OPENP1	LDA	PDEV,Y
	STA	FILNAM,Y
	DEY
	BPL	OPENP1
	LDA	#8
	STA	IODIR
	BNE	OPENFIL
;
;Custom Input Routine
;
;This is my famous INPUT routine
;that I used in DEBUG+ and
;about 10 other programs. It
;will fetch a 24 character
;string from the keyboard and
;return it in MYBUF, terminated
;by a EOL ($9B).
;
INPUT	LDA	#0	;length = 0
	STA	CEND
	INC	IPUT	;signal input
	JSR	ERMYBF	;and buffer
GETC	JSR	GETKEY	;get a key
	CMP	#27	;ESCape?
	BNE	GOTCHR	;nope.
	DEC	IPUT
	SEC		;signal error
	RTS		;and leave
GOTCHR	LDY	#ILEGS
	AND	#$7F
CHKLEG	CMP	ILLEG,Y
	BEQ	GETC
	DEY
	BPL	CHKLEG
	LDA	OLDAC
INPDEL	CMP	#126	;Delete?
	BNE	NOTDEL	;no.
	DEC	CEND	;lower length
	BPL	TS2	;<0? no.
	LDA	#0	;make zero.
	STA	CEND
TS2	JSR	TST1	;test length
	LDA	CEND	;get length
	BEQ	GETC	;if not 0 go!
	LDY	CEND	;put in a spc
	CPY	#24
	BNE	DODEL
	DEY
DODEL	LDA	#0
	STA	COMLN,Y	;erase char
	STA	COMLN+1,Y	;erase cursor
	BEQ	GETC	;get next.
NOTDEL	CMP	#156	;Delete Line?
	BEQ	GETC	;yes.
	LDY	CEND
	STA	MYBUF,Y
	CMP	#EOL	;EOL?
	BEQ	ATEND	;done!
	JSR	ASC2IC	;make icode
	CPY	#24
	BNE	SHCH
	DEY
SHCH	STA	COMLN,Y	;to screen
	INY
	CPY	#25
	BCC	TST9
	DEY
TST9	STY	CEND
	JSR	TST1	;length?
	JMP	GETC	;do again.
ATEND	LDA	MYBUF
	CMP	#EOL
	BEQ	INPUT
	LDA	#0
	STA	COMLN,Y	;erase cursor
	STA	IPUT
	CLC		;show good input
	RTS		;bye.
;
;Test INPUT length
;
TST1	LDA	CEND
	BNE	TL1
	STA	COMLN
	STA	COMLN+1
TL1	RTS
;
;Get and copy Filename
;
;This calls INPUT to fetch a
;filename, if ESC is pressed
;it returns to MAIN. Otherwise
;it converts the filename to
;upper-case and moves it to the
;FILNAMe buffer.
;If the user tried to use the
;E: or S: devices for file I/O
;the routine defaults to D:
;
COPFIL	JSR	INPUT
	BCC	COP0
	PLA
	PLA
	JMP	CLRWIN
;
COP0	LDX	#0
	LDA	MYBUF+1	;second char
	CMP	#':
	BEQ	YZERO
	LDA	MYBUF+2	;third char
	CMP	#':
	BEQ	YZERO
	LDY	#2
COP1	LDA	D1TXT,Y
	STA	FILNAM,Y
	DEY
	BPL	COP1
	LDY	#3
	BNE	COPMYBF
YZERO	LDY	#0
COPMYBF	LDA	MYBUF,X
	JSR	CONL2U
	STA	FILNAM,Y
	CMP	#EOL
	BEQ	COPFILD
	INY
	INX
	CPX	#25
	BNE	COPMYBF
COPFILD	LDA	FILNAM
	CMP	#'E
	BEQ	INSDD
	CMP	#'S
	BNE	COPFILD2
INSDD	LDA	#'D
	STA	FILNAM
COPFILD2	RTS
;
;Perform I/O Operation
;
PERFIO	LDX	#$10
	STA	ICCOM,X
	LDA	MEMST
	STA	ICBAL,X
	LDA	MEMST+1
	STA	ICBAH,X
	JMP	CIOV
;
;Convert lower to UPPER
;
;This simply check to see of
;the char is lower-case or a
;CONTROL character, if so it
;converts it to upper-case.
;
CONL2U	CMP	#EOL
	BEQ	CNNCR
	CMP	#123
	BCS	CNNCR
	CMP	#97
	BCC	CNL2
	SEC
	SBC	#$20
CNL2	CMP	#$20
	BCS	CNNCR
	CLC
	ADC	#$40
CNNCR	RTS
;
;LPRINT MYBUF to printer
;
;This is similar to the BASIC
;LPRINT statement. It sends
;MYBUF to the printer, setting
;a max output of 80 chars,
;terminated with an EOL.
;
LPRINTR	LDX	#$10
	LDA	#$09
	STA	ICCOM,X
	LDA	#<MYBUF
	STA	ICBAL,X
	LDA	#>MYBUF
	STA	ICBAH,X
	LDA	#80
	STA	ICBLL,X
	LDA	#0
	STA	ICBLH,X
	JMP	CIOV
;
;Print a CR to printer
;
;This simply sends out a blank
;line to the printer by first
;erasing MYBUF (a precaution)
;then putting an EOL in the
;first position in MYBUF, then
;it falls through to LPRINT.
;
LPCR	JSR	ERMYBF
	LDA	#EOL
	STA	MYBUF
;
;Print a line and check for
;page break.
;
;This first sends out the line
;in MYBUF, then bumps the
;number of lines printed,
;checks to see if we should do
;a FORM FEED, if so we do and
;then we increase the PAGENUM.
;If an error happens during the
;print LPRINT returns the CIO
;error code in the Y-reg.
;
LPRINT	JSR	LPRINTR
	BMI	LPERR
	INC	LINES
	LDA	LINES
	CMP	#62
	BCC	LPOUT
	LDA	#EOL
	STA	MYBUF
	JSR	LPRINTR
	JSR	LPRINTR
	JSR	LPRINTR
	INC	PAGENUM
	LDA	#0
	STA	LINES
LPOUT	LDA	#0
LPERR	RTS
;
;This is the directory routine.
;It first asks what drive to
;get the directory from (12348)
;and then will get and print
;the directory, putting 2 file-
;names per line.  If the end of
;the screen is reached before
;the directory is done, we will
;wait for a key, then clear the
;screen and start at the top
;again.
;
DODIR		PRINT DIRMS
	JSR	GETKEY
	LDY	#4
DIRLP1	CMP	DIRNUMS,Y
	BEQ	GOTDIRN
	DEY
	BPL	DIRLP1
	RTS
;
GOTDIRN	STA	DIRTXT+1
	LDY	#6
DIRLP2	LDA	DIRTXT,Y
	STA	FILNAM,Y
	DEY
	BPL	DIRLP2
	LDA	#6
	STA	IODIR
	JSR	CLOSE1
	JSR	OPENFIL	;open disk
	BPL	DIRGOOD
		PRINT DIRER
	JSR	CLOSE1
	DEC	PAUSE?
	JMP	GETKEY
DIRGOOD	JSR	CLRSCR
	LDA	#2
	CLC
	ADC	#<SCMEM
	STA	SCR
	LDA	#>SCMEM
	ADC	#0
	STA	SCR+1
	LDA	#0
	STA	COLS
	STA	LINES
DIRLP3	JSR	READIR
	BMI	DIRDONE
	LDY	#0
DIRLP4	LDA	MYBUF,Y
	CMP	#EOL
	BEQ	ENTRYFIN
	JSR	ASC2IC
	STA	(SCR),Y
	INY
	BNE	DIRLP4
ENTRYFIN	INC	COLS
	LDA	COLS
	CMP	#2
	BCC	ADD20
	LDA	#0
	STA	COLS
	INC	LINES
	LDA	LINES
	CMP	#20
	BEQ	PAUSEDIR
ADD20	LDA	SCR
	CLC
	ADC	#20
	STA	SCR
	LDA	SCR+1
	ADC	#0
	STA	SCR+1
	JMP	DIRLP3
;
PAUSEDIR		PRINT DIRPS
	JSR	GETKEY
	CMP	#27
	BEQ	DIRLEAVE
		PRINT DIRMS
	JMP	DIRGOOD
;
DIRDONE		PRINT DIRFN
	JSR	GETKEY
DIRLEAVE	JSR	CLOSE1
	DEC	PAUSE?
	JMP	CLRSCR
;
;This routine will get one
;directory entry from the disk
;and put it in MYBUF.
;
READIR	LDX	#$10
	LDA	#5
	STA	ICCOM,X
	LDA	#<MYBUF
	STA	ICBAL,X
	LDA	#>MYBUF
	STA	ICBAH,X
	LDA	#20
	STA	ICBLL,X
	LDA	#0
	STA	ICBLH,X
	JMP	CIOV
;
;This routine relies on the
;fact that all text is stored
;in ICODE in memory, else all
;is lost.
;
SCRDRAW	LDA	#2
	CLC
	ADC	#<SCMEM
	STA	SCR
	LDA	#>SCMEM
	ADC	#0
	STA	SCR+1
	LDA	TOPLN
	SEC
	SBC	MEMST
	STA	TEMP
	LDA	TOPLN+1
	SBC	MEMST+1
	ORA	TEMP
	BCS	ADROK
	LDA	MEMST
	STA	TOPLN
	LDA	MEMST+1
	STA	TOPLN+1
ADROK	LDA	TOPLN
	STA	TEXTP
	LDA	TOPLN+1
	STA	TEXTP+1
	LDX	#1
PPAGE	LDY	#0
PLINE	LDA	(TEXTP),Y
	STA	LBUFF,Y
	INY
	CMP	#$7F
	BNE	RCRET
	STX	CURY
	STY	CURX
	LDA	CHARUNDR
RCRET	AND	#$7F
	CMP	#EOLCHAR
	BEQ	BREAK
	CPY	#38
	BNE	PLINE
	DEY
SLOOP	LDA	(TEXTP),Y
	AND	#$7F
	CMP	#$7F
	BNE	NXCUR
	LDA	CHARUNDR
NXCUR	CMP	#0
	BEQ	SBRK	;IF = 0
	DEY
	BNE	SLOOP
	LDY	#37	;LINELEN-1
SBRK	INY
BREAK	STY	TEMP
	LDY	#0
COPY	LDA	LBUFF,Y
	STA	(SCR),Y
	INY
	CPY	TEMP
	BNE	COPY
	CLC
	TYA
	ADC	TEXTP
	STA	TEXTP
	LDA	TEXTP+1
	ADC	#0
	STA	TEXTP+1
	TYA
	STA	LENTABLE-1,X
CLRLN	CPY	#38
	BEQ	CLEARED
	LDA	#64	;SOME CHAR
	STA	(SCR),Y
	INY
	JMP	CLRLN
CLEARED	CLC
	LDA	SCR
	ADC	#40
	STA	SCR
	BCC	INCNOT
	INC	SCR+1
INCNOT	INX
	CPX	#21	;LINE COUNTER
	BEQ	PDONE
	JMP	PPAGE
PDONE	LDA	TEXTP
	STA	BOTSCR
	LDA	TEXTP+1
	STA	BOTSCR+1
	RTS
;
;This routine will find the
;length of the line just off
;the top of the screen.  Thus
;allowing the user to cursor
;off the top of the screen
;
CUROFF	LDA	CURMEM
	CMP	MEMST
	BNE	NPAST
	LDA	CURMEM+1
	CMP	MEMST+1
	BNE	NPAST
	LDY	#$FF
	RTS		;finished.
NPAST	LDA	#0
	STA	TEXTP
	LDA	CURMEM+1
	SEC
	SBC	#4
	STA	TEXTP+1
	CMP	MEMST+1
	BCS	NP1
	LDA	MEMST
	STA	TEXTP
	LDA	MEMST+1
	STA	TEXTP+1
NP1	LDY	#0
PLN1	LDA	(TEXTP),Y
	INY
	CMP	#EOLCHAR
	BEQ	BRKL
	CPY	#38
	BNE	PLN1
	DEY
SLP1	LDA	(TEXTP),Y
	BEQ	SPBRK
	DEY
	BNE	SLP1
	LDY	#37
SPBRK	INY
BRKL	CLC
	TYA
	ADC	TEXTP
	STA	TEXTP
	LDA	TEXTP+1
	ADC	#0
	STA	TEXTP+1
	CMP	CURMEM+1
	BCC	NP1
	LDA	TEXTP
	CMP	CURMEM
	BCC	NP1
ALLD	RTS