10 WIDTH 128
20 DIM LN(758)  'temporary storage during character menu
30 CUR$=CHR$(27)+"=" 'cursor position command
40 HOME$=CHR$(0)+CHR$(32)  'home cursor using CUR$
50 B$=CHR$(27)+"("  'BRIGHT command for character menu
60 G0$=CHR$(27)+"G"  'end graphics mode command
70 G1$=CHR$(27)+"g"  'start graphics mode command
80 D$=CHR$(27)+")"  'DIM command for character menu
90 LIMIT1%=100:LIMIT2%=80  ' if LIMIT2<LIMIT1 then the cursor blinks
100 LIMIT1F%=40:LIMIT2F%=30  'different cursor speed for move w/o mod.
110 DEF FN PC$(ROW%,COL%)=CHR$(27)+CHR$(61)+CHR$(ROW%+31)+CHR$(COL%+31)
120 REM  Print intro heading
130 PRINT CHR$(26):GOSUB 1630  'print border
140 PRINT FN PC$(5,12);"OSBORNE 1 SCREEN PAINTER"
150 PRINT FN PC$(7,22);"by"
160 PRINT FN PC$(9,8);"John Conway (Boston Osborne Group)"
170 PRINT FN PC$(10,5);"Jay Hanlon (Chicago's First Osborne Group)"
180 PRINT FN PC$(12,5);"Extensive modifications by Ben Jones (CFOG)"
190 PRINT FN PC$(20,5); D$;:INPUT "Hit return to continue";RER$
200 REM  Input name of old file to be modified
210 PRINT B$
220 PRINT CHR$(26):SCR=61440!
230 PRINT "DO YOU WANT TO MODIFY AN EXISTING SUBROUTINE?"
240 INPUT "  (Subroutine must start at 10000.)  ";A1$
250 A$=LEFT$(A1$,1):IF A$="N" OR A$="n" OR A$="" THEN 330
260 IF A$<>"Y" AND A$<>"y" THEN PRINT "Try again.":GOTO 230
270 PRINT:INPUT "Enter name of old file (USE CAPS):  ",INFILE$
280 IF INFILE$="" THEN PRINT "Try again.":GOTO 270
290 A$=LEFT$(INFILE$,2)
300 IF A$<>"A:" AND A$<>"B:" THEN PRINT:INPUT "WHICH DRIVE? ",DRIVE$:IF DRIVE$="A" OR DRIVE$="B" THEN INFILE$=DRIVE$+":"+INFILE$
310 ELSE 300
320 OPEN "I",#1,INFILE$:INPUT #1,A:CLOSE #1:IF A<>10000 THEN PRINT "File does not begin at 10000":END
330 PRINT:PRINT:PRINT:INPUT "DO YOU WANT TO SAVE RESULTS (Y/N)?  ",YN$
340 A$=LEFT$(YN$,1):IF A$="N" OR A$="n" OR A$="" THEN 450
350 IF A$<>"Y" AND A$<>"y" THEN PRINT "Try again.":GOTO 330
360 GOSUB 1690  ' get name of new file
370 PRINT:PRINT:PRINT "What size screen do you want to save?"
380 PRINT "     24 X 52  -- A"
390 PRINT "     32 X 128 -- B  (default)"
400 INPUT "A OR B (A stores faster): ",SIZE$
410 IF SIZE$="a" OR SIZE$="b" THEN SIZE$=CHR$(ASC(SIZE$)-32)
420 IF SIZE$<>"A" AND SIZE$<>"B" AND SIZE$<>"" THEN 400
430 IF SIZE$="A" THEN LINES=23:COLS=51:ELSE LINES=31:COLS=127
440 REM print menu of commands
450 PRINT CHR$(26);
460 PRINT FN PC$(1,3);"^A toggles cursor underlining"
470 PRINT FN PC$(3,3);"^U toggles character underlining"
480 PRINT FN PC$(5,3);"^? toggles movement without modification"
490 PRINT FN PC$(7,3);"^B toggles blinking"
500 PRINT FN PC$(9,3);"TAB permits change of, and prints menu of graphics"
510 PRINT FN PC$(11,3);"ESC ends session"
520 PRINT FN PC$(13,3);"Hitting any character changes to that character"
530 PRINT FN PC$(15,3);"Remember the ASCII characters:"
540 PRINT FN PC$(16,15);"~  =  ^/"
550 PRINT FN PC$(17,15);"{  =  ^,"
560 PRINT FN PC$(18,15);"}  =  ^."
570 PRINT FN PC$(19,15);"`  =  ^="
580 PRINT FN PC$(21,3)"Writing over code number in corner removes it"
590 PRINT FN PC$(24,10);CHR$(27)+")";"Hit RETURN to continue.";
600 INPUT A$
610 PRINT B$;CHR$(26)
620 CH=32:U$="Y":T$="N"  'if U$=Y then underlining
630 C1$="N":C2$="Y":DEL$=""
640 REM  START OF MAIN PROGRAM ******************
650 IF INFILE$="" THEN 700  'get existing subroutine and run it
660 CHAIN MERGE INFILE$,670,ALL
670 REM  >>>>>IMPORTANT<<<<<  CHAIN in previous line MUST refer here
680 PRINT CHR$(&H1A);
690 GOSUB 10000:CH=PEEK(61440!)
700 IF DEL$<>"Y" THEN PRINT FN PC$(23,50);CH 'code # is printed
710 IF SCR=64306! THEN DEL$="Y"  ' code # is written over:  don't print it
720 IF C1$="Y" THEN CH=PEEK(SCR) ' move without altering
730 POKE SCR,CH  'put current char. on screen
740 IF U$="Y" THEN POKE SCR,CH OR 128  'underline at current position
750 REM   START OF DO LOOP FOR BLINKING DURING INPUT
760 FOR TIME%=1 TO LIMIT1%
770 A$=INKEY$
780 IF A$<>"" THEN 820
790 IF TIME%=LIMIT2% THEN POKE SCR,32  'blink current char.
800 NEXT
810 GOTO 730
820 D=ASC(A$)
830 POKE SCR,CH  'put current char. back on screen
840 IF D<13 AND D>7 THEN ON D-7 GOTO 940,960,970,990,1010
850 REM          CURSOR MOVEMENT      L,  CH, D,  U,  R
860 IF D=&H15 THEN CH=CH OR 128:GOTO 730
870 IF D=2 THEN SWAP LIMIT1%,LIMIT2%:SWAP LIMIT1F%,LIMIT2F%:GOTO 720 'Toggle for blinking
880 IF D=127 THEN SWAP C1$,C2$:SWAP LIMIT1%,LIMIT1F%:SWAP LIMIT2%,LIMIT2F%:CH=PEEK(SCR):GOTO 720  'Toggle for cursor movement
890 IF D>&H1F THEN CH=D:GOTO 730  'change to new char.
900 REM    Toggle underlining for cursor
910 IF D=1 THEN SWAP U$,T$:IF U$="Y" THEN POKE SCR,(CH OR 128):GOTO 700
920 IF D=27 THEN GOTO 1030 REM <ESC> TO END PROGRAM
930 GOTO 710
940 IF SCR=61440! THEN GOTO 710  'MOVE LEFT
950 SCR=SCR-1:GOTO 710
960 GOSUB 1790:GOTO 730  ' TAB:  CHANGE CHARACTER
970 IF (SCR+128)>65535! THEN 710  'MOVE DOWN
980 SCR=SCR+128:GOTO 710
990 IF (SCR-128)<61440! THEN 710  'MOVE UP
1000 SCR=SCR-128:GOTO 710
1010 IF SCR = 65535! THEN 710  'MOVE RIGHT
1020 SCR=SCR+1:GOTO 710
1030 A$=LEFT$(YN$,1):IF A$="N" OR A$="n" OR A$="" THEN 1050
1040 GOSUB 1080:PRINT CHR$(7)
1050 INPUT "ANOTHER SESSION?  ",A$:A$=LEFT$(A$,1):IF A$="Y" OR A$="y" THEN 220
1060 END '******************************END OF PROGRAM
1070 REM   Subroutine for saving screen as subroutine on disk
1080 OPEN "O",#1,FILE$
1090 PRINT #1,"10000 REM GRAPHICS SUBROUTINE START"
1100 LN=10010  'first line number in saved subroutine
1110 CH=27
1120 REM  locate horizontal series of char.'s 
1130 FOR J=0 TO LINES
1140 COUNT = 1:CH=27
1150 FOR I=0 TO COLS
1160 SCR=61440!+((J)*128)+I
1170 IF PEEK(SCR)=32 AND CH=32 THEN 1220
1180 INCHAR = PEEK(SCR)
1190 IF INCHAR=CH THEN COUNT=COUNT+1:GOTO 1220
1200 IF COUNT>3 THEN GOSUB 1440  'save series as DO loop
1210 CH=INCHAR:COUNT=1
1220 NEXT I:IF COUNT>3 THEN GOSUB 1440
1230 NEXT J
1240 REM  locate vertical series of char.'s
1250 FOR J=0 TO COLS
1260 COUNT=1:CH=32
1270 FOR I=61440!+J TO 65408!+J STEP 128
1280 IF PEEK(I)=32 AND CH=32 THEN 1330
1290 INCHAR=PEEK(I)
1300 IF INCHAR=CH THEN COUNT=COUNT+1:GOTO 1330
1310 IF COUNT>3 THEN GOSUB 1510  'save series as DO loops 
1320 CH=INCHAR:COUNT =1
1330 NEXT I:IF COUNT>3 THEN GOSUB 1510
1340 NEXT J
1350 REM  Begin GOSUB printing single characters to disk
1360 FOR J=0 TO LINES
1370 FOR I=0 TO COLS
1380 SCR=61440!+(J*128)+I
1390 IF PEEK(SCR)<>32 THEN GOSUB 1570
1400 NEXT I,J
1410 PRINT #1,STR$(LN);" RETURN":CLOSE #1
1420 RETURN
1430 REM  Begin GOSUB printing horizontal series to disk as DO loops
1440 PRINT #1,STR$(LN);"FOR SCRNPOS=";STR$(SCR-COUNT);"TO";
1450 PRINT #1,STR$(SCR-1);":POKE SCRNPOS,";STR$(CH);":NEXT"
1460 REM  Erase saved char.'s from screen
1470 FOR CLEANUP=SCR-COUNT TO SCR-1:POKE CLEANUP,32:NEXT
1480 LN=LN+10
1490 RETURN
1500 REM  Begin GOSUB printing vertical DO loops to disk
1510 PRINT #1,STR$(LN);"FOR SCRNPOS=";STR$(I-COUNT*128);" TO";
1520 PRINT #1,STR$(I-128);" STEP 128:POKE SCRNPOS,";STR$(CH);":NEXT"
1530 REM  Erase saved characters from screen
1540 FOR CLEANUP=I-COUNT*128 TO I-128 STEP 128 : POKE CLEANUP,32:NEXT
1550 LN=LN+10
1560 RETURN
1570 REM  Begin GOSUB printing single char.'s to disk
1580 PRINT #1,STR$(LN);" POKE";STR$(SCR)+","+STR$(PEEK(SCR))
1590 LN=LN+10
1600 POKE SCR,32  'erase saved char. from screen
1610 RETURN  '***************  END OF SAVE ON DISK ROUTINES
1620 REM  Begin GOSUB printing border of starting display
1630 FOR I=61440! TO 61491!:POKE I,11:NEXT
1640 FOR I=61568! TO 64256! STEP 128:POKE I,27:NEXT
1650 FOR I=61619! TO 64307! STEP 128:POKE I,27:NEXT
1660 FOR I=64384! TO 64435!:POKE I,11:NEXT
1670 RETURN
1680 REM  Begin GOSUB inputting name of file to be saved
1690 PRINT:PRINT "Enter name of output file (USE CAPS): "
1700 INPUT "  (Default filename: 'GRAPHSUB.BAS')  ",FILE$
1710 IF FILE$="" THEN FILE$="GRAPHSUB.BAS"
1720 A$=LEFT$(FILE$,2)
1730 IF A$="A:" OR A$="B:" THEN 1760
1740 PRINT:INPUT "WHICH DRIVE? ",DRIVE$:IF DRIVE$<>"A" AND DRIVE$<>"B" THEN 1740
1750 FILE$=DRIVE$+":"+FILE$
1760 OPEN "O",#1,FILE$:CLOSE #1
1770 RETURN
1780 REM **********************************
1790 REM  START OF GOSUB FOR CHOOSING GRAPHICS CHARACTERS MENU
1800 REM       first store lines 0-4
1810 J=0:FOR I=0 TO 52:GOSUB 2200:NEXT
1820 PRINT CUR$+HOME$;"Hit any key or wait for menu."
1830 FOR J=1 TO 4
1840 FOR I=0 TO 52
1850 GOSUB 2200
1860 A$=INKEY$:IF A$<>"" THEN 2140
1870 NEXT I,J
1880 J=0
1890 REM  Print graphics characters
1900 PRINT CUR$+HOME$;
1910 FOR I=0 TO 16:GOSUB 1950:NEXT
1920 POKE 61440!+28,9:GOTO 2000  'Bandaid for mystery bug #1
1930 GOTO 2000
1940 IF I=31 THEN PRINT CUR$+CHR$(2)+CHR$(74); 'Bandaid for mystery bug #2
1950 PRINT D$;G1$;CHR$(&H16);G0$;B$;G1$;CHR$(I);
1960 IF I=27 THEN PRINT CHR$(I);  ' ESCAPE must be printed twice
1970 PRINT G0$;D$;G1$;CHR$(&H16);G0$;
1980 RETURN
1990 REM   print ASCII codes for graphics char.'s
2000 PRINT B$:PRINT " 0";:FOR I=1 TO 16:PRINT USING "###";I;:NEXT
2010 PRINT:FOR I=17 TO 32:GOSUB 1940:NEXT
2020 PRINT B$:PRINT "17";:FOR I=18 TO 32:PRINT USING "###";I;:NEXT
2030 PRINT:PRINT "        ";CHR$(&HD);:INPUT CH  'input code
2040 IF CH<0 OR CH>127 THEN CH=0
2050 REM restore user's graphics stored in LN
2060 PRINT CUR$+HOME$;
2070 FOR J=0 TO 4:FOR I=0 TO 52:PRINT " ";:NEXT:PRINT:NEXT
2080 PRINT CUR$+HOME$;
2090 FOR J=0 TO 4
2100 FOR I=0 TO 52
2110 GOSUB 2210
2120 NEXT I,J
2130 RETURN
2140 REM    start GOSUB for inputting graphics code
2150 PRINT CUR$+HOME$;"                              ";CUR$+HOME$;
2160 INPUT "ASCII #: ",CH:IF CH<0 OR CH>127 THEN PRINT CUR$+HOME$;:GOTO 2160
2170 J=0:FOR I=0 TO 30:GOSUB 2210:NEXT
2180 PRINT CUR$+CHR$(31)+CHR$(32);
2190 RETURN
2200 LN(J*52+I)=PEEK(61440! + J*128 + I):RETURN 'Store character
2210 POKE (61440! + J*128 + I),LN(J*52 + I):RETURN  'Restore screen
J*52+I)=PEEK(61440! + J*128 + I):RETURN 'Store character
2210 POKE (61440! + J*128 + I),LN(J*52 + I):R