#include <windows.h>
#include <imm.h>
#include <commctrl.h>
+#include <mmsystem.h>
#ifndef AUTO_WINSOCK
#ifdef WINSOCK_TWO
#include <winsock2.h>
#define IDM_SAVEDSESS 0x0150
#define IDM_COPYALL 0x0160
+#define IDM_SESSLGP 0x0250 /* log type printable */
+#define IDM_SESSLGA 0x0260 /* log type all chars */
+#define IDM_SESSLGE 0x0270 /* log end */
#define IDM_SAVED_MIN 0x1000
#define IDM_SAVED_MAX 0x2000
static char *window_name, *icon_name;
-static Ldisc *real_ldisc;
-
static int compose_state = 0;
-void begin_session(void) {
- ldisc = real_ldisc;
-}
+/* Dummy routine, only required in plink. */
+void ldisc_update(int echo, int edit) {}
int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) {
static char appname[] = "PuTTY";
return 1;
}
- real_ldisc = (cfg.ldisc_term ? &ldisc_term : &ldisc_simple);
- /* To start with, we use the simple line discipline, so we can
- * type passwords etc without fear of them being echoed... */
- ldisc = &ldisc_simple;
-
if (!prev) {
wndclass.style = 0;
wndclass.lpfnWndProc = WndProc;
error = back->init (cfg.host, cfg.port, &realhost);
if (error) {
- sprintf(msg, "Unable to open connection:\n%s", error);
+ sprintf(msg, "Unable to open connection to\n"
+ "%.800s\n"
+ "%s", cfg.host, error);
MessageBox(NULL, msg, "PuTTY Error", MB_ICONERROR | MB_OK);
return 0;
}
}
if(!timer_id)
timer_id = SetTimer(hwnd, 1, 20, NULL);
- DispatchMessage (&msg);
+ if (!(IsWindow(logbox) && IsDialogMessage(logbox, &msg)))
+ DispatchMessage (&msg);
/* Make sure we blink everything that needs it. */
term_blink(0);
term_out();
term_update();
ShowCaret(hwnd);
- if (!has_focus)
+ if (in_vbell)
+ /* Hmm, term_update didn't want to do an update too soon ... */
+ timer_id = SetTimer(hwnd, 1, 50, NULL);
+ else if (!has_focus)
timer_id = SetTimer(hwnd, 1, 59500, NULL);
else
timer_id = SetTimer(hwnd, 1, 100, NULL);
long_timer = 1;
/* There's no point rescanning everything in the message queue
- * so we do an apperently unneccesary wait here
+ * so we do an apparently unnecessary wait here
*/
WaitMessage();
if (GetMessage (&msg, NULL, 0, 0) != 1)
vsprintf(stuff, fmt, ap);
va_end(ap);
MessageBox(hwnd, stuff, "PuTTY Fatal Error", MB_ICONERROR | MB_OK);
- if (cfg.close_on_exit)
+ if (cfg.close_on_exit == COE_ALWAYS)
PostQuitMessage(1);
else {
session_closed = TRUE;
ret = select_result (pend_netevent_wParam, pend_netevent_lParam);
reentering = 0;
- if (ret == 0) {
- if (cfg.close_on_exit)
+ if (ret == 0 && !session_closed) {
+ /* Abnormal exits will already have set session_closed and taken
+ * appropriate action. */
+ if (cfg.close_on_exit == COE_ALWAYS ||
+ cfg.close_on_exit == COE_NORMAL)
PostQuitMessage(0);
else {
- session_closed = TRUE;
- MessageBox(hwnd, "Connection closed by remote host",
- "PuTTY", MB_OK | MB_ICONINFORMATION);
- SetWindowText (hwnd, "PuTTY (inactive)");
+ session_closed = TRUE;
+ SetWindowText (hwnd, "PuTTY (inactive)");
+ MessageBox(hwnd, "Connection closed by remote host",
+ "PuTTY", MB_OK | MB_ICONINFORMATION);
}
}
}
hdc = GetDC(hwnd);
font_height = cfg.fontheight;
+ if (font_height > 0) {
+ font_height = -MulDiv(font_height, GetDeviceCaps(hdc, LOGPIXELSY), 72);
+ }
font_width = pick_width;
#define f(i,c,w,u) \
init_fonts(0);
sfree(logpal);
/*
- * Telnet will change local echo -> remote if the
- * remote asks.
+ * Flush the line discipline's edit buffer in the
+ * case where local editing has just been disabled.
*/
- if (cfg.protocol != PROT_TELNET)
- ldisc = (cfg.ldisc_term ? &ldisc_term : &ldisc_simple);
+ ldisc_send(NULL, 0);
if (pal)
DeleteObject(pal);
logpal = NULL;
TO_CHR_Y(Y_POS(lParam)));
}
return 0;
+ case WM_NCMOUSEMOVE:
+ show_mouseptr(1);
+ noise_ultralight(lParam);
+ return 0;
case WM_IGNORE_CLIP:
ignore_clip = wParam; /* don't panic on DESTROYCLIPBOARD */
break;
len = TranslateKey (message, wParam, lParam, buf);
if (len == -1)
return DefWindowProc (hwnd, message, wParam, lParam);
- ldisc->send (buf, len);
+ ldisc_send (buf, len);
if (len > 0)
show_mouseptr(0);
buf[1] = wParam;
buf[0] = wParam >> 8;
- ldisc->send (buf, 2);
+ ldisc_send (buf, 2);
}
case WM_CHAR:
case WM_SYSCHAR:
*/
{
char c = xlat_kbd2tty((unsigned char)wParam);
- ldisc->send (&c, 1);
+ ldisc_send (&c, 1);
}
return 0;
}
* have one.)
*/
void sys_cursor(int x, int y) {
- SetCaretPos(x * font_width, y * font_height);
+ if (has_focus)
+ SetCaretPos(x * font_width, y * font_height);
}
/*
#endif
/* This is CP437 ... junk translation */
static const unsigned char oemhighhalf[] = {
- 0xff, 0xad, 0x9b, 0x9c, 0x6f, 0x9d, 0x7c, 0x15,
+ 0x20, 0xad, 0x9b, 0x9c, 0x6f, 0x9d, 0x7c, 0x15,
0x22, 0x43, 0xa6, 0xae, 0xaa, 0x2d, 0x52, 0xc4,
0xf8, 0xf1, 0xfd, 0x33, 0x27, 0xe6, 0x14, 0xfa,
0x2c, 0x31, 0xa7, 0xaf, 0xac, 0xab, 0x2f, 0xa8,
keystate[VK_RMENU] = keystate[VK_MENU];
}
- /* Note if AltGr was pressed and if it was used as a compose key */
- if (cfg.compose_key) {
- if (wParam == VK_MENU && (HIWORD(lParam)&KF_EXTENDED))
- {
- if (!compose_state) compose_key = wParam;
- }
- if (wParam == VK_APPS && !compose_state)
- compose_key = wParam;
-
- if (wParam == compose_key)
- {
- if (compose_state == 0 && (HIWORD(lParam)&(KF_UP|KF_REPEAT))==0)
- compose_state = 1;
- else if (compose_state == 1 && (HIWORD(lParam)&KF_UP))
- compose_state = 2;
- else
- compose_state = 0;
- }
- else if (compose_state==1 && wParam != VK_CONTROL)
- compose_state = 0;
- } else {
- compose_state = 0;
- }
/* Nastyness with NUMLock - Shift-NUMLock is left alone though */
if ( (cfg.funky_type == 3 ||
key_down = ((HIWORD(lParam)&KF_UP)==0);
- /* Make sure Ctrl-ALT is not the same as AltGr for ToAscii */
- if (left_alt && (keystate[VK_CONTROL]&0x80))
- keystate[VK_MENU] = 0;
+ /* Make sure Ctrl-ALT is not the same as AltGr for ToAscii unless told. */
+ if (left_alt && (keystate[VK_CONTROL]&0x80)) {
+ if (cfg.ctrlaltkeys)
+ keystate[VK_MENU] = 0;
+ else {
+ keystate[VK_RMENU] = 0x80;
+ left_alt = 0;
+ }
+ }
scan = (HIWORD(lParam) & (KF_UP | KF_EXTENDED | 0xFF));
shift_state = ((keystate[VK_SHIFT]&0x80)!=0)
+ ((keystate[VK_CONTROL]&0x80)!=0)*2;
+ /* Note if AltGr was pressed and if it was used as a compose key */
+ if (!compose_state) {
+ compose_key = 0x100;
+ if (cfg.compose_key) {
+ if (wParam == VK_MENU && (HIWORD(lParam)&KF_EXTENDED))
+ compose_key = wParam;
+ }
+ if (wParam == VK_APPS)
+ compose_key = wParam;
+ }
+
+ if (wParam == compose_key)
+ {
+ if (compose_state == 0 && (HIWORD(lParam)&(KF_UP|KF_REPEAT))==0)
+ compose_state = 1;
+ else if (compose_state == 1 && (HIWORD(lParam)&KF_UP))
+ compose_state = 2;
+ else
+ compose_state = 0;
+ }
+ else if (compose_state==1 && wParam != VK_CONTROL)
+ compose_state = 0;
+
/*
* Record that we pressed key so the scroll window can be reset, but
* be careful to avoid Shift-UP/Down
{
*p++ = 3; return p - output;
}
+ if (wParam == VK_PAUSE) /* Break/Pause */
+ {
+ *p++ = 26; *p++ = 0; return -2;
+ }
/* Control-2 to Control-8 are special */
if (shift_state == 2 && wParam >= '2' && wParam <= '8')
{
/* Reorder edit keys to physical order */
if (cfg.funky_type == 3 && code <= 6 ) code = "\0\2\1\4\5\3\6"[code];
+ if (vt52_mode && code > 0 && code <= 6) {
+ p += sprintf((char *)p, "\x1B%c", " HLMEIG"[code]);
+ return p - output;
+ }
+
+ if (cfg.funky_type == 5 && code >= 11 && code <= 24) {
+ p += sprintf((char *)p, "\x1B[%c", code + 'M' - 11);
+ return p - output;
+ }
+ if ((vt52_mode || cfg.funky_type == 4) && code >= 11 && code <= 24) {
+ int offt = 0;
+ if (code>15) offt++; if (code>21) offt++;
+ if (vt52_mode)
+ p += sprintf((char *)p, "\x1B%c", code + 'P' - 11 - offt);
+ else
+ p += sprintf((char *)p, "\x1BO%c", code + 'P' - 11 - offt);
+ return p - output;
+ }
if (cfg.funky_type == 1 && code >= 11 && code <= 15) {
p += sprintf((char *)p, "\x1B[[%c", code + 'A' - 11);
return p - output;
return p-output;
}
+ /* If we're definitly not building up an ALT-54321 then clear it */
+ if (!left_alt) keys[0] = 0;
}
/* ALT alone may or may not want to bring up the System menu */
} else
return 0;
}
+ else alt_state = 0;
return -1;
}
/*
* Beep.
*/
-void beep(int errorbeep) {
- static long last_beep = 0;
- long now, beep_diff;
-
- now = GetTickCount();
- beep_diff = now-last_beep;
-
- /* Make sure we only respond to one beep per packet or so */
- if (beep_diff>=0 && beep_diff<50)
- return;
-
- if(errorbeep)
- MessageBeep(MB_ICONHAND);
- else
- MessageBeep(MB_OK);
-
- last_beep = GetTickCount();
+void beep(int mode) {
+ if (mode == BELL_DEFAULT) {
+ /*
+ * For MessageBeep style bells, we want to be careful of
+ * timing, because they don't have the nice property of
+ * PlaySound bells that each one cancels the previous
+ * active one. So we limit the rate to one per 50ms or so.
+ */
+ static long lastbeep = 0;
+ long now, beepdiff;
+
+ now = GetTickCount();
+ beepdiff = now - lastbeep;
+ if (beepdiff >= 0 && beepdiff < 50)
+ return;
+ MessageBeep(MB_OK);
+ lastbeep = now;
+ } else if (mode == BELL_WAVEFILE) {
+ if (!PlaySound(cfg.bell_wavefile, NULL, SND_ASYNC | SND_FILENAME)) {
+ char buf[sizeof(cfg.bell_wavefile)+80];
+ sprintf(buf, "Unable to play sound file\n%s\n"
+ "Using default sound instead", cfg.bell_wavefile);
+ MessageBox(hwnd, buf, "PuTTY Sound Error", MB_OK | MB_ICONEXCLAMATION);
+ cfg.beep = BELL_DEFAULT;
+ }
+ }
}