]> asedeno.scripts.mit.edu Git - PuTTY.git/commitdiff
Further merges from trunk: Jacob's specials menu work, Jacob's extra
authorSimon Tatham <anakin@pobox.com>
Sun, 24 Oct 2004 13:29:03 +0000 (13:29 +0000)
committerSimon Tatham <anakin@pobox.com>
Sun, 24 Oct 2004 13:29:03 +0000 (13:29 +0000)
-N docs, my environment variables patch, and my UTF-8 locale
override mechanism in Unix PuTTY/pterm.

[originally from svn r4673]

16 files changed:
config.c
doc/config.but
doc/man-pl.but
doc/plink.but
plink.c
putty.h
settings.c
ssh.c
telnet.c
unix/pterm.c
unix/pty.c
unix/unix.h
unix/uxcfg.c
unix/uxplink.c
unix/uxucs.c
window.c

index 8588b23c31530764a5399148ab7e67f1a50226b7..7898c7a8b45575d787abc9594387f857179a24bc 100644 (file)
--- a/config.c
+++ b/config.c
@@ -1288,6 +1288,36 @@ void setup_config_box(struct controlbox *b, struct sesslist *sesslist,
                         HELPCTX(connection_username),
                         dlg_stdeditbox_handler, I(offsetof(Config,username)),
                         I(sizeof(((Config *)0)->username)));
