Wordy

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

WORDY is a multi-page word processor that stores up to ten pages of text, each 640 characters long (20 lines × 32 columns), held in a two-dimensional string array A$(10,640). It provides two editing modes—Writing and Editing—with the Editing mode offering cursor movement via keys 5/6/7/8, character insertion and deletion, cut-and-paste via a working buffer B$, a clipboard D$ for deleted blocks, and a rudimentary text-justification routine triggered by key J. Text can be saved to tape, sent to the line printer one page or all pages at a time, and the editor uses POKE 16441/16442 to restrict the display area to the top 20 rows. The justify routine (lines 1870–2130) uses a multi-pass algorithm with spacing variables GH and AS to redistribute spaces across each 32-character line, halting at a < sentinel character.


Program Analysis

Program Structure

WORDY is organised into a set of loosely labelled functional regions jumped to via GOTO and GOSUB. The main menu occupies lines 140–320, with branches to save (80), print (330), write (480), edit (800), and clear (1820). The Writing mode loop runs from line 570 and the Editing mode loop from line 870. A shared buffer-flush subroutine lives at line 1620, and a justify routine occupies lines 1870–2130. Error messages are gathered at 2300–2450 and all share a common PAUSE 100 / return-to-menu path.

Data Model

All text is held in A$(10,640), a 6,400-character two-dimensional string array. Each of the ten “pages” is 640 characters, representing 20 rows of 32 columns. Position within a page is tracked by the integer POS (1–640), with row and column derived as:

  • WL = INT(POS/32) — row (0–19)
  • WC = POS - WL*32 - 1 — column (0–31)

There is an edge-case correction at line 2140 (subroutine): when POS is an exact multiple of 32, WL is decremented and WC is set to 31, placing the cursor at the end of the previous row rather than the start of the next.

Display Management

The screen is divided into a 20-line text area (rows 0–19) and a two-line status bar (rows 20–21). Lines 550–560 use POKE 16441,20 and POKE 16442,30 to set the system variables controlling the number of lines and scroll threshold, preventing automatic scrolling into the text area. The separator line at row 20 is drawn with block-graphic characters (\.. = ▄) in Writing mode and a dashed pattern in Editing mode.

Writing Mode

Writing mode (line 480) offers a simple sequential entry loop. Key handling:

  • CHR$ 224 — exit to menu
  • CHR$ 121 (y) — tab: advance POS to the next 32-column boundary
  • CHR$ 118 (v) — insert a space (routes through line 780)
  • CHR$ 228 — backspace: decrements POS and clears the character (line 1730)
  • CHR$ 217 — jump to Editing mode mid-session (line 840)

When POS exceeds 640, writing automatically advances to the next page (lines 1780–1810). Note that line 680 checks for CHR$ 121 again after it was already tested at line 640 — this is a dead branch and can never be reached.

Editing Mode

Editing mode (line 800) uses a cursor displayed by printing the inverse of the character under the cursor (CHR$(128+CODE A$(X,POS))) followed immediately by the normal character in an attract-style flicker loop (lines 900–910). Navigation and commands are single-keypress:

KeyAction
5/6/7/8Move cursor left/right/up/down (line 940, expression-based)
HHome — set POS=1
CClear character at cursor (space)
SInsert single space, shifting text right; saves overflow to B$
LInsert a full 32-character blank line, saving overflow to B$
IInsert typed string at cursor position
DDelete character, pulling from B$ if available
1Cut n characters to clipboard D$
PPaste clipboard D$ at cursor
A/BMove to next/previous page (flushing B$)
OClear working buffer B$
JJustify current page
WSwitch to Writing mode (flushing B$)
TWait and accept a single typed character
MMove-cursor submode
EExit to main menu (flushing B$)
RRedraw page (flush only)

Buffer System

Two string buffers supplement the page array. B$ is a working overflow buffer: when text is inserted, characters pushed off the right edge of a page are prepended to B$; when characters are deleted, the first character of B$ is pulled back in from the right. The buffer-flush subroutine (line 1620) distributes the contents of B$ across subsequent pages in FAST mode. D$ is a separate cut buffer, populated by the cut command (line 1450) and pasted by command P (line 1500).

Justify Routine

The justify command (line 1870) operates on a single page in FAST mode. It iterates over each 32-character line, counts trailing spaces (GH), strips them from the right, then redistributes them by inserting spaces at existing space positions across the line. The stride variable AS starts at 2 and increments on each redistribution pass to spread spaces more evenly. The character < acts as a stop sentinel, halting the justify loop; > resets the GH counter mid-line. This provides rudimentary paragraph-break control.

Move-Cursor Submode

