Wordy

This file is part of and 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

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
 1000 IF X$="L" THEN GOTO 1200
 1010 IF X$="A" THEN GOTO 1330
 1020 IF X$="I" THEN GOTO 1240
 1030 IF X$="C" THEN GOTO 1310
 1040 IF X$="B" THEN GOTO 1370
 1050 IF X$="T" THEN GOTO 1410
 1060 IF X$="1" THEN GOTO 1450
 1070 IF X$="P" THEN GOTO 1500
 1080 IF X$="R" THEN GOTO 1530
 1090 IF X$="E" THEN GOTO 1600
 1100 IF X$="O" THEN LET B$=""
 1110 IF X$="J" THEN GOTO 1870
 1120 IF X$="W" THEN GOTO 1760
 1130 IF X$="M" THEN GOTO 2170
 1140 GOTO 870
 1150 LET B$=A$(X,640)+B$
 1160 LET A$(X)=A$(X,1 TO POS-1)+" "+A$(X,POS TO 640)
 1170 LET POS=POS+1
 1180 IF LEN B$>200 THEN GOTO 2380
 1190 GOTO 860
 1200 LET B$=A$(X,640-32 TO 640)+B$
 1210 LET A$(X)=A$(X,1 TO POS-1)+"                                "+A$(X,POS TO 640)
 1220 IF LEN B$>200 THEN GOTO 2380
 1230 GOTO 860
 1240 PRINT AT 21,0;"ENTER TEXT              "
 1250 INPUT X$
 1260 LET A=LEN X$
 1270 LET B$=A$(X,640-A TO 640)+B$
 1280 LET A$(X)=A$(X,1 TO POS-1)+X$+A$(X,POS TO 640)
 1290 IF LEN B$>200 THEN GOTO 2380
 1300 GOTO 840
 1310 LET A$(X,POS)=" "
 1320 GOTO 860
 1330 GOSUB 1620
 1340 IF X=10 THEN GOTO 2300
 1350 LET X=X+1
 1360 GOTO 840
 1370 GOSUB 1620
 1380 IF X=1 THEN GOTO 2300
 1390 LET X=X-1
 1400 GOTO 840
 1410 PAUSE 100
 1420 IF INKEY$="" THEN GOTO 1420
 1430 LET A$(X,POS)=INKEY$
 1440 GOTO 860
 1450 PRINT AT 21,0;"AMOUNT?"
 1460 INPUT A
 1470 LET D$=A$(X,POS-A TO POS-1)
 1480 LET A$(X)=A$(X,1 TO POS-A-1)+A$(X,POS TO 640)
 1490 GOTO 840
 1500 LET A$(X)=A$(X,1 TO POS-1)+D$+A$(X,POS TO 640)
 1510 LET D$=""
 1520 GOTO 860
 1530 GOSUB 1620
 1540 GOTO 860
 1550 IF B$="" THEN LET A$(X)=A$(X,1 TO POS-2)+A$(X,POS TO 640)
 1560 IF B$<>"" THEN LET A$(X)=A$(X,1 TO POS-2)+A$(X,POS TO 640)+B$(1)
 1570 IF B$<>"" THEN LET B$=B$(2 TO )
 1580 LET POS=POS-1
 1590 GOTO 860
 1600 GOSUB 1620
 1610 GOTO 140
 1620 IF B$="" THEN RETURN 
 1630 FAST 
 1640 LET A=LEN B$
 1650 FOR B=X+1 TO 9
 1660 LET C$=A$(B,640-A TO 640)
 1670 LET A$(B)=B$+A$(B,1 TO 640-A-1)
 1680 LET B$=C$
 1690 NEXT B
 1700 LET B$=""
 1710 SLOW 
 1720 RETURN 
 1730 LET POS=POS-1
 1740 LET A$(X,POS+1)=" "
 1750 GOTO 540
 1760 GOSUB 1620
 1770 GOTO 520
 1780 LET X=X+1
 1790 IF X>10 THEN GOTO 2300
 1800 LET POS=1
 1810 GOTO 520
 1820 PRINT "  PAGE TO CLEAR?"
 1830 INPUT X
 1840 IF X>10 OR X<1 THEN GOTO 2320
 1850 LET A$(X)=""
 1860 GOTO 140
 1870 LET GH=0
 1880 LET AS=2
 1890 FAST 
 1900 FOR Z=1 TO 640-32 STEP 32
 1910 FOR Y=Z+31 TO Z STEP -1
 1920 IF A$(X,Y)="<" THEN GOTO 2060
 1930 IF A$(X,Y)=">" THEN GOTO 2030
 1940 IF A$(X,Y)<>" " THEN GOTO 1970
 1950 LET GH=GH+1
 1960 NEXT Y
 1970 LET A$(X)=A$(X,1 TO Z+31-GH)+A$(X,Z+31+1 TO 640)
 1980 FOR Y=Z TO Z+31
 1990 IF GH=0 THEN GOTO 2030
 2000 IF A$(X,Y)=" " THEN GOSUB 2080
 2010 NEXT Y
 2020 IF GH<>0 THEN GOTO 2120
 2030 LET GH=0
 2040 LET AS=2
 2050 NEXT Z
 2060 SLOW 
 2070 GOTO 840
 2080 LET A$(X)=A$(X,1 TO Y-1)+" "+A$(X,Y TO 640)
 2090 LET GH=GH-1
 2100 LET Y=Y+AS
 2110 RETURN 
 2120 LET AS=AS+1
 2130 GOTO 1980
 2140 LET WC=31
 2150 LET WL=WL-1
 2160 RETURN 
 2170 FAST 
 2180 LET WL=INT (POS/32)
 2190 FAST 
 2200 LET WC=POS-WL*32-1
 2210 IF POS/32=INT (POS/32) THEN GOSUB 2140
 2220 PRINT AT WL,WC;"%M"
 2230 SLOW 
 2240 IF INKEY$="" THEN GOTO 2240
 2250 PRINT AT WL,WC;A$(X,POS)
 2260 LET X$=INKEY$
 2270 IF X$=CHR$ 118 THEN GOTO 840
 2280 LET POS=POS+(X$="8")-(X$="5")+32*(X$="6")-32*(X$="7")
 2290 GOTO 2180
 2300 PRINT AT 21,0;"<ERROR>YOU HAVE USED ALL FILES"
 2310 GOTO 2450
 2320 PRINT AT 21,0;"<ERROR>THERE IS NO SUCH PAGE   "
 2330 GOTO 2450
 2340 PRINT AT 21,0;"<ERROR>PROGRAM NAME IS INVALID"
 2350 GOTO 2450
 2360 PRINT AT 21,0;"<ERROR>RUNNING INTO NEXT PAGE"
 2370 GOTO 2450
 2380 PRINT AT 21,0;"<ERROR>WORKING BUFFER IS FULL"
 2390 GOSUB 1620
 2400 GOTO 2450
 2410 PRINT AT 21,0;"<ERROR>TEXT INSERTION IS TOO LARGE"
 2420 FOR F=1 TO 20
 2430 NEXT F
 2440 GOTO 840
 2450 PAUSE 100
 2460 GOTO 140
 2470 CLEAR 
 2480 SAVE "1000%4"
 2490 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