Word Processor

This file is part of Timex Sinclair Public Domain Library Tape 1001 . Download the collection to get this file.
Date: 198x
Type: Program
Platform(s): TS 1000

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 RangeFunction
3Bootstrap jump to start-up menu (line 5000)
15–70Main entry loop: display page, accept command string, dispatch
100–140Tape SAVE routine
999–1070Cursor 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–4067Search routine
4500–4610Edit menu display
5000–5075Title/main menu screen
5490–5599Command reference screen
6000–6010LPRINT (print to paper)
6200–6270“LOOK” — scroll text to screen with optional copy/pause
7000–7999Full edit mode (cursor movement, delete, insert, replace)
8000–8100Page selection subroutine
9000–9090New-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: FAST is used during intensive string scanning (search, space removal) and SLOW for 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 an IF branch.
  • INKEY$ polling loop: Lines 5060–5075 poll INKEY$ in a tight loop without PAUSE, 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 310 when 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, but B is 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, implying A$(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", and 9090 RUN appear after 9060 GOTO 15 and are never reachable during normal execution; they appear to be remnants of a bootstrap/auto-run loader.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10001 – 10050.

Related Products

Related Articles

Related Content

Image Gallery

Word Processor

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
\n1000 LET XX=CODE A$(INDEX)
\n1010 LET B$=A$(INDEX)
\n1020 IF XX<0 OR XX>127 THEN RETURN 
\n1030 LET XX=XX+128
\n1040 LET A$(INDEX)=CHR$ XX
\n1050 RETURN 
\n1060 LET A$(INDEX)=B$(1)
\n1070 RETURN 
\n2000 REM %S%P%A%C%E% %L%I%N%E%S
\n2001 SLOW 
\n2002 LET PAGE=640
\n2010 LET IP=B
\n2020 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
\n2030 LET PO=IP-1
\n2040 IF A$(PO)=" " THEN GOTO 2060
\n2045 LET PO=PO-1
\n2050 GOTO 2040
\n2060 LET DIF=IP-PO
\n2062 LET BOT=BOT+DIF
\n2065 LET A$(IP TO IP+((BOT-DIF)-PO))=A$(PO TO BOT-DIF)
\n2070 LET A$(PO TO IP)=C$(1 TO DIF+1)
\n2100 RETURN 
\n2500 LET IP=IP+32
\n2501 IF PAGE<IP THEN LET PAGE=PAGE+640
\n2502 GOSUB 8050
\n2505 PRINT AT 1,0;A$(PAGE-639 TO PAGE)
\n2510 IF IP>=BOT THEN GOTO 15
\n2520 GOTO 2020
\n3000 REM %R%E%M%O%V%E% %S%P%A%C%E%S% %(%O%V%E%R% %2%)
\n3001 LET Z$=""
\n3002 SLOW 
\n3003 LET PAGE=640
\n3010 FOR A=1 TO BOT
\n3020 IF A$(A)=" " AND A$(A+1)=" " THEN GOSUB 3100
\n3030 NEXT A
\n3040 GOTO 15
\n3100 LET BA=A+1
\n3105 LET BA=BA+1
\n3106 IF BA>=BOT THEN GOTO 15
\n3110 IF A$(BA)=" " THEN GOTO 310
\n3140 LET BA=BA-1
\n3150 LET DIF=BA-A
\n3160 LET A$(A TO A+(BOT-BA))=A$(BA TO BOT)
\n3190 LET BOT=BOT-DIF
\n3191 LET A$(BOT TO BOT+DIF)=C$(1 TO DIF+1)
\n3192 IF PAGE<A THEN LET PAGE=PAGE+640
\n3193 GOSUB 8050
\n3194 PRINT AT 1,0;A$(PAGE-639 TO PAGE)
\n4000 REM %S%E%A%R%C%H
\n4001 PRINT AT 21,6;"% % % % %S%E%A%R%C%H% % % % "
\n4002 GOSUB 7150
\n4010 INPUT Z$
\n4011 FAST 
\n4030 LET ZZ=LEN Z$-1
\n4040 FOR A=1 TO BOT
\n4050 IF A$(INDEX TO INDEX+ZZ)=Z$ THEN GOTO 4066
\n4055 LET ENDEX=INDEX+1
\n4060 NEXT A
\n4061 LET Z$=""
\n4065 GOTO 15
\n4067 SLOW 
\n4070 GOTO 7015
\n4500 REM %E%D%I%T% %M%E%N%U
\n4501 CLS 
\n4505 PRINT AT 0,7;"%E%D%I%T% %M%E%N%U"
\n4510 PRINT 
\n4511 PRINT "1 = CURSOR TO PAGE END"
\n4512 PRINT "2 = CURSOR TO MIDDLE LINE"
\n4513 PRINT "3 = BACK 1 PAGE"
\n4514 PRINT "4 = FORWARD 1 PAGE"
\n4515 PRINT "5 TO 8 = AS ARROWS ON KEYS"
\n4516 PRINT "9 = CURSOR TO PAGE START"
\n4518 PRINT "0 = PLACE FOUND GOTO MENU.2"
\n4519 PRINT "S = SEARCH FOR A WORD"
\n4520 PRINT "R = RETURN TO MAIN MENU"
\n4530 PRINT 
\n4531 PRINT TAB 7;"%M%E%N%U% %2% "
\n4532 PRINT 
\n4533 PRINT "D = DELETE CHARACTER"
\n4534 PRINT "I = INSERT CHARACTERS"
\n4535 PRINT "C = CHANGE CHARACTERS"
\n4536 PRINT "R = RETURN TO EDIT MENU 1"
\n4600 PRINT AT 21,0;"PRESS ANY KEY TO CONTINUE"
\n4605 IF INKEY$="" THEN GOTO 4605
\n4610 GOTO 7000
\n5000 REM %S%T%A%R%T
\n5001 CLS 
\n5002 SLOW 
\n5020 PRINT AT 6,8;"%W%O%R%D% %P%R%O%C%E%S%S%O%R"
\n5040 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)"
\n5050 PRINT "PRESS 3 TO STOP"
\n5055 PRINT "PRESS 4 TO LOOK AT COMMANDS"
\n5060 IF INKEY$="1" THEN GOTO 15
\n5070 IF INKEY$="2" THEN GOTO 9000
\n5071 IF INKEY$="4" THEN GOTO 5490
\n5072 IF INKEY$="3" THEN STOP 
\n5075 GOTO 5060
\n5412 PRINT "1 = CURSOR TO PAGE END"
\n5490 CLS 
\n5500 PRINT AT 2,0;"LINE = REMOVE SPLIT WORDS"
\n5501 PRINT "SPACE = REMOVE ALL DOUBLE(OR OVER) SPACES."
\n5502 PRINT "EDIT = GO TO EDIT MODE"
\n5503 PRINT "LOOK = PRINT TEXT ON SCREEN"
\n5504 PRINT " LPRINT (K/WORD) = PRINT ON PAPER"
\n5505 PRINT "SAVE = SAVE ON TAPE"
\n5506 PRINT "PAGE = SELECT ANOTHER PAGE"
\n5507 PRINT " STOP (K/WORD) = RETURN TO MENU"
\n5508 PRINT 
\n5509 PRINT 
\n5510 PRINT "IN EDIT ""M"" PRINTSAN EDIT MENU"
\n5570 PRINT AT 0,7;"%C%O%M%M%A%N%D%S% %A%V%A%I%L%A%B%L%E"
\n5580 PRINT AT 21,0;"PRESS A KEY TO CONTINUE"
\n5590 IF INKEY$="" THEN GOTO 5590
\n5599 GOTO 5000
\n6000 REM %P%R%I%N%T
\n6001 LPRINT A$(  TO BOT-1)
\n6010 GOTO 15
\n6200 REM %L%O%O%K% %A%T
\n6205 CLS 
\n6206 SLOW 
\n6207 PRINT AT 2,0;"P = COPY TO SCREEN"
\n6208 PRINT "S = WAIT UNTIL S KEY RELEASED"
\n6209 PRINT "ANY KEY EXCEPT SPACE WILL RETURN"
\n6210 FOR C=1 TO BOT-1 STEP 32
\n6220 SCROLL 
\n6225 LET B$=A$(C TO C+31)
\n6230 PRINT B$
\n6235 IF INKEY$<>"" THEN GOTO 6250
\n6240 NEXT C
\n6244 PAUSE 200
\n6245 FAST 
\n6246 CLS 
\n6247 GOTO 15
\n6250 IF INKEY$<>"P" OR INKEY$<>"S" THEN GOTO 6245
\n6255 IF INKEY$="P" THEN COPY 
\n6260 IF INKEY$="S" THEN GOTO 6260
\n6270 GOTO 6240
\n7000 REM %E%D%I%T
\n7001 SLOW 
\n7010 LET INDEX=PAGE-639
\n7015 PRINT AT 21,0;"      % %E%D%I%T% %M%O%D%E% ";"           "
\n7016 PRINT AT 0,0;"SPACE LEFT=";5120-BOT;"  "
\n7020 GOSUB 1000
\n7030 PRINT AT 1,0;A$(PAGE-639 TO PAGE)
\n7045 GOSUB 1060
\n7049 LET Z$=INKEY$
\n7050 LET INDEX=INDEX+(Z$="8")-(Z$="5")
\n7051 IF Z$="6" THEN LET INDEX=INDEX+32
\n7052 IF Z$="7" THEN LET INDEX=INDEX-32
\n7053 IF Z$="5" OR Z$="6" OR Z$="7" OR Z$="8" THEN GOTO 7020
\n7054 IF Z$="0" THEN GOTO 7200
\n7055 IF Z$="R" THEN GOTO 7900
\n7056 IF Z$="S" THEN GOTO 4000
\n7057 IF Z$="1" THEN LET INDEX=PAGE
\n7058 IF Z$="2" THEN LET INDEX=PAGE-319
\n7059 IF Z$="4" THEN LET PAGE=PAGE+640
\n7060 IF PAGE>5000 THEN LET PAGE=5120
\n7061 IF Z$="4" THEN LET INDEX =PAGE-639
\n7063 IF Z$="3" THEN LET PAGE=PAGE-640
\n7064 IF PAGE<640 THEN LET PAGE=640
\n7065 IF Z$="3" THEN LET INDEX=PAGE-639
\n7066 IF Z$="M" THEN GOTO 4500
\n7067 IF Z$="9" THEN LET INDEX=PAGE-639
\n7068 PRINT AT 0,25;"PAGE ";INT (PAGE/640)
\n7070 GOTO 7020
\n7200 PRINT AT 21,7;"%C%H%A%N%G%E% % % % % "
\n7209 IF INKEY$="D" THEN GOTO 7300
\n7210 IF INKEY$="I" THEN GOTO 7500
\n7220 IF INKEY$="C" THEN GOTO 7700
\n7230 IF INKEY$="R" THEN GOTO 7900
\n7299 GOTO 7209
\n7300 REM %D%E%L%E%T%E
\n7310 LET B$=A$(INDEX+1 TO BOT)
\n7320 LET A$(INDEX TO BOT-1)=B$
\n7340 LET BOT=BOT-1
\n7341 LET A$(BOT+1)=" "
\n7350 LET B$=""
\n7399 GOTO 7015
\n7501 PRINT AT 21,6;"%I%N%S%E%R%T% %C%H%A%R%A%C%T%E%R%S"
\n7502 INPUT Z$
\n7503 GOSUB 1060
\n7505 LET ZZ=LEN Z$
\n7510 LET NBOT=BOT+ZZ
\n7525 LET B$=A$(INDEX TO BOT)
\n7540 LET B$=Z$+B$
\n7570 LET A$(INDEX TO NBOT)=B$
\n7580 LET BOT=NBOT
\n7590 LET B$=""
\n7599 GOTO 7015
\n7700 REM %C%H%A%N%G%E
\n7701 PRINT AT 21,6;"% %R%E%P%L%A%C%E% "
\n7710 INPUT Z$
\n7720 LET A$(INDEX TO INDEX+LEN Z$-1)=Z$
\n7799 GOTO 7015
\n7900 REM %R%E%T%U%R%N
\n7901 FAST 
\n7910 GOSUB 1060
\n7999 GOTO 15
\n8000 REM %P%A%G%E% %R%O%U%T%I%N%E
\n8020 SLOW 
\n8030 PRINT AT 21,6;"% %W%H%I%C%H% %P%A%G%E% %N%U%M%B%E%R%?% "
\n8036 INPUT PAGE
\n8040 LET PAGE=PAGE*640
\n8050 IF PAGE<640 THEN LET PAGE=640
\n8051 IF PAGE>5120 THEN LET PAGE=4976
\n8060 PRINT AT 21,6;"                    "
\n8099 LET Z$=""
\n8100 RETURN 
\n9000 CLS 
\n9001 PRINT AT 6,4;"TYPE ""YES"" IF YOU WISH          TO CLEAR FILE"
\n9002 INPUT Z$
\n9003 IF Z$<>"YES" THEN GOTO 5000
\n9005 DIM A$(5120)
\n9020 LET B=32
\n9030 LET BOT=1
\n9040 LET PAGE=640
\n9050 LET C$="                               "
\n9060 GOTO 15
\n9070 CLEAR 
\n9080 SAVE "1000%5"
\n9090 RUN 

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

People

No people associated with this content.

Scroll to Top