Google
 

Trailing-Edge - PDP-10 Archives - bb-r775e-bm_tops20_ks_upd_5 - sources/edt/scrupdate.bli
There are 10 other files named scrupdate.bli in the archive. Click here to see a list.
 %TITLE 'SCRUPDATE - update the screen'
MODULE SCRUPDATE (				! Update the screen
		IDENT = '3-003'			! File: SCRUPDATE.BLI Edit: CJG3003
		) =
BEGIN
!
!			  COPYRIGHT (c) 1981, 1985 BY
!	      DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
!		ALL RIGHTS RESERVED.
!
! THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED AND  COPIED
! ONLY  IN  ACCORDANCE  WITH  THE  TERMS  OF  SUCH  LICENSE AND WITH THE
! INCLUSION OF THE ABOVE COPYRIGHT NOTICE.  THIS SOFTWARE OR  ANY  OTHER
! COPIES  THEREOF MAY NOT BE PROVIDED OR OTHERWISE MADE AVAILABLE TO ANY
! OTHER PERSON.  NO TITLE TO AND OWNERSHIP OF  THE  SOFTWARE  IS  HEREBY
! TRANSFERRED.
!
! THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE  WITHOUT  NOTICE
! AND  SHOULD  NOT  BE  CONSTRUED  AS  A COMMITMENT BY DIGITAL EQUIPMENT
! CORPORATION.
!
! DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR  RELIABILITY  OF  ITS
! SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY DIGITAL.
!

!++
! FACILITY:	EDT -- The DEC Standard Editor
!
! ABSTRACT:
!
!	This module does a screen update.
!
! ENVIRONMENT:	Runs at any access mode - AST reentrant
!
! AUTHOR: Bob Kushlis, CREATION DATE: September 8, 1979
!
! MODIFIED BY:
!
! 1-001	- Original.  DJS 12-Feb-1981.  This module was created by
!	extracting the routine EDT$$SC_UPD  from module SCREEN.
! 1-002	- Regularize headers.  JBS 13-Mar-1981
! 1-003	- Make sure the [EOB] test is valid when scrolling backwards.
!	   JBS 17-Sep-1981
! 1-004	- Revise autorepeat subroutine call.  JBS 30-Jan-1982
! 1-005	- Correct some spelling errors in comments.  JBS 02-Apr-1982
! 1-006	- Use new flag for scrolling logic.  JBS 02-Sep-1982
! 1-007 - Use the new screen structure and logic.  SMB 21-Sep-1982
! 1-008	- Remove unused external declaration of EDT$$FMT_LIT.  JBS 05-Oct-1982
! 1-009 - More debugging of screen scrolling and select.  SMB 08-Oct-1982
! 1-010	- Debug NOTRUNCATE mode.  JBS 12-Oct-1982
! 1-011 - Add insert and delete scrolling.  SMB 13-Oct-1982
! 1-012	- Clear RECS_INSERTED.  JBS 21-Oct-1982
! 1-013 - Scrolling debugging.  SMB 21-Oct-1982
! 1-014	- Move the code for marking select changes for repaint.  JBS 23-Oct-1982
! 1-015	- Simplify the logic that repaints the old screen.  JBS 24-Oct-1982
! 1-016	- Make sure all lines off the screen are marked for repaint, and
!	   support non-scrolling-region terminals.  JBS 24-Oct-1982
! 1-017	- Fix a performance problem with deselecting.  JBS 24-Oct-1982
! 1-018	- Watch out for deleted lines when updating the old screen.  JBS 24-Oct-1982
! 1-019	- Create UPDATE_LINE, so we can add fancy screen stuff for inserted and
!	   deleted lines.  JBS 23-Oct-1982
! 1-021 - Add scrolling to inset and delete line code.  SMB 25-Oct-1982
! 1-022 - Fix scrolling bug - add more notruncate code.  SMB 27-Oct-1982
! 1-023	- If we delete the top line, make the next line top.  JBS 01-Nov-1982
! 1-024	- Don't lose the line number if we must repaint but need not rebuild
!	   the screen data base.  JBS 01-Nov-1982
! 1-025	- Add the call to EDT$$FIX_NOTRUNC.  JBS 01-Nov-1982
! 1-026	- Fix a problem scrolling up on a small screen.  JBS 02-Nov-1982
! 1-027	- Speed up deselecting.  JBS 09-Nov-1982
! 1-028	- Rearrange select range processing.  JBS 10-Nov-1982
! 1-029	- Watch out for deleting the last line of the screen.  JBS 11-Nov-1982
! 1-030	- Recover from running out of memory.  JBS 15-Nov-1982
! 1-031 - Fix bug with cuts on noscroll terminal.  SMB 16-Nov-1982
! 1-032 - Fix notruncate bugs.  SMB 23-Nov-1982
! 1-033	- Worry about deleted lines.  JBS 25-Nov-1982
! 1-034	- Make a few efficiency improvements.  JBS 02-Dec-1982
! 1-035 - Add two paramaters to the SC_LNINS routine.  SMB 03-Dec-1982
! 1-036 - Change calculation of distance to select line. STS 07-Dec-1982
! 1-037	- When scrolling down, if we do not have scrolling regions
!	   erase the line that should have scrolled out of view.  JBS 14-Dec-1982
! 1-038 - Fix small bugs with boundary conditions.  SMB 20-Dec-1982
! 1-039	- Remove the edit buffer.  JBS 27-Dec-1982
! 1-040	- Do less repainting on select.  JBS 27-Dec-1982
! 1-041	- Add a missing dot in edit 1-040.  JBS 28-Dec-1982
! 1-042	- Collapse inserts and deletes together.  JBS 28-Dec-1982
! 1-043	- Add more TOP logic, to recover from rebuilds better.  JBS 29-Dec-1982
! 1-044	- Fix a bug that caused unnecessary rebuilding in NOTRUNCATE mode.  JBS 30-Dec-1982
! 1-045 - Modify setting of scrolling regions for multiple inserts.  SMB 30-Dec-1982
! 1-046 - Bug fixes on setting of top and more multiple insert work.  SMB 05-Jan-198f
! 1-047 - Fix bugs introduced in edit 046.  SMB 11-Jan-1983
! 1-048 - Bug fixes for "moving window" problems on deletes.  SMB 14-Jan-1983
! 1-049	- Worry about deleting the only line in the buffer.  JBS 18-Jan-1983
! 1-050	- Fix painting select regions on continuation lines.  JBS 19-Jan-1983
! 1-051	- Be more cautious about using the old cursor line after a rebuild.  JBS 20-Jan-1983
! 1-052 - Fix scrolling problems for NOSCROLL terminals.  SMB 25-Jan-1983
! 1-053 - Repair backwards scrolling bug introduced by edit 1-052.  SMB 26-Jan-1983
! 1-054	- We were updating the screen wrong if all of the following happened:
!	   1) we reset the screen, 2) we show the current position, and 3) we
!	   must jump to, rather than scroll to, the new position.  In showing
!	   the new position we should not assume that the screen is still erased.  JBS 28-Jan-1983
! 1-055	- Fix unreversing of backward select ranges.  JBS 28-Jan-1983
! 1-056 - Fix VT52 erase to end of screen bug with messages.  SMB 01-Feb-1983
! 1-057 - Avoid excess repainting after a CUT that crosses a line boundry.  JBS 25-Feb-1983
! 1-058	- Don't initialize the screen so often.  JBS 02-Mar-1983
! 1-059	- Mark the select region better on continued lines.  JBS 07-Mar-1983
! 3-001 - Add updates from V3 sources. GB 03-May-1983
! 3-002 - Fix translation bug in TOP command. CJG 6-Oct-1983
! 3-003 - Modify ASSERT macro to include error code. CJG 30-Jan-1984
!--
%SBTTL 'Declarations'
!
! TABLE OF CONTENTS:
!

REQUIRE 'EDTSRC:TRAROUNAM';

FORWARD ROUTINE
    EDT$$SC_UPD : NOVALUE,
    DELETE_LINE,
    INSERT_LINE;

!
! INCLUDE FILES:
!

REQUIRE 'EDTSRC:EDTREQ';

!
! MACROS:
!
!	NONE
!
! EQUATED SYMBOLS:
!
!	NONE
!
! OWN STORAGE:
!
!	NONE
!
! EXTERNAL REFERENCES:
!
!	In the routine
%SBTTL 'EDT$$SC_UPD  - update the screen'

GLOBAL ROUTINE EDT$$SC_UPD 			! Update the screen
    : NOVALUE =