+
+           ctrl_text(s, "Environment variables:", HELPCTX(telnet_environ));
+           ctrl_columns(s, 2, 80, 20);
+           ed = (struct environ_data *)
+               ctrl_alloc(b, sizeof(struct environ_data));
+           ed->varbox = ctrl_editbox(s, "Variable", 'v', 60,
+                                     HELPCTX(telnet_environ),
+                                     environ_handler, P(ed), P(NULL));
+           ed->varbox->generic.column = 0;
+           ed->valbox = ctrl_editbox(s, "Value", 'l', 60,
+                                     HELPCTX(telnet_environ),
+                                     environ_handler, P(ed), P(NULL));
+           ed->valbox->generic.column = 0;
+           ed->addbutton = ctrl_pushbutton(s, "Add", 'd',
+                                           HELPCTX(telnet_environ),
+                                           environ_handler, P(ed));
+           ed->addbutton->generic.column = 1;
+           ed->rembutton = ctrl_pushbutton(s, "Remove", 'r',
+                                           HELPCTX(telnet_environ),
+                                           environ_handler, P(ed));
+           ed->rembutton->generic.column = 1;
+           ctrl_columns(s, 1, 100);
+           ed->listbox = ctrl_listbox(s, NULL, NO_SHORTCUT,
+                                      HELPCTX(telnet_environ),
+                                      environ_handler, P(ed));
+           ed->listbox->listbox.height = 3;
+           ed->listbox->listbox.ncols = 2;
+           ed->listbox->listbox.percentages = snewn(2, int);
+           ed->listbox->listbox.percentages[0] = 30;
+           ed->listbox->listbox.percentages[1] = 70;
        }
 
        s = ctrl_getset(b, "Connection", "keepalive",
@@ -1389,40 +1419,6 @@ void setup_config_box(struct controlbox *b, struct sesslist *sesslist,
        ctrl_settitle(b, "Connection/Telnet",
                      "Options controlling Telnet connections");
 
-       if (!midsession) {
-           s = ctrl_getset(b, "Connection/Telnet", "data",
-                           "Data to send to the server");
-           ctrl_text(s, "Environment variables:", HELPCTX(telnet_environ));
-           ctrl_columns(s, 2, 80, 20);
-           ed = (struct environ_data *)
-               ctrl_alloc(b, sizeof(struct environ_data));
-           ed->varbox = ctrl_editbox(s, "Variable", 'v', 60,
-                                     HELPCTX(telnet_environ),
-                                     environ_handler, P(ed), P(NULL));
-           ed->varbox->generic.column = 0;
-           ed->valbox = ctrl_editbox(s, "Value", 'l', 60,
-                                     HELPCTX(telnet_environ),
-                                     environ_handler, P(ed), P(NULL));
-           ed->valbox->generic.column = 0;
-           ed->addbutton = ctrl_pushbutton(s, "Add", 'd',
-                                           HELPCTX(telnet_environ),
-                                           environ_handler, P(ed));
-           ed->addbutton->generic.column = 1;
-           ed->rembutton = ctrl_pushbutton(s, "Remove", 'r',
-                                           HELPCTX(telnet_environ),
-                                           environ_handler, P(ed));
-           ed->rembutton->generic.column = 1;
-           ctrl_columns(s, 1, 100);
-           ed->listbox = ctrl_listbox(s, NULL, NO_SHORTCUT,
-                                      HELPCTX(telnet_environ),
-                                      environ_handler, P(ed));
-           ed->listbox->listbox.height = 3;
-           ed->listbox->listbox.ncols = 2;
-           ed->listbox->listbox.percentages = snewn(2, int);
-           ed->listbox->listbox.percentages[0] = 30;
-           ed->listbox->listbox.percentages[1] = 70;
-       }
-
        s = ctrl_getset(b, "Connection/Telnet", "protocol",
                        "Telnet protocol adjustments");
 
index 994caeec36f3db5a99d8f3995d4b480c03f46063..6fb95b6b9f553e7f6e8f3233cb19e20389678027 100644 (file)
@@ -1,4 +1,4 @@
-\versionid $Id: config.but,v 1.92.2.1 2004/10/24 13:21:11 simon Exp $
+\versionid $Id: config.but,v 1.92.2.2 2004/10/24 13:29:02 simon Exp $
 
 \C{config} Configuring PuTTY
 
@@ -1502,6 +1502,30 @@ it explicitly every time. (Some Telnet servers don't support this.)
 
 In this box you can type that user name.
 
+\S{config-environ} Setting environment variables on the server
+
+\cfg{winhelp-topic}{telnet.environ}
+
+The Telnet protocol provides a means for the client to pass
+environment variables to the server. Many Telnet servers have
+stopped supporting this feature due to security flaws, but PuTTY
+still supports it for the benefit of any servers which have found
+other ways around the security problems than just disabling the
+whole mechanism.
+
+Version 2 of the SSH protocol also provides a similar mechanism,
+which is easier to implement without security flaws. Newer SSH2
+servers are more likely to support it than older ones.
+
+This configuration data is not used in the SSHv1, rlogin or raw
+protocols.
+
+To add an environment variable to the list transmitted down the
+connection, you enter the variable name in the \q{Variable} box,
+enter its value in the \q{Value} box, and press the \q{Add} button.
+To remove one from the list, select it in the list box and press
+\q{Remove}.
+
 \S{config-keepalive} Using keepalives to prevent disconnection
 
 \cfg{winhelp-topic}{connection.keepalive}
@@ -1768,23 +1792,6 @@ configuration fields will be ignored.
 The Telnet panel allows you to configure options that only apply to
 Telnet sessions.
 
-\S{config-environ} Setting environment variables on the server
-
-\cfg{winhelp-topic}{telnet.environ}
-
-The Telnet protocol provides a means for the client to pass
-environment variables to the server. Many Telnet servers have
-stopped supporting this feature due to security flaws, but PuTTY
-still supports it for the benefit of any servers which have found
-other ways around the security problems than just disabling the
-whole mechanism.
-
-To add an environment variable to the list transmitted down the
-connection, you enter the variable name in the \q{Variable} box,
-enter its value in the \q{Value} box, and press the \q{Add} button.
-To remove one from the list, select it in the list box and press
-\q{Remove}.
-
 \S{config-oldenviron} \q{Handling of OLD_ENVIRON ambiguity}
 
 \cfg{winhelp-topic}{telnet.oldenviron}
index 1f34dc1a7f845eb2907c1fc9980f0aefdaf114c0..cf0d4194f183b6fa32cd42088d08f8d69e27eb70 100644 (file)
@@ -136,6 +136,10 @@ tunnel all their connections. Only works in SSH.
 
 \dd Remote command is SSH subsystem (SSH-2 only).
 
+\dt \cw{-N}
+
+\dd Don't start a remote command or shell at all (SSH-2 only).
+
 \S{plink-manpage-more-information} MORE INFORMATION
 
 For more information on plink, it's probably best to go and look at
index 3741645647344d6f07852397c8edc599242db394..74974ce51a262ba98362e52f8a1a92c406fc7129 100644 (file)
@@ -1,4 +1,4 @@
-\versionid $Id: plink.but,v 1.25 2004/08/19 13:14:55 jacob Exp $
+\versionid $Id: plink.but,v 1.25.2.1 2004/10/24 13:29:02 simon Exp $
 
 \C{plink} Using the command-line connection tool Plink
 
@@ -71,6 +71,7 @@ use Plink:
 \c   -C        enable compression
 \c   -i key    private key file for authentication
 \c   -s        remote command is an SSH subsystem (SSH-2 only)
+\c   -N        don't start a shell/command (SSH-2 only)
 
 Once this works, you are ready to use Plink.
 
diff --git a/plink.c b/plink.c
index f6e2a70243f0944ec5660038034924df672e256d..b99646af63b273c223d1d31f8f13c38fe5ff63cf 100644 (file)
--- a/plink.c
+++ b/plink.c
@@ -234,6 +234,7 @@ static void usage(void)
     printf("  -C        enable compression\n");
     printf("  -i key    private key file for authentication\n");
     printf("  -s        remote command is an SSH subsystem (SSH-2 only)\n");
+    printf("  -N        don't start a shell/command (SSH-2 only)\n");
     exit(1);
 }
 
diff --git a/putty.h b/putty.h
index bc7782544e864b5351651bc44cbd0fb5bc939389..34a7a76002c50bdbe7610ff253bd69b87fdb74e1 100644 (file)
--- a/putty.h
+++ b/putty.h
@@ -450,6 +450,7 @@ struct config_tag {
     /* translations */
     int vtmode;
     char line_codepage[128];
+    int utf8_override;
     int xlat_capslockcyr;
     /* X11 forwarding */
     int x11_forward;
@@ -562,6 +563,10 @@ void sys_cursor(void *frontend, int x, int y);
 void request_paste(void *frontend);
 void frontend_keypress(void *frontend);
 void ldisc_update(void *frontend, int echo, int edit);
+/* It's the backend's responsibility to invoke this at the start of a
+ * connection, if necessary; it can also invoke it later if the set of
+ * special commands changes. It does not need to invoke it at session
+ * shutdown. */
 void update_specials_menu(void *frontend);
 int from_backend(void *frontend, int is_stderr, const char *data, int len);
 #define OPTIMISE_IS_SCROLL 1
index b0f223e97540dc15df88cd2d091f2f873843049a..a8f709172ac600c0758a72d2908ef00820625853 100644 (file)
@@ -314,6 +314,7 @@ void save_open_settings(void *sesskey, int do_host, Config *cfg)
        write_setting_s(sesskey, buf, buf2);
     }
     write_setting_s(sesskey, "LineCodePage", cfg->line_codepage);
+    write_setting_i(sesskey, "UTF8Override", cfg->utf8_override);
     write_setting_s(sesskey, "Printer", cfg->printer);
     write_setting_i(sesskey, "CapsLockCyr", cfg->xlat_capslockcyr);
     write_setting_i(sesskey, "ScrollBar", cfg->scrollbar);
@@ -608,6 +609,7 @@ void load_open_settings(void *sesskey, int do_host, Config *cfg)
      */
     gpps(sesskey, "LineCodePage", "", cfg->line_codepage,
         sizeof(cfg->line_codepage));
+    gppi(sesskey, "UTF8Override", 1, &cfg->utf8_override);
     gpps(sesskey, "Printer", "", cfg->printer, sizeof(cfg->printer));
     gppi (sesskey, "CapsLockCyr", 0, &cfg->xlat_capslockcyr);
     gppi(sesskey, "ScrollBar", 1, &cfg->scrollbar);
diff --git a/ssh.c b/ssh.c
index 8356a075b184cec79927f54a9437e9cb9cadb4bd..4fed0b8c8ff57ed393d620a6edeeb9b23b82c0de 100644 (file)
--- a/ssh.c
+++ b/ssh.c
@@ -4788,6 +4788,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt)
        int siglen, retlen, len;
        char *q, *agentreq, *ret;
        int try_send;
+       int num_env, env_left, env_ok;
     };
     crState(do_ssh2_authconn_state);
 
