Google
 

Trailing-Edge - PDP-10 Archives - BB-H138F-BM_1988 - 7-sources/chmeinput.bli
There are 11 other files named chmeinput.bli in the archive. Click here to see a list.
 %TITLE 'CHMEINPUT - read with echo if possible'
MODULE CHMEINPUT (				! Read with echo if possible
		IDENT = '3-003'			! File: CHMEINPUT.BLI Edit: CJG3003
		) =
BEGIN
!COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1981, 1988.  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 THAT IS NOT SUPPLIED BY DIGITAL.
!
!
!++
! FACILITY:	EDT -- The DEC Standard Editor
!
! ABSTRACT:
!
!	This module determines whether a special read can be performed
!	which leaves character echoing to the terminal driver, and does the
!	read if so.
!
! ENVIRONMENT:	Runs at any access mode - AST reentrant
!
! AUTHOR: Bob Kushlis, CREATION DATE: Unknown
!
! MODIFIED BY:
!
! 1-001	- Original.  DJS 04-Feb-1981.  This module was created by
!	extracting the routine EDT$$RD_ECHO  from module CHANGE.BLI.
! 1-002	- regularize headers.  JBS 27-Feb-1981
! 1-003	- Fix module name.  JBS 02-Mar-1981
! 1-004	- Revise journaling, and only do line reads if we can read at least
!	   four characters.  JBS 18-Jun-1981
! 1-005	- Prompt from the global string, if requested.  JBS 21-Oct-1981
! 1-006	- Remove length of prompt string.  JBS 23-Oct-1981
! 1-007	- Make the reads shorter to allow for the cursor positioning sequence.
!	   JBS 29-Jan-1982
! 1-008	- Don't make the lengths of the reads depend on the special prompt;
!	   otherwise the QA system has trouble.  JBS 29-Jan-1982
! 1-009	- Add JOU_VALID.  JBS 09-Apr-1982
! 1-010	- Worry about control C.  JBS 24-May-1982
! 1-011	- New screen update logic.  JBS 13-Sep-1982
! 1-012	- Include the EOL test routine, since it was only called from here.  JBS 22-Sep-1982
! 1-013	- Correct a misspelling in edit 1-012.  JBS 23-Sep-1982
! 1-014	- Add insert mode for VT102s.  JBS 27-Sep-1982
! 1-015	- Use a local text buffer, to avoid clobbering text if we are inserting.  JBS 27-Sep-1982
! 1-016	- Fix journaling of inserted text.  JBS 28-Sep-1982
! 1-017	- Remove EDT$$G_LN_NO for new screen update logic.  JBS 29-Sep-1982
! 1-018	- Keep EDT$$G_PRV_COL up to date.  JBS 05-Oct-1982
! 1-019	- Allow for fat characters to the right of the cursor.  JBS 06-Oct-1982
! 1-020	- Don't do optimized input if there is text on the message line.  JBS 06-Oct-1982
! 1-021 - Don't write out to the journal file here. STS 07-Oct-1982
! 1-022	- Fix call to EDT$$FMT_CHWID.  JBS 13-Oct-1982
! 1-023	- Don't send the CR and reposition the cursor unless the terminal
!	   driver needs it.  JBS 16-Oct-1982
! 1-024	- Handle some cases of DEL.  JBS 10-Nov-1982
! 1-025	- Don't redundently enter insert mode.  JBS 11-Nov-1982
! 1-026	- Take into account characters already read when allowing for end of line.  JBS 16-Nov-1982
! 1-027	- Take into account characters already read when positioning the cursor.  JBS 22-Nov-1982
! 1-028	- Don't forget that DEL also repositions the cursor.  JBS 24-Nov-1982
! 1-029	- Don't forget to journal the DEL.  Also, repaint the line if NOTRUNCATE.  JBS 25-Nov-1982
! 1-030	- Journal the correct text after DEL.  JBS 25-Nov-1982
! 1-031	- Change the call to EDT$$TST_KEYDEF.  JBS 14-Dec-1982
! 1-032	- Remove EDT$$G_SHF.  JBS 14-Dec-1982
! 1-033	- Don't do it at the front of any line, even a continuation line.  JBS 20-Dec-1982
! 1-034	- Change the call to EDT$$MRK_LNCHG.  JBS 27-Dec-1982
! 1-035	- Maintain EDT$$G_CS_OLDCHNO.  JBS 27-Dec-1982
! 1-036	- If the screen is shifted don't do it.  JBS 29-Dec-1982
! 1-037	- Start on improving quality by going closer to the right margin before quitting.  JBS 14-Jan-1982
! 1-038	- Never read more than 70 characters at a time.  JBS 08-Feb-1983
! 1-039	- Read closer to the right margin.  JBS 09-Feb-1983
! 3-001 - Fix for TOPS-20 operation. GB 8-Jun-1983
! 3-002 - Modify to use EDT$$TI_BUFSTR for journalling. CJG 15-Jun-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$$RD_ECHO;				! Try to optimize terminal input

