%	*****************************************************************
%	*								*
%	*	This module is a part of the SAO VAX/VMS		*
%	*	RED full-screen text editor				*
%	*								*
%	*	It was created by					*
%	*	Roger Hauck						*
%	*	Smithsonian Institution					*
%	*	Astrophysical Observatory				*
%	*	Cambridge, Massachusetts  02138				*
%	*	(617)495-7151  (FTS 830-7151)				*
%	*								*
%	*	This module may be reproduced				*
%	*	provided that this header is retained.			*
%	*								*
%	*****************************************************************

%  Define Window-related Variables

0 'PNTR VARIABLE

0 'TOPWINDOW VARIABLE  % # of bytes before cursor in window
0 'BOTWINDOW VARIABLE  % # of bytes after cursor in window
0 'BLANK_LINES VARIABLE  % # of blank lines in window

'TOPOWINDOW@ :  % TOPOWINDOW@, address of first byte of window
  BOTOTOP @ TOPWINDOW @ -
  ;

'TOPOWINDOW! :  % address, TOPWINDOW! (establishes top of window)
  BOTOTOP @ - MINUS TOPWINDOW !
  ;

'BOTOWINDOW@ :
  TOPOBOT @ BOTWINDOW @ +
  ;

'BOTOWINDOW! :
  TOPOBOT @ - BOTWINDOW !
  ;

'TOP_WINDOW_STRING :  % TOP_WINDOW_STRING, descriptor
%	of string from top of window to cursor
  TOPWINDOW @ BOTOTOP @ OVER - SWAP
  ;

'BOT_WINDOW_STRING :  % BOT_WINDOW_STRING, descriptor
%	of string from cursor to bottom of window
  TOPOBOT @ BOTWINDOW @
  ;


%  Operations relating to window management.

'S.CUP :  % S.CUP  (puts cursor at preselected position)
  SROW D@ CUP
  ;

'E.CR_TYO :
  DROP  % drop attribute request
  CRET TYO  % output CR
  ;

'E.TAB_TYO :
  TAB_MODE @ IF  % hard tabs?
    DROP  % drop attribute request
    09 TYO ELSE  % output hard tab
    1 OR SGR 49 TYO 0 SGR THEN  % output bold I
  ;

'E.TYO :
  DUP 80 LE_IF  % is mark bit set?
    7F AND 4 ELSE  % yes, reset bit, request underline
    0 THEN SWAP  % no
  DISPATCH 0D E.CR_TYO
  DISPATCH 8D E.CR_TYO
  DISPATCH 09 E.TAB_TYO
  DUP 20 GT_IF  % is it a control character?
    40 + SWAP 1 OR ELSE  % yes, make upper case and request bold
    SWAP THEN  % no
  NEZ_IF  % any attribute requests?
    UNDROP SGR TYO 0 SGR ELSE  % yes, output byte with attributes
    TYO THEN  % no, normal
  ;

'PLINE :
  BEGIN
    DUP 1+ SWAP B@  % get next character
    DUP CRET NE IF
      E.TYO REPEAT  % output it
  DROP CR  % drop CR, output NL
  8 IDLES  %  idle
  ;

'TW_COUNT :  % TW_COUNT, descriptor of top of window
  TOPOWINDOW@ TOPWINDOW @
  ;

'BW_COUNT :  % BW_COUNT, descriptor of bottom of window
  TOPOBOT @ BOTWINDOW @
  ;

'E.TYPE :
  NEZ_IF
    UNDROP ERASE_REST_OF_LINE
    (
      DUP I + B@ DUP E.TYO CRET EQ_IF
        0A TYO ERASE_THIS_LINE THEN )
    THEN DROP
  ;

'SBB_COUNT :
  GTZ_IF
    UNDROP (
      SBB DUP LEZ_IF EXIT THEN
      )
    THEN
  LAST_I
  ;

09 'TAB CONSTANT

ASSEMBLER<
'D.TAB :  % current column #, D.TAB, new column #
  TAB_MODE @ IF  % hard tabs?
    DECL (P) BICL2 S^ 7 (P) ADDL2 S^ 9 (P) ELSE  % yes
    1+ THEN  % no
  ;
>

'FIND_CURSOR_COLUMN :
  CRET TOP_COUNT SBB GEZ_IF  % search backwards for carriage return, found?
    UNDROP + 1+ THEN  % yes, calculate location
  BOTOTOP @ OVER -  % descriptor of string passed over
  1 SWAP  % initialize column count
    (
      OVER I + B@ TAB EQ_IF
        D.TAB ELSE  % yes, calculate new column
        1+ THEN )  % no, increment column #   
  SCOL !  % record it
  2DROP  % drop search byte, pointer to beginning of line
  ;

