Add a configuration option for TCP keepalives (SO_KEEPALIVE), default off.
[u/mdw/putty] / window.c
index c76b083..e720ed3 100644 (file)
--- a/window.c
+++ b/window.c
@@ -110,7 +110,6 @@ static struct unicode_data ucsdata;
 static int session_closed;
 
 static const struct telnet_special *specials;
-static int specials_menu_position;
 
 static struct {
     HMENU menu;
@@ -612,7 +611,8 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
        char *realhost;
 
        error = back->init(NULL, &backhandle, &cfg,
-                          cfg.host, cfg.port, &realhost, cfg.tcp_nodelay);
+                          cfg.host, cfg.port, &realhost, cfg.tcp_nodelay,
+                          cfg.tcp_keepalives);
        back->provide_logctx(backhandle, logctx);
        if (error) {
            char *str = dupprintf("%s Error", appname);
@@ -1082,6 +1082,36 @@ static void init_palette(void)
 }
 
 /*
+ * This is a wrapper to ExtTextOut() to force Windows to display
+ * the precise glyphs we give it. Otherwise it would do its own
+ * bidi and Arabic shaping, and we would end up uncertain which
+ * characters it had put where.
+ */
+static void exact_textout(HDC hdc, int x, int y, CONST RECT *lprc,
+                         unsigned short *lpString, UINT cbCount,
+                         CONST INT *lpDx)
+{
+
+    GCP_RESULTSW gcpr;
+    char *buffer = snewn(cbCount*2+2, char);
+    char *classbuffer = snewn(cbCount, char);
+    memset(&gcpr, 0, sizeof(gcpr));
+    memset(buffer, 0, cbCount*2+2);
+    memset(classbuffer, GCPCLASS_NEUTRAL, cbCount);
+
+    gcpr.lStructSize = sizeof(gcpr);
+    gcpr.lpGlyphs = (void *)buffer;
+    gcpr.lpClass = classbuffer;
+    gcpr.nGlyphs = cbCount;
+
+    GetCharacterPlacementW(hdc, lpString, cbCount, 0, &gcpr,
+                          FLI_MASK | GCP_CLASSIN);
+
+    ExtTextOut(hdc, x, y, ETO_GLYPH_INDEX | ETO_CLIPPED | ETO_OPAQUE, lprc,
+              buffer, cbCount, lpDx);
+}
+
+/*
  * Initialise all the fonts we will need initially. There may be as many as
  * three or as few as one.  The other (poentially) twentyone fonts are done
  * if/when they are needed.
@@ -2078,11 +2108,42 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
             * window, we put up the System menu instead of doing
             * selection.
             */
