X-Git-Url: https://git.distorted.org.uk/u/mdw/putty/blobdiff_plain/35100bc36e3de343ab93dc7ba71dbde9f3d0c558..39934deb5202149f98198c111a35c21cb4d0d0f8:/unix/pterm.c diff --git a/unix/pterm.c b/unix/pterm.c index ec1ffec4..a374d506 100644 --- a/unix/pterm.c +++ b/unix/pterm.c @@ -40,6 +40,13 @@ GdkAtom compound_text_atom, utf8_string_atom; extern char **pty_argv; /* declared in pty.c */ extern int use_pty_argv; +/* + * Timers are global across all sessions (even if we were handling + * multiple sessions, which we aren't), so the current timer ID is + * a global variable. + */ +static guint timer_id = 0; + struct gui_data { GtkWidget *window, *area, *sbar; GtkBox *hbox; @@ -1022,7 +1029,6 @@ gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data) show_mouseptr(inst, 0); term_seen_key_event(inst->term); - term_out(inst->term); } return TRUE; @@ -1130,9 +1136,9 @@ void frontend_keypress(void *handle) exit(0); } -gint timer_func(gpointer data) +void notify_remote_exit(void *frontend) { - struct gui_data *inst = (struct gui_data *)data; + struct gui_data *inst = (struct gui_data *)frontend; int exitcode; if (!inst->exited && @@ -1153,10 +1159,40 @@ gint timer_func(gpointer data) } gtk_widget_show(inst->restartitem); } +} - term_update(inst->term); - term_blink(inst->term, 0); - return TRUE; +static gint timer_trigger(gpointer data) +{ + long now = GPOINTER_TO_INT(data); + long next; + long ticks; + + if (run_timers(now, &next)) { + ticks = next - GETTICKCOUNT(); + timer_id = gtk_timeout_add(ticks > 0 ? ticks : 1, timer_trigger, + GINT_TO_POINTER(next)); + } + + /* + * Never let a timer resume. If we need another one, we've + * asked for it explicitly above. + */ + return FALSE; +} + +void timer_change_notify(long next) +{ + long ticks; + + if (timer_id) + gtk_timeout_remove(timer_id); + + ticks = next - GETTICKCOUNT(); + if (ticks <= 0) + ticks = 1; /* just in case */ + + timer_id = gtk_timeout_add(ticks, timer_trigger, + GINT_TO_POINTER(next)); } void fd_input_func(gpointer data, gint sourcefd, GdkInputCondition condition) @@ -1183,7 +1219,6 @@ gint focus_event(GtkWidget *widget, GdkEventFocus *event, gpointer data) { struct gui_data *inst = (struct gui_data *)data; inst->term->has_focus = event->in; - term_out(inst->term); term_update(inst->term); show_mouseptr(inst, 1); return FALSE; @@ -2737,8 +2772,8 @@ void setup_fonts_ucs(struct gui_data *inst) 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->direct_to_font = init_ucs(&inst->ucsdata, inst->cfg.line_codepage, + inst->cfg.utf8_override, font_charset, inst->cfg.vtmode); } @@ -3160,22 +3195,51 @@ void update_specials_menu(void *frontend) else specials = NULL; + /* I believe this disposes of submenus too. */ gtk_container_foreach(GTK_CONTAINER(inst->specialsmenu), (GtkCallback)gtk_widget_destroy, NULL); if (specials) { int i; - GtkWidget *menuitem; - for (i = 0; specials[i].name; i++) { - if (*specials[i].name) { + GtkWidget *menu = inst->specialsmenu; + /* A lame "stack" for submenus that will do for now. */ + GtkWidget *saved_menu = NULL; + int nesting = 1; + for (i = 0; nesting > 0; i++) { + GtkWidget *menuitem = NULL; + switch (specials[i].code) { + case TS_SUBMENU: + assert (nesting < 2); + saved_menu = menu; /* XXX lame stacking */ + menu = gtk_menu_new(); + menuitem = gtk_menu_item_new_with_label(specials[i].name); + gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), menu); + gtk_container_add(GTK_CONTAINER(saved_menu), menuitem); + gtk_widget_show(menuitem); + menuitem = NULL; + nesting++; + break; + case TS_EXITMENU: + nesting--; + if (nesting) { + menu = saved_menu; /* XXX lame stacking */ + saved_menu = NULL; + } + break; + case TS_SEP: + menuitem = gtk_menu_item_new(); + break; + default: menuitem = gtk_menu_item_new_with_label(specials[i].name); gtk_object_set_data(GTK_OBJECT(menuitem), "user-data", GINT_TO_POINTER(specials[i].code)); gtk_signal_connect(GTK_OBJECT(menuitem), "activate", GTK_SIGNAL_FUNC(special_menuitem), inst); - } else - menuitem = gtk_menu_item_new(); - gtk_container_add(GTK_CONTAINER(inst->specialsmenu), menuitem); - gtk_widget_show(menuitem); + break; + } + if (menuitem) { + gtk_container_add(GTK_CONTAINER(menu), menuitem); + gtk_widget_show(menuitem); + } } gtk_widget_show(inst->specialsitem1); gtk_widget_show(inst->specialsitem2); @@ -3217,7 +3281,6 @@ static void start_backend(struct gui_data *inst) sfree(title); } inst->back->provide_logctx(inst->backhandle, inst->logctx); - update_specials_menu(inst); term_provide_resize_fn(inst->term, inst->back->size, inst->backhandle); @@ -3364,7 +3427,6 @@ int pt_main(int argc, char **argv) if (inst->cfg.scrollbar) gtk_signal_connect(GTK_OBJECT(inst->sbar_adjust), "value_changed", GTK_SIGNAL_FUNC(scrollbar_moved), inst); - gtk_timeout_add(20, timer_func, inst); gtk_widget_add_events(GTK_WIDGET(inst->area), GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | @@ -3436,6 +3498,8 @@ int pt_main(int argc, char **argv) inst->specialsitem1 = menuitem; MKMENUITEM(NULL, NULL); inst->specialsitem2 = menuitem; + gtk_widget_hide(inst->specialsitem1); + gtk_widget_hide(inst->specialsitem2); MKMENUITEM("Clear Scrollback", clear_scrollback_menuitem); MKMENUITEM("Reset Terminal", reset_terminal_menuitem); MKMENUITEM("Copy All", copy_all_menuitem);