summaryrefslogtreecommitdiff
path: root/app/xterm/misc.c
diff options
context:
space:
mode:
Diffstat (limited to 'app/xterm/misc.c')
-rw-r--r--app/xterm/misc.c452
1 files changed, 388 insertions, 64 deletions
diff --git a/app/xterm/misc.c b/app/xterm/misc.c
index 5d5b0f2cb..e3397261a 100644
--- a/app/xterm/misc.c
+++ b/app/xterm/misc.c
@@ -1,7 +1,7 @@
-/* $XTermId: misc.c,v 1.1044 2023/01/07 01:11:16 tom Exp $ */
+/* $XTermId: misc.c,v 1.1094 2024/06/26 08:05:39 tom Exp $ */
/*
- * Copyright 1999-2022,2023 by Thomas E. Dickey
+ * Copyright 1999-2023,2024 by Thomas E. Dickey
*
* All Rights Reserved
*
@@ -138,8 +138,6 @@
static Boolean xtermAllocColor(XtermWidget, XColor *, const char *);
static Cursor make_hidden_cursor(XtermWidget);
-static char emptyString[] = "";
-
#if OPT_EXEC_XTERM
/* Like readlink(2), but returns a malloc()ed buffer, or NULL on
error; adapted from libc docs */
@@ -308,14 +306,9 @@ do_xevents(XtermWidget xw)
TScreen *screen = TScreenOf(xw);
if (xtermAppPending()
- ||
-#if defined(VMS) || defined(__VMS)
- screen->display->qlen > 0
-#else
- GetBytesAvailable(ConnectionNumber(screen->display)) > 0
-#endif
- )
+ || GetBytesAvailable(screen->display) > 0) {
xevents(xw);
+ }
}
void
@@ -1346,7 +1339,7 @@ AtomBell(XtermWidget xw, int which)
for (n = 0; n < XtNumber(table); ++n) {
if (table[n].value == which) {
- result = XInternAtom(XtDisplay(xw), table[n].name, False);
+ result = CachedInternAtom(XtDisplay(xw), table[n].name);
break;
}
}
@@ -1780,10 +1773,11 @@ xtermDeiconify(XtermWidget xw)
Display *dpy = screen->display;
Window target = VShellWindow(xw);
XEvent e;
- Atom atom_state = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False);
+ Atom atom_state = CachedInternAtom(dpy, "_NET_ACTIVE_WINDOW");
if (xtermIsIconified(xw)) {
TRACE(("...de-iconify window %#lx\n", target));
+ ResetHiddenHint(xw);
XMapWindow(dpy, target);
memset(&e, 0, sizeof(e));
@@ -1833,8 +1827,8 @@ xtermIsIconified(XtermWidget xw)
unsigned char *prop_return = 0;
long long_length = 1024;
Atom requested_type = XA_ATOM;
- Atom is_hidden = XInternAtom(dpy, "_NET_WM_STATE_HIDDEN", False);
- Atom wm_state = XInternAtom(dpy, "_NET_WM_STATE", False);
+ Atom is_hidden = CachedInternAtom(dpy, "_NET_WM_STATE_HIDDEN");
+ Atom wm_state = CachedInternAtom(dpy, "_NET_WM_STATE");
/* this works with non-EWMH */
result = (win_attrs.map_state != IsViewable) ? True : False;
@@ -2484,9 +2478,11 @@ GenerateLogPath(void)
}
}
#else
- static const char log_def_name[] = "XtermLog.XXXXXX";
- if ((log_default = x_strdup(log_def_name)) != NULL) {
- MakeTemp(log_default);
+ {
+ static const char log_def_name[] = "XtermLog.XXXXXX";
+ if ((log_default = x_strdup(log_def_name)) != NULL) {
+ MakeTemp(log_default);
+ }
}
#endif
@@ -3482,7 +3478,7 @@ xtermIsPrintable(XtermWidget xw, Char **bufp, Char *last)
PtyData data;
if (decodeUtf8(screen, fakePtyData(&data, cp, last))) {
- if (data.utf_data != UCS_REPL
+ if (!is_UCS_SPECIAL(data.utf_data)
&& (data.utf_data >= 128 ||
ansi_table[data.utf_data] == CASE_PRINT)) {
next += (data.utf_size - 1);
@@ -4462,7 +4458,7 @@ parse_decudk(XtermWidget xw, const char *cp)
* Parse numeric parameters. Normally we use a state machine to simplify
* interspersing with control characters, but have the string already.
*/
-static void
+void
parse_ansi_params(ANSI *params, const char **string)
{
const char *cp = *string;
@@ -4615,7 +4611,6 @@ parse_decdld(ANSI *params, const char *string)
#define parse_decdld(p,q) /* nothing */
#endif
-#if OPT_DEC_RECTOPS
static const char *
skip_params(const char *cp)
{
@@ -4624,9 +4619,11 @@ skip_params(const char *cp)
return cp;
}
+#if OPT_MOD_FKEYS || OPT_DEC_RECTOPS || (OPT_VT525_COLORS && OPT_ISO_COLORS)
static int
parse_int_param(const char **cp)
{
+ Boolean found = False;
int result = 0;
const char *s = *cp;
while (*s != '\0') {
@@ -4635,15 +4632,18 @@ parse_int_param(const char **cp)
break;
} else if (*s >= '0' && *s <= '9') {
result = (result * 10) + (*s++ - '0');
+ found = True;
} else {
s += strlen(s);
}
}
- TRACE(("parse-int %s ->%d, %#x->%s\n", *cp, result, result, s));
+ TRACE(("parse-int \"%s\" ->%d, %#x->\"%s\"\n", *cp, result, result, s));
*cp = s;
- return result;
+ return found ? result : -1;
}
+#endif
+#if OPT_DEC_RECTOPS
static int
parse_chr_param(const char **cp)
{
@@ -4658,11 +4658,17 @@ parse_chr_param(const char **cp)
}
}
}
- TRACE(("parse-chr %s ->%d, %#x->%s\n", *cp, result, result, s));
+ TRACE(("parse-chr %s ->%#x, %#x->%s\n", *cp, result, result, s));
*cp = s;
return result;
}
+#if OPT_TRACE
+#define done_DECCIR() do { TRACE(("...quit DECCIR @%d\n", __LINE__)); return; } while(0)
+#else
+#define done_DECCIR() return
+#endif
+
static void
restore_DECCIR(XtermWidget xw, const char *cp)
{
@@ -4671,22 +4677,33 @@ restore_DECCIR(XtermWidget xw, const char *cp)
/* row */
if ((value = parse_int_param(&cp)) <= 0 || value > MaxRows(screen))
- return;
+ done_DECCIR();
screen->cur_row = (value - 1);
/* column */
if ((value = parse_int_param(&cp)) <= 0 || value > MaxCols(screen))
- return;
+ done_DECCIR();
screen->cur_col = (value - 1);
/* page */
if (parse_int_param(&cp) != 1)
- return;
+ done_DECCIR();
/* rendition */
- if (((value = parse_chr_param(&cp)) & 0xf0) != 0x40)
- return;
+ if (((value = parse_chr_param(&cp)) & 0xf0) != 0x40) {
+ if (value & 0x10) {
+ /*
+ * VT420 is documented for bit 5 always reset; VT520/VT525 are not
+ * documented, but do use the bit for setting invisible mode.
+ */
+ if (screen->vtXX_level <= 4)
+ done_DECCIR();
+ } else if (!(value & 0x40)) {
+ done_DECCIR();
+ }
+ }
UIntClr(xw->flags, (INVERSE | BLINK | UNDERLINE | BOLD));
+ xw->flags |= (value & 16) ? INVISIBLE : 0;
xw->flags |= (value & 8) ? INVERSE : 0;
xw->flags |= (value & 4) ? BLINK : 0;
xw->flags |= (value & 2) ? UNDERLINE : 0;
@@ -4694,38 +4711,39 @@ restore_DECCIR(XtermWidget xw, const char *cp)
/* attributes */
if (((value = parse_chr_param(&cp)) & 0xfe) != 0x40)
- return;
+ done_DECCIR();
screen->protected_mode &= ~DEC_PROTECT;
screen->protected_mode |= (value & 1) ? DEC_PROTECT : 0;
/* flags */
if (((value = parse_chr_param(&cp)) & 0xf0) != 0x40)
- return;
+ done_DECCIR();
screen->do_wrap = (value & 8) ? True : False;
screen->curss = (Char) ((value & 4) ? 3 : ((value & 2) ? 2 : 0));
UIntClr(xw->flags, ORIGIN);
xw->flags |= (value & 1) ? ORIGIN : 0;
if ((value = (parse_chr_param(&cp) - '0')) < 0 || value >= NUM_GSETS)
- return;
+ done_DECCIR();
screen->curgl = (Char) value;
if ((value = (parse_chr_param(&cp) - '0')) < 0 || value >= NUM_GSETS)
- return;
+ done_DECCIR();
screen->curgr = (Char) value;
/* character-set size */
- if (parse_chr_param(&cp) != 0x4f) /* works for xterm */
- return;
+ if (parse_chr_param(&cp) == 0xffff) /* FIXME: limit SCS? */
+ done_DECCIR();
/* SCS designators */
for (value = 0; value < NUM_GSETS; ++value) {
- if (*cp == '%') {
- xtermDecodeSCS(xw, value, 0, '%', *++cp);
- } else if (*cp != '\0') {
- xtermDecodeSCS(xw, value, 0, '\0', *cp);
+ if (*cp == '\0') {
+ done_DECCIR();
+ } else if (strchr("%&\"", *cp) != NULL) {
+ int prefix = *cp++;
+ xtermDecodeSCS(xw, value, 0, prefix, *cp);
} else {
- return;
+ xtermDecodeSCS(xw, value, 0, '\0', *cp);
}
cp++;
}
@@ -4747,10 +4765,8 @@ restore_DECTABSR(XtermWidget xw, const char *cp)
--stop;
if (OkTAB(stop)) {
TabSet(xw->tabs, stop);
- stop = 0;
- } else {
- fail = True;
}
+ stop = 0;
} else {
fail = True;
}
@@ -4762,7 +4778,116 @@ restore_DECTABSR(XtermWidget xw, const char *cp)
TRACE(("...done DECTABSR\n"));
}
-#endif
+#endif /* OPT_DEC_RECTOPS */
+
+/*
+ * VT510 and VT520 reference manual have the same explanation for Pn (params),
+ * but it does not agree with the possible values for Dscs because it refers
+ * to "ISO Latin-7" (ISO 8859-13 aka "Baltic Rim"), and omits ISO Greek
+ * (ISO 8859-7):
+ *
+ * ------------------------------------------------------------------------
+ * Pn Meaning
+ * ------------------------------------------------------------------------
+ * 0 DEC, ISO Latin-1, ISO Latin-2
+ * 1 ISO Latin-5, ISO Latin-7, ISO Cyrillic, ISO Hebrew
+ * ------------------------------------------------------------------------
+ *
+ * versus
+ *
+ * ------------------------------------------------------------------------
+ * Dscs Character Set
+ * ------------------------------------------------------------------------
+ * %5 DEC Supplemental
+ * "? DEC Greek
+ * "4 DEC Hebrew
+ * %0 DEC Turkish
+ * &4 DEC Cyrillic
+ * < User-preferred Supplemental
+ * A ISO Latin-1 Supplemental
+ * B ISO Latin-2 Supplemental
+ * F ISO Greek Supplemental
+ * H ISO Hebrew Supplemental
+ * M ISO Latin-5 Supplemental
+ * L ISO Latin-Cyrillic
+ * ------------------------------------------------------------------------
+ *
+ * DEC 070, page 5-123 explains that Pn ("Ps" in the text) selects 94 or 96
+ * character sets (0 or 1, respectively), and on the next page states that
+ * the valid combinations are 0 (DEC Supplemental) and 1 (ISO Latin-1
+ * supplemental). The document comments in regard to LS0 that (applications)
+ * should not assume that they can use 96-character sets for G0, but that it
+ * is possible to do this using UPSS.
+ *
+ * The VT510/VT520 reference manuals under SCS Select Character Set show
+ * a list of 94- and 96-character sets with "DEC" and "NRCS" as 94-characters,
+ * and the "ISO" as 96-characters. A few 94-character sets are added, based
+ * on testing VT520/VT525 that shows that DEC Special Graphics also is allowed.
+ */
+static Bool
+decode_upss(XtermWidget xw, const char *cp, char psarg, DECNRCM_codes * upss)
+{
+ /* *INDENT-OFF* */
+ static const struct {
+ DECNRCM_codes code;
+ int params; /* 0 for 94-characters, 1 for 96-characters */
+ int prefix;
+ int suffix;
+ int min_level;
+ int max_level;
+ } upss_table[] = {
+ { DFT_UPSS, 0, '%', '5', 3, 9 },
+ { nrc_ASCII, 0, 0, 'A', 1, 9 }, /* undocumented */
+ { nrc_DEC_Spec_Graphic, 0, 0, '0', 1, 9 }, /* undocumented */
+ { nrc_DEC_Technical, 0, 0, '>', 3, 9 }, /* undocumented */
+ { nrc_DEC_Greek_Supp, 0, '"', '?', 5, 9 },
+ { nrc_DEC_Hebrew_Supp, 0, '"', '4', 5, 9 },
+ { nrc_DEC_Turkish_Supp, 0, '%', '0', 5, 9 },
+ { nrc_DEC_Cyrillic, 0, '&', '4', 5, 9 },
+ { ALT_UPSS, 1, 0, 'A', 3, 9 },
+ { nrc_ISO_Latin_2_Supp, 1, 0, 'B', 5, 9 },
+ { nrc_ISO_Greek_Supp, 1, 0, 'F', 5, 9 },
+ { nrc_ISO_Hebrew_Supp, 1, 0, 'H', 5, 9 },
+ { nrc_ISO_Latin_5_Supp, 1, 0, 'M', 5, 9 },
+ { nrc_ISO_Latin_Cyrillic, 1, 0, 'L', 5, 9 },
+ };
+ /* *INDENT-ON* */
+ TScreen *screen = TScreenOf(xw);
+ Bool result = False;
+
+ *upss = nrc_ASCII;
+ if (screen->vtXX_level >= 3) {
+ Cardinal n;
+ for (n = 0; n < XtNumber(upss_table); ++n) {
+ if (((int) psarg - '0') != upss_table[n].params)
+ continue;
+
+ if (cp[1] == '\0') {
+ if (upss_table[n].suffix != cp[0])
+ continue;
+ } else if (cp[2] == '\0') {
+ if (upss_table[n].prefix != cp[0])
+ continue;
+ if (upss_table[n].suffix != cp[1])
+ continue;
+ } else {
+ continue;
+ }
+
+ result = True;
+ *upss = upss_table[n].code;
+ if (*upss == DFT_UPSS) {
+ TRACE(("DECAUPSS (default)\n"));
+ } else if (*upss == ALT_UPSS) {
+ TRACE(("DECAUPSS (alternate)\n"));
+ }
+ break;
+ }
+ TRACE(("DECAUPSS %ssuccessful %s\n",
+ result ? "" : "not ", visibleScsCode(*upss)));
+ }
+ return result;
+}
void
do_dcs(XtermWidget xw, Char *dcsbuf, size_t dcslen)
@@ -4772,8 +4897,12 @@ do_dcs(XtermWidget xw, Char *dcsbuf, size_t dcslen)
const char *cp = (const char *) dcsbuf;
Bool okay;
ANSI params;
-#if OPT_DEC_RECTOPS
char psarg = '0';
+#if OPT_VT525_COLORS && OPT_ISO_COLORS
+ const char *cp2;
+#endif
+#if (OPT_VT525_COLORS && OPT_ISO_COLORS) || OPT_MOD_FKEYS
+ int ival;
#endif
TRACE(("do_dcs(%s:%lu)\n", (char *) dcsbuf, (unsigned long) dcslen));
@@ -4864,12 +4993,79 @@ do_dcs(XtermWidget xw, Char *dcsbuf, size_t dcslen)
cp);
} else
#endif
+#if OPT_DEC_RECTOPS
+ if (!strcmp(cp, "*x")) { /* DECSACE */
+ TRACE(("reply DECSACE\n"));
+ sprintf(reply, "%d%s",
+ screen->cur_decsace,
+ cp);
+ } else
+#endif
if (!strcmp(cp, "*|")) { /* DECSNLS */
TRACE(("reply DECSNLS\n"));
sprintf(reply, "%d%s",
screen->max_row + 1,
cp);
- } else {
+ } else
+#if OPT_VT525_COLORS && OPT_ISO_COLORS
+ if (screen->terminal_id == 525
+ && !strcmp((cp2 = skip_params(cp)), ",}")) { /* DECATC */
+ ival = parse_int_param(&cp);
+ TRACE(("reply DECATC:%s\n", cp));
+ if (ival >= 0 && ival < 16 && *cp2 == ',') {
+ sprintf(reply, "%d;%d;%d%s", ival,
+ screen->alt_colors[ival].fg,
+ screen->alt_colors[ival].bg,
+ cp2);
+ } else {
+ okay = False;
+ }
+ } else if (screen->terminal_id == 525
+ && !strcmp((cp2 = skip_params(cp)), ",|")) { /* DECAC */
+ ival = parse_int_param(&cp);
+ TRACE(("reply DECAC\n"));
+ switch (ival) {
+ case 1: /* normal text */
+ sprintf(reply, "%d,%d%s",
+ screen->assigned_fg,
+ screen->assigned_bg,
+ cp2);
+ break;
+ case 2: /* window frame (not implemented) */
+ /* FALLTHRU */
+ default:
+ okay = False;
+ break;
+ }
+ } else
+#endif
+#if OPT_MOD_FKEYS
+ if (*cp == '>' && !strcmp(skip_params(1 + cp), "m")) { /* XTQMODKEYS */
+ ++cp;
+ okay = True;
+ ival = parse_int_param(&cp);
+#define GET_MOD_FKEYS(field) xw->keyboard.modify_now.field
+#define FMT_MOD_FKEYS(field) sprintf(reply, ">%d;%dm", ival, GET_MOD_FKEYS(field))
+ switch (ival) {
+ case 0:
+ FMT_MOD_FKEYS(allow_keys);
+ break;
+ case 1:
+ FMT_MOD_FKEYS(cursor_keys);
+ break;
+ case 2:
+ FMT_MOD_FKEYS(function_keys);
+ break;
+ case 4:
+ FMT_MOD_FKEYS(other_keys);
+ break;
+ default:
+ okay = False;
+ break;
+ }
+ } else
+#endif
+ {
okay = False;
}
@@ -4935,7 +5131,7 @@ do_dcs(XtermWidget xw, Char *dcsbuf, size_t dcslen)
unparseputn(xw, xw->rgb_widths[0]);
} else {
char temp[1024];
- sprintf(temp, "%d/%d/%d",
+ sprintf(temp, "%u/%u/%u",
xw->rgb_widths[0],
xw->rgb_widths[1],
xw->rgb_widths[2]);
@@ -4988,6 +5184,7 @@ do_dcs(XtermWidget xw, Char *dcsbuf, size_t dcslen)
break; /* no data found, error */
}
if ((cp - parsed) > 1024) {
+ free(name);
break; /* ignore improbable resource */
}
TRACE(("query-feature '%s'\n", name));
@@ -5032,8 +5229,25 @@ do_dcs(XtermWidget xw, Char *dcsbuf, size_t dcslen)
#endif
}
break;
-#if OPT_DEC_RECTOPS
+ case '0':
+ /* FALLTHRU */
case '1':
+ if (screen->vtXX_level >= 3 && *skip_params(cp) == '!') {
+ DECNRCM_codes upss;
+ psarg = *cp++;
+ if (*cp++ == '!' && *cp++ == 'u') {
+#if OPT_WIDE_CHARS
+ if (screen->wide_chars && screen->utf8_mode) {
+ ; /* EMPTY */
+ } else
+#endif
+ if (decode_upss(xw, cp, psarg, &upss)) {
+ screen->gsets_upss = upss;
+ }
+ }
+ break;
+ }
+#if OPT_DEC_RECTOPS
/* FALLTHRU */
case '2':
if (*skip_params(cp) == '$') {
@@ -5058,7 +5272,6 @@ do_dcs(XtermWidget xw, Char *dcsbuf, size_t dcslen)
/* FALLTHRU */
default:
if (optRegisGraphics(screen) ||
- optSixelGraphics(screen) ||
screen->vtXX_level >= 2) { /* VT220 */
parse_ansi_params(&params, &cp);
switch (params.a_final) {
@@ -5071,14 +5284,7 @@ do_dcs(XtermWidget xw, Char *dcsbuf, size_t dcslen)
TRACE(("ignoring ReGIS graphic (compilation flag not enabled)\n"));
#endif
break;
- case 'q': /* sixel */
-#if OPT_SIXEL_GRAPHICS
- if (optSixelGraphics(screen)) {
- (void) parse_sixel(xw, &params, cp);
- }
-#else
- TRACE(("ignoring sixel graphic (compilation flag not enabled)\n"));
-#endif
+ case 'q': /* sixel is done in charproc.c */
break;
case '|': /* DECUDK */
if (screen->vtXX_level >= 2) { /* VT220 */
@@ -5304,6 +5510,9 @@ do_dec_rqm(XtermWidget xw, int nparams, int *params)
if_PRINT_GRAPHICS2(result = MdBool(screen->graphics_print_color_syntax))
result = MdFlag(xw->flags, REVERSEWRAP);
break;
+ case srm_REVERSEWRAP2: /* extended reverse wraparound */
+ result = MdFlag(xw->flags, REVERSEWRAP2);
+ break;
#if defined(ALLOWLOGGING)
case srm_ALLOWLOGGING: /* logging */
if_PRINT_GRAPHICS2(result = MdBool(screen->graphics_print_background_mode))
@@ -5429,6 +5638,9 @@ do_dec_rqm(XtermWidget xw, int nparams, int *params)
case srm_SAVE_CURSOR:
result = MdBool(screen->sc[screen->whichBuf].saved);
break;
+ case srm_FAST_SCROLL:
+ result = MdBool(screen->fastscroll);
+ break;
#if OPT_TCAP_FKEYS
case srm_TCAP_FKEYS:
result = MdBool(xw->keyboard.type == keyboardIsTermcap);
@@ -5489,6 +5701,35 @@ do_dec_rqm(XtermWidget xw, int nparams, int *params)
result = MdBool(screen->sixel_scrolls_right);
break;
#endif
+ case srm_DECARSM: /* ignore */
+ case srm_DECATCBM: /* ignore */
+ case srm_DECATCUM: /* ignore */
+ case srm_DECBBSM: /* ignore */
+ case srm_DECCAAM: /* ignore */
+ case srm_DECCANSM: /* ignore */
+ case srm_DECCAPSLK: /* ignore */
+ case srm_DECCRTSM: /* ignore */
+ case srm_DECECM: /* ignore */
+ case srm_DECFWM: /* ignore */
+ case srm_DECHCCM: /* ignore */
+ case srm_DECHDPXM: /* ignore */
+ case srm_DECHEM: /* ignore */
+ case srm_DECHWUM: /* ignore */
+ case srm_DECIPEM: /* ignore */
+ case srm_DECKBUM: /* ignore */
+ case srm_DECKLHIM: /* ignore */
+ case srm_DECKPM: /* ignore */
+ case srm_DECRLM: /* ignore */
+ case srm_DECMCM: /* ignore */
+ case srm_DECNAKB: /* ignore */
+ case srm_DECNULM: /* ignore */
+ case srm_DECNUMLK: /* ignore */
+ case srm_DECOSCNM: /* ignore */
+ case srm_DECPCCM: /* ignore */
+ case srm_DECRLCM: /* ignore */
+ case srm_DECRPL: /* ignore */
+ case srm_DECVCCM: /* ignore */
+ case srm_DECXRLM: /* ignore */
default:
TRACE(("DATA_ERROR: requested report for unknown private mode %d\n",
params[0]));
@@ -5914,7 +6155,9 @@ ChangeGroup(XtermWidget xw, const char *attribute, char *value)
char *buf = 0;
XtSetArg(args[0], my_attr, &buf);
XtGetValues(top, args, 1);
- TRACE(("...comparing{%s}\n", NonNull(buf)));
+ TRACE(("...comparing resource{%s} to new value{%s}\n",
+ NonNull(buf),
+ NonNull(value)));
if (buf != 0 && strcmp(value, buf) == 0)
changed = False;
}
@@ -5932,7 +6175,7 @@ ChangeGroup(XtermWidget xw, const char *attribute, char *value)
const char *propname = (!strcmp(my_attr, XtNtitle)
? "_NET_WM_NAME"
: "_NET_WM_ICON_NAME");
- Atom my_atom = XInternAtom(dpy, propname, False);
+ Atom my_atom = CachedInternAtom(dpy, propname);
if (my_atom != None) {
changed = True;
@@ -5997,9 +6240,6 @@ ChangeGroup(XtermWidget xw, const char *attribute, char *value)
void
ChangeIconName(XtermWidget xw, char *name)
{
- if (name == 0) {
- name = emptyString;
- }
if (!showZIconBeep(xw, name))
ChangeGroup(xw, XtNiconName, name);
}
@@ -6023,7 +6263,7 @@ ChangeXprop(char *buf)
if (pchEndPropName)
*pchEndPropName = '\0';
- aprop = XInternAtom(dpy, buf, False);
+ aprop = CachedInternAtom(dpy, buf);
if (pchEndPropName == NULL) {
/* no "=value" given, so delete the property */
XDeleteProperty(dpy, w, aprop);
@@ -6581,7 +6821,7 @@ xt_error(String message)
if (x_getenv("DISPLAY") == 0) {
xtermWarning("DISPLAY is not set\n");
}
- exit(1);
+ exit(ERROR_MISC);
}
int
@@ -7593,6 +7833,90 @@ xtermSetWinSize(XtermWidget xw)
}
}
+static void
+xtermInitTitle(TScreen *screen, int which)
+{
+ TRACE(("xtermInitTitle #%d\n", which));
+ screen->saved_titles.data[which].iconName = NULL;
+ screen->saved_titles.data[which].windowName = NULL;
+}
+
+/*
+ * Store/update an item on the title stack.
+ */
+void
+xtermPushTitle(TScreen *screen, int which, SaveTitle * item)
+{
+ if (which-- <= 0) {
+ which = screen->saved_titles.used++;
+ screen->saved_titles.used %= MAX_SAVED_TITLES;
+ }
+ which %= MAX_SAVED_TITLES;
+ xtermFreeTitle(&screen->saved_titles.data[which]);
+ screen->saved_titles.data[which] = *item;
+ TRACE(("xtermPushTitle #%d: icon='%s', window='%s'\n", which,
+ NonNull(item->iconName),
+ NonNull(item->windowName)));
+}
+
+/*
+ * Pop/retrieve an item from the title stack.
+ */
+Boolean
+xtermPopTitle(TScreen *screen, int which, SaveTitle * item)
+{
+ Boolean result = True;
+ Boolean popped = False;
+
+ if (which-- > 0) {
+ which %= MAX_SAVED_TITLES;
+ } else if (screen->saved_titles.used > 0) {
+ which = ((--(screen->saved_titles.used) + MAX_SAVED_TITLES) % MAX_SAVED_TITLES);
+ popped = True;
+ } else {
+ result = False;
+ }
+ if (result) {
+ *item = screen->saved_titles.data[which];
+ TRACE(("xtermPopTitle #%d: icon='%s', window='%s'\n", which,
+ NonNull(item->iconName),
+ NonNull(item->windowName)));
+
+ /* if the data is incomplete, try to get it from the next levels */
+#define TryHigher(name) \
+ if (item->name == NULL) { \
+ int n; \
+ for (n = 1; n < MAX_SAVED_TITLES; ++n) { \
+ int nw = ((which - n) + MAX_SAVED_TITLES) % MAX_SAVED_TITLES; \
+ if ((item->name = screen->saved_titles.data[nw].name) != NULL) { \
+ item->name = x_strdup(item->name); \
+ break; \
+ } \
+ } \
+ }
+ TryHigher(iconName);
+ TryHigher(windowName);
+
+ if (popped) {
+ xtermInitTitle(screen, which);
+ }
+ }
+ return result;
+}
+
+/*
+ * Discard data used for pushing or popping title.
+ */
+void
+xtermFreeTitle(SaveTitle * item)
+{
+ TRACE(("xtermFreeTitle icon='%s', window='%s'\n",
+ NonNull(item->iconName),
+ NonNull(item->windowName)));
+ FreeAndNull(item->iconName);
+ FreeAndNull(item->windowName);
+}
+
#if OPT_XTERM_SGR
#if OPT_TRACE