! EDIT.BAS - Line editor for Alpha Micro text files.
!       Dave Britson
!       Des Moines, IA
!       August '85
!
!       XCALL Subroutines used: STRIP, GETEM, RENAME.

MAP1 EDIT'LINE(500),S,100
MAP1 MAX'LINES,F,6,500

MAP1 VARIABLES
       MAP2 CHAR,S,1
       MAP2 STAT,S,3
       MAP2 QUEST,S,100
       MAP2 QUEST2,S,100
       MAP2 RPLC'STRING,S,100
       MAP2 NEW'STRING,S,100
       MAP2 TMP'LINE1,S,101
       MAP2 TMP'LINE2,S,100
       MAP2 FILENAME,S,10
       MAP2 BCKFILE,S,10

FILEBASE 1
SIGNIFICANCE 11

INPUT LINE "File to Edit> ";FILENAME
PRINT : XCALL STRIP,FILENAME
IF LEN(FILENAME)=0 PRINT "ERROR - INVALID FILENAME" : GOTO BACKOUT
IF INSTR(1,FILENAME,".")=0 FILENAME=FILENAME+".BAS"

LOOKUP FILENAME,THERE
IF THERE=0 CALL NEW'FILE
IF STAT="NOF" GOTO BACKOUT

BCKFILE=FILENAME[1,INSTR(1,FILENAME,".")-1]+".BAK"
LOOKUP BCKFILE,THERE : IF THERE#0 KILL BCKFILE
CALL INPUT'FILE

COMMAND'LOOP:
       INPUT LINE "EDIT> ";QUEST
       XCALL STRIP,QUEST : QUEST=UCS(QUEST)
       ON INSTR(1,"ADEHILPRS",QUEST[1;1]) CALL &
               ENTER'LINE,DELETE'LINE,EDIT'LINE,HELP, &
               INSERT'LINE,LIST'FILE,LIST'FILE,REPLACE,SEARCH

       IF (QUEST[1;1]="S" &
               OR QUEST[1;1]="R") &
               AND FND=0 &
               PRINT "String not found"

       IF QUEST[1;1]="Q" &
               PRINT "Abandoning Changes" : &
               GOTO BACKOUT

       IF QUEST[1;1]="F" GOTO FINISH
       PRINT
       GOTO COMMAND'LOOP

INPUT'FILE:
       PRINT "Getting ";FILENAME;
       OPEN #1,FILENAME,INPUT
       X=1
INPUT'LOOP:
       INPUT LINE #1,TMP'LINE1
       IF TMP'LINE1[101;1]#"" &
               PRINT : &
               PRINT "WARNING - LINE ";X USING "###";" LONGER THAN 100 CHARACTERS"

       IF EOF(1) &
               X=X-1 : PRINT : &
               CLOSE #1 : RETURN

       IF X=>MAX'LINES &
               PRINT : CLOSE #1 : &
               GOTO FILE'TOO'LARGE

       EDIT'LINE(X)=TMP'LINE1
       X=X+1 : IF X/10=INT(X/10) PRINT ".";
       GOTO INPUT'LOOP

LIST'FILE:
       IF QUEST[1;1]="P" BEGLINE=1 : ENDLINE=X
       C=INSTR(1,QUEST,",")
       IF C>0 &
               BEGLINE=VAL(QUEST[3;C-1]) : &
               ENDLINE=VAL(QUEST[C+1,LEN(QUEST)]) &
       ELSE &
               BEGLINE=VAL(QUEST[3;LEN(QUEST)]) : &
               ENDLINE=BEGLINE

       PRINT
       IF BEGLINE>X PRINT "ERROR - OUT OF RANGE" : RETURN
       IF BEGLINE<=0 AND ENDLINE<=0 BEGLINE=1 : ENDLINE=X
       IF BEGLINE<=0 BEGLINE=1
       IF ENDLINE=0 ENDLINE=BEGLINE
       IF ENDLINE>X ENDLINE=X
       FOR I = BEGLINE TO ENDLINE
               PRINT I USING "###";" ";EDIT'LINE(I)
               IF QUEST[1;1]="P" &
                       AND I/22=INT(I/22) &
                       PRINT : &
                       INPUT LINE "CR to continue or Q)uit> ";QUEST2 : &
                       PRINT : &
                       IF UCS(QUEST2[1;1])="Q" I=X

               XCALL GETEM,CHAR
               IF ASC(CHAR)=32 I=X
       NEXT I
       RETURN