!
! INCLUDE FILES:
!

REQUIRE 'EDTSRC:EDTREQ';

!
! MACROS:
!
!	NONE
!
! EQUATED SYMBOLS:
!
LITERAL
    CHAR_LIMIT_1 = 2,			! Do optimized input even if only this many characters can be read
    CHAR_LIMIT_2 = 1;			! Read this many chars less than we can
!
! OWN STORAGE:
!
!	NONE
!
! EXTERNAL REFERENCES:
!
!	In the routine
%SBTTL 'EDT$$RD_ECHO  - read with echo if possible'

GLOBAL ROUTINE EDT$$RD_ECHO 			! Read with echo if possible
    =

!++
! FUNCTIONAL DESCRIPTION:
!
!	This routine determines whether or not an optimization for terminal
!	input can be done.  If we are currently positioned at the end of a line,
!	or if the terminal has the VT102 "insert character mode" feature,
!	then it is possible to let the terminal driver do the echoing of printable
!	characters for us up to the input of a character which may be a definable
!	key, or to near the end of the line, where even a non-definable key needs
!	special handling, such as wrap or display of a diamond.  This is much more
!	efficient than the single character input with no echo which is normally donem
!
!	This routine checks a whole series of conditions which must be met before
!	optimized input is possible, then comes up with the number of
!	characters which can be read with echo.  If this is large enough then a special
!	read routine is called to do the input.  If the input is terminated by an
!	escape or control character, that character will be put in the type-ahead
!	character, so it will be the next character returned by EDT$$TI_INPCH.
!
! FORMAL PARAMETERS:
!
!	NONE
!
! IMPLICIT INPUTS:
!
!	CUR_COL
!	CS_LNO
!	SEL_BUF
!	SHF
!	KPAD
!	RCOV_MOD
!	CUR_BUF
!	TI_WID
!	WD_WRAP
!	LN_BUF
!	LN_PTR
!	LN_END
!	WK_LN
!	PRV_COL
!	PMT_KPD
!	MSGFLG
!	TI_DUMB
!	RD_AHED
!	RD_AHEDBF
!	TRUN
!	CSR_SCRPTR
!
! IMPLICIT OUTPUTS:
!
!	LN_PTR
!	PRV_COL
!	LN_CHGD
!	JOU_VALID
!	CC_DONE
!	RD_AHED
!	VERT
!	T_DEL_CH
!	DEL_CHLEN
!	CS_OLDCHNO
!
! ROUTINE VALUE:
!
!	0 = read with echo not possible, 1 = read with echo done.
!
! SIDE EFFECTS:
!
!	NONE
!
!--

    BEGIN

    EXTERNAL ROUTINE
	EDT$$CHK_CC,				! Test for a control C
	EDT$$FMT_LIT : NOVALUE,			! Format a literal string
	EDT$$TI_RDSTR : NOVALUE,		! Read with echo
	EDT$$TI_BUFCH : NOVALUE,		! Put characters in the journal buffer
	EDT$$TI_BUFSTR : NOVALUE,		! Put a string in the journal file
	EDT$$UPD_LNLEN : NOVALUE,		! Update the length of the current line
	EDT$$SC_POSCSIF : NOVALUE,		! Position the cursor if necessary
	EDT$$SC_NONREVID : NOVALUE,		! End reverse video
	EDT$$SC_REVID : NOVALUE,		! Start reverse video
	EDT$$SEL_RNGPOS,			! Compare the select line with the current line
	EDT$$FMT_CHWID,				! Compute the width of a character
	EDT$$TST_KEYDEF,			! Test a key for a given definition
	EDT$$SC_ERATOEOL : NOVALUE,		! Erase to end of line
	EDT$$MRK_LNCHG : NOVALUE;		! Mark a line as having changed

    EXTERNAL
	CUR_COL,				! current column
	LN_CHGD,				! Indicates current line has changed.
	CS_LNO,					! cursor line.
	SEL_BUF,				! Pointer to select buffer.
	VERT,					! Last entity was VERT flag.
	KPAD,					! Keypad activated?
	RCOV_MOD,				! In recovery mode?
	CUR_BUF : REF TBCB_BLOCK,		! The current buffer tbcb
	TI_WID,					! Width of terminal line
	WD_WRAP,				! Word wrap
	LN_BUF,					! Current line buffer
	LN_PTR : REF VECTOR,			! Current character pointer
	LN_END,					! Pointer to end of current line
	PRV_COL,				! Previous column number
	PMT_KPD : VECTOR,			! Counted ASCII string for keypad prompt
	JOU_VALID,				! The journal record is valid
	CC_DONE,				! Control C actually aborted something
	WK_LN,					! The curent work line
	EOB_LN,					! The specal line that marks end of buffer
	TI_EDIT,				! 1= This terminal has insert character mode
	MSGFLG,					! 1 = There is text on the message line
	TI_DUMB,				! 1 = Trminal driver needs CR to avoid wrapping lines
	RDAHED,					! Number of chars in read ahead buffer
	RDAHEDBF,				! The read-ahead buffer
	DEL_CH,					! Deleted character buffer.
	DEL_CHLEN,				! Length of deleted character buffer
	TRUN,					! 0 = NOTRUNCATE mode
	CSR_SCRPTR : REF SCREEN_LINE,		! Pointer to current screen info for current line
	CS_OLDCHNO,				! Old character position on the line
	SHF;					! Screen shift amount
	
    LOCAL
	CPTR,
	BUF_LEFT,
	NUM_CHARS,
	COUNT,
	NUM_READ,
	READ,
	READ_DONE,
	TERMINATOR_PROCESSED,
	INS_MODE,
	TEXT_BUF : BLOCK [CH$ALLOCATION (132, BYTE_SIZE)];


