eterm/src/term.c

2050 lines
52 KiB
C
Raw Normal View History

/* term.c -- Eterm terminal emulation module
*
* This file is original work by Michael Jennings <mej@eterm.org> and
* Tuomo Venalainen <vendu@cc.hut.fi>. This file, and any other file
* bearing this same message or a similar one, is distributed under
* the GNU Public License (GPL) as outlined in the COPYING file.
*
* Copyright (C) 1997-1999, Michael Jennings and Tuomo Venalainen
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
static const char cvs_ident[] = "$Id$";
#include "config.h"
#include "feature.h"
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <limits.h>
#include "../libmej/debug.h"
#include "../libmej/mem.h"
#include "../libmej/strings.h"
#include "debug.h"
#include "actions.h"
#include "command.h"
#include "e.h"
#include "events.h"
#include "font.h"
#include "startup.h"
#include "options.h"
#include "pixmap.h"
#include "screen.h"
#include "scrollbar.h"
#include "term.h"
#include "windows.h"
#ifdef META8_OPTION
unsigned char meta_char = 033; /* Alt-key prefix */
#endif
unsigned long PrivateModes = PrivMode_Default;
unsigned long SavedModes = PrivMode_Default;
char *def_colorName[] =
{
"rgb:ff/ff/ff", "rgb:0/0/0", /* fg/bg */
"rgb:0/0/0", /* 0: black (#000000) */
#ifndef NO_BRIGHTCOLOR
/* low-intensity colors */
"rgb:cc/00/00", /* 1: red */
"rgb:00/cc/00", /* 2: green */
"rgb:cc/cc/00", /* 3: yellow */
"rgb:00/00/cc", /* 4: blue */
"rgb:cc/00/cc", /* 5: magenta */
"rgb:00/cc/cc", /* 6: cyan */
"rgb:fa/eb/d7", /* 7: white */
/* high-intensity colors */
"rgb:33/33/33", /* 8: bright black */
#endif /* NO_BRIGHTCOLOR */
"rgb:ff/00/00", /* 1/9: bright red */
"rgb:00/ff/00", /* 2/10: bright green */
"rgb:ff/ff/00", /* 3/11: bright yellow */
"rgb:00/00/ff", /* 4/12: bright blue */
"rgb:ff/00/ff", /* 5/13: bright magenta */
"rgb:00/ff/ff", /* 6/14: bright cyan */
"rgb:ff/ff/ff", /* 7/15: bright white */
#ifndef NO_CURSORCOLOR
NULL, NULL, /* cursorColor, cursorColor2 */
#endif /* NO_CURSORCOLOR */
NULL, NULL /* pointerColor, borderColor */
#ifndef NO_BOLDUNDERLINE
,NULL, NULL /* colorBD, colorUL */
#endif /* NO_BOLDUNDERLINE */
,"rgb:ff/ff/ff" /* menuTextColor */
,"rgb:b2/b2/b2" /* scrollColor: match Netscape color */
,NULL /* menuColor: match scrollbar color */
,NULL /* unfocusedscrollColor: somebody chose black? */
,NULL /* unfocusedMenuColor */
};
char *rs_color[NRS_COLORS];
Pixel PixColors[NRS_COLORS + NSHADOWCOLORS];
/* To handle buffer overflows properly, we must malloc a buffer. Free it when done. */
#ifdef USE_XIM
# define LK_RET() do {if (kbuf_alloced) FREE(kbuf); return;} while (0)
#else
# define LK_RET() return
#endif
/* Convert the keypress event into a string */
void
lookup_key(XEvent * ev)
{
static int numlock_state = 0;
int ctrl, meta, shft, len;
KeySym keysym;
#ifdef USE_XIM
int valid_keysym = 0;
static unsigned char short_buf[256];
unsigned char *kbuf = short_buf;
int kbuf_alloced = 0;
#else
static unsigned char kbuf[KBUFSZ];
#endif
#if DEBUG >= DEBUG_CMD
static int debug_key = 1; /* accessible by a debugger only */
#endif
#ifdef GREEK_SUPPORT
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
*/
shft = (ev->xkey.state & ShiftMask);
ctrl = (ev->xkey.state & ControlMask);
meta = (ev->xkey.state & Mod1Mask);
if (numlock_state || (ev->xkey.state & Mod5Mask)) {
numlock_state = (ev->xkey.state & Mod5Mask); /* numlock toggle */
PrivMode((!numlock_state), PrivMode_aplKP);
}
#ifdef USE_XIM
if (xim_input_context != NULL) {
Status status_return;
kbuf[0] = '\0';
len = XmbLookupString(xim_input_context, &ev->xkey, (char *) kbuf,
sizeof(short_buf), &keysym, &status_return);
if (status_return == XBufferOverflow) {
kbuf = (unsigned char *) MALLOC(len + 1);
kbuf_alloced = 1;
len = XmbLookupString(xim_input_context, &ev->xkey, (char *) kbuf, len, &keysym, &status_return);
}
valid_keysym = (status_return == XLookupKeySym) || (status_return == XLookupBoth);
} else {
len = XLookupString(&ev->xkey, (char *) kbuf, sizeof(short_buf), &keysym, NULL);
valid_keysym = 1;
}
#else /* USE_XIM */
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 (!len && (keysym >= 0x0100) && (keysym < 0x0400)) {
len = 1;
kbuf[0] = (keysym & 0xff);
}
#endif /* USE_XIM */
#ifdef USE_XIM
if (valid_keysym) {
#endif
if (action_dispatch(ev, keysym)) {
LK_RET();
}
if (len) {
if (keypress_exit) {
exit(0);
} else if (Options & Opt_homeOnInput) {
TermWin.view_start = 0;
}
}
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 */
if (HOTKEY) {
if (keysym == ks_bigfont) {
change_font(0, FONT_UP);
LK_RET();
} else if (keysym == ks_smallfont) {
change_font(0, FONT_DN);
LK_RET();
}
}
#endif
if (shft) {
/* Shift + F1 - F10 generates F11 - F20 */
if (keysym >= XK_F1 && keysym <= XK_F10) {
keysym += (XK_F11 - XK_F1);
shft = 0; /* turn off Shift */
} else if (!ctrl && !meta && (PrivateModes & PrivMode_ShiftKeys)) {
int lnsppg; /* Lines per page to scroll */
#ifdef PAGING_CONTEXT_LINES
lnsppg = TermWin.nrow - PAGING_CONTEXT_LINES;
#else
lnsppg = TermWin.nrow * 4 / 5;
#endif
switch (keysym) {
/* normal XTerm key bindings */
case XK_Prior: /* Shift+Prior = scroll back */
if (TermWin.saveLines) {
scr_page(UP, lnsppg);
LK_RET();
}
break;
case XK_Next: /* Shift+Next = scroll forward */
if (TermWin.saveLines) {
scr_page(DN, lnsppg);
LK_RET();
}
break;
case XK_Insert: /* Shift+Insert = paste mouse selection */
selection_request(ev->xkey.time, ev->xkey.x, ev->xkey.y);
LK_RET();
break;
case XK_KP_Add: /* Shift+KP_Add = bigger font */
change_font(0, FONT_UP);
LK_RET();
break;
case XK_KP_Subtract: /* Shift+KP_Subtract = smaller font */
change_font(0, FONT_DN);
LK_RET();
break;
}
}
}
#ifdef UNSHIFTED_SCROLLKEYS
else if (!ctrl && !meta) {
switch (keysym) {
case XK_Prior:
if (TermWin.saveLines) {
scr_page(UP, TermWin.nrow * 4 / 5);
LK_RET();
}
break;
case XK_Next:
if (TermWin.saveLines) {
scr_page(DN, TermWin.nrow * 4 / 5);
LK_RET();
}
break;
}
}
#endif
switch (keysym) {
case XK_Print:
#if DEBUG >= DEBUG_SELECTION
if (debug_level >= DEBUG_SELECTION) {
debug_selection();
}
#endif
#ifdef PRINTPIPE
scr_printscreen(ctrl | shft);
LK_RET();
#endif
break;
case XK_Mode_switch:
#ifdef GREEK_SUPPORT
greek_mode = !greek_mode;
if (greek_mode) {
xterm_seq(XTerm_title, (greek_getmode() == GREEK_ELOT928 ? "[Greek: iso]" : "[Greek: ibm]"));
greek_reset();
} else
xterm_seq(XTerm_title, APL_NAME "-" VERSION);
LK_RET();
#endif
break;
}
if (keysym >= 0xFF00 && keysym <= 0xFFFF) {
#ifdef KEYSYM_ATTRIBUTE
if (!(shft | ctrl) && KeySym_map[keysym - 0xFF00] != NULL) {
const unsigned char *tmpbuf;
unsigned int len;
tmpbuf = (KeySym_map[keysym - 0xFF00]);
len = *tmpbuf++;
/* escape prefix */
if (meta
# ifdef META8_OPTION
&& (meta_char == 033)
# endif
) {
const unsigned char ch = '\033';
tt_write(&ch, 1);
}
tt_write(tmpbuf, len);
LK_RET();
} else
#endif
switch (keysym) {
case XK_BackSpace:
len = 1;
#ifdef FORCE_BACKSPACE
kbuf[0] = (!(shft | ctrl) ? '\b' : '\177');
#elif defined(FORCE_DELETE)
kbuf[0] = ((shft | ctrl) ? '\b' : '\177');
#else
kbuf[0] = (((PrivateModes & PrivMode_BackSpace) ? !(shft | ctrl) : (shft | ctrl)) ? '\b' : '\177');
#endif
break;
case XK_Tab:
if (shft) {
len = 3;
strcpy(kbuf, "\033[Z");
}
break;
#ifdef XK_KP_Home
case XK_KP_Home:
/* allow shift to override */
if ((PrivateModes & PrivMode_aplKP) ? !shft : shft) {
len = 3;
strcpy(kbuf, "\033Ow");
break;
}
/* -> else FALL THROUGH */
#endif
case XK_Home:
len = strlen(strcpy(kbuf, KS_HOME));
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 */
if ((PrivateModes && PrivMode_aplKP) ? !shft : shft) {
len = 3;
strcpy(kbuf, "\033OZ");
kbuf[2] = ("txvw"[keysym - XK_KP_Left]);
break;
} else {
/* translate to std. cursor key */
keysym = XK_Left + (keysym - XK_KP_Left);
}
/* FALL THROUGH */
#endif
case XK_Left: /* "\033[D" */
case XK_Up: /* "\033[A" */
case XK_Right: /* "\033[C" */
case XK_Down: /* "\033[B" */
len = 3;
strcpy(kbuf, "\033[@");
kbuf[2] = ("DACB"[keysym - XK_Left]);
if (PrivateModes & PrivMode_aplCUR) {
kbuf[1] = 'O';
} else if (shft) { /* do Shift first */
kbuf[2] = ("dacb"[keysym - XK_Left]);
} else if (ctrl) {
kbuf[1] = 'O';
kbuf[2] = ("dacb"[keysym - XK_Left]);
}
break;
#ifndef UNSHIFTED_SCROLLKEYS
# ifdef XK_KP_Prior
case XK_KP_Prior:
/* allow shift to override */
if ((PrivateModes & PrivMode_aplKP) ? !shft : shft) {
len = 3;
strcpy(kbuf, "\033Oy");
break;
}
/* -> else FALL THROUGH */
# endif /* XK_KP_Prior */
case XK_Prior:
len = 4;
strcpy(kbuf, "\033[5~");
break;
# ifdef XK_KP_Next
case XK_KP_Next:
/* allow shift to override */
if ((PrivateModes & PrivMode_aplKP) ? !shft : shft) {
len = 3;
strcpy(kbuf, "\033Os");
break;
}
/* -> else FALL THROUGH */
# endif /* XK_KP_Next */
case XK_Next:
len = 4;
strcpy(kbuf, "\033[6~");
break;
#endif /* UNSHIFTED_SCROLLKEYS */
#ifdef XK_KP_End
case XK_KP_End:
/* allow shift to override */
if ((PrivateModes & PrivMode_aplKP) ? !shft : shft) {
len = 3;
strcpy(kbuf, "\033Oq");
break;
}
/* -> else FALL THROUGH */
#endif /* XK_KP_End */
case XK_End:
len = strlen(strcpy(kbuf, KS_END));
break;
case XK_Select:
len = 4;
strcpy(kbuf, "\033[4~");
break;
#ifdef DXK_Remove /* support for DEC remove like key */
case DXK_Remove: /* drop */
#endif
case XK_Execute:
len = 4;
strcpy(kbuf, "\033[3~");
break;
case XK_Insert:
len = 4;
strcpy(kbuf, "\033[2~");
break;
case XK_Menu:
len = 5;
strcpy(kbuf, "\033[29~");
break;
case XK_Find:
len = 4;
strcpy(kbuf, "\033[1~");
break;
case XK_Help:
len = 5;
strcpy(kbuf, "\033[28~");
break;
case XK_KP_Enter:
/* allow shift to override */
if ((PrivateModes & PrivMode_aplKP) ? !shft : shft) {
len = 3;
strcpy(kbuf, "\033OM");
} else {
len = 1;
kbuf[0] = '\r';
}
break;
#ifdef XK_KP_Begin
case XK_KP_Begin:
len = 3;
strcpy(kbuf, "\033Ou");
break;
case XK_KP_Insert:
len = 3;
strcpy(kbuf, "\033Op");
break;
case XK_KP_Delete:
len = 3;
strcpy(kbuf, "\033On");
break;
#endif /* XK_KP_Begin */
case XK_KP_F1: /* "\033OP" */
case XK_KP_F2: /* "\033OQ" */
case XK_KP_F3: /* "\033OR" */
case XK_KP_F4: /* "\033OS" */
len = 3;
strcpy(kbuf, "\033OP");
kbuf[2] += (keysym - XK_KP_F1);
break;
case XK_KP_Multiply: /* "\033Oj" : "*" */
case XK_KP_Add: /* "\033Ok" : "+" */
case XK_KP_Separator: /* "\033Ol" : "," */
case XK_KP_Subtract: /* "\033Om" : "-" */
case XK_KP_Decimal: /* "\033On" : "." */
case XK_KP_Divide: /* "\033Oo" : "/" */
case XK_KP_0: /* "\033Op" : "0" */
case XK_KP_1: /* "\033Oq" : "1" */
case XK_KP_2: /* "\033Or" : "2" */
case XK_KP_3: /* "\033Os" : "3" */
case XK_KP_4: /* "\033Ot" : "4" */
case XK_KP_5: /* "\033Ou" : "5" */
case XK_KP_6: /* "\033Ov" : "6" */
case XK_KP_7: /* "\033Ow" : "7" */
case XK_KP_8: /* "\033Ox" : "8" */
case XK_KP_9: /* "\033Oy" : "9" */
/* allow shift to override */
if ((PrivateModes & PrivMode_aplKP) ? !shft : shft) {
len = 3;
strcpy(kbuf, "\033Oj");
kbuf[2] += (keysym - XK_KP_Multiply);
} else {
len = 1;
kbuf[0] = ('*' + (keysym - XK_KP_Multiply));
}
break;
#define FKEY(n,fkey) do { \
len = 5; \
sprintf((char *) kbuf,"\033[%02d~", (int)((n) + (keysym - fkey))); \
} while (0);
case XK_F1: /* "\033[11~" */
case XK_F2: /* "\033[12~" */
case XK_F3: /* "\033[13~" */
case XK_F4: /* "\033[14~" */
case XK_F5: /* "\033[15~" */
FKEY(11, XK_F1);
break;
case XK_F6: /* "\033[17~" */
case XK_F7: /* "\033[18~" */
case XK_F8: /* "\033[19~" */
case XK_F9: /* "\033[20~" */
case XK_F10: /* "\033[21~" */
FKEY(17, XK_F6);
break;
case XK_F11: /* "\033[23~" */
case XK_F12: /* "\033[24~" */
case XK_F13: /* "\033[25~" */
case XK_F14: /* "\033[26~" */
FKEY(23, XK_F11);
break;
case XK_F15: /* "\033[28~" */
case XK_F16: /* "\033[29~" */
FKEY(28, XK_F15);
break;
case XK_F17: /* "\033[31~" */
case XK_F18: /* "\033[32~" */
case XK_F19: /* "\033[33~" */
case XK_F20: /* "\033[34~" */
case XK_F21: /* "\033[35~" */
case XK_F22: /* "\033[36~" */
case XK_F23: /* "\033[37~" */
case XK_F24: /* "\033[38~" */
case XK_F25: /* "\033[39~" */
case XK_F26: /* "\033[40~" */
case XK_F27: /* "\033[41~" */
case XK_F28: /* "\033[42~" */
case XK_F29: /* "\033[43~" */
case XK_F30: /* "\033[44~" */
case XK_F31: /* "\033[45~" */
case XK_F32: /* "\033[46~" */
case XK_F33: /* "\033[47~" */
case XK_F34: /* "\033[48~" */
case XK_F35: /* "\033[49~" */
FKEY(31, XK_F17);
break;
#undef FKEY
#ifdef KS_DELETE
case XK_Delete:
len = strlen(strcpy(kbuf, KS_DELETE));
break;
#endif
}
#ifdef META8_OPTION
if (meta && (meta_char == 0x80) && len > 0) {
kbuf[len - 1] |= 0x80;
}
#endif
} else if (ctrl && keysym == XK_minus) {
len = 1;
kbuf[0] = '\037'; /* Ctrl-Minus generates ^_ (31) */
} else {
#ifdef META8_OPTION
/* set 8-bit on */
if (meta && (meta_char == 0x80)) {
unsigned char *ch;
for (ch = kbuf; ch < kbuf + len; ch++)
*ch |= 0x80;
meta = 0;
}
#endif
#ifdef GREEK_SUPPORT
if (greek_mode)
len = greek_xlat(kbuf, len);
#endif
}
#ifdef USE_XIM
}
#endif
if (len <= 0)
LK_RET(); /* not mapped */
/*
* these modifications only affect the static keybuffer
* pass Shift/Control indicators for function keys ending with `~'
*
* eg,
* Prior = "ESC[5~"
* Shift+Prior = "ESC[5~"
* Ctrl+Prior = "ESC[5^"
* Ctrl+Shift+Prior = "ESC[5@"
*/
if (kbuf[0] == '\033' && kbuf[1] == '[' && kbuf[len - 1] == '~')
kbuf[len - 1] = (shft ? (ctrl ? '@' : '$') : (ctrl ? '^' : '~'));
/* escape prefix */
if (meta
#ifdef META8_OPTION
&& (meta_char == 033)
#endif
) {
const unsigned char ch = '\033';
tt_write(&ch, 1);
}
#if DEBUG >= DEBUG_CMD
if (debug_level >= DEBUG_CMD && debug_key) { /* Display keyboard buffer contents */
char *p;
int i;
fprintf(stderr, "key 0x%04X[%d]: `", (unsigned int) keysym, len);
for (i = 0, p = (char *) kbuf; i < len; i++, p++)
fprintf(stderr, (*p >= ' ' && *p < '\177' ? "%c" : "\\%03o"), *p);
fprintf(stderr, "'\n");
}
#endif /* DEBUG_CMD */
tt_write(kbuf, len);
1999-09-14 18:37:01 -07:00
LK_RET();
}
/* print pipe */
#ifdef PRINTPIPE
FILE *
popen_printer(void)
{
FILE *stream = (FILE *) popen(rs_print_pipe, "w");
if (stream == NULL)
print_error("can't open printer pipe \"%s\" -- %s", rs_print_pipe, strerror(errno));
return stream;
}
int
pclose_printer(FILE * stream)
{
fflush(stream);
return pclose(stream);
}
/* simulate attached vt100 printer */
void
process_print_pipe(void)
{
const char *const escape_seq = "\033[4i";
const char *const rev_escape_seq = "i4[\033";
int index;
FILE *fd;
if ((fd = popen_printer()) != NULL) {
for (index = 0; index < 4; /* nil */ ) {
unsigned char ch = cmd_getc();
if (ch == escape_seq[index])
index++;
else if (index)
for ( /*nil */ ; index > 0; index--)
fputc(rev_escape_seq[index - 1], fd);
if (index == 0)
fputc(ch, fd);
}
pclose_printer(fd);
}
}
#endif /* PRINTPIPE */
/* process escape sequences */
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();
break;
case '(':
scr_charset_set(0, cmd_getc());
break;
case ')':
scr_charset_set(1, cmd_getc());
break;
case '*':
scr_charset_set(2, cmd_getc());
break;
case '+':
scr_charset_set(3, cmd_getc());
break;
#ifdef MULTI_CHARSET
case '$':
scr_charset_set(-2, cmd_getc());
break;
#endif
case '7':
scr_cursor(SAVE);
break;
case '8':
scr_cursor(RESTORE);
break;
case '=':
case '>':
PrivMode((ch == '='), PrivMode_aplKP);
break;
case '@':
(void) cmd_getc();
break;
case 'D':
scr_index(UP);
break;
case 'E':
scr_add_lines((unsigned char *) "\n\r", 1, 2);
break;
case 'G':
if ((ch = cmd_getc()) == 'Q') { /* query graphics */
tt_printf((unsigned char *) "\033G0\n"); /* no graphics */
} else {
do {
ch = cmd_getc();
} while (ch != ':');
}
break;
case 'H':
scr_set_tab(1);
break;
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 */
case '[':
process_csi_seq();
break;
case ']':
process_xterm_seq();
break;
case 'c':
scr_poweron();
break;
case 'n':
scr_charset_choose(2);
break;
case 'o':
scr_charset_choose(3);
break;
}
}
/* process CSI (code sequence introducer) sequences `ESC[' */
void
process_csi_seq(void)
{
unsigned char ch, priv;
unsigned int nargs;
int arg[ESC_ARGS];
nargs = 0;
arg[0] = 0;
arg[1] = 0;
priv = 0;
ch = cmd_getc();
if (ch >= '<' && ch <= '?') {
priv = ch;
ch = cmd_getc();
}
/* read any numerical arguments */
do {
int n;
for (n = 0; isdigit(ch); ch = cmd_getc())
n = n * 10 + (ch - '0');
if (nargs < ESC_ARGS)
arg[nargs++] = n;
if (ch == '\b') {
scr_backspace();
} else if (ch == 033) {
process_escape_seq();
return;
} else if (ch < ' ') {
scr_add_lines(&ch, 0, 1);
return;
}
if (ch < '@')
ch = cmd_getc();
}
while (ch >= ' ' && ch < '@');
if (ch == 033) {
process_escape_seq();
return;
} else if (ch < ' ')
return;
switch (ch) {
#ifdef PRINTPIPE
case 'i': /* printing */
switch (arg[0]) {
case 0:
scr_printscreen(0);
break;
case 5:
process_print_pipe();
break;
}
break;
#endif
case 'A':
case 'e': /* up <n> */
scr_gotorc((arg[0] ? -arg[0] : -1), 0, RELATIVE);
break;
case 'B': /* down <n> */
scr_gotorc((arg[0] ? +arg[0] : +1), 0, RELATIVE);
break;
case 'C':
case 'a': /* right <n> */
scr_gotorc(0, (arg[0] ? +arg[0] : +1), RELATIVE);
break;
case 'D': /* left <n> */
scr_gotorc(0, (arg[0] ? -arg[0] : -1), RELATIVE);
break;
case 'E': /* down <n> & to first column */
scr_gotorc((arg[0] ? +arg[0] : +1), 0, R_RELATIVE);
break;
case 'F': /* up <n> & to first column */
scr_gotorc((arg[0] ? -arg[0] : -1), 0, R_RELATIVE);
break;
case 'G':
case '`': /* move to col <n> */
scr_gotorc(0, (arg[0] ? arg[0] - 1 : +1), R_RELATIVE);
break;
case 'd': /* move to row <n> */
scr_gotorc((arg[0] ? arg[0] - 1 : +1), 0, C_RELATIVE);
break;
case 'H':
case 'f': /* position cursor */
switch (nargs) {
case 0:
scr_gotorc(0, 0, 0);
break;
case 1:
scr_gotorc((arg[0] ? arg[0] - 1 : 0), 0, 0);
break;
default:
scr_gotorc(arg[0] - 1, arg[1] - 1, 0);
break;
}
break;
case 'I':
scr_tab(arg[0] ? +arg[0] : +1);
break;
case 'Z':
scr_tab(arg[0] ? -arg[0] : -1);
break;
case 'J':
scr_erase_screen(arg[0]);
break;
case 'K':
scr_erase_line(arg[0]);
break;
case '@':
scr_insdel_chars((arg[0] ? arg[0] : 1), INSERT);
break;
case 'L':
scr_insdel_lines((arg[0] ? arg[0] : 1), INSERT);
break;
case 'M':
scr_insdel_lines((arg[0] ? arg[0] : 1), DELETE);
break;
case 'X':
scr_insdel_chars((arg[0] ? arg[0] : 1), ERASE);
break;
case 'P':
scr_insdel_chars((arg[0] ? arg[0] : 1), DELETE);
break;
case 'c':
#ifndef NO_VT100_ANS
tt_printf(VT100_ANS);
#endif
break;
case 'm':
process_sgr_mode(nargs, arg);
break;
case 'n': /* request for information */
switch (arg[0]) {
case 5:
tt_printf((unsigned char *) "\033[0n");
break; /* ready */
case 6:
scr_report_position();
break;
#if defined (ENABLE_DISPLAY_ANSWER)
case 7:
tt_printf((unsigned char *) "%s\n", display_name);
break;
#endif
case 8:
xterm_seq(XTerm_title, APL_NAME "-" VERSION);
break;
case 9:
#ifdef PIXMAP_OFFSET
if (image_mode_is(image_bg, MODE_TRANS)) {
char tbuff[70];
char shading = 0;
unsigned long tint = 0xffffff;
if (images[image_bg].current->iml->mod) {
shading = images[image_bg].current->iml->mod->brightness / 0xff * 100;
}
if (images[image_bg].current->iml->rmod) {
tint = (tint & 0x00ffff) | ((images[image_bg].current->iml->rmod->brightness & 0xff) << 16);
}
if (images[image_bg].current->iml->gmod) {
tint = (tint & 0xff00ff) | ((images[image_bg].current->iml->gmod->brightness & 0xff) << 8);
}
if (images[image_bg].current->iml->bmod) {
tint = (tint & 0xffff00) | (images[image_bg].current->iml->bmod->brightness & 0xff);
}
snprintf(tbuff, sizeof(tbuff), APL_NAME "-" VERSION ": Transparent - %d%% shading - 0x%06lx tint mask",
shading, tint);
xterm_seq(XTerm_title, tbuff);
} else
#endif
#ifdef PIXMAP_SUPPORT
{
char *tbuff;
unsigned short len;
if (background_is_pixmap()) {
char *fname = images[image_bg].current->iml->im->filename;
len = strlen(fname) + sizeof(APL_NAME) + sizeof(VERSION) + 5;
tbuff = MALLOC(len);
snprintf(tbuff, len, APL_NAME "-" VERSION ": %s", fname);
xterm_seq(XTerm_title, tbuff);
FREE(tbuff);
} else {
xterm_seq(XTerm_title, APL_NAME "-" VERSION ": No Pixmap");
}
}
#endif /* PIXMAP_SUPPORT */
break;
}
break;
case 'r': /* set top and bottom margins */
if (priv != '?') {
if (nargs < 2 || arg[0] >= arg[1])
scr_scroll_region(0, 10000);
else
scr_scroll_region(arg[0] - 1, arg[1] - 1);
break;
}
/* drop */
case 't':
if (priv != '?') {
process_window_mode(nargs, arg);
break;
}
/* drop */
case 's':
if (ch == 's' && !nargs) {
scr_cursor(SAVE);
break;
}
/* drop */
case 'h':
case 'l':
process_terminal_mode(ch, priv, nargs, arg);
break;
case 'u':
if (!nargs) {
scr_cursor(RESTORE);
}
break;
case 'g':
switch (arg[0]) {
case 0:
scr_set_tab(0);
break; /* delete tab */
case 3:
scr_set_tab(-1);
break; /* clear all tabs */
}
break;
case 'W':
switch (arg[0]) {
case 0:
scr_set_tab(1);
break; /* = ESC H */
case 2:
scr_set_tab(0);
break; /* = ESC [ 0 g */
case 5:
scr_set_tab(-1);
break; /* = ESC [ 3 g */
}
break;
}
}
/* process xterm text parameters sequences `ESC ] Ps ; Pt BEL' */
void
process_xterm_seq(void)
{
unsigned char ch, string[STRING_MAX];
int arg;
ch = cmd_getc();
if (isdigit(ch)) {
for (arg = 0; isdigit(ch); ch = cmd_getc()) {
arg = arg * 10 + (ch - '0');
}
} else if (ch == ';') {
arg = 0;
} else {
arg = ch;
ch = cmd_getc();
}
if (ch == ';') {
unsigned long n = 0;
while ((ch = cmd_getc()) != 007) {
if (ch) {
if (ch == '\t')
ch = ' '; /* translate '\t' to space */
else if ((ch < ' ') && !(isspace(ch) && arg == XTerm_EtermIPC))
return; /* control character - exit */
if (n < sizeof(string) - 1)
string[n++] = ch;
}
}
string[n] = '\0';
xterm_seq(arg, (char *) string);
} else {
unsigned long n = 0;
for (; ch != '\033'; ch = cmd_getc()) {
if (ch) {
if (ch == '\t')
ch = ' '; /* translate '\t' to space */
else if (ch < ' ')
return; /* control character - exit */
if (n < sizeof(string) - 1)
string[n++] = ch;
}
}
string[n] = '\0';
if ((ch = cmd_getc()) != '\\') {
return;
}
switch (arg) {
case 'l':
xterm_seq(XTerm_title, (char *) string);
break;
case 'L':
xterm_seq(XTerm_iconName, (char *) string);
break;
case 'I':
set_icon_pixmap((char *) string, NULL);
break;
default:
break;
}
}
}
/* Process window manipulations */
void
process_window_mode(unsigned int nargs, int args[])
{
register unsigned int i;
int x, y;
Screen *scr;
Window dummy_child;
char buff[128], *name;
if (!nargs)
return;
scr = ScreenOfDisplay(Xdisplay, Xscreen);
if (!scr)
return;
for (i = 0; i < nargs; i++) {
if (args[i] == 14) {
int dummy_x, dummy_y;
unsigned int dummy_border, dummy_depth;
/* Store current width and height in x and y */
XGetGeometry(Xdisplay, TermWin.parent, &dummy_child, &dummy_x, &dummy_y, (unsigned int *) (&x), (unsigned int *) (&y), &dummy_border, &dummy_depth);
}
switch (args[i]) {
case 1:
XRaiseWindow(Xdisplay, TermWin.parent);
break;
case 2:
XIconifyWindow(Xdisplay, TermWin.parent, Xscreen);
break;
case 3:
if (i + 2 >= nargs)
return; /* Make sure there are 2 args left */
x = args[++i];
y = args[++i];
if (((unsigned int) x > (unsigned int) scr->width) || ((unsigned int) y > (unsigned int) scr->height))
return; /* Don't move off-screen */
XMoveWindow(Xdisplay, TermWin.parent, x, y);
break;
case 4:
if (i + 2 >= nargs)
return; /* Make sure there are 2 args left */
y = args[++i];
x = args[++i];
XResizeWindow(Xdisplay, TermWin.parent, x, y);
#ifdef USE_XIM
xim_set_status_position();
#endif
break;
case 5:
XRaiseWindow(Xdisplay, TermWin.parent);
break;
case 6:
XLowerWindow(Xdisplay, TermWin.parent);
break;
case 7:
XClearWindow(Xdisplay, TermWin.vt);
XSync(Xdisplay, False);
scr_touch();
scr_refresh(DEFAULT_REFRESH);
break;
case 8:
if (i + 2 >= nargs)
return; /* Make sure there are 2 args left */
y = args[++i];
x = args[++i];
XResizeWindow(Xdisplay, TermWin.parent,
Width2Pixel(x) + 2 * TermWin.internalBorder + (scrollbar_is_visible()? scrollbar_trough_width() : 0),
Height2Pixel(y) + 2 * TermWin.internalBorder);
break;
case 11:
break;
case 13:
XTranslateCoordinates(Xdisplay, TermWin.parent, Xroot, 0, 0, &x, &y, &dummy_child);
snprintf(buff, sizeof(buff), "\033[3;%d;%dt", x, y);
tt_write((unsigned char *) buff, strlen(buff));
break;
case 14:
snprintf(buff, sizeof(buff), "\033[4;%d;%dt", y, x);
tt_write((unsigned char *) buff, strlen(buff));
break;
case 18:
snprintf(buff, sizeof(buff), "\033[8;%d;%dt", TermWin.nrow, TermWin.ncol);
tt_write((unsigned char *) buff, strlen(buff));
break;
case 20:
XGetIconName(Xdisplay, TermWin.parent, &name);
snprintf(buff, sizeof(buff), "\033]L%s\033\\", name);
tt_write((unsigned char *) buff, strlen(buff));
XFree(name);
break;
case 21:
XFetchName(Xdisplay, TermWin.parent, &name);
snprintf(buff, sizeof(buff), "\033]l%s\033\\", name);
tt_write((unsigned char *) buff, strlen(buff));
XFree(name);
break;
default:
break;
}
}
}
/* process DEC private mode sequences `ESC [ ? Ps mode' */
/*
* mode can only have the following values:
* 'l' = low
* 'h' = high
* 's' = save
* 'r' = restore
* 't' = toggle
*/
void
process_terminal_mode(int mode, int priv, unsigned int nargs, int arg[])
{
unsigned int i;
int state;
if (nargs == 0)
return;
/* make lo/hi boolean */
switch (mode) {
case 'l':
mode = 0;
break;
case 'h':
mode = 1;
break;
}
switch (priv) {
case 0:
if (mode && mode != 1)
return; /* only do high/low */
for (i = 0; i < nargs; i++)
switch (arg[i]) {
case 4:
scr_insert_mode(mode);
break;
/* case 38: TEK mode */
}
break;
case '?':
for (i = 0; i < nargs; i++)
switch (arg[i]) {
case 1: /* application cursor keys */
PrivCases(PrivMode_aplCUR);
break;
/* case 2: - reset charsets to USASCII */
case 3: /* 80/132 */
PrivCases(PrivMode_132);
if (PrivateModes & PrivMode_132OK)
set_width(state ? 132 : 80);
break;
/* case 4: - smooth scrolling */
case 5: /* reverse video */
PrivCases(PrivMode_rVideo);
scr_rvideo_mode(state);
break;
case 6: /* relative/absolute origins */
PrivCases(PrivMode_relOrigin);
scr_relative_origin(state);
break;
case 7: /* autowrap */
PrivCases(PrivMode_Autowrap);
scr_autowrap(state);
break;
/* case 8: - auto repeat, can't do on a per window basis */
case 9: /* X10 mouse reporting */
PrivCases(PrivMode_MouseX10);
/* orthogonal */
if (PrivateModes & PrivMode_MouseX10)
PrivateModes &= ~(PrivMode_MouseX11);
break;
#ifdef scrollbar_esc
case scrollbar_esc:
PrivCases(PrivMode_scrollbar);
map_scrollbar(state);
break;
#endif
case 25: /* visible/invisible cursor */
PrivCases(PrivMode_VisibleCursor);
scr_cursor_visible(state);
break;
case 35:
PrivCases(PrivMode_ShiftKeys);
break;
case 40: /* 80 <--> 132 mode */
PrivCases(PrivMode_132OK);
break;
case 47: /* secondary screen */
PrivCases(PrivMode_Screen);
scr_change_screen(state);
break;
case 66: /* application key pad */
PrivCases(PrivMode_aplKP);
break;
case 67:
PrivCases(PrivMode_BackSpace);
break;
case 1000: /* X11 mouse reporting */
PrivCases(PrivMode_MouseX11);
/* orthogonal */
if (PrivateModes & PrivMode_MouseX11)
PrivateModes &= ~(PrivMode_MouseX10);
break;
#if 0
case 1001:
break; /* X11 mouse highlighting */
#endif
case 1010: /* Scroll to bottom on TTY output */
if (Options & Opt_homeOnEcho)
Options &= ~Opt_homeOnEcho;
else
Options |= Opt_homeOnEcho;
break;
case 1011: /* scroll to bottom on refresh */
if (Options & Opt_homeOnRefresh)
Options &= ~Opt_homeOnRefresh;
else
Options |= Opt_homeOnRefresh;
break;
case 1012: /* Scroll to bottom on TTY input */
if (Options & Opt_homeOnInput)
Options &= ~Opt_homeOnInput;
else
Options |= Opt_homeOnInput;
break;
}
break;
}
}
/* process sgr sequences */
void
process_sgr_mode(unsigned int nargs, int arg[])
{
unsigned int i;
if (nargs == 0) {
scr_rendition(0, ~RS_None);
return;
}
for (i = 0; i < nargs; i++)
switch (arg[i]) {
case 0:
scr_rendition(0, ~RS_None);
break;
case 1:
scr_rendition(1, RS_Bold);
break;
case 4:
scr_rendition(1, RS_Uline);
break;
case 5:
scr_rendition(1, RS_Blink);
break;
case 7:
scr_rendition(1, RS_RVid);
break;
case 22:
scr_rendition(0, RS_Bold);
break;
case 24:
scr_rendition(0, RS_Uline);
break;
case 25:
scr_rendition(0, RS_Blink);
break;
case 27:
scr_rendition(0, RS_RVid);
break;
case 30:
case 31: /* set fg color */
case 32:
case 33:
case 34:
case 35:
case 36:
case 37:
scr_color(minColor + (arg[i] - 30), RS_Bold);
break;
case 39: /* default fg */
scr_color(restoreFG, RS_Bold);
break;
case 40:
case 41: /* set bg color */
case 42:
case 43:
case 44:
case 45:
case 46:
case 47:
scr_color(minColor + (arg[i] - 40), RS_Blink);
break;
case 49: /* default bg */
scr_color(restoreBG, RS_Blink);
break;
}
}
/* color aliases, fg/bg bright-bold */
void
color_aliases(int idx)
{
if (rs_color[idx] && isdigit(*rs_color[idx])) {
int i = atoi(rs_color[idx]);
if (i >= 8 && i <= 15) { /* bright colors */
i -= 8;
#ifndef NO_BRIGHTCOLOR
rs_color[idx] = rs_color[minBright + i];
return;
#endif
}
if (i >= 0 && i <= 7) /* normal colors */
rs_color[idx] = rs_color[minColor + i];
}
}
/* find if fg/bg matches any of the normal (low-intensity) colors */
#ifndef NO_BRIGHTCOLOR
void
set_colorfgbg(void)
{
unsigned int i;
static char *colorfgbg_env = NULL;
char *p;
int fg = -1, bg = -1;
if (!colorfgbg_env) {
colorfgbg_env = (char *) malloc(30);
strcpy(colorfgbg_env, "COLORFGBG=default;default;bg");
}
for (i = BlackColor; i <= WhiteColor; i++) {
if (PixColors[fgColor] == PixColors[i]) {
fg = (i - BlackColor);
break;
}
}
for (i = BlackColor; i <= WhiteColor; i++) {
if (PixColors[bgColor] == PixColors[i]) {
bg = (i - BlackColor);
break;
}
}
p = strchr(colorfgbg_env, '=');
p++;
if (fg >= 0)
sprintf(p, "%d;", fg);
else
strcpy(p, "default;");
p = strchr(p, '\0');
if (bg >= 0)
sprintf(p,
# ifdef PIXMAP_SUPPORT
"default;"
# endif
"%d", bg);
else
strcpy(p, "default");
putenv(colorfgbg_env);
colorfgbg = DEFAULT_RSTYLE;
for (i = minColor; i <= maxColor; i++) {
if (PixColors[fgColor] == PixColors[i]
# ifndef NO_BOLDUNDERLINE
&& PixColors[fgColor] == PixColors[colorBD]
# endif /* NO_BOLDUNDERLINE */
/* if we wanted boldFont to have precedence */
# if 0 /* ifndef NO_BOLDFONT */
&& TermWin.boldFont == NULL
# endif /* NO_BOLDFONT */
)
colorfgbg = SET_FGCOLOR(colorfgbg, i);
if (PixColors[bgColor] == PixColors[i])
colorfgbg = SET_BGCOLOR(colorfgbg, i);
}
}
#endif /* NO_BRIGHTCOLOR */
#ifdef SMART_WINDOW_TITLE
static void
set_title(const char *str)
{
char *name;
if (!str) str = APL_NAME "-" VERSION;
if (XFetchName(Xdisplay, TermWin.parent, &name) == 0) {
D_X11(("set_title(): XFetchName() failed.\n"));
name = NULL;
}
if (name == NULL || strcmp(name, str)) {
D_X11(("set_title(): Setting window title to \"%s\"\n", str));
XStoreName(Xdisplay, TermWin.parent, str);
#if DEBUG >= DEBUG_X11
if (debug_level >= DEBUG_X11) {
if (name) XFree(name);
if (XFetchName(Xdisplay, TermWin.parent, &name) == 0) {
print_error("set_title(): Unable to set the window title to \"%s\"! What the heck is going on?!\n");
} else if (!name || strcmp(name, str)) {
print_error("set_title(): Window title still says \"%s\" after being set to \"%s\". I am a confused Eterm. :(\n", NONULL(name), str);
} else {
D_X11(("set_title(): Succeeded.\n"));
}
}
#endif
}
if (name) XFree(name);
}
static void
set_icon_name(const char *str)
{
char *name;
if (!str) str = APL_NAME "-" VERSION;
if (XGetIconName(Xdisplay, TermWin.parent, &name) == 0) {
D_X11(("set_icon_name(): XGetIconName() failed.\n"));
name = NULL;
}
if (name == NULL || strcmp(name, str)) {
D_X11(("set_icon_name(): Setting window icon name to \"%s\"\n", str));
XSetIconName(Xdisplay, TermWin.parent, str);
#if DEBUG >= DEBUG_X11
if (debug_level >= DEBUG_X11) {
if (name) XFree(name);
if (XGetIconName(Xdisplay, TermWin.parent, &name) == 0) {
print_error("set_icon_name(): Unable to set the window icon name to \"%s\"! What the heck is going on?!\n");
} else if (!name || strcmp(name, str)) {
print_error("set_icon_name(): Window icon name still says \"%s\" after being set to \"%s\". I am a confused Eterm. :(\n", NONULL(name), str);
} else {
D_X11(("set_icon_name(): Succeeded.\n"));
}
}
#endif
}
if (name) XFree(name);
}
#endif
/*
* XTerm escape sequences: ESC ] Ps;Pt BEL
* 0 = change iconName/title
* 1 = change iconName
* 2 = change title
* 46 = change logfile (not implemented)
* 50 = change font
*
* rxvt/Eterm extensions:
* 5 = Hostile takeover (grab focus and raise)
* 6 = Transparency mode stuff
* 10 = menu
* 20 = bg pixmap
* 39 = change default fg color
* 49 = change default bg color
*/
void
xterm_seq(int op, const char *str)
{
XColor xcol;
char *nstr, *tnstr, *orig_tnstr, *valptr;
unsigned char eterm_seq_op, which = 0;
#ifdef PIXMAP_SUPPORT
unsigned char changed = 0, scaled = 0;
char *color, *mod;
#endif
if (!str)
return;
#ifdef PIXMAP_SUPPORT
orig_tnstr = tnstr = StrDup(str);
#endif
switch (op) {
case XTerm_title:
set_title(str);
break;
case XTerm_prop:
if ((nstr = (char *) strsep(&tnstr, ";")) == NULL) {
break;
}
if ((valptr = strchr(nstr, '=')) != NULL) {
*(valptr++) = 0;
}
set_text_property(TermWin.parent, nstr, valptr);
break;
case XTerm_name:
set_title(str); /* drop */
case XTerm_iconName:
set_icon_name(str);
break;
case XTerm_Takeover:
XSetInputFocus(Xdisplay, TermWin.parent, RevertToParent, CurrentTime);
XRaiseWindow(Xdisplay, TermWin.parent);
break;
case XTerm_EtermSeq:
/* Eterm proprietary escape sequences
Syntax: ESC ] 6 ; <op> ; <arg> BEL
where <op> is: 0 Set/toggle transparency
1 Set color modifiers
3 Force update of pseudo-transparent background
10 Set scrollbar type/width
11 Set/toggle right-side scrollbar
12 Set/toggle floating scrollbar
13 Set/toggle popup scrollbar
20 Set/toggle visual bell
21 Set/toggle map alert
22 Set/toggle xterm selection behavior
23 Set/toggle triple-click line selection
24 Set/toggle viewport mode
25 Set/toggle selection of trailing spaces
30 Do not use
40 Do not use
50 Move window to another desktop
70 Exit Eterm
71 Save current configuration to a file
and <arg> is an optional argument, depending
on the particular sequence being used. It
(along with its preceeding semicolon) may or
may not be needed.
*/
D_CMD(("Got XTerm_EtermSeq sequence\n"));
nstr = (char *) strsep(&tnstr, ";");
eterm_seq_op = (unsigned char) strtol(nstr, (char **) NULL, 10);
D_CMD((" XTerm_EtermSeq operation is %d\n", eterm_seq_op));
/* Yes, there is order to the numbers for this stuff. And here it is:
0-9 Transparency Configuration
10-14 Scrollbar Configuration
15-19 Menu Configuration
20-29 Miscellaneous Toggles
30-39 Foreground/Text Color Configuration
40-49 Background Color Configuration
50-69 Window/Window Manager Configuration/Interaction
70-79 Internal Eterm Operations
*/
switch (eterm_seq_op) {
#ifdef PIXMAP_OFFSET
case 0:
nstr = (char *) strsep(&tnstr, ";");
if (nstr) {
if (BOOL_OPT_ISTRUE(nstr)) {
D_CMD((" Request to enable transparency.\n"));
FOREACH_IMAGE(if (!image_mode_is(idx, MODE_TRANS) && image_mode_is(idx, ALLOW_TRANS)) { \
image_set_mode(idx, MODE_TRANS); \
if (images[idx].current->pmap->pixmap != None) { \
Imlib_free_pixmap(imlib_id, images[idx].current->pmap->pixmap); \
} \
images[idx].current->pmap->pixmap = None; \
});
} else if (BOOL_OPT_ISFALSE(nstr)) {
D_CMD((" Request to disable transparency.\n"));
FOREACH_IMAGE(if (image_mode_is(idx, MODE_TRANS)) {if (image_mode_is(idx, ALLOW_IMAGE)) {image_set_mode(idx, MODE_IMAGE);} else {image_set_mode(idx, MODE_SOLID);}});
} else {
D_CMD((" Bad boolean value in transparency request.\n"));
break;
}
} else {
D_CMD((" Request to toggle transparency.\n"));
FOREACH_IMAGE(if (!image_mode_is(idx, MODE_TRANS) && image_mode_is(idx, ALLOW_TRANS)) { \
image_set_mode(idx, MODE_TRANS); \
if (images[idx].current->pmap->pixmap != None) { \
Imlib_free_pixmap(imlib_id, images[idx].current->pmap->pixmap); \
} \
images[idx].current->pmap->pixmap = None; \
} else if (image_mode_is(idx, MODE_TRANS)) {if (image_mode_is(idx, ALLOW_IMAGE)) {image_set_mode(idx, MODE_IMAGE);} else {image_set_mode(idx, MODE_SOLID);}});
}
redraw_all_images();
break;
case 1:
changed = 0;
for (; 1;) {
if ((color = (char *) strsep(&tnstr, ";")) == NULL) {
break;
}
if ((strlen(color) == 2) || (!strcasecmp(color, "down"))) {
/* They specified an image index */
if (!strcasecmp(color, "bg")) {
which = image_bg;
} else if (!strcasecmp(color, "sb")) {
which = image_sb;
} else if (!strcasecmp(color, "sa")) {
which = image_sa;
} else if (!strcasecmp(color, "up")) {
which = image_up;
} else if (!strcasecmp(color, "down")) {
which = image_down;
} else {
break;
}
if ((color = (char *) strsep(&tnstr, ";")) == NULL) {
break;
}
} else {
which = image_bg;
}
if ((mod = (char *) strsep(&tnstr, ";")) == NULL) {
break;
}
if (!strcasecmp(mod, "clear")) {
imlib_t *iml = images[which].current->iml;
if (!strcasecmp(color, "image")) {
FREE(iml->mod);
} else if (!strcasecmp(color, "red")) {
FREE(iml->rmod);
} else if (!strcasecmp(color, "green")) {
FREE(iml->gmod);
} else if (!strcasecmp(color, "blue")) {
FREE(iml->bmod);
}
changed = 1;
continue;
}
if ((valptr = (char *) strsep(&tnstr, ";")) == NULL) {
break;
}
D_CMD(("Modifying the %s attribute of the %s color modifier of the %s image to be %s\n", mod, color, get_image_type(which), valptr));
changed = 1;
if (image_mode_is(which, MODE_TRANS) && (desktop_pixmap != None)) {
free_desktop_pixmap();
}
if (image_mode_is(which, MODE_VIEWPORT) && (viewport_pixmap != None)) {
XFreePixmap(Xdisplay, viewport_pixmap);
viewport_pixmap = None; /* Force the re-read */
}
if (!strcasecmp(color, "image")) {
imlib_t *iml = images[which].current->iml;
if (iml->mod == NULL) {
iml->mod = (ImlibColorModifier *) MALLOC(sizeof(ImlibColorModifier));
iml->mod->brightness = iml->mod->contrast = iml->mod->gamma = 0xff;
}
if (!BEG_STRCASECMP("brightness", mod)) {
iml->mod->brightness = (int) strtol(valptr, (char **) NULL, 0);
} else if (!BEG_STRCASECMP("contrast", mod)) {
iml->mod->contrast = (int) strtol(valptr, (char **) NULL, 0);
} else if (!BEG_STRCASECMP("gamma", mod)) {
iml->mod->gamma = (int) strtol(valptr, (char **) NULL, 0);
}
} else if (!strcasecmp(color, "red")) {
imlib_t *iml = images[which].current->iml;
if (iml->rmod == NULL) {
iml->rmod = (ImlibColorModifier *) MALLOC(sizeof(ImlibColorModifier));
iml->rmod->brightness = iml->rmod->contrast = iml->rmod->gamma = 0xff;
}
if (!BEG_STRCASECMP("brightness", mod)) {
iml->rmod->brightness = (int) strtol(valptr, (char **) NULL, 0);
} else if (!BEG_STRCASECMP("contrast", mod)) {
iml->rmod->contrast = (int) strtol(valptr, (char **) NULL, 0);
} else if (!BEG_STRCASECMP("gamma", mod)) {
iml->rmod->gamma = (int) strtol(valptr, (char **) NULL, 0);
}
} else if (!strcasecmp(color, "green")) {
imlib_t *iml = images[which].current->iml;
if (iml->gmod == NULL) {
iml->gmod = (ImlibColorModifier *) MALLOC(sizeof(ImlibColorModifier));
iml->gmod->brightness = iml->gmod->contrast = iml->gmod->gamma = 0xff;
}
if (!BEG_STRCASECMP("brightness", mod)) {
iml->gmod->brightness = (int) strtol(valptr, (char **) NULL, 0);
} else if (!BEG_STRCASECMP("contrast", mod)) {
iml->gmod->contrast = (int) strtol(valptr, (char **) NULL, 0);
} else if (!BEG_STRCASECMP("gamma", mod)) {
iml->gmod->gamma = (int) strtol(valptr, (char **) NULL, 0);
}
} else if (!strcasecmp(color, "blue")) {
imlib_t *iml = images[which].current->iml;
if (iml->bmod == NULL) {
iml->bmod = (ImlibColorModifier *) MALLOC(sizeof(ImlibColorModifier));
iml->bmod->brightness = iml->bmod->contrast = iml->bmod->gamma = 0xff;
}
if (!BEG_STRCASECMP("brightness", mod)) {
iml->bmod->brightness = (int) strtol(valptr, (char **) NULL, 0);
} else if (!BEG_STRCASECMP("contrast", mod)) {
iml->bmod->contrast = (int) strtol(valptr, (char **) NULL, 0);
} else if (!BEG_STRCASECMP("gamma", mod)) {
iml->bmod->gamma = (int) strtol(valptr, (char **) NULL, 0);
}
}
}
if (changed) {
redraw_all_images();
}
break;
case 3:
get_desktop_window();
if (desktop_window == None) {
FOREACH_IMAGE(if (image_mode_is(idx, MODE_TRANS)) {image_set_mode(idx, MODE_IMAGE); image_allow_mode(idx, ALLOW_IMAGE);});
break;
}
get_desktop_pixmap();
redraw_all_images();
break;
#endif
case 10:
nstr = (char *) strsep(&tnstr, ";");
if (nstr && *nstr) {
if (!strcasecmp(nstr, "xterm")) {
#ifdef XTERM_SCROLLBAR
scrollbar_change_type(SCROLLBAR_XTERM);
#else
print_error("Support for xterm scrollbars was not compiled in. Sorry.");
#endif
} else if (!strcasecmp(nstr, "next")) {
#ifdef NEXT_SCROLLBAR
scrollbar_change_type(SCROLLBAR_NEXT);
#else
print_error("Support for NeXT scrollbars was not compiled in. Sorry.");
#endif
} else if (!strcasecmp(nstr, "motif")) {
#ifdef MOTIF_SCROLLBAR
scrollbar_change_type(SCROLLBAR_MOTIF);
#else
print_error("Support for motif scrollbars was not compiled in. Sorry.");
#endif
} else {
print_error("Unrecognized scrollbar type \"%s\".", nstr);
}
}
nstr = (char *) strsep(&tnstr, ";");
if (nstr && *nstr) {
scrollbar_change_width((unsigned short) strtoul(nstr, (char **) NULL, 0));
}
break;
case 11:
nstr = (char *) strsep(&tnstr, ";");
OPT_SET_OR_TOGGLE(nstr, Options, Opt_scrollbar_right);
scr_touch();
parent_resize();
break;
case 12:
nstr = (char *) strsep(&tnstr, ";");
OPT_SET_OR_TOGGLE(nstr, Options, Opt_scrollbar_floating);
scrollbar_reposition_and_always_draw();
break;
case 13:
nstr = (char *) strsep(&tnstr, ";");
OPT_SET_OR_TOGGLE(nstr, Options, Opt_scrollbar_popup);
break;
case 20:
nstr = (char *) strsep(&tnstr, ";");
OPT_SET_OR_TOGGLE(nstr, Options, Opt_visualBell);
break;
#ifdef MAPALERT_OPTION
case 21:
nstr = (char *) strsep(&tnstr, ";");
OPT_SET_OR_TOGGLE(nstr, Options, Opt_mapAlert);
break;
#endif
case 22:
nstr = (char *) strsep(&tnstr, ";");
OPT_SET_OR_TOGGLE(nstr, Options, Opt_xterm_select);
break;
case 23:
nstr = (char *) strsep(&tnstr, ";");
OPT_SET_OR_TOGGLE(nstr, Options, Opt_select_whole_line);
break;
case 24:
nstr = (char *) strsep(&tnstr, ";");
FOREACH_IMAGE(if (!image_mode_is(idx, MODE_VIEWPORT) && image_mode_is(idx, ALLOW_VIEWPORT)) {image_set_mode(idx, MODE_VIEWPORT);});
redraw_all_images();
break;
case 25:
nstr = (char *) strsep(&tnstr, ";");
OPT_SET_OR_TOGGLE(nstr, Options, Opt_select_trailing_spaces);
break;
case 26:
nstr = (char *) strsep(&tnstr, ";");
OPT_SET_OR_TOGGLE(nstr, Options, Opt_report_as_keysyms);
break;
case 30:
nstr = (char *) strsep(&tnstr, ";");
if (nstr) {
if (XParseColor(Xdisplay, cmap, nstr, &xcol) && XAllocColor(Xdisplay, cmap, &xcol)) {
PixColors[fgColor] = xcol.pixel;
scr_refresh(DEFAULT_REFRESH);
}
}
break;
case 40:
nstr = (char *) strsep(&tnstr, ";");
if (nstr) {
if (XParseColor(Xdisplay, cmap, nstr, &xcol) && XAllocColor(Xdisplay, cmap, &xcol)) {
PixColors[bgColor] = xcol.pixel;
scr_refresh(DEFAULT_REFRESH);
}
}
break;
case 50:
/* Change desktops */
nstr = (char *) strsep(&tnstr, ";");
if (nstr && *nstr) {
XClientMessageEvent xev;
rs_desktop = (int) strtol(nstr, (char **) NULL, 0);
xev.type = ClientMessage;
xev.window = TermWin.parent;
xev.message_type = XInternAtom(Xdisplay, "_WIN_WORKSPACE", False);
xev.format = 32;
xev.data.l[0] = rs_desktop;
XChangeProperty(Xdisplay, TermWin.parent, xev.message_type, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) &rs_desktop, 1);
XSendEvent(Xdisplay, Xroot, False, SubstructureNotifyMask, (XEvent *) & xev);
}
break;
case 70:
/* Exit Eterm */
exit(0);
break;
case 71:
/* Save current config */
nstr = (char *) strsep(&tnstr, ";");
if (nstr && *nstr) {
save_config(nstr);
} else {
save_config(NULL);
}
break;
case 80:
/* Set debugging level */
nstr = (char *) strsep(&tnstr, ";");
if (nstr && *nstr) {
debug_level = (unsigned int) strtoul(nstr, (char **) NULL, 0);
}
break;
default:
break;
}
break;
case XTerm_Pixmap:
#ifdef PIXMAP_SUPPORT
FOREACH_IMAGE(if (!image_mode_is(idx, MODE_IMAGE) && image_mode_is(idx, ALLOW_IMAGE)) {image_set_mode(idx, MODE_IMAGE);});
if (!strcmp(str, ";")) {
load_image("", image_bg);
bg_needs_update = 1;
} else {
nstr = (char *) strsep(&tnstr, ";");
if (nstr) {
if (*nstr) {
set_pixmap_scale("", images[image_bg].current->pmap);
bg_needs_update = 1;
load_image(nstr, image_bg);
}
while ((nstr = (char *) strsep(&tnstr, ";")) && *nstr) {
changed += set_pixmap_scale(nstr, images[image_bg].current->pmap);
scaled = 1;
}
} else {
load_image("", image_bg);
bg_needs_update = 1;
}
}
if ((changed) || (bg_needs_update)) {
redraw_image(image_bg);
}
#endif /* PIXMAP_SUPPORT */
break;
case XTerm_EtermIPC:
for (; (nstr = (char *) strsep(&tnstr, ";"));) {
eterm_ipc_parse(nstr);
}
break;
case XTerm_restoreFG:
#ifdef XTERM_COLOR_CHANGE
set_window_color(fgColor, str);
#endif
break;
case XTerm_restoreBG:
#ifdef XTERM_COLOR_CHANGE
set_window_color(bgColor, str);
#endif
break;
case XTerm_logfile:
break;
case XTerm_font:
change_font(0, str);
break;
#ifdef ETERM_COMMAND_MODE
case ETerm_command_mode:
fprintf(stderr, "ETerm_command_mode\n");
break;
#endif
default:
D_CMD(("Unsupported xterm escape sequence operator: 0x%02x\n", op));
break;
}
#ifdef PIXMAP_SUPPORT
FREE(orig_tnstr);
#endif
}