Wed Mar 1 18:37:18 PST 2000 Michael Jennings <mej@eterm.org>

I'm still not done with the commenting work I've been doing, but I've
	made some fixes, so I figured it was time to commit what I've done so
	far.

	I've added support for multi-byte selection/pastes from programs like
	Netscape, thanks in part to a patch from Yasuyuki Furukawa
	<yasu@on.cs.keio.ac.jp>.  I've also applied a bugfix for pty
	allocation on Irix from David Kaelbling <drk@sgi.com>, a display
	bugfix pointed out by Valdis Kletnieks <Valdis.Kletnieks@vt.edu>, and
	a fix for a missing menu in the auto theme discovered by someone on
	IRC.

	I've also added quite a few comments to term.c to help people grok
	the parsing of escape sequences a little better.


SVN revision: 2168
This commit is contained in:
Michael Jennings 2000-03-02 03:31:41 +00:00
parent d2ca8950e1
commit 8e9f100232
9 changed files with 221 additions and 94 deletions

View File

@ -3242,3 +3242,21 @@ Fri Feb 18 21:09:29 PST 2000 Michael Jennings <mej@eterm.org>
functions to do it. :-)
-------------------------------------------------------------------------------
Wed Mar 1 18:37:18 PST 2000 Michael Jennings <mej@eterm.org>
I'm still not done with the commenting work I've been doing, but I've
made some fixes, so I figured it was time to commit what I've done so
far.
I've added support for multi-byte selection/pastes from programs like
Netscape, thanks in part to a patch from Yasuyuki Furukawa
<yasu@on.cs.keio.ac.jp>. I've also applied a bugfix for pty
allocation on Irix from David Kaelbling <drk@sgi.com>, a display
bugfix pointed out by Valdis Kletnieks <Valdis.Kletnieks@vt.edu>, and
a fix for a missing menu in the auto theme discovered by someone on
IRC.
I've also added quite a few comments to term.c to help people grok
the parsing of escape sequences a little better.
-------------------------------------------------------------------------------

View File

@ -144,7 +144,7 @@ AC_TYPE_UID_T
dnl# Checks for library functions.
AC_TYPE_SIGNAL
AC_CHECK_FUNCS(atexit _exit unsetenv setutent seteuid memmove putenv strsep setresuid setresgid memmem usleep snprintf)
AC_CHECK_FUNCS(atexit _exit unsetenv setutent seteuid memmove putenv strsep setresuid setresgid memmem usleep snprintf X11/Xmu/Atoms.h)
dps_snprintf_oflow()
dnl# Check for the need for -lutil on BSD systems
@ -586,7 +586,12 @@ echo " the --x-libraries parameter to configure.";
AC_CHECK_LIB(Xext, XShapeQueryExtension, AC_DEFINE(HAVE_X_SHAPE_EXT), , $X_LIBS $SUBLIBS)
# check if we need X_LOCALE definition
AC_CHECK_LIB(X11, _Xsetlocale, , AC_DEFINE(NO_XLOCALE), , $X_LIBS $SUBLIBS)
AC_CHECK_LIB(X11, _Xsetlocale, , AC_DEFINE(NO_XLOCALE), $X_LIBS $SUBLIBS)
# For multibyte selection handling
if test "$MULTICHAR_ENCODING" != "none"; then
AC_CHECK_LIB(Xmu, XmuInternAtom, X_LIBS="-lXmu $X_LIBS", , $X_LIBS $SUBLIBS)
fi
# check X11R6 for XIM
if test "$XIM" = "TRUE"; then

View File