!++
! FUNCTIONAL DESCRIPTION:
!
!	This routine is called to do a screen update.  Most of the work done
!	by this routine involves deciding on whether or not scrolling should
!	be done.  Basically, it figures out which line should be on the top
!	of the screen, then determines how far away from the current line it
!	has moved.  The actual update is handled by the EDT$$SC_RFRELN routine.
!
! FORMAL PARAMETERS:
!
!	NONE
!
! IMPLICIT INPUTS:
!
!	OLD_SEL
!	LNO_EMPTY
!	SCR_REBUILD
!	EOB_SCRPTR
!	SCR_CHGD
!	LN_BUF
!	LST_SCRPTR
!	CUR_SCRPTR
!	WK_LN
!	EOB_LN
!	SCR_BUF
!	FST_SCRPTR
!	CS_CHNO
!	CS_OLDCHNO
!	CS_LN
!	CS_LNO
!	CUR_COL
!	LN_NO
!	SEL_BUF
!	TOP_LN
!	CUR_BUF
!	SCR_LNS
!	SCLL_TOP
!	SCLL_BOT
!	TI_TYP
!	LN_PTR
!	TI_SCROLL
!	CSR_SCRPTR
!	TOP_SCRPTR
!	BOT_SCRPTR
!	CUR_SCRLN
!	FST_AVLN
!	TRUN
!	RECS_INSERTED
!	BOT_LINE
!
! IMPLICIT OUTPUTS:
!
!	OLD_SEL
!	SCR_REBUILD
!	CSR_SCRPTR
!	TOP_SCRPTR
!	CUR_SCRLN
!	SEL_BUF
!	CS_CHNO
!	CS_OLDCHNO
!	CS_LN
!	CS_LNO
!	LN_NO
!	TOP_LN
!	CUR_COL
!	RECS_INSERTED
!	FST_AVLN
!	BOT_SCRPTR
!	MEM_CNT
!	BOT_LINE
!
! ROUTINE VALUE:
!
!	NONE
!
! SIDE EFFECTS:
!
!	MANY
!
!--

    BEGIN

    EXTERNAL ROUTINE
	EDT$$CMP_LNO,			! Compare line numbers
	EDT$$SC_SETSCLLREG,		! Set the scrolling region
	EDT$$SC_LNINS,			! Insert a record into the screen data base
	EDT$$FMT_LIT,			! Output a literal string
	EDT$$SC_FNDREC,			! Find the current screen pointer
	EDT$$OUT_FMTBUF,		! Output the format buffer to the screen
	EDT$$RPL_CHGDLN,		! Replace a modified line in the work file
	EDT$$SC_INIT,			! Initialize the screen
	EDT$$SC_CPUCSPOS : NOVALUE,	! Compute the cursor position
	EDT$$SC_POSCSIF : NOVALUE,	! Position the cursor
	EDT$$SC_ERAALL : NOVALUE,	! Erase the screen
	EDT$$SC_MOVTOLN,		! Move to a record in the work file relative to the current record
	EDT$$SC_RFRELN : NOVALUE,	! Refresh a screen lint
	EDT$$SC_NONREVID : NOVALUE,	! Put the screen in normal video mode
	EDT$$SC_REPAINT : NOVALUE,	! Mark some lines in the screen data base for repaint
	EDT$$TI_ENBLAUTREP : NOVALUE,	! Enable or disable autorepeat
	EDT$$FIX_NOTRUNC : NOVALUE;	! Fix screen data base in NOTRUNCATE mode

    EXTERNAL
	BOT_SCRPTR : REF SCREEN_LINE,	! Address of bottom screen line
	OLD_SEL,			! Address of old select buffer
	LNO_EMPTY : LN_BLOCK,		! Code for empty line
	SCR_REBUILD,			! Rebuild the screen
	EOB_SCRPTR : REF SCREEN_LINE,	! EOB screen pointer
	SCR_CHGD,			! non-zero = the screen has been mangled
	MESSAGE_LINE,			! Message line
	LN_BUF,				! Start of line buffer
	CSR_SCRPTR : REF SCREEN_LINE,	! Current cursor line screen info
	CUR_SCRPTR : REF SCREEN_LINE,	! Current workfile line screen pointer
	LST_SCRPTR : REF SCREEN_LINE,	! Last data structure pointer
	WK_LN : REF LIN_BLOCK,		! Pointer to current line in work file
	EOB_LN,				! Special structure for [EOB] line
	SCR_BUF : REF TBCB_BLOCK,	! Current screen buffer
	FST_SCRPTR : REF SCREEN_LINE,	! First screen line info address
	TOP_SCRPTR : REF SCREEN_LINE,	! Top screen line info address
	CUR_SCRLN : LN_BLOCK,		! Current screen line record number
	CS_CHNO,			! character position of cursor
	CS_OLDCHNO,			! Previous character position of cursor
	CS_LN : LN_BLOCK,		! record number of cursor line
	CS_LNO,				! current cursor line
	CUR_COL,			! current cursor column
	LN_NO,				! current line number.
	SEL_POS,			! select character position
	SEL_LN : LN_BLOCK,		! select record
	SEL_BUF,			! select buffer.
	TOP_LN : LN_BLOCK,		! Line number of enforced top line.
	CUR_BUF : REF TBCB_BLOCK,	! The current buffer tbcb.
	SCR_LNS,			! No of lines on screen
	SCLL_TOP,			! Top line for scrolling up
	SCLL_BOT,			! Bottom line for scrolling down
	TI_TYP,				! Terminal type.
	LN_PTR,				! Current character pointer.
	TI_SCROLL,			! 1 = we have scrolling regions
	RECS_INSERTED,			! Number of records inserted since the last screen update
	FST_AVLN : REF SCREEN_LINE,	! List of available screen line data blocks
	TRUN,				! 0 = SET NOTRUNCATE
	MEM_CNT,			! Number of lines in the screen data base
	LNO0,				! Line number of 1
	BOT_LINE;			! All lines below this one have been erased

    LOCAL
	DOLOOPS,			! Code bypass flag
	TOP_DIST,			! Displacement to top scrptr
	TEMP_LINE : LN_BLOCK,		! Temp line number
	TOP_DISP,			! Top line displacement from current
	DIR,				! Direction of motion since last screen update
	SCLL_NUM,			! Scroll line limit
	TOP_SET,			! Top record successfully set
	DISP,				! Displacement from cursor screen line
	ABOVE,				! Number of lines above current
	BUILD_SCR,			! Flag which says rebuild screen
	SCRPTR : REF SCREEN_LINE,	! Address of a current screen line buffer
	CURSOR_POS,			! Column position of cursor
	CURSOR_LINE,			! Number of screen lines before cursor.
	BELOW,				! No. of screen lines below cursor line.
	REC_NO,				! Current relative reocrd number
	OLD_TOP_RECNO,			! Rel record number of old top record
	OLD_BOT_RECNO,			! Rel record number of old bottom record
	TOP_RECNO,			! Rel record number of new top record
	TOP_PTR : REF SCREEN_LINE,	! Address of the top line on the screen
	ERASE_ALL,			! 1 = we have erased the text part of the screen
	LNINS_VAL;			! Value returned by EDT$$SC_LNINS

!+
! Make sure we are in normal video if no select range.
!-

    IF (.SEL_BUF NEQA .CUR_BUF) THEN EDT$$SC_NONREVID ();

!+
! Remember the original character position and relative line number in
! work file terms.
!-
    LN_NO = 0;
    CS_CHNO = CH$DIFF (.LN_PTR, CH$PTR (LN_BUF,, BYTE_SIZE));
    MOVELINE (CUR_BUF [TBCB_CUR_LIN], CS_LN);
    EDT$$RPL_CHGDLN ();
!+
! If we are in NOTRUNCATE mode, make sure lines get adjusted due to carry from
! or borrow to earlier lines.
!-

    IF ( NOT .TRUN) THEN EDT$$FIX_NOTRUNC ();

    SCRPTR = 0;
!+
! Compute the cursor position.  We will recompute if we must rebuild the screen data base.
!-
    EDT$$SC_CPUCSPOS (CURSOR_LINE, CURSOR_POS);
    CURSOR_LINE = .CS_LNO;
!+
! If the screen has been mangled, or we have changed buffers, erase the screen and
! repaint all the lines.
!-

    IF ((.SCR_CHGD NEQ 0) OR (.SCR_BUF NEQA .CUR_BUF))
    THEN
	BEGIN
!+
! Don't initialize the terminal unless it has been requested.
!-

	IF (.SCR_CHGD EQL 2) THEN EDT$$SC_INIT ();

!+
! Erase the screen.
!-
	CS_LNO = 0;
	EDT$$SC_ERAALL ();
	BOT_LINE = 0;
	ERASE_ALL = 1;
	END
    ELSE
	ERASE_ALL = 0;

!+
! Determine whether the screen structure has to be rebuilt.
!-
    BUILD_SCR = .SCR_REBUILD;
!+
! If the current position is not in the screen data base, rebuild.
!-

    IF ( NOT .BUILD_SCR)
    THEN
	BEGIN
	CUR_SCRPTR = EDT$$SC_FNDREC (CH$DIFF (.LN_PTR, CH$PTR (LN_BUF,, BYTE_SIZE)), DISP);

	IF ((.CUR_SCRPTR EQLA 0) OR (.TOP_SCRPTR [SCR_NXT_LINE] EQLA 0)) THEN BUILD_SCR = 1;

	END;

!+
! Compute the direction of motion since the last screen update.
! If we have changed buffers, assume forward.
!-

    IF ((EDT$$CMP_LNO (LNO_EMPTY, CUR_SCRLN) EQL 0) OR (.SCR_BUF NEQA .CUR_BUF))
    THEN
	DIR = 1
    ELSE
	DIR = EDT$$CMP_LNO (CS_LN, CUR_SCRLN);

    IF ( NOT .BUILD_SCR)
    THEN
	BEGIN

	IF ((.SEL_BUF NEQA .OLD_SEL) AND (.TI_TYP EQL TERM_VT100))
	THEN
	    BEGIN
!+
! We have started or ended a selection.  Repaint all selected or formerly selected lines.
!-

	    LOCAL
		CHAR_NO,
		SELDIR,
		REC_OFFSET,
		OUR_LINE : LN_BLOCK,
		OUR_CHNO,
		OUR_SCRPTR : REF SCREEN_LINE;

