X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/962468d4b96c33869e9131eb42a0c784591f5884..8df5b84fdf848119a9e2ba5e5a60846b6eab9886:/unix/gtkwin.c diff --git a/unix/gtkwin.c b/unix/gtkwin.c index 334decb6..03f28551 100644 --- a/unix/gtkwin.c +++ b/unix/gtkwin.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -24,6 +25,10 @@ #include #include +#if GTK_CHECK_VERSION(2,0,0) +#include +#endif + #define PUTTY_DO_GLOBALS /* actually _define_ globals */ #include "putty.h" @@ -68,6 +73,9 @@ struct gui_data { *restartitem; GtkWidget *sessionsmenu; GdkPixmap *pixmap; +#if GTK_CHECK_VERSION(2,0,0) + GtkIMContext *imc; +#endif unifont *fonts[4]; /* normal, bold, wide, widebold */ int xpos, ypos, gotpos, gravity; GdkCursor *rawcursor, *textcursor, *blankcursor, *waitcursor, *currcursor; @@ -104,14 +112,14 @@ struct gui_data { guint32 input_event_time; /* Timestamp of the most recent input event. */ int reconfiguring; /* Cached things out of conf that we refer to a lot */ - int bold_colour; + int bold_style; int window_border; int cursor_type; }; static void cache_conf_values(struct gui_data *inst) { - inst->bold_colour = conf_get_int(inst->conf, CONF_bold_colour); + inst->bold_style = conf_get_int(inst->conf, CONF_bold_style); inst->window_border = conf_get_int(inst->conf, CONF_window_border); inst->cursor_type = conf_get_int(inst->conf, CONF_cursor_type); } @@ -489,6 +497,10 @@ gint configure_area(GtkWidget *widget, GdkEventConfigure *event, gpointer data) if (inst->term) term_invalidate(inst->term); +#if GTK_CHECK_VERSION(2,0,0) + gtk_im_context_set_client_window(inst->imc, widget->window); +#endif + return TRUE; } @@ -520,6 +532,7 @@ gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data) char output[256]; wchar_t ucsoutput[2]; int ucsval, start, end, special, output_charset, use_ucsoutput; + int nethack_mode, app_keypad_mode; /* Remember the timestamp. */ inst->input_event_time = event->time; @@ -539,21 +552,26 @@ gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data) * inconvenience in having to type a zero before a single-digit * character code. */ - if (event->type == GDK_KEY_RELEASE && - (event->keyval == GDK_Meta_L || event->keyval == GDK_Alt_L || - event->keyval == GDK_Meta_R || event->keyval == GDK_Alt_R) && - inst->alt_keycode >= 0 && inst->alt_digits > 1) { + if (event->type == GDK_KEY_RELEASE) { + if ((event->keyval == GDK_Meta_L || event->keyval == GDK_Alt_L || + event->keyval == GDK_Meta_R || event->keyval == GDK_Alt_R) && + inst->alt_keycode >= 0 && inst->alt_digits > 1) { #ifdef KEY_DEBUGGING - printf("Alt key up, keycode = %d\n", inst->alt_keycode); + printf("Alt key up, keycode = %d\n", inst->alt_keycode); +#endif + /* + * FIXME: we might usefully try to do something clever here + * about interpreting the generated key code in a way that's + * appropriate to the line code page. + */ + output[0] = inst->alt_keycode; + end = 1; + goto done; + } +#if GTK_CHECK_VERSION(2,0,0) + if (gtk_im_context_filter_keypress(inst->imc, event)) + return TRUE; #endif - /* - * FIXME: we might usefully try to do something clever here - * about interpreting the generated key code in a way that's - * appropriate to the line code page. - */ - output[0] = inst->alt_keycode; - end = 1; - goto done; } if (event->type == GDK_KEY_PRESS) { @@ -656,6 +674,10 @@ gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data) special = FALSE; use_ucsoutput = FALSE; + nethack_mode = conf_get_int(inst->conf, CONF_nethack_keypad); + app_keypad_mode = (inst->term->app_keypad_keys && + !conf_get_int(inst->conf, CONF_no_applic_k)); + /* ALT+things gives leading Escape. */ output[0] = '\033'; #if !GTK_CHECK_VERSION(2,0,0) @@ -669,13 +691,73 @@ gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data) output_charset = CS_ISO8859_1; strncpy(output+1, event->string, lenof(output)-1); #else + /* + * 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_Num_Lock || + event->keyval == GDK_KP_Divide || + event->keyval == GDK_KP_Multiply || + event->keyval == GDK_KP_Subtract || + event->keyval == GDK_KP_Add || + event->keyval == GDK_KP_Enter || + event->keyval == GDK_KP_0 || + event->keyval == GDK_KP_Insert || + event->keyval == GDK_KP_1 || + event->keyval == GDK_KP_End || + event->keyval == GDK_KP_2 || + event->keyval == GDK_KP_Down || + event->keyval == GDK_KP_3 || + event->keyval == GDK_KP_Page_Down || + event->keyval == GDK_KP_4 || + event->keyval == GDK_KP_Left || + event->keyval == GDK_KP_5 || + event->keyval == GDK_KP_Begin || + event->keyval == GDK_KP_6 || + event->keyval == GDK_KP_Right || + event->keyval == GDK_KP_7 || + event->keyval == GDK_KP_Home || + event->keyval == GDK_KP_8 || + event->keyval == GDK_KP_Up || + event->keyval == GDK_KP_9 || + event->keyval == GDK_KP_Page_Up || + event->keyval == GDK_KP_Decimal || + event->keyval == GDK_KP_Delete)) { + /* app keypad; do nothing */ + } else if (nethack_mode && + (event->keyval == GDK_KP_1 || + event->keyval == GDK_KP_End || + event->keyval == GDK_KP_2 || + event->keyval == GDK_KP_Down || + event->keyval == GDK_KP_3 || + event->keyval == GDK_KP_Page_Down || + event->keyval == GDK_KP_4 || + event->keyval == GDK_KP_Left || + event->keyval == GDK_KP_5 || + event->keyval == GDK_KP_Begin || + event->keyval == GDK_KP_6 || + event->keyval == GDK_KP_Right || + event->keyval == GDK_KP_7 || + event->keyval == GDK_KP_Home || + event->keyval == GDK_KP_8 || + event->keyval == GDK_KP_Up || + event->keyval == GDK_KP_9 || + event->keyval == GDK_KP_Page_Up)) { + /* nethack mode; do nothing */ + } else { + if (gtk_im_context_filter_keypress(inst->imc, event)) + return TRUE; + } + /* * GDK 2.0 arranges to have done some translation for us: in * GDK 2.0, event->string is encoded in the current locale. * - * (However, it's also deprecated; we really ought to be - * using a GTKIMContext.) - * * 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. @@ -800,7 +882,7 @@ gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data) /* * NetHack keypad mode. */ - if (conf_get_int(inst->conf, CONF_nethack_keypad)) { + if (nethack_mode) { char *keys = NULL; switch (event->keyval) { case GDK_KP_1: case GDK_KP_End: keys = "bB\002"; break; @@ -829,8 +911,7 @@ gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data) /* * Application keypad mode. */ - if (inst->term->app_keypad_keys && - !conf_get_int(inst->conf, CONF_no_applic_k)) { + if (app_keypad_mode) { int xkey = 0; switch (event->keyval) { case GDK_Num_Lock: xkey = 'P'; break; @@ -1136,6 +1217,16 @@ gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data) return TRUE; } +#if GTK_CHECK_VERSION(2,0,0) +void input_method_commit_event(GtkIMContext *imc, gchar *str, gpointer data) +{ + struct gui_data *inst = (struct gui_data *)data; + lpage_send(inst->ldisc, CS_UTF8, str, strlen(str), 1); + show_mouseptr(inst, 0); + term_seen_key_event(inst->term); +} +#endif + gboolean button_internal(struct gui_data *inst, guint32 timestamp, GdkEventType type, guint ebutton, guint state, gdouble ex, gdouble ey) @@ -2061,11 +2152,11 @@ void do_text_internal(Context ctx, int x, int y, wchar_t *text, int len, nfg = nbg; nbg = t; } - if (inst->bold_colour && (attr & ATTR_BOLD)) { + if ((inst->bold_style & 2) && (attr & ATTR_BOLD)) { if (nfg < 16) nfg |= 8; else if (nfg >= 256) nfg |= 1; } - if (inst->bold_colour && (attr & ATTR_BLINK)) { + if ((inst->bold_style & 2) && (attr & ATTR_BLINK)) { if (nbg < 16) nbg |= 8; else if (nbg >= 256) nbg |= 1; } @@ -2083,7 +2174,7 @@ void do_text_internal(Context ctx, int x, int y, wchar_t *text, int len, widefactor = 1; } - if ((attr & ATTR_BOLD) && !inst->bold_colour) { + if ((attr & ATTR_BOLD) && (inst->bold_style & 1)) { bold = 1; fontid |= 1; } else { @@ -2328,6 +2419,17 @@ void do_cursor(Context ctx, int x, int y, wchar_t *text, int len, x*inst->font_width+inst->window_border, y*inst->font_height+inst->window_border, len*widefactor*inst->font_width, inst->font_height); + +#if GTK_CHECK_VERSION(2,0,0) + { + GdkRectangle cursorrect; + cursorrect.x = x*inst->font_width+inst->window_border; + cursorrect.y = y*inst->font_height+inst->window_border; + cursorrect.width = len*widefactor*inst->font_width; + cursorrect.height = inst->font_height; + gtk_im_context_set_cursor_location(inst->imc, &cursorrect); + } +#endif } GdkCursor *make_mouse_ptr(struct gui_data *inst, int cursor_val) @@ -2725,6 +2827,24 @@ void uxsel_input_remove(int id) { gdk_input_remove(id); } +int frontend_net_pending_error_idle_id; +int frontend_got_net_pending_errors = FALSE; +gboolean frontend_net_pending_errors(gpointer data) +{ + net_pending_errors(); + gtk_idle_remove(frontend_net_pending_error_idle_id); + frontend_got_net_pending_errors = FALSE; + return FALSE; +} +void frontend_net_error_pending(void) +{ + if (!frontend_got_net_pending_errors) { + frontend_got_net_pending_errors = TRUE; + frontend_net_pending_error_idle_id = + gtk_idle_add(frontend_net_pending_errors, NULL); + } +} + void setup_fonts_ucs(struct gui_data *inst) { int shadowbold = conf_get_int(inst->conf, CONF_shadowbold); @@ -2971,6 +3091,8 @@ void change_settings_menuitem(GtkMenuItem *item, gpointer data) conf_get_fontspec(newconf, CONF_wideboldfont)->name) || strcmp(conf_get_str(oldconf, CONF_line_codepage), conf_get_str(newconf, CONF_line_codepage)) || + conf_get_int(oldconf, CONF_utf8_override) != + conf_get_int(newconf, CONF_utf8_override) || conf_get_int(oldconf, CONF_vtmode) != conf_get_int(newconf, CONF_vtmode) || conf_get_int(oldconf, CONF_shadowbold) != @@ -3426,6 +3548,8 @@ int pt_main(int argc, char **argv) extern int cfgbox(Conf *conf); struct gui_data *inst; + setlocale(LC_CTYPE, ""); + /* * Create an instance structure and initialise to zeroes */ @@ -3487,6 +3611,10 @@ int pt_main(int argc, char **argv) inst->area = gtk_drawing_area_new(); +#if GTK_CHECK_VERSION(2,0,0) + inst->imc = gtk_im_multicontext_new(); +#endif + setup_fonts_ucs(inst); init_cutbuffers(); @@ -3577,6 +3705,10 @@ int pt_main(int argc, char **argv) GTK_SIGNAL_FUNC(selection_get), inst); gtk_signal_connect(GTK_OBJECT(inst->area), "selection_clear_event", GTK_SIGNAL_FUNC(selection_clear), inst); +#if GTK_CHECK_VERSION(2,0,0) + g_signal_connect(G_OBJECT(inst->imc), "commit", + G_CALLBACK(input_method_commit_event), inst); +#endif if (conf_get_int(inst->conf, CONF_scrollbar)) gtk_signal_connect(GTK_OBJECT(inst->sbar_adjust), "value_changed", GTK_SIGNAL_FUNC(scrollbar_moved), inst);