@@ -5645,6 +5646,7 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt)
        ssh->mainchan->v.v2.remmaxpkt = ssh_pkt_getuint32(ssh);
        bufchain_init(&ssh->mainchan->v.v2.outbuffer);
        add234(ssh->channels, ssh->mainchan);
+       update_specials_menu(ssh->frontend);
        logevent("Opened channel for session");
     } else
        ssh->mainchan = NULL;
@@ -5953,6 +5955,82 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt)
        ssh->editing = ssh->echoing = 1;
     }
 
+    /*
+     * Send environment variables.
+     * 
+     * Simplest thing here is to send all the requests at once, and
+     * then wait for a whole bunch of successes or failures.
+     */
+    if (ssh->mainchan && *ssh->cfg.environmt) {
+       char *e = ssh->cfg.environmt;
+       char *var, *varend, *val;
+
+       s->num_env = 0;
+
+       while (*e) {
+           var = e;
+           while (*e && *e != '\t') e++;
+           varend = e;
+           if (*e == '\t') e++;
+           val = e;
+           while (*e) e++;
+           e++;
+
+           ssh2_pkt_init(ssh, SSH2_MSG_CHANNEL_REQUEST);
+           ssh2_pkt_adduint32(ssh, ssh->mainchan->remoteid);
+           ssh2_pkt_addstring(ssh, "env");
+           ssh2_pkt_addbool(ssh, 1);          /* want reply */
+           ssh2_pkt_addstring_start(ssh);
+           ssh2_pkt_addstring_data(ssh, var, varend-var);
+           ssh2_pkt_addstring(ssh, val);
+           ssh2_pkt_send(ssh);
+
+           s->num_env++;
+       }
+
+       logeventf(ssh, "Sent %d environment variables", s->num_env);
+
+       s->env_ok = 0;
+       s->env_left = s->num_env;
+
+       while (s->env_left > 0) {
+           do {
+               crWaitUntilV(ispkt);
+               if (ssh->pktin.type == SSH2_MSG_CHANNEL_WINDOW_ADJUST) {
+                   unsigned i = ssh_pkt_getuint32(ssh);
+                   struct ssh_channel *c;
+                   c = find234(ssh->channels, &i, ssh_channelfind);
+                   if (!c)
+                       continue;              /* nonexistent channel */
+                   c->v.v2.remwindow += ssh_pkt_getuint32(ssh);
+               }
+           } while (ssh->pktin.type == SSH2_MSG_CHANNEL_WINDOW_ADJUST);
+
+           if (ssh->pktin.type != SSH2_MSG_CHANNEL_SUCCESS) {
+               if (ssh->pktin.type != SSH2_MSG_CHANNEL_FAILURE) {
+                   bombout(("Unexpected response to environment request:"
+                            " packet type %d", ssh->pktin.type));
+                   crStopV;
+               }
+           } else {
+               s->env_ok++;
+           }
+
+           s->env_left--;
+       }
+
+       if (s->env_ok == s->num_env) {
+           logevent("All environment variables successfully set");
+       } else if (s->env_ok == 0) {
+           logevent("All environment variables refused");
+           c_write_str(ssh, "Server refused to set environment variables\r\n");
+       } else {
+           logeventf(ssh, "%d environment variables refused",
+                     s->num_env - s->env_ok);
+           c_write_str(ssh, "Server refused to set all environment variables\r\n");
+       }
+    }
+
     /*
      * Start a shell or a remote command. We may have to attempt
      * this twice if the config data has provided a second choice
@@ -6150,7 +6228,9 @@ static void do_ssh2_authconn(Ssh ssh, unsigned char *in, int inlen, int ispkt)
                /* Do pre-close processing on the channel. */
                switch (c->type) {
                  case CHAN_MAINSESSION:
-                   break;             /* nothing to see here, move along */
+                   ssh->mainchan = NULL;
+                   update_specials_menu(ssh->frontend);
+                   break;
                  case CHAN_X11:
                    if (c->u.x11.s != NULL)
                        x11_close(c->u.x11.s);
@@ -6801,23 +6881,49 @@ static void ssh_size(void *handle, int width, int height)
  */
 static const struct telnet_special *ssh_get_specials(void *handle)
 {
+    static const struct telnet_special ignore_special[] = {
+       {"IGNORE message", TS_NOP},
+    };
+    static const struct telnet_special ssh2_session_specials[] = {
+       {"", 0},
+       {"Break", TS_BRK}
+       /* XXX we should also support signals */
+    };
+    static const struct telnet_special specials_end[] = {
+       {NULL, 0}
+    };
+    static struct telnet_special ssh_specials[lenof(ignore_special) +
+                                             lenof(ssh2_session_specials) +
+                                             lenof(specials_end)];
     Ssh ssh = (Ssh) handle;
+    int i = 0;
+#define ADD_SPECIALS(name) \
+    do { \
+       assert((i + lenof(name)) <= lenof(ssh_specials)); \
+       memcpy(&ssh_specials[i], name, sizeof name); \
+       i += lenof(name); \
+    } while(0)
 
     if (ssh->version == 1) {
-       static const struct telnet_special ssh1_specials[] = {
-           {"IGNORE message", TS_NOP},
-           {NULL, 0}
-       };
-       return ssh1_specials;
+       /* Don't bother offering IGNORE if we've decided the remote
+        * won't cope with it, since we wouldn't bother sending it if
+        * asked anyway. */
+       if (!(ssh->remote_bugs & BUG_CHOKES_ON_SSH1_IGNORE))
+           ADD_SPECIALS(ignore_special);
     } else if (ssh->version == 2) {
-       static const struct telnet_special ssh2_specials[] = {
-           {"Break", TS_BRK},
-           {"IGNORE message", TS_NOP},
-           {NULL, 0}
-       };
-       return ssh2_specials;
-    } else
+       /* XXX add rekey, when implemented */
+       ADD_SPECIALS(ignore_special);
+       if (ssh->mainchan)
+           ADD_SPECIALS(ssh2_session_specials);
+    } /* else we're not ready yet */
+
+    if (i) {
+       ADD_SPECIALS(specials_end);
+       return ssh_specials;
+    } else {
        return NULL;
+    }
+#undef ADD_SPECIALS
 }
 
 /*
index 5b3404888157793b9b841114cbd3c12aa6226136..540c6d2c3b2240859cc75cc308ab727542ae8cac 100644 (file)
--- a/telnet.c
+++ b/telnet.c
@@ -762,6 +762,11 @@ static const char *telnet_init(void *frontend_handle, void **backend_handle,
      */
     telnet->in_synch = FALSE;
 
