From ec55b2200b3a40631648cfa02ed63207b58832fe Mon Sep 17 00:00:00 2001 From: simon Date: Mon, 9 Oct 2000 12:53:32 +0000 Subject: [PATCH] Robert de Bath's big patch: - cope with strange WinSock wrappers not supporting SIOCATMARK - define yet more terminal compatibility modes - support UK-ASCII (just like US-ASCII but # is a sterling sign) - support connection keepalives at a configurable interval git-svn-id: svn://svn.tartarus.org/sgt/putty@692 cda61777-01e9-0310-a592-d414129be87e --- putty.h | 3 +- settings.c | 2 + ssh.c | 8 +++ telnet.c | 13 ++++- terminal.c | 107 +++++++++++++++++++++++++++++------ windlg.c | 80 ++++++++++++++++---------- window.c | 188 +++++++++++++++++++++++++++++++++++++++++++++---------------- 7 files changed, 303 insertions(+), 98 deletions(-) diff --git a/putty.h b/putty.h index 48e9d2e5..88437d88 100644 --- a/putty.h +++ b/putty.h @@ -92,7 +92,7 @@ GLOBAL char *logfile; typedef enum { TS_AYT, TS_BRK, TS_SYNCH, TS_EC, TS_EL, TS_GA, TS_NOP, TS_ABORT, - TS_AO, TS_IP, TS_SUSP, TS_EOR, TS_EOF, TS_LECHO, TS_RECHO + TS_AO, TS_IP, TS_SUSP, TS_EOR, TS_EOF, TS_LECHO, TS_RECHO, TS_PING } Telnet_Special; typedef enum { @@ -139,6 +139,7 @@ typedef struct { enum { PROT_RAW, PROT_TELNET, PROT_SSH } protocol; int close_on_exit; int warn_on_close; + int ping_interval; /* SSH options */ char remote_cmd[512]; int nopty; diff --git a/settings.c b/settings.c index de1fb260..36db32ee 100644 --- a/settings.c +++ b/settings.c @@ -48,6 +48,7 @@ void save_settings (char *section, int do_host, Config *cfg) { } write_setting_i (sesskey, "CloseOnExit", !!cfg->close_on_exit); write_setting_i (sesskey, "WarnOnClose", !!cfg->warn_on_close); + write_setting_i (sesskey, "PingInterval", cfg->ping_interval); write_setting_s (sesskey, "TerminalType", cfg->termtype); write_setting_s (sesskey, "TerminalSpeed", cfg->termspeed); { @@ -157,6 +158,7 @@ void load_settings (char *section, int do_host, Config *cfg) { gppi (sesskey, "CloseOnExit", 1, &cfg->close_on_exit); gppi (sesskey, "WarnOnClose", 1, &cfg->warn_on_close); + gppi (sesskey, "PingInterval", 0, &cfg->ping_interval); gpps (sesskey, "TerminalType", "xterm", cfg->termtype, sizeof(cfg->termtype)); gpps (sesskey, "TerminalSpeed", "38400,38400", cfg->termspeed, diff --git a/ssh.c b/ssh.c index f0a26aad..509ea3ab 100644 --- a/ssh.c +++ b/ssh.c @@ -2611,6 +2611,14 @@ static void ssh_special (Telnet_Special code) { ssh2_pkt_send(); } logevent("Sent EOF message"); + } else if (code == TS_PING) { + if (ssh_version == 1) { + send_packet(SSH1_MSG_IGNORE, PKT_STR, "", PKT_END); + } else { + ssh2_pkt_init(SSH2_MSG_IGNORE); + ssh2_pkt_addstring_start(); + ssh2_pkt_send(); + } } else { /* do nothing */ } diff --git a/telnet.c b/telnet.c index 4fb39c63..97183481 100644 --- a/telnet.c +++ b/telnet.c @@ -631,8 +631,11 @@ static int telnet_msg (WPARAM wParam, LPARAM lParam) { case FD_CLOSE: { int clear_of_oob = 1; - if (ioctlsocket (s, SIOCATMARK, &clear_of_oob) < 0 ) - return -20000-WSAGetLastError(); + + /* Don't check for error return; some shims don't support + * this ioctl. + */ + ioctlsocket (s, SIOCATMARK, &clear_of_oob); in_synch = !clear_of_oob; @@ -747,6 +750,12 @@ static void telnet_special (Telnet_Special code) { send_opt (o_echo.nsend, o_echo.option); } break; + case TS_PING: + if (o_they_sga.state == ACTIVE) { + b[1] = NOP; + s_write (b, 2); + } + break; } } diff --git a/terminal.c b/terminal.c index e38daa37..8a1d68d3 100644 --- a/terminal.c +++ b/terminal.c @@ -25,7 +25,6 @@ #define CL_ANSI 0x2000 /* ANSI ECMA-48 not in the VT100..VT420 */ #define CL_OTHER 0x4000 /* Others, Xterm, linux, putty, dunno, etc */ -#define TM_ANSIMIN (CL_ANSIMIN) #define TM_VT100 (CL_ANSIMIN|CL_VT100) #define TM_VT100AVO (TM_VT100|CL_VT100AVO) #define TM_VT102 (TM_VT100AVO|CL_VT102) @@ -710,7 +709,7 @@ static void toggle_mode (int mode, int query, int state) { repeat_off = !state; break; case 25: /* enable/disable cursor */ - compatibility(VT220); + compatibility2(OTHER,VT220); cursor_on = state; seen_disp_event = TRUE; break; @@ -734,7 +733,7 @@ static void toggle_mode (int mode, int query, int state) { * DONT send TS_RECHO/TS_LECHO; the telnet daemon tries to fix the * tty and _really_ confuses some programs. */ - compatibility(VT220); + compatibility2(OTHER,VT220); ldisc = (state? &ldisc_simple : &ldisc_term); break; case 20: /* Return sends ... */ @@ -903,6 +902,14 @@ static int beep_overload = 0; } seen_disp_event = TRUE; break; + case '\177': /* Destructive backspace + This does nothing on a real VT100 */ + compatibility(OTHER); + if (curs_x && !wrapnext) curs_x--; + wrapnext = FALSE; + fix_cpos; + *cpos = (' ' | curr_attr | ATTR_ASCII); + break; } } else switch (termstate) { @@ -928,12 +935,21 @@ static int beep_overload = 0; * we use the same font as well as the same encoding. */ case ATTR_LINEDRW: - if (c<0x60 || c>0x7F) + if (c<0x5f || c>0x7F) *cpos++ = xlat_tty2scr((unsigned char)c) | curr_attr | ATTR_ASCII; + else if (c==0x5F) + *cpos++ = ' ' | curr_attr | ATTR_ASCII; else *cpos++ = ((unsigned char)c) | curr_attr | ATTR_LINEDRW; break; + case ATTR_GBCHR: + /* If UK-ASCII, make the '#' a LineDraw Pound */ + if (c == '#') { + *cpos++ = '}' | curr_attr | ATTR_LINEDRW; + break; + } + /*FALLTHROUGH*/ default: *cpos++ = xlat_tty2scr((unsigned char)c) | curr_attr | (c <= 0x7F ? cset_attr[cset] : ATTR_ASCII); @@ -1299,16 +1315,16 @@ static int beep_overload = 0; case 7: /* enable reverse video */ curr_attr |= ATTR_REVERSE; break; case 22: /* disable bold */ - compatibility(VT220); + compatibility2(OTHER,VT220); curr_attr &= ~ATTR_BOLD; break; case 24: /* disable underline */ - compatibility(VT220); + compatibility2(OTHER,VT220); curr_attr &= ~ATTR_UNDER; break; case 25: /* disable blink */ - compatibility(VT220); + compatibility2(OTHER,VT220); curr_attr &= ~ATTR_BLINK; break; case 27: /* disable reverse video */ - compatibility(VT220); + compatibility2(OTHER,VT220); curr_attr &= ~ATTR_REVERSE; break; case 30: case 31: case 32: case 33: case 34: case 35: case 36: case 37: @@ -1424,8 +1440,8 @@ static int beep_overload = 0; * This first appeared in the VT220, but we do need to get * back to PuTTY mode so I won't check it. * - * The arg == 60 is a PuTTY extension. - * The 2nd arg, 8bit vs 7bit is not obeyed. + * The arg in 40..42 are a PuTTY extension. + * The 2nd arg, 8bit vs 7bit is not checked. * * Setting VT102 mode should also change the Fkeys to * generate PF* codes as a real VT102 has no Fkeys. @@ -1435,9 +1451,47 @@ static int beep_overload = 0; * Note ESC c will NOT change this! */ - if (esc_args[0] == 61) compatibility_level = TM_VT102; - else if (esc_args[0] == 60) compatibility_level = TM_ANSIMIN; - else compatibility_level = TM_PUTTY; + switch (esc_args[0]) { + case 61: compatibility_level &= ~TM_VTXXX; + compatibility_level |= TM_VT102; break; + case 62: compatibility_level &= ~TM_VTXXX; + compatibility_level |= TM_VT220; break; + + default: if( esc_args[0] > 60 && esc_args[0] < 70 ) + compatibility_level |= TM_VTXXX; + break; + + case 40: compatibility_level &= TM_VTXXX; break; + case 41: compatibility_level = TM_PUTTY; break; + case 42: compatibility_level = TM_SCOANSI; break; + + case ARG_DEFAULT: + compatibility_level = TM_PUTTY; break; + case 50: break; + } + + /* Change the response to CSI c */ + if (esc_args[0] == 50) { + int i; + char lbuf[64]; + strcpy(id_string, "\033[?"); + for (i=1; isend ("\033/Z", 3); break; case '=': - app_cursor_keys = TRUE; + app_keypad_keys = TRUE; break; case '>': - app_cursor_keys = FALSE; + app_keypad_keys = FALSE; break; case '<': /* XXX This should switch to VT100 mode not current or default @@ -2000,7 +2054,28 @@ void term_mouse (Mouse_Button b, Mouse_Action a, int x, int y) { nl = TRUE; } while (q < nlpos && q < selend) - *p++ = (unsigned char) (*q++ & CHAR_MASK); + { + /* VT Specials -> ISO8859-1 */ + static const char poorman2[] = + "* # HTFFCRLF\xB0 \xB1 NLVT+ + + + + - - - - - + + + + | <=>=PI!=\xA3 \xB7 "; + + int ch = (*q & CHAR_MASK); + + if ((*q & ATTR_LINEDRW) && ch >= 0x60 && ch < 0x7F ) + { + int x; + *p++ = poorman2[2*(ch-0x60)]; + if ( (x = poorman2[2*(ch-0x60)+1]) != ' ') + *p++ = x; + } +#if 0 + else if ((*q & ATTR_GBCHR) && ch == '#') + *p++ = (unsigned char) 0xA3; +#endif + else + *p++ = (unsigned char) ch; + q++; + } if (nl) { int i; for (i=0; i STATICHEIGHT ? EDITHEIGHT : STATICHEIGHT); RECT r; int lwid, rwid, rpos; - rpos = GAPBETWEEN + (cp->width + GAPBETWEEN) / 2; + rpos = GAPBETWEEN + (100-percentedit) * (cp->width + GAPBETWEEN) / 100; lwid = rpos - 2*GAPBETWEEN; rwid = cp->width + GAPBETWEEN - rpos; @@ -766,8 +767,8 @@ enum { IDCX_ABOUT = IDC_ABOUT, IDCX_TAB, controlstartvalue, IDC0_SESSLOAD, IDC0_SESSSAVE, IDC0_SESSDEL, - IDC0_CLOSEEXIT, - IDC0_CLOSEWARN, + IDC0_PINGSTATIC, + IDC0_PINGEDIT, connectionpanelend, keyboardpanelstart, @@ -781,6 +782,7 @@ enum { IDCX_ABOUT = IDC_ABOUT, IDCX_TAB, controlstartvalue, IDC1_FUNCTILDE, IDC1_FUNCLINUX, IDC1_FUNCXTERM, + IDC1_FUNCVT400, IDC1_KPSTATIC, IDC1_KPNORMAL, IDC1_KPAPPLIC, @@ -819,6 +821,8 @@ enum { IDCX_ABOUT = IDC_ABOUT, IDCX_TAB, controlstartvalue, IDC3_LOCKSIZE, IDC3_WINTITLE, IDC3_WINEDIT, + IDC3_CLOSEEXIT, + IDC3_CLOSEWARN, windowpanelend, telnetpanelstart, @@ -948,18 +952,18 @@ static void init_dlg_ctrls(HWND hwnd) { CheckRadioButton (hwnd, IDC0_PROTRAW, IDC0_PROTSSH, cfg.protocol==PROT_SSH ? IDC0_PROTSSH : cfg.protocol==PROT_TELNET ? IDC0_PROTTELNET : IDC0_PROTRAW ); - CheckDlgButton (hwnd, IDC0_CLOSEEXIT, cfg.close_on_exit); - CheckDlgButton (hwnd, IDC0_CLOSEWARN, cfg.warn_on_close); + SetDlgItemInt (hwnd, IDC0_PINGEDIT, cfg.ping_interval, FALSE); CheckRadioButton (hwnd, IDC1_DEL008, IDC1_DEL127, cfg.bksp_is_delete ? IDC1_DEL127 : IDC1_DEL008); CheckRadioButton (hwnd, IDC1_HOMETILDE, IDC1_HOMERXVT, cfg.rxvt_homeend ? IDC1_HOMERXVT : IDC1_HOMETILDE); CheckRadioButton (hwnd, IDC1_FUNCTILDE, IDC1_FUNCXTERM, - cfg.funky_type ? - (cfg.funky_type==2 ? IDC1_FUNCXTERM - : IDC1_FUNCLINUX ) - : IDC1_FUNCTILDE); + cfg.funky_type == 0 ? IDC1_FUNCTILDE : + cfg.funky_type == 1 ? IDC1_FUNCLINUX : + cfg.funky_type == 2 ? IDC1_FUNCXTERM : + cfg.funky_type == 3 ? IDC1_FUNCVT400 : + IDC1_FUNCTILDE ); CheckRadioButton (hwnd, IDC1_CURNORMAL, IDC1_CURAPPLIC, cfg.app_cursor ? IDC1_CURAPPLIC : IDC1_CURNORMAL); CheckRadioButton (hwnd, IDC1_KPNORMAL, IDC1_KPNH, @@ -987,6 +991,8 @@ static void init_dlg_ctrls(HWND hwnd) { CheckDlgButton (hwnd, IDC3_BLINKCUR, cfg.blink_cur); CheckDlgButton (hwnd, IDC3_SCROLLBAR, cfg.scrollbar); CheckDlgButton (hwnd, IDC3_LOCKSIZE, cfg.locksize); + CheckDlgButton (hwnd, IDC3_CLOSEEXIT, cfg.close_on_exit); + CheckDlgButton (hwnd, IDC3_CLOSEWARN, cfg.warn_on_close); SetDlgItemText (hwnd, IDC4_TTEDIT, cfg.termtype); SetDlgItemText (hwnd, IDC4_TSEDIT, cfg.termspeed); @@ -1155,8 +1161,8 @@ static int GenericMainDlgProc (HWND hwnd, UINT msg, "&Save", IDC0_SESSSAVE, "&Delete", IDC0_SESSDEL, NULL); } - checkbox(&cp, "Close Window on E&xit", IDC0_CLOSEEXIT); - checkbox(&cp, "&Warn on Close", IDC0_CLOSEWARN); + staticedit(&cp, "Keepalive inter&val (minutes)", + IDC0_PINGSTATIC, IDC0_PINGEDIT, 25); tab.mask = TCIF_TEXT; tab.pszText = "Connection"; TabCtrl_InsertItem (tabctl, i++, &tab); @@ -1172,10 +1178,11 @@ static int GenericMainDlgProc (HWND hwnd, UINT msg, radioline(&cp, "Action of Home and End:", IDC1_HOMESTATIC, 2, "&Standard", IDC1_HOMETILDE, "&rxvt", IDC1_HOMERXVT, NULL); - radioline(&cp, "Function key and keypad layout:", IDC1_FUNCSTATIC, 3, + radioline(&cp, "Function key and keypad layout:", IDC1_FUNCSTATIC, 4, "&VT400", IDC1_FUNCTILDE, "&Linux", IDC1_FUNCLINUX, - "&Xterm R6", IDC1_FUNCXTERM, NULL); + "&Xterm R6", IDC1_FUNCXTERM, + "&VT400", IDC1_FUNCVT400, NULL); radioline(&cp, "Initial state of cursor keys:", IDC1_CURSTATIC, 2, "&Normal", IDC1_CURNORMAL, "A&pplication", IDC1_CURAPPLIC, NULL); @@ -1192,7 +1199,7 @@ static int GenericMainDlgProc (HWND hwnd, UINT msg, TabCtrl_InsertItem (tabctl, i++, &tab); } - /* The Terminal panel. Accelerators used: [aco] dghlmnprsw */ + /* The Terminal panel. Accelerators used: [aco] dghlmnprsvw */ { struct ctlpos cp; ctlposinit(&cp, hwnd, 6, 30); @@ -1224,6 +1231,8 @@ static int GenericMainDlgProc (HWND hwnd, UINT msg, checkbox(&cp, "&Blinking cursor", IDC3_BLINKCUR); checkbox(&cp, "Displa&y scrollbar", IDC3_SCROLLBAR); checkbox(&cp, "Loc&k Window size", IDC3_LOCKSIZE); + checkbox(&cp, "Close Window on E&xit", IDC3_CLOSEEXIT); + checkbox(&cp, "&Warn on Close", IDC3_CLOSEWARN); tab.mask = TCIF_TEXT; tab.pszText = "Window"; TabCtrl_InsertItem (tabctl, i++, &tab); } @@ -1233,9 +1242,9 @@ static int GenericMainDlgProc (HWND hwnd, UINT msg, struct ctlpos cp; ctlposinit(&cp, hwnd, 6, 30); if (dlgtype == 0) { - staticedit(&cp, "Terminal-&type string", IDC4_TTSTATIC, IDC4_TTEDIT); - staticedit(&cp, "Terminal-&speed string", IDC4_TSSTATIC, IDC4_TSEDIT); - staticedit(&cp, "Auto-login &username", IDC4_LOGSTATIC, IDC4_LOGEDIT); + staticedit(&cp, "Terminal-&type string", IDC4_TTSTATIC, IDC4_TTEDIT, 50); + staticedit(&cp, "Terminal-&speed string", IDC4_TSSTATIC, IDC4_TSEDIT, 50); + staticedit(&cp, "Auto-login &username", IDC4_LOGSTATIC, IDC4_LOGEDIT, 50); envsetter(&cp, "Environment variables:", IDC4_ENVSTATIC, "&Variable", IDC4_VARSTATIC, IDC4_VAREDIT, "Va&lue", IDC4_VALSTATIC, IDC4_VALEDIT, @@ -1254,8 +1263,8 @@ static int GenericMainDlgProc (HWND hwnd, UINT msg, struct ctlpos cp; ctlposinit(&cp, hwnd, 6, 30); if (dlgtype == 0) { - staticedit(&cp, "Terminal-&type string", IDC5_TTSTATIC, IDC5_TTEDIT); - staticedit(&cp, "Auto-login &username", IDC5_LOGSTATIC, IDC5_LOGEDIT); + staticedit(&cp, "Terminal-&type string", IDC5_TTSTATIC, IDC5_TTEDIT, 50); + staticedit(&cp, "Auto-login &username", IDC5_LOGSTATIC, IDC5_LOGEDIT, 50); multiedit(&cp, "&Remote command:", IDC5_CMDSTATIC, IDC5_CMDEDIT, 100, NULL); @@ -1340,7 +1349,7 @@ static int GenericMainDlgProc (HWND hwnd, UINT msg, { HWND ctl; ctl = GetDlgItem(hwnd, IDC0_HOST); - if (!ctl) ctl = GetDlgItem(hwnd, IDC0_CLOSEEXIT); + if (!ctl) ctl = GetDlgItem(hwnd, IDC0_PINGEDIT); SetFocus(ctl); } @@ -1427,16 +1436,6 @@ static int GenericMainDlgProc (HWND hwnd, UINT msg, if (HIWORD(wParam) == EN_CHANGE) MyGetDlgItemInt (hwnd, IDC0_PORT, &cfg.port); break; - case IDC0_CLOSEEXIT: - if (HIWORD(wParam) == BN_CLICKED || - HIWORD(wParam) == BN_DOUBLECLICKED) - cfg.close_on_exit = IsDlgButtonChecked (hwnd, IDC0_CLOSEEXIT); - break; - case IDC0_CLOSEWARN: - if (HIWORD(wParam) == BN_CLICKED || - HIWORD(wParam) == BN_DOUBLECLICKED) - cfg.warn_on_close = IsDlgButtonChecked (hwnd, IDC0_CLOSEWARN); - break; case IDC0_SESSEDIT: if (HIWORD(wParam) == EN_CHANGE) { SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_SETCURSEL, @@ -1529,6 +1528,10 @@ static int GenericMainDlgProc (HWND hwnd, UINT msg, SendDlgItemMessage (hwnd, IDC0_SESSLIST, LB_SETCURSEL, (WPARAM) -1, 0); } + case IDC0_PINGEDIT: + if (HIWORD(wParam) == EN_CHANGE) + MyGetDlgItemInt (hwnd, IDC0_PINGEDIT, &cfg.ping_interval); + break; case IDC1_DEL008: case IDC1_DEL127: if (HIWORD(wParam) == BN_CLICKED || @@ -1546,6 +1549,11 @@ static int GenericMainDlgProc (HWND hwnd, UINT msg, HIWORD(wParam) == BN_DOUBLECLICKED) cfg.funky_type = 2; break; + case IDC1_FUNCVT400: + if (HIWORD(wParam) == BN_CLICKED || + HIWORD(wParam) == BN_DOUBLECLICKED) + cfg.funky_type = 3; + break; case IDC1_FUNCTILDE: case IDC1_FUNCLINUX: if (HIWORD(wParam) == BN_CLICKED || @@ -1689,6 +1697,16 @@ static int GenericMainDlgProc (HWND hwnd, UINT msg, GetDlgItemText (hwnd, IDC3_WINEDIT, cfg.wintitle, sizeof(cfg.wintitle)-1); break; + case IDC3_CLOSEEXIT: + if (HIWORD(wParam) == BN_CLICKED || + HIWORD(wParam) == BN_DOUBLECLICKED) + cfg.close_on_exit = IsDlgButtonChecked (hwnd, IDC3_CLOSEEXIT); + break; + case IDC3_CLOSEWARN: + if (HIWORD(wParam) == BN_CLICKED || + HIWORD(wParam) == BN_DOUBLECLICKED) + cfg.warn_on_close = IsDlgButtonChecked (hwnd, IDC3_CLOSEWARN); + break; case IDC4_TTEDIT: if (HIWORD(wParam) == EN_CHANGE) GetDlgItemText (hwnd, IDC4_TTEDIT, cfg.termtype, diff --git a/window.c b/window.c index 7b7dee12..822cb01e 100644 --- a/window.c +++ b/window.c @@ -10,6 +10,7 @@ #include #include #include +#include #define PUTTY_DO_GLOBALS /* actually _define_ globals */ #include "putty.h" @@ -57,6 +58,8 @@ static WPARAM pend_netevent_wParam = 0; static LPARAM pend_netevent_lParam = 0; static void enact_pending_netevent(void); +static time_t last_movement = 0; + #define FONT_NORMAL 0 #define FONT_BOLD 1 #define FONT_UNDERLINE 2 @@ -512,10 +515,11 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) { has_focus = (GetForegroundWindow() == hwnd); UpdateWindow (hwnd); + if (GetMessage (&msg, NULL, 0, 0) == 1) { int timer_id = 0, long_timer = 0; - while (GetMessage (&msg, NULL, 0, 0) == 1) { + while (msg.message != WM_QUIT) { /* Sometimes DispatchMessage calls routines that use their own * GetMessage loop, setup this timer so we get some control back. * @@ -530,9 +534,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) { timer_id = SetTimer(hwnd, 1, 20, NULL); DispatchMessage (&msg); - /* This is too fast, but I'll leave it for now 'cause it shows - * how often term_update is called (far too often at times!) - */ + /* Make sure we blink everything that needs it. */ term_blink(0); /* Send the paste buffer if there's anything to send */ @@ -542,31 +544,44 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) { * we've delayed, reading the socket, writing, and repainting * the window. */ - if (!PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE)) { - if (pending_netevent) { - enact_pending_netevent(); + if (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) + continue; - term_blink(1); - } - } else continue; - if (!PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE)) { - if (timer_id) { - KillTimer(hwnd, timer_id); - timer_id = 0; - } - HideCaret(hwnd); - if (inbuf_head) - term_out(); - term_update(); - ShowCaret(hwnd); - if (!has_focus) - timer_id = SetTimer(hwnd, 1, 2000, NULL); - else if (cfg.blinktext) - timer_id = SetTimer(hwnd, 1, 250, NULL); - else - timer_id = SetTimer(hwnd, 1, 500, NULL); - long_timer = 1; + if (pending_netevent) { + enact_pending_netevent(); + + /* Force the cursor blink on */ + term_blink(1); + + if (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) + continue; } + + /* Okay there is now nothing to do so we make sure the screen is + * completely up to date then tell windows to call us in a little + * while. + */ + if (timer_id) { + KillTimer(hwnd, timer_id); + timer_id = 0; + } + HideCaret(hwnd); + if (inbuf_head) + term_out(); + term_update(); + ShowCaret(hwnd); + if (!has_focus) + timer_id = SetTimer(hwnd, 1, 59500, NULL); + else + timer_id = SetTimer(hwnd, 1, 250, NULL); + long_timer = 1; + + /* There's no point rescanning everything in the message queue + * so we do an apperently unneccesary wait here + */ + WaitMessage(); + if (GetMessage (&msg, NULL, 0, 0) != 1) + break; } } @@ -1013,6 +1028,16 @@ static LRESULT CALLBACK WndProc (HWND hwnd, UINT message, HideCaret(hwnd); term_update(); ShowCaret(hwnd); + if (cfg.ping_interval > 0) + { + time_t now; + time(&now); + if (now-last_movement > cfg.ping_interval * 60 - 10) + { + back->special(TS_PING); + last_movement = now; + } + } return 0; case WM_CREATE: break; @@ -1290,6 +1315,7 @@ static LRESULT CALLBACK WndProc (HWND hwnd, UINT message, pending_netevent = TRUE; pend_netevent_wParam=wParam; pend_netevent_lParam=lParam; + time(&last_movement); return 0; case WM_SETFOCUS: has_focus = TRUE; @@ -1569,16 +1595,7 @@ void do_text (Context ctx, int x, int y, char *text, int len, } } - if (attr & ATTR_GBCHR) { - int i; - /* - * GB mapping: map # to pound, and everything else stays - * normal. - */ - for (i=0; i= VK_F1 && wParam <= VK_F20 ) + debug(("K_F%d", wParam+1-VK_F1)); + else switch(wParam) + { + case VK_SHIFT: debug(("SHIFT")); break; + case VK_CONTROL: debug(("CTRL")); break; + case VK_MENU: debug(("ALT")); break; + default: debug(("VK_%02x", wParam)); + } + if(message == WM_SYSKEYDOWN || message == WM_SYSKEYUP) + debug(("*")); + debug((", S%02x", scan=(HIWORD(lParam) & 0xFF) )); + + ch = MapVirtualKey(wParam, 2); + if (ch>=' ' && ch<='~') debug((", '%c'", ch)); + else if (ch) debug((", $%02x", ch)); + + if (keys[0]) debug((", KB0=%02x", keys[0])); + if (keys[1]) debug((", KB1=%02x", keys[1])); + if (keys[2]) debug((", KB2=%02x", keys[2])); + + if ( (keystate[VK_SHIFT]&0x80)!=0) debug((", S")); + if ( (keystate[VK_CONTROL]&0x80)!=0) debug((", C")); + if ( (HIWORD(lParam)&KF_EXTENDED) ) debug((", E")); + if ( (HIWORD(lParam)&KF_UP) ) debug((", U")); + } + + if ((HIWORD(lParam)&(KF_UP|KF_REPEAT))==KF_REPEAT) + ; + else if ( (HIWORD(lParam)&KF_UP) ) + oldstate[wParam&0xFF] ^= 0x80; + else + oldstate[wParam&0xFF] ^= 0x81; + + for(ch=0; ch<256; ch++) + if (oldstate[ch] != keystate[ch]) + debug((", M%02x=%02x", ch, keystate[ch])); + + memcpy(oldstate, keystate, sizeof(oldstate)); + } +#endif + /* Note if AltGr was pressed and if it was used as a compose key */ if (wParam == VK_MENU && (HIWORD(lParam)&KF_EXTENDED)) { @@ -1789,7 +1865,7 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam, unsigned cha compose_state = 0; /* Nastyness with NUMLock - Shift-NUMLock is left alone though */ - if ( (cfg.funky_type == 0 || (cfg.funky_type == 1 && app_keypad_keys)) + if ( (cfg.funky_type == 3 || (cfg.funky_type <= 1 && app_keypad_keys)) && wParam==VK_NUMLOCK && !(keystate[VK_SHIFT]&0x80)) { wParam = VK_EXECUTE; @@ -1835,7 +1911,7 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam, unsigned cha /* Sanitize the number pad if not using a PC NumPad */ if( left_alt || (app_keypad_keys && cfg.funky_type != 2) - || cfg.nethack_keypad || compose_state ) + || cfg.funky_type == 3 || cfg.nethack_keypad || compose_state ) { if ((HIWORD(lParam)&KF_EXTENDED) == 0) { @@ -1890,6 +1966,11 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam, unsigned cha SendMessage (hwnd, WM_SYSCOMMAND, SC_KEYMENU, 0); return -1; } + /* Control-Numlock for app-keypad mode switch */ + if (wParam == VK_PAUSE && shift_state == 2) { + app_keypad_keys ^= 1; + return 0; + } /* Nethack keypad */ if (cfg.nethack_keypad && !left_alt) { @@ -1910,9 +1991,9 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam, unsigned cha if (!left_alt) { int xkey = 0; - if ( cfg.funky_type == 0 || - ( cfg.funky_type == 1 && app_keypad_keys)) switch(wParam) { - case VK_EXECUTE: if (app_keypad_keys) xkey = 'P'; break; + if ( cfg.funky_type == 3 || + ( cfg.funky_type <= 1 && app_keypad_keys)) switch(wParam) { + case VK_EXECUTE: xkey = 'P'; break; case VK_DIVIDE: xkey = 'Q'; break; case VK_MULTIPLY:xkey = 'R'; break; case VK_SUBTRACT:xkey = 'S'; break; @@ -1930,9 +2011,17 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam, unsigned cha case VK_NUMPAD9: xkey = 'y'; break; case VK_DECIMAL: xkey = 'n'; break; - case VK_ADD: if(shift_state) xkey = 'm'; - else xkey = 'l'; + case VK_ADD: if(cfg.funky_type==2) { + if(shift_state) xkey = 'l'; + else xkey = 'k'; + } else if(shift_state) xkey = 'm'; + else xkey = 'l'; break; + + case VK_DIVIDE: if(cfg.funky_type==2) xkey = 'o'; break; + case VK_MULTIPLY:if(cfg.funky_type==2) xkey = 'j'; break; + case VK_SUBTRACT:if(cfg.funky_type==2) xkey = 'm'; break; + case VK_RETURN: if (HIWORD(lParam)&KF_EXTENDED) xkey = 'M'; @@ -2031,12 +2120,18 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam, unsigned cha case VK_PRIOR: code = 5; break; case VK_NEXT: code = 6; break; } + /* Reorder edit keys to physical order */ + if (cfg.funky_type == 3 && code <= 6 ) code = "\0\2\1\4\5\3\6"[code]; + if (cfg.funky_type == 1 && code >= 11 && code <= 15) { p += sprintf((char *)p, "\x1B[[%c", code + 'A' - 11); return p - output; } if (cfg.funky_type == 2 && code >= 11 && code <= 14) { - p += sprintf((char *)p, "\x1BO%c", code + 'P' - 11); + if (vt52_mode) + p += sprintf((char *)p, "\x1B%c", code + 'P' - 11); + else + p += sprintf((char *)p, "\x1BO%c", code + 'P' - 11); return p - output; } if (cfg.rxvt_homeend && (code == 1 || code == 4)) { @@ -2141,10 +2236,7 @@ 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) - { - keystate[VK_MENU] = 0; return 0; - } return -1; } -- 2.11.0