-           if (is_full_screen() && press && button == MBT_LEFT &&
-               X_POS(lParam) == 0 && Y_POS(lParam) == 0) {
-               SendMessage(hwnd, WM_SYSCOMMAND, SC_MOUSEMENU, 0);
-               return 0;
+           {
+               char mouse_on_hotspot = 0;
+               POINT pt;
+
+               GetCursorPos(&pt);
+#ifndef NO_MULTIMON
+               {
+                   HMONITOR mon;
+                   MONITORINFO mi;
+
+                   mon = MonitorFromPoint(pt, MONITOR_DEFAULTTONULL);
+
+                   if (mon != NULL) {
+                       mi.cbSize = sizeof(MONITORINFO);
+                       GetMonitorInfo(mon, &mi);
+
+                       if (mi.rcMonitor.left == pt.x &&
+                           mi.rcMonitor.top == pt.y) {
+                           mouse_on_hotspot = 1;
+                       }
+                       CloseHandle(mon);
+                   }
+               }
+#else
+               if (pt.x == 0 && pt.y == 0) {
+                   mouse_on_hotspot = 1;
+               }
+#endif
+               if (is_full_screen() && press &&
+                   button == MBT_LEFT && mouse_on_hotspot) {
+                   SendMessage(hwnd, WM_SYSCOMMAND, SC_MOUSEMENU,
+                               MAKELPARAM(pt.x, pt.y));
+                   return 0;
+               }
            }
+
            if (press) {
                click(button,
                      TO_CHR_X(X_POS(lParam)), TO_CHR_Y(Y_POS(lParam)),
@@ -2959,9 +3020,13 @@ void do_text(Context ctx, int x, int y, char *text, int len,
        for (i = 0; i < len; i++)
            wbuf[i] = (WCHAR) ((attr & CSET_MASK) + (text[i] & CHAR_MASK));
 
-       ExtTextOutW(hdc, x,
+       /* print Glyphs as they are, without Windows' Shaping*/
+       exact_textout(hdc, x, y - font_height * (lattr == LATTR_BOT) + text_adjust,
+                     &line_box, wbuf, len, IpDx);
+/*     ExtTextOutW(hdc, x,
                    y - font_height * (lattr == LATTR_BOT) + text_adjust,
                    ETO_CLIPPED | ETO_OPAQUE, &line_box, wbuf, len, IpDx);
+ */
 
        /* And the shadow bold hack. */
        if (bold_mode == BOLD_SHADOW && (attr & ATTR_BOLD)) {
@@ -3140,6 +3205,7 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam,
 
     HKL kbd_layout = GetKeyboardLayout(0);
 
+    /* keys is for ToAsciiEx. There's some ick here, see below. */
     static WORD keys[3];
     static int compose_char = 0;
     static WPARAM compose_key = 0;
@@ -3831,7 +3897,27 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam,
            keystate[VK_CAPITAL] = 0;
        }
 
-       r = ToAsciiEx(wParam, scan, keystate, keys, 0, kbd_layout);
+       /* XXX how do we know what the max size of the keys array should
+        * be is? There's indication on MS' website of an Inquire/InquireEx
+        * functioning returning a KBINFO structure which tells us. */
+       if (osVersion.dwPlatformId == VER_PLATFORM_WIN32_NT) {
+           /* XXX 'keys' parameter is declared in MSDN documentation as
+            * 'LPWORD lpChar'.
+            * The experience of a French user indicates that on
+            * Win98, WORD[] should be passed in, but on Win2K, it should
+            * be BYTE[]. German WinXP and my Win2K with "US International"
+            * driver corroborate this.
+            * Experimentally I've conditionalised the behaviour on the
+            * Win9x/NT split, but I suspect it's worse than that.
+            * See wishlist item `win-dead-keys' for more horrible detail
+            * and speculations. */
+           BYTE keybs[3];
+           int i;
+           r = ToAsciiEx(wParam, scan, keystate, (LPWORD)keybs, 0, kbd_layout);
+           for (i=0; i<3; i++) keys[i] = keybs[i];
+       } else {
+           r = ToAsciiEx(wParam, scan, keystate, keys, 0, kbd_layout);
+       }
 #ifdef SHOW_TOASCII_RESULT
        if (r == 1 && !key_down) {
            if (alt_sum) {
@@ -4570,7 +4656,7 @@ char *get_window_title(void *frontend, int icon)
 /*
  * See if we're in full-screen mode.
  */
-int is_full_screen()
+static int is_full_screen()
 {
     if (!IsZoomed(hwnd))
        return FALSE;
@@ -4609,7 +4695,7 @@ static int get_fullscreen_rect(RECT * ss)
  * Go full-screen. This should only be called when we are already
  * maximised.
  */
-void make_full_screen()
+static void make_full_screen()
 {
     DWORD style;
        RECT ss;
@@ -4643,7 +4729,7 @@ void make_full_screen()
 /*
  * Clear the full-screen attributes.
  */
-void clear_full_screen()
+static void clear_full_screen()
 {
     DWORD oldstyle, style;
 
@@ -4673,7 +4759,7 @@ void clear_full_screen()
 /*
  * Toggle full-screen mode.
  */
-void flip_full_screen()
+static void flip_full_screen()
 {
     if (is_full_screen()) {
        ShowWindow(hwnd, SW_RESTORE);