+    /*
+     * We can send special commands from the start.
+     */
+    update_specials_menu(telnet->frontend);
+
     return NULL;
 }
 
index 56130c995ef1c6fb841cda4478a50c6d7a2d91e0..79ebc70a18139a744e81ad60763f3870a533e629 100644 (file)
@@ -2721,8 +2721,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);
 }
 
@@ -3201,7 +3201,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);
 
@@ -3420,6 +3419,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);
index 0be58fb6d4ca22d97bb50e9ffef1e1a6be1d167d..61b9d03a4ab4f503bd1680211c46a661a1a8b092 100644 (file)
@@ -590,6 +590,29 @@ static const char *pty_init(void *frontend, void **backend_handle, Config *cfg,
            sprintf(windowid_env_var, "WINDOWID=%ld", windowid);
            putenv(windowid_env_var);
        }
+       {
+           char *e = cfg->environmt;
+           char *var, *varend, *val, *varval;
+           while (*e) {
+               var = e;
+               while (*e && *e != '\t') e++;
+               varend = e;
+               if (*e == '\t') e++;
+               val = e;
+               while (*e) e++;
+               e++;
+
+               varval = dupprintf("%.*s=%s", varend-var, var, val);
+               putenv(varval);
+               /*
+                * We must not free varval, since putenv links it
+                * into the environment _in place_. Weird, but
+                * there we go. Memory usage will be rationalised
+                * as soon as we exec anyway.
+                */
+           }
+       }
+
        /*
         * SIGINT and SIGQUIT may have been set to ignored by our
         * parent, particularly by things like sh -c 'pterm &' and
index f12f576d5608acc7700ac5790d7edd69949276f0..384789aa1acf090c0fcbca89d0f003d275537751 100644 (file)
@@ -118,8 +118,8 @@ void (*putty_signal(int sig, void (*func)(int)))(int);
  * Exports from unicode.c.
  */
 struct unicode_data;
