So, now that we can do screen dumps and engage the various printer control functions, how about a word processor? Sorry folks, but this is where your BASIC fails you utterly. It is just too slow for most people, especially if there is any input checking. So while there have been several valiant attempts at coding full-feature (or even not-so-full feature) word-processors in BASIC, all have the speed problem inherent in floating-point, interpretive high-level languages.
Now the good news. If all you need to do is write letters and other text that won’t require extensive editing, and you aren’t too annoyed by operating in FAST mode, then you can put together a workable “typewriter” in BASIC with a minimum of effort. Such a program is presented here. The program will print any selected number of columns, but it won’t right-justify. It uses one long string to hold the text, and employs string slicing to change/add/delete words. You could extend it to edit larger blocks (such as sentences and paragraphs), but keep in mind that the more programming you add the less space you have for text. Another BASIC drawback; it’s extravagant with memory. String slicing, while easy to implement, requires up to 3 times the length of the string during intermediate operations, so your practical limit is about 5K of text in 16K of memory, even with the most austere of BASIC drivers. However, it’s easy, relatively fast and quite workable, if you’re a reasonably good typist and don’t have to do extensive editing. The first three issues of SWN (through 1:2) were written on a slight variation of this very program shown below! Though I now use Memotext exclusively, my “Caveman WP” served me well for correspondence and even newslettering for quite some time. I hope it does the same for some of you.
First, a few notes are prescribed. To avoid the double line-feed problem when printing strings over 64 characters long, the program adjusts the line feed to 1/2 of normal when the line is over 64 spaces long. This is somewhat more reliable than the suggested “double CHR$ terminator,” on my printer this has on occasion caused “lock-up.” Though a little cumbersome, the alternative works every time. The first part of the program prints a graphic letterhead logo that you may have seen somewhere before. You can change this to whatever graphic creation you desire, or simply omit it. Control codes are accessed the same way as in the Demo, using a string to hold the control sequence and a subroutine to POKE it into the line 1 REM for execution. The text printing routine may look familiar; it is based on an example in the CIF manual. Array A holds the start position of each paragraph in the long text string; if you want more paragraphs, DIMension a larger array. By the way, the lines (830-834) that edit the string require that the string be stored twice; if you replaced these lines with the apparently simpler LET S$=S$(TO S-N1)+B$+S$(F+N1 TO), it takes THREE TIMES the length of the string during slicing. So although it’s a couple more program lines, step-at-a-time slicing is more memory efficient. This is, by the way, where you’ll bomb with out-of-memory code 4/831. Delete some luxuries until GOTO 830 keeps the program going. Operating instructions are given after the program listing.
CAVEMAN
Line 1 as per Conversion Table
1 REM ..(AS PER LISTING FROM SWN 1:3)
2 REM DONT DELETE
10 LET N0=0
11 LET N1=1
12 LET N2=2
14 LET N4=4
18 LET O0=10
20 LET T8=8000
22 LET H1=100
24 LET H4=N4*H1
35 LET P=N0
37 LET SC=704
38 LET PC=8900
45 LPRINT
50 GOSUB T8+H1
60 GOSUB 8300
100 LET Z$="[illegible]"
105 GOSUB T8
110 LET Z$="[illegible]"
115 GOSUB T8
120 LET Z$="[illegible]"
125 GOSUB T8
130 LET Z$="[illegible] CO."
135 GOSUB T8
140 LPRINT
145 GOSUB 8200
150 LPRINT "▒E";"PO B[illegible] 5177,"
155 LPRINT "▒E";"E[illegible], CA. 91734"
160 GOSUB T8+H4
165 IF P<>N0 THEN GOTO 187
170 PRINT "DATE=?";
175 INPUT D$
177 PRINT D$
178 PRINT "HEADING (H$)? 4 LINES"
180 DIM H$(N4,31)
182 FOR A=N1 TO N4
183 INPUT H$(A)
184 PRINT H$(A)
185 NEXT A
187 PRINT " LPRINT HEADING?"
188 PAUSE 40000
189 IF INKEY$<>"Y" THEN GOTO H4
190 LPRINT ,,,D$
191 LPRINT
192 LPRINT
193 FOR A=N1 TO N4
195 LPRINT H$(A)
197 NEXT A
198 IF P<>N0 THEN GOTO H4
200 CLS
205 PRINT "LETTER WRITER",,,," BY F. NACHBAUR"
210 PRINT ,,"NUMBER OF COLUMNS=?"
220 INPUT Z
300 DIM A(N1+O0)
305 LET S$=""
310 FOR P=1 TO O0
315 CLS
317 PRINT "PARAGRAPH ";P
318 IF P=O0 THEN PRINT "LAST PARAGRAPH"
320 GOSUB 500
325 LET S$=S$+R$
330 LET A(P+N1)=LEN S$
340 IF A(P+N1)=A(P) THEN GOTO H4-O0
350 NEXT P
390 LET P=P-N1
400 CLS
401 PRINT "[illegible]; [illegible]:"
402 PRINT ,,"""P"" TO PRINT TO PAPER"
403 PRINT """S"" TO SAVE "
405 PRINT """R"" TO REVIEW/EDIT"
406 PRINT """N"" TO START NEW LETTER"
409 PAUSE 40000
410 IF INKEY$="P" THEN GOTO 420
411 IF INKEY$="S" THEN SAVE "LETTE[illegible]"
413 IF INKEY$="R" THEN GOSUB 700
414 IF INKEY$="N" THEN RUN
415 GOTO H4
420 FOR D=N1 TO P
430 LET X$=S$(A(D)+N1 TO A(D+N1))
450 GOSUB 1000
460 NEXT D
465 LPRINT
470 LPRINT ,,,"S[illegible],"
475 FOR A=1 TO 5
480 LPRINT
485 NEXT A
490 LPRINT ,,,"F[illegible]N[illegible]"
495 STOP
500 LET R$=""
510 INPUT I$
520 LET R$=R$+I$
540 PRINT I$;
542 IF R$="" THEN RETURN
545 IF R$(LEN R$)="*" THEN GOTO 600
550 GOTO 510
600 FOR C=N1 TO INT (LEN R$/SC+N1)
630 CLS
640 LET D=SC*C
650 IF D>LEN R$ THEN LET D=LEN R$
660 PRINT R$(SC*(C-N1)+N1 TO D)
670 PAUSE H1*H4
680 NEXT C
690 RETURN
700 LET L=N0
705 FOR I=N1 TO P
710 LET R$=S$(A(I)+N1 TO A(I+N1))
720 GOSUB 600
722 IF INKEY$<>"E" THEN GOTO 850
725 PRINT AT O0*N2,N0;"EDIT LINE?"
730 INPUT A$
732 IF A$="R" THEN RETURN
735 IF A$="" THEN GOTO 850
740 LET L=VAL A$
745 PRINT AT O0*N2,O0/N2;"WORD"
750 INPUT A$
760 LET W=VAL A$-N1
770 LET N=N0
775 LET M=N1+A(I)+32*(L-1)
780 IF S$(M)=" " OR S$(M)="▒" THEN LET N=N+N1
785 IF N>W THEN GOTO T8/O0
790 LET M=M+N1
795 GOTO 780
800 LET S=M
805 LET M=M+N1
810 IF S$(M)=" " OR S$(M)="▒" THEN GOTO 820
815 GOTO 805
820 LET F=M
824 LET A$=S$(S TO F)
826 PRINT AT O0*N2,N0;" ";AT O0*N2,N0;A$
828 INPUT B$
829 IF B$="" THEN LET B$=A$
830 LET R$=S$( TO S-N1)+B$
831 LET Z$=S$(F+N1 TO )
832 LET S$=""
833 LET S$=R$+Z$
834 LET Z$=""
835 FOR A=I+N1 TO P+N1
840 LET A(A)=A(A)+LEN B$-LEN A$
845 NEXT A
847 GOTO 710
850 NEXT I
860 RETURN
1040 CLS
1050 LPRINT
1060 IF LEN X$>Z THEN GOTO 1100
1065 GOSUB 8200
1070 LPRINT X$( TO LEN X$-N1)
1090 RETURN
1100 LET Y=N0
1110 IF Y=Z THEN GOTO 1060
1120 LET Y$=X$(Z-Y)
1130 IF X$(Z+N1-Y)=" " OR X$(Z+N1-Y)="▒" OR Y$="-" OR Y$="," OR Y$="." OR Y$=";" OR Y$=":" OR Y$="?" OR Y$="▒" OR Y$=CHR$ 11 THEN GOTO 1170
1140 LET Y=Y+N1
1150 GOTO 1110
1170 LET Y$=X$( TO Z-Y)
1172 GOSUB 8200+50*(LEN Y$>64)
1175 LPRINT Y$
1180 LET X$=X$(Z+N1-Y TO )
1190 IF X$(N1)<>" " AND X$(N1)<>"▒" THEN GOTO 1060
1200 LET X$=X$(N2 TO )
1210 GOTO 1190
8000 FOR A=16514 TO 16513+LEN Z$
8020 POKE A,PEEK (16600+CODE Z$(A-16513))
8025 NEXT A
8030 POKE A,N0
8035 LPRINT "▒E▒"
8050 RETURN
8100 REM GR LF
8110 LET P$="▒7▒N▒ "
8120 GOTO PC
8200 REM LF=1/6
8210 LET P$="▒M "
8220 GOTO PC
8250 REM LF=1/12
8260 LET P$="▒N' "
8270 GOTO PC
8300 REM ENH
8310 LET P$="▒"+CHR$ 69+" "
8320 GOTO PC
8400 REM UNEN
8410 LET P$="▒"+CHR$ 70+" "
8420 GOTO PC
8500 REM 1 SHEET
8510 LET P$="▒S "
8520 GOTO PC
8550 REM FORM
8560 LET P$="▒T "
8570 GOTO PC
8900 FOR A=N1 TO LEN P$
8910 POKE 16513+A,CODE P$(A)
8920 NEXT A
8930 POKE A+16513,0
8950 LPRINT "[illegible]"
8960 RETURN
MEMOTECH I/F USERS:
Add the listing as shown to your line 1 REM ASCII buffer/ conversion table. Controls are handled just like in the demo, except that the strings are defined using the characters instead of CHR$ number to conserve space; only problem with this approach is that the inverse periods prevent LLISTing with the Memo I/F. (Which is why I made the listing on a 2040.) Also, BEWARE of inverse periods in your text!!! If unintentional, these will falsely flag the I/F that a control is coming, with a crash likely to result. You CAN use it to imbed “Group I” controls (see last issue) in your text; experiment.
TS2040 USERS:
You can use this program with your TS2040 with some simple changes. Delete lines 38, 50, 60. Change LET Z$= in lines 100, 110, 120, 130 to LPRINT commands (no need for graphics translation) and delete 105, 115, 125, and 135. Delete 145, remove the control codes for double width from 150 & 155. Delete lines 1065, 1172, and everything from 8000 on.
INSTRUCTIONS:
FAST mode is recommended, though SLOW will work. Enter RUN to start the program. It prints the letterhead, and prompts for date and heading (name and address). Pressing “Y” prints the date and heading. Enter number of columns desired (to 80, or 32 for TS2040). The program goes right on to the text input section, with paragraph 1 (which might be “Dear ??,” etc). Input as much or as little text as you like, and press enter whenever you feel like it to move the input line to the top part of the screen. To go on to the next paragraph, enter “*” (asterisk) as your last character. The completed paragraph is shown, press Enter to go on to the next. When entering a long paragraph, you might run out of screen; enter CONT to keep going. The first spaces of each paragraph are left alone, so you can indent by entering spaces.
When you’ve entered all your paragraphs, pressing ENTER (only) gets you out of “text creating” mode and goes on to the review/print menu. Press “R” to review; each paragraph is displayed in sequence. (If the paragraph is longer than one screen, then it is automatically split into two or more screens). Press any key (e.g. “R” or ENTER) to go on to the next screen or paragraph. If you find an error, press “E” (for edit). You are asked “which line;” count down how many lines (on the screen) the error is and enter the number. (If the error is in the second screen of a long paragraph, add 22 to the line number; e.g., the top line of the second screen would be 23, etc). At this point, you can also return to menu by entering “R” or to the next paragraph with ENTER only. Otherwise, you’re now asked “which word?” Count how many spaces occur on that line before the incorrect word; enter this and the word is brought down to line 22. (If it starts right at the edge of the line, enter 0. Negative numbers are allowed, so you can even “space back” to a previous line if you goofed on the line number.) Now re-type it as it should be, complete with leading AND trailing space (or inverse space; we’re using the I/F’s conversion table here); and the offending word will be replaced with the correct version and the paragraph reprinted. If you omit the leading or trailing space, then the word will be run together with the preceding or following word. To delete the word, enter a single space. To leave it the way it was, press ENTER only. With a little practice and experimentation you’ll quickly get the hang of it. The end of paragraph marker * is left in, but ignored in printing (actual limits are stored in array A, which is updated every time you make a change). Also, though the screen will show exactly as you typed and will make words wrap to the next line, your printed output will never split a word. See SWN through No. 2 for sample output. Build your own custom program from the pieces available here and elsewhere. You’ll find that this kind of programming can be rather fun… though I wouldn’t want to do it for a living!
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.