Remove a couple of unused variables.
[u/mdw/putty] / windows / window.c
index b7561cf..fe16c94 100644 (file)
@@ -61,6 +61,7 @@
 #define WM_IGNORE_CLIP (WM_APP + 2)
 #define WM_FULLSCR_ON_MAX (WM_APP + 3)
 #define WM_AGENT_CALLBACK (WM_APP + 4)
+#define WM_GOT_CLIPDATA (WM_APP + 6)
 
 /* Needed for Chinese support and apparently not always defined. */
 #ifndef VK_PROCESSKEY
@@ -93,6 +94,7 @@ static int is_full_screen(void);
 static void make_full_screen(void);
 static void clear_full_screen(void);
 static void flip_full_screen(void);
+static int process_clipdata(HGLOBAL clipdata, int unicode);
 
 /* Window layout information */
 static void reset_window(int);
@@ -127,6 +129,9 @@ static const struct telnet_special *specials = NULL;
 static HMENU specials_menu = NULL;
 static int n_specials = 0;
 
+static wchar_t *clipboard_contents;
+static size_t clipboard_length;
+
 #define TIMING_TIMER_ID 1234
 static long timing_next_time;
 
@@ -219,12 +224,7 @@ static void start_backend(void)
      * 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;
-       }
+    back = backend_from_proto(cfg.protocol);
     if (back == NULL) {
        char *str = dupprintf("%s Internal Error", appname);
        MessageBox(NULL, "Unsupported protocol number found",
@@ -361,17 +361,18 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
     {
        char *p;
        int got_host = 0;
+       /* By default, we bring up the config dialog, rather than launching
+        * a session. This gets set to TRUE if something happens to change
+        * that (e.g., a hostname is specified on the command-line). */
+       int allow_launch = FALSE;
 
        default_protocol = be_default_protocol;
        /* Find the appropriate default port. */
        {
-           int i;
+           Backend *b = backend_from_proto(default_protocol);
            default_port = 0; /* illegal */
-           for (i = 0; backends[i].backend != NULL; i++)
-               if (backends[i].protocol == default_protocol) {
-                   default_port = backends[i].backend->default_port;
-                   break;
-               }
+           if (b)
+               default_port = b->default_port;
        }
        cfg.logtype = LGTYP_NONE;
 
@@ -397,6 +398,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
            if (!cfg_launchable(&cfg) && !do_config()) {
                cleanup_exit(0);
            }
+           allow_launch = TRUE;    /* allow it to be launched directly */
        } else if (*p == '&') {
            /*
             * An initial & means we've been given a command line
@@ -415,6 +417,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
            } else if (!do_config()) {
                cleanup_exit(0);
            }
+           allow_launch = TRUE;
        } else {
            /*
             * Otherwise, break up the command line and deal with
@@ -539,8 +542,10 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
 
        cmdline_run_saved(&cfg);
 
-       if ((!loaded_session || !cfg_launchable(&cfg)) &&
-           !do_config()) {
+       if (loaded_session || got_host)
+           allow_launch = TRUE;
+
+       if ((!allow_launch || !cfg_launchable(&cfg)) && !do_config()) {
            cleanup_exit(0);
        }
 
@@ -597,15 +602,6 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
        }
     }
 
-    /* Check for invalid Port number (i.e. zero) */
-    if (cfg.port == 0) {
-       char *str = dupprintf("%s Internal Error", appname);
-       MessageBox(NULL, "Invalid Port Number",
-                  str, MB_OK | MB_ICONEXCLAMATION);
-       sfree(str);
-       cleanup_exit(1);
-    }
-
     if (!prev) {
        wndclass.style = 0;
        wndclass.lpfnWndProc = WndProc;
@@ -2251,7 +2247,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
            term_copyall(term);
            break;
          case IDM_PASTE:
-           term_do_paste(term);
+           request_paste(NULL);
            break;
          case IDM_CLRSB:
            term_clrsb(term);
@@ -3013,6 +3009,10 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
            sfree(c);
        }
        return 0;
+      case WM_GOT_CLIPDATA:
+       if (process_clipdata((HGLOBAL)lParam, wParam))
+           term_do_paste(term);
+       return 0;
       default:
        if (message == wm_mousewheel || message == WM_MOUSEWHEEL) {
            int shift_pressed=0, control_pressed=0;
@@ -3046,16 +3046,22 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
 
                if (send_raw_mouse &&
                    !(cfg.mouse_override && shift_pressed)) {
-                   /* send a mouse-down followed by a mouse up */
-                   term_mouse(term, b, translate_button(b),
-                              MA_CLICK,
-                              TO_CHR_X(X_POS(lParam)),
-                              TO_CHR_Y(Y_POS(lParam)), shift_pressed,
-                              control_pressed, is_alt_pressed());
-                   term_mouse(term, b, translate_button(b),
-                              MA_RELEASE, TO_CHR_X(X_POS(lParam)),
-                              TO_CHR_Y(Y_POS(lParam)), shift_pressed,
-                              control_pressed, is_alt_pressed());
+                   /* Mouse wheel position is in screen coordinates for
+                    * some reason */
+                   POINT p;
+                   p.x = X_POS(lParam); p.y = Y_POS(lParam);
+                   if (ScreenToClient(hwnd, &p)) {
+                       /* send a mouse-down followed by a mouse up */
+                       term_mouse(term, b, translate_button(b),
+                                  MA_CLICK,
+                                  TO_CHR_X(p.x),
+                                  TO_CHR_Y(p.y), shift_pressed,
+                                  control_pressed, is_alt_pressed());
+                       term_mouse(term, b, translate_button(b),
+                                  MA_RELEASE, TO_CHR_X(p.x),
+                                  TO_CHR_Y(p.y), shift_pressed,
+                                  control_pressed, is_alt_pressed());
+                   } /* else: not sure when this can fail */
                } else {
                    /* trigger a scroll */
                    term_scroll(term, 0,
@@ -3564,8 +3570,9 @@ int char_width(Context ctx, int uc) {
 
 /*
  * Translate a WM_(SYS)?KEY(UP|DOWN) message into a string of ASCII
- * codes. Returns number of bytes used or zero to drop the message
- * or -1 to forward the message to windows.
+ * codes. Returns number of bytes used, zero to drop the message,
+ * -1 to forward the message to Windows, or another negative number
+ * to indicate a NUL-terminated "special" string.
  */
 static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam,
                        unsigned char *output)
@@ -3806,7 +3813,7 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam,
            return 0;
        }
        if (wParam == VK_INSERT && shift_state == 1) {
-           term_do_paste(term);
+           request_paste(NULL);
            return 0;
        }
        if (left_alt && wParam == VK_F4 && cfg.alt_f4) {
@@ -3985,9 +3992,9 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam,
            return p - output;
        }
        if (wParam == VK_CANCEL && shift_state == 2) {  /* Ctrl-Break */
-           *p++ = 3;
-           *p++ = 0;
-           return -2;
+           if (back)
+               back->special(backhandle, TS_BRK);
+           return 0;
        }
        if (wParam == VK_PAUSE) {      /* Break/Pause */
            *p++ = 26;
@@ -4003,7 +4010,7 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam,
            *p++ = 0x1F;
            return p - output;
        }
-       if (shift_state == 2 && wParam == 0xDF) {
+       if (shift_state == 2 && (wParam == 0xDF || wParam == 0xDC)) {
            *p++ = 0x1C;
            return p - output;
        }
@@ -4421,16 +4428,6 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam,
     return -1;
 }
 
-void request_paste(void *frontend)
-{
-    /*
-     * In Windows, pasting is synchronous: we can read the
-     * clipboard with no difficulty, so request_paste() can just go
-     * ahead and paste.
-     */
-    term_do_paste(term);
-}
-
 void set_title(void *frontend, char *title)
 {
     sfree(window_name);
@@ -4904,46 +4901,89 @@ void write_clip(void *frontend, wchar_t * data, int *attr, int len, int must_des
        SendMessage(hwnd, WM_IGNORE_CLIP, FALSE, 0);
 }
 
-void get_clip(void *frontend, wchar_t ** p, int *len)
+static DWORD WINAPI clipboard_read_threadfunc(void *param)
 {
-    static HGLOBAL clipdata = NULL;
-    static wchar_t *converted = 0;
-    wchar_t *p2;
+    HWND hwnd = (HWND)param;
+    HGLOBAL clipdata;
 
-    if (converted) {
-       sfree(converted);
-       converted = 0;
-    }
-    if (!p) {
-       if (clipdata)
-           GlobalUnlock(clipdata);
-       clipdata = NULL;
-       return;
-    } else if (OpenClipboard(NULL)) {
+    if (OpenClipboard(NULL)) {
        if ((clipdata = GetClipboardData(CF_UNICODETEXT))) {
-           CloseClipboard();
-           *p = GlobalLock(clipdata);
-           if (*p) {
-               for (p2 = *p; *p2; p2++);
-               *len = p2 - *p;
-               return;
-           }
-       } else if ( (clipdata = GetClipboardData(CF_TEXT)) ) {
-           char *s;
-           int i;
-           CloseClipboard();
-           s = GlobalLock(clipdata);
+           SendMessage(hwnd, WM_GOT_CLIPDATA, (WPARAM)1, (LPARAM)clipdata);
+       } else if ((clipdata = GetClipboardData(CF_TEXT))) {
+           SendMessage(hwnd, WM_GOT_CLIPDATA, (WPARAM)0, (LPARAM)clipdata);
+       }
+       CloseClipboard();
+    }
+
+    return 0;
+}
+
+static int process_clipdata(HGLOBAL clipdata, int unicode)
+{
+    sfree(clipboard_contents);
+    clipboard_contents = NULL;
+    clipboard_length = 0;
+
+    if (unicode) {
+       wchar_t *p = GlobalLock(clipdata);
+       wchar_t *p2;
+
+       if (p) {
+           /* Unwilling to rely on Windows having wcslen() */
+           for (p2 = p; *p2; p2++);
+           clipboard_length = p2 - p;
+           clipboard_contents = snewn(clipboard_length + 1, wchar_t);
+           memcpy(clipboard_contents, p, clipboard_length * sizeof(wchar_t));
+           clipboard_contents[clipboard_length] = L'\0';
+           return TRUE;
+       }
+    } else {
+       char *s = GlobalLock(clipdata);
+       int i;
+
+       if (s) {
            i = MultiByteToWideChar(CP_ACP, 0, s, strlen(s) + 1, 0, 0);
-           *p = converted = snewn(i, wchar_t);
-           MultiByteToWideChar(CP_ACP, 0, s, strlen(s) + 1, converted, i);
-           *len = i - 1;
-           return;
-       } else
-           CloseClipboard();
+           clipboard_contents = snewn(i, wchar_t);
+           MultiByteToWideChar(CP_ACP, 0, s, strlen(s) + 1,
+                               clipboard_contents, i);
+           clipboard_length = i - 1;
+           clipboard_contents[clipboard_length] = L'\0';
+           return TRUE;
+       }
     }
 
-    *p = NULL;
-    *len = 0;
+    return FALSE;
+}
+
+void request_paste(void *frontend)
+{
+    /*
+     * I always thought pasting was synchronous in Windows; the
+     * clipboard access functions certainly _look_ synchronous,
+     * unlike the X ones. But in fact it seems that in some
+     * situations the contents of the clipboard might not be
+     * immediately available, and the clipboard-reading functions
+     * may block. This leads to trouble if the application
+     * delivering the clipboard data has to get hold of it by -
+     * for example - talking over a network connection which is
+     * forwarded through this very PuTTY.
+     *
+     * Hence, we spawn a subthread to read the clipboard, and do
+     * our paste when it's finished. The thread will send a
+     * message back to our main window when it terminates, and
+     * that tells us it's OK to paste.
+     */
+    DWORD in_threadid; /* required for Win9x */
+    CreateThread(NULL, 0, clipboard_read_threadfunc,
+                hwnd, 0, &in_threadid);
+}
+
+void get_clip(void *frontend, wchar_t **p, int *len)
+{
+    if (p) {
+       *p = clipboard_contents;
+       *len = clipboard_length;
+    }
 }
 
 #if 0