#include <winsock.h>
#include <stdio.h>
#include <stdlib.h>
+#include <ctype.h>
#define PUTTY_DO_GLOBALS /* actually _define_ globals */
#include "putty.h"
#define WM_IGNORE_SIZE (WM_USER + 2)
#define WM_IGNORE_CLIP (WM_USER + 3)
-static int WINAPI WndProc (HWND, UINT, WPARAM, LPARAM);
+static LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
static int TranslateKey(WPARAM wParam, LPARAM lParam, unsigned char *output);
static void cfgtopalette(void);
static void init_palette(void);
tolower(p[2]) == 'h') {
default_protocol = cfg.protocol = PROT_SSH;
default_port = cfg.port = 22;
+ } else if (q == p + 3 &&
+ tolower(p[0]) == 'l' &&
+ tolower(p[1]) == 'o' &&
+ tolower(p[2]) == 'g') {
+ logfile = "putty.log";
}
p = q + strspn(q, " \t");
}
*/
HANDLE filemap;
Config *cp;
- if (sscanf(p+1, "%x", &filemap) == 1 &&
+ if (sscanf(p+1, "%p", &filemap) == 1 &&
(cp = MapViewOfFile(filemap, FILE_MAP_READ,
0, 0, sizeof(Config))) != NULL) {
cfg = *cp;
}
}
- back = (cfg.protocol == PROT_SSH ? &ssh_backend :
- cfg.protocol == PROT_TELNET ? &telnet_backend :
- &raw_backend);
+ /*
+ * Select protocol. This is farmed out into a table in a
+ * separate file to enable an ssh-free variant.
+ */
+ {
+ int i;
+ back = NULL;
+ for (i = 0; backends[i].backend != NULL; i++)
+ if (backends[i].protocol == cfg.protocol) {
+ back = backends[i].backend;
+ break;
+ }
+ if (back == NULL) {
+ MessageBox(NULL, "Unsupported protocol number found",
+ "PuTTY Internal Error", MB_OK | MB_ICONEXCLAMATION);
+ WSACleanup();
+ return 1;
+ }
+ }
ldisc = (cfg.ldisc_term ? &ldisc_term : &ldisc_simple);
set_icon (msg);
}
+ session_closed = FALSE;
+
/*
* Set up the input and output buffers.
*/
inbuf_reap = inbuf_head = 0;
outbuf_reap = outbuf_head = 0;
+ /*
+ * Choose unscroll method
+ */
+ unscroll_event = US_DISP;
+
/*
* Prepare the mouse handler.
*/
AppendMenu (m, MF_POPUP | MF_ENABLED, (UINT) p, "Telnet Command");
AppendMenu (m, MF_SEPARATOR, 0, 0);
}
- AppendMenu (m, MF_ENABLED, IDM_SHOWLOG, "Event Log");
+ AppendMenu (m, MF_ENABLED, IDM_SHOWLOG, "&Event Log");
AppendMenu (m, MF_SEPARATOR, 0, 0);
- AppendMenu (m, MF_ENABLED, IDM_NEWSESS, "New Session");
- AppendMenu (m, MF_ENABLED, IDM_DUPSESS, "Duplicate Session");
+ AppendMenu (m, MF_ENABLED, IDM_NEWSESS, "Ne&w Session");
+ AppendMenu (m, MF_ENABLED, IDM_DUPSESS, "&Duplicate Session");
s = CreateMenu();
get_sesslist(TRUE);
for (i = 1 ; i < ((nsessions < 256) ? nsessions : 256) ; i++)
AppendMenu (s, MF_ENABLED, IDM_SAVED_MIN + (16 * i) , sessions[i]);
- AppendMenu (m, MF_POPUP | MF_ENABLED, (UINT) s, "Saved Sessions");
- AppendMenu (m, MF_ENABLED, IDM_RECONF, "Change Settings");
+ AppendMenu (m, MF_POPUP | MF_ENABLED, (UINT) s, "Sa&ved Sessions");
+ AppendMenu (m, MF_ENABLED, IDM_RECONF, "Chan&ge Settings");
AppendMenu (m, MF_SEPARATOR, 0, 0);
- AppendMenu (m, MF_ENABLED, IDM_CLRSB, "Clear Scrollback");
- AppendMenu (m, MF_ENABLED, IDM_RESET, "Reset Terminal");
+ AppendMenu (m, MF_ENABLED, IDM_CLRSB, "C&lear Scrollback");
+ AppendMenu (m, MF_ENABLED, IDM_RESET, "Rese&t Terminal");
AppendMenu (m, MF_SEPARATOR, 0, 0);
- AppendMenu (m, MF_ENABLED, IDM_ABOUT, "About PuTTY");
+ AppendMenu (m, MF_ENABLED, IDM_ABOUT, "&About PuTTY");
}
/*
*/
static void init_fonts(void) {
TEXTMETRIC tm;
- int i, j;
- int widths[5];
+ int i;
+ int fsize[5];
HDC hdc;
int fw_dontcare, fw_bold;
+ int firstchar = ' ';
+font_messup:
for (i=0; i<8; i++)
fonts[i] = NULL;
fw_bold = FW_BOLD;
}
+ hdc = GetDC(hwnd);
+
+ font_height = cfg.fontheight;
+ font_width = 0;
+
#define f(i,c,w,u) \
- fonts[i] = CreateFont (cfg.fontheight, 0, 0, 0, w, FALSE, u, FALSE, \
+ fonts[i] = CreateFont (font_height, font_width, 0, 0, w, FALSE, u, FALSE, \
c, OUT_DEFAULT_PRECIS, \
CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, \
FIXED_PITCH | FF_DONTCARE, cfg.font)
+
if (cfg.vtmode != VT_OEMONLY) {
f(FONT_NORMAL, cfg.fontcharset, fw_dontcare, FALSE);
+
+ SelectObject (hdc, fonts[FONT_NORMAL]);
+ GetTextMetrics(hdc, &tm);
+ font_height = tm.tmHeight;
+ font_width = tm.tmAveCharWidth;
+
f(FONT_UNDERLINE, cfg.fontcharset, fw_dontcare, TRUE);
- }
- if (cfg.vtmode == VT_OEMANSI || cfg.vtmode == VT_OEMONLY) {
- f(FONT_OEM, OEM_CHARSET, fw_dontcare, FALSE);
- f(FONT_OEMUND, OEM_CHARSET, fw_dontcare, TRUE);
- }
- if (bold_mode == BOLD_FONT) {
- if (cfg.vtmode != VT_OEMONLY) {
+
+ if (bold_mode == BOLD_FONT) {
f(FONT_BOLD, cfg.fontcharset, fw_bold, FALSE);
f(FONT_BOLDUND, cfg.fontcharset, fw_bold, TRUE);
}
- if (cfg.vtmode == VT_OEMANSI || cfg.vtmode == VT_OEMONLY) {
- f(FONT_OEMBOLD, OEM_CHARSET, fw_bold, FALSE);
- f(FONT_OEMBOLDUND, OEM_CHARSET, fw_bold, TRUE);
+
+ if (cfg.vtmode == VT_OEMANSI) {
+ f(FONT_OEM, OEM_CHARSET, fw_dontcare, FALSE);
+ f(FONT_OEMUND, OEM_CHARSET, fw_dontcare, TRUE);
+
+ if (bold_mode == BOLD_FONT) {
+ f(FONT_OEMBOLD, OEM_CHARSET, fw_bold, FALSE);
+ f(FONT_OEMBOLDUND, OEM_CHARSET, fw_bold, TRUE);
+ }
+ }
+ }
+ else
+ {
+ f(FONT_OEM, cfg.fontcharset, fw_dontcare, FALSE);
+
+ SelectObject (hdc, fonts[FONT_OEM]);
+ GetTextMetrics(hdc, &tm);
+ font_height = tm.tmHeight;
+ font_width = tm.tmAveCharWidth;
+
+ f(FONT_OEMUND, cfg.fontcharset, fw_dontcare, TRUE);
+
+ if (bold_mode == BOLD_FONT) {
+ f(FONT_BOLD, cfg.fontcharset, fw_bold, FALSE);
+ f(FONT_BOLDUND, cfg.fontcharset, fw_bold, TRUE);
}
- } else {
- fonts[FONT_BOLD] = fonts[FONT_BOLDUND] = NULL;
- fonts[FONT_OEMBOLD] = fonts[FONT_OEMBOLDUND] = NULL;
}
#undef f
- hdc = GetDC(hwnd);
+ descent = tm.tmAscent + 1;
+ if (descent >= font_height)
+ descent = font_height - 1;
+ firstchar = tm.tmFirstChar;
- if (cfg.vtmode == VT_OEMONLY)
- j = 4;
- else
- j = 0;
+ if( cfg.vtmode == VT_XWINDOWS && firstchar >= ' ' )
+ cfg.vtmode = VT_POORMAN;
- for (i=0; i<(cfg.vtmode == VT_OEMANSI ? 5 : 4); i++) {
- if (fonts[i+j]) {
- SelectObject (hdc, fonts[i+j]);
+ for (i=0; i<8; i++) {
+ if (fonts[i]) {
+ SelectObject (hdc, fonts[i]);
GetTextMetrics(hdc, &tm);
- if (i == 0 || i == 4) {
- font_height = tm.tmHeight;
- font_width = tm.tmAveCharWidth;
- descent = tm.tmAscent + 1;
- if (descent >= font_height)
- descent = font_height - 1;
- }
- widths[i] = tm.tmAveCharWidth;
+ fsize[i] = tm.tmAveCharWidth + 256 * tm.tmHeight;
}
}
ReleaseDC (hwnd, hdc);
- if (widths[FONT_UNDERLINE] != widths[FONT_NORMAL] ||
+ if (fsize[FONT_UNDERLINE] != fsize[FONT_NORMAL] ||
(bold_mode == BOLD_FONT &&
- widths[FONT_BOLDUND] != widths[FONT_BOLD])) {
+ fsize[FONT_BOLDUND] != fsize[FONT_BOLD])) {
und_mode = UND_LINE;
DeleteObject (fonts[FONT_UNDERLINE]);
if (bold_mode == BOLD_FONT)
DeleteObject (fonts[FONT_BOLDUND]);
+
+#if 0
+ MessageBox(NULL, "Disabling underline font",
+ "Font Size Mismatch", MB_ICONINFORMATION | MB_OK);
+#endif
}
if (bold_mode == BOLD_FONT &&
- widths[FONT_BOLD] != widths[FONT_NORMAL]) {
+ fsize[FONT_BOLD] != fsize[FONT_NORMAL]) {
bold_mode = BOLD_SHADOW;
DeleteObject (fonts[FONT_BOLD]);
if (und_mode == UND_FONT)
DeleteObject (fonts[FONT_BOLDUND]);
+
+#if 0
+ MessageBox(NULL, "Disabling bold font",
+ "Font Size Mismatch", MB_ICONINFORMATION | MB_OK);
+#endif
}
- if (cfg.vtmode == VT_OEMANSI && widths[FONT_OEM] != widths[FONT_NORMAL]) {
- MessageBox(NULL, "The OEM and ANSI versions of this font are\n"
+ if (cfg.vtmode == VT_OEMANSI && fsize[FONT_OEM] != fsize[FONT_NORMAL] ) {
+ if( cfg.fontcharset == OEM_CHARSET )
+ {
+ MessageBox(NULL, "The OEM and ANSI versions of this font are\n"
"different sizes. Using OEM-only mode instead",
"Font Size Mismatch", MB_ICONINFORMATION | MB_OK);
- cfg.vtmode = VT_OEMONLY;
- for (i=0; i<4; i++)
+ cfg.vtmode = VT_OEMONLY;
+ }
+ else if( firstchar < ' ' )
+ {
+ MessageBox(NULL, "The OEM and ANSI versions of this font are\n"
+ "different sizes. Using XTerm mode instead",
+ "Font Size Mismatch", MB_ICONINFORMATION | MB_OK);
+ cfg.vtmode = VT_XWINDOWS;
+ }
+ else
+ {
+ MessageBox(NULL, "The OEM and ANSI versions of this font are\n"
+ "different sizes. Using ISO8859-1 mode instead",
+ "Font Size Mismatch", MB_ICONINFORMATION | MB_OK);
+ cfg.vtmode = VT_POORMAN;
+ }
+
+ for (i=0; i<8; i++)
if (fonts[i])
DeleteObject (fonts[i]);
+ goto font_messup;
}
}
lasttime = thistime;
}
-static int WINAPI WndProc (HWND hwnd, UINT message,
- WPARAM wParam, LPARAM lParam) {
+static LRESULT CALLBACK WndProc (HWND hwnd, UINT message,
+ WPARAM wParam, LPARAM lParam) {
HDC hdc;
static int ignore_size = FALSE;
static int ignore_clip = FALSE;
case WM_CREATE:
break;
case WM_CLOSE:
- if (!cfg.warn_on_close ||
+ if (!cfg.warn_on_close || session_closed ||
MessageBox(hwnd, "Are you sure you want to close this session?",
"PuTTY Exit Confirmation",
MB_ICONWARNING | MB_OKCANCEL) == IDOK)
UnmapViewOfFile(p);
}
}
- sprintf(c, "putty &%08x", filemap);
+ sprintf(c, "putty &%p", filemap);
cl = c;
} else if (wParam == IDM_SAVEDSESS) {
char *session = sessions[(lParam - IDM_SAVED_MIN) / 16];
init_fonts();
sfree(logpal);
ldisc = (cfg.ldisc_term ? &ldisc_term : &ldisc_simple);
+ back->special (cfg.ldisc_term ? TS_LECHO : TS_RECHO);
if (pal)
DeleteObject(pal);
logpal = NULL;
if (cfg.close_on_exit)
PostQuitMessage(0);
else {
+ session_closed = TRUE;
MessageBox(hwnd, "Connection closed by remote host",
"PuTTY", MB_OK | MB_ICONINFORMATION);
SetWindowText (hwnd, "PuTTY (inactive)");
ignore_size = TRUE; /* don't panic on next WM_SIZE msg */
break;
case WM_ENTERSIZEMOVE:
- EnableSizeTip(1);
- break;
+ EnableSizeTip(1);
+ break;
case WM_EXITSIZEMOVE:
- EnableSizeTip(0);
- break;
+ EnableSizeTip(0);
+ break;
case WM_SIZING:
{
int width, height, w, h, ew, eh;
height = r->bottom - r->top - extra_height;
w = (width + font_width/2) / font_width; if (w < 1) w = 1;
h = (height + font_height/2) / font_height; if (h < 1) h = 1;
- UpdateSizeTip(hwnd, w, h);
+ UpdateSizeTip(hwnd, w, h);
ew = width - w * font_width;
eh = height - h * font_height;
if (ew != 0) {
else
return 0;
}
- break;
+ /* break; (never reached) */
case WM_SIZE:
if (wParam == SIZE_MINIMIZED) {
SetWindowText (hwnd,
static const char poorman[] =
"*#****\xB0\xB1**+++++-----++++|****\xA3\xB7";
static const char oemmap[] =
- "*\xB1****\xF8\xF1**\xD9\xBF\xDA\xC0\xC5"
- "\xC4\xC4\xC4\xC4\xC4\xC3\xB4\xC1\xC2\xB3****\x9C\xFA";
+ "\x04\xB1****\xF8\xF1**\xD9\xBF\xDA\xC0\xC5"
+ "\xC4\xC4\xC4\xC4\xC4\xC3\xB4\xC1\xC2\xB3\xF3\xF2\xE3*\x9C\xFA";
/*
* Line drawing mapping: map ` thru ~ (0x60 thru 0x7E) to
ret = GetKeyboardState(keystate);
/*
+ * Record that we pressed key so the scroll window can be reset, but
+ * be careful to avoid Shift-UP/Down
+ */
+ if( wParam != VK_SHIFT && wParam != VK_PRIOR && wParam != VK_NEXT ) {
+ seen_key_event = 1;
+ }
+
+ /*
* 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.
}
/*
+ * Shift-Tab should send ESC [ Z.
+ */
+ if (ret && (keystate[VK_SHIFT] & 0x80) && wParam == VK_TAB) {
+ *p++ = 0x1B; /* ESC */
+ *p++ = '[';
+ *p++ = 'Z';
+ return p - output;
+ }
+
+ /*
* 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