Created a shiny new abstraction for the socket handling. Has many
[u/mdw/putty] / window.c
index 410ba1a..1e38a48 100644 (file)
--- a/window.c
+++ b/window.c
@@ -14,6 +14,7 @@
 
 #define PUTTY_DO_GLOBALS                      /* actually _define_ globals */
 #include "putty.h"
+#include "winstuff.h"
 #include "storage.h"
 #include "win_res.h"
 
 #define WM_IGNORE_SIZE (WM_XUSER + 1)
 #define WM_IGNORE_CLIP (WM_XUSER + 2)
 
+/* Needed for Chinese support and apparently not always defined. */
+#ifndef VK_PROCESSKEY
+#define VK_PROCESSKEY 0xE5
+#endif
+
 static LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
 static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam, unsigned char *output);
 static void cfgtopalette(void);
@@ -107,7 +113,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) {
     MSG msg;
     int guess_width, guess_height;
 
-    putty_inst = inst;
+    hinst = inst;
     flags = FLAG_VERBOSE | FLAG_INTERACTIVE;
 
     winsock_ver = MAKEWORD(1, 1);
@@ -123,9 +129,14 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) {
        return 1;
     }
     /* WISHLIST: maybe allow config tweaking even if winsock not present? */
+    sk_init();
 
     InitCommonControls();
 
+    /* Ensure a Maximize setting in Explorer doesn't maximise the
+     * config box. */
+    defuse_showwindow();
+
     /*
      * Process the command line.
      */
