!
SYSTEMROUTINESPEC  CHANGEFILESIZE(STRING (31) FILE, INTEGER  NEWSIZE,
    INTEGERNAME  FLAG)
SYSTEMROUTINESPEC  UCTRANSLATE(INTEGER  ADDR,L)
EXTERNALSTRING (255)FNSPEC  UCSTRING(STRING (255)S)
CONSTSTRING (1) SNL = "
"
ROUTINE  MOVE(INTEGER  LENGTH,FROM,TO)
      *LB_LENGTH
      *JAT_14,<L99>
      *LDTB_X'18000000'
      *LDB_ B 
      *LDA_FROM
      *CYD_0
      *LDA_TO
      *MV_ L = DR 
L99:END ;                                !OF MOVE
EXTERNALROUTINESPEC  PROMPT(STRING (15) S)
EXTERNALSTRINGFNSPEC  INTERRUPT
SYSTEMROUTINESPEC  TOJOURNAL(INTEGER  FROM,LEN)
RECORDFORMAT  FRF(INTEGER  CONAD,FILETYPE,DATASTART,DATEND,SIZE,RUP,EEP,MODE,
   USERS,ARCH, STRING (6) TRAN, STRING (8) DATE,TIME, INTEGER  COUNT,SPARE1,
   SPARE2)
RECORDFORMAT  RF(INTEGER  CONAD,FILETYPE,DATASTART,DATAEND)
SYSTEMROUTINESPEC  FINFO(STRING (31) FILE, INTEGER  MODE,
    RECORD (FRF) NAME  R, INTEGERNAME  FLAG)
SYSTEMROUTINESPEC  REROUTECONTINGENCY(INTEGER  EP,CLASS, LONGINTEGER  MASK,
    ROUTINE  CLOSE(INTEGER  A,B), INTEGERNAME  FLAG)
SYSTEMROUTINESPEC  SIGNAL(INTEGER  EP,CLASS,SUBCLASS, INTEGERNAME  FLAG)
EXTERNALROUTINESPEC  CHERISH(STRING (255) NAME)
EXTERNALSTRINGFNSPEC  UINFS(INTEGER  N)
SYSTEMROUTINESPEC  GETJOURNAL(STRINGNAME  FILE, INTEGERNAME  FLAG)
SYSTEMROUTINESPEC  SENDFILE(STRING (31) FILE, STRING (16) DEVICE,
    STRING (24) NAME, INTEGER  COPIES,FORMS, INTEGERNAME  FLAG)
SYSTEMROUTINESPEC  DESTROY(STRING (31) FILE, INTEGERNAME  FLAG)
!%SYSTEMROUTINESPEC CLEARUSE(%STRING(31) S,%INTEGERNAME FLAG)
SYSTEMROUTINESPEC  SETUSE(STRING  (31) FILE, INTEGER  MODE, VALUE)
SYSTEMROUTINESPEC  DISCONNECT(STRING (31) S, INTEGERNAME  FLAG)
SYSTEMROUTINESPEC  RENAME(STRING (31) OLDN,NEWN, INTEGERNAME  FLAG)
SYSTEMROUTINESPEC  MODPDFILE(INTEGER  EP, STRING (31) PDFILE,
    STRING (11) MEMBER, STRING (31) INFILE, INTEGERNAME  FLAG)
SYSTEMINTEGERFNSPEC  PARMAP
SYSTEMROUTINESPEC  SETPAR(STRING (255) S)
SYSTEMSTRINGFNSPEC  SPAR(INTEGER  N)
SYSTEMROUTINESPEC  NEWGEN(STRING (31) S,T, INTEGERNAME  FLAG)
SYSTEMROUTINESPEC  SETWORK(INTEGERNAME  ADDR,FLAG)
SYSTEMROUTINESPEC  SETFNAME(STRING (40) NAME)
SYSTEMROUTINESPEC  PSYSMES(INTEGER  ROOT,FLAG)
SYSTEMROUTINESPEC  CONNECT(STRING (31) S, INTEGER  ACCESS,MAXBYTES,
   PROTECTION, RECORD (RF) NAME  R, INTEGERNAME  FLAG)
SYSTEMROUTINESPEC  OUTFILE(STRING (31) NAME, INTEGER  LENGTH,MAXBYTES,
   PROTECTION, INTEGERNAME  CONAD,FLAG)
SYSTEMINTEGERMAPSPEC  COMREG(INTEGER  I)
!*
!*
!*

CONSTBYTEINTEGERARRAY  ONECASE(0:255) =    0,
   1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16,
  17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
  33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
  49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
  65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
  81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
  65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
  81, 82, 83, 84, 85, 86, 87, 88, 89, 90,123,124,125,126,127,128,
 129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,
 145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,
 161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,
 177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,
 193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,
 209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,
 225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,
 241,242,243,244,245,246,247,248,249,250,251,252,253,254,255

CONSTBYTEINTEGERARRAY  TWOCASE(0:255) =    0,
   1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16,
  17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
  33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
  49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
  65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
  81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
  97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,112,
 113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,
 129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,
 145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,160,
 161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,176,
 177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192,
 193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208,
 209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224,
 225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,
 241,242,243,244,245,246,247,248,249,250,251,252,253,254,255
CONSTSTRING (15)SYSDICTNAME="SUBSYS.EDITDICT"
CONSTSTRING (10) PRIVDICTNAME="E#EDITDICT"
CONSTSTRING (6) ARRAY  PRT(0:2) = C 
"Edit", "Look", "Recall"
CONSTINTEGER  SSCHARFILETYPE = 3
CONSTINTEGER  MAXI = X'02000000';        !MAXIMUM INTEGER ALLOWED
CONSTBYTEINTEGERARRAY  SPS(-2:131) = C 
           NL(2),' '(132)
CONSTBYTEINTEGERARRAY  ROOT(0:2) =      59,78,58
                                         !FOR MESSAGES
INTEGERFNSPEC  ED(INTEGER  EMODE, STRING (63) S)
EXTERNALROUTINE  EDIT(STRING (255) S)
INTEGER  I
STRING (31) S1,S2
STRING (63) HOLDS
CONSTSTRING (9) ARRAY  TERMMESS(1:2) = C 
"completed","abandoned"
      HOLDS = S;                         !FOR TERMINATE MESSAGE
      UNLESS  S->S1.(",").S2 THEN  S = S.",".S
                                         !EDIT(A) BECOMES EDIT(A,A)
      I = ED(0,S)
      IF  1<=I<=2 START 
                                         !STANDARD CLOSE + FULLMESSAGES
         PRINTCH(NL);                    !NEWLINE
         PRINTSTRING("EDIT ".HOLDS."  ".TERMMESS(I))
         PRINTCH(NL);                    !NEWLINE
      FINISH 
      RETURN ;                           !NORMAL RETURN
END ;                                    ! EDIT
EXTERNALROUTINE  LOOK(STRING (255) S)
INTEGER  I
      IF  S="" THEN  S = "T#LIST"
      I = ED(1,S.",.NULL")
      PRINTSTRING("LOOK ".S." finished.".SNL)
END ;                                    ! LOOK
EXTERNALROUTINE  RECALL(STRING (255) S)
INTEGER  FLAG,I
STRING (11) FILE
      GETJOURNAL(FILE,FLAG)
      ->ERR IF  FLAG#0
      I = ED(2,FILE.",.NULL")
ERR:  IF  FLAG#0 THEN  PSYSMES(58,FLAG)
END ;                                    !OF RECALL
INTEGERFN  ED(INTEGER  EMODE, STRING (63) S)
!***********************************************************************
!*     VALUES OF EMODE:   0  =  EDIT                                   *
!*                        1  =  LOOK                                   *
!*                        2  =  RECALL                                 *
!***********************************************************************
RECORDFORMAT  CELL(INTEGER  LL,LP,RP,RL)
ROUTINESPEC  INITIALISE(INTEGERNAME  FLAG)
INTEGERFNSPEC  MAPTXT(INTEGER  I)
ROUTINESPEC  INSERT
INTEGERFNSPEC  FIND
INTEGERFNSPEC  FINDB
ROUTINESPEC  REPLACE
ROUTINESPEC  DELETE
ROUTINESPEC  PRINTTEXT
INTEGERFNSPEC  CHARSON(INTEGER  N)
INTEGERFNSPEC  LINESON(INTEGER  N)
INTEGERFNSPEC  CHARSBACK(INTEGER  N)
INTEGERFNSPEC  LINESBACK(INTEGER  N)
INTEGERFNSPEC  READCSTRING
INTEGERFNSPEC  NEWCELL
ROUTINESPEC  ERMESS(INTEGER  NO,LETT)
INTEGERFNSPEC  RETURNCELL(INTEGER  I)
ROUTINESPEC  RETURNLIST(RECORD (CELL)NAME  ONE,TWO)
ROUTINESPEC  COPY(INTEGER  I)
ROUTINESPEC  EXTENDWORK
INTEGERFNSPEC  READTEXT
INTEGERFNSPEC  READI(INTEGERNAME  N)
ROUTINESPEC  KILLPART
ROUTINESPEC  EXTRACT(INTEGER  ADR)
ROUTINESPEC  FORCLOSE(INTEGER  CLASS,SUBCLASS)
ROUTINESPEC  EXIT(INTEGER  WHY)
ROUTINESPEC  POSITION(INTEGER  I)
ROUTINESPEC  HSAVE
ROUTINESPEC  HRESTORE
INTEGERFNSPEC  NEXT WORD
INTEGERFNSPEC  INIT DICT
ROUTINESPEC  SET HASHES
INTEGERFNSPEC  LOOK UP
STRING (31) ARRAY  FILEUSED(1:20);       !LIST OF FILES USED FOR INPUT
INTEGER  FILEUSEDCOUNT;                  !COUNT OF FILES USED
RECORD (CELL) NAME  TOP,BOT,SET,CUR,BEG,END,TXT,NEW,HTOP,HBOT,HCUR,SCUR
BYTEINTEGER  SLINEL,SLINEST,SPARAST
INTEGER  TOPA,BOTA,SETA,CURP,BEGP,ENDP,TXTP
INTEGER  CADOLD,CADNEW,TMPNEW,NEWG,ASL,WSP,WSE,LEVEL,COMP,I,J,K,NEWNEWF
INTEGER  FLAG,ETERMINATE,CASEIND,HALTERED,ALTERED,HCURP,HSET,BACK,CHANGED,
      NLC,INTSTOP,LINECOMPLETE,LCOMP
BYTEINTEGERARRAYNAME  CASE
LONGINTEGER  SYSDICT,PRIVDICT,TEMPDICT
CONSTBYTEINTEGERARRAY  SPELLCH(0:127)=0(45),0(3),0(10),0(7),
                                        'A','B','C','D','E','F','G','H',
                                        'I','J','K','L','M','N','O','P',
                                        'Q','R','S','T','U','V','W','X',
                                        'Y','Z',0(6),
                                        'A','B','C','D','E','F','G','H',
                                        'I','J','K','L','M','N','O','P',
                                        'Q','R','S','T','U','V','W','X',
                                        'Y','Z',0(5);
CONSTINTEGER  MAXHASH=10
BYTEINTEGERARRAY  WORD(-1:31)
INTEGERARRAY  HASH(0:MAXHASH)
STRING (6) SSOWNER
CONSTSTRING (4) TEMPFILE = "T#EH"
STRING (5) PFN
STRING (15) PRSTRING
STRING (31) NEWPDF,NEWPDM
STRING (63) OLDF,NEWF,CYF
SWITCH  ED(0:31)
RECORD (CELL) ARRAY  LASTREC(0:6)
RECORDFORMAT  CFORM(BYTE  LETT,FLAGS,LEVEL,SWNO,ERRNO,LOOP,HALF  COUNT,
         INTEGER  PAR)
RECORD (CFORM) NAME  CURCOM,LASTCOM
RECORD (RF) RR
RECORD (FRF) EHR
RECORD (CFORM) ARRAY  CLIST(0:99)
!
! VALUES FOR CLIST_FLAGS
!
CONSTINTEGER  BACKWARDS = 1,NUMPAR = 2,TEXTPAR = 4,FILEPAR = 8,ERROR = 128,
   NOTINLOOK = 128,SPECIAL = 64,ALLPAR = NUMPAR!TEXTPAR!FILEPAR, NEEDSS=32,
   STOP SPELL=16

!
! VALUES FOR ARRAY CHARTYPE
!
CONSTINTEGER  NL = 10,COMMAND = 1,TEXTCHAR = 2,NUMCHAR = 3,FILECHAR = 4,
   FILEEND = 5,MINUS = 6,LOOPSTART = 7,LOOPEND = 8,NONNULL = 9,SPACE = 32
