--- title: "PHONEDIR" id: 71393 type: "computer_media" slug: "phonedir" url: "http://localhost/computer_media/phonedir/" markdown_url: "http://localhost/computer_media/phonedir.md" published_at: "2026-09-02T10:52:10+00:00" modified_at: "2026-09-02T10:52:11+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2026/09/phondir.png" excerpt: "A six-option telephone directory manager packs names and numbers into a 200-entry string array with built-in sorting and substring search." 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: "Home" slug: "home" taxonomy: "genre" url: "http://localhost/type/home/" media_type: "Program" download_url: "https://archive.org/download/timex-sinclair-software-archive/PHONEDIR%20(198x)(Goldsmith%2C%20Izzy)(TS2068)(US)(Program).zip" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2026/09/phondir.png" related_content: - id: 20969 title: "The Timex Sinclair 2068 Explored" type: "book" url: "http://localhost/book/the-timex-sinclair-2068-explored/" media_type_tags: "Home" --- # PHONEDIR PHONEDIR is a telephone directory manager that stores up to 200 name-and-number entries in a fixed-length string array, each record occupying 32 characters. Entries are concatenated with a space separator into DIM D$(200,32) and sorted in-place using a selection-sort variant that bubbles the largest unsorted entry to the end of the active range. The search routine uses a BASIC substring slice — D$(A)(TO F) — to match only the name portion of each record against the user’s query. Menu options cover creating a new directory, adding entries, searching, saving to tape, and printing via LPRINT. *** ### Program Structure The program is organized around a central menu at lines 340–480, branching to four functional regions: 1. **Initialization / data entry** – lines 40–170: dimensions the array, collects name and number, validates with a correction loop, and concatenates into `D$(D)`. 2. **Sorting** – lines 180–330: selection-sort executed after the user signals they have finished entering names. 3. **Main menu** – lines 340–480: six-option dispatcher using numeric `INPUT B`. 4. **Search** – lines 490–560: linear scan with a substring match. Line 30 (`GO TO 340`) jumps past the data-entry block on first run so the menu is shown immediately, letting the user choose whether to start a new directory or do something else before any data exists. ### Data Storage All records are held in `DIM D$(200,32)`, a two-dimensional fixed-width string array declared at line 40. Each entry is formed by concatenating the name string, a space, and the phone number string at line 140: `LET D$(D)=B$+" "+C$`. Because each row is exactly 32 characters, long combined strings are silently truncated and short ones are padded with spaces — a limitation users must manage by keeping entries brief. The variable `D` serves dual duty: it is both the `FOR` loop counter during entry (lines 50–170) and subsequently the high-water mark indicating how many records have been entered. This is referenced during sorting, printing, and searching. ### Sorting Algorithm The sort (lines 200–330) is a selection sort, but implemented in an unusual descending-boundary style. The outer boundary `G` starts at `D` (the total record count) and shrinks by one each pass (line 320). Within each pass, `Z` walks from 1 upward; whenever `D$(B) > D$(Z)` (i.e., the next element is alphabetically greater than the current), the two are swapped. After each full inner scan the largest remaining element has been moved toward index `G`, and `G` is decremented. `POKE 23692,0` at line 190 resets the BASIC scroll counter so “scroll?” prompts do not interrupt the sort output of sorted entries at line 310. Note that line 310 `PRINT D$(G)` prints each record as it is placed, producing a display of entries in sorted order as the sort completes — a side-effect display rather than a deliberate print routine. ### Search Routine The search (lines 490–560) asks for a name, stores its length in `F`, then iterates over all records with a substring comparison: ``` IF D$(A)(TO F)=A$ THEN PRINT ''D$(A)(F+1 TO ):GO TO 340 ``` The slice `D$(A)(TO F)` extracts just the first `F` characters (the name field) and compares against the input. On a match, `D$(A)(F+1 TO)` prints the remainder — the space and phone number. This is a clean prefix-match idiom that exploits BASIC string slicing. The search is case-sensitive and only finds exact prefix matches. ### Menu and Input Handling The menu at lines 340–410 uses numeric `INPUT B` and a chain of independent `IF` statements (lines 420–470) rather than `ON B GO TO`. Each condition is tested in sequence; unrecognized input falls through to line 480 which loops back to the menu. Option 2 (“add new names”) executes `NEXT D` at line 430, resuming the suspended `FOR D=1 TO 200` loop — a technique that relies on the loop being left intact in memory. Option 5 prints the directory in reverse order (`FOR A=D TO 1 STEP -1`) via `LPRINT`. Since the sort places the largest (alphabetically last) entries near index `D`, printing in reverse produces ascending alphabetical output on the printer. ### Escape Sequences and Display Lines 110, 180, 510, and others use embedded control-code escape sequences such as `\\{20}\\{1}` and `\\{18}\\{1}` to switch on FLASH and BRIGHT or change INK color inline within string literals, providing highlighted prompts without separate `PRINT` attribute statements. ### Bugs and Anomalies - The sort at lines 200–330 is triggered only from inside the entry loop (line 180), so if the user returns to the menu and adds more names later, the directory becomes partially unsorted and the sort must be triggered again manually — but there is no menu option to re-sort without re-entering data. - Option 4 (`SAVE "DIRECTORY"` at line 450) saves the program under a different filename than option at line 570 (`SAVE "PHONEDIR" LINE 10`), and neither save preserves the array data separately — the array is lost if the program is reloaded without a companion `LOAD` for the data. - If the user selects option 2 (add names) before ever entering the entry loop via option 1, `NEXT D` at line 430 references an uninitialized `FOR` variable, which will produce a BASIC error. - The search at line 530 exits immediately on the first match (`GO TO 340`), so duplicate names will never surface results beyond the first occurrence. ## Source Code ``` 10 REM TELEPHONE DIRECTORY 20 REM From Timex Sinclair 2068 explored entered by Izzy Goldsmith LIST Group 30 GO TO 340 40 DIM D$(200,32) 50 FOR D=1 TO 200 60 INPUT "Enter Name ";B$ 70 PRINT AT 0,0;"Name: ";B$ 80 INPUT "Enter telephone number ";C$ 90 CLS 100 PRINT AT 0,0;B$;" ";C$ 110 PRINT ''"If this is correct, press \{20}\{1}ENTER\{20}\{0} If incorrect, press \{18}\{1}'E'\{18}\{0} then ENTER" 120 INPUT E$:CLS 130 IF E$ <>"" THEN GO TO 60 140 LET D$(D)=B$+" "+C$ 150 PRINT ''"Press \{20}\{1}ENTER\{20}\{0} to enter next item,","or any letter, then ENTER, to","sort directory" 160 INPUT E$:CLS 170 IF E$="" THEN NEXT D 180 PRINT PAPER 2;"\{18}\{1}sorting...\{18}\{0}" 190 POKE 23692,0 200 LET B=0 210 LET G=D 220 LET Z=1 230 LET B=Z+1 240 IF B>G THEN GO TO 310 250 IF D$(B)>D$(Z) THEN GO TO 270 260 LET Z=Z+1:GO TO 230 270 LET Q$=D$(Z) 280 LET D$(Z)=D$(B) 290 LET D$(B)=Q$ 300 GO TO 260 310 PRINT D$(G) 320 LET G=G-1 330 IF G>0 THEN GO TO 220 340 PRINT ''"Enter one number:" 350 PRINT '"1 - To start new directory" 360 PRINT '"2 - To add new names" 370 PRINT '"3 - To search for number" 380 PRINT '"4 - To save directory" 390 PRINT '"5 - To print directory" 400 PRINT '"6 - To stop" 410 INPUT B:CLS 420 IF B=1 THEN GO TO 40 430 IF B =2 THEN NEXT D 440 IF B=3 THEN GO TO 490 450 IF B=4 THEN SAVE "DIRECTORY" 460 IF B=5 THEN FOR A=D TO 1 STEP -1:LPRINT D$(A):NEXT A 470 IF B=6 THEN STOP 480 GO TO 340 490 PRINT ''"ENTER NAME REQUIRED" 500 INPUT A$:LET F= LEN A$ 510 PRINT INK 1;"\{18}\{1}Searching for ";A$;"\{18}\{0}" 520 FOR A=1 TO D 530 IF D$(A)( TO F)=A$ THEN PRINT ''D$(A)(F+1 TO ):GO TO 340 540 NEXT A 550 PRINT '"Name not found" 560 GO TO 340 570 SAVE "PHONEDIR" LINE 10 ```