This program is a full-featured word processor. It stores the document as a single large string array `f$` dimensioned to a user-specified number of 32-character lines (up to 320 lines, 10,240 bytes). The editor supports cursor movement, word-wrap, tab stops, insert/delete of characters and lines, caps lock, a status bar on the lower screen, and cassette tape save/load of both the file and the program itself. Keyboard handling uses a two-level control scheme where Caps Shift keys dispatch to editing commands and a “Level Two” menu provides additional functions such as erasing the file, printing via LPRINT, and setting tab stops. Screen position tracking relies directly on system variables at addresses 23688 (column) and 23689 (row) rather than maintaining separate cursor variables.
Program Analysis
Program Structure
The program is organised into clearly labelled functional blocks separated by REM statements. Execution begins at line 15 with a GO TO 3000 for initialisation, then falls into the main edit loop at line 20. The broad structure is:
- Lines 20–99: Main edit loop — display, cursor rendering, key polling, character insertion, and word-wrap logic.
- Lines 100–290: Control-key dispatch table; each Caps Shift key (codes 1–28) jumps to
100+10*a, placing handlers at lines 100, 110, 120, …, 280. - Lines 300–320: Symbol Shift and extended key handling.
- Lines 400–442: Delete-character routine with held-key repeat detection via
IN 61438/IN 65278. - Lines 500–609: “Level Two” command menu, dispatching on digit keys to secondary functions.
- Lines 840–848: Jump-to-line function.
- Lines 1000–1044: Toggle switches (beep, status, word-wrap) and status-bar subroutine.
- Lines 1090–1177: Erase file, print via LPRINT, and tab-stop setup.
- Lines 1380–1389: STOP / exit to BASIC.
- Lines 2000–2098: Menu display (help screen).
- Lines 2100–2196: Save/Load menu with five options.
- Lines 3000–3098: Initialisation — prompts for file size, dimensions arrays, sets defaults.
- Lines 4000–5010: Stubs for 80-column print and spare control (both jump to non-existent line 350).
Document Storage Model
The entire document is held in a single string variable f$, dimensioned to bmax characters where bmax = 32 * lmax and lmax is the user-specified line count (1–320). Each 32-character slice of f$ corresponds to one screen line. The variable by is the logical byte-offset cursor into f$ (1-based). A blank-line buffer e$ is a 32-space string used for padding during insert/delete operations. The tab-stop map is held in t$(32), a one-character-per-column string where "1" marks a tab stop.
Key Polling and Auto-Repeat
The main loop at line 40 polls INKEY$ directly, rejecting codes below 4 (pure shift keys). A simple software auto-repeat mechanism uses variables a (last key code) and c (countdown): on a first press c is set to 12, and subsequent loops decrement it before accepting the key again, producing a short initial delay before repeat. The delete routine (line 400–442) uses a tighter hardware-level repeat: it reads the keyboard matrix ports IN 61438 (half-row containing 0) and IN 65278 (half-row containing Caps Shift) to detect whether both Delete keys are still held, with a small counter dcnt providing a secondary delay before rapid deletion begins. OUT 255,64 and OUT 255,0 bracket the delete loop, presumably driving an external device or the border.
System Variable Manipulation
Rather than tracking screen cursor position in BASIC variables, the program reads and writes the Spectrum system variables directly:
| Address | System Variable | Usage |
|---|---|---|
| 23562 | ERR_SP / FLAGS | Set to 1 (edit mode) or 5 (suppress error reports) |
| 23658 | FLAGS2 | POKEd 8 to set caps-lock flag, 0 to clear |
| 23684–23685 | DF_CC (display file cursor low/high byte) | Direct cursor repositioning within the display file |
| 23688 | S_POSN column | Current print column; used to compute horizontal offsets |
| 23689 | S_POSN row | Current print row; used to detect screen boundaries |
| 23560 | LAST_K | Read directly for Level Two menu key detection after PAUSE 0 |
| 65528–65535 | RAM top area | POKEd during init; likely clears UDG area or interrupt vector |
This direct manipulation allows the program to reposition the print position after redrawing the screen without issuing a fresh PRINT AT, and to compute the cursor’s logical document position from by and the column/row registers.
Word-Wrap Algorithm
Word-wrap (lines 100–118) is triggered when the column counter (PEEK 23688) reaches 2 or below and the character being typed is not a space or hyphen. The routine scans backwards in f$ up to 20 characters for the last space or hyphen (line 112), then uses a string slice assignment to shuffle characters: f$(by-i TO by-1+i)=e$(1 TO i)+f$(by-i TO by-1) inserts i spaces at the split point to push the wrapped word to the next line. The system variable DF_CC and column register are then adjusted to match.
Level Two Command Dispatch
Pressing Caps Shift + key 1 (code 1) enters “Level Two” at line 500. The menu waits for a digit key 0–9 (ASCII 48–57) and dispatches via GO TO 600+k-48, producing jump targets at lines 600–609. Each of these is a single GO TO stub pointing to the real handler, creating a clean indirection table:
- 600 → 152 (delete line)
- 601 → 520 (exit level two)
- 602 → 1170 (set tabs)
- 603 → 1010 (status toggle)
- 604 → 1000 (beep toggle)
- 605 → 1020 (wrap toggle)
- 606 → 2100 (tape save/load)
- 607 → 1090 (erase file)
- 608 → 1150 (print)
- 609 → 141 (insert line)
ON ERR Usage
The program uses the TS2068 ON ERR keyword (displayed here as { per preprocessing rules — but written as ON ERR in the source) at several points: line 25 redirects tape errors and user breaks back to the main loop at line 40; line 1151 catches printer errors; line 2102 catches tape errors in the save/load section; and line 1388 calls RESET followed by STOP to cleanly exit. This confirms the program targets the TS2068, which has ON ERR as a native keyword.
Status Bar
The lower screen (stream #1) provides a persistent status bar. Subroutine 1030 draws a row of inverse-video spaces on row 0 and a blank line on row 1. Subroutine 1040/90 overlays live cursor position information: horizontal offset (34-PEEK 23688), vertical position (25-PEEK 23689), and logical line number (1+INT((by-1)/32)). Toggle states CAPS, BEEP, and WRAP are also displayed in fixed columns of the status line.
Tape Save/Load
The save/load section (lines 2100–2196) offers five options. Options 1 and 4 use SAVE/LOAD q$ DATA f$() to serialise or restore just the document array, allowing the program itself to remain in RAM. Option 2 uses SAVE q$ LINE 20 to save the whole program with auto-run at line 20, which also preserves the current f$ contents embedded in the saved file. Option 3 resets bmax=1 and re-dimensions f$(1) before saving, stripping the document to save tape space. Verify prompts follow each save operation.
Notable Anomalies and Observations
- Lines 120, 130, 260, 270, 280, 290 all contain only
GO TO 40; these are placeholder stubs for Caps Shift codes 2, 3, 6, 7, 8, and 9 that have real handlers elsewhere but are reached via theGO TO 100+10*adispatch — code 2 (Caps Lock) is actually at 160, code 3 (TAB) at 140, etc., so lines 120/130 being simple pass-throughs is consistent. - Line 87 uses
f$(x-95 TO x), which could produce a negative index ifxis small; this path is only taken whenx < bmax-32but the guard onxbeing large enough for the 96-character back-window is implicit rather than explicit. - Lines 4000 and 5010 jump to line 350, which does not exist. These are declared stubs for “80-column print” and “spare control” features that were never implemented.
- Line 522 and 1030 use
\uescape sequences to print UDG character ‘u’ (char 157) filling the top status row — this is used as a solid inverse block to create the status-bar background. - The
POKE 23562,1at line 22 sets the error stack pointer flag to suppress the normal “0 OK” report, keeping the lower screen clean for the status bar.
Content
Source Code
1 REM ***TYPEWRITER***
2 REM VERSION: 841009
5 REM A public-domain word- processor written by Jack Dohany
6 REM (415) 321-7684
10 REM OK TO RUN
15 GO TO 3000: REM INIT
19 BORDER 0: PAPER 0: INK 7
20 CLS : GO SUB 1030
21 LET a=0: LET c=0
22 POKE 23562,1
25 ON ERR GO TO 40
26 LET y=703: IF y>bmax THEN LET y=bmax
27 LET by=1: PRINT f$(by TO y);AT 0,0;
30 PRINT OVER 1; INVERSE 1;" ";CHR$ 8;
31 IF s=0 THEN GO TO 40
32 GO SUB 90
40 IF INKEY$="" THEN LET a=0: GO TO 40
42 LET b=CODE INKEY$: IF b<4 THEN GO TO 40
44 IF a<>b THEN LET a=b: LET c=12: GO TO 50
49 IF c>0 THEN LET c=c-1: GO TO 40
50 IF a<32 OR a>127 THEN GO TO 300
60 IF beep=1 THEN BEEP .002,25
70 IF by>=bmax-1 THEN GO TO 98
80 LET f$(by)=CHR$ a: LET by=by+1
81 IF wrap=1 THEN GO TO 100
82 IF PEEK 23689<5 AND PEEK 23688<3 THEN GO TO 86
84 PRINT CHR$ a;: GO TO 30
86 CLS : LET x=32*INT ((by-1)/32)
87 IF x<bmax-32 THEN BEEP .008,30: PRINT f$(x-95 TO x);: GO SUB 1030: GO TO 30
88 PRINT f$(x-639 TO x);: GO TO 30
90 PRINT #1;AT 1,7;34-PEEK 23688;" ";AT 1,11;25-PEEK 23689;" ";AT 1,15;1+INT ((by-1)/32);" "
92 RETURN
98 PRINT '"END OF FILE": GO TO 40
100 REM WRAP?
102 IF PEEK 23688>2 THEN GO TO 82
104 IF CHR$ a=" " OR CHR$ a="-" THEN GO TO 82
106 IF PEEK 23689<4 THEN GO TO 82
110 REM WRAP!
112 BEEP .02,27: FOR i=1 TO 20: IF f$(by-i-1)=" " OR f$(by-i-1)="-" THEN GO TO 116
114 NEXT i: GO TO 82
116 LET f$(by-i TO by-1+i)=e$(1 TO i)+f$(by-i TO by-1)
117 POKE 23688,PEEK 23688+i-1: POKE 23684,PEEK 23684-i+1: PRINT f$(by-i TO by-1+i);: LET by=by+i
118 GO TO 30
120 GO TO 40
130 GO TO 40
140 GO TO 171: REM tab
141 REM INSERT LINE
142 LET x=PEEK 23688: LET y=PEEK 23689: LET f$(by+x-1 TO bmax)=e$+f$(by+x-1 TO bmax-32)
143 PRINT 'f$(by+x-1 TO by+x-3+32*(y-3));: PRINT AT 24-y,33-x;
144 GO TO 500
150 GO TO 840: REM jump
152 REM DELETE LINE
154 LET by=1+(32*INT (by/32)): POKE 23684,PEEK 23684-(33-PEEK 23688): POKE 23688,33
155 LET f$(by TO bmax)=f$(by+32 TO bmax)+e$
156 LET s1=PEEK 23684: LET s2=PEEK 23685: LET s3=PEEK 23688: LET s4=PEEK 23689: PRINT f$(by TO by-1+32*(s4-2));
157 POKE 23684,s1: POKE 23685,s2: POKE 23688,s3: POKE 23689,s4
158 PRINT OVER 1; INVERSE 1;" ";CHR$ 8;
159 GO TO 500
160 REM CAPS
161 LET cs=1-cs
162 IF cs=1 THEN POKE 23658,8
163 IF cs=0 THEN POKE 23658,0
164 PRINT #1;AT 1,0;" "
165 IF cs=1 THEN PRINT #1;AT 1,0;"CAPS"
166 GO TO 40
170 GO TO 500: REM command
171 LET hp=34-PEEK 23688: REM TAB
172 IF hp>31 THEN GO TO 175
173 FOR i=hp+1 TO 32: IF t$(i)="1" THEN GO TO 177
174 NEXT i
175 FOR i=1 TO hp-1: IF t$(i)="1" THEN GO TO 177
176 NEXT i: GO TO 40
177 LET tab=i-1: PRINT OVER 1; INVERSE 1;" ";CHR$ 8;
178 POKE 23684,PEEK 23684-(33-PEEK 23688)+tab: POKE 23688,33-tab
179 LET by=1+(32*INT (by/32))+tab: GO TO 30
180 REM LEFT
181 IF PEEK 23689>23 AND PEEK 23688>32 THEN GO TO 40
182 PRINT OVER 1; INVERSE 1;" ";CHR$ 8;CHR$ 8;: LET by=by-1
186 GO TO 30
190 REM RIGHT
191 IF by>=bmax-1 OR (PEEK 23689<4 AND PEEK 23688<3) THEN GO TO 30
192 PRINT OVER 1; INVERSE 1;" ";: LET by=by+1: GO TO 30
200 REM DOWN
201 IF PEEK 23689<4 THEN GO TO 205
202 PRINT OVER 1; INVERSE 1;" ";CHR$ 8;: POKE 23689,PEEK 23689-1
203 IF PEEK 23689=16 OR PEEK 23689=8 THEN POKE 23684,33-PEEK 23688: POKE 23685,PEEK 23685+8: LET by=by+32: GO TO 30
204 POKE 23684,PEEK 23684+32: LET by=by+32: GO TO 30
205 IF by>(bmax-32) THEN GO TO 40
206 LET s1=PEEK 23688: LET s2=PEEK 23689: LET s3=PEEK 23684: LET s4=PEEK 23685: LET by=by+32: LET x=1+(32*INT (by/32))
207 CLS : PRINT f$(x-672 TO x+31);: POKE 23688,s1: POKE 23689,s2: POKE 23684,s3: POKE 23685,s4: PRINT ;: GO SUB 1030: GO TO 30
210 REM UP
211 IF PEEK 23689>23 THEN GO TO 215
212 PRINT OVER 1; INVERSE 1;" ";CHR$ 8;: POKE 23689,PEEK 23689+1
213 IF PEEK 23689=17 OR PEEK 23689=9 THEN POKE 23684,PEEK 23684+224: POKE 23685,PEEK 23685-8: LET by=by-32: GO TO 30
214 POKE 23684,PEEK 23684-32: LET by=by-32: GO TO 30
215 IF by<33 THEN BEEP .02,20: GO TO 40
216 LET s1=PEEK 23688: LET s2=PEEK 23689: LET s3=PEEK 23684: LET s4=PEEK 23685: LET by=by-32: LET x=1+(32*INT (by/32))
217 CLS : PRINT f$(x TO x+703);: POKE 23688,s1: POKE 23689,s2: POKE 23684,s3: POKE 23685,s4: PRINT ;: GO SUB 1030: GO TO 30
220 REM DELETE CH
221 IF by<2 THEN GO TO 40
222 GO TO 400
230 REM ENTER
231 LET x=32*INT ((by-1)/32): IF x>=bmax-32 THEN PRINT "FILE FULL": GO TO 40
232 PRINT OVER 1; INVERSE 1;" ";CHR$ 8;
233 IF PEEK 23689<4 THEN GO TO 236
235 PRINT CHR$ 13;: LET by=33+x: GO TO 30
236 CLS : PRINT f$(x-639 TO x+31);AT 21,0;: LET by=33+x: GO SUB 1030: GO TO 30
250 REM INSERT SP
252 IF by>=bmax OR (PEEK 23689<4 AND PEEK 23688<4) THEN BEEP .01,20: GO TO 40
254 LET by=by+1: PRINT " ";: LET s1=PEEK 23684: LET s2=PEEK 23685: LET s3=PEEK 23688: LET s4=PEEK 23689
255 LET f$(by-1 TO by+s3-2)=" "+f$(by-1 TO by+s3-3)
256 PRINT f$(by TO by+s3-2);: POKE 23684,s1: POKE 23685,s2: POKE 23688,s3: POKE 23689,s4: GO TO 30
260 GO TO 40
270 GO TO 40
280 GO TO 40
290 GO TO 40
300 REM CS&SS KEYS
301 IF a<32 THEN GO TO 100+10*a
302 IF a=226 THEN GO TO 1380
303 IF a=197 THEN LET a=164: GO TO 60: REM UNDERLINE
304 IF a=199 THEN GO SUB 2000: GO TO 20
305 IF a=195 THEN LET a=123: GO TO 60
306 IF a=205 THEN LET a=125: GO TO 60
307 IF a=201 THEN LET a=127: GO TO 60
308 IF a=204 THEN LET a=91: GO TO 60
309 IF a=200 THEN LET a=92: GO TO 60
310 IF a=203 THEN LET a=93: GO TO 60
320 GO TO 40
400 REM DELETE
402 OUT 255,64
404 LET dcnt=10
410 IF by<2 THEN OUT 255,0: GO TO 40
414 LET by=by-1: PRINT OVER 1; INVERSE 1;" ";CHR$ 8;CHR$ 8;: LET s1=PEEK 23688: LET s2=PEEK 23689: LET s3=PEEK 23684: LET s4=PEEK 23685
418 LET f$(by TO by+s1-1)=f$(by+1 TO by+s1-2)+" "
424 PRINT f$(by TO by+s1-2);: POKE 23688,s1: POKE 23689,s2: POKE 23684,s3: POKE 23685,s4
428 PRINT OVER 1; INVERSE 1;" ";CHR$ 8;
429 IF s=1 THEN GO SUB 90
430 IF IN 61438=30 AND IN 65278=30 THEN GO TO 440
432 OUT 255,0: GO TO 31
440 IF dcnt=0 THEN GO TO 410
442 LET dcnt=dcnt-1: GO TO 430
500 REM LEVEL TWO
501 PRINT #1;AT 0,0;" **LEVEL TWO** "
502 PAUSE 0: LET k=PEEK 23560
506 IF k=13 THEN GO TO 520
508 IF k<48 OR k>57 THEN GO TO 500
510 BEEP .01,20
512 GO TO 600+k-48
520 REM exit edit-mode
522 PRINT #1;AT 0,0;"\u\u\u\u\u\u\u\u\u\u\u\u\u\u\u\u\u\u\u\u\u\u\u\u\u\u\u\u\u\u\u\u"
524 GO TO 31
600 GO TO 152: REM delete ln
601 GO TO 520: REM exit
602 GO TO 1170: REM set tabs
603 GO TO 1010: REM status sw
604 GO TO 1000: REM beep sw
605 GO TO 1020: REM wrap sw
606 GO TO 2100: REM tape
607 GO TO 1090: REM erase
608 GO TO 1150: REM print
609 GO TO 141: REM insert ln
840 REM JUMP
841 INPUT ("JUMP TO LINE (1-";lmax;"): "); LINE q$: IF q$="" THEN GO TO 40
842 LET fl=VAL q$
843 LET by=1+(32*(fl-1))
844 LET tb=by+703: IF tb>bmax THEN LET tb=bmax
848 CLS : PRINT f$(by TO tb);AT 0,0;: LET cm=0: GO SUB 1030: GO TO 30
1000 REM BEEP SW
1002 LET beep=1-beep
1004 PRINT #1;AT 1,20;" "
1006 IF beep=1 THEN PRINT #1;AT 1,20;"BEEP"
1008 GO TO 502
1010 REM STATUS SW
1012 LET s=1-s
1014 PRINT #1;AT 1,6;" "
1016 IF s=1 THEN GO SUB 1040
1018 GO TO 502
1020 REM WRAP SW
1022 LET wrap=1-wrap
1024 PRINT #1;AT 1,26;" "
1026 IF wrap=1 THEN PRINT #1;AT 1,26;"WRAP"
1028 GO TO 502
1030 PRINT #1;AT 0,0;"\u\u\u\u\u\u\u\u\u\u\u\u\u\u\u\u\u\u\u\u\u\u\u\u\u\u\u\u\u\u\u\u";AT 1,0;e$(1 TO 31)
1031 IF s=1 THEN GO SUB 1040
1032 IF cs=1 THEN PRINT #1;AT 1,0;"CAPS"
1034 IF beep=1 THEN PRINT #1;AT 1,20;"BEEP"
1036 IF wrap=1 THEN PRINT #1;AT 1,26;"WRAP"
1038 RETURN
1040 REM print status
1042 PRINT #1;AT 1,6;"H";34-PEEK 23688;" ";AT 1,10;"V";25-PEEK 23689;" ";AT 1,14;"L";1+INT ((by-1)/32);" "
1044 RETURN
1090 REM ERASE FILE
1092 INPUT "ERASE FILE? (Y=YES)"; LINE q$: IF q$="y" OR q$="Y" THEN DIM f$(bmax): GO TO 20
1094 GO SUB 1030: GO TO 500
1150 REM PRINT
1151 ON ERR GO TO 1158
1152 INPUT ("PRINT FROM LINE (1-";lmax;"): "); LINE q$: IF q$="" THEN GO TO 1158
1153 LET fl=VAL q$: LET fb=1+(32*(fl-1)): IF fl>lmax THEN GO TO 1152
1154 INPUT ("PRINT LINE ";fl;" TO:(";fl+1;"-";lmax;"): "); LINE q$
1155 IF q$="" THEN LET tb=bmax: GO TO 1157
1156 LET tb=32+(32*(VAL q$-1)): IF fb>=tb THEN GO TO 1152
1157 LPRINT f$(fb TO tb)
1158 BEEP .01,25: PAUSE 100: ON ERR GO TO 40: GO TO 20
1170 REM SET TABS
1171 INPUT "SET TABS (1-32)/ENT=done: "; LINE q$: IF q$="" THEN GO SUB 1030: GO TO 500
1172 DIM t$(32)
1173 LET tab=INT VAL q$: IF tab<1 OR tab>32 THEN GO TO 1176
1174 LET t$(tab)="1"
1176 INPUT "SET TABS (1-32)/ENT=done: "; LINE q$: IF q$="" THEN GO SUB 1030: GO TO 500
1177 GO TO 1173
1380 REM STOP
1382 CLS : PRINT AT 10,0;"TO RETURN, GO TO 20."
1384 POKE 23562,5
1388 ON ERR RESET : STOP
1389 GO TO 20
2000 REM MENU
2010 CLS
2015 PRINT TAB 4;"(Caps Shift)";TAB 18;"(Unshifted)"
2016 PRINT "KEY LEVEL ONE";TAB 18;" LEVEL TWO"
2020 PRINT "\u\u\u \u\u\u\u\u\u\u\u\u\u\u\u \u\u\u\u\u\u\u\u\u\u\u"
2022 PRINT " 1";TAB 4;"CHANGE LEVEL";TAB 18;"CHANGE LEVEL"
2024 PRINT " 2 CAPS LOCK";TAB 18;"SET TABS 1-32"
2026 PRINT " 3 TAB";TAB 18;"STATUS ON/OFF"
2028 PRINT " 4 JUMP TO LINE";TAB 18;"BEEP ON/OFF"
2030 PRINT " 5 LEFT";TAB 18;"WRAP ON/OFF"
2032 PRINT '" 6 DOWN";TAB 18;"TAPE"
2034 PRINT " 7 UP";TAB 18;"ERASE FILE"
2036 PRINT " 8 RIGHT";TAB 18;"PRINT 2040"
2038 PRINT " 9 INSERT SPACE";TAB 18;"INSERT LINE"
2040 PRINT " 0 DELETE LEFT";TAB 18;"DELETE LINE"
2042 PRINT '"KEY SYMBOL SHIFT";TAB 18;"-For fast key"'"\u\u\u \u\u\u\u\u\u\u\u\u\u\u\u";TAB 18;" response,"
2044 PRINT " A STOP";TAB 18;" turn off BEEP"
2046 PRINT " Q MENU";TAB 18;" and STATUS."
2048 PRINT " U UNDERLINE"
2090 PRINT #1;AT 0,0;"COPY?"
2092 PAUSE 0: IF INKEY$="y" THEN COPY : RETURN
2098 RETURN
2100 REM SAVE/LOAD
2102 ON ERR GO TO 2170: POKE 23562,5
2104 GO SUB 2190
2110 PAUSE 0: LET a=PEEK 23560: PRINT AT 20,0;e$: IF a<49 OR a>53 THEN GO TO 2110
2112 GO TO 2120+10*(a-49)
2120 REM SAVE FILE
2122 INPUT "FILE NAME: ";q$: IF q$="" THEN GO TO 2104
2124 SAVE q$ DATA f$()
2125 GO SUB 2190: PRINT AT 20,0;"VERIFY? (y/n) ": PAUSE 0: IF INKEY$="y" THEN PRINT "REWIND, then press PLAY": VERIFY q$ DATA f$(): GO SUB 2190: PRINT AT 20,0;"VERIFY OK.": GO TO 2110
2126 GO TO 2110
2130 REM SAVE PR & FL
2132 INPUT " ENTER PROGRAM NAME: ";q$: IF q$="" THEN LET q$="TYPEWRITER"
2134 SAVE q$ LINE 20
2135 GO TO 2145
2140 REM SAVE PROG
2142 PRINT AT 20,0;"ARE YOU SURE?": PAUSE 0: IF INKEY$<>"y" THEN GO TO 2110
2144 PRINT AT 20,0;e$: LET bmax=1: DIM f$(1): SAVE "TYPEWRITER"
2145 GO SUB 2190: PRINT AT 20,0;"VERIFY? (y/n) ": PAUSE 0: IF INKEY$="y" THEN PRINT AT 20,0;"REWIND, then press PLAY": VERIFY "": GO SUB 2190: PRINT AT 20,0;"VERIFY OK.": GO TO 2110
2146 GO TO 2110
2147 GO TO 20
2150 REM LOAD FILE
2151 INPUT "Enter File Name: ";q$: PRINT AT 20,0;"LOADING ";q$
2152 LOAD q$ DATA f$()
2153 BEEP .01,25: LET bmax=LEN f$(): LET lmax=INT (bmax/32)
2154 PRINT AT 20,0;e$;AT 20,0;q$;" LOADED. ": GO TO 2110
2160 REM RETURN
2162 IF bmax<2 THEN GO TO 3000
2164 GO TO 20
2170 GO SUB 2190: PRINT AT 20,0;"TAPE ERROR...or BREAK pressed.": GO TO 2110
2190 REM SL-MENU
2192 CLS : PRINT AT 0,0;" *** SAVE / LOAD ***"
2194 PRINT ''"1: SAVE FILE"''"2: SAVE PROGRAM AND FILE"''"3: CLEAR FILE AND SAVE PROGRAM"''"4: CLEAR FILE AND LOAD FILE"''"5: RETURN"
2196 RETURN
3000 REM INITIALIZATION
3005 BORDER 0: PAPER 0: INK 7: CLS
3010 PRINT AT 0,5;"*** TYPEWRITER ***"
3011 PRINT AT 10,0;"Greetings! You have no file."''"Please tell me how big"'"a file you need...that is,"'"how many lines maximum: from"'"1 to 320:"''"(A large file takes longer to"'"save on tape.)"
3012 INPUT "FILE SIZE (1-320): ";lmax: LET lmax=INT lmax: IF lmax<1 OR lmax>320 THEN PRINT "Please Try again.": GO TO 3012
3013 CLS
3015 DIM t$(32): LET wrap=1: LET cs=0: LET s=1: LET beep=1: LET e$=" "
3016 FOR i=1 TO 32 STEP 4: LET t$(i)="1": NEXT i
3017 POKE 65528,255: FOR i=65529 TO 65535: POKE i,0: NEXT i
3018 LET bmax=32*lmax: DIM f$(bmax): LET by=1
3040 CLS : PRINT AT 10,0;"Your file has ";lmax;" lines."''"Would you like to see the menu?"
3042 PAUSE 0: IF INKEY$="y" THEN GO SUB 2000: GO TO 20
3098 GO TO 20
4000 REM print 80-col
4010 GO TO 350
5000 REM spare control
5010 GO TO 350
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.


