Add the ability to do ssh by default: using -ssh command line option,
[u/mdw/putty] / window.c
index 151441f..6b0f1db 100644 (file)
--- a/window.c
+++ b/window.c
@@ -100,12 +100,33 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) {
     {
        char *p;
 
+       default_protocol = DEFAULT_PROTOCOL;
+       default_port = DEFAULT_PORT;
+
        do_defaults(NULL);
 
        p = cmdline;
        while (*p && isspace(*p)) p++;
 
        /*
+        * Process command line options first. Yes, this can be
+        * done better, and it will be as soon as I have the
+        * energy...
+        */
+       while (*p == '-') {
+           char *q = p + strcspn(p, " \t");
+           p++;
+           if (q == p + 3 &&
+               tolower(p[0]) == 's' &&
+               tolower(p[1]) == 's' &&
+               tolower(p[2]) == 'h') {
+               default_protocol = cfg.protocol = PROT_SSH;
+               default_port = cfg.port = 22;
+           }
+           p = q + strspn(q, " \t");
+       }
+
+       /*
         * An initial @ means to activate a saved session.
         */
        if (*p == '@') {
@@ -163,7 +184,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) {
        wndclass.hInstance     = inst;
        wndclass.hIcon         = LoadIcon (inst,
                                           MAKEINTRESOURCE(IDI_MAINICON));
-       wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW);
+       wndclass.hCursor       = LoadCursor (NULL, IDC_IBEAM);
        wndclass.hbrBackground = GetStockObject (BLACK_BRUSH);
        wndclass.lpszMenuName  = NULL;
        wndclass.lpszClassName = appname;
@@ -267,7 +288,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) {
            return 0;
        }
        window_name = icon_name = NULL;
-       sprintf(msg, "PuTTY: %s", realhost);
+       sprintf(msg, "%s - PuTTY", realhost);
        set_title (msg);
        set_icon (msg);
     }
@@ -556,7 +577,9 @@ void request_resize (int w, int h) {
 }
 
 static void click (Mouse_Button b, int x, int y) {
-    if (lastbtn == b && GetMessageTime() - lasttime < dbltime) {
+    int thistime = GetMessageTime();
+
+    if (lastbtn == b && thistime - lasttime < dbltime) {
        lastact = (lastact == MA_CLICK ? MA_2CLK :
                   lastact == MA_2CLK ? MA_3CLK :
                   lastact == MA_3CLK ? MA_CLICK : MA_NOTHING);
@@ -566,7 +589,7 @@ static void click (Mouse_Button b, int x, int y) {
     }
     if (lastact != MA_NOTHING)
        term_mouse (b, lastact, x, y);
-    lasttime = GetMessageTime();
+    lasttime = thistime;
 }
 
 static int WINAPI WndProc (HWND hwnd, UINT message,
@@ -698,33 +721,46 @@ static int WINAPI WndProc (HWND hwnd, UINT message,
            break;
        }
        break;
+
+#define X_POS(l) ((int)(short)LOWORD(l))
+#define Y_POS(l) ((int)(short)HIWORD(l))
+
+#define TO_CHR_X(x) (((x)<0 ? (x)-font_width+1 : (x)) / font_width)
+#define TO_CHR_Y(y) (((y)<0 ? (y)-font_height+1: (y)) / font_height)
+
       case WM_LBUTTONDOWN:
-       click (MB_SELECT, LOWORD(lParam) / font_width,
-              HIWORD(lParam) / font_height);
+       click (MB_SELECT, TO_CHR_X(X_POS(lParam)),
+              TO_CHR_Y(Y_POS(lParam)));
+        SetCapture(hwnd);
        return 0;
       case WM_LBUTTONUP:
-       term_mouse (MB_SELECT, MA_RELEASE, LOWORD(lParam) / font_width,
-                   HIWORD(lParam) / font_height);
+       term_mouse (MB_SELECT, MA_RELEASE, TO_CHR_X(X_POS(lParam)),
+                   TO_CHR_Y(Y_POS(lParam)));
+        ReleaseCapture();
        return 0;
       case WM_MBUTTONDOWN:
+        SetCapture(hwnd);
        click (cfg.mouse_is_xterm ? MB_PASTE : MB_EXTEND,
-              LOWORD(lParam) / font_width,
-              HIWORD(lParam) / font_height);
+              TO_CHR_X(X_POS(lParam)),
+              TO_CHR_Y(Y_POS(lParam)));
        return 0;
       case WM_MBUTTONUP:
        term_mouse (cfg.mouse_is_xterm ? MB_PASTE : MB_EXTEND,
-                   MA_RELEASE, LOWORD(lParam) / font_width,
-                   HIWORD(lParam) / font_height);
+                   MA_RELEASE, TO_CHR_X(X_POS(lParam)),
+                   TO_CHR_Y(Y_POS(lParam)));
+        ReleaseCapture();
        return 0;
       case WM_RBUTTONDOWN:
+        SetCapture(hwnd);
        click (cfg.mouse_is_xterm ? MB_EXTEND : MB_PASTE,
-              LOWORD(lParam) / font_width,
-              HIWORD(lParam) / font_height);
+              TO_CHR_X(X_POS(lParam)),
+              TO_CHR_Y(Y_POS(lParam)));
        return 0;
       case WM_RBUTTONUP:
        term_mouse (cfg.mouse_is_xterm ? MB_EXTEND : MB_PASTE,
-                   MA_RELEASE, LOWORD(lParam) / font_width,
-                   HIWORD(lParam) / font_height);
+                   MA_RELEASE, TO_CHR_X(X_POS(lParam)),
+                   TO_CHR_Y(Y_POS(lParam)));
+        ReleaseCapture();
        return 0;
       case WM_MOUSEMOVE:
        /*
@@ -742,12 +778,9 @@ static int WINAPI WndProc (HWND hwnd, UINT message,
                b = cfg.mouse_is_xterm ? MB_PASTE : MB_EXTEND;
            else
                b = cfg.mouse_is_xterm ? MB_EXTEND : MB_PASTE;
-           term_mouse (b, MA_DRAG, LOWORD(lParam) / font_width,
-                       HIWORD(lParam) / font_height);
+           term_mouse (b, MA_DRAG, TO_CHR_X(X_POS(lParam)),
+                       TO_CHR_Y(Y_POS(lParam)));
        }
-       lastbtn = MB_NOTHING;
-       lastact = MA_NOTHING;
-       lasttime = GetMessageTime();
        return 0;
       case WM_IGNORE_CLIP:
        ignore_clip = wParam;          /* don't panic on DESTROYCLIPBOARD */