!+
! We can only do this in keypad mode.
!-

    IF ( NOT .KPAD) THEN RETURN (0);

!+
! If we are on a continuation line don't do it.
!-

    IF (.CSR_SCRPTR EQLA 0) THEN RETURN (0);

    IF (.CSR_SCRPTR [SCR_CHR_FROM] NEQ 0) THEN RETURN (0);

!+
! If we are at the left margin don't do it.
!-

    IF (.CSR_SCRPTR [SCR_CHR_FROM] EQL CH$DIFF (.LN_PTR, CH$PTR (LN_BUF,, BYTE_SIZE)))
	 THEN RETURN (0);

!+
! If in recovery mode don't do it.
!-

    IF .RCOV_MOD THEN RETURN (0);

!+
! If at end of buffer don't do it.
!-

    IF (.WK_LN EQLA EOB_LN) THEN RETURN (0);

!+
! If there is text on the message line don't do it, since we want
! to erase the text at the next keystroke.  After that keystroke
! the message line will be erased and we will come back here to
! check again for optimized input.
!-

    IF (.MSGFLG) THEN RETURN (0);

!+
! If the screen is shifted don't do it.
!-

    IF (.SHF NEQ 0) THEN RETURN (0);

!+
! If this terminal has editing features don't do it if there is
! a tab to the right of the cursor.  If this terminal does not
! have editing features, don't do it if there is anything to the
! right of the cursor.
!-

    IF .TI_EDIT
    THEN
	BEGIN

	IF ( NOT CH$FAIL (CH$FIND_CH (CH$DIFF (.LN_END, .LN_PTR), .LN_PTR, ASC_K_TAB)))
	THEN
	    RETURN (0);

	END
    ELSE

	IF (CH$DIFF (.LN_END, .LN_PTR) NEQ 0) THEN RETURN (0);

!+
! Finally, it looks possible.  Keep doing it as long as we can.
!-
    READ_DONE = 0;
    READ = 0;
    INS_MODE = 0;

    DO
	BEGIN
	TERMINATOR_PROCESSED = 0;