DELETE'LINE:
       C=INSTR(1,QUEST,",")
       IF C>0 &
               BEGLINE=VAL(QUEST[3;C-1]) : &
               ENDLINE=VAL(QUEST[C+1,LEN(QUEST)]) &
       ELSE &
               BEGLINE=VAL(QUEST[3;LEN(QUEST)]) : &
               ENDLINE=BEGLINE

       IF BEGLINE<=0 RETURN
       IF ENDLINE=0 ENDLINE=BEGLINE
       IF BEGLINE>X OR ENDLINE>X &
               PRINT "ERROR - OUT OF RANGE" : &
               RETURN

       RANGE=ENDLINE-BEGLINE+1
       FOR I = BEGLINE+RANGE TO X
               EDIT'LINE(I-RANGE)=EDIT'LINE(I)
       NEXT I
       FOR I=X-RANGE+1 TO X
               EDIT'LINE(I)=""
       NEXT I
       X=X-RANGE
       RETURN

INSERT'LINE:
       INPUT LINE "Insert before line # ";LINENO
       IF LINENO=0 RETURN
       IF LINENO>X &
               PRINT "ERROR - LINE OUT OF RANGE" : &
               RETURN

       IF X+1>MAX'LINES &
               PRINT "ERROR - FILE OVERFLOW" : &
               RETURN

       FOR I = X+1 TO LINENO+1 STEP-1
               EDIT'LINE(I)=EDIT'LINE(I-1)
       NEXT I
       EDIT'LINE(LINENO)=""
       X=X+1
       PRINT "LINE ";LINENO USING "###";"> ";
       INPUT LINE TMP'LINE1
       EDIT'LINE(LINENO)=TMP'LINE1
       RETURN

EDIT'LINE:
       PRINT
       INPUT LINE "Edit line # ";LINENO
       IF LINENO=0 RETURN
       IF LINENO<0 OR LINENO>X GOTO EDIT'LINE
       PRINT LINENO USING "###";" ";EDIT'LINE(LINENO)
