Baby Syntext

This file is part of and Synchro-Sette April 1983. Download the collection to get this file.
Date: April 1983
Type: Program
Platform(s): TS 1000

This program implements a full-screen text editor for the ZX81/TS1000, storing up to 2,880 characters of text in the string array A$(2880) and displaying a 22×32 window into that buffer on screen. The editor supports cursor movement in four directions (including word-wrap logic), insert, delete, carriage return, and tab-like jumps of 8 positions, all driven by Sinclair shifted-key codes detected via INKEY$. A blinking cursor is simulated in the GOSUB 5000 subroutine by printing a block graphic and immediately overprinting with the actual buffer character at the current position. The buffer is paged: variable A tracks the index of the first character in the current display window, advancing or retreating in steps of 32 (one screen row) as the cursor moves off screen. An auxiliary 32-character string D$ is used for the “clear to end of line” function, and a HELP menu at line 3000 documents all key bindings.


Program Analysis

Program Structure

The program is organised into a set of clearly separated functional blocks:

  1. Lines 10–70: Initialisation — allocates A$(2880) as the text buffer, sets cursor position variables, and allocates D$(32) as a scratch line buffer.
  2. Line 300: Display refresh — PRINT AT 0,0;A$(A TO A+703) renders the current 22-row window (22 × 32 = 704 characters).
  3. Lines 100–999: Main dispatch loop — calls the keyboard subroutine at 5000 and uses a chain of IF CODE B$=… THEN GOTO tests to route each keypress to its handler.
  4. Lines 1000–1900: Individual key handlers (carriage return, backspace, cursor movement, insert, delete, tab-right, end-of-screen, end-of-line).
  5. Lines 3000–3099: Help menu display.
  6. Lines 3500–3570: Tape save routine.
  7. Lines 5000–5040: Keyboard input / cursor blink subroutine.
  8. Lines 6000–6060: Line-wrap subroutine called when Y exceeds 31.
  9. Lines 7000–7040: Standalone screen dump subroutine (not called from the main loop; likely a debugging aid).
  10. Line 9998–9999: Program self-save and restart.

Buffer and Window Model

The text buffer is the 2,880-character string A$. The display window always shows 704 characters (22 rows × 32 columns) starting at index A. The absolute buffer index of the cursor is B. Screen row and column are tracked in X and Y respectively. Scrolling is achieved by incrementing or decrementing A by 32 (one row), keeping X clamped to 0–21. This means the editor can hold 2880 ÷ 32 = 90 screen-rows of text, far exceeding what can be displayed at once.

The boundary guard at line 5020 warns the user when B exceeds 2816 (i.e., within the last 64 characters of the buffer), printing an inverse-video “NO MORE TEXT CAN BE ENTERED” message.

Key Dispatch Table

CodeKeyHandlerAction
19SHIFT+B1800Jump to beginning (A, last position in window)
115SHIFT+5 / cursor left1000Overtype with buffer char / cursor left
221SHIFT+T1900Clear to end of line
114SHIFT+6 / cursor right-ish1100Backspace / cursor left
216SHIFT+H3000Help menu
16SHIFT+I1200Insert blank at cursor
225SHIFT+S3500Save to tape
228SHIFT+D1300Delete character at cursor
23SHIFT+?20Restart (go to beginning)
113SHIFT+7 / cursor down1400Move cursor down one row
112SHIFT+8 / cursor up1500Move cursor up one row
118ENTER1600Carriage return (move to start of next line)
220SHIFT+N1700Move right 8 positions (tab)
218SHIFT+?191Replace with space graphic "\ '"

Cursor Blink Technique

The subroutine at line 5000 implements a software cursor blink without machine code. Line 5010 uses two consecutive PRINT AT clauses in a single statement: first it prints the block graphic "\. " (▖, a lower-left quarter block) at position (X,Y) to act as a visible cursor marker, then immediately overprints the actual buffer character A$(B) at the same position, creating a flicker effect as the display refreshes. The INKEY$ poll at line 5000 is non-blocking, looping back until a key is held down.

Insert and Delete

Insert (line 1200) uses ZX81 string slicing to open a gap: LET A$=A$( TO B-1)+" "+A$(B TO 2879). This concatenates everything before the cursor with a space and everything from the cursor onward, dropping the last character to keep the total length at 2880. Delete (line 1300) does the reverse: LET A$=A$( TO B-1)+A$(B+1 TO 2880)+" ", removing the character at B and appending a trailing space. Both operations are O(n) in buffer size and will be noticeably slow on real hardware as the buffer fills.

Clear to End of Line

Line 1900 uses LET A$(B TO B+31-Y)=D$(Y+1 TO 32), where D$ is a 32-character string (initialised by DIM D$(32) which fills it with spaces). This overwrites from the cursor position to the end of the current 32-character row with spaces in a single slice assignment — an efficient use of string array slicing.

Carriage Return Behaviour

The ENTER key handler (line 1600) does not insert a newline character into the buffer. Instead it simply advances B to the start of the next row by computing B=B+32-Y, then calls the line 1420 column-overflow handler. This means the editor is a fixed-width, grid-based word processor rather than a stream-oriented text editor — lines are always exactly 32 characters wide.

Content

Appears On

Cassette to accompany the April 1983 issue of Synchro-Sette.

Related Products

Related Articles

Related Content

Image Gallery