!+
! Compute the number of characters left on the line.
!-
	NUM_CHARS = .TI_WID - 1;

!+
! If we are in wrap mode, make sure we get control at the wrap column.
!-

	IF (.WD_WRAP LSS .NUM_CHARS) THEN NUM_CHARS = .WD_WRAP;

!+
! Subtract the current cursor position.
!-
	NUM_CHARS = .NUM_CHARS - .CUR_COL - .READ;
!+
! Subtract the width of the characters to the right of the cursor.  Note that
! unless we are on a terminal with screen editing features this will always
! be zero.  Note also that there can be no HTs to the right of the cursor,
! so the widths of the characters are independent of their position on the line.
! Hence the second parameter to EDT$$FMT_CHWID will not be used.
!-

	CPTR = .LN_PTR;
	DECR COUNT FROM CH$DIFF (.LN_END, .LN_PTR) TO 0 DO
	    NUM_CHARS = .NUM_CHARS - EDT$$FMT_CHWID (CH$RCHAR_A (CPTR), 0);

!+
! Make sure there is enough room left in the line buffer.
!-
	BUF_LEFT = 255 - CH$DIFF (.LN_PTR, CH$PTR (LN_BUF,, BYTE_SIZE));

	IF (.BUF_LEFT LSS .NUM_CHARS) THEN NUM_CHARS = .BUF_LEFT;

!+
! Don't try to read more than the space we have in our local bufferg
!-

	IF ((.NUM_CHARS + .READ) GTR 132) THEN NUM_CHARS = 132 - .READ;

!+
! Now, if we have a reasonable size, we can read with echo.
!-

	IF (.NUM_CHARS GTR CHAR_LIMIT_1)
	THEN
	    BEGIN
!+
! We will do a read with echo.  Make sure the video attributes are right.
!-

	    IF (.SEL_BUF EQL .CUR_BUF)
	    THEN
		BEGIN

		IF (EDT$$SEL_RNGPOS () LEQ 0) THEN EDT$$SC_REVID () ELSE EDT$$SC_NONREVID ()

		END
	    ELSE
		EDT$$SC_NONREVID ();

!+
! If we are not at the end of the line, put the terminal in insert mode.  This
! can only be done on terminals that have the 'edit' feature.
!-

	    IF ((CH$DIFF (.LN_END, .LN_PTR) NEQ 0) AND ( NOT .INS_MODE))
	    THEN
		BEGIN
		ASSERT (5, .TI_EDIT);
		EDT$$FMT_LIT (CH$PTR (UPLIT (%STRING (%CHAR (ASC_K_ESC), '[4h'))), 4);
		INS_MODE = 1;
		END;

!+
! Put out a carriage return to make the terminal driver think we are at the
! beginning of a line, then reposition the cursor.  This is needed only for
! some terminal drivers, that lose track of the cursor and output a CRLF
! if they think that the user is about to type to the right of the screen.
!-

	    IF .TI_DUMB
	    THEN
		BEGIN
		EDT$$FMT_LIT (CH$PTR (UPLIT (%STRING (%CHAR (ASC_K_CR)))), 1);
		PRV_COL = 0;
		END;

!+
! Make sure the cursor is positioned correctly.
!-
	    EDT$$SC_POSCSIF (.CS_LNO, .CUR_COL + .READ);
!+
! Do the special read with echo.  Optionally prompt.  Since the terminal driver may
! count the length of the prompt, it must be short enough that our "worst case" estimate
! of 10 characters in the repositioning allows for it.  Don't read more than 70 characters
! at a time.
!-

	    IF (.PMT_KPD [0] GTR 0)
	    THEN
		EDT$$FMT_LIT (CH$PTR (PMT_KPD [1],, BYTE_SIZE), .PMT_KPD [0]);

	    EDT$$TI_RDSTR (CH$PTR (TEXT_BUF ,.READ, BYTE_SIZE),
		 MIN (70, .NUM_CHARS - CHAR_LIMIT_2), NUM_READ);
	    PRV_COL = .PRV_COL + .NUM_READ;
	    READ_DONE = 1;
	    END
	ELSE
	    NUM_READ = 0;
