/*--------------------------------*-C-*---------------------------------*
* File: command.c
*----------------------------------------------------------------------*
- * $Id: command.C,v 1.9 2003-11-27 10:12:10 pcg Exp $
+ * $Id: command.C,v 1.10 2003-11-27 16:49:45 pcg Exp $
*
* All portions of code are copyright by their respective author/s.
* Copyright (c) 1992 John Bovey, University of Kent at Canterbury <jdb@ukc.ac.uk>
# ifdef META8_OPTION
if (R->meta_char == C0_ESC)
# endif
- rxvt_tt_write(aR_ &ch, 1);
- rxvt_tt_write(aR_ kbuf0, l);
+ R->tt_write(&ch, 1);
+ R->tt_write(kbuf0, l);
return;
} else
#endif
) {
const unsigned char ch = C0_ESC;
- rxvt_tt_write(aR_ &ch, 1);
+ R->tt_write(&ch, 1);
}
#ifdef DEBUG_CMD
if (debug_key) { /* Display keyboard buffer contents */
fprintf(stderr, "'\n");
}
#endif /* DEBUG_CMD */
- rxvt_tt_write(aR_ kbuf, (unsigned int)len);
+ R->tt_write(kbuf, (unsigned int)len);
}
/*}}} */
{
SET_R (this);
- // loop, but don't allow a single term to monopolize us
- // the number of loops is fully arbitrary, and thus wrong
- for (int i = 7; i-- && pty_fill (); )
- {
- //TODO:
- /* once we know the shell is running, send the screen size. Again! */
- //ch = rxvt_cmd_getc(aR); /* wait for something */
- //rxvt_tt_winsize(cmd_fd, TermWin.ncol, TermWin.nrow, cmd_pid);
+ if (revents & EVENT_WRITE)
+ tt_write (0, 0);
+ else if (revents & EVENT_READ)
+ // loop, but don't allow a single term to monopolize us
+ // the number of loops is fully arbitrary, and thus wrong
+ for (int i = 7; i-- && pty_fill (); )
+ {
+ //TODO:
+ /* once we know the shell is running, send the screen size. Again! */
+ //ch = rxvt_cmd_getc(aR); /* wait for something */
+ //rxvt_tt_winsize(cmd_fd, TermWin.ncol, TermWin.nrow, cmd_pid);
- uint32_t ch = NOCHAR;
+ uint32_t ch = NOCHAR;
- for (;;)
- {
- if (ch == NOCHAR)
- ch = next_char ();
+ for (;;)
+ {
+ if (ch == NOCHAR)
+ ch = next_char ();
- if (ch == NOCHAR) // TODO: improve
- break;
+ if (ch == NOCHAR) // TODO: improve
+ break;
- if (ch >= ' ' || ch == '\t' || ch == '\n' || ch == '\r')
- {
- /* Read a text string from the input buffer */
- uint32_t buf[BUFSIZ];
- bool refreshnow = false;
- int nlines = 0;
- uint32_t *str = buf;
-
- *str++ = ch;
-
- for (;;)
- {
- ch = next_char ();
-
- if (ch == NOCHAR || (ch < ' ' && ch != '\t' && ch != '\n' && ch != '\r'))
- break;
- else
- {
- *str++ = ch;
-
- if (ch == '\n')
- {
- nlines++;
- refresh_count++;
-
- if (!(Options & Opt_jumpScroll)
- || (refresh_count >= (refresh_limit * (TermWin.nrow - 1))))
- {
- refreshnow = true;
- ch = NOCHAR;
- break;
- }
- }
-
- if (str >= buf + BUFSIZ)
- {
- ch = NOCHAR;
- break;
- }
- }
- }
-
- rxvt_scr_add_lines (this, buf, nlines, str - buf);
-
- /*
- * If there have been a lot of new lines, then update the screen
- * What the heck I'll cheat and only refresh less than every page-full.
- * the number of pages between refreshes is refresh_limit, which
- * is incremented here because we must be doing flat-out scrolling.
- *
- * refreshing should be correct for small scrolls, because of the
- * time-out
- */
- if (refreshnow)
- {
- if ((Options & Opt_jumpScroll) && refresh_limit < REFRESH_PERIOD)
- refresh_limit++;
-
- rxvt_scr_refresh (this, refresh_type);
- }
+ if (ch >= ' ' || ch == '\t' || ch == '\n' || ch == '\r')
+ {
+ /* Read a text string from the input buffer */
+ uint32_t buf[BUFSIZ];
+ bool refreshnow = false;
+ int nlines = 0;
+ uint32_t *str = buf;
- }
- else
- {
- switch (ch)
- {
- default:
- rxvt_process_nonprinting (this, ch);
- break;
- case C0_ESC: /* escape char */
- rxvt_process_escape_seq (this);
- break;
- /*case 0x9b: */ /* CSI */
- /* rxvt_process_csi_seq (this); */
- }
-
- ch = NOCHAR;
- }
- }
- }
+ *str++ = ch;
+
+ for (;;)
+ {
+ ch = next_char ();
+
+ if (ch == NOCHAR || (ch < ' ' && ch != '\t' && ch != '\n' && ch != '\r'))
+ break;
+ else
+ {
+ *str++ = ch;
+
+ if (ch == '\n')
+ {
+ nlines++;
+ refresh_count++;
+
+ if (!(Options & Opt_jumpScroll)
+ || (refresh_count >= (refresh_limit * (TermWin.nrow - 1))))
+ {
+ refreshnow = true;
+ ch = NOCHAR;
+ break;
+ }
+ }
+
+ if (str >= buf + BUFSIZ)
+ {
+ ch = NOCHAR;
+ break;
+ }
+ }
+ }
+
+ rxvt_scr_add_lines (this, buf, nlines, str - buf);
+
+ /*
+ * If there have been a lot of new lines, then update the screen
+ * What the heck I'll cheat and only refresh less than every page-full.
+ * the number of pages between refreshes is refresh_limit, which
+ * is incremented here because we must be doing flat-out scrolling.
+ *
+ * refreshing should be correct for small scrolls, because of the
+ * time-out
+ */
+ if (refreshnow)
+ {
+ if ((Options & Opt_jumpScroll) && refresh_limit < REFRESH_PERIOD)
+ refresh_limit++;
+
+ rxvt_scr_refresh (this, refresh_type);
+ }
+
+ }
+ else
+ {
+ switch (ch)
+ {
+ default:
+ rxvt_process_nonprinting (this, ch);
+ break;
+ case C0_ESC: /* escape char */
+ rxvt_process_escape_seq (this);
+ break;
+ /*case 0x9b: */ /* CSI */
+ /* rxvt_process_csi_seq (this); */
+ }
+
+ ch = NOCHAR;
+ }
+ }
+ }
flush ();
}
/* loop until we can return something */
if (R->v_bufstr < R->v_bufptr) /* output any pending chars */
- rxvt_tt_write(aR_ NULL, 0);
+ R->tt_write(NULL, 0);
#if defined(MOUSE_WHEEL) && defined(MOUSE_SLIP_WHEELING)
if (R->mouse_slip_wheel_speed) {
x + 1,
y + 1);
#else
- rxvt_tt_printf(aR_ "\033[M%c%c%c",
+ R->tt_printf("\033[M%c%c%c",
(32 + button_number + key_state),
(32 + x + 1),
(32 + y + 1));
&& scrollbarnext_upButton(ev->y))
|| (R->scrollBar.style == R_SB_RXVT
&& scrollbarrxvt_upButton(ev->y)))
- rxvt_tt_printf(aR_ "\033[A");
+ R->tt_printf("\033[A");
else if ((R->scrollBar.style == R_SB_NEXT
&& scrollbarnext_dnButton(ev->y))
|| (R->scrollBar.style == R_SB_RXVT
&& scrollbarrxvt_dnButton(ev->y)))
- rxvt_tt_printf(aR_ "\033[B");
+ R->tt_printf("\033[B");
else
switch (ev->button) {
case Button2:
- rxvt_tt_printf(aR_ "\014");
+ R->tt_printf("\014");
break;
case Button1:
- rxvt_tt_printf(aR_ "\033[6~");
+ R->tt_printf("\033[6~");
break;
case Button3:
- rxvt_tt_printf(aR_ "\033[5~");
+ R->tt_printf("\033[5~");
break;
}
}
switch (ch) {
case C0_ENQ: /* terminal Status */
if (R->rs[Rs_answerbackstring])
- rxvt_tt_write(aR_
+ R->tt_write(
(const unsigned char *)R->rs[Rs_answerbackstring],
(unsigned int)STRLEN(R->rs[Rs_answerbackstring]));
else
- rxvt_tt_write(aR_ (unsigned char *)VT100_ANS,
+ R->tt_write((unsigned char *)VT100_ANS,
(unsigned int)STRLEN(VT100_ANS));
break;
case C0_BEL: /* bell */
rxvt_scr_gotorc(aR_ row, col, 0);
break;
case 'Z': /* identify the terminal type */
- rxvt_tt_printf(aR_ "\033/Z"); /* I am a VT100 emulating a VT52 */
+ R->tt_printf("\033/Z"); /* I am a VT100 emulating a VT52 */
break;
case '<': /* turn off VT52 mode */
PrivMode(0, PrivMode_vt52);
/* 8.3.110: SINGLE CHARACTER INTRODUCER */
case C1_SCI: /* ESC Z */
- rxvt_tt_write(aR_ (const unsigned char *)ESCZ_ANSWER,
+ R->tt_write((const unsigned char *)ESCZ_ANSWER,
(unsigned int)(sizeof(ESCZ_ANSWER) - 1));
break; /* steal obsolete ESC [ c */
switch (priv) {
case '>':
if (ch == CSI_DA) /* secondary device attributes */
- rxvt_tt_printf(aR_ "\033[>%d;%-.8s;0c", 'R', VSTRING);
+ R->tt_printf("\033[>%d;%-.8s;0c", 'R', VSTRING);
break;
case '?':
if (ch == 'h' || ch == 'l' || ch == 'r' || ch == 's' || ch == 't')
break;
case CSI_DA: /* 8.3.24: (0) DEVICE ATTRIBUTES */
- rxvt_tt_write(aR_ (const unsigned char *)VT100_ANS,
+ R->tt_write((const unsigned char *)VT100_ANS,
(unsigned int)(sizeof(VT100_ANS) - 1));
break;
case CSI_DSR: /* 8.3.36: (0) DEVICE STATUS REPORT */
switch (arg[0]) {
case 5: /* DSR requested */
- rxvt_tt_printf(aR_ "\033[0n");
+ R->tt_printf("\033[0n");
break;
case 6: /* CPR requested */
rxvt_scr_report_position(aR);
break;
#if defined (ENABLE_DISPLAY_ANSWER)
case 7: /* unofficial extension */
- rxvt_tt_printf(aR_ "%-.250s\n", R->rs[Rs_display_name]);
+ R->tt_printf("%-.250s\n", R->rs[Rs_display_name]);
break;
#endif
case 8: /* unofficial extension */
case CSI_78: /* DECREQTPARM */
if (arg[0] == 0 || arg[0] == 1)
- rxvt_tt_printf(aR_ "\033[%d;1;1;112;112;1;0x", arg[0] + 2);
+ R->tt_printf("\033[%d;1;1;112;112;1;0x", arg[0] + 2);
/* FALLTHROUGH */
default:
*/
case 11: /* report window state */
XGetWindowAttributes(R->Xdisplay, R->TermWin.parent[0], &wattr);
- rxvt_tt_printf(aR_ "\033[%dt", wattr.map_state == IsViewable ? 1 : 2);
+ R->tt_printf("\033[%dt", wattr.map_state == IsViewable ? 1 : 2);
break;
case 13: /* report window position */
XGetWindowAttributes(R->Xdisplay, R->TermWin.parent[0], &wattr);
XTranslateCoordinates(R->Xdisplay, R->TermWin.parent[0], wattr.root,
-wattr.border_width, -wattr.border_width,
&x, &y, &wdummy);
- rxvt_tt_printf(aR_ "\033[3;%d;%dt", x, y);
+ R->tt_printf("\033[3;%d;%dt", x, y);
break;
case 14: /* report window size (pixels) */
XGetWindowAttributes(R->Xdisplay, R->TermWin.parent[0], &wattr);
- rxvt_tt_printf(aR_ "\033[4;%d;%dt", wattr.height, wattr.width);
+ R->tt_printf("\033[4;%d;%dt", wattr.height, wattr.width);
break;
case 18: /* report window size (chars) */
- rxvt_tt_printf(aR_ "\033[8;%d;%dt", R->TermWin.nrow, R->TermWin.ncol);
+ R->tt_printf("\033[8;%d;%dt", R->TermWin.nrow, R->TermWin.ncol);
break;
#if 0 /* XXX: currently disabled due to security concerns */
case 20: /* report icon label */
XGetIconName(R->Xdisplay, R->TermWin.parent[0], &s);
- rxvt_tt_printf(aR_ "\033]L%-.200s\234", s ? s : ""); /* 8bit ST */
+ R->tt_printf("\033]L%-.200s\234", s ? s : ""); /* 8bit ST */
break;
case 21: /* report window title */
XFetchName(R->Xdisplay, R->TermWin.parent[0], &s);
- rxvt_tt_printf(aR_ "\033]l%-.200s\234", s ? s : ""); /* 8bit ST */
+ R->tt_printf("\033]l%-.200s\234", s ? s : ""); /* 8bit ST */
break;
#endif
}
#ifndef RXVT_GRAPHICS
if (cmd == 'Q') { /* query graphics */
- rxvt_tt_printf(aR_ "\033G0\n"); /* no graphics */
+ R->tt_printf("\033G0\n"); /* no graphics */
return;
}
/* swallow other graphics sequences until terminating ':' */
unsigned char *text = NULL;
if (cmd == 'Q') { /* query graphics */
- rxvt_tt_printf(aR_ "\033G1\n"); /* yes, graphics (color) */
+ R->tt_printf("\033G1\n"); /* yes, graphics (color) */
return;
}
for (nargs = 0; nargs < (sizeof(args) / sizeof(args[0])) - 1;) {
* Send printf() formatted output to the command.
* Only use for small amounts of data.
*/
-/* EXTPROTO */
void
-rxvt_tt_printf(pR_ const char *fmt,...)
+rxvt_term::tt_printf (const char *fmt,...)
{
- va_list arg_ptr;
- unsigned char buf[256];
+ va_list arg_ptr;
+ unsigned char buf[256];
- va_start(arg_ptr, fmt);
- vsprintf((char *)buf, fmt, arg_ptr);
- va_end(arg_ptr);
- rxvt_tt_write(aR_ buf, (unsigned int)STRLEN(buf));
+ va_start (arg_ptr, fmt);
+ vsnprintf ((char *)buf, 256, fmt, arg_ptr);
+ va_end (arg_ptr);
+ tt_write (buf, STRLEN (buf));
}
/* ---------------------------------------------------------------------- */
-/* Addresses pasting large amounts of data and rxvt hang
- * code pinched from xterm (v_write()) and applied originally to
- * rxvt-2.18 - Hops
- * Write data to the pty as typed by the user, pasted with the mouse,
+/* Write data to the pty as typed by the user, pasted with the mouse,
* or generated by us in response to a query ESC sequence.
*/
-/* EXTPROTO */
void
-rxvt_tt_write(pR_ const unsigned char *d, unsigned int len)
+rxvt_term::tt_write (const unsigned char *data, unsigned int len)
{
-#define MAX_PTY_WRITE 256 /* POSIX minimum MAX_INPUT */
- int riten;
- unsigned int p;
- unsigned char *v_buffer, /* start of physical buffer */
- *v_bufstr, /* start of current buffer pending */
- *v_bufptr, /* end of current buffer pending */
- *v_bufend; /* end of physical buffer */
-
- if (R->v_bufstr == NULL && len > 0) {
- p = (len / MAX_PTY_WRITE + 1) * MAX_PTY_WRITE;
- v_buffer = v_bufstr = v_bufptr = (unsigned char *)rxvt_malloc(p);
- v_bufend = v_buffer + p;
- } else {
- v_buffer = R->v_buffer;
- v_bufstr = R->v_bufstr;
- v_bufptr = R->v_bufptr;
- v_bufend = R->v_bufend;
- }
+ enum { MAX_PTY_WRITE = 255 }; // minimum MAX_INPUT
- /*
- * Append to the block we already have. Always doing this simplifies the
- * code, and isn't too bad, either. If this is a short block, it isn't
- * too expensive, and if this is a long block, we won't be able to write
- * it all anyway.
- */
- if (len > 0) {
- if (v_bufend < v_bufptr + len) { /* run out of room */
- if (v_bufstr != v_buffer) {
- /* there is unused space, move everything down */
- MEMMOVE(v_buffer, v_bufstr,
- (unsigned int)(v_bufptr - v_bufstr));
- v_bufptr -= v_bufstr - v_buffer;
- v_bufstr = v_buffer;
- }
- if (v_bufend < v_bufptr + len) {
- /* still won't fit: get more space */
- /* use most basic realloc because an error is not fatal. */
- unsigned int size = v_bufptr - v_buffer;
- unsigned int reallocto;
-
- reallocto = ((size + len) / MAX_PTY_WRITE + 1) * MAX_PTY_WRITE;
- v_buffer = (unsigned char *)realloc(v_buffer, reallocto);
- /* save across realloc */
- if (v_buffer) {
- v_bufstr = v_buffer;
- v_bufptr = v_buffer + size;
- v_bufend = v_buffer + reallocto;
- } else { /* no memory: ignore entire write request */
- rxvt_print_error("data loss: cannot allocate buffer space");
- v_buffer = v_bufstr; /* restore clobbered pointer */
- }
- }
- }
- if (v_bufend >= v_bufptr + len) { /* new stuff will fit */
- MEMCPY(v_bufptr, d, len);
- v_bufptr += len;
- }
- }
+ if (len)
+ {
+ if (v_buflen == 0)
+ {
+ int written = write (cmd_fd, data, min (MAX_PTY_WRITE, len));
+ if (written == len)
+ return;
- /*
- * Write out as much of the buffer as we can.
- * Be careful not to overflow the pty's input silo.
- * We are conservative here and only write a small amount at a time.
- *
- * If we can't push all the data into the pty yet, we expect write
- * to return a non-negative number less than the length requested
- * (if some data written) or -1 and set errno to EAGAIN,
- * EWOULDBLOCK, or EINTR (if no data written).
- *
- * (Not all systems do this, sigh, so the code is actually
- * a little more forgiving.)
- */
- if ((p = v_bufptr - v_bufstr) > 0) {
- riten = write(R->cmd_fd, v_bufstr, min(p, MAX_PTY_WRITE));
- if (riten < 0)
- riten = 0;
- v_bufstr += riten;
- if (v_bufstr >= v_bufptr) /* we wrote it all */
- v_bufstr = v_bufptr = v_buffer;
+ data += written;
+ len -= written;
+ }
+
+
+ v_buffer = (unsigned char *)realloc (v_buffer, v_buflen + len);
+
+ memcpy (v_buffer + v_buflen, data, len);
+ v_buflen += len;
}
- /*
- * If we have lots of unused memory allocated, return it
- */
- if (v_bufend - v_bufptr > MAX_PTY_WRITE * 8) { /* arbitrary hysteresis */
- /* save pointers across realloc */
- unsigned int start = v_bufstr - v_buffer;
- unsigned int size = v_bufptr - v_buffer;
- unsigned int reallocto;
-
- reallocto = (size / MAX_PTY_WRITE + 1) * MAX_PTY_WRITE;
- v_buffer = (unsigned char *)realloc(v_buffer, reallocto);
- if (v_buffer) {
- v_bufstr = v_buffer + start;
- v_bufptr = v_buffer + size;
- v_bufend = v_buffer + reallocto;
- } else {
- /* should we print a warning if couldn't return memory? */
- v_buffer = v_bufstr - start; /* restore clobbered pointer */
- }
+
+ for (;;)
+ {
+ int written = write (cmd_fd, v_buffer, min (MAX_PTY_WRITE, v_buflen));
+
+ if (written > 0)
+ {
+ v_buflen -= written;
+
+ if (v_buflen == 0)
+ {
+ free (v_buffer);
+ v_buffer = 0;
+ v_buflen = 0;
+
+ pty_ev.set (EVENT_READ);
+ return;
+ }
+
+ memmove (v_buffer, v_buffer + written, v_buflen);
+ }
+ else if (written != -1 || (errno != EAGAIN && errno != EINTR))
+ // original code just ignores this...
+ destroy ();
+ else
+ {
+ pty_ev.set (EVENT_READ | EVENT_WRITE);
+ return;
+ }
}
- R->v_buffer = v_buffer;
- R->v_bufstr = v_bufstr;
- R->v_bufptr = v_bufptr;
- R->v_bufend = v_bufend;
}
+
/*----------------------- end-of-file (C source) -----------------------*/