This program is a full-featured word processor, storing up to 5,120 characters of text in a single large string array A$(5120). It supports paged display (640 characters per page), a cursor-based edit mode with character insert, delete, and replace operations, as well as text-flow utilities that remove double spaces and re-join split words across line boundaries. The program uses inverse-video characters (CHR$ 128–255 range) via the cursor routines at lines 1000–1070 to highlight the current edit position within the text. Output can be directed to the screen (“LOOK”), printer (LPRINT), or saved to tape.
Program Analysis
Program Structure
The program is organized as a collection of numbered routines, with a dispatcher at lines 15–70 forming the main entry/edit loop and line 5000 as the title-screen menu. Control flow is entirely via GOTO and GOSUB rather than structured loops, which is typical for BASIC word-processor programs of this era.
| Line Range | Function |
|---|---|
| 3 | Bootstrap jump to start-up menu (line 5000) |
| 15–70 | Main entry loop: display page, accept command string, dispatch |
| 100–140 | Tape SAVE routine |
| 999–1070 | Cursor highlight/restore subroutine (inverse video) |
| 2000–2520 | “LINE” command — re-join words split across line boundaries |
| 3000–3194 | “SPACE” command — collapse runs of more than one space |
| 4000–4067 | Search routine |
| 4500–4610 | Edit menu display |
| 5000–5075 | Title/main menu screen |
| 5490–5599 | Command reference screen |
| 6000–6010 | LPRINT (print to paper) |
| 6200–6270 | “LOOK” — scroll text to screen with optional copy/pause |
| 7000–7999 | Full edit mode (cursor movement, delete, insert, replace) |
| 8000–8100 | Page selection subroutine |
| 9000–9090 | New-file initialisation (clears and dimensions A$) |
Text Storage Model
All document text is held in the single string array A$(5120), treated as a flat byte buffer. The variable BOT acts as a “next free” pointer into this buffer, and PAGE is always a multiple of 640, giving the end address of the currently displayed page (each page holds 640 characters, matching 20 lines × 32 columns). The display window is always A$(PAGE-639 TO PAGE). A sentinel character %* (inverse asterisk) is written at BOT after each entry to mark the end of text.
The variable C$ (initialised at line 9050 to 31 spaces) serves as a “blank filler” string used to erase vacated regions of A$ after deletions and space-removal operations, avoiding stale characters.
Cursor Highlight Technique
The edit cursor is implemented without any machine code by exploiting the inverse-video character encoding. Subroutine at line 1000 reads the character at INDEX, saves it to B$, adds 128 to its code (converting it to its inverse-video counterpart), and writes it back. The companion restore at line 1060 writes B$(1) back, undoing the inversion. This gives a visible blinking-style cursor using only standard BASIC string operations.
Paging and Navigation
Page navigation in edit mode (lines 7059–7065) simply adds or subtracts 640 from PAGE, clamped between 640 and 5120. The numeric keys 5–8 move the cursor by ±1 character or ±32 characters (one screen row), mirroring the conventional arrow-key layout. Keys 1, 2, and 9 jump the cursor to the page end, middle line, and page start respectively.
Key BASIC Idioms
- String-array as byte buffer:
A$(X TO Y)=A$(Y TO Z)style slice assignments perform bulk moves for insert and delete without any machine code. - FAST/SLOW switching:
FASTis used during intensive string scanning (search, space removal) andSLOWfor display-intensive sections, controlling the display driver’s CPU time. - Computed boolean movement: Line 7050 uses
INDEX=INDEX+(Z$="8")-(Z$="5")— a classic idiom where boolean results (0 or 1) directly adjust a variable without anIFbranch. - INKEY$ polling loop: Lines 5060–5075 poll
INKEY$in a tight loop withoutPAUSE, a common idiom for menu key selection.
Word-Wrap / Line Reformatting (LINE Command)
The LINE routine (lines 2000–2520) scans forward from variable B in 32-character steps (IP=IP+32). At each position, if the character is not a natural word boundary (space, period, comma, semicolon, colon, question mark), it searches backward for the nearest space and shifts text to insert a space, effectively re-joining a word that was split across a display line. This is a rudimentary word-wrap correction pass rather than a full reflow engine.
Notable Bugs and Anomalies
- Line 310 (missing): Line 3110 contains
GOTO 310when a chain of spaces is found during the double-space removal pass. Line 310 does not exist in the listing; this would cause a runtime error during space compression of long runs. - Line 6250 logic error: The condition
IF INKEY$<>"P" OR INKEY$<>"S"is always true (no key can simultaneously equal both “P” and “S”), so the intended guard against non-P/S keys never works correctly. The LOOK mode cannot properly branch on key identity as intended. - Uninitialised variable B: The LINE command at line 2010 uses
LET IP=B, butBis never explicitly set anywhere visible in the listing. It appears to be a forward reference to something set elsewhere (possibly the cursor position), but its value at invocation is undefined from a cold start. - Line 7500 gap: The INSERT routine jumps to line 7501 but there is no line 7500 in the listing, so
IF INKEY$="I" THEN GOTO 7500(line 7210) would cause a “line does not exist” error on some interpreters. - LPRINT with bare slice: Line 6001 uses
LPRINT A$( TO BOT-1)with an empty lower bound, implyingA$(1 TO BOT-1)— printing the entire document buffer. This is syntactically valid but relies on the interpreter accepting an omitted lower slice bound. - Lines 9070–9090 unreachable: Lines
9070 CLEAR,9080 SAVE "1000", and9090 RUNappear after9060 GOTO 15and are never reachable during normal execution; they appear to be remnants of a bootstrap/auto-run loader.
Content
Source Code
3 GOTO 5000
15 FAST
16 PRINT AT 1,0;A$(PAGE-639 TO PAGE)
18 PRINT AT 0,0;"SPACE LEFT=";5120-BOT
19 PRINT AT 0,25;"PAGE ";INT (PAGE/640)
20 PRINT AT 21,6;"% %E%N%T%R%Y% %M%O%D%E% "
21 INPUT Z$
22 IF Z$="LOOK" THEN GOTO 6200
23 IF Z$=" LPRINT " THEN GOTO 6000
24 IF Z$="SPACE" THEN GOTO 3000
25 IF Z$="LINE" THEN GOTO 2000
26 IF Z$=" STOP " THEN GOTO 5000
27 IF Z$="SAVE" THEN GOTO 100
28 IF Z$="PAGE" THEN GOSUB 8000
29 IF Z$="EDIT" THEN GOTO 7000
39 LET ZZ=LEN Z$
40 LET TOP=BOT+ZZ
50 LET A$(BOT TO TOP)=Z$
51 LET A$(TOP+1)=" "
52 LET BOT=TOP+1
53 LET A$(BOT)="%*"
55 CLS
70 GOTO 15
100 CLS
110 PRINT "TO SAVE PROGRAM AND DATA ",,,"START TAPE AND PRESS ENTER"
120 INPUT Z$
130 SAVE "WORD PROCESSO%R"
140 GOTO 5000
999 REM %C%U%R%S%O%R% %R%O%U%T%I%N%E%S FOR EDIT
1000 LET XX=CODE A$(INDEX)
1010 LET B$=A$(INDEX)
1020 IF XX<0 OR XX>127 THEN RETURN
1030 LET XX=XX+128
1040 LET A$(INDEX)=CHR$ XX
1050 RETURN
1060 LET A$(INDEX)=B$(1)
1070 RETURN
2000 REM %S%P%A%C%E% %L%I%N%E%S
2001 SLOW
2002 LET PAGE=640
2010 LET IP=B
2020 IF A$(IP)=" " OR A$(IP+1)=" " OR A$(IP)="." OR A$(IP)="," OR A$(IP)=";" OR A$(IP)=":" OR A$(IP)="?" THEN GOTO 2500
2030 LET PO=IP-1
2040 IF A$(PO)=" " THEN GOTO 2060
2045 LET PO=PO-1
2050 GOTO 2040
2060 LET DIF=IP-PO
2062 LET BOT=BOT+DIF
2065 LET A$(IP TO IP+((BOT-DIF)-PO))=A$(PO TO BOT-DIF)
2070 LET A$(PO TO IP)=C$(1 TO DIF+1)
2100 RETURN
2500 LET IP=IP+32
2501 IF PAGE<IP THEN LET PAGE=PAGE+640
2502 GOSUB 8050
2505 PRINT AT 1,0;A$(PAGE-639 TO PAGE)
2510 IF IP>=BOT THEN GOTO 15
2520 GOTO 2020
3000 REM %R%E%M%O%V%E% %S%P%A%C%E%S% %(%O%V%E%R% %2%)
3001 LET Z$=""
3002 SLOW
3003 LET PAGE=640
3010 FOR A=1 TO BOT
3020 IF A$(A)=" " AND A$(A+1)=" " THEN GOSUB 3100
3030 NEXT A
3040 GOTO 15
3100 LET BA=A+1
3105 LET BA=BA+1
3106 IF BA>=BOT THEN GOTO 15
3110 IF A$(BA)=" " THEN GOTO 310
3140 LET BA=BA-1
3150 LET DIF=BA-A
3160 LET A$(A TO A+(BOT-BA))=A$(BA TO BOT)
3190 LET BOT=BOT-DIF
3191 LET A$(BOT TO BOT+DIF)=C$(1 TO DIF+1)
3192 IF PAGE<A THEN LET PAGE=PAGE+640
3193 GOSUB 8050
3194 PRINT AT 1,0;A$(PAGE-639 TO PAGE)
4000 REM %S%E%A%R%C%H
4001 PRINT AT 21,6;"% % % % %S%E%A%R%C%H% % % % "
4002 GOSUB 7150
4010 INPUT Z$
4011 FAST
4030 LET ZZ=LEN Z$-1
4040 FOR A=1 TO BOT
4050 IF A$(INDEX TO INDEX+ZZ)=Z$ THEN GOTO 4066
4055 LET ENDEX=INDEX+1
4060 NEXT A
4061 LET Z$=""
4065 GOTO 15
4067 SLOW
4070 GOTO 7015
4500 REM %E%D%I%T% %M%E%N%U
4501 CLS
4505 PRINT AT 0,7;"%E%D%I%T% %M%E%N%U"
4510 PRINT
4511 PRINT "1 = CURSOR TO PAGE END"
4512 PRINT "2 = CURSOR TO MIDDLE LINE"
4513 PRINT "3 = BACK 1 PAGE"
4514 PRINT "4 = FORWARD 1 PAGE"
4515 PRINT "5 TO 8 = AS ARROWS ON KEYS"
4516 PRINT "9 = CURSOR TO PAGE START"
4518 PRINT "0 = PLACE FOUND GOTO MENU.2"
4519 PRINT "S = SEARCH FOR A WORD"
4520 PRINT "R = RETURN TO MAIN MENU"
4530 PRINT
4531 PRINT TAB 7;"%M%E%N%U% %2% "
4532 PRINT
4533 PRINT "D = DELETE CHARACTER"
4534 PRINT "I = INSERT CHARACTERS"
4535 PRINT "C = CHANGE CHARACTERS"
4536 PRINT "R = RETURN TO EDIT MENU 1"
4600 PRINT AT 21,0;"PRESS ANY KEY TO CONTINUE"
4605 IF INKEY$="" THEN GOTO 4605
4610 GOTO 7000
5000 REM %S%T%A%R%T
5001 CLS
5002 SLOW
5020 PRINT AT 6,8;"%W%O%R%D% %P%R%O%C%E%S%S%O%R"
5040 PRINT AT 14,0;"PRESS 1 TO ADD TO/EDIT TEXT","PRESS 2 TO ENTER NEW TEXT(%C%L%E%A%R% %O%L%D)"
5050 PRINT "PRESS 3 TO STOP"
5055 PRINT "PRESS 4 TO LOOK AT COMMANDS"
5060 IF INKEY$="1" THEN GOTO 15
5070 IF INKEY$="2" THEN GOTO 9000
5071 IF INKEY$="4" THEN GOTO 5490
5072 IF INKEY$="3" THEN STOP
5075 GOTO 5060
5412 PRINT "1 = CURSOR TO PAGE END"
5490 CLS
5500 PRINT AT 2,0;"LINE = REMOVE SPLIT WORDS"
5501 PRINT "SPACE = REMOVE ALL DOUBLE(OR OVER) SPACES."
5502 PRINT "EDIT = GO TO EDIT MODE"
5503 PRINT "LOOK = PRINT TEXT ON SCREEN"
5504 PRINT " LPRINT (K/WORD) = PRINT ON PAPER"
5505 PRINT "SAVE = SAVE ON TAPE"
5506 PRINT "PAGE = SELECT ANOTHER PAGE"
5507 PRINT " STOP (K/WORD) = RETURN TO MENU"
5508 PRINT
5509 PRINT
5510 PRINT "IN EDIT ""M"" PRINTSAN EDIT MENU"
5570 PRINT AT 0,7;"%C%O%M%M%A%N%D%S% %A%V%A%I%L%A%B%L%E"
5580 PRINT AT 21,0;"PRESS A KEY TO CONTINUE"
5590 IF INKEY$="" THEN GOTO 5590
5599 GOTO 5000
6000 REM %P%R%I%N%T
6001 LPRINT A$( TO BOT-1)
6010 GOTO 15
6200 REM %L%O%O%K% %A%T
6205 CLS
6206 SLOW
6207 PRINT AT 2,0;"P = COPY TO SCREEN"
6208 PRINT "S = WAIT UNTIL S KEY RELEASED"
6209 PRINT "ANY KEY EXCEPT SPACE WILL RETURN"
6210 FOR C=1 TO BOT-1 STEP 32
6220 SCROLL
6225 LET B$=A$(C TO C+31)
6230 PRINT B$
6235 IF INKEY$<>"" THEN GOTO 6250
6240 NEXT C
6244 PAUSE 200
6245 FAST
6246 CLS
6247 GOTO 15
6250 IF INKEY$<>"P" OR INKEY$<>"S" THEN GOTO 6245
6255 IF INKEY$="P" THEN COPY
6260 IF INKEY$="S" THEN GOTO 6260
6270 GOTO 6240
7000 REM %E%D%I%T
7001 SLOW
7010 LET INDEX=PAGE-639
7015 PRINT AT 21,0;" % %E%D%I%T% %M%O%D%E% ";" "
7016 PRINT AT 0,0;"SPACE LEFT=";5120-BOT;" "
7020 GOSUB 1000
7030 PRINT AT 1,0;A$(PAGE-639 TO PAGE)
7045 GOSUB 1060
7049 LET Z$=INKEY$
7050 LET INDEX=INDEX+(Z$="8")-(Z$="5")
7051 IF Z$="6" THEN LET INDEX=INDEX+32
7052 IF Z$="7" THEN LET INDEX=INDEX-32
7053 IF Z$="5" OR Z$="6" OR Z$="7" OR Z$="8" THEN GOTO 7020
7054 IF Z$="0" THEN GOTO 7200
7055 IF Z$="R" THEN GOTO 7900
7056 IF Z$="S" THEN GOTO 4000
7057 IF Z$="1" THEN LET INDEX=PAGE
7058 IF Z$="2" THEN LET INDEX=PAGE-319
7059 IF Z$="4" THEN LET PAGE=PAGE+640
7060 IF PAGE>5000 THEN LET PAGE=5120
7061 IF Z$="4" THEN LET INDEX =PAGE-639
7063 IF Z$="3" THEN LET PAGE=PAGE-640
7064 IF PAGE<640 THEN LET PAGE=640
7065 IF Z$="3" THEN LET INDEX=PAGE-639
7066 IF Z$="M" THEN GOTO 4500
7067 IF Z$="9" THEN LET INDEX=PAGE-639
7068 PRINT AT 0,25;"PAGE ";INT (PAGE/640)
7070 GOTO 7020
7200 PRINT AT 21,7;"%C%H%A%N%G%E% % % % % "
7209 IF INKEY$="D" THEN GOTO 7300
7210 IF INKEY$="I" THEN GOTO 7500
7220 IF INKEY$="C" THEN GOTO 7700
7230 IF INKEY$="R" THEN GOTO 7900
7299 GOTO 7209
7300 REM %D%E%L%E%T%E
7310 LET B$=A$(INDEX+1 TO BOT)
7320 LET A$(INDEX TO BOT-1)=B$
7340 LET BOT=BOT-1
7341 LET A$(BOT+1)=" "
7350 LET B$=""
7399 GOTO 7015
7501 PRINT AT 21,6;"%I%N%S%E%R%T% %C%H%A%R%A%C%T%E%R%S"
7502 INPUT Z$
7503 GOSUB 1060
7505 LET ZZ=LEN Z$
7510 LET NBOT=BOT+ZZ
7525 LET B$=A$(INDEX TO BOT)
7540 LET B$=Z$+B$
7570 LET A$(INDEX TO NBOT)=B$
7580 LET BOT=NBOT
7590 LET B$=""
7599 GOTO 7015
7700 REM %C%H%A%N%G%E
7701 PRINT AT 21,6;"% %R%E%P%L%A%C%E% "
7710 INPUT Z$
7720 LET A$(INDEX TO INDEX+LEN Z$-1)=Z$
7799 GOTO 7015
7900 REM %R%E%T%U%R%N
7901 FAST
7910 GOSUB 1060
7999 GOTO 15
8000 REM %P%A%G%E% %R%O%U%T%I%N%E
8020 SLOW
8030 PRINT AT 21,6;"% %W%H%I%C%H% %P%A%G%E% %N%U%M%B%E%R%?% "
8036 INPUT PAGE
8040 LET PAGE=PAGE*640
8050 IF PAGE<640 THEN LET PAGE=640
8051 IF PAGE>5120 THEN LET PAGE=4976
8060 PRINT AT 21,6;" "
8099 LET Z$=""
8100 RETURN
9000 CLS
9001 PRINT AT 6,4;"TYPE ""YES"" IF YOU WISH TO CLEAR FILE"
9002 INPUT Z$
9003 IF Z$<>"YES" THEN GOTO 5000
9005 DIM A$(5120)
9020 LET B=32
9030 LET BOT=1
9040 LET PAGE=640
9050 LET C$=" "
9060 GOTO 15
9070 CLEAR
9080 SAVE "1000%5"
9090 RUN
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
