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



Leave a Reply