VU-Write

Products: Vu-Write
Date: 1983
Type: Cassette
Platform(s): TS 1000

VU-Write is a document processor that allows users to create, edit, and print text documents such as letters. It supports configurable record lengths (up to 30 characters per line), two user-definable tab stops, a document title field, and a saved-program name field. The text editor provides insert, delete, and block-move operations on lines stored in a two-dimensional string array D$(L1,L2), where L1 (maximum line count) is calculated as INT(11144/L2) to fit within available memory. Output is sent to a printer via LPRINT, with lines beginning with “/” treated as blank lines and text right-padded to a fixed column offset of 30 minus the record length. The program uses RAND USR calls at lines 670 and 1010 to invoke machine code routines embedded in the REM statement at line 1.


Program Analysis

Program Structure

VU-Write is organized into clearly labeled subroutines and sections, each introduced by a REM comment. The main modules are:

  • Lines 100–390: Display subroutine — renders document lines on screen scrolling upward from the current line.
  • Lines 500–895: Text editor — handles line entry, move operations, and navigation.
  • Lines 900–990: Title editor — sets the document title stored in T$.
  • Lines 1000–1090: Main menu — presents four top-level options (File, Write, LPrint, Save).
  • Lines 1100–1179: File setup — configures record length, allocates D$() array.
  • Lines 1180–1199: Initialization subroutine — sets constants and dimensions ancillary arrays.
  • Lines 1200–1295: Tab/Title/Text sub-menu — secondary menu branching to tabs, title, or text editor.
  • Lines 1300–1395: LPrint — sends the document to the printer.
  • Lines 1400–1440: Save — saves the program (including data) to tape.
  • Lines 1450–1490: Init — cold-start entry point, calls the init subroutine then falls through to Save.

Machine Code Usage

Line 1 contains a REM statement that encodes machine code routines directly in the program listing. Two entry points are called explicitly:

  • RAND USR VAL "16514" (line 670) — called after a line is confirmed non-empty before advancing the line pointer, likely performing a screen or memory operation.
  • RAND USR VAL "16530" (line 1010) — called at the start of the main menu, likely initializing the display or clearing the screen in a specific way.

Using VAL "number" as the argument to USR is consistent with the program-wide idiom of passing numeric literals through VAL to save memory by avoiding storing floating-point number representations inline.

Key BASIC Idioms

The program makes extensive use of several space- and speed-saving idioms:

  • VAL "number" in GO TO/GO SUB: Almost every branch target is written as GOTO VAL "NNN" rather than a bare numeric literal, saving five bytes per number by storing the line number as a string rather than a five-byte floating-point value.
  • Named constants A and B: A is set to 0 and B to 1 in the init subroutine (lines 1180–1181). These are used throughout as zero and one, again avoiding the five-byte floating-point overhead for frequently used small integers.
  • C as a menu return address: C is set to 1000 (line 1182), and GOTO C is used as a universal “return to main menu” throughout every module.
  • P as a long pause value: P is set to 40000 (line 1183) and used in PAUSE P followed by INKEY$ polling — the standard efficient keypress-wait idiom.
  • S$ as a blank/padding string: S$ is dimensioned to 32 characters (line 1190) and used as a blank-line sentinel and screen-clearing padding throughout.

Document Storage and Memory Calculation

After the user specifies a record length Q (1–30 characters), the program calculates the maximum number of lines as INT(11144/L2) (line 1174), where 11144 is an empirically chosen constant representing available string space. The two-dimensional array D$(L1,L2) is then dimensioned at line 1176. The length of the largest line number in decimal is stored in L via LEN STR$ L1 (line 1175) and used for column alignment in the editor display.

Text Editor Logic

The editor at lines 500–895 operates around a current-line pointer L3 and a mode flag F:

F valueMode
0Normal navigation/entry
1Display refresh only
2Move — source line selected, awaiting destination
3Move — performing the block copy

Entering “M” as the first character of a line number (line 620) sets move mode. The block-move routine (lines 800–895) copies a user-specified quantity of lines from source L4 to destination L3, adjusting iteration direction (Z1 is ±1) to avoid overwriting source data when the destination overlaps the source.

Lines beginning with “/” are treated as paragraph separators: the LPrint module (line 1364) outputs a blank line for them rather than their content, and they are skipped in the display module (line 200) when checking for blank lines.

Display Subroutine

