diff --git a/unix/gtkdlg.c b/unix/gtkdlg.c index 1b9b8d42..a8143ef5 100644 --- a/unix/gtkdlg.c +++ b/unix/gtkdlg.c @@ -3691,13 +3691,6 @@ void old_keyfile_warning(void) */ } -void fatal_message_box(void *window, const char *msg) -{ - message_box(window, "PuTTY Fatal Error", msg, - string_width("REASONABLY LONG LINE OF TEXT FOR BASIC SANITY"), - FALSE, &buttons_ok); -} - void nonfatal_message_box(void *window, const char *msg) { char *title = dupcat(appname, " Error", NULL); diff --git a/unix/gtkwin.c b/unix/gtkwin.c index e8bc2894..a4c70475 100644 --- a/unix/gtkwin.c +++ b/unix/gtkwin.c @@ -167,6 +167,38 @@ static int send_raw_mouse; static void start_backend(struct gui_data *inst); static void exit_callback(void *vinst); +static void destroy_inst_connection(struct gui_data *inst); +static void delete_inst(struct gui_data *inst); + +static void post_fatal_message_box_toplevel(void *vctx) +{ + struct gui_data *inst = (struct gui_data *)vctx; + gtk_widget_destroy(inst->window); +} + +static void post_fatal_message_box(void *vctx, int result) +{ + struct gui_data *inst = (struct gui_data *)vctx; + unregister_dialog(inst, DIALOG_SLOT_CONNECTION_FATAL); + queue_toplevel_callback(post_fatal_message_box_toplevel, inst); +} + +void fatal_message_box(struct gui_data *inst, const char *msg) +{ + char *title = dupcat(appname, " Fatal Error", NULL); + GtkWidget *dialog = create_message_box( + inst->window, title, msg, + string_width("REASONABLY LONG LINE OF TEXT FOR BASIC SANITY"), + FALSE, &buttons_ok, post_fatal_message_box, inst); + register_dialog(inst, DIALOG_SLOT_CONNECTION_FATAL, dialog); + sfree(title); +} + +static void connection_fatal_callback(void *vinst) +{ + struct gui_data *inst = (struct gui_data *)vinst; + destroy_inst_connection(inst); +} void connection_fatal(void *frontend, const char *p, ...) { @@ -177,10 +209,11 @@ void connection_fatal(void *frontend, const char *p, ...) va_start(ap, p); msg = dupvprintf(p, ap); va_end(ap); - fatal_message_box(inst->window, msg); + fatal_message_box(inst, msg); sfree(msg); - queue_toplevel_callback(exit_callback, inst); + inst->exited = TRUE; /* suppress normal exit handling */ + queue_toplevel_callback(connection_fatal_callback, frontend); } /* @@ -2062,19 +2095,9 @@ static void exit_callback(void *vinst) if (!inst->exited && (exitcode = inst->back->exitcode(inst->backhandle)) >= 0) { - inst->exited = TRUE; - close_on_exit = conf_get_int(inst->conf, CONF_close_on_exit); - if (inst->ldisc) { - ldisc_free(inst->ldisc); - inst->ldisc = NULL; - } - inst->back->free(inst->backhandle); - inst->backhandle = NULL; - inst->back = NULL; - term_provide_resize_fn(inst->term, NULL, NULL); - update_specials_menu(inst); - gtk_widget_set_sensitive(inst->restartitem, TRUE); + destroy_inst_connection(inst); + close_on_exit = conf_get_int(inst->conf, CONF_close_on_exit); if (close_on_exit == FORCE_ON || (close_on_exit == AUTO && exitcode == 0)) { gtk_widget_destroy(inst->window); @@ -2089,6 +2112,26 @@ void notify_remote_exit(void *frontend) queue_toplevel_callback(exit_callback, inst); } +static void destroy_inst_connection(struct gui_data *inst) +{ + inst->exited = TRUE; + if (inst->ldisc) { + ldisc_free(inst->ldisc); + inst->ldisc = NULL; + } + if (inst->backhandle) { + inst->back->free(inst->backhandle); + inst->backhandle = NULL; + inst->back = NULL; + } + if (inst->term) + term_provide_resize_fn(inst->term, NULL, NULL); + if (inst->menu) { + update_specials_menu(inst); + gtk_widget_set_sensitive(inst->restartitem, TRUE); + } +} + static void delete_inst(struct gui_data *inst) { int dialog_slot; @@ -2106,19 +2149,11 @@ static void delete_inst(struct gui_data *inst) gtk_widget_destroy(inst->menu); inst->menu = NULL; } - if (inst->backhandle) { - inst->back->free(inst->backhandle); - inst->backhandle = NULL; - inst->back = NULL; - } + destroy_inst_connection(inst); if (inst->term) { term_free(inst->term); inst->term = NULL; } - if (inst->ldisc) { - ldisc_free(inst->ldisc); - inst->ldisc = NULL; - } if (inst->conf) { conf_free(inst->conf); inst->conf = NULL; @@ -4517,7 +4552,7 @@ static void start_backend(struct gui_data *inst) char *msg = dupprintf("Unable to open connection to %s:\n%s", conf_dest(inst->conf), error); inst->exited = TRUE; - fatal_message_box(inst->window, msg); + fatal_message_box(inst, msg); sfree(msg); exit(0); } diff --git a/unix/unix.h b/unix/unix.h index 893f084e..cc9e71d8 100644 --- a/unix/unix.h +++ b/unix/unix.h @@ -155,6 +155,7 @@ enum DialogSlot { DIALOG_SLOT_NETWORK_PROMPT, DIALOG_SLOT_LOGFILE_PROMPT, DIALOG_SLOT_WARN_ON_CLOSE, + DIALOG_SLOT_CONNECTION_FATAL, DIALOG_SLOT_LIMIT /* must remain last */ }; void register_dialog(void *frontend, enum DialogSlot slot, GtkWidget *dialog); @@ -168,7 +169,6 @@ GtkWidget *create_config_box(const char *title, Conf *conf, int midsession, int protcfginfo, post_dialog_fn_t after, void *afterctx); #endif -void fatal_message_box(void *window, const char *msg); void nonfatal_message_box(void *window, const char *msg); void about_box(void *window); void *eventlogstuff_new(void);