GET'RPLC'STRING:
       PRINT
       INPUT LINE "String to replace> ";RPLC'STRING
       RPLC'START=INSTR(1,EDIT'LINE(LINENO),RPLC'STRING)
       IF RPLC'START=0 &
               PRINT "String not found" : &
               GOTO EDIT'LINE

       INPUT LINE "New string> ";NEW'STRING
       IF RPLC'START>1 &
               TMP'LINE1=EDIT'LINE(LINENO)[1,RPLC'START-1] &
       ELSE &
               TMP'LINE=""

       TMP'LINE2=EDIT'LINE(LINENO) &
               [RPLC'START+LEN(RPLC'STRING),LEN(EDIT'LINE(LINENO))]

       EDIT'LINE(LINENO)=TMP'LINE1+NEW'STRING+TMP'LINE2
       PRINT
       PRINT "Line # ";LINENO;" now reads"
       PRINT LINENO USING "###";" ";EDIT'LINE(LINENO)
       RETURN

ENTER'LINE:
       PRINT
       PRINT "'*' - Returns from Add mode"
       X=X+1
ENTRY'LOOP:
       PRINT "LINE ";X USING "###";"> ";
       INPUT LINE TMP'LINE1
       IF UCS(TMP'LINE1[1;1])="*" &
               X=X-1 : &
               RETURN

       XCALL STRIP,TMP'LINE1
       IF TMP'LINE1#"" &
               EDIT'LINE(X)=TMP'LINE1 : &
               X=X+1

       IF X>128 &
               PRINT : PRINT "Maximum number of lines reached" : &
               X=X-1 : &
               RETURN

       GOTO ENTRY'LOOP

NEW'FILE:
       PRINT
       PRINT FILENAME;" does not exist - Create it? ";
       INPUT LINE QUEST
       QUEST=UCS(QUEST)
       IF QUEST[1;1]#"Y" STAT="NOF" : RETURN
       OPEN #1,FILENAME,OUTPUT
       CLOSE #1
       RETURN

HELP:
       PRINT
       PRINT "     > HELP SCREEN < "
       PRINT "L - List file contents"
       PRINT "P - List file by page"
       PRINT "A - Add lines to end of file"
       PRINT "E - Edit an existing line"
       PRINT "I - Insert a line into file"
       PRINT "D - Delete a line from file"
       PRINT "S - Search for specified string"
       PRINT "R - Replace strings"
       PRINT "Q - Quit, no update"
       PRINT "F - Finish, update disk file"
       PRINT "H - This Help screen"
       RETURN

REPLACE:
       RPLC'STRING=QUEST[3,LEN(QUEST)]
!       INPUT LINE "Original string> ";RPLC'STRING
       IF RPLC'STRING="" RETURN
       INPUT LINE "Replacement string> ";NEW'STRING
       XCALL STRIP,RPLC'STRING
       XCALL STRIP,NEW'STRING

GET'ALL'SOME:
       INPUT LINE "A)ll or S)ome? ";QUEST
       QUEST=UCS(QUEST)
       IF QUEST#"A" AND QUEST#"S" GOTO GET'ALL'SOME

       I=0 : FND=0
REPLACE'MAIN'LOOP:
       I=I+1 : J=1
       IF I>X RETURN
REPLACE'SECONDARY'LOOP:
       J=INSTR(J,EDIT'LINE(I),RPLC'STRING)
       IF J=0 GOTO REPLACE'MAIN'LOOP
       STRT=J : LINENO=I : FND=1
       CALL REPLACE'ROUTINE
       IF UCS(QUEST2)="Q" RETURN
       J=J+1
       GOTO REPLACE'SECONDARY'LOOP

REPLACE'ROUTINE:
       RPLC'START=INSTR(STRT,EDIT'LINE(LINENO),RPLC'STRING)
       IF RPLC'START=0 RETURN

       Z=0
       FOR Y = 1 TO RPLC'START
               IF ASC(EDIT'LINE(LINENO)[Y;1])=9 Z=Z+7
       NEXT Y
       IF QUEST="S" &
               PRINT LINENO USING "###";" ";EDIT'LINE(LINENO) : &
               CALL PRINT'MARK : &
               INPUT LINE "Replace this string? ";QUEST2 : &
               IF UCS(QUEST2[1;1])#"Y" RETURN

       IF RPLC'START>1 &
               TMP'LINE1=EDIT'LINE(LINENO)[1,RPLC'START-1] &
       ELSE &
               TMP'LINE1=""

       TMP'LINE2=EDIT'LINE(LINENO) &
               [RPLC'START+LEN(RPLC'STRING),LEN(EDIT'LINE(LINENO))]

       EDIT'LINE(LINENO)=TMP'LINE1+NEW'STRING+TMP'LINE2
       RETURN

SEARCH:
       RPLC'STRING=QUEST[3,LEN(QUEST)]
!       INPUT LINE "Search string> ";RPLC'STRING
       IF RPLC'STRING="" RETURN
       XCALL STRIP,RPLC'STRING

       I=0 : FND=0
SEARCH'MAIN'LOOP:
       I=I+1 : J=1
       IF I>X RETURN
SEARCH'SECONDARY'LOOP:
       J=INSTR(J,EDIT'LINE(I),RPLC'STRING)
       IF J=0 GOTO SEARCH'MAIN'LOOP
       STRT=J : LINENO=I : FND=1
       CALL SEARCH'ROUTINE
       IF QUEST2[1;1]="N" RETURN
       J=J+1
       GOTO SEARCH'SECONDARY'LOOP

SEARCH'ROUTINE:
       RPLC'START=INSTR(STRT,EDIT'LINE(LINENO),RPLC'STRING)
       IF RPLC'START=0 RETURN

       Z=0
       FOR Y = 1 TO LEN(EDIT'LINE(LINENO))
               IF ASC(EDIT'LINE(LINENO)[Y;1])=9 Z=Z+7
       NEXT Y
       PRINT LINENO USING "###";" ";EDIT'LINE(LINENO)
       CALL PRINT'MARK
       INPUT LINE "Find Next String? ";QUEST2
       QUEST2=UCS(QUEST2)
       RETURN

PRINT'MARK:
       IF Z=0 &
               PRINT SPACE(RPLC'START+Z+3);"^" &
       ELSE &
               PRINT SPACE(RPLC'START+Z-1);"^" &

       RETURN

FINISH:
       XCALL RENAME,FILENAME,BCKFILE
       PRINT "Saving ";FILENAME;
       OPEN #1,FILENAME,OUTPUT
       FOR I = 1 TO X
               PRINT #1,EDIT'LINE(I)
               IF I/10=INT(I/10) PRINT ".";
       NEXT I
       CLOSE #1 : PRINT
       GOTO BACKOUT

FILE'TOO'LARGE:
       PRINT "ERROR - FILE TOO LARGE"

BACKOUT:
       END