ZX Linotype

Developer(s): James Hill
Date: 1985
Type: Program
Platform(s): TS 1000

ZX Linotype is a full-screen word processor that stores up to 2,250 characters in a single string array, organized into fixed-width lines whose column width (1–32 characters) is chosen at startup. The program offers eight editing modes — Over, Insert, Delete, Scroll, Find, Print, Save, and Erase — cycled with the arrow keys through a status bar. Text justification is implemented in BASIC at lines 1170–1265, inserting spaces into lines to pad them flush with the right margin. Printer output is handled via LPRINT with a screen-preview alternative, and documents are saved to tape using the standard SAVE command with a user-supplied filename. A short machine-code routine is embedded in the REM at line 1, and the program calls USR 16514 and USR 16536 to compute print positions, suggesting the REM code provides utility functions for the display engine.


Program Analysis

Program Structure

The program is organized into clearly delimited subroutine blocks, each introduced by a REM line with inverse-video labels. Control flow is managed by a status variable S (1–8) and a computed GOTO at line 530 that dispatches to the appropriate mode handler.

LinesFunction
1Machine code in REM
4–50Initialisation, dimension T$, set column width C
147–180Screen setup, display current line
300–410Input routine (Over / Insert modes)
500–570Status menu and dispatcher
600–670Delete mode
700–860Scroll mode
900–975Find / search mode
1000–1350Print mode (LPRINT or screen)
1400–1480Save mode
1500–1550Erase / reset
2000–2040Line number display
3000–3040Locate (jump to line number)
9000–9060Title screen and column-width input; SAVE program

Text Storage Model

All document text lives in the single string T$, dimensioned to 2,250 characters at line 10. The program treats T$ as a flat array of fixed-width lines, each C characters long (where C is chosen by the user, 1–32). The current line pointer X is always a multiple of C plus 1, and T tracks the last used character position. Slicing such as T$(X TO X+C-1) extracts one display line, while T$(TO X-1)+I$+T$(X+C TO ) performs over-type insertion.

Machine Code in REM

Line 1 contains a raw machine-code payload embedded in the REM statement. The byte sequence includes Z80 instructions recognisable as: LD BC,nnnn, LD HL,(nnnn), ADD HL,DE, LD D,H / LD E,L, LDIR, RET, and CPIR. The program calls into this code indirectly via USR 16514 (at lines 390, 760, 1320) and USR 16536 (line 840), which return values used as column arguments to PRINT AT. The trailing bytes itemtype='https://schema.org/Blog' itemscope='itemscope' class="wp-singular computer_media-template-default single single-computer_media postid-56749 wp-custom-logo wp-embed-responsive wp-theme-astra wp-child-theme-astra-child ast-desktop ast-separate-container ast-left-sidebar astra-4.12.7 group-blog ast-blog-single-style-1 ast-custom-post-type ast-single-post ast-inherit-site-logo-transparent ast-hfb-header ast-full-width-primary-header ast-box-layout ast-normal-title-enabled astra-addon-4.12.5"C are ASCII/character data likely used as a parameter table.

Status Dispatching

Eight editing modes are encoded in S (1 = Over, 2 = Insert, 3 = Delete, 4 = Scroll, 5 = Find, 6 = Print, 7 = Save, 8 = Erase). The arrow keys 8 (up) and 5 (down) cycle S with wrap-around arithmetic at lines 506–507. The dispatch at line 530 uses a single computed expression:

GOTO 300*(S<3)+600*(S=3)+700*(S=4)+900*(S=5)+1000*(S=6)+1400*(S=7)+1500*(S=8)

This is a classic Sinclair BASIC idiom: only one term is non-zero, producing exactly the desired destination. CHR$ 118 is the ENTER key code used throughout as the confirmation keystroke.

Text Justification Algorithm

When the rightmost character of a line is not a sentence-ending punctuation mark and justification mode J=1 is active (toggled by </> sentinel characters stored in the last column), the print routine (lines 1170–1265) walks the line backwards from position C, finds spaces, and duplicates them (P$=P$(TO Q)+P$(Q TO )) until the line fills to width C. Centering is applied to lines whose last character is * (lines 1270–1300), padding with leading spaces equal to half the whitespace deficit.