The display subroutine (lines 100–390) renders lines bottom-up on the screen. Starting from line L3 and screen row Z2=16, it walks backward through D$(), printing each non-blank line. When L2<29 (short records), it also prints the line number at column 0 for reference. Any screen rows not filled by document content are cleared by printing S$ (the blank string) at those rows in the cleanup loop at lines 300–320.

Printer Output

The LPrint routine (lines 1300–1395) first prints a header consisting of the save name X$, a separator, and the title T$. Document lines are printed with TAB VAL "30"-L2, centering or indenting the text based on the chosen record length. Empty lines (D$(Z)=S$(TO L2)) are silently skipped (line 1362), while lines starting with “/” produce a blank printed line (line 1380).

Save Mechanism

The Save option (lines 1400–1440) uses SAVE X$ to save the entire program — including the populated D$() array — back to tape. The save name X$ can be updated at save time, defaulting to the previously stored name. This means a saved file reloads as a complete self-contained document.

Anomalies and Notes

  • Line 1130 checks INKEY$<>CHR$ VAL "118"; character 118 is the ENTER key token on this system — effectively waiting for ENTER to proceed past the caution screen.
  • Line 1262 is referenced in the tab-entry input validation (line 1272 GOTO VAL "1262") but the displayed listing shows the loop body starting at 1265; line 1262 does not appear explicitly, meaning the GOTO re-enters the FOR loop mid-body, re-prompting for the same tab without re-printing the label — a deliberate tight retry loop.
  • The initialization cold-start path (lines 1450–1490) calls the init subroutine, sets L1 and L2 to zero (skipping any caution prompt at line 1110), and falls directly into the Save option, prompting the user for a program name before any file is set up — likely intentional to establish the tape name early.

Content

Appears On

Related Products

Easily create documents like letters, document spreadsheets and other programs with full insert, delete, move, and print text. Completely menu-driven,...

Related Articles

Related Content

Image Gallery

VU-Write