@@ -193,6 +204,10 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) {
         * An initial @ means to activate a saved session.
         */
        if (*p == '@') {
+           int i = strlen(p);
+           while (i > 1 && isspace(p[i-1]))
+               i--;
+           p[i] = '\0';
            do_defaults (p+1, &cfg);
            if (!*cfg.host && !do_config()) {
                WSACleanup();
@@ -348,14 +363,14 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) {
     }
 
     {
-       int winmode = WS_OVERLAPPEDWINDOW|WS_VSCROLL;
-       if (!cfg.scrollbar) winmode &= ~(WS_VSCROLL);
-       if (cfg.locksize)   winmode &= ~(WS_THICKFRAME|WS_MAXIMIZEBOX);
-       hwnd = CreateWindow (appname, appname,
-                           winmode,
-                           CW_USEDEFAULT, CW_USEDEFAULT,
-                           guess_width, guess_height,
-                           NULL, NULL, inst, NULL);
+       int winmode = WS_OVERLAPPEDWINDOW|WS_VSCROLL;
+       if (!cfg.scrollbar) winmode &= ~(WS_VSCROLL);
+       if (cfg.locksize)   winmode &= ~(WS_THICKFRAME|WS_MAXIMIZEBOX);
+       hwnd = CreateWindow (appname, appname,
+                            winmode,
+                            CW_USEDEFAULT, CW_USEDEFAULT,
+                            guess_width, guess_height,
+                            NULL, NULL, inst, NULL);
     }
 
     /*
@@ -421,7 +436,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) {
        char msg[1024], *title;
        char *realhost;
 
-       error = back->init (hwnd, cfg.host, cfg.port, &realhost);
+       error = back->init (cfg.host, cfg.port, &realhost);
        if (error) {
            sprintf(msg, "Unable to open connection:\n%s", error);
            MessageBox(NULL, msg, "PuTTY Error", MB_ICONERROR | MB_OK);
@@ -610,6 +625,28 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) {
 }
 
 /*
+ * Set up, or shut down, an AsyncSelect. Called from winnet.c.
+ */
+char *do_select(SOCKET skt, int startup) {
+    int msg, events;
+    if (startup) {
+       msg = WM_NETEVENT;
+       events = FD_READ | FD_WRITE | FD_OOB | FD_CLOSE;
+    } else {
+       msg = events = 0;
+    }
+    if (!hwnd)
+       return "do_select(): internal error (hwnd==NULL)";
+    if (WSAAsyncSelect (skt, hwnd, msg, events) == SOCKET_ERROR) {
+        switch (WSAGetLastError()) {
+          case WSAENETDOWN: return "Network is down";
+          default: return "WSAAsyncSelect(): unknown error";
+        }
+    }
+    return NULL;
+}
+
+/*
  * Print a message box and close the connection.
  */
 void connection_fatal(char *fmt, ...) {
@@ -632,8 +669,9 @@ void connection_fatal(char *fmt, ...) {
  * Actually do the job requested by a WM_NETEVENT
  */
 static void enact_pending_netevent(void) {
-    int i;
     static int reentering = 0;
+    extern int select_result(WPARAM, LPARAM);
+    int ret;
 
     if (reentering)
         return;                        /* don't unpend the pending */
@@ -641,25 +679,10 @@ static void enact_pending_netevent(void) {
     pending_netevent = FALSE;
 
     reentering = 1;
-    i = back->msg (pend_netevent_wParam, pend_netevent_lParam);
+    ret = select_result (pend_netevent_wParam, pend_netevent_lParam);
     reentering = 0;
 
-    if (i < 0) {
-       char buf[1024];
-       switch (WSABASEERR + (-i) % 10000) {
-         case WSAECONNRESET:
-           sprintf(buf, "Connection reset by peer");
-           break;
-         case WSAECONNABORTED:
-           sprintf(buf, "Connection aborted");
-           break;
-         default:
-           sprintf(buf, "Unexpected network error %d", -i);
-           break;
-       }
-        connection_fatal(buf);
-    }
-    if (i <= 0) {
+    if (ret == 0) {
        if (cfg.close_on_exit)
            PostQuitMessage(0);
        else {
@@ -1479,12 +1502,29 @@ static LRESULT CALLBACK WndProc (HWND hwnd, UINT message,
            unsigned char buf[20];
            int len;
 
-           len = TranslateKey (message, wParam, lParam, buf);
-           if (len == -1)
-               return DefWindowProc (hwnd, message, wParam, lParam);
-           ldisc->send (buf, len);
+            if (wParam==VK_PROCESSKEY) {
+               MSG m;
+                m.hwnd = hwnd;
+                m.message = WM_KEYDOWN;
+                m.wParam = wParam;
+                m.lParam = lParam & 0xdfff;
+                TranslateMessage(&m);
+            } else {
+               len = TranslateKey (message, wParam, lParam, buf);
+               if (len == -1)
+                   return DefWindowProc (hwnd, message, wParam, lParam);
+               ldisc->send (buf, len);
+           }
        }
        return 0;
+      case WM_IME_CHAR:
+       {
+           unsigned char buf[2];
+
+           buf[1] = wParam;
+           buf[0] = wParam >> 8;
+           ldisc->send (buf, 2);
+       }
       case WM_CHAR:
       case WM_SYSCHAR:
        /*
@@ -1739,15 +1779,6 @@ static int check_compose(int first, int second) {
     static int recurse = 0;
     int nc = -1;
 
-    if(0)
-    {
-       char buf[256];
-       char * p;
-       sprintf(buf, "cc(%d,%d)", first, second);
-       for(p=buf; *p; p++)
-           c_write1(*p);
-    }
-
     for(c=composetbl; *c; c++) {
        if( (*c)[0] == first && (*c)[1] == second)
        {
@@ -1774,7 +1805,8 @@ static int check_compose(int first, int second) {
  * codes. Returns number of bytes used or zero to drop the message
  * or -1 to forward the message to windows.
  */
-static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam, unsigned char *output) {
+static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam,
+                       unsigned char *output) {
     BYTE keystate[256];
     int  scan, left_alt = 0, key_down, shift_state;
     int  r, i, code;
@@ -1847,25 +1879,28 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam, unsigned cha
 #endif
 
        /* Note if AltGr was pressed and if it was used as a compose key */
-       if (wParam == VK_MENU && (HIWORD(lParam)&KF_EXTENDED))
-       {
-           keystate[VK_RMENU] = keystate[VK_MENU];
-           if (!compose_state) compose_key = wParam;
-       }
-       if (wParam == VK_APPS && !compose_state)
-           compose_key = wParam;
+       if (cfg.compose_key) {
+           if (wParam == VK_MENU && (HIWORD(lParam)&KF_EXTENDED))
+           {
+               keystate[VK_RMENU] = keystate[VK_MENU];
+               if (!compose_state) compose_key = wParam;
+           }
+           if (wParam == VK_APPS && !compose_state)
+               compose_key = wParam;
 
-       if (wParam == compose_key)
-       {
-            if (compose_state == 0 && (HIWORD(lParam)&(KF_UP|KF_REPEAT))==0)
-              compose_state = 1;
-           else if (compose_state == 1 && (HIWORD(lParam)&KF_UP))
-              compose_state = 2;
-           else
-              compose_state = 0;
-       }
-       else if (compose_state==1 && wParam != VK_CONTROL)
-          compose_state = 0;
+           if (wParam == compose_key)
+           {
+               if (compose_state == 0 && (HIWORD(lParam)&(KF_UP|KF_REPEAT))==0)
+                   compose_state = 1;
+               else if (compose_state == 1 && (HIWORD(lParam)&KF_UP))
+                   compose_state = 2;
+               else
+                   compose_state = 0;
+           }
+           else if (compose_state==1 && wParam != VK_CONTROL)
+               compose_state = 0;
+       } else
+           compose_state = 0;
 
        /* Nastyness with NUMLock - Shift-NUMLock is left alone though */
        if ( (cfg.funky_type == 3 || (cfg.funky_type <= 1 && app_keypad_keys))
@@ -2210,7 +2245,7 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam, unsigned cha
 
                    if ((nc=check_compose(compose_char,ch)) == -1)
                    {
-                       c_write1('\007');
+                       MessageBeep(MB_ICONHAND);
                        return 0;
                    }
                    *p++ = xlat_kbd2tty((unsigned char)nc);
@@ -2238,8 +2273,10 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam, unsigned cha
     }
 
     /* This stops ALT press-release doing a 'COMMAND MENU' function */
-    if (message == WM_SYSKEYUP && wParam == VK_MENU) 
-       return 0;
+    if (!cfg.alt_only) {
+       if (message == WM_SYSKEYUP && wParam == VK_MENU) 
+           return 0;
+    }
 
     return -1;
 }