PROC FSEEDIT; BEGIN # *** FSEEDIT - FULL SCREEN EDITOR AND SCREEN MGT FACILITY. * * COPYRIGHT CONTROL DATA SYSTEMS INC. 1992. # DEF LISTCON #0#; CONTROL EJECT; # UNIVERSAL DEFINITIONS # *IFCALL SINGLE,COMFSGL *IFCALL ONLY,COMFONL *IFCALL MULTI,COMFMLT *CALL COMFFSE # EXTERNAL REF'S AND DEF'S # CONTROL IFEQ MULTI,1; XREF ARRAY RENTSTK [1:MAXREENT]; # SUBROUTINE STACK # BEGIN ITEM RSTK; END XREF ITEM RSTKPTR; CONTROL FI; CONTROL IFEQ MULTI,1; XREF PROC VOLUNTEER; # OFFER TO SURRENDER SUBTASK # XREF PROC CLEARINT; # PROCLAIM WE SAW USRBRK # XREF PROC FATALTRAP; # MONITOR PROCESSING FOR EDITOR TROUBLE # XREF PROC CLEARQUE; # MONITOR NO LONGER NEEDS TASKREQUE BIT # CONTROL IFEQ METERING,1; XREF PROC BGNMETER; # ISSUE START-OF-SESSION STATS # CONTROL FI; CONTROL FI; XDEF BEGIN *CALL COMFXED END XREF BEGIN *CALL COMFXSB *CALL COMFXTI *CALL COMFXFO *CALL COMFXSC *CALL COMFXWK *CALL COMFXVT END CONTROL IFEQ SINGLE,1; XREF BEGIN *CALL COMFXCM END CONTROL FI; XREF BEGIN CONTROL IFEQ SINGLE,1; *CALL COMFXFL CONTROL FI; END XREF # XTRNL CIO PROCS # BEGIN PROC READ; # ALL SAME AS # PROC READC; # CORRESPONDING MACROS # PROC WRITE; PROC WRITEF; PROC WRITER; PROC WRITEC; CONTROL IFEQ SINGLE,1; PROC EVICT; PROC RETERN; PROC REWIND; PROC RECALL; CONTROL FI; END XREF # XTRNL MISCELLANEOUS # BEGIN PROC DISSJ; # DISABLE/ENABLE SSJ= # PROC VDTGTN; PROC VDTGTO; PROC EXCHWD; PROC MOVEWD; PROC ZEROWD; FUNC FASTFND B; # OPTIMIZED STRING SEARCH # FUNC FASTLNB; # FIND LAST NON-BLANK # FUNC LENGTH; # LENGTH OF INTERNAL LINE # FUNC LINESZ; FUNC FIXCTL B; # FIX UNWANTED CONTROL BYTES # CONTROL IFEQ SINGLE,1; PROC MESSAGE; # MESSAGE MACRO # PROC DISTCON; # DISABLE TERMINAL CONTROL # PROC ABORT; # ABORT MACRO # PROC SYSREQ; PROC ROLLTE; PROC TSTATUS; CONTROL FI; END # COMMON DATA AREAS # *CALL COMFDS1 *CALL COMFVD2 *CALL COMFDS2 # EDITOR SYNTAX TABLES # *CALL COMFTAB PAGE # VARIOUS USEFUL LITTLE ROUTINES # PROC DSPLCOD(WORD); BEGIN # ** DSPLCOD - CONVERT ONE CHARACTER TO LOWER CASE OR DISPLAY. * * DSPLCOD SUPPRESSES CASE OF INTERNAL CHARACTERS. IT IS * ALSO DEFINED TO CONVERT FROM INTERNAL CHARACTER SET TO * DISPLAY. THUS THE FIRST 64 CHARACTERS OF INTERNAL MUST * EQUAL DISPLAY CODE. WE ENFORCE THIS WITH COMPILE-TIME * CHECKS FOR "A", "Z", AND SEMICOLON. * * ENTRY WORD - INTERNAL CHARSET VALUE TO CONVERT. * * EXIT WORD - CONVERTED. # CONTROL IFNQ CLETTERA,1; ERROR; CONTROL FI; CONTROL IFNQ CLETTERZ,26; ERROR; CONTROL FI; CONTROL IFNQ CSEMCOLON,O"77"; ERROR; CONTROL FI; ITEM WORD; WORD=XLTINTDSP[WORD]; END # OF DSPLCOD # PROC SQUELCH(TEXTLIN); BEGIN # ** SQUELCH - SUPPRESS LOWER-CASE FOR LINE IMAGE. * * ENTRY TEXTLIN - INTERNAL CHARSET LINE IMAGE. * * EXIT TEXTLIN - ALL ALPHABETICS ARE UPPER CASE. * * MACROS GETCHAR, SETCHAR. * * CALLS DSPLCOD, LENGTH. # ARRAY TEXTLIN[0:99]; ITEM TEXTLINE; ITEM TMP1, TMP2; FOR TMP1=0 STEP 1 UNTIL LENGTH(TEXTLIN) DO BEGIN GETCHAR(TEXTLINE,TMP1,TMP2); DSPLCOD(TMP2); SETCHAR(TEXTLINE,TMP1,TMP2); END END # OF SQUELCH # PROC HALT(STR); IOBEGIN(HALT) # ** HALT - SET WARNING MESSAGE AND FLAG COMMAND SHUTDOWN. * * ENTRY STR - ERROR MESSAGE, DISPLAY WITH DOLLAR SIGN. * * EXIT ERRSTRING - EQUAL TO STR. * FOUND - FALSE. * LINCTR - INFINITE. # ITEM STR C(80); FOUND=FALSE; LINCTR=LARGENUM; ERRSTRING=STR; IOEND # OF HALT # CONTROL IFEQ MULTI,1; PROC CHKVICTIM; IOBEGIN(CHKVICTIM) # ** CHKVICTIM - CHECK FOR SMFEX-IMPOSED SESSION ABORT. * * CHKVICTIM LOOKS FOR SMFEX-DETECTED CATASTROPHES. THIS * CURRENTLY INCLUDES ONLY UNRECOVERABLE ECS PARITY ERRORS. * * ENTRY SMFVICTIM - FLAG. * * EXIT VIA FATAL IF NEED TO ABORT. * * CALLS FATAL. # IF SMFVICTIM THEN FATAL(ERRSTRING); IOEND # OF CHKVICTIM # CONTROL FI; PROC CONCAT(LIN1,LIN2); BEGIN # ** CONCAT - CONCATENATE TWO INTERNAL LINE IMAGES. * * ENTRY LIN1, LIN2 - THE LINE IMAGES IN INTERNAL CHARSET. * * EXIT LIN1 - HAS LIN2 APPENDED TO IT. * * MACROS GETCHAR, SETCHAR. * * CALLS LENGTH. # ARRAY LIN1; ITEM LINE1; ARRAY LIN2; ITEM LINE2; ITEM TMP1, TMP2, TMP3, TMP4; TMP1=LENGTH(LIN1); TMP2=LENGTH(LIN2); FOR TMP3=0 STEP 1 WHILE TMP3 LQ TMP2 AND TMP1+TMP3 LQ BUFCM1 DO BEGIN GETCHAR(LINE2,TMP3,TMP4); SETCHAR(LINE1,TMP1+TMP3,TMP4); END SETCHAR(LINE1,TMP1+TMP3,CENDLINE); END # OF CONCAT # PROC NOPOP; # LIKE POP BUT DONT MOVE # BEGIN # ** NOPOP - POP POSITION STACK WITHOUT USING IT. * * NOPOP DIFFERS FROM POP IN THAT WHILE BOTH POP THE LEVEL * OF THE POSITIONING STACK, NOPOP DISCARDS THE STACK VALUES * WHILE POP REPOSITIONS TO THE SAVED LOCATION IN THE FILE. * * ENTRY POSITIONING STACK PREVIOUSLY PUSHED. * * EXIT STACKPTR DECREMENTED. * * CALLS FATAL. # IF STACKPTR LS 0 THEN BEGIN FATAL(" FILE POSITION STACK UNDERFLOWED (2).$"); END STACKPTR=STACKPTR-1; END # OF NOPOP # PROC WINDOLIN(LINEPARM,FILEPARM); BEGIN # ** WINDOLIN - FORCE ADDRESS INTO FILE IMAGE. * * WINDOLIN FORCES LINEPARM TO BE IN BOUNDS FOR THE FILEPARM. * * ENTRY LINEPARM - LINE ADDRESS. * FILEPARM - BRACKET NUMBER FOR FILE. * TOPF(FILEPARM), BOTF(FILEPARM) - BOUNDS. * * EXIT LINEPARM - IN BOUNDS. * FOUND - TRUE OR FALSE FOR VALIDITY OF ORIGINAL VALUE. # ITEM LINEPARM, FILEPARM; FOUND=FALSE; IF TOPF(FILEPARM) EQ BOTF(FILEPARM)-1 THEN LINEPARM=TOPF(FILEPARM); ELSE IF LINEPARM LQ TOPF(FILEPARM) THEN LINEPARM=TOPF(FILEPARM)+1; ELSE IF LINEPARM GQ BOTF(FILEPARM) THEN LINEPARM=BOTF(FILEPARM)-1; ELSE FOUND=TRUE; END # OF WINDOLIN # PROC WINDOPOS(LINEPARM,FILEPARM); BEGIN # ** WINDOPOS - VALIDATE POSITION WITHIN FILE. * * WINDOPOS IS LIKE WINDOLIN EXCEPT THAT IT ALLOWS THE * POSITION TO BE JUST ABOVE THE TOP OF THE FILE. * * ENTRY LINEPARM - AS WINDOLIN. * FILEPARM - AS WINDOLIN. * TOPF(), BOTF() - AS WINDOLIN. * * EXIT LINEPARM - AS WINDOLIN. * FOUND - AS WINDOLIN. # ITEM LINEPARM, FILEPARM; FOUND=FALSE; IF TOPF(FILEPARM) EQ BOTF(FILEPARM)-1 THEN LINEPARM=TOPF(FILEPARM); IF LINEPARM LS TOPF(FILEPARM) THEN LINEPARM=TOPF(FILEPARM); ELSE IF LINEPARM GQ BOTF(FILEPARM) THEN LINEPARM=BOTF(FILEPARM)-1; ELSE FOUND=TRUE; END # OF WINDOPOS # PROC FWDNUM; IOBEGIN(FWDNUM) # ** FWDNUM - MOVE FORWARDS UNTIL NUMBERED LINE FOUND. * * FWDNUM ADVANCES THE CURRENT POSITION IN THE WORKFILE * UNTIL A NUMBERED LINE IS FOUND. NOTE THAT WE ASSUME THE * CALLER HAS VERIFIED THAT WE EXPECT NUMBERED LINES. * * ENTRY CURRENT, CURFILE - WHERE WE ARE. * BOTF(CURFILE) - BOUNDS. * USRBRK - CONTINUOUSLY CHECKED. * * EXIT CURRENT - UPDATED. * * MACROS MOD. * * CALLS FWDZ, GETLNUM, VOLUNTEER(MULTI). * * USES LINENO, WIDTHFOUND, DORNGCTR. # LINENO=NINES; WIDTHFOUND=0; FOR DORNGCTR=1 STEP 1 WHILE WIDTHFOUND EQ 0 AND CURRENT LS BOTF(CURFILE)-1 AND USRBRK EQ 0 DO BEGIN FWDZ; GETLNUM; IF WIDTHFOUND EQ 0 THEN LINENO=NINES; CONTROL IFEQ MULTI,1; IF MOD(DORNGCTR,VOLLINES) EQ 0 THEN VOLUNTEER; CONTROL FI; END IOEND # OF FWDNUM # PROC BAKNUM; IOBEGIN(BAKNUM) # ** BAKNUM - BACK UP IN FILE UNTIL NUMBERED LINE. * * BAKNUM IS LIKE FWDNUM EXCEPT OPPOSITE DIRECTION. * * ENTRY CURRENT, CURFILE - WHERE WE ARE. * TOPF(CURFILE) - BOUNDS. * USRBRK - CONTINUOUSLY CHECKED. * * EXIT CURRENT - UPDATED. * * MACROS MOD. * * CALLS BAKZ, GETLNUM, VOLUNTEER(MULTI). * * USES LINENO, WIDTHFOUND, DORNGCTR. # LINENO=0; WIDTHFOUND=0; FOR DORNGCTR=1 STEP 1 WHILE WIDTHFOUND EQ 0 AND CURRENT GR TOPF(CURFILE)+1 AND USRBRK EQ 0 DO BEGIN BAKZ; GETLNUM; CONTROL IFEQ MULTI,1; IF MOD(DORNGCTR,VOLLINES) EQ 0 THEN VOLUNTEER; CONTROL FI; END IOEND # OF BAKNUM # PROC POSN; IOBEGIN(POSN) # ** POSN - POSITION TO LINE WITH DESIRED SEQUENCE NUMBER. * * POSN MOVES FORWARDS OR BACKWARDS AS NEEDED TO GET TO * THE NEAREST LINE WITH THE RIGHT SEQUENCE NUMBER. WE * ASSUME THE CALLER HAS VERIFIED WE EXPECT NUMBERS. * * ENTRY LINNUM1 - DESIRED SEQUENCE NUMBER. * CURFILE, CURF(CURFILE) - STARTING LOCATION. * TOPF(CURFILE), BOTF(CURFILE) - BOUNDS. * USRBRK - CONTINUOUSLY CHECKED. * * EXIT CURRENT - UPDATED. * * MACROS MOD. * * CALLS POSZ, GETLNUM, BAKZ, VOLUNTEER(MULTI), FWDZ, BAKNUM. * * USES DORNGCTR, LINENO. # POSZ(CURF(FILNUM)); GETLNUM; FOR DORNGCTR=1 STEP 1 WHILE CURRENT GR TOPF(FILNUM) AND (LINENO GR LINNUM1 OR WIDTHFOUND EQ 0) AND USRBRK EQ 0 DO BEGIN BAKZ; GETLNUM; CONTROL IFEQ MULTI,1; IF MOD(DORNGCTR,VOLLINES) EQ 0 THEN VOLUNTEER; CONTROL FI; END FOR DORNGCTR=1 STEP 1 WHILE CURRENT LS BOTF(FILNUM)-1 AND (LINENO LS LINNUM1) AND USRBRK EQ 0 DO BEGIN FWDZ; GETLNUM; CONTROL IFEQ MULTI,1; IF MOD(DORNGCTR,VOLLINES) EQ 0 THEN VOLUNTEER; CONTROL FI; END IF LINENO GR LINNUM1 THEN BAKNUM; IOEND # OF POSN # PROC FITNUM; IOBEGIN(FITNUM) # ** FITNUM - CHECK SEQUENCING GAP AND SELECT INCREMENT. * * FITNUM IS USED WITH SEQUENCE NUMBERED FILES TO SEE IF * THERE IS AN ADEQUATE GAP IN VALUES OF ADJACENT SEQUENCE * NUMBERS TO FIT IN AS MANY LINES AS WE WISH. AN INCREMENT * IS CHOSEN FOR NUMBERING OF THE LINES TO BE ADDED. * * ENTRY CURFILE - WHICH FILE BRACKET. * NUMBERED[CURFILE] - WHETHER TO DO ANYTHING. * CURRENT - LINE AFTER WHICH TO ADD BLOCK. * DINCR - DEFAULT NUMBERING INCREMENT. * LINPTR3 - TARGET, SHOULD EQUAL CURRENT. * LINPTR1, LINPTR2 - INDICATE SIZE OF BLOCK. * LIMIT - ALSO INDICATES SIZE OF BLOCK. * LINNUM3 - SEQUENCE VALUE AT TARGET. * BOTF(CURFILE) - BOUNDS. * * EXIT VIA ERRJUMP IF IT CANNOT BE DONE. * INCR - NEW SEQUENCING INCREMENT. * LINENO - FIRST SEQUENCE MINUS INCR. * * CALLS GETLNUM, PUSH, FWDNUM, POP, MIN, MAX. * * USES LINNUM1, LINNUM2, LCOUNT. # IF NUMBERED[CURFILE] NQ 0 THEN BEGIN GETLNUM; IF WIDTHFOUND LQ 0 THEN BEGIN PUSH; BAKNUM; POP; END LINNUM1=MIN(LINNUM3,NINES); LINNUM1=MAX(LINNUM1,LINENO); IF CURRENT GQ BOTF(CURFILE)-1 THEN LINNUM2=NINES; ELSE BEGIN PUSH; FWDNUM; LINNUM2=LINENO; POP; END LINNUM2=MAX(LINNUM2,LINNUM1+1); LINNUM2=MIN(LINNUM2,NINES+1); LCOUNT=MIN(LIMIT,ABS(LINPTR2-LINPTR1)+1); # NEEDED # GETLNUM; IF LINNUM1 GR LINENO THEN # USER SPECIFIED START # BEGIN IF LCOUNT GR LINNUM2-LINNUM1 THEN ERRJUMP("NOT ENOUGH ROOM FOR INSERTION$"); INCR=(LINNUM2-LINNUM1)/LCOUNT; INCR=MAX(INCR,1); INCR=MIN(INCR,DINCR); LINENO=LINNUM1-INCR; END ELSE # COMPUTED START # BEGIN IF LCOUNT GQ LINNUM2-LINNUM1 THEN ERRJUMP("NOT ENOUGH ROOM FOR INSERTION$"); INCR=(LINNUM2-LINNUM1)/(LCOUNT+1); INCR=MAX(INCR,1); INCR=MIN(INCR,DINCR); LINENO=LINNUM1; END END IOEND # OF FITNUM # PROC SPLICE; IOBEGIN(SPLICE) # ** SPLICE - SPLICE PORTIONS OF LINES IN WORKFILE. * * SPLICE CONCATENATES TWO ADJACENT LINES IN THE FILE. THIS * ROUTINE IS DESIGNED TO BE EXECUTED AFTER DORANGE PROCESSING, * AS IT NO-OPS FOR ONE-LINE RANGES. IT ALSO DELETES IN THE * CASE THAT THE SPLICED LINE PAIR IS OF ZERO LENGTH. * * ENTRY LIN - LINE IMAGE FOR SECOND LINE. * CURFILE, CURRENT - ADDRESS OF SECOND LINE. * CHRPTR3 - IGNORED. * FIRSTRANGE, LASTRANGE - WHETHER AT BOUNDS OF RANGE. * (AS LEFT OVER FROM DORANGE) * * EXIT CHRPTR3 - UNCHANGED. * * CALLS BAKZ, PUSHTEMP, POPTEMP, DOJOIN, DELX, LENGTH. * * USES (WITH RESTORATION) - TEMP, CHRPTR3. # IF NOT (FIRSTRANGE AND LASTRANGE) THEN BEGIN # MULTIPLE STUBS TO MERGE # BAKZ; # TO CUT-DOWN FIRST LINE # PUSHTEMP; TEMP=CHRPTR3; CHRPTR3=0; # ASSURE DOJOIN IS SIMPLE # DOJOIN(0); # ADD ON CUT-DOWN LAST LINE # CHRPTR3=TEMP; # RESTORE CHRPTR3 # POPTEMP; END # DELETE MERGED LINE-PAIR IFF TOTALLY CUT DOWN # IF LENGTH(LIN) EQ 0 THEN BEGIN DELX; IF CURRENT GR TOPF(CURFILE) THEN BAKZ; END IOEND # OF SPLICE # PROC MAKEPAGE(PAGSIZ,FILEPARM); # COMPUTE PAGE BOUNDARIES # BEGIN # ** MAKEPAGE - COMPUTE BOUNDS FOR SECTION OF FILE. * * MAKEPAGE IS USED BY THE VIEW COMMAND IN LINE MODE TO * DETERMINE THE SECTION OF THE FILE TO BE PRINTED, BASED * ON RECENT USAGE OF VIEW COMMANDS. THE SCANNER IS CALLED * BEFORE MAKEPAGE. * * ENTRY LINCTR - NOMINAL ADDRESS TO PRINT. * PAGSIZ - DESIRED SIZE OF VIEW AREA. * FILEPARM - WHICH FILE BRACKET. * FORWARD, BACKWARD - FROM SCANNER. * PAGELAST - WHETHER LAST COMMAND WAS VIEW ALSO. * REGLINE[RNGTOPREG], REGLINE[RNGBOTREG] - LAST RANGE * PRINTED IF PAGELAST IS TRUE. * * EXIT LINPTR1, LINPTR2 - COMPUTED BOUNDARIES. * LINCTR - FORCED TO FIT IF NOT ALREADY. * * CALLS WINDOLIN. # ITEM PAGSIZ, FILEPARM; IF FORWARD THEN BEGIN IF PAGELAST THEN LINPTR1=REGLINE[RNGBOTREG]; ELSE LINPTR1=LINCTR; END ELSE IF BACKWARD THEN BEGIN IF PAGELAST THEN LINPTR1=REGLINE[RNGTOPREG]-PAGSIZ+1; ELSE LINPTR1=LINCTR-PAGSIZ+1; END ELSE LINPTR1=LINCTR-(PAGSIZ/2); WINDOLIN(LINPTR1,FILEPARM); # TO KEEP IN BOUNDS # LINPTR2=LINPTR1+PAGSIZ-1; WINDOLIN(LINPTR2,FILEPARM); # TO KEEP IN BOUNDS # IF LINCTR LS LINPTR1 OR LINCTR GR LINPTR2 THEN BEGIN IF BACKWARD THEN LINCTR=LINPTR1; ELSE LINCTR=LINPTR2; END WINDOLIN(LINCTR,FILEPARM); # MERELY AS STANDARD FOR CMD SKIP # END # OF MAKEPAGE # PROC SETMARK(POSITION,CURSOR); BEGIN # START OF SETMARK # # ** SETMARK - SET BOTH OR SECOND MARKER REGISTERS. * * SETMARK IS CALLED TO SET MARKER REGISTERS. IF NO OR BOTH * MARKERS ARE ALREADY FILLED, WE START OVER AND SET THE * FIRST ONE. IF THE FIRST HAS BEEN PREVIOUSLY SET, WE * SET THE SECOND ONE. IF THE FILE ASSOCIATION HAS CHANGED * BETWEEN SETTING THE FIRST AND SECOND, WE START OVER AND * SET THE FIRST ONE. ANY TIME WE SET THE FIRST ONE, WE * ALSO DEFAULT THE SECOND ONE TO MATCH THE FIRST. * * ENTRY POSITION - LINE ADDRESS TO MARK. * CURSOR - HORIZONTAL CURSOR POSITION TO MARK. * NUMMARKS - NUMBER OF PREVIOUS MARKS. * CURFILE - FILE BRACKET FOR POSITION AND CURSOR. * FDLF(CURFILE) - SETUP. * MRKFILE[0] - SETUP IF NUMMARKS IS ONE. * * EXIT NUMMARKS - UPDATED. * REGLINE[MARKREG] - SETUP IF FIRST MARK SET. * REGLINE[MARKREG+1] - SETUP IF SECOND MARK SET. * MRKFILE[1-2] - SETUP. * MRKCHAR[1-2] - SETUP. * * CALLS PAINTMARKS. # ITEM POSITION, CURSOR; IF (NUMMARKS GQ 2) OR (NUMMARKS EQ 1 AND MRKFILE[0] NQ FDLF(CURFILE)) THEN BEGIN PAINTMARKS(3); NUMMARKS=0; END REGLINE[MARKREG+NUMMARKS]=POSITION; REGLINE[MARKTOP+NUMMARKS]=TOPF(CURFILE); MRKFILE[NUMMARKS]=FDLF(CURFILE); MRKCHAR[NUMMARKS]=CURSOR; NUMMARKS=NUMMARKS+1; IF NUMMARKS EQ 2 THEN BEGIN IF REGLINE[MARKREG] GR POSITION OR (REGLINE[MARKREG] EQ POSITION AND MRKCHAR[0] GR CURSOR) THEN BEGIN REGLINE[MARKREG] = = REGLINE[MARKREG+1]; REGLINE[MARKTOP] = = REGLINE[MARKTOP+1]; MRKFILE[0] = = MRKFILE[1]; MRKCHAR[0] = = MRKCHAR[1]; END END ELSE BEGIN REGLINE[MARKREG+1]=REGLINE[MARKREG]; REGLINE[MARKTOP+1]=REGLINE[MARKTOP]; MRKFILE[1]=MRKFILE[0]; MRKCHAR[1]=MRKCHAR[0]; END PAINTMARKS(1); END # OF SETMARK # PROC FORCEFILE; IOBEGIN(FORCEFILE) # ** FORCEFILE - GET FILE INTO SOME BRACKET. * * FORCE FILE SPECIFIED BY READNAM TO BE OPEN FOR SYNTAX * SCANNERS WHICH NEED TO STUDY ITS BRACKETING. RETURN * FILNUM AS THE BRACKET IN WHICH THE FILE IS OPEN. WE USE * CURFILE AS THE BRACKET ONLY IF THE CURRENT FILE IS ONE AND * THE SAME AS THE REQUESTED FILE. IN ALL OTHER CASES WE USE * THE OPPOSITE BRACKET NUMBER. * * ENTRY CURFILE - BRACKET WHICH CANNOT BE DISTURBED. * READNAM - FILE WE MUST GET OPENED. * * EXIT FILNUM - THE BRACKET INTO WHICH READNAM IS OPEN. * * CALLS PUSH, OPENFILE, POP. * * USES CHARPARM, GETPARM. # FILNUM=CURFILE; IF READNAM EQ PADNAME(FILENAM[FILNUM]) THEN IORET FILNUM=FILNUM LXR 3; # FLIP BRACKET AND RESCAN # IF READNAM NQ PADNAME(FILENAM[FILNUM]) THEN BEGIN # OPEN INTO OTHER BRACKET # CHARPARM=0; GETPARM=0; PUSH; OPENFILE; POP; END IOEND # OF FORCEFILE # PROC REL2ABS(LINEPTR,FILEPTR); BEGIN # ** REL2ABS - CONVERT RELATIVE LINE ADDRESS TO ABSOLUTE. * * REL2ABS TAKES A LINE ADDRESS WHICH IS RELATIVE TO ITS * WORKFILE FILE IMAGE, AND CONVERTS TO AN ABSOLUTE WORKFILE * LINE ADDRESS, FOR ONE OF THE CURRENTLY BRACKETED FILES. * * ENTRY LINEPTR - RELATIVE LINE ADDRESS. * FILEPTR - WHICH BRACKET. * CURFILE - WHICH BRACKET IF FILEPTR IS ZERO. * TOPF() - SETUP. * * EXIT LINEPTR - CONVERTED. # ITEM LINEPTR, FILEPTR; IF LINEPTR LS 0 THEN RETURN; IF FILEPTR EQ 0 THEN LINEPTR=LINEPTR+TOPF(CURFILE); ELSE LINEPTR=LINEPTR+TOPF(FILEPTR); END # OF REL2ABS # PROC CHECKFILPTR; IOBEGIN(CHECKFILPTR) # ** CHECKFILPTR - CONVERT DIRECTORY ADDRESS TO BRACKET. * * CHECKFILPTR CONVERTS (MATCHES) A FILE DIRECTORY LINE * ADDRESS INTO A BRACKET NUMBER. IT IS A NO-OP FOR * ANY PARAMETER VALUE OF ZERO. IT OPENS THE FILE INTO * THE NON-CURRENT BRACKET IF NOT ALREADY BRACKETED. * * ENTRY FILPTR1 - FDLF POINTER OR ZERO. * FDLF(1-2) - SETUP. * CURFILE - CURRENT (NON-PREFERRED) BRACKET. * * EXIT FILPTR1 - CONVERTED TO BRACKET ORDINAL. * * CALLS PUSH, POSZ, SCANFDL, FORCEFILE, POP. * * USES READNAM, FILNUM. # IF FILPTR1 EQ 0 THEN IORET ELSE IF FILPTR1 EQ FDLF(1) AND FILPTR1 EQ FDLF(2) THEN FILPTR1=CURFILE; ELSE IF FILPTR1 EQ FDLF(1) THEN FILPTR1=1; ELSE IF FILPTR1 EQ FDLF(2) THEN FILPTR1=2; ELSE BEGIN PUSH; POSZ(FILPTR1); SCANFDL(READNAM); FORCEFILE; FILPTR1=FILNUM; POP; END IOEND # OF CHECKFILPTR # PROC EXTENDFILE(BOOL); BEGIN # * EXTENDFILE - EXTEND FILE FOR INSERT/COPY/MOVE. * * ENTRY EXTENDSIZE - HOW MUCH CURSOR BEYOND END OF FILE. * PROCESSNDX - WHETHER/WHICH INSERT/COPY/MOVE. * BOTF(FILNUM), FILNUM - END OF FILE. * LINPTR1, LINPTR2 - RANGE BOUNDARIES. * BOOL - WHETHER LINPTR1, LINPTR2 SHOULD RELOCATE. * * EXIT EXTENDSIZE - ZERO IF FILE EXTENDED. * THISEXTEND - FORMER VALUE OF EXTENDSIZE. * LINPTR1, LINPTR2, BOTF(FILNUM) - RELOCATED. * * CALLS INSX, POSZ. * * USES CURFILE(RESTORED). * * NOTE EXTENDFILE IS OPERATIVE ONLY IN SINGLE USER VERSION. * FOR MULTI, SCANNER MUST ASSURE THIS IS NO-OP. # ITEM BOOL B; CONTROL IFEQ SINGLE,1; IF EXTENDSIZE GR 0 THEN BEGIN IF PROCESSNDX EQ KEYST"CCMD" OR PROCESSNDX EQ KEYST"ICMD" OR PROCESSNDX EQ KEYST"MCMD" THEN BEGIN # EXTEND FILE TO TARGET # CURFILE = = FILNUM; # PRESERVE AND FLIPFLOP # POSZ(BOTF(CURFILE)-1); LINE[0]=NULLIN; FOR LINCTR=1 STEP 1 UNTIL EXTENDSIZE DO BEGIN # EXTEND FILE TO TARGET ADDR # # MANUALLY RELOCATE LINPTR1, LINPTR2 AS NEEDED # IF BOOL THEN BEGIN IF CURRENT LS LINPTR1 THEN LINPTR1=LINPTR1+1; IF CURRENT LS LINPTR2 THEN LINPTR2=LINPTR2+1; END INSX; # EXTEND FILE # END CURF(CURFILE)=CURRENT; THISEXTEND=EXTENDSIZE; EXTENDSIZE=0; CURFILE = = FILNUM; END END CONTROL FI; END # OF EXTENDFILE # PAGE # TOKEN -- SCANS COMMAND SYNTAX # PROC TOKEN; BEGIN # ** TOKEN - LOOK FOR NEXT SYNTAX ELEMENT. * * TOKEN SCANS THE COMMAND TEXT FROM SOME CURRENT POSITION * UNTIL SOMETHING IS SEEN. WE EAT BLANKS, AND MUST * EVENTUALLY REACH SOME DELIMITER OR A CONSTANT (INTEGER) OR * A KEYWORD. IF IT IS A CONSTANT, WE DECODE ITS WHOLE VALUE * AND LEAVE THE CURRENT POSITION JUST AFTER THE LAST DIGIT. * IF IT IS A KEYWORD, WE GATHER UP ITS WHOLE TEXT, LEAVE THE * CURRENT POSITION JUST AFTER THE LAST LETTER, AND SEARCH * THE COMMAND TABLES FOR A MATCH, SETTING VARIOUS VARIABLES * TO SHOW THE RESULT OF THE MATCH. * * WE ARE CALLED BY THE OUTER LOGIC OF PROCESS TO GLEAN OUT * COMMAND KEYWORDS. WE ARE CALLED BY ALL SORTS OF PEOPLE, * INCLUDING A VARIETY OF COMMAND PROCESSING ROUTINES, TO * ADVANCE THE SYNTAX SCAN TO COMPLETE THE COMMAND. * * ENTRY SCANPOS - WHERE TO SCAN IN CMDLIN. * CMDLIN - COMMAND TEXT, INTERNAL LINE IMAGE. * SEARCHTYPE - WHICH IF ANY KEYWORD TABLE TO MATCH. * * EXIT TOKENPOS - WHERE WE FOUND SOMETHING. * TOKENTYPE - CLASSIFICATION OF TOKEN. * TOKENVAL - BINARY VALUE IF NUMERIC. * TOKENSYM - KEYWORD IF ALPHA. * TOKENCHAR - FIRST OR ONLY CHARACTER OF TOKEN. * TOKENLEN - NUMBER OF CHARACTERS IN TOKEN. * KEYWDNDX - WHICH KEYWORD MATCHED IT. * SCANPOS - INCREMENTED BEYOND TOKEN. * CMDLIN - ANY MICROS ARE EXPANDED. * * MACROS GETCHAR. * * CALLS LENGTH, EXPAND, DSPLCOD. # ITEM TMP1, TMP2, TMP3; ITEM QUIT B; ITEM CMDLEN; # TOKENSW MUST MATCH TYPST # SWITCH TOKENSW TKDIGIT, TKPLUS, TKMINUS, TKDELIMIT, TKCOLON, TKPAREN, TKEQUAL, TKLETTER, TKSEMI, TKEOL, TKOTHER, TKCONTROL; # ALPHANUM MUST MATCH KEYWDTYPE VALUES # ITEM ALPHANUM=O"42000000000000000000"; # WHICH TYPES ALLOW DIGITS # PAGE # START OF TOKEN # TOKENSTART: # FIRST EAT ANY BLANKS # CMDLEN=LENGTH(CMDLIN); GETCHAR(CMDLINE,SCANPOS,TMP1); WHYLE TMP1 EQ CBLANK DO BEGIN SCANPOS=SCANPOS+1; GETCHAR(CMDLINE,SCANPOS,TMP1); END # EAT ONE COMMA # IF TMP1 EQ CCOMMA THEN SCANPOS=SCANPOS+1; GETCHAR(CMDLINE,SCANPOS,TMP1); WHYLE TMP1 EQ CBLANK DO # EAT ADDITIONAL BLANKS # BEGIN SCANPOS=SCANPOS+1; GETCHAR(CMDLINE,SCANPOS,TMP1); END # SET UP TOKEN DESCRIPTORS # # DISPATCH FOR TOKEN # TOKENPOS=SCANPOS; TOKENCHAR=TMP1; IF SCANPOS GQ CMDLEN OR TMP1 EQ CCOMMA THEN TOKENCHAR=CENDLINE; TOKENTYPE=TYPE[TOKENCHAR]; SCANPOS=SCANPOS+1; GOTO TOKENSW[TOKENTYPE]; # END-OF-LINE AND NULL CASES # TKEOL: TKEQUAL: TKPLUS: TKSEMI: TKCOLON: TKDELIMIT: TKPAREN: TKOTHER: TKCONTROL: RETURN; TKMINUS: # HYPHEN IS SELF IF ALONE, COMMENT IF DOUBLE # GETCHAR(CMDLINE,TOKENPOS+1,TMP1); IF TMP1 EQ CMINUS THEN BEGIN TOKENTYPE=TYPST"EOL"; TOKENCHAR=CENDLINE; TOKENPOS=LENGTH(CMDLIN); SCANPOS=TOKENPOS; END RETURN; # NUMERIC CONSTANT # TKDIGIT: IF BALPHANUM NQ 0 THEN GOTO TKLETTER; TOKENVAL=TOKENCHAR-CDIGIT0; QUIT=FALSE; WHYLE NOT QUIT DO BEGIN GETCHAR(CMDLINE,SCANPOS,TMP1); IF TYPE[TMP1] EQ TYPST"DIGIT" AND SCANPOS-TOKENPOS LQ 10 THEN BEGIN TOKENVAL=TOKENVAL*10+TMP1-CDIGIT0; SCANPOS=SCANPOS+1; END ELSE QUIT=TRUE; END RETURN; # ALPHABETIC KEYWORD # TKLETTER: # GATHER UP KEYWORD, SUPPRESS CASE AND USE REGULAR CHAR # TMP1=TOKENCHAR; TOKENLEN=0; QUIT=FALSE; WHYLE NOT QUIT DO BEGIN DSPLCOD(TMP1); IF TOKENLEN LS 10 THEN BEGIN CTOKENSYM=C<9,1>TMP1; TOKENLEN=TOKENLEN+1; END GETCHAR(CMDLINE,SCANPOS,TMP1); IF TYPE[TMP1] NQ TYPST"LETTER" THEN BEGIN IF TYPE[TMP1] NQ TYPST"DIGIT" OR BALPHANUM EQ 0 THEN BEGIN QUIT=TRUE; TEST; END END SCANPOS=SCANPOS+1; END # KEYWORD SEARCH # KEYWDNDX=-1; IF KEYWDTYPE EQ 0 THEN RETURN; MATCHKEY(TMP3); IF KEYWDNDX LS 0 THEN RETURN; TMP3=MIN(TMP3,TOKENLEN); SCANPOS=TOKENPOS+TMP3; TOKENLEN=TMP3; END # OF TOKEN # PAGE # SCANNER - UNIVERSAL SYNTAX DRIVER # PROC SCANNER; IOBEGIN(SCANNER) # ** SCANNER - MASTER COMMAND SYNTAX SCANNER/DEFAULTER. * * SCANNER DRIVES ALL SYNTAX SCANNING FOR THOSE COMMANDS * WHICH HAVE FAIRLY STANDARD SYNTACTICAL RULES AND SEMANTIC * ELEMENTS. THIS CATEGORY OF COMMANDS INCLUDES ALL WHICH * USE RANGES, LINES, POSITIONS, LIMITS, AND TABS. OTHER * SYNTAXES SUPPORTED BY SCANNER INCLUDE "FORWARD" AND * "BACKWARD" KEYWORD, I.E., DIRECTION/DEFAULT-RANGE, AND * CHARACTER STRINGS. ON THE OTHER HAND, SCANNER IS NOT * DESIGNED TO SUPPORT PARSING OF COMMANDS SUCH AS "SET" * WHICH REQUIRE SPECIAL KEYWORDS, ARBITRARY SYMBOL NAMES, OR * INTEGER PARAMETERS. * * SCANNER OPERATES AS A LOOP UNTIL END OF COMMAND LINE OR * END OF COMMAND DELIMITER (SEMICOLON), BRANCHING OUT ON A * CASE STATEMENT FOR EACH TOKEN ENCOUNTERED. VARIOUS SCAN * SUBROUTINES ARE USED HEAVILY. * * ENTRY COMMAND VERB SCANNED, TOKEN ADVANCED. * TOKENPOS - SETUP. * THE FOLLOWING MUST BE DEFAULTED BY CALLER - * NONDEFAULT, TXTINCMD, BACKWARD, FORWARD, * FOUND, CURRENT, CURFILE, CURSPLIT. * LIMIT - DEFAULT LIMIT COUNT. USUALLY -1 TO SHOW * THAT NORMAL DEFAULTS CAN APPLY. CAN ALSO BE * -2 TO SHOW NO DEFAULTS TO BE SUPPLIED. * WHICHLIN - WHICH LINE POINTER VARIABLE EXPECTED. * WHICHSTR - WHICH STRING VARIABLE EXPECTED. * CURCURSOR, OLDCURSOR - RESIDUAL CURSOR POSITIONS. * OLDLINPTR - RESIDUAL LINE POINTER. * EXECNDX - WHICH COMMAND WE ARE PROCESSING. * NUMMARKS - HOW MANY MARKS ARE AVAILABLE. * SCREENMODE - WHETHER SCREEN OR LINE. * TOPF(), TOPS(), BOTS(), ASCII[] - SETUP. * BOTF(), FDLF() - SETUP. * * EXIT LINPTR1,2,3 - SOURCE AND TARGET ADDRESSES. * FILPTR1,2,3 - SOURCE AND TARGET FILE BRACKETS. * CHRPTR1,2,3 - SOURCE AND TARGET CURSORS. * LINNUM1,2,3 - SOURCE AND TARGET SEQUENCES. * LIMIT - REPEAT COUNT. UNCHANGED IF NO EXPLICIT SYNTAX * AND DEFAULT WAS -2. * SCANBLOCK, SCANWORD, SCANUPPER - SPECIAL OPTIONS. * SCANHOME - SPECIAL OPTION. * NONDEFAULT - TRUE IF SOMETHING SCANNED. * SCANPOS - ADVANCED BEYOND LAST RECOGNIZABLE SYNTAX. * BACKWARD, FORWARD - POSSIBLY SET. * CHARRANGE - CHARACTER/LINE RANGE BOUNDS. * TXTINCMD - POSSIBLY TRUE. * FOUND - WHETHER SOURCE/TARGET IN BOUNDS. * FDLF(1-2) - DIFFERENT FILES MAY BE OPEN. * CURFILE - FILE TO PROCESS FOR SOURCE RANGE. * PROMPTING - POSSIBLY SET. * LOCSTRING1, LOCSTRING2, CHGSTRING, TTYLIN - POSSIBLY * FILLED WITH CHARACTER STRINGS IN INTERNAL FORMAT. * TABVECTOR - POSSIBLY REDEFINED. * FIELDNDX, FIELDFLG, FIELDTARGET - POSSIBLY SET. * NUMMARKS - POSSIBLY CLEARED. * EXECNDX - CERTAIN CHANGES POSSIBLE. * * USES ALL TOKENXXXX VARIABLES, WHICHLIN, WHICHDGT, WHICHSTR, * FILNUM, FORCEFIELD, READNAM, FOUNDOTHER. * * CALLS TOKEN, SCNTAB, MAX, SCNLIN, ERRJUMP, SCANSTR, * SCNFILE, FORCEFILE, GETMARK, PAINTMARKS, SCNEOC, * CHECKFILPTR, REL2ABS, WINDOPOS, WINDOLIN, SQUELCH. # XREF LABEL QQSINGLE; # SCANSW MUST MATCH TYPST # SWITCH SCANSW SCDIGIT, SCPLUS, SCMINUS, SCDELIMIT, SCCOLON, SCPAREN, SCEQUAL, SCALPHA, SCSEMI, SCEOL, SCOTHER, SCCTRL; # KEYMATCH ARRAY MUST MATCH SECTION OF KEYSTR TABLE # # MUST ALSO MATCH SCANKEYSW. # DEF NUMSCANKEYS #20#; ARRAY MATCHKEYS [0:NUMSCANKEYS]; ITEM KEYMATCH C(0,0,10) = [ "ALL", "BLANK", "CURRENT", "END", "FIRST", "HOME", "IN", "LAST", "MARK", "NEXT", "PREVIOUS", "QUIET", "REPEAT", "SCREEN", "TO", "UPPER", "WORD", "X", "Y", "Z" ]; SWITCH SCANKEYSW SKALL, SKBLOCK, SKCURRENT, SKEND, SKFIRST, SKHOME, SKIN, SKLAST, SKMARK, SKNEXT, SKPREVIOUS, SKQUIET, SKREPEAT, SKSCREEN, SKTO, SKUPPER, SKWORD, SKX, SKY, SKZ; # FOLLOWING TEMPORARIES MUST BE USED ONLY INSTANTANEOUSLY # ITEM TMP1, TMP2, BOOL B; PROC GETMARK(WHICH,LINPARM,FILPARM,CHRPARM); BEGIN # ** GETMARK - GET DATA FOR A MARKER. * * ENTRY WHICH - WHICH MARKER, 1 OR 2. * * EXIT LINPARM, FILPARM, CHRPARM - MARKER VALUES. * CHARRANGE - FORCED TRUE AS NEEDED. # ITEM WHICH, LINPARM, FILPARM, CHRPARM; LINPARM=REGLINE[MARKREG-1+WHICH]-REGLINE[MARKTOP-1+WHICH]; FILPARM=MRKFILE[WHICH-1]; CHRPARM=MRKCHAR[WHICH-1]; IF CHRPARM GQ 0 THEN CHARRANGE=TRUE; END # OF GETMARK # PAGE # SCANNER - MAIN CODE # CHRPTR1=-1; CHRPTR2=-1; CHRPTR3=-1; LINPTR1=-1; LINPTR2=-1; LINPTR3=-1; FILPTR1=0; FILPTR2=0; FILPTR3=0; LINNUM1=-1; LINNUM2=-1; LINNUM3=-1; SCANBLOCK=FALSE; SCANWORD=FALSE; SCANUPPER=FALSE; SCANHOME=FALSE; SCANMARK = FALSE; SCANSFILE = FALSE; SCANTO = FALSE; SCNLINX = FALSE; SCNLINY = FALSE; SCNLINZ = FALSE; SCNONCE = FALSE; SCHSTRSPEC=FALSE; WHICHDGT=WHICHLIN; KEYWDTYPE=2; SCANPOS=TOKENPOS; FORCEFIELD=FALSE; FIELDTARGET=0; # FILE EXTENSION IS ONLY ALLOWED IN SINGLE USER VERSION # # FOR THREE SPECIFIC COMMAND TYPES # IF EXTENDSIZE NQ 0 THEN BEGIN IF OKEXTEND[PROCESSNDX] THEN BEGIN CONTROL IFEQ MULTI,1; GOTO QQSINGLE; CONTROL FI; END ELSE BEGIN EXTENDSIZE=0; END END PAGE # MAIN SCANNER LOOP STARTS HERE # SCANTOKEN: TOKEN; SCANLOOP: GOTO SCANSW[TOKENTYPE]; SCDIGIT: IF WHICHDGT EQ DIGITST"LIMIT" THEN BEGIN LIMIT=MAX(TOKENVAL,1); NONDEFAULT=TRUE; TOKEN; WHICHDGT=WHICHLIN; END ELSE SCNLIN; GOTO SCANLOOP; SCPLUS: SCMINUS: SCNLIN; GOTO SCANLOOP; SCCOLON: WHICHLIN=2; WHICHDGT=2; GOTO SCANTOKEN; SCPAREN: SCNLIN; GOTO SCANLOOP; SCDELIMIT: IF WHICHSTR LQ 0 THEN ERRJUMP("STRING NOT ALLOWED$"); IF NOT FORCEFIELD THEN BEGIN FIELDFLG=FALSE; FIELDNDX=0; END SCANSTR; GOTO SCANLOOP; SKALL: IF WHICHDGT EQ DIGITST"LIMIT" THEN BEGIN LIMIT=LARGENUM; TOKEN; END ELSE BEGIN IF LINPTR1 NQ -1 OR LINPTR2 NQ -1 THEN BEGIN ERRJUMP("ONLY ONE RANGE ALLOWED$"); END FILNUM=CURFILE; TOKEN; IF TOKENTYPE EQ TYPST"PAREN" THEN BEGIN SCNFILE(READNAM); SCANSFILE = TRUE; # NOTE THAT WE HAVE SCANNED # FORCEFILE; END LINPTR1=1; LINPTR2=BOTF(FILNUM)-1-TOPF(FILNUM); FILPTR1=FDLF(FILNUM); WHICHLIN=3; WHICHDGT=WHICHLIN; NONDEFAULT=TRUE; END GOTO SCANLOOP; SKBLOCK: SCANBLOCK=TRUE; GOTO SCANTOKEN; SKEND: IF OKEND[PROCESSNDX] THEN EXECNDX=EXECST"APPEND"; ELSE ERRJUMP("CHARACTER SEQUENCE NOT RECOGNIZED$"); GOTO SCANTOKEN; SKHOME: IF OKHOME[PROCESSNDX] THEN SCANHOME=TRUE; ELSE ERRJUMP("CHARACTER SEQUENCE NOT RECOGNIZED$"); GOTO SCANTOKEN; SKPREVIOUS: IF OKMOVE[PROCESSNDX] AND WHICHLIN GR 3 THEN BEGIN # NOTE "TO PREVIOUS" IS A SPECIAL CASE FOR COPY/MOVE WITH NO # # ADDITIONAL SYNTAX ALLOWED, AND SEMANTICS DETERMINED BY # # CHARACTER VERSUS LINE BOUNDARIES FOR SOURCE RANGE # IF NOT CHARRANGE THEN BEGIN FILNUM=CURFILE; EXTENDFILE(FALSE); LINPTR3=CURRENT-TOPF(CURFILE)-1; END END ELSE BEGIN IF FORWARD OR BACKWARD THEN ERRJUMP("ONLY ONE RANGE ALLOWED$"); WHICHDGT=DIGITST"LIMIT"; NONDEFAULT=TRUE; IF LIMIT EQ -1 THEN LIMIT=1; BACKWARD=TRUE; FORWARD=FALSE; END GOTO SCANTOKEN; SKCURRENT: SKFIRST: SKLAST: SKX: SKY: SKZ: # NOTE SCNLIN CAN ENABLE CHARRANGE FOR X,Y,Z # SCNLIN; GOTO SCANLOOP; SKMARK: SCANMARK = TRUE; IF CMDWASDLTE[0] THEN BEGIN # IF COMMAND WAS "DELETE" # KILLMARKS = TRUE; # KILL THE MARKS # FORCEAUTOP[0] = FALSE; FORCEAUTOR[0] = FALSE; END IF NUMMARKS NQ 0 THEN BEGIN # NOTE GETMARK ROUTINE CAN ENABLE CHARRANGE # IF WHICHLIN EQ 3 THEN GETMARK(1,LINPTR3,FILPTR3,CHRPTR3); ELSE BEGIN GETMARK(1,LINPTR1,FILPTR1,CHRPTR1); GETMARK(2,LINPTR2,FILPTR2,CHRPTR2); END NONDEFAULT=TRUE; NUMMARKS = 2; END WHICHLIN=3; WHICHDGT=WHICHLIN; IF NOT FORCEFIELD THEN BEGIN # IF NO *IN* OPTION ON THIS COMMAND # FIELDNDX = 0; # ELIMINATE TAB FIELD RESTRICTION # FIELDFLG = FALSE; END GOTO SCANTOKEN; SKNEXT: IF OKMOVE[PROCESSNDX] AND WHICHLIN GR 3 THEN BEGIN # NOTE "TO NEXT" IS A SPECIAL CASE FOR COPY/MOVE WITH NO # # ADDITIONAL SYNTAX ALLOWED, AND SEMANTICS DETERMINED BY # # CHARACTER VERSUS LINE BOUNDARIES FOR SOURCE RANGE # IF NOT CHARRANGE THEN BEGIN FILNUM=CURFILE; EXTENDFILE(FALSE); LINPTR3=CURRENT-TOPF(CURFILE); END END ELSE BEGIN IF FORWARD OR BACKWARD THEN ERRJUMP("ONLY ONE RANGE ALLOWED$"); WHICHDGT=DIGITST"LIMIT"; IF LIMIT EQ -1 THEN LIMIT=1; FORWARD=TRUE; BACKWARD=FALSE; NONDEFAULT=TRUE; END GOTO SCANTOKEN; SKQUIET: DONTPRINT=TRUE; GOTO SCANTOKEN; SKREPEAT: NONDEFAULT=TRUE; IF LIMIT EQ -1 THEN LIMIT=1; WHICHDGT=DIGITST"LIMIT"; GOTO SCANTOKEN; SKSCREEN: IF LINPTR1 NQ -1 OR LINPTR2 NQ -1 THEN BEGIN ERRJUMP("ONLY ONE RANGE ALLOWED$"); END IF SCREENMODE THEN BEGIN LINPTR1=TOPS(CURSPLIT)+1-TOPF(CURFILE); LINPTR2=BOTS(CURSPLIT)-1-TOPF(CURFILE); IF WHICHLIN GQ 3 THEN BEGIN LINPTR3=LINPTR2; IF BACKWARD THEN LINPTR3=LINPTR1; END NONDEFAULT=TRUE; DONTPRINT=TRUE; END ELSE ERRJUMP("SCREEN MODE REQUIRED$"); WHICHLIN=3; WHICHDGT=WHICHLIN; GOTO SCANTOKEN; SKIN: WHICHDGT=DIGITST"TAB"; TOKEN; # ADVANCE NEXT SYNTAX # SCNTAB; # ANALYZE AND SET *IN* MARGINS # GOTO SCANLOOP; SKTO: IF NOT OKTARGET[PROCESSNDX] THEN BEGIN ERRJUMP("PARAMETER NOT VALID FOR THIS DIRECTIVE$"); END SCANTO = TRUE; SCNONCE = FALSE; WHICHLIN=4; WHICHDGT=WHICHLIN; NONDEFAULT=TRUE; GOTO SCANTOKEN; SKWORD: SCANWORD=TRUE; GOTO SCANTOKEN; SKUPPER: SCANUPPER=TRUE; IF NOT OKUPPER[PROCESSNDX] THEN BEGIN ERRJUMP("PARAMETER NOT VALID FOR THIS DIRECTIVE$"); END GOTO SCANTOKEN; SCALPHA: FOR TMP1=0 STEP 1 WHILE KEYWDNDX GQ 0 AND TMP1 LQ NUMSCANKEYS DO BEGIN IF KEYMATCH[TMP1] EQ KEYWORD[KEYWDNDX] THEN GOTO SCANKEYSW[TMP1]; END ERRJUMP("CHARACTER SEQUENCE NOT RECOGNIZED$"); SCSEMI: SCEOL: SCOTHER: SCCTRL: SCEQUAL: # VERIFY END OF SYNTAX # SCNEOC; # VERIFY SOURCE RANGE WITHIN ONE FILE, AND CONVERT FILE SELECTIONS # # FROM FILE DIRECTORY IDS INTO OPEN BRACKET ORDINALS # IF FILPTR2 NQ 0 THEN BEGIN IF FILPTR1 NQ 0 AND FILPTR1 NQ FILPTR2 THEN ERRJUMP("RANGE MUST BE IN SAME FILE$"); FILPTR1=FILPTR2; END CHECKFILPTR; # CONVERT FILPTR1 # FILPTR2=FILPTR1; # AND FILPTR2 ALSO # # VERIFY THAT BOTH FILES FOR A DUAL-FILE OPERATION CAN BE # # OPENED INTO THE TWO BRACKETS, AND CONVERT TARGET FILE SELECTION # # FROM FILE DIRECTORY ID INTO OPEN BRACKET ORDINAL # IF FILPTR1 NQ 0 AND FILPTR3 NQ 0 AND FILPTR1 NQ FILPTR3 THEN CURFILE=FILPTR1; # ASSURE NEEDED FILES AVAIL # FILPTR1 = = FILPTR3; CHECKFILPTR; # CONVERT FILPTR3 # FILPTR3 = = FILPTR1; IF FILPTR3 EQ 0 THEN FILPTR3=CURFILE; # CONVERT LINPTRS TO ABSOLUTE WORKFILE ORDINALS # REL2ABS(LINPTR1,FILPTR1); REL2ABS(LINPTR2,FILPTR2); REL2ABS(LINPTR3,FILPTR3); # NOW FILL IN DEFAULTS # IF LIMIT EQ -1 THEN BEGIN IF LINPTR2 EQ -1 THEN LIMIT=1; ELSE LIMIT=LARGENUM; END IF LINPTR1 EQ -1 THEN BEGIN CHRPTR1=0; IF FORWARD AND NOT OKSEARCH[PROCESSNDX] THEN LINPTR1=CURRENT+1; ELSE IF BACKWARD THEN BEGIN IF OKSEARCH[PROCESSNDX] THEN BEGIN LINPTR1=CURRENT; IF CURCURSOR GR 0 THEN CHRPTR1=CURCURSOR-1; ELSE BEGIN CHRPTR1=BUFCM1; LINPTR1=CURRENT-1; END END ELSE LINPTR1=CURRENT-1; END ELSE BEGIN LINPTR1=CURRENT; IF SCANWORD OR CHARRANGE THEN CHRPTR1=CURCURSOR; IF OKSEARCH[PROCESSNDX] THEN BEGIN CHRPTR1=CURCURSOR; IF LASTPROCESS EQ PROCESSNDX AND (NOT(SCHSTRSPEC) OR FORWARD) AND CURCURSOR EQ OLDCURSOR AND LINPTR1 EQ OLDLINPTR THEN CHRPTR1=CHRPTR1+STRINGLEN; END END FILPTR1=CURFILE; END IF LINPTR2 EQ -1 THEN BEGIN FILNUM=FILPTR1; IF FILNUM EQ 0 THEN FILNUM=CURFILE; IF BACKWARD THEN LINPTR2=TOPF(FILNUM)+1; ELSE LINPTR2=BOTF(FILNUM)-1; END IF LINPTR3 EQ -1 THEN BEGIN FILNUM=FILPTR3; EXTENDFILE(TRUE); LINPTR3=CURRENT; CHRPTR3=CURCURSOR; END IF OKSEARCH[PROCESSNDX] AND (BACKWARD OR LINPTR1 GR LINPTR2) THEN BEGIN IF CHRPTR1 LS 0 THEN CHRPTR1=BUFCM1; IF CHRPTR2 LS 0 THEN CHRPTR2=0; END CHRPTR1=MAX(CHRPTR1,0); IF CHRPTR2 LS 0 THEN CHRPTR2=BUFCM1; IF CHRPTR2 EQ 0 AND NOT (CHARRANGE OR OKSEARCH[PROCESSNDX]) THEN CHRPTR2=BUFCM1; IF CHRPTR3 LS 0 THEN BEGIN IF CHARRANGE THEN CHRPTR3=CURCURSOR; ELSE CHRPTR3=0; END WINDOPOS(LINPTR3,FILPTR3); # SINGLE USER VERSION ONLY MUST MAKE FILE EXTENSION EXACT # CONTROL IFEQ SINGLE,1; IF THISEXTEND NQ 0 THEN BEGIN PUSH; CURFILE=FILPTR3; WHYLE LINPTR3 LS BOTF(FILPTR3)-1 AND THISEXTEND GR 0 DO BEGIN POSZ(BOTF(FILPTR3)-1); DELX; THISEXTEND=THISEXTEND-1; IF CURRENT LS LINPTR1 THEN LINPTR1=LINPTR1-1; IF CURRENT LS LINPTR2 THEN LINPTR2=LINPTR2-1; END POP; END WINDOPOS(LINPTR3,FILPTR3); CONTROL FI; IF FILPTR1 EQ 0 THEN FILPTR1=CURFILE; CURFILE=FILPTR1; WINDOLIN(LINPTR1,CURFILE); FOUNDOTHER=FOUND; WINDOLIN(LINPTR2,CURFILE); FOUND=FOUND AND FOUNDOTHER; IF LINPTR1 GR LINPTR2 OR (LINPTR1 EQ LINPTR2 AND CHRPTR1 GR CHRPTR2) THEN BEGIN BACKWARD=TRUE; LINPTR1 = = LINPTR2; CHRPTR1 = = CHRPTR2; END IF BACKWARD AND NOT OKREVERSE[PROCESSNDX] THEN BEGIN BACKWARD=FALSE; IF LIMIT LS LARGENUM THEN LINPTR1=MAX(LINPTR1,LINPTR2-MAX(LIMIT,1)+1); END IF WHICHSTR NQ 0 AND ASCII[CURFILE] LQ 1 THEN BEGIN SQUELCH(LOCSTRING1); SQUELCH(LOCSTRING2); SQUELCH(CHGSTRING1); SQUELCH(TTYLIN); END IOEND # OF SCANNER # PAGE # SCAN STUFF -- SCNLIN # PROC SCNLIN; IOBEGIN(SCNLIN) # ** SCNLIN - SCAN LINE ADDRESS SYNTAX. * * SCNLIN IS CAPABLE OF PARSING ONE LINE ADDRESS EXPRESSION. * IT IS INTENDED TO BE CALLED ONLY BY SCANNER. SCNLIN * ASSUMES THE CALLER HAS POSITIONED THE TOKEN AT A * GENUINE LINE ADDRESS EXPRESSION. * * ENTRY WHICHLIN - WHICH LINE PARAMETER TO SET. * LINPTR1,2,3 - POSSIBLE PARAMETERS. * CHRPTR1,2,3 - DITTO. * FILPTR1,2,3 - DITTO. * LINNUM1,2,3 - DITTO. * CURFILE - DEFAULT FILE BRACKET. * TOKENPOS, SCANPOS - BRACKET CURRENT SYNTAX. * CURF(), TOPF(), BOTF() - SETUP. * NUMBERED[] - SETUP. * REGLINE[XYZREG], REGLINE[XYZTOP] - SETUP. * XYZCHAR[], XYZFILE[] - SETUP. * * EXIT ONE SET OF LINPTRX, CHRPTRX, FILPTRX, LINNUMX - * DESCRIBE SCANNED EXPRESSION. * OTHER SETS OF LINPTRX, CHRPTRX, FILPTRX, LINNUMX - * USED TEMPORARILY THEN RESTORED. * IF FILPTRX SET, IN FDLF FORMAT NOT BRACKET. * FILE BRACKETS POSSIBLY RE-OPENED. * CHARRANGE - CAN BE FORCED TRUE FOR X,Y,Z. * PAGELAST - FALSE. * NONDEFAULT - TRUE. * WHICHLIN - INCREMENTED. * WHICHDGT - MATCHES WHICHLIN. * SCANPOS, TOKENPOS - ADVANCED BEYOND SYNTAX. * * USES READNAM, FILNUM, ORIGSCNLIN, TEMP(RESTORES), * ALL TOKENXXXX VARIABLES. * * CALLS PUSHTEMP, MIN, SCNFILE, ERRJUMP, FORCEFILE, * TOKEN, PUSH, POSN, POP, POPTEMP. # # SCNLINSW MUST MATCH TYPST. SLKEYSW MATCHES LINEKEYWD. # SWITCH SCNLINSW SLDIGIT, SLPLUS, SLMINUS, SLDELIMIT, SLCOLON, SLPAREN, SLEQUAL, SLLETTER, SLSEMI, SLEOL, SLOTHER, SLCONTROL; SWITCH SLKEYSW SLCURRENT, SLFIRST, SLLAST, SLX, SLY, SLZ; ARRAY LINEKEYS[0:5]; ITEM LINEKEYWD C(0,0,10) = [ "CURRENT", "FIRST", "LAST", "X", "Y", "Z" ]; ITEM TMP1; # CAN BE USED ONLY INSTANTANEOUSLY # WHICHLIN=MIN(WHICHLIN,3); IF WHICHLIN NQ 2 THEN ORIGSCNLIN=TOKENPOS; FILNUM=CURFILE; NONDEFAULT=TRUE; PAGELAST=FALSE; # SINCE NON-DEFAULT USED # PUSHTEMP; # ALLOCATE TEMP VARIABLE FOR SCRATCH # IF WHICHLIN EQ 2 THEN BEGIN IF FILPTR1 NQ 0 AND FDLF(CURFILE) NQ FILPTR1 THEN FILNUM=CURFILE LXR 3; LINPTR1 == LINPTR2; FILPTR1 == FILPTR2; LINNUM1 == LINNUM2; CHRPTR1 == CHRPTR2; END ELSE IF WHICHLIN EQ 3 THEN BEGIN LINPTR1 == LINPTR3; FILPTR1 == FILPTR3; LINNUM1 == LINNUM3; CHRPTR1 == CHRPTR3; END CHRPTR1=0; # DEFAULT CHARACTER POINTERS # IF WHICHLIN EQ 2 THEN CHRPTR1=BUFCM1; SCNLINLOOP: # THIS IS THE MAIN LOOP # GOTO SCNLINSW[TOKENTYPE]; # DISPATCH BY SYNTAX # SLDELIMIT: SLCOLON: SLSEMI: SLEOL: SLOTHER: SLCONTROL: SLEQUAL: GOTO SLDONE; SLPAREN: # SCAN FILE NAME. IF MATCHES CURRENT FILE, WE CAN CONTINUE # # SCANNING. IF NOT, WE MUST ACCESS FILE AND RE-START ENTIRE# # SCAN SO THAT RELOCATABLE VALUES WILL BE FRESH. # IF SCANSFILE THEN BEGIN # IF ALREADY SCANNED SOURCE # IF NOT SCANTO THEN BEGIN # IF NO *TO* # ERRJUMP ("*TO* REQUIRED BEFORE DESTINATION FILE$"); END END SCNFILE(READNAM); IF READNAM NQ PADNAME(FILENAM[FILNUM]) THEN BEGIN IF WHICHLIN EQ 2 THEN BEGIN WHICHLIN=1; LINPTR2=-1; FILPTR2=0; LINNUM2=-1; CHRPTR2=-1; END FORCEFILE; LINPTR1=CURF(FILNUM)-TOPF(FILNUM); FILPTR1=FDLF(FILNUM); # ASSURE ONLY ONE MORE TRY # IF SCNONCE THEN BEGIN # IF ERROR IN SYNTAX # TMP1 = 0; IF SCNLINZ THEN TMP1 = O"32"; IF SCNLINY THEN TMP1 = O"31"; IF SCNLINX THEN TMP1 = O"30"; IF TMP1 EQ 0 THEN BEGIN # IF NOT *XYZ* ERROR # TOKENPOS = ORIGSCNLIN; ERRJUMP ("ONLY ONE RANGE ALLOWED$"); END GOTO SLERROR; END SCNONCE = TRUE; SCANPOS=ORIGSCNLIN; # FORCE ENTIRE EXPRESSION RESCAN # TOKEN; GOTO SCNLINLOOP; END ELSE BEGIN SCANSFILE = TRUE; IF NOT SCANTO THEN BEGIN # IF NOT TARGET FILE # TMP1 = 0; IF SCNLINZ AND XYZFILE[2] NQ FDLF(FILNUM) THEN TMP1 = O"32"; IF SCNLINY AND XYZFILE[1] NQ FDLF(FILNUM) THEN TMP1 = O"31"; IF SCNLINX AND XYZFILE[0] NQ FDLF(FILNUM) THEN TMP1 = O"30"; IF TMP1 NQ 0 THEN GOTO SLERROR; END END GOTO SLDONE; SLCURRENT: IF WHICHLIN EQ 3 THEN EXTENDFILE(FALSE); LINPTR1=CURF(FILNUM)-TOPF(FILNUM); SLCUR2: FILPTR1=FDLF(FILNUM); SLCUR3: TOKEN; # TO GLEAN OUT MORE # SLCUR4: IF TOKENTYPE EQ TYPST"PLUS" THEN GOTO SLPLUS2; IF TOKENTYPE EQ TYPST"MINUS" THEN GOTO SLMINUS2; GOTO SLDONE; SLFIRST: LINPTR1=1; GOTO SLCUR2; # MORE SYNTAX?? # SLLAST: LINPTR1=BOTF(FILNUM)-1-TOPF(FILNUM); GOTO SLCUR2; # MORE SYNTAX?? # SLPLUS: IF WHICHLIN EQ 3 THEN EXTENDFILE(FALSE); LINPTR1=CURF(FILNUM)-TOPF(FILNUM); FILPTR1=FDLF(FILNUM); SLPLUS2: TEMP=1; SLPLUS3: TOKEN; IF TOKENTYPE EQ TYPST"DIGIT" THEN BEGIN LINPTR1=LINPTR1+TEMP*TOKENVAL; TOKEN; END ELSE LINPTR1=LINPTR1+TEMP; LINNUM1=-1; GOTO SLCUR4; SLMINUS: IF WHICHLIN EQ 3 THEN EXTENDFILE(FALSE); LINPTR1=CURF(FILNUM)-TOPF(FILNUM); FILPTR1=FDLF(FILNUM); SLMINUS2: TEMP=-1; GOTO SLPLUS3; SLX: SCNLINX = TRUE; TEMP=0; SLX2: LINPTR1=REGLINE[XYZREG+TEMP]-REGLINE[XYZTOP+TEMP]; FILPTR1=XYZFILE[TEMP]; CHRPTR1=XYZCHAR[TEMP]; IF CHRPTR1 GQ 0 THEN CHARRANGE=TRUE; GOTO SLCUR3; SLY: SCNLINY = TRUE; TEMP=1; GOTO SLX2; SLZ: SCNLINZ = TRUE; TEMP=2; GOTO SLX2; SLDIGIT: IF NUMBERED[FILNUM] NQ 0 THEN BEGIN LINNUM1=TOKENVAL; PUSH; # REMEMBER WHERE WE ARE # POSN; # SEARCH FOR THAT LINE # LINPTR1=CURRENT-TOPF(FILNUM); POP; END ELSE LINPTR1=TOKENVAL; GOTO SLCUR2; # FOR MORE SYNTAX # SLLETTER: FOR TMP1=0 STEP 1 UNTIL 5 DO BEGIN IF KEYWORD[KEYWDNDX] EQ LINEKEYWD[TMP1] THEN GOTO SLKEYSW[TMP1]; END SLDONE: IF TOKENTYPE EQ TYPST"PAREN" THEN GOTO SLPAREN; POPTEMP; IF WHICHLIN EQ 2 THEN BEGIN CHRPTR1 == CHRPTR2; LINPTR1 == LINPTR2; FILPTR1 == FILPTR2; LINNUM1 == LINNUM2; END ELSE IF WHICHLIN EQ 3 THEN BEGIN CHRPTR1 == CHRPTR3; LINPTR1 == LINPTR3; FILPTR1 == FILPTR3; LINNUM1 == LINNUM3; END WHICHLIN=WHICHLIN+1; WHICHDGT=WHICHLIN; IORET; SLERROR: ERRSTRING = " POINTER NOT SET IN FILE "; C<26,07>ERRSTRING = C<0,7>READNAM; C<00,01>ERRSTRING = TMP1; C<33,01>ERRSTRING = "$"; TOKENPOS = ORIGSCNLIN; ERRJUMP (ERRSTRING); IOEND # OF SCNLIN # PAGE # SCANSET - FOR "SET" COMMAND # PROC SCANSET; IOBEGIN(SCANSET) # ** SCANSET - SCAN SYNTAX OF SET SUBCOMMANDS. * * SCANSET IS CALLED WHEN THE SET COMMAND VERB HAS BEEN * RECOGNIZED. THIS ROUTINE DETERMINES THE SUBCOMMAND, THEN * SCANS SUB-SYNTAX AS APPROPRIATE AND PERFORMS ALL * SUBCOMMAND EXECUTION. * * ENTRY SCANPOS, TOKENPOS - IDENTIFY SUBCOMMAND SYNTAX. * * EXIT COMMAND FULLY EXECUTED. * VIA QQSINGLE IN MULTI-USER VERSION FOR TRANSITION * TO SINGLE-USER WITH RE-EXECUTION. * SCANPOS, TOKENPOS - ADVANCED BEYOND END OF COMMAND. * SCANNER MAY BE CALLED FOR SOME SUBCOMMANDS. * SETMARK POSSIBLY CALLED. * SCREEN MODE INITIALIZATION POSSIBLE. * TABVECTOR POSSIBLY SETUP. * X,Y,Z REGISTER POSSIBLY SETUP. * CURRENT FILE POSSIBLY RENAMED. * TABCHAR POSSIBLY SETUP. * INCR, DINCR - POSSIBLY SETUP. * SCANKEY POSSIBLY CALLED. * FLOAT, NUMBERED[CURFILE] - POSSIBLY REDEFINED. * FKEYNUMROW - POSSIBLY REDEFINED. * CHARRANGE - POSSIBLY DEFINED. * AUDITOFF - POSSIBLY REDEFINED. * USRUMLIN, USRNUMCOL, EDITFIELD, USRSPLTSIZ - * POSSIBLY REDEFINED. * WIDTH - POSSIBLY REDEFINED. * * CALLS AUDITEND, CLEARSCREEN, COPYTABS, ERRJUMP, FSEEDIT, * MIN, MAX, PAINTALL, SCANFUNC, SCANNER, SCNCHAR, * SCNEOC, SCNEQNAM, SCNEQVAL, SCNLSTCOL, SCNONOFF, * SETMARK, SETUPSCREEN, TOKEN, TTSYNC, VDTGTA, * VDTSTD, VDTSTM. * * USES KEYWDTYPE, ALL TOKENXXXX VARIABLES, LINPTR1, * LINPTR2, LINCTR, VTMODEL, LINPTR3, LINNUM1, LINNUM2, * READNAM, KEYWDNDX, WHICHDGT. # CONTROL IFEQ MULTI,1; XREF LABEL QQSINGLE; CONTROL FI; ITEM TMP1, TMP2, BOOL B, TMPNAM C(7); DEF NUMSETKEYS #21#; ARRAY SETKEYS[0:NUMSETKEYS]; ITEM SETKEY C(0,0,10) = [ "ANNOUNCE", "CHAR", "DCOLON", "ECHO", "FILENAME", "HEADER", "INCREMENT", "JUMP", "KEY", "LINE", "MARK", "NUMBER", "PROMPT", "REWRITE", "SCREEN", "TABS", "UNDO", "VIEW", "WORD", "X", "Y", "Z" ]; SWITCH SETSW SSANNOUNCE, SSCHAR, SSDORAC, SSECHO, SSFILE, SSHEADER, SSINCR, SSJUMP, SSKEY, SSLINE, SSMARK, SSNUMBER, SSPROMPT, SSREWRITE, SSSCREEN, SSTABS, SSUNDO, SSVIEW, SSWORD, SSX, SSY, SSZ; KEYWDTYPE=3; SCANPOS=TOKENPOS; TOKEN; IF TOKENTYPE NQ TYPST"LETTER" THEN BEGIN ERRJUMP("KEYWORD MUST FOLLOW SET$"); END TMP1=-1; FOR TMP2=0 STEP 1 UNTIL NUMSETKEYS DO BEGIN IF KEYWORD[KEYWDNDX] EQ SETKEY[TMP2] THEN TMP1=TMP2; END IF TMP1 LS 0 THEN ERRJUMP("KEYWORD MUST FOLLOW SET$"); TOKEN; GOTO SETSW[TMP1]; SSDORAC: # *DC* OR ASCII COLONS ON EXIT # SCNONOFF(BOOL); SCNEOC; ZEROCOLOUT = BOOL; # DO AS USER ASKS # ZEROCOLASK = TRUE; # COLON QUESTION "ASKED" # GOTO SSDONE; SSECHO: # SET ECHO ON OR OFF # SCNONOFF(BOOL); SCNEOC; ECHOOFF = NOT BOOL; # SET ECHO ON OR OFF # GOTO SSDONE; SSJUMP: # AUTO INDENT, BLOCK LANGUAGES # SCNONOFF(BOOL); SCNEOC; AUTOINDENT = BOOL; # DO AS USER ASKS # GOTO SSDONE; SSREWRITE: # SET REWRITE (CHANGED FLAG) # SCNONOFF(BOOL); SCNEOC; IF LOCKED[CURFILE] EQ 0 THEN BEGIN # IF FILE IS NOT LOCKED # IF BOOL THEN BEGIN # IF USER WANTS CHANGED # CHANGED[CURFILE] = 1; IF FILENAM[1] EQ FILENAM[2] THEN BEGIN # IF SAME FILE IN BOTH SPLITS # CHANGED[1] = 1; CHANGED[2] = 1; END END ELSE BEGIN # CLEAR CHANGED STATUS # CHANGED[CURFILE] = 0; IF FILENAM[1] EQ FILENAM[2] THEN BEGIN # IF SAME FILE IN BOTH SPLITS # CHANGED[1] = 0; CHANGED[2] = 0; END END END ELSE BEGIN # LOCKED FILE, REJECT CHANGE # IF BOOL THEN ERRJUMP("CANNOT CHANGE READ-ONLY FILE$"); END GOTO SSDONE; SSMARK: SCANNER; LINPTR2=MIN(LINPTR2,LINPTR1+LIMIT-1); IF SCANWORD THEN BEGIN SETMARK(LINPTR1,CHRPTR1); NEWCURSOR=CURCURSOR+1; IF WHICHLIN GR 2 THEN BEGIN SETMARK(LINPTR2,CHRPTR2); NEWCURSOR=CHRPTR2+1; END END ELSE BEGIN SETMARK(LINPTR1,-1); IF WHICHLIN GR 2 THEN BEGIN SETMARK(LINPTR2,-1); LINPTR1=LINPTR2; END POSZ(LINPTR1); IF SCREENMODE THEN BEGIN # IF SCREENMODE # IF CURRENT EQ TOPS(CURSPLIT) + NUMROWS[CURSPLIT] THEN BEGIN # IF LAST LINE IN SPLIT # FORCEAUTOP[0] = TRUE; END ELSE BEGIN # CHECK FOR LAST LINE IN FILE # IF CURRENT + 1 EQ BOTS(CURSPLIT) THEN FORCEAUTOR[0] = TRUE; END END IF (SCREENMODE AND CURRENT+1 LS BOTS(CURSPLIT)) OR (CURRENT+1 LS BOTF(CURFILE) AND NOT SCREENMODE) THEN BEGIN FWDZ; NEWCURSOR=0; END END GOTO SSDONE; SSTABS: SCNLSTCOL; IF SCREENMODE THEN COPYTABS; GOTO SSDONE; SSX: LINCTR=0; SSX2: SCANNER; IF SCANWORD THEN XYZCHAR[LINCTR]=CHRPTR1; ELSE XYZCHAR[LINCTR]=-1; REGLINE[XYZREG+LINCTR]=LINPTR1; REGLINE[XYZTOP+LINCTR]=TOPF(CURFILE); XYZFILE[LINCTR]=FDLF(CURFILE); GOTO SSDONE; SSY: LINCTR=1; GOTO SSX2; SSZ: LINCTR=2; GOTO SSX2; CONTROL IFEQ MULTI,1; SSANNOUNCE: SSCHAR: SSFILE: SSHEADER: SSINCR: SSKEY: SSLINE: SSNUMBER: SSPROMPT: SSSCREEN: SSUNDO: SSVIEW: SSWORD: GOTO QQSINGLE; CONTROL FI; CONTROL IFEQ SINGLE,1; SSANNOUNCE: WHICHSTR=1; TTYLINE[0]=NULLIN; IF TOKENTYPE EQ TYPST"DELIMIT" THEN SCANSTR; SCNEOC; LINPTR3=1; C<0,1>ERRSTRING=" "; FOR LINPTR1=0 STEP 1 UNTIL MIN(LENGTH(TTYLIN)-1,77) DO BEGIN GETCHAR(TTYLINE,LINPTR1,LINPTR2); DSPLCOD(LINPTR2); CERRSTRING=LINPTR2; LINPTR3=LINPTR1+1; END IF LINPTR3 LAN 1 EQ 0 THEN CERRSTRING="$"; ELSE CERRSTRING=" $"; GOTO SSDONE; SSCHAR: TMP1 = 0; # SET *SET CHAR TAB* FLAG # IF TOKENTYPE EQ TYPST"LETTER" THEN BEGIN KEYWDTYPE = 10; SCANPOS = TOKENPOS; TOKEN; IF KEYWDNDX NQ KEYST"CTAB" THEN BEGIN # IF NOT *SET CHAR TAB* # IF KEYWDNDX EQ KEYST"CCTL" THEN BEGIN # IF *SET CHAR CONTROL* # TMP1 = 1; # SET *SET CHAR CONTROL* FLAG # END ELSE BEGIN # IF NOT *SET CHAR CONTROL* # SCANPOS = TOKENPOS; # SET UP TAB CHARACTER RESCAN # END END KEYWDTYPE = 0; TOKEN; END SCNCHAR; IF TMP1 NQ 0 THEN BEGIN # IF *SET CHAR CONTROL* # IF LINPTR1 EQ CNOTHING THEN LINPTR1 = CBLANK; IF LINPTR1 NQ UNPRINT THEN BEGIN # IF CHARACTER CHANGED # UNPRINT = LINPTR1; IF SCREENMODE THEN BEGIN # IF SCREEN MODE # FOR LINPTR1 = TITLEROW[1] + 1 STEP 1 UNTIL TITLEROW[1] + NUMROWS[1] DO ROWPAINT[LINPTR1] = TRUE; IF SPLITFILE[2] NQ 0 THEN BEGIN # IF SPLIT SCREEN # FOR LINPTR1 = TITLEROW[2] + 1 STEP 1 UNTIL TITLEROW[2] + NUMROWS[2] DO ROWPAINT[LINPTR1] = TRUE; END END END END ELSE TABCHAR = LINPTR1; # IF *SET CHAR TAB* # SCNEOC; GOTO SSDONE; SSFILE: SCNEQNAM(READNAM); SCNEOC; IF READNAM EQ PADNAME(WORKORG) THEN BEGIN # IF SAME AS WORKFILE NAME # ERRJUMP("FILE NAME IN USE$"); END FOR FILNUM=1 STEP 1 UNTIL 2 DO BEGIN # ASSURE DIRECTORY UPTODATE # IF PADNAME(FILENAM[FILNUM]) NQ " " THEN CLOSEFILE; END PUSH; POSZ(TOPC(FILECTL)+1); WHYLE CURRENT LS BOTC(FILECTL) DO BEGIN # VERIFY UNIQUE NAME # SCANFDL(LINPTR1); IF READNAM EQ C<0,7>LINPTR1 AND READNAM NQ "ZZZNULL" AND CURRENT NQ FDLF(CURFILE) THEN BEGIN # IF FILE NAME IN USE # POP; ERRJUMP("FILE NAME IN USE$"); END FWDZ; END POP; TMPNAM=TRIMNAME(READNAM); FOR FILNUM=1 STEP 1 UNTIL 2 DO BEGIN IF FDLF(FILNUM) EQ FDLF(CURFILE) THEN BEGIN IF SPLITFILE[1] EQ FILNUM THEN LASTNAME[1]=TMPNAM; IF SPLITFILE[2] EQ FILNUM THEN LASTNAME[2]=TMPNAM; FILENAM[FILNUM]=TMPNAM; CHANGED[FILNUM]=1; LOCKED[FILNUM]=0; IF NOT WRITEABLE(READNAM) OR READNAM EQ "ZZZNULL" THEN LOCKED[FILNUM]=1; END END FOR FILNUM=1 STEP 1 UNTIL 2 DO BEGIN # ASSURE DIRECTORY UPTODATE # IF PADNAME(FILENAM[FILNUM]) NQ " " THEN CLOSEFILE; END GOTO SSDONE; SSHEADER: SCNONOFF(BOOL); SCNEOC; IF BOOL THEN SHORTTITLE=FALSE; ELSE SHORTTITLE=TRUE; IF SCREENMODE THEN BEGIN ROWPAINT[TITLEROW[1]]=TRUE; IF SPLITFILE[2] NQ 0 THEN ROWPAINT[TITLEROW[2]]=TRUE; END GOTO SSDONE; SSINCR: SCNEQVAL; SCNEOC; IF LINPTR1 LQ 0 OR LINPTR1 GQ NINES THEN ERRJUMP("LINE INCREMENT VALUE TOO LARGE$"); INCR=LINPTR1; DINCR=LINPTR1; GOTO SSDONE; SSKEY: SCANFUNC; GOTO SSDONE; SSLINE: SCNEOC; CLEARSCREEN; GOTO SSDONE; SSNUMBER: KEYWDTYPE=8; SCANPOS=TOKENPOS; TOKEN; KEYWDTYPE=0; TOKEN; SCNEOC; IF KEYWDNDX EQ KEYST"NBAS" OR KEYWDNDX EQ KEYST"NFOR" THEN BEGIN FLOAT=FALSE; IF KEYWDNDX EQ KEYST"NBAS" THEN BLANKS=1; ELSE BLANKS=0; NUMWIDBLK=NUMWIDTH+BLANKS; FOR TMP1 = 1 STEP 1 UNTIL 2 DO # IF SPLIT IS USED THEN RESET # BEGIN IF FDLF(TMP1) EQ FDLF(CURFILE) THEN NUMBERED[TMP1]=1; END END ELSE IF KEYWDNDX EQ KEYST"NAUT" THEN BEGIN FLOAT=TRUE; FOR TMP1 = 1 STEP 1 UNTIL 2 DO # IF SPLIT IS USED THEN RESET # BEGIN IF FDLF(TMP1) EQ FDLF(CURFILE) THEN NUMBERED[TMP1]=0; END END ELSE IF KEYWDNDX EQ KEYST"NONE" THEN BEGIN FLOAT=FALSE; FOR TMP1 = 1 STEP 1 UNTIL 2 DO # IF SPLIT IS USED THEN RESET # BEGIN IF FDLF(TMP1) EQ FDLF(CURFILE) THEN NUMBERED[TMP1]=0; END END ELSE ERRJUMP("CHARACTER SEQUENCE NOT RECOGNIZED$"); GOTO SSDONE; SSPROMPT: LINPTR1=1; WHYLE TOKENTYPE EQ TYPST"DIGIT" OR TOKENTYPE EQ TYPST"LETTER" DO BEGIN IF TOKENTYPE EQ TYPST"DIGIT" THEN BEGIN # IF SET PROMPT 1/2/3 # SCNEQVAL; FKEYNUMROW=MIN(MAX(LINPTR1,0),3); END ELSE BEGIN # IF SET PROMPT SHIFT/NOSHIFT # KEYWDTYPE = 11; SCANPOS = TOKENPOS; TOKEN; KEYWDTYPE = 3; IF KEYWDNDX EQ KEYST"PYDK" THEN SFKEYSHOW = 1; ELSE IF KEYWDNDX EQ KEYST"PNDK" THEN SFKEYSHOW = 0; ELSE ERRJUMP("CHARACTER SEQUENCE NOT RECOGNIZED$"); TOKEN; LINPTR1 = FKEYNUMROW; # PRESERVE CURRENT PROMPT ROWS # END END SCNEOC; LINPTR2=FKEYROW; FKEYNUMROW=MIN(MAX(LINPTR1,0),3); IF SCREENMODE THEN BEGIN # IF SCREEN MODE # IF SPLITFILE[2] NQ 0 THEN SETUPSCREEN(1,2,USRSPLTSZ); ELSE SETUPSCREEN(1,0,0); IF FKEYROW NQ LINPTR2 THEN BEGIN # IF THERE WAS A CHANGE # IF TABATTRCHR[0] AND NUMMARKS NQ 0 THEN PAINTREST(MIN(FKEYROW,LINPTR2)-1); ELSE PAINTREST(MIN(FKEYROW,LINPTR2)); END END GOTO SSDONE; SSSCREEN: IF SYNTAXCHAR[TOKENCHAR] THEN # IF MODEL SPECIFIED # BEGIN IF SCREENMODE THEN CLEARSCREEN; TTLIN("YOU CANNOT SPECIFY A MODEL ON THE$"); TTLIN("*SET SCREEN* EDITOR COMMAND. YOU$"); TTLIN("SHOULD USE THE *QUIT* COMMAND TO$"); TTLIN("END THIS EDIT SESSION, THEN USE THE$"); TTLIN("*SCREEN* COMMAND TO DEFINE YOUR$"); TTLIN("TERMINAL MODEL. THEN YOU CAN START$"); TTLIN("THE EDITOR AGAIN.$"); ERRJUMP(" $"); END ELSE # MODEL NOT SPECIFIED # BEGIN SCNEOC; IF NOT INTERACT THEN GOTO SSDONE; # IF BATCH MODE # IF NOT SCREENMODE THEN # IF LINE MODE # BEGIN TTSYNC; VDTSTM(1,TMP1); # SET SCREEN MODE # END FKEYCHARS=6; FKEYSHOW=8; END IF SCREENMODE THEN # IF SCREEN MODE # BEGIN SCRNSIZES; # SET SCREEN SIZE VALUES # IF TABLOCKMDE[0] THEN BEGIN # IF BLOCK MODE TYPE TERMINAL # SINGLEONLY = TRUE; # DO NOT CONNECT TO MULTI # IF USRNUMCOL GR 1 THEN BEGIN # IF NOT FIRST SET UP OF SCREEN # USRNUMCOL = MIN(USRNUMCOL,VTXMAX-1); END ELSE BEGIN # FIRST SET UP OF SCREEN # USRNUMCOL = VTXMAX - 1; END END ELSE BEGIN # CHARACTER MODE TYPE # IF USRNUMCOL GR 1 THEN BEGIN # IF NOT FIRST SET UP OF SCREEN # USRNUMCOL = MIN(USRNUMCOL,VTXMAX); END ELSE BEGIN # NOT FIRST SET UP OF SCREEN # USRNUMCOL = VTXMAX; END END IF USRNUMLIN GR 1 THEN BEGIN # IF NOT FIRST SET UP OF SCREEN # USRNUMLIN = MIN(USRNUMLIN,VTYMAX); END ELSE BEGIN # NOT FIRST SET UP OF SCREEN # USRNUMLIN = VTYMAX; END IF SPLITFILE[2] NQ 0 THEN SETUPSCREEN(1,2,USRSPLTSZ); ELSE SETUPSCREEN(1,0,0); COPYTABS; PAINTALL; END GOTO SSDONE; SSUNDO: SCNONOFF(BOOL); SCNEOC; IF BOOL THEN AUDITOFF=FALSE; ELSE BEGIN AUDITEND; AUDITOFF=TRUE; END GOTO SSDONE; SSVIEW: SCANVIEW; GOTO SSDONE; SSWORD: KEYWDTYPE=4; SCANPOS=TOKENPOS; KEYWDNDX=-1; TOKEN; IF KEYWDNDX EQ KEYST"XFIL" THEN BEGIN KEYWDTYPE=1; TOKEN; SCNEQVAL; FILLLEFT=MAX(MIN(LINPTR1-1,BUFCHAR-2),0); FILLFIRST=FILLLEFT; IF SYNTAXCHAR[TOKENCHAR] THEN BEGIN SCNEQVAL; FILLRIGHT=MAX( MIN(LINPTR1-1,BUFCM1), FILLLEFT+1); END ELSE BEGIN FILLRIGHT=FILLLEFT; FILLLEFT=0; FILLFIRST=FILLLEFT; END IF SYNTAXCHAR[TOKENCHAR] THEN BEGIN SCNEQVAL; FILLFIRST=MAX(MIN(LINPTR1-1,BUFCHAR-2),0); END IF SYNTAXCHAR[TOKENCHAR] THEN BEGIN # IF SOMETHING ELSE SPECIFIED # IF(C<0,1>TOKENSYM EQ "Y" AND TOKENLEN EQ 1) OR (C<0,3>TOKENSYM EQ "YES" AND TOKENLEN EQ 3) THEN BEGIN # IF RIGHT JUSTIFY REQUESTED # RIGHTJUST[0] = TRUE; END ELSE BEGIN # CHECK FOR NO RIGHT JUSTIFY # IF(C<0,1>TOKENSYM EQ "N" AND TOKENLEN EQ 1) OR (C<0,2>TOKENSYM EQ "NO" AND TOKENLEN EQ 2) THEN BEGIN # IF NOT REQUESTED # RIGHTJUST[0] = FALSE; END ELSE BEGIN # SOMETHING, BUT NOT YES OR NO # ERRJUMP("MUST SPECIFY YES OR NO$"); END END TOKEN; END SCNEOC; END ELSE IF KEYWDNDX EQ KEYST"XCHA" THEN BEGIN TOKEN; SCNCHAR; SCNEOC; BWORDFLAG[LINPTR1/32]=B WORDFLAG[LINPTR1/32] LXR 1; IF BWORDFLAG[LINPTR1/32] EQ 0 THEN BEGIN ERRSTRING="CHARACTER DEFINED AS PUNCTUATOR$"; END ELSE BEGIN ERRSTRING="CHARACTER DEFINED AS ALPHANUMERIC$"; END END ELSE ERRJUMP("PARAMETER NOT VALID FOR THIS DIRECTIVE$"); GOTO SSDONE; CONTROL FI; SSDONE: IOEND # OF SCANSET # PAGE # SCANVIEW - SET VIEW COMMANDS # PROC SCANVIEW; BEGIN # ** SCANVIEW - SCAN PARAMETERS OF "SET VIEW" COMMAND. * * ENTRY SCANPOS, TOKENPOS - BRACKET TOKEN AFTER VIEW. * * EXIT ONE OR MORE OF FOLLWING SETUP - * USRNUMLIN, USRNUMCOL, USRSPLTSZ, EDITFIELD, WIDTH. * LINPTR2 - NEGATIVE IF NO SCREEN REDEFINE NEEDED. * POSITIVE DENOTES VTMODEL TO REDEFINE. * SCANPOS, TOKENPOS - ADVANCED TO END OF COMMAND. * * CALLS TOKEN, SCNEQVAL, ERRJUMP, MIN, SCNEOC. * * USES LINPTR1, ALL TOKENXXXX VARIABLES, WHICHDGT, * KEYWDTYPE, KEYWDNDX, LINPTR3. # DEF MAXVIEWNDX #6#; ARRAY VIEWCONTROL [0:MAXVIEWNDX]; BEGIN ITEM VIEWKEY U(0,00,30)=[ KEYST"VCOL", KEYST"VLIN", KEYST"VOFF", KEYST"VSPL", KEYST"VEDI", KEYST"VWAR", KEYST"VIN" ]; ITEM VIEWNDX U(0,30,30)=[ 1, 0, 3, 2, 4, 5 ,6 ]; END SWITCH SCANVIEWSW SVNUMLIN, SVNUMCOL, SVSPLTSZ, SVOFFSET, SVEDTFLD, SVWIDTH, SVINFLD; PROC FRMTSCR; # TITLE FRMTSCR - FORMAT THE SCREEN. # BEGIN # FRMTSCR # # ** FRMTSCR - FORMAT THE SCREEN FOR THE "SET VIEW" COMMAND. * * ENTRY SCREENMODE - SETUP. * USRNUMCOL - SETUP. * USRNUMLIN - SETUP. * * EXIT USRNUMLIN - SETUP. * USRNUMCOL - SETUP. * USRSPLTSZ - SETUP. * * CALLS COPYTABS, PAINTALL, SETUPSCREEN, VDTSTD. * * USES SPLITFILE. # IF SCREENMODE THEN # IF SCREEN MODE # BEGIN SCRNSIZES; # SET SCREEN SIZE VALUES # IF TABLOCKMDE[0] THEN BEGIN # IF BLOCK MODE TYPE TERMINAL # USRNUMCOL = MIN(USRNUMCOL,VTXMAX-1); END ELSE BEGIN # CHARACTER MODE TYPE # USRNUMCOL = MIN(USRNUMCOL,VTXMAX); END USRNUMLIN = MIN(USRNUMLIN,VTYMAX); IF SPLITFILE[2] NQ 0 THEN SETUPSCREEN(1,2,USRSPLTSZ); ELSE SETUPSCREEN(1,0,0); COPYTABS; PAINTALL; END END # FRMTSCR # # MAIN CODE STARTS HERE. # WHICHDGT=0; WHYLE TOKENTYPE EQ TYPST"DIGIT" OR TOKENTYPE EQ TYPST"LETTER" DO BEGIN IF TOKENTYPE EQ TYPST"LETTER" THEN BEGIN KEYWDTYPE=5; SCANPOS=TOKENPOS; KEYWDNDX=-1; WHICHDGT=-1; TOKEN; FOR LINPTR3=0 STEP 1 UNTIL MAXVIEWNDX DO BEGIN IF KEYWDNDX EQ VIEWKEY[LINPTR3] THEN WHICHDGT=VIEWNDX[LINPTR3]; END IF WHICHDGT LS 0 THEN BEGIN ERRJUMP("CHARACTER SEQUENCE NOT RECOGNIZED$"); END TOKEN; END IF TOKENTYPE EQ TYPST"DIGIT" OR TOKENTYPE EQ TYPST"EQUAL" THEN BEGIN SCNEQVAL; IF WHICHDGT GR MAXVIEWNDX THEN ERRJUMP("TOO MANY PARAMETERS$"); GOTO SCANVIEWSW[WHICHDGT]; SVNUMLIN: IF USRNUMLIN NQ MAX(9,LINPTR1 - 1) THEN BEGIN # IF REAL CHANGE # IF SCREENMODE AND LINPTR1 - 1 LS USRNUMLIN THEN VDTCLS; USRNUMLIN = MAX(9,LINPTR1 - 1); FRMTSCR; # FORMAT THE SCREEN # END XSHIFT[1] = MIN(XSHIFT[1],BUFCHAR-(VTXMAX+1+ATTCOUNT)); XSHIFT[2] = MIN(XSHIFT[2],BUFCHAR-(VTXMAX+1+ATTCOUNT)); GOTO SVNEXT; SVNUMCOL: IF USRNUMCOL NQ MAX(9,LINPTR1 - 1) THEN BEGIN # IF REAL CHANGE # IF TABVTSCLRS[0] OR LINPTR1 GR USRNUMCOL THEN BEGIN # IF SCREEN NEEDS REPAINTING # USRNUMCOL = MAX(9,LINPTR1 - 1); FRMTSCR; # FORMAT THE SCREEN # END ELSE BEGIN # SCREEN DOES NOT NEED REPAINT # IF SCREENMODE THEN BEGIN # IF IN SCREEN MODE # USRNUMCOL = MAX(9,LINPTR1 - 1); SCRNSIZES; # SET SCREEN SIZE VALUES # USRNUMCOL = MIN(USRNUMCOL,VTXMAX); USRNUMLIN = MIN(USRNUMLIN,VTYMAX); COPYTABS; IF FKEYNUMROW GR 0 THEN BEGIN # IF PROMPTS MUST BE REPAINTED # PAINTREST(FKEYROW); END END END END XSHIFT[1] = MIN(XSHIFT[1],BUFCHAR-(VTXMAX+1+ATTCOUNT)); XSHIFT[2] = MIN(XSHIFT[2],BUFCHAR-(VTXMAX+1+ATTCOUNT)); GOTO SVNEXT; SVSPLTSZ: IF USRSPLTSZ NQ LINPTR1 THEN BEGIN # IF REAL CHANGE # SCRNPT1 = MAX(0,FKEYNUMROW*(2+SHIFTFKEY)-1); USRSPLTSZ = MIN(MAX(LINPTR1,1),(USRNUMLIN-(SCRNPT1+4))); IF SCREENMODE THEN BEGIN # IF SCREEN MODE # IF SPLITFILE[2] NQ 0 THEN BEGIN # IF SPLIT SCREEN MODE # SETUPSCREEN(1,2,USRSPLTSZ); FOR LINPTR1 = USRNUMLIN-(USRSPLTSZ-1) STEP 1 UNTIL SCRNPT1 DO BEGIN # UNTIL DONE FOR SPLIT AREA # ROWPAINT[SCRNPT1]= TRUE; END END END END GOTO SVNEXT; SVOFFSET: IF XSHIFT[CURSPLIT] NQ MAX(LINPTR1-1,0) THEN BEGIN # IF REAL CHANGE # XSHIFT[CURSPLIT] = MIN(MAX(LINPTR1-1,0), BUFCHAR-(VTXMAX+1+ATTCOUNT)); IF SCREENMODE THEN BEGIN # IF SCREEN MODE # FOR LINPTR1 = TITLEROW[CURSPLIT] STEP 1 UNTIL TITLEROW[CURSPLIT] + NUMROWS[CURSPLIT] DO ROWPAINT[LINPTR1] = TRUE; END END GOTO SVNEXT; SVEDTFLD: EDITFIELD=MIN(LINPTR1,BUFCHAR); GOTO SVNEXT; SVWIDTH: WIDTH=MIN(LINPTR1,BUFCHAR); GOTO SVNEXT; SVINFLD: DFINFIELD=MAX(0,MIN(LINPTR1,BUFCHAR)); IF TOKENTYPE EQ TYPST"DIGIT" THEN BEGIN # IF SECOND VALUE SUPPLIED # SCNEQVAL; DFINBGN = DFINEND; DFINEND = MAX(0,MIN(LINPTR1,BUFCHAR)); END IF DFINEND EQ 0 THEN DFINEND=BUFCHAR; IF DFINBGN GR DFINEND THEN DFINBGN==DFINEND; DFINBGN=MAX(1,DFINBGN); GOTO SVNEXT; SVNEXT: WHICHDGT=WHICHDGT+1; END END SCNEOC; END # OF SCANVIEW # PAGE # SCRNSIZES - SET SCREEN SIZES # PROC SCRNSIZES; BEGIN # ** SCRNSIZES - SET SIZE VALUES ASSOCIATED WITH SCREEN. * * SETS SCREEN ROWS, COLUMNS AND LABEL LINE AND PADDING SIZES. * * ENTRY USRNUMCOL = SPECIFIED NUMBER OF COLUMNS - 1. * USRNUMLIN = SPECIFIED NUMBER OF LINES - 1. * * EXIT VTXMAX = MAXIMUM COLUMN NUMBER FOR SELECTED FORMAT. * VTYMAX = MAXIMUM ROW NUMBER FOR SELECTED FORMAT. * FKEYLEN = LENGTH OF FUNCTION KEY LABEL LINES. * FKEYPAD = NUMBER OF BLANKS TO BE ADDED BEFORE AND * AFTER EACH FUNCTION KEY LABEL BLOCK. * * CALLS VTDSTD. * * USES FKEYLEN, FKEYPAD. # VDTSTD(USRNUMCOL+1,USRNUMLIN+1); FKEYPAD = (VTXMAX+1-(FKEYCHARS+4)*FKEYSHOW)/(FKEYSHOW*2); FKEYLEN = (2*FKEYPAD+FKEYCHARS+4)*FKEYSHOW-1; END # END OF SCRNSIZES # PAGE # SCANFUNC - SCAN "FUNCTION" CMD # CONTROL IFEQ SINGLE,1; PROC SCANFUNC; BEGIN # ** SCANFUNC - SCAN/EXECUTE SET KEY COMMAND. * * SCANFUNC IS INTENDED TO BE CALLED ONLY BY SCANSET. * SCANFUNC HANDLES FUNCTION KEY REDEFINITION. THIS * ROUTINE COMPLETES SYNTAX SCAN AND EXECUTES THE COMMAND. * * ENTRY TOKENPOS - POINTS AFTER "SET KEY". * FKEYNUMROW - WHETHER TO SET ROWPAINT. * * EXIT TOKENPOS, SCANPOS - ADVANCED TO END OF COMMAND. * FKEYNAME[ANY,ANY] - REDEFINED. * ROWPAINT[] - SET IF NEEDED. * * USES ALL TOKENXXXX VARIABLES, FKEYNDX, KEYWDTYPE, * TTYLIN, WHICHSTR, LINCTR, LINPTR1, LINNUM1, TMPLIN. * * MACROS GETCHAR. * * CALLS DSPLCOD, SCANSTR, SETSCREEN, TOKEN. # BASED ARRAY KEYLIN[0:99]; ITEM KEYLINE; ITEM EXPECT; # 0=CONTENT, 1=LABEL # ITEM WEDIDIT B; ITEM KEY, SHIFT; EXPECT=0; SHIFT=1; WEDIDIT=FALSE; KEY=1; KEYWDTYPE=7; SCANPOS=TOKENPOS; SFLOOP: TOKEN; SFLOOP2: IF TOKENTYPE EQ TYPST"DIGIT" THEN BEGIN KEY=MIN(MAX(TOKENVAL,1),POSFKEYS); GOTO SFLOOP; END IF TOKENTYPE EQ TYPST"LETTER" THEN BEGIN IF KEYWDNDX EQ KEYST"KSHI" THEN BEGIN # SHIFT KEYWORD # SHIFT=-1; GOTO SFLOOP; END ELSE IF KEYWDNDX EQ KEYST"KLAB" THEN BEGIN # LABEL KEYWORD # EXPECT=1; GOTO SFLOOP; END ELSE BEGIN IF SCREENMODE THEN BEGIN # IF SCREEN SETUP NEEDED # IF SPLITFILE[2] EQ 0 THEN SETUPSCREEN(1,0,0); ELSE SETUPSCREEN(1,2,USRSPLTSZ); IF FKEYNUMROW NQ 0 THEN PAINTREST(FKEYROW); END ERRJUMP("CHARACTER SEQUENCE NOT RECOGNIZED$"); END END IF TOKENTYPE EQ TYPST"DELIMIT" THEN BEGIN WEDIDIT=TRUE; TTYLINE[0]=NULLIN; WHICHSTR=1; SCANSTR; # PUTS INTO TTYLIN # # ALWAYS SET LABEL # FKEYNAME[KEY*SHIFT]=" "; LINCTR=LENGTH(TTYLIN); FOR LINPTR1=0 STEP 1 UNTIL MIN(5,LINCTR-1) DO BEGIN GETCHAR(TTYLINE,LINPTR1,LINNUM1); DSPLCOD(LINNUM1); CFKEYNAME[KEY*SHIFT]=LINNUM1; END IF EXPECT EQ 0 THEN # SET CONTENT IF NOT EXPLICIT LABEL # BEGIN EXPECT=1; P=LOC(FKEYSTRING[KEY*SHIFT]); FKEYSTRING[KEY*SHIFT]=NULLIN; FOR LINPTR1=0 STEP 1 UNTIL MIN(14,LINCTR-1) DO BEGIN GETCHAR(TTYLINE,LINPTR1,LINNUM1); SETCHAR(KEYLINE,LINPTR1,LINNUM1); SETCHAR(KEYLINE,LINPTR1+1,CENDLINE); END IF LINCTR GQ 14 THEN BEGIN PUSH; POSZ(TOPK(FKEYS)+KEY*SHIFT+POSFKEYS); FOR LINPTR1=0 STEP 1 UNTIL LINCTR-1 DO BEGIN GETCHAR(TTYLINE,LINPTR1,LINNUM1); SETCHAR(LINE,LINPTR1,LINNUM1); SETCHAR(LINE,LINPTR1+1,CENDLINE); END REPY; POP; END END GOTO SFLOOP2; END SCNEOC; IF SCREENMODE THEN BEGIN # IF SCREEN SETUP NEEDED # IF SPLITFILE[2] EQ 0 THEN SETUPSCREEN(1,0,0); ELSE SETUPSCREEN(1,2,USRSPLTSZ); IF FKEYNUMROW NQ 0 THEN PAINTREST(FKEYROW); END END # OF SCANFUNC # CONTROL FI; PAGE # MISCELLANEOUS SCANNERS # PROC SCNTAB; BEGIN # ** SCNTAB - PARSE SYNTAX FOR *IN* FIELD REFERENCE. * * ENTRY SCANNER ADVANCED TO TOKEN AFTER *IN* KEYWORD. * FORCEFIELD - WHETHER YET INITIALIZED FIELD. * WHICHLIN - WHETHER SET FIELDNDX OR FIELDTARGET. * WHICHDGT - INDICATES TAB FIELD EXPECTED. * * EXIT FORCEFIELD - TRUE. * TOKEN ADVANCED PAST NUMERIC SYNTAX. * FIELDNDX, FIELDTARGET - ONE OF THESE IS SETUP. * WHICHDGT - EQUAL TO WHICHLIN. * * CALLS TOKEN, ERRJUMP. # ITEM TMP1, TMP2; IF NOT FORCEFIELD THEN BEGIN FIELDNDX=0; FIELDTARGET=0; END FORCEFIELD=TRUE; FIELDFLG=TRUE; WHICHDGT=WHICHLIN; IF TOKENTYPE NQ TYPST"DIGIT" THEN BEGIN # IF *IN* ALONE, DEFAULT COLUMNS # INFLDBGN=MAX(0,DFINBGN-1); INFLDEND=MAX(0,DFINEND-1); IF WHICHLIN LS 4 THEN FIELDNDX=-1; ELSE FIELDTARGET=-1; END ELSE BEGIN # IF ONE OR MORE VALUES # TMP1=TOKENVAL; TOKEN; # ADVANCE NEXT SYNTAX # IF TOKENTYPE NQ TYPST"DIGIT" THEN BEGIN # IF TAB FIELD INSTEAD OF COLUMNS # IF TMP1 LQ 0 THEN ERRJUMP("TAB FIELD ORDINAL OUT OF BOUNDS$"); IF WHICHLIN LS 4 THEN FIELDNDX=TMP1; ELSE FIELDTARGET=TMP1; END ELSE BEGIN # IF COLUMNS INSTEAD OF TAB FIELD # TMP2=TOKENVAL; TOKEN; # ADVANCE NEXT SYNTAX # IF TMP2 EQ 0 THEN TMP2=BUFCHAR; INFLDBGN=MAX(0,MIN(BUFCM1,TMP1-1)); INFLDEND=MAX(0,MIN(BUFCM1,TMP2-1)); IF INFLDEND LS INFLDBGN THEN INFLDBGN==INFLDEND; IF WHICHLIN LS 4 THEN FIELDNDX=-1; ELSE FIELDTARGET=-1; END END END # OF SCNTAB # PROC SCANSTR; BEGIN # ** SCANSTR - PARSE CHARACTER STRING SYNTAX. * * SCANSTR IS CALLED BY SCANNER WHEN SCANNER DETECTS ONE * OF THE STRING DELIMITER PUNTUATION MARKS. SCANSTR ANALYSES * THE ENTIRE REMAINDER OF THE COMMAND LINE, THEN DETERMINES * WHAT PORTION OF THE COMMAND LINE REALLY PROVIDES STRINGS * FOR THE CURRENT COMMAND, AND LEAVES FOR SCANNER ANY * PARAMETERS BEYOND THE STRINGS OR ANY ADDITIONAL COMMANDS * BEYOND THE STRINGS. * * ALLOWABLE SYNTAX COMBINATIONS FOR "LOCATE" COMMAND - * * /TEXT * /TEXT/MORE STUFF * /TEXT1/./TEXT2 (ELLIPSIS) * /TEXT1/./TEXT2/MORE STUFF * * ALLOWABLE SYNTAX COMBINATIONS FOR "REPLACE" COMMAND - * * /OLD// (REPLACE WITH NULL) * /OLD/NEW * /OLD/NEW/MORE STUFF * //NEW (USE PREVIOUS SEARCH) * //NEW/MORE STUFF * /// (PREVIOUS SEARCH, NULL REPLACE) * /OLD1/./OLD2// (ELLIPSIS VARIATIONS) * /OLD1/./OLD2/NEW * /OLD1/./OLD2/NEW/MORE STUFF * * ALLOWABLE SYNTAX FOR "INSERT", "ALTER", "SET KEY" - * * /TEXT * /TEXT/MORE STUFF * * ENTRY SCANPOS, TOKENPOS BRACKET INITIAL DELIMETER. * WHICHSTR - 1=COMMAND IS "INSERT" , "ALTER", "SK". * 2=COMMAND IS "LOCATE". * 3=COMMAND IS "REPLACE". * TOKENCHAR - THE PUNCTUATION MARK USED AS DELIMITER. * * EXIT SCANPOS, TOKENPOS - ADVANCED FOR SCANNER TO CONTINUE. * ELLIPSIS, TXTINCMD - MODE FLAGS. * WORDSEARCH, UPPERSEARCH - FALSE FOR LOCATE, REPLACE. * WHICHSTR - SET TO MINUS ONE. * LOCSTRING1, LOCSTRING2 - ONE OR BOTH SET FOR "L", "R". * CHGSTRING1 - SET FOR "R". * LOCSTRLEN1, LOCSTRLEN2, CHGSTRLEN1 - SET PER STRINGS. * TTYLIN - SET FOR "I", "A". * SCHSTRSPEC - SET FOR REPEATED LOCATE/REPLACE. * * MACROS GETCHAR, SETCHAR. * * CALLS MOVESTR(INTERNAL), TOKEN, ERRJUMP. * * USES ALL TOKENXXXX VARIABLES. # ITEM TMP1,TMP2,TMP3; ITEM NUMSTRING, POINTER, DELIM, CHAR, NONDOT B; ARRAY STRINGCTL [1:5]; BEGIN ITEM CTLWORD U(0,0,60); # USED TO CLEAR ALL FIELDS # ITEM ALLDOTS B(0,0,1); ITEM CLOSED B(0,1,1); ITEM TEXTPOS U(0,12,12); ITEM TEXTLEN U(0,24,12); ITEM AFTERPOS U(0,36,12); END PROC MOVESTR(WHICH,BUF,LEN,MAXLEN); # TITLE MOVESTR - MOVE STRING. # BEGIN # MOVESTR # # * MOVESTR - MOVE STRING. * * *MOVESTR* MOVES A STRING FROM THE COMMAND LINE TO THE * LINE BUFFER. * * PROC MOVESTR(WHICH,BUF,LEN,MAXLEN) * * ENTRY WHICH - TYPE OF STRING. * BUF - LINE BUFFER TO UPDATE. * LEN - LINE BUFFER LENGTH. * MAXLEN - MAXIMUM STRING LENGTH. * * EXIT STRING MOVED TO LINE BUFFER. * * MACROS GETCHAR, SETCHAR. * * CALLS ERRJUMP. # ARRAY BUF[0:99]; BEGIN # ARRAY BUF # ITEM LINEBUF I; # LINE BUFFER # END # ARRAY BUF # ITEM WHICH I; # TYPE OF STRING # ITEM LEN I; # LINE BUFFER LENGTH # ITEM MAXLEN I; # MAXIMUM STRING LENGTH # ITEM TMP1 I; # TEMPORARY STORAGE # IF TEXTLEN[WHICH] GR MAXLEN THEN # IF STRING TOO LARGE # BEGIN ERRJUMP("STRING GREATER THAN 80 CHARACTERS$"); END LEN=TEXTLEN[WHICH]; LINEBUF[0]=NULLIN; FOR TMP1=1 STEP 1 UNTIL LEN DO # MOVE STRING # BEGIN GETCHAR(CMDLINE,TEXTPOS[WHICH]+TMP1-1,TMP2); SETCHAR(LINEBUF,TMP1-1,TMP2); END SETCHAR(LINEBUF,LEN,CENDLINE); SCHSTRSPEC=TRUE; # SEARCH STRING SPECIFIED # END # MOVESTR # # MAIN CODE STARTS HERE # NUMSTRING=0; POINTER=TOKENPOS; DELIM=TOKENCHAR; LOOP: NUMSTRING=NUMSTRING+1; CTLWORD[NUMSTRING]=0; TEXTPOS[NUMSTRING]=POINTER+1; NONDOT=FALSE; TMP1=-1; FOR TMP2=POINTER+1 STEP 1 WHILE TMP2 LS LENGTH(CMDLIN) AND TMP1 LS 0 DO BEGIN GETCHAR(CMDLINE,TMP2,TMP3); IF TMP3 NQ DELIM AND TMP3 NQ CPERIOD THEN NONDOT=TRUE; IF TMP3 EQ DELIM THEN TMP1=TMP2; END IF TMP1 GQ 0 THEN BEGIN CLOSED[NUMSTRING]=TRUE; TEXTLEN[NUMSTRING]=TMP1-TEXTPOS[NUMSTRING]; IF TEXTLEN[NUMSTRING] GR 0 AND NOT NONDOT THEN ALLDOTS[NUMSTRING]=TRUE; AFTERPOS[NUMSTRING]=TMP1+1; POINTER=TMP1; IF NUMSTRING LQ 4 THEN GOTO LOOP; END ELSE BEGIN TEXTLEN[NUMSTRING]=LENGTH(CMDLIN)-TEXTPOS[NUMSTRING]; AFTERPOS[NUMSTRING]=LENGTH(CMDLIN); #GOTO PHASE2# END PHASE2: IF WHICHSTR EQ 1 THEN # INSERT, ALTER, SET KEY # BEGIN MOVESTR(1,TTYLIN,TMP1,BUFCM1); TXTINCMD=TRUE; SCANPOS=AFTERPOS[1]; END ELSE IF WHICHSTR EQ 2 THEN # LOCATE # BEGIN WORDSEARCH=FALSE; UPPERSEARCH=FALSE; IF ALLDOTS[2] AND NUMSTRING GQ 3 THEN BEGIN ELLIPSIS=TRUE; IF TEXTLEN[1] NQ 0 THEN MOVESTR(1,LOCSTRING1,LOCSTRLEN1,80); IF TEXTLEN[3] NQ 0 THEN MOVESTR(3,LOCSTRING2,LOCSTRLEN2,80); SCANPOS=AFTERPOS[3]; END ELSE BEGIN IF TEXTLEN[1] NQ 0 THEN MOVESTR(1,LOCSTRING1,LOCSTRLEN1,80); ELLIPSIS=FALSE; SCANPOS=AFTERPOS[1]; END END ELSE IF WHICHSTR EQ 3 THEN # REPLACE # BEGIN WORDSEARCH=FALSE; UPPERSEARCH=FALSE; IF ALLDOTS[2] AND NUMSTRING GQ 4 THEN BEGIN IF TEXTLEN[4] EQ 0 AND NOT CLOSED[4] THEN ERRJUMP("MISSING REPLACEMENT STRING$"); ELLIPSIS=TRUE; IF TEXTLEN[1] NQ 0 THEN MOVESTR(1,LOCSTRING1,LOCSTRLEN1,80); IF TEXTLEN[3] NQ 0 THEN MOVESTR(3,LOCSTRING2,LOCSTRLEN2,80); MOVESTR(4,CHGSTRING1,CHGSTRLEN1,80); SCANPOS=AFTERPOS[4]; END ELSE IF NUMSTRING GQ 2 THEN BEGIN IF TEXTLEN[2] EQ 0 AND NOT CLOSED[2] THEN ERRJUMP("MISSING REPLACEMENT STRING$"); IF TEXTLEN[1] NQ 0 THEN BEGIN MOVESTR(1,LOCSTRING1,LOCSTRLEN1,80); ELLIPSIS=FALSE; END MOVESTR(2,CHGSTRING1,CHGSTRLEN1,80); SCANPOS=AFTERPOS[2]; END END WHICHSTR=-1; TOKEN; END # OF SCANSTR # PROC SCNEOC; BEGIN # ** SCNEOC - VERIFY END OF COMMAND. * * SCNEOC IS CALLED TO MAKE SURE THERE IS NO UNSCANNED * SYNTAX LEFT IN THE CURRENT COMMAND. * * ENTRY SCANPOS, TOKENPOS BRACKET CURRENT SYNTAX. * TOKENCHAR IS CURRENT CHARACTER. * * CALLS ERRJUMP. # IF SYNTAXCHAR[TOKENCHAR] THEN ERRJUMP("TOO MANY PARAMETERS$"); END # OF SCNEOC # PROC SCNONOFF(BOOL); BEGIN # ** SCNONOFF - PARSE YES/NO SYNTAX. * * SCNONOFF RECOGNIZES YES/NO KEYWORDS AND TELLS THE CALLER * WHICH WAS FOUND. SCNONOFF IS CALLED WHEN A YES/NO * KEYWORD IS EXPECTED BUT HAS NOT YET BEEN ENCOUNTERED. * THUS SCNONOFF VERIFIES THAT ONE OF THESE WORDS IS NEXT. * * ENTRY SCANPOS, TOKENPOS - BRACKET NEXT TOKEN. * TOKENTYPE, KEYWDNDX - WHAT THE NEXT TOKEN IS. * * EXIT BOOL - WHICH KEYWORD. * VIA ERRJUMP IF NEITHER. * TOKENPOS, SCANPOS - ADVANCED TO NEXT TOKEN. * * CALLS TOKEN, ERRJUMP. # ITEM BOOL B; SCANPOS=TOKENPOS; KEYWDTYPE=3; TOKEN; IF TOKENTYPE EQ TYPST"LETTER" AND C<0,1>KEYWORD[KEYWDNDX] EQ "Y" THEN BOOL=TRUE; ELSE IF TOKENTYPE EQ TYPST"LETTER" AND C<0,1>KEYWORD[KEYWDNDX] EQ "N" THEN BOOL=FALSE; ELSE ERRJUMP("MUST SPECIFY YES OR NO$"); TOKEN; END # OF SCNONOFF # PROC SCNEQVAL; # SCAN "=VALUE" # BEGIN # ** SCNEQVAL - PARSE NUMERIC SYNTAX PARAMETER. * * SCNEQVAL IS USED BY COMMAND SCANNERS OTHER THAN "SCANNER" * ITSELF. (SCANNER ITSELF HANDLES OR ROUTES TREATMENT OF * NUMERIC PARAMETERS ON ITS OWN) SCNEQVAL IS USED BY COMMAND * SCANNERS THAT EXPECT/DEMAND A NUMERIC VALUE. AN EQUAL * SIGN IS ALLOWED TO PRECEED THE PARAMETER. * * ENTRY SCANPOS, TOKENPOS - BRACKET NEXT TOKEN. * TOKENTYPE, TOKENVAL - DESCRIBE NEXT TOKEN. * * EXIT LINPTR1 - VALUE OF NUMBER. * VIA ERRJUMP IF NO NUMBER FOUND. * SCANPOS, TOKENPOS - ADVANCED TO NEXT TOKEN. * * CALLS TOKEN, ERRJUMP. # IF TOKENTYPE EQ TYPST"EQUAL" THEN TOKEN; IF TOKENTYPE NQ TYPST"DIGIT" THEN ERRJUMP("VALUE MUST BE NUMERIC$"); LINPTR1=TOKENVAL; TOKEN; # ADVANCE TO NEXT SYNTAX # END # OF SCNEQVAL # PROC SCNEQNAM(NAME); BEGIN # ** SCNEQNAM - PARSE ARBITRARY ALPHANUMERIC WORD. * * SCNEQNAM SCANS AN ARBITRARY ALPHANUMERIC WORD, POSSIBLY * PRECEEDED BY AN EQUAL SIGN. * * ENTRY TOKENPOS, SCANPOS - BRACKET CURRENT SYNTAX. * TOKENTYPE - DESCRIBES CURRENT SYNTAX. * * EXIT NAME - THE WORD SCANNED. * SCANPOS, TOKENPOS - ADVANCED. * SCNNAMPTR - POINTS TO WORD. * * CALLS TOKEN, ERRJUMP. * * USES ALL TOKENXXXX VARIABLES, KEYWDTYPE. # ITEM NAME C(7), TMP1; IF TOKENTYPE EQ TYPST"EQUAL" THEN TOKEN; IF TOKENTYPE NQ TYPST"LETTER" AND TOKENTYPE NQ TYPST"DIGIT" THEN ERRJUMP("MUST SPECIFY FILE NAME$"); ELSE BEGIN TMP1=KEYWDTYPE; KEYWDTYPE=0; # ENABLE MIXED LETTERS DIGITS # SCANPOS=TOKENPOS; # SET FOR RESCAN # TOKEN; # RESCAN THE CURRENT SYNTAX # KEYWDTYPE=TMP1; NAME=C<0,7>TOKENSYM; SCNNAMPTR=SCANPOS; TOKEN; # NEXT SYNTAX # END END # OF SCNEQNAM # PROC SCNFILE(NAME); BEGIN # ** SCNFILE - SCAN PARENTHESIZED FILENAME. * * SCNFILE IS CALLED WHEN AN OPENING PARENTHESIS HAS BEEN * DETECTED, AND PARSES OUT THE FILENAME AND ADVANCES THE * SYNTAX BEYOND THE CLOSING PARENTHESIS. * * ENTRY SCANPOS, TOKENPOS - BRACKET CURRENT SYNTAX. * TOKENCHAR - CURRENT CHARACTER. * * EXIT NAME - THE ARBITRARY ALPHANUMERIC WORD. * SCANPOS, TOKENPOS - ADVANCED TO NEXT SYNTAX. * * CALLS TOKEN, SCNEQNAM. * * USES SCNNAMPTR, ALL TOKENXXXX VARIABLES. # ITEM NAME C(7); SCNNAMPTR=TOKENPOS; IF TOKENCHAR EQ CLPAREN THEN BEGIN TOKEN; SCNEQNAM(NAME); SCNNAMPTR=TOKENPOS; IF TOKENCHAR EQ CRPAREN THEN SCNNAMPTR=TOKENPOS+1; END SCANPOS=SCNNAMPTR; TOKEN; END # OF SCNFILE # PROC SCNCHAR; BEGIN # ** SCNCHAR - PARSE ARBITRARY PUNCTUATION OR ALTERNATE NAME. * * SCNCHAR IS CALLED WHEN WE EXPECT AN ARBITRARY PUNCTUATION * MARK AS THE NEXT SYNTAX, OR AN ALTERNATE KEYWORD FOR * BLANK OR SEMICOLON. * * ENTRY SCANPOS, TOKENPOS - BRACKET CURRENT SYNTAX. * TOKENCHAR - CURRENT CHARACTER. * * EXIT LINPTR1 - THE CHARACTER. CONVERTED TO ACTUAL * CHARACTER IF ALTERNATE KEYWORD WAS USED. * SCANPOS, TOKENPOS - ADVANCED TO NEXT SYNTAX. * * MACROS GETCHAR. * * CALLS TOKEN. * * USES ALL TOKENXXXX VARIABLES, KEYWDTYPE(RESTORED). # ITEM TMP1; IF NOT SYNTAXCHAR[TOKENCHAR] THEN LINPTR1=CNOTHING; ELSE BEGIN TMP1=KEYWDTYPE; KEYWDTYPE=0; # ENABLE MIXED LETTERS DIGITS # SCANPOS=TOKENPOS; # SET FOR RESCAN # TOKEN; # RESCAN THE CURRENT SYNTAX # IF TOKENTYPE EQ TYPST"LETTER" AND C<0,7>TOKENSYM EQ "BLANK" THEN LINPTR1=CBLANK; ELSE IF TOKENTYPE EQ TYPST"LETTER" AND C<0,7>TOKENSYM EQ "SEMI" THEN LINPTR1=CSEMCOLON; ELSE BEGIN GETCHAR(CMDLINE,TOKENPOS,LINPTR1); SCANPOS=TOKENPOS+1; END KEYWDTYPE=TMP1; TOKEN; END END # OF SCNCHAR # PROC SCNLSTCOL; BEGIN # ** SCNLSTCOL - PARSE A LIST OF NUMBERS INTO TAB VECTOR. * * SCNLSTCOL IS CALLED WHEN A LIST OF NUMBERS IS EXPECTED. * WE DECODE EACH NUMBER AND PACK UP TO 20 OF THEM INTO * EIGHT-BIT FIELDS IN A THREE-WORD VECTOR. THIS IS CURRENTLY * NEEDED ONLY FOR THE "SET TABS" COMMAND. * * ENTRY TOKENPOS, SCANPOS - BRACKET FIRST NUMBER. * TOKENVAL - VALUE OF FIRST NUMBER. * * EXIT TABVECTOR - ZEROED OR FILLED WITH PACKED LIST. * TOKENPOS, SCANPOS - ADVANCED TO END OF COMMAND. * * CALLS TOKEN, ERRJUMP, SCNEOC. * * USES LINPTR1, LINPTR2, LINNUM1, LINNUM2, ALL TOKENXXXX. # ARRAY TEMPTABS [1:TABWORDS]; BEGIN ITEM TMPTABWRD; END FOR LINPTR1=1 STEP 1 UNTIL TABWORDS DO BEGIN TMPTABWRD[LINPTR1]=0; END LINPTR2=0; LINPTR1=1; # FIRST LEGAL COLUMN # WHYLE TOKENTYPE EQ TYPST"DIGIT" AND LINPTR2 LS USERTABS DO BEGIN IF TOKENVAL LS LINPTR1 OR TOKENVAL GR BUFCHAR THEN ERRJUMP("TAB STOP OUT OF BOUNDS$"); IF TOKENVAL GR 1 THEN BEGIN LINNUM1=LINPTR2/7; LINNUM2=MOD(LINPTR2,7); BTMPTABWRD[LINNUM1+1]=TOKENVAL-1; LINPTR2=LINPTR2+1; END LINPTR1=TOKENVAL+1; TOKEN; END SCNEOC; MOVEWD(TABWORDS,TEMPTABS,TABVECTOR); END # OF SCNLSTCOL # PROC SCNFILOPT; BEGIN # ** SCNFILOPT - SCAN OPTIONS ALLOWABLE ON "FSE" COMMAND. * * SCNFILOPT PROVIDES ALL SCANNING FOR THE * "FSE" COMMAND ONCE THE COMMAND VERB HAS BEEN RECOGNIZED. * THE CALLER IS RESPONSIBLE TO CALL SCNEOC AFTER SCNFILOPT. * * ENTRY TOKENPOS, SCANPOS - BRACKET FIRST SYNTAX AFTER VERB. * * EXIT TOKENPOS, SCANPOS - BRACKET LAST KNOWN SYNTAX. * GETPARM, CHARPARM - SET PER SYNTAX. * FILNUM - 1 OR 2 PER "SPLIT" KEYWORD. * SCREENMODE - ELIGIBLE TO USE "SPLIT" KEYWORD. * * CALLS SCNEQNAM, ERRJUMP, TOKEN. * * USES KEYWDTYPE, ALL TOKENXXXX VARIABLES. # DEF SFOMAXOPT #7#; DEF SFOMAXLBL #5#; STATUS SFOST CSET1, CSET2, CSET3, GET, SPLIT, READ; SWITCH SFOLABELS SFOCS1, SFOCS2, SFOCS3, SFOGET, SFOSPLIT, SFOREAD; ARRAY SFOMATCHES [0:SFOMAXOPT]; BEGIN ITEM SFOKEY U(0,0,30) = [KEYST"XDIS", KEYST"XNOR", KEYST"XASC", KEYST"XASC8", KEYST"XA8", KEYST"XGET", KEYST"XSPL", KEYST"XREA" ]; ITEM SFOLBL U(0,30,30) = [ SFOST"CSET1", SFOST"CSET1", SFOST"CSET2", SFOST"CSET3", SFOST"CSET3", SFOST"GET", SFOST"SPLIT", SFOST"READ" ]; END ITEM TMP1, TMP2; SCNEQNAM(READNAM); GETPARM=0; CHARPARM=0; FILNUM=1; KEYWDTYPE=4; SCANPOS=TOKENPOS; KEYWDNDX=-1; TOKEN; WHYLE TOKENTYPE EQ TYPST"LETTER" OR TOKENTYPE EQ TYPST"DIGIT" DO BEGIN TMP2=-1; FOR TMP1=0 STEP 1 UNTIL SFOMAXOPT DO IF SFOKEY[TMP1] EQ KEYWDNDX THEN TMP2=SFOLBL[TMP1]; IF TMP2 LS 0 THEN BEGIN ERRJUMP("PARAMETER NOT VALID FOR THIS DIRECTIVE$"); END GOTO SFOLABELS[TMP2]; SFOCS1: CHARPARM=1; GOTO SFODONE; SFOCS2: CHARPARM=2; GOTO SFODONE; SFOCS3: CHARPARM=3; GOTO SFODONE; SFOGET: GETPARM=2; GOTO SFODONE; SFOSPLIT: FILNUM=2; IF NOT SCREENMODE THEN ERRJUMP("SCREEN MODE REQUIRED$"); GOTO SFODONE; SFOREAD: GETPARM=3; GOTO SFODONE; SFODONE: KEYWDNDX=-1; TOKEN; END END # OF SCNFILOPT # PAGE # MICRO EXPANSION # PROC EXPANDCMDS; BEGIN # ** EXPANDCMDS - EXPAND MICROS FROM IN COMMAND LINE. * * EXPANDCMDS IS CALLED WHEN THE MAIN PROCESS DRIVER FINDS * THAT THE MAIN SCREEN PROMPT FOR COMMANDS YIELDED ONE OR * MORE MICROS (AMPERSAND SYMBOLS) SPECIFICALLY IN THE * CONVERSION OF FUNCTION KEY STRIKES INTO COMMAND TEXT, * OR IN FETCHING OF COMMAND LINES FROM PROCEDURES. * * ENTRY CMDLIN - COMMAND STRING CONTAINING MICROS. * EXPANDAT - POINTS TO FIRST AMPERSAND. * PROCACTIVE - MUST BE TRUE IF FORCED FALSE, OTHERWISE * TREAT CALL AS NO-OP. * CURFILE - CURRENT FILE BRACKET. * FILENAM[CURFILE] - CURRENT FILE NAME. * CURRENT - CURRENT LINE ADDRESS. * TOPF(CURFILE) - UPPER BOUND FOR FILE. * CURCURSOR - CURRENT CHARACTER POSITION IN FILE. * LIN - TEXT OF CURRENT FILE LINE. * ERRSTRING - USER'S ANNOUNCEMENT FOR "&?". * * EXIT CMDLIN - EXPANDED. * &C REPLACED WITH CURRENT COLUMN. * &F REPLACED WITH CURRENT FILENAME. * &L REPLACED WITH CURRENT LINE ORDINAL. * &P REPLACED WITH CURRENT PROCEDURE FILE NAME. * &T REPLACED WITH CURRENT TERMINAL. * &W REPLACED WITH CURRENT TEXT WORD. * &Z REPLACED WITH CURRENT WORKFILE. * &DIGIT REPLACED WITH PROC PARAMETER. * &? REPLACED WITH INTERACTIVE INPUT. * && REPLACED WITH &. * EXPANDAT - DESTROYED. * * MACROS GETCHAR, SETCHAR, MOD. * * CALLS EXPANDNUM(INTERNAL), DSPLCOD, MIN, LSHIFT, RSHIFT, * LENGTH, PROCPARM, ASKUSER. # ITEM TMP1; ITEM I,J,K,L,M; ITEM MSG C(80); ITEM INCR; PROC EXPANDNAME(NAME); BEGIN # * EXPANDNAME - GENERATE NAME SPECIFIED IN PARAMETER. # ITEM NAME; L=7; FOR I=6 STEP -1 UNTIL 0 DO BEGIN K=BNAME; CONTROL IFNQ CBLANK,O"55"; ERROR; CONTROL FI; IF K EQ CBLANK OR K EQ 0 THEN L=I; END L=MIN(L,BUFCM1-EXPANDAT); # ASSURE IT FITS # LSHIFT(CMDLIN,EXPANDAT+2,2); # REMOVE &F # RSHIFT(CMDLIN,EXPANDAT,L); # MAKE ROOM FOR NAME # FOR I=0 STEP 1 UNTIL L-1 DO BEGIN # NEXT CODE REQUIRES INTERNAL CHARSET MAPS ON DISPLAY CODE # CONTROL IFNQ CLETTERA,1; ERROR; CONTROL FI; K=BNAME; SETCHAR(CMDLINE,J,K); # STORE NAME # J=J+1; END INCR=L; END # EXPANDNAME # PROC EXPANDNUM; BEGIN # ** EXPANDNUM - GENERATE NUMBER SPECIFIED BY L. * * ENTRY L - NUMBER TO ENCODE. * CMDLIN - LINE IMAGE. * POSITION - CHARACTER LOCATION OF AMPERSAND. * * EXIT CMDLIN - UPDATED. * INCR - INCREMENTED * L - DESTROYED. * * USES I, K. * * NOTE SEE HEADER DOCUMENTATION FOR EXPAND. # LSHIFT(CMDLIN,EXPANDAT+1,1); I=0; INCR=1; WHYLE L NQ 0 OR I EQ 0 DO BEGIN K=MOD(L,10)+CDIGIT0; SETCHAR(CMDLINE,EXPANDAT,K); L=L/10; I=I+1; IF L NQ 0 THEN BEGIN RSHIFT(CMDLIN,EXPANDAT,1); INCR=INCR+1; END END END # OF EXPANDNUM # # MAIN CODE OF EXPAND STARTS HERE # WHYLE EXPANDAT LS LENGTH(CMDLIN) DO BEGIN GETCHAR(CMDLINE,EXPANDAT,TMP1); IF TMP1 NQ CAMPER THEN EXPANDAT=EXPANDAT+1; ELSE BEGIN INCR=1; J=EXPANDAT; GETCHAR(CMDLINE,EXPANDAT+1,K); DSPLCOD(K); # MAKE UPPER CASE # IF K EQ CLETTERF THEN # &F = FILENAME # BEGIN EXPANDNAME(FILENAM[CURFILE]); END ELSE IF K EQ CLETTERW THEN # &W = CURRENT WORD # BEGIN L=0; # LENGTH OF WORD # IF CURCURSOR LS LENGTH(LIN) THEN # MUST MEASURE # BEGIN J=CURCURSOR; GETCHAR(LINE,J,K); IF K EQ CBLANK THEN BEGIN WHYLE K EQ CBLANK DO BEGIN J=J+1; GETCHAR(LINE,J,K); END END IF K EQ CENDLINE THEN J=J-1; IF BWORDFLAG[K/32] EQ 0 THEN J=J-1; WHYLE J GQ 0 AND BWORDFLAG[K/32] EQ 1 DO BEGIN J=J-1; GETCHAR(LINE,J,K); END I=J+1; GETCHAR(LINE,I,K); WHYLE K NQ CENDLINE AND BWORDFLAG[K/32] EQ 1 DO BEGIN I=I+1; GETCHAR(LINE,I,K); L=L+1; END END L=MAX(L,1); L=MIN(L,BUFCM1-EXPANDAT); # ASSURE FITS # LSHIFT(CMDLIN,EXPANDAT+2,2); # EXTRACT &W # RSHIFT(CMDLIN,EXPANDAT,L); FOR I=1 STEP 1 UNTIL L DO # INSERT WORD # BEGIN GETCHAR(LINE,J+I,K); SETCHAR(CMDLINE,EXPANDAT+I-1,K); END INCR=L; END ELSE IF K EQ CLETTERL THEN BEGIN L=CURRENT-TOPF(CURFILE); EXPANDNUM; END ELSE IF K EQ CLETTERC THEN BEGIN L=CURCURSOR+1; EXPANDNUM; END ELSE IF K EQ CLETTERP THEN BEGIN # &P = PROCEDURE FILE NAME # EXPANDNAME(PROCNAM); END ELSE IF K EQ CLETTERZ THEN BEGIN EXPANDNAME(WORKORG); END ELSE IF K EQ CLETTERT THEN BEGIN IF SCREENMODE THEN BEGIN C<00,07>M=TABMODNAME[0]; # TERMINAL PROCEDURE # EXPANDNAME(M); END ELSE BEGIN M="LINE "; # LINE PROCEDURE # EXPANDNAME(M); END END ELSE IF K GR CDIGIT0 AND K LQ CDIGIT9 AND PROCACTIVE THEN BEGIN K=K-CDIGIT0; # PARAMETER NUMBER # CONTROL IFEQ SINGLE,1; PROCPARM(CMDLIN,J,K,BUFCM1,INCR); CONTROL FI; END ELSE IF K EQ CAMPER THEN LSHIFT(CMDLIN,EXPANDAT+1,1); ELSE IF K EQ CQUESTION THEN BEGIN MSG=ERRSTRING; # PRESERVE ANNOUNCEMENT # IF MSG EQ " $" THEN MSG="ENTER TEXT$"; ASKUSER(MSG,QCCKWRD); LSHIFT(CMDLIN,EXPANDAT+2,2); # KILL MICRO # L=LENGTH(TTYLIN); RSHIFT(CMDLIN,EXPANDAT,L); FOR I=0 STEP 1 UNTIL L-1 DO BEGIN GETCHAR(TTYLINE,I,J); SETCHAR(CMDLINE,EXPANDAT+I,J); END INCR=L; END EXPANDAT=EXPANDAT+INCR; END END END # EXPANDCMDS # CONTROL IFEQ SINGLE,1; PROC PROCPARM(TXTLIN,POS,NDX,MAXPOS,INCR); BEGIN # ** PROCPARM - EXPAND MICRO FOR PROCEDURE PARAMETERS. * * PROCPARM IS CALLED BY EXPAND TO EXPAND ONE PROC PARAMETER * MICRO, WHICH CONSISTS OF AN AMPERSAND FOLLOWED BY A DIGIT * REPRESENTING THE PARAMETER ORDINAL. IF THERE ARE NOT * ENOUGH PARAMETERS PROVIDED, THEN NULL OUT THE MICRO. * * ENTRY TXTLIN - INTERNAL LINE IMAGE PROVIDING TEXT. * POS - WHERE THE MICRO IS IN TXTLIN. * NDX - WHICH PARAMETER IS REQUESTED BY THE MICRO. * MAXPOS - MAX CHARACTER CAPACITY IN TXTLIN. * * EXIT TXTLIN - UPDATED. * POS - INCREMENTED PAST EXPANSION. * * MACROS GETCHAR, SETCHAR. * * CALLS LSHIFT, RSHIFT. # ARRAY TXTLIN [0:99]; ITEM TXTLINE; ITEM POS,NDX,MAXPOS,INCR; ITEM TMP1,TMP2,TMP3,TMP4,TMP5,TMP6; # FIRST SKIP PREVIOUS PARAMETERS AND BRACKET DESIRED PARM # TMP1=PARMPTR; FOR TMP2=1 STEP 1 UNTIL NDX DO BEGIN GETCHAR(PARMLINE,TMP1,TMP3); # SKIP LEADING BLANKS # WHYLE TMP3 EQ CBLANK DO BEGIN TMP1=TMP1+1; GETCHAR(PARMLINE,TMP1,TMP3); END IF TMP3 EQ CCOMMA THEN TMP1=TMP1+1; # SKIP LEAD COMMA # GETCHAR(PARMLINE,TMP1,TMP3); WHYLE TMP3 EQ CBLANK DO # SKIP FURTHER BLANKS # BEGIN TMP1=TMP1+1; GETCHAR(PARMLINE,TMP1,TMP3); END TMP4=TMP1; # SAVE START # IF TMP3 NQ CCOMMA THEN # NOT SKIPPED PARAMETER # BEGIN # SKIP TO NEXT DELIMETER # TMP5=CBLANK; # TWO NORMAL DELIMITERS # TMP6=CCOMMA; IF TYPE[TMP3] EQ TYPST"DELIMIT" THEN BEGIN # STRING NEEDS EXACT DELIMIT # TMP5=TMP3; TMP6=TMP3; END IF TMP3 NQ CENDLINE THEN TMP3=-1; WHYLE TMP3 NQ TMP5 AND TMP3 NQ TMP6 AND TMP3 NQ CENDLINE DO BEGIN # LOOK FOR EITHER DELIM OR EOL # TMP1=TMP1+1; GETCHAR(PARMLINE,TMP1,TMP3); END # IF STOPPED DUE TO STRING END, ADVANCE PAST IT # IF TMP3 EQ TMP5 AND TMP5 NQ CBLANK THEN TMP1=TMP1+1; END END TMP1=TMP1-TMP4; # LENGTH # TMP1=MIN(TMP1,MAXPOS-LENGTH(TXTLIN)); LSHIFT(TXTLIN,POS+2,2); # KILL @DIGIT # RSHIFT(TXTLIN,POS,TMP1); # MAKE ROOM # FOR TMP2=0 STEP 1 UNTIL TMP1-1 DO BEGIN # COPY THE PARAMETER # GETCHAR(PARMLINE,TMP4+TMP2,TMP3); SETCHAR(TXTLINE,POS+TMP2,TMP3); END POS=POS+TMP1; # ADVANCE PAST EXPANSION # INCR=TMP1; END # OF PROCPARM # CONTROL FI; PAGE # UTILITY ROUTINES ONLY FOR EXEC # FUNC FINDER(POS,LEN) B; # TITLE FINDER - SEARCH CURRENT LINE OF TEXT IN ONE OF EIGHT WAYS. # BEGIN # FINDER # # ** FINDER - SEARCH CURRENT LINE OF TEXT IN ONE OF EIGHT WAYS. * * FUNC FINDER(POS,LEN) * * ENTRY FINDCONTROL - WHICH MANNER OF SEARCH. * 0 = SIMPLE TEXT SEARCH. * NONZERO = COMPLEX SEARCH. * LIN - LINE OF TEXT TO SEARCH. * LOCSTRING1, LOCSTRING2 - ONE OR BOTH STRINGS TO MATCH. * LOCSTRLEN1, LOCSTRLEN2 - LENGTHS OF STRINGS. * FIELDFLG, FIELDBGN, FIELDEND - COLUMN MODE, LIMITS. * WORDSEARCH - MODE. * UPPERSEARCH - MODE. * ELLIPSIS - MODE. * BACKWARD - MODE. * * EXIT FINDER - SUCCESS OR FAILURE. * POS - CHARACTER POSITION WHERE WE MATCHED. * LEN - LENGTH OF TOTAL MATCHED AREA. * * MACROS GETCHAR. * * CALLS FASTFND, FASTLNB, FIND, LENGTH. * * NOTE FINDCONTROL VALUES ARE DESIGNED TO FUNCTION AS * INDEPENDENT BITS. # ITEM BOOL B; # FOUND FLAG # ITEM FIRSTPOS I; # FIRST CHARACTER POSITION # ITEM LASTPOS I; # LAST CHARACTER POSITION # ITEM LEN I; # LENGTH OF MATCHED AREA # ITEM LINLEN I; # LINE LENGTH # ITEM LOOPINDEX1 I; # LOOP INDEX # ITEM POS I; # CHARACTER POSITION OF MATCH # ITEM QUIT B; # QUIT FLAG # ITEM TMP1 I; # TEMPORARY STORAGE # ITEM TMP2 I; # TEMPORARY STORAGE # ITEM TMP3 I; # TEMPORARY STORAGE # ITEM TMP4 I; # TEMPORARY STORAGE # ITEM TMP5 I; # TEMPORARY STORAGE # DEF BOTHCASE #O"03760 00000 00000 00000"#; DEF CASELESS #O"01760 00000 00000 00000"#; FUNC FIND(STRING,STRLEN,SLWOTS,POSITION) B; # TITLE FIND - FIND STRING. # BEGIN # FIND # # ** FIND - FIND STRING. * * THE FIND ROUTINE IS DEPENDENT ON THE INTERNAL * CHARACTER SET WORD FORMATTING. * * FUNC FIND(STRING,STRLEN,SLWOTS,POSITION) * * ENTRY POSITION - POSITION IN STRING. * STRING - STRING TO SEARCH. * STRLEN - STRING LENGTH. * SLWOTS - STRING LENGTH WITHOUT TRAILING SPACES. * * EXIT BOOL - SUCCESS OR FAILURE. * * MACROS DSPLCOD, GETCHAR. * * CALLS DSPLCOD, FASTFND. # CONTROL IFNQ CLETTERA,1; BAD; CONTROL FI; CONTROL IFNQ CLOWERA,65; BAD; CONTROL FI; ARRAY STRING [0:99] P(1); BEGIN # ARRAY STRING # ITEM STRINGWORD I; # STRING WORD # END # ARRAY STRING # ITEM LOOPINDEX2 I; # LOOP INDEX # ITEM POSITION I; # POSITION IN STRING # ITEM STRLEN I; # STRING LENGTH # ITEM SLWOTS I; # STRING LENGTH W/O TRAIL SPACES # ITEM TMP1 I; # TEMPORARY STORAGE # ITEM TMP2 I; # TEMPORARY STORAGE # ITEM TMP3 I; # TEMPORARY STORAGE # ITEM TMP4 I; # TEMPORARY STORAGE # ITEM TMP5 I; # TEMPORARY STORAGE # ITEM TMP6 I; # TEMPORARY STORAGE # LOOPINDEX2=0; BOOL=FALSE; IF FIELDFLG THEN SLWOTS=MAX(SLWOTS,MIN(STRLEN,STRLEN-FIELDEND+LASTPOS)); WHYLE (NOT BOOL) AND (FIRSTPOS LQ LASTPOS) AND (LOOPINDEX2 LQ BUFCHAR) DO BEGIN LOOPINDEX2=LOOPINDEX2+1; IF UPPERSEARCH THEN BEGIN POSITION=FIRSTPOS; WHYLE (NOT BOOL) AND (POSITION LQ LASTPOS-SLWOTS+1) DO BEGIN TMP6=MIN(STRLEN,LASTPOS-POSITION+1); GETCHAR(LINE,POSITION,TMP2); GETCHAR(STRINGWORD,0,TMP3); TMP4=TMP2; TMP5=TMP3; DSPLCOD(TMP4); DSPLCOD(TMP5); IF BWORDFLAG[TMP2/32] EQ 1 AND BWORDFLAG[TMP4/32] EQ 1 THEN TMP2=TMP4; IF BWORDFLAG[TMP3/32] EQ 1 AND BWORDFLAG[TMP5/32] EQ 1 THEN TMP3=TMP5; IF TMP2 EQ TMP3 THEN BEGIN BOOL=TRUE; FOR TMP1=1 STEP 1 WHILE BOOL AND TMP1 LS TMP6 DO BEGIN GETCHAR(LINE,POSITION+TMP1,TMP2); GETCHAR(STRINGWORD,TMP1,TMP3); TMP4=TMP2; TMP5=TMP3; DSPLCOD(TMP4); DSPLCOD(TMP5); IF BWORDFLAG[TMP2/32] EQ 1 AND BWORDFLAG[TMP4/32] EQ 1 THEN TMP2=TMP4; IF BWORDFLAG[TMP3/32] EQ 1 AND BWORDFLAG[TMP5/32] EQ 1 THEN TMP3=TMP5; IF TMP2 NQ TMP3 THEN BOOL=FALSE; END END IF NOT BOOL THEN POSITION=POSITION+1; END END ELSE BOOL=FASTFND(LIN,LASTPOS,FIRSTPOS,STRING,STRLEN-1,SLWOTS-1, POSITION,BOTHCASE); IF BOOL AND WORDSEARCH THEN BEGIN IF POSITION NQ MIN(FIELDBGN,FIELDEND) THEN BEGIN GETCHAR(LINE,POSITION-1,TMP5); IF BWORDFLAG[TMP5/32] EQ 1 THEN BOOL=FALSE; END IF BOOL AND POSITION+STRLEN LS MAX(FIELDBGN,FIELDEND) THEN BEGIN GETCHAR(LINE,POSITION+STRLEN,TMP5); IF BWORDFLAG[TMP5/32] EQ 1 THEN BOOL=FALSE; END END IF NOT BOOL THEN BEGIN FIRSTPOS=1+MAX(FIRSTPOS,POSITION); IF NOT (WORDSEARCH OR UPPERSEARCH) THEN FIRSTPOS=LARGENUM; END END FIND=BOOL; END # FIND # # MAIN FINDER CODE STARTS HERE # LINLEN=LENGTH(LIN); LASTPOS=LINLEN-1; FINDER=FALSE; IF LASTPOS LS NUMWIDBLK THEN RETURN; IF FINDCONTROL EQ 0 THEN BEGIN BOOL=FASTFND(LIN,LASTPOS,FIELDBGN,LOCSTRING1,LOCSTRLEN1-1, FASTLNB(LOCSTRING1)-1,TMP2,BOTHCASE); IF BOOL THEN BEGIN POS=TMP2; LEN=LOCSTRLEN1; END FINDER=BOOL; RETURN; END # ELSE NEED COMPLEX SEARCH ALGORITHM # FIRSTPOS=MIN(FIELDBGN,FIELDEND); LASTPOS=MAX(FIELDBGN,FIELDEND); IF FIELDFLG THEN BEGIN IF BACKWARD THEN BEGIN IF (FIELDEND GQ LINLEN AND FIELDEND LS BUFCM1) OR FIELDEND GR FIELDBGN THEN RETURN; END ELSE BEGIN IF (FIELDBGN GQ LINLEN AND FIELDBGN LS BUFCM1) OR FIELDBGN GR FIELDEND THEN RETURN; END END ELSE BEGIN IF (NOT BACKWARD) AND FIELDBGN GQ FIELDEND THEN LASTPOS=BUFCM1; END FIRSTPOS=MIN(FIRSTPOS,LINLEN-1); LASTPOS=MIN(LASTPOS,LINLEN-1); LOOPINDEX1=0; QUIT=FALSE; WHYLE NOT QUIT DO BEGIN LOOPINDEX1=LOOPINDEX1+1; TMP2=FIRSTPOS; IF ELLIPSIS THEN BOOL=FIND(LOCSTRING1,LOCSTRLEN1,LOCSTRLEN1,TMP1); ELSE BOOL=FIND(LOCSTRING1,LOCSTRLEN1,FASTLNB(LOCSTRING1),TMP1); TMP3=TMP1; TMP4=LOCSTRLEN1; IF ELLIPSIS AND BOOL THEN BEGIN FIRSTPOS=TMP3+TMP4; IF FIRSTPOS LS LINLEN THEN BOOL=FIND(LOCSTRING2,LOCSTRLEN2,FASTLNB(LOCSTRING2),TMP1); ELSE BOOL=FALSE; TMP4=TMP1+LOCSTRLEN2-TMP3; END IF BOOL THEN BEGIN FINDER=TRUE; POS=TMP3; LEN=TMP4; FIRSTPOS=TMP2+1; END ELSE QUIT=TRUE; IF (NOT BACKWARD) OR FIRSTPOS GQ LINLEN THEN QUIT=TRUE; IF LOOPINDEX1 GQ BUFCHAR THEN QUIT=TRUE; END END # FINDER # PROC SUBST; # TITLE SUBST - TEXT SUBSTITUTION FOR REPLACE COMMAND. # BEGIN # SUBST # # ** SUBST - TEXT SUBSTITUTION FOR REPLACE COMMAND. * * THE SUBST ROUTINE IS CRUCIAL TO THE S COMMAND. IT DOES THE * ACTUAL SEARCHING AND ALTERATION WITHIN THE CURRENT LINE. * WE USE THE FINDER FUNCTION. OUR OUTER LOOP JUST KEEPS * LOOKING FOR MORE AND MORE TARGET STRINGS ACROSS THE LINE. * FOR EACH OF THEM, WE SUBSTITUTE, BUT ONLY AFTER WE HAVE * ACCOUNTED FOR CHANGES IN LENGTH THAT CAN SHUFFLE TRAILING * TEXT. TO ACCOMODATE FIELD-ORIENTATION, WE KEEP A COPY OF * THE ORIGINAL TEXT AND REBUILD THE FINAL PART. * * PROC SUBST * * ENTRY LIN - INTERNAL LINE IMAGE TO SEARCH/CHANGE. * LOCSTRING1, LOCSTRING2 - SEARCH KEY(S). * CHGSTRING1 - REPLACEMENT TEXT. * LOCSTRLEN1, LOCSTRLEN2, CHGSTRLEN1 - LENGTHS. * FINDCONTROL - PER "FINDER" HEADER DOCUMENTATION. * FIELDFLG, FIELDBGN, FIELDEND - PER FINDER. * ELLIPSIS, WORDSEARCH, UPPERSEARCH - PER FINDER. * SUBSTONCE - LOOP ONCE OR TO EXHAUSTION. * * EXIT LIN - CHANGED IF SEARCH SUCCEEDED. * FOUND - WHETHER SEARCH SUCCEEDED. * * MACROS GETCHAR, SETCHAR. * * CALLS LENGTH, MOVEWD, FINDER, TRIMPAD. * * USES FIELDBGN WITH RESTORATION. # ITEM DELTA I; # CHANGE REQUESTED # ITEM FINDBGN I; # BEGINNING OF FIELD # ITEM FINDLEN I; # LENGTH OF FIELD # ITEM HOLDBGN I; # HOLD BEGINNING OF FIELD # ITEM HOLDEND I; # HOLD ENDING OF FIELD # ITEM LINLEN I; # LINE LENGTH # ITEM LOOPINDEX I; # LOOP INDEX # ITEM QUIT B; # COMPLETE FLAG # ITEM SUMDELTA I; # TOTAL CHANGE REQUESTED # ITEM TMP1 I; # TEMPORARY STORAGE # ITEM TMP2 I; # TEMPORARY STORAGE # FOUND=FALSE; IF NOT FINDER(FINDBGN,FINDLEN) THEN RETURN; HOLDBGN=FIELDBGN; # MODIFY FIELD AND RESTORE # HOLDEND=FIELDEND; LINLEN=LENGTH(LIN); SUMDELTA=0; LOOPINDEX=0; FOR TMP1=LINLEN+1 STEP 1 UNTIL BUFCM1 DO SETCHAR(LINE,TMP1,CBLANK); MOVEWD(BUFWIDP1,LIN,TMPLIN); QUIT=FALSE; WHYLE FINDER(FINDBGN,FINDLEN) AND NOT QUIT DO BEGIN LINLEN=MAX(LINLEN,FINDBGN+FINDLEN); LOOPINDEX=LOOPINDEX+1; FOUND=TRUE; NEWCURSOR=FINDBGN; STRINGLEN=CHGSTRLEN1; DELTA=FINDLEN-CHGSTRLEN1; SUMDELTA=SUMDELTA+DELTA; IF DELTA GR 0 THEN # SHRINK FIELD # BEGIN FOR TMP1=FINDBGN+FINDLEN STEP 1 UNTIL LINLEN DO BEGIN GETCHAR(LINE,TMP1,TMP2); SETCHAR(LINE,TMP1-DELTA,TMP2); END END ELSE IF DELTA LS 0 THEN # FIELD GROWS # BEGIN FOR TMP1=LINLEN STEP -1 UNTIL FINDBGN+FINDLEN DO BEGIN IF TMP1-DELTA LQ BUFCM1 THEN BEGIN GETCHAR(LINE,TMP1,TMP2); SETCHAR(LINE,TMP1-DELTA,TMP2); END END END FOR TMP1=FINDBGN STEP 1 UNTIL FINDBGN+CHGSTRLEN1-1 DO BEGIN IF TMP1 LQ BUFCM1 THEN BEGIN GETCHAR(CHGSTR1,TMP1-FINDBGN,TMP2); SETCHAR(LINE,TMP1,TMP2); END END SETCHAR(LINE,BUFCHAR,CENDLINE); LINLEN=LENGTH(LIN); IF BACKWARD THEN BEGIN FIELDBGN=FINDBGN-1; IF FIELDBGN LS FIELDEND THEN QUIT=TRUE; END ELSE BEGIN IF FIELDEND GR FINDBGN THEN FIELDEND=FIELDEND-DELTA; FIELDBGN=FINDBGN+CHGSTRLEN1; IF FIELDFLG AND FIELDBGN GR FIELDEND THEN QUIT=TRUE; IF FIELDBGN GQ LINLEN THEN QUIT=TRUE; END IF SUBSTONCE THEN QUIT=TRUE; IF LOOPINDEX GQ BUFCHAR THEN QUIT=TRUE; END IF NOT FOUND THEN RETURN; FIELDBGN=HOLDBGN; # RESTORE FIELD # FIELDEND=HOLDEND; IF FIELDNDX GR 0 THEN BEGIN FIELDEND=MAX(FIELDBGN,FIELDEND); FOR TMP1=LINLEN STEP 1 UNTIL FIELDEND DO SETCHAR(LINE,TMP1,CBLANK); FOR TMP1=1 STEP 1 UNTIL SUMDELTA DO BEGIN SETCHAR(LINE,FIELDEND-TMP1+1,CBLANK); END FOR TMP1=FIELDEND+1 STEP 1 UNTIL BUFCM1 DO BEGIN GETCHAR(TMPLINE,TMP1,TMP2); SETCHAR(LINE,TMP1,TMP2); END END SETCHAR(LINE,BUFCHAR,CENDLINE); TRIMPAD; # REMOVE BLANKS # END # SUBST # PROC XSHOW; IOBEGIN(XSHOW) # ** XSHOW - DISPLAY LINE AND TEST WIDTH. * * ENTRY LIN - LINE OF TEXT. * DONTPRINT, SCREENMODE - CONTROL DISPLAY. * * CALLS CHECKWIDE, YSHOW. # YSHOW; CHECKWIDE; IOEND # OF XSHOW # PROC YSHOW; IOBEGIN(YSHOW) # ** YSHOW - DISPLAY LINE. * * ENTRY LIN - TEXT TO DISPLAY. * DONTPRINT, SCREENMODE - CONTROL DISPLAY. * LCOUNT - EXISTING WORK ACCOUNTING. * * EXIT LCOUNT - INCREMENTED. * * CALLS PRINTL. # IF NOT (DONTPRINT OR SCREENMODE) THEN PRINTL; LCOUNT=LCOUNT+1; # ACCURATE COUNT # IOEND # OF YSHOW # PROC PRINTL; IOBEGIN(PRINTL) # ** PRINTL - PRINT LINE. * * PRINTL PRINTS AN INTERNAL LINE IMAGE IN LINE MODE. FLOAT * LINE ORDINALS ARE PRINTED FOR CERTAIN CONDTIONS. * * ENTRY SCREENMODE - SHOULD NOT BE CALLED UNLESS OFF. * LIN - INTERNAL LINE IMAGE TO PRINT. * FLOAT - MODE FOR DISPLAY OF ORDINALS. * CURRENT, CURFILE - WHERE WE ARE IN FILES. * TOPF(CURFILE) - BOUNDS/RELOCATION FACTOR. * NUMBERED[CURFILE] - OVERRIDES FLOAT IF NON-ZERO. * USRNUMCOL - NQ 1, IF SET BY *SET VIEW COLUMNS*. * * CALLS PUSHTEMP, CONVOUT, TTLPAD, TTSTR, TTSYNC, VDTWTC, * VDTWTO, POPTEMP. FORMERLY ALSO FIXCTL. * * USES TEMP WITH RESTORATION. * * NOTE SINCE FSE ALWAYS DRIVES TERMINAL IN EITHER 6/12 * ASCII OR 8/12 TRANSPARENT MODES, WE CAN COMMENT-OUT * LOGIC USING FIXCTL TO SUPPRESS ACCIDENTAL/MALICIOUS * ISSUANCE OF NOS CONTROL BYTES. THIS OLD LOGIC * SHOULD BE RE-ENABLED IF THE EDITOR IS MODIFIED * TO DRIVE THE TERMINAL IN SIMPLE DISPLAY CODE. * PRINTL PLACES AN END OF LINE CHARACTER (INTERNAL) * INTO THE INTERNAL LINE IMAGE BEFORE TRANSLATION * AND THEN RESTORES THE ACTUAL CHARACTER. THIS * ALLOWS THE USE OF *SET VIEW COLUMNS* IN LINE MODE. * USRNUMCOL IS OFFSET BY FIVE TO PREVENT AUTOMATIC * TERMINAL WRAPPING AND CORRECT FOR LINE NUMBERS * FROM 1 TO 9999. FOR LINES PAST 9999 THE USER * SHOULD DO A SET VIEW COLUMNS TO A SMALLER VALUE. # PUSHTEMP; IF USRNUMCOL NQ 1 THEN BEGIN # IF USER HAS SET COLUMNS # GETCHAR(LINE,USRNUMCOL-5,TEMP); SETCHAR(LINE,USRNUMCOL-5,CENDLINE); END CONTROL IFEQ SINGLE,1; IF TTYOUTPUT OR ASCII[CURFILE] GQ 2 THEN CONVOUT(LIN,2); ELSE CONVOUT(LIN,1); CONTROL FI; CONTROL IFEQ MULTI,1; CONVOUT(LIN,2); CONTROL FI; IF USRNUMCOL NQ 1 THEN BEGIN # IF USER HAS SET COLUMNS # SETCHAR(LINE,USRNUMCOL-5,TEMP); END #IF FIXCTL(BUFWID2P1,TMPLIN) THEN TTLIN(APPROPO WARNING)# IF FLOAT AND NUMBERED[CURFILE] EQ 0 THEN BEGIN CONTROL IFEQ SINGLE,1; TEMP=CURRENT-TOPF(CURFILE); IF TTYOUTPUT THEN BEGIN IF TEMP GR 9999 THEN TTLPAD(TEMP,8," "); ELSE TTLPAD(TEMP,4," "); TTSTR(BLANKWRD); END ELSE BEGIN ITEM POS, BUFF C(10); BUFF=" "; POS=7; WHYLE TEMP NQ 0 DO BEGIN CBUFF=O"33"+MOD(TEMP,10); POS=POS-1; TEMP=TEMP/10; END VDTWTO(BUFF); END CONTROL FI; CONTROL IFEQ MULTI,1; TEMP=CURRENT-TOPF(CURFILE); IF TEMP GR 9999 THEN TTLPAD(TEMP,8," "); ELSE TTLPAD(TEMP,4," "); TTSTR(BLANKWRD); CONTROL FI; END TTSYNC; VDTWTC(TMPLIN); POPTEMP; IOEND # OF PRINTL # PROC CHECKWIDE; IOBEGIN(CHECKWIDE) # ** CHECKWIDE - CHECK LINE FOR EXCESS WIDTH. * * CHECKWIDE ENFORCES THE "SET VIEW WARN" PARAMETER BY * TESTING LINE IMAGE LENGTH AND FOR OVERSIZE LINE, WE * SET UP THE WARNING MESSAGE AND TRIGGER SHUTDOWN OF * DORANGE PROCESSING. * * ENTRY LIN - INTERNAL LINE IMAGE TO TEST. * WIDTH - THRESHHOLD. * NUMWIDBLK - FOR SEQUENCED FILES, NUMBER OF DIGITS. * * EXIT ERRSTRING - SET VIA "HALT" IF WIDE. * LINCTR - LARGENUM IF WIDE TO STOP DORANGE. * * CALLS LENGTH, HALT. # IF LENGTH(LIN) GR WIDTH+NUMWIDBLK AND PROCESSNDX NQ KEYST"DCMD" AND PROCESSNDX NQ KEYST"HCMD" THEN BEGIN HALT("WIDE LINE$"); LINCTR=LARGENUM; END IOEND # OF CHECKWIDE # PROC GETMOD; IOBEGIN(GETMOD) # ** GETMOD - PROMPT FOR ALTERATION MASK. * * GETMOD IS CALLED ANYTIME THE ALTER COMMAND REQUIRES * ADDITIONAL INTERACTION WITH THE USER TO OBTAIN THE * CHARACTER STRING WHICH WILL MASK THE ALTERATIONS. * * ENTRY LINPTR1 - LINE ADDRESS FOR START OF RANGE. * FLOAT - CONTROLS PROMPT ALIGNMENT FOR LINEMODE. * SCREENMODE - SHOULD BE OFF IF THIS ROUTINE CALLED. * CURFILE - WHICH FILE BRACKET IS TO BE ALTERED. * NUMBERED[CURFILE] - CONTROL PROMPTS ALIGNMENT. * ASCII[CURFILE] - CONTROLS LOWERCASE SUPPRESSION. * * EXIT TTYLIN - CONTAINS ALTERATION MASK. * * CALLS PUSHTEMP, TTST, POSZ, PRINTL, PROMPT, CONVIN, TRIM, * SQUELCH, POPTEMP. * * USES TEMP WITH RESTORATION, LIN, CURRENT. # PUSHTEMP; CONTROL IFEQ SINGLE,1; IF NOT INTERACT THEN BEGIN PROMPT(NULLWRD); GOTO GETMOD2; END CONTROL FI; IF FLOAT OR NUMBERED[CURFILE] NQ 0 THEN TEMP=0; ELSE TEMP=4; TTST(" ",TEMP); POSZ(LINPTR1); PRINTL; IF NUMBERED[CURFILE] NQ 0 THEN TEMP=NUMWIDBLK-4; ELSE IF FLOAT AND CURRENT-TOPF(CURFILE) GR 9999 THEN TEMP=5; ELSE IF FLOAT THEN TEMP=1; ELSE TEMP=0; TTST(" ",TEMP); IF TEMP LAN 1 EQ 1 THEN PROMPT(AQCCKWRD); ELSE PROMPT(AQCKWRD); GETMOD2: CONVIN(TTYLIN,2); TRIM(TTYLIN,1); IF ASCII[CURFILE] LQ 1 THEN SQUELCH(TTYLIN); POPTEMP; IOEND # OF GETMOD # PROC APPEND; BEGIN # ** APPEND - APPEND TTYLIN ONTO LIN. * * APPEND MERGES TWO INTERNAL LINE IMAGES WITH SOFT-TABS * INTERPRETED AS NEEDED. * * ENTRY LIN - INTERNAL LINE IMAGE TO APPEND ONTO. * TTYLIN - INTERNAL LINE IMAGE TO APPEND. * * ENTRY LIN - UPDATED. * TMPLIN - POSSIBLY DESTROYED. * * CALLS TRIMPAD, CONCAT, EXCHWD, DOTAB. # ITEM TMP1; TRIMPAD; TMP1=LENGTH(LIN); CONCAT(LIN,TTYLIN); EXCHWD(BUFWIDP1,LIN,TTYLIN); # SO DOTAB WORKS # DOTAB(TMP1,TMP1,NUMWIDBLK); EXCHWD(BUFWIDP1,TTYLIN,LIN); END # OF APPEND # PROC STRETCH; BEGIN # ** STRETCH - ADD BLANKS INSIDE A LINE IMAGE. * * STRETCH ADDS 30 BLANKS INSIDE A LINE WITH ATTENTION * TO THE EDITFIELD RESTRICTION. * * ENTRY LIN - INTERNAL LINE IMAGE. * CURCURSOR - WHERE TO ADD 30 BLANKS. * * EXIT LIN - UPDATED. * * MACROS SETCHAR. * * CALLS SAVEPROT, LENGTH, RSHIFT, TRIMPAD, MERGEPROT. * * USES PROTLIN. # ITEM TMP1, TMP2; TMP1=CURCURSOR; SAVEPROT; IF TMP1 LS LENGTH(LIN) THEN BEGIN RSHIFT(LIN,TMP1,30); FOR TMP2=TMP1 STEP 1 UNTIL TMP1+29 DO SETCHAR(LINE,TMP2,CBLANK); END TRIMPAD; MERGEPROT; END # OF STRETCH # PROC SQUEEZE; # TITLE SQUEEZE - REMOVE BLANKS THEN NONBLANKS THEN BLANKS. # BEGIN # SQUEEZE # # ** SQUEEZE - REMOVE BLANKS THEN NONBLANKS THEN BLANKS. * * PROC SQUEEZE * * ENTRY LIN - INTERNAL LINE IMAGE. * CURCURSOR - WHERE IN LIN TO UPDATE. * * EXIT LIN - UPDATED. * * MACROS GETCHAR, SETCHAR. * * CALLS LENGTH, LSHIFT, MERGEPROT, SAVEPROT, TRIMPAD. * * USES PROTLIN. # ITEM TMP1 I; # TEMPORARY STORAGE # ITEM TMP2 I; # TEMPORARY STORAGE # ITEM TMP3 I; # TEMPORARY STORAGE # TMP1=CURCURSOR; SAVEPROT; IF TMP1 LS LENGTH(LIN) THEN BEGIN TMP2=TMP1; GETCHAR(LINE,TMP2,TMP3); IF TMP3 EQ CBLANK THEN BEGIN WHYLE TMP3 EQ CBLANK DO BEGIN TMP2=TMP2+1; GETCHAR(LINE,TMP2,TMP3); END END ELSE BEGIN IF BWORDFLAG[TMP3/32] EQ 0 THEN TMP2=TMP2+1; ELSE BEGIN WHYLE BWORDFLAG[TMP3/32] EQ 1 DO BEGIN TMP2=TMP2+1; GETCHAR(LINE,TMP2,TMP3); END WHYLE TMP3 EQ CBLANK DO BEGIN TMP2=TMP2+1; GETCHAR(LINE,TMP2,TMP3); END END END LSHIFT(LIN,TMP2,TMP2-TMP1); END TRIMPAD; MERGEPROT; END # SQUEEZE # CONTROL IFEQ SINGLE,1; PROC DOCENTER; BEGIN # ** DOCENTER - ALIGN TEXT IN CENTER OF MARGINS. * * ENTRY LIN - INTERNAL LINE IMAGE. * FILLEFT, FILLRIGHT - MARGINS. * CURFILE, NUMBERED[CURFILE] - CONTROL TEXT ALIGNMENT. * * EXIT LIN - UPDATED. * * MACROS GETCHAR, SETCHAR. * * CALLS GETLNUM, LSHIFT, RSHIFT, TRIM, LENGTH, SETLNUM. * * USES LINENO, WIDTHFOUND. # ITEM TMP1, TMP2, TMP3, TMP4; # FIND FIRST NON-BLANK # TMP1=-1; IF NUMBERED[CURFILE] NQ 0 THEN BEGIN GETLNUM; LSHIFT(LIN,NUMWIDBLK,NUMWIDBLK); END TRIM(LIN,0); TMP4=LENGTH(LIN); FOR TMP2=0 STEP 1 UNTIL TMP4 DO BEGIN GETCHAR(LINE,TMP2,TMP3); IF TMP3 NQ CBLANK AND TMP1 LS 0 THEN TMP1=TMP2; END # CENTER LINE ONLY IF NON-NULL AND NOT TOO LARGE # TMP4=TMP4-TMP1; IF TMP1 GQ 0 AND TMP4 LQ FILLRIGHT-FILLLEFT+1 THEN BEGIN # ELIMINATE LEADING BLANKS # LSHIFT(LIN,TMP1,TMP1); # COMPUTE PADDING FACTOR AND REALIGN # TMP2=(FILLRIGHT-FILLLEFT+1)-TMP4; # NUMBER OF XTRA BLANKS # TMP2=TMP2/2; # SPLIT THE DIFFERENCE # TMP2=TMP2+FILLLEFT; # ADD FIELD START POINT # RSHIFT(LIN,0,TMP2); FOR TMP1=1 STEP 1 UNTIL TMP2 DO SETCHAR(LINE,TMP1-1,CBLANK); END # RESTORE SEQUENCE NUMBER # IF NUMBERED[CURFILE] NQ 0 THEN BEGIN RSHIFT(LIN,0,NUMWIDTH+BLANKS); FOR TMP1=1 STEP 1 UNTIL NUMWIDTH DO SETCHAR(LINE,TMP1-1,CDIGIT0); SETLNUM; END END # OF DOCENTER # CONTROL FI; PROC DOMOD; BEGIN # ** DOMOD - PERFORM MASKED ALTERATIONS ON LINE IMAGE. * * DOMOD IMPLEMENTS THE TEXT PROCESSING FOR THE ALTER * COMMAND. WE SCAN THE TTYLIN, AND ACT UPON EACH CHARACTER * ALTERING LIN. THE CALLER IS RESPONSIBLE FOR HONORING THE * EDITFIELD RESTRICTION. * * ENTRY LIN - INTERNAL LINE IMAGE. * TTYLIN - ALTERATION MASK. * COPCHAR, BLKCHAR, DELCHAR, INSCHAR, TRNCHAR - * ACTION SYMBOLS. * * EXIT LIN - UPDATED. * * MACROS GETCHAR, SETCHAR. * * CALLS PAD, MOVEWD, LENGTH, TRIMPAD. * * USES TMPLIN. # ITEM TMP1,TMP2,TMP3; ITEM NEWPOS,TTYCHAR; ITEM LINLEN, TTYLEN; ITEM LINPOS,TTYPOS; LINLEN=LENGTH(LIN); TTYLEN=LENGTH(TTYLIN); PAD(LIN); MOVEWD(BUFWIDP1,LIN,TMPLIN); LINPOS=NUMWIDBLK; TTYPOS=0; NEWPOS=LINPOS; WHYLE TTYPOS LS TTYLEN AND LINPOS LQ BUFCM1 AND NEWPOS LQ BUFCM1 DO BEGIN GETCHAR(TTYLINE,TTYPOS,TTYCHAR); IF TTYCHAR EQ COPCHAR THEN # COPY 1 CHAR # BEGIN GETCHAR(TMPLINE,NEWPOS,TMP2); SETCHAR(LINE,LINPOS,TMP2); NEWPOS=NEWPOS+1; TTYPOS=TTYPOS+1; LINPOS=LINPOS+1; END ELSE IF TTYCHAR EQ BLKCHAR THEN # GEN A BLANK # BEGIN SETCHAR(LINE,LINPOS,CBLANK); NEWPOS=NEWPOS+1; TTYPOS=TTYPOS+1; LINPOS=LINPOS+1; END ELSE IF TTYCHAR EQ DELCHAR THEN # DELETE A BUNCH # BEGIN # FIND OUT HOW MANY # TMP2=0; FOR TMP1=TTYPOS STEP 1 UNTIL TTYLEN DO BEGIN GETCHAR(TTYLINE,TMP1,TMP3); IF TMP2 EQ 0 AND TMP3 NQ DELCHAR THEN TMP2=TMP1; END # TMP2 GUARANTEED # TMP2=TMP2-TTYPOS; # NOW LENGTH OF DELETION # TTYPOS=TTYPOS+TMP2; NEWPOS=NEWPOS+TMP2; END ELSE IF TTYCHAR EQ INSCHAR THEN # INSERT A BUNCH # BEGIN # SCAN FOR ENTIRE INSERT # TMP2=0; FOR TMP1=TTYPOS+1 STEP 1 UNTIL TTYLEN DO BEGIN GETCHAR(TTYLINE,TMP1,TMP3); IF TMP2 EQ 0 AND TMP3 EQ DELCHAR THEN TMP2=TMP1; END # TMP2 NOT GUARANTEED # IF TMP2 EQ 0 THEN TMP2=TTYLEN; # NOW COPY INSERTED SECTION # FOR TMP1=TTYPOS+1 STEP 1 WHILE TMP1 LS TMP2 AND LINPOS LQ BUFCM1 DO BEGIN GETCHAR(TTYLINE,TMP1,TMP3); SETCHAR(LINE,LINPOS,TMP3); LINPOS=LINPOS+1; END # NOW COPY TYPED-OVER SECTION # FOR TMP1=0 STEP 1 UNTIL TMP2-TTYPOS DO BEGIN IF LINPOS GQ BUFCHAR OR NEWPOS GQ BUFCHAR THEN TEST; GETCHAR(TMPLINE,NEWPOS,TMP3); SETCHAR(LINE,LINPOS,TMP3); NEWPOS=NEWPOS+1; LINPOS=LINPOS+1; END TTYPOS=MIN(TMP2+1,TTYLEN); END ELSE IF TTYCHAR EQ TRNCHAR THEN # TRUNCATE SOURCE # BEGIN FOR TMP1=NEWPOS STEP 1 UNTIL BUFCM1 DO SETCHAR(TMPLINE,TMP1,CBLANK); TTYPOS=TTYPOS+1; END ELSE # JUST OVERSTRIKE # BEGIN SETCHAR(LINE,LINPOS,TTYCHAR); TTYPOS=TTYPOS+1; NEWPOS=NEWPOS+1; LINPOS=LINPOS+1; END END # OF LOOP # # FINALLY COPY BACK ANY TRAILING PART FROM TMPLIN # TMP3=LINPOS; FOR TMP1=NEWPOS STEP 1 UNTIL BUFCM1 DO BEGIN GETCHAR(TMPLINE,TMP1,TMP2); IF TMP3 LQ BUFCM1 THEN BEGIN SETCHAR(LINE,TMP3,TMP2); TMP3=TMP3+1; END END SETCHAR(LINE,TMP3,CENDLINE); TRIMPAD; END # OF DOMOD # CONTROL IFEQ MULTI,1; PROC MULTMOV; IOBEGIN(MULTMOV) # ** MULTMOV - COPY/MOVE COMMANDS, EASY CONDITIONS. * * MULTMOV PERFORMS THE COPY AND MOVE COMMANDS IN MULTI-USER * MODE UNDER EASY CONDITIONS - LESS THAN 40 LINES IN THE * SOURCE BLOCK AND LINE BOUNDARIES AS OPPOSED TO CHARACTER * BOUNDARIES. * * ENTRY COMMAND PROCESSOR HAS RECOGNIZED VERB. * TOKEN ADVANCED BUT NO OTHER SCANNING DONE. * TOKENTYPE, SCANPOS, TOKENPOS, ETC - AS ABOVE. * CURFILE, CURSPLIT, CURRENT - DEFAULT ADDRESS. * CHARRANGE - CHARACTER OR LINE RANGE BOUNDS. * SCREENMODE - FINAL POSITIONING/PRINTING. * WIDTH - THIS SETTING WILL BE IGNORED. * BLANKS - THIS SETTING WILL BE IGNORED. * * EXIT CURFILE, CURRENT - FINAL RESTING PLACE. * (ANOTHER FILE MAY HAVE BEEN OPENED) * * CALLS DOSEGMENT(INTERNAL), MIN, POSZ, PUSH, SQUELCH, * SETLNUM, TRIMPAD, INSX, DORANGE, POP, DELX, FWDZ, * SCANNER, FITNUM, HALT, VFYLOCK. * * USES LINPTR1-3, CHRPTR1-3, FILPTR1-3, LINNUM1-3, * LINCTR, LIMIT, LINENO, P, LCOUNT, * REGLINE[RNGTOPREG], REGLINE[RNGBOTREG], FOUND. # XREF LABEL QQSINGLE; PROC DOSEGMENT; IOBEGIN(DOSEGMENT) # ** DOSEGMENT - MULTMOV INTERNAL ALGORITHM. * * DOSEGMENT EXISTS BECAUSE THE MAJOR ALGORITHM OF MULTMOV * MUST BE EXECUTED TWICE - THUS THIS ROUTINE CONSOLIDATES * CODE. THE ALGORITHM MUST OPERATE ON (POTENTIALLY) TWO * SEGMENTS TO PREVENT AN INFINITE DUPLICATION OF FILE * CONTENT FOR A COPY TO A TARGET WITHIN THE SOURCE RANGE. * * ENTRY LINPTR1, LINPTR2 - FIRST AND LAST LINES OF SOURCE. * LIMIT - NUMBER OF LINES IN SOURCE. * LINPTR3 - TARGET ADDRESS TO INSERT AFTER. * FILPTR1, FILPTR3 - FILE ASSOCIATIONS. * TWO LEVELS OF POSITIONING STACK - USED TO PRESERVE * SECOND SEGMENT BOUNDS WHILE PROCESSING FIRST. * * EXIT TWO LEVELS OF STACK - RELOCATED PROPERLY. * LINPTR1, LINPRT2, LINPTR3 - POSSIBLY DESTROYED. * LCOUNT - NUMBER OF LINES PROCESSED IS INCREMENTED. * * USES LINCTR, REGLINE[RNGTOPREG]. * * NOTE SEE HEADER FOR MULTMOV. # # POSITION TO SOURCE AND PROCESS SEGMENT # POSZ(LINPTR1); FOR LINPTR3=1 STEP 1 WHILE LINPTR3 LQ LIMIT AND USRBRK EQ 0 DO BEGIN PUSH; # KEEP TRACK OF SOURCE POSITION # P=0; # SUPPRESS WORKIO LINE BUFFER READOUT # POSZ(REGLINE[RNGTOPREG]); # GET TO TARGET ADDRESS # P=LOC(LIN); # RESTORE NORMAL WORKIO FUNCTION # CURFILE=FILPTR3; IF ASCII[FILPTR1] GQ 2 AND ASCII[FILPTR3] LQ 1 THEN SQUELCH(LIN); # FIX UP TEXT OF LINE # LINENO=LINENO+INCR; SETLNUM; SETCHAR(LINE,EDITFIELD,CENDLINE); # CLEAR TO END OF LINE # TRIMPAD; INSX; # COPY ONE LINE # REGLINE[RNGTOPREG]=CURRENT; # UPDATE TARGET ADDRESS # POP; # BACK TO SOURCE RANGE # IF FILCMDNDX EQ FILCMDST"MOVE" THEN DELX; LCOUNT=LCOUNT+1; # ADJUST OFFICIAL WORK COUNT # FWDZ; # ADVANCE WITHIN RANGE # END IOEND # OF DOSEGMENT # # MULTMOV ACTUAL CODE STARTS HERE # LCOUNT=TOKENPOS; # TEMPORARY MECHANISM FOR SNGLMOV # SCANNER; # GET ALL ADDRESSES # IF EXECNDX EQ EXECST"MOVE" THEN BEGIN # IF MOVE COMMAND # VFYLOCK; IF SCANMARK THEN KILLMARKS = TRUE; END CURFILE = = FILPTR3; VFYLOCK; CURFILE = = FILPTR3; IF TOPF(CURFILE) EQ BOTF(CURFILE)-1 THEN BEGIN HALT("EMPTY FILE$"); END ELSE IF NOT FOUND THEN BEGIN HALT("OUT OF BOUNDS$"); END IF NOT FOUND THEN IORET LINPTR2=MIN(LINPTR2,LINPTR1+LIMIT-1); # TIGHTEN BOUNDS # LIMIT=LINPTR2-LINPTR1+1; IF LIMIT GQ 40 OR CHARRANGE OR FIELDTARGET NQ 0 THEN GOTO QQSINGLE; # TEST THAT LINE NUMBERS CAN BE FITTED IF NEEDED # POSZ(LINPTR3); FITNUM; NUMWIDBLK=0; IF NUMBERED[FILPTR3] NQ 0 THEN NUMWIDBLK=NUMWIDTH+BLANKS; # CHECK FOR INCOMPATIBLE CHARACTER SETS. IF TARGET FILE IS # # EMPTY, WE CHANGE ITS CHARACTER SET. OTHERWISE, DOSEGMENT # # WILL SUPPRESS CASE OF TEXT. # IF ASCII[FILPTR1] GQ 2 AND ASCII[FILPTR3] EQ 0 AND BOTF(FILPTR3)-TOPF(FILPTR3)-1 EQ THISEXTEND THEN ASCII[FILPTR3]=ASCII[FILPTR1]; # CHECK FOR TARGET INSIDE RANGE. STORE ON STACK THE (FIRST) AND # # (LAST) LINES TO BE PROCESSED AS SECOND SEGMENT. # IF LINPTR3 GQ LINPTR1 AND LINPTR3 LS LINPTR2 THEN BEGIN POSZ(LINPTR3+1); PUSH; POSZ(LINPTR2); PUSH; LINPTR2=LINPTR3; # CUT OFF FIRST SEGMENT # LIMIT=LINPTR2-LINPTR1+1; END ELSE BEGIN POSZ(0); # INDICATE NO SECOND SEGMENT # PUSH; PUSH; END # STORE TARGET ADDRESS IN RELOCATABLE REGISTER # REGLINE[RNGTOPREG]=LINPTR3; LCOUNT=0; # INITIALIZE ACTUAL LINE COUNT # DOSEGMENT; # NOW RETRIEVE BOUNDS FOR SECOND SEGMENT # POP; LINPTR2=CURRENT; POP; LINPTR1=CURRENT; LIMIT=LINPTR2-LINPTR1+1; IF CURRENT GR 0 THEN DOSEGMENT; CURFILE=FILPTR3; # FINAL POSITIONING AND PRINTING # IF SCREENMODE THEN POSZ(REGLINE[RNGTOPREG]-LCOUNT+1); ELSE BEGIN POSZ(REGLINE[RNGTOPREG]); IF NOT DONTPRINT THEN BEGIN LINPTR1=CURRENT-LCOUNT+1; LINPTR2=BOTF(FILPTR3)-1; LIMIT=LCOUNT; EXECNDX=EXECST"TYPE"; DORANGE; END END IOEND # OF MULTMOV # CONTROL FI; PROC SAVEPROT; BEGIN # ** SAVEPROT - SAVE COPY OF LINE IMAGE FOR EDITFIELD. * * SAVEPROT IS ONE OF THE MAJOR INTERFACES BY WHICH EDITING * CODE CAN COMPLY WITH EDITFIELD RESTRICTIONS. SAVEPROT * COPIES THE LINE IMAGE INTO PROTLIN AND TRUNCATES ORIGINAL. * * ENTRY LIN - INTERNAL LINE IMAGE. * EDITFIELD - START COLUMN FOR PROTECTED FIELD. * * EXIT PROTLIN - COPY OF ORIGINAL LIN CONTENT. * LIN - TRUNCATED AT EDITFIELD TO HIDE FIELD. * * MACROS SETCHAR. * * CALLS COPYLIN, TRIMPAD. # IF EDITFIELD GQ BUFCM1 THEN RETURN; COPYLIN(LIN,PROTLIN); SETCHAR(LINE,EDITFIELD,CENDLINE); TRIMPAD; END # OF SAVEPROT # PROC MERGEPROT; # TITLE MERGEPROT - MERGE MODIFIED LINE WITH PROTECTED FIELD. # BEGIN # MERGEPROT # # ** MERGEPROT - MERGE MODIFIED LINE WITH PROTECTED FIELD. * * MERGEPROT IS ONE OF THE MAJOR INTERFACES WITH WHICH * EDITING CODE CAN COMPLY WITH EDITFIELD RESTRICTIONS. * * PROC MERGEPROT * * ENTRY LIN - MODIFIED INTERNAL LINE IMAGE. * PROTLIN - UNMODIFIED VERSION OF SAME LINE. * EDITFIELD - SHOWS WHICH FIELDS TO MERGE. * * EXIT LIN - PARTIALLY DE-MODIFIED. * * MACROS GETCHAR, SETCHAR. * * CALLS EXTENDC, TRIMPAD. # ITEM TMP1 I; # TEMPORARY STORAGE # ITEM TMP2 I; # TEMPORARY STORAGE # IF EDITFIELD GQ BUFCM1 THEN RETURN; IF LENGTH(PROTLIN) LQ EDITFIELD THEN RETURN; EXTENDC(LIN,EDITFIELD); FOR TMP1=EDITFIELD STEP 1 UNTIL BUFCHAR DO BEGIN GETCHAR(PROTLINE,TMP1,TMP2); SETCHAR(LINE,TMP1,TMP2); END SETCHAR(LINE,BUFCHAR,CENDLINE); TRIMPAD; END # MERGEPROT # PROC SETFIELD; BEGIN # ** SETFIELD - ESTABLISH TAB-FIELD RESTRICTIONS. * * SETFIELD IS CALLED TO SET UP THOSE VARIABLES WHICH CAN * CONTROL LIMITATIONS ON TEXT MANIPULATION BY TAB-FIELD * COLUMNS. NOTE THAT ACTUAL COMPLIANCE WITH SUCH * RESTRICTIONS IS LEFT TO THE ACTUAL MANIPULATORS. * * ENTRY FIELDNDX - SHOWS WHICH FIELD IF ANY. * NUMWIDBLK - OFFSET TO IGNORE SEQUENCE NUMBERS. * * EXIT FIELDFLG - WHETHER RESTRICTIONS APPLICABLE. * FIELDBGN, FIELDEND - FIELDNDX CONVERTED TO COLUMNS. * * CALLS TABFN. # ITEM TMP1 I; # TEMPORARY STORAGE # ITEM TMP2 I; # TEMPORARY STORAGE # IF FIELDNDX NQ 0 THEN BEGIN FIELDFLG=TRUE; IF FIELDNDX GR 0 THEN BEGIN # IF USING TAB FIELDS # TMP1 = NUMWIDBLK+TABFN(FIELDNDX-1); TMP2 = NUMWIDBLK+TABFN(FIELDNDX)-1; END ELSE BEGIN # IF USING DIRECT COLUMNS # TMP1 = INFLDBGN; TMP2 = INFLDEND; END IF TMP2 LS TMP1 THEN TMP2 = BUFCM1; IF BACKWARD THEN BEGIN IF NOT (FIRSTRANGE AND (FIELDBGN LS TMP2)) THEN FIELDBGN = TMP2; FIELDEND = TMP1; END ELSE BEGIN IF NOT (FIRSTRANGE AND (FIELDBGN GR TMP1)) THEN FIELDBGN = TMP1; FIELDEND = TMP2; END END END # OF SETFIELD # PROC SETFIRST; BEGIN # ** SETFIRST - SET PARAMETERS FOR FIRST LINE OF RANGE. * * SETFIRST IS USED BY DORANGE TO INDICATE WHEN WE ARE * PROCESSING THE FIRST LINE OF A RANGE, (BY CHRONOLOGY * RATHER THAN POSITION), AND ALSO SETS UP THE VARIABLES * WHICH NORMALLY CONTROL TAB FIELD LIMITATIONS SO AS TO * LIMIT MANIPULATIONS TO OCCUR NO EARLIER THAN A CURSOR * POSITION. THIS CONVERTS SOME OPERATIONS INTO CHARACTER- * MODE IN PLACE OF RANGE MODE. NOTE THAT ACTUAL COMPLIANCE * WITH FIELD LIMITATIONS IS LEFT TO THE MANIPULATORS. * * ENTRY CHRPTR1 - FIRST COLUMN OF STREAM. * * EXIT FINDCONTROL - BOTTOM BIT IS FORCED ON. * FIELDFLG - FORCED TRUE. * FIELDBGN, FIELDEND - BRACKET SECOND HALF OF LINE. * * CALLS MAX. # FIRSTRANGE=TRUE; FINDCONTROL=FINDCONTROL LOR 1; FIELDFLG=TRUE; FIELDBGN=MAX(CHRPTR1,NUMWIDBLK); IF NOT BACKWARD THEN FIELDEND=BUFCM1; END PROC SETLAST; BEGIN # ** SETLAST - SET PARAMETERS FOR LAST LINE OF RANGE. * * SETLAST IS SIMILAR TO SETFIRST EXCEPT THAT IT INDICATES * THE RANGE IS ALMOST DONE AND BRACKETS THE FIRST HALF * INSTEAD OF THE SECOND HALF OF THE LINE FOR CHARACTER- * STREAM ORIENTATION. * * ENTRY CHRPTR2 - LAST EDITABLE COLUMN OF STREAM. * * EXIT LASTRANGE - FORCED TRUE. * FINDCONTROL - BOTTOM BIT FORCE ON. * FIELDFLG - FORCED TRUE. * FIELDEND - BRACKET END OF STREAM. * * CALLS MAX. # LASTRANGE=TRUE; FINDCONTROL=FINDCONTROL LOR 1; FIELDFLG=TRUE; FIELDEND=MAX(CHRPTR2,NUMWIDBLK); END PAGE # EXEC ROUTINE # PROC EXEC; IOBEGIN(EXEC) # ** EXEC - FAN-OUT TO TEXT MANIPULATOR FOR ONE LINE OF RANGE. * * THE EXEC ROUTINE CONTAINS CHUNKS OF CODE THAT NEED TO BE * EXECUTED ONCE PER LINE FOR THOSE COMMANDS THAT WORK ON * RANGES OF LINES. THIS IS A MEDIUM-SIZED SUBSET OF ALL * CMDS. THE COMMAND HANDLING ROUTINES IN PROCESS MUST SELECT * THEIR BROTHER HERE IN EXEC BY SETTING EXECNDX TO THE RIGHT * STATUS VALUE BEFORE CALLING EXEC. EXEC WILL DO A SWITCH * GOTO ON THE BASIS OF EXECNDX. * * THE CASE HANDLERS IN EXEC ARE ALLOWED TO EXECUTE * NON-REENTRANT CODE SEQUENCES FOR THE PURPOSE OF TEXT * MANIPULATION. THESE SEQUENCES CAN USE GLOBAL STORAGE. * TERMINAL OR FILE OPERATIONS HOWEVER MUST FOLLOW REENTRANT * CODING PRINCIPLES. * * THE LINCTR VARIABLE IS THE CRUCIAL LINK BETWEEN DORANGE AND * EXEC. IT IS THE COUNTER FOR USER LIMITS. THE OUTER LOGIC * ALWAYS INCREMENTS IT AS A WISEST ASSUMPTION. THE FIND AND * SUBSTITUTE COMMAND HANDLERS THEN MUST DECREMENT IT UPON * FAILURE SO AS IT KEEP IT CONSTANT. NOTE THAT DORANGE KNOWS * HOW MANY TIMES TO CALL US WITH REGARD TO THE NUMBER OF * LINES IN THE RANGE. * * EXEC IS ALSO OBLIGATED TO CHECK FOR INTERRUPT CONDITIONS * WHICH MUST TERINATE RANGE PROCESSING, AND TO SET LINCTR * UPON INTERRUPTS TO SIGNAL SHUTDOWN TO DORANGE. * * ENTRY LIN - CURRENT INTERNAL LINE IMAGE. * CURRENT, CURFILE, CURSPLIT - WHERE WE ARE IN FILE. * FIELDNDX - DEFINES TAB-FIELD LIMITATIONS. * FIELDFLG, FIELDBGN, FIELDEND - MAY HAVE FIELD LIMITS. * CHARRANGE - MODE. * FIRSTRANGE, LASTRANGE - WHETHER AT BOUNDS OF RANGE. * FORCEFIELD - EXPLICIT FIELD CONSTRAINT IN SYNTAX. * LINPTR1 - SAME AS CURRENT. * LINPTR2 - ORIGINAL LINE ADDRESS FOR END OF RANGE. * CHRPTR1, CHRPTR2 - CHARACTER BOUNDARIES IF ANY. * USRBRK - USER INTERRUPT. * LINCTR - COUNTER AGAINST LIMIT. * LIMIT - LIMIT ON RANGE ITERATION. * EXECNDX - WHICH CODE IN EXEC TO EXECUTE. * LCOUNT - ACCURATE COUNT OF LINES PROCESSED. * CANINTER - CONTROLS INTERRUPTABILITY OF COMMANDS. * DONTPRINT - CONTROL PRINTOUT. * SCREENMODE - ALSO CONTROLS PRINTOUT. * * EXIT LINCTR - INCREMENTED TOWARDS LIMIT. * (NOT INCREMENTED FOR MISSED SEARCH) * (LARGENUM FOR ANY TYPE OF FORCED SHUTDOWN) * LCOUNT - INCREMENTED. * FIELDFLG, FIELDBGN, FIELDEND - POSSIBLY DESTROYED. * LIN - UPDATED AND TRANSMITTED INTO FILE. * DONTPRINT - POSSIBLY DESTROYED IF INTERRUPTED. * NEWCURSOR - CURSOR AFTER SEARCH. * STRINGLEN - LENGTH OF SEARCHED STRING. * * MACROS GETCHAR, SETCHAR. * * CALLS SETCHRPTR(INTERNAL), DODELETE(INTERNAL), * SETFIELD, TRIMPAD, MERGEPROT, REPX, DELX, * CHKVICTIM(MULTI), CLEARQUE(MULTI), * SAVEPROT, APPEND, XSHOW, XFRCMOUT, FINDER, NOPOP, * GLOBALLOCATE, PUSH, DOMOD, DOCENTER, GLOBALCHANGE, * SUBST, LENGTH. * * USES CHRPTR1, CHRPTR2. # # EXECSW MUST MATCH EXECST # SWITCH EXECSW XXAPPEND, XXCENTER, XXCOPY, XXDELETE, XXLOCATE, XXMODIFY, XXMOVE, XXREPLACE, XXTYPE; # INTERNAL PROCEDURES # PROC SETCHRPTR; BEGIN # ** SETCHRPTR - SETUP CHARACTER POINTERS. * * SETCHRPTR IS AN INTERNAL ALGORITHM TO CONSOLIDATE CODE * FREQUENTLY USED WITHIN THE EXEC ROUTINE. SETCHRPTR * SETS UP THE CHRPTR1 AND CHRPTR2 VARIABLES BASED ON * ANY FIELD RESTRICTIONS. * * ENTRY FIELDBGN, FIELDEND - POSSIBLY SETUP BY SETFIRST * OR SETLAST. * FORCEFIELD - WHETHER EXPLICIT FIELD SYNTAX. * FIELDNDX - WHICH TAB FIELD. * NUMWIDBLK - SETUP PER SEQUENCE MODE AND LINE CONTENT. * * EXIT FIELDBGN, FIELDEND - POSSIBLY SETUP BY SETFIELD. * CHRPTR1, CHRPTR2 - POSSIBLY MATCH FIELDBGN, FIELDEND. * FIELDFLG - POSSIBLY SETUP BY SETFIELD. * * CALLS SETFIELD. # SETFIELD; IF FORCEFIELD AND FIELDNDX NQ 0 THEN BEGIN CHRPTR1=FIELDBGN; CHRPTR2=FIELDEND; END END # OF SETCHRPTR # PROC DODELETE; IOBEGIN(DODELETE) # ** DODELETE - ACTUAL LINE/STRING REMOVAL. * * DODELETE DELETES AN ENTIRE LINE WHEN APPROPRIATE, AND * REPLACES A LINE WITH A STRING DELETED OTHERWISE. * * DODELETE IS OBLIGATED TO EXECUTE INSTANTLY UNTIL ANY NEED * FOR MERGEPROT IS DONE OR GONE. * * ENTRY LIN - INTERNAL LINE IMAGE. * CURRENT, CURFILE, CURSPLIT - WHERE WE ARE. * FORCEFIELD - WHETHER EXPLICIT SYNTAX. * CHARRANGE - CHARACTER/LINE BOUNDARY MODE. * FIRSTRANGE, LASTRANGE - WHETHER AT BOUNDS. * FIELDBGN, FIELDEND - POSSIBLY SET BY SETFIRST * OR SETLAST. * FIELDNDX - WHICH TAB FIELD. * * EXIT LIN - UPDATED IF STRING EXTRACTION. * FILE UPDATED. * CURRENT - POSSIBLY DECREMENTED IF LINE DELETE. * FIELDBGN, FIELDEND - POSSIBLY SET BY SETFIELD. * * MACROS GETCHAR, SETCHAR. * * CALLS SETFIELD, LENGTH, TRIMPAD, MERGEPROT, REPX, DELX. # ITEM TMP1, TMP2; IF FORCEFIELD OR (CHARRANGE AND (FIRSTRANGE OR LASTRANGE)) THEN BEGIN # REPLACE LINE, STRING DELETED # SETFIELD; IF FIELDEND GQ LENGTH(LIN) THEN SETCHAR(LINE,FIELDBGN,CENDLINE); # START INSTANTANEOUS CALCULATION # FOR TMP1=FIELDEND+1 STEP 1 UNTIL LENGTH(LIN) DO BEGIN GETCHAR(LINE,TMP1,TMP2); SETCHAR(LINE,FIELDBGN+TMP1-(FIELDEND+1),TMP2); END # END INSTANTANEOUS CALCULATION # IF NOT (CHARRANGE AND FIRSTRANGE) THEN TRIMPAD; MERGEPROT; REPX; END ELSE DELX; # DELETE WHOLE LINE # # NOTE MERGEPROT NOT NEEDED FOR LINE DELETION # IOEND # OF DODELETE # # EXEC MAIN CODE STARTS HERE # CONTROL IFEQ MULTI,1; # CHECK FOR SMFEX CAUSING US GRIEF # CHKVICTIM; CONTROL FI; IF USRBRK NQ 0 OR ESCAPE THEN BEGIN IF CANINTER THEN BEGIN LINCTR=LARGENUM; IORET END DONTPRINT=TRUE; END CONTROL IFEQ MULTI,1; CLEARQUE; CONTROL FI; LINCTR=LINCTR+1; # ASSUME INCR AGAINST LIMIT # GOTO EXECSW[EXECNDX]; PAGE # EXEC COMMAND HANDLERS # XXAPPEND: # A COMMAND # SAVEPROT; # MUST EXECUTE INSTANTLY UNTIL MERGEPROT # APPEND; MERGEPROT; XSHOW; REPX; GOTO EXECDONE; CONTROL IFEQ SINGLE,1; XXCOPY: SETCHRPTR; LCOUNT=LCOUNT+1; # ACCURATE WORK ACCOUNTING # XFRCMOUT; GOTO EXECDONE; XXCENTER: SAVEPROT; DOCENTER; TRIMPAD; MERGEPROT; XSHOW; REPX; GOTO EXECDONE; CONTROL FI; XXDELETE: SAVEPROT; # MUST EXECUTE INSTANTLY UNTIL MERGEPROT # SETCHRPTR; LCOUNT=LCOUNT+1; DODELETE; # THIS ACCOMODATES MERGEPROT # GOTO EXECDONE; XXLOCATE: SETFIELD; FOUND=FINDER(NEWCURSOR,STRINGLEN); IF FOUND THEN BEGIN YSHOW; GLOBALLOCATE; CHECKWIDE; NOPOP; # TO COME BACK HERE # PUSH; END ELSE LINCTR=LINCTR-1; GOTO EXECDONE; XXMODIFY: SAVEPROT; # MUST EXECUTE INSTANTLY UNTIL MERGEPROT # DOMOD; TRIMPAD; MERGEPROT; XSHOW; REPX; GLOBALCHANGE; GOTO EXECDONE; XXTYPE: SAVEPROT; # MUST EXECUTE INSTANTLY UNTIL MERGEPROT # MERGEPROT; # SO FIELD IS PRINTABLE # XSHOW; GOTO EXECDONE; XXREPLACE: SAVEPROT; # MUST EXECUTE INSTANTLY UNTIL MERGEPROT # SETFIELD; SUBST; IF FOUND THEN BEGIN MERGEPROT; YSHOW; REPX; GLOBALCHANGE; CHECKWIDE; NOPOP; # SET UP HERE AS ... # PUSH; # ... PLACE TO COME BACK TO # END ELSE LINCTR=LINCTR-1; GOTO EXECDONE; CONTROL IFEQ SINGLE,1; XXMOVE: SAVEPROT; # MUST EXECUTE INSTANTLY UNTIL MERGEPROT # SETCHRPTR; LCOUNT=LCOUNT+1; # ACCURATE WORK ACCOUNTING # XFRCMOUT; DODELETE; # THIS ACCOMODATES MERGEPROT # GOTO EXECDONE; CONTROL FI; CONTROL IFEQ MULTI,1; XXCENTER: XXCOPY: XXMOVE: # DROP INTO EXECDONE # CONTROL FI; EXECDONE: IOEND # OF EXEC # PAGE # UTILITIES FOR EXEC-LIKE STUFF # PROC GETESCAPE; IOBEGIN(GETESCAPE) # ** GETESCAPE - DETERMINE IF INPUT DATA AT/NEAR END. * * GETESCAPE RECOGNIZES IMMEDIATE END OF INPUT DATA, WHICH * IS A NULL INPUT, AND UPCOMING END OF INPUT DATA, WHICH IS * A TRAILING SOFT-TAB CHARACTER ON A NON-NULL INPUT. * * ENTRY TTYLIN - INTERNAL LINE IMAGE OF TERMINAL INPUT. * TXTINCMD - WHETHER TTYLIN EXTRACTED FROM COMMAND. * * EXIT ESCAPE - TRUE FOR IMMEDIATE END OF INPUT. * NXTESCAPE - TRUE FOR UPCOMING ESCAPE. * TTLIN - TRAILING TAB CONVERTED TO BLANK. * * MACROS GETCHAR, SETCHAR. * * CALLS LENGTH, TRIM. # ITEM TMP1, TMP2; CONTROL IFEQ SINGLE,1; # IF NOT MULTI USER FSE # IF NOT INTERACT AND NOT TXTINCMD THEN BEGIN # IF BATCH MODE INSERTION # TRIM(TTYLIN,0); # TRIM TRAILING BLANKS # END CONTROL FI; # END OF NOT MULTI USER FSE # TMP2=LENGTH(TTYLIN); IF TMP2 EQ 0 THEN ESCAPE=TRUE; ELSE BEGIN GETCHAR(TTYLINE,TMP2-1,TMP1); IF TMP1 EQ TABCHAR THEN BEGIN SETCHAR(TTYLINE,TMP2-1,CBLANK); TRIM(TTYLIN,1); IF LENGTH(TTYLIN) EQ 0 THEN ESCAPE=TRUE; ELSE NXTESCAPE=TRUE; END END IF TXTINCMD THEN NXTESCAPE=TRUE; IOEND # OF GETESCAPE # PROC DOTAB(OFFSETI,OFFSETO,OFFSETTAB); BEGIN # ** DOTAB - EXPAND SOFT-TABS. * * DOTAB EXPANDS TABS WITHIN TTYLIN, USING TMPLIN AS A SCRATCH * BUFFER. FOR THE BENEFIT OF NUMBERS THE CALLER HAS GIVEN US * AN OFFSET TO WORK AGAINST. * * ENTRY TTYLIN - INTERNAL LINE IMAGE OF TEXT TO EXPAND. * OFFSETI - OFFSET TO START LOOKING IN TTYLIN. * OFFSETO - OFFSET TO START EXPANDING IN TTYLIN. * OFFSETTAB - OFFSET FOR TABS. * TABCHAR - SOFT-TAB CHARACTER VALUE. * TABVECTOR - SETUP. * * EXIT TTYLIN - UPDATED. * * MACROS GETCHAR, SETCHAR. * * CALLS LENGTH, COPYLIN, TABFN, TRIM. * * USES TMPLIN. # ITEM OFFSETI,OFFSETO,OFFSETTAB; ITEM TMP1, TMP2, TMP3, TMP4; COPYLIN(TTYLIN,TMPLIN); FOR TMP1=OFFSETI STEP 1 UNTIL OFFSETO-1 DO SETCHAR(TMPLINE,TMP1,CBLANK); TMP2=OFFSETO; FOR TMP1=OFFSETI STEP 1 WHILE TMP1 LS LENGTH(TTYLIN) AND TMP2 LS BUFCHAR DO BEGIN GETCHAR(TTYLINE,TMP1,TMP3); IF TMP3 NQ TABCHAR OR TABVCTWRD[1] EQ 0 THEN BEGIN SETCHAR(TMPLINE,TMP2,TMP3); TMP2=TMP2+1; END ELSE # IT IS TAB # BEGIN TMP3=0; FOR TMP4=1 STEP 1 UNTIL USERTABS DO BEGIN IF TMP3 EQ 0 AND TABFN(TMP4) GR (TMP2-OFFSETTAB) THEN TMP3=TABFN(TMP4)-(TMP2-OFFSETTAB); END IF TMP3 EQ 0 THEN TMP3=1; # TMP3=NUMBER OF BLANKS TO GENERATE # FOR TMP4=1 STEP 1 WHILE TMP4 LQ TMP3 AND TMP2 LS BUFCHAR DO BEGIN SETCHAR(TMPLINE,TMP2,CBLANK); TMP2=TMP2+1; END END END # OF LOOP # SETCHAR(TMPLINE,MIN(TMP2,BUFCHAR),CENDLINE); COPYLIN(TMPLIN,TTYLIN); TRIM(TTYLIN,MAX(OFFSETO,1)); END # OF DOTAB # PAGE # EXEC-LIKE STUFF. EXECINS # PROC EXECINS; IOBEGIN(EXECINS) # ** EXECINS - PROCESS ONE ONE LINE OF LINE-MODE INPUT. * * THE INSERT COMMAND IS NOT IMPLEMENTED THRU DORANGE AND EXEC * AS IT WORKS ON A LINE POSITION, NOT A RANGE OF LINES. THE * PROCESS COMMAND HANDLER FOR INSERT WILL REPEATEDLY CALL * EXECINS. EXECINS WORKS IN THE AREA OF ESCAPE SEQUENCING * PLUS DRIVING OF PARSING OUT TEXT ON THE COMMAND LINE PLUS * PROMPTING AND GENERATION OF LINE NUMBER TEXT. EXECINS IS * ONLY RELEVANT TO LINE-MODE AND SHOULD NOT BE CALLED WHEN * IN SCREEN-MODE. * * ENTRY NXTESCAPE - WHETHER UPCOMING END OF INPUT. * TXTINCMD - WHETHER TEXT ALREADY IN TTYLIN FROM CMD. * CURRENT, CURFILE - WHERE WE ARE IN FILE. * NUMBERED[CURFILE] - CONTROL PROMPTING AND SEQUENCING. * LINENO - SEQUENCE NUMBER FOR NEW LINE. * NUMWIDBLK - STANDARD SEQUENCING OFFSET. * BLANKS - WHETHER TO ADD BLANK AFTER SEQUENCE NUMBER. * TOPF(CURFILE) - RELOCATION FACTOR AND BOUNDS. * ASCII[CURFILE] - CONTROLS LOWERCASE SUPPRESSION. * * EXIT LIN - INPUT LINE READY TO GO INTO FILE. * NXTESCAPE, ESCAPE - UPDATED. * * MACROS SETCHAR. * * CALLS PUSHTEMP, POPTEMP, TTLPAD, TTSTR, TTST, TTLIN, TTBRK, * PROMPT, CONVIN, TRIM, SQUELCH, GETESCAPE, DOTAB, * COPYLIN, SETLNUM, TRIMPAD, CHECKWIDE, CHKVICTIM(MULTI) * * USES TTYLIN, TMPLIN, TEMP(RESTORED), DUMB. # PUSHTEMP; IF NXTESCAPE THEN BEGIN ESCAPE=TRUE; GOTO EXINSDONE; END IF NOT TXTINCMD THEN BEGIN CONTROL IFEQ SINGLE,1; IF NOT INTERACT THEN GOTO EXECINS2; CONTROL FI; IF NUMBERED[CURFILE] NQ 0 THEN BEGIN TTLPAD(LINENO,NUMWIDTH,"0"); TEMP=NUMWIDBLK; IF B<59,1>TEMP NQ 0 THEN TTSTR(BLANKWRD); TEMP=BLANKS; TTST(" ",TEMP); TTLIN(CKWRD); END ELSE IF FLOAT THEN BEGIN TEMP=CURRENT-TOPF(CURFILE)+1; IF TEMP GR 9999 THEN TTLPAD(TEMP,8," "); ELSE TTLPAD(TEMP,4," "); TTLIN(BCCKWRD); END ELSE TTBRK; EXECINS2: PROMPT(NULLWRD); CONVIN(TTYLIN,2); TRIM(TTYLIN,1); IF ASCII[CURFILE] LQ 1 THEN SQUELCH(TTYLIN); END GETESCAPE; # DETERMINES UPCOMING ESCAPE # IF ESCAPE THEN GOTO EXINSDONE; DOTAB(0,NUMWIDBLK,NUMWIDBLK); COPYLIN(TTYLIN,LIN); IF NUMBERED[CURFILE] NQ 0 THEN BEGIN FOR DUMB=1 STEP 1 UNTIL NUMWIDTH DO SETCHAR(LINE,DUMB-1,CDIGIT0); SETLNUM; END TRIMPAD; CHECKWIDE; EXINSDONE: POPTEMP; CONTROL IFEQ MULTI,1; CHKVICTIM; # SEE IF SMFEX IN TROUBLE # CONTROL FI; IOEND # OF EXECINS # PAGE # DORANGE ROUTINE # PROC DORANGE; IOBEGIN(DORANGE) # ** DORANGE - PROCESS RANGE OF LINES FOR COMMAND. * * DORANGE IS USED TO MOVE THRU THE FILE ONE LINE AT A TIME * CALLING EXEC EACH TIME. WE ARE THUS USED ONLY AND ALWAYS * BY THOSE PROCESS COMMAND HANDLERS WHO DEAL WITH RANGES OF * LINES. REMEMBER EXEC SUPPLIES THE PER-LINE GOODIES. WE * ASSUME THAT OUR PROCESS ROUTINE HAS ALREADY SET UP EXECNDX, * WHICH WILL TELL EXEC WHICH COMMAND IS ALIVE. WE ASSUME * THAT THE PROCESS ROUTINE EITHER KNOWS THE RANGE IMPLICITLY * OR HAS CALLED SCANNER, THUS LINPTR1 AND LINPTR2 GIVE THE * RANGE. EXEC WILL DEAL ALSO WITH LINCTR AND LCOUNT. * * ENTRY BACKWARD - DIRECTION OF RANGE. * LINPTR1 - TOP ADDRESS OF RANGE. * LINPTR2 - BOTTOM ADDRESS OF RANGE. * CURFILE, CURSPLIT - CURRENT FILE. * ELLIPSIS, WORDSEARCH, UPPERSEARCH - SEARCH MODES. * FIELDNDX - WHETHER/WHICH TAB FIELD LIMIT. * LIMIT - MAXIMUM ITERATIONS. * TOPF(CURFILE), BOTF(CURFILE) - BOUNDS. * FOUND - WHETHER SYNTAX GAVE VALID BOUNDS. * PROCESSNDX - WHICH COMMAND. * EXECNDX - WHICH EXEC PROCESSOR. * NUMBERED[CURFILE] - SEQUENCING MODE. * * EXIT LINPTR1, LINPTR2 - DESTROYED. * LASTPROCESS - INDICATES TYPE OF COMMAND EXECUTED. * NEWCURSOR - ZEROED. * * CALLS EXECONE(INTERNAL), GETLNUM, SETFIRST, SETLAST, * EXEC, VOLUNTEER(MULTI), HALT, POSZ, MIN, FWDZ, * BAKZ, MAX. * * USES LINPTR1, LINENO, WIDTHFOUND, FIELDFLG, FIELDBGN, * FIELDEND, FINDCONTROL, LINPTR2, FIRSTRANGE, LASTRANGE, * DORNGCTR, LCOUNT, LINCTR, YCURSOR, DELETEDONE, * REGLINE[RNGTOPREG], REGLINE[RNGBOTREG], DELETCTL. # PROC EXECONE(FIRST,LAST); IOBEGIN(EXECONE) # ** EXECONE - EXECUTE COMMAND PROCESSOR FOR ONE LINE. * * EXECONE IS AN INTERNAL ALGORITHM OF DORANGE WHICH * EXISTS TO CONSOLIDATE CODE. INTERFACE TO EXEC ROUTINE. * * ENTRY FIRST - LINE ADDRESS FOR FIRST LINE OF RANGE. * LAST - LINE ADDRESS FOR LAST LINE OF RANGE. * (FIRST, LAST ARE IN CHRONOLOGICAL ORDER) * CURRENT, CURFILE, CURSPLIT - LINE TO PROCESS. * LIN - TEXT OF LINE TO PROCESS. * NUMBERED[CURFILE] - MODE. * * EXIT CONDITIONS AS LEFT BY EXEC ROUTINE. * * USES FIELDFLG, FIELDBGN, FIELDEND, NUMWIDBLK, DELETEDONE. * * CALLS EXEC, SETFIRST, SETLAST, GETLNUM. * * NOTE THIS ROUTINE IS REENTRANT AND HAS PARAMETERS. IT * MUST EXECUTE NON-REENTRANTLY UNTIL PARAMETER * ARE COMPLETE AND CANNOT ALTER THE PARAMETERS. # ITEM FIRST, LAST; DELETEDONE=FALSE; IF NUMBERED[CURFILE] NQ 0 THEN BEGIN GETLNUM; NUMWIDBLK=WIDTHFOUND+BLANKS; END FIELDFLG=FALSE; FIELDBGN=NUMWIDBLK; IF BACKWARD THEN FIELDBGN=BUFCM1; FIELDEND=BUFCM1; IF BACKWARD THEN FIELDEND=NUMWIDBLK; FINDCONTROL=FINDCONTROL LAN 2; FIRSTRANGE=FALSE; LASTRANGE=FALSE; IF CURRENT EQ FIRST THEN SETFIRST; IF CURRENT EQ LAST THEN SETLAST; # END PARAMETERS # EXEC; LINPTR1=CURRENT; CONTROL IFEQ MULTI,1; IF MOD(DORNGCTR,VOLLINES) EQ 0 THEN VOLUNTEER; CONTROL FI; IOEND # OF EXECONE # # MAIN CODE OF DORANGE STARTS HERE # LCOUNT=0; # DEFAULT WORK ACCOMPLISHED # LINCTR=0; LASTPROCESS=PROCESSNDX; YCURSOR=-1; # TO RE-ADDRESS CURSOR # NEWCURSOR=0; FINDCONTROL=0; # SET TEXT SEARCH OPTIONS # IF ELLIPSIS OR WORDSEARCH OR UPPERSEARCH OR BACKWARD OR FIELDNDX NQ 0 THEN FINDCONTROL=2; IF BACKWARD THEN BEGIN LINPTR1 = = LINPTR2; CHRPTR1 = = CHRPTR2; END IF TOPF(CURFILE) EQ BOTF(CURFILE)-1 THEN BEGIN HALT("EMPTY FILE$"); END ELSE IF NOT FOUND THEN BEGIN HALT("OUT OF BOUNDS$"); END IF NOT FOUND THEN IORET # IF HALT CALLED # POSZ(LINPTR1); # POSITION START OF RANGE # DELETEDONE=TRUE; # TO TRICK FIRST PASS # IF LINPTR1 LQ LINPTR2 THEN BEGIN IF EXECNDX NQ EXECST"LOCATE" AND EXECNDX NQ EXECST"REPLACE" THEN LINPTR2=MIN(LINPTR2,LINPTR1+LIMIT-1); DELETCTL=1; REGLINE[RNGTOPREG]=LINPTR1-1; REGLINE[RNGBOTREG]=LINPTR2+1; FOR DORNGCTR=1 STEP 1 WHILE LINPTR1 GR REGLINE[RNGTOPREG] AND LINPTR1 LS REGLINE[RNGBOTREG] AND LINCTR LS LIMIT DO BEGIN IF NOT DELETEDONE THEN BEGIN LINPTR1=LINPTR1+1; IF LINPTR1 LS REGLINE[RNGBOTREG] THEN FWDZ; ELSE TEST; END ELSE IF DELETCTL EQ 0 THEN BEGIN LINCTR=LARGENUM; TEST; END EXECONE(REGLINE[RNGTOPREG]+1,REGLINE[RNGBOTREG]-1); END IF DELETEDONE AND DELETCTL EQ 1 THEN BAKZ; END ELSE BEGIN IF EXECNDX NQ EXECST"LOCATE" AND EXECNDX NQ EXECST"REPLACE" THEN LINPTR1=MAX(LINPTR1,LINPTR2-LIMIT+1); DELETCTL=0; REGLINE[RNGTOPREG]=LINPTR2-1; REGLINE[RNGBOTREG]=LINPTR1+1; FOR DORNGCTR=1 STEP 1 WHILE LINPTR1 GR REGLINE[RNGTOPREG] AND LINPTR1 LS REGLINE[RNGBOTREG] AND LINCTR LS LIMIT DO BEGIN IF NOT DELETEDONE THEN BEGIN LINPTR1=LINPTR1-1; IF LINPTR1 GR REGLINE[RNGTOPREG] THEN BAKZ; ELSE TEST; END EXECONE(REGLINE[RNGBOTREG]-1,REGLINE[RNGTOPREG]+1); END END IOEND # OF DORANGE # PAGE # PROGRAM INTERPRETATION CONTROL # CONTROL IFEQ SINGLE,1; FUNC COMPARLIN(TEXTLIN,KEYWORD,ABBREV) B; BEGIN # ** COMPARLIN - COMPARE INTERNAL LINE TO DISPLAY KEYWORD. * * COMPARLIN COMPARES A LINE IMAGE (INTERNAL CHARACTER SET) * TO A KEYWORD (DISPLAY CODE). THE KEYWORD IS VARIABLE IN * LENGTH UP TO TEN CHARACTERS. THE LINE MUST EXACTLY * EQUAL THE KEYWORD IN LENGTH AND CONTENT, EXCEPT THAT THE * CASE OF LETTERS DOES NOT MATTER. * * ENTRY TEXTLIN, KEYWORD - WHAT WE COMPARE. * ABBREV - WHETHER ABBREVIATIONS ARE PERMISSIBLE. * * EXIT COMPARLIN - RESULT OF COMPARISON. * * CALLS LENGTH, DSPLCOD. # ARRAY TEXTLIN[0:99]; ITEM TEXTLINE; ITEM KEYWORD; ITEM ABBREV B; ITEM TMP1, TMP2, TMP3, TMP4, TMP5, TMP6, TMP7, TMP8, BOOL B; PROC CHECKWORD(LEN); BEGIN ITEM LEN; # ENTRY - TMP1=KEYWORD POSITION (ALREADY SCANNED) # # TMP2=TEXTLINE POSITION (NEEDS SCAN) # # TMP3=LENGTH OF WORD - NOT USED HERE # # LEN=HOW MANY CHARACTERS TO CHECK # # EXIT - BOOL=RESULT OF COMPARE # # TMP4=POSITION AT WHICH TEXTLINE HAD THE WORD # # TMP5=LENGTH PARAMETER # BOOL=FALSE; TMP4=TMP2; GETCHAR(TEXTLINE,TMP4,TMP5); WHYLE TMP4 LS LENGTH(TEXTLIN) AND TMP5 EQ CBLANK DO BEGIN # FIND START OF WORD # TMP4=TMP4+1; GETCHAR(TEXTLINE,TMP4,TMP5); END IF TMP4 GQ LENGTH(TEXTLIN) THEN RETURN; # NO WORDS AVAIL # TMP5=TMP4+1; GETCHAR(TEXTLINE,TMP5,TMP6); WHYLE TMP6 NQ CBLANK AND TMP6 NQ CENDLINE DO BEGIN # LOOK FOR END OF WORD # TMP5=TMP5+1; GETCHAR(TEXTLINE,TMP5,TMP6); END TMP5=TMP5-TMP4; # LENGTH OF WORD # IF TMP5 GQ LEN THEN # WORD MIGHT MATCH # BEGIN FOR TMP6=0 STEP 1 UNTIL LEN-1 DO BEGIN GETCHAR(TEXTLINE,TMP4+TMP6,TMP7); DSPLCOD(TMP7); TMP8=CKEYWORD; IF TMP7 NQ TMP8 THEN RETURN; END TMP5=LEN; BOOL=TRUE; END END # OF CHECKWORD # # MAIN COMPARLIN CODE STARTS HERE # COMPARLIN=FALSE; IF ABBREV THEN BEGIN TMP1=0; # KEYWORD POSITION # TMP2=0; # TEXTLINE POSITION # BOOL=FALSE; WHYLE TMP1 LQ 9 DO BEGIN IF CKEYWORD EQ " " OR CKEYWORD EQ 0 THEN TMP1=TMP1+1; # KEEP LOOKING FOR WORD # ELSE # WORD FOUND # BEGIN TMP3=TMP1+1; # END OF WORD # WHYLE TMP3 LQ 9 AND CKEYWORD NQ " " AND CKEYWORD NQ 0 DO TMP3=TMP3+1; TMP3=TMP3-TMP1; # LENGTH OF WORD # CHECKWORD(TMP3); # TEST ALL POSSIBLE ABBREV-S # IF (NOT BOOL) AND (TMP3 GR 3) THEN CHECKWORD(3); IF (NOT BOOL) AND (TMP3 GR 1) THEN CHECKWORD(1); IF BOOL THEN # PREPARE TO CHECK NEXT WORD # BEGIN TMP1=TMP1+TMP3; TMP2=TMP4+TMP5; END ELSE TMP1=10; # IMMEDIATE FAILURE # END END IF BOOL THEN BEGIN GETCHAR(TEXTLINE,TMP2,TMP5); WHYLE TMP5 EQ CBLANK DO # LOOK FOR EOL OR SURPLUS TEXT # BEGIN TMP2=TMP2+1; GETCHAR(TEXTLINE,TMP2,TMP5); END IF TMP5 EQ CENDLINE THEN COMPARLIN=TRUE; END END ELSE BEGIN TMP1=9; BOOL=FALSE; FOR TMP2=9 STEP -1 WHILE TMP2 GQ 0 AND NOT BOOL DO BEGIN IF CKEYWORD EQ " " OR CKEYWORD EQ 0 THEN TMP1=TMP2; ELSE BOOL=TRUE; END IF TMP1 EQ LENGTH(TEXTLIN) THEN BEGIN FOR TMP2=0 STEP 1 UNTIL TMP1-1 DO BEGIN GETCHAR(TEXTLINE,TMP2,TMP3); DSPLCOD(TMP3); TMP4=CKEYWORD; IF TMP3 NQ TMP4 THEN RETURN; END COMPARLIN=TRUE; END END END # OF COMPARLIN # PROC GETPROCNXT; BEGIN # ** GETPROCNXT - GET NEXT COMMAND LINE FROM PROCEDURE. * * ENTRY CURP(PROCCTL) - PREVIOUS PROCEDURE ADDRESS. * BOTP(PROCCTL) - BOUNDS ON PROC FILE. * PROCACTIVE - SHOULD BE TRUE. * * EXIT CMDLIN - NEW COMMAND LINE IF NOT END OF PROC. * CURP(PROCCTL) - INCREMENTED. * PROCACTIVE - FORCED FALSE IF END OF PROC. * SCANPOS, TOKENPOS, KEYWDTYPE - RE-INITIALIZED. * * CALLS CLEARPROC, COMPARLIN, PUSH, POP, STARTCMD. * * USES P (RESTORED TO LOC(LIN)). # CURP(PROCCTL)=CURP(PROCCTL)+1; IF CURP(PROCCTL) GQ BOTP(PROCCTL) THEN CLEARPROC; ELSE BEGIN PUSH; P=LOC(CMDLIN); POSZ(CURP(PROCCTL)); P=LOC(LIN); POP; STARTCMD; IF COMPARLIN(CMDLIN,EORCON,FALSE) THEN CLEARPROC; IF COMPARLIN(CMDLIN,EOFCON,FALSE) THEN CLEARPROC; EXPANDAT=0; EXPANDCMDS; END END # OF GETPROCNXT # PROC CLEARPROC; BEGIN # ** CLEARPROC - GET OUT OF PROCEDURE EXECUTION MODE. * * EXIT PROCACTIVE - FALSE. * CMDLIN - NULL. * * CALLS STARTCMD. # PROCACTIVE=FALSE; CMDLINE[0]=NULLIN; STARTCMD; END # OF CLEARPROC # CONTROL FI; PAGE # SINGLE/MULTI CONNECTION # CONTROL IFEQ SINGLE,1; CONTROL IFEQ NEVERMULTI,1; PROC CONNECT; BEGIN END PROC PRECONNECT; BEGIN END PROC POSTCONNECT; BEGIN END CONTROL FI; CONTROL IFEQ NEVERMULTI,0; PROC PRECONNECT; BEGIN # ** PRECONNECT - FIRST STEP IN CONNECTING TO MULTI-USER EDITOR. * * PRECONNECT DETERMINES WHETHER CONNECTION SHOULD BE ATTEMPTED. * IF CONNECTION SHOULD PROCEED, PRECONNECT SIGNALS THIS * WITH THE CONNECTED FLAG AND CHECKPOINTS THE WORKFILE. * THE WORKFILE CARRIES THE SMFINCTL FLAG SO WE CAN TELL * WHETHER SMFEX REACHES A NORMAL END OF SESSION, AS OPPOSED * TO A RECOVERY SITUATION. * * ENTRY SINGLEONLY - WHETHER CONNECTION SHOULD PROCEED. * * EXIT CONNECTED - WHETHER CONNECTION SHOULD PROCEED. * SMFINCTL - SET INTO WORKFILE IF CONNECTED. * CMDLIN - NULLED OUT IF CONNECTED. * WORKFILE CHECKPOINTED IF CONNECTED. * * CALLS CHECKIO, VDTEOO, TTSYNC, VDTCLO. # IF NOT SINGLEONLY THEN BEGIN CONNECTED=TRUE; SMFINCTL=TRUE; # SO WE WILL KNOW IF RCVCRY # IF SCREENMODE THEN VDTEOO; ELSE TTSYNC; VDTCLO(1); CHECKIO; # DE-INTERLOCK FILE # END END # OF PRECONNECT # PROC CONNECT; BEGIN # ** CONNECT - ACTUAL ATTEMPT TO CONNECT TO MULTI. * * CONNECT ACTUALLY ATTEMPTS TO CONNECT TO THE MULTI-USER * EDITING SUBSYSTEM, SMFEX. CONNECT SHOULD BE CALLED ONLY * IF PRECONNECT RETURNED A POSITIVE RESULT. CONNECT FIRST * FLUSHES ANY PENDING TERMINAL OUTPUT. * * ENTRY SCREENMODE - CONTROL MANNER OF OUTPUT FLUSH. * FETFNT - NEGATIVE FIELD LENGTH ADDR OF WORKFILE. * CONNECTED - SHOULD BE TRUE. * * EXIT CONNECTED - FORCED FALSE IF ATTEMPT FAILED. * * CALLS DISSJ, POSZ, RESUMIO, SYSREQ(TLX). # ARRAY XFRVECTOR; BEGIN ITEM XFRWORD; ITEM XFRFNTR U(0,0,12)=[0]; ITEM XFRFNTS U(0,12,12)=[0]; ITEM XFRSSID U(0,24,12)=[SMFSSID]; ITEM XFRFILL U(0,36,12)=[0]; ITEM XFRSTAT U(0,48,11)=[0]; ITEM XFRCOMP U(0,59,1)=[0]; END XFRFNTS=FETFNT; XFRCOMP=0; DISSJ(3); # ENABLE SSJ= # SYSREQ("TLX",1,LOC(XFRWORD),TLXFUNC*64); DISSJ(2); # DISABLE SSJ= # IF XFRSTAT NQ 0 THEN BEGIN RESUMIO; # RE-INTERLOCK FILE # POSZ(SAVECURL); CONNECTED=FALSE; # INDICATE NO CONNECT OCCURRED # SINGLEONLY=TRUE; END END # OF CONNECT # PROC POSTCONNECT; # TITLE POSTCONNECT - VERIFY REVIVAL OF SINGLE-USER EDITOR. # BEGIN # POSTCONNECT # # ** POSTCONNECT - VERIFY REVIVAL OF SINGLE-USER EDITOR. * * POSTCONNECT REVIVES THE SINGLE-USER EDITOR AFTER AN * ATTEMPT TO CONNECT TO THE MULTI-USER VERSION OF THE * FULL SCREEN EDITOR. IF THE CONNECTION ATTEMPT WAS NOT * SUCCESSFUL, THEN POSTCONNECT SERVES ONLY TO INDICATE * THAT NO FUTURE CONNECTIONS SHOULD BE ATTEMPTED. FOR A * NORMAL CONNECTION, POSTCONNECT RESUMES WORKFILE CONTENT * INTO WORK STORAGE AND INITIALIZES THE SYNTAX SCANNER TO * USE THE COMMAND STRING RETURNED BY SMFEX. * * PROC POSTCONNECT * * EXIT CONNECTED - FALSE. * PAINTAGAIN - FORCED TRUE IF NO CONNECTION. * SINGLEONLY - FORCED TRUE IF NO CONNECTION. * SCANPOS - SET ACCORDING TO START OF COMMAND. * ENTIRE DATA SEGMENT AND ARRAY SEGMENT - PER SMFEX. * * CALLS FATAL, PAINTALL, POSZ, RESUMIO, STARTCMD. # RESUMIO; # GET SMF RESULT AND INTERLOCK # IF NOT IORESUMED THEN BEGIN FATAL(" WORKFILE IS NOT IN A RESUMEABLE STATE.$"); END CONNECTED=FALSE; SCANPOS=CMDMARKER; # LOOK BACK TO CMD START # BUILDCIO=0; IF FORCENULL OR SMFINCTL THEN BEGIN FORCENULL=FALSE; SMFINCTL=FALSE; SINGLEONLY=TRUE; CMDLINE[0]=NULLIN; ERRSTRING="SYSTEM INTERRUPT, PROCEED NOW$"; STARTCMD; PAINTALL; PAINTAGAIN=TRUE; # SET PAINT AGAIN FLAG # END POSZ(SAVECURL); END # POSTCONNECT # CONTROL FI; CONTROL FI; PAGE # UTILITIES ONLY USED BY PROCESS # PROC ERRJUMP(STR); BEGIN # ** ERRJUMP - ISSUE ERROR MESSAGE AND JUMP TO FRESH COMMANDS. * * ERRJUMP PROCESSES ERROR MESSAGES FOR SYNTAX ERRORS IN * COMMAND PROCESSORS. ERRJUMP THEN IGNORES THE SUBROUTINE * CALLING CHAIN AND BRANCHES DIRECTLY TO THE MAIN COMMAND * SEQUENCING LOOP. THUS, ERRJUMP CAN ONLY BE CALLED BY * ROUTINES WHICH WERE THEMSELVES CALLED BY THE MAIN COMMAND * SEQUENCING LOOP. NOTE THAT IN THE MULTI-USER VERSION OF * THE EDITOR, THE CODE AT LABEL "PRERROR" WILL BE EXPECTED * TO RESET ALL STRUCTURES HAVING TO DO WITH REENTRANT * SUBROUTINE CALLING CHAINS. * * ENTRY STR - MESSAGE TO BE PRINTED. * SCREENMODE - MODE. * TOKENPOS - WHERE ERROR WAS DETECTED. * COMMANDROW - SETUP. * PROCACTIVE - MODE. * CURP(PROCCTL) - WHERE WE ARE IN PROC IF ANY. * CURPROCNAM - NAME OF CURRENT PROC. * USRSPLTSZ - SETUP. * CMDLIN - BAD COMMAND TEXT. * * EXIT VIA LABEL "PRERROR". * ERRSTRING - COPY OF THE MESSAGE. * ERRCURSOR, YCURSOR - POINT TO SYNTAX ERROR. * SCREEN FORMATTED TO DISPLAY SOURCE OF ERROR. * CMDLIN - NULLED OUT UNDER CERTAIN CONDITIONS. * CURFILE, CURSPLIT - MAY BE OPENED INTO PROC. * * CALLS OPENFILE, POSZ, SETUPSCREEN, TTBRK, TTLIN, TTSTR, * CONVOUT, VDTWTC. * * USES TMPLIN, FILNUM, GETPARM, CHARPARM, CURF(2), * CURFILE, CURSPLIT, CURRENT, LIN, LINCTR. # ITEM STR C(40); XREF LABEL PRERROR; ERRSTRING=STR; ERRCURSOR=TOKENPOS; IF SCREENMODE THEN BEGIN IF TOKENPOS GQ 0 THEN YCURSOR=COMMANDROW; CONTROL IFEQ SINGLE,1; IF PROCACTIVE THEN BEGIN READNAM=CURPROCNAM; FILNUM=2; GETPARM=0; CHARPARM=0; OPENFILE; CURF(2)=CURP(PROCCTL); POSZ(CURF(2)); CURFILE=2; CURSPLIT=2; SETUPSCREEN(1,2,USRSPLTSZ); YCURSOR=LTOY(CURRENT,2); CMDLINE[0]=NULLIN; END CONTROL FI; END ELSE # LINE MODE # BEGIN CONTROL IFEQ SINGLE,1; IF PROCACTIVE THEN BEGIN IF INTERACT THEN BEGIN # IF INTERACTIVE PROCEDURE ERROR # TTBRK; TTLIN("ERROR IN THIS PROCEDURE LINE: $"); TTSTR(" $"); TTSYNC; CONVOUT(CMDLIN,2); VDTWTC(TMPLIN); END END CONTROL FI; CMDLINE[0]=NULLIN; IF C<0,2>ERRSTRING NQ " $" THEN BEGIN TTBRK; FOR LINCTR=1 STEP 1 UNTIL TOKENPOS+3 DO TTSTR(BLANKWRD); TTSTR("!$"); TTBRK; CONTROL IFEQ SINGLE,1; IF NOT INTERACT AND PROCACTIVE THEN BEGIN # IF BATCH PROCEDURE ERROR # TTLIN(" ERROR IN PROCEDURE LINE ABOVE WAS: $"); END CONTROL FI; END END GOTO PRERROR; END # OF ERRJUMP # PROC VFYLOCK; BEGIN # ** VFYLOCK - VERIFY PERMISSION TO CHANGE CURRENT FILE. * * ENTRY CURFILE - CURRENT FILE. * LOCKED[CURFILE] - TRUE IF READ-ONLY FILE. * * EXIT VIA ERRJUMP IF NOT VALIDATED. # IF LOCKED[CURFILE] NQ 0 THEN BEGIN ERRJUMP("CANNOT CHANGE READ-ONLY FILE$"); END END # OF VFYLOCK # PAGE # FILE ASSIGNMENT HISTORY # PROC PUSHBACK; BEGIN # ** PUSHBACK - PUSH CURRENT FILES AND SPLITS ONTO BACKSTACK. * * ENTRY FILENAM[1-2] CONTAIN CURRENT OPEN FILES. * NUMROWS[2] HAS SPLITSIZE. * * EXIT BACKIN (AND MAYBE BACKOUT) INCREMENTED. * BACKSTACK[BACKIN] CONTAINS FILES,SPLITS. * * CALLS INCR(INTERNAL). # PROC INCR(I); BEGIN # INCR - INCREMENT BACK POINTER # ITEM I; I=I+1; IF I GR BACKMAX THEN I=0; END # OF INCR # INCR(BACKIN); BACKFIL1[BACKIN]=FDLF(1); BACKFIL2[BACKIN]=FDLF(2); BACKSPL2[BACKIN]=SPLITFILE[2]; BACKSPLN[BACKIN]=NUMROWS[2]; IF BACKIN EQ BACKOUT THEN INCR(BACKOUT); END # OF PUSHBACK # FUNC SAMEBACK B; BEGIN # ** SAMEBACK - TEST WHETHER FILES/SPLITS CHANGED. * * SAMEBACK ALLOWS THE CALLER TO KNOW WHETHER THE FILE * BRACKETS HAVE CHANGED IN FILE CHOICE OR IN SPLIT * DISPLAY DIMENSIONS, SINCE THE LAST CALL TO PUSHBACK. * * ENTRY FILENAM[1-2], SPLITFILE[2], NUMROWS[2] - SETUP. * BACKIN - AS LEFT BY PUSHBACK. * BACKSTACK[BACKIN] - AS LEFT BY PUSHBACK. * * EXIT SAMEBACK - RESULT OF COMPARISON. # SAMEBACK=TRUE; IF BACKFIL1[BACKIN] NQ FDLF(1) OR BACKFIL2[BACKIN] NQ FDLF(2) OR BACKSPL2[BACKIN] NQ SPLITFILE[2] OR BACKSPLN[BACKIN] NQ NUMROWS[2] THEN SAMEBACK=FALSE; END # OF SAMEBACK # PROC DECRBACK; BEGIN # ** DECRBACK - DECREMENT FILE SELECTION QUEUE. * * DECRBACK BACKS UP THE CIRCULAR QUEUE OF FILE SELECTIONS. * * ENTRY BACKIN - POINTER TO BE BACKED AROUND CIRCLE. * * EXIT BACKIN - DECREMENTED OR RECIRCULATED. # IF BACKIN NQ BACKOUT THEN BEGIN BACKIN=BACKIN-1; IF BACKIN LS 0 THEN BACKIN=BACKMAX; END END # OF DECRBACK # PROC RESTSAVPOS; IOBEGIN(RESTSAVPOS) # ** RESTSAVPOS - RESTORE SAVED POSITION. * * RESTSAVPOS ACCOMPLISHES THE FILE SWITCHING OF THE * BACK DIRECTIVE EXCHANGE OPERATION. * IT IS CALLED TO SET UP THE FILE POSITION IN EFFECT * WHEN THE LAST BACK OR DATA DIRECTIVE WAS EXECUTED. * * ENTRY FILNUM - INDICATES WHICH SPLIT IS BEING ACTIVATED. * BKSPLIT2[BACKIND] - INDICATES SINGLE FILE IS ACTIVE. * CURSPLIT - RECENT HISTORY OF FILE SELECTION. * REGSTCLIN(BCKCURLIN) - REGISTER STACK LINE POINTER. * * EXIT DESIGNATED FILE OPENED AND POSSIBLY POINTING * TO THE EXACT WORKING LINE. * * CALLS OPENFILE, POSZ, SCANFDL. * * USES CHARPARM, CURF(FILNUM), CURRENT, GETPARM, * LINCTR, READNAM. # CHARPARM = 0; GETPARM = 0; IF (FILNUM EQ 1) THEN POSZ(BKFDLFF1[BACKIND]); ELSE POSZ(BKFDLFF2[BACKIND]); SCANFDL(READNAM); # RETRIEVE FILE NAME FROM FDL # OPENFILE; # ACCESS THE FILE # IOEND # OF RESTSAVPOS # PROC EXCHSAVPOS; IOBEGIN(EXCHSAVPOS) # ** EXCHSAVPOS - EXCHANGE CURRENT POSITION WITH SAVED POSITION. * EXCHSAVPOS COMPRISES THE FUNCTIONAL OPERATION OF THE * BACK DIRECTIVE EXCHANGE OPERATION. * IT IS CALLED BY THE BACK DIRECTIVE TO ACCOMPLISH THE * SWITCH BETWEEN THE CURRENT POSITION ON THE SCREEN * WITH THE POSITION IN EFFECT AFTER THE MOST RECENT BACK * OR EDIT DIRECTIVE. * EXCHSAVPOS FIRST SAVES THE CURRENT FILE(S), SPLIT LOGIC, * ACTIVE LINE, AND CURSOR POSITION IN TEMPORARY STORAGE. * THE PREVIOUSLY STORED POSITION IS THEN RECALLED, AND THE * TEMPORARY VALUES ARE THEN SAVED IN PERMANENT STORAGE. * * EXIT BACKSTORE ARRAY CONTAINS NEW POSITION. * FILE(S) AND SCREEN UPDATED TO REFLECT PREVIOUSLY * STORED POSITION. * * CALLS POP, PUSH, RESTSAVPOS. * * USES BACKSTORE, CURSPLIT, FILNUM, LINPTR1, LINPTR2, * NEWCURSOR, REGSTCLIN, TEMPCURLIN, YCURSOR. * # LINPTR1 = 0; LINPTR2 = 0; # PLACE CURRENT SCREEN POSITION INTO TEMPORARY STORAGE. # PUSH; BKFDLFF1[TEMPIND] = FDLF(1); BKFDLFF2[TEMPIND] = FDLF(2); BKSPLIT2[TEMPIND] = SPLITFILE[2]; BKNROWS1[TEMPIND] = NUMROWS[1]; BKNROWS2[TEMPIND] = NUMROWS[2]; BKWHCHSP[TEMPIND] = CURSPLIT; IF ( CURSPLIT EQ 1 ) THEN TEMPCURLIN = CURF(1); ELSE TEMPCURLIN = CURF(2); BKCURSOR[TEMPIND] = CURCURSOR; POP; # RETRIEVE STORED POSITION. # CURSPLIT = BKWHCHSP[BACKIND]; IF (BKSPLIT2[BACKIND] EQ 0) THEN # SINGLE FILE, NO SPLIT # BEGIN FILNUM = 1; RESTSAVPOS; # RESTORE SINGLE FILE # END ELSE BEGIN # SPLIT FILES # IF (CURSPLIT NQ 1) THEN BEGIN # TOP FIRST, THEN BOTTOM # FILNUM = 1; RESTSAVPOS; FILNUM = 2; RESTSAVPOS; # RESTORE SPLIT FILE # END ELSE BEGIN # BOTTOM FIRST, THEN TOP # FILNUM = 2; RESTSAVPOS; # RESTORE SPLIT FILE # FILNUM = 1; RESTSAVPOS; # RESTORE TOP FILE # END END LINPTR1 = BKSPLIT2[BACKIND]; LINPTR2 = BKNROWS2[BACKIND]; YCURSOR = -1; NEWCURSOR = BKCURSOR[BACKIND]; # MOVE CURRENT POSITION FROM TEMPORARY TO PERMANENT STORAGE. # BKFDLFF1[BACKIND] = BKFDLFF1[TEMPIND]; BKFDLFF2[BACKIND] = BKFDLFF2[TEMPIND]; BKSPLIT2[BACKIND] = BKSPLIT2[TEMPIND]; BKNROWS1[BACKIND] = BKNROWS1[TEMPIND]; BKNROWS2[BACKIND] = BKNROWS2[TEMPIND]; BKWHCHSP[BACKIND] = BKWHCHSP[TEMPIND]; REGSTCLIN(BCKCURLIN) = TEMPCURLIN; BKCURSOR[BACKIND] = BKCURSOR[TEMPIND]; IOEND # OF EXCHSAVPOS # PROC STORCURPOS; IOBEGIN(STORCURPOS) # ** STORCURPOS - STORE CURRENT POSITION. * * STORCURPOS PLACES THE CURRENT SCREEN AND FILE POSITIONS * INTO PERMANENT STORAGE, FOR LATER RECALL BY THE BACK * DIRECTIVE. A FLAG IS SET TO INDICATE THAT THE STORAGE * HAS TAKEN PLACE. * * EXIT CURRENT FILE(S) AND SCREEN POSITION STORED IN * BACKSTORE. * * CALLS POP, PUSH. * * USES BACKSTORE[BACKIND], REGSTCLIN. * # # STORE CURRENT POSITION FOR LATER RECALL BY BACK DIRECTIVE.# PUSH; BKFDLFF1[BACKIND] = FDLF(1); BKFDLFF2[BACKIND] = FDLF(2); BKSPLIT2[BACKIND] = SPLITFILE[2]; BKNROWS1[BACKIND] = NUMROWS[1]; BKNROWS2[BACKIND] = NUMROWS[2]; BKWHCHSP[BACKIND] = CURSPLIT; IF ( CURSPLIT EQ 1 ) THEN REGSTCLIN(BCKCURLIN) = CURF(1); ELSE REGSTCLIN(BCKCURLIN) = CURF(2); BKCURSOR[BACKIND] = CURCURSOR; POP; IOEND # OF STORCURPOS # PROC DOBACK; IOBEGIN(DOBACK) # ** DOBACK - REVERT TO EARLIER FILE SELECTION. * * DOBACK CONSTITUTES THE ESSENTIAL FUNCTION OF THE BACK * COMMAND, WHICH IS TO CHANGE THE EDITORS SELECTION OF * ONE OR TWO OPEN FILE BRACKETS TO THE SELECTION IN * EFFECT ONE CHRONOLOGICAL UNIT EARLIER. * * ENTRY BACKIN, BACKOUT - CIRCULAR POINTERS FOR QUEUE. * BACKSTACK - RECENT HISTORY OF FILE SELECTION. * * EXIT ONE OR BOTH FILE BRACKETS OPENED. * BACKIN - CIRCULARLY DECREMENTED. * LINPTR1, LINPTR2 - INDICATE SCREEN FORMATTING. * * CALLS PADNAME, OPENFILE, DECRBACK, SCANFDL. * * USES READNAM, FILNUM, CHARPARM, GETPARM. # LINPTR1=0; LINPTR2=0; DECRBACK; IF BACKIN NQ BACKOUT THEN BEGIN POSZ(BACKFIL1[BACKIN]); SCANFDL(READNAM); FILNUM=1; CHARPARM=0; GETPARM=0; OPENFILE; IF BACKSPL2[BACKIN] NQ 0 THEN BEGIN POSZ(BACKFIL2[BACKIN]); SCANFDL(READNAM); FILNUM=2; OPENFILE; END LINPTR1=BACKSPL2[BACKIN]; LINPTR2=BACKSPLN[BACKIN]; DECRBACK; END IOEND # OF DOBACK # PROC MAKENONTRIV; IOBEGIN(MAKENONTRIV) # * MAKENONTRIV - MAKE FILE SELECTION NON-TRIVIAL. * * MAKENONTRIV IS RESPONSIBLE TO TRY TO AVOID SHOWING THE * THE USER ANY DISCARDED FILE IMAGES, WHICH HAVE FILE NAMES * OF ZZZNULL. THIS IS DONE BY CHECKING FOR THAT RESERVED * FILE NAME, AND WHEN IT APPEARS, THE ALGORITHM ATTEMPTS TO * SELECT A BETTER FILE USING THE "LAST NON-TRIVIAL FILE CLOSED" * INFORMATION WHICH WAS MAINTAINED BY THE CLOSEFILE ROUTINE. * * ENTRY FILENAM[1-2] - CURRENT FILE NAMES. * FILEFILE[2 - WHETHER SECOND FILE BRACKET ACTIVE. * NONTRIVFILE[ALL] - RECENT VALID FILES. * * EXIT ONE OR BOTH FILE IMAGES POSSIBLY RE-OPENED. * * CALLS OPENFILE, SCANFDL, PICKFILE(INTERNAL), POSZ. * * USES READNAM, FILNUM, GETPARM, CHARPARM, LINENO. # PROC PICKFILE; IOBEGIN(PICKFILE) # * PICKFILE - INTERNAL ALGORITHM FOR MAKENONTRIV. * * NOTE SEE HEADER DOCUMENTATION FOR MAKENONTRIV. # POSZ(LINENO); SCANFDL(READNAM); GETPARM=0; CHARPARM=0; OPENFILE; IF FILNUM EQ CURFILE AND NOT SCREENMODE THEN BEGIN CONTROL IFEQ SINGLE,1; IF NOT INTERACT THEN TTSTR(" $"); CONTROL FI; TTSTR("EDIT: $"); TTLFN(FILENAM[FILNUM]); TTBRK; END IOEND # OF PICKFILE # # MAKENONTRIV MAIN ALGORITHM STARTS HERE # PUSHTEMP; IF SPLITFILE[2] NQ 0 AND FILENAM[2] EQ "ZZZNULL" THEN BEGIN FILNUM=2; LINENO=FDLF(2); IF FILENAM[1] NQ "ZZZNULL" THEN LINENO=FDLF(1); ELSE BEGIN FOR TEMP=4 STEP -1 UNTIL 1 DO BEGIN IF NONTRIVFILE[2,TEMP] NQ 0 THEN LINENO=NONTRIVFILE[2,TEMP]; END END PICKFILE; END IF FILENAM[1] EQ "ZZZNULL" THEN BEGIN FILNUM=1; LINENO=FDLF(1); IF SPLITFILE[2] NQ 0 AND FILENAM[2] NQ "ZZZNULL" THEN LINENO=FDLF(2); ELSE BEGIN FOR TEMP=4 STEP -1 UNTIL 1 DO BEGIN IF NONTRIVFILE[1,TEMP] NQ 0 THEN LINENO=NONTRIVFILE[1,TEMP]; END END PICKFILE; END POPTEMP; IOEND # OF MAKENONTRIV # PAGE # GLOBAL PROMPTING # PROC CHECKGLOBAL; BEGIN # ** CHECKGLOBAL - SEE IF GLOBAL SEARCH/CHANGE IN EFFECT. * * CHECKGLOBAL TESTS WHETHER THE PROMPTING FLAG SHOULD BE SET * FOR GLOBAL LOCATE/CHANGE MENU PROMPTS. THE DECISION * REQUIRES SCREEN MODE, LARGE LIMIT IN THE COMMAND RANGE, * LACK OF QUIET MODE, LACK OF COMMAND PROCEDURE, AT LEAST ONE * RANGE BOUNDARY OFF-SCREEN. * * ENTRY LIMIT, SCREENMODE, DONTPRINT - MODES. * LINPTR1, LINPTR2 - RANGE BOUNDS. * CURSPLIT, TOPS(CURSPLIT), BOTS(CURSPLIT) - BOUNDS. * * EXIT PROMPTING - FORCED TRUE IF RIGHT CONDITIONS. * ROWSUSED - FORCED ZERO SAME CONDITIONS. # IF LIMIT GR 1 AND SCREENMODE AND ( NOT DONTPRINT ) AND ( LINPTR1 LQ TOPS(CURSPLIT) OR LINPTR1 GQ BOTS(CURSPLIT) OR LINPTR2 LQ TOPS(CURSPLIT) OR LINPTR2 GQ BOTS(CURSPLIT) OR (LINPTR1 EQ TOPF(CURFILE)+1 AND LINPTR2 EQ BOTF(CURFILE)-1) ) THEN BEGIN PROMPTING=TRUE; ROWSUSED=0; END END # OF CHECKGLOBAL # PROC LASTGLOBAL; IOBEGIN(LASTGLOBAL) # ** LASTGLOBAL - DETERMINE IF LAST ITERATION OF CHANGE. * * LASTGLOBAL DETERMINES WHETHER A RECENTLY COMPLETED * ALTER OR REPLACE COMMAND NEEDS ONE LAST GLOBAL CHANGE * MENU DISPLAY. * * ENTRY PROMPTING - WHETHER IN GLOBVAL DISPLAY MODE. * ROWSUSED - HOW MANY MENU ITEMS PENDING USER PROMPT. * * EXIT LINCTR - POSSIBLY LARGENUM. * CMDLIN - POSSIBLY CONTAINS UNDO COMMAND. * * CALLS GLOBALCHANGE. # IF PROMPTING THEN BEGIN LINCTR=LARGENUM; # FOR FINAL PROMPT # IF ROWSUSED NQ 0 THEN GLOBALCHANGE; END IOEND # OF LASTGLOBAL # PROC ASKUSER(STR1,STR2); IOBEGIN(ASKUSER); # ** ASKUSER - ASK QUESTION EITHER SCREEN OR LINE. * * ASKUSER IS ABLE TO INQUIRE OF THE USER FOR EXTRA INSTRUCTIONS * USING EITHER THE SCREEN DISPLAY OR BY PROMPTING ON A LINE * MODE TERMINAL. * * ENTRY STR1 - PROMPT STRING FOR SCREEN DEVICE. * STR2 - PROMPT STRING FOR LINE DEVICE. * SCREENMODE - WHICH MODE IS IN EFFECT. * COMMANDROW - WHERE TO PUT STR1. * CURFILE, ASCII[CURFILE] - LOWERCASE SUPPRESSION. * * EXIT TTYLIN - USER'S REPLY. * PROMPTING - FORCED FALSE ON RETURN. * ERRSTRING - FORCED BLANK ON RETURN. * ROWPAINT[COMMANDROW] - FORCED TRUE. * FOUND - FALSE FOR FUNCTION KEY COMMAND OVERRIDE. * ESCAPE - TRUE FOR FUNCTION OVERRIDE. * CMDLIN - IF OVERRIDE, FUNCTION COMMAND. * SCANPOS, TOKENPOS - ZEROED FOR OVERRIDE. * * CALLS COPYLIN, PUSH, PAINTSCREEN, DOSCREEN, POP, STARTCMD, * EXCHWD, TTSTR, PROMPT, CONVIN, TRIM, SQUELCH, * PUSHTEMP, POPTEMP. * * USES TEMP, TMPLIN, XCURSOR, YCURSOR. # ITEM STR1 C(80); ITEM STR2 C(10); CONTROL IFEQ SINGLE,1; ARRAY CMDTEMP[0:BUFWID]; # SAVE COMMAND LINE # BEGIN ITEM CMDLINSAVE = [BUFWIDP1(NULLIN)]; END CONTROL FI; IF SCREENMODE THEN BEGIN CONTROL IFEQ SINGLE,1; COPYLIN(CMDLIN,CMDTEMP); # SAVE # CONTROL FI; CONTROL IFEQ MULTI,1; COPYLIN(CMDLIN,TTYLIN); # SAVE # CONTROL FI; CMDLINE[0]=NULLIN; PUSH; PUSHTEMP; TEMP=CURCURSOR; IF ERRSTRING NQ " $" AND ERRSTRING NQ STR1 THEN BEGIN # IF UNIQUE ERRSTRING PRESENT # XCURSOR = 0; # MERGE WITH PROMPT # YCURSOR = 0; WHYLE CERRSTRING NQ "$" DO XCURSOR = XCURSOR + 1; CERRSTRING = ", "; XCURSOR = XCURSOR + 2; WHYLE XCURSOR LQ 77 AND CSTR1 NQ "$" DO BEGIN CERRSTRING = CSTR1; XCURSOR = XCURSOR + 1; YCURSOR = YCURSOR + 1; END CERRSTRING = "$"; END ELSE BEGIN # NO UNIQUE ERRSTRING YET # ERRSTRING = STR1; # SET TO PROMPT # END XCURSOR=0; YCURSOR=COMMANDROW; PROMPTING=TRUE; # RESTRICT KEYBOARD TRICKS # PAINTSCREEN; DOSCREEN; PROMPTING=FALSE; ROWPAINT[COMMANDROW]=TRUE; CURCURSOR=TEMP; POPTEMP; POP; IF ESCAPE THEN BEGIN MOVEWD(BUFWIDP1,CMDLIN,TTYLIN); STARTCMD; END CONTROL IFEQ SINGLE,1; ELSE BEGIN # RESTORE # COPYLIN(CMDLIN,TTYLIN); COPYLIN(CMDTEMP,CMDLIN); END CONTROL FI; CONTROL IFEQ MULTI,1; ELSE EXCHWD(BUFWIDP1,CMDLIN,TTYLIN); # RESTORE # CONTROL FI; END ELSE BEGIN ERRSTRING=STR2; TTSTR(STR1); PROMPT(ERRSTRING); CONVIN(TTYLIN,2); TRIM(TTYLIN,1); END IF ASCII[CURFILE] LQ 1 THEN SQUELCH(TTYLIN); ERRSTRING=" $"; IOEND # OF ASKUSER # PAGE # PROCESS ROUTINE # PROC PROCESS; IOBEGIN(PROCESS) # ** PROCESS - STEADY-STATE MAIN PROCESS OF EDITOR. * * PROCESS PROVIDES THE MAIN LOOP FOR EDITOR EXECUTION IN THE * STEADY STATE, (I.E. AFTER INITIALIZE AND BEFORE * TERMINATE), AND DRIVES THE SCANNING AND EXECUTION OF EACH * OF THE COMMANDS. THE MAIN LOOP OF PROCESS IS BROKEN IN THE * FOLLOWING LABELED SECTIONS -- * * "PRCLEAR" - THIS SECTION DRIVES INTERACTION WITH THE * TERMINAL TO OBTAIN NEW COMMANDS. SINCE PRCLEAR MAY BE * ACTIVATED BEFORE THE PREVIOUS COMMAND SEQUENCE CLEANLY * TERMINATED, (I.E. AFTER TERMINAL INTERRUPT OR SYNTAX * ERROR), LOGIC IS PROVIDED TO CLEAN UP ANY CLUTTER. THE * FETCHING OF COMMANDS MAY OCCUR VIA GETPROCNXT, GETCMD, * DOSCREEN, OR VIA CONNECTION FROM THE SINGLE-USER EDITOR TO * THE MULTI-USER EDITOR. * * GETPROCNXT AND GETCMD SIMPLY OBTAIN ONE LINE OF COMMAND * TEXT FROM EITHER AN ACTIVE EDITOR PROCEDURE OR FROM A * LINE-MODE TERMINAL. DOSCREEN OBTAIN COMMANDS FROM A SCREEN * TERMINAL, AND MAY PERFORM ANY FILE MANIPULATIONS OFF THE * KEYBOARD BEFORE IDENTIFYING A COMMAND STRING. BEFORE * CALLING DOSCREEN, PRCLEAR MUST CALL PAINTSCREEN TO BRING * THE SCREEN DISPLAY UP TO DATE WITH RESULTS OF THE PREVIOUS * COMMAND SEQUENCE. CONNECTION TO MULTI MAY CAUSE ANY AMOUNT * OF EDITING TO BE DONE BEFORE THE MULTI-USER EDITOR RETURNS * A COMMAND STRING WHICH IT DOES NOT KNOW HOW TO EXECUTE. * * "PRNEXT" CONTINUES AFTER PRCLEAR BY INITIALIZING THE SYNTAX * SCANNER TO THE BEGINNING OF A STRING OF SEVERAL COMMANDS. * THE PROCESS ROUTINE IS ALLOWED TO SKIP PRCLEAR AND START * WITH THE PRNEXT SECTION SHOULD A COMMAND STRING BE * AVAILABLE AS A RESULT OF EDITOR INITIALIZATION. * * "PRMORE" CONTINUES SYNTAX SCAN FOR EACH COMMAND VERB. * PRMORE RE-DEFAULTS A NUMBER OF EDITOR VARIABLES RELATED TO * SYNTAX OPTIONS THEN IDENTIFIES THE COMMAND VERB AND FANS * OUT TO THE APPROPRIATE PROCESSING LABEL. THERE IS ONE * PROCESSING LABEL FOR EACH COMMAND VERB (LABELS "PPXXXX") * PLUS A NUMBER OF PROCESSING LABELS FOR QUASI COMMANDS. * (LABELS "QQXXXX") * * "PREND" IS THE RETURN POINT FOR COMMANDS THAT COMPLETE * NORMALLY. IT SIMPLY DETERMINES WHETHER TO GO TO PRMORE FOR * EXECUTION OF ADDITIONAL COMMAND VERBS FROM THE SAME COMMAND * STRING, OR TO GO TO PRCLEAR TO RESET THE TERMINAL AND * PROMPT FOR MORE COMMANDS. * * "PRERROR" IS THE RETURN POINT FOR COMMANDS THAT CANNOT * COMPLETE THEIR NORMAL FUNCTION DUE TO A USER'S ERROR. FOR * THE MULTI-USER VERSION OF THE EDITOR, PRERROR MUST * RE-DEFAULT THE SUBROUTINE CALLING LINKAGE TO KEEP * REENTRANCY WORKING CORRECTLY. * * THERE IS ONLY ONE MECHANISM TO RETURN OUT OF THE PROCESS * ROUTINE - THE "QQEXIT" LABELED SECTION. * * ENTRY WHEN PROCESS IS ENTERED, ALL THAT IS EXPECTED IS * THERE IS A VALID WORKFILE WITH A FILE DIRECTORY * BRACKET, ONE OR MORE FILE IMAGE BRACKETS, AND AN * AUDIT TRAIL BRACKET. THE RELOCATION VECTOR MUST * CONTAIN VALID BRACKET POINTERS FOR THESE SECTIONS. * THE INPUT AND OUTPUT FILES MUST BE READY TO BE USED. * * EXIT WHEN PROCESS COMPLETES, ALL COMMANDS HAVE BEEN * PROCESSED IN THE CASE OF THE SINGLE-USER VERSION, OR * CMDLIN CONTAINS AN UNEXECUTABLE COMMAND IN THE CASE * OF THE MULTI-USER VERSION. AFTER PROCESS COMPLETES, * THE MULTI-USER VERSION IS EXPECTED TO CHECKPOINT AND * RE-TRANSFER THE WORKFILE. THE SINGLE-USER VERSION * IS EXPECTED TO RE-BUILD FILES ACCORDING TO THE * ATTRIBUTES IN THE FILE DIRECTORY. # XDEF LABEL PRERROR; CONTROL IFEQ MULTI,1; XDEF LABEL QQSINGLE; CONTROL FI; SWITCH PROCESSSW PPALTER, PPBACK, PPCOPY, PPDELETE, PPDATA, PPEDIT, PPFSE, PPGET, PPHELP, PPINSERT, PPLOCATE, PPMOVE, PPPRINT, PPQUIT, PPREPLACE, PPSET, PPTEACH, PPUNDO, PPVIEW; PAGE # OUTER LOGIC OF PROCESS # ORIGSTKPTR=STACKPTR; STARTCMD; GOTO PRNEXT; # CTL CARD HAS 1ST CMD # PRCLEAR: # NEW INTERACTION # CURF(CURFILE)=MIN(MAX(CURRENT,TOPF(CURFILE)),BOTF(CURFILE)); IF USRBRK NQ 0 THEN BEGIN USRBRK=0; TTINIT; VDTFLS; # THROW AWAY INCOMPLETE I/O # VDTDRN; CONTROL IFEQ MULTI,1; CLEARINT; # CLEAR SMFEX INTRPT, REQUE # CONTROL FI; CONTROL IFEQ SINGLE,1; IF PROCACTIVE THEN CLEARPROC; CONTROL FI; CMDLINE[0]=LINECMD; # SET LINE # CMDLINE[1]=NULLIN; STARTCMD; GOTO PRNEXT; END FORWARD=FALSE; BACKWARD=FALSE; PROMPTING=FALSE; NUMWIDBLK=NUMWIDTH+BLANKS; IF NUMBERED[CURFILE] EQ 0 THEN NUMWIDBLK=0; CONTROL IFEQ SINGLE,1; # NOTE - MUST TEST VDTAPS BEFORE PROCACTIVE. IF VDTAPS, JUMP # # FORWARD TO AVOID PROCACTIVE TEST. # IF NOT APSTRREAD[0] THEN BEGIN # IF APPLICATION STRING NOT READ # VDTAPS("FSEKEYS",CMDLIN,LINPTR1,LINPTR2); IF LINPTR2 EQ 0 THEN # GOT A COMMAND # BEGIN IF LINPTR1 LQ BUFCM1 THEN BEGIN # IF TDU STRING IS SMALL ENOUGH # FOR LINPTR3=0 STEP 1 UNTIL LINPTR1-1 DO BEGIN # TRANSLATE COMMAND # GETCHAR(CMDLINE,LINPTR3,LINPTR2); LINPTR2=XLTXPINT[LINPTR2]; SETCHAR(CMDLINE,LINPTR3,LINPTR2); END SETCHAR(CMDLINE,LINPTR1,CENDLINE); END ELSE BEGIN # TDU FSEKEYS STRING IS TOO LONG # CMDLINE[0]=NULLIN; # NULL COMMAND # ERRSTRING = "FSEKEYS IN TDU DEFINITION TOO LONG$"; END STARTCMD; GOTO PRNEXT; END ELSE # END OF COMMANDS # BEGIN IF SCREENMODE THEN APSTRREAD[0] = TRUE; END END # NOTE - MUST TEST PROCACTIVE BEFORE CTLCDCMD. IF PROCACTIVE, # # JUMP FORWARD TO AVOID CTLCDCMD TEST. SINCE GETPROCNXT MIGHT # # TURN PROCACTIVE OFF, THE CODE CANNOT USE IF/ELSE LOGIC BUT # # MUST TEST THE FLAG TWICE. # IF PROCACTIVE THEN GETPROCNXT; # MUST TEST TWICE # IF PROCACTIVE THEN GOTO PRNEXT; # CANNOT USE "ELSE" # # NOTE - MUST TEST CTLCDCMD BEFORE READING A COMMAND BUFFER FROM # # THE TERMINAL. IF CTLCDCMD, JUMP FORWARD TO AVOID TERMINAL IO. # IF CTLCDCMD THEN # FETCH CTL CARD CMDS # BEGIN P=CCDR; MOVEWD(8,FROM,TMPLIN); CONVIN(CMDLIN,1); LINPTR3=-1; FOR LINPTR1=0 STEP 1 WHILE LINPTR3 LS 0 DO BEGIN GETCHAR(CMDLINE,LINPTR1,LINPTR2); IF LINPTR2 EQ CPERIOD OR LINPTR2 EQ CRPAREN THEN LINPTR3=LINPTR1+1; IF LINPTR2 EQ CENDLINE THEN LINPTR3=LINPTR1; END FOR LINPTR1=LINPTR3 STEP 1 UNTIL LENGTH(CMDLIN) DO BEGIN GETCHAR(CMDLINE,LINPTR1,LINPTR2); SETCHAR(CMDLINE,LINPTR1-LINPTR3,LINPTR2); END CTLCDCMD=FALSE; # ASSURE NO FURTHER USAGE # STARTCMD; IF LENGTH(CMDLIN) NQ 0 THEN GOTO PRNEXT; END CONTROL FI; AUDITCHECK; # SINCE THIS IS NEW TRANSACTION CYCLE # IF CURFILE EQ 2 AND SPLITFILE[2] EQ 0 THEN BEGIN # MUST GET CURRENT FILE INTO BRACKET 1 # CURF(2)=MIN(MAX(CURRENT,TOPF(2)),BOTF(2)); READNAM=PADNAME(FILENAM[2]); FILNUM=1; CHARPARM=0; GETPARM=0; OPENFILE; END MAKENONTRIV; # MAKE FILE SELECT NONTRIVIAL # IF ERRCURSOR LS 0 THEN CMDLINE[0]=NULLIN; IF SCREENMODE THEN BEGIN IF FORCEDHOME THEN # IF HOME REQUESTED # BEGIN FORCEDHOME=FALSE; XCURSOR=0; YCURSOR=COMMANDROW; END PAINTSCREEN; IF PAINTAGAIN THEN # IF SCREEN SHOULD BE PAINTED # BEGIN PAINTALL; # SET PAINT SCREEN BITS # PAINTAGAIN=FALSE; # RESET PAINT FLAG # END END ELSE BEGIN # LINE MODE # IF ERRSTRING NQ " $" THEN BEGIN # IF MESSAGE TO OUTPUT # CONTROL IFEQ SINGLE,1; IF NOT INTERACT THEN TTSTR(" $"); CONTROL FI; TTLIN(ERRSTRING); END END IF ERRSTRING NQ " $" THEN BEGIN # IF MESSAGE TO CLEAR # ROWPAINT[RESPONSEROW] = TRUE; ERRSTRING = " $"; END ERRCURSOR=-1; STARTCMD; CONTROL IFEQ SINGLE,1; IF LENGTH(CMDLIN) EQ 0 THEN PRECONNECT; IF CONNECTED THEN CONNECT; # MUST TEST TWICE # IF CONNECTED THEN POSTCONNECT; # CANNOT USE *ELSE* HERE # ELSE # BUT MUST USE *ELSE* HERE # BEGIN PUSH; IF NULLINPUT THEN BEGIN CMDLINE[0]=NULLIN; GOTO QQEXIT; END IF SCREENMODE THEN DOSCREEN; ELSE GETCMD; NOPOP; END IF EXPANDAT GQ 0 THEN EXPANDCMDS; CONTROL FI; CONTROL IFEQ MULTI,1; PUSH; IF SCREENMODE THEN DOSCREEN; ELSE GETCMD; NOPOP; IF EXPANDAT GQ 0 THEN EXPANDCMDS; CONTROL FI; PRNEXT: # DROP THRU OR SKIP AT START # CONTROL IFEQ SINGLE,1; IF NOT (ECHOOFF OR INTERACT) THEN BEGIN # IF NOT INTERACTIVE # IF LENGTH(CMDLIN) NQ 0 THEN BEGIN # IF COMMAND, ECHO # TTSTR(" $"); SCRNPT3 = LENGTH(CMDLIN); FOR SCRNPT5 = 0 STEP 1 UNTIL SCRNPT3 - 1 DO BEGIN GETCHAR(CMDLINE,SCRNPT5,SCRNPT4); SCRNPT4 = XLTINTDSP[SCRNPT4]; TTCHR(SCRNPT4); END TTBRK; END END CONTROL FI; KEYWDTYPE=1; TOKEN; PRMORE: # CONTINUE MULTI-CMD LINE # CONTROL IFEQ MULTI,1; CHKVICTIM; # IN CASE SMFEX PROBLEM # RSTKSAVE=RSTKPTR; # IN CASE SYNTAX ERROR # OLDCURFIL=CURFILE; # IN CASE CHANGE OF FILE ... # OLDFDLF1=FDLF(1); # ... SELECTION IN SWITCH ... # OLDFDLF2=FDLF(2); # ... MULTI TO SINGLE. # CONTROL FI; DATAPTR=-1; # ASSURE CLEAN DATA STACK # CMDMARKER=TOKENPOS; # REMEMBER BEFORE PREFICES # DELETCTL=0; NONDEFAULT=FALSE; TXTINCMD=FALSE; BACKWARD=FALSE; FORWARD=FALSE; CHARRANGE=FALSE; NUMWIDBLK=NUMWIDTH+BLANKS; IF NUMBERED[CURFILE] EQ 0 THEN NUMWIDBLK=0; DONTPRINT=FALSE; FOUND=TRUE; LIMIT=-1; WHICHLIN=1; WHICHSTR=0; FILNUM=0; CURF(CURFILE)=MIN(MAX(CURRENT,TOPF(CURFILE)),BOTF(CURFILE)); NEWCURSOR=CURCURSOR; ESCAPE=FALSE; NXTESCAPE=FALSE; THISEXTEND=0; CMDWASDLTE[0] = FALSE; FORCEAUTOP[0] = FALSE; FORCEAUTOR[0] = FALSE; IF USRBRK NQ 0 THEN GOTO PRCLEAR; CANINTER=TRUE; PUSH; # REMEMBER CURRENT # PUSHBACK; CONTROL IFEQ MULTI,1; IF FORCESINGLE THEN BEGIN FORCESINGLE=FALSE; TOKEN; GOTO QQSINGLE; END CONTROL FI; PROCESSNDX=-1; # DEFAULT IS BAD CMD # IF NOT SYNTAXCHAR[TOKENCHAR] THEN BEGIN IF TOKENCHAR EQ CSEMCOLON AND NOT SCREENMODE THEN TTLIN(" $"); GOTO PREND2; END IF TOKENCHAR EQ CSLASH THEN GOTO QQNOS; ELSE IF TOKENCHAR EQ CPERIOD THEN GOTO QQWORD; ELSE IF TOKENCHAR EQ CMINUS THEN GOTO QQXECUTE; ELSE IF TOKENTYPE EQ TYPST"LETTER" THEN PROCESSNDX=KEYWDNDX; IF PROCESSNDX EQ -1 THEN ERRJUMP("UNKNOWN DIRECTIVE$"); TOKEN; GOTO PROCESSSW[PROCESSNDX]; PREND: # RESUME HERE AFTER COMMAND # PAGELAST=FALSE; PREND1: # RESUME HERE AFTER VIEW COMMAND # OLDLINPTR=CURRENT; OLDCURSOR=NEWCURSOR; CURCURSOR=NEWCURSOR; XCURSOR=NEWCURSOR-XSHIFT[CURSPLIT]; YCURSOR=-1; PREND2: # RESUME HERE FOR NULL CMD LINE, PROC CALL # CONTROL IFEQ SINGLE,1; IF NOT INTERACT AND PROCACTIVE AND ERRSTRING NQ " $" THEN BEGIN # IF BATCH PROCEDURE ERRSTRING # TTSTR(" $"); TTLIN(ERRSTRING); ERRSTRING = " $"; END CONTROL FI; IF KILLMARKS THEN BEGIN KILLMARKS=FALSE; PAINTMARKS(3); NUMMARKS=0; END NOPOP; # COMMAND DID POS # IF SAMEBACK THEN DECRBACK; IF ESCAPE THEN GOTO PRNEXT; IF NOT FOUND THEN GOTO PRCLEAR; KEYWDTYPE=1; TOKEN; IF TOKENTYPE EQ TYPST"EOL" THEN GOTO PRCLEAR; GOTO PRMORE; PRERROR: # RESUME HERE AFTER ERROR # CONTROL IFEQ MULTI,1; RSTKPTR=RSTKSAVE; # SINCE ERROR COULD BE NESTED # CONTROL FI; CONTROL IFEQ SINGLE,1; IF PROCACTIVE THEN CLEARPROC; CONTROL FI; POP; # RESTORES CURRENT # IF SAMEBACK THEN DECRBACK; CONTROL IFEQ SINGLE,1; IF NOT INTERACT THEN BEGIN TTSTR(" $"); TTLIN(ERRSTRING); MORTAL(" BATCH JOBS MUST BE ERROR FREE.$"); END CONTROL FI; GOTO PRCLEAR; PAGE # PROCESS COMMAND HANDLERS # PPALTER: TTYLINE[0]=NULLIN; WHICHSTR=1; EXECNDX=EXECST"MODIFY"; SCANNER; VFYLOCK; IF EXECNDX EQ EXECST"APPEND" THEN GOTO QQAPPEND; IF NOT TXTINCMD THEN BEGIN IF SCREENMODE THEN ASKUSER("ALTER WHAT ?$",CKWRD); ELSE GETMOD; END CONTROL IFEQ MULTI,1; IF SCREENMODE THEN BEGIN # IF SCREEN MODE # CONTROL FI; CONTROL IFEQ SINGLE,1; IF SCREENMODE OR NOT INTERACT THEN BEGIN # IF SCREEN OR BATCH MODE # CONTROL FI; DOTAB(0,XSHIFT[CURSPLIT],0); END ELSE BEGIN # INTERACTIVE LINE MODE # DOTAB(0,0,0); END CHECKGLOBAL; DORANGE; LASTGLOBAL; GOTO PREND; PPBACK: SCNEOC; IF DATAKEYPRS[0] THEN BEGIN SCNEOC; EXCHSAVPOS; # EXCHANGE WITH STORED SCREEN # SETUPSCREEN(1,LINPTR1,LINPTR2); END ELSE BEGIN ERRSTRING = "NO FILE DATA STORED WITH 'DATA'$"; END GOTO PREND; PPCOPY: FILCMDNDX=FILCMDST"COPY"; EXECNDX=EXECST"COPY"; PPCOPY2: NEWCURSOR=0; CONTROL IFEQ SINGLE,1; SNGLMOV; CONTROL FI; CONTROL IFEQ MULTI,1; MULTMOV; CONTROL FI; GOTO PREND; PPDELETE: CMDWASDLTE[0] = TRUE; SCANNER; VFYLOCK; IF SCANBLOCK THEN GOTO QQCLOSE; IF SCANWORD THEN GOTO QQSQUEEZE; IF NOT (SCREENMODE OR DONTPRINT) THEN BEGIN EXECNDX=EXECST"TYPE"; DORANGE; IF NOT FOUND THEN GOTO PREND; LINPTR1=REGLINE[RNGTOPREG]+1; LINPTR2=REGLINE[RNGBOTREG]-1; END EXECNDX=EXECST"DELETE"; DORANGE; IF CHARRANGE THEN BEGIN SPLICE; NEWCURSOR=CHRPTR3; END IF CURRENT LQ TOPF(CURFILE) THEN FWDZ; # IF FIRST LINE DELETED # GOTO PREND; PPDATA: SCNEOC; # SCAN TO END OF COMMAND # STORCURPOS; # STORE CURRENT POSITION # DATAKEYPRS[0] = TRUE; # SET FLAG REFERENCE BY BACK # ERRSTRING = "FILE DATA STORED FOR USE WITH 'BACK'$"; GOTO PREND; PPEDIT: SCNEOC; # SCAN TO END OF COMMAND # IF SPLITFILE[2] NQ 0 THEN BEGIN # IF IN SPLIT SCREEN MODE # SETUPSCREEN(1,0,0); # EDIT THE TOP SPLIT ONLY # CURFILE = 1; POSZ(CURF(1)); END ELSE BEGIN # NOT IN SPLIT SCREEN MODE # IF INITFILE[1] EQ 0 THEN BEGIN # IF CURRENT FILE NOT FIRST # PUSH; POSZ(TOPC(FILECTL)+1); SCNFDINIT = 0; WHYLE SCNFDINIT EQ 0 AND CURRENT NQ BOTC(FILECTL) DO BEGIN SCANFDL(LINPTR1); FWDZ; END POP; FILNUM = 1; CLOSEFILE; # CLOSE CURRENT FILE # READNAM = C<0,7>LINPTR1; # OPEN INITIAL FILE # CHARPARM = 0; GETPARM = 0; FILNUM = 1; OPENFILE; ERRSTRING = "EDITING INITIAL FILE$"; END ELSE # CURRENT FILE IS INITIAL # BEGIN ERRSTRING = "CURRENT FILE IS INITIAL FILE$"; END END GOTO PREND; PPFSE: SCNFILOPT; SCNEOC; OPENFILE; IF FILNUM EQ 2 THEN SETUPSCREEN(1,2,USRSPLTSZ); ELSE SETUPSCREEN(1,0,0); NEWCURSOR=0; GOTO PREND; PPGET: SCNEQNAM(READNAM); SCNEOC; IF C<0,1>READNAM EQ "S" THEN GOTO QQSTATUS; # "GET STATUS" # IF C<0,1>READNAM EQ "A" THEN GOTO QQPSCALE; # "GET ALIGN" # CONTROL IFEQ MULTI,1; CONTROL IFEQ METERING,1; IF C<0,1>READNAM EQ "D" THEN # "GET DATA" # BEGIN FOR LINPTR1=LOC(BGNSTATS) STEP 1 UNTIL LOC(ENDSTATS) DO BEGIN FOR LINPTR2=0 STEP 1 UNTIL 19 DO BEGIN SETCHAR(LINE,LINPTR2,CDIGIT0+BMEM[LINPTR1]); END SETCHAR(LINE,20,CENDLINE); INSX; END END CONTROL FI; CONTROL FI; GOTO PREND; PPHELP: CONTROL IFEQ MULTI,1; GOTO QQSINGLE; CONTROL FI; CONTROL IFEQ SINGLE,1; HELPCMD; NEWCURSOR=0; GOTO PREND; CONTROL FI; PPINSERT: TTYLINE[0]=NULLIN; LIMIT=-2; WHICHSTR=1; WHICHLIN=4; SCANNER; VFYLOCK; IF FORWARD THEN LINPTR3=LINPTR3+1; ELSE IF BACKWARD THEN LINPTR3=LINPTR3-1; WINDOPOS(LINPTR3,FILPTR3); IF NOT FOUND THEN BEGIN HALT("OUT OF BOUNDS$"); GOTO PREND; END IF SCANBLOCK THEN GOTO QQOPEN; IF SCANWORD THEN GOTO QQSTRETCH; IF NOT TXTINCMD AND SCREENMODE THEN BEGIN ASKUSER("INSERT WHAT ?$",CKWRD); IF NOT FOUND THEN GOTO PREND; TXTINCMD=TRUE; END POSZ(LINPTR3); # TARGET FOR INSERTION # CURFILE=FILPTR3; LIMIT=1; # INDICATE ONE LINE MUST FIT # FITNUM; LINCTR=0; WHYLE NOT ESCAPE DO BEGIN IF NUMBERED[CURFILE] NQ 0 THEN BEGIN LINENO=LINENO+INCR; IF LINENO GQ LINNUM2 OR LINENO GR NINES THEN BEGIN ESCAPE=TRUE; TEST; # THIS KILLS LOOP # END END EXECINS; # PROCESSES ESCAPE, READS TTY # IF ESCAPE THEN TEST; # AND KILL LOOP # INSX; # FINALLY GOT A LINE # LINCTR=LINCTR+1; END # OF EVERYTHING LOOP # NEWCURSOR=0; ESCAPE=FALSE; GOTO PREND; PPLOCATE: EXECNDX=EXECST"LOCATE"; WHICHSTR=2; PPLOCATE2: SCANNER; IF EXECNDX EQ EXECST"REPLACE" THEN VFYLOCK; IF SCANWORD THEN WORDSEARCH=TRUE; IF SCANUPPER THEN UPPERSEARCH=TRUE; IF LIMIT EQ 1 THEN SUBSTONCE=TRUE; ELSE SUBSTONCE=FALSE; IF LOCSTRLEN1 EQ 0 THEN # NEED STRING # BEGIN ASKUSER("LOCATE WHAT?$",CKWRD); IF LENGTH(TTYLIN) GR 0 THEN MOVEWD(STRWID,TTYLIN,LOCSTRING1); SETCHAR(LOCSTR1,80,CENDLINE); # ASSURE TERMINATED # LOCSTRLEN1=LENGTH(LOCSTRING1); ELLIPSIS=FALSE; END CHECKGLOBAL; PUSH; # REMEMBER WHERE WE ARE # FOUNDOTHER=FOUND; # REMEMBER WHETHER IN BOUNDS # DORANGE; FOUND=FOUNDOTHER; IF FOUND AND (LINCTR EQ 0 OR (LINCTR LS LIMIT AND LIMIT LS LARGENUM)) THEN BEGIN # IF IN BOUNDS BUT TOO FEW HITS # IF SCHSTRSPEC AND SCREENMODE AND NOT PROCACTIVE THEN BEGIN # IF NEED TO PRESERVE COMMAND LINE # POP; ERRJUMP("NOT FOUND$"); END HALT("NOT FOUND$"); END IF EXECNDX EQ EXECST"REPLACE" THEN LASTGLOBAL; IF PROMPTING AND EXECNDX EQ EXECST"LOCATE" THEN BEGIN LINCTR=LARGENUM; # FOR FINAL PROMPT # IF ROWSUSED NQ 0 THEN # FORCE FINAL PROMPT # BEGIN POP; # GET TO LAST FOUND LINE # PUSH; # SAME STACK DEPTH # GLOBALLOCATE; NOPOP; # HOLD THIS POSITION # PUSH; # GET THIS LINE ONTO STACK # END END POP; # GO TO LAST LINE FOUND, OR OLD CURRENT IF NONE FOUND # IF PROMPTING THEN NEWCURSOR=0; GOTO PREND; PPMOVE: FILCMDNDX=FILCMDST"MOVE"; EXECNDX=EXECST"MOVE"; GOTO PPCOPY2; PPPRINT: EXECNDX=EXECST"TYPE"; SCANNER; LASTPROCESS=PROCESSNDX; IF SCREENMODE AND LIMIT EQ 1 THEN POSZ(LINPTR1); ELSE DORANGE; NEWCURSOR=CHRPTR1; GOTO PREND; PPQUIT: GOTO QQEXIT; PPREPLACE: EXECNDX=EXECST"REPLACE"; WHICHSTR=3; GOTO PPLOCATE2; PPSET: SCANSET; GOTO PREND; PPTEACH: GOTO PPHELP; PPUNDO: CONTROL IFEQ MULTI,1; GOTO QQSINGLE; CONTROL FI; CONTROL IFEQ SINGLE,1; UNDOCMD; GOTO PREND; CONTROL FI; PPVIEW: WHICHLIN=3; SCANNER; LINCTR=LINPTR3; # SELECT CENTER LINE # IF SCREENMODE THEN BEGIN IF SCANHOME THEN # SPECIAL - ONLY MOVE CURSOR # BEGIN FORCEDHOME=TRUE; # PUT CURSOR AT HOME POSITION # GOTO PREND2; END IF FORWARD THEN BEGIN TOPS(CURSPLIT)=LINCTR-1; END ELSE IF BACKWARD THEN BEGIN TOPS(CURSPLIT)=LINCTR-NUMROWS[CURSPLIT]; END ELSE BEGIN TOPS(CURSPLIT)=LINCTR-(NUMROWS[CURSPLIT]/2)-1; END SETTOPS(CURSPLIT); SETBOTS(CURSPLIT); IF FORWARD OR BACKWARD THEN BEGIN LINCTR=TOPS(CURSPLIT)+(NUMROWS[CURSPLIT]/2+1); END LINCTR=MAX(LINCTR,TOPF(CURFILE)+1); LINCTR=MIN(LINCTR,BOTF(CURFILE)-1); POSZ(LINCTR); END ELSE BEGIN MAKEPAGE(GROUPSIZ,CURFILE); BACKWARD=FALSE; LIMIT=LARGENUM; EXECNDX=EXECST"TYPE"; DORANGE; END PAGELAST=TRUE; GOTO PREND1; PAGE # ADDITIONAL PROCESSORS # QQABORT: TOKEN; SCNEOC; CONTROL IFEQ MULTI,1; GOTO QQSINGLE; CONTROL FI; CONTROL IFEQ SINGLE,1; IF SCREENMODE THEN CLEARSCREEN; EVICT(FET,1); # ASSURE NO RESUMED EDIT # ABORT; CONTROL FI; QQAPPEND: IF NOT TXTINCMD THEN ASKUSER("APPEND WHAT?$",CKWRD); DORANGE; GOTO PREND; QQCLOSE: POSZ(LINPTR1); IF LINPTR1 LQ TOPF(CURFILE) THEN FWDZ; WHYLE CURRENT LS BOTF(CURFILE) AND NOTEXT DO BEGIN DELETCTL=1; DELX; POSZ(CURRENT); END NEWCURSOR=0; GOTO PREND; QQEXIT: EXITFLAGS=0; WHYLE TOKENTYPE EQ TYPST"LETTER" DO BEGIN KEYWDNDX=-1; KEYWDTYPE=9; SCANPOS=TOKENPOS; TOKEN; IF TOKENSYM EQ "UNDO" THEN GOTO QQABORT; ELSE IF KEYWDNDX EQ KEYST"QPRO" THEN GOTO QQQUITPROC; ELSE IF KEYWDNDX EQ KEYST"QREP" THEN EXITSAVE=TRUE; ELSE IF KEYWDNDX EQ KEYST"QQUI" THEN DONTPRINT=TRUE; ELSE ERRJUMP("PARAMETER NOT VALID FOR THIS DIRECTIVE$"); TOKEN; END IF TOKENTYPE NQ TYPST"DELIMIT" THEN SCNEOC; QQNOS: TOKEN; KEYWDTYPE=0; SCANPOS=TOKENPOS; TOKEN; EXITCMD=TRUE; CONTROL IFEQ SINGLE,1; IF SCREENMODE THEN BEGIN CLEARSCREEN; END IF TOKENTYPE NQ TYPST"EOL" THEN # USER WANTS EXCST # BEGIN TTYLINE[0]=NULLIN; # COPY CONTROL STATEMENT # LINPTR2=0; LINNUM1=0; FOR LINPTR1=TOKENPOS STEP 1 UNTIL LENGTH(CMDLIN) DO BEGIN GETCHAR(CMDLINE,LINPTR1,LINCTR); SETCHAR(TTYLINE,LINPTR2,LINCTR); LINPTR2=LINPTR2+1; IF LINCTR EQ CPERIOD OR LINCTR EQ CRPAREN THEN LINNUM1=1; IF LINCTR NQ CBLANK AND LINCTR NQ CENDLINE THEN EXITEXCST=TRUE; END IF LINNUM1 EQ 0 THEN # NEEDS PUNCTUATION HELP # BEGIN SETCHAR(TTYLINE,LINPTR2-1,CPERIOD); SETCHAR(TTYLINE,LINPTR2,CENDLINE); END END PROCACTIVE=FALSE; CONTROL FI; CONTROL IFEQ MULTI,1; IF TOKENTYPE NQ TYPST"EOL" THEN EXITCMD=FALSE; QQSINGLE: IF CURFILE NQ OLDCURFIL OR FDLF(1) NQ OLDFDLF1 OR FDLF(2) NQ OLDFDLF2 THEN BEGIN # RESTORE FILE SELECTION IN EFFECT AT START OF COMMAND # # SINCE COMMAND WILL BE RESTARTED IN SINGLE. # PUSH; POSZ(OLDFDLF1); SCANFDL(READNAM); FILNUM=1; GETPARM=0; CHARPARM=0; OPENFILE; IF OLDFDLF2 NQ 0 THEN BEGIN POSZ(OLDFDLF2); SCANFDL(READNAM); FILNUM=2; GETPARM=0; CHARPARM=0; OPENFILE; END POP; CURFILE=OLDCURFIL; END CONTROL FI; STACKPTR=ORIGSTKPTR; # UNDOES PUSH IN PROCESS MAIN LOOP # IORET # THIS IS ONLY RETURN FROM PROCESS # QQOPEN: POSZ(LINPTR3); IF LIMIT NQ -2 THEN LINCTR=MIN(100,LIMIT); ELSE BEGIN LINCTR=GROUPSIZ; IF SCREENMODE THEN BEGIN LINCTR=NUMROWS[CURSPLIT]-4; LINPTR1=CURRENT-2; IF NUMROWS[CURSPLIT] LQ 8 THEN BEGIN LINCTR=LINCTR+2; LINPTR1=CURRENT-1; END IF NUMROWS[CURSPLIT] LQ 2 THEN BEGIN LINCTR=1; LINPTR1=CURRENT; END TOPS(CURSPLIT)=LINPTR1; SETTOPS(CURSPLIT); SETBOTS(CURSPLIT); END END FOR LINPTR2=1 STEP 1 UNTIL LINCTR DO BEGIN LINE[0]=NULLIN; INSX; END; POSZ(CURRENT-LINCTR+1); NEWCURSOR=0; GOTO PREND; QQPSCALE: SCNEOC; IF SCREENMODE THEN BEGIN ROWCOLUM[LTOY(CURRENT,CURSPLIT)]=TRUE; ROWPAINT[LTOY(CURRENT,CURSPLIT)]=TRUE; GOTO PREND; END IF NUMBERED[CURFILE] NQ 0 THEN LINPTR1=NUMWIDBLK; ELSE IF FLOAT THEN LINPTR1=5; ELSE LINPTR1=0; TTST(" ",LINPTR1); FOR LINCTR=1 STEP 1 UNTIL WIDTH DO BEGIN LINNUM2=MOD(LINCTR,10); TTDEC(LINNUM2); END TTBRK; GOTO PREND; QQQUITPROC: CONTROL IFEQ SINGLE,1; TOKEN; IF NOT SYNTAXCHAR[TOKENCHAR] THEN CLEARPROC; SCANNER; SCNEOC; IF BACKWARD OR NOT FOUND THEN CLEARPROC; CONTROL FI; GOTO PREND; QQSQUEEZE: POSZ(LINPTR1); SQUEEZE; REPX; GOTO PREND; QQSTATUS: CONTROL IFEQ MULTI,1; GOTO QQSINGLE; CONTROL FI; CONTROL IFEQ SINGLE,1; GETSTATUS; GOTO PREND; CONTROL FI; QQSTRETCH: POSZ(LINPTR3); STRETCH; REPX; GOTO PREND; QQWORD: TOKEN; SCANPOS=TOKENPOS; # RESTART SCAN ON SUBCOMMAND # KEYWDTYPE=6; TOKEN; KEYWDTYPE=0; IF KEYWDNDX LS 0 THEN BEGIN ERRJUMP("PARAMETER NOT VALID FOR THIS DIRECTIVE$"); END IF KEYWDNDX EQ KEYST"WINC" THEN BEGIN VFYLOCK; TOKEN; SETCHAR(TTYLINE,0,CBLANK); SETCHAR(TTYLINE,1,CENDLINE); IF TOKENTYPE EQ TYPST"DELIMIT" THEN BEGIN WHICHSTR=1; SCANSTR; END SCNEOC; SAVEPROT; RSHIFT(LIN,CURCURSOR,LENGTH(TTYLIN)); # MAKE ROOM # FOR LINPTR1=0 STEP 1 UNTIL LENGTH(TTYLIN)-1 DO BEGIN # INSERT STRING # GETCHAR(TTYLINE,LINPTR1,LINPTR2); SETCHAR(LINE,CURCURSOR+LINPTR1,LINPTR2); END MERGEPROT; REPX; GOTO PREND; END ELSE IF KEYWDNDX EQ KEYST"WDLC" THEN BEGIN VFYLOCK; TOKEN; SCNEOC; SAVEPROT; LSHIFT(LIN,CURCURSOR+1,1); MERGEPROT; REPX; GOTO PREND; END ELSE IF KEYWDNDX EQ KEYST"WEND" THEN BEGIN TOKEN; SCNEOC; NEWCURSOR=LENGTH(LIN); IF NEWCURSOR GR USRNUMCOL+XSHIFT[CURSPLIT] THEN ERRSTRING="END OF LINE BEYOND EDGE OF SCREEN$"; GOTO PREND; END ELSE IF KEYWDNDX EQ KEYST"WPOS" THEN BEGIN KEYWDTYPE=2; TOKEN; LINPTR1=CURCURSOR; IF TOKENTYPE EQ TYPST"DIGIT" THEN BEGIN SCNEQVAL; LINPTR1=LINPTR1-1; END IF KEYWDNDX EQ KEYST"XPRM" OR KEYWDNDX EQ KEYST"YPRM" OR KEYWDNDX EQ KEYST"ZPRM" THEN BEGIN # NOTE - CODE ASSUMES X, Y, Z ARE CONSECUTIVE IN TABLES # LINPTR1=XYZCHAR[KEYWDNDX-KEYST"XPRM"]; TOKEN; END LINPTR2=0; IF TOKENTYPE EQ TYPST"PLUS" THEN LINPTR2=1; ELSE IF TOKENTYPE EQ TYPST"MINUS" THEN LINPTR2=-1; LINPTR3=1; IF LINPTR2 NQ 0 THEN BEGIN TOKEN; IF TOKENTYPE EQ TYPST"DIGIT" THEN BEGIN LINPTR3=TOKENVAL; TOKEN; END LINPTR1=LINPTR1+LINPTR2*LINPTR3; END NEWCURSOR=MAX(LINPTR1,0); IF NEWCURSOR GR BUFCM1 THEN BEGIN # IF BEYOND MAXIMUM LINE LENGTH # NEWCURSOR = BUFCM1; ERRSTRING = "POSITION REQUESTED EXCEEDS MAXIMUM LINE LENGTH$"; END SCNEOC; GOTO PREND; END ELSE IF KEYWDNDX EQ KEYST"WJOI" THEN BEGIN TOKEN; # ADVANCE TO NEXT SYNTAX # WHICHLIN=3; CHARRANGE=TRUE; SCANNER; VFYLOCK; IF NOT FOUND THEN GOTO PREND; # OUT OF BOUNDS # POSZ(LINPTR3); CURFILE=FILPTR3; DOJOIN(1); GOTO PREND; END ELSE IF KEYWDNDX EQ KEYST"WSPL" THEN BEGIN TOKEN; # ADVANCE TO NEXT SYNTAX # WHICHLIN=3; CHARRANGE=TRUE; SCANNER; VFYLOCK; IF NOT FOUND THEN GOTO PREND; # OUT OF BOUNDS # POSZ(LINPTR3); CURFILE=FILPTR3; DOSPLIT(2); IF SCREENMODE AND CURRENT EQ BOTS(CURSPLIT) THEN FORCEAUTOP[0] = TRUE; NEWCURSOR=0; GOTO PREND; END CONTROL IFEQ MULTI,1; GOTO QQSINGLE; CONTROL FI; CONTROL IFEQ SINGLE,1; WORDCMD; GOTO PREND; CONTROL FI; QQXECUTE: TOKEN; CONTROL IFEQ MULTI,1; GOTO QQSINGLE; CONTROL FI; CONTROL IFEQ SINGLE,1; SCNEQNAM(PROCREC); # RECORD NAME # PARMPTR=SCNNAMPTR; # REMEMBER WHERE PARMS START # READNAM=PROCNAM; # DEFAULT PROC FILE # IF TOKENCHAR EQ CLPAREN THEN # USER HAS FILE NAME # BEGIN SCNFILE(READNAM); PARMPTR=SCNNAMPTR; END CURPROCNAM=READNAM; IF NOT PROCACTIVE THEN BEGIN EXPANDAT=PARMPTR; EXPANDCMDS; # EXPAND PARAMETER REFERENCES # END COPYLIN(CMDLIN,PARMLIN); # SAVE FOR PARAMETER REFERENCES # IF READNAM EQ "0" THEN GOTO PREND; # IF NO FILE # IF PROCACTIVE THEN # DETERMINE IF LOOPING # BEGIN IF PROCREC EQ OLDPROCREC AND READNAM EQ OLDPROCFIL THEN BEGIN # LOOPING ON SAME PROC # CURP(PROCCTL)=TOPP(PROCCTL); GOTO QQXECUTE2; # CAN BYPASS FILE SEARCH # END END OLDPROCREC=PROCREC; # SAVE FOR POSSIBLE LOOP # OLDPROCFIL=READNAM; PUSH; # SAVE FILE/LINE WHILE OPENING..# CURFILE=2; # ..PROCEDURE FILE, .. # POSZ(CURF(2)); # FOR CURRENT FILE AND FILE 2 # PUSH; PUSHBACK; # SAVE FILE CHOICES ALSO # FILNUM=2; # ACCESS THE FILE # CHARPARM=0; GETPARM=1; OPENFILE; LINENO=1; # 1=NEED RECORDNAME, 2=NEED EOR, 0=FOUND # POSZ(TOPF(2)+1); WHYLE CURRENT LS BOTF(2) AND LINENO NQ 0 AND USRBRK EQ 0 DO BEGIN TRIMPAD; IF LINENO EQ 1 THEN BEGIN IF COMPARLIN(LIN,PROCREC,FALSE) THEN LINENO=0; ELSE IF COMPARLIN(LIN," ",FALSE) THEN LINENO=1; ELSE LINENO=2; END IF LINENO EQ 2 THEN BEGIN IF COMPARLIN(LIN,"QUIT PROC",TRUE) THEN LINENO=1; ELSE IF COMPARLIN(LIN,EORCON,FALSE) THEN LINENO=1; ELSE IF COMPARLIN(LIN,EOFCON,FALSE) THEN LINENO=1; END IF LINENO NQ 0 THEN FWDZ; END IF LINENO NQ 0 AND PROCREC NQ "STARTUP" AND NOT PROCACTIVE THEN BEGIN # IF ERROR DISPLAY NEEDED # IF SCREENMODE THEN BEGIN # IF NEED TO PRESERVE COMMAND # DOBACK; POP; CURF(CURFILE)=CURRENT; POP; ERRJUMP("PROCEDURE NOT FOUND$"); END HALT("PROCEDURE NOT FOUND$"); END TOPP(PROCCTL)=CURRENT; CURP(PROCCTL)=CURRENT; BOTP(PROCCTL)=BOTF(2); PROCACTIVE=TRUE; DOBACK; POP; # RESTORE CURRENT FILE/LINE # CURF(CURFILE)=CURRENT; POP; QQXECUTE2: CMDLINE[0]=NULLIN; STARTCMD; GOTO PREND2; CONTROL FI; IOEND # OF PROCESS, FINALLY # PAGE # EDTINIT, EDTTERM - MAIN PGM # PROC EDTINIT; IOBEGIN(EDTINIT) CONTROL IFEQ MULTI,1; RESUMIO; # GETS DATA SEGMENT, CHECKS FILE # IF NOT IORESUMED THEN BEGIN FATAL(" PREVIOUS VERSION OF WORKFILE.$"); END POSZ(SAVECURL); CONTROL IFEQ METERING,1; BGNMETER; CONTROL FI; CONTROL FI; IOEND # OF EDTINIT # PROC EDTTERM; IOBEGIN(EDTTERM) CONTROL IFEQ MULTI,1; SMFINCTL=FALSE; # SHOW NORMAL NOT RCVRY # USRBRK=0; CHECKIO; # CHECKPOINTS EDIT # # NOTE WE ROLLIN SINGLE-USER JOB TO DO FILREBUILD # CONTROL FI; CONTROL IFEQ SINGLE,1; PAUSEIO; # FOR OTHER OVL'S BUFFERS # CONTROL FI; IOEND # OF EDTTERM # END TERM