Source Code

   1 REM E£RND7 FAST )5 ;SGN ' ? ' GOSUB %KTAN 5~~ 67RND6~~RNDTAN 
  10 REM DOCUMENT PROCESSOR
  11 REM VU-WRITE / 2C.01 / 3069 
  15 REM PROPRIETARY TO:
  16 REM MANAGEMENT SERVICES CO. 
 100 REM ** DISPLAY **
 150 LET Z1=L3
 160 LET Z2=VAL "16"
 170 LET Z3=A
 180 IF L2<VAL "29" THEN LET Z3=L+B
 200 IF D$(Z1)=S$( TO L2) AND Z1<>L3 THEN GOTO 250
 210 IF L2<29 THEN PRINT AT Z2,0;Z1;"    ";
 220 PRINT AT Z2,Z3;D$(Z1);
 230 LET Z2=Z2-1
 250 IF Z2<0 OR F=1 THEN RETURN 
 260 LET Z1=Z1-1
 290 IF Z1 THEN GOTO 200
 300 FOR Z=Z2 TO 0 STEP -1
 310 PRINT AT Z,0;S$;
 320 NEXT Z
 390 RETURN 
 500 REM ** TEXT **
 550 CLS 
 560 IF NOT L3 THEN GOTO VAL "600"
 570 LET F=A
 575 GOSUB VAL "100"
 600 PRINT AT VAL "18",A;R$;"--LINE";S$( TO VAL "28");"ENTER LINE NO.: (1<=";L1;",M,E)"," ";R$( TO L);S$( TO VAL "31"-L)
 605 LET F=A
 610 INPUT Q$
 615 IF Q$="" THEN GOTO VAL "650"
 620 IF Q$(B)<>"M" THEN GOTO VAL "625"
 621 LET F=VAL "2"
 622 LET Q$=Q$(VAL "2" TO )
 625 IF NOT LEN Q$ OR LEN Q$>L THEN GOTO VAL "610"
 626 IF Q$(B)="E" THEN GOTO VAL "1220"
 630 LET Q=A
 632 FOR Z=B TO LEN Q$
 634 IF Q$(Z)<"0" OR Q$(Z)>"9" THEN LET Q=B
 636 NEXT Z
 638 IF NOT Q THEN IF VAL Q$>=B AND VAL Q$<=L1 THEN GOTO VAL "640"
 639 GOTO VAL "610"
 640 LET L3=VAL Q$
 645 GOTO VAL "680"
 650 IF L3=L1 THEN GOTO VAL "610"
 655 IF NOT F THEN LET F=B
 660 IF L3 AND F<VAL "3" THEN IF D$(L3)<>S$( TO L2) THEN GOTO VAL "670"
 665 GOTO VAL "675"
 670 RAND USR VAL "16514"
 675 LET L3=L3+B
 680 IF F=VAL "3" THEN GOTO VAL "800"
 685 GOSUB VAL "100"
 690 PRINT AT VAL "19",VAL "5";L3
 692 IF F<VAL "2" THEN GOTO VAL "700"
 694 PRINT AT VAL "19",A;"MOVE"," TO ";
 696 LET F=VAL "3"
 698 LET L4=L3
 699 GOTO VAL "610"
 700 PRINT TAB VAL "10";":";S$( TO VAL "20"),TAB B;R$( TO L2);S$( TO VAL "30"-L2);AT VAL "21",T(B);"+";AT VAL "21",T(B+B);"+"
 720 SLOW 
 730 INPUT Q$
 740 FAST 
 750 IF Q$="" THEN GOTO VAL "600"
 760 LET D$(L3)=Q$
 770 LET F=B
 780 GOSUB VAL "100"
 790 GOTO VAL "600"
 800 LET Z1=B
 810 LET Z2=L1-L4+B
 820 IF L3>L4 THEN LET Z2=L1-L3+B
 830 PRINT L3,TAB VAL "6";"QTY TO MOVE: (0<=";Z2;")";S$;AT VAL "21",A;R$( TO L)
 840 INPUT Q
 842 IF Q<A OR Q>Z2 THEN GOTO VAL "840"
 844 IF NOT Q THEN GOTO VAL "600"
 850 LET Q=Q-B
 860 IF L3<=L4 THEN GOTO VAL "870"
 862 LET L3=L3+Q
 864 LET L4=L4+Q
 866 LET Q=-Q
 868 LET Z1=-Z1
 870 FOR Z=A TO Q STEP Z1
 875 LET D$(L3+Z)=D$(L4+Z)
 880 NEXT Z
 890 IF L3<=L4 THEN LET L3=L3+Q
 895 GOTO VAL "780"
 900 REM ** TITLE **
 910 CLS 
 920 PRINT "OPTION: TITLE";AT VAL "11",A;"TITLE:  ";T$;AT VAL "21",B;R$( TO 24)
 930 INPUT Q$
 940 IF Q$="" THEN GOTO VAL "1220"
 950 LET T$=Q$
 990 GOTO VAL "1220"
 1000 REM ** MENU **
 1010 RAND USR VAL "16530"
 1015 FAST 
 1020 CLS 
 1025 PRINT TAB VAL "11";"""VU-WRITE""",TAB VAL "7";"DOCUMENT PROCESSOR",TAB B;R$,,TAB VAL "11";"1. FILE",,TAB VAL "11";"2. WRITE",,TAB VAL "11";"3. LPRINT ",,TAB VAL "11";"4. SAVE ",,,,TAB VAL "6";"ENTER OPTION: (1<=4)",,TAB B;R$,TAB VAL "10";"** STATUS **",,," SAVED: ";X$," TITLE: ";T$;" LINES: ";L1,"LENGTH: ";L2," TAB 1: ";T(B)," TAB 2: ";T(B+B)
 1030 PAUSE P
 1050 LET Q$=INKEY$
 1060 IF Q$<"1" OR Q$>"4" THEN GOTO VAL "1030"
 1080 CLS 
 1090 GOTO VAL Q$*VAL "100"+C
 1100 REM ** FILE **
 1110 IF NOT L1 THEN GOTO VAL "1140"
 1115 PRINT "OPTION: SET FILE";AT VAL "8",VAL "6";"%C%A%U%T%I%O%N:  THIS OPTION",,TAB VAL "3";"WILL CLEAR AND REDEFINE THE",,TAB VAL "5";"TEXT FILE.  PRESS %E%N%T%E%R",,TAB VAL "10";" TO CONTINUE."
 1120 PAUSE VAL "60"
 1130 IF INKEY$<>CHR$ VAL "118" THEN GOTO C
 1140 CLS 
 1145 PRINT "OPTION: SET FILE";AT VAL "11",VAL "11";"(1<=30)";AT VAL "10",VAL "4";"ENTER RECORD LENGTH: ";
 1150 INPUT Q
 1152 IF Q<B OR Q>VAL "30" THEN GOTO VAL "1150"
 1154 PRINT Q
 1156 POKE VAL "16507",Q
 1160 PRINT AT VAL "21",VAL "7";"CORRECT? (%END-Y-N)"
 1162 PAUSE P
 1164 IF INKEY$="Y" THEN GOTO VAL "1170"
 1166 IF INKEY$="N" THEN GOTO VAL "1140"
 1168 GOTO C
 1170 CLEAR 
 1171 GOSUB VAL "1180"
 1172 LET L3=A
 1173 LET L2=PEEK VAL "16507"
 1174 LET L1=INT (VAL "11144"/L2)
 1175 LET L=LEN STR$ L1
 1176 DIM D$(L1,L2)
 1179 GOTO C
 1180 LET A=VAL "0"
 1181 LET B=VAL "1"
 1182 LET C=VAL "1000"
 1183 LET P=VAL "40000"
 1184 LET R$="------------------------------"
 1190 DIM S$(VAL "32")
 1191 DIM T(VAL "2")
 1192 DIM T$(VAL "24")
 1193 DIM X$(VAL "8")
 1199 RETURN 
 1200 REM ** TAB **
 1210 IF NOT L1 THEN GOTO C
 1220 CLS 
 1225 PRINT TAB VAL "11";"""VU-WRITE""",TAB VAL "7";"DOCUMENT PROCESSOR",TAB B;R$,,TAB VAL "12";"1. TABS",,TAB VAL "12";"2. TITLE",,TAB VAL "12";"3. TEXT",,,,TAB VAL "6";"ENTER OPTION: (1<=3)",,TAB B;R$
 1230 PAUSE P
 1240 IF INKEY$="3" THEN GOTO VAL "500"
 1242 IF INKEY$="2" THEN GOTO VAL "900"
 1244 IF INKEY$<>"1" THEN GOTO C
 1250 CLS 
 1255 PRINT "OPTION: SET TABS";AT VAL "10",VAL "2";"ENTER TAB POSITIONS (0<=";L2;")",,TAB VAL "5";"TAB 1:"," TAB 2:"
 1260 FOR Z=B TO B+B
 1265 PRINT AT VAL "12",Z*VAL "12";"%<"
 1270 INPUT T(Z)
 1272 IF T(Z)<A OR T(Z)>L2 THEN GOTO VAL "1262"
 1274 PRINT AT VAL "12",Z*VAL "12";T(Z)
 1278 NEXT Z
 1280 PRINT AT VAL "21",VAL "9";"CORRECT? (Y-N)"
 1285 PAUSE P
 1290 IF INKEY$<>"N" THEN GOTO VAL "1220"
 1295 GOTO VAL "1250"
 1300 REM ** LPRINT **
 1310 IF NOT L1 THEN GOTO C
 1320 PRINT "OPTION: LPRINT ";AT VAL "11",VAL "7";"OK TO PRINT? (N-Y)"
 1330 PAUSE P
 1340 IF INKEY$<>"Y" THEN GOTO C
 1350 LPRINT X$,S$,T$,,,,,
 1360 FOR Z=B TO L1
 1362 IF D$(Z)=S$( TO L2) THEN GOTO VAL "1390"
 1364 IF D$(Z,B)="/" THEN GOTO VAL "1380"
 1370 LPRINT TAB VAL "30"-L2;D$(Z)
 1375 GOTO VAL "1390"
 1380 LPRINT 
 1390 NEXT Z
 1395 GOTO C
 1400 REM ** SAVE **
 1410 PRINT "OPTION: SAVE ";AT VAL "6",B;"ENTER PGM NAME: (";X$;",END)"
 1412 INPUT Q$
 1414 IF Q$="END" THEN GOTO C
 1416 IF Q$<>"" THEN LET X$=Q$
 1420 PRINT AT VAL "6",A;S$,TAB VAL "7";"PGM NAME: ";X$,,,,TAB VAL "5";"PRESS %E%N%T%E%R WHEN READY",,TAB VAL "8";" OR %END TO ABORT."
 1422 PAUSE P
 1424 IF INKEY$<>CHR$ VAL "118" THEN GOTO C
 1430 SAVE X$
 1440 GOTO C
 1450 REM ** INIT **
 1460 GOSUB VAL "1180"
 1470 LET L1=A
 1480 LET L2=A
 1490 GOTO VAL "1400"

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

People

No people associated with this content.

Scroll to Top