From:	CRDGW2::CRDGW2::MRGATE::"SMTP::CRVAX.SRI.COM::RELAY-INFO-VAX" 28-JUL-1990 01:08:08.84
To:	MRGATE::"ARISIA::EVERHART"
CC:	
Subj:	TPU Rectangular cut and paste with INSERT mode 1 of 1

Received:  by crdgw1.ge.com (5.57/GE 1.70)
	 id AA02200; Sat, 28 Jul 90 00:46:20 EDT
Received: From UCBVAX.BERKELEY.EDU by CRVAX.SRI.COM with TCP; Fri, 27 JUL 90 17:11:47 PDT
Received: by ucbvax.Berkeley.EDU (5.63/1.42)
	id AA08917; Fri, 27 Jul 90 17:02:35 -0700
Received: from USENET by ucbvax.Berkeley.EDU with netnews
	for info-vax@kl.sri.com (info-vax@kl.sri.com)
	(contact usenet@ucbvax.Berkeley.EDU if you have questions)
Date: 28 Jul 90 02:16:45 GMT
From: daemon@bloom-beacon.mit.edu
Organization: M.I.T. Lab for Nuclear Science
Subject: TPU Rectangular cut and paste with INSERT mode 1 of 1
Message-Id: <1990Jul27.233239.5182@athena.mit.edu>
Sender: info-vax-request@kl.sri.com
To: info-vax@kl.sri.com

-Message-Text-Follows-

   15 people asked for this in 24 hours so I thought I'd post it. It is a 
