--- title: "Computacalc" id: 51870 type: "computer_media" slug: "computacalc" url: "http://localhost/computer_media/computacalc/" markdown_url: "http://localhost/computer_media/computacalc.md" published_at: "2023-08-16T01:42:19+00:00" modified_at: "2026-04-03T07:59:14+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2019/02/20230809-041332.jpg" excerpt: "A fully functional spreadsheet with formula replication, absolute and relative cell references, and four selectable column-width layouts — all in BASIC." 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: "Mindware" slug: "mindware" taxonomy: "post_tag" url: "http://localhost/tag/mindware/" - 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: "Spreadsheet" slug: "spreadsheet" taxonomy: "genre" url: "http://localhost/type/spreadsheet/" media_type: "Cassette" download_url: "https://archive.org/download/timex-sinclair-software-archive/Computacalc (198x)(Mindware)(US)(TS1000)(Cassette).zip" mediadate: "198x" producer_company: - id: 11120 title: "Mindware, Inc." type: "company" url: "http://localhost/company/mindware/" related_products: - id: 12201 title: "Computacalc" type: "product" url: "http://localhost/product/computacalc/" media_type_tags: "Spreadsheet" --- # Computacalc Computacalc is a spreadsheet program that provides a grid-based calculation environment with support for numeric entries, text labels, and user-defined formulas. The program offers four display layouts: 3 columns of 9-digit numbers, 4 columns of 6-digit numbers, 5 columns of 5-digit numbers, or 7 columns of 3-digit numbers. Formulas can reference other cells using an “F” prefix notation (e.g., F0102 for row 01, column 02) and are stored as BASIC expressions in a string array, evaluated with VAL at recalculation time. Both absolute and relative cell referencing are supported, with relative formulas capable of being replicated across rows or down columns automatically. Grid size is dynamically calculated based on available memory and the number of formulas requested, using a DIM statement sized at runtime. *** ## Program Analysis ### Program Structure The program is organized into a main menu/navigation loop, initialization routines, display subroutines, and formula-handling sections. Execution begins at line 1 with `GOTO 5000`, which jumps to the splash screen and configuration menu. After the user selects a layout, control flows through lines 6110–6900 to initialize variables and then falls into the main loop at line 100. | Line Range | Purpose | | --- | --- | | 1–5 | Shared utility subroutines (cell write, display, error) | | 40–75 | Row-display subroutines for each of the four column layouts | | 80–95 | Error handler | | 100–300 | Main display and key-dispatch loop | | 400–470 | Screen refresh subroutine | | 1000–1720 | Cursor movement (down, up, right, left) with scrolling | | 2000–2030 | Data entry (number or title) | | 2500–2560 | Title/hardcopy (COPY) handler | | 3000–3280 | Absolute formula entry and storage | | 3300–3790 | Recalculation (full grid) and formula display toggle | | 3500–3620 | Visible-area recalculation | | 4000–4760 | Relative formula entry and replication (across/down) | | 4300–4355 | Formula repeat/change at cursor | | 4990–4995 | Save with data | | 5000–6080 | Splash screen and layout selection | | 6110–6900 | Layout initialization and grid sizing | ### Data Storage Model The spreadsheet uses two main string arrays allocated at runtime. `B$` is a two-dimensional string array dimensioned as `DIM B$(C, C*V+3)`, where `C` is the computed grid size and `V` is the column width in characters. Each cell occupies `V` characters within a row string: the first character (at offset `N*V-(V-1)`) is a formula token if the cell contains a formula, otherwise a space, and the remaining `V-1` characters hold the displayed value. `C$` is a one-dimensional array `DIM C$(VAL A$, 60)` holding the BASIC expression string for each formula slot. Grid size `C` is computed dynamically at line 6760 as `INT(SQR((4000-(A*60))/V))`, balancing available memory between the formula array and the cell data array. This makes the grid square (C×C cells). ### Formula System Formulas are entered using an “F” prefix notation where each cell reference is five characters: “F” followed by two digits for the row and two digits for the column (e.g., `F0102`). The parser at lines 3070–3180 (absolute) and 4060–4180 (relative) scans the formula string character by character, copying literal text and translating each `F`-prefixed reference into a `VAL B$(row, colStart TO colEnd)` expression, which is then stored as a string in `C$`. At recalculation time (lines 3517–3600 or 3700–3770), the program iterates over all cells, checks the formula-token byte, retrieves the corresponding expression from `C$`, and evaluates it using `VAL C$(A)` — exploiting the fact that `VAL` on a string containing a BASIC numeric expression will execute it. The result is stored back as a string in `B$`. For relative formulas, cell references are translated at entry time into expressions involving `M` (the loop row variable) and `N` (the loop column variable) with fixed offsets, so the same formula expression evaluates correctly when applied to different cells during replication or recalculation. ### Column Layout and Variable V The variable `V` controls the column width in characters. It is set at line 6286 as `2*(5-A)+2` (with a special case `V=7` for option 2), giving: | Option (A) | Columns (R) | V (width) | | --- | --- | --- | | 1 | 3 | 10 | | 2 | 4 | 7 | | 3 | 5 | 6 | | 4 | 7 | 4 | The four display subroutines at lines 40–75 print column separators (“`:`“) at hardcoded positions matching each layout. The variable `L` at line 6278 is set to `30+A*10` but does not appear to be used in the visible recalculation path — it may be a vestigial variable. ### Cursor and Scrolling The on-screen cursor position is tracked by `X` (column, in screen characters) and `Y` (row, in screen lines, always odd because rows are displayed on even lines with labels on odd). The logical window offset into the grid is tracked by `B` (first visible row) and `E`/`D` (first/last visible column character offset). Navigation routines at lines 1000–1720 move the cursor, switching between cursor movement and grid scrolling at the screen boundary. Key repeat is suppressed by waiting for key-release (`IF INKEY$<>"" THEN GOTO ...`) before re-entering the movement loop. ### Key Dispatch The main loop at lines 204–300 uses a chain of `IF INKEY$=` tests after a `PAUSE 0`-equivalent key-wait at line 204. Both letter keys and symbol keys are accepted for most functions (e.g., `"M"` or `">"` for move down, `"I"` or `"("` for move up), accommodating shifted and unshifted entry styles. ### Notable Techniques - Dynamic memory allocation: `DIM` statements are issued at runtime after computing `C` based on available memory and chosen layout parameters. - Formula evaluation via `VAL` on stored expression strings — a macro-expansion approach that avoids writing a formula interpreter. - Relative formula replication embeds loop variables `M` and `N` directly into the stored expression string, so the same string works for all replicated copies. - The cursor “pixel” `P$` is built from `▀` characters sized to `V-1` at initialization (line 6635–6645), adapting automatically to the chosen column width. - The column-header string `N$` at line 6260 encodes column numbers 1–50 as two-character pairs using a long literal string, accessed by slicing. - `ON ERR` is not used; instead, error recovery at lines 80–95 appears to be called manually or via the BASIC error mechanism redirected by a `GOTO 80`-equivalent path, writing “ERROR” into the offending cell. ### Bugs and Anomalies - Line 270 tests `INKEY$=" FAST"`, which can never be true since `INKEY$` returns at most one character. This condition is always false; the FAST-mode recalculation from the main loop via the space bar is therefore unreachable through this path. - Lines 3740–3750 duplicate the same assignment `LET B$(M,N*V-(V-2) TO N*V)="F"+STR$ A` on consecutive lines with no effect difference. - The variable `L` set at line 6278 is used as the `GOSUB` target variable (line 440: `GOSUB L`), selecting between the four layout display subroutines (40, 50, 60, 70). The formula `L=30+A*10` gives 40, 50, 60, 70 for A=1,2,3,4 respectively — this is an elegant computed `GOSUB`. - Line 4720 validates `VAL A$>C` (intended to check column bounds) but uses the same bound `C` as both the row and column limit, which is correct only because the grid is square. - The variable `L$` initialized at line 6275 as eight block characters is used in line 6800 to pad column header entries to width `V-2`, but if `V>9` (not possible with current options) this would be insufficient. ## Source Code ``` 1 GOTO 5000 2 LET B$(B+Y/2-1.5,E+X-3)=U$ 3 PRINT AT Y-1,X;R$ 4 PRINT AT Y-1,X;"F";CODE U$ 5 RETURN 40 PRINT AT S,0;N$(F*2-1 TO F*2);AT S,2;B$(F,E TO D);AT S,11;":";AT S,21;":";AT S,31;":" 45 RETURN 50 PRINT AT S,0;N$(F*2-1 TO F*2);AT S,2;B$(F,E TO D);AT S,8;":";AT S,15;":";AT S,22;":";AT S,29;":" 55 RETURN 60 PRINT AT S,0;N$(F*2-1 TO F*2);AT S,2;B$(F,E TO D);AT S,7;":";AT S,13;":";AT S,19;":";AT S,25;":";AT S,31;":" 65 RETURN 70 PRINT AT S,0;N$(F*2-1 TO F*2);AT S,2;B$(F,E TO D);AT S,5;":";AT S,9;":";AT S,13;":";AT S,17;":";AT S,21;":";AT S,25;":";AT S,29;":" 75 RETURN 80 SLOW 90 PRINT AT 0,0;"AN ERROR HAS OCCURRED IN LINE ";M;AT 1,23;"COLUMN ";N;AT 3,0;"PRESS ANY KEY (EXCEPT BREAK) TO CONTINUE AND RE-ENTER YOUR FORMULA" 92 IF INKEY$ ="" THEN GOTO 92 95 LET B$(M,N*V-(V-2) TO N*V)="ERROR" 100 SLOW 110 CLS 120 PRINT AT 0,0;"COMPUTACALC ZX" 125 FOR H=1 TO 21 STEP 2 130 PRINT AT H,0;"██" 135 PRINT AT H,2;"------------------------------" 140 NEXT H 160 GOSUB 400 200 PRINT AT 0,0;"PRESS K TO MAKE AN ENTRY " 204 IF INKEY$ ="" THEN GOTO 204 210 IF INKEY$ ="M" OR INKEY$ =">" THEN GOTO 1000 220 IF INKEY$ ="I" OR INKEY$ ="(" THEN GOTO 1200 230 IF INKEY$ ="L" OR INKEY$ ="=" THEN GOTO 1400 235 IF INKEY$ ="J" OR INKEY$ ="-" THEN GOTO 1600 240 IF INKEY$ ="K" THEN GOTO 2000 250 IF INKEY$ ="Q" THEN GOSUB 2 260 IF INKEY$ ="C" OR INKEY$ ="F" THEN GOSUB 3500 270 IF INKEY$ ="?" OR INKEY$ =" FAST" THEN GOSUB 3300 275 IF INKEY$ ="P" THEN GOTO 4300 280 IF INKEY$ ="R" THEN GOTO 5000 285 IF INKEY$ ="H" THEN GOTO 2500 290 IF INKEY$ ="D" THEN GOTO 4330 300 GOTO 204 400 PRINT AT 1,2;M$(E TO D) 410 LET J=B+9 420 FOR F=B TO J 430 LET S=(F-B)*2+2 440 GOSUB L 450 NEXT F 460 PRINT AT Y,X;P$ 470 RETURN 1000 IF INKEY$ <>"M" AND INKEY$ <>">" THEN GOTO 200 1010 IF Y>19 THEN GOTO 1060 1015 PRINT AT Y,X;Q$ 1020 LET Y=Y+2 1025 PRINT AT Y,X;P$ 1026 IF INKEY$ <>"" AND INKEY$ <>">" THEN GOTO 1026 1030 GOTO 1000 1060 IF B"I" AND INKEY$ <>"(" THEN GOTO 200 1210 IF Y<4 THEN GOTO 1260 1215 PRINT AT Y,X;Q$ 1220 LET Y=Y-2 1225 PRINT AT Y,X;P$ 1226 IF INKEY$ <>"" AND INKEY$ <>"(" THEN GOTO 1226 1230 GOTO 1200 1260 IF B>1 THEN LET B=B-1 1270 IF INKEY$ ="(" THEN GOTO 1300 1280 GOSUB 400 1290 GOTO 1200 1300 PRINT AT 2,0;N$(B*2-1 TO B*2) 1320 GOTO 1260 1400 IF INKEY$ <>"L" AND INKEY$ <>"=" THEN GOTO 200 1410 IF X>29-V THEN GOTO 1460 1415 PRINT AT Y,X;Q$ 1420 LET X=X+V 1425 PRINT AT Y,X;P$ 1426 IF INKEY$ <>"" AND INKEY$ <>"=" THEN GOTO 1426 1430 GOTO 1400 1460 IF E>T-30 THEN GOTO 1480 1461 LET D=D+V 1462 LET E=E+V 1470 IF INKEY$ ="=" THEN GOTO 1500 1480 GOSUB 400 1490 GOTO 1400 1500 PRINT AT 1,2;M$(E TO D) 1520 GOTO 1460 1600 IF INKEY$ <>"J" AND INKEY$ <>"-" THEN GOTO 200 1610 IF X<3 THEN GOTO 1660 1615 PRINT AT Y,X;Q$ 1620 LET X=X-V 1625 PRINT AT Y,X;P$ 1626 IF INKEY$ <>"" AND INKEY$ <>"-" THEN GOTO 1626 1630 GOTO 1600 1660 IF E<3 THEN GOTO 1680 1661 LET D=D-V 1662 LET E=E-V 1670 IF INKEY$ ="-" THEN GOTO 1700 1680 GOSUB 400 1690 GOTO 1600 1700 PRINT AT 1,2;M$(E TO D) 1720 GOTO 1660 2000 PRINT AT 0,0;"NUMBER/TITLE. N/L FOR FORMULA. " 2001 INPUT A$ 2002 IF A$="" THEN GOTO 3000 2010 LET B$(B+Y/2-2,E+X-2 TO E+X+(V-4))=A$ 2015 PRINT AT Y-1,X;R$ 2020 PRINT AT Y-1,X;A$ 2025 PRINT AT 0,16;" " 2030 GOTO 200 2500 PRINT AT 0,0;"ENTER TITLE THEN C-COPY,R-RETURN" 2510 INPUT A$ 2515 PRINT AT 0,0;" " 2520 PRINT AT 0,0;A$ 2530 IF INKEY$ ="" THEN GOTO 2530 2540 IF INKEY$ ="C" THEN COPY 2550 IF INKEY$ ="R" THEN GOTO 200 2560 GOTO 2530 3000 LET K=K+1 3005 LET Q=K 3015 PRINT AT 0,0;"ENTER FORMULA . " 3020 INPUT A$ 3022 IF A$="" THEN GOTO 3020 3025 PRINT AT 0,0;"RELATIVE (R) OR ABSOLUTE (A) " 3035 IF INKEY$ ="" THEN GOTO 3035 3038 IF INKEY$ ="R" THEN GOTO 4000 3040 IF INKEY$ ="A" THEN GOTO 3045 3042 GOTO 3035 3045 PRINT AT 0,0;"ABSOLUTE " 3050 LET E$="" 3060 LET P=1 3070 IF A$(P TO P)="F" THEN GOTO 3140 3080 LET E$=E$+A$(P TO P) 3100 LET P=P+1 3120 IF P>LEN A$ THEN GOTO 3185 3130 GOTO 3070 3140 LET E$=E$+"VAL B$("+A$(P+1 TO P+2)+","+STR$ (VAL A$(P+3 TO P+4)*V-(V-2))+" TO "+STR$ (VAL A$(P+3 TO P+4)*V)+")" 3160 LET P=P+5 3180 IF PLEN A$ THEN GOTO 4200 4130 GOTO 4060 4140 LET Z=E+X-2 4150 LET E$=E$+"VAL B$("+"M+"+STR$ (VAL A$(P+1 TO P+2)-(B+Y/2-1.5))+","+"N*V-(V-2)+"+STR$ (VAL A$(P+3 TO P+4)*V-(V-2)-Z)+" TO N*V+"+STR$ (VAL A$(P+3 TO P+4)*V-(V-2)-Z)+")" 4160 LET P=P+5 4180 IF P<=LEN A$ THEN GOTO 4060 4200 LET C$(Q)=E$ 4210 LET U$=CHR$ Q 4215 LET B$(B+Y/2-2,E+X-3)=U$ 4220 PRINT AT Y-1,X;R$ 4225 PRINT AT Y-1,X;"F";Q 4230 PRINT AT 0,0;"ACROSS(A),DOWN(D) OR MANUALLY(M)" 4240 IF INKEY$ ="" THEN GOTO 4240 4250 IF INKEY$ ="A" THEN GOTO 4400 4260 IF INKEY$ ="D" THEN GOTO 4700 4270 IF INKEY$ ="M" THEN GOTO 4275 4274 GOTO 4240 4275 IF INKEY$ <>"" THEN GOTO 4275 4276 GOTO 200 4300 IF B$(B+Y/2-2,E+X-3)<>" " THEN GOTO 4308 4302 PRINT AT 0,0;"NO FORMULA PRESENT " 4303 FOR I=1 TO 15 4305 NEXT I 4306 GOTO 200 4308 PRINT AT 0,0;"REPEAT(R) OR CHANGE(C) " 4310 IF INKEY$ ="" THEN GOTO 4310 4315 IF INKEY$ ="R" THEN LET U$=B$(B+Y/2-2,E+X-3) 4317 IF INKEY$ ="R" THEN GOTO 4230 4322 IF INKEY$ ="C" THEN GOTO 4350 4325 GOTO 4310 4330 LET B$(B+Y/2-2,E+X-3)=" " 4332 PRINT AT Y-1,X;R$ 4333 LET B$(B+Y/2-2,E+X-2 TO E+X+(V-4))=R$ 4335 GOTO 200 4350 LET Q=CODE B$(B+Y/2-2,E+X-3) 4355 GOTO 3015 4400 PRINT AT 0,0;"TO WHICH COLUMN ? " 4410 INPUT A$ 4420 IF VAL A$>C THEN GOTO 4400 4430 FOR I=E+X-3 TO VAL A$*V STEP V 4440 LET B$(B+Y/2-2,I)=U$ 4450 NEXT I 4460 GOTO 200 4700 PRINT AT 0,0;"TO WHICH LINE ? " 4710 INPUT A$ 4720 IF VAL A$>C THEN GOTO 4700 4730 FOR I=B+Y/2-2 TO VAL A$ 4740 LET B$(I,E+X-3)=U$ 4750 NEXT I 4760 GOTO 200 4990 CLEAR 4995 SAVE "COMPUTACAL[C]" 5000 SLOW 5005 CLS 5010 PRINT AT 0,0;"█████████[C][O][M][P][U][T][A][C][A][L][C]█[Z][X]█████████" 5030 PRINT AT 2,11;"OPTIONS" 5040 PRINT AT 3,11;"▀▀▀▀▀▀▀" 5060 PRINT AT 5,0;"1. 3 COLUMNS OF 9-FIGURE NUMBERS",,"2. 4 COLUMNS OF 6-FIGURE NUMBERS",,"3. 5 COLUMNS OF 5-FIGURE NUMBERS",,"4. 7 COLUMNS OF 3-FIGURE NUMBERS" 5070 PRINT AT 13,4;"------------------------" 5080 PRINT AT 16,0;"5. CONTINUE WITH DATA ",,"6. SAVE WITH DATA ",,"7. SAVE WITHOUT DATA" 6000 INPUT A$ 6010 IF A$="5" THEN GOTO 100 6020 IF A$="6" THEN GOTO 4995 6030 IF A$="7" THEN GOTO 4990 6040 IF A$="1" THEN RUN 6110 6050 IF A$="2" THEN RUN 6120 6060 IF A$="3" THEN RUN 6130 6070 IF A$="4" THEN RUN 6140 6080 GOTO 6000 6110 LET A=1 6112 LET R=3 6114 GOTO 6200 6120 LET A=2 6122 LET R=4 6124 GOTO 6200 6130 LET A=3 6132 LET R=5 6134 GOTO 6200 6140 LET A=4 6142 LET R=7 6144 GOTO 6200 6200 FAST 6210 LET K=0 6250 LET M$="█" 6260 LET N$="█[1]█[2]█[3]█[4]█[5]█[6]█[7]█[8]█[9][1][0][1][1][1][2][1][3][1][4][1][5][1][6][1][7][1][8][1][9][2][0][2][1][2][2][2][3][2][4][2][5][2][6][2][7][2][8][2][9][3][0][3][1][3][2][3][3][3][4][3][5][3][6][3][7][3][8][3][9][4][0][4][1][4][2][4][3][4][4][4][5][4][6][4][7][4][8][4][9][5][0]" 6275 LET L$="████████" 6278 LET L=30+A*10 6286 LET V=2*(5-A)+2 6287 IF A=2 THEN LET V=7 6595 LET E=2 6596 LET D=E+29 6625 LET Q$="" 6627 LET R$="" 6630 LET P$="" 6635 FOR I=1 TO V-1 6640 LET P$=P$+"▀" 6641 LET Q$=Q$+"-" 6642 LET R$=R$+" " 6645 NEXT I 6690 CLS 6695 SLOW 6700 PRINT AT 0,0;"█████████[C][O][M][P][U][T][A][C][A][L][C]█[Z][X]█████████" 6730 PRINT AT 4,0;"HOW MANY FORMULAE WILL YOU NEED?" 6750 INPUT A$ 6752 FAST 6755 LET A=VAL A$ 6760 LET C=INT (SQR ((4000-(A*60))/V)) 6770 DIM C$(VAL A$,60) 6775 DIM B$(C,C*V+3) 6780 LET T=C*V 6785 LET B=1 6786 LET X=2 6787 LET Y=3 6790 LET M$="" 6795 FOR I=1 TO C 6800 LET M$=M$+N$(I*2-1 TO I*2)+L$( TO V-2) 6810 NEXT I 6812 LET M$="█"+M$+"██" 6815 SLOW 6850 PRINT AT 4,0;" " 6880 PRINT AT 4,0;"YOUR GRID SIZE IS ";C;" BY ";C 6885 FOR I=1 TO 15 6886 NEXT I 6900 GOTO 100 ```