Lines 2170–2290 implement a secondary cursor-navigation mode (triggered by key M in editing, or CHR$ 121 in writing). The cursor is shown as inverse M ("%M"). Movement uses the same 5/6/7/8 expression idiom as editing mode. CHR$ 118 exits back to editing mode. The duplicate FAST call at line 2190 is redundant (already set at 2170).

Key BASIC Idioms

  • Expression-based movement: LET POS=POS+(X$="8")-(X$="5")+32*(X$="6")-32*(X$="7") uses Boolean expressions (0 or 1) to compute cursor displacement in a single statement.
  • Inverse video cursor: CHR$(128+CODE A$(X,POS)) renders any character in inverse, giving a block cursor without machine code.
  • INKEY$ polling loops: Used throughout rather than INPUT for single-key commands, avoiding the need to press ENTER.
  • Array slicing for text manipulation: Insertion and deletion use slice concatenation on A$(X), e.g., A$(X,1 TO POS-1)+" "+A$(X,POS TO 640).

Bugs and Anomalies

  • Line 680 tests X$=CHR$ 121 again after line 640 already tested the same condition — this branch is unreachable.
  • Line 960 tests CODE X$<37 AND CODE X$>32, which can only be true for CODE X$=33, 34, 35, or 36 (i.e., !, ", #, $). The intent appears to be to skip re-displaying the page for movement keys, but the range is very narrow and likely not what was intended.
  • Lines 2410–2440 (error for text insertion too large) are defined but never jumped to — the insertion routine at 1240–1290 goes to 2380 (buffer full), not 2410.
  • Line 1200 saves the last 33 characters (640-32 TO 640) but the loop inserts 32 spaces, creating a one-character discrepancy in overflow tracking.
  • Lines 2470–2490 (CLEAR, SAVE, GOTO 10) are unreachable dead code at the end of the listing.

Content

Appears On

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

Related Products

Related Articles

Related Content

Image Gallery

Wordy

Source Code

  10 REM "WORDY"
  20 DIM A$(10,640)
  30 LET B$=""
  40 LET D$=""
  50 LET POS=1
  60 LET PAGE=1
  70 GOTO 140
  80 PRINT "WORDY ENTER PROGRAM NAME-"
  90 INPUT Z$
 100 IF Z$="" THEN GOTO 2340
 110 PRINT "SET UP TAPE DECK THEN PRESS<N/L>"
 120 INPUT X$
 130 SAVE Z$
 140 CLS 
 150 PRINT "\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\.."
 160 PRINT "WORDY"
 170 PRINT "\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\.."
 180 PRINT AT 4,2;"   1:SAVE ON TAPE"
 190 PRINT AT 6,2;"   2:SEND TO PRINTER"
 200 PRINT AT 8,2;"   3:WRITE PAGE"
 210 PRINT AT 10,2;"   4:EDIT PAGE"
 220 PRINT AT 12,2;"   5:CLEAR PAGE"
 230 PRINT AT 14,0;"    ENTER OPTION (1 TO 4)"
 240 PRINT AT 14,25;"% "
 250 LET X$=INKEY$
 260 IF X$="1" THEN GOTO 80
 270 IF X$="2" THEN GOTO 330
 280 PRINT AT 14,25;"?"
 290 IF X$="3" THEN GOTO 480
 300 IF X$="4" THEN GOTO 800
 310 IF X$="5" THEN GOTO 1820
 320 GOTO 240
 330 PRINT "ENTER PAGE TO BE PRINTED OUT"
 340 INPUT X
 350 IF X=11 THEN GOTO 400
 360 IF X=12 THEN GOTO 140
 370 IF X>11 OR X<1 THEN GOTO 2320
 380 LPRINT A$(X)
 390 GOTO 430
 400 FOR X=1 TO 10
 410 LPRINT A$(X)
 420 NEXT X
 430 PRINT "  ANYMORE"
 440 LET X$=INKEY$
 450 IF X$="Y" THEN GOTO 330
 460 IF X$="N" THEN GOTO 140
 470 GOTO 440
 480 PRINT "ENTER PAGE FOR WRITING ON"
 490 INPUT X
 500 IF X>10 OR X<1 THEN GOTO 2320
 510 LET POS=1
 520 PRINT AT 21,0;" MODE:WRITING    ";AT 21,22;"PAGE:";X
 530 PRINT AT 20,0;"\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\.."
 540 PRINT AT 0,0;A$(X)
 550 POKE 16441,20
 560 POKE 16442,30
 570 LET WL=INT (POS/32)
 580 LET WC=POS-WL*32-1
 590 IF POS/32=INT (POS/32) THEN GOSUB 2140
 600 PRINT AT WL,WC;"%O"
 610 IF INKEY$="" THEN GOTO 610
 620 LET X$=INKEY$
 630 IF X$=CHR$ 224 THEN GOTO 140
 640 IF X$=CHR$ 121 THEN GOTO 740
 650 IF X$=CHR$ 118 THEN GOTO 780
 660 IF X$=CHR$ 228 THEN GOTO 1730
 670 IF X$=CHR$ 217 THEN GOTO 840
 680 IF X$=CHR$ 121 THEN GOTO 2170
 690 LET A$(X,POS)=X$
 700 PRINT AT WL,WC;A$(X,POS)
 710 LET POS=POS+1
 720 IF POS>640 OR POS<1 THEN GOTO 1780
 730 GOTO 570
 740 LET UU=(WL+1)*32-POS
 750 LET POS=POS+UU+1
 760 PRINT AT WL,WC;A$(X,POS-UU-1)
 770 GOTO 720
 780 LET X$=" "
 790 GOTO 690
 800 PRINT "ENTER PAGE FOR EDITING"
 810 INPUT X
 820 IF X>10 OR X<1 THEN GOTO 2320
 830 LET POS=1
 840 PRINT AT 20,0;"% % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % "
 850 PRINT AT 21,0;" MODE:EDITING  ";AT 21,22;"PAGE:";X
 860 PRINT AT 0,0;A$(X)
 870 LET WL=INT (POS/32)
 880 LET WC=POS-WL*32-1
 890 IF POS/32=INT (POS/32) THEN GOSUB 2140
 900 PRINT AT WL,WC;CHR$ (128+CODE A$(X,POS))
 910 PRINT AT WL,WC;A$(X,POS)
 920 IF INKEY$="" THEN GOTO 900
 930 LET X$=INKEY$
 940 LET POS=POS+(X$="8")-(X$="5")+32*(X$="6")-32*(X$="7")
 950 IF POS>640 OR POS<1 THEN GOTO 2360
 960 IF CODE X$<37 AND CODE X$>32 THEN GOTO 870
 970 IF X$="H" THEN LET POS=1
 980 IF X$="D" THEN GOTO 1550
 990 IF X$="S" THEN GOTO 1150
\n1000 IF X$="L" THEN GOTO 1200
\n1010 IF X$="A" THEN GOTO 1330
\n1020 IF X$="I" THEN GOTO 1240
\n1030 IF X$="C" THEN GOTO 1310
\n1040 IF X$="B" THEN GOTO 1370
\n1050 IF X$="T" THEN GOTO 1410
\n1060 IF X$="1" THEN GOTO 1450
\n1070 IF X$="P" THEN GOTO 1500
\n1080 IF X$="R" THEN GOTO 1530
\n1090 IF X$="E" THEN GOTO 1600
\n1100 IF X$="O" THEN LET B$=""
\n1110 IF X$="J" THEN GOTO 1870
\n1120 IF X$="W" THEN GOTO 1760
\n1130 IF X$="M" THEN GOTO 2170
\n1140 GOTO 870
\n1150 LET B$=A$(X,640)+B$
\n1160 LET A$(X)=A$(X,1 TO POS-1)+" "+A$(X,POS TO 640)
\n1170 LET POS=POS+1
\n1180 IF LEN B$>200 THEN GOTO 2380
\n1190 GOTO 860
\n1200 LET B$=A$(X,640-32 TO 640)+B$
\n1210 LET A$(X)=A$(X,1 TO POS-1)+"                                "+A$(X,POS TO 640)
\n1220 IF LEN B$>200 THEN GOTO 2380
\n1230 GOTO 860
\n1240 PRINT AT 21,0;"ENTER TEXT              "
\n1250 INPUT X$
\n1260 LET A=LEN X$
\n1270 LET B$=A$(X,640-A TO 640)+B$
\n1280 LET A$(X)=A$(X,1 TO POS-1)+X$+A$(X,POS TO 640)
\n1290 IF LEN B$>200 THEN GOTO 2380
\n1300 GOTO 840
\n1310 LET A$(X,POS)=" "
\n1320 GOTO 860
\n1330 GOSUB 1620
\n1340 IF X=10 THEN GOTO 2300
\n1350 LET X=X+1
\n1360 GOTO 840
\n1370 GOSUB 1620
\n1380 IF X=1 THEN GOTO 2300
\n1390 LET X=X-1
\n1400 GOTO 840
\n1410 PAUSE 100
\n1420 IF INKEY$="" THEN GOTO 1420
\n1430 LET A$(X,POS)=INKEY$
\n1440 GOTO 860
\n1450 PRINT AT 21,0;"AMOUNT?"
\n1460 INPUT A
\n1470 LET D$=A$(X,POS-A TO POS-1)
\n1480 LET A$(X)=A$(X,1 TO POS-A-1)+A$(X,POS TO 640)
\n1490 GOTO 840
\n1500 LET A$(X)=A$(X,1 TO POS-1)+D$+A$(X,POS TO 640)
\n1510 LET D$=""
\n1520 GOTO 860
\n1530 GOSUB 1620
\n1540 GOTO 860
\n1550 IF B$="" THEN LET A$(X)=A$(X,1 TO POS-2)+A$(X,POS TO 640)
\n1560 IF B$<>"" THEN LET A$(X)=A$(X,1 TO POS-2)+A$(X,POS TO 640)+B$(1)
\n1570 IF B$<>"" THEN LET B$=B$(2 TO )
\n1580 LET POS=POS-1
\n1590 GOTO 860
\n1600 GOSUB 1620
\n1610 GOTO 140
\n1620 IF B$="" THEN RETURN 
\n1630 FAST 
\n1640 LET A=LEN B$
\n1650 FOR B=X+1 TO 9
\n1660 LET C$=A$(B,640-A TO 640)
\n1670 LET A$(B)=B$+A$(B,1 TO 640-A-1)
\n1680 LET B$=C$
\n1690 NEXT B
\n1700 LET B$=""
\n1710 SLOW 
\n1720 RETURN 
\n1730 LET POS=POS-1
\n1740 LET A$(X,POS+1)=" "
\n1750 GOTO 540
\n1760 GOSUB 1620
\n1770 GOTO 520
\n1780 LET X=X+1
\n1790 IF X>10 THEN GOTO 2300
\n1800 LET POS=1
\n1810 GOTO 520
\n1820 PRINT "  PAGE TO CLEAR?"
\n1830 INPUT X
\n1840 IF X>10 OR X<1 THEN GOTO 2320
\n1850 LET A$(X)=""
\n1860 GOTO 140
\n1870 LET GH=0
\n1880 LET AS=2
\n1890 FAST 
\n1900 FOR Z=1 TO 640-32 STEP 32
\n1910 FOR Y=Z+31 TO Z STEP -1
\n1920 IF A$(X,Y)="<" THEN GOTO 2060
\n1930 IF A$(X,Y)=">" THEN GOTO 2030
\n1940 IF A$(X,Y)<>" " THEN GOTO 1970
\n1950 LET GH=GH+1
\n1960 NEXT Y
\n1970 LET A$(X)=A$(X,1 TO Z+31-GH)+A$(X,Z+31+1 TO 640)
\n1980 FOR Y=Z TO Z+31
\n1990 IF GH=0 THEN GOTO 2030
\n2000 IF A$(X,Y)=" " THEN GOSUB 2080
\n2010 NEXT Y
\n2020 IF GH<>0 THEN GOTO 2120
\n2030 LET GH=0
\n2040 LET AS=2
\n2050 NEXT Z
\n2060 SLOW 
\n2070 GOTO 840
\n2080 LET A$(X)=A$(X,1 TO Y-1)+" "+A$(X,Y TO 640)
\n2090 LET GH=GH-1
\n2100 LET Y=Y+AS
\n2110 RETURN 
\n2120 LET AS=AS+1
\n2130 GOTO 1980
\n2140 LET WC=31
\n2150 LET WL=WL-1
\n2160 RETURN 
\n2170 FAST 
\n2180 LET WL=INT (POS/32)
\n2190 FAST 
\n2200 LET WC=POS-WL*32-1
\n2210 IF POS/32=INT (POS/32) THEN GOSUB 2140
\n2220 PRINT AT WL,WC;"%M"
\n2230 SLOW 
\n2240 IF INKEY$="" THEN GOTO 2240
\n2250 PRINT AT WL,WC;A$(X,POS)
\n2260 LET X$=INKEY$
\n2270 IF X$=CHR$ 118 THEN GOTO 840
\n2280 LET POS=POS+(X$="8")-(X$="5")+32*(X$="6")-32*(X$="7")
\n2290 GOTO 2180
\n2300 PRINT AT 21,0;"<ERROR>YOU HAVE USED ALL FILES"
\n2310 GOTO 2450
\n2320 PRINT AT 21,0;"<ERROR>THERE IS NO SUCH PAGE   "
\n2330 GOTO 2450
\n2340 PRINT AT 21,0;"<ERROR>PROGRAM NAME IS INVALID"
\n2350 GOTO 2450
\n2360 PRINT AT 21,0;"<ERROR>RUNNING INTO NEXT PAGE"
\n2370 GOTO 2450
\n2380 PRINT AT 21,0;"<ERROR>WORKING BUFFER IS FULL"
\n2390 GOSUB 1620
\n2400 GOTO 2450
\n2410 PRINT AT 21,0;"<ERROR>TEXT INSERTION IS TOO LARGE"
\n2420 FOR F=1 TO 20
\n2430 NEXT F
\n2440 GOTO 840
\n2450 PAUSE 100
\n2460 GOTO 140
\n2470 CLEAR 
\n2480 SAVE "1000%4"
\n2490 GOTO 10

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

People

No people associated with this content.

Scroll to Top