VMS_SHARE file. Get rid of these lines and execute it as a com file to unpack 
it. We don't get stuff in VMSNET.SOURCES  so I assumed something is broke there
and didn't post it there. If some one wants to cross post please do. I 
thought it would be O.K. to post here since its not too big, and there
was some interest. If someone can put this on a mail server please do
I won't repost it due to net bandwidth considerations. If you get a screwed
up copy write me (don't post) and I'll mail one to you.


$! ------------------ CUT HERE -----------------------
$ v='f$verify(f$trnlnm("SHARE_VERIFY"))'
$!
$! This archive created by VMS_SHARE Version 7.1-004  3-AUG-1989
$!   On 27-JUL-1990 19:14:58.74   By user CHUCK 
$!
$! This VMS_SHARE Written by:
$!    Andy Harper, Kings College London UK
$!
$! Acknowledgements to:
$!    James Gray       - Original VMS_SHARE
$!    Michael Bednarek - Original Concept and implementation
$!
$! TO UNPACK THIS SHARE FILE, CONCATENATE ALL PARTS IN ORDER
$! AND EXECUTE AS A COMMAND PROCEDURE  (  @name  )
$!
$! THE FOLLOWING FILE(S) WILL BE CREATED AFTER UNPACKING:
$!       1. NEWRECT.TPU;5
$!
$set="set"
$set symbol/scope=(nolocal,noglobal)
$f=f$parse("SHARE_TEMP","SYS$SCRATCH:.TMP_"+f$getjpi("","PID"))
$e="write sys$error  ""%UNPACK"", "
$w="write sys$output ""%UNPACK"", "
$ if f$trnlnm("SHARE_LOG") then $ w = "!"
$ if f$getsyi("version") .ges. "V4.4" then $ goto START
$ e "-E-OLDVER, Must run at least VMS 4.4"
$ v=f$verify(v)
$ exit 44
$UNPACK: SUBROUTINE ! P1=filename, P2=checksum
$ if f$search(P1) .eqs. "" then $ goto file_absent
$ e "-W-EXISTS, File ''P1' exists. Skipped."
$ delete/nolog 'f'*
$ exit
$file_absent:
$ if f$parse(P1) .nes. "" then $ goto dirok
$ dn=f$parse(P1,,,"DIRECTORY")
$ w "-I-CREDIR, Creating directory ''dn'."
$ create/dir 'dn'
$ if $status then $ goto dirok
$ e "-E-CREDIRFAIL, Unable to create ''dn'. File skipped."
$ delete/nolog 'f'*
$ exit
$dirok:
$ w "-I-PROCESS, Processing file ''P1'."
$ define/user sys$output nl:
$ EDIT/TPU/NOSEC/NODIS/COM=SYS$INPUT 'f'/OUT='P1'
PROCEDURE Unpacker ON_ERROR ENDON_ERROR;SET(FACILITY_NAME,"UNPACK");SET(
SUCCESS,OFF);SET(INFORMATIONAL,OFF);f:=GET_INFO(COMMAND_LINE,"file_name");
buff:=CREATE_BUFFER(f,f);p:=SPAN(" ")@r&LINE_END;POSITION(BEGINNING_OF(buff))
;LOOP EXITIF SEARCH(p,FORWARD)=0;POSITION(r);ERASE(r);ENDLOOP;POSITION(
BEGINNING_OF(buff));g:=0;LOOP EXITIF MARK(NONE)=END_OF(buff);x:=
ERASE_CHARACTER(1);IF g = 0 THEN IF x="X" THEN MOVE_VERTICAL(1);ENDIF;IF x=
"V" THEN APPEND_LINE;MOVE_HORIZONTAL(-CURRENT_OFFSET);MOVE_VERTICAL(1);ENDIF;
IF x="+" THEN g:=1;ERASE_LINE;ENDIF;ELSE IF x="-" THEN g:=0;ENDIF;ERASE_LINE;
ENDIF;ENDLOOP;p:="`";POSITION(BEGINNING_OF(buff));LOOP r:=SEARCH(p,FORWARD);
EXITIF r=0;POSITION(r);ERASE(r);COPY_TEXT(ASCII(INT(ERASE_CHARACTER(3))));
ENDLOOP;o:=GET_INFO(COMMAND_LINE,"output_file");WRITE_FILE(buff,o);
ENDPROCEDURE;Unpacker;EXIT;
$ delete/nolog 'f'*
$ CHECKSUM 'P1'
$ IF CHECKSUM$CHECKSUM .eqs. P2 THEN $ EXIT
$ e "-E-CHKSMFAIL, Checksum of ''P1' failed."
$ ENDSUBROUTINE
$START:
$ create/nolog 'f'
X! This is slightly modified from the DECUS eveplus distribution. I looked
X! in our source files but found no author for the EVEPLUS origonal.
X! Apologies and thanks to that person, I only made a few simple changes.
X!
X! The major advantage is that this version includes a insert mode as
X!well as the overlay mode of the origional. In insert mode  if you
X!cut out a column the text to the right of that column moves left.
X!In overstrike mode the column is replaced by spaces. Conversely when
X!you insert in INSERT mode the text moves over to make room, and is
X!overwritten in OVERSTRIKE mode
X!
X!  To use this code:
X!
X!    EDIT/TPU/SECTION=MY_OLD_EVE_BASED_EDITOR.TPU$SECTION   THIS_FILE.TPU
X!  Hit the DO key and type
X!    EXTEND TPU *  <Ret>
X!  If you don't use the EDT key pad you may want to skip the next step
X!  it won't completly work, since the GOLD key (PF1) won't be defined.
X!  If you don't already use the keypad but want to then
X!    DO
X!    SET KEYPAD EDT <Ret>
X!  This defines the keys to work with the EDT style keypad
X!    DO
X!    DEFINE RECTANGULAR KEYS <Ret>
X!  Do this to save your configuration
X!    DO <RET>
X!    SAVE EXTENDED TPU SYS$LOGIN:MY_NEW_EDITOR.TPU$SECTION
X!
X!  You are all set. If you have defined the rectangular keys here is what
X!  you do.
X!
X!       Hit "PF1 F17". This toggles  cut and paste to rectangular
X!       Move the cursor to the top left corner of what you want to remove
X!       Hit "PF1" keypad "." or "Select" key
X!       Move the to the bottom right.
X!       Hit  keypad "6"  or "Remove" the rectangle gets removed!
X!       Hit  "PF1" keypad "6"  or "Insert here"the rectangle gets replaced!
X!       Hit "PF1 F17". This toggles  cut and paste back to normal EVE mode
X!
X!       Hit "PF1" "F20" toggle back and forth between insert and overstrike
X!       mode. Just try it a few times to see how it works
X!
X!       Hit "PF1" "F19" to put a box around a selected rectangle. This
X!       also responds to the insert/overstrike mode.
X!
X!      If you want to define your own keys here are the relevent routines
X!
X!      eve_define_rectangular_keys    Sets up the PF1 F17-F20 keys
X!      eve_toggle_cut_and_paste_mode  Toggles cut/paste keys RECTANGULAR/EDT
X!      EVE_SET_RECTANGULAR            Sets  cuts/paste keys to RECTANGULAR
X!      EVE_SET_NORECTANGULAR          Sets  cuts/paste keys to EDT
X!      eve_toggle_rectangular_mode    Toggles insert/overstrike mode
X!      EVE_RECTANGULAR_SELECT         Begin rectangular selection
X!      eve_rectangular_remove         Rectangular CUT
X!      eve_rectangular_insert_here    Rectangular PASTE
X!      eve_draw_box                   Draw a box around the selected region
X!
X!
X!
X!
X!
X
Xprocedure eve_define_rectangular_keys
Xeve$cut_paste_mode:="EDT";
Xdefine_key("eve_toggle_cut_and_paste_mode",key_name(f17,shift_key),
X             "Toggles between normal/rectangle cut and paste mode ");
Xdefine_key("eve_set_norectangular",key_name(f18,shift_key),
X                    "normal cut and paste mode (reset from rectangle mode)")
V;
Xdefine_key("eve_draw_box",key_name(f19,shift_key),
X                "Draws box around selected region OVERSTRIKES CHARACTERS");
Xdefine_key("eve_toggle_rectangular_mode",key_name(f20,shift_key),
X"Toggles between cut/past OVERSTRIKE mode and more EDT like INSERT mode.");
X!
Xendprocedure;
X
X!`009Set rectangular mode for both VT200 keys and EVEDT numeric keypad
X!
Xprocedure eve_toggle_cut_and_paste_mode
X      if (eve$cut_paste_mode = "EDT") then
X         eve_set_rectangular;
X      else
X         eve_set_norectangular;
X      endif;
X      message("Cut and paste keys are now in "+eve$cut_paste_mode+" mode");
Xendprocedure;
X
X
X!  ********************************************************************
X!   MODIFIED AND ADDED BELOW PROCEDURE TO ALLOW INSERT MODE FOR PASTE
X!        AND DELETE MODE FOR CUT
X!      EVE_toggle_CUT_MODE
X!**************************************************************
X! RECTANGULAR cut and paste source
X!**************************************************************
XProcedure EVE_SET_RECTANGULAR
Xeveplus_v_begin_select := 0;
Xeve$cut_paste_mode:="RECTANGULAR";
Xdefine_key("eve_rectangular_remove", e3, "edd_remove");
Xdefine_key("eve_rectangular_insert_here", e2, "edd_insert_here");
Xdefine_key("eve_rectangular_select", e4, "edd_select");
Xdefine_key("eve_rectangular_remove", kp6, "edd_remove");
Xdefine_key("eve_rectangular_insert_here", key_name(kp6,shift_key),
X        "edd_insert_here");
Xdefine_key("eve_rectangular_select", period, "edd_select");
Xdefine_key("eve_rectangular_select", key_name(period,shift_key),
X`009"edd_select");
Xendprocedure
X
X!
X!`009Set norectangular mode for both VT200 keys and EVEDT numeric keypad
X!
XProcedure EVE_SET_NORECTANGULAR
Xeveplus_v_begin_select := 0;
Xeve$cut_paste_mode:="EDT";
Xdefine_key("eve_remove", e3, "remove");
Xdefine_key("eve_insert_here", e2, "insert_here");
Xdefine_key("eve_select", e4, "select");
Xdefine_key("eve_remove", kp6, "remove");
Xdefine_key("eve_insert_here", key_name(kp6,shift_key), "insert_here");
Xdefine_key("eve_select", period, "select");
Xdefine_key("eve_select", key_name(period,shift_key), "select");
Xendprocedure
X!===========================================================================
V=
X!**************************************************************
X!Rectangular cut and paste source
X!**************************************************************
X!+
X!`009RECCUTPAS.TPU - Eve version of  rectangular cut and paste
X!-
X!
X! TPU emulation of  rectangular CUT/PASTE including following routines:
X!`009EVE_DRAW_BOX
X!`009EVE_RECTANGULAR_REMOVE
X!       EVE_RECTANGULAR_INSERT_HERE
X!       EVE_RECTANGULAR_SELECT
X!       EVEPLUS_PAD_BLANK
X!       EVE_SET_RECTANGULAR
X!       EVE_SET_NORECTANGULAR
X!       EVEPLUS_SET_MODE
X!       EVEPLUS_BLANK_CHARS
X!       EVEPLUS_ADVANCE_HORIZONTAL
X!
X!  ********************************************************************
X!   MODIFIED AND ADDED BELOW PROCEDURE TO ALLOW INSERT MODE FOR PASTE
X!        AND DELETE MODE FOR CUT
X!      EVE_toggle_CUT_MODE
Xprocedure eve_toggle_rectangular_mode
X      if(eve$rectangular_mode = "INSERT")then
X         eve$rectangular_mode:="OVERSTRIKE";
X      else
X         eve$rectangular_mode:="INSERT";
X      endif;
X      message("Rectangular cut and paste mode is now "+eve$rectangular_mode)
V;
Xendprocedure;
X!
X!
X!
X!
X! Rectangular CUT/PASTE provides a way to select a corner of a rectangular
X! region on the screen that is to be CUT.  This select point is highlighted
X! in reverse video.  The cursor can then be positioned to the opposite
X! corner of the box at which point the CUT can be done to place the rectangu
Vlar
X! region in paste_buffer.  PASTE can then be done to overstrike the
X! rectangular region in paste_buffer onto the current_buffer using the
X! current position as the upper left corner for the pasted region.  Note
X! that no provision is made if there are TAB chars in the current buffer.
X! Also, no provision is made if the cut or paste is done with part of the
X! region to be cut or pasted over not being visible on the screen.
X!
X! These procedures can be run with the current buffer set to overstrike
X! or insert mode - CUT/PASTE need to switch to insert mode temporarily
X! to get the chars replaced properly, but the previous mode setting for
X! the current buffer is restored when either the cut or paste routine comple
Vtes.
X!
X! GLOBAL VARIABLES created/used
X!`009eveplus_v_begin_select -`009position where selected region begins
X!       eve$x_vt200_keypad
X!
X! GLOBAL VARIABLES used
X!       current_buffer
X!`009paste_buffer
X!
X! This TPU file rebinds the SELECT/REMOVE/INSERT HERE keys to the included
X! routines and initializes the eveplus_v_begin_select variable when the
X! eve_set_rectangular procedure is executed.  The standard Eve key bindings
X! are restored when the eve_set_norectangular procedure is executed.
X!
X`012
X!+
X!   Procedure to calculate the current column from the current offset, treat
Ving
X!   TAB characters as up to 8 blanks.
X!-
XPROCEDURE edd_current_column
XLOCAL
X    i,
X    line,
X    col;
X
Xline := current_line;
XIF INDEX(line,ASCII(9)) = 0
XTHEN
X    edd_current_column := current_offset
XELSE
X    i := 1;
X    col := 0;
X    LOOP
X`009EXITIF i > current_offset;
X`009IF SUBSTR(line,i,1) = ASCII(9)
X`009THEN
X`009    col := ((col + 8)/8)*8
X`009ELSE
X`009    col := col + 1
X`009ENDIF;
X`009i := i + 1
X    ENDLOOP;
X    edd_current_column := col
XENDIF
XENDPROCEDURE
X
X!+
X!   Procedure to replace TAB characters by the appropriate number of
X!   blanks on the current line, then pad the line out to a given length, if
V it
X!   is shorter.  The routine assumes overstrike mode is in
X!   effect.  It leave the current position at the beginning of the line.
X!-
XPROCEDURE edd_replace_tabs_with_blanks_and_pad(target_length)
XLOCAL
X    i,
X    col,
X    cur_length,
X    new_line,
X    eight_blanks;
X
X!+
X!   Make sure we're not on the EOB marker.
X!-
XIF MARK(NONE) <> END_OF(CURRENT_BUFFER)
XTHEN
X    IF INDEX(CURRENT_LINE, ASCII(9)) <> 0
X    THEN
X`009new_line := '';
X`009eight_blanks := "        ";
X`009i := 1;
X`009col := 0;
X`009LOOP
X`009    EXITIF i > LENGTH(CURRENT_LINE);
X`009    IF SUBSTR(CURRENT_LINE,i,1) = ASCII(9)
X`009    THEN
X`009`009col := ((col + 8)/8)*8;
X`009`009new_line := new_line + SUBSTR(eight_blanks,1,col-LENGTH(new_line))
X`009    ELSE
X`009`009new_line := new_line + SUBSTR(CURRENT_LINE,i,1);
X`009`009col := col + 1
X`009    ENDIF;
X`009    i := i + 1
X`009ENDLOOP;
X
X`009MOVE_HORIZONTAL(-CURRENT_OFFSET);
X`009COPY_TEXT(new_line)
X    ENDIF
XENDIF;
X
XMOVE_HORIZONTAL(-CURRENT_OFFSET);
X
X!+
X!   Now pad out the line if we have to
X!-
XIF MARK(NONE) = END_OF(CURRENT_BUFFER)
XTHEN
X    cur_length := 0
XELSE
X    cur_length := LENGTH(CURRENT_LINE)
XENDIF;
X
XIF cur_length < target_length
XTHEN
X    MOVE_HORIZONTAL(cur_length);
X    COPY_TEXT(eveplus_blank_chars(target_length - cur_length));
XENDIF;
X
XMOVE_HORIZONTAL(-CURRENT_OFFSET)
XENDPROCEDURE
X
X`012
XPROCEDURE eve_draw_box
X    LOCAL
X`009saved_mode,
X`009end_column,
X`009start_column,
X`009temp,
X`009end_select,
X`009top_bottom_text;
X
X    !+
X    !   Check for no select active
X    !-
X    IF eveplus_v_begin_select = 0
X    THEN
X`009MESSAGE("Select not active");
X`009RETURN
X    ENDIF;
X
X    !+
X    !  Set INSERT mode
X    !-
X    saved_mode := eveplus_set_mode(INSERT);
X
X    !+
X    !   Make sure there is a character at the corner of the box opposite
X    !   the begin_select mark.  If the end_select mark is before the
X    !   begin_select mark, juggle the markers so that begin_select precedes
X    !   end_select.
X    !-
X    eveplus_pad_blank;
X    IF MARK(NONE) >= eveplus_v_begin_select
X    THEN
X`009end_select := MARK(NONE)
X    ELSE
X`009end_select := eveplus_v_begin_select;
X`009eveplus_v_begin_select := MARK(NONE);
X`009POSITION(end_select)
X    ENDIF;
X
X    !+
X    !   Figure out what column the box ends in and set END_COLUMN there.
X    !   Then, clear out the video on EVEPLUS_V_BEGIN_SELECT.  Figure out
X    !   the start column.
X    !-
X    end_column := edd_current_column;
X    POSITION(eveplus_v_begin_select);
X    eveplus_v_begin_select := MARK(NONE);
X    start_column := edd_current_column;
X
X    !+
X    !   We may have the upper right and lower left corners of the box
X    !   selected.  If so, START_COLUMN and END_COLUMN need to be reversed.
X    !-
X    IF start_column > end_column
X    THEN
X`009temp := end_column;
X`009end_column := start_column;
X`009start_column := temp
X    ENDIF;
X
X    !+
X    !   We may be building the box on the first line of the buffer.  In
X    !   that case, we must put a new top line in the buffer.
X    !-
X    MOVE_HORIZONTAL(-CURRENT_OFFSET);
X    IF MARK(NONE) = BEGINNING_OF(CURRENT_BUFFER)
X    THEN
X`009SPLIT_LINE;
X`009POSITION(BEGINNING_OF(CURRENT_BUFFER));
X`009COPY_TEXT(eveplus_blank_chars(start_column));
X`009MOVE_VERTICAL(1);
X`009MOVE_HORIZONTAL(-CURRENT_OFFSET)
X    ENDIF;
X    !+
X    !   Move back one line and put in the top line of the box
X    !-
X    top_bottom_text := '+' + eveplus_blank_chars(end_column-start_column+1)
V +
X`009'+';
X    TRANSLATE(top_bottom_text, "-", " ");
X    SET(OVERSTRIKE, current_buffer);
X    MOVE_VERTICAL(-1);
X
X    !+
X    !   Replace all TABs with blanks on this line and pad it, if we need to.
X    !-
X    edd_replace_tabs_with_blanks_and_pad(end_column + 1);
X
X    !*
X    !*  In insert mode we want to move to column not column-1
X    !*
X    if eve$rectangular_mode = "INSERT" then
X      MOVE_HORIZONTAL(start_column);
X      SET(INSERT, current_buffer);
X    else
X      IF start_column <> 0 then
X`009MOVE_HORIZONTAL(start_column - 1)
X      endif;
X    ENDIF;
X
X    COPY_TEXT(top_bottom_text);
X    MOVE_VERTICAL(1);
X    MOVE_HORIZONTAL(-CURRENT_OFFSET);
X
X    !+
X    !   Step through the selected lines, putting vertical bars on either sid
Ve
X    !   of the selected text.
X    !-
X    LOOP
X`009EXITIF MARK(NONE) > end_select;
X
X`009!+
X`009!   Replace all TABs with blanks on this line, if we need to.
X`009!-
X`009edd_replace_tabs_with_blanks_and_pad(end_column + 1);
X
X`009!+
X`009!   If START_COLUMN is zero, we must insert a vertical bar to do the
X`009!   left column, then put the right vertical bar one column farther out
X`009!   than normal.
X`009!-
X        IF (eve$rectangular_mode="INSERT")THEN
X`009  MOVE_HORIZONTAL(start_column);
X`009  SET(INSERT, CURRENT_BUFFER);
X          COPY_TEXT("`124");
X`009  MOVE_HORIZONTAL(end_column - CURRENT_OFFSET + 2);
X`009ELSE
X          IF (start_column = 0)then
X`009    SET(INSERT, CURRENT_BUFFER);
X`009    COPY_TEXT("`124");
X`009    SET(OVERSTRIKE, CURRENT_BUFFER);
X`009    MOVE_HORIZONTAL(end_column + 1);
X          ELSE
X`009    MOVE_HORIZONTAL(start_column-1);
X`009    COPY_TEXT("`124");
X`009    MOVE_HORIZONTAL(end_column - CURRENT_OFFSET + 1);
X          endif;
X`009ENDIF;
X
X`009COPY_TEXT("`124");
X`009MOVE_HORIZONTAL(-CURRENT_OFFSET);
X`009MOVE_VERTICAL(1)
X    ENDLOOP;
X    SET(OVERSTRIKE, CURRENT_BUFFER);
X
X    !+
X    !   Now put in the bottom line of the box.
X    !-
X
X    !+
X    !   Replace all TABs with blanks on this line, if we need to.
X    !-
X    edd_replace_tabs_with_blanks_and_pad(end_column + 1);
X    !*
X    !*  In insert mode we want to move to column not column-1
X    !*
X    if eve$rectangular_mode = "INSERT" then
X      MOVE_HORIZONTAL(start_column);
X      SET(INSERT, current_buffer);
X    else
X      IF start_column <> 0 then
X`009MOVE_HORIZONTAL(start_column - 1)
X      endif;
X    ENDIF;
X
X    COPY_TEXT(top_bottom_text);
X
X    !+
X    !   Position to the beginning of the cut area, reset BEGIN_SELECT,
X    !   restore old insert/overstrike setting
X    !-
X    POSITION(eveplus_v_begin_select);
X    eveplus_v_begin_select := 0;
X    MOVE_HORIZONTAL(-CURRENT_OFFSET);
X    IF start_column = 0
X    THEN
X`009MOVE_HORIZONTAL(1)
X    ELSE
X`009MOVE_HORIZONTAL(start_column)
X    ENDIF;
X
X    SET(saved_mode, CURRENT_BUFFER)
XENDPROCEDURE
XPROCEDURE eve_rectangular_remove
X    LOCAL
X`009saved_mode,
X`009end_select,
X`009end_column,
X`009start_column,
X`009temp,
X`009pad_chars,
X`009save_position,
X`009blank_chars,
X        ptr,
X`009cut_text;
X
X    !+
X    !   Check for no select active
X    !-
X    IF eveplus_v_begin_select = 0
X    THEN
X`009MESSAGE("Select not active");
X`009RETURN
X    ENDIF;
X
X    !+
X    !   Set INSERT mode and erase PASTE_BUFFER
X    !-
X    saved_mode := eveplus_set_mode(INSERT);
X    ERASE(paste_buffer);
X
X    !+
X    !   Make sure there is a character at the corner of the box opposite
X    !   the begin_select mark.  If the end_select mark is before the
X    !   begin_select mark, juggle the markers so that begin_select precedes
X    !   end_select.
X    !-
X    eveplus_pad_blank;
X    IF MARK(NONE) >= eveplus_v_begin_select
X    THEN
X`009end_select := MARK(NONE)
X    ELSE
X`009end_select := eveplus_v_begin_select;
X`009eveplus_v_begin_select := MARK(NONE);
X`009POSITION(end_select)
X    ENDIF;
X
X    !+
X    !   Figure out what column the box ends in and set END_COLUMN there.
X    !   Then, clear out the video on EVEPLUS_V_BEGIN_SELECT.  Figure out
X    !   the start column.
X    !-
X    end_column := edd_current_column;
X    POSITION(eveplus_v_begin_select);
X    eveplus_v_begin_select := MARK(NONE);
X    start_column := edd_current_column;
X
X    !+
X    !   We may have the upper right and lower left corners of the box
X    !   selected.  If so, START_COLUMN and END_COLUMN need to be reversed.
X    !-
X    IF start_column > end_column
X    THEN
X`009temp := end_column;
X`009end_column := start_column;
X`009start_column := temp
X    ENDIF;
X
X    !+
X    !   Get a string of the appropriate number of blanks to paste back in
X    !-
X    pad_chars := eveplus_blank_chars(end_column - start_column + 1);
X
X    !+
X    !   Step through the selected lines, copying the text to the paste buffe
Vr
X    !   and replacing it with blanks as we go.  Replace all TABs with blanks
X    !   before we look at it so we get the columns straight.
X    !-
X    MOVE_HORIZONTAL(-current_offset);
X    SET(OVERSTRIKE, current_buffer);
X    LOOP
X`009EXITIF MARK(NONE) > end_select;
X
X`009!+
X`009!   Replace all TABs with blanks on this line, if we need to.
X`009!-
X`009edd_replace_tabs_with_blanks_and_pad(end_column + 1);
X
X`009!+
X`009!   Obtain the text we're cutting
X`009!-
X`009cut_text := SUBSTR(CURRENT_LINE, start_column + 1,
X`009    end_column - start_column + 1);
X
X`009!+
X`009!   In insert mode REMOVE the text
X`009!-
X        if eve$rectangular_mode = "INSERT" then
X           move_horizontal(start_column);
X           ptr:=search(cut_text,forward);
X           erase(ptr);
X        else
X`009!+
X`009!   Replace the text with blanks
X`009!-
X          MOVE_HORIZONTAL(start_column);
X          COPY_TEXT(pad_chars);
X        endif;
X`009!+
X`009!   Copy the text to the paste buffer
X`009!-
X`009save_position := MARK(NONE);
X`009POSITION(paste_buffer);
X`009COPY_TEXT(cut_text);
X`009MOVE_HORIZONTAL(1);
X
X`009!+
X`009!   Reposition to the other buffer and move to the next line
X`009!-
X`009POSITION(save_position);
X`009MOVE_HORIZONTAL(-CURRENT_OFFSET);
X`009MOVE_VERTICAL(1)
X    ENDLOOP;
X
X    !+
X    !   Position to the beginning of the cut area, reset BEGIN_SELECT,
X    !   restore old insert/overstrike setting
X    !-
X    POSITION(eveplus_v_begin_select);
X    eveplus_v_begin_select := 0;
X    MOVE_HORIZONTAL(-CURRENT_OFFSET);
X    MOVE_HORIZONTAL(start_column);
X    SET(saved_mode, CURRENT_BUFFER)
XENDPROCEDURE
X`012
XPROCEDURE eve_rectangular_insert_here
X!+
X!   This procedure pastes the rectangular region in the paste buffer
X!   using the current position in the current buffer as the upper left corne
Vr.
X!-
X    LOCAL
X`009save_position,
X`009start_column,
X`009paste_line,
X`009save_buffer,
X`009save_mode;
X
X    save_buffer := CURRENT_BUFFER;
X    save_position := MARK(NONE);
X    start_column := edd_current_column;
X    if eve$rectangular_mode = "INSERT" then
X      save_mode := eveplus_set_mode(insert);
X    else
X      save_mode := eveplus_set_mode(OVERSTRIKE);
X    endif;
X    POSITION(BEGINNING_OF(paste_buffer));
X    IF MARK(NONE) = END_OF(paste_buffer)
X    THEN
X`009MESSAGE("Paste buffer is empty");
X`009RETURN
X    ENDIF;
X
X    !+
X    !   Loop through lines in the paste buffer, putting them at the
X    !   appropriate offset in the current buffer.
X    !-
X    LOOP
X`009EXITIF MARK(NONE) = END_OF(paste_buffer);
X
X`009!+
X`009!   Get the current line of the paste buffer.
X`009!-
X`009paste_line := CURRENT_LINE;
X`009MOVE_VERTICAL(1);
X
X`009!+
X`009!   Convert tabs to blanks on the line in the current buffer.
X`009!-
X`009POSITION(save_buffer);
X`009edd_replace_tabs_with_blanks_and_pad(start_column+1);
X
X`009!+
X`009!   Position at the correct offset and overwrite the text there.
X`009!-
X`009MOVE_HORIZONTAL(start_column);
X`009COPY_TEXT(paste_line);
X`009MOVE_VERTICAL(1);
X`009POSITION(paste_buffer)
X    ENDLOOP;
X
X    !+
X    !   Position to start of pasted text and restore old mode setting.
X    !-
X    POSITION(save_position);
X    MOVE_HORIZONTAL(-CURRENT_OFFSET);
X    MOVE_HORIZONTAL(start_column);
X    SET(save_mode, CURRENT_BUFFER);
XENDPROCEDURE
X`012
XPROCEDURE EVE_RECTANGULAR_SELECT
X    if eveplus_v_begin_select = 0
X    then
X`009eveplus_pad_blank;
X`009eveplus_v_begin_select := mark(REVERSE);
X`009message("Selection started.  Press Remove when finished.");
X    else
X`009eveplus_v_begin_select := 0;
X`009message("Selection cancelled");
X    endif;
Xendprocedure`009! eve_rectangular_select
X`012
XPROCEDURE EVEPLUS_PAD_BLANK
X
X!+
X! This procedure drops a space at the current position if the current
X! character is null so that any mark will be for an existing character.
X! In EDD, we really want a mark in a particular screen column.  In TPU,
X! an EOL mark would move if the line were extended.  Also in EDD, we
X! want to highlight the select point so we need a character there.
X! The cursor is returned to its original position after the space is
X! copied to the current position in the current buffer.
X!-
X    IF MARK(NONE) = END_OF(CURRENT_BUFFER)
X    THEN
X`009copy_text(" ");
X`009move_horizontal(-1)
X    ELSE
X`009if current_character = ""
X`009then
X`009    copy_text(" ");
X`009    move_horizontal(-1);
X`009endif
X    ENDIF
Xendprocedure`009! eveplus_pad_blank
X`012
XPROCEDURE EVEPLUS_SET_MODE(new_mode)
X
X!+
X! This procedure returns the current mode for the current buffer
X! and sets it to the value in NEW_MODE.
X!-
X
X    eveplus_set_mode := get_info(current_buffer,"MODE");
X    set(new_mode, current_buffer);
Xendprocedure`009! eveplus_set_mode
X`012
XPROCEDURE EVEPLUS_BLANK_CHARS(eveplus_v_blank_count)
X
X!+
X! This procedure returns a string of eveplus_v_blank_count blank chars.
X!-
X  local
X    eveplus_v_blank_chars,
X    eveplus_v_oldlen,
X    eveplus_v_blanks_so_far;`009! Length of blank char string so far
X
X    IF eveplus_v_blank_count = 0
X    THEN
X`009RETURN ""
X    ENDIF;
X
X    eveplus_v_blank_chars := " ";
X    eveplus_v_blanks_so_far := 1;
X    loop
X`009exitif eveplus_v_blanks_so_far >= eveplus_v_blank_count;
X`009eveplus_v_oldlen := LENGTH(eveplus_v_blank_chars);
X`009eveplus_v_blank_chars := eveplus_v_blank_chars + eveplus_v_blank_chars;
X`009eveplus_v_blanks_so_far := eveplus_v_blanks_so_far + eveplus_v_oldlen;
X    endloop;
X
X    IF eveplus_v_blanks_so_far > eveplus_v_blank_count
X    THEN
X`009eveplus_v_blank_chars :=
X`009    SUBSTR(eveplus_v_blank_chars,1,eveplus_v_blank_count)
X    ENDIF;
X    RETURN eveplus_v_blank_chars
Xendprocedure`009! eveplus_blank_chars
X`012
XPROCEDURE EVEPLUS_ADVANCE_HORIZONTAL(eveplus_v_columns,eveplus_v_blank_chars
V)
X
X!+
X! This procedure advances current_offset to be eveplus_v_columns from
X! current_offset.  eveplus_v_blanks_chars must be
X! a string of blank chars of at least length eveplus_v_columns.
X!-
X  local
X    eveplus_v_save_offset,`009`009! current_offset on entry to this procedur
Ve
X    eveplus_v_eol_columns;`009`009! Number of columns to `091EOL`093
X
X    eveplus_v_save_offset := current_offset;
X    if eveplus_v_columns <= 0
X    then
X`009move_horizontal(eveplus_v_columns);
X    else
X`009!+
X`009! Find out how far to `091EOL`093.
X`009!-
X`009eveplus_v_eol_columns := length(current_line)-current_offset;
X`009if eveplus_v_eol_columns >= eveplus_v_columns
X`009then
X`009    move_horizontal(eveplus_v_columns);
X`009else
X`009    move_horizontal(eveplus_v_eol_columns);
X`009    copy_text(substr(eveplus_v_blank_chars,1,
X`009`009`009     eveplus_v_columns-eveplus_v_save_offset));
X`009endif;
X    endif;
Xendprocedure`009! eveplus_advance_horizontal
X
XPROCEDURE tpu$define_keys_edd
XDEFINE_KEY("EVE_RECTANGULAR_SELECT", F17, "EDD SELECT");
XDEFINE_KEY("EVE_RECTANGULAR_REMOVE", F18, "EDD CUT");
XDEFINE_KEY("EVE_RECTANGULAR_INSERT_HERE", F19, "EDD PASTE");
XDEFINE_KEY("EVE_DRAW_BOX", F20, "EDD DRAW BOX")
XENDPROCEDURE
X
XPROCEDURE tpu$init_proc_edd
Xeveplus_v_begin_select := 0
XENDPROCEDURE
$ CALL UNPACK NEWRECT.TPU;5 1880374810
$ v=f$verify(v)
$ EXIT