!+
! If this is a deselection we must repaint from the old line to the select line.
! If this is a selection we must repaint from the current line to the select line.
!-

	    IF (.SEL_BUF EQLA 0)
	    THEN
		BEGIN
		MOVELINE (CUR_SCRLN, OUR_LINE);
		SUBLINE (CUR_SCRLN, CS_LN, TEMP_LINE);
		REC_OFFSET = .(TEMP_LINE [LN_LO])<0, 18, 1>;
		OUR_CHNO = .CS_OLDCHNO;
		OUR_SCRPTR = .CSR_SCRPTR;
		END
	    ELSE
		BEGIN
		MOVELINE (CS_LN, OUR_LINE);
		REC_OFFSET = 0;
		OUR_CHNO = .CS_CHNO;
		OUR_SCRPTR = .CUR_SCRPTR;
		END;

	    SUBLINE (OUR_LINE, SEL_LN, TEMP_LINE);

	    IF ((.TEMP_LINE [LN_HI] AND %O'400000') NEQ 0)
	    THEN
		SELDIR = -1
	    ELSE

		IF (.TEMP_LINE [LN_LO] NEQU 0) THEN SELDIR = 1 ELSE SELDIR = 0;

	    REC_NO = .(TEMP_LINE [LN_LO])<0, 18, 1> - .REC_OFFSET;
	    EDT$$SC_MOVTOLN (.REC_NO);
	    SCRPTR = EDT$$SC_FNDREC (CH$DIFF (.SEL_POS, CH$PTR (LN_BUF,, BYTE_SIZE)), DISP);

	    IF (.SCRPTR EQLA 0)
	    THEN
		BUILD_SCR = 1
	    ELSE
		BEGIN

		CHAR_NO = CH$DIFF (.SEL_POS, CH$PTR (LN_BUF,, BYTE_SIZE));
		IF (.SELDIR EQL 0)
		THEN
		    BEGIN

		    IF (.CHAR_NO LSS .OUR_CHNO)	!
		    THEN
			EDT$$SC_REPAINT (.SCRPTR, 	!
			    .OUR_SCRPTR, 	!
			    .CHAR_NO - .SCRPTR [SCR_CHR_FROM],
			    .OUR_CHNO - .OUR_SCRPTR [SCR_CHR_FROM] - 1, 0)
		    ELSE

			IF (.CHAR_NO GTR .OUR_CHNO)	!
			THEN
			    EDT$$SC_REPAINT (.OUR_SCRPTR, 	!
				.SCRPTR, 	!
				.OUR_CHNO - .OUR_SCRPTR [SCR_CHR_FROM], 	!
				.CHAR_NO - .SCRPTR [SCR_CHR_FROM] - 1, 0);

		    END
		ELSE

		    IF (.SELDIR GTR 0)
		    THEN
			EDT$$SC_REPAINT (.OUR_SCRPTR, 	!
			    .SCRPTR, 		!
			    .OUR_CHNO - .OUR_SCRPTR [SCR_CHR_FROM], 	!
			    .CHAR_NO - .SCRPTR [SCR_CHR_FROM] - 1, 0)
		    ELSE

			IF (.SELDIR LSS 0)
			THEN
			    EDT$$SC_REPAINT (.SCRPTR, 	!
				.OUR_SCRPTR, 	!
				.CHAR_NO - .SCRPTR [SCR_CHR_FROM], 	!
				.OUR_CHNO - .OUR_SCRPTR [SCR_CHR_FROM] - 1, 0)
			ELSE
			    ASSERT (22, 0);

		END;
	    END;
	END;


    IF ( NOT .BUILD_SCR)
    THEN
	BEGIN

	IF ((.SEL_BUF EQLA .CUR_BUF) AND (.TI_TYP EQL TERM_VT100))
	THEN
	    BEGIN
!+
! The select range is in the current buffer.  Repaint lines between the previous
! and the current cursor, to be sure they are properly reversed or not.
!-

	    IF (.DIR LSS 0)
	    THEN
		EDT$$SC_REPAINT (.CUR_SCRPTR, .CSR_SCRPTR,
		    .CS_CHNO - .CUR_SCRPTR [SCR_CHR_FROM],
		    .CS_OLDCHNO - .CSR_SCRPTR [SCR_CHR_FROM] - 1, 0)
	    ELSE

		IF (.DIR GTR 0)
		THEN
		    EDT$$SC_REPAINT (.CSR_SCRPTR, .CUR_SCRPTR,
			.CS_OLDCHNO - .CSR_SCRPTR [SCR_CHR_FROM], 	!
			.CS_CHNO - .CUR_SCRPTR [SCR_CHR_FROM] - 1, 0)
		ELSE

		    IF (.CS_CHNO LSS .CS_OLDCHNO)	!
		    THEN
			EDT$$SC_REPAINT (.CUR_SCRPTR, 	!
			    .CSR_SCRPTR, 	!
			    .CS_CHNO - .CUR_SCRPTR [SCR_CHR_FROM],
			    .CS_OLDCHNO - .CSR_SCRPTR [SCR_CHR_FROM] - 1, 0)
		    ELSE

			IF (.CS_CHNO GTR .CS_OLDCHNO)	!
			THEN
			    EDT$$SC_REPAINT (.CSR_SCRPTR, 	!
				.CUR_SCRPTR, 	!
				.CS_OLDCHNO - .CSR_SCRPTR [SCR_CHR_FROM], 	!
				.CS_CHNO - .CUR_SCRPTR [SCR_CHR_FROM] - 1, 0);

	    END;

	END;

!+
! Mark all lines off the screen for repaint.
!-

    IF ( NOT .BUILD_SCR)
    THEN
	BEGIN
!+
! If the screen has been erased we must repaint everything, otherwise only lines
! off the screen will need to be repainted.  Marking the lines off the screen for
! repaint removes the deleted lines from the screen data base, to avoid confusing
! our count of the number of lines above and below the current line.
!-

	IF .ERASE_ALL
	THEN
	    EDT$$SC_REPAINT (.FST_SCRPTR, .LST_SCRPTR, 0, 255, 1)
	ELSE
	    BEGIN

	    IF (.RECS_INSERTED GTR 0)
	    THEN
		BEGIN

		IF (.TOP_SCRPTR NEQA 0)
		THEN
		    BEGIN
		    SCRPTR = .TOP_SCRPTR [SCR_PRV_LINE];

		    IF (.SCRPTR NEQA 0) THEN EDT$$SC_REPAINT (.FST_SCRPTR, .SCRPTR, 0, 255, 1);

		    END;

		IF (.BOT_SCRPTR NEQA 0)
		THEN
		    BEGIN
		    SCRPTR = .BOT_SCRPTR [SCR_NXT_LINE];

		    IF (.SCRPTR NEQA 0) THEN EDT$$SC_REPAINT (.SCRPTR, .LST_SCRPTR, 0, 255, 1);

		    END;

		END;

	    END;

	END;

!+
! If we have lost our record of the top of the screen we must rebuild.
!-

    IF (.TOP_SCRPTR EQLA 0) THEN BUILD_SCR = 1;

    IF ( NOT .BUILD_SCR)
    THEN
	BEGIN
!+
! Find the relative record number of the old cursor line.
! We must be careful of deleted lines.  The convention is that a deleted line
! has the record number of the next lower line.  This prevents deleted
! lines before record zero from having negative absolute record numbers.
!-
	SCRPTR = .CUR_SCRPTR;
	REC_NO = 0;

	CASE .DIR FROM -1 TO 1 OF
	    SET

	    [1] :
		BEGIN
!+
! The new line is after the old.  We must move back in the work file.
!-

		DO
		    BEGIN

		    IF ((.SCRPTR [SCR_LINE_IDX] EQL 0) OR 	!
			((.SCRPTR [SCR_EDIT_FLAGS] AND SCR_EDIT_DELLN) NEQ 0))
		    THEN
			BEGIN

			LOCAL
			    PREV_SCRPTR : REF SCREEN_LINE;

			PREV_SCRPTR = .SCRPTR [SCR_PRV_LINE];

			IF (.PREV_SCRPTR NEQA 0)
			THEN
			    BEGIN

			    IF ((.PREV_SCRPTR [SCR_EDIT_FLAGS] AND SCR_EDIT_DELLN) EQL 0)
			    THEN
				REC_NO = .REC_NO - 1;

			    END;

			END;

		    SCRPTR = .SCRPTR [SCR_PRV_LINE];
		    END
		UNTIL ((.SCRPTR EQLA .CSR_SCRPTR) OR (.SCRPTR EQLA 0));

		END;

	    [0] :
		BEGIN
!+
! We are positioned correctly in the work file.
!-
		SCRPTR = .CSR_SCRPTR;
		END;

	    [-1] :
		BEGIN
!+
! The new line is before the old.  We must move forward in the work file.
!-

		DO
		    BEGIN

		    LOCAL
			NEXT_SCRPTR : REF SCREEN_LINE;

		    NEXT_SCRPTR = .SCRPTR [SCR_NXT_LINE];

		    IF (.NEXT_SCRPTR NEQA 0)
		    THEN
			BEGIN

			IF (((.SCRPTR [SCR_EDIT_FLAGS] AND SCR_EDIT_DELLN) EQL 0) AND 	!
			    ((.NEXT_SCRPTR [SCR_LINE_IDX] EQL 0) OR 	!
			    ((.NEXT_SCRPTR [SCR_EDIT_FLAGS] AND SCR_EDIT_DELLN) NEQ 0)))
			THEN
			    REC_NO = .REC_NO + 1;

			END;

		    SCRPTR = .SCRPTR [SCR_NXT_LINE];
		    END
		UNTIL ((.SCRPTR EQLA .CSR_SCRPTR) OR (.SCRPTR EQLA 0));

		END;

	    [OUTRANGE] :
		ASSERT (11, 0);
	    TES;

!+
! If we couldn't find it, rebuild the screen.
!-

	IF (.SCRPTR NEQA .CSR_SCRPTR) THEN BUILD_SCR = 1;

	END;

    IF ( NOT .BUILD_SCR)
    THEN
	BEGIN
!+
! Now work backwards to the old top line.
!-

	WHILE ((.SCRPTR NEQA .TOP_SCRPTR) AND (.SCRPTR NEQA 0)) DO
	    BEGIN

	    IF ((.SCRPTR [SCR_LINE_IDX] EQL 0) OR 	!
		((.SCRPTR [SCR_EDIT_FLAGS] AND SCR_EDIT_DELLN) NEQ 0))
	    THEN
		BEGIN

		LOCAL
		    PREV_SCRPTR : REF SCREEN_LINE;

		PREV_SCRPTR = .SCRPTR [SCR_PRV_LINE];

		IF (.PREV_SCRPTR NEQA 0)
		THEN
		    BEGIN

		    IF ((.PREV_SCRPTR [SCR_EDIT_FLAGS] AND SCR_EDIT_DELLN) EQL 0) THEN REC_NO = .REC_NO - 1;

		    END;

		END;

	    SCRPTR = .SCRPTR [SCR_PRV_LINE];
	    END;

	OLD_TOP_RECNO = .REC_NO;
	END;

