[comp.windows.x] Cut_Buffer_Fixes

prb@UMN-REI-UC.ARPA.UUCP (04/11/87)

Since I have gotten several requests for my xterm hacks (and that is what
they are) to fix the cut buffers I will just post the changes for all to
enjoy and mock.

To fix the Cut Buffer problem in Xterm 6.6A2 I have added Code Fragment #1
(see below) in charproc.c just before the definition of in_put() (around line
750 or so).  Just before in_put() there is also a definition:

	static int select_maskl;
Add
	static int write_mask;

Change the tail end of in_put() to Code Fragment #2.
Add Code Fragment #3 to the end of charproc.c.  

In input.c change the beginning of the code for the Input() function to
look like Code Fragment #4.

In button.c change the 4 calls to write() to be calls to v_write().  (Each
of these writes should be writing to file descriptor `pty').

That's it.

What this gets you:

	a) When you paste a cut buffer the whole buffer should be pasted
	   and not the first `some number less that you wanted' bytes.

	b) If a key is mapped to an ascii string that starts with a '\377'
	   then the rest of the characters in that string will be read as
	   if they were output instead of input (mapo feature of SUN's
	   suntools).

Have fun.

				-Paul R Borman
				 Cray Research, Inc.
				 prb@umn-rei-uc.arpa

------- Code Fragment # 1 ------
static char v_buffer[4096];
static char *v_bufstr;
static char *v_bufptr;
static char *v_bufend;
#define	ptymask()	(v_bufptr > v_bufstr ? pty_mask : 0)

v_write(f, d, l)
int f;
char *d;
int l;
{
	int r;
	int c = l;

	if (!v_bufstr) {
		v_bufstr = v_buffer;
		v_bufptr = v_buffer;
		v_bufend = &v_buffer[4096];
	}

	if ((1 << f) != pty_mask)
		return(write(f, d, l));

	if (v_bufptr > v_bufstr) {
		if (l) {
			if (v_bufend > v_bufptr + l) {
				bcopy(d, v_bufptr, l);
				v_bufptr += l;
			} else {
				if (v_bufstr != v_buffer) {
					bcopy(v_bufstr, v_buffer,
					      v_bufptr - v_bufstr);
					v_bufptr -= v_bufstr - v_buffer;
					v_bufstr = v_buffer;
				}
				if (v_bufend > v_bufptr + l) {
					bcopy(d, v_bufptr, l);
					v_bufptr += l;
				} else if (v_bufptr < v_bufend) {
					fprintf(stderr, "Out of buffer space\n");
					c = v_bufend - v_bufptr;
					bcopy(d, v_bufptr, c);
					v_bufptr = v_bufend;
				} else {
					fprintf(stderr, "Out of buffer space\n");
					c = 0;
				}
			}
		}
		if (v_bufptr > v_bufstr) {
			if ((r = write(f, v_bufstr, v_bufptr - v_bufstr)) <= 0)
				return(r);
			if ((v_bufstr += r) >= v_bufptr)
				v_bufstr = v_bufptr = v_buffer;
		}
	} else if (l) {
		if ((r = write(f, d, l)) < 0) {
			if (errno == EWOULDBLOCK)
				r = 0;
			else if (errno == EINTR)
				r = 0;
			else
				return(r);
		}
		if (l - r) {
			if (l - r > v_bufend - v_buffer) {
				fprintf(stderr, "Truncating to %d\n",
						v_bufend - v_buffer);
				l = (v_bufend - v_buffer) + r;
			}
			bcopy(d + r, v_buffer, l - r);
			v_bufstr = v_buffer;
			v_bufptr = v_buffer + (l - r);
		}
	}
	return(c);
}

----- Code Fragment #2 -------
		if(QLength())
			select_mask = X_mask;
		else {
			write_mask = ptymask();
			XFlush();
			select_mask = Select_mask;
			if((i = select(max_plus1, &select_mask, &write_mask,
				       NULL, screen->timeout)) < 0) {
				if (errno != EINTR)
					SysError(ERROR_SELECT);
				continue;
			} else if(i == 0) {
				if(GetButtonState(screen->sb) & HILITED)
					WindowScroll(screen,
					 ButtonRegion(screen->sb));
				screen->timeout->tv_usec = STEPTIME;
				continue;
			}
		}
		if (write_mask & ptymask())
			v_write(screen->respond, 0, 0);	/* flush buffer */
		if (select_mask & X_mask) {
			if (bcnt <= 0) {
				bcnt = 0;
				bptr = buffer;
			}
			xevents();
			if (bcnt > 0)
				break;
		}
	}
	bcnt--;
	return(*bptr++);
}

----- Code Fragment # 3 -----

fakinput(string, nbytes)
char *string;
int nbytes;
{
	if (bptr + bcnt + nbytes < &buffer[BUF_SIZE]) {
		strncpy(bptr+bcnt, string, nbytes);
		bcnt += nbytes;
	}
}
----- Code Fragment # 4 -----

	string = XLookupMapping (event, &nbytes);

	if (nbytes > 0) {
		if (*string == 0377) {
			fakinput(string+1, nbytes-1);
			return;
		}
		if(screen->TekGIN) {
			TekEnqMouse(*string++);
			TekGINoff();
			nbytes--;
		}
----- End of Code Fragments -----