+ case 0:
+ /* Make sure the values are sane */
+ width = (ss.right - ss.left - extra_width) / 4;
+ height = (ss.bottom - ss.top - extra_height) / 6;
+
+ if (w > width || h > height)
+ return;
+ if (w < 15)
+ w = 15;
+ if (h < 1)
+ h = 1;
+ }
+ }
+
+ term_size(h, w, cfg.savelines);
+
+ if (cfg.lockfont) {
+ width = extra_width + font_width * w;
+ height = extra_height + font_height * h;
+
+ SetWindowPos(hwnd, NULL, 0, 0, width, height,
+ SWP_NOACTIVATE | SWP_NOCOPYBITS |
+ SWP_NOMOVE | SWP_NOZORDER);
+ } else
+ reset_window(0);
+
+ InvalidateRect(hwnd, NULL, TRUE);
+}
+
+static void reset_window(int reinit) {
+ /*
+ * This function decides how to resize or redraw when the
+ * user changes something.
+ *
+ * This function doesn't like to change the terminal size but if the
+ * font size is locked that may be it's only soluion.
+ */
+ int win_width, win_height;
+ RECT cr, wr;
+
+#ifdef RDB_DEBUG_PATCH
+ debug((27, "reset_window()"));
+#endif
+
+ /* Current window sizes ... */
+ GetWindowRect(hwnd, &wr);
+ GetClientRect(hwnd, &cr);
+
+ win_width = cr.right - cr.left;
+ win_height = cr.bottom - cr.top;
+
+ /* Are we being forced to reload the fonts ? */
+ if (reinit>1) {
+#ifdef RDB_DEBUG_PATCH
+ debug((27, "reset_window() -- Forced deinit"));
+#endif
+ deinit_fonts();
+ init_fonts(0,0);
+ }
+
+ /* Oh, looks like we're minimised */
+ if (win_width == 0 || win_height == 0)
+ return;
+
+ /* Is the window out of position ? */
+ if ( !reinit &&
+ (offset_width != (win_width-font_width*cols)/2 ||
+ offset_height != (win_height-font_height*rows)/2) ){
+ offset_width = (win_width-font_width*cols)/2;
+ offset_height = (win_height-font_height*rows)/2;
+ InvalidateRect(hwnd, NULL, TRUE);
+#ifdef RDB_DEBUG_PATCH
+ debug((27, "reset_window() -> Reposition terminal"));
+#endif
+ }
+
+ if (IsZoomed(hwnd)) {
+ /* We're fullscreen, this means we must not change the size of
+ * the window so it's the font size or the terminal itself.
+ */
+
+ extra_width = wr.right - wr.left - cr.right + cr.left;
+ extra_height = wr.bottom - wr.top - cr.bottom + cr.top;
+
+ if (!cfg.lockfont) {
+ if ( font_width != win_width/cols ||
+ font_height != win_height/rows) {
+ deinit_fonts();
+ init_fonts(win_width/cols, win_height/rows);
+ offset_width = (win_width-font_width*cols)/2;
+ offset_height = (win_height-font_height*rows)/2;
+ InvalidateRect(hwnd, NULL, TRUE);
+#ifdef RDB_DEBUG_PATCH
+ debug((25, "reset_window() -> Z font resize to (%d, %d)",
+ font_width, font_height));
+#endif
+ }
+ } else {
+ if ( font_width != win_width/cols ||
+ font_height != win_height/rows) {
+ /* Our only choice at this point is to change the
+ * size of the terminal; Oh well.
+ */
+ term_size( win_height/font_height, win_width/font_width,
+ cfg.savelines);
+ offset_width = (win_width-font_width*cols)/2;
+ offset_height = (win_height-font_height*rows)/2;
+ InvalidateRect(hwnd, NULL, TRUE);
+#ifdef RDB_DEBUG_PATCH
+ debug((27, "reset_window() -> Zoomed term_size"));
+#endif
+ }
+ }
+ return;
+ }
+
+ /* Hmm, a force re-init means we should ignore the current window
+ * so we resize to the default font size.
+ */
+ if (reinit>0) {
+#ifdef RDB_DEBUG_PATCH
+ debug((27, "reset_window() -> Forced re-init"));
+#endif
+
+ offset_width = offset_height = cfg.window_border;
+ extra_width = wr.right - wr.left - cr.right + cr.left + offset_width*2;
+ extra_height = wr.bottom - wr.top - cr.bottom + cr.top +offset_height*2;
+
+ if (win_width != font_width*cols + offset_width*2 ||
+ win_height != font_height*rows + offset_height*2) {
+
+ /* If this is too large windows will resize it to the maximum
+ * allowed window size, we will then be back in here and resize
+ * the font or terminal to fit.
+ */
+ SetWindowPos(hwnd, NULL, 0, 0,
+ font_width*cols + extra_width,
+ font_height*rows + extra_height,
+ SWP_NOMOVE | SWP_NOZORDER);
+ }
+ return;
+ }
+
+ /* Okay the user doesn't want us to change the font so we try the
+ * window. But that may be too big for the screen which forces us
+ * to change the terminal.
+ */
+ if ((cfg.lockfont && reinit==0) || reinit>0) {
+ offset_width = offset_height = cfg.window_border;
+ extra_width = wr.right - wr.left - cr.right + cr.left + offset_width*2;
+ extra_height = wr.bottom - wr.top - cr.bottom + cr.top +offset_height*2;
+
+ if (win_width != font_width*cols + offset_width*2 ||
+ win_height != font_height*rows + offset_height*2) {
+
+ static RECT ss;
+ int width, height;
+
+ GetClientRect(GetDesktopWindow(), &ss);
+ width = (ss.right - ss.left - extra_width) / font_width;
+ height = (ss.bottom - ss.top - extra_height) / font_height;
+
+ /* Grrr too big */
+ if ( rows > height || cols > width ) {
+ if ( height > rows ) height = rows;
+ if ( width > cols ) width = cols;
+ term_size(height, width, cfg.savelines);
+#ifdef RDB_DEBUG_PATCH
+ debug((27, "reset_window() -> term resize to (%d,%d)",
+ height, width));
+#endif
+ }
+
+ SetWindowPos(hwnd, NULL, 0, 0,
+ font_width*cols + extra_width,
+ font_height*rows + extra_height,
+ SWP_NOMOVE | SWP_NOZORDER);
+
+ InvalidateRect(hwnd, NULL, TRUE);
+#ifdef RDB_DEBUG_PATCH
+ debug((27, "reset_window() -> window resize to (%d,%d)",
+ font_width*cols + extra_width,
+ font_height*rows + extra_height));
+#endif
+ }
+ return;
+ }
+
+ /* We're allowed to or must change the font but do we want to ? */
+
+ if (font_width != (win_width-cfg.window_border*2)/cols ||
+ font_height != (win_height-cfg.window_border*2)/rows) {
+
+ deinit_fonts();
+ init_fonts((win_width-cfg.window_border*2)/cols,
+ (win_height-cfg.window_border*2)/rows);
+ offset_width = (win_width-font_width*cols)/2;
+ offset_height = (win_height-font_height*rows)/2;
+
+ extra_width = wr.right - wr.left - cr.right + cr.left +offset_width*2;
+ extra_height = wr.bottom - wr.top - cr.bottom + cr.top+offset_height*2;
+
+ InvalidateRect(hwnd, NULL, TRUE);
+#ifdef RDB_DEBUG_PATCH
+ debug((25, "reset_window() -> font resize to (%d,%d)",
+ font_width, font_height));
+#endif
+ }
+}
+
+static void click(Mouse_Button b, int x, int y, int shift, int ctrl)
+{
+ int thistime = GetMessageTime();
+
+ if (send_raw_mouse && !(cfg.mouse_override && shift)) {
+ lastbtn = MBT_NOTHING;
+ term_mouse(b, MA_CLICK, x, y, shift, ctrl);
+ return;
+ }
+
+ if (lastbtn == b && thistime - lasttime < dbltime) {
+ lastact = (lastact == MA_CLICK ? MA_2CLK :
+ lastact == MA_2CLK ? MA_3CLK :
+ lastact == MA_3CLK ? MA_CLICK : MA_NOTHING);
+ } else {
+ lastbtn = b;
+ lastact = MA_CLICK;
+ }
+ if (lastact != MA_NOTHING)
+ term_mouse(b, lastact, x, y, shift, ctrl);
+ lasttime = thistime;
+}
+
+/*
+ * Translate a raw mouse button designation (LEFT, MIDDLE, RIGHT)
+ * into a cooked one (SELECT, EXTEND, PASTE).
+ */
+Mouse_Button translate_button(Mouse_Button button)
+{
+ if (button == MBT_LEFT)
+ return MBT_SELECT;
+ if (button == MBT_MIDDLE)
+ return cfg.mouse_is_xterm ? MBT_PASTE : MBT_EXTEND;
+ if (button == MBT_RIGHT)
+ return cfg.mouse_is_xterm ? MBT_EXTEND : MBT_PASTE;
+ return 0; /* shouldn't happen */
+}
+
+static void show_mouseptr(int show)
+{
+ static int cursor_visible = 1;
+ if (!cfg.hide_mouseptr) /* override if this feature disabled */
+ show = 1;
+ if (cursor_visible && !show)
+ ShowCursor(FALSE);
+ else if (!cursor_visible && show)
+ ShowCursor(TRUE);
+ cursor_visible = show;
+}
+
+static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
+ WPARAM wParam, LPARAM lParam)
+{
+ HDC hdc;
+ static int ignore_clip = FALSE;
+ static int resizing = FALSE;
+ static int need_backend_resize = FALSE;
+
+ switch (message) {
+ case WM_TIMER:
+ if (pending_netevent)
+ enact_pending_netevent();
+ if (inbuf_head)
+ term_out();
+ noise_regular();
+ HideCaret(hwnd);
+ term_update();
+ ShowCaret(hwnd);
+ if (cfg.ping_interval > 0) {
+ time_t now;
+ time(&now);
+ if (now - last_movement > cfg.ping_interval) {
+ back->special(TS_PING);
+ last_movement = now;
+ }
+ }
+ return 0;
+ case WM_CREATE:
+ break;
+ case WM_CLOSE:
+ show_mouseptr(1);
+ 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)
+ DestroyWindow(hwnd);
+ return 0;
+ case WM_DESTROY:
+ show_mouseptr(1);
+ PostQuitMessage(0);
+ return 0;
+ case WM_SYSCOMMAND:
+ switch (wParam & ~0xF) { /* low 4 bits reserved to Windows */
+ case IDM_SHOWLOG:
+ showeventlog(hwnd);
+ break;
+ case IDM_NEWSESS:
+ case IDM_DUPSESS:
+ case IDM_SAVEDSESS:
+ {
+ char b[2048];
+ char c[30], *cl;
+ int freecl = FALSE;
+ STARTUPINFO si;
+ PROCESS_INFORMATION pi;
+ HANDLE filemap = NULL;
+
+ if (wParam == IDM_DUPSESS) {
+ /*
+ * Allocate a file-mapping memory chunk for the
+ * config structure.
+ */
+ SECURITY_ATTRIBUTES sa;
+ Config *p;
+
+ sa.nLength = sizeof(sa);
+ sa.lpSecurityDescriptor = NULL;
+ sa.bInheritHandle = TRUE;
+ filemap = CreateFileMapping((HANDLE) 0xFFFFFFFF,
+ &sa,
+ PAGE_READWRITE,
+ 0, sizeof(Config), NULL);
+ if (filemap) {
+ p = (Config *) MapViewOfFile(filemap,
+ FILE_MAP_WRITE,
+ 0, 0, sizeof(Config));
+ if (p) {
+ *p = cfg; /* structure copy */
+ UnmapViewOfFile(p);
+ }
+ }
+ sprintf(c, "putty &%p", filemap);
+ cl = c;
+ } else if (wParam == IDM_SAVEDSESS) {
+ char *session =
+ sessions[(lParam - IDM_SAVED_MIN) / 16];
+ cl = smalloc(16 + strlen(session)); /* 8, but play safe */
+ if (!cl)
+ cl = NULL; /* not a very important failure mode */
+ else {
+ sprintf(cl, "putty @%s", session);
+ freecl = TRUE;
+ }
+ } else
+ cl = NULL;
+
+ GetModuleFileName(NULL, b, sizeof(b) - 1);
+ si.cb = sizeof(si);
+ si.lpReserved = NULL;
+ si.lpDesktop = NULL;
+ si.lpTitle = NULL;
+ si.dwFlags = 0;
+ si.cbReserved2 = 0;
+ si.lpReserved2 = NULL;
+ CreateProcess(b, cl, NULL, NULL, TRUE,
+ NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi);
+
+ if (filemap)
+ CloseHandle(filemap);
+ if (freecl)
+ sfree(cl);
+ }
+ break;
+ case IDM_RECONF:
+ {
+ Config prev_cfg;
+ int init_lvl = 1;
+
+ GetWindowText(hwnd, cfg.wintitle, sizeof(cfg.wintitle));
+ prev_cfg = cfg;
+
+ if (!do_reconfig(hwnd))
+ break;
+
+ if (strcmp(prev_cfg.logfilename, cfg.logfilename) ||
+ prev_cfg.logtype != cfg.logtype) {
+ logfclose(); /* reset logging */
+ logfopen();
+ }
+
+ sfree(logpal);
+ /*
+ * Flush the line discipline's edit buffer in the
+ * case where local editing has just been disabled.
+ */
+ ldisc_send(NULL, 0);
+ if (pal)
+ DeleteObject(pal);
+ logpal = NULL;
+ pal = NULL;
+ cfgtopalette();
+ init_palette();
+
+ /* Screen size changed ? */
+ if (cfg.height != prev_cfg.height ||
+ cfg.width != prev_cfg.width ||
+ cfg.savelines != prev_cfg.savelines ||
+ cfg.locksize )
+ term_size(cfg.height, cfg.width, cfg.savelines);
+
+ /* Enable or disable the scroll bar, etc */
+ {
+ LONG nflg, flag = GetWindowLong(hwnd, GWL_STYLE);
+ LONG nexflag, exflag =
+ GetWindowLong(hwnd, GWL_EXSTYLE);
+
+ nexflag = exflag;
+ if (cfg.alwaysontop != prev_cfg.alwaysontop) {
+ if (cfg.alwaysontop) {
+ nexflag |= WS_EX_TOPMOST;
+ SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0,
+ SWP_NOMOVE | SWP_NOSIZE);
+ } else {
+ nexflag &= ~(WS_EX_TOPMOST);
+ SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0,
+ SWP_NOMOVE | SWP_NOSIZE);
+ }
+ }
+ if (cfg.sunken_edge)
+ nexflag |= WS_EX_CLIENTEDGE;
+ else
+ nexflag &= ~(WS_EX_CLIENTEDGE);
+
+ nflg = flag;
+ if (cfg.scrollbar)
+ nflg |= WS_VSCROLL;
+ else
+ nflg &= ~WS_VSCROLL;
+ if (cfg.locksize && cfg.lockfont)
+ nflg &= ~(WS_THICKFRAME | WS_MAXIMIZEBOX);
+ else
+ nflg |= (WS_THICKFRAME | WS_MAXIMIZEBOX);
+
+ if (nflg != flag || nexflag != exflag) {
+ if (nflg != flag)
+ SetWindowLong(hwnd, GWL_STYLE, nflg);
+ if (nexflag != exflag)
+ SetWindowLong(hwnd, GWL_EXSTYLE, nexflag);
+
+ SetWindowPos(hwnd, NULL, 0, 0, 0, 0,
+ SWP_NOACTIVATE | SWP_NOCOPYBITS |
+ SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER |
+ SWP_FRAMECHANGED);
+
+ init_lvl = 2;
+ }
+ }
+
+ /* Oops */
+ if (cfg.locksize && cfg.lockfont && IsZoomed(hwnd)) {
+ force_normal(hwnd);
+ init_lvl = 2;
+ }
+
+ set_title(cfg.wintitle);
+ if (IsIconic(hwnd)) {
+ SetWindowText(hwnd,
+ cfg.win_name_always ? window_name :
+ icon_name);
+ }
+
+ if (strcmp(cfg.font, prev_cfg.font) != 0 ||
+ strcmp(cfg.line_codepage, prev_cfg.line_codepage) != 0 ||
+ cfg.fontisbold != prev_cfg.fontisbold ||
+ cfg.fontheight != prev_cfg.fontheight ||
+ cfg.fontcharset != prev_cfg.fontcharset ||
+ cfg.vtmode != prev_cfg.vtmode ||
+ cfg.bold_colour != prev_cfg.bold_colour ||
+ (cfg.lockfont && !prev_cfg.lockfont))
+ init_lvl = 2;
+
+ InvalidateRect(hwnd, NULL, TRUE);
+ reset_window(init_lvl);
+ }
+ break;
+ case IDM_COPYALL:
+ term_copyall();
+ break;
+ case IDM_CLRSB:
+ term_clrsb();
+ break;
+ case IDM_RESET:
+ term_pwron();
+ break;
+ case IDM_TEL_AYT:
+ back->special(TS_AYT);
+ break;
+ case IDM_TEL_BRK:
+ back->special(TS_BRK);
+ break;
+ case IDM_TEL_SYNCH:
+ back->special(TS_SYNCH);
+ break;
+ case IDM_TEL_EC:
+ back->special(TS_EC);
+ break;
+ case IDM_TEL_EL:
+ back->special(TS_EL);
+ break;
+ case IDM_TEL_GA:
+ back->special(TS_GA);
+ break;
+ case IDM_TEL_NOP:
+ back->special(TS_NOP);
+ break;
+ case IDM_TEL_ABORT:
+ back->special(TS_ABORT);
+ break;
+ case IDM_TEL_AO:
+ back->special(TS_AO);
+ break;
+ case IDM_TEL_IP:
+ back->special(TS_IP);
+ break;
+ case IDM_TEL_SUSP:
+ back->special(TS_SUSP);
+ break;
+ case IDM_TEL_EOR:
+ back->special(TS_EOR);
+ break;
+ case IDM_TEL_EOF:
+ back->special(TS_EOF);
+ break;