[comp.windows.x] xterm cut and paste

rws@EXPO.LCS.MIT.EDU (Bob Scheifler) (07/22/90)

The following is an xterm enhancement we received at one point.
This code has been integrated into our sources, but it is quite
possible bugs were fixed in the process.  Our xterm sources are
sufficiently changed that I am not interested in trying to mmake
up an official patch.  But you are welcome to the following,
without express or implied warranty. :-)


From: Mark Moraes <moraes@csri.toronto.edu>
Subject: cut and paste fix for xterm

The following fix makes xterm not insert newlines into selections if
the the lines ended because of wrapping, rather than because of an
explicit CarriageReturn. So cutting a line that wrapped around will
produce one line in the cut buffer, not two. This makes it much more
pleasant to cut and paste between xterm and editors. This fix works
with programs that write straight to the screen (eg.cat, sed, echo
etc), and "/usr/ucb/more" and emacs. It does NOT work with less, becase
less second guesses the terminal and sticks carriage returns into the
text. Sigh. It does not work with vi, for the same reason. It doesn't
work with Jove because Jove does not wrap lines, but instead truncates
them. (will be fixed in the X version of Jove)

*** /tmp/,RCSt1a23391	Tue Jan 16 23:52:44 1990
--- button.c	Tue Jan 16 23:45:33 1990
***************
*** 979,984 ****
--- 979,985 ----
  {
  	register TScreen *screen = &term->screen;
  	register int i, j = 0;
+ 	int eol;
  	char *line, *lp;
  	static _OwnSelection();
  
***************
*** 1013,1028 ****
  
  	line[j] = '\0';		/* make sure it is null terminated */
  	lp = line;		/* lp points to where to save the text */
! 	if ( row == crow ) lp = SaveText(screen, row, ccol, col, lp);
  	else {
! 		lp = SaveText(screen, crow, ccol, screen->max_col, lp);
! 		*lp ++ = '\n';	/* put in newline at end of line */
  		for(i = crow +1; i < row; i++) {
! 			lp = SaveText(screen, i, 0, screen->max_col, lp);
! 			*lp ++ = '\n';
  			}
  		if (col >= 0)
! 			lp = SaveText(screen, row, 0, col, lp);
  	}
  	*lp = '\0';		/* make sure we have end marked */
  	
--- 1014,1031 ----
  
  	line[j] = '\0';		/* make sure it is null terminated */
  	lp = line;		/* lp points to where to save the text */
! 	if ( row == crow ) lp = SaveText(screen, row, ccol, col, lp, &eol);
  	else {
! 		lp = SaveText(screen, crow, ccol, screen->max_col, lp, &eol);
! 		if (eol)
! 			*lp ++ = '\n';	/* put in newline at end of line */
  		for(i = crow +1; i < row; i++) {
! 			lp = SaveText(screen, i, 0, screen->max_col, lp, &eol);
! 			if (eol)
! 				*lp ++ = '\n';
  			}
  		if (col >= 0)
! 			lp = SaveText(screen, row, 0, col, lp, &eol);
  	}
  	*lp = '\0';		/* make sure we have end marked */
  	
***************
*** 1255,1272 ****
  }
  
  /* copies text into line, preallocated */