!+
! Cause the characters to appear in the next journal record.
!-

	CPTR = CH$PTR (TEXT_BUF, .READ, BYTE_SIZE);
	EDT$$TI_BUFSTR (.CPTR, .NUM_READ);

	JOU_VALID = 1;
	READ = .READ + .NUM_READ;
!+
! If the line was terminated by a control C bail out.  If any characters were
! read the insert is aborted; otherwise the control C is effectively ignored.
!-

	IF EDT$$CHK_CC ()
	THEN
	    BEGIN

	    IF (.READ GTR 0) THEN CC_DONE = 1;

!+
! If we have put the terminal in insert mode, take it out.
!-

	    IF .INS_MODE
	    THEN
		BEGIN
		ASSERT (5, .TI_EDIT);
		EDT$$FMT_LIT (CH$PTR (UPLIT (%STRING (%CHAR (ASC_K_ESC), '[4l'))), 4);
		INS_MODE = 0;
		END;

	    RETURN (0);
	    END;

!+
! If there is a single terminator, and if it is defined to delete
! the last character, shorten the string by one and do another read.
!-

	IF ((.RDAHED EQL 1) AND 		!
	    EDT$$TST_KEYDEF (CH$RCHAR (CH$PTR (RDAHEDBF,, BYTE_SIZE)),
		 UPLIT (%STRING ('D-C.')), 4, 0) AND (.READ GEQ 1))
	THEN
	    BEGIN
!+
! Make sure the delete character appears in the journal.
!-
	    EDT$$TI_BUFCH (CH$RCHAR (CH$PTR (RDAHEDBF,, BYTE_SIZE)));
	    READ = .READ - 1;
	    EDT$$SC_POSCSIF (.CS_LNO, .PRV_COL - 1);

	    IF .INS_MODE
	    THEN
		BEGIN
!+
! We must delete exactly one character.
!-
		EDT$$FMT_LIT (CH$PTR (UPLIT (%STRING (%CHAR (ASC_K_ESC), '[P'))), 3);
		END
	    ELSE
		BEGIN
!+
! We are just before the character to delete, and there are no visible characters after
! the character to delete.  We can erase to end of line.
!-
		EDT$$SC_ERATOEOL ();
		END;

!+
! Store the character deleted in the delete character buffer.
!-
	    DEL_CHLEN = 1;
	    CPTR = CH$PTR (DEL_CH,, BYTE_SIZE);
	    CH$WCHAR_A (DIR_BACKWARD, CPTR);
	    CH$WCHAR (CH$RCHAR (CH$PTR (TEXT_BUF, .READ, BYTE_SIZE)), CPTR);
	    RDAHED = 0;
	    VERT = 0;
	    TERMINATOR_PROCESSED = 1;
	    END;

!+
! Keep reading if we processed the terminator.
!-
	END
    UNTIL ( NOT .TERMINATOR_PROCESSED);

!+
! Insert the characters read into the line.
!-
    EDT$$CPY_STR (CH$DIFF (.LN_END, .LN_PTR), .LN_PTR, CH$PLUS (.LN_PTR, .READ));
    EDT$$CPY_STR (.READ, CH$PTR (TEXT_BUF,, BYTE_SIZE), .LN_PTR);

!+
! Add the number of characters read to the line size.
!-
    EDT$$UPD_LNLEN (.READ);
!+
! If we actually read some characters update the cursor position.
!-

    IF (.READ NEQ 0)
    THEN
	BEGIN
	CUR_COL = .CUR_COL + .READ;
	VERT = 0;
!+
! Note that the line is not marked as changed for the screen
! updater, since the modification to the screen has already
! been made.  However, we must note for the work file system
! that the current line has been changed.
!-
	LN_CHGD = 1;
	END;

!+
! Update the current character pointer.
!-
    LN_PTR = CH$PLUS (.LN_PTR, .READ);
    CS_OLDCHNO = .CS_OLDCHNO + .READ;
!+
! If we have put the terminal in insert mode, take it out.
!-

    IF .INS_MODE
    THEN
	BEGIN
	ASSERT (5, .TI_EDIT);
	EDT$$FMT_LIT (CH$PTR (UPLIT (%STRING (%CHAR (ASC_K_ESC), '[4l'))), 4);
	INS_MODE = 0;
	END;

    RETURN (.READ_DONE);
    END;					! of routine EDT$$RD_ECHO

END						! of module CHMEINPUT

ELUDOM