/* Maximum number of sessions on saved-session submenu */
#define MENU_SAVED_MAX ((IDM_SAVED_MAX-IDM_SAVED_MIN) / MENU_SAVED_STEP)
-#define WM_IGNORE_CLIP (WM_XUSER + 2)
-#define WM_FULLSCR_ON_MAX (WM_XUSER + 3)
-#define WM_AGENT_CALLBACK (WM_XUSER + 4)
+#define WM_IGNORE_CLIP (WM_APP + 2)
+#define WM_FULLSCR_ON_MAX (WM_APP + 3)
+#define WM_AGENT_CALLBACK (WM_APP + 4)
/* Needed for Chinese support and apparently not always defined. */
#ifndef VK_PROCESSKEY
static void another_font(int);
static void deinit_fonts(void);
static void set_input_locale(HKL);
+static void update_savedsess_menu(void);
static int is_full_screen(void);
static void make_full_screen(void);
static struct unicode_data ucsdata;
static int session_closed;
-static int reconfiguring;
+static int reconfiguring = FALSE;
static const struct telnet_special *specials;
static int n_specials;
int specials_submenu_pos;
} popup_menus[2];
enum { SYSMENU, CTXMENU };
+static HMENU savedsess_menu;
Config cfg; /* exported to windlg.c */
-extern struct sesslist sesslist; /* imported from windlg.c */
+static struct sesslist sesslist; /* for saved-session menu */
struct agent_callback {
void (*callback)(void *, void *, int);
{
}
+char *get_ttymode(void *frontend, const char *mode)
+{
+ return term_get_ttymode(term, mode);
+}
+
static void start_backend(void)
{
const char *error;
sfree(s1);
sfree(s2);
exit(0);
+ } else if (!strcmp(p, "-pgpfp")) {
+ pgp_fingerprints();
+ exit(1);
} else if (*p != '-') {
char *q = p;
if (got_host) {
* Set up the session-control options on the system menu.
*/
{
- HMENU s, m;
- int i, j;
+ HMENU m;
+ int j;
char *str;
popup_menus[SYSMENU].menu = GetSystemMenu(hwnd, FALSE);
popup_menus[CTXMENU].menu = CreatePopupMenu();
AppendMenu(popup_menus[CTXMENU].menu, MF_ENABLED, IDM_PASTE, "&Paste");
- s = CreateMenu();
+ savedsess_menu = CreateMenu();
get_sesslist(&sesslist, TRUE);
- /* skip sesslist.sessions[0] == Default Settings */
- for (i = 1;
- i < ((sesslist.nsessions <= MENU_SAVED_MAX+1) ? sesslist.nsessions
- : MENU_SAVED_MAX+1);
- i++)
- AppendMenu(s, MF_ENABLED, IDM_SAVED_MIN + (i-1)*MENU_SAVED_STEP,
- sesslist.sessions[i]);
+ update_savedsess_menu();
for (j = 0; j < lenof(popup_menus); j++) {
m = popup_menus[j].menu;
AppendMenu(m, MF_SEPARATOR, 0, 0);
AppendMenu(m, MF_ENABLED, IDM_NEWSESS, "Ne&w Session...");
AppendMenu(m, MF_ENABLED, IDM_DUPSESS, "&Duplicate Session");
- AppendMenu(m, MF_POPUP | MF_ENABLED, (UINT) s, "Sa&ved Sessions");
+ AppendMenu(m, MF_POPUP | MF_ENABLED, (UINT) savedsess_menu,
+ "Sa&ved Sessions");
AppendMenu(m, MF_ENABLED, IDM_RECONF, "Chan&ge Settings...");
AppendMenu(m, MF_SEPARATOR, 0, 0);
AppendMenu(m, MF_ENABLED, IDM_COPYALL, "C&opy All to Clipboard");
set_input_locale(GetKeyboardLayout(0));
/*
- * Open the initial log file if there is one.
- */
- logfopen(logctx);
-
- /*
* Finally show the window!
*/
ShowWindow(hwnd, show);
}
/*
+ * Refresh the saved-session submenu from `sesslist'.
+ */
+static void update_savedsess_menu(void)
+{
+ int i;
+ while (DeleteMenu(savedsess_menu, 0, MF_BYPOSITION)) ;
+ /* skip sesslist.sessions[0] == Default Settings */
+ for (i = 1;
+ i < ((sesslist.nsessions <= MENU_SAVED_MAX+1) ? sesslist.nsessions
+ : MENU_SAVED_MAX+1);
+ i++)
+ AppendMenu(savedsess_menu, MF_ENABLED,
+ IDM_SAVED_MIN + (i-1)*MENU_SAVED_STEP,
+ sesslist.sessions[i]);
+}
+
+/*
* Update the Special Commands submenu.
*/
void update_specials_menu(void *frontend)
for (i = 0; i < NEXTCOLOURS; i++) {
if (i < 216) {
int r = i / 36, g = (i / 6) % 6, b = i % 6;
- defpal[i+16].rgbtRed = r * 0x33;
- defpal[i+16].rgbtGreen = g * 0x33;
- defpal[i+16].rgbtBlue = b * 0x33;
+ defpal[i+16].rgbtRed = r ? r * 40 + 55 : 0;
+ defpal[i+16].rgbtGreen = g ? g * 40 + 55 : 0;
+ defpal[i+16].rgbtBlue = b ? b * 40 + 55 : 0;
} else {
int shade = i - 216;
- shade = (shade + 1) * 0xFF / (NEXTCOLOURS - 216 + 1);
+ shade = shade * 10 + 8;
defpal[i+16].rgbtRed = defpal[i+16].rgbtGreen =
defpal[i+16].rgbtBlue = shade;
}
unsigned short *lpString, UINT cbCount,
CONST INT *lpDx, int opaque)
{
-
+#ifdef __LCC__
+ /*
+ * The LCC include files apparently don't supply the
+ * GCP_RESULTSW type, but we can make do with GCP_RESULTS
+ * proper: the differences aren't important to us (the only
+ * variable-width string parameter is one we don't use anyway).
+ */
+ GCP_RESULTS gcpr;
+#else
GCP_RESULTSW gcpr;
+#endif
char *buffer = snewn(cbCount*2+2, char);
char *classbuffer = snewn(cbCount, char);
memset(&gcpr, 0, sizeof(gcpr));
#define f(i,c,w,u) \
fonts[i] = CreateFont (font_height, font_width, 0, 0, w, FALSE, u, FALSE, \
c, OUT_DEFAULT_PRECIS, \
- CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, \
+ CLIP_DEFAULT_PRECIS, FONT_QUALITY(cfg.font_quality), \
FIXED_PITCH | FF_DONTCARE, cfg.font.name)
f(FONT_NORMAL, cfg.font.charset, fw_dontcare, FALSE);
- lfont.lfHeight = font_height;
- lfont.lfWidth = font_width;
- lfont.lfEscapement = 0;
- lfont.lfOrientation = 0;
- lfont.lfWeight = fw_dontcare;
- lfont.lfItalic = FALSE;
- lfont.lfUnderline = FALSE;
- lfont.lfStrikeOut = FALSE;
- lfont.lfCharSet = cfg.font.charset;
- lfont.lfOutPrecision = OUT_DEFAULT_PRECIS;
- lfont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
- lfont.lfQuality = DEFAULT_QUALITY;
- lfont.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
- strncpy(lfont.lfFaceName, cfg.font.name, LF_FACESIZE);
-
SelectObject(hdc, fonts[FONT_NORMAL]);
GetTextMetrics(hdc, &tm);
+ GetObject(fonts[FONT_NORMAL], sizeof(LOGFONT), &lfont);
+
if (pick_width == 0 || pick_height == 0) {
font_height = tm.tmHeight;
font_width = tm.tmAveCharWidth;
fonts[fontno] =
CreateFont(font_height * (1 + !!(fontno & FONT_HIGH)), x, 0, 0, w,
FALSE, u, FALSE, c, OUT_DEFAULT_PRECIS,
- CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
+ CLIP_DEFAULT_PRECIS, FONT_QUALITY(cfg.font_quality),
FIXED_PITCH | FF_DONTCARE, s);
fontflag[fontno] = 1;
show_mouseptr(1);
PostQuitMessage(0);
return 0;
+ case WM_INITMENUPOPUP:
+ if ((HMENU)wParam == savedsess_menu) {
+ /* About to pop up Saved Sessions sub-menu.
+ * Refresh the session list. */
+ get_sesslist(&sesslist, FALSE); /* free */
+ get_sesslist(&sesslist, TRUE);
+ update_savedsess_menu();
+ return 0;
+ }
+ break;
case WM_COMMAND:
case WM_SYSCOMMAND:
switch (wParam & ~0xF) { /* low 4 bits reserved to Windows */
{
Config prev_cfg;
int init_lvl = 1;
+ int reconfig_result;
if (reconfiguring)
- break;
+ break;
else
- reconfiguring = TRUE;
+ reconfiguring = TRUE;
GetWindowText(hwnd, cfg.wintitle, sizeof(cfg.wintitle));
prev_cfg = cfg;
- if (!do_reconfig(hwnd, back ? back->cfg_info(backhandle) : 0))
+ reconfig_result =
+ do_reconfig(hwnd, back ? back->cfg_info(backhandle) : 0);
+ reconfiguring = FALSE;
+ if (!reconfig_result)
break;
{
/* Enable or disable the scroll bar, etc */
{
- LONG nflg, flag = GetWindowLong(hwnd, GWL_STYLE);
+ LONG nflg, flag = GetWindowLongPtr(hwnd, GWL_STYLE);
LONG nexflag, exflag =
- GetWindowLong(hwnd, GWL_EXSTYLE);
+ GetWindowLongPtr(hwnd, GWL_EXSTYLE);
nexflag = exflag;
if (cfg.alwaysontop != prev_cfg.alwaysontop) {
if (nflg != flag || nexflag != exflag) {
if (nflg != flag)
- SetWindowLong(hwnd, GWL_STYLE, nflg);
+ SetWindowLongPtr(hwnd, GWL_STYLE, nflg);
if (nexflag != exflag)
- SetWindowLong(hwnd, GWL_EXSTYLE, nexflag);
+ SetWindowLongPtr(hwnd, GWL_EXSTYLE, nexflag);
SetWindowPos(hwnd, NULL, 0, 0, 0, 0,
SWP_NOACTIVATE | SWP_NOCOPYBITS |
cfg.font.isbold != prev_cfg.font.isbold ||
cfg.font.height != prev_cfg.font.height ||
cfg.font.charset != prev_cfg.font.charset ||
+ cfg.font_quality != prev_cfg.font_quality ||
cfg.vtmode != prev_cfg.vtmode ||
cfg.bold_colour != prev_cfg.bold_colour ||
cfg.resize_action == RESIZE_DISABLED ||
InvalidateRect(hwnd, NULL, TRUE);
reset_window(init_lvl);
net_pending_errors();
- reconfiguring = FALSE;
}
break;
case IDM_COPYALL:
RealizePalette(hdc);
}
+ /*
+ * We have to be careful about term_paint(). It will
+ * set a bunch of character cells to INVALID and then
+ * call do_paint(), which will redraw those cells and
+ * _then mark them as done_. This may not be accurate:
+ * when painting in WM_PAINT context we are restricted
+ * to the rectangle which has just been exposed - so if
+ * that only covers _part_ of a character cell and the
+ * rest of it was already visible, that remainder will
+ * not be redrawn at all. Accordingly, we must not
+ * paint any character cell in a WM_PAINT context which
+ * already has a pending update due to terminal output.
+ * The simplest solution to this - and many, many
+ * thanks to Hung-Te Lin for working all this out - is
+ * not to do any actual painting at _all_ if there's a
+ * pending terminal update: just mark the relevant
+ * character cells as INVALID and wait for the
+ * scheduled full update to sort it out.
+ *
+ * I have a suspicion this isn't the _right_ solution.
+ * An alternative approach would be to have terminal.c
+ * separately track what _should_ be on the terminal
+ * screen and what _is_ on the terminal screen, and
+ * have two completely different types of redraw (one
+ * for full updates, which syncs the former with the
+ * terminal itself, and one for WM_PAINT which syncs
+ * the latter with the former); yet another possibility
+ * would be to have the Windows front end do what the
+ * GTK one already does, and maintain a bitmap of the
+ * current terminal appearance so that WM_PAINT becomes
+ * completely trivial. However, this should do for now.
+ */
term_paint(term, hdc,
(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,
- TRUE);
+ !term->window_update_pending);
if (p.fErase ||
p.rcPaint.left < offset_width ||
unsigned char buf[20];
int len;
- if (wParam == VK_PROCESSKEY) {
- MSG m;
- m.hwnd = hwnd;
- m.message = WM_KEYDOWN;
- m.wParam = wParam;
- m.lParam = lParam & 0xdfff;
- TranslateMessage(&m);
+ if (wParam == VK_PROCESSKEY) { /* IME PROCESS key */
+ if (message == WM_KEYDOWN) {
+ MSG m;
+ m.hwnd = hwnd;
+ m.message = WM_KEYDOWN;
+ m.wParam = wParam;
+ m.lParam = lParam & 0xdfff;
+ TranslateMessage(&m);
+ } else break; /* pass to Windows for default processing */
} else {
len = TranslateKey(message, wParam, lParam, buf);
if (len == -1)
set_input_locale((HKL)lParam);
sys_cursor_update();
break;
- case WM_IME_NOTIFY:
- if(wParam == IMN_SETOPENSTATUS) {
+ case WM_IME_STARTCOMPOSITION:
+ {
HIMC hImc = ImmGetContext(hwnd);
ImmSetCompositionFont(hImc, &lfont);
ImmReleaseContext(hwnd, hImc);
- return 0;
}
break;
case WM_IME_COMPOSITION:
}
}
+ /*
+ * Any messages we don't process completely above are passed through to
+ * DefWindowProc() for default processing.
+ */
return DefWindowProc(hwnd, message, wParam, lParam);
}
rtfsize = 100 + strlen(cfg.font.name);
rtf = snewn(rtfsize, char);
- sprintf(rtf, "{\\rtf1\\ansi%d{\\fonttbl\\f0\\fmodern %s;}\\f0",
+ sprintf(rtf, "{\\rtf1\\ansi%d{\\fonttbl\\f0\\fmodern %s;}\\f0 ",
GetACP(), cfg.font.name);
rtflen = strlen(rtf);
/*
* Beep.
*/
-void beep(void *frontend, int mode)
+void do_beep(void *frontend, int mode)
{
if (mode == BELL_DEFAULT) {
/*
{
if (!IsZoomed(hwnd))
return FALSE;
- if (GetWindowLong(hwnd, GWL_STYLE) & WS_CAPTION)
+ if (GetWindowLongPtr(hwnd, GWL_STYLE) & WS_CAPTION)
return FALSE;
return TRUE;
}
return;
/* Remove the window furniture. */
- style = GetWindowLong(hwnd, GWL_STYLE);
+ style = GetWindowLongPtr(hwnd, GWL_STYLE);
style &= ~(WS_CAPTION | WS_BORDER | WS_THICKFRAME);
if (cfg.scrollbar_in_fullscreen)
style |= WS_VSCROLL;
else
style &= ~WS_VSCROLL;
- SetWindowLong(hwnd, GWL_STYLE, style);
+ SetWindowLongPtr(hwnd, GWL_STYLE, style);
/* Resize ourselves to exactly cover the nearest monitor. */
get_fullscreen_rect(&ss);
DWORD oldstyle, style;
/* Reinstate the window furniture. */
- style = oldstyle = GetWindowLong(hwnd, GWL_STYLE);
+ style = oldstyle = GetWindowLongPtr(hwnd, GWL_STYLE);
style |= WS_CAPTION | WS_BORDER;
if (cfg.resize_action == RESIZE_DISABLED)
style &= ~WS_THICKFRAME;
else
style &= ~WS_VSCROLL;
if (style != oldstyle) {
- SetWindowLong(hwnd, GWL_STYLE, style);
+ SetWindowLongPtr(hwnd, GWL_STYLE, style);
SetWindowPos(hwnd, NULL, 0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER |
SWP_FRAMECHANGED);
return term_data(term, is_stderr, data, len);
}
+int from_backend_untrusted(void *frontend, const char *data, int len)
+{
+ return term_data_untrusted(term, data, len);
+}
+
+int get_userpass_input(prompts_t *p, unsigned char *in, int inlen)
+{
+ int ret;
+ ret = cmdline_get_passwd_input(p, in, inlen);
+ if (ret == -1)
+ ret = term_get_userpass_input(term, p, in, inlen);
+ return ret;
+}
+
void agent_schedule_callback(void (*callback)(void *, void *, int),
void *callback_ctx, void *data, int len)
{