Path: utzoo!utgpu!news-server.csri.toronto.edu!mailrus!uwm.edu!cs.utexas.edu!uunet!snorkelwacker!bloom-beacon!EXPO.LCS.MIT.EDU!rws From: rws@EXPO.LCS.MIT.EDU (Bob Scheifler) Newsgroups: comp.windows.x Subject: xterm cut and paste Message-ID: <9007221535.AA04491@expo.lcs.mit.edu> Date: 22 Jul 90 15:35:05 GMT Sender: daemon@athena.mit.edu (Mr Background) Organization: The Internet Lines: 235 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 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; + }