!+
! If we didn't find it, rebuild the screen data base.
!-

    IF (.SCRPTR NEQA .TOP_SCRPTR) THEN BUILD_SCR = 1;

    IF ( NOT .BUILD_SCR)
    THEN
!+
! Update the lines which are on the screen.
!-
	BEGIN

	LOCAL
	    UPDATE_DONE,
	    ANOTHER_PASS,
	    BEG_SCRPTR : REF SCREEN_LINE,
	    INS_COUNT,
	    PREV_INS_COUNT;

!+
! Check for regions containing an equal number of inserted and deleted lines.
! Avoid double scrolling (and scrolling lines off the screen then back on) by
! changing all inserted lines in such regions into modified lines, and freeing
! the deleted lines.
!-

	DO
	    BEGIN
	    ANOTHER_PASS = 0;
	    INS_COUNT = 0;
	    SCRPTR = .TOP_SCRPTR;

	    DO
		BEGIN
		UPDATE_DONE = 0;
		PREV_INS_COUNT = .INS_COUNT;

		IF ((.SCRPTR [SCR_EDIT_FLAGS] AND SCR_EDIT_INSLN) NEQ 0) THEN INS_COUNT = .INS_COUNT + 1;

		IF ((.SCRPTR [SCR_EDIT_FLAGS] AND SCR_EDIT_DELLN) NEQ 0) THEN INS_COUNT = .INS_COUNT - 1;

		IF ((.INS_COUNT NEQ 0) AND (.PREV_INS_COUNT EQL 0)) THEN BEG_SCRPTR = .SCRPTR;

		IF ((.INS_COUNT EQL 0) AND (.PREV_INS_COUNT NEQ 0))
		THEN
		    BEGIN
!+
! Move the top line down, if it was deleted.
!-

		    IF (.BEG_SCRPTR EQLA .TOP_SCRPTR)
		    THEN

			WHILE ((.TOP_SCRPTR [SCR_EDIT_FLAGS] AND SCR_EDIT_DELLN) NEQ 0) DO
			    TOP_SCRPTR = .TOP_SCRPTR [SCR_NXT_LINE];

!+
! Free deleted lines and mark all other lines to be repainted.
!-
		    EDT$$SC_REPAINT (.BEG_SCRPTR, .SCRPTR, 0, 255, 1);
		    UPDATE_DONE = 1;
		    ANOTHER_PASS = 1;
		    END
		ELSE
		    BEGIN

		    IF (.SCRPTR EQLA .BOT_SCRPTR) OR (.SCRPTR [SCR_NXT_LINE] EQLA 0)
		    THEN
			UPDATE_DONE = 1
		    ELSE
			SCRPTR = .SCRPTR [SCR_NXT_LINE];

		    END;

		END
	    UNTIL .UPDATE_DONE;

!+
! The screen is no longer erased.  Subsequent lines painted must issue an "erase to end of line" to
! blank out the end of a completely painted line, except in special cases such as scrolling a line
! onto the screen.
!-
	    ERASE_ALL = 0;
	    END
	UNTIL ( NOT .ANOTHER_PASS);

!+
! Now repaint all the lines so marked, and do any residual inserts and deletes on the screen.
!-

	DO
	    BEGIN

	    LOCAL
		STATUS;				! Insert or Delete status

	    ANOTHER_PASS = 0;
	    REC_NO = .OLD_TOP_RECNO;
	    SCRPTR = .TOP_SCRPTR;
	    CS_LNO = 0;

	    DO
		BEGIN
		UPDATE_DONE = 0;

		IF ((.SCRPTR [SCR_EDIT_FLAGS] AND 	!
		    (SCR_EDIT_MODIFY OR SCR_EDIT_INSLN OR SCR_EDIT_DELLN)) NEQ 0)
		THEN
		    BEGIN
!+
! Is this a deleted line?
!-

		    IF ((.SCRPTR [SCR_EDIT_FLAGS] AND SCR_EDIT_DELLN) NEQ 0)
		    THEN
			BEGIN
			STATUS = DELETE_LINE (.SCRPTR, .REC_NO, .ERASE_ALL, OLD_TOP_RECNO);
			END
		    ELSE

			IF ((.SCRPTR [SCR_EDIT_FLAGS] AND SCR_EDIT_INSLN) NEQ 0)
			THEN
			    BEGIN
			    STATUS = INSERT_LINE (.SCRPTR, .REC_NO, .ERASE_ALL, OLD_TOP_RECNO);
			    END
			ELSE
			    BEGIN
!+
! The line is neither inserted nor deleted.  Just paint it on the screen.
!-
			    ASSERT (12, EDT$$SC_MOVTOLN (.REC_NO));
			    EDT$$SC_RFRELN (.SCRPTR, .ERASE_ALL);
			    STATUS = 1;
			    END;

		    IF ( NOT .STATUS)
		    THEN
			BEGIN
			UPDATE_DONE = 1;
			ANOTHER_PASS = 1;
			END;

		    END;

		IF ( NOT .UPDATE_DONE)
		THEN
		    BEGIN
		    CS_LNO = .CS_LNO + 1;

		    IF (.CS_LNO EQL .SCR_LNS)
		    THEN
			UPDATE_DONE = 1
		    ELSE
			BEGIN

			IF (.SCRPTR [SCR_NXT_LINE] EQLA 0)
			THEN
			    BEGIN
!+
! We have run out of screen data base, but we have not yet filled the screen.  If we
! are at [EOB] that is OK, otherwise extend the screen data base.
!-

			    IF (.SCRPTR EQLA .EOB_SCRPTR)
			    THEN
				BEGIN
!+
! We have reached [EOB] before filling the screen.  This will be fixed by scrolling later,
! if that is possible.  Erase the rest of the screen unless the whole screen has been
! erased already.
!-

				IF (.CS_LNO LSS .BOT_LINE) THEN EDT$$SC_ERAALL ();

				UPDATE_DONE = 1
				END
			    ELSE
				BEGIN
!+
! We are not at [EOB].  Add another record to the screen data base, and keep
! painting the screen.
!-
				REC_NO = .REC_NO + 1;
				ASSERT (12, EDT$$SC_MOVTOLN (.REC_NO));
				LNINS_VAL = EDT$$SC_LNINS (0, WK_LN [LIN_TEXT],
				    .WK_LN [LIN_LENGTH]);

				IF (.LNINS_VAL EQL 0)
				THEN
				    UPDATE_DONE = 1
				ELSE
				    BEGIN
				    SCRPTR = .SCRPTR;
				    ASSERT (23, .SCRPTR [SCR_NXT_LINE] NEQA 0);
				    SCRPTR = .SCRPTR [SCR_NXT_LINE];
				    ASSERT (23, .SCRPTR [SCR_LINE_IDX] EQL 0);
				    END;

				END;

			    END
			ELSE
			    BEGIN

			    LOCAL
				NEXT_SCRPTR : REF SCREEN_LINE;

			    NEXT_SCRPTR = .SCRPTR [SCR_NXT_LINE];

			    IF (.NEXT_SCRPTR NEQA 0)
			    THEN
				BEGIN

				IF (((.SCRPTR [SCR_EDIT_FLAGS] AND SCR_EDIT_DELLN) EQL 0) AND 	!
				    ((.NEXT_SCRPTR [SCR_LINE_IDX] EQL 0) OR 	!
				    ((.NEXT_SCRPTR [SCR_EDIT_FLAGS] AND SCR_EDIT_DELLN) NEQ 0)))
				THEN
				    REC_NO = .REC_NO + 1;

				END;

			    SCRPTR = .SCRPTR [SCR_NXT_LINE];
			    END;

			END;

		    END;

		END
	    UNTIL .UPDATE_DONE;

	    END
	UNTIL ( NOT .ANOTHER_PASS);

	EDT$$SC_SETSCLLREG (0, .SCR_LNS);
	BOT_LINE = .CS_LNO;
	OLD_BOT_RECNO = .REC_NO;
	BOT_SCRPTR = .SCRPTR;
	END;

    IF .BUILD_SCR
    THEN
	BEGIN
!+
! We must rebuild the screen data base.  Put all the screen line
! blocks on the free list.
!-

	IF (.FST_SCRPTR NEQA 0)
	THEN
	    BEGIN
	    LST_SCRPTR [SCR_NXT_LINE] = .FST_AVLN;
	    FST_AVLN = .FST_SCRPTR;
	    END;

	FST_SCRPTR = 0;
	LST_SCRPTR = 0;
	TOP_SCRPTR = 0;
	CUR_SCRPTR = 0;
	BOT_SCRPTR = 0;
	EOB_SCRPTR = 0;
	MEM_CNT = 0;
	END;

!+
! Align the cursor screen pointer with the current screen pointer.
!-
    REC_NO = 0;
    ASSERT (12, EDT$$SC_MOVTOLN (.REC_NO));
    SCR_BUF = .CUR_BUF;
    MOVELINE (CUR_BUF [TBCB_CUR_LIN], CUR_SCRLN);

    IF .BUILD_SCR
    THEN
	BEGIN
	EDT$$SC_LNINS (0, WK_LN [LIN_TEXT], .WK_LN [LIN_LENGTH]);
	CSR_SCRPTR = .FST_SCRPTR;

	IF (.TRUN EQL 0)			!
	THEN
	    CUR_SCRPTR = EDT$$SC_FNDREC (.CS_CHNO, DISP)
	ELSE
	    CUR_SCRPTR = .CSR_SCRPTR;

	END;

