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:
DIMstatements are issued at runtime after computingCbased on available memory and chosen layout parameters. - Formula evaluation via
VALon stored expression strings — a macro-expansion approach that avoids writing a formula interpreter. - Relative formula replication embeds loop variables
MandNdirectly into the stored expression string, so the same string works for all replicated copies. - The cursor “pixel”
P$is built from▀characters sized toV-1at 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 ERRis not used; instead, error recovery at lines 80–95 appears to be called manually or via the BASIC error mechanism redirected by aGOTO 80-equivalent path, writing “ERROR” into the offending cell.
Bugs and Anomalies
- Line 270 tests
INKEY$=" FAST", which can never be true sinceINKEY$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$ Aon consecutive lines with no effect difference. - The variable
Lset at line 6278 is used as theGOSUBtarget variable (line 440:GOSUB L), selecting between the four layout display subroutines (40, 50, 60, 70). The formulaL=30+A*10gives 40, 50, 60, 70 for A=1,2,3,4 respectively — this is an elegant computedGOSUB. - Line 4720 validates
VAL A$>C(intended to check column bounds) but uses the same boundCas 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 widthV-2, but ifV>9(not possible with current options) this would be insufficient.
Content
Image Gallery
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<C-9 THEN LET B=B+1
1070 IF INKEY$ =">" THEN GOTO 1100
1080 GOSUB 400
1090 GOTO 1000
1100 PRINT AT 2,0;N$(B*2-1 TO B*2)
1120 GOTO 1060
1200 IF INKEY$ <>"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 P<LEN A$ THEN GOTO 3070
3200 LET C$(Q)=E$
3202 LET U$=CHR$ Q
3210 LET B$(B+Y/2-2,E+X-3)=U$
3215 PRINT AT Y-1,X;R$
3220 PRINT AT Y-1,X;"F";Q
3280 GOTO 200
3300 FAST
3310 LET O=1
3320 LET J=C
3330 LET G=1
3340 LET H=C
3345 IF INKEY$ =" FAST" THEN GOTO 3700
3350 GOTO 3515
3500 FAST
3505 LET G=INT ((E-1)/V)+1
3506 LET H=G+R-1
3507 LET O=B
3510 LET J=B+9
3515 IF INKEY$ ="F" THEN GOTO 3700
3517 FOR M=O TO J
3520 FOR N=G TO H
3530 IF B$(M,N*V-(V-1))=" " THEN GOTO 3580
3540 LET A=CODE B$(M,N*V-(V-1))
3550 LET W=VAL C$(A)
3560 LET B$(M,N*V-(V-2) TO N*V)=STR$ W
3580 NEXT N
3600 NEXT M
3610 SLOW
3620 GOTO 400
3700 FOR M=O TO J
3710 FOR N=G TO H
3720 IF B$(M,N*V-(V-1))=" " THEN GOTO 3760
3730 LET A=CODE B$(M,N*V-(V-1))
3740 LET B$(M,N*V-(V-2) TO N*V)="F"+STR$ A
3750 LET B$(M,N*V-(V-2) TO N*V)="F"+STR$ A
3760 NEXT N
3770 NEXT M
3780 SLOW
3790 GOTO 400
4000 PRINT AT 0,0;"RELATIVE "
4002 LET E$=""
4040 LET P=1
4060 IF A$(P)="F" THEN GOTO 4140
4080 LET E$=E$+A$(P)
4100 LET P=P+1
4120 IF P>LEN 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
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.