PROCEDURE MOVEIT; VAR SCROLLMARK,X,LINE,I: INTEGER; EXITPROMPT: BOOLEAN; (* PROMPT AFTER LEAVING MOVEIT! *) OLDLINE,OLDX: INTEGER; NEWDIST,DIST: INTEGER; DOFFSCREEN,ATEND,INREPLACE,INDELETE: BOOLEAN; PTR,ANCHOR,OLDCURSOR: PTRTYPE; PROCEDURE SCROLLUP(BOTTOMLINE:PTRTYPE; HOWMANY: INTEGER); (* bottomline is the "linestart" of the line to be scrolled up *) VAR PTR: PTRTYPE; I: INTEGER; BEGIN (* DISPLAY THE NEXT LINE ON THE BOTTOM OF THE SCREEN *) I:=0; PTR:=SCAN(MAXCHAR,=CHR(EOL),EBUF^[LINE1PTR])+LINE1PTR+1; WHILE (I=HOWMANY) OR (BOTTOMLINE>=BUFCOUNT-1); EXITPROMPT:=TRUE; END(* SCROLLUP *); PROCEDURE CLEAR(X1,Y1,X2,Y2: INTEGER); FORWARD; PROCEDURE CENTER; BEGIN IF INDELETE THEN BEGIN IF LINE>=SCREENHEIGHT THEN BEGIN CENTERCURSOR(LINE,2,TRUE); IF ABS(CURSOR-ANCHOR) > ABS(DIST) THEN CLEAR(0,1,MAX(X-1,0),LINE) END ELSE BEGIN CENTERCURSOR(LINE,SCREENHEIGHT-1,TRUE); GOTOXY(X,LINE); IF ABS(CURSOR-ANCHOR) > ABS(DIST) THEN WRITE(CHR(11)) END; DOFFSCREEN:=TRUE; END ELSE IF (COMMAND=PARAC) AND ((DIRECTION='<') OR (LINE MOD SCREENHEIGHT=OLDLINE)) THEN CENTERCURSOR(LINE,OLDLINE,TRUE) ELSE CENTERCURSOR(LINE,MIDDLE,TRUE); IF EXITPROMPT AND (COMMAND<>QUITC) THEN BEGIN PROMPT; EXITPROMPT:=FALSE END; OLDLINE:=LINE; OLDX:=X; END; PROCEDURE UPMOVE; VAR I:INTEGER; BEGIN I:=1; GETLEADING; (* FIND THE LINE FIRST *) WHILE (I<=REPEATFACTOR) AND (LINESTART>1) DO BEGIN CURSOR:=LINESTART-1; (* LAST CHAR OF LINE ABOVE *) GETLEADING; LINE:=LINE-1; I:=I+1; END; (* If possible set the cursor at the same x coord we came from. Otherwise, set it either to the beginning of the buffer, the beginning of text on that line, or the end of the text on that line *) CURSOR:= MAX(1, (* The beginning of the buffer *) MAX(STUFFSTART, (* The beginning of the text *) MIN(X-BLANKS+BYTES+LINESTART, (* same col *) SCAN(MAXCHAR,=CHR(EOL),EBUF^[CURSOR])+CURSOR (* eol *) ) ) ); IF LINE<1 THEN CENTER; END(* UPALINE *); PROCEDURE DOWNMOVE; VAR I: INTEGER; NEXTEOL: PTRTYPE; BEGIN I:=1; NEXTEOL:=SCAN(MAXCHAR,=CHR(EOL),EBUF^[CURSOR])+CURSOR; WHILE (NEXTEOLSCREENHEIGHT THEN IF (LINE-SCREENHEIGHT>=SCREENHEIGHT) OR (INDELETE) THEN CENTER ELSE SCROLLUP(SCROLLMARK,LINE-SCREENHEIGHT); GETLEADING; (* If possible set the cursor at the same x coord we came from. Otherwise, set it either to the end of the buffer, the beginning of text on that line, or the end of the text on that line *) CURSOR:=MIN(BUFCOUNT-1, (* End of the buffer *) MAX(STUFFSTART, (* Not in the indentation *) MIN(X-BLANKS+BYTES+LINESTART (* Where it wants to be *) ,SCAN(MAXCHAR,=CHR(EOL),EBUF^[CURSOR])+CURSOR ) ) ); END(* DOWNMOVE *); PROCEDURE LEFTMOVE; BEGIN GETLEADING; (* SET LINESTART AND STUFFSTART *) WHILE (STUFFSTART>CURSOR-REPEATFACTOR) AND (CURSOR>REPEATFACTOR) DO BEGIN REPEATFACTOR:=REPEATFACTOR-(CURSOR-STUFFSTART+1); (* CHARS MOVED OVER *) IF EBUF^[CURSOR]=CHR(EOL) THEN CURSOR:=CURSOR-1; CURSOR:=MAX(SCAN(-MAXCHAR,=CHR(EOL),EBUF^[CURSOR])+CURSOR,1); LINE:=LINE-1; GETLEADING; (* RESET LINESTART AND STUFFSTART *) END; CURSOR:=MAX(CURSOR-REPEATFACTOR,1); IF LINE<1 THEN CENTER; FINDXY(X,LINE); END (* LEFTMOVE *); PROCEDURE RIGHTMOVE; VAR EOLPTR: PTRTYPE; BEGIN EOLPTR:=SCAN(MAXCHAR,=CHR(EOL),EBUF^[CURSOR])+CURSOR; WHILE (EOLPTRSCREENHEIGHT THEN IF (LINE-SCREENHEIGHT>=SCREENHEIGHT) OR (INDELETE) THEN CENTER ELSE SCROLLUP(SCROLLMARK,LINE-SCREENHEIGHT); CURSOR:=MIN(BUFCOUNT-1,CURSOR+REPEATFACTOR); FINDXY(X,LINE); END(* RIGHTMOVE *); PROCEDURE LINEMOVE(REPEATFACTOR: INTEGER); VAR I: INTEGER; BEGIN I:=1; IF DIRECTION='<' THEN BEGIN WHILE (I<=REPEATFACTOR) AND (CURSOR>1) DO BEGIN IF EBUF^[CURSOR]=CHR(EOL) THEN CURSOR:=CURSOR-1; (* NULL LINE CASE *) CURSOR:=SCAN(-MAXCHAR,=CHR(EOL),EBUF^[CURSOR])+CURSOR; (* 1 UP *) IF CURSOR>=1 THEN BEGIN LINE:=LINE-1; I:=I+1 END; END; CURSOR:=MAX(1,CURSOR); (* BACK INTO REALITY *) ATEND:= (CURSOR=1); IF LINE<1 THEN CENTER END ELSE BEGIN (* DIRECTION='>' *) WHILE (I<=REPEATFACTOR) AND (CURSOR=BUFCOUNT-1); IF LINE>SCREENHEIGHT THEN IF (LINE-SCREENHEIGHT>=SCREENHEIGHT) OR (COMMAND=PARAC) OR INDELETE THEN CENTER ELSE IF INREPLACE THEN BEGIN WRITE(CHR(LF)); LINE:=LINE-1; PTR:=SCAN(MAXCHAR,=CHR(EOL),EBUF^[LINE1PTR])+LINE1PTR+1; IF PTR<=BUFCOUNT-1 THEN LINE1PTR:=PTR; END ELSE SCROLLUP(SCROLLMARK,LINE-SCREENHEIGHT); CURSOR:=MIN(CURSOR,BUFCOUNT-1) END; GETLEADING; CURSOR:=STUFFSTART; (* FORCED TO BEGINNING OF STUFF *) X:=BLANKS; END(* LINEMOVE *); PROCEDURE JUMPBEGIN; BEGIN CURSOR:=1; CENTERCURSOR(TRASH,1,FALSE) END; PROCEDURE JUMPEND; BEGIN CURSOR:=BUFCOUNT-1; CENTERCURSOR(TRASH,SCREENHEIGHT,FALSE) END; PROCEDURE ADJUSTING; LABEL 1; TYPE MODES=(RELATIVE,LEFTJ,RIGHTJ,CENTER); VAR LLENGTH,TDELTA,I: INTEGER; SAVEDIR: CHAR; MODE: MODES; PROCEDURE DOIT(DELTA:INTEGER); VAR EOLDIST: INTEGER; T: PACKED ARRAY [0..MAXSTRING] OF CHAR; BEGIN GETLEADING; (* Set linestart, stuffstart, and blanks *) IF BLANKS+DELTA<0 THEN DELTA:=-BLANKS; IF (EBUF^[LINESTART]=CHR(DLE)) AND (STUFFSTART-LINESTART=2) THEN X:=ORD(EBUF^[LINESTART+1])+DELTA-32 ELSE BEGIN IF STUFFSTART-LINESTART>2 THEN MOVELEFT(EBUF^[STUFFSTART],EBUF^[LINESTART+2],BUFCOUNT-STUFFSTART) ELSE BEGIN IF BUFCOUNT>BUFSIZE-100 THEN BEGIN ERROR('Buffer overflow',NONFATAL); EXIT(ADJUSTING) END ELSE MOVERIGHT(EBUF^[STUFFSTART],EBUF^[LINESTART+2],BUFCOUNT-STUFFSTART); END; IF LINESTART+2<>STUFFSTART THEN BEGIN READJUST(LINESTART,LINESTART+2-STUFFSTART); BUFCOUNT:=BUFCOUNT+LINESTART+2-STUFFSTART; END; EBUF^[LINESTART]:=CHR(DLE); X:=BLANKS+DELTA; END; EBUF^[LINESTART+1]:=CHR(X+32); CURSOR:=LINESTART+2; GETLEADING; GOTOXY(0,LINE); ERASETOEOL; (* erase the line *) LINEOUT(LINESTART,BYTES,BLANKS,LINE); GOTOXY(X,LINE); END(* DOIT *); BEGIN (* adjusting *) WITH PAGEZERO DO BEGIN SAVEDIR:=DIRECTION; EXITPROMPT:=FALSE; INDELETE:=FALSE; LASTPAT:=CURSOR; INREPLACE:=TRUE; PROMPTLINE:= ' Adjust: L(just R(just C(enter { to leave}'; PROMPT; NEEDPROMPT:=TRUE; MODE:=RELATIVE; SHOWCURSOR; FINDXY(X,LINE); TDELTA:=0; REPEAT CH:=GETCH; COMMAND:=TRANSLATE[CH]; INFINITY:=FALSE; IF COMMAND=SLASHC THEN BEGIN REPEATFACTOR:=1; INFINITY:=TRUE; CH:=GETCH; COMMAND:=TRANSLATE[CH] END ELSE IF COMMAND=DIGIT THEN REPEATFACTOR:=GETNUM ELSE REPEATFACTOR:=1; IF COMMAND IN [UP,DOWN] THEN BEGIN IF COMMAND=UP THEN DIRECTION:='<' ELSE DIRECTION:='>'; I:=1; ATEND:=FALSE; WHILE NOT ATEND AND ((I<=REPEATFACTOR) OR INFINITY) DO BEGIN I:=I+1; LINEMOVE(1); IF NOT ATEND THEN BEGIN IF MODE=RELATIVE THEN DOIT(TDELTA) ELSE BEGIN LLENGTH:=SCAN(MAXCHAR,=CHR(EOL),EBUF^[STUFFSTART]); CASE MODE OF LEFTJ: DOIT(LMARGIN-BLANKS); RIGHTJ: DOIT((RMARGIN-LLENGTH+1)-BLANKS); CENTER: DOIT(((RMARGIN-LMARGIN+1)-LLENGTH) DIV 2-BLANKS+LMARGIN) END (* case *) END (* else *) END; (* if not atend *) END (* while ... *) END ELSE IF COMMAND=LEFT THEN BEGIN DOIT(-REPEATFACTOR); TDELTA:=TDELTA-REPEATFACTOR; MODE:=RELATIVE END ELSE IF COMMAND=RIGHT THEN BEGIN DOIT(REPEATFACTOR); TDELTA:=TDELTA+REPEATFACTOR; MODE:=RELATIVE END ELSE IF COMMAND IN [LISTC,REPLACEC,COPYC] THEN BEGIN GETLEADING; LLENGTH:=SCAN(MAXCHAR,=CHR(EOL),EBUF^[STUFFSTART]); IF COMMAND=LISTC THEN BEGIN MODE:=LEFTJ; DOIT(LMARGIN-BLANKS) END ELSE IF COMMAND=REPLACEC THEN BEGIN MODE:=RIGHTJ; DOIT((RMARGIN-LLENGTH+1)-BLANKS) END ELSE (* COMMAND=COPYC *) BEGIN MODE:=CENTER; DOIT(((RMARGIN-LMARGIN+1)-LLENGTH) DIV 2-BLANKS+LMARGIN) END END ELSE IF CH<>CHR(ETX) THEN BEGIN ERRWAIT; SHOWCURSOR END; 1: UNTIL CH=CHR(ETX); DIRECTION:=SAVEDIR; END; END; FUNCTION TABBY: INTEGER; BEGIN IF REPEATFACTOR > 0 THEN IF DIRECTION = '>' THEN TABBY:=8*(REPEATFACTOR-1)+ 8-X+ORD(ODD(X) AND ODD(248)) ELSE BEGIN IF X=0 THEN TABBY:=REPEATFACTOR*8 ELSE TABBY:=8*(REPEATFACTOR-1)+X-ORD(ODD(X-1) AND ODD(248)) END ELSE TABBY:=0 END; PROCEDURE MOVING; BEGIN INDELETE:=FALSE; INREPLACE:=FALSE; EXITPROMPT:=FALSE; IF INFINITY THEN BEGIN CASE COMMAND OF UP,LEFT: JUMPBEGIN; DOWN,RIGHT: JUMPEND; SPACE,ADVANCE,TAB: IF DIRECTION='<' THEN JUMPBEGIN ELSE JUMPEND END; NEEDPROMPT:=TRUE; NEXTCOMMAND; EXIT(MOVEIT) END; FINDXY(X,LINE); REPEAT OLDX:=X; OLDLINE:=LINE; CASE COMMAND OF LEFT: LEFTMOVE; RIGHT: RIGHTMOVE; SPACE: IF DIRECTION='<' THEN LEFTMOVE ELSE RIGHTMOVE; UP: UPMOVE; DOWN: DOWNMOVE; ADVANCE: LINEMOVE(REPEATFACTOR); PARAC: IF REPEATFACTOR>1000 THEN ERROR('Too many',NONFATAL) ELSE LINEMOVE(SCREENHEIGHT*REPEATFACTOR); TAB: BEGIN IF REPEATFACTOR >= 4096 THEN ERROR('Integer Overflow',NONFATAL) ELSE BEGIN REPEATFACTOR:=TABBY; IF DIRECTION='<' THEN LEFTMOVE ELSE RIGHTMOVE; REPEATFACTOR:=1; WHILE X MOD 8<>0 DO IF DIRECTION='<' THEN LEFTMOVE ELSE RIGHTMOVE; END END END; IF LINE=OLDLINE THEN BEGIN IF X=OLDX+1 THEN CONTROL(FS) ELSE IF X=OLDX-1 THEN WRITE(CHR(BS)) ELSE GOTOXY(X,LINE) END ELSE IF X=OLDX THEN BEGIN IF LINE=OLDLINE+1 THEN WRITE(CHR(LF)) ELSE IF LINE=OLDLINE-1 THEN CONTROL(US) ELSE GOTOXY(X,LINE); END ELSE GOTOXY(X,LINE); REPEATFACTOR:=1; NEXTCOMMAND UNTIL NOT (COMMAND IN [UP,DOWN,LEFT,RIGHT,ADVANCE,SPACE,TAB]); IF EXITPROMPT THEN PROMPT; SHOWCURSOR; END (* MOVING *); PROCEDURE PUTITBACK(C1,C2: PTRTYPE); VAR PTR: PTRTYPE; INDENT,LOFF: INTEGER; BEGIN PTR:=C1; WHILE PTR<=C2 DO BEGIN IF EBUF^[PTR]=CHR(EOL) THEN BEGIN PTR:=PTR+1; WRITELN; INDENT:=LEADBLANKS(PTR,LOFF); IF (PTR0) THEN WRITE(' ':INDENT); PTR:=PTR+LOFF END ELSE BEGIN WRITE(EBUF^[PTR]); PTR:=PTR+1 END; END; END; PROCEDURE CLEAR(*X1,Y1,X2,Y2: INTEGER*); (* Screen co-ordinate (X1,Y1) is assumed to be before (X2,Y2). This procedure takes these co-ordinates and clears (writes blanks) over the screen between them (inclusive) *) VAR I: INTEGER; BEGIN GOTOXY(X1,Y1); FOR I:=Y1 TO Y2-1 DO BEGIN IF I<>0 THEN ERASETOEOL; WRITELN END; IF Y1<>Y2 THEN FOR I:=0 TO X2 DO WRITE(' ') ELSE FOR I:=X1 TO X2 DO WRITE(' ') END; PROCEDURE RESOLVESCREEN; VAR X1,X2,Y1,Y2,SAVE: INTEGER; C1,C2: PTRTYPE; BEGIN X1:=X; Y1:=LINE; X2:=OLDX; Y2:=OLDLINE; IF NEWDIST>DIST THEN BEGIN C1:=CURSOR-1; C2:=OLDCURSOR; X1:=X1-1 END ELSE IF NEWDISTY2) OR ((Y1=Y2) AND (X1>X2)) THEN BEGIN SAVE:=C1; C1:=C2; C2:=SAVE; SAVE:=Y1; Y1:=Y2; Y2:=SAVE; SAVE:=X1; X1:=X2; X2:=SAVE END; IF ABS(NEWDIST)>ABS(DIST) THEN CLEAR(X1,Y1,X2,Y2) ELSE BEGIN GOTOXY(X1,Y1); PUTITBACK(C1,C2) END; GOTOXY(X,LINE) END; PROCEDURE DELETING; LABEL 1; VAR ATBOL,ANCHOR,SAVE: PTRTYPE; OK,ATBOT,NOMOVE: BOOLEAN; STARTLINE: INTEGER; BEGIN DOFFSCREEN:=FALSE; INDELETE:=TRUE; INREPLACE:=FALSE; EXITPROMPT:=FALSE; ANCHOR:=CURSOR; NEWDIST:=0; GETLEADING; ATBOL:=LINESTART; ATBOT:=(CURSOR=STUFFSTART); PROMPTLINE:= ' Delete: < > { to delete, to abort}'; PROMPT; NEEDPROMPT:=TRUE; SHOWCURSOR; FINDXY(X,LINE); STARTLINE:=LINE; REPEAT OLDCURSOR:=CURSOR; DIST:=NEWDIST; OLDX:=X; OLDLINE:=LINE; CH:=GETCH; COMMAND:=TRANSLATE[CH]; IF COMMAND=DIGIT THEN REPEATFACTOR:=GETNUM ELSE REPEATFACTOR:=1; IF COMMAND IN [REVERSEC..DIGIT,ADVANCE,SPACE] THEN BEGIN CASE COMMAND OF LEFT: LEFTMOVE; RIGHT: RIGHTMOVE; SPACE: IF DIRECTION='<' THEN LEFTMOVE ELSE RIGHTMOVE; UP: UPMOVE; DOWN: DOWNMOVE; ADVANCE: LINEMOVE(REPEATFACTOR); REVERSEC,FORWARDC: BEGIN IF COMMAND=REVERSEC THEN DIRECTION:='<' ELSE DIRECTION:='>'; GOTOXY(0,0); WRITE(DIRECTION); GOTOXY(X,LINE) END; TAB: BEGIN IF REPEATFACTOR>=4096 THEN ERROR('Integer Ovflw',NONFATAL) ELSE BEGIN REPEATFACTOR:=TABBY; IF DIRECTION='<' THEN LEFTMOVE ELSE RIGHTMOVE END END END; NEWDIST:=CURSOR-ANCHOR; RESOLVESCREEN; END ELSE IF (CH<>CHR(ESC)) AND (CH<>CHR(ETX)) THEN BEGIN ERRWAIT; GOTOXY(X,LINE) END UNTIL (CH IN [CHR(ETX),CHR(ESC)]); IF CH=CHR(ETX) THEN BEGIN GETLEADING; (* Indentation fixup *) IF ATBOT AND (CURSOR=STUFFSTART) THEN BEGIN CURSOR:=LINESTART; SAVE:=ANCHOR; ANCHOR:=ATBOL END; IF OKTODEL(CURSOR,ANCHOR) THEN BEGIN READJUST(MIN(CURSOR,ANCHOR),-ABS(CURSOR-ANCHOR)); COPYLINE:=(CURSOR=LINESTART) AND ATBOT; IF ANCHOR