]> asedeno.scripts.mit.edu Git - PuTTY.git/commitdiff
Implement `Restart Session', in both Unix and Windows PuTTY. Largely
authorSimon Tatham <anakin@pobox.com>
Sat, 14 Aug 2004 13:04:18 +0000 (13:04 +0000)
committerSimon Tatham <anakin@pobox.com>
Sat, 14 Aug 2004 13:04:18 +0000 (13:04 +0000)
because Owen questioned whether it was really easy enough to be
labelled `fun' in the bug database :-)

[originally from svn r4453]

unix/pterm.c
window.c

index f23f07b7cf1c2af2fc70fe265a3e6386faaa0a0b..04c722c3524f27000c1603d9239cf7aa01878d74 100644 (file)
@@ -44,7 +44,8 @@ struct gui_data {
     GtkWidget *window, *area, *sbar;
     GtkBox *hbox;
     GtkAdjustment *sbar_adjust;
-    GtkWidget *menu, *specialsmenu, *specialsitem1, *specialsitem2;
+    GtkWidget *menu, *specialsmenu, *specialsitem1, *specialsitem2,
+       *restartitem;
     GtkWidget *sessionsmenu;
     GdkPixmap *pixmap;
     GdkFont *fonts[4];                 /* normal, bold, wide, widebold */
@@ -94,6 +95,8 @@ static int send_raw_mouse;
 
 static char *app_name = "pterm";
 
+static void start_backend(struct gui_data *inst);
+
 char *x_get_default(const char *key)
 {
     return XGetDefault(GDK_DISPLAY(), app_name, key);
@@ -981,7 +984,8 @@ gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
             * should never matter.
             */
            output[end] = '\0';        /* NUL-terminate */
-           ldisc_send(inst->ldisc, output+start, -2, 1);
+           if (inst->ldisc)
+               ldisc_send(inst->ldisc, output+start, -2, 1);
        } else if (!inst->direct_to_font) {
            if (!use_ucsoutput) {
                /*
@@ -996,21 +1000,24 @@ gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
                 * 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 (inst->ldisc)
+                   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);
+               if (inst->ldisc)
+                   luni_send(inst->ldisc, ucsoutput+start, end-start, 1);
            }
        } else {
            /*
             * In direct-to-font mode, we just send the string
             * exactly as we received it.
             */
-           ldisc_send(inst->ldisc, output+start, end-start, 1);
+           if (inst->ldisc)
+               ldisc_send(inst->ldisc, output+start, end-start, 1);
        }
 
        show_mouseptr(inst, 0);
@@ -1134,6 +1141,17 @@ gint timer_func(gpointer data)
        if (inst->cfg.close_on_exit == FORCE_ON ||
            (inst->cfg.close_on_exit == AUTO && exitcode == 0))
            exit(0);                   /* just go. */
+       if (inst->ldisc) {
+           ldisc_free(inst->ldisc);
+           inst->ldisc = NULL;
+       }
+       if (inst->back) {
+           inst->back->free(inst->backhandle);
+           inst->backhandle = NULL;
+           inst->back = NULL;
+           update_specials_menu(inst);
+       }
+       gtk_widget_show(inst->restartitem);
     }
 
     term_update(inst->term);
@@ -2732,7 +2750,8 @@ void reset_terminal_menuitem(GtkMenuItem *item, gpointer data)
 {
     struct gui_data *inst = (struct gui_data *)data;
     term_pwron(inst->term);
-    ldisc_send(inst->ldisc, NULL, 0, 0);
+    if (inst->ldisc)
+       ldisc_send(inst->ldisc, NULL, 0, 0);
 }
 
 void copy_all_menuitem(GtkMenuItem *item, gpointer data)
@@ -2747,7 +2766,8 @@ void special_menuitem(GtkMenuItem *item, gpointer data)
     int code = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(item),
                                                   "user-data"));
 
-    inst->back->special(inst->backhandle, code);
+    if (inst->back)
+       inst->back->special(inst->backhandle, code);
 }
 
 void about_menuitem(GtkMenuItem *item, gpointer data)
@@ -2788,11 +2808,13 @@ void change_settings_menuitem(GtkMenuItem *item, gpointer data)
          * Flush the line discipline's edit buffer in the case
          * where local editing has just been disabled.
          */