!+
! When we reach this point either the old screen has been updated
! or we will be rebuilding the screen data base.
! Determine which line should be at the top of the screen
!-
    SCRPTR = .CUR_SCRPTR;
    REC_NO = 0;
    BELOW = 0;
    ABOVE = 0;
!+
! Calculate the number of lines above and below the current line
! because we might have to move the cursor.  This may cause the screen
! data structure to be extended.
!-
    DOLOOPS = 0;

    IF ((.RECS_INSERTED GTR 0)		!
	OR (.CSR_SCRPTR NEQA .CUR_SCRPTR)	!
	OR (.BUILD_SCR)				!
	OR (EDT$$CMP_LNO (TOP_LN, LNO_EMPTY) NEQ 0))
    THEN
	BEGIN

	LOCAL
	    AT_BOTTOM;

	DOLOOPS = 1;
	AT_BOTTOM = 0;

	WHILE ((.BELOW LSS (.SCR_LNS*2)) AND ( NOT .AT_BOTTOM)) DO
	    BEGIN

	    IF (.SCRPTR EQLA 0)
	    THEN
		BEGIN
		ASSERT (12, EDT$$SC_MOVTOLN (.REC_NO));
		LNINS_VAL = EDT$$SC_LNINS (0, WK_LN [LIN_TEXT], .WK_LN [LIN_LENGTH]);

		IF (.LNINS_VAL EQL 0)
		THEN
		    AT_BOTTOM = 1
		ELSE
		    BEGIN
		    BELOW = .BELOW + .LNINS_VAL;
		    REC_NO = .REC_NO + 1;

		    IF (.WK_LN EQLA EOB_LN)
		    THEN
			BEGIN
			EOB_SCRPTR = .LST_SCRPTR;
			AT_BOTTOM = 1;
			END;

		    END;

		END
	    ELSE
		BEGIN
		BELOW = .BELOW + 1;

		IF (.SCRPTR EQLA .EOB_SCRPTR)
		THEN
		    AT_BOTTOM = 1
		ELSE
		    BEGIN
		    SCRPTR = .SCRPTR [SCR_NXT_LINE];

		    IF (.SCRPTR EQLA 0)
		    THEN
			REC_NO = .REC_NO + 1
		    ELSE

			IF (.SCRPTR [SCR_LINE_IDX] EQL 0) THEN REC_NO = .REC_NO + 1;

		    END;

		END;

	    END;

	END;

!+
! Now see how many lines are available above the current line.
!-
    SCRPTR = .CUR_SCRPTR;
    REC_NO = 0;

    IF (.DOLOOPS)
    THEN
	BEGIN
	BEGIN

	LOCAL
	    AT_TOP;

	AT_TOP = 0;

	WHILE ((.ABOVE LSS (.SCR_LNS*2)) AND ( NOT .AT_TOP)) DO
	    BEGIN

	    IF (.SCRPTR NEQA 0)
	    THEN
		BEGIN

		IF (.SCRPTR [SCR_LINE_IDX] EQL 0) THEN REC_NO = .REC_NO - 1;

		SCRPTR = .SCRPTR [SCR_PRV_LINE];
		END;

!+
! If the screen data structure ends, try to add new items to the front of it.
!-

	    IF (.SCRPTR EQLA 0)
	    THEN
		BEGIN

		IF EDT$$SC_MOVTOLN (.REC_NO)
		THEN
		    BEGIN
		    LNINS_VAL = EDT$$SC_LNINS (.FST_SCRPTR, WK_LN [LIN_TEXT],
			.WK_LN [LIN_LENGTH]);

		    IF (.LNINS_VAL EQL 0)
		    THEN
			AT_TOP = 1
		    ELSE
			BEGIN
			ABOVE = .ABOVE + .LNINS_VAL;
			SCRPTR = .FST_SCRPTR;
			END;

		    END
		ELSE
		    AT_TOP = 1;

		END
	    ELSE
		ABOVE = .ABOVE + 1;

	    END;

	END;
	SCRPTR = .CUR_SCRPTR;
!+
! Now compute the top line.  If there is an enforced top line, we try to use it.
! If there is not, we try to use the old top line.  Otherwise we go up a number of
! lines depending on the direction of the last move, to preserve as much context
! as possible.
!-
	TOP_SET = 0;

	IF (EDT$$CMP_LNO (TOP_LN, LNO_EMPTY) NEQ 0)
	THEN
	    BEGIN
!+
! There is a request for a top line.  If it is below the current line, reject it.
!-

	    IF (EDT$$CMP_LNO (TOP_LN, CS_LN) GTR 0)
	    THEN
		MOVELINE (LNO_EMPTY, TOP_LN)
	    ELSE
		BEGIN
!+
! The requested top line is above or on the current line.  If it is too far above, reject it.
!-
		TOP_DIST = 0;
		SCRPTR = .CUR_SCRPTR;
		MOVELINE (CS_LN, TEMP_LINE);

		WHILE ((EDT$$CMP_LNO (TEMP_LINE, TOP_LN) NEQ 0) AND 	!
		    (.TOP_DIST LSS .SCLL_BOT) AND 	!
		    (.SCRPTR NEQA 0)) DO
		    BEGIN

		    IF (.SCRPTR [SCR_LINE_IDX] EQL 0) THEN SUBLINE (LNO0, TEMP_LINE, TEMP_LINE);

		    SCRPTR = .SCRPTR [SCR_PRV_LINE];

		    IF (.SCRPTR NEQA 0) THEN TOP_DIST = .TOP_DIST + 1;

		    END;

!+
! If we found the line and it would not require [EOB] to be above the bottom
! of the screen, accept it.
!-

		IF ((EDT$$CMP_LNO (TEMP_LINE, TOP_LN) EQL 0) AND ((.BELOW + .TOP_DIST) GEQ .SCR_LNS))
		THEN
		    TOP_SET = 1
		ELSE
		    MOVELINE (LNO_EMPTY, TOP_LN);

		END;

	    END;

!+
! If we have no top determined yet, try to use the old top.
!-

	IF (( NOT .TOP_SET) AND (.TOP_SCRPTR NEQA 0))
	THEN
	    BEGIN
	    SCRPTR = .CUR_SCRPTR;
	    REC_NO = 0;
	    TOP_DIST = 0;

	    WHILE ((.TOP_DIST LEQ .SCLL_BOT) AND 	!
		(.SCRPTR NEQA .TOP_SCRPTR) AND 	!
		(.SCRPTR NEQA 0)) DO
		BEGIN

		IF (.SCRPTR [SCR_LINE_IDX] EQL 0) THEN REC_NO = .REC_NO - 1;

		SCRPTR = .SCRPTR [SCR_PRV_LINE];

		IF (.SCRPTR NEQA 0) THEN TOP_DIST = .TOP_DIST + 1;

		END;

!+
! If we found the old top line and it will leave the cursor line in range
! and not put the [EOB] above the bottom of the screen, use it.
!-

	    IF ((.TOP_DIST LEQ .SCLL_BOT) AND 	!
		(.TOP_DIST GEQ .SCLL_TOP) AND 	!
		((.BELOW + .TOP_DIST) GEQ .SCR_LNS) AND 	!
		(.SCRPTR EQLA .TOP_SCRPTR))
	    THEN
		TOP_SET = 1;

	    END;

!+
! If top is still not set and there is a record of a previous cursor line
! and we are rebuilding the screen data base, try to compute the top line
! such that the cursor stays where it was.  This is useful in case the code
! for fixing notruncated lines must force a rebuild of the screen data base.
!-

	IF (( NOT .TOP_SET) AND .SCR_REBUILD AND (.CURSOR_LINE GEQ .SCLL_TOP) AND 	!
	    (.CURSOR_LINE LEQ .SCLL_BOT) AND ((.BELOW + .CURSOR_LINE) GEQ .SCR_LNS))
	THEN
	    BEGIN
	    SCRPTR = .CUR_SCRPTR;
	    TOP_DIST = -1;

	    WHILE ((.SCRPTR NEQA 0) AND (.TOP_DIST NEQ .CURSOR_LINE)) DO
		BEGIN
		SCRPTR = .SCRPTR [SCR_PRV_LINE];
		TOP_DIST = .TOP_DIST + 1;
		END;

	    IF (.TOP_DIST EQL .CURSOR_LINE) THEN TOP_SET = 1;

	    END;

!+
! If top is still not set, try to find a new top line a suitable distance
! above the current line.
!-

	IF ( NOT .TOP_SET)
	THEN
	    BEGIN
!+
! Work back until the beginning of the screen data structure or until TOP_DIST is
! big enough for the direction we are moving.
!-
!+
! The (.CURSOR_LINE + .RECS_INSERTED) code is here to fix a problem on VT52's
! with the screen scrolling too far up on a paste.
!-

	    IF ((.DIR GEQ 0) OR (((.CURSOR_LINE + .RECS_INSERTED) GTR .SCLL_BOT)	!
		AND (.RECS_INSERTED GTR 0)))
	    THEN
		SCLL_NUM = .SCLL_BOT
	    ELSE
		SCLL_NUM = .SCLL_TOP;

!+
! If necessary, work back further to avoid lifting the [EOB] above the last line
! of the screen.
!-
	    SCLL_NUM = MAX (.SCLL_NUM, .SCR_LNS - .BELOW);
!
	    REC_NO = 0;
	    SCRPTR = .CUR_SCRPTR;
	    TOP_DIST = -1;

	    WHILE ((.SCRPTR NEQA 0) AND (.TOP_DIST NEQ .SCLL_NUM)) DO
		BEGIN
		SCRPTR = .SCRPTR [SCR_PRV_LINE];
		TOP_DIST = .TOP_DIST + 1;
		END;

!+
! If we found the line we were looking for, accept it.
!-

	    IF (.TOP_DIST EQL .SCLL_NUM) THEN TOP_SET = 1;

	    END;