!
! VALUES OF ERROR MESSAGES
!
CONSTINTEGER  SYNTAXERROR = 0,INVALIDLOOP = 1,CHINLOOK = 2
!
CONSTBYTEINTEGERARRAY  CHARTYPE(0:127) = 0(10),NL,0(14),NL,0(6),
                  SPACE,NONNULL(6),{!,",#,$,%,&}
                  TEXTCHAR,{'} LOOPSTART,{(} LOOPEND,{)}
                  NUMCHAR(2),{*+} NONNULL,{,} MINUS,
                  TEXTCHAR(2),{.,/} NUMCHAR(10),{0-9}
                  NONNULL(2),{:;} FILECHAR,{<} NONNULL,{=} FILEEND,{>}
                  TEXTCHAR,{?}
                  NONNULL,{@} COMMAND(9),{A-I}
                  COMMAND,{J - JUSTIFY}
                  COMMAND,{K}
                  COMMAND,{L - LAYOUT}
                  COMMAND(2),{MN}
                  COMMAND(7),{O-U} NONNULL,{V}
                  COMMAND(3){WXY},
                  COMMAND{Z},NONNULL(5),
                  NONNULL,{@} COMMAND(9),{A-I}
                  COMMAND,{J - JUSTIFY}
                  COMMAND,{K}
                  NONNULL,{L -RESERVED FOR LAYOUT}
                  COMMAND(2),{MN}
                  COMMAND(7),{O-U} NONNULL,{V}
                  COMMAND(3){WXY},
                  COMMAND{Z},NONNULL(4),
                  0{ERASE}

!
! COMMAND DEFINITION IS  SW FOR NO OR NUMBERPARAM<<24!SW FOR TEXT<<16
!                 ! LASTREC POINTER<<12! FLAG BITS
!
CONSTINTEGERARRAY  COMDEF('A':'Z') = C 
            {A} 8<<24!7<<16!0<<12!ALLPAR!BACKWARDS!STOP SPELL,
            {B} 2<<24!STOP SPELL,
            {C} NUMPAR!SPECIAL,
            {D} 12<<24!11<<16!1<<12!ALLPAR!BACKWARDS!NOTINLOOK!STOP SPELL,
            {E} 3<<24,
            {F} 24<<16!FILEPAR,
            {G} 23<<24!NUMPAR!NOTINLOOK!STOP SPELL,
            {H} 18<<24!SPECIAL!STOP SPELL,
            {I} 4<<16!2<<12!FILEPAR!TEXTPAR!NOTINLOOK!STOP SPELL,
            {J} 28<<24!NUMPAR!NOTINLOOK!STOP SPELL,
            {K} 17<<24!NEEDSS!STOP SPELL,
            {L} 27<<24!NUMPAR!NOTINLOOK!STOP SPELL,
            {M} 6<<24!5<<16!3<<12!ALLPAR!BACKWARDS!STOP SPELL,
            {N} 31<<24,
            {O} 21<<24!NEEDSS!STOP SPELL,
            {P} 10<<24!9<<16!4<<12!ALLPAR!BACKWARDS,
            {Q} 15<<24,
            {R} 14<<24!13<<16!5<<12!ALLPAR!BACKWARDS!NOTINLOOK!STOP SPELL,
            {S} 16<<24,
            {T} 1<<24!STOP SPELL,
            {U} 20<<24!19<<16!6<<12!ALLPAR!BACKWARDS!NOTINLOOK!NEEDSS!STOP SPELL,
            {V} -1,
            {W} 25<<24!NOTINLOOK!STOP SPELL,
            {X} 29<<24,
            {Y} 30<<24,
            {Z} 26<<24
ON  EVENT  12 START ;               ! EVENT 12 FOR FRCED ENDING
      RESULT =2
FINISH 
INTEGERFN  NEWCELL
!***********************************************************************
!*                                                                     *
!* NEWCELL                                                             *
!* THIS FUNCTION RETURNS THE ADDRESS OF A NEW, EMPTY CELL. ASL         *
!* CONTAINS THE ADDRESS OF THE NEXT CELL TO BE USED AND IF IT IS       *
!* ZERO MEANS THAT MORE SPACE IS NEEDED. SPACE IS OBTAINED FROM THE    *
!* WORKFILE IN 1 PAGE UNITS (256 CELLS) AND IF EXTEND WORK FAILS       *
!* THEN AN EDIT:E IS INVOKED. THIS IS NOT LIKELY TO OCCUR VERY         *
!* OFTEN.                                                              *
!*                                                                     *
!***********************************************************************
INTEGER  I,J,K
RECORD (CELL) NAME  CLEAR
      I = ASL
      IF  I=0 START ;                    !GET SOME MORE SPACE
         I = (WSP+3)&X'FFFFFFFC';        !WORD ALIGN
         J = I+4096
         IF  J>WSE THEN  EXTENDWORK;     ! ABANDON IF NO ROOM LEFT
                                         ! **** Causes immediate exit
         WSP = J
         K = 0
         WHILE  J>I CYCLE ;              !ALL BUT LAST RECORD
            J = J-16
            INTEGER(J) = K;              !EACH CELL POINTS TO NEXT
            K = J
         REPEAT 
      FINISH 
      ASL = INTEGER(I);                  !ASL POINTS TO NEXT ONE
      CLEAR == RECORD(I)
      CLEAR = 0;                         !CLEAR THE CELL
      RESULT  = I
END ;                                    !OF NEWCELL
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ROUTINE  RETURNLIST(RECORD (CELL)NAME  ONE,TWO)
RECORD (CELL)NAME  WORK
INTEGER  I
      WORK==ONE
      WHILE  WORK¬== TWO CYCLE 
         I=WORK_RL
         MONITOR  AND  EXIT  IF  I=0
         WORK==RECORD(RETURNCELL(ADDR(WORK)))
         REPEAT 
END 
INTEGERFN  RETURNCELL(INTEGER  I)
      INTEGER(I) = ASL
      ASL = I
      RESULT  = INTEGER(I+12)
END ;                                    !OF RETURN CELL
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
INTEGERFN  READTEXT
INTEGER  MARKER,CHAR,SKIPPEDCH
      SKIPSYMBOL WHILE  NEXTSYMBOL<=' '
      IF  NEXTSYMBOL='<' THENSTART 
         MARKER = '>'; CHAR = 0
      FINISHELSESTART 
         READSYMBOL(MARKER)
         RESULT  = 0 UNLESS  MARKER='.' OR  MARKER='/' OR  MARKER='?'
                                         ! %RESULT = 0 if no text found.
         CHAR = NEXTCH
         IF  CHAR=MARKER THENSTART 
            READCH(SKIPPEDCH)
            IF  NEXTCH#MARKER THENRESULT  = 0
         FINISH 
      FINISH 
      PROMPT(TOSTRING(MARKER).":")
      TXT == RECORD(NEWCELL)
      TXT_LL = 0
      TXT_LP = WSP
      UNTIL  CHAR#MARKER CYCLE 
         READCH(SKIPPEDCH)
         UNTIL  CHAR=MARKER CYCLE 
            IF  WSP=WSE THEN  EXTENDWORK; ! FORCE EDIT:E IF FAIL
                                         ! **** Causes immediate exit
            BYTEINTEGER(WSP) = CHAR
            WSP = WSP+1
            READCH(CHAR) UNTIL  MARKER#'>' OR (CHAR#NL AND  CHAR#' ')
         REPEAT 
         CHAR = NEXTCH
      REPEAT 
      TXT_RP = WSP-1
      TXT_RL = 0
      IF  LEVEL=0 THEN  PROMPT(PRSTRING) ELSE  PROMPT("):")
      RESULT  = 1
END ;                                    !READ TEXT
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
INTEGERFN  READI(INTEGERNAME  N)
INTEGER  J,I,SIGN,K
      READSYMBOL(I) UNTIL  I>' '
      IF  I='-' THEN  SIGN = -1 ELSE  SIGN = +1
      UNLESS  '-'#I#'+' THEN  READSYMBOL(I)
      IF  I='*' THENSTART 
         J = 1
         K = MAXI
      FINISHELSESTART 
         J = 0
         K = 0
         WHILE  '0'<=I<='9' CYCLE 
            K = 10*K+I-'0'
            IF  K>=MAXI THEN  RESULT =0
                                         ! You aren't allowed to specify +/- MAXI as a literal.  MAXI
                                         ! is used internally to stand for '*'.
            IF  J#0 THEN  SKIPSYMBOL ELSE  J = 1
            I = NEXTSYMBOL
            SKIP SYMBOL AND  I =NEXT SYMBOL WHILE  I=' '
         REPEAT 
      FINISH 
      N = K*SIGN
      RESULT  = J
END ;                                    !OF READ I
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
INTEGERFN  MAPTXT(INTEGER  ADR)
STRING (31) OWNER,REST
STRING (31) FILE
INTEGER  HOLE,FLAG,I,D,Q
      ADR = IMOD(ADR);                   !MOVE BACK HELD AS -ADDRESS
      TXT == RECORD(ADR)
      D = TXT_LP
      Q = BYTEINTEGER(D)
      IF  Q=0 THENSTART 
                                         ! If the leftmost byte is zero, the following bytes are assumed
                                         ! to be a file name.
         Q = TXT_RP-D;                   ! This is the length of the file name.
         IF  Q>31 THEN  Q = 31
         BYTEINTEGER(D) = Q
         FILE = STRING(D)
         IF  FILE=NEWF THENSTART 
            FLAG = 266
            ->ERR
         FINISH 
         IF  FILE=OLDF THEN  HOLE = CADOLD ELSESTART 
            CONNECT(FILE,0,0,0,RR,FLAG)
            IF  FLAG#0 THEN  ->ERR;      ! OPEN FAILS
            UNLESS  RR_FILETYPE=3 THENSTART ; ! INVALID FILE TYPE
               FLAG = 267
               SETFNAME(FILE)
               ->ERR
            FINISH 
            HOLE = RR_CONAD
                                         ! STANDARDISE FILENAME
            UNLESS  FILE->OWNER.(".").REST THEN  FILE = SSOWNER.".".FILE
            I = 1
            WHILE  I<=FILEUSEDCOUNT AND  FILEUSED(I)#FILE CYCLE 
               I = I+1
            REPEAT 
                                         ! ADD NAME TO LIST (DON'T BOTHER BEYOND 20 - NOT LIKELY)
            IF  FILEUSEDCOUNT<I<=20 THENSTART 
               FILEUSEDCOUNT = I
               UCTRANSLATE(ADDR(FILE)+1,LENGTH(FILE))
               FILEUSED(I) = FILE
            FINISH 
         FINISH 
         BYTEINTEGER(D) = 0;             !FOR RE-USE
         D = HOLE+INTEGER(HOLE+4)
         TXT_LP = D
         TXT_RP = HOLE+INTEGER(HOLE)-1
      FINISH 
      RESULT  = 0 IF  TXT_RP<D
      RESULT  = 1
ERR:  PSYSMES(31,FLAG);                  !OPEN FAILS
      RESULT  = 0;                       !FAILURE
END ;                                    !OF MAP TXT
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ROUTINE  SEPARATE
!***********************************************************************
!*                                                                     *
!* SEPARATE                                                            *
!* CREATE A NEW CELL WHICH STARTS AT CUR_LP AND ENDS AT CURP-1.        *
!* ALSO ALTER CURRENT CELL TO START AT CURP                            *
!*                                                                     *
!***********************************************************************
      NEW == RECORD(NEWCELL)
      INTEGER(CUR_LL+12) = ADDR(NEW_LL)
      NEW_LL = CUR_LL
      NEW_LP = CUR_LP
      NEW_RP = CURP-1
      CUR_LP = CURP
      CUR_LL = ADDR(NEW_LL)
      NEW_RL = ADDR(CUR_LL)
      ALTERED=ALTERED+1;                ! LIST ALTERED SINCE "HSAVE"
END ;                                    !OF SEPARATE

ROUTINE  HSAVE
!***********************************************************************
!*    SAVE THE CURRENT STATE OF THE FILE BY COPYING THE LINKED LIST    *
!*    THE COPY IS SKIPPED IF THE LIST HAS NOT BEEN ALTERED SINCE       *
!*    THE LAST CALL OF HSAVE                                           *
!***********************************************************************
INTEGER  I,J
RECORD (CELL)NAME  WORK,LAST,COPY
      IF  HALTERED<ALTERED START ;      ! LIST ALTERED SINCE LAST COPY
      RETURN LIST(RECORD(HTOP_RL),HBOT); ! LEAVING HTOP&HBOT
!
! NOW FORM A COPY OF THE LIST
!
         I=TOP_RL; LAST==HTOP
         CYCLE 
            COPY==RECORD(I);            ! CELL TO BE COPIED
            EXIT  IF  COPY==BOT;        ! LIST END REACHED
            J=NEWCELL; LAST_RL=J;       ! NEWCELL LINKED IN
            WORK==RECORD(J)
            WORK_LL=ADDR(LAST)
            WORK_LP=COPY_LP
            WORK_RP=COPY_RP
            I=COPY_RL
            IF  COPY==CUR THEN  HCUR==WORK AND  SCUR==CUR AND  HCURP=CURP
            LAST==WORK
         REPEAT 
         IF  CUR==BOT THEN  HCUR==HBOT AND  SCUR==CUR AND  HCURP=CURP
         HBOT_LL=ADDR(LAST)
         LAST_RL=ADDR(HBOT)
         HALTERED=ALTERED
         RETURN 
      FINISH 
!
! LIST NOT ALTERED BUT CURSER MAY HAVE MOVED. IF CURSER NOT THE SAME
! CELL AS WHEN COPY MADE(CUR##SCUR) A FULL SEARCH IS NEEDED. REMEMBER
! THAT MULTIPLE INSERTS OF THE SAME PIECE OF TEXT CAN RESULT IN MULTIPLE
! IDENTICAL CELLS!
!
      IF  SCUR¬==CUR THEN  START ;      ! IN A DIFFERENT CELL
         COPY==TOP
         WORK==HTOP
         CYCLE 
            EXIT  IF  COPY==CUR
            COPY==RECORD(COPY_RL)
            WORK==RECORD(WORK_RL)
         REPEAT 
         HCUR==WORK
         SCUR==CUR
      FINISH 
      HCURP=CURP
END 
ROUTINE  HRESTORE
!***********************************************************************
!*    RESTORE FILE TO STATE IT WAS WHEN HSAVE WAS LAST CALLED          *
!***********************************************************************
INTEGER  I,J
RECORD (CELL)NAME  WORK,LAST,COPY
      SETA=0;                           ! KILL OLD SEPERATOR
      RETURN LIST(RECORD(TOP_RL),BOT);   ! LEAVING TOP&BOT
!
      LAST==TOP
      I=HTOP_RL
      CYCLE 
         COPY==RECORD(I);               ! CELL FROM SAVED LIST
         EXIT  IF  COPY==HBOT
         J=NEWCELL
         LAST_RL=J
         WORK==RECORD(J)
         WORK_LL=ADDR(LAST)
         WORK_LP=COPY_LP
         WORK_RP=COPY_RP
         I=COPY_RL
         IF  WORK_LP=WORK_RP=0 THEN  SET==WORK AND  SETA=J
         IF  COPY==HCUR THEN  CUR==WORK AND  SCUR==WORK AND  CURP=HCURP
         LAST==WORK
      REPEAT 
      IF  HCUR==HBOT THEN  CUR==BOT AND  SCUR==BOT AND  CURP=HCURP
      LAST_RL=BOTA
      BOT_LL=ADDR(LAST)
      ALTERED=HALTERED
END 
ROUTINE  INSERT
!***********************************************************************
!*                                                                     *
!* INSERT                                                              *
!* LINKS TXT INTO FILE AT CURP MAKING ADDITIONAL CELL IF NEC BY        *
!* CALL OF SEPARATE. NO REPLY                                          *
!*                                                                     *
!***********************************************************************
INTEGER  NEW,PREVIOUS,AC
      UNLESS  TXT_LP=TXT_RP=0 THEN  CHANGED = 1; !IF NOT JUST *S* TO INDICATE CHANGE MADE
         ALTERED=ALTERED+1;             ! LIST ALTERED SINCE "HSAVE"
      IF  CURP#CUR_LP THEN  SEPARATE
      AC = ADDR(CUR_LL)
      PREVIOUS = INTEGER(AC)
      NEW = ADDR(TXT_LL)
      INTEGER(AC) = NEW
      INTEGER(PREVIOUS+12) = NEW
      INTEGER(NEW) = PREVIOUS
      INTEGER(NEW+12) = AC
END ;                                    !OF INSERT
!%INTEGERFN FIND
!%INTEGER I
!         BEG==CUR
!         BEGP=CURP
!         I=BYTE INTEGER(TXT_LP)
!L3:       %IF BEGP=0 %THEN %RESULT=0
!L2:       %IF BYTE INTEGER(BEGP)=I %THEN ->L1
!L6:       BEGP=BEGP+1
!         ->L2 %UNLESS BEGP>BEG_RP
!         BEG==RECORD(BEG_RL)
!         BEGP=BEG_LP
!         ->L3
!L1:       END==BEG
!         ENDP=BEGP
!         TXTP=TXT_LP
!L5:       ENDP=ENDP+1
!         ->L4 %UNLESS ENDP>END_RP
!         END==RECORD(END_RL)
!         ENDP=END_LP
!L4:       %IF TXTP=TXT_RP %THEN %RESULT=1
!         TXTP=TXTP+1
!         %IF ENDP=0 %THEN %START
!             BEG==END
!             BEGP=0
!             %RESULT=0
!         %FINISH
!         %IF BYTE INTEGER(ENDP)=BYTE INTEGER(TXTP) %THEN ->L5
!         ->L6
!%END
!OF FIND
INTEGERFN  FIND
!***********************************************************************
!*                                                                     *
!* FIND                                                                *
!* THIS FUNCTION IS CALLED BY MANY COMMANDS TO FIND TEXT DEFINED BY    *
!* TXT IT SETS BEG AND BEGP TO THE START OF THE TEXT AND END AND       *
!* ENDP TO THE END OF THE TEXT. IF THE TEXT IS NOT FOUND THEN BEG      *
!* AND BEGP ARE LEFT POINTING AT *S* OR *B* AS APPROPRIATE             *
!* THE FUNCTION USES THE MACHINE CODE INSTRUCTIONS SWNE AND CPS.       *
!* SWNE IS USED TO FIND THE FIRST CHARACTER OF THE REQUESTED TEXT.     *
!* IF THERE IS ENOUGH ROOM IN THE CURRENT RECORD THEN CPS IS USED      *
!* TO TEST FOR THE REST OF THE TEXT. IF NOT THEN FOR SIMPLICITY AN     *
!* IMP VERSION IS USED.                                                *
!* ALL IMP VERSIONS SHOULD EXCHANGE THE ALL IMP VERSION OF FIND FOR    *
!* THIS ONE                                                            *
!*                                                                     *
!***********************************************************************
INTEGER  LENB,TLEN,FIRST,TLP,B
INTEGER  DR0,DR1,ACC0,ACC1;              !DR0-DR1 AND ACC0-ACC1 MUST STAY AS PAIRS
      BEG == CUR
      BEGP = CURP
      TLP = TXT_LP;                      !ADDR OF START OF TEXT
      TLEN = TXT_RP-TLP+1;               !NO OF CHAS TO BE TESTED
      FIRST = BYTEINTEGER(TLP);          !FIRST CHAR TO BE FOUND
START:IF  BEGP=0 THENRESULT  = 0;        !HIT *B* OR *S*
AGAIN:LENB = BEG_RP-BEGP+1;              !NUMBER LEFT IN CURRENT RECORD
                                         !LOOK FOR FIRST CHARACTER
                                         !SWNE INS REQUIRES B REGISTER TO CONTAIN MASK IN BITS 16-23
                                         !AND REF BYTE IN BITS 24-31. DR MUST CONTAIN A DESCRIPTOR
                                         !TO THE STRING TO BE SEARCHED
      B = (32*CASEIND)<<8!FIRST;         !MASK<<8 ! TEST CHAR
      DR0 = X'58000000'!LENB;            !STRING DESCRIPTOR
      DR1 = BEGP;                        !ADDRESS OF STRING
      *LB_B;                             !LOAD B REGISTER
      *LD_DR0;                           !LOAD DESCRIPTOR REGISTER
      *SWNE_ L = DR 
                                         !CONDITION CODE NOW SET AS FOLLOWS
                                         !0 REF BYTE NOT FOUND
                                         !1 REF BYTE FOUND - ADDRESS IN BOTTOM OF DR
      *JCC_8,<FIRSTNOTFOUND>;            !JUMP IF NOT FOUND
      *STD_DR0;                          !STORE DESCRIPTOR REGISTER
      BEGP = DR1;                        !POSSIBLE FIRST BYTE
                                         !NOW DEAL WITH SINGLE CHARACTER SEARCH
      IF  CASEIND#0 THEN  ->IMP1
      IF  TLEN=1 THEN  ->FOUND;          !FIRST AND ONLY CHARACTER MATCHED OK
                                         !NOW NEED TO COMPARE REST OF TEXT
                                         !IF ENOUGH TEXT IN CURRENT SECTION USE CPS INSTRUCTION ELSE
                                         !USE IMP VERSION
      IF  BEG_RP-BEGP+1<TLEN THEN  ->IMP1
                                         !JUMP IF TOO LONG
                                         !CPS(COMPARE STRINGS) INSTRUCTION REQUIRES DESCRIPTORS TO TWO
                                         !STRINGS IN DR AND ACC
      DR0 = X'58000000'!(TLEN-1);        !NO NEED TO TEST FIRST CHAR AGAIN
      DR1 = TLP+1;                       !START OF STRING TO BE TESTED
      ACC0 = DR0
      ACC1 = BEGP+1;                     !POSSIBLE SECOND CHARACTER
      *LD_DR0;                           !LOAD DESCRIPTOR REGISTER
      *LSD_ACC0;                         !SET ACS TO 64 AND LOAD
      *PUT_X'A500'
                                         !*CPS_X'100' COMPARE STRINGS
                                         !CONDITION CODE NOW 0 IF STRINGS EQUAL
      *JCC_8,<FOUND>;                    !JUMP IF EQUAL
                                         !INCREMENT BEGP AND TRY ALL OVER AGAIN
      BEGP = BEGP+1;                     !CANNOT HIT END OF SEGMENT BECAUSE STRING CONTAINS AT LEAST 2 CHAS
      ->AGAIN;                           !TRY AGAIN
FOUND:                                   !THIS IS EXIT FOR SIMPLE CASE WHERE ALL TEXT IN ONE SEGMENT
      END == BEG
      ENDP = BEGP+TLEN
      IF  ENDP>END_RP THENSTART ;        ! END OF TEXT EXACTLY AT END OF SEGMENT
         END == RECORD(END_RL)
         ENDP = END_LP
      FINISH 
      TXTP = TXT_RP;                     !WHY?
      RESULT  = 1;                       !SUCCESS
FIRSTNOTFOUND:                           !NEED TO GET NEXT BLOCK
      BEG == RECORD(BEG_RL)
      BEGP = BEG_LP
      ->START;                           !TO INCLUDE CHECK FOR *B* AND *S*
IMP1: END == BEG
      ENDP = BEGP
      TXTP = TXT_LP
      CYCLE 
         IF  CASE(BYTEINTEGER(ENDP))#CASE(BYTEINTEGER(TXTP)) THENEXIT 
         ENDP = ENDP+1
         IF  ENDP>END_RP START 
            END == RECORD(END_RL)
            ENDP = END_LP
         FINISH 
         IF  TXTP=TXT_RP THENRESULT  = 1
                                         !SUCCESS
         TXTP = TXTP+1
         IF  ENDP=0 START ;              !HIT *B* OR *S*
            BEG == END
            BEGP = 0
            RESULT  = 0;                 !NOT FOUND
         FINISH 
      REPEAT 
      BEGP = BEGP+1
      IF  BEGP>BEG_RP START 
         BEG == RECORD(BEG_RL)
         BEGP = BEG_LP
         ->START;                        !TRY ALL OVER AGAIN
      FINISH 
      ->AGAIN
END ;                                    !OF FIND
INTEGERFN  FINDB
!***********************************************************************
!*                                                                     *
!* FINDB                                                               *
!* MOVE BACK FROM CURRENT POSITION TO TEXT. IF O.K. LEAVE END AND      *
!* ENDP AT END OF TEXT AND BEG AND BEGP AT START OF TEXT. IF NOT       *
!* RESULT=0 AND END,ENDP,BEG AND BEGP ALL AT *T* OR *S*                *
!*                                                                     *
!***********************************************************************
INTEGER  LAST
      END == CUR
      ENDP = CURP
      LAST = CASE(BYTEINTEGER(TXT_RP));  ! LAST CHARACTER TO BE FOUND
      CYCLE 
         UNTIL  CASE(BYTEINTEGER(ENDP))=LAST CYCLE 
            IF  ENDP=END_LP START 
               IF  INTEGER(END_LL+8)=0 START ; !HIT *T* OR *S*
                  BEG == END
                  BEGP = ENDP
                  RESULT  = 0
               FINISH 
               END == RECORD(END_LL)
               ENDP = END_RP
            FINISHELSE  ENDP = ENDP-1
         REPEAT 
         BEG == END
         BEGP = ENDP
         TXTP = TXT_RP;                  ! LAST CHAR OF REQUIRED TEXT
         UNTIL  CASE(BYTEINTEGER(TXTP))#CASE(BYTEINTEGER(BEGP)) CYCLE 
            IF  TXTP<=TXT_LP THENSTART 
                                         ! GOT HERE SO TEXT MATCHES. MOVE ENDP FORWARD 1 CHAR
               ENDP = ENDP+1
               IF  ENDP>END_RP START ;   !OFF END OF CELL
                  END == RECORD(END_RL)
                  ENDP = END_LP
               FINISH 
               RESULT  = 1;              !SUCCESS
            FINISH 
            BEGP = BEGP-1
            IF  BEGP<BEG_LP THENSTART 
               IF  INTEGER(BEG_LL+8)=0 THENSTART ; ! *T* OR *S*
                  BEGP = BEG_LP
                  RESULT  = 0
               FINISH 
               BEG == RECORD(BEG_LL)
               BEGP = BEG_RP
            FINISH 
            TXTP = TXTP-1
                                         ! NO GOOD - TRY AGAIN
         REPEAT 
      REPEAT 
END ;                                    !OF FINDB
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ROUTINE  DELETE
!***********************************************************************
!*                                                                     *
!* DELETE                                                              *
!* DELETES TEXT FROM BEGP TO ENDP. NO REPLY.                           *
!* The character at BEGP is deleted, but the character at ENDP is not. *
!*                                                                     *
!***********************************************************************
INTEGER  I
      CHANGED = 1;                       !TO INDICATE CHANGE MADE
         ALTERED=ALTERED+1;             ! LIST ALTERED SINCE "HSAVE"
      IF  ADDR(BEG_LL)=ADDR(END_LL) THENSTART 
         IF  BEGP=ENDP THENRETURN 
         IF  BEGP=BEG_LP THENSTART 
            BEG_LP = ENDP
         FINISHELSESTART 
            END == RECORD(NEWCELL)
            END_RL = BEG_RL
            INTEGER(END_RL) = ADDR(END_LL)
            END_RP = BEG_RP
            END_LP = ENDP
            END_LL = ADDR(BEG_LL)
            BEG_RL = ADDR(END_LL)
            BEG_RP = BEGP-1
         FINISH 
      FINISHELSESTART 
         I = BEG_RL
         WHILE  I#ADDR(END_LL) CYCLE 
            I = RETURNCELL(I)
         REPEAT 
                                         ! I is equal to ADDR (END_LL) at this point
         BEG_RL = I
         END_LL = ADDR(BEG_LL)
         END_LP = ENDP
         IF  BEGP=BEG_LP THENSTART 
            END_LL = BEG_LL
            UNLESS  END_LL=0 THEN  INTEGER(END_LL+12) = I
            I = RETURNCELL(ADDR(BEG_LL))
         FINISHELSESTART 
            BEG_RP = BEGP-1
         FINISH 
      FINISH 
      CUR == END
      CURP = ENDP
END ;                                    !OF DELETE
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ROUTINE  PRINTTEXT
INTEGER  I,J
      J = 0
      IF  BEGP=BEG_LP THENSTART 
         IF  BEG_LL=TOPA THEN  PRINTSTRING("*T*".SNL)
         IF  BEG_LL=SETA THEN  PRINTSTRING("*S*".SNL)
      FINISH 
      CYCLE 
         IF  BEGP=CURP AND  ADDR(BEG_LL)=ADDR(CUR_LL) THEN  PRINTCH(94)
         IF  BEGP=ENDP AND  ADDR(BEG_LL)=ADDR(END_LL) THENSTART 
            IF  BEGP=0 THENSTART 
               IF  ADDR(BEG_LL)=SETA THEN  PRINTSTRING("*S*".SNL)
               IF  ADDR(BEG_LL)=BOTA THEN  PRINTSTRING("*B*".SNL)
            FINISH 
            RETURN 
         FINISH 
         I = BYTEINTEGER(BEGP)
         PRINTCH(I)
         IF  I=NL START 
            NLC = NLC+1
                                         ! CHECK ON LINES 4,8,12 ETC
            IF  NLC&3=0 AND  UCSTRING(INTERRUPT)="STOP" THENSTART 
               INTSTOP = 1
               RETURN 
            FINISH 
         FINISH 
         BEGP = BEGP+1
         IF  BEGP>BEG_RP START 
            BEG == RECORD(BEG_RL)
            BEGP = BEG_LP
         FINISH 
      REPEAT 
END ;                                    !OF PRINT TEXT
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
INTEGERFN  CHARSON(INTEGER  N)
INTEGER  LEN
      END == CUR
      ENDP = CURP
      WHILE  ENDP#0 CYCLE 
         LEN = END_RP-ENDP;              !LENGTH LEFT IN THIS CELL
         IF  N<=LEN START ;              !NEW POSITION IS IN THIS CELL
            ENDP = ENDP+N
            RESULT  = 1;                 !FOUND OK
         FINISH ;                        !TRY NEXT CELL
         N = N-(LEN+1);                  !DECREMENT BY CHAS LEFT +CURRENT ONE
         END == RECORD(END_RL)
         ENDP = END_LP
         IF  N=0 THENRESULT  = 1;        !HIT *S* OR *B* EXACTLY
      REPEAT 
      RESULT  = 0;                       !HIT *B* OR *S*
END ;                                    !OF CHARS ON
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!         %INTEGERFN LINES ON(%INTEGER N)
!         %INTEGER I
!            END == CUR
!            ENDP = CURP
!            I = 0
!L1:         %IF I = N %THEN %RESULT = 1
!            %IF ENDP = 0 %THEN %RESULT = 0
!            %IF BYTE INTEGER(ENDP) = NL %THEN I = I+1
!            ENDP = ENDP+1
!            -> L1 %UNLESS ENDP > END_RP
!            END == RECORD(END_RL)
!            ENDP = END_LP
!            -> L1
!         %END
                                         !OF LINES ON
INTEGERFN  LINESON(INTEGER  COUNT)
!***********************************************************************
!*                                                                     *
!* LINESON                                                             *
!* MOVES END AND ENDP FORWARD FROM CUR AND CURP UNTIL POSITIONED       *
!* AFTER COUNT NEWLINE CHAS. USES CHARSON IF PARAMETER WAS '*'.        *
!* OTHERWISE USES SWNE(SCAN WHILE NOT EQUAL)INSTRUCTION TO LOCATE      *
!* EACH NL CHARACTER                                                   *
!*                                                                     *
!***********************************************************************
INTEGER  LENE;                           !COUNT OF CHAS LEFT IN CURRENT SECTION
INTEGER  B,DR0,DR1;                      !DR0 AND DR1 MUST STAY TOGETHER
      IF  COUNT=MAXI THENRESULT  = CHARSON(COUNT)
                                         !QUICKER TO USE CHARSON
      END == CUR
      ENDP = CURP
AGAIN:IF  ENDP=0 THENRESULT  = 0;        !HIT *B* OR *S* BEFORE ENOUGH NLS
      LENE = END_RP-ENDP+1;              !CHAS LEFT IN CURRENT SECTION
      B = X'000A';                       !MASK<<8 ! REF CHARACTER
      DR0 = X'58000000'!LENE;            !TYPE AND BOUND
      DR1 = ENDP;                        !START OF SCAN AREA
      *LB_B;                             !LOAD B REGISTER
      *LD_DR0;                           !LOAD DESCRIPTOR REGISTER
      *PUT_X'A300';                      !SWNE_X'100' - SKIP WHILE NOT EQUAL - USING LENGTH FROM DR
                                         !CONDITION CODE NOW CONTAINS 0 IF CHARACTER NOT FOUND
      *JCC_8,<NEXTSECT>;                 !GET NEXT SECTION
                                         !DR NOW CONTAINS POINTER TO FIRST NL CHAR FOUND
      *STD_DR0;                          !PUT DR BACK IN DR0-DR1
      ENDP = DR1+1;                      !POINTS TO ONE BYTE AFTER NL
      IF  ENDP>END_RP START 
         END == RECORD(END_RL)
         ENDP = END_LP
      FINISH 
      COUNT = COUNT-1
      IF  COUNT=0 THENRESULT  = 1;       !SUCCESSFUL
      ->AGAIN
NEXTSECT:END == RECORD(END_RL)
      ENDP = END_LP
      ->AGAIN
END ;                                    !OF LINESON
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
INTEGERFN  CHARSBACK(INTEGER  N)
INTEGER  LEN
      BEG == CUR
      BEGP = CURP
      CYCLE 
         LEN = BEGP-BEG_LP;              !LENGTH LEFT IN THIS CELL
         IF  LEN-N>=0 START ;            !N IS NEGATIVE
            BEGP = BEGP-N
            RESULT  = 1
         FINISH 
         BEGP = BEG_LP;                  !POINT TO START OF CELL
         N = N-(LEN+1);                  ! ALL THIS CELL AND LAST CHAR OF NEXT CE
         IF  INTEGER(BEG_LL+8)=0 THENRESULT  = 0
!*T* OR *S*
         BEG == RECORD(BEG_LL);          !THE NEXT CELL
         BEGP = BEG_RP;                  !POINT TO LAST BYTE IN IT
      REPEAT 
END ;                                    !OF CHARS BACK
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
INTEGERFN  LINESBACK(INTEGER  N)
INTEGER  I
      IF  N=MAXI THENRESULT  = CHARSBACK(N)
                                         !QUICKER TO USE CHARS BACK
      BEG == CUR
      BEGP = CURP
      I = -1
      UNTIL  I=N CYCLE 
         IF  BEGP=BEG_LP THENSTART 
            IF  INTEGER(BEG_LL+8)=0 THENSTART 
               IF  I=N-1 THENRESULT  = 1 ELSERESULT  = 0
            FINISH 
            BEG == RECORD(BEG_LL)
            BEGP = BEG_RP
         FINISHELSE  BEGP = BEGP-1
         IF  BYTEINTEGER(BEGP)=NL THEN  I = I+1
      REPEAT 
      BEGP = BEGP+1
      IF  BEGP>BEG_RP THENSTART 
         BEG == RECORD(BEG_RL)
         BEGP = BEG_LP
      FINISH 
      RESULT  = 1
END ;                                    !OF LINES BACK
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ROUTINE  POSITION(INTEGER  N)
INTEGER  I
      N = N-1;                           !POINT TO BEFORE CHARACTER N
      IF  N<0 THEN  N = 0
      IF  N>132 THEN  N = 132
      I = LINESBACK(0);                  ! START OF CURRENT LINE
      I = 0;                             ! POSITION IN LINE
      CYCLE 
         IF  I=N THENSTART 
            CUR == BEG
            CURP = BEGP
            RETURN 
         FINISH 
         IF  BEGP=0 OR  BYTEINTEGER(BEGP)=NL THENSTART 
            IF  BEGP#0 THENSTART 
               END == BEG
               ENDP = BEGP+1
               IF  ENDP>END_RP THENSTART 
                  END == RECORD(END_RL)
                  ENDP = END_LP
               FINISH 
            FINISH 
            CUR == BEG
            CURP = BEGP
            TXT == RECORD(NEWCELL)
            TXT_LL = 0
            TXT_LP = ADDR(SPS(0))
            TXT_RP = TXT_LP+N-I-1
            TXT_RL = 0
            INSERT
            RETURN 
         FINISH 
         BEGP = BEGP+1
         I = I+1
         IF  BEGP>BEG_RP THENSTART 
            BEG == RECORD(BEG_RL)
            BEGP = BEG_LP
         FINISH 
      REPEAT 
END ;                                    ! POSITION
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ROUTINE  KILLPART
INTEGER  DUMMY
      ALTERED=ALTERED+1;             ! LIST ALTERED SINCE "HSAVE"
      INTEGER(SET_LL+12) = SET_RL;       !POINT RL OF LOWER CELL TO HIGHER CELL
      INTEGER(SET_RL) = SET_LL;          !POINT LL OF UPPER CELL TO LOWER CELL
      IF  ADDR(CUR_LL)=SETA THENSTART ;  !IF CURSOR POSITIONED AFTER *S* THEN CORRECT IT
         CUR == RECORD(CUR_RL)
         CURP = CUR_LP
      FINISH 
      DUMMY = RETURNCELL(SETA);          !FREE SET CELL - IGNORE RESULT
      SETA = 0
END ;                                    !OF KILL PART
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ROUTINE  EXTRACT(INTEGER  ADR)
!THIS PUTS TEXT FROM POINTER TO *S* OR *B*
!INTO FILE <FILENAME>
!BEFORE OUTPUTTING TO A FILE IT CHECKS THAT THE FILE HAS NOT BEEN
!USED SO FAR DURING THIS EDIT SESSION FOR INPUT.
STRING (16) DEVICE
STRING (31) FILE,OWNER,REST
INTEGER  I,FLAG,COUNT,CONAD,L,MOD
      RETURNIF  CURP=0;                  !ALREADY AT *B* OR *S*
      TXT == RECORD(ADR)
      BYTEINTEGER(TXT_LP) = TXT_RP-TXT_LP
      FILE = STRING(TXT_LP)
      UCTRANSLATE(ADDR(FILE)+1,LENGTH(FILE))
      IF  FILE->FILE.("-MOD") THEN  MOD = 1 ELSE  MOD = 0
      IF  CHARNO(FILE,1)#'.' START ;     !MUST BE A FILENAME
         UNLESS  FILE->OWNER.(".").REST THEN  FILE = SSOWNER.".".FILE
         I = 0
         WHILE  I<FILEUSEDCOUNT CYCLE 
            I = I+1
            IF  FILEUSED(I)=FILE START 
               FLAG = 266;               !FILE CURRENTLY IN USE
               ->ERR
            FINISH 
         REPEAT 
      FINISHELSESTART ;                  ! OUTPUT TO DEVICE
         DEVICE <- FILE
         FILE = TEMPFILE
      FINISH 
      L = CUR_RP-CURP+1;                 ! DETERMINE LENGTH OF OUTPUT FILE
      COUNT = L
      BEG == RECORD(CUR_RL)
      WHILE  BEG_LP#0 CYCLE 
         COUNT = COUNT+BEG_RP-BEG_LP+1
         BEG == RECORD(BEG_RL)
      REPEAT 
      IF  MOD#0 THENSTART ;              !OPEN FILE -MOD I.E. APPEND TO END
         CONNECT(FILE,3,0,0,RR,FLAG)
         IF  FLAG=218 THENSTART ;        !FILE DOES NOT EXIST
            MOD = 0
         FINISHELSESTART 
            IF  FLAG#0 THEN  ->ERR;      !SOME OTHER FAILURE
            IF  RR_FILETYPE#3 THENSTART 
               FLAG = 267
               SETFNAME(FILE)
               ->ERR
            FINISH 
            COUNT = RR_DATAEND+COUNT;    !NEW TOTAL LENGTH
            DISCONNECT(FILE,FLAG);       !MIGHT NOT BE ROOM TO EXTEND
            CHANGEFILESIZE(FILE,COUNT,FLAG)
            ->ERR IF  FLAG#0
            CONNECT(FILE,3,0,0,RR,FLAG)
            ->ERR IF  FLAG#0
            I = RR_CONAD+RR_DATAEND;     !START PUTTING NEW TEXT HERE
            INTEGER(RR_CONAD) = COUNT;   !TOTAL LENGTH
            INTEGER(RR_CONAD+8) = (COUNT+4095)&X'FFFFF000'
         FINISH 
      FINISH 
      IF  MOD=0 THENSTART ;              ! CREATE A NEW FILE OR OVERWRITE EXISTING ONE
         OUTFILE(FILE,COUNT+32,0,0,CONAD,FLAG); ! CREATE OUTPUT FILE
         IF  FLAG#0 THEN  ->ERR
         INTEGER(CONAD) = COUNT+32
         I = CONAD+32
         INTEGER(CONAD+12) = SSCHARFILETYPE
      FINISH 
      MOVE(L,CURP,I)
      I = I+L
      BEG == RECORD(CUR_RL)
      WHILE  BEG_LP#0 CYCLE 
         COUNT = BEG_RP-BEG_LP+1
         MOVE(COUNT,BEG_LP,I)
         I = I+COUNT
         BEG == RECORD(BEG_RL)
      REPEAT 
      DISCONNECT (FILE, FLAG)
      IF  FILE=TEMPFILE THENSTART 
         SENDFILE(FILE,DEVICE,"EDITOUT",0,0,FLAG)
         IF  FLAG#0 THEN  PSYSMES(1000,FLAG)
      FINISH 
      RETURN 
ERR:  PSYSMES(31,FLAG)
END ;                                    !OF EXTRACT
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ROUTINE  REPLACE
      IF  BEGP#BEG_LP THENSTART 
         CUR == BEG
         CURP = BEGP
         SEPARATE
      FINISH 
      CUR == END
      CURP = ENDP
      IF  ENDP=END_LP THEN  NEW == RECORD(CUR_LL) ELSESTART 
         SEPARATE
         IF  ADDR(BEG_LL)=ADDR(END_LL) THEN  BEG == NEW
      FINISH 
      IF  ADDR(BEG_LL)#ADDR(BOT_LL) AND  ADDR(NEW_LL)#ADDR(TOP_LL) THENSTART 
         CHANGED = 1;                    !TO INDICATE CHANGE MADE
         ALTERED=ALTERED+1;             ! LIST ALTERED SINCE "HSAVE"
         CUR_LL = BEG_LL
         INTEGER(BEG_LL+12) = NEW_RL
         BEG_LL = SET_LL
         INTEGER(SET_LL+12) = ADDR(BEG_LL)
         NEW_RL = SETA
         SET_LL = ADDR(NEW_LL)
      FINISH 
END ;                                    !OF REPLACE
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ROUTINE  COPY(INTEGER  I)
      TXT == RECORD(NEWCELL)
      MOVE(16,I,ADDR(TXT_LL))
END ;                                    !OF COPY
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
INTEGERFN  LAYOUT(INTEGER  PARAM,JUSTIFY)
!***********************************************************************
!*    LAYS OUT A PARAGRAPH AS DEFINED BY PARAM AND-OR DEFAULTS         *
!***********************************************************************
INTEGERFNSPEC  JUST(INTEGER  FIRST,LAST,DESIRED,SS)
INTEGER  LINEL,LINEST,PARAST,I,J,K,PTOPP,SYM,LINE,FIRSTPOS,N,SCURP
RECORD (CELL)NAME  PTOP,PBOT,SCUR
BYTEINTEGERARRAY  CLINE(0:160)
INTEGERFNSPEC  ADJUSTLINE(INTEGER  INITLENGTH)
      *LSS_PARAM; *IMDV_1000; *IMDV_100
      *ST_LINEST; *LSS_TOS ; *ST_PARAST
      *LSS_TOS ; *ST_LINEL
      IF  LINEL=0 THEN  LINEL=SLINEL
      IF  LINEST=0 THEN  LINEST=SLINEST
      IF  PARAST=0 THEN  PARAST=SPARAST
      SLINEL=LINEL; SLINEST=LINEST; SPARAST=PARAST
      TXT==RECORD(NEWCELL)
      TXT_LP=ADDR(SPS(-2))
      TXT_RP=TXT_LP+1;                ! RECORD DEFINING DOUBLE NL
!
! STAGE 1 DEFINE THE PARAGRAPH AND DEAL WITH NULLS
!
      I=FIND
      CUR==BEG; CURP=BEGP
!
! REMOVE ANY TRAILING SPACES BEFORE INSERT SEPERATOR
!
      END==CUR; ENDP=CURP
      CYCLE 
         IF  CHARSBACK(1)=0 THEN  EXIT 
         IF  BYTEINTEGER(BEGP)#' ' THEN  EXIT 
         DELETE
      REPEAT 
      CUR==END; CURP=ENDP
      TXT=0; INSERT;                    ! INSERT PSEUDO SEPARATOR
      PBOT==TXT;                        ! TO MARK THE END
      CUR==PBOT
      CURP=CUR_RP;                      ! BEFOR PSEUDO SEP
      TXT==RECORD(NEWCELL)
      TXT_LP=ADDR(SPS(-2))
      TXT_RP=TXT_LP+1
      I=FINDB
      PTOP==END; PTOPP=ENDP;            ! TOP OF PARAGRAPH
      CUR==PTOP; CURP=PTOPP
      I=RETURN CELL(ADDR(TXT))
                                        ! SKIP EMPTY PARAGRAPHS
!
! CYCLE TO DEAL WITH EACH LINE IN PARAGRAPH
!
      LINE=0
      CYCLE 
         LINE=LINE+1
         IF  LINE=1 THEN  I=PARAST ELSE  I=LINEST
         J=I-1
         CLINE(J)=' ' AND  J=J-1 WHILE  J>=1;! SPACE LH MARGIN
         FIRSTPOS=I;                    ! NEEDED LATER
         EXIT  IF  CUR==PBOT;           ! REACHED PSEUDOSEP
         SCUR==CUR; SCURP=CURP;          ! NEEDED FOR DELETE
!
! DISCARD ANY REDUNDANT SPACES ON FRONT OF LINE. ALSO A NL IF LEFT
! FROM ADJUSTMENT OF PREVIOUS LINE
!
         CYCLE 
            I=BYTEINTEGER(CURP)
            EXIT  UNLESS  I=' ' OR  I=NL
            IF  CURP<CUR_RP THEN  CURP=CURP+1 ELSE  START 
               CUR==RECORD(CUR_RL)
              CURP=CUR_LP
               ->WAYOUT IF  CUR==PBOT
            FINISH 
         REPEAT 
!
! COPY IN ENOUGH OF THE LINE
!
         N=FIRST POS
         CYCLE 
            SYM=BYTEINTEGER(CURP)
            CLINE(N)=SYM AND  N=N+1 UNLESS  C 
               JUSTIFY#0 AND  N>FIRST POS AND  CLINE(N-1)=' '=SYM
            IF  CURP<CUR_RP THEN  CURP=CURP+1 ELSE  START 
               CUR==RECORD(CUR_RL)
               CURP=CUR_LP
            FINISH 
            WHILE  SYM=NL AND  N>FIRST POS+1 AND  CLINE(N-2)=' ' CYCLE 
               N=N-1
               CLINE(N-1)=NL;           ! REMOVE TRAILING SPACES
            REPEAT 
            IF  SYM=NL OR  N>LINEL+1 OR  CUR==PBOT THEN  EXIT 
         REPEAT 
         J=ADJUST LINE(N-1);            ! MAY RECURSE
         I=FIRST POS
         IF  I<LINEST THEN  I=LINEST;   ! FOR REVERSE INDENTING ON LINE 1
         IF  JUSTIFY#0 AND  CUR##PBOT THEN  J=JUST(I,J-1,LINEL,0);! J= NL POSN
!
! OUTPUT THE ADJUSTED LINE  AND DELETE ORIGINAL
!
         BEG==SCUR; BEGP=SCURP
         END==CUR; ENDP=CURP
         DELETE
         EXIT  IF  J<=FIRSTPOS
         TXT==RECORD(NEWCELL)
         TXT_LP=WSP
         FOR  I=1,1,J CYCLE 
            BYTEINTEGER(WSP)=CLINE(I)
            WSP=WSP+1
         REPEAT 
         TXT_RP=WSP-1
         INSERT
      REPEAT 
WAYOUT:
      SCUR==RECORD(PBOT_LL)
      SCUR_RL=PBOT_RL
      CUR==RECORD(PBOT_RL)
      CUR_LL=PBOT_LL
      CURP=CUR_LP
      I=RETURN CELL(ADDR(PBOT))
      I=CHARSON(2)
      CUR==END; CURP=ENDP
      RESULT =I
INTEGERFN  ADJUSTLINE(INTEGER  LAST)
!***********************************************************************
!*    MORES WORDS TO OR FROM THE LAST LINE TO IMPROVE FIT              *
!*    PARAMETER LAST EXCLUDES NL OR OVERFLOWING CHAR 'SYM' WHICH       *
!*    IS IN THE BUFFER                                                 *
!***********************************************************************
INTEGER  I,J,K,XCURP
RECORD (CELL)NAME  XCUR
      IF  CUR==PBOT THEN  RESULT =LAST
      IF  SYM=NL AND  LINEL<=LAST<=LINEL+1 THEN  RESULT =LAST
      IF  LAST<LINEL THEN  ->TOO SHORT
!
! LINE IS TOO SHORT TRY TO FIND EARLIER BREAK
!
      I=LAST+1
      WHILE  I>FIRSTPOS CYCLE 
         EXIT  IF  CLINE(I)=' '
         I=I-1
      REPEAT 
      IF  I=FIRSTPOS START ;            ! NO BREAKPOINTS!
         CLINE(LAST+1)=NL
         RESULT =LAST+1
      FINISH 
      J=CHARSBACK(LAST-I+1)
      CLINE(I)=NL
      CURP=BEGP; CUR==BEG
      RESULT =I
TOO SHORT:                              ! TRY TO ADD WORD FROM NEXT LINE
      XCUR==CUR; XCURP=CURP;            ! IN CASE IT WONT FIT
      J=BYTEINTEGER(CURP)
      WHILE  J=' ' OR  J=NL CYCLE 
         IF  CURP<CUR_RP THEN  CURP=CURP+1 ELSE  START 
            CUR==RECORD(CUR_RL)
            CURP=CUR_LP
            IF  CUR==PBOT THEN  ->MISS
         FINISH 
         J=BYTEINTEGER(CURP)
      REPEAT 
      I=LAST+1
      CYCLE 
         J=BYTEINTEGER(CURP)
         EXIT  IF  J=' ' OR  J=NL
         CLINE(I)=J
         IF  I>LINEL THEN  ->MISS
         I=I+1
         IF  CURP<CUR_RP THEN  CURP=CURP+1 ELSE  START 
            CUR==RECORD(CUR_RL); CURP=CUR_LP
            CLINE(LAST)=' ' AND  RESULT =I-1 IF  CUR==PBOT;  ! END OF PARA REACHED
         FINISH 
      REPEAT 
      CLINE(LAST)=' '
      CLINE(I)=NL
      SYM=NL
      RESULT =ADJUSTLINE(I)
MISS:                                   ! WONT FIT
      CUR==XCUR; CURP=XCURP
      RESULT =LAST
END 
INTEGERFN  JUST(INTEGER  FIRST,LAST,DESIRED,SS)
!***********************************************************************
!*    JUSTIFY RIGHT MARGIN BY DOUBLING UP SPACES. NO ATTEMPT TO ADD    *
!*    EXTRA SPACES BETWEEN SENTENCES AS THIS INFO IS NOT READILY       *
!*    AVAILABLE. RECURSES IF ONE PASS INSUFFICENT                      *
!***********************************************************************
ROUTINESPEC  INSERT SP(INTEGER  AFTER)
INTEGER  GAPS,NEEDED,I,FLIP,SGAPS,SYM
      NEEDED=DESIRED-LAST; GAPS=0; SGAPS=0
      RESULT =LAST+1 IF  NEEDED<=0
      FOR  I=FIRST+1,1,LAST CYCLE 
         IF  CLINE(I)=' ' START 
            SYM=CLINE(I-1)
            IF  SYM#' ' THEN  GAPS=GAPS+1
            IF  SYM='.' OR  SYM=',' OR  SYM=';' OR  SYM='!' C 
               OR  SYM='?' THEN  SGAPS=SGAPS+1
         FINISH 
      REPEAT 
      RESULT =LAST+1 IF  GAPS=0;        ! NO GAPS= ONE WORD LIN!?!
!
      IF  SS=0 AND  SGAPS>0 START ;     ! FIRST FEW EXTRA SPACES AFTR'.' ETC
         I=FIRST+1
         CYCLE 
            IF  CLINE(I)=' ' START 
               SYM=CLINE(I-1)
               IF  SYM='.' OR  SYM=',' OR  SYM=';' OR  SYM='?' C 
                  OR  SYM='!' START 
                  INSERT SP(I)
                  SGAPS=SGAPS-1
                  NEEDED=NEEDED-1
                  IF  0<NEEDED>SGAPS THEN  INSERT SP(I) AND  NEEDED=NEEDED-1
                  IF  NEEDED<=0 THEN  RESULT =LAST+1
               FINISH 
            FINISH 
            I=I+1
            EXIT  UNLESS  I<LAST AND  SGAPS>0
            REPEAT 
      FINISH 
      FLIP=1
      IF  LINE&1#0 THEN  FLIP=-1
      IF  FLIP>0 THEN  I=FIRST+1 ELSE  I=LAST
      CYCLE 
         IF  CLINE(I)=' ' AND  CLINE(I-1)#' ' START 
            INSERT SP(I)
            I=I+FLIP
            NEEDED=NEEDED-1
            IF  NEEDED<=0 THEN  RESULT =LAST+1
         FINISH 
         I=I+FLIP
         EXIT  UNLESS  FIRST<I<LAST
      REPEAT 
      RESULT =JUST(FIRST,LAST,DESIRED,1)
ROUTINE  INSERT SP(INTEGER  AFTER)
INTEGER  K
      FOR  K=LAST+2,-1,AFTER+1 CYCLE 
         CLINE(K)=CLINE(K-1)
      REPEAT 
      LAST=LAST+1
END 
END ;                                   ! OF FN JUST
END 
INTEGERFN  INIT DICT
!***********************************************************************
!*    INITIALISES BIT DESCRIPTORS FOR SYS&PRIV DICTS                   *
!***********************************************************************
CONSTINTEGER  MAXPDICT=X'4000'-X'20'
INTEGER  I,CONAD
      CONNECT(SYSDICTNAME,0,0,0,RR,I)
      IF  I=0 START 
         CONAD=RR_CONAD
         IF  RR_FILETYPE#4 THEN  I=267
         SYSDICT=CONAD+INTEGER(CONAD+4)
         SYSDICT=SYSDICT!(INTEGER(CONAD)-INTEGER(CONAD+4))*X'800000000'
      FINISH  ELSE  SYSDICT=-1
      IF  I#0 THEN  SETFNAME(SYSDICTNAME) AND  PSYSMES(ROOT(EMODE),I)
      CONNECT(PRIVDICTNAME,3,0,0,RR,I)
      IF  I=218 START ;                 ! DOES NOT EXIST
         OUTFILE(PRIVDICTNAME,MAX PDICT,0,0,CONAD,I)
         IF  I=0 THEN  START 
            INTEGER(CONAD+12)=4
            INTEGER(CONAD)=MAXPDICT;! SET AS SMAP FILE
            CHERISH(PRIVDICTNAME)
            RR_CONAD = CONAD
            RR_FILETYPE = 4
            RR_DATASTART = 32
            RR_DATAEND = MAXPDICT
         FINISH 
      FINISH 
      RESULT =I UNLESS  I=0
      IF  RR_FILETYPE#4 THEN  SETFNAME(PRIVDICTNAME) AND  RESULT =267
      CONAD=RR_CONAD
      PRIVDICT=CONAD+INTEGER(CONAD+4)
      PRIVDICT=PRIVDICT!(INTEGER(CONAD)-INTEGER(CONAD+4))*X'800000000'
      WSP=(WSP+3)&(-4)
      TEMPDICT=X'0000800000000000'+WSP
      IF  WSP+4096>=WSE THEN  EXTENDWORK
      CYCLE  I=0,1,1023
         INTEGER(WSP)=0
         WSP=WSP+4
      REPEAT ;                          ! CLEAR 4K OF TEMP DICTIONARY
      RESULT =0
END 
INTEGERFN  NEXT WORD
INTEGER  CH,L
      IF  CURP=0 THEN  RESULT =0;       ! AT *B* ETC
      CH=BYTEINTEGER(CURP)&127
!
! FIRST MOVE BACK TO START OF WORD
!
!
! NOW MOVE ON PAST ANY SEPERATORS
!
      WHILE  SPELLCH(CH)>0 CYCLE 
         IF  CHARSBACK(1)=0 THEN  EXIT 
         CUR==BEG; CURP=BEGP
         CH=BYTEINTEGER(CURP)&127
      REPEAT 
      CYCLE 
         CH=BYTE INTEGER(CURP)&127
         EXIT  IF  65<=SPELLCH(CH)<=90; ! INITIAL LETTER
         IF  CURP<CUR_RP THEN  CURP=CURP+1 ELSE  START 
            CUR==RECORD(CUR_RL)
            CURP=CUR_LP
         RESULT =0 IF  CURP=0
         FINISH 
      REPEAT 
      L=1
      CYCLE 
         CH=BYTE INTEGER(CURP)&127
         EXIT  IF  SPELLCH(CH)=0
         WORD(L)=SPELLCH(CH)
         L=L+1
         EXIT  IF  L>31
         IF  CURP<CUR_RP THEN  CURP=CURP+1 ELSE  START 
            CUR==RECORD(CUR_RL)
            CURP=CUR_LP
            EXIT  IF  CURP=0
         FINISH 
      REPEAT 
      IF  L=2 THEN  RESULT =NEXT WORD;   ! IGNORE THE SINGLE LETTERS
      WORD(0)=L-1
      WORD(-1)=WORD(0)
      RESULT =1
END 
ROUTINE  SET HASHES
INTEGER  I,J
CONSTINTEGERARRAY  HCONSTS(0:56)=0,1,
                                        997, 47, 2897, 19, 937, 2203,
                                        311, 1019, 23, 3041, 823, 227,
                               2239, 211, 3181, 197, 3889,
                               191, 2447, 179, 2153, 167, 163,
                               3121, 2213, 149, 139, 2551, 131,
                               3947, 113, 2707, 107, 103, 3109, 97,
                               2647, 83, 79, 3797, 71, 2333,
                               61, 3517, 53, 43, 3821, 37,
                               31, 29, 17, 13, 11,
                                7,  5;
      HASH(I)=0 FOR  I=1,1,MAXHASH
      FOR  I=1,1,MAXHASH CYCLE 
         FOR  J=1,1,WORD(0) CYCLE 
            HASH(I)=HASH(I)+WORD(J)*HCONSTS(J+2*I)
         REPEAT 
      REPEAT 
END 
INTEGERFN  LOOKUP
!***********************************************************************
!*    LOOK UP THE WORD RESULT=1 IF IN SYSDICT,=2 IF IN PRIVATE DICT    *
!*    =0 IF NOT KNOWN                                                  *
!***********************************************************************
INTEGER  I,J
      I=ADDR(HASH(1))
      *LD_SYSDICT
      *JCC_7,<NO SYS>
      *LCT_I
      *LSS_(CTB +0);                    ! HASH(1)
      *IMDV_SYSDICT;                   ! REMAINDER DIVIDE
      *LB_(DR +TOS );                    ! FIRST BIT TO B
      *LSS_(CTB +1)
      *IMDV_SYSDICT
      *ADB_(DR +TOS )
      *LSS_(CTB +2)
      *IMDV_SYSDICT
      *ADB_(DR +TOS )
      *LSS_(CTB +3)
      *IMDV_SYSDICT
      *ADB_(DR +TOS )
      *LSS_(CTB +4)
      *IMDV_SYSDICT
      *ADB_(DR +TOS )
      *LSS_(CTB +5)
      *IMDV_SYSDICT
      *ADB_(DR +TOS )
      *LSS_(CTB +6)
      *IMDV_SYSDICT
      *ADB_(DR +TOS )
      *LSS_(CTB +7)
      *IMDV_SYSDICT
      *ADB_(DR +TOS )
      *LSS_(CTB +8)
      *IMDV_SYSDICT
      *ADB_(DR +TOS )
      *LSS_(CTB +9)
      *IMDV_SYSDICT
      *ADB_(DR +TOS )
      *STB_J
      RESULT =1 IF  J=10;               !ALL 10 BITS SET =WORD IN DICT
NOSYS:                                     ! SYSTEM DICTIONARY MISSING
      *LD_PRIVDICT
      *LCT_I
      *LSS_(CTB +0);                    ! HASH(1)
      *IMDV_PRIVDICT;                   ! REMAINDER DIVIDE
      *LB_(DR +TOS );                    ! FIRST BIT TO B
      *LSS_(CTB +1)
      *IMDV_PRIVDICT
      *ADB_(DR +TOS )
      *LSS_(CTB +2)
      *IMDV_PRIVDICT
      *ADB_(DR +TOS )
      *LSS_(CTB +3)
      *IMDV_PRIVDICT
      *ADB_(DR +TOS )
      *LSS_(CTB +4)
      *IMDV_PRIVDICT
      *ADB_(DR +TOS )
      *LSS_(CTB +5)
      *IMDV_PRIVDICT
      *ADB_(DR +TOS )
      *LSS_(CTB +6)
      *IMDV_PRIVDICT
      *ADB_(DR +TOS )
      *LSS_(CTB +7)
      *IMDV_PRIVDICT
      *ADB_(DR +TOS )
      *LSS_(CTB +8)
      *IMDV_PRIVDICT
      *ADB_(DR +TOS )
      *LSS_(CTB +9)
      *IMDV_PRIVDICT
      *ADB_(DR +TOS )
      *STB_J
      RESULT =2 IF  J=10
      *LD_TEMPDICT
      *LCT_I
      *LSS_(CTB +0);                    ! HASH(1)
      *IMDV_TEMPDICT;                   ! REMAINDER DIVIDE
      *LB_(DR +TOS );                    ! FIRST BIT TO B
      *LSS_(CTB +1)
      *IMDV_TEMPDICT
      *ADB_(DR +TOS )
      *LSS_(CTB +2)
      *IMDV_TEMPDICT
      *ADB_(DR +TOS )
      *LSS_(CTB +3)
      *IMDV_TEMPDICT
      *ADB_(DR +TOS )
      *LSS_(CTB +4)
      *IMDV_TEMPDICT
      *ADB_(DR +TOS )
      *LSS_(CTB +5)
      *IMDV_TEMPDICT
      *ADB_(DR +TOS )
      *LSS_(CTB +6)
      *IMDV_TEMPDICT
      *ADB_(DR +TOS )
      *LSS_(CTB +7)
      *IMDV_TEMPDICT
      *ADB_(DR +TOS )
      *LSS_(CTB +8)
      *IMDV_TEMPDICT
      *ADB_(DR +TOS )
      *LSS_(CTB +9)
      *IMDV_TEMPDICT
      *ADB_(DR +TOS )
      *STB_J
      RESULT =3 IF  J=10
      RESULT =0
END 
ROUTINE  ENTER
!***********************************************************************
!*    ENTERS WORD "WORD" INTO PRIVATE  DICTIONARY                      *
!***********************************************************************
INTEGER  I
      I=ADDR(HASH(1))
      *LD_PRIVDICT
      *LCT_I
      *LB_1
      *LSS_(CTB +0);                    ! HASH(1)
      *IMDV_PRIVDICT;                   ! REMAINDER DIVIDE
      *STB_(DR +TOS );                    ! FIRST BIT TO B
      *LSS_(CTB +1)
      *IMDV_PRIVDICT
      *STB_(DR +TOS )
      *LSS_(CTB +2)
      *IMDV_PRIVDICT
      *STB_(DR +TOS )
      *LSS_(CTB +3)
      *IMDV_PRIVDICT
      *STB_(DR +TOS )
      *LSS_(CTB +4)
      *IMDV_PRIVDICT
      *STB_(DR +TOS )
      *LSS_(CTB +5)
      *IMDV_PRIVDICT
      *STB_(DR +TOS )
      *LSS_(CTB +6)
      *IMDV_PRIVDICT
      *STB_(DR +TOS )
      *LSS_(CTB +7)
      *IMDV_PRIVDICT
      *STB_(DR +TOS )
      *LSS_(CTB +8)
      *IMDV_PRIVDICT
      *STB_(DR +TOS )
      *LSS_(CTB +9)
      *IMDV_PRIVDICT
      *STB_(DR +TOS )
END 
ROUTINE  ENTERTEMP
!***********************************************************************
!*    ENTERS WORD "WORD" INTO TEMPORARY DICTIONARY                     *
!***********************************************************************
INTEGER  I
      I=ADDR(HASH(1))
      *LD_TEMPDICT
      *LCT_I
      *LB_1
      *LSS_(CTB +0);                    ! HASH(1)
      *IMDV_TEMPDICT;                   ! REMAINDER DIVIDE
      *STB_(DR +TOS );                    ! FIRST BIT TO B
      *LSS_(CTB +1)
      *IMDV_TEMPDICT
      *STB_(DR +TOS )
      *LSS_(CTB +2)
      *IMDV_TEMPDICT
      *STB_(DR +TOS )
      *LSS_(CTB +3)
      *IMDV_TEMPDICT
      *STB_(DR +TOS )
      *LSS_(CTB +4)
      *IMDV_TEMPDICT
      *STB_(DR +TOS )
      *LSS_(CTB +5)
      *IMDV_TEMPDICT
      *STB_(DR +TOS )
      *LSS_(CTB +6)
      *IMDV_TEMPDICT
      *STB_(DR +TOS )
      *LSS_(CTB +7)
      *IMDV_TEMPDICT
      *STB_(DR +TOS )
      *LSS_(CTB +8)
      *IMDV_TEMPDICT
      *STB_(DR +TOS )
      *LSS_(CTB +9)
      *IMDV_TEMPDICT
      *STB_(DR +TOS )
END 
ROUTINE  EXTENDWORK
!***********************************************************************
!*                                                                     *
!* ROUTINE NO LONGER ATTEMPTS TO EXTEND WORK FILE.  IT SIMPLY          *
!* SIMULATES EDIT:E.  THIS SHOULD NOW BE SAFE SINCE THIS ROUTINE IS    *
!* NOT CALLED AT CRITICAL PLACES SUCH AS FROM WITHIN EXIT ITSELF.      *
!*                                                                     *
!***********************************************************************
      PRINTSTRING("
WORKSPACE FULL
EDIT:E     INVOKED".SNL)
      EXIT(0)
      SIGNAL  EVENT  12,1;              !RETURN TO COMMAND LEVEL
END ;                                    !OF EXTEND WORK
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ROUTINE  EXIT(INTEGER  WHY)
!***********************************************************************
!*    TERMINATES THE EDIT. WHY=0 FOR NORMAL STOP                       *
!*                WHY=1 FOR INT:W                                      *
!*                WHY=2 FOR INT:X                                      *
!*                WHY=3 FOR INT:Y (LINE BREAK NO OUTPUT POSSIBLE)      *
!*                why=-1 for command W                                 *
!***********************************************************************
INTEGERFNSPEC  SAVETEMPFILE(STRINGNAME  NF, INTEGER  F)
STRING (50) MESS
INTEGER  L,FILELENGTH,FLAG,I
      PFN = ""
      IF  WHY>=0 AND  SYSDICT#0 THEN  DISCONNECT(PRIVDICTNAME,FLAG)
      IF  NEWF=".NULL" OR ((NEWG=1 OR  CYF=OLDF) AND  CHANGED=0) THENSTART 
                                         !LOOK,RECALL,EDIT(A)(NO CHANGES) OR EDIT(A,.NULL)
         DISCONNECT(OLDF,FLAG) IF  NEWG=1
         DISCONNECT(NEWPDF,FLAG) IF  CYF#""
         ETERMINATE = 1
         -> EXOUT
      FINISH 
      KILLPART IF  SETA#0
      FILELENGTH = 0
      CUR == RECORD(TOP_RL)
      WHILE  CUR_LP#0 CYCLE 
         FILELENGTH = FILELENGTH+CUR_RP-CUR_LP+1
         CUR == RECORD(CUR_RL)
      REPEAT 
      L = FILELENGTH+32;                 ! L HAS LENGTH OF FILE REQUIRED
      IF  WHY>0 THEN  ->SAVEEDIT
      OUTFILE(NEWF,L,0,0,CADNEW,FLAG)
      IF  FLAG=0 THEN  ->WRITEIT
                                         ! EXTEND fails.
      IF  NEWF=TEMPFILE OR  FLAG=275 OR  FLAG=276 OR  FLAG=280 OR  C 
         FLAG=308 OR  FLAG=309 THEN  ->ABORT
                                         !  275   File system full
                                         !  276   No free descriptors in file index
                                         !  280   User individual file limit exceeded
                                         !  308   User total limit exceeded
                                         !  309   Too many files connected
      PSYSMES(59,FLAG)
SAVEEDIT:                                ! TRY TO SAVE EDITING IN E#EHA
      PFN = "E#EHA"
      OUTFILE(PFN,L,0,0,CADNEW,I)
      IF  I#0 THEN  -> EXOUT
      MESS = "EDITed text will be saved in ".PFN.SNL
      IF  WHY#3 THEN  PRINTSTRING(MESS) ELSE  C 
         TOJOURNAL(ADDR(MESS),LENGTH(MESS))
      NEWF = PFN
      NEWG = 0
      CYF = ""
WRITEIT:                                 ! WRITE EDITING INTO FILE
      TMPNEW = CADNEW
      INTEGER(TMPNEW) = FILELENGTH+32
      INTEGER(TMPNEW+4) = 32
      INTEGER(TMPNEW+12) = 3;            !TYPE=CHARACTER
      TMPNEW = TMPNEW+32
      CUR == RECORD(TOP_RL)
      WHILE  CUR_LP#0 CYCLE 
         I = CUR_RP-CUR_LP+1
         MOVE(I,CUR_LP,TMPNEW)
         TMPNEW = TMPNEW+I
         CUR == RECORD(RETURN CELL(ADDR(CUR)))
      REPEAT 
      IF  NEWG=1 THENSTART 
         DISCONNECT(OLDF,FLAG)
         IF  FLAG#0 START 
            IF  SAVETEMPFILE(OLDF,FLAG)#0 THEN  ->ABORT
         FINISH  ELSE  START ;          ! FLAG 0 DISCONNECT OK
            SETUSE (TEMPFILE, -1, 0)
            NEWGEN(TEMPFILE,OLDF,FLAG)
            IF  FLAG#0 THEN  ->ABORT;    !UNLIKELY FAILURE
         FINISH 
      FINISHELSESTART 
         IF  CYF#"" THENSTART 
            MODPDFILE(2,NEWPDF,NEWPDM,"",FLAG)
            MODPDFILE(1,NEWPDF,NEWPDM,NEWF,FLAG)
            IF  FLAG#0 THEN  START 
               IF  SAVETEMPFILE(CYF,FLAG) #0 THEN  ->ABORT
            FINISH 
            DISCONNECT(NEWPDF,FLAG)
         FINISHELSE  DISCONNECT(NEWF,FLAG)
      FINISH 
      ETERMINATE = 1;                    !FOR EDITOR TERMINATION MESSAGE
      -> EXOUT
ABORT:PSYSMES(59,FLAG)
EXOUT:
      I = 1
      WHILE  I<=FILEUSEDCOUNT CYCLE 
         DISCONNECT (FILEUSED(I),FLAG)
         I = I + 1
      REPEAT 
      RETURN 
INTEGERFN  SAVETEMPFILE(STRINGNAME  NF, INTEGER  FLAG)
      PSYSMES(59,FLAG)
      PRINTSTRING("Unable to copy EDITed text into ".NF)
      PFN = "E#EHA"
      RENAME(NEWF,PFN,FLAG)
      IF  FLAG=0 THEN  PRINTSTRING("
It has been saved in ".PFN.".".SNL) ELSE  PRINTSTRING("
Unable to save editing".SNL)
      RESULT =FLAG
END 
END ;                                    !OF EXIT
ROUTINE  CHECKFF(INTEGERNAME  FLAG)
INTEGER  I,DOOUTFILE,CMODE,NEWSIZE
STRING (31) TEMPF,OWNER
      CYF = ""
      FLAG = 0
      DOOUTFILE = 0
      UNLESS  NEWF=".NULL" THENSTART 
                                         ! Check for misuse of another user's file.
                                         ! It is not enough to rely on file protection: you could
                                         ! have WRITE access to another user's file, but you still
                                         ! would not be able to change the overall file size.
         IF  NEWF->OWNER.(".").TEMPF AND  OWNER#SSOWNER THEN  C 
            FLAG = 258 AND  SETFNAME(NEWF) ELSESTART 
                                         ! We will try to connect ordinary files for writing, but PD file
                                         ! members for reading.
            IF  NEWF->NEWPDF.("_").NEWPDM THEN  CMODE = 0 ELSE  CMODE = 3
            DOOUTFILE = -1;              ! For most EDITs we will need to
                                         ! create a new file (temporary or
                                         ! permanent).  In those cases
                                         ! where no new file is needed
                                         ! we reset DO OUTFILE to zero to
                                         ! suppress the file creation.
            IF  CMODE=0 THEN  CONNECT(NEWPDF,3,0,0,RR,FLAG)
                                         ! **** **** I have a note that that should say        **** ****
                                         !    %IF ... %THEN %START
                                         !       CONNECT (...)
                                         !       %IF FLAG=0 %THEN DISCONNECT (NEWPDF,I)
                                         !    %FINISH
                                         ! **** **** but I can't remember why.  Check this     **** ****
                                         ! **** **** before implementing it.                   **** ****
                                         !
            IF  FLAG=0 THEN  CONNECT(NEWF,CMODE,0,0,RR,FLAG)
            FILEUSEDCOUNT=1
         FILEUSED(1)<-SSOWNER.".".NEWF
                                         ! Try to connect.
            IF  NEWF=OLDF THENSTART ;    ! Editing a file onto itself.
               IF  FLAG=0 THENSTART ;    ! Connected O.K. - File exists.
                  IF  CMODE=3 THENSTART ; ! For ordinary files
                     NEWF = TEMPFILE;    ! we will use a temporary file
                     NEWG = 1;           ! and do NEWGEN when finished.
                     SETUSE (OLDF, -1, 0)
                  FINISH ;               ! For PD file members, we will use
                                         ! a temporary file - see below.
                                         ! It might be a good idea to
                                         ! DISCONNECT the member at this point
                                         ! since it will be reCONNECTed in
                                         ! CHECKFF.  This might also cure
                                         ! BR42 (whatever that was).
               FINISHELSE  OLDF = ".NEW"; ! If FLAG was non-zero
                                         ! we assume for the moment that
                                         ! it is because NEWF does not
                                         ! exist, and since OLDF=NEWF we
                                         ! must be editing to create a new
                                         ! file.  If the non-zero FLAG was
                                         ! for any other reason, that will be
                                         ! detected later.
            FINISHELSESTART ;            ! Editing from one file into
                                         ! another.
               IF  FLAG=0 THENSTART ;    ! The destination file does exist.
                  PRINTSTRING(NEWF." already exists")
                  IF  RR_FILETYPE#3 THEN  START 
                     PRINTSTRING(" but is not a character file")
                     FLAG=267
                     SETFNAME(NEWF)
                  FINISH 
                  NEWLINE
                  IF  CMODE=3 THEN  DOOUTFILE = 0; ! For editing into an ordinary
                                         ! file which does already exist, we
                                         ! do not need to create any new file.
                                         ! For PD file members, we will need
                                         ! to create a temporary file - see
                                         ! below.
               FINISH 
            FINISH 
            IF (CMODE=3 AND  FLAG=218) OR (CMODE=0 AND  FLAG=288) THENSTART 
                                         ! The 'acceptable' failures from CONNECT are 'file does not exist'
                                         ! for an ordinary file, and 'member does not exist' for a PD file
                                         ! member.
               FLAG = 0;                 ! This is no failure.
               PRINTSTRING(NEWF." is a new ")
               IF  CMODE=0 THEN  PRINTSTRING("member".SNL) ELSE  C 
                  PRINTSTRING("file".SNL)
               NEWNEWF = 1;              ! To indicate that a new NEWF has been created.
            FINISH 
            IF  FLAG=0 THENSTART ;       ! New file validated.
               IF  CMODE=0 THENSTART ;   ! If it's a PD file member, we must
                  CYF = NEWF;            ! use a temporary file and remember
                  NEWF = TEMPFILE;       ! to copy it into the member at the end.
               FINISH 
            FINISH 
         FINISH 
      FINISH 
      IF  FLAG=0 THEN  START 
         IF  OLDF#".NEW" THEN  START 
            CONNECT(OLDF,0,0,0,RR,FLAG);    !CONNECT FOR READING
            TEMPF=OLDF
            UNLESS  TEMPF->(".") THEN  TEMPF=SSOWNER.".".TEMPF
            FILEUSEDCOUNT=FILEUSEDCOUNT+1
            FILEUSED(FILEUSEDCOUNT)<-TEMPF
            IF  FLAG = 0 THENSTART 
               CADOLD = RR_CONAD;           !CONNECT ADDRESS OF OLDF
               IF  RR_FILETYPE # 3 THENSTART 
                  FLAG = 267;               !INVALID FILETYPE
                  SETFNAME(OLDF)
               FINISH 
            FINISH 
         FINISH 
      FINISH 
      IF  FLAG=0 AND  DOOUTFILE#0 THEN  START 
         ! Create the file to ensure it can be constructed, but
         ! don't connect it.
         IF    OLDF=".NEW" THEN  NEWSIZE = 4096 C 
         ELSE  NEWSIZE = INTEGER(CADOLD)+2048
         OUTFILE(NEWF, - NEWSIZE,-1,0,I,FLAG)
      FINISH 
END ;                                    !OF CHECKFF
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1
!!!!!!!!!!!!!!!!!!! INITIALISATION !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!
      PRSTRING = UCSTRING(INTERRUPT);   !TO CLEAR INTERRUPT
      PRSTRING=PRT(EMODE).":"
      COMREG(24)=0
      CASEIND = 1
      CASE == ONECASE
      SSOWNER = UINFS(1);                !SET OWNER NAME
      CYCLE  I = 0,1,6
         LASTREC(I)_LP = 0
      REPEAT 
      IF  EMODE=0 THENSTART ;            ! GENUINE EDIT
         FINFO("E#EHA",1,EHR,FLAG)
         IF  FLAG#218 START ;            ! ALREADY EXISTS
            PRINTSTRING("
Former editing is saved in file E#EHA. Rename or destroy before
attempting any further EDITs")
            RESULT  = 2
         FINISH 
         REROUTECONTINGENCY(3,65,X'F0000000F'<<('V'-64),FORCLOSE,FLAG)
                                        ! TRAP UPPER&LOWER CASE VERSIONS
                                        ! OF INT:W,INT:X & INT:Y
                                         ! FLAG NOT TESTED SINCE NO
                                         ! SENSIBLE ACTION SEEMS POSSIBLE
      FINISH 
      I = 128*X'1000';                  ! 2 SEGMENTS FOR WORK FILE
      SYSDICT=0
      WORD(0)=0;                        ! NO WORDS FOR DICT LOOKUP YET
      SETWORK(I,FLAG)
      ->ERR IF  FLAG#0
      WSP = I+INTEGER(I+4)
      WSE = I+INTEGER(I+8)
      COMP=0
      SLINEST=1; SPARAST=6; SLINEL=72;  ! SET LAYOUT DEFAULTS
      ASL = 0
      INITIALISE(FLAG)
      IF  FLAG#0 THEN  ->ERR
      LASTCOM==CLIST(0);                ! SO NOT UNASSIGNED ON IMMEDIATE ERROR
      CYCLE ;                            ! **** **** Start of the primary editor loop.
      
         LINECOMPLETE = READCSTRING
         IF  LINECOMPLETE<0 THENSTART ;  ! FOR INVALID LINES.
            PROMPT(PRSTRING)
                                         !FAULT DURING COMMAND INPUT
            SKIPSYMBOL WHILE  NEXTSYMBOL#NL; !SKIP REST OF LINE
         FINISH 
         IF  HSET=0 THEN  HSAVE
         I = 0
         WHILE  I<COMP CYCLE 
            LASTCOM == CURCOM UNLESS  I=0 OR  CURCOM_SWNO=0
                                        ! REMEMBER FOR FINAL P1
                                        ! BUT NOT IF REPEAT COMMAND
            CURCOM == CLIST(I)
            I = I+1
            J=CURCOM_FLAGS
            IF  J&NEEDSS#0 AND  SETA=0 THEN  ERMESS(3,CURCOM_LETT) C 
               AND  I=COMP-1 AND  CONTINUE 
            BACK = J&BACKWARDS
            IF  J&STOP SPELL#0 THEN  WORD(0)=0;! DESTROY "CURRENT" WORD
            IF  J&ERROR=0 THEN  ->ED(CURCOM_SWNO)
            ERMESS(CURCOM_ERRNO,CURCOM_LETT)
            I=COMP-1
            CONTINUE 
ED(0):                                  ! LOOP TEST
            IF  UCSTRING(INTERRUPT)="STOP" THEN  ->L31
            CURCOM_COUNT<-CURCOM_COUNT+1
            IF  CURCOM_COUNT>=CURCOM_PAR THEN  CURCOM_COUNT=0 C 
               ELSE  I=CURCOM_LOOP
            CONTINUE 
ED(1):                                   ! T
            CUR == RECORD(TOP_RL)
            CURP = CUR_LP
            CONTINUE 
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ED(2):                                   ! B
            CUR == BOT
            CURP = 0
            CONTINUE 
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ED(3):                                   ! E
            EXIT(0)
            REROUTE CONTINGENCY(0,0,0,FORCLOSE,FLAG)
            RESULT  = ETERMINATE
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ED(4):                                   ! I
            EXIT  IF  MAPTXT(CURCOM_PAR)=0
            COPY(CURCOM_PAR)
            INSERT
            CONTINUE 
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ED(5):                                   ! M TEXT
            EXIT  IF  MAPTXT(CURCOM_PAR)=0
            IF  BACK=0 THEN  K = FIND ELSE  K = FINDB
            CUR == BEG
            CURP = BEGP
            IF  K=0 THEN  ->L31 ELSE  CONTINUE 
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ED(6):                                   ! M NO.
            IF  BACK=0 AND  CURCOM_PAR>0 THENSTART 
               K = LINESON(CURCOM_PAR)
               CUR == END
               CURP = ENDP
            FINISHELSESTART 
               K = LINESBACK(CURCOM_PAR)
               CUR == BEG
               CURP = BEGP
            FINISH 
            IF  K=0 THEN  ->L31 ELSE  CONTINUE 
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ED(7):                                   ! A TEXT
            EXIT  IF  MAPTXT(CURCOM_PAR)=0
            IF  BACK=0 THEN  K = FIND ELSE  K = FINDB
            IF  K=0 START ;              !FAILURE
               CUR == BEG
               CURP = BEGP
               ->L31
            FINISH 
            CUR == END
            CURP = ENDP
            CONTINUE 
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ED(8):                                   ! A NO.
            IF  BACK=0 THENSTART 
               K = CHARSON(CURCOM_PAR)
               CUR == END
               CURP = ENDP
            FINISHELSESTART 
               K = CHARSBACK(CURCOM_PAR)
               CUR == BEG
               CURP = BEGP
            FINISH 
            IF  K=0 THEN  ->L31 ELSE  CONTINUE 
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ED(9):                                   ! P TEXT
            EXIT  IF  MAPTXT(CURCOM_PAR)=0
            IF  BACK=0 START ;           !P/TEXT/
               IF  FIND=0 THENSTART 
                  END == BEG
                  ENDP = BEGP
               FINISHELSESTART 
                  BEG == CUR
                  BEGP = CURP
                  CUR == END
                  CURP = ENDP
                  K = LINESON(1)
                  CUR == BEG
                  CURP = BEGP
               FINISH 
               J = LINESBACK(0)
            FINISHELSESTART ;            !P-/TEXT/
               K = FINDB;                !DOES NOT MATTER IF IT FAILS SINCE BEG L
               END == CUR;               !SAVE CUR AND CURP
               ENDP = CURP
               CUR == BEG
               CURP = BEGP
               K = LINESBACK(0);         !PRINT FROM START OF LINE CONTAINING TEX
               CUR == END;               !RESTORE CUR AND CURP
               CURP = ENDP
               K = LINESON(1);           !MOVE END TO AFTER END OF LINE
            FINISH 
            PRINTTEXT
            IF  INTSTOP=1 THEN  EXIT ;   !INT:STOP FOUND
            CONTINUE 
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ED(10):                                  ! P NO.
                                        ! OMIT FINAL P1 IF POSSIBLE
            IF  I=COMP AND  LASTCOM_LETT='P' THEN  CONTINUE 
            IF  BACK=0 AND  CURCOM_PAR>0 THENSTART 
               J = LINESBACK(0)
               K = LINESON(CURCOM_PAR)
            FINISHELSESTART 
               K = LINESBACK(CURCOM_PAR)
               J = LINESON(1)
            FINISH 
            PRINTTEXT
            IF  J=0 OR  K=0 THEN  ->L31
            IF  INTSTOP=1 THEN  EXIT ;   !INT: STOP FOUND
            CONTINUE 
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ED(11):                                  ! D TEXT
            EXIT  IF  MAPTXT(CURCOM_PAR)=0
            IF  BACK=0 START ;           !D/TEXT/
               IF  FIND=0 THENSTART 
                  CUR == BEG
                  CURP = BEGP
                  ->L31
               FINISH 
               BEG == CUR
               BEGP = CURP
            FINISHELSESTART ;            !D-/TEXT/
               IF  FINDB=0 START ;       !FAILURE TO FIND TEXT
                  CUR == BEG
                  CURP = BEGP
                  ->L31
               FINISH 
               END == CUR
               ENDP = CURP
            FINISH 
            DELETE
            CONTINUE 
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ED(12):                                  ! D NO.
            J = LINESBACK(0)
            IF  CURCOM_PAR=0 START ;    ! D0 IS NOOP
               CUR == BEG
               CURP=BEGP
               CONTINUE 
            FINISH 
            IF  BACK=0 THENSTART 
               K = LINESON(CURCOM_PAR)
            FINISHELSESTART 
               END == BEG
               ENDP = BEGP
               K = LINESBACK(CURCOM_PAR)
            FINISH 
            IF  K=0 THEN  ->L31
            DELETE
            CONTINUE 
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ED(13):                                  ! R TEXT
            EXIT  IF  MAPTXT(CURCOM_PAR)=0
            IF  BACK=0 THEN  K = FIND ELSE  K = FINDB
            IF  K=0 THENSTART 
               CUR == BEG
               CURP = BEGP
               ->L31
            FINISH 
            DELETE
            CONTINUE 
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ED(14):                                  ! R NO.
            IF  BACK=0 THENSTART 
               BEG == CUR
               BEGP = CURP
               K = CHARSON(CURCOM_PAR)
            FINISHELSESTART 
               K = CHARSBACK(CURCOM_PAR)
               END == CUR
               ENDP = CURP
            FINISH 
            IF  K=0 THEN  ->L31
            DELETE
            CONTINUE 
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ED(15):                                  ! Q
            IF  EMODE=0 AND  CHANGED#0 START ;! EDIT AND CHANGES MADE
               PROMPT("QUIT:")
               READSYMBOL(J)
               PROMPT(PRSTRING)
            FINISH  ELSE  J='Q'
            UNLESS  'Q'#ONE CASE(J)#'Y' START 
                                         !%IF NEWF#".NULL" %THEN CLEARUSE(NEWF,J)
                                         !CHANGE TO READ
                                         ! The DESTROY on the next line is only necessary if CYF="".
               IF  NEWNEWF=1 THEN  DESTROY(NEWF,J) ELSESTART 
                                         !DONT NEED IT
                  IF  NEWG=1 THEN  DISCONNECT(OLDF,J) ELSE  DISCONNECT(NEWF,J)
               FINISH 
               IF  CYF#"" THEN  DISCONNECT(NEWPDF,J)
               IF  SYSDICT#0 THEN  DISCONNECT(PRIVDICTNAME,J)
               J = 1
               WHILE  J<=FILEUSEDCOUNT CYCLE 
                  DISCONNECT (FILEUSED(J),FLAG)
                  J = J + 1
               REPEAT 
               RESULT  = 2
            FINISH 
            CONTINUE 
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ED(16):                                  ! S
            IF  SETA#0 THEN  KILLPART
            SETA = NEWCELL
            TXT == RECORD(SETA)
            INSERT
            SET == TXT
            CONTINUE 
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ED(17):                                  ! K
            CUR == SET
            KILLPART
            CONTINUE 
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ED(18):                                  ! H
            HRESTORE
            CONTINUE 
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ED(19):                                  ! U TEXT
            EXIT  IF  MAPTXT(CURCOM_PAR)=0
            IF  BACK=0 START ;           !U/TEXT/
               IF  FIND=0 THENSTART 
                  CUR == BEG
                  CURP = BEGP
                  ->L31
               FINISH 
               BEG == CUR
               BEGP = CURP
            FINISHELSESTART ;            !U-/TEXT/
               IF  FINDB=0 START 
                  CUR == BEG
                  CURP = BEGP
                  ->L31
               FINISH 
               END == CUR
               ENDP = CURP
            FINISH 
            REPLACE
            CONTINUE 
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ED(20):                                  ! U NO.
            J = LINESBACK(0)
            IF  CURCOM_PAR=0 START ;    ! U0 IS NOOP
               CUR == BEG
               CURP=BEGP
               CONTINUE 
            FINISH 
            IF  BACK=0 THENSTART 
               K = LINESON(CURCOM_PAR)
            FINISHELSESTART 
               END == BEG
               ENDP = BEGP
               K = LINESBACK(CURCOM_PAR)
            FINISH 
            IF  K=0 THEN  ->L31
            REPLACE
            CONTINUE 
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ED(21):                                  ! O
            CUR == RECORD(SETA)
            CURP = 0
            CONTINUE 
ED(23):                                  !G NO
                                         !POSITION AT CHARACTER NO IN CURRENT LINE, SPACE
                                         !FILLING IF NECESSARY
            POSITION(CURCOM_PAR)
            CONTINUE 
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ED(24):     EXTRACT(CURCOM_PAR);         !F
            CONTINUE 
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ED(25):                                  !W - WELD
            IF  NEWF#".NULL" START ;     !IGNORE IF EDIT TO .NULL
               J=SETA
               IF  SETA#0 THEN  KILL PART
               K=CURP-CUR_RP-1
               WHILE  CUR¬==TOP CYCLE 
                  K=K+CUR_RP-CUR_LP+1
                  CUR==RECORD(CUR_LL)
               REPEAT 
               EXIT(-1);                 !CLOSE FILES
               IF  NEWF=TEMPFILE THENSTART 
                  IF  CYF="" THEN  NEWF = OLDF ELSESTART 
                     IF  PFN="" THEN  NEWF = CYF ELSERESULT  = 2
                  FINISH 
               FINISH 
               PRINTSTRING("All changes incorporated in ".NEWF.SNL)
               IF  J#0 THEN  PRINTSTRING("NB Separator *S* has been killed
")
               S = NEWF.",".NEWF;        !EDIT (A,B) BECOMES EDIT(B,B)
               RETURN LIST(HTOP,HBOT);! HSAVE LIST
                  J=RETURN CELL(ADDR(HBOT))
               INITIALISE(FLAG)
               IF  FLAG#0 THEN  ->ERR
               J=CHARSON(K)
               CUR==END
               CURP=ENDP
            FINISH 
            CONTINUE 
ED(26):                                 ! Z = FLIP CASE DEPENDENCY
            IF  CASEIND=0 START 
               CASEIND=1; CASE== ONE CASE
            FINISH  ELSE  START 
               CASEIND=0; CASE==TWO CASE
            FINISH 
            CONTINUE 
ED(27):                                 ! L=LAYOUT
            IF  LAYOUT(CURCOM_PAR,0)=0 THEN  ->L31
            CONTINUE 
ED(28):                                 ! J=JUSTIFY
            IF  LAYOUT(CURCOM_PAR,1)=0 THEN  ->L31
            CONTINUE 
ED(29):                                 ! X=MOVE TO NEXT WRONGLY SPELT WRD
            IF  SYSDICT=0 START 
               J=INIT DICT
               IF  J#0 THEN  ERMESS(4,0) AND  ->L31
            FINISH 
            CYCLE 
               J=NEXT WORD
               ->L31 UNLESS  J>0;       ! *B* ETC

               SET HASHES
            J=LOOK UP
            REPEAT  UNTIL  J=0
            J=CHARSBACK(WORD(-1));      ! IN FRONTY OF BUM WORD
            CUR==BEG; CURP=BEGP
            CONTINUE 
ED(30):                                 ! Y="YES WORD IS SPELT CORRECTLY"
            IF  WORD(0)=0 THEN  ERMESS(5,0) AND  ->L31
            ENTER
            J=CHARSON(WORD(0))
            CURP=ENDP; CUR==END
            CONTINUE 
ED(31):                                 ! N="NO IGNORE WRONG WORD"
            IF  WORD(0)=0 THEN  ERMESS(5,0) AND  ->L31
            ENTER TEMP;                 ! SO IGNORED WORDS QUERIED ONCE
            J=CHARSON(WORD(0))
            CURP=ENDP; CUR==END
            CONTINUE 
L31:     
            I = COMP-1;                  ! Go on to final P1.
         REPEAT 
      REPEAT ;                           ! **** **** End of the primary editor loop **** ****
ERR:  COMREG(24) = FLAG;                 !RETURN CODE
      PSYSMES(ROOT(EMODE),FLAG)
      RESULT  = 0
INTEGERFN  READCSTRING
!***********************************************************************
!*    READS A COMMAND STRING INTO ARRAY CLIST                          *
!*    LEVEL=0 OUTER LEVEL NORMAL TYPED COMMANDS                        *
!*    LEVEL>0 NESTED COMMANDS BETWEEN BRACKETS                         *
!*    CAN NOT USE RECURSION AS THE C COMMAND CAN CHANGE LEVELS!        *
!***********************************************************************
ROUTINESPEC  GOODCOMMAND(INTEGER  SYM,FLAG,PARAM)
ROUTINESPEC  BADCOMMAND(INTEGER  SYM,ERRNO)
SWITCH  SUB,STYPE(1:10)
INTEGER  I,J,K,SYM,ERR,DEF,CFLAGS,PARVAL,LRPTR
BYTEINTEGERARRAY  LOOPBACK(0:40)
RECORD (CFORM) NAME  CURRCOMP
ON  EVENT  9 START ;                    ! INPUT ENDED
      PRINTSTRING("Input Ended ")
      EXIT(1)
      SIGNAL  EVENT  12,2
FINISH 
                                        ! INITIALISE FOR A NEW COMMAND LINE
      LCOMP=COMP;                       ! PREVIOS STRING RETAINED FOR REPEAT
      COMP = 0; LEVEL = 0; HSET = 0;     ! NO H COMMAND SEEN YET
      NLC = 0;                           ! COUNT OF NEWLINES O-P
      INTSTOP = 0; LINECOMPLETE = 0
      ->NORMAL
REENTER:                                ! FOR PSEUDO RECURSIVE ENTRY
      LEVEL = LEVEL+1
      PROMPT("):")
      LOOPBACK(LEVEL) = COMP
!
NORMAL:      
      UNTIL  LINECOMPLETE#0 CYCLE ;      ! UNTIL END OF COMMAND
         CYCLE 
            SYM = ONECASE(NEXT SYMBOL)
            J = CHARTYPE(SYM);           ! CLASSIFY SYMBOL
            EXITUNLESS  J=0 OR  J=SPACE
            SKIP SYMBOL
         REPEAT 
         ERR = SYNTAXERROR;              ! MOST COMMON ERROR
         ->STYPE(J);                     ! SWITCH ON SYMBOL CLASS
STYPE(NUMCHAR):                          ! DIGIT OUT OF CONTEXT
         IF  COMP=0 AND  LCOMP>1 AND  READI(I)>0 AND  NEXTSYMBOL=NL START 
            CURRCOMP==CLIST(LCOMP-2)
            IF  CURRCOMP_LETT=']' THEN  COMP=LCOMP-1 ELSE  C 
               CURRCOMP==CLIST(LCOMP-1) AND  COMP=LCOMP
            CURRCOMP=0
            CURRCOMP_LETT=']'
            CURRCOMP_PAR=I
         CONTINUE 
         FINISH 
STYPE(TEXTCHAR):                         ! ?. ETC OUT OF CONTEXT
STYPE(FILECHAR):
STYPE(FILEEND):                          ! < & > OUT OF CONTEXT
STYPE(MINUS):                            ! - OUT OF CONTEXT
STYPE(NONNULL):                          ! INVALID SYMBOL
SUB(LOOPSTART):
SUB(LOOPEND):                            ! PARENS INSTEAD OF PARAMS
SUB(MINUS):
SUB(NONNULL):                            ! WRONG CH STARTS PARAM
SUB(FILEEND):
SUB(COMMAND):                            ! COMMAND FOLLOWS COMMAND
            SKIP SYMBOL
BAD:     BADCOMMAND(SYM,ERR)
         GOOD COMMAND('P',NUMPAR,1);    ! STILL NEED A P1
         LINECOMPLETE = -1
         CONTINUE 
STYPE(NL):                               ! NEWLINE
         SKIP SYMBOL
         CONTINUEIF  LEVEL>0 OR  COMP=0;! IGNORE IN A LOOP OR BEFORE FIRST
         GOODCOMMAND('P',NUMPAR,1);      ! P1 AT END
         LINECOMPLETE = 1
         CONTINUE 
STYPE(LOOPEND):                          ! ) FOUND
         SKIP SYMBOL
         ->BAD IF  LEVEL=0;              ! INVALID AT OUTER LEVEL
         ->BAD IF  LOOPBACK(LEVEL)>=COMP
         IF  READI(I)>0 START 
            GOODCOMMAND(SYM,0,I)
            CURRCOMP_LOOP = LOOPBACK(LEVEL)
            LEVEL = LEVEL -1
            ->BACKUP
         FINISH 
         ERR = INVALIDLOOP
         ->BAD
STYPE(LOOPSTART):                        ! '('
         SKIP SYMBOL
         ->REENTER;                     ! PSEUDO RECURSION
BACKUP:                                 ! FOR PSEUDO RETURN
         IF  LEVEL=0 THEN  PROMPT(PRSTRING)
         IF  I<0 THENRESULT  = I
         CONTINUE 
STYPE(COMMAND):                          ! VALID COMMAND LETTER
         SKIP SYMBOL
         DEF = COMDEF(SYM);              ! DEFINITION FROM TABLE
         LRPTR=DEF>>12&15;              ! PTR TO RELEVANT ALT OF LASTREC
         CFLAGS = DEF&(STOP SPELL!NEEDSS); PARVAL=0; ! NO FLAGS AS YET
         IF  EMODE#0 AND  DEF&NOTINLOOK#0 THEN  ERR = CHINLOOK AND  ->BAD
                                         ! ATTEMPT TO CHANGE WHILE LOOKING
         IF  DEF&ALLPAR=0 THEN  ->NOPARAM; ! REQUIRES NO PARAMAETERS
         CYCLE 
            K = NEXTSYMBOL
            ->BAD IF  K=NL AND  LEVEL=0
            EXIT  IF  K>' '
            SKIPSYMBOL
         REPEAT 
         J = CHARTYPE(K)
         IF  J=MINUS START ;             ! '- SIGNIFIES BACKWARDS
            IF  DEF&BACKWARDS=0 THEN  ->BAD
            CFLAGS = CFLAGS!BACKWARDS
            SKIPSYMBOL AND  K = NEXTSYMBOL UNTIL  K>' '
            J = CHARTYPE(K)
         FINISH 
         ->SUB(J);                       ! SWITCH ON FIRST PARAMETER CH
SUB(NUMCHAR):                            ! NUMERIC PARAM (INCLUDES *)
         ->BAD IF  DEF&NUMPAR=0;         ! NOT ALLOWED
         ->BAD IF  READI(PARVAL)=0;      ! NOT VALID
         IF  (SYM='L' OR  SYM='J') AND  PARVAL#0 START 
            *LSS_PARVAL; *IMDV_1000; *IMDV_100
            *ST_I; *LSS_TOS ; *ST_J
            *LSS_TOS ; *ST_K
            IF  I=0 THEN  I=SLINEST
            IF  J=0 THEN  J=SPARAST
            IF  K=0 THEN  K=SLINEL
         ->BAD UNLESS  0<I<K AND  0<J<K AND  K<=132 AND  J<=50
         FINISH 
         CFLAGS = CFLAGS!NUMPAR
         ->NOPARAM
SUB(TEXTCHAR):                           ! TEXT PARAMETER
         ->BAD IF  DEF&TEXTPAR=0;        ! TEXT PARAM NOT ALLOWED
         IF  K#'''' START ;              ! NOT A SINGLE QUOTE
            ->BAD IF  READTEXT=0;        ! NOT GIVEN CORRECTLY
            LASTREC(LRPTR) = TXT;        ! SAVE PARAM FOR FUTURE '
         FINISHELSESTART ;               ! ' PARAM. RECOVER PREVIOUS TEXT
            SKIPSYMBOL
            ->BAD UNLESS  LASTREC(LRPTR)_LP#0
            COPY(ADDR(LASTREC(LRPTR)))
         FINISH 
         PARVAL = ADDR(TXT)
         CFLAGS = CFLAGS!TEXTPAR
         ->NOPARAM
SUB(FILECHAR):                           ! '<'
         ->BAD IF  DEF&FILEPAR=0
         ->BAD IF  READTEXT=0
         CFLAGS = CFLAGS!FILEPAR
         PARVAL = ADDR(TXT)
NOPARAM:                                 ! PARAM NOT REQUIRED OR FOUND OK
         IF  DEF&SPECIAL#0 START ;       ! SPECIAL ACTIONS HERE
            IF  SYM='H' THEN  HSET = 1
            IF  SYM='C' THENSTART 
               IF  PARVAL>COMP THEN  PARVAL = COMP
               CYCLE  COMP = COMP-1,-1,COMP-PARVAL
                  IF  CLIST(COMP)_FLAGS&TEXTPAR#0 THEN  C 
                     J = RETURNCELL(CLIST(COMP)_PAR)
               REPEAT 
               IF  COMP=0 THEN  LEVEL = 0 ELSE  LEVEL = CLIST(COMP-1)_LEVEL
               IF  LEVEL=0 THEN  PROMPT(PRSTRING) ELSE  PROMPT("):")
               CONTINUE 
            FINISH 
         FINISH 
         GOODCOMMAND(SYM,CFLAGS,PARVAL)
      REPEAT 
      RESULT  = LINECOMPLETE
ROUTINE  GOODCOMMAND(INTEGER  SYM,FLAGS,PARAM)
!***********************************************************************
!*    RECORD A GOOD COMMAND
!***********************************************************************
INTEGER  LAB,I
      IF  COMP>99 START 
         PRINTSTRING("TOO MANY COMMANDS".SNL)
         EXIT(0);                        ! FORCE EDIT E
         SIGNAL  EVENT  12,3
      FINISH 
      IF  COMP=0 AND  LCOMP>0 START ;   ! THROW PREVIOUS COMMAND STRING
         I = 0
         UNTIL  I=LCOMP CYCLE 
            CUR COM==CLIST(I)
            IF  CURCOM_FLAGS&(TEXTPAR!FILEPAR)#0 THEN  C 
               J = RETURNCELL(CURCOM_PAR)
            I = I+1
         REPEAT 

         LCOMP=0
      FINISH 
      IF  'A'<=SYM<='Z' THEN  LAB = COMDEF(SYM)>>16 ELSE  LAB = 0
      IF  FLAGS&(TEXTPAR!FILEPAR)=0 THEN  LAB = LAB>>8
      CURRCOMP == CLIST(COMP)
      COMP = COMP+1
      CURRCOMP = 0
      CURRCOMP_LETT = SYM
      CURRCOMP_FLAGS = FLAGS
      IF  FLAGS&ERROR=0 THEN  CURRCOMP_PAR = PARAM ELSE  CURRCOMP_ERRNO = PARAM
      CURRCOMP_LEVEL = LEVEL
      CURRCOMP_SWNO <- LAB;              ! TO BE REVISED
END 
ROUTINE  BADCOMMAND(INTEGER  SYM,ERRNO)
      GOODCOMMAND(SYM,ERROR,ERRNO)
END 
END 
ROUTINE  ERMESS(INTEGER  NO,LETT)
!***********************************************************************
!*    OUTPUTS AN ERROR MESSAGE
!***********************************************************************
STRING (60) A,B,C
CONSTSTRING (36)ARRAY  ETEXT(0:5)=
         "Syntax error in command string",
         "Invalid loop repetition count",
         "## not allowed when '&&'ing",
         "Separator S not set for ##",
         "Cannot create private lexicon",
         "No word set up for Y command"
      A=ETEXT(NO)
      IF  A->B.("##").C THEN  A=B.TOSTRING(LETT).C
      IF  A->B.("&&").C THEN  A=B.PRT(EMODE).C
      PRINTSTRING(A.SNL)
END 
ROUTINE  FORCLOSE(INTEGER  CLASS,SUBCLASS)
!***********************************************************************
!*    THIS IS CALLED AFTER A SYSTEM CONTINGENCY. INVOKE EXIT           *
!*    TO TRY TO SALVAGE EDITING BEFORE PASSING BACK TO SUBSYSTEM       *
!***********************************************************************
INTEGER  FLAG
CONSTBYTEINTEGERARRAY  ECODE('V'&15:'Y'&15)=2,1,2,3;
      REROUTECONTINGENCY(0,0,0,FORCLOSE,FLAG); ! CANCELL REROUTE
      EXIT(ECODE(SUBCLASS&15));                ! TRY TO END TIDILY
      SIGNAL(3,CLASS,SUBCLASS,FLAG)
END ;                                    ! OF FORCLOSE
ROUTINE  INITIALISE(INTEGERNAME  FLAG)
!***********************************************************************
!*    THIS ROUTINE HAS INITIALISING THAT IS ALSO REQUIRED AFTER W      *
!***********************************************************************
      PROMPT(PRSTRING)
      NEWNEWF = 0;                       !INDICATES NEW NEWF CREATED
      NEWG = 0;                          !INDICATES REQUIREMENT TO CALL NEWGEN BE
      ETERMINATE = 0;                    !INITIALISE
      FILEUSEDCOUNT = 0
      SETPAR(S);                         ! STATICISE PARAMS
      UNLESS  PARMAP=3 THEN  FLAG=263 AND  RETURN ;! WRONG NO OF PARAMS
      OLDF = SPAR(1);                    !FIRST PARAM
      NEWF = SPAR(2)
      CHECKFF(FLAG)
      RETURN  IF  FLAG#0
!
!             CMODE  NEWF  CYF  NEWNEWF  NEWG  OLDF
! OLDF=NEWF
!   NEWF exists
!     member    0    T#EH  NEWF*   0      0    NEWF*
!     file      3    T#EH  null    0      1    NEWF*
!   NEWF does not exist
!     member    0    T#EH  NEWF*   1      0    .NEW
!     file      3    NEWF* null    1      0    .NEW
! OLDF#NEWF
!   NEWF exists
!     member    0    T#EH  NEWF*   0      0    OLDF*
!     file      3    NEWF* null    0      0    OLDF*
!   NEWF does not exist
!     member    0    T#EH  NEWF*   1      0    OLDF*
!     file      3    NEWF* null    1      0    OLDF*
!
! (NEWF* and OLDF* are the original values of NEWF and OLDF).
!
! After CHECKFF has been called, and provided it
! returns a zero flag, then:
!   1.  The file whose name is the final value of NEWF exists and is
!       usable.  This is the file in which the edited text must be
!       constructed when "E" or "W" is requested.
!   2.  If OLDF # ".NEW" then the file whose name is the final value
!       of OLDF exists and is usable.  This is the file containing the
!       text to be edited.  If OLDF is ".NEW", then there is no such
!       text.
!   3.  CYF is non-null if and only if NEWF* specified a member of
!       a partitioned file.  In that case, NEWPDF will have the
!       partitioned file name, and NEWPDM will have the member name.
!       On "E" or "W", after the edited text has been constructed in
!       NEWF, then NEWF must be copied into NEWPDF_NEWPDM.
!   4.  If NEWG # 0, then after the edited text has been constructed
!       in NEWF, we must do NEWGEN(NEWF,OLDF) to complete the
!       processing of "E" or "W".
!   5.  If 3 or 4 does not apply, then no further action is required
!       for "E" or "W" beyond constructing the edited text in NEWF.
!   6.  NEWNEWF will be non-zero if and only if NEWF* did not exist
!       before the editor was entered.  It is used in handling "Q"
!       to determine whether NEWF needs to be DESTROYed.
!
      BOT == RECORD(NEWCELL)
      TOP == RECORD(NEWCELL)
      HTOP==RECORD(NEWCELL)
      HBOT==RECORD(NEWCELL)
      HTOP_RL=ADDR(HBOT)
      HBOT_LL=ADDR(HTOP)
      BOTA = ADDR(BOT_LL)
      TOP_RL = BOTA
      TOPA = ADDR(TOP_LL)
      BOT_LL = TOPA
      CUR == BOT
      CURP = 0
      ALTERED=0
      CHANGED=0;                        ! NEEDS RESETIING AFTER INSERTING FILE
      SETA = 0
      IF  OLDF#".NEW" THENSTART 
         IF  INTEGER(CADOLD)>INTEGER(CADOLD+4) START 
                                         !FILE CONTAINS SOMETHING
            TXT == RECORD(NEWCELL)
            TXT_LP = CADOLD+INTEGER(CADOLD+4)
            TXT_RP = CADOLD+INTEGER(CADOLD)-1
            INSERT
            IF  EMODE#2 START ;          !MOVE CURSOR TO *T* EXCEPT FOR RECALL
               CUR == RECORD(TOP_RL)
               CURP = CUR_LP
            FINISH 
         FINISH 
      FINISH 
      CHANGED = 0;                       !USED TO DETERMINE WHETHER FILE HAS BEEN
      ALTERED=0;                        ! TO DETERMINE WHEN TO COPY LIST
      HALTERED=-1;                      ! FORCE COPY BEFORE 1ST COMMAND
      HSAVE
END 
END ;                                    !OF ED
ENDOFFILE