Robert de Bath's asynchronous-connect patch. Helps a lot in port
[u/mdw/putty] / window.c
index 3d4f080..378634f 100644 (file)
--- a/window.c
+++ b/window.c
@@ -128,6 +128,8 @@ static char *window_name, *icon_name;
 
 static int compose_state = 0;
 
+static OSVERSIONINFO osVersion;
+
 /* Dummy routine, only required in plink. */
 void ldisc_update(int echo, int edit)
 {
@@ -166,6 +168,16 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
      * config box. */
     defuse_showwindow();
 
+    {
+       ZeroMemory(&osVersion, sizeof(osVersion));
+       osVersion.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
+       if (!GetVersionEx ( (OSVERSIONINFO *) &osVersion)) {
+            MessageBox(NULL, "Windows refuses to report a version",
+                       "PuTTY Fatal Error", MB_OK | MB_ICONEXCLAMATION);
+           return 1;
+        }
+    }
+
     /*
      * Process the command line.
      */
@@ -694,7 +706,8 @@ char *do_select(SOCKET skt, int startup)
     int msg, events;
     if (startup) {
        msg = WM_NETEVENT;
-       events = FD_READ | FD_WRITE | FD_OOB | FD_CLOSE;
+       events = (FD_CONNECT | FD_READ | FD_WRITE |
+                 FD_OOB | FD_CLOSE | FD_ACCEPT);
     } else {
        msg = events = 0;
     }
@@ -1117,7 +1130,8 @@ static void click(Mouse_Button b, int x, int y, int shift, int ctrl)
 {
     int thistime = GetMessageTime();
 
-    if (send_raw_mouse) {
+    if (send_raw_mouse && !(cfg.mouse_override && shift)) {
+       lastbtn = MBT_NOTHING;
        term_mouse(b, MA_CLICK, x, y, shift, ctrl);
        return;
     }
@@ -1480,6 +1494,17 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
          case IDM_ABOUT:
            showabout(hwnd);
            break;
+          case SC_KEYMENU:
+           /*
+            * We get this if the System menu has been activated.
+            * This might happen from within TranslateKey, in which
+            * case it really wants to be followed by a `space'
+            * character to actually _bring the menu up_ rather
+            * than just sitting there in `ready to appear' state.
+            */
+           if( lParam == 0 )
+               PostMessage(hwnd, WM_CHAR, ' ', 0);
+           break;
          default:
            if (wParam >= IDM_SAVED_MIN && wParam <= IDM_SAVED_MAX) {
                SendMessage(hwnd, WM_SYSCOMMAND, IDM_SAVEDSESS, wParam);
@@ -1642,6 +1667,9 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
        pending_netevent = TRUE;
        pend_netevent_wParam = wParam;
        pend_netevent_lParam = lParam;
+       if (WSAGETSELECTEVENT(lParam) != FD_READ)
+           enact_pending_netevent();
+
        time(&last_movement);
        return 0;
       case WM_SETFOCUS:
@@ -1851,10 +1879,19 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
                len = TranslateKey(message, wParam, lParam, buf);
                if (len == -1)
                    return DefWindowProc(hwnd, message, wParam, lParam);
-               ldisc_send(buf, len);
 
-               if (len > 0)
+               if (len != 0) {
+                   /*
+                    * We need not bother about stdin backlogs
+                    * here, because in GUI PuTTY we can't do
+                    * anything about it anyway; there's no means
+                    * of asking Windows to hold off on KEYDOWN
+                    * messages. We _have_ to buffer everything
+                    * we're sent.
+                    */
+                   ldisc_send(buf, len);
                    show_mouseptr(0);
+               }
            }
        }
        return 0;
@@ -1873,6 +1910,31 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
            kbd_codepage = atoi(lbuf);
        }
        break;
+      case WM_IME_COMPOSITION:
+       {
+           HIMC hIMC;
+           int n;
+           char *buff;
+   
+           if(osVersion.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS || 
+               osVersion.dwPlatformId == VER_PLATFORM_WIN32s) break; /* no Unicode */
+
+           if ((lParam & GCS_RESULTSTR) == 0) /* Composition unfinished. */
+               break; /* fall back to DefWindowProc */
+
+           hIMC = ImmGetContext(hwnd);
+           n = ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, NULL, 0);
+
+           if (n > 0) {
+               buff = (char*) smalloc(n);
+               ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, buff, n);
+               luni_send((unsigned short *)buff, n / 2);
+               free(buff);
+           }
+           ImmReleaseContext(hwnd, hIMC);
+           return 1;
+       }
+
       case WM_IME_CHAR:
        if (wParam & 0xFF00) {
            unsigned char buf[2];
@@ -1916,8 +1978,27 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
  */
 void sys_cursor(int x, int y)
 {
-    if (has_focus)
-       SetCaretPos(x * font_width, y * font_height);
+    COMPOSITIONFORM cf;
+    HIMC hIMC;
+
+    if (!has_focus) return;
+    
+    SetCaretPos(x * font_width, y * font_height);
+
+    /* IMM calls on Win98 and beyond only */
+    if(osVersion.dwPlatformId == VER_PLATFORM_WIN32s) return; /* 3.11 */
+    
+    if(osVersion.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS &&
+           osVersion.dwMinorVersion == 0) return; /* 95 */
+
+    /* we should have the IMM functions */
+    hIMC = ImmGetContext(hwnd);
+    cf.dwStyle = CFS_POINT;
+    cf.ptCurrentPos.x = x * font_width;
+    cf.ptCurrentPos.y = y * font_height;
+    ImmSetCompositionWindow(hIMC, &cf);
+
+    ImmReleaseContext(hwnd, hIMC);
 }
 
 /*
@@ -2228,7 +2309,6 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam,
     int scan, left_alt = 0, key_down, shift_state;
     int r, i, code;
     unsigned char *p = output;
-    static int alt_state = 0;
     static int alt_sum = 0;
 
     HKL kbd_layout = GetKeyboardLayout(0);
@@ -2469,8 +2549,6 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam,
            return -1;
        }
        if (left_alt && wParam == VK_SPACE && cfg.alt_space) {
-           alt_state = 0;
-           PostMessage(hwnd, WM_CHAR, ' ', 0);
            SendMessage(hwnd, WM_SYSCOMMAND, SC_KEYMENU, 0);
            return -1;
        }
@@ -2730,6 +2808,8 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam,
          case VK_F20:
            code = 34;
            break;
+       }
+       if ((shift_state&2) == 0) switch (wParam) {
          case VK_HOME:
            code = 1;
            break;
@@ -2942,6 +3022,15 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam,
                            luni_send(&keybuf, 1);
                        } else {
                            ch = (char) alt_sum;
+                           /*
+                            * We need not bother about stdin
+                            * backlogs here, because in GUI PuTTY
+                            * we can't do anything about it
+                            * anyway; there's no means of asking
+                            * Windows to hold off on KEYDOWN
+                            * messages. We _have_ to buffer
+                            * everything we're sent.
+                            */
                            ldisc_send(&ch, 1);
                        }
                        alt_sum = 0;