@@ -854,7 +887,10 @@ static int WINAPI WndProc (HWND hwnd, UINT message,
        if (wParam == SIZE_RESTORED || wParam == SIZE_MAXIMIZED)
            SetWindowText (hwnd, window_name);
        if (!ignore_size) {
-           int width, height, w, h, ew, eh;
+           int width, height, w, h;
+#if 0 /* we have fixed this using WM_SIZING now */
+            int ew, eh;
+#endif
 
            width = LOWORD(lParam);
            height = HIWORD(lParam);
@@ -938,6 +974,33 @@ static int WINAPI WndProc (HWND hwnd, UINT message,
            back->send (buf, len);
        }
        return 0;
+      case WM_KEYUP:
+      case WM_SYSKEYUP:
+       /*
+        * We handle KEYUP ourselves in order to distinghish left
+        * and right Alt or Control keys, which Windows won't do
+        * right if left to itself. See also the special processing
+        * at the top of TranslateKey.
+        */
+       {
+            BYTE keystate[256];
+            int ret = GetKeyboardState(keystate);
+            if (ret && wParam == VK_MENU) {
+               if (lParam & 0x1000000) keystate[VK_RMENU] = 0;
+               else keystate[VK_LMENU] = 0;
+                SetKeyboardState (keystate);
+            }
+            if (ret && wParam == VK_CONTROL) {
+               if (lParam & 0x1000000) keystate[VK_RCONTROL] = 0;
+               else keystate[VK_LCONTROL] = 0;
+                SetKeyboardState (keystate);
+            }
+       }
+        /*
+         * We don't return here, in order to allow Windows to do
+         * its own KEYUP processing as well.
+         */
+       break;
       case WM_CHAR:
       case WM_SYSCHAR:
        /*
@@ -1072,18 +1135,24 @@ void do_text (Context ctx, int x, int y, char *text, int len,
        TextOut (hdc, x-1, y, text, len);
     }
     if (und_mode == UND_LINE && (attr & ATTR_UNDER)) {
-       SelectObject (hdc, CreatePen(PS_SOLID, 0, fg));
+        HPEN oldpen;
+       oldpen = SelectObject (hdc, CreatePen(PS_SOLID, 0, fg));
        MoveToEx (hdc, x, y+descent, NULL);
        LineTo (hdc, x+len*font_width, y+descent);
+        oldpen = SelectObject (hdc, oldpen);
+        DeleteObject (oldpen);
     }
     if (attr & ATTR_PASCURS) {
        POINT pts[5];
+        HPEN oldpen;
        pts[0].x = pts[1].x = pts[4].x = x;
        pts[2].x = pts[3].x = x+font_width-1;
        pts[0].y = pts[3].y = pts[4].y = y;
        pts[1].y = pts[2].y = y+font_height-1;
-       SelectObject (hdc, CreatePen(PS_SOLID, 0, colours[23]));
+       oldpen = SelectObject (hdc, CreatePen(PS_SOLID, 0, colours[23]));
        Polyline (hdc, pts, 5);
+        oldpen = SelectObject (hdc, oldpen);
+        DeleteObject (oldpen);
     }
 }
 
@@ -1095,12 +1164,7 @@ static int TranslateKey(WPARAM wParam, LPARAM lParam, unsigned char *output) {
     unsigned char *p = output;
     BYTE keystate[256];
     int ret, code;
-
-    /*
-     * Prepend ESC if ALT was pressed at the time.
-     */
-    if (lParam & 0x20000000)
-        *p++ = 0x1B;
+    int cancel_alt = FALSE;
 
     /*
      * Get hold of the keyboard state, because we'll need it a few
@@ -1108,6 +1172,33 @@ static int TranslateKey(WPARAM wParam, LPARAM lParam, unsigned char *output) {
      */
     ret = GetKeyboardState(keystate);
 
+    /* 
+     * Windows does not always want to distinguish left and right
+     * Alt or Control keys. Thus we keep track of them ourselves.
+     * See also the WM_KEYUP handler.
+     */
+    if (wParam == VK_MENU) {
+        if (lParam & 0x1000000) keystate[VK_RMENU] = 0x80;
+        else keystate[VK_LMENU] = 0x80;
+        SetKeyboardState (keystate);
+        return 0;
+    }
+    if (wParam == VK_CONTROL) {
+        if (lParam & 0x1000000) keystate[VK_RCONTROL] = 0x80;
+        else keystate[VK_LCONTROL] = 0x80;
+        SetKeyboardState (keystate);
+        return 0;
+    }
+
+    /*
+     * Prepend ESC, and cancel ALT, if ALT was pressed at the time
+     * and it wasn't AltGr.
+     */
+    if (lParam & 0x20000000 && (keystate[VK_LMENU] & 0x80)) {
+        *p++ = 0x1B;
+        cancel_alt = TRUE;
+    }
+
     /*
      * Shift-PgUp, Shift-PgDn, and Alt-F4 all produce window
      * events: we'll deal with those now.
@@ -1191,13 +1282,16 @@ static int TranslateKey(WPARAM wParam, LPARAM lParam, unsigned char *output) {
     }
 
     /*
-     * Before doing Windows charmap translation, remove ALT from
-     * the keymap, since its sole effect should be to prepend ESC,
-     * which we've already done. Note that removal of ALT has to
-     * happen _after_ the above call to SetKeyboardState, or dire
-     * things will befall.
+     * Before doing Windows charmap translation, remove LeftALT
+     * from the keymap, since its sole effect should be to prepend
+     * ESC, which we've already done. Note that removal of LeftALT
+     * has to happen _after_ the above call to SetKeyboardState, or
+     * dire things will befall.
      */
-    keystate[VK_MENU] = keystate[VK_LMENU] = keystate[VK_RMENU] = 0;
+    if (cancel_alt) {
+        keystate[VK_MENU] = keystate[VK_RMENU];
+        keystate[VK_LMENU] = 0;
+    }
 
     /*
      * Attempt the Windows char-map translation.
@@ -1315,7 +1409,7 @@ void set_title (char *title) {
     sfree (window_name);
     window_name = smalloc(1+strlen(title));
     strcpy (window_name, title);
-    if (!IsIconic(hwnd))
+    if (cfg.win_name_always || !IsIconic(hwnd))
        SetWindowText (hwnd, title);
 }
 
@@ -1323,7 +1417,7 @@ void set_icon (char *title) {
     sfree (icon_name);
     icon_name = smalloc(1+strlen(title));
     strcpy (icon_name, title);
-    if (IsIconic(hwnd))
+    if (!cfg.win_name_always && IsIconic(hwnd))
        SetWindowText (hwnd, title);
 }
 
@@ -1335,10 +1429,11 @@ void set_sbar (int total, int start, int page) {
     si.nMax = total - 1;
     si.nPage = page;
     si.nPos = start;
-    SetScrollInfo (hwnd, SB_VERT, &si, TRUE);
+    if (hwnd)
+        SetScrollInfo (hwnd, SB_VERT, &si, TRUE);
 }
 
-Context get_ctx() {
+Context get_ctx(void) {
     HDC hdc;
     if (hwnd) {
        hdc = GetDC (hwnd);
@@ -1466,11 +1561,10 @@ void get_clip (void **p, int *len) {
  */
 void optimised_move (int to, int from, int lines) {
     RECT r;
-    int min, max, d;
+    int min, max;
 
     min = (to < from ? to : from);
     max = to + from - min;
-    d = max - min;
 
     r.left = 0; r.right = cols * font_width;
     r.top = min * font_height; r.bottom = (max+lines) * font_height;