-        ldisc_send(inst->ldisc, NULL, 0, 0);
+        if (inst->ldisc)
+           ldisc_send(inst->ldisc, NULL, 0, 0);
         /* Pass new config data to the terminal */
         term_reconfig(inst->term, &cfg2);
         /* Pass new config data to the back end */
-        inst->back->reconfig(inst->backhandle, &cfg2);
+        if (inst->back)
+           inst->back->reconfig(inst->backhandle, &cfg2);
 
         /*
          * Just setting inst->cfg is sufficient to cause colour
@@ -3083,6 +3105,17 @@ void new_session_menuitem(GtkMenuItem *item, gpointer data)
     fork_and_exec_self(inst, -1, NULL);
 }
 
+void restart_session_menuitem(GtkMenuItem *item, gpointer data)
+{
+    struct gui_data *inst = (struct gui_data *)data;
+
+    if (!inst->back) {
+       logevent(inst, "----- Session restarted -----");
+       start_backend(inst);
+       inst->exited = FALSE;
+    }
+}
+
 void saved_session_menuitem(GtkMenuItem *item, gpointer data)
 {
     struct gui_data *inst = (struct gui_data *)data;
@@ -3104,7 +3137,11 @@ void update_specials_menu(void *frontend)
 
     const struct telnet_special *specials;
 
-    specials = inst->back->get_specials(inst->backhandle);
+    if (inst->back)
+       specials = inst->back->get_specials(inst->backhandle);
+    else
+       specials = NULL;
+
     gtk_container_foreach(GTK_CONTAINER(inst->specialsmenu),
                          (GtkCallback)gtk_widget_destroy, NULL);
     if (specials) {
@@ -3130,9 +3167,51 @@ void update_specials_menu(void *frontend)
     }
 }
 
-int pt_main(int argc, char **argv)
+static void start_backend(struct gui_data *inst)
 {
     extern Backend *select_backend(Config *cfg);
+    char *realhost;
+    const char *error;
+
+    inst->back = select_backend(&inst->cfg);
+
+    error = inst->back->init((void *)inst, &inst->backhandle,
+                            &inst->cfg, inst->cfg.host, inst->cfg.port,
+                            &realhost, inst->cfg.tcp_nodelay,
+                            inst->cfg.tcp_keepalives);
+
+    if (error) {
+       char *msg = dupprintf("Unable to open connection to %s:\n%s",
+                             inst->cfg.host, error);
+       inst->exited = TRUE;
+       fatal_message_box(inst->window, msg);
+       sfree(msg);
+       exit(0);
+    }
+
+    if (inst->cfg.wintitle[0]) {
+       set_title(inst, inst->cfg.wintitle);
+       set_icon(inst, inst->cfg.wintitle);
+    } else {
+       char *title = make_default_wintitle(realhost);
+       set_title(inst, title);
+       set_icon(inst, title);
+       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);
+
+    inst->ldisc =
+       ldisc_create(&inst->cfg, inst->term, inst->back, inst->backhandle,
+                    inst);
+
+    gtk_widget_hide(inst->restartitem);
+}
+
+int pt_main(int argc, char **argv)
+{
     extern int cfgbox(Config *cfg);
     struct gui_data *inst;
 
@@ -3298,6 +3377,9 @@ int pt_main(int argc, char **argv)
 } while (0)
        if (new_session)
            MKMENUITEM("New Session", new_session_menuitem);
+        MKMENUITEM("Restart Session", restart_session_menuitem);
+       inst->restartitem = menuitem;
+       gtk_widget_hide(inst->restartitem);
         MKMENUITEM("Duplicate Session", dup_session_menuitem);
        if (saved_sessions) {
            struct sesslist sesslist;
@@ -3363,42 +3445,8 @@ int pt_main(int argc, char **argv)
 
     term_size(inst->term, inst->cfg.height, inst->cfg.width, inst->cfg.savelines);
 
-    inst->back = select_backend(&inst->cfg);
-    {
-       char *realhost;
-       const char *error;
-
-       error = inst->back->init((void *)inst, &inst->backhandle,
-                                 &inst->cfg, inst->cfg.host, inst->cfg.port,
-                                 &realhost, inst->cfg.tcp_nodelay,
-                                inst->cfg.tcp_keepalives);
-
-       if (error) {
-           char *msg = dupprintf("Unable to open connection to %s:\n%s",
-                                  inst->cfg.host, error);
-            inst->exited = TRUE;
-           fatal_message_box(inst->window, msg);
-            sfree(msg);
-           return 0;
-       }
-
-        if (inst->cfg.wintitle[0]) {
-            set_title(inst, inst->cfg.wintitle);
-            set_icon(inst, inst->cfg.wintitle);
-       } else {
-            char *title = make_default_wintitle(realhost);
-            set_title(inst, title);
-            set_icon(inst, title);
-            sfree(title);
-        }
-    }
-    inst->back->provide_logctx(inst->backhandle, inst->logctx);
-    update_specials_menu(inst);
+    start_backend(inst);
 
-    term_provide_resize_fn(inst->term, inst->back->size, inst->backhandle);
-
-    inst->ldisc =
-       ldisc_create(&inst->cfg, inst->term, inst->back, inst->backhandle, inst);
     ldisc_send(inst->ldisc, NULL, 0, 0);/* cause ldisc to notice changes */
 
     /* now we're reday to deal with the child exit handler being
index 1c724e2fd509f6262bf7362a9ad413f748831d3b..4cb6003071940e5cbde793b17a5e72f4c2cecc8a 100644 (file)
--- a/window.c
+++ b/window.c
 #define IDM_SHOWLOG   0x0010
 #define IDM_NEWSESS   0x0020
 #define IDM_DUPSESS   0x0030
-#define IDM_RECONF    0x0040
-#define IDM_CLRSB     0x0050
-#define IDM_RESET     0x0060
+#define IDM_RESTART   0x0040
+#define IDM_RECONF    0x0050
+#define IDM_CLRSB     0x0060
+#define IDM_RESET     0x0070
 #define IDM_HELP      0x0140
 #define IDM_ABOUT     0x0150
 #define IDM_SAVEDSESS 0x0160
@@ -182,6 +183,110 @@ void ldisc_update(void *frontend, int echo, int edit)
 {
 }
 
+static void start_backend(void)
+{
+    const char *error;
+    char msg[1024], *title;
+    char *realhost;
+    int i;
+
+    /*
+     * Select protocol. This is farmed out into a table in a
+     * separate file to enable an ssh-free variant.
+     */
+    back = NULL;
+    for (i = 0; backends[i].backend != NULL; i++)
+       if (backends[i].protocol == cfg.protocol) {
+           back = backends[i].backend;
+           break;
+       }
+    if (back == NULL) {
+       char *str = dupprintf("%s Internal Error", appname);
+       MessageBox(NULL, "Unsupported protocol number found",
+                  str, MB_OK | MB_ICONEXCLAMATION);
+       sfree(str);
+       cleanup_exit(1);
+    }
+
+    error = back->init(NULL, &backhandle, &cfg,
+                      cfg.host, cfg.port, &realhost, cfg.tcp_nodelay,
+                      cfg.tcp_keepalives);
+    back->provide_logctx(backhandle, logctx);
+    if (error) {
+       char *str = dupprintf("%s Error", appname);
+       sprintf(msg, "Unable to open connection to\n"
+               "%.800s\n" "%s", cfg.host, error);
+       MessageBox(NULL, msg, str, MB_ICONERROR | MB_OK);
+       sfree(str);
+       exit(0);
+    }
+    window_name = icon_name = NULL;
+    if (*cfg.wintitle) {
+       title = cfg.wintitle;
+    } else {
+       sprintf(msg, "%s - %s", realhost, appname);
+       title = msg;
+    }
+    sfree(realhost);
+    set_title(NULL, title);
+    set_icon(NULL, title);
+
+    /*
+     * Connect the terminal to the backend for resize purposes.
+     */
+    term_provide_resize_fn(term, back->size, backhandle);
+
+    /*
+     * Set up a line discipline.
+     */
+    ldisc = ldisc_create(&cfg, term, back, backhandle, NULL);
+
+    /*
+     * Destroy the Restart Session menu item. (This will return
+     * failure if it's already absent, as it will be the very first
+     * time we call this function. We ignore that, because as long
+     * as the menu item ends up not being there, we don't care
+     * whether it was us who removed it or not!)
+     */
+    for (i = 0; i < lenof(popup_menus); i++) {
+       DeleteMenu(popup_menus[i].menu, IDM_RESTART, MF_BYCOMMAND);
+    }
+
+    session_closed = FALSE;
+}
+
+static void close_session(void)
+{
+    char morestuff[100];
+    int i;
+
+    session_closed = TRUE;
+    sprintf(morestuff, "%.70s (inactive)", appname);
+    set_icon(NULL, morestuff);
+    set_title(NULL, morestuff);
+
+    if (ldisc) {
+       ldisc_free(ldisc);
+       ldisc = NULL;
+    }
+    if (back) {
+       back->free(backhandle);
+       backhandle = NULL;
+       back = NULL;
+       update_specials_menu(NULL);
+    }
+
+    /*
+     * Show the Restart Session menu item. Do a precautionary
+     * delete first to ensure we never end up with more than one.
+     */
+    for (i = 0; i < lenof(popup_menus); i++) {
+       DeleteMenu(popup_menus[i].menu, IDM_RESTART, MF_BYCOMMAND);
+       InsertMenu(popup_menus[i].menu, IDM_DUPSESS, MF_BYCOMMAND | MF_ENABLED,
+                  IDM_RESTART, "&Restart Session");
+    }
+}
+
 int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
 {
     WNDCLASS wndclass;
@@ -452,27 +557,6 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
        }
     }
 