@ -1134,10 +1134,11 @@ __inline__ int sgi_get_pty(void);
__inline__ int
sgi_get_pty(void)
{
int fd = -1;
privileges(INVOKE);
ptydev = ttydev = _getpty(&fd, O_RDWR | O_NDELAY, 0620, 0);
privileges(REVERT);
return (ptydev == NULL ? -1 : fd);
}
@ -2503,6 +2504,13 @@ cmd_getc(void)
return (0);
}
/* Put a character back in the buffer. Only use this once at a time. */
void
cmd_ungetc(void)
{
cmdbuf_ptr--;
}
/* tt_write(), tt_printf() - output to command */
/*
* Send count characters directly to the command

View File

@ -266,9 +266,9 @@ if (test) PrivateModes |= (bit); else PrivateModes &= ~(bit);} while (0)
# define SIG_RETURN(x) return
#endif
#define CHARS_READ() (cmdbuf_ptr < cmdbuf_endp)
#define CHARS_BUFFERED() (count != CMD_BUF_SIZE)
#define RETURN_CHAR() do { refreshed = 0; return (*cmdbuf_ptr++); } while (0)
#define CHARS_READ() (cmdbuf_ptr < cmdbuf_endp)
#define CHARS_BUFFERED() (count != CMD_BUF_SIZE)
#define RETURN_CHAR() do { refreshed = 0; return (*cmdbuf_ptr++); } while (0)
#ifdef REFRESH_DELAY
# define REFRESH_DELAY_USEC (1000000/25)
@ -364,6 +364,7 @@ extern unsigned int cmd_write(const unsigned char *, unsigned int);
extern RETSIGTYPE check_pixmap_change(int);
#endif
extern unsigned char cmd_getc(void);
extern void cmd_ungetc(void);
extern void tt_write(const unsigned char *, unsigned int);
extern void tt_printf(const unsigned char *, ...);
extern void main_loop(void);

View File

@ -3568,7 +3568,6 @@ init_defaults(void)
rs_name = StrDup(APL_NAME " " VERSION);
Options = (Opt_scrollbar | Opt_select_trailing_spaces);
Xdisplay = NULL;
display_name = NULL;
rs_term_name = NULL;
#ifdef CUTCHAR_OPTION
rs_cutchars = NULL;
@ -3650,11 +3649,11 @@ post_parse(void)
#ifdef PRINTPIPE
if (!rs_print_pipe)
rs_print_pipe = PRINTPIPE;
rs_print_pipe = StrDup(PRINTPIPE);
#endif
#ifdef CUTCHAR_OPTION
if (!rs_cutchars)
rs_cutchars = CUTCHARS;
rs_cutchars = StrDup(CUTCHARS);
#endif
#ifndef NO_BOLDFONT

View File

@ -24,6 +24,9 @@ static const char cvs_ident[] = "$Id$";
#include <errno.h>
#include <X11/Xatom.h>
#include <X11/Xmd.h> /* CARD32 */
#ifdef HAVE_X11_XMU_ATOMS_H
# include <X11/Xmu/Atoms.h>
#endif
#include "../libmej/debug.h"
#include "../libmej/mem.h"
@ -2383,15 +2386,30 @@ selection_paste(Window win, unsigned prop, int Delete)
if (prop == None)
return;
for (nread = 0, bytes_after = 1; bytes_after > 0;) {
if ((XGetWindowProperty(Xdisplay, win, prop, (nread / 4), PROP_SIZE,
Delete, AnyPropertyType, &actual_type, &actual_fmt,
&nitems, &bytes_after, &data) != Success)) {
if ((XGetWindowProperty(Xdisplay, win, prop, (nread / 4), PROP_SIZE, Delete, AnyPropertyType, &actual_type, &actual_fmt, &nitems, &bytes_after, &data) != Success)) {
XFree(data);
return;
}
nread += nitems;
PasteIt(data, nitems);
if (actual_type == XA_STRING) {
PasteIt(data, nitems);
} else {
int size, i, ret;
XTextProperty xtextp;
char **cl;
xtextp.value = data;
xtextp.encoding = actual_type;
xtextp.format = actual_fmt;
xtextp.nitems = nitems;
XmbTextPropertyToTextList(Xdisplay, &xtextp, &cl, &size);
for (i = 0 ; i < size ; i ++) {
PasteIt(cl[i], strlen(cl[i]));
}
XFreeStringList(cl);
}
XFree(data);
}
}
@ -2415,8 +2433,11 @@ selection_request(Time tm, int x, int y)
selection_paste(Xroot, XA_CUT_BUFFER0, False);
} else {
prop = XInternAtom(Xdisplay, "VT_SELECTION", False);
XConvertSelection(Xdisplay, XA_PRIMARY, XA_STRING, prop, TermWin.vt,
tm);
#ifdef MULTI_CHARSET
XConvertSelection(Xdisplay, XA_PRIMARY, XA_COMPOUND_TEXT(Xdisplay), prop, TermWin.vt, tm);
#else
XConvertSelection(Xdisplay, XA_PRIMARY, XA_STRING, prop, TermWin.vt, tm);
#endif
}
}
@ -3194,10 +3215,25 @@ selection_send(XSelectionRequestEvent * rq)
(unsigned char *) target_list,
(sizeof(target_list) / sizeof(target_list[0])));
ev.xselection.property = rq->property;
#ifdef MULTI_CHARSET
} else if (rq->target == XA_STRING || rq->target == XA_TEXT(Xdisplay) || rq->target == XA_COMPOUND_TEXT(Xdisplay)) {
XTextProperty xtextp;
char *l[1];
*l = selection.text;
xtextp.value = NULL;
xtextp.nitems = 0;
if (XmbTextListToTextProperty(Xdisplay, l, 1, XCompoundTextStyle, &xtextp) == Success) {
if (xtextp.nitems > 0 && xtextp.value != NULL) {
XChangeProperty(Xdisplay, rq->requestor, rq->property, XA_COMPOUND_TEXT(Xdisplay), 8, PropModeReplace, xtextp.value, xtextp.nitems);
ev.xselection.property = rq->property;
}
}
#else
} else if (rq->target == XA_STRING) {
XChangeProperty(Xdisplay, rq->requestor, rq->property, rq->target,
8, PropModeReplace, selection.text, selection.len);
XChangeProperty(Xdisplay, rq->requestor, rq->property, rq->target, 8, PropModeReplace, selection.text, selection.len);
ev.xselection.property = rq->property;
#endif
}
XSendEvent(Xdisplay, rq->requestor, False, 0, &ev);
}