Key Idioms and Techniques

  • FAST/SLOW switching: FAST is engaged for computationally intensive operations (input processing, printing loops) and SLOW for interactive display to maintain readable output.
  • Sentinel characters: < and > in the last column of a stored line act as justification on/off flags, and * triggers centering — a compact in-band signalling scheme.
  • Empty-string variable E$: Used pervasively as a blank-line filler (PRINT AT n,0;E$) to clear rows without CLS; E$ is never explicitly assigned, so it defaults to "".
  • £ as command character: The pound sign (currency symbol) is repurposed as a mode-switch trigger (line 320) and as a search-continuation command (line 930), exploiting its non-alphabetic status.
  • Keyboard polling loop: Patterns like IF INKEY$<>"" THEN GOTO n followed immediately by a main poll loop flush any held key before entering a new mode, preventing accidental double-triggers.

Notable Bugs and Anomalies

  • Line 810 (LET X=X-C) is reached by GOTO 810 from line 740, but the listing shows this line numbered 820 with line 810 absent — the GOTO 810 at line 740 targets a non-existent line; on a real system this would cause a NEXT WITHOUT FOR or similar error when scrolling backward unless line 810 exists in the actual tokenised file and was omitted from this listing.
  • The DIM I$(C) at line 40 and DIM P$(C) at line 147 are re-dimensioned each run but I$ is used as an INPUT buffer and P$ as a working line copy — both correctly sized to C characters.
  • Line 9050 (SAVE "ZX %L") and line 9060 (GOTO 1) are unreachable during normal execution; they exist as a developer convenience for re-saving the program.
  • The search routine (lines 941–950) resets X=1 on a new search term but does not reset it when continuing with £, allowing incremental forward search — this is intentional design, not a bug.

Content

Appears On

Related Products

Related Articles

Related Content

Image Gallery