-    /*
-     * Select protocol. This is farmed out into a table in a
-     * separate file to enable an ssh-free variant.
-     */
-    {
-       int i;
-       back = NULL;
-       for (i = 0; backends[i].backend != NULL; i++)
-           if (backends[i].protocol == cfg.protocol) {
-               back = backends[i].backend;
-               break;
-           }
-       if (back == NULL) {
-           char *str = dupprintf("%s Internal Error", appname);
-           MessageBox(NULL, "Unsupported protocol number found",
-                      str, MB_OK | MB_ICONEXCLAMATION);
-           sfree(str);
-           cleanup_exit(1);
-       }
-    }
-
     /* Check for invalid Port number (i.e. zero) */
     if (cfg.port == 0) {
        char *str = dupprintf("%s Internal Error", appname);
@@ -602,49 +686,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
        SetScrollInfo(hwnd, SB_VERT, &si, FALSE);
     }
 
-    /*
-     * Start up the telnet connection.
-     */
-    {
-       const char *error;
-       char msg[1024], *title;
-       char *realhost;
-
-       error = back->init(NULL, &backhandle, &cfg,
-                          cfg.host, cfg.port, &realhost, cfg.tcp_nodelay,
-                          cfg.tcp_keepalives);
-       back->provide_logctx(backhandle, logctx);
-       if (error) {
-           char *str = dupprintf("%s Error", appname);
-           sprintf(msg, "Unable to open connection to\n"
-                   "%.800s\n" "%s", cfg.host, error);
-           MessageBox(NULL, msg, str, MB_ICONERROR | MB_OK);
-           sfree(str);
-           return 0;
-       }
-       window_name = icon_name = NULL;
-       if (*cfg.wintitle) {
-           title = cfg.wintitle;
-       } else {
-           sprintf(msg, "%s - %s", realhost, appname);
-           title = msg;
-       }
-       sfree(realhost);
-       set_title(NULL, title);
-       set_icon(NULL, title);
-    }
-
-    /*
-     * Connect the terminal to the backend for resize purposes.
-     */
-    term_provide_resize_fn(term, back->size, backhandle);
-
-    /*
-     * Set up a line discipline.
-     */
-    ldisc = ldisc_create(&cfg, term, back, backhandle, NULL);
-
-    session_closed = FALSE;
+    start_backend();
 
     /*
      * Prepare the mouse handler.
@@ -865,13 +907,17 @@ char *do_select(SOCKET skt, int startup)
  */
 void update_specials_menu(void *frontend)
 {
-    HMENU m = GetSystemMenu(hwnd, FALSE);
+    HMENU p;
     int menu_already_exists = (specials != NULL);
     int i, j;
 
-    specials = back->get_specials(backhandle);
+    if (back)
+       specials = back->get_specials(backhandle);
+    else
+       specials = NULL;
+
     if (specials) {
-       HMENU p = CreateMenu();
+       p = CreateMenu();
        for (i = 0; specials[i].name; i++) {
            assert(IDM_SPECIAL_MIN + 0x10 * i < IDM_SPECIAL_MAX);
            if (*specials[i].name)
@@ -880,15 +926,22 @@ void update_specials_menu(void *frontend)
            else
                AppendMenu(p, MF_SEPARATOR, 0, 0);
        }
-       for (j = 0; j < lenof(popup_menus); j++) {
-           if (menu_already_exists)
-               DeleteMenu(popup_menus[j].menu,
-                          popup_menus[j].specials_submenu_pos,
-                          MF_BYPOSITION);
-           else
-               InsertMenu(popup_menus[j].menu,
-                          popup_menus[j].specials_submenu_pos,
-                          MF_BYPOSITION | MF_SEPARATOR, 0, 0);
+    } else
+       p = NULL;
+
+    for (j = 0; j < lenof(popup_menus); j++) {
+       if (menu_already_exists) {
+           DeleteMenu(popup_menus[j].menu,
+                      popup_menus[j].specials_submenu_pos,
+                      MF_BYPOSITION);
+           DeleteMenu(popup_menus[j].menu,
+                      popup_menus[j].specials_submenu_pos,
+                      MF_BYPOSITION);
+       }
+       if (specials) {
+           InsertMenu(popup_menus[j].menu,
+                      popup_menus[j].specials_submenu_pos,
+                      MF_BYPOSITION | MF_SEPARATOR, 0, 0);
            InsertMenu(popup_menus[j].menu,
                       popup_menus[j].specials_submenu_pos,
                       MF_BYPOSITION | MF_POPUP | MF_ENABLED,
@@ -925,10 +978,7 @@ void connection_fatal(void *frontend, char *fmt, ...)
     if (cfg.close_on_exit == FORCE_ON)
        PostQuitMessage(1);
     else {
-       session_closed = TRUE;
-       sprintf(morestuff, "%.70s (inactive)", appname);
-       set_icon(NULL, morestuff);
-       set_title(NULL, morestuff);
+       close_session();
     }
 }
 
@@ -973,11 +1023,8 @@ static void enact_pending_netevent(void)
        if (cfg.close_on_exit == FORCE_ON ||
            cfg.close_on_exit == AUTO) PostQuitMessage(0);
        else {
-           char morestuff[100];
+           close_session();
            session_closed = TRUE;
-           sprintf(morestuff, "%.70s (inactive)", appname);
-           set_icon(NULL, morestuff);
-           set_title(NULL, morestuff);
            MessageBox(hwnd, "Connection closed by remote host",
                       appname, MB_OK | MB_ICONINFORMATION);
        }
@@ -1738,7 +1785,8 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
            time_t now;
            time(&now);
            if (now - last_movement > cfg.ping_interval) {
-               back->special(backhandle, TS_PING);
+               if (back)
+                   back->special(backhandle, TS_PING);
                last_movement = now;
            }
        }
@@ -1840,6 +1888,13 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
                if (freecl)
                    sfree(cl);
            }
+           break;
+         case IDM_RESTART:
+           if (!back) {
+               logevent(NULL, "----- Session restarted -----");
+               start_backend();
+           }
+
            break;
          case IDM_RECONF:
            {
@@ -1873,7 +1928,8 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
                 * Flush the line discipline's edit buffer in the
                 * case where local editing has just been disabled.
                 */
-               ldisc_send(ldisc, NULL, 0, 0);
+               if (ldisc)
+                   ldisc_send(ldisc, NULL, 0, 0);
                if (pal)
                    DeleteObject(pal);
                logpal = NULL;
@@ -1885,7 +1941,8 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
                term_reconfig(term, &cfg);
 
                /* Pass new config data to the back end */
-               back->reconfig(backhandle, &cfg);
+               if (back)
+                   back->reconfig(backhandle, &cfg);
 
                /* Screen size changed ? */
                if (cfg.height != prev_cfg.height ||
@@ -1993,7 +2050,8 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
            break;
          case IDM_RESET:
            term_pwron(term);
-           ldisc_send(ldisc, NULL, 0, 0);
+           if (ldisc)
+               ldisc_send(ldisc, NULL, 0, 0);
            break;
          case IDM_ABOUT:
            showabout(hwnd);
@@ -2041,7 +2099,8 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
                    if (!specials || !specials[j].name)
                        break;
                if (j == i) {
-                   back->special(backhandle, specials[i].code);
+                   if (back)
+                       back->special(backhandle, specials[i].code);
                    net_pending_errors();
                }
            }
@@ -2613,7 +2672,8 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
                     * we're sent.
                     */
                    term_seen_key_event(term);
-                   ldisc_send(ldisc, buf, len, 1);
+                   if (ldisc)
+                       ldisc_send(ldisc, buf, len, 1);
                    show_mouseptr(0);
                }
            }
@@ -2661,7 +2721,8 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
                 */
                term_seen_key_event(term);
                for (i = 0; i < n; i += 2) {
-                   luni_send(ldisc, (unsigned short *)(buff+i), 1, 1);
+                   if (ldisc)
+                       luni_send(ldisc, (unsigned short *)(buff+i), 1, 1);
                }
                free(buff);
            }