! char *SaveText(screen, row, scol, ecol, lp)
  int row;
  int scol, ecol;
  TScreen *screen;
  register char *lp;		/* pointer to where to put the text */
  {
  	register int i = 0;
  	register Char *ch = screen->buf[2 * (row + screen->topline)];
  	register int c;
  
  	if ((i = Length(screen, row, scol, ecol)) == 0) return(lp);
  	ecol = scol + i;
  	for (i = scol; i < ecol; i++) {
  		if ((c = ch[i]) == 0)
  			c = ' ';
--- 1258,1291 ----
  }
  
  /* copies text into line, preallocated */
! char *SaveText(screen, row, scol, ecol, lp, eol)
  int row;
  int scol, ecol;
  TScreen *screen;
  register char *lp;		/* pointer to where to put the text */
+ int *eol;
  {
  	register int i = 0;
  	register Char *ch = screen->buf[2 * (row + screen->topline)];
+ 	register Char attr;
+ 	int oldecol = ecol;
  	register int c;
  
+ 	*eol = 1;
  	if ((i = Length(screen, row, scol, ecol)) == 0) return(lp);
  	ecol = scol + i;
+ 	*eol = (ecol < oldecol) ? 1 : 0;
+ 	if (*eol == 0) {
+ 		if(ScrnGetAttributes(screen, row, ecol - 1, &attr, 1) == 1) {
+ 			*eol = (attr & ENDLINE) ? 1 : 0;
+ 		} else {
+ 			/* If we can't get the attributes, assume ENDLINE */
+ 			/* CANTHAPPEN */
+ 			(void)fprintf(stderr, "%s: no attributes for %d, %d\n",
+ 				xterm_name, row, ecol - 1);
+ 			*eol = 1;
+ 		}
+ 	}
  	for (i = scol; i < ecol; i++) {
  		if ((c = ch[i]) == 0)
  			c = ' ';
No differences encountered
*** /tmp/,RCSt1a23391	Tue Jan 16 23:52:46 1990
--- cursor.c	Tue Jan 16 23:34:50 1990
***************
*** 219,224 ****
--- 219,228 ----
  CarriageReturn(screen)
  register TScreen *screen;
  {
+ 	extern void ScrnSetAttributes();
+ 	
+ 	ScrnSetAttributes(screen, screen->cur_row, screen->cur_col,
+ 			  ENDLINE, ENDLINE, 1);
  	screen->cur_col = 0;
  	screen->do_wrap = 0;
  	_CheckSelection(screen);
*** /tmp/,RCSt1a23391	Tue Jan 16 23:52:46 1990
--- ptyx.h	Tue Jan 16 23:34:49 1990
***************
*** 433,439 ****
  #define REVERSE_VIDEO	0x10	/* true if screen white on black */
  #define ORIGIN		0x20	/* true if in origin mode */
  #define INSERT		0x40	/* true if in insert mode */
! #define SMOOTHSCROLL	0x80	/* true if in smooth scroll mode */
  #define IN132COLUMNS	0x200	/* true if in 132 column mode */
  #define LINEFEED	0x400
  #define	REVERSEWRAP	0x800	/* true if reverse wraparound mode */
--- 433,447 ----
  #define REVERSE_VIDEO	0x10	/* true if screen white on black */
  #define ORIGIN		0x20	/* true if in origin mode */
  #define INSERT		0x40	/* true if in insert mode */
! #define ENDLINE		0x80	/*
! 				 * always false in term->flags, used to
! 				 * indicate the end of a line in the
! 				 * screen->buf attributes so we can tell the
! 				 * difference between lines that have wrapped
! 				 * around and lines that have ended naturally
! 				 * with a CR at column max_col.
! 				 */
! #define SMOOTHSCROLL	0x100	/* true if in smooth scroll mode */
  #define IN132COLUMNS	0x200	/* true if in 132 column mode */
  #define LINEFEED	0x400
  #define	REVERSEWRAP	0x800	/* true if reverse wraparound mode */
*** /tmp/,RCSt1a23391	Tue Jan 16 23:52:47 1990
--- screen.c	Tue Jan 16 23:34:48 1990
***************
*** 555,557 ****
--- 555,614 ----
  	return (0);
  }
  
+ /*
+  * Sets the attributes from the row, col, to row, col + length according to
+  * mask and value. The bits in the attribute byte specified by the mask are
+  * set to the corresponding bits in the value byte. If length would carry us
+  * over the end of the line, it stops at the end of the line.
+  */
+ void
+ ScrnSetAttributes(screen, row, col, mask, value, length)
+ TScreen *screen;
+ int row, col;
+ unsigned mask, value;
+ register int length;		/* length of string */
+ {
+ 	register Char *attrs;
+ 	register int avail  = screen->max_col - col + 1;
+ 
+ 	if (length > avail)
+ 	    length = avail;
+ 	if (length <= 0)
+ 		return;
+ 	attrs = screen->buf[2 * row + 1] + col;
+ 	value &= mask;	/* make sure we only change the bits allowed by mask*/
+ 	while(length-- > 0) {
+ 		*attrs &= mask;		/* clear the bits */
+ 		*attrs |= value;	/* copy in the new values */
+ 		attrs++;
+ 	}
+ }
+ 
+ /*
+  * Gets the attributes from the row, col, to row, col + length into the
+  * supplied array, which is assumed to be big enough.  If length would carry us
+  * over the end of the line, it stops at the end of the line. Returns
+  * the number of bytes of attributes (<= length)
+  */
+ int
+ ScrnGetAttributes(screen, row, col, str, length)
+ TScreen *screen;
+ int row, col;
+ Char *str;
+ register int length;		/* length of string */
+ {
+ 	register Char *attrs;
+ 	register int avail  = screen->max_col - col + 1;
+ 	int ret;
+ 
+ 	if (length > avail)
+ 	    length = avail;
+ 	if (length <= 0)
+ 		return 0;
+ 	ret = length;
+ 	attrs = screen->buf[2 * row + 1] + col;
+ 	while(length-- > 0) {
+ 		*str++ = *attrs++;
+ 	}
+ 	return ret;
+ }

moraes@cs.toronto.edu (Mark Moraes) (07/27/90)

In <9007221535.AA04491@expo.lcs.mit.edu>, rws@EXPO.LCS.MIT.EDU (Bob Scheifler)
writes:

>The following is an xterm enhancement we received at one point.
>This code has been integrated into our sources, but it is quite
>possible bugs were fixed in the process.

Jim Fulton fixed at least one bug in my fix -- enclosed.  Please apply
this as well as the one in the referenced article, otherwise there are
likely to be garbage characters, (usually NULs at the end of the cut
text)

	Mark.

*** /tmp/,RCSt1a25742	Fri Jul 27 02:39:32 1990
--- button.c	Fri Jul 27 02:34:40 1990
***************
*** 1047,1051 ****
  	*lp = '\0';		/* make sure we have end marked */
  	
! 	screen->selection_length = j;
  	_OwnSelection(term, params, num_params);
  }
--- 1047,1051 ----
  	*lp = '\0';		/* make sure we have end marked */
  	
! 	screen->selection_length = lp - line;
  	_OwnSelection(term, params, num_params);
  }

chris@sage0.gsfc.nasa.gov (Chris P. Ross) (07/27/90)

In <90Jul27.024537edt.446@smoke.cs.toronto.edu> moraes@cs.toronto.edu (Mark Moraes) writes:

>In <9007221535.AA04491@expo.lcs.mit.edu>, rws@EXPO.LCS.MIT.EDU (Bob Scheifler)
>writes:

>>The following is an xterm enhancement we received at one point.
>>This code has been integrated into our sources, but it is quite
>>possible bugs were fixed in the process.

>Jim Fulton fixed at least one bug in my fix -- enclosed.  Please apply
>this as well as the one in the referenced article, otherwise there are
>likely to be garbage characters, (usually NULs at the end of the cut
>text)

  I have been greatly annoyed by these problems with not being able to cut
and paste in xterms, and now I have a way to fix it.  The problem is, we
got out X11R4 in binary form.  It had been compiled on another machine, and
they just tar'd and compress'd it and sent iot to us.  We extracted it into
the correct directories, and it works.  But, therefore, I don't have a source
to xterm.  If anyone couldpack up only what is neccessary for me to compile
xterm, and mail it to me, I'd be much appriciative.  I don't know where in 
the MIT tapes that it is, and don't want to have to search for it.  Thanks.
Request:  Could you please send a notification before sending the file?
I will then ask ONE person to send it to me.  This way I won't get 30
million copies.  Thanks.

                                       - Chris

--
-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-
  Chris P. Ross    (301)/286-7242   | InterNet: chris@sage0.gsfc.nasa.gov
  EGRET Programmer, NASA / GSFC     |           chris@olgao.umd.edu
-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-=*=-

jnford@jay.weeg.uiowa.edu (Jay Ford) (07/31/90)

In article <90Jul27.024537edt.446@smoke.cs.toronto.edu>,
moraes@cs.toronto.edu (Mark Moraes) writes:
|> 
|> Jim Fulton fixed at least one bug in my fix -- enclosed.  Please apply
|> this as well as the one in the referenced article, otherwise there are
|> likely to be garbage characters, (usually NULs at the end of the cut
|> text)
|> 
	[patch deleted]

That patch did get rid of the NULs, but there is another problem.

Blanks at the end of a line get incorrectly truncated when the line is not the
last one in the cut region.  That is, the line with the trailing blanks is
followed by other lines, and all the lines are to be cut as one wrapped line.

Here is the behavior I see, where the line in question is not the last line.

condition				result
---------				------
1. no blanks at end of line		lines are cut correctly, as one line

2. one blank at end of line		the lines are cut as one line, but the
					single trailing blank is removed

3. multiple blanks at end of line	the blanks are truncated, and the cut
					contains a NL at the end of this line

Perhaps some examples would help.  Assume a window width of 20 columns.

Condition 1:
	         1         2
	12345678901234567890
	% echo abcdefghijklm
	nop

	resulting cut region is:
		echo abcdefghijklmnop

Condition 2:
	         1         2
	12345678901234567890
	% echo abcdefghijkl
	nop

	resulting cut region is:
		echo abcdefghijklnop
	(blank is missing after l)

Condition 3:
	         1         2
	12345678901234567890
	% echo abcdefghijk
	nop

	resulting cut region is:
		echo abcdefghijk
		nop
	(newline after k)


From glancing at the xterm code (button.c) it seems that the blank truncation
might be hard to work around.  The LastTextCol and Length functions ignore
trailing blanks, so anything which uses those functions will not get the blanks
counted in the line length.


Jay Ford,  Weeg Computing Center,  University of Iowa,  Iowa City,  IA  52242
jnford@jay.weeg.uiowa.edu  or  jnfordpb@uiamvs.bitnet,  319-335-5555

egreshko@fuji.jpntok.cdc.COM (Ed Greshko) (01/29/91)

	I've a Sun 3/160 running SunOS 3.5.

	When using cut and paste in an xterm window running vi the
tabs in the pasted text are not preserved.  Is this considered
normal behavior?

-- 
Ed Greshko  			     email : egreshko@jpntok.cdc.com
CDCMAIL : Edward M. Greshko, ARH257  Home  :   011-81-(3)3704-6158
T.I.T.  : 011-81-(3)3726-0527        FAX   :   011-81-(3)3726-5799

melby@daffy.yk.Fujitsu.CO.JP (John B. Melby) (01/30/91)

>When using cut and paste in an xterm window running vi the
>tabs in the pasted text are not preserved.  Is this considered
>normal behavior?

Unfortunately, yes.  Both the STRING and COMPOUND_TEXT targets allow for
the presence of tab characters, but nobody seems to have gotten around to
patching xterm/kterm up to transfer tabs intact....

-----
John B. Melby
Fujitsu Limited, Machida, Japan
melby%yk.fujitsu.co.jp@uunet