--- title: "Wordy" id: 56936 type: "computer_media" slug: "wordy" url: "http://localhost/computer_media/wordy/" markdown_url: "http://localhost/computer_media/wordy.md" published_at: "2024-10-02T00:48:49+00:00" modified_at: "2026-04-03T07:58:47+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2024/09/4Wordy.png" excerpt: "A full-featured, ten-page word processor with two editing modes, cut-and-paste buffers, text justification, and printer output — all in pure BASIC." category: - name: "Archived Media" slug: "archived-media" taxonomy: "category" url: "http://localhost/category/archived-media/" post_tag: - name: "Downloadable" slug: "downloadable" taxonomy: "post_tag" url: "http://localhost/tag/downloadable/" - name: "TS 1000" slug: "ts1000" taxonomy: "post_tag" url: "http://localhost/tag/ts1000/" model: - name: "Timex/Sinclair 1000" slug: "ts-1000" taxonomy: "model" url: "http://localhost/model/ts-1000/" genre: - name: "Word Processor" slug: "word-processor" taxonomy: "genre" url: "http://localhost/type/word-processor/" media_contents: - id: 56732 title: "Timex Sinclair Public Domain Library Tape 1001" type: "computer_media" url: "http://localhost/computer_media/timex-sinclair-public-domain-library-tape-1001/" media_type: "Program" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2024/09/4Wordy.png" media_type_tags: "Word Processor" --- # Wordy 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: | Key | Action | | --- | --- | | 5/6/7/8 | Move cursor left/right/up/down (line 940, expression-based) | | H | Home — set `POS=1` | | C | Clear character at cursor (space) | | S | Insert single space, shifting text right; saves overflow to `B$` | | L | Insert a full 32-character blank line, saving overflow to `B$` | | I | Insert typed string at cursor position | | D | Delete character, pulling from `B$` if available | | 1 | Cut *n* characters to clipboard `D$` | | P | Paste clipboard `D$` at cursor | | A/B | Move to next/previous page (flushing `B$`) | | O | Clear working buffer `B$` | | J | Justify current page | | W | Switch to Writing mode (flushing `B$`) | | T | Wait and accept a single typed character | | M | Move-cursor submode | | E | Exit to main menu (flushing `B$`) | | R | Redraw 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. ## 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" 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;"YOU HAVE USED ALL FILES" 2310 GOTO 2450 2320 PRINT AT 21,0;"THERE IS NO SUCH PAGE " 2330 GOTO 2450 2340 PRINT AT 21,0;"PROGRAM NAME IS INVALID" 2350 GOTO 2450 2360 PRINT AT 21,0;"RUNNING INTO NEXT PAGE" 2370 GOTO 2450 2380 PRINT AT 21,0;"WORKING BUFFER IS FULL" 2390 GOSUB 1620 2400 GOTO 2450 2410 PRINT AT 21,0;"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 ```