!+
! If no line is suitable, use the first line in the screen data base.  This can happen when we
! have a buffer that fits on the screen.
!-

	IF ( NOT .TOP_SET)
	THEN
	    BEGIN
	    TOP_DIST = -1;
	    SCRPTR = .CUR_SCRPTR;

	    WHILE (.SCRPTR NEQA 0) DO
		BEGIN
		TOP_DIST = .TOP_DIST + 1;
		SCRPTR = .SCRPTR [SCR_PRV_LINE];
		END;

	    END;

!+
! Now that TOP_DIST is computed, find the new top screen pointer.
!-
	SCRPTR = .CUR_SCRPTR;
	REC_NO = 0;

	INCR I FROM 1 TO .TOP_DIST DO
	    BEGIN

	    IF (.SCRPTR [SCR_LINE_IDX] EQL 0) THEN REC_NO = .REC_NO - 1;

	    SCRPTR = .SCRPTR [SCR_PRV_LINE];
	    END;

	TOP_RECNO = .REC_NO;
	TOP_PTR = .SCRPTR;
!+
! Compute the number of lines between the old and new top lines,
! so we can see how far to scroll, and in which direction.
!-

	IF ((.TOP_SCRPTR NEQA 0) AND (.TOP_SCRPTR NEQA .TOP_PTR))
	THEN
	    BEGIN

	    LOCAL
		SEEN_OLD,
		SEEN_NEW;

	    SEEN_OLD = 0;
	    SEEN_NEW = 0;
	    SCLL_NUM = 0;
	    SCRPTR = .FST_SCRPTR;

	    WHILE ((.SCRPTR NEQA 0) AND ( NOT (.SEEN_OLD AND .SEEN_NEW))) DO
		BEGIN

		IF (.SEEN_OLD AND ( NOT .SEEN_NEW)) THEN SCLL_NUM = .SCLL_NUM + 1;

		IF (.SEEN_NEW AND ( NOT .SEEN_OLD)) THEN SCLL_NUM = .SCLL_NUM - 1;

		IF (.SCRPTR EQLA .TOP_PTR) THEN SEEN_NEW = 1;

		IF (.SCRPTR EQLA .TOP_SCRPTR) THEN SEEN_OLD = 1;

		SCRPTR = .SCRPTR [SCR_NXT_LINE];
		END;

	    ASSERT (23, .SEEN_NEW);
!+
! If the old top line is not in the data base, it must be too far away
! to scroll.
!-

	    IF ( NOT .SEEN_OLD) THEN SCLL_NUM = 0;

!+
! If the amount to scroll is too large, don't do any scrolling.
!-

	    IF (ABS (.SCLL_NUM) GEQ .SCR_LNS) THEN SCLL_NUM = 0;

!+
! The sign of SCLL_NUM says which way to scroll, and the magnitude says
! how much.  First position to the bottom or top of the old screen,
! depending on which way we are scrolling.
!-

	    WHILE (.SCLL_NUM NEQ 0) DO

		IF (.SCLL_NUM GTR 0)
		THEN
		    BEGIN
!+
! The cursor is moving down, so scroll the screen up.
!-
		    SCRPTR = .BOT_SCRPTR;
		    REC_NO = .OLD_BOT_RECNO;
		    SCRPTR = .SCRPTR [SCR_NXT_LINE];

		    IF (.SCRPTR [SCR_LINE_IDX] EQL 0) THEN REC_NO = .REC_NO + 1;

		    OLD_BOT_RECNO = .REC_NO;

		    IF .TI_SCROLL
		    THEN
			BEGIN
			EDT$$SC_POSCSIF (.SCR_LNS - 1, 0);
			EDT$$FMT_LIT (CH$PTR (UPLIT (%STRING (%CHAR (ASC_K_LF)))), 1);
			END
		    ELSE
			BEGIN
			EDT$$SC_POSCSIF (.MESSAGE_LINE + 1, 0);
			EDT$$FMT_LIT (CH$PTR (UPLIT (%STRING (%CHAR (ASC_K_LF)))), 1);
			EDT$$SC_POSCSIF (.SCR_LNS - 1, 0);
			END;

		    CS_LNO = .SCR_LNS - 1;
		    EDT$$SC_REPAINT (.SCRPTR, .SCRPTR, 0, 255, 1);
		    ASSERT (12, EDT$$SC_MOVTOLN (.REC_NO));
		    EDT$$SC_RFRELN (.SCRPTR, .TI_SCROLL);
		    TOP_SCRPTR = .TOP_SCRPTR [SCR_NXT_LINE];
		    BOT_SCRPTR = .SCRPTR;
		    SCLL_NUM = .SCLL_NUM - 1;
		    END
		ELSE
		    BEGIN
!+
! The cursor is moving up, so scroll the screen down.
!-
		    SCRPTR = .TOP_SCRPTR;
		    REC_NO = .OLD_TOP_RECNO;

		    IF (.SCRPTR [SCR_LINE_IDX] EQL 0) THEN REC_NO = .REC_NO - 1;

		    OLD_TOP_RECNO = .REC_NO;
		    SCRPTR = .SCRPTR [SCR_PRV_LINE];
		    EDT$$SC_POSCSIF (0, 0);

		    IF (.TI_TYP EQL TERM_VT52)
		    THEN
			EDT$$FMT_LIT (CH$PTR (UPLIT (%STRING (%CHAR (ASC_K_ESC), 'I'))), 2)
		    ELSE
			EDT$$FMT_LIT (CH$PTR (UPLIT (%STRING (%CHAR (ASC_K_ESC), 'M'))), 2);

		    IF ( NOT .TI_SCROLL)
		    THEN
			BEGIN
			CS_LNO = .SCR_LNS;
			EDT$$SC_ERAALL ();
			END;

		    CS_LNO = 0;
		    EDT$$SC_REPAINT (.SCRPTR, .SCRPTR, 0, 255, 1);
		    ASSERT (12, EDT$$SC_MOVTOLN (.REC_NO));
		    EDT$$SC_RFRELN (.SCRPTR, 1);
		    TOP_SCRPTR = .SCRPTR;
		    BOT_SCRPTR = .BOT_SCRPTR [SCR_PRV_LINE];
		    SCLL_NUM = .SCLL_NUM + 1;
		    END;

	    END;

!+
! Make a final update pass over the screen.  This will be needed if
! no scrolling took place because the new screen is too far from
! the old screen.
!-
	REC_NO = .TOP_RECNO;
	SCRPTR = .TOP_PTR;
	CURSOR_LINE = -1;
	TOP_SCRPTR = .TOP_PTR;
	CS_LNO = 0;

	WHILE ((.CS_LNO LSS .SCR_LNS) AND (.SCRPTR NEQA 0)) DO
	    BEGIN

	    IF ((.SCRPTR [SCR_EDIT_FLAGS] AND (SCR_EDIT_MODIFY OR SCR_EDIT_INSLN OR SCR_EDIT_DELLN)) NEQ 0)
	    THEN
		BEGIN
		ASSERT (12, EDT$$SC_MOVTOLN (.REC_NO));
		EDT$$SC_RFRELN (.SCRPTR, .ERASE_ALL);
		END;

	    BOT_SCRPTR = .SCRPTR;

	    IF (.SCRPTR EQLA .CUR_SCRPTR) THEN CURSOR_LINE = .CS_LNO;

	    SCRPTR = .SCRPTR [SCR_NXT_LINE];
	    CS_LNO = .CS_LNO + 1;

	    IF (.SCRPTR NEQA 0)
	    THEN
		BEGIN

		IF (.SCRPTR [SCR_LINE_IDX] EQL 0) THEN REC_NO = .REC_NO + 1;

		END;

	    END;

!+
! If there is more room on the screen, erase it if necessary.
!-

	IF (.CS_LNO LSS .BOT_LINE) THEN EDT$$SC_ERAALL ();

	BOT_LINE = .CS_LNO;
!+
! Mark the lines off the screen for repaint in case we have to scroll
! them back on in the next pass thru SC_UPD.
!-

	IF (.FST_SCRPTR NEQA .TOP_SCRPTR)
	THEN
	    BEGIN
	    SCRPTR = .TOP_SCRPTR [SCR_PRV_LINE];
	    EDT$$SC_REPAINT (.FST_SCRPTR, .SCRPTR, 0, 255, 1);
	    END;

	IF (.BOT_SCRPTR NEQA .LST_SCRPTR)
	THEN
	    BEGIN
	    SCRPTR = .BOT_SCRPTR [SCR_NXT_LINE];
	    EDT$$SC_REPAINT (.SCRPTR, .LST_SCRPTR, 0, 255, 1);
	    END;

	END;

!+
! Do the clean-up on the screen data pointers.
!-
    OLD_SEL = .SEL_BUF;
    SCR_REBUILD = 0;
    REC_NO = 0;
    ASSERT (12, EDT$$SC_MOVTOLN (.REC_NO));
    MOVELINE (CS_LN, CUR_SCRLN);
    CSR_SCRPTR = .CUR_SCRPTR;
    CS_OLDCHNO = .CS_CHNO;
    EDT$$SC_POSCSIF (.CURSOR_LINE, .CURSOR_POS);
    CS_LNO = .CURSOR_LINE;
    CUR_COL = .CURSOR_POS;
    EDT$$TI_ENBLAUTREP (1);
    EDT$$OUT_FMTBUF ();
    LN_PTR = CH$PTR (LN_BUF, .CS_CHNO, BYTE_SIZE);
    RECS_INSERTED = 0;
    END;					! of routine EDT$$SC_UPD
%SBTTL 'DELETE_LINE - delete a line on the screen'
ROUTINE DELETE_LINE (				! Delete a line on the screen
    SCRPTR, 					! The line to delete
    REC_NO, 					! It's relative record number
    ERASE_ALL, 					! 1 = screen has been erased
    OLD_TOP_RECNO				! Record number of the top line
    ) =