Source Code

   1 REM 1C602AC409545D1E702AC40918C1EDB0C917322AC409545D15222AC40918C1EDB8C921222324251C
   4 REM ZX LINOTYPE  (C) 1985 BY JAMES L. HILL
   5 GOSUB 9000
  10 DIM T$(2250)
  30 LET H$="BEGIN NEW DOCUMENT"
  40 DIM I$(C)
  50 LET T=0
 147 DIM P$(C)
 148 PRINT AT 6,15-LEN H$/2;H$
 150 LET X=1
 160 PRINT AT 2,0;"''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''";AT 5,0;"................................................................";AT 19,0;"<><><><><><><><><><><><><><><><>"
 165 PRINT AT 20,0;T$(X TO X+C-1)
 170 LET S=1
 180 PRINT AT 0,0;S$(S)
 299 REM %I%N%P%U%T% %R%O%U%T%I%N%E
 300 FAST 
 301 PRINT AT 3,0;"ENTER TEXT - ENTER ""£"" TO CHANGESTATUS OR ""££"" FOR LINE NUMBERS "
 302 IF S=1 THEN PRINT AT 19,0;"<<<<<<%T%Y%P%E% %O%V%E%R% %N%E%X%T% %L%I%N%E>>>>>>>"
 303 IF S=2 THEN PRINT AT 19,0;"<<<<<<<<%I%N%S%E%R%T% %T%E%X%T% %H%E%R%E>>>>>>>>"
 309 PRINT AT 21,0;"..%1%2%3%4%5%6%7%8%9%0%1%2%3%4%5%6%7%8%9%0%1%2%3%4%5%6%7%8%9%0.."
 310 INPUT I$
 320 IF I$(1)="£" THEN GOTO 500
 330 IF S=1 AND X>=2250-C+1 THEN GOTO 310
 340 IF S=2 AND T>=2250-C THEN GOTO 310
 350 IF S=1 THEN LET T$=T$( TO X-1)+I$+T$(X+C TO )
 360 IF S=2 THEN LET T$=T$( TO X-1)+I$+T$(X TO )
 370 LET X=X+C
 375 IF S=1 AND X>T THEN LET T=T+C
 380 IF S=2 THEN LET T=T+C
 390 PRINT AT 18,USR 16514;I$
 400 PRINT AT 20,0;T$(X TO X+C-1)
 410 GOTO 309
 499 REM %S%T%A%T%U%S
 500 SLOW 
 501 IF I$(2)="£" THEN GOTO 2000
 502 IF INKEY$<>"" THEN GOTO 502
 503 PRINT AT 3,0;"  USE ARROWS TO CHANGE STATUS          THEN TOUCH ""ENTER""       ";AT 19,0;"<><><><><><><><><><><><><><><><>"
 504 LET D$=INKEY$
 506 IF D$="8" THEN LET S=S+(S<=7)-7*(S=8)
 507 IF D$="5" THEN LET S=S-(S>=2)+7*(S=1)
 508 PRINT AT 0,0;S$(S)
 530 IF D$=CHR$ 118 THEN GOTO 300*(S<3)+600*(S=3)+700*(S=4)+900*(S=5)+1000*(S=6)+1400*(S=7)+1500*(S=8)
 560 PRINT AT 0,0;"0VER   INSERT   DELETE   SCROLL FIND   PRINT    SAVE     ERASE  "
 570 GOTO 504
 600 REM %D%E%L%E%T%E
 601 IF INKEY$<>"" THEN GOTO 615
 605 PRINT AT 3,0;"     SHIFT ""0"" TO DELETE OR      TOUCH ""ENTER"" TO CHANGE STATUS ";AT 19,0;"<<<<<<<<%D%E%L%E%T%E% %N%E%X%T% %L%I%N%E>>>>>>>>"
 615 IF INKEY$<>"" THEN GOTO 615
 620 LET D$=INKEY$
 640 IF D$=CHR$ 118 THEN GOTO 500
 645 IF X>T OR X>=2250-C+1 THEN GOTO 620
 650 IF D$=CHR$ 119 THEN LET T$=T$( TO X-1)+T$(X+C TO )
 655 IF D$=CHR$ 119 THEN LET T=T-C
 660 PRINT AT 20,0;T$(X TO X+C-1)
 670 GOTO 620
 700 REM %S%C%R%O%L%L
 701 IF INKEY$<>"" THEN GOTO 701
 702 PRINT AT 3,0;"    USE ARROWS TO SCROLL OR      TOUCH ""ENTER"" TO CHANGE STATUS "
 710 LET D$=INKEY$
 730 IF D$="7" AND X<T AND X<2250-C+1 THEN GOTO 760
 740 IF D$="6" AND X>=C+1 THEN GOTO 810
 750 IF D$=CHR$ 118 THEN GOTO 500
 755 GOTO 710
 760 PRINT AT 18,USR 16514;T$(X TO X+C-1)
 770 LET X=X+C
 790 PRINT AT 20,0;T$(X TO X+C-1)
 800 GOTO 710
 820 LET X=X-C
 830 PRINT AT 20,0;T$(X TO X+C-1)
 840 IF X>=13*C+1 THEN PRINT AT 6,USR 16536;T$(X-13*C TO X-13*C+C-1)
 850 IF X<13*C+1 THEN PRINT AT 6,USR 16536;E$
 860 GOTO 710
 900 REM %F%I%N%D
 901 IF INKEY$<>"" THEN GOTO 901
 905 PRINT AT 3,0;"ENTER WORD OR PHRASE TO FIND  OR TOUCH ""ENTER"" TO CHANGE STATUS "
 910 SLOW 
 911 INPUT D$
 912 PRINT AT 20,0;E$
 915 IF D$="" THEN GOTO 500
 920 FAST 
 921 FOR N=6 TO 18
 922 PRINT AT N,0;E$
 923 NEXT N
 930 IF D$<>"£" THEN LET F$=D$
 940 IF D$<>"£" THEN LET X=1
 941 FOR N=X TO T-LEN F$+1
 945 IF T$(N TO N+LEN F$-1)=F$ THEN GOTO 965
 950 NEXT N
 955 PRINT AT 20,0;"*******SEARCH IS COMPLETE*******"
 960 GOTO 905
 965 LET X=INT (N/C)*C+1
 970 PRINT AT 20,0;T$(X TO X+C-1);AT 3,0;"ENTER ""£"" TO CONTINUE SEARCH  OR"
 973 LET X=X+C
 975 GOTO 910
 1000 REM %P%R%I%N%T
 1010 IF INKEY$<>"" THEN GOTO 1010
 1020 PRINT AT 3,0;"ENTER ""P""(PRINTER) - ""S""(SCREEN)TOUCH ""ENTER"" TO CHANGE STATUS  "
 1030 INPUT D$
 1035 IF D$="" THEN GOTO 500
 1040 LET PS=(D$="P")
 1050 PRINT AT 3,0;"ENTER NO. OF FIRST LINE TO PRINT";E$
 1060 INPUT L1
 1070 PRINT AT 4,0;"ENTER NO. OF LAST LINE TO PRINT "
 1080 INPUT L2
 1082 FOR N=6 TO 18
 1084 PRINT AT N,0;E$
 1086 NEXT N
 1087 PRINT AT 20,0;E$
 1090 IF PS=1 THEN FAST 
 1092 LET J=0
 1100 IF L2*C>T THEN LET L2=T/C
 1110 FOR N=L1 TO L2
 1115 LET CJ=0
 1120 LET P$=T$(N*C-C+1 TO N*C)
 1130 IF P$(C)="<" THEN LET J=1
 1140 IF P$(C)=">" THEN LET J=0
 1150 IF P$(C)=">" OR P$(C)="<" THEN LET P$(C)=" "
 1160 IF P$(C)="*" THEN GOTO 1270
 1165 IF J=0 THEN GOTO 1310
 1170 FOR M=C TO 1 STEP -1
 1180 IF P$(M)="." OR P$(M)=":" OR P$(M)="?" THEN GOTO 1310
 1190 IF P$(M)<>" " THEN GOTO 1220
 1200 NEXT M
 1210 GOTO 1310
 1220 FOR Q=M TO 1 STEP -1
 1225 IF P$(Q)=" " THEN LET CJ=1
 1230 IF P$(Q)=" " THEN LET P$=P$( TO Q)+P$(Q TO )
 1240 IF P$(C)<>" " THEN GOTO 1310
 1250 NEXT Q
 1260 IF CJ=1 THEN GOTO 1170
 1265 GOTO 1310
 1270 FOR M=C-1 TO 1 STEP -1
 1280 IF P$(M)<>" " THEN GOTO 1300
 1290 NEXT M
 1300 LET P$=E$( TO (C-M)/2)+P$
 1310 IF PS=1 THEN LPRINT P$
 1320 IF PS=0 THEN PRINT AT 18,USR 16514;P$
 1330 NEXT N
 1340 SLOW 
 1350 GOTO 1020
 1400 REM %S%A%V%E
 1410 IF INKEY$<>"" THEN GOTO 1410
 1420 PRINT AT 3,0;"   ENTER NAME OF DOCUMENT OR    TOUCH ""ENTER"" TO CHANGE STATUS  "
 1430 INPUT H$
 1440 IF H$="" THEN GOTO 500
 1450 PRINT AT 3,0;"ENTER ""S"" WHEN RECORDER IS READY";E$
 1460 INPUT D$
 1470 SAVE H$
 1480 GOTO 148
 1500 REM %E%R%A%S%E
 1510 IF INKEY$<>"" THEN GOTO 1510
 1520 PRINT AT 3,0;" ENTER ""E"" TO ERASE DOCUMENT OR  TOUCH ""ENTER"" TO CHANGE STATUS "
 1530 INPUT D$
 1540 IF D$<>"E" THEN GOTO 500
 1545 CLS 
 1546 FAST 
 1550 GOTO 1
 2000 REM %L%I%N%E% %N%U%M%B%E%R%S
 2001 PRINT AT 19,0;E$;AT 19,0;"%L%I%N%E% %B%E%L%O%W%= ";(X+C-1)/C,"%L%I%N%E%S% %U%S%E%D%= ";T/C
 2010 SLOW 
 2020 FOR N=1 TO 40
 2030 NEXT N
 2040 GOTO 300
 3000 REM %L%O%C%A%T%E
 3001 PRINT "ENTER LINE NUMBER"
 3010 INPUT D$
 3015 FAST 
 3020 LET X=(VAL D$)*C-C+1
 3030 IF X>T THEN LET X=T-C+1
 3040 GOTO 160
 9000 REM %T%I%T%L%E
 9001 SLOW 
 9002 PRINT AT 6,10;"ZX LINOTYPE";AT 10,3;"(C) 1985 - JAMES L. HILL";AT 19,4;"TOUCH ""ENTER"" TO BEGIN"
 9010 INPUT D$
 9021 PRINT AT 19,0;"         COLUMN WIDTH?           (ENTER A NUMBER  1 THROUGH 32)"
 9022 INPUT C
 9023 FAST 
 9024 CLS 
 9030 RETURN 
 9050 SAVE "ZX %L"
 9060 GOTO 1

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

Scroll to Top