--- title: "List Manager" id: 51732 type: "computer_media" slug: "list-manager" url: "http://localhost/computer_media/list-manager/" markdown_url: "http://localhost/computer_media/list-manager.md" published_at: "2023-08-13T23:14:29+00:00" modified_at: "2026-04-03T07:59:17+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2022/04/20230809-041332.jpg" excerpt: "A dual-configuration database manager stores mailing list or phone book records using clever free-memory detection, character-encoded record indexes, and a machine code search routine." 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: "Timex Computer Corporation" slug: "timex-computer-corporation" taxonomy: "post_tag" url: "http://localhost/tag/timex-computer-corporation/" - name: "TS 1000" slug: "ts1000" taxonomy: "post_tag" url: "http://localhost/tag/ts1000/" model: - name: "Timex/Sinclair 1000" slug: "ts-1000" taxonomy: "model" url: "http://localhost/model/ts-1000/" genre: - name: "Database" slug: "database" taxonomy: "genre" url: "http://localhost/type/database/" media_type: "Cassette" download_url: "https://archive.org/download/timex-sinclair-software-archive/List Manager (1982)(Timex)(US)(TS1000)(Cassette).zip" mediadate: "1982" producer_company: - id: 11401 title: "Timex Computer Corporation" type: "company" url: "http://localhost/company/timex-computer-corporation/" related_products: - id: 14342 title: "The List Manager" type: "product" url: "http://localhost/product/the-list-manager/" media_type_tags: "Database" --- List Manager is a configurable flat-file database program supplied in two preset configurations: a mailing list (with fields for name, address, city, state, and ZIP) and a phone book (name and number). Records are stored in a two-dimensional string array, with each record’s slot number encoded as a single character in an index string, allowing up to 255 entries. Free-memory calculations use direct PEEK of system variables at addresses 16386, 16387, 16412, and 16413 to determine how many records can fit before dimensioning the data arrays. A machine code routine is called via USR 16524 to perform fast string searching during the delete operation, with the search key POKEd into address 16514. The UI draws a block-graphic bordered window using concatenated strings and animates a blinking cursor character in the menu by directly POKEing the display file address, calculated from the system variable at address 16396. *** ## Program Analysis ### Program Structure The listing is actually two complete, nearly identical programs sharing the same line numbers. The first is configured as a mailing list (5 fields: NAME, ADDRESS, CITY, STATE, ZIP) and the second as a phone book (2 fields: NAME, NUMBER). Both programs share the same engine; only the field definitions, titles, and default filenames differ. The code is organized into clearly labeled subroutine blocks: 1. Lines 10–880: Initialization — build screen template, calculate available memory, dimension arrays 2. Lines 1000–1250: Main menu loop with animated cursor 3. Lines 2000–2240: Add record 4. Lines 3000–3090: Delete record 5. Lines 4000–4550: Search/find records 6. Lines 5000–5080: Save to tape 7. Lines 6000–6020: Quit 8. Lines 7000–7250: List records (screen/printer/both) 9. Lines 8000–8790: Utility subroutines (wait for Enter, print output, pagination, totals) 10. Lines 9800–9830: Machine code search helper ### Variable Conventions The program uses a consistent set of named constants initialized at startup to avoid magic numbers and improve readability: | Variable | Value | Purpose | | --- | --- | --- | | `O` | 1 (PI/PI) | Numeric constant 1, used everywhere in place of the literal | | `Z` | 0 (O-O) | Numeric constant 0 | | `LL` | 32 | Line length (characters per screen row) | | `MS` | 6 | Menu size (rows in menu area) | | `SZ` | 15 (22-1-MS) | Screen zone boundary row | | `NLEN` | 7 | Max field name length | | `FLDS` | 5 or 2 | Number of data fields | | `RLEN` | sum of F() | Total record length in characters | | `DF` | 16396 | System variable address for display file pointer | Using `O=PI/PI` and `Z=O-O` instead of literals 1 and 0 is a space-saving technique: the integer representations of these computed values take fewer bytes in the stored program than the literal digits would. ### Record Storage and Indexing Records are stored in the two-dimensional string array `D$(MAX,RLEN)`, where each row is one fixed-length record. The index of which slots are in use is maintained in the string `U$`, where each character’s ASCII code is the row number within `D$`. Free slots are pre-loaded into `E$` at line 860–880 by concatenating `CHR$ B` for B from 1 to MAX. Adding a record (line 2190–2200) pops the first character of `E$` as the slot address; deleting (line 3020) pushes it back. A parallel string `N$` of length `RLEN` serves as a blank record for clearing deleted slots. ### Dynamic Memory Calculation At lines 550–580, the program calculates available RAM before dimensioning the record array, using a `VAL` string trick to keep the expression compact. It PEEKs system variables at 16386/16387 (RAMTOP) and 16412/16413 (start of spare memory area), subtracts 400 bytes of overhead, and divides by `RLEN+5` to compute the maximum number of records. The result is capped at 255 (line 565) because record slot numbers are encoded as single characters. ### Screen Template Construction The bordered screen template string `S$` is assembled at initialization time by concatenating block-graphic border characters and content rows into a single long string. The string is then displayed in one `PRINT AT 0,0;S$` call (line 1010), which redraws the entire screen frame efficiently. Field labels are embedded directly into `S$` using substring assignment (line 820), and the program title is centered and written into `S$` at line 250 using `S$(S TO S+LEN X$-O)`. ### Animated Cursor Technique The main menu loop at lines 1140–1170 implements a blinking cursor without PAUSE by directly POKEing the display file. Line 1120 reads the display file base address from the system variable at `DF` (16396). Lines 1152 and 1154 then POKE two cursor characters at fixed offsets (+67 and +98) into the display file, alternating between two block-graphic characters from the string `"▛▟"` and `"▜▙"` indexed by flag `FL`, which toggles via `NOT FL` each iteration. ### Machine Code Search Routine The delete operation (line 3000) calls `GOSUB 9800`, which uses a machine code routine resident at address 16524. The search character (the record slot number being deleted) is POKEd to address 16514 at line 9810. The routine is called via `USR 16524` and its return value is subtracted from 255 to yield the 1-based position `J` of the character within `Q$` (which holds a copy of `U$`). This avoids a slow BASIC loop scan for the record’s position in the index string. ### Navigation and Input In the main loop, key codes 112 and 113 (corresponding to specific keys) scroll the current record pointer `CR` up and down through `U$` (lines 8510–8520). The display of the current record (lines 1020–1060) iterates over fields and prints each using an offset `OF` into the fixed-length record string. Menu dispatch at line 1250 uses `GOTO VAL "1000+1000*VAL C$"` to jump to the appropriate routine based on the digit pressed, a compact computed-GOTO idiom. ### Search (Find) Implementation The search routine at lines 4000–4340 reuses the add-record input subroutine (`GOSUB 2115`) to collect search keys into the same buffer `B$`. It then iterates over all records in `U$`, comparing each field after trimming trailing spaces via the `GOSUB 4500` helper. Matched records are collected into `L$`; if any are found, the program temporarily replaces `U$` with `L$`, calls the list routine, then restores `U$`. The trimming subroutine (4500–4550) loops `LEN X$` times checking and shortening both `X$` and `Y$` from the right, which is correct but redundant since the loop count never changes as strings shrink. ### Totals Feature The listing subroutine (line 7000) includes a totals mechanism at lines 8600–8790. If any field name begins with “.” and the variable `NUM` is non-zero, that field’s values are accumulated numerically in array `T(FLDS)` and printed as totals after the list. In both supplied configurations `NUM=0` (line 498), so the totals feature is present but inactive. ### Bugs and Anomalies - Line 570 prints “RECORDS AVAILIBLE” — a misspelling of “AVAILABLE” that appears in both configurations. - The search loop at lines 4510–4540 uses a `FOR G=1 TO LEN X$` counter but the loop body never references `G`; the trimming is performed solely by the conditional checks, and the loop count is based on the original length of `X$` before trimming begins. This works correctly as a worst-case iteration count but is inelegant. - Line 1200 is referenced by `GOTO 1200` at line 1150 but does not exist as an explicit line; execution falls through from line 1150’s jump target to line 1210, which is the intended behavior in this BASIC dialect. - The `DIM Q$(255)` at line 20 allocates a fixed 255-character string used as scratch space in the machine code search, independent of `MAX`. ## Source Code ``` 10 REM ▘.........E(RND7777#7#7U▙RND GOSUB [L]TAN 20 DIM Q$(255) 60 SLOW 70 PRINT "INITIALIZING..." 80 LET B$=" " 85 LET LL=32 90 LET O=PI/PI 95 LET Z=O-O 100 LET MS=6 105 LET SZ=VAL "22-1-MS" 110 LET CR=O 115 LET Z$=B$+B$ 117 LET Z$=B$+B$+"▛▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▜" 120 LET X$="▌ ▐" 125 FAST 130 FOR K=O+O+O TO SZ-O-O 140 LET Z$=Z$+X$ 150 NEXT K 160 LET Z$=Z$+"▙▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▟" 170 LET X$="▌ █ ▐" 180 FOR K=O TO MS 190 LET Z$=Z$+X$ 200 NEXT K 210 LET Z$=Z$+"▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀" 220 LET S$=Z$ 230 LET X$="TIMEX MAILING LIST" 235 LET H$="MLIST" 240 LET S=16-LEN X$/2 250 LET S$(S TO S+LEN X$-O)=X$ 260 LET DF=16396 290 LET NLEN=7 300 LET FLDS=5 305 DIM F$(FLDS,NLEN) 310 DIM F(FLDS) 320 LET F(1)=20 330 LET F(2)=20 335 LET F(3)=15 340 LET F(4)=4 345 LET F(5)=5 400 LET F$(1)="NAME" 410 LET F$(2)="ADDRESS" 420 LET F$(3)="CITY" 430 LET F$(4)="STATE" 440 LET F$(5)="ZIP" 498 LET NUM=0 500 REM CALCULATE RLEN 510 LET RLEN=Z 520 FOR F=O TO FLDS 530 LET RLEN=RLEN+F(F) 540 NEXT F 545 SLOW 550 LET FRE=VAL "((PEEK 16386+PEEK 16387*256)-(PEEK 16412+PEEK 16413*256)-400)" 560 LET MAX=INT (FRE/(RLEN+5)) 565 IF MAX>255 THEN LET MAX=255 570 PRINT "RECORDS AVAILIBLE: ";MAX 580 DIM D$(MAX,RLEN) 590 DIM N$(RLEN) 700 LET T2=1 710 LET T1=SZ+O 720 DIM B$(RLEN) 735 FAST 800 FOR F=O TO FLDS 810 LET S=LL*(F+O+O)+O+O 820 LET S$(S TO S+NLEN)=F$(F)+":" 830 NEXT F 840 LET U$="" 850 LET E$="" 860 FOR B=O TO MAX 870 LET E$=E$+CHR$ B 880 NEXT B 1000 REM MAIN LOOP 1005 SLOW 1010 PRINT AT Z,Z;S$ 1015 PRINT AT 3,1; 1017 LET OF=O 1018 IF CR>LEN U$ OR CR<1 OR U$="" THEN GOTO 1100 1020 FOR F=O TO FLDS 1030 PRINT TAB NLEN+O+O; 1040 PRINT D$(CODE U$(CR),OF TO OF+F(F)-O) 1050 LET OF=OF+F(F) 1060 NEXT F 1100 PRINT AT SZ,O;"(1) ADD";TAB O;"(2) DELETE";TAB O;"(3) SEARCH";TAB O;"(4) SAVE";TAB O;"(5) QUIT" 1105 PRINT TAB O;"(6) LIST" 1110 PRINT AT SZ,14;"SELECT: "; 1120 LET D=PEEK DF+PEEK (DF+O)*256 1130 LET FL=1 1140 LET C$=INKEY$ 1145 IF C$=CHR$ 112 OR C$=CHR$ 113 THEN GOTO 8500 1150 IF C$>="1" AND C$<="6" THEN GOTO 1200 1152 POKE D+67,CODE "▛▟"(FL+1) 1154 POKE D+98,CODE "▜▙"(FL+1) 1156 LET FL=NOT FL 1170 GOTO 1140 1210 PRINT AT SZ,14;" " 1220 FOR J=20 TO SZ+VAL C$-O STEP -O 1225 IF J<20 THEN PRINT AT J+1,13;"█" 1230 PRINT AT J,13;"[<]" 1240 NEXT J 1250 GOTO VAL "1000+1000*VAL C$" 2000 REM ADD 2010 IF E$>"" THEN GOTO 2100 2020 PRINT AT T1,T2;"THERE ARE NO FREE";TAB T2;"RECORDS." 2030 GOTO 8000 2100 REM ADD 2110 PRINT AT Z,Z;S$ 2115 LET OF=O 2120 FOR F=O TO FLDS 2130 PRINT AT 2+F,NLEN+O+O;"[~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~]"( TO F(F)) 2140 INPUT I$ 2150 LET B$(OF TO OF+F(F)-O)=I$ 2160 PRINT AT 2+F,NLEN+O+O;B$(OF TO OF+F(F)-O) 2165 LET OF=OF+F(F) 2170 NEXT F 2180 IF C$="3" THEN RETURN 2190 LET CR=CODE E$ 2200 LET E$=E$(2 TO ) 2220 LET D$(CR)=B$ 2230 LET U$=U$+CHR$ CR 2240 GOTO 1100 3000 REM DELETE 3020 LET E$=E$+CHR$ CR 3030 LET A$=CHR$ CR 3040 LET Q$=U$ 3060 GOSUB 9800 3070 LET U$=U$( TO J-1)+U$(J+1 TO ) 3080 LET D$(CR)=N$ 3090 GOTO 1000 4000 REM FIND 4005 LET L$="" 4007 DIM T(FLDS) 4010 PRINT AT 0,0;S$ 4020 PRINT AT SZ+2,T1;"ENTER YOUR";TAB T1;"SEARCH KEYS:" 4030 GOSUB 2115 4035 PRINT AT SZ+2,T1;" ";TAB T1;" " 4040 PRINT AT SZ+2,1;"SEARCHING.." 4042 FOR H=1 TO 10 4044 NEXT H 4050 FOR J=1 TO LEN U$ 4056 FAST 4060 LET Z$=D$(CODE U$(J)) 4065 LET T$=B$ 4070 FOR F=1 TO FLDS 4080 LET X$=T$( TO F(F)) 4090 LET Y$=Z$( TO F(F)) 4095 GOSUB 4500 4100 LET T$=T$(F(F)+1 TO ) 4110 LET Z$=Z$(F(F)+1 TO ) 4121 IF X$="" THEN GOTO 4150 4130 IF Y$( TO LEN X$)=X$ THEN GOTO 4150 4140 GOTO 4200 4150 NEXT F 4160 LET L$=L$+U$(J) 4200 NEXT J 4201 IF L$>"" THEN GOTO 4300 4210 PRINT AT SZ+2,1;"NOT FOUND" 4220 GOSUB 8200 4230 GOTO 1000 4300 REM 4305 SLOW 4310 LET G$=U$ 4320 LET U$=L$ 4330 GOSUB 7000 4335 LET U$=G$ 4340 GOTO 1000 4500 REM REMOVE SPACES FM X$/Y$ 4510 FOR G=1 TO LEN X$ 4520 IF X$(LEN X$)=" " THEN LET X$=X$( TO LEN X$-1) 4530 IF Y$(LEN Y$)=" " THEN LET Y$=Y$( TO LEN Y$-1) 4540 NEXT G 4550 RETURN 4999 STOP 5000 REM SAVE 5005 CLS 5010 PRINT TAB O;"UNDER WHAT NAME SHALL I SAVE THE INFORMATION: "; 5020 INPUT A$ 5030 IF A$="" THEN LET A$=H$ 5040 PRINT TAB O;TAB O;"START THE TAPE, AND THEN PRESS [E][N][T][E][R]." 5050 INPUT Z$ 5055 CLS 5060 SAVE A$ 5070 PRINT TAB O;TAB O;"STOP THE TAPE." 5080 GOTO 8000 6000 REM QUIT 6010 STOP 6020 GOTO 1000 7000 REM LIST 7005 DIM T(FLDS) 7010 CLS 7020 PRINT "LIST TO PRINTER (P), SCREEN (S) OR BOTH (B)?" 7030 LET K$=INKEY$ 7040 IF K$<>"S" AND K$<>"B" AND K$<>"P" THEN GOTO 7030 7050 LET PRI=K$<>"S" 7060 LET SCR=K$<>"P" 7070 CLS 7075 LET LCNT=INT (18/(FLDS+2)) 7080 FOR K=1 TO LEN U$ 7090 FAST 7100 LET Z$=D$(CODE U$(K)) 7110 FOR N=1 TO FLDS 7115 IF F$(N)(1)="." THEN LET T(N)=T(N)+VAL Z$( TO F(N)) 7120 LET O$=F$(N) 7130 LET O$=O$+": "+Z$( TO F(N)) 7140 LET Z$=Z$(F(N)+1 TO ) 7150 GOSUB 8100 7160 NEXT N 7170 LET O$="" 7180 FOR G=1 TO 2 7190 GOSUB 8100 7200 NEXT G 7205 LET LCNT=LCNT-1 7210 IF (SCR) AND (LCNT=0) THEN GOSUB 8200 7220 NEXT K 7230 LET O$="TOTAL RECORDS: "+STR$ LEN U$ 7240 GOSUB 8100 7242 GOSUB 8600 7245 GOSUB 8200 7247 IF C$="3" THEN RETURN 7250 GOTO 1000 8000 REM ENTER 8010 PRINT AT 20,T2;"PRESS [E][N][T][E][R]" 8020 INPUT Z$ 8030 GOTO 1000 8100 REM 8110 IF PRI THEN LPRINT O$ 8120 IF SCR THEN PRINT O$ 8130 RETURN 8200 REM 8210 PRINT AT 20,1;"PRESS [E][N][T][E][R]." 8220 INPUT W$ 8230 CLS 8235 LET LCNT=INT (18/(FLDS+2)) 8237 IF W$=" STOP" THEN GOTO 1000 8240 RETURN 8500 REM 8510 IF C$=CHR$ 113 THEN LET CR=CR+(CR1) 8530 GOTO 1015 8600 REM TOTALS 8605 IF NOT NUM THEN RETURN 8610 LET O$="" 8620 GOSUB 8100 8630 GOSUB 8100 8640 LET O$="TOTALS:" 8650 GOSUB 8100 8660 LET O$="" 8670 GOSUB 8100 8680 FOR F=1 TO FLDS 8690 IF F$(F)(1)<>"." THEN GOTO 8750 8700 LET O$=" "+F$(F)+": "+STR$ T(F) 8710 GOSUB 8100 8750 NEXT F 8760 LET O$="" 8770 GOSUB 8100 8780 GOSUB 8100 8790 RETURN 9800 REM SEARCH 9810 POKE 16514,CODE A$ 9820 LET J=255-USR 16524 9830 RETURN 10 REM ▘.........E(RND7777#7#7U▙RND GOSUB [L]TAN 20 DIM Q$(255) 60 SLOW 70 PRINT "INITIALIZING..." 80 LET B$=" " 85 LET LL=32 90 LET O=PI/PI 95 LET Z=O-O 100 LET MS=6 105 LET SZ=VAL "22-1-MS" 110 LET CR=O 115 LET Z$=B$+B$ 117 LET Z$=B$+B$+"▛▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▜" 120 LET X$="▌ ▐" 125 FAST 130 FOR K=O+O+O TO SZ-O-O 140 LET Z$=Z$+X$ 150 NEXT K 160 LET Z$=Z$+"▙▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▟" 170 LET X$="▌ █ ▐" 180 FOR K=O TO MS 190 LET Z$=Z$+X$ 200 NEXT K 210 LET Z$=Z$+"▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀" 220 LET S$=Z$ 230 LET X$="TIMEX PHONE BOOK" 235 LET H$="BBOOK" 240 LET S=16-LEN X$/2 250 LET S$(S TO S+LEN X$-O)=X$ 260 LET DF=16396 290 LET NLEN=7 300 LET FLDS=2 305 DIM F$(FLDS,NLEN) 310 DIM F(FLDS) 320 LET F(1)=20 330 LET F(2)=20 400 LET F$(1)="NAME" 410 LET F$(2)="NUMBER" 498 LET NUM=0 500 REM CALCULATE RLEN 510 LET RLEN=Z 520 FOR F=O TO FLDS 530 LET RLEN=RLEN+F(F) 540 NEXT F 545 SLOW 550 LET FRE=VAL "((PEEK 16386+PEEK 16387*256)-(PEEK 16412+PEEK 16413*256)-400)" 560 LET MAX=INT (FRE/(RLEN+5)) 565 IF MAX>255 THEN LET MAX=255 570 PRINT "RECORDS AVAILIBLE: ";MAX 580 DIM D$(MAX,RLEN) 590 DIM N$(RLEN) 700 LET T2=1 710 LET T1=SZ+O 720 DIM B$(RLEN) 735 FAST 800 FOR F=O TO FLDS 810 LET S=LL*(F+O+O)+O+O 820 LET S$(S TO S+NLEN)=F$(F)+":" 830 NEXT F 840 LET U$="" 850 LET E$="" 860 FOR B=O TO MAX 870 LET E$=E$+CHR$ B 880 NEXT B 1000 REM MAIN LOOP 1005 SLOW 1010 PRINT AT Z,Z;S$ 1015 PRINT AT 3,1; 1017 LET OF=O 1018 IF CR>LEN U$ OR U$="" OR CR<1 THEN GOTO 1100 1020 FOR F=O TO FLDS 1030 PRINT TAB NLEN+O+O; 1040 PRINT D$(CODE U$(CR),OF TO OF+F(F)-O) 1050 LET OF=OF+F(F) 1060 NEXT F 1100 PRINT AT SZ,O;"(1) ADD";TAB O;"(2) DELETE";TAB O;"(3) SEARCH";TAB O;"(4) SAVE";TAB O;"(5) QUIT" 1105 PRINT TAB O;"(6) LIST" 1110 PRINT AT SZ,14;"SELECT: "; 1120 LET D=PEEK DF+PEEK (DF+O)*256 1130 LET FL=1 1140 LET C$=INKEY$ 1145 IF C$=CHR$ 112 OR C$=CHR$ 113 THEN GOTO 8500 1150 IF C$>="1" AND C$<="6" THEN GOTO 1200 1152 POKE D+67,CODE "▛▟"(FL+1) 1154 POKE D+98,CODE "▜▙"(FL+1) 1156 LET FL=NOT FL 1170 GOTO 1140 1210 PRINT AT SZ,14;" " 1220 FOR J=20 TO SZ+VAL C$-O STEP -O 1225 IF J<20 THEN PRINT AT J+1,13;"█" 1230 PRINT AT J,13;"[<]" 1240 NEXT J 1250 GOTO VAL "1000+1000*VAL C$" 2000 REM ADD 2010 IF E$>"" THEN GOTO 2100 2020 PRINT AT T1,T2;"THERE ARE NO FREE";TAB T2;"RECORDS." 2030 GOTO 8000 2100 REM ADD 2110 PRINT AT Z,Z;S$ 2115 LET OF=O 2120 FOR F=O TO FLDS 2130 PRINT AT 2+F,NLEN+O+O;"[~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~]"( TO F(F)) 2140 INPUT I$ 2150 LET B$(OF TO OF+F(F)-O)=I$ 2160 PRINT AT 2+F,NLEN+O+O;B$(OF TO OF+F(F)-O) 2165 LET OF=OF+F(F) 2170 NEXT F 2180 IF C$="3" THEN RETURN 2190 LET CR=CODE E$ 2200 LET E$=E$(2 TO ) 2220 LET D$(CR)=B$ 2230 LET U$=U$+CHR$ CR 2240 GOTO 1100 3000 REM DELETE 3020 LET E$=E$+CHR$ CR 3030 LET A$=CHR$ CR 3040 LET Q$=U$ 3060 GOSUB 9800 3070 LET U$=U$( TO J-1)+U$(J+1 TO ) 3080 LET D$(CR)=N$ 3090 GOTO 1000 4000 REM FIND 4005 LET L$="" 4007 DIM T(FLDS) 4010 PRINT AT 0,0;S$ 4020 PRINT AT SZ+2,T1;"ENTER YOUR";TAB T1;"SEARCH KEYS:" 4030 GOSUB 2115 4035 PRINT AT SZ+2,T1;" ";TAB T1;" " 4040 PRINT AT SZ+2,1;"SEARCHING.." 4042 FOR H=1 TO 10 4044 NEXT H 4050 FOR J=1 TO LEN U$ 4056 FAST 4060 LET Z$=D$(CODE U$(J)) 4065 LET T$=B$ 4070 FOR F=1 TO FLDS 4080 LET X$=T$( TO F(F)) 4090 LET Y$=Z$( TO F(F)) 4095 GOSUB 4500 4100 LET T$=T$(F(F)+1 TO ) 4110 LET Z$=Z$(F(F)+1 TO ) 4121 IF X$="" THEN GOTO 4150 4130 IF Y$( TO LEN X$)=X$ THEN GOTO 4150 4140 GOTO 4200 4150 NEXT F 4160 LET L$=L$+U$(J) 4200 NEXT J 4201 IF L$>"" THEN GOTO 4300 4210 PRINT AT SZ+2,1;"NOT FOUND" 4220 GOSUB 8200 4230 GOTO 1000 4300 REM 4305 SLOW 4310 LET G$=U$ 4320 LET U$=L$ 4330 GOSUB 7000 4335 LET U$=G$ 4340 GOTO 1000 4500 REM REMOVE SPACES FM X$/Y$ 4510 FOR G=1 TO LEN X$ 4520 IF X$(LEN X$)=" " THEN LET X$=X$( TO LEN X$-1) 4530 IF Y$(LEN Y$)=" " THEN LET Y$=Y$( TO LEN Y$-1) 4540 NEXT G 4550 RETURN 4999 STOP 5000 REM SAVE 5005 CLS 5010 PRINT TAB O;"UNDER WHAT NAME SHALL I SAVE THE INFORMATION: "; 5020 INPUT A$ 5030 IF A$="" THEN LET A$=H$ 5040 PRINT TAB O;TAB O;"START THE TAPE, AND THEN PRESS [E][N][T][E][R]." 5050 INPUT Z$ 5055 CLS 5060 SAVE A$ 5070 PRINT TAB O;TAB O;"STOP THE TAPE." 5080 GOTO 8000 6000 REM QUIT 6010 STOP 6020 GOTO 1000 7000 REM LIST 7005 DIM T(FLDS) 7010 CLS 7020 PRINT "LIST TO PRINTER (P), SCREEN (S) OR BOTH (B)?" 7030 LET K$=INKEY$ 7040 IF K$<>"S" AND K$<>"B" AND K$<>"P" THEN GOTO 7030 7050 LET PRI=K$<>"S" 7060 LET SCR=K$<>"P" 7070 CLS 7075 LET LCNT=INT (18/(FLDS+2)) 7080 FOR K=1 TO LEN U$ 7090 FAST 7100 LET Z$=D$(CODE U$(K)) 7110 FOR N=1 TO FLDS 7115 IF F$(N)(1)="." THEN LET T(N)=T(N)+VAL Z$( TO F(N)) 7120 LET O$=F$(N) 7130 LET O$=O$+": "+Z$( TO F(N)) 7140 LET Z$=Z$(F(N)+1 TO ) 7150 GOSUB 8100 7160 NEXT N 7170 LET O$="" 7180 FOR G=1 TO 2 7190 GOSUB 8100 7200 NEXT G 7205 LET LCNT=LCNT-1 7210 IF (SCR) AND (LCNT=0) THEN GOSUB 8200 7220 NEXT K 7230 LET O$="TOTAL RECORDS: "+STR$ LEN U$ 7240 GOSUB 8100 7242 GOSUB 8600 7245 GOSUB 8200 7247 IF C$="3" THEN RETURN 7250 GOTO 1000 8000 REM ENTER 8010 PRINT AT 20,T2;"PRESS [E][N][T][E][R]" 8020 INPUT Z$ 8030 GOTO 1000 8100 REM 8110 IF PRI THEN LPRINT O$ 8120 IF SCR THEN PRINT O$ 8130 RETURN 8200 REM 8210 PRINT AT 20,1;"PRESS [E][N][T][E][R]." 8220 INPUT W$ 8230 CLS 8235 LET LCNT=INT (18/(FLDS+2)) 8237 IF W$=" STOP" THEN GOTO 1000 8240 RETURN 8500 REM 8510 IF C$=CHR$ 113 THEN LET CR=CR+(CR1) 8530 GOTO 1015 8600 REM TOTALS 8605 IF NOT NUM THEN RETURN 8610 LET O$="" 8620 GOSUB 8100 8630 GOSUB 8100 8640 LET O$="TOTALS:" 8650 GOSUB 8100 8660 LET O$="" 8670 GOSUB 8100 8680 FOR F=1 TO FLDS 8690 IF F$(F)(1)<>"." THEN GOTO 8750 8700 LET O$=" "+F$(F)+": "+STR$ T(F) 8710 GOSUB 8100 8750 NEXT F 8760 LET O$="" 8770 GOSUB 8100 8780 GOSUB 8100 8790 RETURN 9800 REM SEARCH 9810 POKE 16514,CODE A$ 9820 LET J=255-USR 16524 9830 RETURN ```