@@ -2676,11 +2737,13 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
            buf[1] = wParam;
            buf[0] = wParam >> 8;
            term_seen_key_event(term);
-           lpage_send(ldisc, kbd_codepage, buf, 2, 1);
+           if (ldisc)
+               lpage_send(ldisc, kbd_codepage, buf, 2, 1);
        } else {
            char c = (unsigned char) wParam;
            term_seen_key_event(term);
-           lpage_send(ldisc, kbd_codepage, &c, 1, 1);
+           if (ldisc)
+               lpage_send(ldisc, kbd_codepage, &c, 1, 1);
        }
        return (0);
       case WM_CHAR:
@@ -2694,7 +2757,8 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
        {
            char c = (unsigned char)wParam;
            term_seen_key_event(term);
-           lpage_send(ldisc, CP_ACP, &c, 1, 1);
+           if (ldisc)
+               lpage_send(ldisc, CP_ACP, &c, 1, 1);
        }
        return 0;
       case WM_SETCURSOR:
@@ -3990,7 +4054,8 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam,
                    }
                    keybuf = nc;
                    term_seen_key_event(term);
-                   luni_send(ldisc, &keybuf, 1, 1);
+                   if (ldisc)
+                       luni_send(ldisc, &keybuf, 1, 1);
                    continue;
                }
 
