{
if (!strcmp(name, "CloseOnExit"))
return 2; /* maps to FORCE_ON after painful rearrangement :-( */
+ if (!strcmp(name, "WinNameAlways"))
+ return 0; /* X natively supports icon titles, so use 'em by default */
return def;
}
return term_data(inst->term, is_stderr, data, len);
}
-void logevent(void *frontend, char *string)
+void logevent(void *frontend, const char *string)
{
struct gui_data *inst = (struct gui_data *)frontend;
char *get_window_title(void *frontend, int icon)
{
struct gui_data *inst = (struct gui_data *)frontend;
- return icon ? inst->wintitle : inst->icontitle;
+ return icon ? inst->icontitle : inst->wintitle;
}
gint delete_window(GtkWidget *widget, GdkEvent *event, gpointer data)
{
struct gui_data *inst = (struct gui_data *)data;
char output[32];
- int start, end, special;
+ wchar_t ucsoutput[2];
+ int ucsval, start, end, special, use_ucsoutput;
/* By default, nothing is generated. */
end = start = 0;
- special = FALSE;
+ special = use_ucsoutput = FALSE;
/*
* If Alt is being released after typing an Alt+numberpad
}
special = FALSE;
+ use_ucsoutput = FALSE;
/* ALT+things gives leading Escape. */
output[0] = '\033';
strncpy(output+1, event->string, 31);
- output[31] = '\0';
- end = strlen(output);
+ if (!*event->string &&
+ (ucsval = keysym_to_unicode(event->keyval)) >= 0) {
+ ucsoutput[0] = '\033';
+ ucsoutput[1] = ucsval;
+ use_ucsoutput = TRUE;
+ end = 2;
+ } else {
+ output[31] = '\0';
+ end = strlen(output);
+ }
if (event->state & GDK_MOD1_MASK) {
start = 0;
if (end == 1) end = 0;
if (!event->string[0] && event->keyval == '`' &&
(event->state & GDK_CONTROL_MASK)) {
output[1] = '\x1C';
+ use_ucsoutput = FALSE;
end = 2;
}
if (event->keyval == GDK_Break &&
(event->state & GDK_CONTROL_MASK)) {
output[1] = '\003';
+ use_ucsoutput = FALSE;
end = 2;
special = TRUE;
}
* special to ldisc. */
if (event->keyval == GDK_Return) {
output[1] = '\015';
+ use_ucsoutput = FALSE;
end = 2;
special = TRUE;
}
(event->state & (GDK_SHIFT_MASK |
GDK_CONTROL_MASK)) == GDK_CONTROL_MASK) {
output[1] = '\0';
+ use_ucsoutput = FALSE;
end = 2;
}
(event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK)) ==
(GDK_SHIFT_MASK | GDK_CONTROL_MASK)) {
output[1] = '\240';
+ use_ucsoutput = FALSE;
end = 2;
}
if (event->keyval == GDK_BackSpace &&
!(event->state & GDK_SHIFT_MASK)) {
output[1] = inst->cfg.bksp_is_delete ? '\x7F' : '\x08';
+ use_ucsoutput = FALSE;
end = 2;
special = TRUE;
}
if (event->keyval == GDK_BackSpace &&
(event->state & GDK_SHIFT_MASK)) {
output[1] = inst->cfg.bksp_is_delete ? '\x08' : '\x7F';
+ use_ucsoutput = FALSE;
end = 2;
special = TRUE;
}
if (event->keyval == GDK_ISO_Left_Tab ||
(event->keyval == GDK_Tab && (event->state & GDK_SHIFT_MASK))) {
end = 1 + sprintf(output+1, "\033[Z");
+ use_ucsoutput = FALSE;
}
/*
output[1] = keys[1];
else
output[1] = keys[0];
+ use_ucsoutput = FALSE;
goto done;
}
}
end = 1 + sprintf(output+1, "\033?%c", xkey);
} else
end = 1 + sprintf(output+1, "\033O%c", xkey);
+ use_ucsoutput = FALSE;
goto done;
}
}
if (inst->term->vt52_mode && code > 0 && code <= 6) {
end = 1 + sprintf(output+1, "\x1B%c", " HLMEIG"[code]);
+ use_ucsoutput = FALSE;
goto done;
}
if (event->state & GDK_SHIFT_MASK) index += 12;
if (event->state & GDK_CONTROL_MASK) index += 24;
end = 1 + sprintf(output+1, "\x1B[%c", codes[index]);
+ use_ucsoutput = FALSE;
goto done;
}
if (inst->cfg.funky_type == 5 && /* SCO small keypad */
} else {
end = 1 + sprintf(output+1, "\x1B[%c", codes[code-1]);
}
+ use_ucsoutput = FALSE;
goto done;
}
if ((inst->term->vt52_mode || inst->cfg.funky_type == 4) &&
else
end = 1 + sprintf(output+1,
"\x1BO%c", code + 'P' - 11 - offt);
+ use_ucsoutput = FALSE;
goto done;
}
if (inst->cfg.funky_type == 1 && code >= 11 && code <= 15) {
end = 1 + sprintf(output+1, "\x1B[[%c", code + 'A' - 11);
+ use_ucsoutput = FALSE;
goto done;
}
if (inst->cfg.funky_type == 2 && code >= 11 && code <= 14) {
end = 1 + sprintf(output+1, "\x1B%c", code + 'P' - 11);
else
end = 1 + sprintf(output+1, "\x1BO%c", code + 'P' - 11);
+ use_ucsoutput = FALSE;
goto done;
}
if (inst->cfg.rxvt_homeend && (code == 1 || code == 4)) {
end = 1 + sprintf(output+1, code == 1 ? "\x1B[H" : "\x1BOw");
+ use_ucsoutput = FALSE;
goto done;
}
if (code) {
end = 1 + sprintf(output+1, "\x1B[%d~", code);
+ use_ucsoutput = FALSE;
goto done;
}
}
} else {
end = 1 + sprintf(output+1, "\033[%c", xkey);
}
+ use_ucsoutput = FALSE;
goto done;
}
}
output[end] = '\0'; /* NUL-terminate */
ldisc_send(inst->ldisc, output+start, -2, 1);
} else if (!inst->direct_to_font) {
- /*
- * The stuff we've just generated is assumed to be
- * ISO-8859-1! This sounds insane, but `man
- * XLookupString' agrees: strings of this type returned
- * from the X server are hardcoded to 8859-1. Strictly
- * speaking we should be doing this using some sort of
- * GtkIMContext, which (if we're lucky) would give us
- * our data directly in Unicode; but that's not
- * supported in GTK 1.2 as far as I can tell, and it's
- * poorly documented even in 2.0, so it'll have to
- * wait.
- */
- lpage_send(inst->ldisc, CS_ISO8859_1, output+start, end-start, 1);
+ if (!use_ucsoutput) {
+ /*
+ * The stuff we've just generated is assumed to be
+ * ISO-8859-1! This sounds insane, but `man
+ * XLookupString' agrees: strings of this type
+ * returned from the X server are hardcoded to
+ * 8859-1. Strictly speaking we should be doing
+ * this using some sort of GtkIMContext, which (if
+ * we're lucky) would give us our data directly in
+ * Unicode; but that's not supported in GTK 1.2 as
+ * far as I can tell, and it's poorly documented
+ * even in 2.0, so it'll have to wait.
+ */
+ lpage_send(inst->ldisc, CS_ISO8859_1, output+start,
+ end-start, 1);
+ } else {
+ /*
+ * We generated our own Unicode key data from the
+ * keysym, so use that instead.
+ */
+ luni_send(inst->ldisc, ucsoutput+start, end-start, 1);
+ }
} else {
/*
* In direct-to-font mode, we just send the string
}
}
+static void set_window_titles(struct gui_data *inst)
+{
+ /*
+ * We must always call set_icon_name after calling set_title,
+ * since set_title will write both names. Irritating, but such
+ * is life.
+ */
+ gtk_window_set_title(GTK_WINDOW(inst->window), inst->wintitle);
+ if (!inst->cfg.win_name_always)
+ gdk_window_set_icon_name(inst->window->window, inst->icontitle);
+}
+
void set_title(void *frontend, char *title)
{
struct gui_data *inst = (struct gui_data *)frontend;
strncpy(inst->wintitle, title, lenof(inst->wintitle));
inst->wintitle[lenof(inst->wintitle)-1] = '\0';
- gtk_window_set_title(GTK_WINDOW(inst->window), inst->wintitle);
+ set_window_titles(inst);
}
void set_icon(void *frontend, char *title)
struct gui_data *inst = (struct gui_data *)frontend;
strncpy(inst->icontitle, title, lenof(inst->icontitle));
inst->icontitle[lenof(inst->icontitle)-1] = '\0';
- gdk_window_set_icon_name(inst->window->window, inst->icontitle);
+ set_window_titles(inst);
}
void set_sbar(void *frontend, int total, int start, int page)
char *p = *++argv;
int ret;
+ /*
+ * Shameless cheating. Debian requires all X terminal
+ * emulators to support `-T title'; but
+ * cmdline_process_param will eat -T (it means no-pty) and
+ * complain that pterm doesn't support it. So, in pterm
+ * only, we convert -T into -title.
+ */
+ if ((cmdline_tooltype & TOOLTYPE_NONNETWORK) &&
+ !strcmp(p, "-T"))
+ p = "-title";
+
ret = cmdline_process_param(p, (argc > 1 ? argv[1] : NULL),
do_everything ? 1 : -1, cfg);
gdk_input_remove(id);
}
+char *guess_derived_font_name(GdkFont *font, int bold, int wide)
+{
+ XFontStruct *xfs = GDK_FONT_XFONT(font);
+ Display *disp = GDK_FONT_XDISPLAY(font);
+ Atom fontprop = XInternAtom(disp, "FONT", False);
+ unsigned long ret;
+ if (XGetFontProperty(xfs, fontprop, &ret)) {
+ char *name = XGetAtomName(disp, (Atom)ret);
+ if (name && name[0] == '-') {
+ char *strings[13];
+ char *dupname, *extrafree = NULL, *ret;
+ char *p, *q;
+ int nstr;
+
+ p = q = dupname = dupstr(name); /* skip initial minus */
+ nstr = 0;
+
+ while (*p && nstr < lenof(strings)) {
+ if (*p == '-') {
+ *p = '\0';
+ strings[nstr++] = p+1;
+ }
+ p++;
+ }
+
+ if (nstr < lenof(strings))
+ return NULL; /* XLFD was malformed */
+
+ if (bold)
+ strings[2] = "bold";
+
+ if (wide) {
+ /* 4 is `wideness', which obviously may have changed. */
+ /* 5 is additional style, which may be e.g. `ja' or `ko'. */
+ strings[4] = strings[5] = "*";
+ strings[11] = extrafree = dupprintf("%d", 2*atoi(strings[11]));
+ }
+
+ ret = dupcat("-", strings[ 0], "-", strings[ 1], "-", strings[ 2],
+ "-", strings[ 3], "-", strings[ 4], "-", strings[ 5],
+ "-", strings[ 6], "-", strings[ 7], "-", strings[ 8],
+ "-", strings[ 9], "-", strings[10], "-", strings[11],
+ "-", strings[12], NULL);
+ sfree(extrafree);
+ sfree(dupname);
+
+ return ret;
+ }
+ }
+ return NULL;
+}
+
void setup_fonts_ucs(struct gui_data *inst)
{
int font_charset;
+ char *name;
+ int guessed;
if (inst->fonts[0])
gdk_font_unref(inst->fonts[0]);
exit(1);
}
font_charset = set_font_info(inst, 0);
+
if (inst->cfg.boldfont.name[0]) {
- inst->fonts[1] = gdk_font_load(inst->cfg.boldfont.name);
- if (!inst->fonts[1]) {
- fprintf(stderr, "%s: unable to load bold font \"%s\"\n", appname,
- inst->cfg.boldfont.name);
- exit(1);
- }
+ name = inst->cfg.boldfont.name;
+ guessed = FALSE;
+ } else {
+ name = guess_derived_font_name(inst->fonts[0], TRUE, FALSE);
+ guessed = TRUE;
+ }
+ inst->fonts[1] = name ? gdk_font_load(name) : NULL;
+ if (inst->fonts[1]) {
set_font_info(inst, 1);
- } else
- inst->fonts[1] = NULL;
+ } else if (!guessed) {
+ fprintf(stderr, "%s: unable to load bold font \"%s\"\n", appname,
+ inst->cfg.boldfont.name);
+ exit(1);
+ }
+ if (guessed)
+ sfree(name);
+
if (inst->cfg.widefont.name[0]) {
- inst->fonts[2] = gdk_font_load(inst->cfg.widefont.name);
- if (!inst->fonts[2]) {
- fprintf(stderr, "%s: unable to load wide font \"%s\"\n", appname,
- inst->cfg.widefont.name);
- exit(1);
- }
+ name = inst->cfg.widefont.name;
+ guessed = FALSE;
+ } else {
+ name = guess_derived_font_name(inst->fonts[0], FALSE, TRUE);
+ guessed = TRUE;
+ }
+ inst->fonts[2] = name ? gdk_font_load(name) : NULL;
+ if (inst->fonts[2]) {
set_font_info(inst, 2);
- } else
- inst->fonts[2] = NULL;
+ } else if (!guessed) {
+ fprintf(stderr, "%s: unable to load wide font \"%s\"\n", appname,
+ inst->cfg.widefont.name);
+ exit(1);
+ }
+ if (guessed)
+ sfree(name);
+
if (inst->cfg.wideboldfont.name[0]) {
- inst->fonts[3] = gdk_font_load(inst->cfg.wideboldfont.name);
- if (!inst->fonts[3]) {
- fprintf(stderr, "%s: unable to load wide/bold font \"%s\"\n",
- appname, inst->cfg.wideboldfont.name);
- exit(1);
- }
+ name = inst->cfg.wideboldfont.name;
+ guessed = FALSE;
+ } else {
+ /*
+ * Here we have some choices. We can widen the bold font,
+ * bolden the wide font, or widen and bolden the standard
+ * font. Try them all, in that order!
+ */
+ if (inst->cfg.widefont.name[0])
+ name = guess_derived_font_name(inst->fonts[2], TRUE, FALSE);
+ else if (inst->cfg.boldfont.name[0])
+ name = guess_derived_font_name(inst->fonts[1], FALSE, TRUE);
+ else
+ name = guess_derived_font_name(inst->fonts[0], TRUE, TRUE);
+ guessed = TRUE;
+ }
+ inst->fonts[3] = name ? gdk_font_load(name) : NULL;
+ if (inst->fonts[3]) {
set_font_info(inst, 3);
- } else
- inst->fonts[3] = NULL;
+ } else if (!guessed) {
+ fprintf(stderr, "%s: unable to load wide/bold font \"%s\"\n", appname,
+ inst->cfg.wideboldfont.name);
+ exit(1);
+ }
+ if (guessed)
+ sfree(name);
inst->font_width = gdk_char_width(inst->fonts[0], ' ');
inst->font_height = inst->fonts[0]->ascent + inst->fonts[0]->descent;
inst->direct_to_font = init_ucs(&inst->ucsdata,
- inst->cfg.line_codepage, font_charset);
+ inst->cfg.line_codepage, font_charset,
+ inst->cfg.vtmode);
}
void set_geom_hints(struct gui_data *inst)
void special_menuitem(GtkMenuItem *item, gpointer data)
{
struct gui_data *inst = (struct gui_data *)data;
- int code = (int)gtk_object_get_data(GTK_OBJECT(item), "user-data");
+ int code = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(item),
+ "user-data"));
inst->back->special(inst->backhandle, code);
}
*/
if (strcmp(oldcfg.wintitle, cfg2.wintitle))
set_title(inst, cfg2.wintitle);
+ set_window_titles(inst);
/*
* Redo the whole tangled fonts and Unicode mess if
strcmp(oldcfg.boldfont.name, cfg2.boldfont.name) ||
strcmp(oldcfg.widefont.name, cfg2.widefont.name) ||
strcmp(oldcfg.wideboldfont.name, cfg2.wideboldfont.name) ||
- strcmp(oldcfg.line_codepage, cfg2.line_codepage)) {
+ strcmp(oldcfg.line_codepage, cfg2.line_codepage) ||
+ oldcfg.vtmode != cfg2.vtmode) {
setup_fonts_ucs(inst);
need_size = 1;
} else
if (*specials[i].name) {
menuitem = gtk_menu_item_new_with_label(specials[i].name);
gtk_object_set_data(GTK_OBJECT(menuitem), "user-data",
- (gpointer)specials[i].code);
+ GINT_TO_POINTER(specials[i].code));
gtk_signal_connect(GTK_OBJECT(menuitem), "activate",
GTK_SIGNAL_FUNC(special_menuitem), inst);
} else
inst->back = select_backend(&inst->cfg);
{
- char *realhost, *error;
+ char *realhost;
+ const char *error;
error = inst->back->init((void *)inst, &inst->backhandle,
&inst->cfg, inst->cfg.host, inst->cfg.port,
return 0;
}
- if (inst->cfg.wintitle[0])
+ if (inst->cfg.wintitle[0]) {
set_title(inst, inst->cfg.wintitle);
- else {
+ set_icon(inst, inst->cfg.wintitle);
+ } else {
char *title = make_default_wintitle(realhost);
set_title(inst, title);
+ set_icon(inst, title);
sfree(title);
}
}