!++
! FUNCTIONAL DESCRIPTION:
!
!	Delete one screen line.
!
! FORMAL PARAMETERS:
!
!  SCRPTR		The screen data block to delete
!
!  REC_NO		The relative record number of that line
!
!  ERASE_ALL		1 = the screen has been erased
!
!  OLD_TOP_RECNO	Record number of the top line
!
! IMPLICIT INPUTS:
!
!	FST_SCRPTR
! 	LST_SCRPTR
!	TI_SCROLL
!	TOP_SCRPTR
!	SCR_LNS
!	SCLL_BOT
!	BOT_SCRPTR
!	CS_LNO
!	LST_SCRPTR
!	BOT_LINE
!
! IMPLICIT OUTPUTS:
!
!	TOP_SCRPTR
!	BOT_SCRPTR
!	BOT_LINE
!
! ROUTINE VALUE:
!
!	1 = OK, 0 = must start update over
!
! SIDE EFFECTS:
!
!	Will store into the format buffer
!
!--

    BEGIN

    MAP
	SCRPTR : REF SCREEN_LINE;

    EXTERNAL ROUTINE
	EDT$$SC_ERAALL,				! Erase to end of screen
	EDT$$SC_MOVTOLN,		! Move to a record in the work file relative to the current record
	EDT$$SC_RFRELN : NOVALUE,		! Refresh a screen line
	EDT$$SC_LNDEL,				! Delete a line from data structure
	EDT$$SC_SETSCLLREG,			! Set scrolling region
	EDT$$FMT_LIT,				! Format a literal for output
	EDT$$SC_POSCSIF : NOVALUE,		! Position the cursor
	EDT$$SC_REPAINT : NOVALUE;		! Mark some lines in the screen data base for repaint

    EXTERNAL
	MSGFLG,				! Is a message on the screen
	MESSAGE_LINE,			! Line number for prompts
	TI_TYP,				! Terminal type
	TI_EDIT,				! VT102 editing features
	SCR_LNS,				! Number of lines on screen
	SCLL_BOT,			! Cursor screen line
	FST_SCRPTR : REF SCREEN_LINE,	! First data structure pointer
	BOT_SCRPTR : REF SCREEN_LINE,	! Bottom screen pointer
	LST_SCRPTR : REF SCREEN_LINE,	! Last data structure pointer
	TOP_SCRPTR : REF SCREEN_LINE,	! Top screen line info address
	EOB_SCRPTR : REF SCREEN_LINE,	! EOB screen pointer
	CS_LNO,				! current cursor line
	TI_SCROLL,			! 1 = we have scrolling regions
	BOT_LINE;			! All lines below this one have been erased

    LOCAL
	PRV_SCRPTR : REF SCREEN_LINE,		! Previous screen pointer
	NXT_SCRPTR : REF SCREEN_LINE;		! Next screen pointer

    NXT_SCRPTR = .SCRPTR [SCR_NXT_LINE];
!+
! If we are deleting the top line, make the following line the top line
! unless there are lines preceding it that have been modified or inserted,
! in which case we paint over the deleted line instead of scrolling.
!-

    IF (.SCRPTR EQLA .TOP_SCRPTR)
    THEN
	BEGIN
	PRV_SCRPTR = .SCRPTR [SCR_PRV_LINE];

	IF (.PRV_SCRPTR NEQA 0)
	THEN
!+
! Test for insertion or modification of previous lines.
!-

	    IF ((.PRV_SCRPTR [SCR_EDIT_FLAGS] AND (SCR_EDIT_INSLN OR SCR_EDIT_MODIFY)) NEQ 0)
	    THEN
		BEGIN
!+
! Delete the current line and backup to the previous line for a
! repaint.  The top screen pointer and record number offsets
! must also be updated.  No further processing is needed on this pass.
!-
		EDT$$SC_LNDEL (.SCRPTR);
		TOP_SCRPTR = .PRV_SCRPTR;

		IF ((.PRV_SCRPTR [SCR_LINE_IDX] EQL 0) AND 	!
		    ((.PRV_SCRPTR [SCR_EDIT_FLAGS] AND SCR_EDIT_DELLN) EQL 0))
		THEN
		    BEGIN
		    .OLD_TOP_RECNO = ..OLD_TOP_RECNO - 1;
		    REC_NO = .REC_NO - 1;
		    END;

		ASSERT (12, EDT$$SC_MOVTOLN (.REC_NO));
		EDT$$SC_RFRELN (.PRV_SCRPTR, .ERASE_ALL);
		RETURN (0);
		END;

!+
! The previous line is non-existent or has not been modified.  Handle this in the usual way.
!-
	END;

    IF ((.EOB_SCRPTR EQLA .BOT_SCRPTR) AND (.TOP_SCRPTR [SCR_PRV_LINE] NEQA 0))
    THEN
	BEGIN
!+
! The [EOB] appears on the screen, but the buffer is long enough that there is a line
! before the top line that appears on the screen.
! Move the top screen pointer up one line.  This must be done before deleting
! the current line in case the top line is the current line.
!-
	TOP_SCRPTR = .TOP_SCRPTR [SCR_PRV_LINE];
!+
! Adjust the record number of the top line.
!-

	IF ((.TOP_SCRPTR [SCR_LINE_IDX] EQL 0) AND 	!
	    ((.TOP_SCRPTR [SCR_EDIT_FLAGS] AND SCR_EDIT_DELLN) EQL 0))
	THEN
	    .OLD_TOP_RECNO = ..OLD_TOP_RECNO - 1;

	IF (.TI_SCROLL)
	THEN
	    BEGIN

	    LOCAL
		TMP_SCRPTR : REF SCREEN_LINE,
		SCLL_LINE;

	    SCLL_LINE = .CS_LNO;
	    TMP_SCRPTR = .SCRPTR;
!+
! To speed up deletes, the scrolling line will be the last line which is
! marked for delete.
!-

	    DO
		BEGIN
		SCLL_LINE = .SCLL_LINE + 1;
		TMP_SCRPTR = .TMP_SCRPTR [SCR_NXT_LINE];
		END
	    UNTIL ((.TMP_SCRPTR [SCR_EDIT_FLAGS] AND SCR_EDIT_DELLN) EQL 0);

!+
! Scroll down
!-
	    EDT$$SC_SETSCLLREG (0, .SCLL_LINE);
	    EDT$$SC_POSCSIF (0, 0);
	    EDT$$FMT_LIT (CH$PTR (UPLIT (%STRING (%CHAR (ASC_K_ESC), 'M'))), 2);
	    EDT$$SC_LNDEL (.SCRPTR);
	    END
	ELSE
!+
! Repaint from the first line to the current line on a noscroll terminal.
!-
	    BEGIN

	    LOCAL
		SAV_CS_LN;

	    EDT$$SC_LNDEL (.SCRPTR);

	    IF (.NXT_SCRPTR NEQA 0) THEN EDT$$SC_REPAINT (.NXT_SCRPTR, .LST_SCRPTR, 0, 255, 0);

	    SAV_CS_LN = .CS_LNO;
	    EDT$$SC_POSCSIF (0, 0);
!+
! Scroll down.
!-

	    IF (.TI_TYP EQL TERM_VT52)
	    THEN
		EDT$$FMT_LIT (CH$PTR (UPLIT (%STRING (%CHAR (ASC_K_ESC), 'I'))), 2)
	    ELSE
		EDT$$FMT_LIT (CH$PTR (UPLIT (%STRING (%CHAR (ASC_K_ESC), 'M'))), 2);

!+
! If we've done a scroll then the message is no longer on the screen.
!-
	    MSGFLG = 0;
	    BOT_LINE = .BOT_LINE + 1;
	    CS_LNO = .SCR_LNS;
	    EDT$$SC_ERAALL ();
	    CS_LNO = .SAV_CS_LN;
	    END;

	END
    ELSE
	BEGIN
!+
! Either [EOB] does not appear on the screen or, if it does, the buffer is short enough
! that it all fits on the screen.  We will be scrolling up.
! If we are deleting the top line, make the next line the top line.  We don't need to
! worry about the top line record number since deleted lines have the record number
! of the next following non-deleted line.
!-
	PRV_SCRPTR = .TOP_SCRPTR;

	IF (.SCRPTR EQLA .TOP_SCRPTR) THEN TOP_SCRPTR = .NXT_SCRPTR;

	IF ((.TI_SCROLL) AND (.CS_LNO LSS (.SCR_LNS - 1)))
	THEN
	    BEGIN
!+
! Set the scrolling region so we can update the screen without repainting text
! that has moved up.
!-

	    IF (.TI_EDIT)
	    THEN
!+
! Use VT102 edit feature
!-
		BEGIN
		EDT$$SC_POSCSIF (.CS_LNO, 0);
		EDT$$FMT_LIT (CH$PTR (UPLIT (%STRING (%CHAR (ASC_K_ESC), '[M'))), 3);
		END
	    ELSE
		BEGIN
!+
! Simulate edit feature.
!-
		EDT$$SC_SETSCLLREG (.CS_LNO, .SCR_LNS);
		EDT$$SC_POSCSIF (.SCR_LNS - 1, 0);
		EDT$$FMT_LIT (CH$PTR (UPLIT (%STRING (%CHAR (ASC_K_LF)))), 1);
		END;

!+
! Free the deleted line.
!-
	    EDT$$SC_LNDEL (.SCRPTR);
	    END
	ELSE
	    BEGIN
