Spectrum LOGO is a full turtle-graphics interpreter written in BASIC that implements a substantial subset of the LOGO programming language, including commands for movement (FORWARD, BACK), turning (LEFT, RIGHT), pen control (PENUP, PENDOWN, PENCOLOUR), wrapping behavior (WRAP, NOWRAP), coordinate positioning (SETX, SETY, SETXY, SETHEADING), and structured repetition (REPEAT). Users can define and edit named procedures using DEFINE and EDIT, with each procedure stored as a packed string in arrays using CHR$ 0 as a delimiter. The interpreter supports both full keyword names and two-character abbreviations, dispatching execution via a table of line-number addresses stored in numeric arrays. Wrap-around drawing uses trigonometric calculations to clip and continue lines at screen boundaries, and the turtle cursor itself is drawn using PLOT/DRAW with INVERSE to toggle its visibility.
Program Structure
The program is organized into clearly separated functional regions by line number ranges:
- Lines 60–300: Initialization — dimensions arrays, loads command dispatch tables from
DATAstatements. - Lines 400–480: Setup — pokes flags, allocates runtime buffers, jumps to HOME and the main input loop.
- Lines 520–760: Error handler — dispatches to error message strings based on an
errcode. - Lines 1030–1070: Tokenizer subroutine — walks
z$extracting whitespace-delimited tokens intoy$. - Lines 1110–1190: Turtle cursor drawing — draws a small arrow indicating heading using PLOT/DRAW with INVERSE.
- Lines 1220–1290: Number parser — validates and converts a token to a numeric value in
a. - Lines 1300–1350: Procedure name lookup — checks
f$()array and dispatches viag()addresses. - Lines 1400–1710: Boundary clipping — trigonometric routines for wrapping lines at screen edges (X and Y axes separately, then combined).
- Lines 2020–2230: Main REPL — reads input, dispatches to 2-char abbreviations via
x$()/u()or full names viaw$()/v(). - Lines 3020–3660: Movement commands — FORWARD, BACK, LEFT, RIGHT, including wrap-around draw logic.
- Lines 3820–3900: HOME and CLS — resets turtle to center screen at heading 0.
- Lines 4020–4715: Pen and positional commands — PENUP, PENDOWN, REPEAT, PENCOLOUR, WRAP, NOWRAP, SAVE, COPY, STOP, SETX, SETY, SETXY, SETHEADING.
- Lines 5005–5130: DEFINE — interactive procedure definition with multi-line input.
- Lines 5205–5730: EDIT — full-screen interactive editor for stored procedures (edit, insert, delete, remove).
- Lines 6005–6050: Procedure call executor — pushes/pops state for nested procedure calls.
- Line 8010–8020: RANDOM command — returns a random integer in the range [0, a).
Command Dispatch Tables
All commands are resolved through three parallel arrays loaded at startup from DATA blocks:
| Array | Purpose | Size |
|---|---|---|
x$() / u() | 2-character abbreviations and their target line numbers | 16 entries |
w$() / v() | Full keyword names (up to 12 chars) and their target line numbers | 22 built-in entries |
f$() / g() | Extended or special command names and their target line numbers | 1 entry initially (RANDOM) |
Line numbers in the dispatch tables are stored as VAL "nnnn" expressions in the DATA statements — a standard memory-optimization technique for BASIC that avoids storing large integer literals directly. Dispatch is performed with GO SUB u(i) or GO SUB v(i), targeting the appropriate handler subroutine.
Tokenizer and Parser
The subroutine at line 1030 implements a simple whitespace-delimited tokenizer. It walks the current input string z$ from position s, skipping spaces and CHR$ 0 characters, and accumulates non-whitespace characters into y$. The flag t tracks whether token collection has started. The flag t1 is set when the end of the string is reached.
Numeric parsing at line 1220 validates that each character of y$ is a digit (ASCII codes 48–57) before applying VAL y$ to obtain the value.
Turtle State and Cursor
Turtle state is maintained in the following global variables:
x,y— current pixel position (screen coordinates 0–255, 0–175)dir— current heading in degrees (0 = up/north)pp— pen state:SGN PI(1) = pen down,NOT PI(0) = pen upwr— wrap mode:SGN PI= wrap enabled,NOT PI= no-wrapturt— turtle visibility: 0 = visible, 1 = hidden; used as the INVERSE parameter in PLOT/DRAW calls
The turtle cursor is drawn at line 1110 as two short lines emanating from the turtle position at angles 160° and 200° offset from the heading, using PLOT INVERSE turt to toggle the pixels. This makes the cursor appear and disappear cleanly without erasing background graphics.
Wrap-Around Drawing
Lines 1400–1710 implement edge-wrapping using trigonometry. The subroutine at 1600 determines which boundary (left, right, top, or bottom) a line will hit first, computes the intersection point, draws to that point, subtracts the distance traveled from the remaining distance a, then continues from the opposite edge. This is repeated via GO TO 3050 until the full distance is drawn. The heading angle q is converted to radians for SIN/COS/TAN calculations.
Procedure Definition and Storage
User-defined procedures are entered interactively via the DEFINE command (line 5005). Each procedure body consists of up to 10 lines of up to 28 characters each, stored in the 2D string array b$() with lengths in c(). When definition is complete, all lines are concatenated into a single string separated by CHR$ 0 delimiters and stored in k$(def) with total length in l(def). The procedure name (padded to 12 characters) is stored in w$(n+def), extending the command dispatch table at runtime. Up to 40 user procedures can be defined (DIM k$(40, 200)).
Procedure Execution and Call Stack
The subroutine at line 6005 handles procedure calls with a software call stack using arrays m() and n() (dimensioned to 40). Before entering a procedure, it saves the current command index (comm) and string position (s). The variable count tracks the stack depth. On return, the saved state is restored. The outermost level saves the original input string z$ and position into p$ and s1.
REPEAT Implementation
REPEAT is implemented using a separate stack array r(20, 2), where each entry stores the start position in the input string and the remaining iteration count. The subroutine at 4110 finds and validates the opening [ bracket, then stores the position and count. The ] command (line 4200) decrements the count and jumps back to the saved position or pops the stack when done. Up to 20 nested REPEATs are supported.
Constant Encoding Idioms
Throughout the program, numeric constants are expressed using BASIC intrinsic functions rather than literal integers, a common technique to reduce token storage size:
SGN PI— evaluates to 1NOT PI— evaluates to 0INT PI— evaluates to 3VAL "nnnn"— used for larger constants, especially line-number targets in dispatch tables
Interactive Editor
The EDIT command (line 5200) provides a full-screen procedure editor. After looking up the named procedure and unpacking it into b$()/c(), it presents a menu with five options: edit a line, insert a line, delete a line, remove the whole procedure, or return. INKEY$ polling is used throughout the editor for single-keypress menu selection. Line display is formatted with PRINT i; TAB 3; b$(i).
Notable Anomalies
- Line
5415has a logical bug: the conditionz$<"0" AND z$> STR$ (k-SGN PI)uses AND where OR was likely intended, so valid line-number input may not be correctly rejected. - Line
5520referencesGO TO VAL "5915"which is the RETURN of the yes/no confirmation subroutine — branching into the middle of a subroutine body to effectively skip input and return immediately, an intentional shortcut. - The variable names
mandnare reused: initially scalar variables holding array dimension counts (lines 60–70), they are later re-dimensioned as arraysDIM m(40)andDIM n(40)at line 470, which destroys the original scalar values. This works because the scalar values are no longer needed after initialization. - Line
3800(the DRAW/HOME subroutine referenced byGO SUB VAL "3800"at line480) does not correspond to any listed line; the actual home initialization is at line3820. The program relies on BASIC’s behavior of running the next available line when a non-existent line is targeted.
Source Code
60 READ m:READ n:READ o
65 DIM x$(m, VAL "2"):DIM w$(n+ VAL "40", VAL "12"):DIM f$(o, VAL "12")
70 DIM u(m) :DIM v(n):DIM g(o)
75 LET pp= SGN PI:LET wr= SGN PI:LET turt= SGN PI
80 FOR i= SGN PI TO m:READ x$(i)
85 READ u(i):NEXT i
90 FOR i= SGN PI TO n:READ w$(i)
95 READ v(i):NEXT i
100 FOR i= SGN PI TO o:READ f$(i)
105 READ g(i):NEXT i
110 DATA VAL "16", VAL "22", SGN PI
115 DATA "FD", VAL "3000","BK", VAL "3200","LT", VAL "3400","RT", VAL "3600"
120 DATA "PU", VAL "4000","PD", VAL "4050"
125 DATA "RP", VAL "4100","PC", VAL "4300","WR", VAL "4400","NW", VAL "4600"
130 DATA "SX", VAL "4600","SY", VAL "4630","XY", VAL "4660","SH", VAL "4700"
135 DATA "DF", VAL "5000","ED", VAL "5200"
200 DATA "FORWARD", VAL "3000","BACK", VAL "3200","LEFT", VAL "3400"
205 DATA "RIGHT", VAL "3600","DRAW", VAL "3800","HOME", VAL "3850"
210 DATA "PENUP", VAL "4000","PENDOWN", VAL "4050"
215 DATA "REPEAT", VAL "4100","]", VAL "4200","PENCOLOUR", VAL "4300","WRAP", VAL "4400","NOWRAP", VAL "4450"
220 DATA "SAVE", VAL "4500","COPY", VAL "4520","STOP", VAL "4550"
225 DATA "SETX", VAL "4600","SETY", VAL "4630","SETXY", VAL "4660","SETHEADING", VAL "4700"
230 DATA "DEFINE", VAL "5000","EDIT", VAL "5200"
300 DATA "RANDOM", VAL "8000"
400 POKE VAL "23658", VAL "8"
450 DIM r(VAL "20", VAL "2")
465 LET def= NOT PI:DIM k$(VAL "40", VAL "200"):DIM l(VAL "40")
470 DIM b$(VAL "10", VAL "28"):DIM c(VAL "10"):DIM m(VAL "40"):DIM n(VAL "40")
480 GO SUB VAL "3800":GO TO VAL "2000"
520 GO SUB (VAL "690"+err* VAL "10")
530 PRINT # SGN PI;a$
540 PAUSE VAL "250"
550 RETURN
700 LET a$="Command error - re-enter the line.":RETURN
710 LET a$="Number error - re-enter the line":RETURN
720 LET a$="No wrap - the line cannot be drawn":RETURN
730 LET a$="Too many REPEATS":RETURN
740 LET a$="DEFINE name error":RETURN
750 LET a$="No room for further commands":RETURN
760 LET a$="Incorrect Command name":RETURN
1030 LET t= NOT PI:LET y$=""
1040 LET s=s+ SGN PI:IF s> LEN z$ THEN LET t1= SGN PI:RETURN
1050 IF (z$(s)=" " OR z$(s)= CHR$ NOT PI) AND t= NOT PI THEN GO TO VAL "1040"
1060 IF (z$(s)=" " OR z$(s)= CHR$ NOT PI) AND t= SGN PI THEN RETURN
1070 LET y$=y$+z$(s):LET t= SGN PI:GO TO VAL "1040"
1110 IF x< INT PI OR x> VAL "252" OR y< INT PI OR y> VAL "172" THEN RETURN
1120 FOR j= VAL "160" TO VAL "200" STEP VAL "40"
1130 LET q=dir+j:IF q< NOT PI THEN LET q= VAL "360"-j
1140 IF q> VAL "360" THEN LET q=q- VAL "360"
1150 LET q=q* PI/ VAL "180"
1160 LET x1= VAL "5"* SIN q:LET y1= VAL "5"* COS q
1170 PLOT INVERSE turt;x,y
1180 DRAW INVERSE turt;x1,y1
1190 NEXT j:RETURN
1220 GO SUB VAL "1020":IF err= SGN PI THEN LET err= VAL "2":RETURN
1230 IF CODE y$> VAL "57" THEN GO TO VAL "1300"
1240 IF y$="" THEN LET err= VAL "2":RETURN
1250 FOR k= SGN PI TO LEN y$
1260 IF CODE y$(k)< VAL "48" OR CODE y$(k)> VAL "57" THEN LET err= VAL "2"
1270 NEXT k
1280 IF err= NOT PI THEN LET a= VAL y$
1290 LET t= NOT PI:RETURN
1310 LET y$=(y$+" ")( TO VAL "12")
1320 FOR i= SGN PI TO o:IF y$=f$(i) THEN GO TO VAL "1340"
1330 NEXT i:LET err= VAL "2":RETURN
1340 GO SUB g(i):RETURN
1410 LET cr= SGN PI:IF q< VAL "2"* PI AND q> PI THEN LET cr=- SGN PI
1420 IF cr= SGN PI THEN LET x1= VAL "255"-x:IF q> VAL "1.57" THEN LET y1= NOT PI:LET x2= NOT PI:GO TO VAL "1430"
1425 IF cr= SGN PI THEN LET y1=x1/ TAN q:LET x2= NOT PI
1430 IF cr=- SGN PI THEN LET x1=-x:LET y1=(x1/ TAN (q- PI)):LET x2= VAL "255"
1440 LET y2=y+y1:LET a=a- INT SQR (ABS (x1)^ VAL "2"+ ABS (y1)^ VAL "2")
1450 RETURN
1510 LET cr= SGN PI:IF q> PI/ VAL "2" AND q< INT PI* PI/ VAL "2" THEN LET cr=- SGN PI
1520 IF cr= SGN PI THEN LET y1= VAL "175"-y:LET x1=y1* TAN q:LET y2= NOT PI
1530 IF cr=- SGN PI THEN LET y1=y:LET x1=-(y1* TAN (q- PI)):LET y2= VAL "175":LET y1=-y
1540 LET x2=x+x1:LET a=a- INT SQR (ABS (x1)^ VAL "2"+ ABS (y1)^ VAL "2")
1550 RETURN
1605 IF q> PI/ VAL "2" THEN GO TO VAL "1630"
1610 LET x3=x+(VAL "175"-y)* TAN q
1615 IF x3> VAL "255" THEN GO TO VAL "1400"
1620 IF x3< VAL "255" THEN GO TO VAL "1500"
1625 GO TO VAL "1680"
1630 IF q> PI THEN GO TO VAL "1645"
1635 LET x3=x+y* TAN (PI-q)
1640 GO TO VAL "1615"
1645 IF q> INT PI* PI/ VAL "2" THEN GO TO VAL "1670"
1650 LET x3=x-y* TAN (q- PI)
1655 IF x3< NOT PI THEN GO TO VAL "1400"
1660 IF x3> NOT PI THEN GO TO VAL "1500"
1665 GO TO VAL "1680"
1670 LET x3=x-(VAL "175"-y)* TAN (VAL "2"* PI-q)
1675 GO TO VAL "1655"
1680 IF y1 >=x1 THEN LET a1= INT (y1/ COS q+ VAL "1.5")
1685 IF y1<x1 THEN LET a1= INT (x1/ SIN q+ VAL "1.5")
1690 LET a=a-a1:GO SUB VAL "1450":IF y2< NOT PI THEN LET y2= VAL "175"
1695 IF y2> VAL "175" THEN LET y2= NOT PI
1700 GO SUB VAL "1500":IF x2< NOT PI THEN LET x2= VAL "255"
1705 IF x2> VAL "255" THEN LET x2= NOT PI
1710 RETURN
2020 INPUT "W:"; LINE z$:LET s= NOT PI
2025 LET count= NOT PI:LET rc= NOT PI:GO SUB VAL "2040":GO TO VAL "2020"
2060 LET t= NOT PI:LET t1= NOT PI:LET err= NOT PI
2070 GO SUB VAL "1020"
2080 IF t1= SGN PI AND y$="" AND count= NOT PI THEN LET turt= NOT PI:GO SUB VAL "1100"
2085 IF t1= SGN PI AND y$="" THEN RETURN
2090 IF LEN y$ <> VAL "2" THEN GO TO VAL "2130"
2100 FOR i= SGN PI TO m
2110 IF y$=x$(i) THEN GO TO VAL "2200"
2120 NEXT i
2130 LET y$=(y$+" ")( TO VAL "12")
2140 FOR i= SGN PI TO n+def
2150 IF y$=w$(i) THEN GO TO VAL "2210"
2160 NEXT i
2180 LET err= SGN PI:IF turt= SGN PI THEN LET turt= NOT PI:GO SUB VAL "1100"
2190 GO TO VAL "520"
2200 GO SUB u(i):GO TO VAL "2220"
2210 IF i <=n THEN GO SUB v(i):GO TO VAL "2220"
2215 GO SUB VAL "6000"
2220 IF err> NOT PI THEN GO TO VAL "520"
2230 GO TO VAL "2070"
3020 GO SUB VAL "1200":IF err> NOT PI THEN RETURN
3030 IF turt= NOT PI THEN LET turt= SGN PI:GO SUB VAL "1100"
3040 LET q=dir* PI/ VAL "180"
3050 LET x1= INT (VAL ".5"+a* SIN q):LET y1= INT (VAL ".5"+a* COS q)
3060 LET tr= NOT PI:LET x2=x+x1:LET y2=y+y1
3070 IF x2< NOT PI OR x2> VAL "255" THEN LET tr= SGN PI
3080 IF y2< NOT PI OR y2> VAL "175" THEN LET tr=tr+ VAL "2"
3090 IF tr> NOT PI AND wr= NOT PI THEN LET err= INT PI:RETURN
3100 IF tr= NOT PI THEN GO TO VAL "3120"
3110 GO SUB (VAL "1300"+tr* VAL "100")
3120 IF pp= SGN PI THEN PLOT x,y:DRAW x1,y1
3130 IF pp= NOT PI THEN PLOT INVERSE SGN PI; OVER SGN PI;x,y:DRAW INVERSE SGN PI; OVER SGN PI;x1,y1
3140 LET x=x2:LET y=y2:IF tr> NOT PI THEN GO TO VAL "3050"
3150 LET t= NOT PI:RETURN
3220 IF turt= NOT PI THEN LET turt= SGN PI:GO SUB VAL "1100"
3230 LET dir=dir+ VAL "180":IF dir> VAL "360" THEN LET dir=dir- VAL "360"
3240 GO TO VAL "3020"
3420 IF turt= NOT PI THEN LET turt= SGN PI:GO SUB VAL "1100"
3430 GO SUB VAL "1200":IF err> NOT PI THEN RETURN
3440 LET dir=dir-a
3450 IF dir< NOT PI THEN LET dir= VAL "360"+dir:GO TO VAL "3450"
3460 RETURN
3620 IF turt= NOT PI THEN LET turt= SGN PI:GO SUB VAL "1100"
3630 GO SUB VAL "1200":IF err> NOT PI THEN RETURN
3640 LET dir=dir+a
3650 IF dir> VAL "360" THEN LET dir=dir- VAL "360":GO TO VAL "3650"
3660 RETURN
3820 CLS
3870 IF turt= NOT PI THEN LET turt= SGN PI:GO SUB VAL "1100"
3880 LET x= VAL "128":LET y= VAL "88"
3890 LET dir= NOT PI:LET turt= NOT PI
3900 GO SUB VAL "1100":RETURN
4020 LET pp= NOT PI:RETURN
4070 LET pp= SGN PI:RETURN
4110 GO SUB VAL "1200":IF err> NOT PI THEN RETURN
4115 LET s=s+ SGN PI:IF s> LEN z$ THEN LET err= SGN PI:RETURN
4120 IF z$(s)=" " THEN GO TO VAL "4115"
4125 IF z$(s)="[" THEN GO TO VAL "4135"
4130 LET err= SGN PI:RETURN
4135 LET rc=rc+ SGN PI:LET s=s+ SGN PI
4140 IF rc> VAL "20" THEN LET err= VAL "4":RETURN
4145 LET r(rc, SGN PI)=s:LET r(rc, VAL "2")=a
4150 RETURN
4210 LET r(rc, VAL "2")=r(rc, VAL "2")- SGN PI
4215 IF r(rc, VAL "2")> NOT PI THEN LET s=r(rc, SGN PI):RETURN
4220 LET rc=rc- SGN PI:RETURN
4310 GO SUB VAL "1200":IF err> NOT PI THEN RETURN
4315 IF a> VAL "7" THEN LET err= VAL "2":RETURN
4320 INK a:RETURN
4410 LET wr= SGN PI:RETURN
4460 LET wr= NOT PI:RETURN
4505 INPUT "SAVE - Enter file name ";n$
4510 SAVE n$ LINE VAL "2000":RETURN
4525 COPY :RETURN
4555 CLS :STOP
4605 GO SUB VAL "1200":IF err> NOT PI THEN RETURN
4610 IF turt= NOT PI THEN LET turt= SGN PI:GO SUB VAL "1100"
4615 IF a< NOT PI OR a> VAL "255" THEN LET err= VAL "2":RETURN
4620 LET y2=y:LET tr= NOT PI:LET y1= NOT PI:LET x1=a-x:LET x2=a:GO TO VAL "3120"
4635 GO SUB VAL "1200":IF err> NOT PI THEN RETURN
4640 IF turt= NOT PI THEN LET turt= SGN PI:GO SUB VAL "1100"
4645 IF a< NOT PI OR a> VAL "175" THEN LET err= VAL "2":RETURN
4650 LET x2=x:LET tr= NOT PI:LET x1= NOT PI:LET y1=a-y:LET y2=a:GO TO VAL "3120"
4665 IF turt= NOT PI THEN LET turt= SGN PI:GO SUB VAL "1100"
4670 GO SUB VAL "1200":IF err> NOT PI THEN RETURN
4675 IF a< NOT PI OR a> VAL "255" THEN LET err= VAL "2":RETURN
4680 LET x1=a-x:LET x2=a:GO SUB VAL "1200":IF err> NOT PI THEN RETURN
4685 IF a< NOT PI OR a> VAL "175" THEN LET err= VAL "2":RETURN
4690 LET tr= NOT PI:LET y1=a-y:LET y2=a:GO TO VAL "3120"
4705 GO SUB VAL "1200":IF err> NOT PI THEN RETURN
4710 IF a< NOT PI OR a> VAL "359" THEN LET err= VAL "2":RETURN
4715 LET dir=a:RETURN
5005 GO SUB VAL "1020":IF t1= SGN PI AND LEN y$< VAL "2" THEN LET err= VAL "5":RETURN
5010 IF LEN y$ <> VAL "2" THEN GO TO VAL "5025"
5015 FOR i= SGN PI TO m:IF y$=x$(i) THEN LET err= VAL "5":RETURN
5020 NEXT i
5025 LET y$=(y$+" ")( TO VAL "12")
5030 FOR i= SGN PI TO def+n:IF y$=w$(i) THEN LET err= VAL "5":RETURN
5035 NEXT i:IF def> VAL "39" THEN LET err= VAL "6":RETURN
5040 CLS :PRINT "DEFINE ";y$''
5050 LET def=def+ SGN PI:LET no= NOT PI
5055 INPUT "W:"; LINE z$:IF LEN z$> VAL "28" THEN PRINT # SGN PI;"Too Long!":PAUSE VAL "200":GO TO VAL "5055"
5060 IF LEN z$< VAL "2" THEN PRINT # SGN PI;"Nonsense!":PAUSE VAL "200":GO TO VAL "5055"
5065 PRINT no; TAB INT PI;z$'':LET no=no+ SGN PI:LET len= LEN z$
5070 IF len< INT PI THEN GO TO VAL "5085"
5075 FOR i= SGN PI TO len- VAL "2":IF z$(i TO i+ VAL "2")="END" THEN GO TO VAL "5095"
5080 NEXT i
5085 IF no< VAL "11" THEN LET b$(no)=z$:LET c(no)=len:GO TO VAL "5055"
5090 PRINT # SGN PI;"No more space is available for ";y$:PAUSE VAL "200":GO TO VAL "5100"
5095 LET len=len- INT PI:LET b$(no)=z$( TO len):LET c(no)=len:IF no< VAL "10" THEN LET c(no+ SGN PI)= NOT PI
5100 LET w$(n+def)=y$:LET c$="":LET no= SGN PI:LET len= NOT PI
5105 IF c(no)= NOT PI THEN GO TO VAL "5120"
5110 LET c$=c$+b$(no, TO c(no))+ CHR$ NOT PI:LET len=len+c(no)+ SGN PI
5115 LET no=no+ SGN PI:IF no< VAL "10" THEN GO TO VAL "5105"
5120 LET k$(def)=c$:LET l(def)=len
5125 CLS :PRINT "STORED - ";y$
5130 PAUSE VAL "200":CLS :RETURN
5205 GO SUB VAL "1020":IF t1= SGN PI AND LEN y$< VAL "2" THEN LET err= VAL "6":RETURN
5210 LET y$=(y$+" ")( TO VAL "12")
5215 IF def= NOT PI THEN LET err= VAL "4":RETURN
5220 FOR i=n+ SGN PI TO n+def:IF y$=w$(i) THEN GO TO VAL "5230"
5225 NEXT i:LET err= VAL "4":RETURN
5230 GO SUB VAL "5800"
5240 GO SUB VAL "5950"
5250 PRINT # SGN PI;"1:EDIT 2:INSERT 3:DELETE 4:REMOVE 5:RETURN"
5255 LET z$= INKEY$:IF z$="" THEN GO TO VAL "5255"
5260 IF z$<"1" OR z$>"5" THEN GO TO VAL "5255"
5265 LET z= VAL z$:GO TO VAL "5200"+ VAL "100"*z
5275 GO TO VAL "5235"
5300 GO SUB VAL "5950":PRINT # SGN PI;"EDIT - Enter the line"
5305 LET z$= INKEY$:IF z$="" THEN GO TO VAL "5305"
5310 IF z$<"0" OR z$>"9" THEN GO TO VAL "5305"
5315 LET lin= VAL z$
5320 INPUT (lin);" W:"; LINE z$:IF LEN z$> VAL "28" THEN PRINT # SGN PI;" Too long":PAUSE VAL "200":GO TO VAL "5320"
5325 LET b$(lin+ SGN PI)=z$:LET c(lin+ SGN PI)= LEN z$
5330 GO TO VAL "5235"
5400 IF k> VAL "9" THEN PRINT # SGN PI;"No space for another line":PAUSE VAL "200":RETURN
5405 GO SUB VAL "5950":PRINT # SGN PI;"INSERT - Enter line number"
5410 LET z$= INKEY$:IF z$="" THEN GO TO VAL "5410"
5415 IF z$<"0" AND z$> STR$ (k- SGN PI) THEN GO TO VAL "5410"
5420 LET ins= VAL z$
5425 INPUT (ins);" W:"; LINE z$:IF LEN z$> VAL "28" THEN PRINT # SGN PI;"Too Long":PAUSE VAL "200":GO TO VAL "5425"
5430 LET ins=ins+ SGN PI
5435 FOR i=k TO ins STEP - SGN PI
5440 LET b$(i+ SGN PI)=b$(i):LET c(i+ SGN PI)=c(i):NEXT i
5445 LET b$(ins)=z$:LET c(ins)= LEN z$
5450 LET k=k+ SGN PI:GO TO VAL "5235"
5500 LET z$="DELETE ":GO SUB VAL "5950":GO SUB VAL "5900"
5505 IF a$="N" THEN GO TO VAL "5235"
5510 GO SUB VAL "5950":PRINT # SGN PI;z$;"- Enter the line number"
5515 LET z$= INKEY$:IF z$="" THEN GO TO VAL "5515"
5520 IF z$<"0" OR z$> STR$ (k- SGN PI) THEN GO TO VAL "5915"
5525 LET k=k- SGN PI
5530 FOR i= SGN PI+ VAL z$ TO k
5535 LET b$(i)=b$(i+ SGN PI):LET c(i)=c(i+ SGN PI):NEXT i
5540 GO TO VAL "5235"
5600 LET z$="REMOVE ":GO SUB VAL "5950":GO SUB VAL "5900"
5605 IF a$="N" THEN GO TO VAL "5235"
5610 LET def=def- SGN PI:IF def= NOT PI OR ed=def+ SGN PI THEN RETURN
5620 FOR i=n+ed TO def+n
5625 LET w$(i)=w$(i+ SGN PI):NEXT i
5630 FOR i=ed TO def
5635 LET k$(i)=k$(i+ SGN PI):LET l(i)=l(i+ SGN PI):NEXT i
5640 CLS :RETURN
5700 LET c$="":LET no= NOT PI
5705 FOR i= SGN PI TO k
5710 LET c$=c$+b$(i, TO c(i))+ CHR$ NOT PI:LET no=no+c(i)+ SGN PI
5715 NEXT i
5720 LET k$(ed)=c$:LET l(ed)=no
5725 CLS :PRINT "STORED - ";y$:PAUSE VAL "200"
5730 CLS :RETURN
5800 LET ed=i-n:CLS :PRINT "EDIT ";y$''"Please wait"
5805 LET len= SGN PI:LET k= NOT PI:LET z$=k$(ed, TO l(ed))
5810 IF len>l(ed) THEN RETURN
5815 LET c$="":LET no= NOT PI:LET k=k+ SGN PI
5820 IF z$(len) <> CHR$ NOT PI THEN LET c$=c$+z$(len):LET no=no+ SGN PI:LET len=len+ SGN PI:GO TO VAL "5820"
5825 LET len=len+ SGN PI:LET b$(k)=c$:LET c(k)=no:GO TO VAL "5810"
5830 RETURN
5900 PRINT # SGN PI;z$;"- Are you sure? (y/n)"
5905 LET a$= INKEY$:IF a$="" THEN GO TO VAL "5905"
5910 IF NOT (a$="Y" OR a$="N") THEN GO TO VAL "5905"
5915 RETURN
5950 CLS :PRINT "EDIT ";y$''
5955 FOR i= SGN PI TO k
5960 PRINT i- SGN PI; TAB INT PI;b$(i)'':NEXT i
5965 RETURN
6005 IF count= NOT PI THEN LET p$=z$:LET s1=s
6010 IF count> NOT PI THEN LET m(count)=comm:LET n(count)=s
6015 LET comm=i-n:LET z$=k$(comm, TO l(comm))
6020 LET count=count+ SGN PI
6025 LET s= NOT PI:GO SUB VAL "2040"
6030 LET count=count- SGN PI
6035 IF count> NOT PI THEN LET comm=m(count):LET z$=k$(comm, TO l(comm)):LET s=n(count)
6040 IF count= NOT PI THEN LET z$=p$:LET s=s1
6045 IF count< NOT PI THEN LET err= SGN PI
6050 RETURN
8010 GO SUB VAL "1210":IF err= VAL "2" THEN RETURN
8020 LET a= INT (RND*a):RETURN
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.