--- title: "Word Pro" id: 55218 type: "computer_media" slug: "word-pro" url: "http://localhost/computer_media/word-pro/" markdown_url: "http://localhost/computer_media/word-pro.md" published_at: "2024-06-20T11:50:00+00:00" modified_at: "2026-03-31T23:19:01+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2019/02/20230809-041332.jpg" excerpt: "A full-featured BASIC word processor supporting 300-line documents, text justification, tape save/load, and character-by-character keyboard editing with cursor control." 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 2068" slug: "ts2068" taxonomy: "post_tag" url: "http://localhost/tag/ts2068/" model: - name: "Timex/Sinclair 2068" slug: "ts-2068" taxonomy: "model" url: "http://localhost/model/ts-2068/" indiv: - name: "Peter Hoffman" slug: "peter-hoffman" taxonomy: "indiv" url: "http://localhost/indiv/peter-hoffman/" genre: - name: "Word Processor" slug: "word-processor" taxonomy: "genre" url: "http://localhost/type/word-processor/" media_contents: - id: 55220 title: "Long Island Sinclair Timex (LIST) User Group Library Tape #7" type: "computer_media" url: "http://localhost/computer_media/long-island-sinclair-timex-list-user-group-library-tape-7/" media_type: "Program" programmers: - name: "Peter Hoffman" slug: "peter-hoffman" taxonomy: "indiv" url: "http://localhost/indiv/peter-hoffman/" download_url: "https://archive.org/download/timex-sinclair-software-archive/Word%20Pro%20%28198x%29%28Hoffmann%2C%20Peter%29%28TS2068%29%28US%29%28Program%29.zip" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2024/06/Word-Pro.png" media_type_tags: "Word Processor" --- Word Pro is a screen-based word processor that stores up to 300 lines of 32-character text in a single two-dimensional string array, `w$(300,32)`, supporting up to 15 pages of 20 lines each. Text entry uses a character-by-character input loop with PAUSE 0 and INKEY$, handling backspace (CHR$ 8), tab/cursor movement (CHR$ 9), delete (CHR$ 12), and carriage return (CHR$ 13). A justify routine (lines 5000–5300) right-justifies text by iteratively inserting spaces after existing spaces until the 32nd column is filled. Completed documents can be saved to or loaded from tape as a DATA array using SAVE/LOAD with the array name, and a COPY command sends the current page to the printer. *** ## Program Analysis ### Program Structure The program is organized into several clearly separated functional blocks: 1. **Lines 1–25:** Initialization and main menu (Load from tape or keyboard entry). 2. **Lines 100–600:** Full-screen text editor for one 20-line page. 3. **Lines 1000–1210:** Post-page menu: Print, Justify, Continue, or Save. 4. **Lines 5000–5300:** Text justification subroutine. 5. **Lines 7000–7070:** Load text array from tape and review it. 6. **Lines 8000–8050:** Save text array to tape. 7. **Lines 9000, 9999:** Program self-save and stop. ### Data Storage The entire document is stored in `w$(300,32)`, a two-dimensional string array of 300 rows, each 32 characters wide. Pages are indexed by variable `x` (0–14), giving a maximum of 15 pages of 20 lines each (300 lines total). The current page’s row `j` maps to array index `x*20+j+1`. This layout allows the entire document to be saved and loaded as a single DATA array with `SAVE n$ DATA w$()` and `LOAD n$ DATA w$()`. ### Text Entry Loop The editor (lines 200–600) uses nested `FOR` loops over rows (`j`, 0–19) and columns (`l`, 0–31). Each iteration calls `PAUSE 0` followed by `INKEY$` to wait for a keypress. The column variable `l` is manipulated directly within the loop body using `GO TO 500` (to `NEXT l`) or `GO TO 540` (to skip past `NEXT l` to `NEXT j`), effectively using the FOR loop counter as a cursor position that can be rewound or advanced. ### Control Character Handling | CHR$ code | Key | Action | | --- | --- | --- | | 8 | Backspace | Moves cursor left; wraps to previous line at column 0 | | 9 | Tab/Right | Moves cursor right; wraps to next line at column 31 | | 12 | Delete | Clears current character and moves left; wraps to previous line | | 13 | Enter/Return | Stores CHR$ 13 as a line-end marker and advances to next row | Line 400 discards any remaining control characters below CHR$ 32. Line 360 detects a period entered in column 0 as a document-end sentinel, jumping to the post-page menu. ### Right Margin and Word-Wrap Behavior At column 26, a short beep warns the user they are approaching the right margin (line 520). If a space or hyphen is typed at columns 26–31 (line 530), `l` is set to 32, which causes `NEXT l` to terminate the inner loop and advance to the next row — a simple word-wrap trigger. If a non-space, non-return character is typed exactly at column 31 (line 410), it is silently replaced with a hyphen (CHR$ 45), forcing a hard line break. ### Justification Subroutine (Lines 5000–5300) The justification routine processes each line of the current page. For lines that do not already fill column 32, it repeatedly scans left-to-right for spaces and shifts all characters from that position rightward by one, inserting an extra space. The scan restarts from progressively later positions (`d` tracks offset) on each pass, distributing inserted spaces somewhat evenly. The loop continues until column 32 is non-space or all 32 characters are blank. Justified lines are written back to `w$(j)` and reprinted on screen. ### Tape Load Review Mode After loading from tape (lines 7000–7050), the program prints each block of 20 lines using `LPRINT` rather than `PRINT`, sending output to the printer. The user can stop or continue reviewing pages, then choose to repeat or exit. This appears to serve as a “print loaded document” path rather than a display-review path. ### Notable Bugs and Anomalies - **Line 370 condition:** The delete-left handler checks `1<>0` (a literal `1`) instead of `l<>0`, so this branch is always true regardless of column position. This is almost certainly a typo for `l<>0`, meaning the column-boundary check for delete is never applied. - **Line 330 backspace wrap:** When wrapping to the previous row, the column is set to 30 (via `l=30`, which becomes 31 after `NEXT l`), placing the cursor at the last character of the previous line rather than the last filled character. - **Line 5030 loop termination:** The `IF s=32 THEN GO TO 5200` appears after `NEXT l` on the same logical line, relying on the Spectrum BASIC behavior of executing the `IF` after the loop completes. - **Line 8030:** The REM at line 4 instructs the user to type `GOTO 8030` to return to the Print/Justify/Continue menu, but line 8030 actually begins the SAVE sequence rather than jumping to line 1000. This is misleading documentation. - **Line 9000:**`CLEAR : SAVE "WP" LINE 0` attempts to auto-run from line 0, which does not exist; the program starts at line 1. ### Key BASIC Idioms - Using `FOR` loop variables as cursor coordinates, manipulated mid-loop with `GO TO`, is a common ZX Spectrum BASIC technique for screen editors. - `PAUSE 0` immediately before `INKEY$` is the standard efficient keypress-wait idiom. - Two-dimensional string arrays are used for structured document storage, avoiding the need for string concatenation or parsing. - `b$` (a 32-space string from `DIM b$(32)`) is used as a blank-line printer to clear status rows. ## Source Code ``` 1 REM "word pro" 2 REM submittedto LIST by Peter Hoffmann 3 REM to end letter or document type a .(period) at beginning of next line 4 REM type GOTO 8030 to get back to Print/Justify/Continue menu 5 DIM w$(300,32): DIM b$(32) 10 CLS : PRINT TAB 10;"TS2068-word pro";AT 5,0;"T=LOAD TEXT FROM TAPE"''"K=ENTER TEXT FROM KEYBOARD" 15 IF INKEY$="k" OR INKEY$="K" THEN GO TO 100 20 IF INKEY$="t" OR INKEY$="T" THEN GO TO 7000 25 GO TO 15 100 LET x=0 150 CLS 200 FOR j=0 TO 19 210 FOR l=0 TO 31 300 PRINT AT j,l; FLASH 1; OVER 1;CHR$ 32 310 PAUSE 0: LET i$=INKEY$ 320 IF i$=CHR$ 8 AND l<>0 THEN LET l=l-2: GO TO 500 330 IF i$=CHR$ 8 AND j<>0 THEN PRINT AT j,0;w$(x*20+j+1,1): LET j=j-1: LET l=30: GO TO 500 340 IF i$=CHR$ 9 AND l<>31 THEN GO TO 500 350 IF i$=CHR$ 9 AND j<>19 THEN PRINT AT j,31;CHR$ (CODE (w$(x*20+j+1,32))+19*(w$(x*20+j+1,32)=CHR$ 13)): LET j=j+1: LET l=1: GO TO 500 360 IF l=0 AND i$="." THEN LET l=31: LET j=19: GO TO 540 370 IF i$=CHR$ 12 AND 1<>0 THEN LET w$(x*20+j+1,l)=CHR$ 32: LET l=l-2: GO TO 500 380 IF i$=CHR$ 12 AND j<>0 THEN PRINT AT j,0;w$(x*20+j+1): LET j=j-1: LET l=31: LET w$(x*20+j+1,l)=CHR$ 32: LET l=l-2: GO TO 500 390 IF i$=CHR$ 13 THEN LET l=31: GO TO 410 400 IF i$CHR$ 32 AND i$<>CHR$ 13 THEN LET i$=CHR$ 45 420 BEEP .01,20+20*(i$=CHR$ 32) 430 LET w$(x*20+j+1,l+1)=i$ 500 PRINT AT j,0;w$(x*20+j+1) 510 IF w$(x*20+j+1,32)=CHR$ 13 THEN PRINT AT j,31;CHR$ 32 520 IF l=26 THEN BEEP .5,50 530 IF l>25 AND (i$=CHR$ 32 OR i$=CHR$ 45) THEN LET l=32 540 NEXT l: BEEP .5,20 600 NEXT j 1000 PRINT AT 21,0;"P=PRINT:J=JUSTIFY:C=CONT" 1010 IF INKEY$="c" OR INKEY$="C" THEN GO TO 1100 1020 IF INKEY$="P" OR INKEY$="p" THEN GO TO 1050 1030 IF INKEY$="J" OR INKEY$="j" THEN GO SUB 5000: GO TO 1000 1040 GO TO 1010 1050 PRINT AT 21,0;b$: COPY : GO TO 1000 1100 CLS : PRINT "M=More Text:S=Save" 1110 IF INKEY$="M" OR INKEY$="m" THEN GO TO 1200 1120 IF INKEY$="S" OR INKEY$="s" THEN GO TO 8000 1130 GO TO 1110 1200 IF x=14 THEN PRINT AT 21,0;"No More room:Choose Save option": PAUSE 0: GO TO 1100 1210 LET x=x+1: GO TO 150 5000 PRINT AT 21,0;b$ 5005 FOR j=x*20+1 TO x*20+20 5010 LET a$=w$(j) 5015 IF a$(32)<>CHR$ 32 THEN GO TO 5200 5020 LET s=0: FOR l=32 TO 1 STEP -1 5025 IF a$(l)<>CHR$ 32 THEN GO TO 5035 5030 LET s=s+1: NEXT l: IF s=32 THEN GO TO 5200 5035 LET d=2 5040 FOR l=2 TO 32 5045 IF a$(l)<>CHR$ 32 THEN GO TO 5090 5050 FOR k=32 TO l+1 STEP -1: LET a$(k)=a$(k-1): NEXT k 5055 LET l=l+d 5060 IF a$(32)<>CHR$ 32 THEN GO TO 5100 5090 NEXT l 5100 PRINT AT j-x*20-1,0;a$ 5150 IF a$(32)=CHR$ 32 THEN LET d=d+1: GO TO 5040 5170 LET w$(j)=a$ 5200 NEXT j 5300 RETURN 7000 INPUT "Filename?";n$ 7005 IF n$="" THEN GO TO 7000 7010 PRINT AT 15,0;"LOAD TAPE";n$ 7015 LOAD n$ DATA w$() 7020 LET x=0 7025 FOR j=x+1 TO x+20: LPRINT w$(j): NEXT j 7030 LET x=x+20: IF x=300 THEN GO TO 7055 7035 CLS : PRINT "Press S to stop"''"or any other key to continue" 7040 PAUSE 0 7045 IF INKEY$="s" OR INKEY$="S" THEN GO TO 7055 7050 GO TO 7025 7055 CLS : PRINT "TEXT COMPLETE"''"PRESS R TO REPEAT"''"OR X TO STOP" 7060 IF INKEY$="R" OR INKEY$="r" THEN GO TO 7020 7065 IF INKEY$="X" OR INKEY$="x" THEN GO TO 9999 7070 GO TO 7060 8000 INPUT "Filename?";n$ 8010 IF n$="" THEN GO TO 8000 8020 IF LEN n$>10 THEN LET n$=n$( TO 10) 8030 PRINT "Saving as: ";n$ 8040 SAVE n$ DATA w$() 8050 GO TO 9999 9000 CLEAR : SAVE "WP" LINE 0 9999 STOP ```