+#if !GTK_CHECK_VERSION(2,0,0)
+ /*
+ * In vanilla X, and hence also GDK 1.2, the string received
+ * as part of a keyboard event is assumed to be in
+ * ISO-8859-1. (Seems woefully shortsighted in i18n terms,
+ * but it's true: see the man page for XLookupString(3) for
+ * confirmation.)
+ */
+ output_charset = CS_ISO8859_1;
+ strncpy(output+1, event->string, lenof(output)-1);
+#else /* !GTK_CHECK_VERSION(2,0,0) */
+ /*
+ * Most things can now be passed to
+ * gtk_im_context_filter_keypress without breaking anything
+ * below this point. An exception is the numeric keypad if
+ * we're in Nethack or application mode: the IM will eat
+ * numeric keypad presses if Num Lock is on, but we don't want
+ * it to.
+ */
+ if (app_keypad_mode &&
+ (event->keyval == GDK_KEY_Num_Lock ||
+ event->keyval == GDK_KEY_KP_Divide ||
+ event->keyval == GDK_KEY_KP_Multiply ||
+ event->keyval == GDK_KEY_KP_Subtract ||
+ event->keyval == GDK_KEY_KP_Add ||
+ event->keyval == GDK_KEY_KP_Enter ||
+ event->keyval == GDK_KEY_KP_0 ||
+ event->keyval == GDK_KEY_KP_Insert ||
+ event->keyval == GDK_KEY_KP_1 ||
+ event->keyval == GDK_KEY_KP_End ||
+ event->keyval == GDK_KEY_KP_2 ||
+ event->keyval == GDK_KEY_KP_Down ||
+ event->keyval == GDK_KEY_KP_3 ||
+ event->keyval == GDK_KEY_KP_Page_Down ||
+ event->keyval == GDK_KEY_KP_4 ||
+ event->keyval == GDK_KEY_KP_Left ||
+ event->keyval == GDK_KEY_KP_5 ||
+ event->keyval == GDK_KEY_KP_Begin ||
+ event->keyval == GDK_KEY_KP_6 ||
+ event->keyval == GDK_KEY_KP_Right ||
+ event->keyval == GDK_KEY_KP_7 ||
+ event->keyval == GDK_KEY_KP_Home ||
+ event->keyval == GDK_KEY_KP_8 ||
+ event->keyval == GDK_KEY_KP_Up ||
+ event->keyval == GDK_KEY_KP_9 ||
+ event->keyval == GDK_KEY_KP_Page_Up ||
+ event->keyval == GDK_KEY_KP_Decimal ||
+ event->keyval == GDK_KEY_KP_Delete)) {
+ /* app keypad; do nothing */
+ } else if (nethack_mode &&
+ (event->keyval == GDK_KEY_KP_1 ||
+ event->keyval == GDK_KEY_KP_End ||
+ event->keyval == GDK_KEY_KP_2 ||
+ event->keyval == GDK_KEY_KP_Down ||
+ event->keyval == GDK_KEY_KP_3 ||
+ event->keyval == GDK_KEY_KP_Page_Down ||
+ event->keyval == GDK_KEY_KP_4 ||
+ event->keyval == GDK_KEY_KP_Left ||
+ event->keyval == GDK_KEY_KP_5 ||
+ event->keyval == GDK_KEY_KP_Begin ||
+ event->keyval == GDK_KEY_KP_6 ||
+ event->keyval == GDK_KEY_KP_Right ||
+ event->keyval == GDK_KEY_KP_7 ||
+ event->keyval == GDK_KEY_KP_Home ||
+ event->keyval == GDK_KEY_KP_8 ||
+ event->keyval == GDK_KEY_KP_Up ||
+ event->keyval == GDK_KEY_KP_9 ||
+ event->keyval == GDK_KEY_KP_Page_Up)) {
+ /* nethack mode; do nothing */
+ } else {
+ int try_filter = TRUE;
+
+#ifdef META_MANUAL_MASK
+ if (event->state & META_MANUAL_MASK & inst->meta_mod_mask) {
+ /*
+ * If this key event had a Meta modifier bit set which
+ * is also in META_MANUAL_MASK, that means passing
+ * such an event to the GtkIMContext will be unhelpful
+ * (it will eat the keystroke and turn it into
+ * something not what we wanted).
+ */
+#ifdef KEY_EVENT_DIAGNOSTICS
+ debug((" - Meta modifier requiring manual intervention, "
+ "suppressing IM filtering\n"));
+#endif
+ try_filter = FALSE;
+ }
+#endif
+
+ if (try_filter) {
+#ifdef KEY_EVENT_DIAGNOSTICS
+ debug((" - general key press, passing to IM\n"));
+#endif
+ if (gtk_im_context_filter_keypress(inst->imc, event)) {
+#ifdef KEY_EVENT_DIAGNOSTICS
+ debug((" - key press accepted by IM\n"));
+#endif
+ return TRUE;
+ } else {
+#ifdef KEY_EVENT_DIAGNOSTICS
+ debug((" - key press not accepted by IM\n"));
+#endif
+ }
+ }
+ }
+
+ /*
+ * GDK 2.0 arranges to have done some translation for us: in
+ * GDK 2.0, event->string is encoded in the current locale.
+ *
+ * So we use the standard C library function mbstowcs() to
+ * convert from the current locale into Unicode; from there
+ * we can convert to whatever PuTTY is currently working in.
+ * (In fact I convert straight back to UTF-8 from
+ * wide-character Unicode, for the sake of simplicity: that
+ * way we can still use exactly the same code to manipulate
+ * the string, such as prefixing ESC.)
+ */
+ output_charset = CS_UTF8;
+ {
+ wchar_t widedata[32];
+ const wchar_t *wp;
+ int wlen;
+ int ulen;
+
+ wlen = mb_to_wc(DEFAULT_CODEPAGE, 0,
+ event->string, strlen(event->string),
+ widedata, lenof(widedata)-1);
+
+#ifdef KEY_EVENT_DIAGNOSTICS
+ {
+ char *string_string = dupstr("");
+ int i;
+
+ for (i = 0; i < wlen; i++) {
+ char *old = string_string;
+ string_string = dupprintf("%s%s%04x", string_string,
+ string_string[0] ? " " : "",
+ (unsigned)widedata[i]);
+ sfree(old);
+ }
+ debug((" - string translated into Unicode = [%s]\n",
+ string_string));
+ sfree(string_string);
+ }
+#endif
+
+ wp = widedata;
+ ulen = charset_from_unicode(&wp, &wlen, output+1, lenof(output)-2,
+ CS_UTF8, NULL, NULL, 0);
+
+#ifdef KEY_EVENT_DIAGNOSTICS
+ {
+ char *string_string = dupstr("");
+ int i;
+
+ for (i = 0; i < ulen; i++) {
+ char *old = string_string;
+ string_string = dupprintf("%s%s%02x", string_string,
+ string_string[0] ? " " : "",
+ (unsigned)output[i+1] & 0xFF);
+ sfree(old);
+ }
+ debug((" - string translated into UTF-8 = [%s]\n",
+ string_string));
+ sfree(string_string);
+ }
+#endif
+
+ output[1+ulen] = '\0';
+ }
+#endif /* !GTK_CHECK_VERSION(2,0,0) */
+
+ if (!output[1] &&