static void another_font(int);
static void deinit_fonts(void);
static void set_input_locale(HKL);
-static int do_mouse_wheel_msg(UINT message, WPARAM wParam, LPARAM lParam);
static int is_full_screen(void);
static void make_full_screen(void);
static int caret_x = -1, caret_y = -1;
+static int kbd_codepage;
+
static void *ldisc;
+static Backend *back;
+static void *backhandle;
+
+static struct unicode_data ucsdata;
+static int session_closed;
+
+Config cfg; /* exported to windlg.c */
+
+extern struct sesslist sesslist; /* imported from windlg.c */
#define FONT_NORMAL 0
#define FONT_BOLD 1
char *p;
int got_host = 0;
- default_protocol = DEFAULT_PROTOCOL;
- default_port = DEFAULT_PORT;
+ default_protocol = be_default_protocol;
+ /* Find the appropriate default port. */
+ {
+ int i;
+ default_port = 0; /* illegal */
+ for (i = 0; backends[i].backend != NULL; i++)
+ if (backends[i].protocol == default_protocol) {
+ default_port = backends[i].backend->default_port;
+ break;
+ }
+ }
cfg.logtype = LGTYP_NONE;
do_defaults(NULL, &cfg);
char *p = argv[i];
int ret;
- ret = cmdline_process_param(p, i+1<argc?argv[i+1]:NULL, 1);
+ ret = cmdline_process_param(p, i+1<argc?argv[i+1]:NULL,
+ 1, &cfg);
if (ret == -2) {
cmdline_error("option \"%s\" requires an argument", p);
} else if (ret == 2) {
* argument, so that it will be deferred
* until it's a good moment to run it.
*/
- int ret = cmdline_process_param("-P", p, 1);
+ int ret = cmdline_process_param("-P", p, 1, &cfg);
assert(ret == 2);
} else if (!strncmp(q, "telnet:", 7)) {
/*
cfg.host[sizeof(cfg.host) - 1] = '\0';
got_host = 1;
}
+ } else {
+ cmdline_error("unknown option \"%s\"", p);
}
}
}
- cmdline_run_saved();
+ cmdline_run_saved(&cfg);
if (!*cfg.host && !do_config()) {
WSACleanup();
hwnd = NULL;
- term = term_init();
+ memset(&ucsdata, 0, sizeof(ucsdata));
+
+ term = term_init(&cfg, &ucsdata, NULL);
+ logctx = log_init(NULL, &cfg);
+ term_provide_logctx(term, logctx);
cfgtopalette();
char msg[1024], *title;
char *realhost;
- error = back->init((void *)term, &backhandle,
+ error = back->init((void *)term, &backhandle, &cfg,
cfg.host, cfg.port, &realhost, cfg.tcp_nodelay);
+ back->provide_logctx(backhandle, logctx);
if (error) {
sprintf(msg, "Unable to open connection to\n"
"%.800s\n" "%s", cfg.host, error);
title = msg;
}
sfree(realhost);
- set_title(title);
- set_icon(title);
+ set_title(NULL, title);
+ set_icon(NULL, title);
}
/*
/*
* Set up a line discipline.
*/
- ldisc = ldisc_create(term, back, backhandle, NULL);
+ ldisc = ldisc_create(&cfg, term, back, backhandle, NULL);
session_closed = FALSE;
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++)
+ get_sesslist(&sesslist, TRUE);
+ for (i = 1;
+ i < ((sesslist.nsessions < 256) ? sesslist.nsessions : 256);
+ i++)
AppendMenu(s, MF_ENABLED, IDM_SAVED_MIN + (16 * i),
- sessions[i]);
+ sesslist.sessions[i]);
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);
/*
* Open the initial log file if there is one.
*/
- logfopen();
+ logfopen(logctx);
/*
* Finally show the window!
/*
* set or clear the "raw mouse message" mode
*/
-void set_raw_mouse_mode(int activate)
+void set_raw_mouse_mode(void *frontend, int activate)
{
activate = activate && !cfg.no_mouse_rep;
send_raw_mouse = activate;
/*
* Print a message box and close the connection.
*/
-void connection_fatal(char *fmt, ...)
+void connection_fatal(void *frontend, char *fmt, ...)
{
va_list ap;
char stuff[200];
PostQuitMessage(1);
else {
session_closed = TRUE;
- SetWindowText(hwnd, "PuTTY (inactive)");
+ set_icon(NULL, "PuTTY (inactive)");
+ set_title(NULL, "PuTTY (inactive)");
}
}
cfg.close_on_exit == COE_NORMAL) PostQuitMessage(0);
else {
session_closed = TRUE;
- SetWindowText(hwnd, "PuTTY (inactive)");
+ set_icon(NULL, "PuTTY (inactive)");
+ set_title(NULL, "PuTTY (inactive)");
MessageBox(hwnd, "Connection closed by remote host",
"PuTTY", MB_OK | MB_ICONINFORMATION);
}
/* !!! Yes the next line is right */
if (cset == OEM_CHARSET)
- font_codepage = GetOEMCP();
+ ucsdata.font_codepage = GetOEMCP();
else
- if (TranslateCharsetInfo
- ((DWORD *) cset, &info, TCI_SRCCHARSET)) font_codepage =
- info.ciACP;
+ if (TranslateCharsetInfo ((DWORD *) cset, &info, TCI_SRCCHARSET))
+ ucsdata.font_codepage = info.ciACP;
else
- font_codepage = -1;
+ ucsdata.font_codepage = -1;
- GetCPInfo(font_codepage, &cpinfo);
- dbcs_screenfont = (cpinfo.MaxCharSize > 1);
+ GetCPInfo(ucsdata.font_codepage, &cpinfo);
+ ucsdata.dbcs_screenfont = (cpinfo.MaxCharSize > 1);
}
f(FONT_UNDERLINE, cfg.fontcharset, fw_dontcare, TRUE);
}
fontflag[0] = fontflag[1] = fontflag[2] = 1;
- init_ucs_tables();
+ init_ucs(&cfg, &ucsdata);
}
static void another_font(int fontno)
}
}
-void request_resize(int w, int h)
+void request_resize(void *frontend, int w, int h)
{
int width, height;
* Translate a raw mouse button designation (LEFT, MIDDLE, RIGHT)
* into a cooked one (SELECT, EXTEND, PASTE).
*/
-Mouse_Button translate_button(Mouse_Button button)
+Mouse_Button translate_button(void *frontend, Mouse_Button button)
{
if (button == MBT_LEFT)
return MBT_SELECT;
sprintf(c, "putty &%p", filemap);
cl = c;
} else if (wParam == IDM_SAVEDSESS) {
- if ((lParam - IDM_SAVED_MIN) / 16 < nsessions) {
+ if ((lParam - IDM_SAVED_MIN) / 16 < sesslist.nsessions) {
char *session =
- sessions[(lParam - IDM_SAVED_MIN) / 16];
+ sesslist.sessions[(lParam - IDM_SAVED_MIN) / 16];
cl = smalloc(16 + strlen(session));
/* 8, but play safe */
if (!cl)
}
}
- if (strcmp(prev_cfg.logfilename, cfg.logfilename) ||
- prev_cfg.logtype != cfg.logtype) {
- logfclose(); /* reset logging */
- logfopen();
- }
+ /* Pass new config data to the logging module */
+ log_reconfig(logctx, &cfg);
sfree(logpal);
/*
cfgtopalette();
init_palette();
- /* Give terminal a heads-up on miscellaneous stuff */
- term_reconfig(term);
+ /* Pass new config data to the terminal */
+ term_reconfig(term, &cfg);
+
+ /* Pass new config data to the back end */
+ back->reconfig(backhandle, &cfg);
/* Screen size changed ? */
if (cfg.height != prev_cfg.height ||
init_lvl = 2;
}
- set_title(cfg.wintitle);
+ set_title(NULL, cfg.wintitle);
if (IsIconic(hwnd)) {
SetWindowText(hwnd,
cfg.win_name_always ? window_name :
(p.rcPaint.left-offset_width)/font_width,
(p.rcPaint.top-offset_height)/font_height,
(p.rcPaint.right-offset_width-1)/font_width,
- (p.rcPaint.bottom-offset_height-1)/font_height);
+ (p.rcPaint.bottom-offset_height-1)/font_height,
+ is_alt_pressed());
if (p.fErase ||
p.rcPaint.left < offset_width ||
* 1) Keep the sizetip uptodate
* 2) Make sure the window size is _stepped_ in units of the font size.
*/
- if (cfg.resize_action != RESIZE_FONT && !alt_pressed) {
+ if (cfg.resize_action != RESIZE_FONT && !is_alt_pressed()) {
int width, height, w, h, ew, eh;
LPRECT r = (LPRECT) lParam;
* down the connection during an NT opaque drag.)
*/
if (resizing) {
- if (cfg.resize_action != RESIZE_FONT && !alt_pressed) {
+ if (cfg.resize_action != RESIZE_FONT && !is_alt_pressed()) {
need_backend_resize = TRUE;
w = (width-cfg.window_border*2) / font_width;
if (w < 1) w = 1;
break;
case WM_PALETTECHANGED:
if ((HWND) wParam != hwnd && pal != NULL) {
- HDC hdc = get_ctx();
+ HDC hdc = get_ctx(NULL);
if (hdc) {
if (RealizePalette(hdc) > 0)
UpdateColors(hdc);
break;
case WM_QUERYNEWPALETTE:
if (pal != NULL) {
- HDC hdc = get_ctx();
+ HDC hdc = get_ctx(NULL);
if (hdc) {
if (RealizePalette(hdc) > 0)
UpdateColors(hdc);
}
default:
if (message == wm_mousewheel || message == WM_MOUSEWHEEL) {
- int shift_pressed=0, control_pressed=0, alt_pressed=0;
+ int shift_pressed=0, control_pressed=0;
if (message == WM_MOUSEWHEEL) {
wheel_accumulator += (short)HIWORD(wParam);
* helper software tracks the system caret, so we should arrange to
* have one.)
*/
-void sys_cursor(int x, int y)
+void sys_cursor(void *frontend, int x, int y)
{
int cx, cy;
if (lattr == LATTR_TOP || lattr == LATTR_BOT)
text_adjust *= 2;
attr &= ~CSET_MASK;
- text[0] = (char) (unitab_xterm['q'] & CHAR_MASK);
- attr |= (unitab_xterm['q'] & CSET_MASK);
+ text[0] = (char) (ucsdata.unitab_xterm['q'] & CHAR_MASK);
+ attr |= (ucsdata.unitab_xterm['q'] & CSET_MASK);
if (attr & ATTR_UNDER) {
attr &= ~ATTR_UNDER;
force_manual_underline = 1;
line_box.right = font_width*term->cols+offset_width;
/* We're using a private area for direct to font. (512 chars.) */
- if (dbcs_screenfont && (attr & CSET_MASK) == ATTR_ACP) {
+ if (ucsdata.dbcs_screenfont && (attr & CSET_MASK) == ATTR_ACP) {
/* Ho Hum, dbcs fonts are a PITA! */
/* To display on W9x I have to convert to UCS */
static wchar_t *uni_buf = 0;
for(nlen = mptr = 0; mptr<len; mptr++) {
uni_buf[nlen] = 0xFFFD;
- if (IsDBCSLeadByteEx(font_codepage, (BYTE) text[mptr])) {
+ if (IsDBCSLeadByteEx(ucsdata.font_codepage, (BYTE) text[mptr])) {
IpDx[nlen] += char_width;
- MultiByteToWideChar(font_codepage, MB_USEGLYPHCHARS,
+ MultiByteToWideChar(ucsdata.font_codepage, MB_USEGLYPHCHARS,
text+mptr, 2, uni_buf+nlen, 1);
mptr++;
}
else
{
- MultiByteToWideChar(font_codepage, MB_USEGLYPHCHARS,
+ MultiByteToWideChar(ucsdata.font_codepage, MB_USEGLYPHCHARS,
text+mptr, 1, uni_buf+nlen, 1);
}
nlen++;
/* This function gets the actual width of a character in the normal font.
*/
-int CharWidth(Context ctx, int uc) {
+int char_width(Context ctx, int uc) {
HDC hdc = ctx;
int ibuf = 0;
switch (uc & CSET_MASK) {
case ATTR_ASCII:
- uc = unitab_line[uc & 0xFF];
+ uc = ucsdata.unitab_line[uc & 0xFF];
break;
case ATTR_LINEDRW:
- uc = unitab_xterm[uc & 0xFF];
+ uc = ucsdata.unitab_xterm[uc & 0xFF];
break;
case ATTR_SCOACS:
- uc = unitab_scoacs[uc & 0xFF];
+ uc = ucsdata.unitab_scoacs[uc & 0xFF];
break;
}
if (DIRECT_FONT(uc)) {
- if (dbcs_screenfont) return 1;
+ if (ucsdata.dbcs_screenfont) return 1;
/* Speedup, I know of no font where ascii is the wrong width */
if ((uc&CHAR_MASK) >= ' ' && (uc&CHAR_MASK)<= '~')
}
}
- alt_pressed = (left_alt && key_down);
-
scan = (HIWORD(lParam) & (KF_UP | KF_EXTENDED | 0xFF));
shift_state = ((keystate[VK_SHIFT] & 0x80) != 0)
+ ((keystate[VK_CONTROL] & 0x80) != 0) * 2;
SendMessage(hwnd, WM_VSCROLL, SB_PAGEUP, 0);
return 0;
}
+ if (wParam == VK_PRIOR && shift_state == 2) {
+ SendMessage(hwnd, WM_VSCROLL, SB_LINEUP, 0);
+ return 0;
+ }
if (wParam == VK_NEXT && shift_state == 1) {
SendMessage(hwnd, WM_VSCROLL, SB_PAGEDOWN, 0);
return 0;
}
+ if (wParam == VK_NEXT && shift_state == 2) {
+ SendMessage(hwnd, WM_VSCROLL, SB_LINEDOWN, 0);
+ return 0;
+ }
if (wParam == VK_INSERT && shift_state == 1) {
term_do_paste(term);
return 0;
*p++ = "\000\033\034\035\036\037\177"[wParam - '2'];
return p - output;
}
- if (shift_state == 2 && wParam == 0xBD) {
+ if (shift_state == 2 && (wParam == 0xBD || wParam == 0xBF)) {
*p++ = 0x1F;
return p - output;
}
#ifdef SHOW_TOASCII_RESULT
if (r == 1 && !key_down) {
if (alt_sum) {
- if (in_utf(term) || dbcs_screenfont)
+ if (in_utf(term) || ucsdata.dbcs_screenfont)
debug((", (U+%04x)", alt_sum));
else
debug((", LCH(%d)", alt_sum));
if (!key_down) {
if (alt_sum) {
- if (in_utf(term) || dbcs_screenfont) {
+ if (in_utf(term) || ucsdata.dbcs_screenfont) {
keybuf = alt_sum;
term_seen_key_event(term);
luni_send(ldisc, &keybuf, 1, 1);
if (!left_alt)
keys[0] = 0;
/* If we will be using alt_sum fix the 256s */
- else if (keys[0] && (in_utf(term) || dbcs_screenfont))
+ else if (keys[0] && (in_utf(term) || ucsdata.dbcs_screenfont))
keys[0] = 10;
}
return -1;
}
-void request_paste(void)
+void request_paste(void *frontend)
{
/*
* In Windows, pasting is synchronous: we can read the
term_do_paste(term);
}
-void set_title(char *title)
+void set_title(void *frontend, char *title)
{
sfree(window_name);
window_name = smalloc(1 + strlen(title));
SetWindowText(hwnd, title);
}
-void set_icon(char *title)
+void set_icon(void *frontend, char *title)
{
sfree(icon_name);
icon_name = smalloc(1 + strlen(title));
SetWindowText(hwnd, title);
}
-void set_sbar(int total, int start, int page)
+void set_sbar(void *frontend, int total, int start, int page)
{
SCROLLINFO si;
SetScrollInfo(hwnd, SB_VERT, &si, TRUE);
}
-Context get_ctx(void)
+Context get_ctx(void *frontend)
{
HDC hdc;
if (hwnd) {
colours[n] = RGB(r, g, b);
}
-void palette_set(int n, int r, int g, int b)
+void palette_set(void *frontend, int n, int r, int g, int b)
{
static const int first[21] = {
0, 2, 4, 6, 8, 10, 12, 14,
if (first[n] >= 18)
real_palette_set(first[n] + 1, r, g, b);
if (pal) {
- HDC hdc = get_ctx();
+ HDC hdc = get_ctx(frontend);
UnrealizeObject(pal);
RealizePalette(hdc);
free_ctx(hdc);
}
}
-void palette_reset(void)
+void palette_reset(void *frontend)
{
int i;
if (pal) {
HDC hdc;
SetPaletteEntries(pal, 0, NCOLOURS, logpal->palPalEntry);
- hdc = get_ctx();
+ hdc = get_ctx(frontend);
RealizePalette(hdc);
free_ctx(hdc);
}
}
-void write_aclip(char *data, int len, int must_deselect)
+void write_aclip(void *frontend, char *data, int len, int must_deselect)
{
HGLOBAL clipdata;
void *lock;
/*
* Note: unlike write_aclip() this will not append a nul.
*/
-void write_clip(wchar_t * data, int len, int must_deselect)
+void write_clip(void *frontend, wchar_t * data, int len, int must_deselect)
{
HGLOBAL clipdata, clipdata2, clipdata3;
int len2;
SendMessage(hwnd, WM_IGNORE_CLIP, FALSE, 0);
}
-void get_clip(wchar_t ** p, int *len)
+void get_clip(void *frontend, wchar_t ** p, int *len)
{
static HGLOBAL clipdata = NULL;
static wchar_t *converted = 0;
* Move `lines' lines from position `from' to position `to' in the
* window.
*/
-void optimised_move(int to, int from, int lines)
+void optimised_move(void *frontend, int to, int from, int lines)
{
RECT r;
int min, max;
/*
* Beep.
*/
-void beep(int mode)
+void beep(void *frontend, int mode)
{
if (mode == BELL_DEFAULT) {
/*
* Minimise or restore the window in response to a server-side
* request.
*/
-void set_iconic(int iconic)
+void set_iconic(void *frontend, int iconic)
{
if (IsIconic(hwnd)) {
if (!iconic)
/*
* Move the window in response to a server-side request.
*/
-void move_window(int x, int y)
+void move_window(void *frontend, int x, int y)
{
if (cfg.resize_action == RESIZE_DISABLED ||
cfg.resize_action == RESIZE_FONT ||
* Move the window to the top or bottom of the z-order in response
* to a server-side request.
*/
-void set_zorder(int top)
+void set_zorder(void *frontend, int top)
{
if (cfg.alwaysontop)
return; /* ignore */
/*
* Refresh the window in response to a server-side request.
*/
-void refresh_window(void)
+void refresh_window(void *frontend)
{
InvalidateRect(hwnd, NULL, TRUE);
}
* Maximise or restore the window in response to a server-side
* request.
*/
-void set_zoomed(int zoomed)
+void set_zoomed(void *frontend, int zoomed)
{
if (IsZoomed(hwnd)) {
if (!zoomed)
/*
* Report whether the window is iconic, for terminal reports.
*/
-int is_iconic(void)
+int is_iconic(void *frontend)
{
return IsIconic(hwnd);
}
/*
* Report the window's position, for terminal reports.
*/
-void get_window_pos(int *x, int *y)
+void get_window_pos(void *frontend, int *x, int *y)
{
RECT r;
GetWindowRect(hwnd, &r);
/*
* Report the window's pixel size, for terminal reports.
*/
-void get_window_pixels(int *x, int *y)
+void get_window_pixels(void *frontend, int *x, int *y)
{
RECT r;
GetWindowRect(hwnd, &r);
/*
* Return the window or icon title.
*/
-char *get_window_title(int icon)
+char *get_window_title(void *frontend, int icon)
{
return icon ? icon_name : window_name;
}