100 '************** THE STOPGAP EDITOR IN IBM BASIC ******************
110 ' ***** by D.E. Cortesi
120 DEFINT A-Z : MAXL = 300 : MAXW = 79 :' MAXW=40 FOR COLOR TV
130 GOTO 1490
140 ' ::: right-arrow key: move cursor right
150 IF SCOL=MAXW THEN RETURN
160 SCOL=SCOL+1 : INSCHAR=FALSE : LOCATE SROW,SCOL,1,CSL : RETURN
170 ' ::: left-arrow key: move cursor left
180 IF SCOL=1 THEN RETURN
190 SCOL=SCOL-1 : INSCHAR=FALSE : LOCATE SROW,SCOL,1,CSL : RETURN
200 ' ::: tab key: jump right from one to eight columns
210 S=((SCOL+8) AND (-8))+1 : IF S<=MAXW THEN SCOL=S
220 INSCHAR=FALSE : LOCATE SROW,SCOL,1,CSL : RETURN
230 ' ::: end key: go to right end of the current line
240 SCOL=MAXW : INSCHAR=FALSE : LOCATE SROW,SCOL,1,CSL : RETURN
250 ' ::: printable character, action depends on INSCHAR
260 IF NOT LMOD THEN L$=LT$(LCUR) : LMOD=TRUE
270 IF NOT INSCHAR THEN MID$(L$,SCOL,1)=CIN$ : GOTO 300
280 CIN$=CIN$+MID$(L$,SCOL,MAXW-SCOL)
290 L$=LEFT$(L$,SCOL-1)+CIN$
300 PRINT CIN$; : IF SCOL<MAXW THEN SCOL=SCOL+1
303 REM IF SCOL=> (MAXW - 3) THEN BEEP ' alert typist to end of line
305 IF SCOL=> (MAXW - 7) AND CIN$ = " " THEN GOSUB 600 : GOTO 1330 ' word wrap
307 IF SCOL = MAXW THEN GOSUB 600 : GOTO 1330 ' line wrap around
310 LOCATE SROW,SCOL,1 : RETURN
320 ' ::: backspace: blank currrent character, move left
330 IF NOT LMOD THEN L$=LT$(LCUR) : LMOD=TRUE
340 MID$(L$,SCOL,1)=" " : PRINT " ";
350 IF SCOL>1 THEN SCOL=SCOL-1
360 INSCHAR=FALSE : LOCATE SROW,SCOL,1,CSL : RETURN
370 ' ::: del key: kill current char, pull rest left
380 IF NOT LMOD THEN L$=LT$(LCUR) : LMOD=TRUE
390 CIN$=RIGHT$(L$,MAXW-SCOL)+" " : PRINT CIN$;
400 L$=LEFT$(L$,SCOL-1)+CIN$
410 INSCHAR=FALSE : LOCATE SROW,SCOL,1,CSL : RETURN
420 ' ::: if current line has changed, update the file
430 INSCHAR=FALSE : LOCATE ,,1,CSL : IF NOT LMOD THEN RETURN
440 FMOD=LMOD : LT$(LCUR)=L$ : LMOD=FALSE : RETURN
450 ' ::: return the index of the next free line in L
460 IF LFREE=0 THEN L=FALSE : RETURN :'NO FREE LINES LEFT
470 L=LFREE : LFREE=LF(L) : LF(L)=0 : LT$(L)=LMT$ : RETURN
480 ' ::: free the line whose index is in L
490 LF(L)=LFREE : LFREE=L : LT$(L)="" : RETURN
500 ' ::: forward one line in the file image
510 GOSUB 430 : L=LF(LCUR) :' L=0 IF LCUR IS BOTTOM LINE
520 IF L=0 THEN GOSUB 460 : IF L THEN LF(LCUR)=L : LB(L)=LCUR
530 IF L THEN LCUR=L :' FALSE IF BOTTOM AND NO FREE LINES
540 RETURN
550 ' ::: backward one line in the file image
560 GOSUB 430 : L=LB(LCUR)
570 IF L THEN LCUR=L :' FALSE IF TOP LINE
580 RETURN
590 ' ::: enter key: cursor to left margin, then down
600 SCOL=1
610 ' ::: down-arrow: cursor down (data up, on line 24)
620 Q=LCUR : GOSUB 510 : IF Q=LCUR THEN RETURN
630 SROW=SROW+1 : IF SROW<25 THEN LOCATE SROW,SCOL,1 : RETURN
640 SROW=24 : PRINT :' FORCE BLANK LINE, RETURN CURSOR
650 PRINT LT$(LCUR); : LOCATE SROW,SCOL,1 : RETURN
660 ' ::: up-arrow: cursor up (data down 23 lines, on line 1)
670 IF SROW=1 THEN 710
680 Q=LCUR : GOSUB 560 : IF Q=LCUR THEN RETURN
690 SROW=SROW-1 : LOCATE SROW,SCOL,1 : RETURN
700 ' ::: up-arrow on line 1: slide current line down 23
710 GOSUB 960 : S=0
720 WHILE (S<22) AND LB(T) : T=LB(T) : B=LB(B) : S=S+1 : WEND
730 SROW=SROW+S : GOTO 1020
740 ' ::: PgUp key: back up 23 lines, hold cursor still
750 GOSUB 430 : GOSUB 960 : S=0
760 WHILE (S<23) AND LB(T) : GOSUB 560 : T=LB(T) : B=LB(B) : S=S+1 : WEND
770 GOTO 1020
780 ' ::: PgDn key: ahead 23 lines, hold cursor still
790 GOSUB 430 : GOSUB 960 : S=0
800 WHILE (S<23) AND LF(B) : GOSUB 510 : T=LF(T) : B=LF(B) : S=S+1 : WEND
810 GOTO 1020
820 ' ::: Home key: go to left, then to top, then to bottom
830 IF SCOL>1 THEN SCOL=1 : INSCHAR=FALSE : LOCATE SROW,SCOL,1,CSL : RETURN
840 GOSUB 430 : GOSUB 960 : S=SROW
850 IF SROW=1 THEN WHILE LCUR<>B : GOSUB 510 : S=S+1 : WEND
860 IF SROW>1 THEN WHILE LCUR<>T : GOSUB 560 : S=S-1 : WEND
870 SROW=S : LOCATE SROW,SCOL,1 : RETURN
880 ' ::: control-a: go to top of the file
890 GOSUB 430 : GOSUB 2240 : LCUR=A
900 SROW=1 : SCOL=1 : GOSUB 960 : GOTO 1020
910 ' ::: control-z: go to the end of the file
920 GOSUB 430 : GOSUB 2240 : LCUR=Z : T=Z : B=Z : S=1
930 WHILE LB(T) AND S<24 : T=LB(T) : S=S+1 : WEND
940 SROW=S : SCOL=1 : GOTO 1020
950 ' ::: find the lines now at the top(T) and bottom(B) of the screen
960 S=SROW : T=LCUR
970 WHILE (S>1) AND LB(T) : S=S-1 : T=LB(T) : WEND
980 S=SROW : B=LCUR
990 WHILE (S<24) AND LF(B) : S=S+1 : B=LF(B) : WEND
1000 RETURN
1010 ' ::: redraw the screen using lines from T to B
1020 CLS : L=T
1030 WHILE L<>B : PRINT LT$(L) : L=LF(L) : WEND
1040 PRINT LT$(B);
1050 LOCATE SROW,SCOL,1 : RETURN
1060 ' ::: Ins key: toggle insert-character mode
1070 INSCHAR=NOT INSCHAR
1080 IF INSCHAR THEN LOCATE ,,1,CSL,1 ELSE LOCATE ,,1,CSL
1090 RETURN
1100 ' ::: control-o: split the file for bulk insertion
1110 IF INSLINE OR LF(LCUR)=0 OR LFREE=0 THEN RETURN
1120 GOSUB 430 : LINS=LCUR : LCUR=LB(LCUR)
1130 IF LCUR THEN LF(LCUR)=0 : GOSUB 510
1140 IF LCUR=0 THEN GOSUB 460 : LB(L)=0 : LCUR=L
1150 INSLINE=TRUE : GOSUB 960 : GOTO 1020
1160 ' ::: control-c: splice the file after bulk insert
1170 IF NOT INSLINE THEN RETURN
1180 GOSUB 430 : WHILE LF(LCUR) : LCUR=LF(LCUR) : WEND
1190 LF(LCUR)=LINS : LB(LINS)=LCUR
1200 IF LT$(LCUR)<>LMT$ THEN 1240
1210 L=LCUR : LCUR=LF(LCUR) : LB(LCUR)=LB(L)
1220 IF LB(L) THEN LF(LB(L))=LCUR
1230 GOSUB 490
1240 INSLINE=FALSE : GOSUB 960 : GOTO 1020
1250 ' ::: control-d: delete the current line
1260 IF LF(LCUR)+LB(LCUR)=0 THEN RETURN :'CAN'T DELETE ONLY LINE
1270 IF LB(LCUR) THEN LF(LB(LCUR))=LF(LCUR)
1280 IF LF(LCUR) THEN LB(LF(LCUR))=LB(LCUR)
1290 L=LCUR : IF LF(L)>0 THEN LCUR=LF(L)
1300 IF LF(L)=0 THEN LCUR=LB(L) : IF SROW>0 THEN SROW=SROW-1
1310 GOSUB 490 : GOSUB 960 : GOTO 1020
1320 ' ************ THE MAIN LOOP ******************************
1330 CIN$=INKEY$ : ON 1+LEN(CIN$) GOTO 1330,1390,1350
1340 'handle a special key (numeric pad, Ins, Del)
1350 S=ASC(RIGHT$(CIN$,1)) : IF S<71 OR S>83 THEN 1330
1360 ON S-70 GOSUB 830,670,750,1330,180,1330,150,1330,240,620,790,1070,380
1370 GOTO 1330
1380 'handle regular control or character key
1390 S=ASC(CIN$) : IF S>31 THEN GOSUB 260 : GOTO 1330
1400 IF S=>8 AND S<=13 THEN ON S-7 GOSUB 330,210,620,830,1330,600 : GOTO 1330
1410 IF S=1 THEN GOSUB 890 : GOTO 1330
1420 IF S=3 THEN GOSUB 1170 : GOTO 1330
1430 IF S=4 THEN GOSUB 1260 : GOTO 1330
1440 IF S=15 THEN GOSUB 1110 : GOTO 1330
1450 IF S=26 THEN GOSUB 920 : GOTO 1330
1460 IF S=27 THEN GOSUB 1630 : GOTO 1330
1470 GOTO 1330
1480 ' ************ INITIALIZATION *****************************
1490 GOSUB 1520 : FSPEC$="" :' CLEAR ALL DATA AND SET UP
1500 CLS : LOCATE SROW,SCOL,1 : GOTO 1330
1510 ' ::: clear all variables, set up a null data array
1520 DIM LF(MAXL),LB(MAXL),LT$(MAXL)
1530 LMT$=SPACE$(MAXW)
1540 FALSE=(1=2) : TRUE=NOT FALSE
1550 LMOD=FALSE : FMOD=FALSE
1560 CSL=12 :' CURSOR SCAN LINE -- MAKE 7 FOR COLOR TV
1570 INSCHAR=FALSE : LOCATE ,,1,CSL : INSLINE=FALSE
1580 FOR I=2 TO MAXL-1 : LF(I)=I+1 : NEXT I : LF(MAXL)=0 : LFREE=2
1590 LCUR=1 : LF(LCUR)=0 : LB(LCUR) = O : LT$(LCUR)=LMT$
1600 SROW=1 : SCOL=1 : LCUR=1 : T=1 : B = 1
1610 RETURN
1620 ' ************ GLOBAL COMMANDS ****************************
1630 GOSUB 1170 : GOSUB 430 : GOSUB 960
1640 CLS : LOCATE 10,1
1650 PRINT "Command choices are..." : PRINT
1660 PRINT " 1. SAVE the present file"
1670 PRINT " 2. LOAD another file"
1680 PRINT " 3. CLEAR the data buffer of all data"
1690 PRINT " 4. QUIT and return to DOS."
1700 PRINT " Press ENTER to resume editing."
1710 INPUT "Your choice of 1,2,3,4 ";CIN$
1720 IF CIN$="" THEN GOSUB 1020 : GOTO 1330
1730 CIN$=LEFT$(CIN$,1)
1740 IF CIN$="1" THEN GOSUB 1800 : GOTO 1640
1750 IF CIN$="2" THEN GOSUB 1930 : GOTO 1640
1760 IF CIN$="3" THEN GOSUB 2070 : GOTO 1640
1770 IF CIN$="4" THEN GOSUB 2100 : GOTO 1640
1780 GOTO 1640
1790 ' ::: the command is: SAVE
1800 GOSUB 2180 : OPEN FSPEC$ FOR OUTPUT AS #1
1810 GOSUB 2240 :'find the top and bottom of the data
1820 'write all lines, deleting trailing blanks
1830 WHILE A<>Z
1840 L$=LT$(A)
1850 I=MAXW
1860 WHILE I>1 AND MID$(L$,I,1)=" " : I=I+1 : WEND
1870 L$=LEFT$(L$,I)
1880 PRINT#1,L$
1890 A=LF(A)
1900 WEND
1910 CLOSE#1 : FMOD=FALSE : RETURN
1920 ' ::: the command is: LOAD
1930 GOSUB 2070 : IF NOT Q THEN RETURN
1940 GOSUB 2180 : OPEN FSPEC$ FOR INPUT AS #1
1950 'read up to MAXL lines, force all to MAXW bytes
1960 WHILE (LFREE>0) AND NOT(EOF(1))
1970 LINE INPUT#1,CIN$
1973 REM FOR I = 1 TO LEN(CIN$)
1975 REM IF ASC(MID$(CIN$,I,1)) = 9 THEN MID$(CIN$,I,1) = " "
1977 REM NEXT I
1980 L$=LMT$ : LSET L$ = LEFT$(CIN$,MAXW)
1990 LMOD=TRUE
2000 GOSUB 510
2010 WEND
2020 CLOSE#1
2030 LMOD=FALSE : FMOD=FALSE
2040 LCUR=1 : SROW=1 : SCOL=1 : GOSUB 960
2050 RETURN
2060 ' ::: the command is: CLEAR (or clear prior to LOAD)
2070 GOSUB 2120 : IF NOT Q THEN RETURN
2080 ERASE LT$,LF,LB : GOSUB 1520 : RETURN
2090 ' ::: the command is: QUIT
2100 GOSUB 2120 : IF Q THEN SYSTEM ELSE RETURN
2110 ' ::: if the file has been changed, get confirmation
2120 IF NOT FMOD THEN Q=TRUE : RETURN
2130 PRINT : PRINT "The file has been MODIFIED...!"
2140 INPUT "...are you SURE you want to do this (Y/N> ";CIN$
2150 CIN$=LEFT$(CIN$,1)
2160 Q=(CIN$="y") OR (CIN$="Y") : RETURN
2170 ' ::: get a filespec for load or save
2180 PRINT : PRINT "Give me a filespec";
2190 IF FSPEC$<>"" THEN PRINT " (";FSPEC$;")";
2200 INPUT CIN$ : IF (CIN$+FSPEC$)="" THEN PRINT : GOTO 2180
2210 IF CIN$<>"" THEN FSPEC$=CIN$
2220 RETURN
2230 ' ::: find the top(A) and bottom(Z) lines of data
2240 A=LCUR : WHILE LB(A) : A=LB(A) : WEND
2250 Z=LCUR : WHILE LF(Z) : Z=LF(Z) : WEND
2260 '..minus trailing, empty lines, if any
2270 WHILE LT$(Z)="" AND Z<>A : Z=LB(Z) : WEND
2280 RETURN