View File

@ -97,6 +97,13 @@ Pixel PixColors[NRS_COLORS + NSHADOWCOLORS];
unsigned int MetaMask = 0, AltMask = 0, NumLockMask = 0;
unsigned int modmasks[] = { Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask };
/* This function queries X to see which modifier keys (specifically Alt, Meta, and NumLock,
since that's really all we care about) are bound to the 5 modifier masks. It then sets
the variables MetaMask, AltMask, and NumLockMask to the appropriate modifier mask (e.g.,
Mod1Mask). That way, we can use MetaMask in lookup_key() instead of using a specific
ModMask. This function also handles fallbacks, so that if there is no Meta key, the Alt
key will be used as Meta, and vice versa. get_modifiers() is called once on startup and
after each MappingNotify event. */
void
get_modifiers(void)
{
@ -107,6 +114,8 @@ get_modifiers(void)
modmap = XGetModifierMapping(Xdisplay);
kc = modmap->modifiermap;
/* For each of the 5 modifier masks... */
for (i = Mod5MapIndex; i >= Mod1MapIndex; i--) {
unsigned short j;
register unsigned short k, l;
@ -114,12 +123,14 @@ get_modifiers(void)
k = i * modmap->max_keypermod;
l = i - Mod1MapIndex;
/* Find each key bound to it... */
for (j = 0; j < modmap->max_keypermod; j++, k++) {
unsigned char match = 0;
if (kc[k] == 0) {
break;
}
/* Check to see if it's one that we care about. */
switch (XKeycodeToKeysym(Xdisplay, kc[k], 0)) {
case XK_Meta_L:
case XK_Meta_R:
@ -144,6 +155,7 @@ get_modifiers(void)
}
}
XFreeModifiermap(modmap);
/* Fallbacks. */
if (MetaMask == 0) {
if (AltMask != 0) {
D_X11(("Defaulted Meta key to match Alt mask\n"));
@ -165,7 +177,14 @@ get_modifiers(void)
#else
# define LK_RET() return
#endif
/* Convert the keypress event into a string */
/* This function is called for every keypress event we receive. Its job is to convert
the keypress into its corresponding action. It is responsible for calling the action
bindings routine to see if there is an action binding for that keysym; if there is,
this routine will exit. If not, it continues. It then uses the keysym to determine
the action or escape sequence which should result from the keypress. Actions are
performed and the event discarded. Escape sequences are generated and sent to the
child process. */
void
lookup_key(XEvent * ev)
{
@ -185,15 +204,13 @@ lookup_key(XEvent * ev)
static short greek_mode = 0;
#endif
/*
* use Num_Lock to toggle Keypad on/off. If Num_Lock is off, allow an
* escape sequence to toggle the Keypad.
*
* Always permit `shift' to override the current setting
*/
/* Quick boolean variables tell us which modifier keys were pressed. */
shft = (ev->xkey.state & ShiftMask);
ctrl = (ev->xkey.state & ControlMask);
meta = (ev->xkey.state & MetaMask);
/* The num lock key toggles application keypad
mode. Num lock on, app. keypad mode off. */
if (numlock_state || (ev->xkey.state & NumLockMask)) {
numlock_state = (ev->xkey.state & NumLockMask);
PrivMode((!numlock_state), PrivMode_aplKP);
@ -203,8 +220,9 @@ lookup_key(XEvent * ev)
Status status_return;
kbuf[0] = '\0';
len = XmbLookupString(xim_input_context, &ev->xkey, (char *) kbuf,
sizeof(short_buf), &keysym, &status_return);
/* Lookup the string equivalent in terms of the XIM input context. */
len = XmbLookupString(xim_input_context, &ev->xkey, (char *) kbuf, sizeof(short_buf), &keysym, &status_return);
/* Whoops, it's too long. Allocate a new buffer and repeat the call. */
if (status_return == XBufferOverflow) {
kbuf = (unsigned char *) MALLOC(len + 1);
kbuf_alloced = 1;
@ -212,16 +230,15 @@ lookup_key(XEvent * ev)
}
valid_keysym = (status_return == XLookupKeySym) || (status_return == XLookupBoth);
} else {
/* No XIM input context. Do it the normal way. */
len = XLookupString(&ev->xkey, (char *) kbuf, sizeof(short_buf), &keysym, NULL);
valid_keysym = 1;
}
#else /* USE_XIM */
/* Translate the key event into its corresponding string according to X. This also gets us a keysym. */
len = XLookupString(&ev->xkey, (char *) kbuf, sizeof(kbuf), &keysym, NULL);
/*
* have unmapped Latin[2-4] entries -> Latin1
* good for installations with correct fonts, but without XLOCALE
*/
/* If there is no string and it's a Latin2-4 character, replace it with the Latin1 character instead. */
if (!len && (keysym >= 0x0100) && (keysym < 0x0400)) {
len = 1;
kbuf[0] = (keysym & 0xff);
@ -229,23 +246,28 @@ lookup_key(XEvent * ev)
#endif /* USE_XIM */
#ifdef USE_XIM
/* Don't do anything without a valid keysym. */
if (valid_keysym) {
#endif
/* Check for a corresponding action binding. If there is one, we're done with this event. */
if (action_dispatch(ev, keysym)) {
LK_RET();
}
/* If we're in pause mode, exit. */
if (len && keypress_exit) {
exit(0);
}
/* This is a special mode that reports all extended keysyms (above 0xff00) to the application
as escape sequences. Very few applications use it, but it can be a handy thing to have. */
if ((Options & Opt_report_as_keysyms) && (keysym >= 0xff00)) {
len = sprintf((char *) kbuf, "\033[k%X;%X~", (unsigned int) (ev->xkey.state & 0xff), (unsigned int) (keysym & 0xff));
tt_write(kbuf, len);
LK_RET();
}
#ifdef HOTKEY
/* for some backwards compatibility */
/* Ctrl-> and Ctrl-< should change font sizes. (Meta if HOTKEY has been changed to Meta.) */
if (HOTKEY) {
if (keysym == ks_bigfont) {
change_font(0, BIGGER_FONT);
@ -261,7 +283,7 @@ lookup_key(XEvent * ev)
/* Shift + F1 - F10 generates F11 - F20 */
if (keysym >= XK_F1 && keysym <= XK_F10) {
keysym += (XK_F11 - XK_F1);
shft = 0; /* turn off Shift */
shft = 0;
} else if (!ctrl && !meta && (PrivateModes & PrivMode_ShiftKeys)) {
int lnsppg; /* Lines per page to scroll */
@ -273,32 +295,31 @@ lookup_key(XEvent * ev)
#endif
switch (keysym) {
/* normal XTerm key bindings */
case XK_Prior: /* Shift+Prior = scroll back */
case XK_Prior: /* Shift-PgUp scrolls up a page */
if (TermWin.saveLines) {
scr_page(UP, lnsppg);
LK_RET();
}
break;
case XK_Next: /* Shift+Next = scroll forward */
case XK_Next: /* Shift-PgDn scrolls down a page */
if (TermWin.saveLines) {
scr_page(DN, lnsppg);
LK_RET();
}
break;
case XK_Insert: /* Shift+Insert = paste mouse selection */
case XK_Insert: /* Shift-Ins pastes the current selection. */
selection_request(ev->xkey.time, ev->xkey.x, ev->xkey.y);
LK_RET();
break;
case XK_KP_Add: /* Shift+KP_Add = bigger font */
case XK_KP_Add: /* Shift-Plus on the keypad increases the font size */
change_font(0, BIGGER_FONT);
LK_RET();
break;
case XK_KP_Subtract: /* Shift+KP_Subtract = smaller font */
case XK_KP_Subtract: /* Shift-Minus on the keypad decreases the font size */
change_font(0, SMALLER_FONT);
LK_RET();
break;
@ -306,6 +327,7 @@ lookup_key(XEvent * ev)
}
}
#ifdef UNSHIFTED_SCROLLKEYS
/* Allow PgUp/PgDn by themselves to scroll. Not recommended. */
else if (!ctrl && !meta) {
switch (keysym) {
case XK_Prior:
@ -326,7 +348,7 @@ lookup_key(XEvent * ev)
#endif
switch (keysym) {
case XK_Print:
case XK_Print: /* Print the screen contents out to the print pipe */
#if DEBUG >= DEBUG_SELECTION
if (debug_level >= DEBUG_SELECTION) {
debug_selection();
@ -356,14 +378,16 @@ lookup_key(XEvent * ev)
TermWin.view_start = 0;
}
if (keysym >= 0xFF00 && keysym <= 0xFFFF) {
/* Process extended keysyms. This is where the conversion to escape sequences happens. */
if (keysym >= 0xff00 && keysym <= 0xffff) {
#ifdef KEYSYM_ATTRIBUTE
if (!(shft | ctrl) && KeySym_map[keysym - 0xFF00] != NULL) {
/* The "keysym" attribute in the config file gets handled here. */
if (!(shft | ctrl) && KeySym_map[keysym - 0xff00] != NULL) {
const unsigned char *tmpbuf;
unsigned int len;
tmpbuf = (KeySym_map[keysym - 0xFF00]);
tmpbuf = (KeySym_map[keysym - 0xff00]);
len = *tmpbuf++;
/* escape prefix */
@ -380,6 +404,7 @@ lookup_key(XEvent * ev)
LK_RET();
} else
#endif
/* This is a big-ass switch statement that handles all the special keysyms */
switch (keysym) {
case XK_BackSpace:
len = 1;
@ -392,6 +417,7 @@ lookup_key(XEvent * ev)
#endif
break;
/* Tab key is normal unless it's shift-tab. */
case XK_Tab:
if (shft) {
len = 3;
@ -415,20 +441,19 @@ lookup_key(XEvent * ev)
break;
#ifdef XK_KP_Left
case XK_KP_Left: /* \033Ot or standard */
case XK_KP_Up: /* \033Ox or standard */
case XK_KP_Right: /* \033Ov or standard */
case XK_KP_Down: /* \033Ow or standard */
case XK_KP_Left: /* \033Ot or standard cursor key */
case XK_KP_Up: /* \033Ox or standard cursor key */
case XK_KP_Right: /* \033Ov or standard cursor key */
case XK_KP_Down: /* \033Or or standard cursor key */
if ((PrivateModes & PrivMode_aplKP) ? !shft : shft) {
len = 3;
strcpy(kbuf, "\033OZ");
strcpy(kbuf, "\033OZ"); /* The Z is replaced by t, x, v, or r */
kbuf[2] = ("txvr"[keysym - XK_KP_Left]);
break;
} else {
/* translate to std. cursor key */
keysym = XK_Left + (keysym - XK_KP_Left);
}
/* FALL THROUGH */
/* Continue on with the normal cursor keys... */
#endif
case XK_Left: /* "\033[D" */
case XK_Up: /* "\033[A" */
@ -446,6 +471,8 @@ lookup_key(XEvent * ev)
kbuf[2] = ("dacb"[keysym - XK_Left]);
}
break;
/* Keypad and normal PgUp/PgDn */
#ifndef UNSHIFTED_SCROLLKEYS
# ifdef XK_KP_Prior
case XK_KP_Prior:
@ -476,6 +503,8 @@ lookup_key(XEvent * ev)
strcpy(kbuf, "\033[6~");
break;
#endif /* UNSHIFTED_SCROLLKEYS */
/* End key */
#ifdef XK_KP_End
case XK_KP_End:
/* allow shift to override */
@ -495,8 +524,8 @@ lookup_key(XEvent * ev)
strcpy(kbuf, "\033[4~");
break;
#ifdef DXK_Remove /* support for DEC remove like key */
case DXK_Remove: /* drop */
#ifdef DXK_Remove
case DXK_Remove:
#endif
case XK_Execute:
len = 4;
@ -684,6 +713,7 @@ sprintf((char *) kbuf,"\033[%02d~", (int)((n) + (keysym - fkey))); \
}
#endif
/* All processed. If there's still no string, we're done. */
if (len <= 0) {
LK_RET();
}
@ -724,23 +754,29 @@ sprintf((char *) kbuf,"\033[%02d~", (int)((n) + (keysym - fkey))); \
fprintf(stderr, "'\n");
}
#endif /* DEBUG_CMD */
tt_write(kbuf, len);
tt_write(kbuf, len); /* Send the resulting string to the child process */
LK_RET();
}
/* print pipe */
#ifdef PRINTPIPE
/* Open the print pipe. */
FILE *
popen_printer(void)
{
FILE *stream = (FILE *) popen(rs_print_pipe, "w");
FILE *stream;
if (stream == NULL)
print_error("can't open printer pipe \"%s\" -- %s", rs_print_pipe, strerror(errno));
if (((my_ruid != my_euid) || (my_rgid != my_egid)) && (strcmp(rs_print_pipe, PRINTPIPE))) {
print_warning("Running setuid/setgid. Refusing to use custom printpipe.");
RESET_AND_ASSIGN(rs_print_pipe, StrDup(PRINTPIPE));
}
if ((stream = (FILE *) popen(rs_print_pipe, "w")) == NULL) {
print_error("Can't open printer pipe \"%s\" -- %s", rs_print_pipe, strerror(errno));
}
return stream;
}
/* Close the print pipe. */
int
pclose_printer(FILE * stream)
{
@ -748,7 +784,7 @@ pclose_printer(FILE * stream)
return pclose(stream);
}
/* simulate attached vt100 printer */
/* Print everything until we hit a \e[4i sequence. */
void
process_print_pipe(void)
{
@ -775,14 +811,18 @@ process_print_pipe(void)
}
#endif /* PRINTPIPE */
/* process escape sequences */
/* This routine processes escape sequences; i.e., when a \033 character is encountered in the
input stream, this function is called to process it. First, we get the next character off
the input stream (the one after the ESC) and store it in ch. Then we proceed based on what
ch is. Some escape sequences are only ESC followed by a single character, so the
processing of those ends here. Others are longer and get passed on to other functions from
this one. */
void
process_escape_seq(void)
{
unsigned char ch = cmd_getc();
switch (ch) {
/* case 1: do_tek_mode (); break; */
case '#':
if (cmd_getc() == '8')
scr_E();
@ -838,11 +878,9 @@ process_escape_seq(void)
case 'M':
scr_index(DN);
break;
/*case 'N': scr_single_shift (2); break; */
/*case 'O': scr_single_shift (3); break; */
case 'Z':
tt_printf((unsigned char *) ESCZ_ANSWER);
break; /* steal obsolete ESC [ c */
break;
case '[':
process_csi_seq();
break;
@ -861,7 +899,10 @@ process_escape_seq(void)
}
}
/* process CSI (code sequence introducer) sequences `ESC[' */
/* This function handles Code Sequence Introducer (CSI) escape sequences. At this point,
we've read "\e[" from the input stream. CSI sequences take an arbitrary number of
parameters and are used almost exclusively for terminal window navigation and
manipulation. */
void
process_csi_seq(void)
{
@ -875,12 +916,12 @@ process_csi_seq(void)
arg[1] = 0;
priv = 0;
ch = cmd_getc();
ch = cmd_getc(); /* Get the next character */
if (ch >= '<' && ch <= '?') {
priv = ch;
priv = ch; /* DEC private mode sequence. Get next character. */
ch = cmd_getc();
}
/* read any numerical arguments */
/* Read semicolon-delimited numerical arguments, if any. */
do {
int n;
@ -892,64 +933,63 @@ process_csi_seq(void)
if (ch == '\b') {
scr_backspace();
} else if (ch == 033) {
process_escape_seq();
cmd_ungetc(); /* New escape sequence starting in the middle of one. Punt. */
return;
} else if (ch < ' ') {
scr_add_lines(&ch, 0, 1);
scr_add_lines(&ch, 0, 1); /* Insert verbatim non-printable character (NPC) */
return;
}
if (ch < '@')
ch = cmd_getc();
}
while (ch >= ' ' && ch < '@');
ch = cmd_getc(); /* Separator. Go to next digit or operation. */
} while (ch >= ' ' && ch < '@');
if (ch == 033) {
process_escape_seq();
cmd_ungetc();
return;
} else if (ch < ' ')
return;
return; /* An NPC. Punt. */
switch (ch) {
#ifdef PRINTPIPE
case 'i': /* printing */
case 'i':
switch (arg[0]) {
case 0:
scr_printscreen(0);
scr_printscreen(0); /* Print screen "\e[0i" */
break;
case 5:
process_print_pipe();
process_print_pipe(); /* Start printing to print pipe "\e[5i" */
break;
}
break;
#endif
case 'A':
case 'e': /* up <n> */
case 'e': /* Cursor up n lines "\e[<n>A" */
scr_gotorc((arg[0] ? -arg[0] : -1), 0, RELATIVE);
break;
case 'B': /* down <n> */
case 'B': /* Cursor down n lines "\e[<n>B" */
scr_gotorc((arg[0] ? +arg[0] : +1), 0, RELATIVE);
break;
case 'C':
case 'a': /* right <n> */
case 'a': /* Cursor right n columns "\e[<n>C" */
scr_gotorc(0, (arg[0] ? +arg[0] : +1), RELATIVE);
break;
case 'D': /* left <n> */
case 'D': /* Cursor left n columns "\e[<n>D" */
scr_gotorc(0, (arg[0] ? -arg[0] : -1), RELATIVE);
break;
case 'E': /* down <n> & to first column */
case 'E': /* Cursor down n lines and to first column "\e[<n>E" */
scr_gotorc((arg[0] ? +arg[0] : +1), 0, R_RELATIVE);
break;
case 'F': /* up <n> & to first column */
case 'F': /* Cursor up n lines and to first column "\e[<n>F" */
scr_gotorc((arg[0] ? -arg[0] : -1), 0, R_RELATIVE);
break;
case 'G':
case '`': /* move to col <n> */
case '`': /* Cursor to column n "\e[<n>G" */
scr_gotorc(0, (arg[0] ? arg[0] - 1 : +1), R_RELATIVE);
break;
case 'd': /* move to row <n> */
case 'd': /* Cursor to row n "\e[<n>d" */
scr_gotorc((arg[0] ? arg[0] - 1 : +1), 0, C_RELATIVE);
break;
case 'H':
case 'f': /* position cursor */
case 'f': /* Cursor to row r, column c "\e[<r>;<c>H" */
switch (nargs) {
case 0:
scr_gotorc(0, 0, 0);
@ -962,16 +1002,16 @@ process_csi_seq(void)
break;
}
break;
case 'I':
case 'I': /* Tab right n tab stops "\e[<n>I" */
scr_tab(arg[0] ? +arg[0] : +1);
break;
case 'Z':
case 'Z': /* Tab left n tab stops "\e[<n>Z" */
scr_tab(arg[0] ? -arg[0] : -1);
break;
case 'J':
case 'J': /* Clear part or all of screen, depending on n "\e[<n>J" */
scr_erase_screen(arg[0]);
break;
case 'K':
case 'K': /* Clear part or all of line, depending on n "\e[<n>K" */
scr_erase_line(arg[0]);
break;
case '@':

View File

@ -230,18 +230,19 @@ remove_utmp_entry(void)
if (!ut_id[0])
return; /* entry not made */
privileges(INVOKE);
utmpname(UTMP_FILENAME);
setutent();
if (getutid(&utmp) == NULL)
strncpy(utmp.ut_id, ut_id, sizeof(utmp.ut_id));
utmp.ut_type = USER_PROCESS;
if (getutid(&utmp) == NULL) {
return;
}
utmp.ut_type = DEAD_PROCESS;
utmp.ut_time = time(NULL);
pututline(&utmp);
getutmpx(&utmp, &utmpx);
update_wtmp(WTMP_FILENAME, &utmpx);
endutent();
privileges(REVERT);
# else /* HAVE_UTMPX_H */
struct utmp *putmp;
@ -250,7 +251,6 @@ remove_utmp_entry(void)
if (!ut_id[0])
return; /* entry not made */
privileges(INVOKE);
utmpname(UTMP_FILENAME);
setutent();
/*
@ -269,7 +269,6 @@ remove_utmp_entry(void)
}
}
endutent();
privileges(REVERT);
# endif /* HAVE_UTMPX_H */
}
# endif /* ifndef HAVE_UTEMPTER */

View File

@ -866,6 +866,27 @@ begin menu
end
end
begin menu
title "Eterm Operations"
begin menuitem
text "Version"
action string "\e[8n"
end
begin menuitem
text "Status"
action string "\e[9n"
end
separator
begin menuitem
text "Save Settings..."
action string "\e]6;71\a"
end
begin menuitem
text "Exit"
action string "\e]6;70\a"
end
end
# This is the menu that gets called by Ctrl-Button3
begin menu
title Eterm