'DEFINE_TOP_OF_WINDOW :
  CRET TOP_COUNT TF @ 1+  % setup to search
  DUP 1+ SROW !  % set cursor row to center of window
  SBB_COUNT  % do search
  TF @ - MINUS 0 MAX BLANK_LINES !  % calculate & store # of blank lines
  + 1+ TOPOWINDOW!  % find top of window
  DROP  % drop search byte
  FIND_CURSOR_COLUMN
  ;

'FILL_BOTTOM_WINDOW :  % (cursor must be correctly positioned first)
  TOPOBOT @  % save pointer
  TF @ 1+ (  % loop through bottom lines
  ERASE_REST_OF_LINE
    BEGIN
      BOPOP IF  % anything left?
        DUP CRET NE ELSE  % yes, indicate whether it's a carriage return
        CRET 0 THEN  % no, simulate carriage return
      IF  % was it a carriage return?
        E.TYO REPEAT  % no, output character
    TYO I' NEZ_IF  % yes, output carriage return, last line?
      LFEED TYO THEN  % no, output line feed
    )
  TOPOBOT @ SWAP TOPOBOT ! BOTOWINDOW!  % record pointers
  ;

'ADD_LINE_AT_BOTTOM :
  TOPOBOT @ BOTOWINDOW@ TOPOBOT !  % temporarily redefine bottom buffer
  BEGIN
    BOPOP IF  % anything left?
      DUP E.TYO  % yes, output it
      CRET EQ ELSE  % stop if CR
      -1 THEN  % EOF, stop
    END
  TOPOBOT @  % new bottom of window
  SWAP TOPOBOT !  % restore bottom buffer
  BOTOWINDOW!  % store bottom of window
  ;

'FIND_CURSOR :
  SCOL 1<- SROW 1<-
  TW_COUNT (  % scan through bottom of window
    DUP I + B@  % next byte
    CRET EQ_IF  % is it a CR
      SCOL 1<- SROW 1+<- ELSE  % yes, reset column, increment row
      UNDROP TAB EQ_IF  % is it a tab?
        SCOL @ D.TAB SCOL ! ELSE  % yes, get column #
        SCOL 1+! THEN THEN  % no, increment column
    ) DROP
  SROW BLANK_LINES @ 1+ +<-  % get real row #
  ;

'SETSCREEN :
  DISP_FLAG 2 <-
  ;

'DISP :
  DISP_FLAG @ 1 OR DISP_FLAG !
  ;

%****************  TEMPORARY DEFINITIONS  ***************
'NSCROLL : DROP DISP ;
'-NSCROLL : DROP DISP ;
%********************************************************

'REVISE_WINDOW :  % (scrolls if necessary and redraws cursor)
  1 SROW @ - DUP GEZ IF  % cursor above window?
    1+ -NSCROLL ELSE  % yes, scroll down
    WINDOW_SIZE + MINUS DUP GTZ IF  % cursor below window?
      NSCROLL ELSE DROP THEN THEN  % yes, scroll up
  S.CUP
  ;

'SCROLL_DOWN_1 :  % screen must be set up first
  RI  % scroll down
  TOPOWINDOW@ DUP 1- TOPOTOP @ MAX DUP TOPOWINDOW!  % reduce at least one
  BEGIN  % loop till top of file or CR
    1- DUP TOPOTOP @ GT IF  % past the beginning?
      -1 ELSE  % yes, signal exit
      DUP B@ CRET EQ THEN  % signal exit if CR
    END 1+  % new value for TOPOWINDOW
  SWAP OVER - GTZ_IF
    UNDROP ( DUP I + B@ E.TYO ) ELSE  % draw the line
    BLANK_LINES 1+!
    THEN  % store new value
  TOPOWINDOW!
  ;

'FIND_BOTOWINDOW :  % stores position of first char. below screen in BOTOWINDOW
  TOPOBOT @  % save TOPOBOT
  WINDOW_SIZE 2+ SROW @ - (
    BEGIN
      BOPOP IF  % any more bytes?
        CRET EQ ELSE  % signal end if CR
        -1 THEN  % EOF, signal end
      END
    )  % got it
  TOPOBOT @  % new bottom of window
  SWAP TOPOBOT !  % restore bottom buffer
  BOTOWINDOW!  % store bottom of window
  ;