-int init_ucs(struct unicode_data *ucsdata,
-            char *line_codepage, int font_charset, int vtmode);
+int init_ucs(struct unicode_data *ucsdata, char *line_codepage,
+            int utf8_override, int font_charset, int vtmode);
 
 /*
  * Spare function exported directly from uxnet.c.
index 813009ef563f1a5b8cf7e065d4ae23aa10685315..fff29680221b572f4c5b360b6ba22d24b52b1565 100644 (file)
@@ -129,6 +129,21 @@ void unix_setup_config_box(struct controlbox *b, int midsession, void *win)
                 HELPCTX(no_help), dlg_stdeditbox_handler,
                  I(offsetof(Config,shadowboldoffset)), I(-1));
 
+    /*
+     * Markus Kuhn feels, not totally unreasonably, that it's good
+     * for all applications to shift into UTF-8 mode if they notice
+     * that they've been started with a LANG setting dictating it,
+     * so that people don't have to keep remembering a separate
+     * UTF-8 option for every application they use. Therefore,
+     * here's an override option in the Translation panel.
+     */
+    s = ctrl_getset(b, "Window/Translation", "trans",
+                   "Character set translation on received data");
+    ctrl_checkbox(s, "Override with UTF-8 if locale says so", 'l',
+                 HELPCTX(translation_utf8_override),
+                 dlg_stdcheckbox_handler,
+                 I(offsetof(Config,utf8_override)));
+
     /*
      * Unix supports a local-command proxy. This also means we must
      * adjust the text on the `Telnet command' control.
index 146fcb30133d7b7b872fc2c417972cf723b8ec5e..e2b4d3d97d4890ff366c8165b2374778cb29a692 100644 (file)
@@ -230,6 +230,7 @@ static void usage(void)
     printf("  -C        enable compression\n");
     printf("  -i key    private key file for authentication\n");
     printf("  -s        remote command is an SSH subsystem (SSH-2 only)\n");
+    printf("  -N        don't start a shell/command (SSH-2 only)\n");
     exit(1);
 }
 
index 601b35dac6b44554c47acdf78a933dd6540713d7..83595538a8138d7e6a6daffcb0684c28b0707007 100644 (file)
@@ -106,8 +106,8 @@ int wc_to_mb(int codepage, int flags, wchar_t *wcstr, int wclen,
 /*
  * Return value is TRUE if pterm is to run in direct-to-font mode.
  */