Source Code

  10 DIM A$(2880)
  20 LET X=0
  30 LET Y=0
  40 LET A=1
  50 LET B=1
  60 DIM D$(32)
  70 GOTO 300
 100 SLOW 
 102 GOSUB 5000
 103 FAST 
 105 IF CODE B$=19 THEN GOTO 1800
 110 IF CODE B$=115 THEN GOTO 1000
 115 IF CODE B$=221 THEN GOTO 1900
 120 IF CODE B$=114 THEN GOTO 1100
 125 IF CODE B$=216 THEN GOTO 3000
 130 IF CODE B$=16 THEN GOTO 1200
 135 IF CODE B$=225 THEN GOTO 3500
 140 IF CODE B$=228 THEN GOTO 1300
 150 IF CODE B$=23 THEN GOTO 20
 160 IF CODE B$=113 THEN GOTO 1400
 170 IF CODE B$=112 THEN GOTO 1500
 180 IF CODE B$=118 THEN GOTO 1600
 190 IF CODE B$=220 THEN GOTO 1700
 191 IF CODE B$=218 THEN LET B$=" '"
 200 LET A$(B)=B$
 210 LET B=B+1
 220 LET Y=Y+1
 230 IF Y>31 THEN GOSUB 6000
 300 PRINT AT 0,0;A$(A TO A+703)
 999 GOTO 100
 1000 LET B$=A$(B)
 1010 IF X=21 AND Y=31 THEN GOTO 1030
 1020 GOTO 200
 1030 LET Y=-1
 1040 LET A=A+32
 1050 LET B$=A$(B)
 1060 GOTO 200
 1100 IF B=1 THEN GOTO 100
 1105 LET B$=A$(B)
 1110 LET B=B-1
 1120 LET Y=Y-1
 1130 IF Y<0 THEN GOTO 1150
 1140 GOTO 300
 1150 LET Y=31
 1160 LET X=X-1
 1170 IF X<0 THEN GOTO 1190
 1180 GOTO 300
 1190 LET X=0
 1192 IF A<32 THEN GOTO 300
 1194 LET A=A-32
 1199 GOTO 300
 1200 LET A$=A$( TO B-1)+" "+A$(B TO 2879)
 1210 GOTO 300
 1300 LET A$=A$( TO B-1)+A$(B+1 TO 2880)+" "
 1310 GOTO 300
 1400 LET X=X+1
 1410 LET B=B+32
 1420 IF X=22 THEN GOTO 1440
 1430 GOTO 300
 1440 LET A=A+32
 1450 LET X=21
 1460 GOTO 300
 1500 IF B<33 THEN GOTO 300
 1510 LET B=B-32
 1520 IF X=0 THEN GOTO 1550
 1530 LET X=X-1
 1540 GOTO 300
 1550 LET A=A-32
 1560 GOTO 300
 1600 LET B=B+32-Y
 1610 LET X=X+1
 1620 LET Y=0
 1630 GOTO 1420
 1700 LET B=B+8
 1710 LET Y=Y+8
 1720 IF Y>31 THEN GOTO 1740
 1730 GOTO 300
 1740 LET Y=Y-32
 1750 LET X=X+1
 1760 GOTO 1420
 1800 LET B=A+703
 1810 LET X=21
 1820 LET Y=31
 1830 GOTO 300
 1900 LET A$(B TO B+31-Y)=D$(Y+1 TO 32)
 1910 GOTO 300
 3000 CLS 
 3005 PRINT "     HELP MENU"
 3010 PRINT ,,"SHIFT <5>","CURSOR LEFT"
 3015 PRINT "SHIFT <6>","CURSOR DOWN"
 3020 PRINT "SHIFT <7>","CURSOR UP"
 3025 PRINT "SHIFT <8>","CURSOR RIGHT"
 3030 PRINT "SHIFT <B>","BEGINNING TEXT"
 3035 PRINT "SHIFT <N>","END OF SCREEN"
 3040 PRINT "SHIFT <Y>","RIGHT 8 POS."
 3045 PRINT "SHIFT <T>","CLEAR END LINE"
 3050 PRINT "SHIFT <I>","INSERT BLANK"
 3055 PRINT "SHIFT <D>","DELETE R. CHAR."
 3060 PRINT "SHIFT <H>","HELP MENU"
 3065 PRINT "SHIFT <S>","SAVE ON TAPE"
 3070 PRINT "ENTER","CARR. RET."
 3080 PRINT ,,"IF PROGRAM BREAKS, <GOTO 20>    FOR BEGINNING OF TEXT. <GOTO    300> FOR LAST CURSOR POSITION.  DO NOT PRESS THE <BREAK> KEY FORSPACE BETWEEN CHARACTERS."
 3097 INPUT Z$
 3098 CLS 
 3099 GOTO 300
 3500 CLS 
 3510 PRINT ,,"SET UP RECORDER AND ENTER NAME  OF FILE. FILE WILL BE SAVED WHEN<ENTER KEY IS PRESSED."
 3520 SLOW 
 3530 INPUT Y$
 3540 SAVE Y$
 3550 FAST 
 3560 CLS 
 3570 GOTO 300
 5000 LET B$=INKEY$
 5010 PRINT AT X,Y;". ";AT X,Y;A$(B)
 5020 IF B>2816 THEN PRINT AT 21,0;"% %N%O% %M%O%R%E% %T%E%X%T% %C%A%N% %B%E% %E%N%T%E%R%E%D% "
 5030 IF B$="" THEN GOTO 5000
 5040 RETURN 
 6000 LET X=X+1
 6010 LET Y=0
 6020 IF X=22 THEN GOTO 6040
 6030 RETURN 
 6040 LET X=21
 6050 LET A=A+32
 6060 RETURN 
 7000 FAST 
 7010 CLS 
 7020 PRINT A$(A TO A+703)
 7030 SLOW 
 7040 RETURN 
 9998 SAVE "SYNTEX%T"
 9999 RUN 

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

People

No people associated with this content.

Scroll to Top