@@ -2953,6 +3042,7 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam,
                    lpage_send(kbd_codepage, cbuf + !left_alt,
                               1 + !!left_alt);
                }
+               show_mouseptr(0);
            }
 
            /* This is so the ALT-Numpad and dead keys work correctly. */
@@ -2968,19 +3058,15 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam,
            keys[0] = 10;
     }
 
-    /* ALT alone may or may not want to bring up the System menu */
-    if (wParam == VK_MENU) {
-       if (cfg.alt_only) {
-           if (message == WM_SYSKEYDOWN)
-               alt_state = 1;
-           else if (message == WM_SYSKEYUP && alt_state)
-               PostMessage(hwnd, WM_CHAR, ' ', 0);
-           if (message == WM_SYSKEYUP)
-               alt_state = 0;
-       } else
-           return 0;
-    } else
-       alt_state = 0;
+    /*
+     * ALT alone may or may not want to bring up the System menu.
+     * If it's not meant to, we return 0 on presses or releases of
+     * ALT, to show that we've swallowed the keystroke. Otherwise
+     * we return -1, which means Windows will give the keystroke
+     * its default handling (i.e. bring up the System menu).
+     */
+    if (wParam == VK_MENU && !cfg.alt_only)
+       return 0;
 
     return -1;
 }