@@ -4001,7 +4066,8 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam,
                        if (in_utf(term) || ucsdata.dbcs_screenfont) {
                            keybuf = alt_sum;
                            term_seen_key_event(term);
-                           luni_send(ldisc, &keybuf, 1, 1);
+                           if (ldisc)
+                               luni_send(ldisc, &keybuf, 1, 1);
                        } else {
                            ch = (char) alt_sum;
                            /*
@@ -4014,12 +4080,14 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam,
                             * everything we're sent.
                             */
                            term_seen_key_event(term);
-                           ldisc_send(ldisc, &ch, 1, 1);
+                           if (ldisc)
+                               ldisc_send(ldisc, &ch, 1, 1);
                        }
                        alt_sum = 0;
                    } else {
                        term_seen_key_event(term);
-                       lpage_send(ldisc, kbd_codepage, &ch, 1, 1);
+                       if (ldisc)
+                           lpage_send(ldisc, kbd_codepage, &ch, 1, 1);
                    }
                } else {
                    if(capsOn && ch < 0x80) {
@@ -4027,14 +4095,16 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam,
                        cbuf[0] = 27;
                        cbuf[1] = xlat_uskbd2cyrllic(ch);
                        term_seen_key_event(term);
-                       luni_send(ldisc, cbuf+!left_alt, 1+!!left_alt, 1);
+                       if (ldisc)
+                           luni_send(ldisc, cbuf+!left_alt, 1+!!left_alt, 1);
                    } else {
                        char cbuf[2];
                        cbuf[0] = '\033';
                        cbuf[1] = ch;
                        term_seen_key_event(term);
-                       lpage_send(ldisc, kbd_codepage,
-                                  cbuf+!left_alt, 1+!!left_alt, 1);
+                       if (ldisc)
+                           lpage_send(ldisc, kbd_codepage,
+                                      cbuf+!left_alt, 1+!!left_alt, 1);
                    }
                }
                show_mouseptr(0);