--- title: "Spectrum LOGO" id: 71501 type: "computer_media" slug: "spectrum-logo" url: "http://localhost/computer_media/spectrum-logo/" markdown_url: "http://localhost/computer_media/spectrum-logo.md" published_at: "2026-09-09T09:06:47+00:00" modified_at: "2026-09-09T09:06:48+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2022/04/20230809-041332.jpg" excerpt: "A complete LOGO turtle-graphics interpreter in BASIC, supporting named procedure definitions, REPEAT loops, pen color, coordinate commands, and an interactive line editor." 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/" genre: - name: "Programming" slug: "programming" taxonomy: "genre" url: "http://localhost/type/programming/" media_type: "Program" download_url: "https://archive.org/download/timex-sinclair-software-archive/Spectrum%20LOGO%20(198x)(-)(TS2068)(US)(Program).zip" tsrun_member: "Spectrum LOGO (198x)(-)(TS2068)(US)(Program).tap" mediadate: "198x" media_type_tags: "Programming" --- # Spectrum LOGO 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 `DATA` statements. - **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 `err` code. - **Lines 1030–1070:** Tokenizer subroutine — walks `z$` extracting whitespace-delimited tokens into `y$`. - **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 via `g()` 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 via `w$()/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 up - `wr` — wrap mode: `SGN PI` = wrap enabled, `NOT PI` = no-wrap - `turt` — 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 1 - `NOT PI` — evaluates to 0 - `INT PI` — evaluates to 3 - `VAL "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 `5415` has a logical bug: the condition `z$<"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 `5520` references `GO 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 `m` and `n` are reused: initially scalar variables holding array dimension counts (lines 60–70), they are later re-dimensioned as arrays `DIM m(40)` and `DIM 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 by `GO SUB VAL "3800"` at line `480`) does not correspond to any listed line; the actual home initialization is at line `3820`. 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 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 ```