-int init_ucs(struct unicode_data *ucsdata, 
-            char *linecharset, int font_charset, int vtmode)
+int init_ucs(struct unicode_data *ucsdata, char *linecharset,
+            int utf8_override, int font_charset, int vtmode)
 {
     int i, ret = 0;
 
@@ -120,10 +120,27 @@ int init_ucs(struct unicode_data *ucsdata,
     ucsdata->font_codepage = -1;
 
     /*
-     * line_codepage should be decoded from the specification in
-     * cfg.
+     * If utf8_override is set and the POSIX locale settings
+     * dictate a UTF-8 character set, then just go straight for
+     * UTF-8.
      */
-    ucsdata->line_codepage = decode_codepage(linecharset);
+    ucsdata->line_codepage = CS_NONE;
+    if (utf8_override) {
+       const char *s;
+       if (((s = getenv("LC_ALL"))   && *s) ||
+           ((s = getenv("LC_CTYPE")) && *s) ||
+           ((s = getenv("LANG"))     && *s)) {
+           if (strstr(s, "UTF-8"))
+               ucsdata->line_codepage = CS_UTF8;
+       }
+    }
+
+    /*
+     * Failing that, line_codepage should be decoded from the
+     * specification in cfg.
+     */
+    if (ucsdata->line_codepage == CS_NONE)
+       ucsdata->line_codepage = decode_codepage(linecharset);
 
     /*
      * If line_codepage is _still_ CS_NONE, we assume we're using
index 793a5166be67269c3122cf27a98c24978b6378a0..e5526629a1978838812f7a4e442cba33e82ee3cc 100644 (file)
--- a/window.c
+++ b/window.c
@@ -686,8 +686,6 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
        SetScrollInfo(hwnd, SB_VERT, &si, FALSE);
     }
 
-    start_backend();
-
     /*
      * Prepare the mouse handler.
      */
@@ -742,7 +740,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
        }
     }
 
-    update_specials_menu(NULL);
+    start_backend();
 
     /*
      * Set up the initial input locale.