!+
! If we cannot use the scrolling region, repaint the screen from the point
! of the deletion to the bottom.  If we're deleting the top line, then
! just scroll up instead of repainting.
!-

	    IF (.SCRPTR EQLA .PRV_SCRPTR)
	    THEN
		BEGIN
		EDT$$SC_LNDEL (.SCRPTR);
		EDT$$SC_POSCSIF (.MESSAGE_LINE + 1, 0);
		EDT$$FMT_LIT (CH$PTR (UPLIT (%STRING (%CHAR (ASC_K_LF)))), 1);
		END
	    ELSE
		BEGIN
		EDT$$SC_LNDEL (.SCRPTR);

		IF (.NXT_SCRPTR NEQA 0)
		THEN

		    IF (.NXT_SCRPTR EQLA .EOB_SCRPTR) OR ((.NXT_SCRPTR [SCR_EDIT_FLAGS] AND
			SCR_EDIT_DELLN) EQL 0)
		    THEN
			EDT$$SC_REPAINT (.NXT_SCRPTR, .LST_SCRPTR, 0, 255, 0);

		END;

	    END;

!+
! Adjust the bottom screen pointer if it is not the EOB.
!-

	IF ((.BOT_SCRPTR NEQA 0) AND (.BOT_SCRPTR NEQA .EOB_SCRPTR))
	THEN
	    BOT_SCRPTR = .BOT_SCRPTR [SCR_NXT_LINE];

	END;

!+
! Make another pass over the screen data.
!-
    RETURN (0);
    END;					! of routine DELETE_LINE
%SBTTL 'INSERT_LINE - insert a line on the screen'
ROUTINE INSERT_LINE (				! Insert a line on the screen
    SCRPTR, 					! The line to insert
    REC_NO, 					! It's relative record number
    ERASE_ALL, 					! 1 = screen has been erased
    OLD_TOP_RECNO				! Record number of the top line
    ) =

!++
! FUNCTIONAL DESCRIPTION:
!
!	Insert one screen line.  It may be marked inserted or deleted.
!	This routine is not called unless it has some kind of edit.
!
! FORMAL PARAMETERS:
!
!  SCRPTR		The screen data block to insert
!
!  REC_NO		The relative record number of that line
!
!  ERASE_ALL		1 = the screen has been erased
!
!  OLD_TOP_RECNO	Record number of the top line
!
! IMPLICIT INPUTS:
!
!	TI_SCROLL
!	TOP_SCRPTR
!	SCR_LNS
!	SCLL_BOT
!	BOT_SCRPTR
!	CS_LNO
!	LST_SCRPTR
!	BOT_LINE
!
! IMPLICIT OUTPUTS:
!
!	TOP_SCRPTR
!	BOT_SCRPTR
!	BOT_LINE
!
! ROUTINE VALUE:
!
!	1 = OK, 0 = must start update over
!
! SIDE EFFECTS:
!
!	Will store into the format buffer
!
!--

    BEGIN

    MAP
	SCRPTR : REF SCREEN_LINE;

    EXTERNAL ROUTINE
	EDT$$SC_LNDEL,				! Free a deleted line
	EDT$$SC_SETSCLLREG,			! Set scrolling region
	EDT$$FMT_LIT,				! Format a literal for output
	EDT$$SC_POSCSIF : NOVALUE,		! Position the cursor
	EDT$$SC_MOVTOLN,		! Move to a record in the work file relative to the current record
	EDT$$SC_RFRELN : NOVALUE,		! Refresh a screen line
	EDT$$SC_REPAINT : NOVALUE;		! Mark some lines in the screen data base for repaint

    EXTERNAL
	MESSAGE_LINE,			! Line number for error msgs
	TI_EDIT,				! VT102 editing features
	SCR_LNS,				! Number of lines on screen
	SCLL_BOT,			! Cursor screen line
	BOT_SCRPTR : REF SCREEN_LINE,	! Bottom screen pointer
	LST_SCRPTR : REF SCREEN_LINE,	! Last data structure pointer
	TOP_SCRPTR : REF SCREEN_LINE,	! Top screen line info address
	EOB_SCRPTR : REF SCREEN_LINE,	! EOB screen pointer
	CS_LNO,				! current cursor line
	TI_SCROLL,			! 1 = we have scrolling regions
	BOT_LINE;			! All lines below this one have been erased

    LOCAL
	NXT_SCRPTR : REF SCREEN_LINE;		! Next screen pointer

!+
! Now check for inserted lines and perform scrolls based upon this information
!-

    IF ((.CS_LNO GEQ .SCLL_BOT) AND (.BOT_LINE GEQ .SCR_LNS))
    THEN
	BEGIN
	NXT_SCRPTR = .SCRPTR [SCR_NXT_LINE];

	IF (.TI_SCROLL)
	THEN
	    BEGIN

	    IF (.NXT_SCRPTR NEQA 0)
	    THEN

		IF ((.NXT_SCRPTR [SCR_EDIT_FLAGS] AND SCR_EDIT_DELLN) NEQ 0)
		THEN
		    EDT$$SC_LNDEL (.NXT_SCRPTR)
		ELSE
		    BEGIN
!+
! Scroll up.
!-
		    CS_LNO = .CS_LNO - 1;
		    EDT$$SC_SETSCLLREG (0, .CS_LNO + 1);
		    EDT$$SC_POSCSIF (.CS_LNO, 0);
		    EDT$$FMT_LIT (CH$PTR (UPLIT (%STRING (%CHAR (ASC_K_LF)))), 1);	! Scroll up
!+
! Mark the top line for repaint since it is moving off the screen.
!-
		    EDT$$SC_REPAINT (.TOP_SCRPTR, .TOP_SCRPTR, 0, 255, -1);
		    TOP_SCRPTR = .TOP_SCRPTR [SCR_NXT_LINE];
!+
! Adjust the record number of the top line.
!-

		    IF ((.TOP_SCRPTR [SCR_LINE_IDX] EQL 0) AND 	!
			((.TOP_SCRPTR [SCR_EDIT_FLAGS] AND SCR_EDIT_DELLN) EQL 0))
		    THEN
			.OLD_TOP_RECNO = ..OLD_TOP_RECNO + 1;

		    END;

	    END
	ELSE
	    BEGIN
!+
! Do a repaint from the top down and scroll up once if we have a noscroll terminal.
!-
	    EDT$$SC_REPAINT (.SCRPTR, .LST_SCRPTR, 0, 255, 1);
	    EDT$$SC_POSCSIF (.MESSAGE_LINE + 1, 0);
	    EDT$$FMT_LIT (CH$PTR (UPLIT (%STRING (%CHAR (ASC_K_LF)))), 1);
	    TOP_SCRPTR = .TOP_SCRPTR [SCR_NXT_LINE];
!+
! Adjust the record number of the top line.
!-

	    IF ((.TOP_SCRPTR [SCR_LINE_IDX] EQL 0) AND 	!
		((.TOP_SCRPTR [SCR_EDIT_FLAGS] AND SCR_EDIT_DELLN) EQL 0))
	    THEN
		.OLD_TOP_RECNO = ..OLD_TOP_RECNO + 1;

	    RETURN (0);
	    END;

	END
    ELSE
	BEGIN

	IF (.TI_SCROLL)
	THEN
	    BEGIN
	    NXT_SCRPTR = .SCRPTR [SCR_NXT_LINE];

	    IF (.NXT_SCRPTR NEQA 0)
	    THEN

		IF ((.NXT_SCRPTR [SCR_EDIT_FLAGS] AND SCR_EDIT_DELLN) NEQ 0)
		THEN
		    EDT$$SC_LNDEL (.NXT_SCRPTR)
		ELSE
		    BEGIN
!+
! Scroll down.
!-

		    IF (.TI_EDIT)
		    THEN
!+
! Use VT102 edit feature
!-
			BEGIN
			EDT$$SC_POSCSIF (.CS_LNO, 0);
			EDT$$FMT_LIT (CH$PTR (UPLIT (%STRING (%CHAR (ASC_K_ESC), '[L'))), 3);
			END
		    ELSE
			BEGIN
!+
! Simulate edit feature
!-
			EDT$$SC_SETSCLLREG (.CS_LNO, .SCR_LNS);
			EDT$$SC_POSCSIF (.CS_LNO, 0);
			EDT$$FMT_LIT (CH$PTR (UPLIT (%STRING (%CHAR (ASC_K_ESC), 'M'))), 2);	! Scroll down
			END;

!+
! If the bottom line will move off the screen, arrange to repaint it if it should move back on.
!-

		    IF ((.BOT_SCRPTR NEQA 0) AND (.BOT_LINE GEQ (.SCR_LNS - 1)))
		    THEN
			BEGIN
			EDT$$SC_REPAINT (.BOT_SCRPTR, .BOT_SCRPTR, 0, 255, 0);
			BOT_SCRPTR = .BOT_SCRPTR [SCR_PRV_LINE];
			END;

!+
! The bottom line may be lower on the screen.  It doesn't matter much if BOT_LINE is too large.
!-
		    BOT_LINE = .BOT_LINE + 1;
		    END;

	    END
	ELSE
	    BEGIN
	    EDT$$SC_REPAINT (.SCRPTR, .LST_SCRPTR, 0, 255, 1);
!+
! If the bottom line will move off the screen, arrange to repaint it if it should move back on.
!-

	    IF ((.BOT_SCRPTR NEQA 0) AND (.BOT_LINE GEQ (.SCR_LNS - 1)))
	    THEN
		BEGIN
		EDT$$SC_REPAINT (.BOT_SCRPTR, .BOT_SCRPTR, 0, 255, 0);
		BOT_SCRPTR = .BOT_SCRPTR [SCR_PRV_LINE];
		END;

!+
! The bottom line may be lower on the screen.  It doesn't matter much if BOT_LINE is too large.
!-
	    BOT_LINE = .BOT_LINE + 1;
	    RETURN (0);
	    END;

	END;

    ASSERT (12, EDT$$SC_MOVTOLN (.REC_NO));
    EDT$$SC_RFRELN (.SCRPTR, .ERASE_ALL);
    RETURN (1);
    END;					! of routine INSERT_LINE
!<BLF/PAGE>
END						! of module EDT$SCRUPDATE

ELUDOM