Word Processors in BASIC, Part 2

Nibblewriter

Found in November 1988 issue of Nibble magazine.

Archive.org link here.

The project was alerted to the existence of a few text editors and word processors in Nibble magazine by someone on matrix.

What we found was a great wealth of BASIC programs for the Apple II computer. We uncovered several particularly interesting BASIC word processors. Two that are of particular interest are Quickwriter and this one, Nibblewriter.

diskM8 File Dump

Please find an ASCII conversion of the BASIC dump obtained using the following commands:

$ diskm8 -ingest /path/to/your/disk/images
$ diskm8 -search "nibblewriter"
$ diskm8 -with-disk "your_disk_image.do" -file-extract "NIBBLEWRITER.BAS"

Code Listing

10  REM *************************
20  REM *     NIBBLEWRITER      *
21  REM *     ------------      *
30  REM *  BY ROBERT T. YUILLE  *
40  REM *  COPYRIGHT (C) 1988   *
50  REM *  BY MICROSPARC, INC.  *
60  REM *  CONCORD, MA  01742   *
70  REM *************************
80  HOME : PRINT  CHR$ (21)
90  REM   SET HIMEM
100 PRODOS =  PEEK (48896) = 76: IF  NOT PRODOS THEN  HIMEM: 24832: GOTO 170
110  REM   FOR PRODOS
120  POKE 768,32: POKE 769,248: POKE 770,190
130  POKE 771,169: POKE 772,53: POKE 773,32
140  POKE 774,245: POKE 775,190: POKE 776,96
150  CALL 768
160  REM   INITIALIZATION
170 LM$ = "1.0":RM$ = "1.0":TM$ = "1.0":BM$ = "1.0"
180 LM = 8:RM = 66:TM = 6:BM = 60
190  POKE 30,0: POKE 233,0: REM  NEWF & PRNTF
200 D$ =  CHR$ (4):B$ =  CHR$ (7):E$ =  CHR$ (27):R$ =  CHR$ (13): IF  NOT PRODOS THEN D$ =  CHR$ (13) +  CHR$ (4)
210 M1$ = "MARGIN VALUE EXCEEDS MAXIMUM"
220 M2$ = "MARGIN VALUE IS LESS THAN MINIMUM"
230 M3$ = "CHAR CANNOT BE USED IN THIS INPUT"
240 FL$ = "WP.40.O"
250 FADDR = 26124: REM   FILENAME ($660C)
260 ST = 6:DR = 1: REM  DEFAULT SLOT AND DRIVE
270  PRINT D$"PR#0"
280 :
290  REM   LOAD WP OBJECT FILE
300 :
310 LK = 1: ONERR  GOTO 3130
320  PRINT D$"BLOAD NW.BIN"
330  POKE 216,0: REM  RESET ERROR FLAG
340 :
350  REM    INITIALIZE & READ MENU DATA
360 :
370  READ MITEMS: DIM MENU$(9): FOR J = 0 TO MITEMS: READ MENU$(J): NEXT 
380  DIM X$(1):X$(0) = "   ":X$(1) = "-->"
390 :
400  REM   MAIN MENU
410 :
420  TEXT : HOME : GOSUB 3040: POKE 216,0: ONERR  GOTO 3130
430 PX = 38:SX = 4:SE = SE + (SE = 0):MX = MITEMS: GOSUB 2960: IF Z = 20 THEN  PRINT B$: GOTO 420
440  ON SE GOTO 480,560,670,890,940,990,1480,2750,1740
450 :
460  REM   START NEW DOCUMENT
470 :
480  IF  PEEK (30) = 2 THEN  GOSUB 2660: IF ESCF = 1 THEN 420
490  GOSUB 1830: IF ESCF = 1 THEN 420
500  POKE 30,0
510  CALL 26112: REM   ENTRY ($6600)
520  GOTO 420
530 :
540  REM   LOAD NEW DOCUMENT
550 :
560  IF  PEEK (30) = 2 THEN  GOSUB 2660: IF ESCF = 1 THEN 420
570  GOSUB 1830: IF ESCF = 1 THEN 420
580  HTAB 1: VTAB 20: PRINT "LOADING "FL$
590 LK = 3: ONERR  GOTO 3130
600  PRINT D$"BLOAD "FL$",S"ST",D"DR
610  POKE 216,0
620  POKE 30,1: REM  SET NEWF FOR LOADED FILE
630  GOTO 510
640 :
650  REM   SAVE CURRENT DOCUMENT
660 :
670  HOME : IF  PEEK (30) <  > 2 THEN  VTAB 5: PRINT "THERE IS NO CURRENT DOCUMENT": VTAB 10: PRINT "PRESS RETURN FOR MAIN MENU: ";: GET A$: GOTO 420
680 EF =  PEEK (252) + 256 *  PEEK (253): REM  EFL($FC) & EFH($FD)
690 LN = EF - 28672
700  ONERR  GOTO 800
710  PRINT D$"VERIFY "FL$",S"ST",D"DR
720  HOME : VTAB 5: PRINT "FILE: '"FL$"' ALREADY EXISTS"
730  VTAB 13: PRINT "PRESS 'Y' TO REPLACE EXISTING FILE": PRINT : PRINT "PRESS 'N' TO RENAME FILE": VTAB 10: PRINT "DO YOU WANT TO REPLACE": PRINT "THE EXISTING FILE? (Y/N) ";
740  GET A$
750  IF A$ = "N" OR A$ = "n" THEN  POKE 216,0: GOTO 840
760  IF A$ <  > "Y" AND A$ <  > "y" THEN  GOTO 740
770  HTAB 1: VTAB 20: PRINT "DELETING "FL$
780 LK = 2: ONERR  GOTO 3130
790  PRINT D$"DELETE "FL$",S"ST",D"DR
800  HTAB 1: VTAB 21: PRINT "SAVING "FL$
810 LK = 2: ONERR  GOTO 3130
820  PRINT D$"BSAVE "FL$",A$7000,L"LN",S"ST",D"DR
830  POKE 216,0: GOTO 420
840  GOSUB 1830: IF ESCF = 1 THEN 420
850  GOTO 670
860 :
870  REM   RENAME CURRENT DOCUMENT
880 :
890  GOSUB 1830: IF ESCF = 1 THEN 420
900  GOTO 510
910 :
920  REM   CONTINUE WITH CURRENT DOCUMENT
930 :
940  IF  PEEK (30) <  > 2 THEN 670
950  GOTO 510
960 :
970  REM   PRINTER ROUTINE
980 :
990  IF  PEEK (30) <  > 2 THEN 670
1000  HOME : VTAB 2: PRINT "MARGIN VALUES ARE AS FOLLOWS:": PRINT : PRINT "LM= "LM$"  RM= "RM$"  TM= "TM$"  BM= "BM$
1010  VTAB 10: PRINT "DO YOU WANT TO CHANGE MARGINS (Y/N)? ";
1020  GET A$
1030  IF A$ = "Y" OR A$ = "y" THEN 1060
1040  IF A$ <  > "N" AND A$ <  > "n" THEN 1020
1050  GOTO 1370
1060 M$ = "LM":MA$ = "7.0":MI$ = "0.5"
1070  GOSUB 2330: IF ESCF = 1 THEN 420
1080 N =  VAL (N$)
1090  IF N > 7 THEN MSG$ = M1$: GOSUB 2250: GOTO 1060
1100  IF N < .5 THEN MSG$ = M2$: GOSUB 2250: GOTO 1060
1110 LM = N * 10 - 2
1120 LM$ = N$
1130 M$ = "RM":MA$ = "7.0":MI$ = "0.5"
1140  GOSUB 2330: IF ESCF = 1 THEN 420
1150 N =  VAL (N$)
1160  IF N > 7 THEN MSG$ = M1$: GOSUB 2250: GOTO 1130
1170  IF N < .5 THEN MSG$ = M2$: GOSUB 2250: GOTO 1130
1180 RM = 80 - (N * 10 - 4) - LM
1190  IF RM <  = 0 THEN MSG$ = "LEFT MARGIN EXCEEDS RIGHT MARGIN": GOSUB 2250:RM = 66: GOTO 990
1200 RM$ = N$
1210 M$ = "TM":MA$ = "8.0":MI$ = "0.2"
1220  GOSUB 2330: IF ESCF = 1 THEN 420
1230 N =  VAL (N$)
1240  IF N > 8 THEN MSG$ = M1$: GOSUB 2250: GOTO 1210
1250  IF N < .2 THEN MSG$ = M2$: GOSUB 2250: GOTO 1210
1260 TM =  INT (6 * N + .5)
1270 TM$ = N$
1280 M$ = "BM":MA$ = "8.0":MI$ = "0.2"
1290  GOSUB 2330: IF ESCF = 1 THEN 420
1300 N =  VAL (N$)
1310  IF N > 8 THEN MSG$ = M1$: GOSUB 2250: GOTO 1280
1320  IF N < .2 THEN MSG$ = M2$: GOSUB 2250: GOTO 1280
1330 BM = 66 -  INT (6 * N + .5)
1340  IF TM >  = BM THEN MSG$ = "TOP MARGIN EXCEEDS BOTTOM MARGIN": GOSUB 2250: GOTO 1210
1350 BM$ = N$
1360  GOTO 990
1370  POKE 26,TM: POKE 27,BM: POKE 28,LM: POKE 29,RM
1380  HOME : VTAB 2: PRINT "BE SURE YOUR PRINTER IS READY": VTAB 10: PRINT "PRESS RETURN TO CONTINUE: ";: GET A$
1390  HOME : VTAB 15: PRINT "PRESS ESCAPE TO CANCEL PRINTING."
1400  VTAB 10: PRINT "PRESS SPACE BAR TO CONTINUE: "
1410  PRINT D$"PR#1"
1420  PRINT  CHR$ (9)"80N": POKE 233,1: CALL 26112: POKE 233,0
1430  PRINT D$"PR#0"
1440  GOTO 420
1450 :
1460  REM   HELP SCREEN
1470 :
1480  TEXT : HOME 
1490  NORMAL : PRINT "             HELP SCREEN": REM  13 SPACES
1500  PRINT : PRINT 
1510  PRINT "<ARROWS> - MOVE CURSOR"
1520  PRINT 
1530  PRINT "<ESCAPE> - RETURN TO MAIN MENU"
1540  PRINT 
1550  PRINT "<DELETE> - DELETE CHAR LEFT OF CURSOR"
1560  PRINT 
1570  PRINT "<CTRL>-D - DELETE CHAR UNDER CURSOR"
1580  PRINT 
1590  PRINT "<CTRL>-E - CHANGE INSERT/REPLACE CURSOR"
1600  PRINT 
1610  PRINT "<CTRL>-Y - CLEAR FROM CURSOR TO EOL"
1620  PRINT 
1630  PRINT "<CTRL>-Z - SHOW CR'S AS INV ASTERISK"
1640  PRINT 
1650  PRINT "   <TAB> - MOVE CURSOR TO NEXT TAB POS"
1660  PRINT 
1670  PRINT "<CTRL>-F - MOVE TO FIRST LINE"
1680  PRINT "<CTRL>-C - MOVE TO CENTER LINE"
1690  PRINT "<CTRL>-L - MOVE TO LAST LINE";
1700  HTAB 1: VTAB 24: PRINT "PRESS RETURN TO CONTINUE: ";: GET A$: GOTO 420
1710 :
1720  REM   QUIT
1730 :
1740  HOME : VTAB 10: PRINT "DO YOU REALLY WANT TO QUIT (Y/N)? ";
1750  GET A$
1760  IF A$ = "Y" OR A$ = "y" THEN 1790
1770  IF A$ = "N" OR A$ = "n" THEN 420
1780  GOTO 1750
1790  HOME : END 
1800 :
1810  REM   FILENAME INPUT ROUTINE
1820 :
1830  HOME :N$ = "":ESCF = 0
1840  VTAB 2: PRINT "ENTER FILENAME FOR DOCUMENT": PRINT : PRINT 
1850  PRINT "PRESS '?' TO CATALOG DISK": PRINT 
1860  PRINT "ESCAPE ON 1ST CHAR RETURNS TO MAIN MENU": PRINT 
1870  PRINT "ESCAPE ON ANY OTHER CHARACTER": PRINT " CANCELS INPUT AND STARTS OVER": PRINT 
1880  PRINT "RETURN ACCEPTS INPUT"
1890  HTAB 1: VTAB 15: PRINT "FILENAME: ";
1900  GET C$
1910  IF C$ = E$ THEN ESCF = 1: RETURN 
1920  IF C$ = "?" THEN  PRINT D$ LEFT$ ("CATALOG",7 - 4 * PRODOS)",S"ST",D"DR: HTAB 1: VTAB 24: PRINT "PRESS RETURN TO CONTINUE: ";: GET A$: GOTO 1830
1930 AN =  ASC (C$)
1940  IF AN > 96 AND AN < 123 THEN AN = AN - 32
1950  IF AN < 65 OR AN > 90 THEN MSG$ = "FIRST POSITION MUST BE A LETTER": GOSUB 2250: GOTO 1830
1960  PRINT  CHR$ (AN)
1970 N$ =  CHR$ (AN)
1980  FOR K = 1 TO 15
1990  HTAB 1: VTAB 18: CALL  - 958
2000  VTAB 15: HTAB (11 + K)
2010  GET C$
2020  IF C$ = E$ THEN K = 15: NEXT : GOTO 1830
2030  IF C$ =  CHR$ (8) AND K = 1 THEN K = 15: NEXT : GOTO 1830
2040  IF C$ =  CHR$ (8) THEN K = K - 1: HTAB (11 + K): PRINT " ":N$ =  LEFT$ (N$,K): GOTO 2000
2050  IF C$ = R$ THEN LC = K:K = 15: GOTO 2110
2060 AN =  ASC (C$)
2070  IF AN > 96 AND AN < 123 THEN AN = AN - 32
2080  IF (AN < 65 OR AN > 90) AND (AN < 48 OR AN > 57) AND AN <  > 46 THEN MSG$ = "CHARACTER CANNOT BE USED IN FILENAME": GOSUB 2250: GOTO 1990
2090  PRINT  CHR$ (AN)
2100 N$ = N$ +  CHR$ (AN)
2110  NEXT 
2120  IF C$ <  > R$ THEN MSG$ = "FILENAME TOO LONG, LIMIT - 15 CHARACTERS": GOSUB 2250: GOTO 1830
2130 FL$ = N$
2140  FOR I = 0 TO 15
2150  POKE FADDR + I,0
2160  NEXT 
2170  FOR K = 1 TO  LEN (N$)
2180  POKE FADDR - 1 + K, ASC ( MID$ (N$,K,1)) + 128
2190  NEXT 
2200  POKE FADDR + LC,0
2210  RETURN 
2220 :
2230  REM   ERROR MESSAGES
2240 :
2250  PRINT B$
2260  HTAB 1: VTAB 18
2270  PRINT MSG$: PRINT : PRINT 
2280  PRINT "PRESS RETURN AND TRY AGAIN: ";: POKE  - 16368,0: GET AA$
2290  RETURN 
2300 :
2310  REM   PRINTER MARGIN ROUTINE
2320 :
2330  HOME :N$ = "":ESCF = 0
2340  VTAB 2: PRINT "ENTER VALUE FOR "M$: PRINT "MAXIMUM "MA$" - MINIMUM "MI$: PRINT 
2350  PRINT "ESCAPE ON 1ST CHAR RETURNS TO MAIN MENU": PRINT 
2360  PRINT "ESCAPE ON ANY OTHER CHARACTER": PRINT " CANCELS INPUT AND STARTS OVER": PRINT 
2370  PRINT "RETURN ACCEPTS INPUT"
2380  PRINT : PRINT "RETURN ON 1ST CHAR ACCEPTS DEFAULT (1.0)"
2390  HTAB 1: VTAB 15: PRINT M$":  1.0"
2400  HTAB 5: VTAB 15
2410  GET C$
2420  IF C$ = E$ THEN ESCF = 1: RETURN 
2430  IF C$ = R$ THEN N$ = "1.0": RETURN 
2440 AN =  ASC (C$)
2450  IF AN < 48 OR AN > 57 THEN MSG$ = M3$: GOSUB 2250: GOTO 2330
2460  PRINT C$;: CALL  - 868
2470 N$ = C$
2480  FOR K = 1 TO 3
2490  HTAB 1: VTAB 18: CALL  - 958
2500  VTAB 15: HTAB (5 + K)
2510  GET C$
2520  IF C$ = E$ THEN K = 3: NEXT : GOTO 2330
2530  IF C$ =  CHR$ (8) AND K = 1 THEN K = 3: NEXT : GOTO 2330
2540  IF C$ =  CHR$ (8) THEN K = K - 1: HTAB (5 + K): PRINT " ":N$ =  LEFT$ (N$,K): GOTO 2500
2550  IF C$ = R$ THEN K = 3: GOTO 2600
2560 AN =  ASC (C$)
2570  IF (AN < 48 OR AN > 57) AND AN <  > 46 THEN MSG$ = M3$: GOSUB 2250: GOTO 2490
2580  PRINT C$
2590 N$ = N$ + C$
2600  NEXT 
2610  IF C$ <  > R$ THEN MSG$ = "INPUT TOO LONG, LIMIT - 3 CHARACTERS": GOSUB 2250: GOTO 2330
2620  RETURN 
2630 :
2640  REM  ERASE CURRENT DOCUMENT?
2650 :
2660  HOME :ESCF = 0: VTAB 8: PRINT "YOU ARE ABOUT TO ERASE": PRINT "THE CURRENT DOCUMENT."
2670  VTAB 12: PRINT "DO YOU REALLY WANT TO DO THIS? (Y/N) ";
2680  GET A$
2690  IF A$ = "N" OR A$ = "n" THEN ESCF = 1: RETURN 
2700  IF A$ <  > "Y" AND A$ <  > "y" THEN 2680
2710  RETURN 
2720 :
2730  REM  SELECT SLOT AND DRIVE
2740 :
2750  HOME : VTAB 1: PRINT "WHICH SLOT DO YOU WANT TO USE? (2-7) ";
2760  GET A$
2770  IF A$ =  > "2" AND A$ <  =  CHR$ (54 + PRODOS) THEN  PRINT A$:ST =  VAL (A$): GOTO 2790
2780  GOTO 2760
2790  VTAB 5: PRINT "WHICH DISK DRIVE": PRINT "DO YOU WANT TO USE? (1-2) ";
2800  GET A$
2810  IF A$ = "1" OR A$ = "2" THEN  PRINT A$:DR =  VAL (A$): GOTO 2830
2820  GOTO 2800
2830  POKE 216,0: ONERR  GOTO 2870: IF PRODOS THEN  PRINT D$"PREFIX,S";ST;",D";DR:
2840  IF PRODOS THEN  GOTO 420
2850  PRINT D$"VERIFY JUNK,S";ST;",D";DR
2860  GOTO 420
2870  POKE 216,0:EN =  PEEK (222):EL =  PEEK (218) + 256 *  PEEK (219): IF EL = 2850 AND EN = 6 THEN 420
2880  VTAB 23: PRINT "DISK ERROR": PRINT "PRESS RETURN TO CONTINUE ";: POKE  - 16368,0: GET AA$: GOTO 420
2890 :
2900  REM  DATA FOR MAIN MENU
2910 :
2920  DATA  9,MAIN MENU,START NEW DOCUMENT,LOAD DOCUMENT,SAVE DOCUMENT,RENAME DOCUMENT,CONTINUE WITH CURRENT DOCUMENT,PRINT DOCUMENT,HELP,SET SLOT/DRIVE,QUIT
2930 :
2940  REM   MENU HANDLER
2950 :
2960 SL = SE
2970 N = SL:OS = SL: GOSUB 3000:Z = 0: VTAB 24: HTAB PX: CALL  - 868: POKE  - 16368,0
2980  VTAB 24: HTAB PX: PRINT SL;: WAIT  - 16384,128:Z =  PEEK ( - 16384) - 128: IF Z >  = 49 AND Z <  = MX + 48 THEN SL = Z - 48:N = OS: GOSUB 3000: GOTO 2970
2990 Z = (Z = 21 OR Z = 10) - (Z = 8 OR Z = 11) + 10 * (Z = 13) + 20 * (Z = 27): ON  NOT Z GOTO 2980:SL = SL + Z * (Z < 10):SL = SL - MX * (SL > MX) + MX * (SL < 1):N = OS: GOSUB 3000: ON Z < 10 GOTO 2970:SE = SL: POKE  - 16368,0: RETURN 
3000  VTAB 3 + 2 * N: HTAB SX: PRINT X$(SL = OS);: RETURN 
3010 :
3020  REM   PRINT A MENU
3030 :
3040  HOME :TL$ = MENU$(0): VTAB 1: PRINT "NIBBLEWRITER   (C)1988   MICROSPARC,INC.": VTAB 2: FOR I = 1 TO 40: PRINT "-";: NEXT 
3050  VTAB 3: HTAB  INT ((40 -  LEN (TL$)) / 2)
3060  PRINT TL$
3070  FOR I = 1 TO MITEMS: VTAB 3 + 2 * I: HTAB 8: PRINT I". "MENU$(I): NEXT 
3080  VTAB 24: HTAB 1: PRINT "USE ARROWS/NUMBERS & PRESS RETURN: ";
3090  RETURN 
3100 :
3110  REM  DISK ERRORS
3120 :
3130  HOME : VTAB 10
3140  POKE 216,0
3150  IF  PEEK (222) = 6 OR  PEEK (222) = 7 THEN MSG$ = "FILE (" + FL$ + ")" +  CHR$ (13) + "IS NOT ON THIS DISK.": ON (( PEEK (218) + 256 *  PEEK (219) = 320) + 1) GOTO 3210,3230
3160  IF  PEEK (222) = 13 THEN MSG$ = "FILE (" + FL$ + ")" +  CHR$ (13) + "IS NOT A BINARY FILE.": GOTO 3210
3170  IF  PEEK (222) = 9 OR  PEEK (222) = 17 THEN MSG$ = "DISK OR DIRECTORY IS FULL.": GOTO 3210
3180  IF  PEEK (222) = 10 THEN MSG$ = "EXISTING FILE (" + FL$ + ")" +  CHR$ (13) + "IS LOCKED.": GOTO 3210
3190  PRINT "SYSTEM ERROR #"; PEEK (222);" HAS OCCURRED"
3200  PRINT "AT LINE #"; PEEK (218) +  PEEK (219) * 256:MSG$ = ""
3210  GOSUB 2250
3220  GOTO 420
3230  VTAB 24: PRINT "BINARY FILE NOT FOUND": END

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *