From f9e572595bb8cb65f8fab86f8a84a3bbefaa1895 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Tue, 13 Sep 2022 09:00:19 +0100 Subject: [PATCH] windows/window.c: move (most) static vars into WinGuiSeat. This is a piece of refactoring that's been overdue forever. In the Unix front end, all the variables specific to a particular SSH session live in a big 'inst' structure, and calls to any of the trait APIs like Seat or TermWin can recover the right 'inst' from their input context pointer. But the Windows frontend was written before that kind of thing became habitual to me, and all its variables have been just lying around at the top level of window.c, and most of those context pointers were just ignored. Now I've swept them all up and put them where they ought to be, in a big context structure. This was made immeasurably easier by the very nifty 'clang-rename' tool, which can rename a single variable in a C source file, and find just the right set of identifiers to change even if other variables in the file have the same name, even in sub-scopes. So I started by clang-renaming all the top-level variables in question to have names beginning with a prefix that didn't previously appear anywhere in the code; checked that still worked; and then moved all the declarations into the struct type and did a purely textual search-and-replace of the prefix with 'wgs->'. One potential benefit of this change is that it allows more than one instance of the WinGuiSeat structure to exist in the same process. I don't have any immediate plans to actually do that, but it's nice to know it wouldn't be ruled out if we ever did need it. But that's not the main reason I did it. The main reason is that I recently looked at the output of a Windows build using clang -Wall, and was horrified by the number of casual shadowings of generically-named global variables like 'term' and 'conf' with local variables of the same name. That seemed like a recipe for confusion, and I decided the best way to disambiguate them all was to do this refactoring that I'd wanted anyway for years. A few uses of the global variables occurred in functions that didn't have convenient access to the right WinGuiSeat via a callback parameter of some kind. Those had to be treated specially. Most were cleaned up in advance by the previous few commits; the remaining fixes in this commit itself were in functions like modalfatalbox(), nonfatal() and cleanup_exit(). The error reporting functions want the terminal HWND to use as a MessageBox parameter; they also have the side effect of un-hiding the mouse pointer in the terminal window, in case it's hidden; and cleanup_exit wanted to free some resources dangling off the WinGuiSeat. For most of those cases, I've made a linked list of all currently live WinGuiSeat structures, so that they can loop over _all_ live instances (whether there's one as usual, none, or maybe more than one in future). The parent window for non-connection-specific error messages is found by simply picking one arbitrarily off the linked list (if any); the cleanups are done by iterating over the _whole_ list. The mouse-pointer unhiding is dealt with by simply allowing show_mouseptr to take a _null_ WinGuiSeat pointer. The only thing it needs the context for at all is to check whether pointer-hiding is enabled in the session's Conf; so if we're _un_-hiding the pointer we don't need to check, and can unhide it unconditionally. The remaining global variables in window.c are the new linked list of all WinGuiSeat structures; 'wm_mousewheel' and 'trust_icon' which really should be global across all WinGuiSeats even if we were to have more than one; and there's a static variable 'cursor_visible' in show_mouseptr() which is likewise legitimately Seat-independent (since it records the last value we passed to the Win32 API ShowCursor function, and _that's_ global across the whole process state). All of this should cause no functional change whatsoever. --- windows/win-gui-seat.h | 134 ++- windows/window.c | 1967 ++++++++++++++++++++-------------------- 2 files changed, 1133 insertions(+), 968 deletions(-) diff --git a/windows/win-gui-seat.h b/windows/win-gui-seat.h index 19c5cbea..4b42e8f6 100644 --- a/windows/win-gui-seat.h +++ b/windows/win-gui-seat.h @@ -1,14 +1,142 @@ /* - * Small implementation of Seat and LogPolicy shared between window.c - * and dialog.c. + * Main state structure for an instance of the Windows PuTTY front + * end, containing all the PuTTY objects and all the Windows API + * resources like the window handle. */ typedef struct WinGuiSeat WinGuiSeat; +struct PopupMenu { + HMENU menu; +}; +enum { SYSMENU, CTXMENU }; /* indices into popup_menus field */ + +#define FONT_NORMAL 0 +#define FONT_BOLD 1 +#define FONT_UNDERLINE 2 +#define FONT_BOLDUND 3 +#define FONT_WIDE 0x04 +#define FONT_HIGH 0x08 +#define FONT_NARROW 0x10 + +#define FONT_OEM 0x20 +#define FONT_OEMBOLD 0x21 +#define FONT_OEMUND 0x22 +#define FONT_OEMBOLDUND 0x23 + +#define FONT_MAXNO 0x40 +#define FONT_SHIFT 5 + +enum BoldMode { + BOLD_NONE, BOLD_SHADOW, BOLD_FONT +}; +enum UnderlineMode { + UND_LINE, UND_FONT +}; + +struct _dpi_info { + POINT cur_dpi; + RECT new_wnd_rect; +}; + +/* + * Against the future possibility of having more than one of these + * in a process (and the current possibility of having zero), we + * keep a linked list of all live WinGuiSeats, so that cleanups + * can be done to any that exist. + */ +struct WinGuiSeatListNode { + struct WinGuiSeatListNode *next, *prev; +}; +extern struct WinGuiSeatListNode wgslisthead; /* static end pointer */ + struct WinGuiSeat { - HWND term_hwnd; + struct WinGuiSeatListNode wgslistnode; + Seat seat; + TermWin termwin; LogPolicy logpolicy; + + HWND term_hwnd; + + int caret_x, caret_y; + + int kbd_codepage; + + Ldisc *ldisc; + Backend *backend; + + cmdline_get_passwd_input_state cmdline_get_passwd_state; + + struct unicode_data ucsdata; + bool session_closed; + bool reconfiguring; + + const SessionSpecial *specials; + HMENU specials_menu; + int n_specials; + + struct PopupMenu popup_menus[2]; + HMENU savedsess_menu; + + Conf *conf; + LogContext *logctx; + Terminal *term; + + int cursor_type; + int vtmode; + + HFONT fonts[FONT_MAXNO]; + LOGFONT lfont; + bool fontflag[FONT_MAXNO]; + enum BoldMode bold_font_mode; + + bool bold_colours; + enum UnderlineMode und_mode; + int descent, font_strikethrough_y; + + COLORREF colours[OSC4_NCOLOURS]; + HPALETTE pal; + LPLOGPALETTE logpal; + bool tried_pal; + COLORREF colorref_modifier; + + struct _dpi_info dpi_info; + + int dbltime, lasttime, lastact; + Mouse_Button lastbtn; + + bool send_raw_mouse; + int wheel_accumulator; + + bool pointer_indicates_raw_mouse; + + BusyStatus busy_status; + + wchar_t *window_name, *icon_name; + + int compose_state; + + HDC wintw_hdc; + + bool resizing; + + long next_flash; + bool flashing; }; extern const LogPolicyVtable win_gui_logpolicy_vt; /* in dialog.c */ + +static inline void wgs_link(WinGuiSeat *wgs) +{ + wgs->wgslistnode.prev = wgslisthead.prev; + wgs->wgslistnode.next = &wgslisthead; + wgs->wgslistnode.prev->next = &wgs->wgslistnode; + wgs->wgslistnode.next->prev = &wgs->wgslistnode; +} + +static inline void wgs_unlink(WinGuiSeat *wgs) +{ + wgs->wgslistnode.prev->next = wgs->wgslistnode.next; + wgs->wgslistnode.next->prev = wgs->wgslistnode.prev; +} diff --git a/windows/window.c b/windows/window.c index 68c4d5a9..2888519e 100644 --- a/windows/window.c +++ b/windows/window.c @@ -91,29 +91,29 @@ #define VK_PACKET 0xE7 #endif -static Mouse_Button translate_button(Mouse_Button button); -static void show_mouseptr(bool show); +static Mouse_Button translate_button(WinGuiSeat *wgs, Mouse_Button button); +static void show_mouseptr(WinGuiSeat *wgs, bool show); static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); -static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam, - unsigned char *output); -static void init_palette(void); -static void init_fonts(int, int); -static void init_dpi_info(void); -static void another_font(int); -static void deinit_fonts(void); -static void set_input_locale(HKL); -static void update_savedsess_menu(void); +static int TranslateKey(WinGuiSeat *wgs, UINT message, WPARAM wParam, + LPARAM lParam, unsigned char *output); +static void init_palette(WinGuiSeat *wgs); +static void init_fonts(WinGuiSeat *wgs, int, int); +static void init_dpi_info(WinGuiSeat *wgs); +static void another_font(WinGuiSeat *wgs, int); +static void deinit_fonts(WinGuiSeat *wgs); +static void set_input_locale(WinGuiSeat *wgs, HKL); +static void update_savedsess_menu(WinGuiSeat *wgs); static void init_winfuncs(void); -static bool is_full_screen(void); -static void make_full_screen(void); -static void clear_full_screen(void); -static void flip_full_screen(void); -static void process_clipdata(HGLOBAL clipdata, bool unicode); +static bool is_full_screen(WinGuiSeat *wgs); +static void make_full_screen(WinGuiSeat *wgs); +static void clear_full_screen(WinGuiSeat *wgs); +static void flip_full_screen(WinGuiSeat *wgs); +static void process_clipdata(WinGuiSeat *wgs, HGLOBAL clipdata, bool unicode); static void setup_clipboards(Terminal *, Conf *); /* Window layout information */ -static void reset_window(int); +static void reset_window(WinGuiSeat *wgs, int reinit); static int extra_width, extra_height; static int font_width, font_height; static bool font_dualwidth, font_varpitch; @@ -121,76 +121,14 @@ static int offset_width, offset_height; static bool was_zoomed = false; static int prev_rows, prev_cols; -static void flash_window(int mode); -static void sys_cursor_update(void); -static bool get_fullscreen_rect(RECT *ss); +static void flash_window(WinGuiSeat *wgs, int mode); +static void sys_cursor_update(WinGuiSeat *wgs); +static bool get_fullscreen_rect(WinGuiSeat *wgs, RECT *ss); -static int caret_x = -1, caret_y = -1; - -static int kbd_codepage; - -static Ldisc *ldisc; -static Backend *backend; - -static cmdline_get_passwd_input_state cmdline_get_passwd_state; - -static struct unicode_data ucsdata; -static bool session_closed; -static bool reconfiguring = false; - -static const SessionSpecial *specials = NULL; -static HMENU specials_menu = NULL; -static int n_specials = 0; - -static struct { - HMENU menu; -} popup_menus[2]; -enum { SYSMENU, CTXMENU }; -static HMENU savedsess_menu; - -static Conf *conf; -static LogContext *logctx; -static Terminal *term; - -static void conf_cache_data(void); -static int cursor_type; -static int vtmode; +static void conf_cache_data(WinGuiSeat *wgs); static struct sesslist sesslist; /* for saved-session menu */ -#define FONT_NORMAL 0 -#define FONT_BOLD 1 -#define FONT_UNDERLINE 2 -#define FONT_BOLDUND 3 -#define FONT_WIDE 0x04 -#define FONT_HIGH 0x08 -#define FONT_NARROW 0x10 - -#define FONT_OEM 0x20 -#define FONT_OEMBOLD 0x21 -#define FONT_OEMUND 0x22 -#define FONT_OEMBOLDUND 0x23 - -#define FONT_MAXNO 0x40 -#define FONT_SHIFT 5 -static HFONT fonts[FONT_MAXNO]; -static LOGFONT lfont; -static bool fontflag[FONT_MAXNO]; -static enum { - BOLD_NONE, BOLD_SHADOW, BOLD_FONT -} bold_font_mode; -static bool bold_colours; -static enum { - UND_LINE, UND_FONT -} und_mode; -static int descent, font_strikethrough_y; - -static COLORREF colours[OSC4_NCOLOURS]; -static HPALETTE pal; -static LPLOGPALETTE logpal; -bool tried_pal = false; -COLORREF colorref_modifier = 0; - enum MONITOR_DPI_TYPE { MDT_EFFECTIVE_DPI, MDT_ANGULAR_DPI, MDT_RAW_DPI, MDT_DEFAULT }; DECL_WINDOWS_FUNCTION(static, BOOL, GetMonitorInfoA, (HMONITOR, LPMONITORINFO)); DECL_WINDOWS_FUNCTION(static, HMONITOR, MonitorFromPoint, (POINT, DWORD)); @@ -199,30 +137,14 @@ DECL_WINDOWS_FUNCTION(static, HRESULT, GetDpiForMonitor, (HMONITOR hmonitor, enu DECL_WINDOWS_FUNCTION(static, HRESULT, GetSystemMetricsForDpi, (int nIndex, UINT dpi)); DECL_WINDOWS_FUNCTION(static, HRESULT, AdjustWindowRectExForDpi, (LPRECT lpRect, DWORD dwStyle, BOOL bMenu, DWORD dwExStyle, UINT dpi)); -static struct _dpi_info { - POINT cur_dpi; - RECT new_wnd_rect; -} dpi_info; - static HBITMAP caretbm; -static int dbltime, lasttime, lastact; -static Mouse_Button lastbtn; - -/* this allows xterm-style mouse handling. */ -static bool send_raw_mouse = false; -static int wheel_accumulator = 0; - -static bool pointer_indicates_raw_mouse = false; - -static BusyStatus busy_status = BUSY_NOT; - -static wchar_t *window_name, *icon_name; - -static int compose_state = 0; - static UINT wm_mousewheel = WM_MOUSEWHEEL; +struct WinGuiSeatListNode wgslisthead = { + .next = &wgslisthead, .prev = &wgslisthead, +}; + #define IS_HIGH_VARSEL(wch1, wch2) \ ((wch1) == 0xDB40 && ((wch2) >= 0xDD00 && (wch2) <= 0xDDEF)) #define IS_LOW_VARSEL(wch) \ @@ -286,33 +208,33 @@ static const TermWinVtable windows_termwin_vt = { .unthrottle = wintw_unthrottle, }; -static TermWin wintw[1]; -static HDC wintw_hdc; - static HICON trust_icon = INVALID_HANDLE_VALUE; const bool share_can_be_downstream = true; const bool share_can_be_upstream = true; -static bool is_utf8(void) +static bool is_utf8(WinGuiSeat *wgs) { - return ucsdata.line_codepage == CP_UTF8; + return wgs->ucsdata.line_codepage == CP_UTF8; } static bool win_seat_is_utf8(Seat *seat) { - return is_utf8(); + WinGuiSeat *wgs = container_of(seat, WinGuiSeat, seat); + return is_utf8(wgs); } static char *win_seat_get_ttymode(Seat *seat, const char *mode) { - return term_get_ttymode(term, mode); + WinGuiSeat *wgs = container_of(seat, WinGuiSeat, seat); + return term_get_ttymode(wgs->term, mode); } static StripCtrlChars *win_seat_stripctrl_new( Seat *seat, BinarySink *bs_out, SeatInteractionContext sic) { - return stripctrl_new_term(bs_out, false, 0, term); + WinGuiSeat *wgs = container_of(seat, WinGuiSeat, seat); + return stripctrl_new_term(bs_out, false, 0, wgs->term); } static size_t win_seat_output( @@ -360,26 +282,24 @@ static const SeatVtable win_seat_vt = { .interactive = nullseat_interactive_yes, .get_cursor_position = win_seat_get_cursor_position, }; -static WinGuiSeat wgs = { .seat.vt = &win_seat_vt, - .logpolicy.vt = &win_gui_logpolicy_vt }; -static void start_backend(void) +static void start_backend(WinGuiSeat *wgs) { const struct BackendVtable *vt; char *error, *realhost; int i; - cmdline_get_passwd_state = cmdline_get_passwd_input_state_new; + wgs->cmdline_get_passwd_state = cmdline_get_passwd_input_state_new; - vt = backend_vt_from_conf(conf); + vt = backend_vt_from_conf(wgs->conf); - seat_set_trust_status(&wgs.seat, true); - error = backend_init(vt, &wgs.seat, &backend, logctx, conf, - conf_get_str(conf, CONF_host), - conf_get_int(conf, CONF_port), + seat_set_trust_status(&wgs->seat, true); + error = backend_init(vt, &wgs->seat, &wgs->backend, wgs->logctx, wgs->conf, + conf_get_str(wgs->conf, CONF_host), + conf_get_int(wgs->conf, CONF_port), &realhost, - conf_get_bool(conf, CONF_tcp_nodelay), - conf_get_bool(conf, CONF_tcp_keepalives)); + conf_get_bool(wgs->conf, CONF_tcp_nodelay), + conf_get_bool(wgs->conf, CONF_tcp_keepalives)); if (error) { char *str = dupprintf("%s Error", appname); char *msg; @@ -388,7 +308,7 @@ static void start_backend(void) msg = dupprintf("Unable to open terminal:\n%s", error); } else { msg = dupprintf("Unable to open connection to\n%s\n%s", - conf_dest(conf), error); + conf_dest(wgs->conf), error); } sfree(error); MessageBox(NULL, msg, str, MB_ICONERROR | MB_OK); @@ -396,18 +316,18 @@ static void start_backend(void) sfree(msg); exit(0); } - term_setup_window_titles(term, realhost); + term_setup_window_titles(wgs->term, realhost); sfree(realhost); /* * Connect the terminal to the backend for resize purposes. */ - term_provide_backend(term, backend); + term_provide_backend(wgs->term, wgs->backend); /* * Set up a line discipline. */ - ldisc = ldisc_create(conf, term, backend, &wgs.seat); + wgs->ldisc = ldisc_create(wgs->conf, wgs->term, wgs->backend, &wgs->seat); /* * Destroy the Restart Session menu item. (This will return @@ -416,43 +336,44 @@ static void start_backend(void) * as the menu item ends up not being there, we don't care * whether it was us who removed it or not!) */ - for (i = 0; i < lenof(popup_menus); i++) { - DeleteMenu(popup_menus[i].menu, IDM_RESTART, MF_BYCOMMAND); + for (i = 0; i < lenof(wgs->popup_menus); i++) { + DeleteMenu(wgs->popup_menus[i].menu, IDM_RESTART, MF_BYCOMMAND); } - session_closed = false; + wgs->session_closed = false; } -static void close_session(void *ignored_context) +static void close_session(void *vctx) { + WinGuiSeat *wgs = (WinGuiSeat *)vctx; char *newtitle; int i; - session_closed = true; + wgs->session_closed = true; newtitle = dupprintf("%s (inactive)", appname); - win_set_icon_title(wintw, newtitle, DEFAULT_CODEPAGE); - win_set_title(wintw, newtitle, DEFAULT_CODEPAGE); + win_set_icon_title(&wgs->termwin, newtitle, DEFAULT_CODEPAGE); + win_set_title(&wgs->termwin, newtitle, DEFAULT_CODEPAGE); sfree(newtitle); - if (ldisc) { - ldisc_free(ldisc); - ldisc = NULL; + if (wgs->ldisc) { + ldisc_free(wgs->ldisc); + wgs->ldisc = NULL; } - if (backend) { - backend_free(backend); - backend = NULL; - term_provide_backend(term, NULL); - seat_update_specials_menu(&wgs.seat); + if (wgs->backend) { + backend_free(wgs->backend); + wgs->backend = NULL; + term_provide_backend(wgs->term, NULL); + seat_update_specials_menu(&wgs->seat); } /* * Show the Restart Session menu item. Do a precautionary * delete first to ensure we never end up with more than one. */ - for (i = 0; i < lenof(popup_menus); i++) { - DeleteMenu(popup_menus[i].menu, IDM_RESTART, MF_BYCOMMAND); - InsertMenu(popup_menus[i].menu, IDM_DUPSESS, MF_BYCOMMAND | MF_ENABLED, - IDM_RESTART, "&Restart Session"); + for (i = 0; i < lenof(wgs->popup_menus); i++) { + DeleteMenu(wgs->popup_menus[i].menu, IDM_RESTART, MF_BYCOMMAND); + InsertMenu(wgs->popup_menus[i].menu, IDM_DUPSESS, + MF_BYCOMMAND | MF_ENABLED, IDM_RESTART, "&Restart Session"); } } @@ -565,7 +486,18 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) setup_gui_timing(); - conf = conf_new(); + WinGuiSeat *wgs = snew(WinGuiSeat); + memset(wgs, 0, sizeof(*wgs)); + wgs_link(wgs); + + wgs->seat.vt = &win_seat_vt; + wgs->logpolicy.vt = &win_gui_logpolicy_vt; + wgs->termwin.vt = &windows_termwin_vt; + + wgs->caret_x = wgs->caret_y = -1; + wgs->busy_status = BUSY_NOT; + + wgs->conf = conf_new(); /* * Initialize COM. @@ -582,11 +514,11 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) /* * Process the command line. */ - gui_term_process_cmdline(conf, cmdline); + gui_term_process_cmdline(wgs->conf, cmdline); - memset(&ucsdata, 0, sizeof(ucsdata)); + memset(&wgs->ucsdata, 0, sizeof(wgs->ucsdata)); - conf_cache_data(); + conf_cache_data(wgs); /* * Guess some defaults for the window size. This all gets @@ -599,11 +531,13 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) font_height = 20; extra_width = 25; extra_height = 28; - guess_width = extra_width + font_width * conf_get_int(conf, CONF_width); - guess_height = extra_height + font_height*conf_get_int(conf, CONF_height); + guess_width = extra_width + font_width * conf_get_int( + wgs->conf, CONF_width); + guess_height = extra_height + font_height * conf_get_int( + wgs->conf, CONF_height); { RECT r; - get_fullscreen_rect(&r); + get_fullscreen_rect(wgs, &r); if (guess_width > r.right - r.left) guess_width = r.right - r.left; if (guess_height > r.bottom - r.top) @@ -619,68 +553,70 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) if (vt && vt->flags & BACKEND_RESIZE_FORBIDDEN) resize_forbidden = true; wchar_t *uappname = dup_mb_to_wc(DEFAULT_CODEPAGE, 0, appname); - window_name = dup_mb_to_wc(DEFAULT_CODEPAGE, 0, appname); - icon_name = dup_mb_to_wc(DEFAULT_CODEPAGE, 0, appname); - if (!conf_get_bool(conf, CONF_scrollbar)) + wgs->window_name = dup_mb_to_wc(DEFAULT_CODEPAGE, 0, appname); + wgs->icon_name = dup_mb_to_wc(DEFAULT_CODEPAGE, 0, appname); + if (!conf_get_bool(wgs->conf, CONF_scrollbar)) winmode &= ~(WS_VSCROLL); - if (conf_get_int(conf, CONF_resize_action) == RESIZE_DISABLED || + if (conf_get_int(wgs->conf, CONF_resize_action) == RESIZE_DISABLED || resize_forbidden) winmode &= ~(WS_THICKFRAME | WS_MAXIMIZEBOX); - if (conf_get_bool(conf, CONF_alwaysontop)) + if (conf_get_bool(wgs->conf, CONF_alwaysontop)) exwinmode |= WS_EX_TOPMOST; - if (conf_get_bool(conf, CONF_sunken_edge)) + if (conf_get_bool(wgs->conf, CONF_sunken_edge)) exwinmode |= WS_EX_CLIENTEDGE; #ifdef TEST_ANSI_WINDOW /* For developer testing of ANSI window support, pretend * CreateWindowExW failed */ - wgs.term_hwnd = NULL; + wgs->term_hwnd = NULL; SetLastError(ERROR_CALL_NOT_IMPLEMENTED); #else unicode_window = true; sw_PeekMessage = PeekMessageW; sw_DispatchMessage = DispatchMessageW; sw_DefWindowProc = DefWindowProcW; - wgs.term_hwnd = CreateWindowExW( + wgs->term_hwnd = CreateWindowExW( exwinmode, terminal_window_class_w(), uappname, winmode, CW_USEDEFAULT, CW_USEDEFAULT, guess_width, guess_height, NULL, NULL, inst, NULL); #endif #if defined LEGACY_WINDOWS || defined TEST_ANSI_WINDOW - if (!wgs.term_hwnd && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) { + if (!wgs->term_hwnd && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED) { /* Fall back to an ANSI window, swapping in all the ANSI * window message handling functions */ unicode_window = false; sw_PeekMessage = PeekMessageA; sw_DispatchMessage = DispatchMessageA; sw_DefWindowProc = DefWindowProcA; - wgs.term_hwnd = CreateWindowExA( + wgs->term_hwnd = CreateWindowExA( exwinmode, terminal_window_class_a(), appname, winmode, CW_USEDEFAULT, CW_USEDEFAULT, guess_width, guess_height, NULL, NULL, inst, NULL); } #endif - if (!wgs.term_hwnd) { + if (!wgs->term_hwnd) { modalfatalbox("Unable to create terminal window: %s", win_strerror(GetLastError())); } - memset(&dpi_info, 0, sizeof(struct _dpi_info)); - init_dpi_info(); + memset(&wgs->dpi_info, 0, sizeof(struct _dpi_info)); + init_dpi_info(wgs); sfree(uappname); } + SetWindowLongPtr(wgs->term_hwnd, GWLP_USERDATA, (LONG_PTR)wgs); + /* * Initialise the fonts, simultaneously correcting the guesses * for font_{width,height}. */ - init_fonts(0,0); + init_fonts(wgs, 0, 0); /* * Prepare a logical palette. */ - init_palette(); + init_palette(wgs); /* * Initialise the terminal. (We have to do this _after_ @@ -688,23 +624,23 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) * which will call schedule_timer(), which will in turn call * timer_change_notify() which will expect hwnd to exist.) */ - wintw->vt = &windows_termwin_vt; - term = term_init(conf, &ucsdata, wintw); - setup_clipboards(term, conf); - logctx = log_init(&wgs.logpolicy, conf); - term_provide_logctx(term, logctx); - term_size(term, conf_get_int(conf, CONF_height), - conf_get_int(conf, CONF_width), - conf_get_int(conf, CONF_savelines)); + wgs->term = term_init(wgs->conf, &wgs->ucsdata, &wgs->termwin); + setup_clipboards(wgs->term, wgs->conf); + wgs->logctx = log_init(&wgs->logpolicy, wgs->conf); + term_provide_logctx(wgs->term, wgs->logctx); + term_size(wgs->term, conf_get_int(wgs->conf, CONF_height), + conf_get_int(wgs->conf, CONF_width), + conf_get_int(wgs->conf, CONF_savelines)); /* * Correct the guesses for extra_{width,height}. */ { RECT cr, wr; - GetWindowRect(wgs.term_hwnd, &wr); - GetClientRect(wgs.term_hwnd, &cr); - offset_width = offset_height = conf_get_int(conf, CONF_window_border); + GetWindowRect(wgs->term_hwnd, &wr); + GetClientRect(wgs->term_hwnd, &cr); + offset_width = offset_height = + conf_get_int(wgs->conf, CONF_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; } @@ -713,9 +649,9 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) * Resize the window, now we know what size we _really_ want it * to be. */ - guess_width = extra_width + font_width * term->cols; - guess_height = extra_height + font_height * term->rows; - SetWindowPos(wgs.term_hwnd, NULL, 0, 0, guess_width, guess_height, + guess_width = extra_width + font_width * wgs->term->cols; + guess_height = extra_height + font_height * wgs->term->rows; + SetWindowPos(wgs->term_hwnd, NULL, 0, 0, guess_width, guess_height, SWP_NOMOVE | SWP_NOREDRAW | SWP_NOZORDER); /* @@ -729,7 +665,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) caretbm = CreateBitmap(font_width, font_height, 1, 1, bits); sfree(bits); } - CreateCaret(wgs.term_hwnd, caretbm, font_width, font_height); + CreateCaret(wgs->term_hwnd, caretbm, font_width, font_height); /* * Initialise the scroll bar. @@ -740,18 +676,18 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) si.cbSize = sizeof(si); si.fMask = SIF_ALL | SIF_DISABLENOSCROLL; si.nMin = 0; - si.nMax = term->rows - 1; - si.nPage = term->rows; + si.nMax = wgs->term->rows - 1; + si.nPage = wgs->term->rows; si.nPos = 0; - SetScrollInfo(wgs.term_hwnd, SB_VERT, &si, false); + SetScrollInfo(wgs->term_hwnd, SB_VERT, &si, false); } /* * Prepare the mouse handler. */ - lastact = MA_NOTHING; - lastbtn = MBT_NOTHING; - dbltime = GetDoubleClickTime(); + wgs->lastact = MA_NOTHING; + wgs->lastbtn = MBT_NOTHING; + wgs->dbltime = GetDoubleClickTime(); /* * Set up the session-control options on the system menu. @@ -761,24 +697,26 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) int j; char *str; - popup_menus[SYSMENU].menu = GetSystemMenu(wgs.term_hwnd, false); - popup_menus[CTXMENU].menu = CreatePopupMenu(); - AppendMenu(popup_menus[CTXMENU].menu, MF_ENABLED, IDM_COPY, "&Copy"); - AppendMenu(popup_menus[CTXMENU].menu, MF_ENABLED, IDM_PASTE, "&Paste"); + wgs->popup_menus[SYSMENU].menu = GetSystemMenu(wgs->term_hwnd, false); + wgs->popup_menus[CTXMENU].menu = CreatePopupMenu(); + AppendMenu(wgs->popup_menus[CTXMENU].menu, MF_ENABLED, + IDM_COPY, "&Copy"); + AppendMenu(wgs->popup_menus[CTXMENU].menu, MF_ENABLED, + IDM_PASTE, "&Paste"); - savedsess_menu = CreateMenu(); + wgs->savedsess_menu = CreateMenu(); get_sesslist(&sesslist, true); - update_savedsess_menu(); + update_savedsess_menu(wgs); - for (j = 0; j < lenof(popup_menus); j++) { - m = popup_menus[j].menu; + for (j = 0; j < lenof(wgs->popup_menus); j++) { + m = wgs->popup_menus[j].menu; AppendMenu(m, MF_SEPARATOR, 0, 0); AppendMenu(m, MF_ENABLED, IDM_SHOWLOG, "&Event Log"); 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_PTR) savedsess_menu, + AppendMenu(m, MF_POPUP | MF_ENABLED, (UINT_PTR)wgs->savedsess_menu, "Sa&ved Sessions"); AppendMenu(m, MF_ENABLED, IDM_RECONF, "Chan&ge Settings..."); AppendMenu(m, MF_SEPARATOR, 0, 0); @@ -786,7 +724,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) 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, (conf_get_int(conf, CONF_resize_action) + AppendMenu(m, (conf_get_int(wgs->conf, CONF_resize_action) == RESIZE_DISABLED) ? MF_GRAYED : MF_ENABLED, IDM_FULLSCREEN, "&Full Screen"); AppendMenu(m, MF_SEPARATOR, 0, 0); @@ -799,27 +737,27 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) } if (restricted_acl()) { - lp_eventlog(&wgs.logpolicy, "Running with restricted process ACL"); + lp_eventlog(&wgs->logpolicy, "Running with restricted process ACL"); } - winselgui_set_hwnd(wgs.term_hwnd); - start_backend(); + winselgui_set_hwnd(wgs->term_hwnd); + start_backend(wgs); /* * Set up the initial input locale. */ - set_input_locale(GetKeyboardLayout(0)); + set_input_locale(wgs, GetKeyboardLayout(0)); /* * Finally show the window! */ - ShowWindow(wgs.term_hwnd, show); - SetForegroundWindow(wgs.term_hwnd); + ShowWindow(wgs->term_hwnd, show); + SetForegroundWindow(wgs->term_hwnd); - term_set_focus(term, GetForegroundWindow() == wgs.term_hwnd); - UpdateWindow(wgs.term_hwnd); + term_set_focus(wgs->term, GetForegroundWindow() == wgs->term_hwnd); + UpdateWindow(wgs->term_hwnd); - gui_terminal_ready(wgs.term_hwnd, &wgs.seat, backend); + gui_terminal_ready(wgs->term_hwnd, &wgs->seat, wgs->backend); while (1) { int n; @@ -848,7 +786,7 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) } else { timeout = INFINITE; /* The messages seem unreliable; especially if we're being tricky */ - term_set_focus(term, GetForegroundWindow() == wgs.term_hwnd); + term_set_focus(wgs->term, GetForegroundWindow() == wgs->term_hwnd); } HandleWaitList *hwl = get_handle_wait_list(); @@ -899,6 +837,16 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) return msg.wParam; /* ... but optimiser doesn't know */ } +static void wgs_cleanup(WinGuiSeat *wgs) +{ + deinit_fonts(wgs); + sfree(wgs->logpal); + if (wgs->pal) + DeleteObject(wgs->pal); + wgs_unlink(wgs); + sfree(wgs); +} + char *handle_restrict_acl_cmdline_prefix(char *p) { /* @@ -1013,10 +961,11 @@ void cleanup_exit(int code) /* * Clean up. */ - deinit_fonts(); - sfree(logpal); - if (pal) - DeleteObject(pal); + while (wgslisthead.next != &wgslisthead) { + WinGuiSeat *wgs = container_of( + wgslisthead.next, WinGuiSeat, wgslistnode); + wgs_cleanup(wgs); + } sk_cleanup(); random_save_seed(); @@ -1031,20 +980,21 @@ void cleanup_exit(int code) /* * Refresh the saved-session submenu from `sesslist'. */ -static void update_savedsess_menu(void) +static void update_savedsess_menu(WinGuiSeat *wgs) { int i; - while (DeleteMenu(savedsess_menu, 0, MF_BYPOSITION)) ; + while (DeleteMenu(wgs->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, + AppendMenu(wgs->savedsess_menu, MF_ENABLED, IDM_SAVED_MIN + (i-1)*MENU_SAVED_STEP, sesslist.sessions[i]); if (sesslist.nsessions <= 1) - AppendMenu(savedsess_menu, MF_GRAYED, IDM_SAVED_MIN, "(No sessions)"); + AppendMenu(wgs->savedsess_menu, MF_GRAYED, IDM_SAVED_MIN, + "(No sessions)"); } /* @@ -1052,15 +1002,16 @@ static void update_savedsess_menu(void) */ static void win_seat_update_specials_menu(Seat *seat) { + WinGuiSeat *wgs = container_of(seat, WinGuiSeat, seat); HMENU new_menu; int i, j; - if (backend) - specials = backend_get_specials(backend); + if (wgs->backend) + wgs->specials = backend_get_specials(wgs->backend); else - specials = NULL; + wgs->specials = NULL; - if (specials) { + if (wgs->specials) { /* We can't use Windows to provide a stack for submenus, so * here's a lame "stack" that will do for now. */ HMENU saved_menu = NULL; @@ -1068,7 +1019,7 @@ static void win_seat_update_specials_menu(Seat *seat) new_menu = CreatePopupMenu(); for (i = 0; nesting > 0; i++) { assert(IDM_SPECIAL_MIN + 0x10 * i < IDM_SPECIAL_MAX); - switch (specials[i].code) { + switch (wgs->specials[i].code) { case SS_SEP: AppendMenu(new_menu, MF_SEPARATOR, 0, 0); break; @@ -1078,7 +1029,7 @@ static void win_seat_update_specials_menu(Seat *seat) saved_menu = new_menu; /* XXX lame stacking */ new_menu = CreatePopupMenu(); AppendMenu(saved_menu, MF_POPUP | MF_ENABLED, - (UINT_PTR) new_menu, specials[i].name); + (UINT_PTR) new_menu, wgs->specials[i].name); break; case SS_EXITMENU: nesting--; @@ -1089,43 +1040,43 @@ static void win_seat_update_specials_menu(Seat *seat) break; default: AppendMenu(new_menu, MF_ENABLED, IDM_SPECIAL_MIN + 0x10 * i, - specials[i].name); + wgs->specials[i].name); break; } } /* Squirrel the highest special. */ - n_specials = i - 1; + wgs->n_specials = i - 1; } else { new_menu = NULL; - n_specials = 0; + wgs->n_specials = 0; } - for (j = 0; j < lenof(popup_menus); j++) { - if (specials_menu) { + for (j = 0; j < lenof(wgs->popup_menus); j++) { + if (wgs->specials_menu) { /* XXX does this free up all submenus? */ - DeleteMenu(popup_menus[j].menu, (UINT_PTR)specials_menu, + DeleteMenu(wgs->popup_menus[j].menu, (UINT_PTR)wgs->specials_menu, MF_BYCOMMAND); - DeleteMenu(popup_menus[j].menu, IDM_SPECIALSEP, MF_BYCOMMAND); + DeleteMenu(wgs->popup_menus[j].menu, IDM_SPECIALSEP, MF_BYCOMMAND); } if (new_menu) { - InsertMenu(popup_menus[j].menu, IDM_SHOWLOG, + InsertMenu(wgs->popup_menus[j].menu, IDM_SHOWLOG, MF_BYCOMMAND | MF_POPUP | MF_ENABLED, (UINT_PTR) new_menu, "S&pecial Command"); - InsertMenu(popup_menus[j].menu, IDM_SHOWLOG, + InsertMenu(wgs->popup_menus[j].menu, IDM_SHOWLOG, MF_BYCOMMAND | MF_SEPARATOR, IDM_SPECIALSEP, 0); } } - specials_menu = new_menu; + wgs->specials_menu = new_menu; } -static void update_mouse_pointer(void) +static void update_mouse_pointer(WinGuiSeat *wgs) { LPTSTR curstype = NULL; bool force_visible = false; static bool forced_visible = false; - switch (busy_status) { + switch (wgs->busy_status) { case BUSY_NOT: - if (pointer_indicates_raw_mouse) + if (wgs->pointer_indicates_raw_mouse) curstype = IDC_ARROW; else curstype = IDC_IBEAM; @@ -1143,7 +1094,7 @@ static void update_mouse_pointer(void) } { HCURSOR cursor = LoadCursor(NULL, curstype); - SetClassLongPtr(wgs.term_hwnd, GCLP_HCURSOR, (LONG_PTR)cursor); + SetClassLongPtr(wgs->term_hwnd, GCLP_HCURSOR, (LONG_PTR)cursor); SetCursor(cursor); /* force redraw of cursor at current posn */ } if (force_visible != forced_visible) { @@ -1158,19 +1109,22 @@ static void update_mouse_pointer(void) static void win_seat_set_busy_status(Seat *seat, BusyStatus status) { - busy_status = status; - update_mouse_pointer(); + WinGuiSeat *wgs = container_of(seat, WinGuiSeat, seat); + wgs->busy_status = status; + update_mouse_pointer(wgs); } static void wintw_set_raw_mouse_mode(TermWin *tw, bool activate) { - send_raw_mouse = activate; + WinGuiSeat *wgs = container_of(tw, WinGuiSeat, termwin); + wgs->send_raw_mouse = activate; } static void wintw_set_raw_mouse_mode_pointer(TermWin *tw, bool activate) { - pointer_indicates_raw_mouse = activate; - update_mouse_pointer(); + WinGuiSeat *wgs = container_of(tw, WinGuiSeat, termwin); + wgs->pointer_indicates_raw_mouse = activate; + update_mouse_pointer(wgs); } /* @@ -1178,15 +1132,16 @@ static void wintw_set_raw_mouse_mode_pointer(TermWin *tw, bool activate) */ static void win_seat_connection_fatal(Seat *seat, const char *msg) { + WinGuiSeat *wgs = container_of(seat, WinGuiSeat, seat); char *title = dupprintf("%s Fatal Error", appname); - show_mouseptr(true); - MessageBox(wgs.term_hwnd, msg, title, MB_ICONERROR | MB_OK); + show_mouseptr(wgs, true); + MessageBox(wgs->term_hwnd, msg, title, MB_ICONERROR | MB_OK); sfree(title); - if (conf_get_int(conf, CONF_close_on_exit) == FORCE_ON) + if (conf_get_int(wgs->conf, CONF_close_on_exit) == FORCE_ON) PostQuitMessage(1); else { - queue_toplevel_callback(close_session, NULL); + queue_toplevel_callback(close_session, wgs); } } @@ -1195,12 +1150,23 @@ static void win_seat_connection_fatal(Seat *seat, const char *msg) */ static void win_seat_nonfatal(Seat *seat, const char *msg) { + WinGuiSeat *wgs = container_of(seat, WinGuiSeat, seat); char *title = dupprintf("%s Error", appname); - show_mouseptr(true); - MessageBox(wgs.term_hwnd, msg, title, MB_ICONERROR | MB_OK); + show_mouseptr(wgs, true); + MessageBox(wgs->term_hwnd, msg, title, MB_ICONERROR | MB_OK); sfree(title); } +static HWND find_window_for_msgbox(void) +{ + if (wgslisthead.next != &wgslisthead) { + WinGuiSeat *wgs = container_of( + wgslisthead.next, WinGuiSeat, wgslistnode); + return wgs->term_hwnd; + } + return NULL; +} + /* * Report an error at the command-line parsing stage. */ @@ -1213,7 +1179,7 @@ void cmdline_error(const char *fmt, ...) message = dupvprintf(fmt, ap); va_end(ap); title = dupprintf("%s Command Line Error", appname); - MessageBox(wgs.term_hwnd, message, title, MB_ICONERROR | MB_OK); + MessageBox(find_window_for_msgbox(), message, title, MB_ICONERROR | MB_OK); sfree(message); sfree(title); exit(1); @@ -1230,7 +1196,8 @@ static inline rgb rgb_from_colorref(COLORREF cr) static void wintw_palette_get_overrides(TermWin *tw, Terminal *term) { - if (conf_get_bool(conf, CONF_system_colour)) { + WinGuiSeat *wgs = container_of(tw, WinGuiSeat, termwin); + if (conf_get_bool(wgs->conf, CONF_system_colour)) { rgb rgb; rgb = rgb_from_colorref(GetSysColor(COLOR_WINDOWTEXT)); @@ -1376,26 +1343,26 @@ static int get_font_width(HDC hdc, const TEXTMETRIC *tm) return ret; } -static void init_dpi_info(void) +static void init_dpi_info(WinGuiSeat *wgs) { - if (dpi_info.cur_dpi.x == 0 || dpi_info.cur_dpi.y == 0) { + if (wgs->dpi_info.cur_dpi.x == 0 || wgs->dpi_info.cur_dpi.y == 0) { if (p_GetDpiForMonitor && p_MonitorFromWindow) { UINT dpiX, dpiY; HMONITOR currentMonitor = p_MonitorFromWindow( - wgs.term_hwnd, MONITOR_DEFAULTTOPRIMARY); + wgs->term_hwnd, MONITOR_DEFAULTTOPRIMARY); if (p_GetDpiForMonitor(currentMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY) == S_OK) { - dpi_info.cur_dpi.x = (int)dpiX; - dpi_info.cur_dpi.y = (int)dpiY; + wgs->dpi_info.cur_dpi.x = (int)dpiX; + wgs->dpi_info.cur_dpi.y = (int)dpiY; } } /* Fall back to system DPI */ - if (dpi_info.cur_dpi.x == 0 || dpi_info.cur_dpi.y == 0) { - HDC hdc = GetDC(wgs.term_hwnd); - dpi_info.cur_dpi.x = GetDeviceCaps(hdc, LOGPIXELSX); - dpi_info.cur_dpi.y = GetDeviceCaps(hdc, LOGPIXELSY); - ReleaseDC(wgs.term_hwnd, hdc); + if (wgs->dpi_info.cur_dpi.x == 0 || wgs->dpi_info.cur_dpi.y == 0) { + HDC hdc = GetDC(wgs->term_hwnd); + wgs->dpi_info.cur_dpi.x = GetDeviceCaps(hdc, LOGPIXELSX); + wgs->dpi_info.cur_dpi.y = GetDeviceCaps(hdc, LOGPIXELSY); + ReleaseDC(wgs->term_hwnd, hdc); } } } @@ -1419,7 +1386,7 @@ static void init_dpi_info(void) * * - find a trust sigil icon that will look OK with the chosen font. */ -static void init_fonts(int pick_width, int pick_height) +static void init_fonts(WinGuiSeat *wgs, int pick_width, int pick_height) { TEXTMETRIC tm; OUTLINETEXTMETRIC otm; @@ -1432,14 +1399,15 @@ static void init_fonts(int pick_width, int pick_height) int fw_dontcare, fw_bold; for (i = 0; i < FONT_MAXNO; i++) - fonts[i] = NULL; + wgs->fonts[i] = NULL; - bold_font_mode = conf_get_int(conf, CONF_bold_style) & 1 ? + wgs->bold_font_mode = conf_get_int(wgs->conf, CONF_bold_style) & 1 ? BOLD_FONT : BOLD_NONE; - bold_colours = conf_get_int(conf, CONF_bold_style) & 2 ? true : false; - und_mode = UND_FONT; + wgs->bold_colours = conf_get_int(wgs->conf, CONF_bold_style) & 2 ? + true : false; + wgs->und_mode = UND_FONT; - font = conf_get_fontspec(conf, CONF_font); + font = conf_get_fontspec(wgs->conf, CONF_font); if (font->isbold) { fw_dontcare = FW_BOLD; fw_bold = FW_HEAVY; @@ -1448,7 +1416,7 @@ static void init_fonts(int pick_width, int pick_height) fw_bold = FW_BOLD; } - hdc = GetDC(wgs.term_hwnd); + hdc = GetDC(wgs->term_hwnd); if (pick_height) font_height = pick_height; @@ -1456,28 +1424,28 @@ static void init_fonts(int pick_width, int pick_height) font_height = font->height; if (font_height > 0) { font_height = - -MulDiv(font_height, dpi_info.cur_dpi.y, 72); + -MulDiv(font_height, wgs->dpi_info.cur_dpi.y, 72); } } font_width = pick_width; - quality = conf_get_int(conf, CONF_font_quality); + quality = conf_get_int(wgs->conf, CONF_font_quality); #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, FONT_QUALITY(quality), \ - FIXED_PITCH | FF_DONTCARE, font->name) + wgs->fonts[i] = CreateFont (font_height, font_width, 0, 0, w, false, u, \ + false, c, OUT_DEFAULT_PRECIS, \ + CLIP_DEFAULT_PRECIS, FONT_QUALITY(quality), \ + FIXED_PITCH | FF_DONTCARE, font->name) f(FONT_NORMAL, font->charset, fw_dontcare, false); - SelectObject(hdc, fonts[FONT_NORMAL]); + SelectObject(hdc, wgs->fonts[FONT_NORMAL]); GetTextMetrics(hdc, &tm); if (GetOutlineTextMetrics(hdc, sizeof(otm), &otm)) - font_strikethrough_y = tm.tmAscent - otm.otmsStrikeoutPosition; + wgs->font_strikethrough_y = tm.tmAscent - otm.otmsStrikeoutPosition; else - font_strikethrough_y = tm.tmAscent - (tm.tmAscent * 3 / 8); + wgs->font_strikethrough_y = tm.tmAscent - (tm.tmAscent * 3 / 8); - GetObject(fonts[FONT_NORMAL], sizeof(LOGFONT), &lfont); + GetObject(wgs->fonts[FONT_NORMAL], sizeof(LOGFONT), &wgs->lfont); /* Note that the TMPF_FIXED_PITCH bit is defined upside down :-( */ if (!(tm.tmPitchAndFamily & TMPF_FIXED_PITCH)) { @@ -1504,15 +1472,15 @@ static void init_fonts(int pick_width, int pick_height) /* !!! Yes the next line is right */ if (cset == OEM_CHARSET) - ucsdata.font_codepage = GetOEMCP(); + wgs->ucsdata.font_codepage = GetOEMCP(); else if (TranslateCharsetInfo ((DWORD *)(ULONG_PTR)cset, &info, TCI_SRCCHARSET)) - ucsdata.font_codepage = info.ciACP; + wgs->ucsdata.font_codepage = info.ciACP; else - ucsdata.font_codepage = -1; + wgs->ucsdata.font_codepage = -1; - GetCPInfo(ucsdata.font_codepage, &cpinfo); - ucsdata.dbcs_screenfont = (cpinfo.MaxCharSize > 1); + GetCPInfo(wgs->ucsdata.font_codepage, &cpinfo); + wgs->ucsdata.dbcs_screenfont = (cpinfo.MaxCharSize > 1); } f(FONT_UNDERLINE, font->charset, fw_dontcare, true); @@ -1544,7 +1512,7 @@ static void init_fonts(int pick_width, int pick_height) und_dc = CreateCompatibleDC(hdc); und_bm = CreateCompatibleBitmap(hdc, font_width, font_height); und_oldbm = SelectObject(und_dc, und_bm); - SelectObject(und_dc, fonts[FONT_UNDERLINE]); + SelectObject(und_dc, wgs->fonts[FONT_UNDERLINE]); SetTextAlign(und_dc, TA_TOP | TA_LEFT | TA_NOUPDATECP); SetTextColor(und_dc, RGB(255, 255, 255)); SetBkColor(und_dc, RGB(0, 0, 0)); @@ -1560,24 +1528,24 @@ static void init_fonts(int pick_width, int pick_height) DeleteObject(und_bm); DeleteDC(und_dc); if (!gotit) { - und_mode = UND_LINE; - DeleteObject(fonts[FONT_UNDERLINE]); - fonts[FONT_UNDERLINE] = 0; + wgs->und_mode = UND_LINE; + DeleteObject(wgs->fonts[FONT_UNDERLINE]); + wgs->fonts[FONT_UNDERLINE] = 0; } } - if (bold_font_mode == BOLD_FONT) { + if (wgs->bold_font_mode == BOLD_FONT) { f(FONT_BOLD, font->charset, fw_bold, false); } #undef f - descent = tm.tmAscent + 1; - if (descent >= font_height) - descent = font_height - 1; + wgs->descent = tm.tmAscent + 1; + if (wgs->descent >= font_height) + wgs->descent = font_height - 1; for (i = 0; i < 3; i++) { - if (fonts[i]) { - if (SelectObject(hdc, fonts[i]) && GetTextMetrics(hdc, &tm)) + if (wgs->fonts[i]) { + if (SelectObject(hdc, wgs->fonts[i]) && GetTextMetrics(hdc, &tm)) fontsize[i] = get_font_width(hdc, &tm) + 256 * tm.tmHeight; else fontsize[i] = -i; @@ -1585,7 +1553,7 @@ static void init_fonts(int pick_width, int pick_height) fontsize[i] = -i; } - ReleaseDC(wgs.term_hwnd, hdc); + ReleaseDC(wgs->term_hwnd, hdc); if (trust_icon != INVALID_HANDLE_VALUE) { DestroyIcon(trust_icon); @@ -1595,25 +1563,25 @@ static void init_fonts(int pick_width, int pick_height) LR_DEFAULTCOLOR); if (fontsize[FONT_UNDERLINE] != fontsize[FONT_NORMAL]) { - und_mode = UND_LINE; - DeleteObject(fonts[FONT_UNDERLINE]); - fonts[FONT_UNDERLINE] = 0; + wgs->und_mode = UND_LINE; + DeleteObject(wgs->fonts[FONT_UNDERLINE]); + wgs->fonts[FONT_UNDERLINE] = 0; } - if (bold_font_mode == BOLD_FONT && + if (wgs->bold_font_mode == BOLD_FONT && fontsize[FONT_BOLD] != fontsize[FONT_NORMAL]) { - bold_font_mode = BOLD_SHADOW; - DeleteObject(fonts[FONT_BOLD]); - fonts[FONT_BOLD] = 0; + wgs->bold_font_mode = BOLD_SHADOW; + DeleteObject(wgs->fonts[FONT_BOLD]); + wgs->fonts[FONT_BOLD] = 0; } - fontflag[0] = true; - fontflag[1] = true; - fontflag[2] = true; + wgs->fontflag[0] = true; + wgs->fontflag[1] = true; + wgs->fontflag[2] = true; - init_ucs(conf, &ucsdata); + init_ucs(wgs->conf, &wgs->ucsdata); } -static void another_font(int fontno) +static void another_font(WinGuiSeat *wgs, int fontno) { int basefont; int fw_dontcare, fw_bold, quality; @@ -1622,14 +1590,14 @@ static void another_font(int fontno) char *s; FontSpec *font; - if (fontno < 0 || fontno >= FONT_MAXNO || fontflag[fontno]) + if (fontno < 0 || fontno >= FONT_MAXNO || wgs->fontflag[fontno]) return; basefont = (fontno & ~(FONT_BOLDUND)); - if (basefont != fontno && !fontflag[basefont]) - another_font(basefont); + if (basefont != fontno && !wgs->fontflag[basefont]) + another_font(wgs, basefont); - font = conf_get_fontspec(conf, CONF_font); + font = conf_get_fontspec(wgs->conf, CONF_font); if (font->isbold) { fw_dontcare = FW_BOLD; @@ -1656,25 +1624,25 @@ static void another_font(int fontno) if (fontno & FONT_UNDERLINE) u = true; - quality = conf_get_int(conf, CONF_font_quality); + quality = conf_get_int(wgs->conf, CONF_font_quality); - fonts[fontno] = + wgs->fonts[fontno] = CreateFont(font_height * (1 + !!(fontno & FONT_HIGH)), x, 0, 0, w, false, u, false, c, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, FONT_QUALITY(quality), DEFAULT_PITCH | FF_DONTCARE, s); - fontflag[fontno] = true; + wgs->fontflag[fontno] = true; } -static void deinit_fonts(void) +static void deinit_fonts(WinGuiSeat *wgs) { int i; for (i = 0; i < FONT_MAXNO; i++) { - if (fonts[i]) - DeleteObject(fonts[i]); - fonts[i] = 0; - fontflag[i] = false; + if (wgs->fonts[i]) + DeleteObject(wgs->fonts[i]); + wgs->fonts[i] = 0; + wgs->fontflag[i] = false; } if (trust_icon != INVALID_HANDLE_VALUE) { @@ -1685,25 +1653,26 @@ static void deinit_fonts(void) static void wintw_request_resize(TermWin *tw, int w, int h) { + WinGuiSeat *wgs = container_of(tw, WinGuiSeat, termwin); const struct BackendVtable *vt; int width, height; /* If the window is maximized suppress resizing attempts */ - if (IsZoomed(wgs.term_hwnd)) { - if (conf_get_int(conf, CONF_resize_action) == RESIZE_TERM) + if (IsZoomed(wgs->term_hwnd)) { + if (conf_get_int(wgs->conf, CONF_resize_action) == RESIZE_TERM) return; } - if (conf_get_int(conf, CONF_resize_action) == RESIZE_DISABLED) return; + if (conf_get_int(wgs->conf, CONF_resize_action) == RESIZE_DISABLED) return; vt = backend_vt_from_proto(be_default_protocol); if (vt && vt->flags & BACKEND_RESIZE_FORBIDDEN) return; - if (h == term->rows && w == term->cols) return; + if (h == wgs->term->rows && w == wgs->term->cols) return; /* Sanity checks ... */ { RECT ss; - if (get_fullscreen_rect(&ss)) { + if (get_fullscreen_rect(wgs, &ss)) { /* Make sure the values aren't too big */ width = (ss.right - ss.left - extra_width) / 4; height = (ss.bottom - ss.top - extra_height) / 6; @@ -1717,12 +1686,12 @@ static void wintw_request_resize(TermWin *tw, int w, int h) } } - if (conf_get_int(conf, CONF_resize_action) != RESIZE_FONT && - !IsZoomed(wgs.term_hwnd)) { + if (conf_get_int(wgs->conf, CONF_resize_action) != RESIZE_FONT && + !IsZoomed(wgs->term_hwnd)) { width = extra_width + font_width * w; height = extra_height + font_height * h; - SetWindowPos(wgs.term_hwnd, NULL, 0, 0, width, height, + SetWindowPos(wgs->term_hwnd, NULL, 0, 0, width, height, SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_NOMOVE | SWP_NOZORDER); } else { @@ -1731,34 +1700,35 @@ static void wintw_request_resize(TermWin *tw, int w, int h) * terminal the new size immediately, so that reset_window * will know what to do. */ - term_size(term, h, w, conf_get_int(conf, CONF_savelines)); - reset_window(0); + term_size(wgs->term, h, w, conf_get_int(wgs->conf, CONF_savelines)); + reset_window(wgs, 0); } - term_resize_request_completed(term); - InvalidateRect(wgs.term_hwnd, NULL, true); + term_resize_request_completed(wgs->term); + InvalidateRect(wgs->term_hwnd, NULL, true); } -static void recompute_window_offset(void) +static void recompute_window_offset(WinGuiSeat *wgs) { RECT cr; - GetClientRect(wgs.term_hwnd, &cr); + GetClientRect(wgs->term_hwnd, &cr); int win_width = cr.right - cr.left; int win_height = cr.bottom - cr.top; - int new_offset_width = (win_width-font_width*term->cols)/2; - int new_offset_height = (win_height-font_height*term->rows)/2; + int new_offset_width = (win_width-font_width*wgs->term->cols)/2; + int new_offset_height = (win_height-font_height*wgs->term->rows)/2; if (offset_width != new_offset_width || offset_height != new_offset_height) { offset_width = new_offset_width; offset_height = new_offset_height; - InvalidateRect(wgs.term_hwnd, NULL, true); + InvalidateRect(wgs->term_hwnd, NULL, true); } } -static void reset_window(int reinit) { +static void reset_window(WinGuiSeat *wgs, int reinit) +{ /* * This function decides how to resize or redraw when the * user changes something. @@ -1774,14 +1744,14 @@ static void reset_window(int reinit) { #endif /* Current window sizes ... */ - GetWindowRect(wgs.term_hwnd, &wr); - GetClientRect(wgs.term_hwnd, &cr); + GetWindowRect(wgs->term_hwnd, &wr); + GetClientRect(wgs->term_hwnd, &cr); win_width = cr.right - cr.left; win_height = cr.bottom - cr.top; - resize_action = conf_get_int(conf, CONF_resize_action); - window_border = conf_get_int(conf, CONF_window_border); + resize_action = conf_get_int(wgs->conf, CONF_resize_action); + window_border = conf_get_int(wgs->conf, CONF_window_border); if (resize_action == RESIZE_DISABLED) reinit = 2; @@ -1791,8 +1761,8 @@ static void reset_window(int reinit) { #ifdef RDB_DEBUG_PATCH debug("reset_window() -- Forced deinit\n"); #endif - deinit_fonts(); - init_fonts(0,0); + deinit_fonts(wgs); + init_fonts(wgs, 0, 0); } /* Oh, looks like we're minimised */ @@ -1801,13 +1771,13 @@ static void reset_window(int reinit) { /* Is the window out of position ? */ if (!reinit) { - recompute_window_offset(); + recompute_window_offset(wgs); #ifdef RDB_DEBUG_PATCH debug("reset_window() -> Reposition terminal\n"); #endif } - if (IsZoomed(wgs.term_hwnd)) { + if (IsZoomed(wgs->term_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. */ @@ -1816,29 +1786,30 @@ static void reset_window(int reinit) { extra_height = wr.bottom - wr.top - cr.bottom + cr.top; if (resize_action != RESIZE_TERM) { - if (font_width != win_width/term->cols || - font_height != win_height/term->rows) { - deinit_fonts(); - init_fonts(win_width/term->cols, win_height/term->rows); - offset_width = (win_width-font_width*term->cols)/2; - offset_height = (win_height-font_height*term->rows)/2; - InvalidateRect(wgs.term_hwnd, NULL, true); + if (font_width != win_width/wgs->term->cols || + font_height != win_height/wgs->term->rows) { + deinit_fonts(wgs); + init_fonts(wgs, win_width/wgs->term->cols, + win_height/wgs->term->rows); + offset_width = (win_width-font_width*wgs->term->cols)/2; + offset_height = (win_height-font_height*wgs->term->rows)/2; + InvalidateRect(wgs->term_hwnd, NULL, true); #ifdef RDB_DEBUG_PATCH debug("reset_window() -> Z font resize to (%d, %d)\n", font_width, font_height); #endif } } else { - if (font_width * term->cols != win_width || - font_height * term->rows != win_height) { + if (font_width * wgs->term->cols != win_width || + font_height * wgs->term->rows != win_height) { /* Our only choice at this point is to change the * size of the terminal; Oh well. */ - term_size(term, win_height/font_height, win_width/font_width, - conf_get_int(conf, CONF_savelines)); - offset_width = (win_width-font_width*term->cols)/2; - offset_height = (win_height-font_height*term->rows)/2; - InvalidateRect(wgs.term_hwnd, NULL, true); + term_size(wgs->term, win_height/font_height, win_width/font_width, + conf_get_int(wgs->conf, CONF_savelines)); + offset_width = (win_width-font_width*wgs->term->cols)/2; + offset_height = (win_height-font_height*wgs->term->rows)/2; + InvalidateRect(wgs->term_hwnd, NULL, true); #ifdef RDB_DEBUG_PATCH debug("reset_window() -> Zoomed term_size\n"); #endif @@ -1851,28 +1822,31 @@ static void reset_window(int reinit) { if (reinit == 3 && p_GetSystemMetricsForDpi && p_AdjustWindowRectExForDpi) { RECT rect; rect.left = rect.top = 0; - rect.right = (font_width * term->cols); - if (conf_get_bool(conf, CONF_scrollbar)) + rect.right = (font_width * wgs->term->cols); + if (conf_get_bool(wgs->conf, CONF_scrollbar)) rect.right += p_GetSystemMetricsForDpi(SM_CXVSCROLL, - dpi_info.cur_dpi.x); - rect.bottom = (font_height * term->rows); + wgs->dpi_info.cur_dpi.x); + rect.bottom = (font_height * wgs->term->rows); p_AdjustWindowRectExForDpi( - &rect, GetWindowLongPtr(wgs.term_hwnd, GWL_STYLE), - FALSE, GetWindowLongPtr(wgs.term_hwnd, GWL_EXSTYLE), - dpi_info.cur_dpi.x); + &rect, GetWindowLongPtr(wgs->term_hwnd, GWL_STYLE), + FALSE, GetWindowLongPtr(wgs->term_hwnd, GWL_EXSTYLE), + wgs->dpi_info.cur_dpi.x); rect.right += (window_border * 2); rect.bottom += (window_border * 2); - OffsetRect(&dpi_info.new_wnd_rect, - ((dpi_info.new_wnd_rect.right - dpi_info.new_wnd_rect.left) - + OffsetRect(&wgs->dpi_info.new_wnd_rect, + ((wgs->dpi_info.new_wnd_rect.right - + wgs->dpi_info.new_wnd_rect.left) - (rect.right - rect.left)) / 2, - ((dpi_info.new_wnd_rect.bottom - dpi_info.new_wnd_rect.top) - + ((wgs->dpi_info.new_wnd_rect.bottom - + wgs->dpi_info.new_wnd_rect.top) - (rect.bottom - rect.top)) / 2); - SetWindowPos(wgs.term_hwnd, NULL, - dpi_info.new_wnd_rect.left, dpi_info.new_wnd_rect.top, + SetWindowPos(wgs->term_hwnd, NULL, + wgs->dpi_info.new_wnd_rect.left, + wgs->dpi_info.new_wnd_rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER); - InvalidateRect(wgs.term_hwnd, NULL, true); + InvalidateRect(wgs->term_hwnd, NULL, true); return; } @@ -1888,20 +1862,20 @@ static void reset_window(int reinit) { 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*term->cols + offset_width*2 || - win_height != font_height*term->rows + offset_height*2) { + if (win_width != font_width*wgs->term->cols + offset_width*2 || + win_height != font_height*wgs->term->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(wgs.term_hwnd, NULL, 0, 0, - font_width*term->cols + extra_width, - font_height*term->rows + extra_height, + SetWindowPos(wgs->term_hwnd, NULL, 0, 0, + font_width*wgs->term->cols + extra_width, + font_height*wgs->term->rows + extra_height, SWP_NOMOVE | SWP_NOZORDER); } - InvalidateRect(wgs.term_hwnd, NULL, true); + InvalidateRect(wgs->term_hwnd, NULL, true); return; } @@ -1916,38 +1890,38 @@ static void reset_window(int reinit) { 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*term->cols + offset_width*2 || - win_height != font_height*term->rows + offset_height*2) { + if (win_width != font_width*wgs->term->cols + offset_width*2 || + win_height != font_height*wgs->term->rows + offset_height*2) { static RECT ss; int width, height; - get_fullscreen_rect(&ss); + get_fullscreen_rect(wgs, &ss); width = (ss.right - ss.left - extra_width) / font_width; height = (ss.bottom - ss.top - extra_height) / font_height; /* Grrr too big */ - if ( term->rows > height || term->cols > width ) { + if ( wgs->term->rows > height || wgs->term->cols > width ) { if (resize_action == RESIZE_EITHER) { /* Make the font the biggest we can */ - if (term->cols > width) + if (wgs->term->cols > width) font_width = (ss.right - ss.left - extra_width) - / term->cols; - if (term->rows > height) + / wgs->term->cols; + if (wgs->term->rows > height) font_height = (ss.bottom - ss.top - extra_height) - / term->rows; + / wgs->term->rows; - deinit_fonts(); - init_fonts(font_width, font_height); + deinit_fonts(wgs); + init_fonts(wgs, font_width, font_height); width = (ss.right - ss.left - extra_width) / font_width; height = (ss.bottom - ss.top - extra_height) / font_height; } else { - if ( height > term->rows ) height = term->rows; - if ( width > term->cols ) width = term->cols; - term_size(term, height, width, - conf_get_int(conf, CONF_savelines)); + if ( height > wgs->term->rows ) height = wgs->term->rows; + if ( width > wgs->term->cols ) width = wgs->term->cols; + term_size(wgs->term, height, width, + conf_get_int(wgs->conf, CONF_savelines)); #ifdef RDB_DEBUG_PATCH debug("reset_window() -> term resize to (%d,%d)\n", height, width); @@ -1955,12 +1929,12 @@ static void reset_window(int reinit) { } } - SetWindowPos(wgs.term_hwnd, NULL, 0, 0, - font_width*term->cols + extra_width, - font_height*term->rows + extra_height, + SetWindowPos(wgs->term_hwnd, NULL, 0, 0, + font_width*wgs->term->cols + extra_width, + font_height*wgs->term->rows + extra_height, SWP_NOMOVE | SWP_NOZORDER); - InvalidateRect(wgs.term_hwnd, NULL, true); + InvalidateRect(wgs->term_hwnd, NULL, true); #ifdef RDB_DEBUG_PATCH debug("reset_window() -> window resize to (%d,%d)\n", font_width*term->cols + extra_width, @@ -1972,19 +1946,19 @@ static void reset_window(int reinit) { /* We're allowed to or must change the font but do we want to ? */ - if (font_width != (win_width-window_border*2)/term->cols || - font_height != (win_height-window_border*2)/term->rows) { + if (font_width != (win_width-window_border*2)/wgs->term->cols || + font_height != (win_height-window_border*2)/wgs->term->rows) { - deinit_fonts(); - init_fonts((win_width-window_border*2)/term->cols, - (win_height-window_border*2)/term->rows); - offset_width = (win_width-font_width*term->cols)/2; - offset_height = (win_height-font_height*term->rows)/2; + deinit_fonts(wgs); + init_fonts(wgs, (win_width-window_border*2)/wgs->term->cols, + (win_height-window_border*2)/wgs->term->rows); + offset_width = (win_width-font_width*wgs->term->cols)/2; + offset_height = (win_height-font_height*wgs->term->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(wgs.term_hwnd, NULL, true); + InvalidateRect(wgs->term_hwnd, NULL, true); #ifdef RDB_DEBUG_PATCH debug("reset_window() -> font resize to (%d,%d)\n", font_width, font_height); @@ -1992,67 +1966,75 @@ static void reset_window(int reinit) { } } -static void set_input_locale(HKL kl) +static void set_input_locale(WinGuiSeat *wgs, HKL kl) { char lbuf[20]; GetLocaleInfo(LOWORD(kl), LOCALE_IDEFAULTANSICODEPAGE, lbuf, sizeof(lbuf)); - kbd_codepage = atoi(lbuf); + wgs->kbd_codepage = atoi(lbuf); } -static void click(Mouse_Button b, int x, int y, +static void click(WinGuiSeat *wgs, Mouse_Button b, int x, int y, bool shift, bool ctrl, bool alt) { int thistime = GetMessageTime(); - if (send_raw_mouse && - !(shift && conf_get_bool(conf, CONF_mouse_override))) { - lastbtn = MBT_NOTHING; - term_mouse(term, b, translate_button(b), MA_CLICK, + if (wgs->send_raw_mouse && + !(shift && conf_get_bool(wgs->conf, CONF_mouse_override))) { + wgs->lastbtn = MBT_NOTHING; + term_mouse(wgs->term, b, translate_button(wgs, b), MA_CLICK, x, y, shift, ctrl, alt); 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); + if (wgs->lastbtn == b && thistime - wgs->lasttime < wgs->dbltime) { + wgs->lastact = (wgs->lastact == MA_CLICK ? MA_2CLK : + wgs->lastact == MA_2CLK ? MA_3CLK : + wgs->lastact == MA_3CLK ? MA_CLICK : MA_NOTHING); } else { - lastbtn = b; - lastact = MA_CLICK; + wgs->lastbtn = b; + wgs->lastact = MA_CLICK; } - if (lastact != MA_NOTHING) - term_mouse(term, b, translate_button(b), lastact, + if (wgs->lastact != MA_NOTHING) + term_mouse(wgs->term, b, translate_button(wgs, b), wgs->lastact, x, y, shift, ctrl, alt); - lasttime = thistime; + wgs->lasttime = thistime; } /* * Translate a raw mouse button designation (LEFT, MIDDLE, RIGHT) * into a cooked one (SELECT, EXTEND, PASTE). */ -static Mouse_Button translate_button(Mouse_Button button) +static Mouse_Button translate_button(WinGuiSeat *wgs, Mouse_Button button) { if (button == MBT_LEFT) return MBT_SELECT; if (button == MBT_MIDDLE) - return conf_get_int(conf, CONF_mouse_is_xterm) == 1 ? + return conf_get_int(wgs->conf, CONF_mouse_is_xterm) == 1 ? MBT_PASTE : MBT_EXTEND; if (button == MBT_RIGHT) - return conf_get_int(conf, CONF_mouse_is_xterm) == 1 ? + return conf_get_int(wgs->conf, CONF_mouse_is_xterm) == 1 ? MBT_EXTEND : MBT_PASTE; return 0; /* shouldn't happen */ } -static void show_mouseptr(bool show) +static void show_mouseptr(WinGuiSeat *wgs, bool show) { /* NB that the counter in ShowCursor() is also frobbed by * update_mouse_pointer() */ static bool cursor_visible = true; - if (!conf_get_bool(conf, CONF_hide_mouseptr)) - show = true; /* override if this feature disabled */ + if (wgs) { + if (!conf_get_bool(wgs->conf, CONF_hide_mouseptr)) + show = true; /* hiding mouse pointer disabled in Conf */ + } else { + /* + * You can pass wgs==NULL if you want to _show_ the pointer + * rather than hiding it, because that's never disallowed. + */ + assert(show); + } if (cursor_visible && !show) ShowCursor(false); else if (!cursor_visible && show) @@ -2073,15 +2055,14 @@ static bool is_alt_pressed(void) return false; } -static bool resizing; - static void exit_callback(void *vctx) { + WinGuiSeat *wgs = (WinGuiSeat *)vctx; int exitcode, close_on_exit; - if (!session_closed && - (exitcode = backend_exitcode(backend)) >= 0) { - close_on_exit = conf_get_int(conf, CONF_close_on_exit); + if (!wgs->session_closed && + (exitcode = backend_exitcode(wgs->backend)) >= 0) { + close_on_exit = conf_get_int(wgs->conf, CONF_close_on_exit); /* Abnormal exits will already have set session_closed and taken * appropriate action. */ if (close_on_exit == FORCE_ON || @@ -2089,13 +2070,13 @@ static void exit_callback(void *vctx) PostQuitMessage(0); } else { queue_toplevel_callback(close_session, NULL); - session_closed = true; + wgs->session_closed = true; /* exitcode == INT_MAX indicates that the connection was closed * by a fatal error, so an error box will be coming our way and * we should not generate this informational one. */ if (exitcode != INT_MAX) { - show_mouseptr(true); - MessageBox(wgs.term_hwnd, "Connection closed by remote host", + show_mouseptr(wgs, true); + MessageBox(wgs->term_hwnd, "Connection closed by remote host", appname, MB_OK | MB_ICONINFORMATION); } } @@ -2104,47 +2085,48 @@ static void exit_callback(void *vctx) static void win_seat_notify_remote_exit(Seat *seat) { - queue_toplevel_callback(exit_callback, NULL); + WinGuiSeat *wgs = container_of(seat, WinGuiSeat, seat); + queue_toplevel_callback(exit_callback, wgs); } -static void conf_cache_data(void) +static void conf_cache_data(WinGuiSeat *wgs) { /* Cache some items from conf to speed lookups in very hot code */ - cursor_type = conf_get_int(conf, CONF_cursor_type); - vtmode = conf_get_int(conf, CONF_vtmode); + wgs->cursor_type = conf_get_int(wgs->conf, CONF_cursor_type); + wgs->vtmode = conf_get_int(wgs->conf, CONF_vtmode); } static const int clips_system[] = { CLIP_SYSTEM }; -static HDC make_hdc(void) +static HDC make_hdc(WinGuiSeat *wgs) { HDC hdc; - if (!wgs.term_hwnd) + if (!wgs->term_hwnd) return NULL; - hdc = GetDC(wgs.term_hwnd); + hdc = GetDC(wgs->term_hwnd); if (!hdc) return NULL; - SelectPalette(hdc, pal, false); + SelectPalette(hdc, wgs->pal, false); return hdc; } -static void free_hdc(HDC hdc) +static void free_hdc(WinGuiSeat *wgs, HDC hdc) { - assert(wgs.term_hwnd); + assert(wgs->term_hwnd); SelectPalette(hdc, GetStockObject(DEFAULT_PALETTE), false); - ReleaseDC(wgs.term_hwnd, hdc); + ReleaseDC(wgs->term_hwnd, hdc); } static bool need_backend_resize = false; -static void wm_size_resize_term(LPARAM lParam, bool border) +static void wm_size_resize_term(WinGuiSeat *wgs, LPARAM lParam, bool border) { int width = LOWORD(lParam); int height = HIWORD(lParam); - int border_size = border ? conf_get_int(conf, CONF_window_border) : 0; + int border_size = border ? conf_get_int(wgs->conf, CONF_window_border) : 0; int w = (width - border_size*2) / font_width; int h = (height - border_size*2) / font_height; @@ -2152,7 +2134,7 @@ static void wm_size_resize_term(LPARAM lParam, bool border) if (w < 1) w = 1; if (h < 1) h = 1; - if (resizing) { + if (wgs->resizing) { /* * If we're in the middle of an interactive resize, we don't * call term_size. This means that, firstly, the user can drag @@ -2163,11 +2145,11 @@ static void wm_size_resize_term(LPARAM lParam, bool border) * numbers of resize events. */ need_backend_resize = true; - conf_set_int(conf, CONF_height, h); - conf_set_int(conf, CONF_width, w); + conf_set_int(wgs->conf, CONF_height, h); + conf_set_int(wgs->conf, CONF_width, w); } else { - term_size(term, h, w, - conf_get_int(conf, CONF_savelines)); + term_size(wgs->term, h, w, + conf_get_int(wgs->conf, CONF_savelines)); } } @@ -2181,21 +2163,23 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, static bool in_scrollbar_loop = false; static UINT last_mousemove = 0; int resize_action; + WinGuiSeat *wgs = (WinGuiSeat *)GetWindowLongPtr(hwnd, GWLP_USERDATA); switch (message) { case WM_CREATE: break; case WM_CLOSE: { char *title, *msg, *additional = NULL; - show_mouseptr(true); + show_mouseptr(wgs, true); title = dupprintf("%s Exit Confirmation", appname); - if (backend && backend->vt->close_warn_text) { - additional = backend->vt->close_warn_text(backend); + if (wgs->backend && wgs->backend->vt->close_warn_text) { + additional = wgs->backend->vt->close_warn_text(wgs->backend); } msg = dupprintf("Are you sure you want to close this session?%s%s", additional ? "\n" : "", additional ? additional : ""); - if (session_closed || !conf_get_bool(conf, CONF_warn_on_close) || + if (wgs->session_closed || + !conf_get_bool(wgs->conf, CONF_warn_on_close) || MessageBox(hwnd, msg, title, MB_ICONWARNING | MB_OKCANCEL | MB_DEFBUTTON1) == IDOK) @@ -2206,16 +2190,16 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, return 0; } case WM_DESTROY: - show_mouseptr(true); + show_mouseptr(wgs, true); PostQuitMessage(0); return 0; case WM_INITMENUPOPUP: - if ((HMENU)wParam == savedsess_menu) { + if ((HMENU)wParam == wgs->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(); + update_savedsess_menu(wgs); return 0; } break; @@ -2268,7 +2252,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, int size; serbuf = strbuf_new(); - conf_serialise(BinarySink_UPCAST(serbuf), conf); + conf_serialise(BinarySink_UPCAST(serbuf), wgs->conf); size = serbuf->len; sa.nLength = sizeof(sa); @@ -2325,10 +2309,10 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, break; } case IDM_RESTART: - if (!backend) { - lp_eventlog(&wgs.logpolicy, "----- Session restarted -----"); - term_pwron(term, false); - start_backend(); + if (!wgs->backend) { + lp_eventlog(&wgs->logpolicy, "----- Session restarted -----"); + term_pwron(wgs->term, false); + start_backend(wgs); } break; @@ -2337,30 +2321,31 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, int init_lvl = 1; bool reconfig_result; - if (reconfiguring) + if (wgs->reconfiguring) break; else - reconfiguring = true; + wgs->reconfiguring = true; - term_pre_reconfig(term, conf); - prev_conf = conf_copy(conf); + term_pre_reconfig(wgs->term, wgs->conf); + prev_conf = conf_copy(wgs->conf); reconfig_result = do_reconfig( - hwnd, conf, backend ? backend_cfg_info(backend) : 0); - reconfiguring = false; + hwnd, wgs->conf, + wgs->backend ? backend_cfg_info(wgs->backend) : 0); + wgs->reconfiguring = false; if (!reconfig_result) { conf_free(prev_conf); break; } - conf_cache_data(); + conf_cache_data(wgs); - resize_action = conf_get_int(conf, CONF_resize_action); + resize_action = conf_get_int(wgs->conf, CONF_resize_action); { /* Disable full-screen if resizing forbidden */ int i; - for (i = 0; i < lenof(popup_menus); i++) - EnableMenuItem(popup_menus[i].menu, IDM_FULLSCREEN, + for (i = 0; i < lenof(wgs->popup_menus); i++) + EnableMenuItem(wgs->popup_menus[i].menu, IDM_FULLSCREEN, MF_BYCOMMAND | (resize_action == RESIZE_DISABLED ? MF_GRAYED : MF_ENABLED)); @@ -2370,51 +2355,51 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, } /* Pass new config data to the logging module */ - log_reconfig(logctx, conf); + log_reconfig(wgs->logctx, wgs->conf); - sfree(logpal); + sfree(wgs->logpal); /* * Flush the line discipline's edit buffer in the * case where local editing has just been disabled. */ - if (ldisc) { - ldisc_configure(ldisc, conf); - ldisc_echoedit_update(ldisc); + if (wgs->ldisc) { + ldisc_configure(wgs->ldisc, wgs->conf); + ldisc_echoedit_update(wgs->ldisc); } - if (conf_get_bool(conf, CONF_system_colour) != + if (conf_get_bool(wgs->conf, CONF_system_colour) != conf_get_bool(prev_conf, CONF_system_colour)) - term_notify_palette_changed(term); + term_notify_palette_changed(wgs->term); /* Pass new config data to the terminal */ - term_reconfig(term, conf); - setup_clipboards(term, conf); + term_reconfig(wgs->term, wgs->conf); + setup_clipboards(wgs->term, wgs->conf); /* Reinitialise the colour palette, in case the terminal * just read new settings out of Conf */ - if (pal) - DeleteObject(pal); - logpal = NULL; - pal = NULL; - init_palette(); + if (wgs->pal) + DeleteObject(wgs->pal); + wgs->logpal = NULL; + wgs->pal = NULL; + init_palette(wgs); /* Pass new config data to the back end */ - if (backend) - backend_reconfig(backend, conf); + if (wgs->backend) + backend_reconfig(wgs->backend, wgs->conf); /* Screen size changed ? */ - if (conf_get_int(conf, CONF_height) != + if (conf_get_int(wgs->conf, CONF_height) != conf_get_int(prev_conf, CONF_height) || - conf_get_int(conf, CONF_width) != + conf_get_int(wgs->conf, CONF_width) != conf_get_int(prev_conf, CONF_width) || - conf_get_int(conf, CONF_savelines) != + conf_get_int(wgs->conf, CONF_savelines) != conf_get_int(prev_conf, CONF_savelines) || resize_action == RESIZE_FONT || (resize_action == RESIZE_EITHER && IsZoomed(hwnd)) || resize_action == RESIZE_DISABLED) - term_size(term, conf_get_int(conf, CONF_height), - conf_get_int(conf, CONF_width), - conf_get_int(conf, CONF_savelines)); + term_size(wgs->term, conf_get_int(wgs->conf, CONF_height), + conf_get_int(wgs->conf, CONF_width), + conf_get_int(wgs->conf, CONF_savelines)); /* Enable or disable the scroll bar, etc */ { @@ -2423,9 +2408,9 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, GetWindowLongPtr(hwnd, GWL_EXSTYLE); nexflag = exflag; - if (conf_get_bool(conf, CONF_alwaysontop) != + if (conf_get_bool(wgs->conf, CONF_alwaysontop) != conf_get_bool(prev_conf, CONF_alwaysontop)) { - if (conf_get_bool(conf, CONF_alwaysontop)) { + if (conf_get_bool(wgs->conf, CONF_alwaysontop)) { nexflag |= WS_EX_TOPMOST; SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); @@ -2435,13 +2420,13 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, SWP_NOMOVE | SWP_NOSIZE); } } - if (conf_get_bool(conf, CONF_sunken_edge)) + if (conf_get_bool(wgs->conf, CONF_sunken_edge)) nexflag |= WS_EX_CLIENTEDGE; else nexflag &= ~(WS_EX_CLIENTEDGE); nflg = flag; - if (conf_get_bool(conf, is_full_screen() ? + if (conf_get_bool(wgs->conf, is_full_screen(wgs) ? CONF_scrollbar_in_fullscreen : CONF_scrollbar)) nflg |= WS_VSCROLL; @@ -2449,7 +2434,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, nflg &= ~WS_VSCROLL; if (resize_action == RESIZE_DISABLED || - is_full_screen()) + is_full_screen(wgs)) nflg &= ~WS_THICKFRAME; else nflg |= WS_THICKFRAME; @@ -2481,21 +2466,21 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, } { - FontSpec *font = conf_get_fontspec(conf, CONF_font); + FontSpec *font = conf_get_fontspec(wgs->conf, CONF_font); FontSpec *prev_font = conf_get_fontspec(prev_conf, CONF_font); if (!strcmp(font->name, prev_font->name) || - !strcmp(conf_get_str(conf, CONF_line_codepage), + !strcmp(conf_get_str(wgs->conf, CONF_line_codepage), conf_get_str(prev_conf, CONF_line_codepage)) || font->isbold != prev_font->isbold || font->height != prev_font->height || font->charset != prev_font->charset || - conf_get_int(conf, CONF_font_quality) != + conf_get_int(wgs->conf, CONF_font_quality) != conf_get_int(prev_conf, CONF_font_quality) || - conf_get_int(conf, CONF_vtmode) != + conf_get_int(wgs->conf, CONF_vtmode) != conf_get_int(prev_conf, CONF_vtmode) || - conf_get_int(conf, CONF_bold_style) != + conf_get_int(wgs->conf, CONF_bold_style) != conf_get_int(prev_conf, CONF_bold_style) || resize_action == RESIZE_DISABLED || resize_action == RESIZE_EITHER || @@ -2505,27 +2490,27 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, } InvalidateRect(hwnd, NULL, true); - reset_window(init_lvl); + reset_window(wgs, init_lvl); conf_free(prev_conf); break; } case IDM_COPYALL: - term_copyall(term, clips_system, lenof(clips_system)); + term_copyall(wgs->term, clips_system, lenof(clips_system)); break; case IDM_COPY: - term_request_copy(term, clips_system, lenof(clips_system)); + term_request_copy(wgs->term, clips_system, lenof(clips_system)); break; case IDM_PASTE: - term_request_paste(term, CLIP_SYSTEM); + term_request_paste(wgs->term, CLIP_SYSTEM); break; case IDM_CLRSB: - term_clrsb(term); + term_clrsb(wgs->term); break; case IDM_RESET: - term_pwron(term, true); - if (ldisc) - ldisc_echoedit_update(ldisc); + term_pwron(wgs->term, true); + if (wgs->ldisc) + ldisc_echoedit_update(wgs->ldisc); break; case IDM_ABOUT: showabout(hwnd); @@ -2538,7 +2523,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, * We get this if the System menu has been activated * using the mouse. */ - show_mouseptr(true); + show_mouseptr(wgs, true); break; case SC_KEYMENU: /* @@ -2549,12 +2534,12 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, * the menu up_ rather than just sitting there in * `ready to appear' state. */ - show_mouseptr(true); /* make sure pointer is visible */ + show_mouseptr(wgs, true); /* make sure pointer is visible */ if( lParam == 0 ) PostMessage(hwnd, WM_CHAR, ' ', 0); break; case IDM_FULLSCREEN: - flip_full_screen(); + flip_full_screen(wgs); break; default: if (wParam >= IDM_SAVED_MIN && wParam < IDM_SAVED_MAX) { @@ -2567,11 +2552,11 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, * which would cause us to reference invalid memory * and crash. Perhaps I'm just too paranoid here. */ - if (i >= n_specials) + if (i >= wgs->n_specials) break; - if (backend) - backend_special( - backend, specials[i].code, specials[i].arg); + if (wgs->backend) + backend_special(wgs->backend, wgs->specials[i].code, + wgs->specials[i].arg); } } break; @@ -2589,15 +2574,15 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, case WM_RBUTTONUP: if (message == WM_RBUTTONDOWN && ((wParam & MK_CONTROL) || - (conf_get_int(conf, CONF_mouse_is_xterm) == 2))) { + (conf_get_int(wgs->conf, CONF_mouse_is_xterm) == 2))) { POINT cursorpos; /* Just in case this happened in mid-select */ - term_cancel_selection_drag(term); + term_cancel_selection_drag(wgs->term); - show_mouseptr(true); /* make sure pointer is visible */ + show_mouseptr(wgs, true); /* make sure pointer is visible */ GetCursorPos(&cursorpos); - TrackPopupMenu(popup_menus[CTXMENU].menu, + TrackPopupMenu(wgs->popup_menus[CTXMENU].menu, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RIGHTBUTTON, cursorpos.x, cursorpos.y, 0, hwnd, NULL); @@ -2642,7 +2627,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, button = 0; press = false; } - show_mouseptr(true); + show_mouseptr(wgs, true); /* * Special case: in full-screen mode, if the left * button is clicked in the very top left corner of the @@ -2675,7 +2660,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, if (pt.x == 0 && pt.y == 0) { mouse_on_hotspot = true; } - if (is_full_screen() && press && + if (is_full_screen(wgs) && press && button == MBT_LEFT && mouse_on_hotspot) { SendMessage(hwnd, WM_SYSCOMMAND, SC_MOUSEMENU, MAKELPARAM(pt.x, pt.y)); @@ -2684,14 +2669,14 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, } if (press) { - click(button, + click(wgs, button, TO_CHR_X(X_POS(lParam)), TO_CHR_Y(Y_POS(lParam)), wParam & MK_SHIFT, wParam & MK_CONTROL, is_alt_pressed()); SetCapture(hwnd); } else { - term_mouse(term, button, translate_button(button), MA_RELEASE, - TO_CHR_X(X_POS(lParam)), + term_mouse(wgs->term, button, translate_button(wgs, button), + MA_RELEASE, TO_CHR_X(X_POS(lParam)), TO_CHR_Y(Y_POS(lParam)), wParam & MK_SHIFT, wParam & MK_CONTROL, is_alt_pressed()); if (!(wParam & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON))) @@ -2709,7 +2694,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, static LPARAM lp = 0; if (wParam != wp || lParam != lp || last_mousemove != WM_MOUSEMOVE) { - show_mouseptr(true); + show_mouseptr(wgs, true); wp = wParam; lp = lParam; last_mousemove = WM_MOUSEMOVE; } @@ -2728,7 +2713,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, b = MBT_MIDDLE; else b = MBT_RIGHT; - term_mouse(term, b, translate_button(b), MA_DRAG, + term_mouse(wgs->term, b, translate_button(wgs, b), MA_DRAG, TO_CHR_X(X_POS(lParam)), TO_CHR_Y(Y_POS(lParam)), wParam & MK_SHIFT, wParam & MK_CONTROL, is_alt_pressed()); @@ -2740,7 +2725,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, static LPARAM lp = 0; if (wParam != wp || lParam != lp || last_mousemove != WM_NCMOUSEMOVE) { - show_mouseptr(true); + show_mouseptr(wgs, true); wp = wParam; lp = lParam; last_mousemove = WM_NCMOUSEMOVE; } @@ -2752,7 +2737,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, break; case WM_DESTROYCLIPBOARD: if (!ignore_clip) - term_lost_clipboard_ownership(term, CLIP_SYSTEM); + term_lost_clipboard_ownership(wgs->term, CLIP_SYSTEM); ignore_clip = false; return 0; case WM_PAINT: { @@ -2760,8 +2745,8 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, HideCaret(hwnd); hdc = BeginPaint(hwnd, &p); - if (pal) { - SelectPalette(hdc, pal, true); + if (wgs->pal) { + SelectPalette(hdc, wgs->pal, true); RealizePalette(hdc); } @@ -2797,29 +2782,29 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, * current terminal appearance so that WM_PAINT becomes * completely trivial. However, this should do for now. */ - assert(!wintw_hdc); - wintw_hdc = hdc; - term_paint(term, + assert(!wgs->wintw_hdc); + wgs->wintw_hdc = hdc; + term_paint(wgs->term, (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, - !term->window_update_pending); - wintw_hdc = NULL; + !wgs->term->window_update_pending); + wgs->wintw_hdc = NULL; if (p.fErase || p.rcPaint.left < offset_width || p.rcPaint.top < offset_height || - p.rcPaint.right >= offset_width + font_width*term->cols || - p.rcPaint.bottom>= offset_height + font_height*term->rows) + p.rcPaint.right >= offset_width + font_width*wgs->term->cols || + p.rcPaint.bottom>= offset_height + font_height*wgs->term->rows) { HBRUSH fillcolour, oldbrush; HPEN edge, oldpen; fillcolour = CreateSolidBrush ( - colours[ATTR_DEFBG>>ATTR_BGSHIFT]); + wgs->colours[ATTR_DEFBG>>ATTR_BGSHIFT]); oldbrush = SelectObject(hdc, fillcolour); edge = CreatePen(PS_SOLID, 0, - colours[ATTR_DEFBG>>ATTR_BGSHIFT]); + wgs->colours[ATTR_DEFBG>>ATTR_BGSHIFT]); oldpen = SelectObject(hdc, edge); /* @@ -2835,8 +2820,8 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, ExcludeClipRect(hdc, offset_width, offset_height, - offset_width+font_width*term->cols, - offset_height+font_height*term->rows); + offset_width+font_width*wgs->term->cols, + offset_height+font_height*wgs->term->rows); Rectangle(hdc, p.rcPaint.left, p.rcPaint.top, p.rcPaint.right, p.rcPaint.bottom); @@ -2858,41 +2843,41 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, winselgui_response(wParam, lParam); return 0; case WM_SETFOCUS: - term_set_focus(term, true); + term_set_focus(wgs->term, true); CreateCaret(hwnd, caretbm, font_width, font_height); ShowCaret(hwnd); - flash_window(0); /* stop */ - compose_state = 0; - term_update(term); + flash_window(wgs, 0); /* stop */ + wgs->compose_state = 0; + term_update(wgs->term); break; case WM_KILLFOCUS: - show_mouseptr(true); - term_set_focus(term, false); + show_mouseptr(wgs, true); + term_set_focus(wgs->term, false); DestroyCaret(); - caret_x = caret_y = -1; /* ensure caret is replaced next time */ - term_update(term); + wgs->caret_x = wgs->caret_y = -1; /* ensure caret replaced next time */ + term_update(wgs->term); break; case WM_ENTERSIZEMOVE: #ifdef RDB_DEBUG_PATCH debug("WM_ENTERSIZEMOVE\n"); #endif EnableSizeTip(true); - resizing = true; + wgs->resizing = true; need_backend_resize = false; break; case WM_EXITSIZEMOVE: EnableSizeTip(false); - resizing = false; + wgs->resizing = false; #ifdef RDB_DEBUG_PATCH debug("WM_EXITSIZEMOVE\n"); #endif if (need_backend_resize) { - term_size(term, conf_get_int(conf, CONF_height), - conf_get_int(conf, CONF_width), - conf_get_int(conf, CONF_savelines)); + term_size(wgs->term, conf_get_int(wgs->conf, CONF_height), + conf_get_int(wgs->conf, CONF_width), + conf_get_int(wgs->conf, CONF_savelines)); InvalidateRect(hwnd, NULL, true); } - recompute_window_offset(); + recompute_window_offset(wgs); break; case WM_SIZING: /* @@ -2900,15 +2885,15 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, * 1) Keep the sizetip uptodate * 2) Make sure the window size is _stepped_ in units of the font size. */ - resize_action = conf_get_int(conf, CONF_resize_action); + resize_action = conf_get_int(wgs->conf, CONF_resize_action); if (resize_action == RESIZE_TERM || (resize_action == RESIZE_EITHER && !is_alt_pressed())) { int width, height, w, h, ew, eh; LPRECT r = (LPRECT) lParam; if (!need_backend_resize && resize_action == RESIZE_EITHER && - (conf_get_int(conf, CONF_height) != term->rows || - conf_get_int(conf, CONF_width) != term->cols)) { + (conf_get_int(wgs->conf, CONF_height) != wgs->term->rows || + conf_get_int(wgs->conf, CONF_width) != wgs->term->cols)) { /* * Great! It seems that both the terminal size and the * font size have been changed and the user is now dragging. @@ -2918,8 +2903,8 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, * * This would be easier but it seems to be too confusing. */ - conf_set_int(conf, CONF_height, term->rows); - conf_set_int(conf, CONF_width, term->cols); + conf_set_int(wgs->conf, CONF_height, wgs->term->rows); + conf_set_int(wgs->conf, CONF_width, wgs->term->cols); InvalidateRect(hwnd, NULL, true); need_backend_resize = true; @@ -2956,7 +2941,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, return 0; } else { int width, height, w, h, rv = 0; - int window_border = conf_get_int(conf, CONF_window_border); + int window_border = conf_get_int(wgs->conf, CONF_window_border); int ex_width = extra_width + (window_border - offset_width) * 2; int ex_height = extra_height + (window_border - offset_height) * 2; LPRECT r = (LPRECT) lParam; @@ -2964,25 +2949,25 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, width = r->right - r->left - ex_width; height = r->bottom - r->top - ex_height; - w = (width + term->cols/2)/term->cols; - h = (height + term->rows/2)/term->rows; - if ( r->right != r->left + w*term->cols + ex_width) + w = (width + wgs->term->cols/2)/wgs->term->cols; + h = (height + wgs->term->rows/2)/wgs->term->rows; + if ( r->right != r->left + w*wgs->term->cols + ex_width) rv = 1; if (wParam == WMSZ_LEFT || wParam == WMSZ_BOTTOMLEFT || wParam == WMSZ_TOPLEFT) - r->left = r->right - w*term->cols - ex_width; + r->left = r->right - w*wgs->term->cols - ex_width; else - r->right = r->left + w*term->cols + ex_width; + r->right = r->left + w*wgs->term->cols + ex_width; - if (r->bottom != r->top + h*term->rows + ex_height) + if (r->bottom != r->top + h*wgs->term->rows + ex_height) rv = 1; if (wParam == WMSZ_TOP || wParam == WMSZ_TOPRIGHT || wParam == WMSZ_TOPLEFT) - r->top = r->bottom - h*term->rows - ex_height; + r->top = r->bottom - h*wgs->term->rows - ex_height; else - r->bottom = r->top + h*term->rows + ex_height; + r->bottom = r->top + h*wgs->term->rows + ex_height; return rv; } @@ -2991,11 +2976,11 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, fullscr_on_max = true; break; case WM_MOVE: - term_notify_window_pos(term, LOWORD(lParam), HIWORD(lParam)); - sys_cursor_update(); + term_notify_window_pos(wgs->term, LOWORD(lParam), HIWORD(lParam)); + sys_cursor_update(wgs); break; case WM_SIZE: - resize_action = conf_get_int(conf, CONF_resize_action); + resize_action = conf_get_int(wgs->conf, CONF_resize_action); #ifdef RDB_DEBUG_PATCH debug("WM_SIZE %s (%d,%d)\n", (wParam == SIZE_MINIMIZED) ? "SIZE_MINIMIZED": @@ -3005,7 +2990,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, "...", LOWORD(lParam), HIWORD(lParam)); #endif - term_notify_minimised(term, wParam == SIZE_MINIMIZED); + term_notify_minimised(wgs->term, wParam == SIZE_MINIMIZED); { /* * WM_SIZE's lParam tells us the size of the client area. @@ -3015,17 +3000,17 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, RECT r; GetWindowRect(hwnd, &r); term_notify_window_size_pixels( - term, r.right - r.left, r.bottom - r.top); + wgs->term, r.right - r.left, r.bottom - r.top); } if (wParam == SIZE_MINIMIZED) sw_SetWindowText(hwnd, - conf_get_bool(conf, CONF_win_name_always) ? - window_name : icon_name); + conf_get_bool(wgs->conf, CONF_win_name_always) ? + wgs->window_name : wgs->icon_name); if (wParam == SIZE_RESTORED || wParam == SIZE_MAXIMIZED) - sw_SetWindowText(hwnd, window_name); + sw_SetWindowText(hwnd, wgs->window_name); if (wParam == SIZE_RESTORED) { processed_resize = false; - clear_full_screen(); + clear_full_screen(wgs); if (processed_resize) { /* * Inhibit normal processing of this WM_SIZE; a @@ -3039,7 +3024,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, if (wParam == SIZE_MAXIMIZED && fullscr_on_max) { fullscr_on_max = false; processed_resize = false; - make_full_screen(); + make_full_screen(wgs); if (processed_resize) { /* * Inhibit normal processing of this WM_SIZE; a @@ -3055,30 +3040,30 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, if (resize_action == RESIZE_DISABLED) { /* A resize, well it better be a minimize. */ - reset_window(-1); + reset_window(wgs, -1); } else { if (wParam == SIZE_MAXIMIZED) { was_zoomed = true; - prev_rows = term->rows; - prev_cols = term->cols; + prev_rows = wgs->term->rows; + prev_cols = wgs->term->cols; if (resize_action == RESIZE_TERM) - wm_size_resize_term(lParam, false); - reset_window(0); + wm_size_resize_term(wgs, lParam, false); + reset_window(wgs, 0); } else if (wParam == SIZE_RESTORED && was_zoomed) { was_zoomed = false; if (resize_action == RESIZE_TERM) { - wm_size_resize_term(lParam, true); - reset_window(2); + wm_size_resize_term(wgs, lParam, true); + reset_window(wgs, 2); } else if (resize_action != RESIZE_FONT) - reset_window(2); + reset_window(wgs, 2); else - reset_window(0); + reset_window(wgs, 0); } else if (wParam == SIZE_MINIMIZED) { /* do nothing */ } else if (resize_action == RESIZE_TERM || (resize_action == RESIZE_EITHER && !is_alt_pressed())) { - wm_size_resize_term(lParam, true); + wm_size_resize_term(wgs, lParam, true); /* * Sometimes, we can get a spontaneous resize event @@ -3093,39 +3078,39 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, * recompute the border around the window and do a * full redraw to clear the new border. */ - if (!resizing) - recompute_window_offset(); + if (!wgs->resizing) + recompute_window_offset(wgs); } else { - reset_window(0); + reset_window(wgs, 0); } } - sys_cursor_update(); + sys_cursor_update(wgs); return 0; case WM_DPICHANGED: - dpi_info.cur_dpi.x = LOWORD(wParam); - dpi_info.cur_dpi.y = HIWORD(wParam); - dpi_info.new_wnd_rect = *(RECT*)(lParam); - reset_window(3); + wgs->dpi_info.cur_dpi.x = LOWORD(wParam); + wgs->dpi_info.cur_dpi.y = HIWORD(wParam); + wgs->dpi_info.new_wnd_rect = *(RECT*)(lParam); + reset_window(wgs, 3); return 0; case WM_VSCROLL: switch (LOWORD(wParam)) { case SB_BOTTOM: - term_scroll(term, -1, 0); + term_scroll(wgs->term, -1, 0); break; case SB_TOP: - term_scroll(term, +1, 0); + term_scroll(wgs->term, +1, 0); break; case SB_LINEDOWN: - term_scroll(term, 0, +1); + term_scroll(wgs->term, 0, +1); break; case SB_LINEUP: - term_scroll(term, 0, -1); + term_scroll(wgs->term, 0, -1); break; case SB_PAGEDOWN: - term_scroll(term, 0, +term->rows / 2); + term_scroll(wgs->term, 0, +wgs->term->rows / 2); break; case SB_PAGEUP: - term_scroll(term, 0, -term->rows / 2); + term_scroll(wgs->term, 0, -wgs->term->rows / 2); break; case SB_THUMBPOSITION: case SB_THUMBTRACK: { @@ -3139,7 +3124,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, si.fMask = SIF_TRACKPOS; if (GetScrollInfo(hwnd, SB_VERT, &si) == 0) si.nTrackPos = HIWORD(wParam); - term_scroll(term, 1, si.nTrackPos); + term_scroll(wgs->term, 1, si.nTrackPos); break; } } @@ -3186,26 +3171,26 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, * way round. Many people on the Internet have noticed * this, e.g. https://stackoverflow.com/q/55528397 */ - term_update(term); + term_update(wgs->term); } break; case WM_PALETTECHANGED: - if ((HWND) wParam != hwnd && pal != NULL) { - HDC hdc = make_hdc(); + if ((HWND) wParam != hwnd && wgs->pal != NULL) { + HDC hdc = make_hdc(wgs); if (hdc) { if (RealizePalette(hdc) > 0) UpdateColors(hdc); - free_hdc(hdc); + free_hdc(wgs, hdc); } } break; case WM_QUERYNEWPALETTE: - if (pal != NULL) { - HDC hdc = make_hdc(); + if (wgs->pal != NULL) { + HDC hdc = make_hdc(wgs); if (hdc) { if (RealizePalette(hdc) > 0) UpdateColors(hdc); - free_hdc(hdc); + free_hdc(wgs, hdc); return true; } } @@ -3242,7 +3227,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, TranslateMessage(&m); } else break; /* pass to Windows for default processing */ } else { - len = TranslateKey(message, wParam, lParam, buf); + len = TranslateKey(wgs, message, wParam, lParam, buf); if (len == -1) return sw_DefWindowProc(hwnd, message, wParam, lParam); @@ -3255,8 +3240,8 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, * messages. We _have_ to buffer everything * we're sent. */ - term_keyinput(term, -1, buf, len); - show_mouseptr(false); + term_keyinput(wgs->term, -1, buf, len); + show_mouseptr(wgs, false); } } } @@ -3264,12 +3249,12 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, case WM_INPUTLANGCHANGE: /* wParam == Font number */ /* lParam == Locale */ - set_input_locale((HKL)lParam); - sys_cursor_update(); + set_input_locale(wgs, (HKL)lParam); + sys_cursor_update(wgs); break; case WM_IME_STARTCOMPOSITION: { HIMC hImc = ImmGetContext(hwnd); - ImmSetCompositionFont(hImc, &lfont); + ImmSetCompositionFont(hImc, &wgs->lfont); ImmReleaseContext(hwnd, hImc); break; } @@ -3299,20 +3284,20 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, * instead we send the characters one by one. */ /* don't divide SURROGATE PAIR */ - if (ldisc) { + if (wgs->ldisc) { for (i = 0; i < n; i += 2) { WCHAR hs = *(unsigned short *)(buff+i); if (IS_HIGH_SURROGATE(hs) && i+2 < n) { WCHAR ls = *(unsigned short *)(buff+i+2); if (IS_LOW_SURROGATE(ls)) { term_keyinputw( - term, (unsigned short *)(buff+i), 2); + wgs->term, (unsigned short *)(buff+i), 2); i += 2; continue; } } term_keyinputw( - term, (unsigned short *)(buff+i), 1); + wgs->term, (unsigned short *)(buff+i), 1); } } free(buff); @@ -3327,11 +3312,11 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, buf[1] = wParam; buf[0] = wParam >> 8; - term_keyinput(term, kbd_codepage, buf, 2); + term_keyinput(wgs->term, wgs->kbd_codepage, buf, 2); } else { char c = (unsigned char) wParam; - term_seen_key_event(term); - term_keyinput(term, kbd_codepage, &c, 1); + term_seen_key_event(wgs->term); + term_keyinput(wgs->term, wgs->kbd_codepage, &c, 1); } return (0); case WM_CHAR: @@ -3352,40 +3337,40 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, wchar_t pair[2]; pair[0] = pending_surrogate; pair[1] = c; - term_keyinputw(term, pair, 2); + term_keyinputw(wgs->term, pair, 2); } else if (!IS_SURROGATE(c)) { - term_keyinputw(term, &c, 1); + term_keyinputw(wgs->term, &c, 1); } } else { char c = (unsigned char)wParam; - term_seen_key_event(term); - if (ldisc) - term_keyinput(term, CP_ACP, &c, 1); + term_seen_key_event(wgs->term); + if (wgs->ldisc) + term_keyinput(wgs->term, CP_ACP, &c, 1); } return 0; case WM_SYSCOLORCHANGE: - if (conf_get_bool(conf, CONF_system_colour)) { + if (conf_get_bool(wgs->conf, CONF_system_colour)) { /* Refresh palette from system colours. */ - term_notify_palette_changed(term); - init_palette(); + term_notify_palette_changed(wgs->term); + init_palette(wgs); /* Force a repaint of the terminal window. */ - term_invalidate(term); + term_invalidate(wgs->term); } break; case WM_GOT_CLIPDATA: - process_clipdata((HGLOBAL)lParam, wParam); + process_clipdata(wgs, (HGLOBAL)lParam, wParam); return 0; default: if (message == wm_mousewheel || message == WM_MOUSEWHEEL) { bool shift_pressed = false, control_pressed = false; if (message == WM_MOUSEWHEEL) { - wheel_accumulator += (short)HIWORD(wParam); + wgs->wheel_accumulator += (short)HIWORD(wParam); shift_pressed=LOWORD(wParam) & MK_SHIFT; control_pressed=LOWORD(wParam) & MK_CONTROL; } else { BYTE keys[256]; - wheel_accumulator += (int)wParam; + wgs->wheel_accumulator += (int)wParam; if (GetKeyboardState(keys)!=0) { shift_pressed=keys[VK_SHIFT]&0x80; control_pressed=keys[VK_CONTROL]&0x80; @@ -3393,21 +3378,21 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, } /* process events when the threshold is reached */ - while (abs(wheel_accumulator) >= WHEEL_DELTA) { + while (abs(wgs->wheel_accumulator) >= WHEEL_DELTA) { int b; /* reduce amount for next time */ - if (wheel_accumulator > 0) { + if (wgs->wheel_accumulator > 0) { b = MBT_WHEEL_UP; - wheel_accumulator -= WHEEL_DELTA; - } else if (wheel_accumulator < 0) { + wgs->wheel_accumulator -= WHEEL_DELTA; + } else if (wgs->wheel_accumulator < 0) { b = MBT_WHEEL_DOWN; - wheel_accumulator += WHEEL_DELTA; + wgs->wheel_accumulator += WHEEL_DELTA; } else break; - if (send_raw_mouse && - !(conf_get_bool(conf, CONF_mouse_override) && + if (wgs->send_raw_mouse && + !(conf_get_bool(wgs->conf, CONF_mouse_override) && shift_pressed)) { /* Mouse wheel position is in screen coordinates for * some reason */ @@ -3415,7 +3400,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, p.x = X_POS(lParam); p.y = Y_POS(lParam); if (ScreenToClient(hwnd, &p)) { /* send a mouse-down followed by a mouse up */ - term_mouse(term, b, translate_button(b), + term_mouse(wgs->term, b, translate_button(wgs, b), MA_CLICK, TO_CHR_X(p.x), TO_CHR_Y(p.y), shift_pressed, @@ -3423,9 +3408,9 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, } /* else: not sure when this can fail */ } else { /* trigger a scroll */ - term_scroll(term, 0, + term_scroll(wgs->term, 0, b == MBT_WHEEL_UP ? - -term->rows / 2 : term->rows / 2); + -wgs->term->rows / 2 : wgs->term->rows / 2); } } return 0; @@ -3447,9 +3432,10 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, */ static void wintw_set_cursor_pos(TermWin *tw, int x, int y) { + WinGuiSeat *wgs = container_of(tw, WinGuiSeat, termwin); int cx, cy; - if (!term->has_focus) return; + if (!wgs->term->has_focus) return; /* * Avoid gratuitously re-updating the cursor position and IMM @@ -3457,25 +3443,25 @@ static void wintw_set_cursor_pos(TermWin *tw, int x, int y) */ cx = x * font_width + offset_width; cy = y * font_height + offset_height; - if (cx == caret_x && cy == caret_y) + if (cx == wgs->caret_x && cy == wgs->caret_y) return; - caret_x = cx; - caret_y = cy; + wgs->caret_x = cx; + wgs->caret_y = cy; - sys_cursor_update(); + sys_cursor_update(wgs); } -static void sys_cursor_update(void) +static void sys_cursor_update(WinGuiSeat *wgs) { COMPOSITIONFORM cf; HIMC hIMC; - if (!term->has_focus) return; + if (!wgs->term->has_focus) return; - if (caret_x < 0 || caret_y < 0) + if (wgs->caret_x < 0 || wgs->caret_y < 0) return; - SetCaretPos(caret_x, caret_y); + SetCaretPos(wgs->caret_x, wgs->caret_y); /* IMM calls on Win98 and beyond only */ if (osPlatformId == VER_PLATFORM_WIN32s) return; /* 3.11 */ @@ -3484,17 +3470,17 @@ static void sys_cursor_update(void) osMinorVersion == 0) return; /* 95 */ /* we should have the IMM functions */ - hIMC = ImmGetContext(wgs.term_hwnd); + hIMC = ImmGetContext(wgs->term_hwnd); cf.dwStyle = CFS_POINT; - cf.ptCurrentPos.x = caret_x; - cf.ptCurrentPos.y = caret_y; + cf.ptCurrentPos.x = wgs->caret_x; + cf.ptCurrentPos.y = wgs->caret_y; ImmSetCompositionWindow(hIMC, &cf); - ImmReleaseContext(wgs.term_hwnd, hIMC); + ImmReleaseContext(wgs->term_hwnd, hIMC); } -static void draw_horizontal_line_on_text(int y, int lattr, RECT line_box, - COLORREF colour) +static void draw_horizontal_line_on_text( + WinGuiSeat *wgs, int y, int lattr, RECT line_box, COLORREF colour) { if (lattr == LATTR_TOP || lattr == LATTR_BOT) { y *= 2; @@ -3505,10 +3491,10 @@ static void draw_horizontal_line_on_text(int y, int lattr, RECT line_box, if (!(0 <= y && y < font_height)) return; - HPEN oldpen = SelectObject(wintw_hdc, CreatePen(PS_SOLID, 0, colour)); - MoveToEx(wintw_hdc, line_box.left, line_box.top + y, NULL); - LineTo(wintw_hdc, line_box.right, line_box.top + y); - oldpen = SelectObject(wintw_hdc, oldpen); + HPEN oldpen = SelectObject(wgs->wintw_hdc, CreatePen(PS_SOLID, 0, colour)); + MoveToEx(wgs->wintw_hdc, line_box.left, line_box.top + y, NULL); + LineTo(wgs->wintw_hdc, line_box.right, line_box.top + y); + oldpen = SelectObject(wgs->wintw_hdc, oldpen); DeleteObject(oldpen); } @@ -3519,7 +3505,7 @@ static void draw_horizontal_line_on_text(int y, int lattr, RECT line_box, * We are allowed to fiddle with the contents of `text'. */ static void do_text_internal( - int x, int y, wchar_t *text, int len, + WinGuiSeat *wgs, int x, int y, wchar_t *text, int len, unsigned long attr, int lattr, truecolour truecolour) { COLORREF fg, bg, t; @@ -3545,7 +3531,7 @@ static void do_text_internal( char_width *= 2; /* Only want the left half of double width lines */ - if (lattr != LATTR_NORM && x*2 >= term->cols) + if (lattr != LATTR_NORM && x*2 >= wgs->term->cols) return; x *= fnt_width; @@ -3553,7 +3539,8 @@ static void do_text_internal( x += offset_width; y += offset_height; - if ((attr & TATTR_ACTCURS) && (cursor_type == 0 || term->big_cursor)) { + if ((attr & TATTR_ACTCURS) && + (wgs->cursor_type == 0 || wgs->term->big_cursor)) { truecolour.fg = truecolour.bg = optionalrgb_none; attr &= ~(ATTR_REVERSE|ATTR_BLINK|ATTR_COLOURS|ATTR_DIM); /* cursor fg and bg */ @@ -3562,7 +3549,7 @@ static void do_text_internal( } nfont = 0; - if (vtmode == VT_POORMAN && lattr != LATTR_NORM) { + if (wgs->vtmode == VT_POORMAN && lattr != LATTR_NORM) { /* Assume a poorman font is borken in other ways too. */ lattr = LATTR_WIDE; } else @@ -3598,7 +3585,7 @@ static void do_text_internal( } if (lattr == LATTR_TOP || lattr == LATTR_BOT) text_adjust *= 2; - text[0] = ucsdata.unitab_xterm['q']; + text[0] = wgs->ucsdata.unitab_xterm['q']; if (attr & ATTR_UNDER) { attr &= ~ATTR_UNDER; force_manual_underline = true; @@ -3620,20 +3607,20 @@ static void do_text_internal( nfg = ((attr & ATTR_FGMASK) >> ATTR_FGSHIFT); nbg = ((attr & ATTR_BGMASK) >> ATTR_BGSHIFT); - if (bold_font_mode == BOLD_FONT && (attr & ATTR_BOLD)) + if (wgs->bold_font_mode == BOLD_FONT && (attr & ATTR_BOLD)) nfont |= FONT_BOLD; - if (und_mode == UND_FONT && (attr & ATTR_UNDER)) + if (wgs->und_mode == UND_FONT && (attr & ATTR_UNDER)) nfont |= FONT_UNDERLINE; - another_font(nfont); - if (!fonts[nfont]) { + another_font(wgs, nfont); + if (!wgs->fonts[nfont]) { if (nfont & FONT_UNDERLINE) force_manual_underline = true; /* Don't do the same for manual bold, it could be bad news. */ nfont &= ~(FONT_BOLD | FONT_UNDERLINE); } - another_font(nfont); - if (!fonts[nfont]) + another_font(wgs, nfont); + if (!wgs->fonts[nfont]) nfont = FONT_NORMAL; if (attr & ATTR_REVERSE) { struct optionalrgb trgb; @@ -3646,37 +3633,37 @@ static void do_text_internal( truecolour.fg = truecolour.bg; truecolour.bg = trgb; } - if (bold_colours && (attr & ATTR_BOLD) && !is_cursor) { + if (wgs->bold_colours && (attr & ATTR_BOLD) && !is_cursor) { if (nfg < 16) nfg |= 8; else if (nfg >= 256) nfg |= 1; } - if (bold_colours && (attr & ATTR_BLINK)) { + if (wgs->bold_colours && (attr & ATTR_BLINK)) { if (nbg < 16) nbg |= 8; else if (nbg >= 256) nbg |= 1; } - if (!pal && truecolour.fg.enabled) + if (!wgs->pal && truecolour.fg.enabled) fg = RGB(truecolour.fg.r, truecolour.fg.g, truecolour.fg.b); else - fg = colours[nfg]; + fg = wgs->colours[nfg]; - if (!pal && truecolour.bg.enabled) + if (!wgs->pal && truecolour.bg.enabled) bg = RGB(truecolour.bg.r, truecolour.bg.g, truecolour.bg.b); else - bg = colours[nbg]; + bg = wgs->colours[nbg]; - if (!pal && (attr & ATTR_DIM)) { + if (!wgs->pal && (attr & ATTR_DIM)) { fg = RGB(GetRValue(fg) * 2 / 3, GetGValue(fg) * 2 / 3, GetBValue(fg) * 2 / 3); } - SelectObject(wintw_hdc, fonts[nfont]); - SetTextColor(wintw_hdc, fg); - SetBkColor(wintw_hdc, bg); + SelectObject(wgs->wintw_hdc, wgs->fonts[nfont]); + SetTextColor(wgs->wintw_hdc, fg); + SetBkColor(wgs->wintw_hdc, bg); if (attr & TATTR_COMBINING) - SetBkMode(wintw_hdc, TRANSPARENT); + SetBkMode(wgs->wintw_hdc, TRANSPARENT); else - SetBkMode(wintw_hdc, OPAQUE); + SetBkMode(wgs->wintw_hdc, OPAQUE); line_box.left = x; line_box.top = y; line_box.right = x + char_width * len; @@ -3701,8 +3688,8 @@ static void do_text_internal( } /* Only want the left half of double width lines */ - if (line_box.right > font_width*term->cols+offset_width) - line_box.right = font_width*term->cols+offset_width; + if (line_box.right > font_width*wgs->term->cols+offset_width) + line_box.right = font_width*wgs->term->cols+offset_width; if (font_varpitch) { /* @@ -3713,7 +3700,7 @@ static void do_text_internal( * generally reasonable results. */ xoffset = char_width / 2; - SetTextAlign(wintw_hdc, TA_TOP | TA_CENTER | TA_NOUPDATECP); + SetTextAlign(wgs->wintw_hdc, TA_TOP | TA_CENTER | TA_NOUPDATECP); lpDx_maybe = NULL; maxlen = 1; } else { @@ -3722,7 +3709,7 @@ static void do_text_internal( * in the normal way. */ xoffset = 0; - SetTextAlign(wintw_hdc, TA_TOP | TA_LEFT | TA_NOUPDATECP); + SetTextAlign(wgs->wintw_hdc, TA_TOP | TA_LEFT | TA_NOUPDATECP); lpDx_maybe = lpDx; maxlen = len; } @@ -3771,7 +3758,8 @@ static void do_text_internal( } /* We're using a private area for direct to font. (512 chars.) */ - if (ucsdata.dbcs_screenfont && (text[0] & CSET_MASK) == CSET_ACP) { + if (wgs->ucsdata.dbcs_screenfont && + (text[0] & CSET_MASK) == CSET_ACP) { /* Ho Hum, dbcs fonts are a PITA! */ /* To display on W9x I have to convert to UCS */ static wchar_t *uni_buf = 0; @@ -3785,34 +3773,36 @@ static void do_text_internal( for(nlen = mptr = 0; mptrucsdata.font_codepage, (BYTE) text[mptr])) { char dbcstext[2]; dbcstext[0] = text[mptr] & 0xFF; dbcstext[1] = text[mptr+1] & 0xFF; lpDx[nlen] += char_width; - MultiByteToWideChar(ucsdata.font_codepage, MB_USEGLYPHCHARS, - dbcstext, 2, uni_buf+nlen, 1); + MultiByteToWideChar( + wgs->ucsdata.font_codepage, MB_USEGLYPHCHARS, + dbcstext, 2, uni_buf+nlen, 1); mptr++; } else { char dbcstext[1]; dbcstext[0] = text[mptr] & 0xFF; - MultiByteToWideChar(ucsdata.font_codepage, MB_USEGLYPHCHARS, - dbcstext, 1, uni_buf+nlen, 1); + MultiByteToWideChar( + wgs->ucsdata.font_codepage, MB_USEGLYPHCHARS, + dbcstext, 1, uni_buf+nlen, 1); } nlen++; } if (nlen <= 0) return; /* Eeek! */ - ExtTextOutW(wintw_hdc, x + xoffset, + ExtTextOutW(wgs->wintw_hdc, x + xoffset, y - font_height * (lattr == LATTR_BOT) + text_adjust, ETO_CLIPPED | (opaque ? ETO_OPAQUE : 0), &line_box, uni_buf, nlen, lpDx_maybe); - if (bold_font_mode == BOLD_SHADOW && (attr & ATTR_BOLD)) { - SetBkMode(wintw_hdc, TRANSPARENT); - ExtTextOutW(wintw_hdc, x + xoffset - 1, + if (wgs->bold_font_mode == BOLD_SHADOW && (attr & ATTR_BOLD)) { + SetBkMode(wgs->wintw_hdc, TRANSPARENT); + ExtTextOutW(wgs->wintw_hdc, x + xoffset - 1, y - font_height * (lattr == LATTR_BOT) + text_adjust, ETO_CLIPPED, &line_box, uni_buf, nlen, lpDx_maybe); @@ -3827,12 +3817,12 @@ static void do_text_internal( for (size_t i = 0; i < len; i++) directbuf[i] = text[i] & 0xFF; - ExtTextOut(wintw_hdc, x + xoffset, + ExtTextOut(wgs->wintw_hdc, x + xoffset, y - font_height * (lattr == LATTR_BOT) + text_adjust, ETO_CLIPPED | (opaque ? ETO_OPAQUE : 0), &line_box, directbuf, len, lpDx_maybe); - if (bold_font_mode == BOLD_SHADOW && (attr & ATTR_BOLD)) { - SetBkMode(wintw_hdc, TRANSPARENT); + if (wgs->bold_font_mode == BOLD_SHADOW && (attr & ATTR_BOLD)) { + SetBkMode(wgs->wintw_hdc, TRANSPARENT); /* GRR: This draws the character outside its box and * can leave 'droppings' even with the clip box! I @@ -3843,7 +3833,7 @@ static void do_text_internal( * or -1 for this shift depending on if the leftmost * column is blank... */ - ExtTextOut(wintw_hdc, x + xoffset - 1, + ExtTextOut(wgs->wintw_hdc, x + xoffset - 1, y - font_height * (lattr == LATTR_BOT) + text_adjust, ETO_CLIPPED, &line_box, directbuf, len, lpDx_maybe); @@ -3864,15 +3854,15 @@ static void do_text_internal( wbuf[i] = text[i]; /* print Glyphs as they are, without Windows' Shaping*/ - general_textout(wintw_hdc, x + xoffset, + general_textout(wgs->wintw_hdc, x + xoffset, y - font_height * (lattr==LATTR_BOT) + text_adjust, &line_box, wbuf, len, lpDx, opaque && !(attr & TATTR_COMBINING)); /* And the shadow bold hack. */ - if (bold_font_mode == BOLD_SHADOW && (attr & ATTR_BOLD)) { - SetBkMode(wintw_hdc, TRANSPARENT); - ExtTextOutW(wintw_hdc, x + xoffset - 1, + if (wgs->bold_font_mode == BOLD_SHADOW && (attr & ATTR_BOLD)) { + SetBkMode(wgs->wintw_hdc, TRANSPARENT); + ExtTextOutW(wgs->wintw_hdc, x + xoffset - 1, y - font_height * (lattr == LATTR_BOT) + text_adjust, ETO_CLIPPED, &line_box, wbuf, len, lpDx_maybe); @@ -3883,16 +3873,18 @@ static void do_text_internal( * If we're looping round again, stop erasing the background * rectangle. */ - SetBkMode(wintw_hdc, TRANSPARENT); + SetBkMode(wgs->wintw_hdc, TRANSPARENT); opaque = false; } - if (lattr != LATTR_TOP && (force_manual_underline || - (und_mode == UND_LINE && (attr & ATTR_UNDER)))) - draw_horizontal_line_on_text(descent, lattr, line_box, fg); + if (lattr != LATTR_TOP && + (force_manual_underline || (wgs->und_mode == UND_LINE && + (attr & ATTR_UNDER)))) + draw_horizontal_line_on_text(wgs, wgs->descent, lattr, line_box, fg); if (attr & ATTR_STRIKE) - draw_horizontal_line_on_text(font_strikethrough_y, lattr, line_box, fg); + draw_horizontal_line_on_text(wgs, wgs->font_strikethrough_y, lattr, + line_box, fg); } /* @@ -3902,6 +3894,7 @@ static void wintw_draw_text( TermWin *tw, int x, int y, wchar_t *text, int len, unsigned long attr, int lattr, truecolour truecolour) { + WinGuiSeat *wgs = container_of(tw, WinGuiSeat, termwin); if (attr & TATTR_COMBINING) { unsigned long a = 0; int len0 = 1; @@ -3910,13 +3903,13 @@ static void wintw_draw_text( len0 = 2; if (len-len0 >= 1 && IS_LOW_VARSEL(text[len0])) { attr &= ~TATTR_COMBINING; - do_text_internal(x, y, text, len0+1, attr, lattr, truecolour); + do_text_internal(wgs, x, y, text, len0+1, attr, lattr, truecolour); text += len0+1; len -= len0+1; a = TATTR_COMBINING; } else if (len-len0 >= 2 && IS_HIGH_VARSEL(text[len0], text[len0+1])) { attr &= ~TATTR_COMBINING; - do_text_internal(x, y, text, len0+2, attr, lattr, truecolour); + do_text_internal(wgs, x, y, text, len0+2, attr, lattr, truecolour); text += len0+2; len -= len0+2; a = TATTR_COMBINING; @@ -3926,30 +3919,33 @@ static void wintw_draw_text( while (len--) { if (len >= 1 && IS_SURROGATE_PAIR(text[0], text[1])) { - do_text_internal(x, y, text, 2, attr | a, lattr, truecolour); + do_text_internal(wgs, x, y, text, 2, attr | a, lattr, + truecolour); len--; text++; } else - do_text_internal(x, y, text, 1, attr | a, lattr, truecolour); + do_text_internal(wgs, x, y, text, 1, attr | a, lattr, + truecolour); text++; a = TATTR_COMBINING; } } else - do_text_internal(x, y, text, len, attr, lattr, truecolour); + do_text_internal(wgs, x, y, text, len, attr, lattr, truecolour); } static void wintw_draw_cursor( TermWin *tw, int x, int y, wchar_t *text, int len, unsigned long attr, int lattr, truecolour truecolour) { + WinGuiSeat *wgs = container_of(tw, WinGuiSeat, termwin); int fnt_width; int char_width; - int ctype = cursor_type; + int ctype = wgs->cursor_type; lattr &= LATTR_MODE; - if ((attr & TATTR_ACTCURS) && (ctype == 0 || term->big_cursor)) { + if ((attr & TATTR_ACTCURS) && (ctype == 0 || wgs->term->big_cursor)) { if (*text != UCSWIDE) { win_draw_text(tw, x, y, text, len, attr, lattr, truecolour); return; @@ -3966,22 +3962,23 @@ static void wintw_draw_cursor( x += offset_width; y += offset_height; - if ((attr & TATTR_PASCURS) && (ctype == 0 || term->big_cursor)) { + if ((attr & TATTR_PASCURS) && (ctype == 0 || wgs->term->big_cursor)) { POINT pts[5]; HPEN oldpen; pts[0].x = pts[1].x = pts[4].x = x; pts[2].x = pts[3].x = x + char_width - 1; pts[0].y = pts[3].y = pts[4].y = y; pts[1].y = pts[2].y = y + font_height - 1; - oldpen = SelectObject(wintw_hdc, CreatePen(PS_SOLID, 0, colours[261])); - Polyline(wintw_hdc, pts, 5); - oldpen = SelectObject(wintw_hdc, oldpen); + oldpen = SelectObject(wgs->wintw_hdc, + CreatePen(PS_SOLID, 0, wgs->colours[261])); + Polyline(wgs->wintw_hdc, pts, 5); + oldpen = SelectObject(wgs->wintw_hdc, oldpen); DeleteObject(oldpen); } else if ((attr & (TATTR_ACTCURS | TATTR_PASCURS)) && ctype != 0) { int startx, starty, dx, dy, length, i; if (ctype == 1) { startx = x; - starty = y + descent; + starty = y + wgs->descent; dx = 1; dy = 0; length = char_width; @@ -3998,15 +3995,17 @@ static void wintw_draw_cursor( if (attr & TATTR_ACTCURS) { HPEN oldpen; oldpen = - SelectObject(wintw_hdc, CreatePen(PS_SOLID, 0, colours[261])); - MoveToEx(wintw_hdc, startx, starty, NULL); - LineTo(wintw_hdc, startx + dx * length, starty + dy * length); - oldpen = SelectObject(wintw_hdc, oldpen); + SelectObject(wgs->wintw_hdc, + CreatePen(PS_SOLID, 0, wgs->colours[261])); + MoveToEx(wgs->wintw_hdc, startx, starty, NULL); + LineTo(wgs->wintw_hdc, startx + dx * length, starty + dy * length); + oldpen = SelectObject(wgs->wintw_hdc, oldpen); DeleteObject(oldpen); } else { for (i = 0; i < length; i++) { if (i % 2 == 0) { - SetPixel(wintw_hdc, startx, starty, colours[261]); + SetPixel(wgs->wintw_hdc, startx, starty, + wgs->colours[261]); } startx += dx; starty += dy; @@ -4017,12 +4016,14 @@ static void wintw_draw_cursor( static void wintw_draw_trust_sigil(TermWin *tw, int x, int y) { + WinGuiSeat *wgs = container_of(tw, WinGuiSeat, termwin); + x *= font_width; y *= font_height; x += offset_width; y += offset_height; - DrawIconEx(wintw_hdc, x, y, trust_icon, font_width * 2, font_height, + DrawIconEx(wgs->wintw_hdc, x, y, trust_icon, font_width * 2, font_height, 0, NULL, DI_NORMAL); } @@ -4030,6 +4031,7 @@ static void wintw_draw_trust_sigil(TermWin *tw, int x, int y) */ static int wintw_char_width(TermWin *tw, int uc) { + WinGuiSeat *wgs = container_of(tw, WinGuiSeat, termwin); int ibuf = 0; /* If the font max is the same as the font ave width then this @@ -4039,45 +4041,45 @@ static int wintw_char_width(TermWin *tw, int uc) switch (uc & CSET_MASK) { case CSET_ASCII: - uc = ucsdata.unitab_line[uc & 0xFF]; + uc = wgs->ucsdata.unitab_line[uc & 0xFF]; break; case CSET_LINEDRW: - uc = ucsdata.unitab_xterm[uc & 0xFF]; + uc = wgs->ucsdata.unitab_xterm[uc & 0xFF]; break; case CSET_SCOACS: - uc = ucsdata.unitab_scoacs[uc & 0xFF]; + uc = wgs->ucsdata.unitab_scoacs[uc & 0xFF]; break; } if (DIRECT_FONT(uc)) { - if (ucsdata.dbcs_screenfont) return 1; + if (wgs->ucsdata.dbcs_screenfont) return 1; /* Speedup, I know of no font where ascii is the wrong width */ if ((uc&~CSET_MASK) >= ' ' && (uc&~CSET_MASK)<= '~') return 1; if ( (uc & CSET_MASK) == CSET_ACP ) { - SelectObject(wintw_hdc, fonts[FONT_NORMAL]); + SelectObject(wgs->wintw_hdc, wgs->fonts[FONT_NORMAL]); } else if ( (uc & CSET_MASK) == CSET_OEMCP ) { - another_font(FONT_OEM); - if (!fonts[FONT_OEM]) return 0; + another_font(wgs, FONT_OEM); + if (!wgs->fonts[FONT_OEM]) return 0; - SelectObject(wintw_hdc, fonts[FONT_OEM]); + SelectObject(wgs->wintw_hdc, wgs->fonts[FONT_OEM]); } else return 0; - if (GetCharWidth32(wintw_hdc, uc & ~CSET_MASK, + if (GetCharWidth32(wgs->wintw_hdc, uc & ~CSET_MASK, uc & ~CSET_MASK, &ibuf) != 1 && - GetCharWidth(wintw_hdc, uc & ~CSET_MASK, + GetCharWidth(wgs->wintw_hdc, uc & ~CSET_MASK, uc & ~CSET_MASK, &ibuf) != 1) return 0; } else { /* Speedup, I know of no font where ascii is the wrong width */ if (uc >= ' ' && uc <= '~') return 1; - SelectObject(wintw_hdc, fonts[FONT_NORMAL]); - if (GetCharWidth32W(wintw_hdc, uc, uc, &ibuf) == 1) + SelectObject(wgs->wintw_hdc, wgs->fonts[FONT_NORMAL]); + if (GetCharWidth32W(wgs->wintw_hdc, uc, uc, &ibuf) == 1) /* Okay that one worked */ ; - else if (GetCharWidthW(wintw_hdc, uc, uc, &ibuf) == 1) + else if (GetCharWidthW(wgs->wintw_hdc, uc, uc, &ibuf) == 1) /* This should work on 9x too, but it's "less accurate" */ ; else return 0; @@ -4116,8 +4118,8 @@ static void init_winfuncs(void) * -1 to forward the message to Windows, or another negative number * to indicate a NUL-terminated "special" string. */ -static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam, - unsigned char *output) +static int TranslateKey(WinGuiSeat *wgs, UINT message, WPARAM wParam, + LPARAM lParam, unsigned char *output) { BYTE keystate[256]; int scan, shift_state; @@ -4125,10 +4127,10 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam, int r, i; unsigned char *p = output; static int alt_sum = 0; - int funky_type = conf_get_int(conf, CONF_funky_type); - bool no_applic_k = conf_get_bool(conf, CONF_no_applic_k); - bool ctrlaltkeys = conf_get_bool(conf, CONF_ctrlaltkeys); - bool nethack_keypad = conf_get_bool(conf, CONF_nethack_keypad); + int funky_type = conf_get_int(wgs->conf, CONF_funky_type); + bool no_applic_k = conf_get_bool(wgs->conf, CONF_no_applic_k); + bool ctrlaltkeys = conf_get_bool(wgs->conf, CONF_ctrlaltkeys); + bool nethack_keypad = conf_get_bool(wgs->conf, CONF_nethack_keypad); char keypad_key = '\0'; HKL kbd_layout = GetKeyboardLayout(0); @@ -4223,7 +4225,7 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam, /* Nastiness with NUMLock - Shift-NUMLock is left alone though */ if ((funky_type == FUNKY_VT400 || - (funky_type <= FUNKY_LINUX && term->app_keypad_keys && + (funky_type <= FUNKY_LINUX && wgs->term->app_keypad_keys && !no_applic_k)) && wParam == VK_NUMLOCK && !(keystate[VK_SHIFT] & 0x80)) { @@ -4239,7 +4241,7 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam, } /* Disable Auto repeat if required */ - if (term->repeat_off && + if (wgs->term->repeat_off && (HIWORD(lParam) & (KF_UP | KF_REPEAT)) == KF_REPEAT) return 0; @@ -4263,9 +4265,9 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam, + ((keystate[VK_CONTROL] & 0x80) != 0) * 2; /* Note if AltGr was pressed and if it was used as a compose key */ - if (!compose_state) { + if (!wgs->compose_state) { compose_keycode = 0x100; - if (conf_get_bool(conf, CONF_compose_key)) { + if (conf_get_bool(wgs->conf, CONF_compose_key)) { if (wParam == VK_MENU && (HIWORD(lParam) & KF_EXTENDED)) compose_keycode = wParam; } @@ -4274,23 +4276,23 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam, } if (wParam == compose_keycode) { - if (compose_state == 0 && + if (wgs->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; + wgs->compose_state = 1; + else if (wgs->compose_state == 1 && (HIWORD(lParam) & KF_UP)) + wgs->compose_state = 2; else - compose_state = 0; - } else if (compose_state == 1 && wParam != VK_CONTROL) - compose_state = 0; + wgs->compose_state = 0; + } else if (wgs->compose_state == 1 && wParam != VK_CONTROL) + wgs->compose_state = 0; - if (compose_state > 1 && left_alt) - compose_state = 0; + if (wgs->compose_state > 1 && left_alt) + wgs->compose_state = 0; /* Sanitize the number pad if not using a PC NumPad */ - if (left_alt || (term->app_keypad_keys && !no_applic_k - && funky_type != FUNKY_XTERM) - || funky_type == FUNKY_VT400 || nethack_keypad || compose_state) { + if (left_alt || (wgs->term->app_keypad_keys && !no_applic_k + && funky_type != FUNKY_XTERM) || + funky_type == FUNKY_VT400 || nethack_keypad || wgs->compose_state) { if ((HIWORD(lParam) & KF_EXTENDED) == 0) { int nParam = 0; switch (wParam) { @@ -4337,47 +4339,48 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam, } /* If a key is pressed and AltGr is not active */ - if (key_down && (keystate[VK_RMENU] & 0x80) == 0 && !compose_state) { + if (key_down && (keystate[VK_RMENU] & 0x80) == 0 && !wgs->compose_state) { /* Okay, prepare for most alts then ... */ if (left_alt) *p++ = '\033'; /* Lets see if it's a pattern we know all about ... */ if (wParam == VK_PRIOR && shift_state == 1) { - SendMessage(wgs.term_hwnd, WM_VSCROLL, SB_PAGEUP, 0); + SendMessage(wgs->term_hwnd, WM_VSCROLL, SB_PAGEUP, 0); return 0; } if (wParam == VK_PRIOR && shift_state == 3) { /* ctrl-shift-pageup */ - SendMessage(wgs.term_hwnd, WM_VSCROLL, SB_TOP, 0); + SendMessage(wgs->term_hwnd, WM_VSCROLL, SB_TOP, 0); return 0; } if (wParam == VK_NEXT && shift_state == 3) { /* ctrl-shift-pagedown */ - SendMessage(wgs.term_hwnd, WM_VSCROLL, SB_BOTTOM, 0); + SendMessage(wgs->term_hwnd, WM_VSCROLL, SB_BOTTOM, 0); return 0; } if (wParam == VK_PRIOR && shift_state == 2) { - SendMessage(wgs.term_hwnd, WM_VSCROLL, SB_LINEUP, 0); + SendMessage(wgs->term_hwnd, WM_VSCROLL, SB_LINEUP, 0); return 0; } if (wParam == VK_NEXT && shift_state == 1) { - SendMessage(wgs.term_hwnd, WM_VSCROLL, SB_PAGEDOWN, 0); + SendMessage(wgs->term_hwnd, WM_VSCROLL, SB_PAGEDOWN, 0); return 0; } if (wParam == VK_NEXT && shift_state == 2) { - SendMessage(wgs.term_hwnd, WM_VSCROLL, SB_LINEDOWN, 0); + SendMessage(wgs->term_hwnd, WM_VSCROLL, SB_LINEDOWN, 0); return 0; } if ((wParam == VK_PRIOR || wParam == VK_NEXT) && shift_state == 3) { - term_scroll_to_selection(term, (wParam == VK_PRIOR ? 0 : 1)); + term_scroll_to_selection(wgs->term, (wParam == VK_PRIOR ? 0 : 1)); return 0; } if (wParam == VK_INSERT && shift_state == 2) { - switch (conf_get_int(conf, CONF_ctrlshiftins)) { + switch (conf_get_int(wgs->conf, CONF_ctrlshiftins)) { case CLIPUI_IMPLICIT: break; /* no need to re-copy to CLIP_LOCAL */ case CLIPUI_EXPLICIT: - term_request_copy(term, clips_system, lenof(clips_system)); + term_request_copy(wgs->term, clips_system, + lenof(clips_system)); break; default: break; @@ -4385,12 +4388,12 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam, return 0; } if (wParam == VK_INSERT && shift_state == 1) { - switch (conf_get_int(conf, CONF_ctrlshiftins)) { + switch (conf_get_int(wgs->conf, CONF_ctrlshiftins)) { case CLIPUI_IMPLICIT: - term_request_paste(term, CLIP_LOCAL); + term_request_paste(wgs->term, CLIP_LOCAL); break; case CLIPUI_EXPLICIT: - term_request_paste(term, CLIP_SYSTEM); + term_request_paste(wgs->term, CLIP_SYSTEM); break; default: break; @@ -4398,11 +4401,12 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam, return 0; } if (wParam == 'C' && shift_state == 3) { - switch (conf_get_int(conf, CONF_ctrlshiftcv)) { + switch (conf_get_int(wgs->conf, CONF_ctrlshiftcv)) { case CLIPUI_IMPLICIT: break; /* no need to re-copy to CLIP_LOCAL */ case CLIPUI_EXPLICIT: - term_request_copy(term, clips_system, lenof(clips_system)); + term_request_copy(wgs->term, clips_system, + lenof(clips_system)); break; default: break; @@ -4410,47 +4414,50 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam, return 0; } if (wParam == 'V' && shift_state == 3) { - switch (conf_get_int(conf, CONF_ctrlshiftcv)) { + switch (conf_get_int(wgs->conf, CONF_ctrlshiftcv)) { case CLIPUI_IMPLICIT: - term_request_paste(term, CLIP_LOCAL); + term_request_paste(wgs->term, CLIP_LOCAL); break; case CLIPUI_EXPLICIT: - term_request_paste(term, CLIP_SYSTEM); + term_request_paste(wgs->term, CLIP_SYSTEM); break; default: break; } return 0; } - if (left_alt && wParam == VK_F4 && conf_get_bool(conf, CONF_alt_f4)) { + if (left_alt && wParam == VK_F4 && + conf_get_bool(wgs->conf, CONF_alt_f4)) { return -1; } - if (left_alt && wParam == VK_SPACE && conf_get_bool(conf, - CONF_alt_space)) { - SendMessage(wgs.term_hwnd, WM_SYSCOMMAND, SC_KEYMENU, 0); + if (left_alt && wParam == VK_SPACE && + conf_get_bool(wgs->conf, CONF_alt_space)) { + SendMessage(wgs->term_hwnd, WM_SYSCOMMAND, SC_KEYMENU, 0); return -1; } if (left_alt && wParam == VK_RETURN && - conf_get_bool(conf, CONF_fullscreenonaltenter) && - (conf_get_int(conf, CONF_resize_action) != RESIZE_DISABLED)) { + conf_get_bool(wgs->conf, CONF_fullscreenonaltenter) && + (conf_get_int(wgs->conf, CONF_resize_action) != RESIZE_DISABLED)) { if ((HIWORD(lParam) & (KF_UP | KF_REPEAT)) != KF_REPEAT) - flip_full_screen(); + flip_full_screen(wgs); return -1; } /* Control-Numlock for app-keypad mode switch */ if (wParam == VK_PAUSE && shift_state == 2) { - term->app_keypad_keys = !term->app_keypad_keys; + wgs->term->app_keypad_keys = !wgs->term->app_keypad_keys; return 0; } if (wParam == VK_BACK && shift_state == 0) { /* Backspace */ - *p++ = (conf_get_bool(conf, CONF_bksp_is_delete) ? 0x7F : 0x08); + *p++ = (conf_get_bool(wgs->conf, CONF_bksp_is_delete) ? + 0x7F : 0x08); *p++ = 0; return -2; } if (wParam == VK_BACK && shift_state == 1) { /* Shift Backspace */ /* We do the opposite of what is configured */ - *p++ = (conf_get_bool(conf, CONF_bksp_is_delete) ? 0x08 : 0x7F); + *p++ = (conf_get_bool(wgs->conf, CONF_bksp_is_delete) ? + 0x08 : 0x7F); *p++ = 0; return -2; } @@ -4469,8 +4476,8 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam, return p - output; } if (wParam == VK_CANCEL && shift_state == 2) { /* Ctrl-Break */ - if (backend) - backend_special(backend, SS_BRK, 0); + if (wgs->backend) + backend_special(wgs->backend, SS_BRK, 0); return 0; } if (wParam == VK_PAUSE) { /* Break/Pause */ @@ -4529,7 +4536,7 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam, { int nchars = format_numeric_keypad_key( - (char *)p, term, keypad_key, + (char *)p, wgs->term, keypad_key, shift_state & 1, shift_state & 2); if (!nchars) { /* @@ -4581,7 +4588,7 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam, case VK_F20: fkey_number = 20; goto numbered_function_key; numbered_function_key: consumed_alt = false; - p += format_function_key((char *)p, term, fkey_number, + p += format_function_key((char *)p, wgs->term, fkey_number, shift_state & 1, shift_state & 2, left_alt, &consumed_alt); if (consumed_alt) @@ -4600,7 +4607,7 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam, if (shift_state & 2) break; - p += format_small_keypad_key((char *)p, term, sk_key, + p += format_small_keypad_key((char *)p, wgs->term, sk_key, shift_state & 1, shift_state & 2, left_alt, &consumed_alt); if (consumed_alt) @@ -4615,7 +4622,7 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam, case VK_CLEAR: xkey = 'G'; goto arrow_key; /* close enough */ arrow_key: consumed_alt = false; - p += format_arrow_key((char *)p, term, xkey, shift_state & 1, + p += format_arrow_key((char *)p, wgs->term, xkey, shift_state & 1, shift_state & 2, left_alt, &consumed_alt); if (consumed_alt) left_alt = false; /* supersedes the usual prefixing of Esc */ @@ -4627,7 +4634,7 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam, goto numeric_keypad; } ordinary_return_key: - if (shift_state == 0 && term->cr_lf_return) { + if (shift_state == 0 && wgs->term->cr_lf_return) { *p++ = '\r'; *p++ = '\n'; return p - output; @@ -4646,7 +4653,7 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam, /* helg: clear CAPS LOCK state if caps lock switches to cyrillic */ if(keystate[VK_CAPITAL] != 0 && - conf_get_bool(conf, CONF_xlat_capslockcyr)) { + conf_get_bool(wgs->conf, CONF_xlat_capslockcyr)) { capsOn= !left_alt; keystate[VK_CAPITAL] = 0; } @@ -4706,31 +4713,32 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam, for (i = 0; i < r; i++) { wchar_t wch = keys_unicode[i]; - if (compose_state == 2 && wch >= ' ' && wch < 0x80) { + if (wgs->compose_state == 2 && wch >= ' ' && wch < 0x80) { compose_char = wch; - compose_state++; + wgs->compose_state++; continue; } - if (compose_state == 3 && wch >= ' ' && wch < 0x80) { + if (wgs->compose_state == 3 && wch >= ' ' && wch < 0x80) { int nc; - compose_state = 0; + wgs->compose_state = 0; if ((nc = check_compose(compose_char, wch)) == -1) { MessageBeep(MB_ICONHAND); return 0; } keybuf = nc; - term_keyinputw(term, &keybuf, 1); + term_keyinputw(wgs->term, &keybuf, 1); continue; } - compose_state = 0; + wgs->compose_state = 0; if (!key_down) { if (alt_sum) { - if (in_utf(term) || ucsdata.dbcs_screenfont) { + if (in_utf(wgs->term) || + wgs->ucsdata.dbcs_screenfont) { keybuf = alt_sum; - term_keyinputw(term, &keybuf, 1); + term_keyinputw(wgs->term, &keybuf, 1); } else { char ch = (char) alt_sum; /* @@ -4742,26 +4750,28 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam, * messages. We _have_ to buffer * everything we're sent. */ - term_keyinput(term, -1, &ch, 1); + term_keyinput(wgs->term, -1, &ch, 1); } alt_sum = 0; } else { - term_keyinputw(term, &wch, 1); + term_keyinputw(wgs->term, &wch, 1); } } else { if(capsOn && wch < 0x80) { WCHAR cbuf[2]; cbuf[0] = 27; cbuf[1] = xlat_uskbd2cyrllic(wch); - term_keyinputw(term, cbuf+!left_alt, 1+!!left_alt); + term_keyinputw( + wgs->term, cbuf+!left_alt, 1+!!left_alt); } else { WCHAR cbuf[2]; cbuf[0] = '\033'; cbuf[1] = wch; - term_keyinputw(term, cbuf +!left_alt, 1+!!left_alt); + term_keyinputw( + wgs->term, cbuf +!left_alt, 1+!!left_alt); } } - show_mouseptr(false); + show_mouseptr(wgs, false); } /* This is so the ALT-Numpad and dead keys work correctly. */ @@ -4773,7 +4783,8 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam, if (!left_alt) keys_unicode[0] = 0; /* If we will be using alt_sum fix the 256s */ - else if (keys_unicode[0] && (in_utf(term) || ucsdata.dbcs_screenfont)) + else if (keys_unicode[0] && (in_utf(wgs->term) || + wgs->ucsdata.dbcs_screenfont)) keys_unicode[0] = 10; } @@ -4784,7 +4795,7 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam, * we return -1, which means Windows will give the keystroke * its default handling (i.e. bring up the System menu). */ - if (wParam == VK_MENU && !conf_get_bool(conf, CONF_alt_only)) + if (wParam == VK_MENU && !conf_get_bool(wgs->conf, CONF_alt_only)) return 0; return -1; @@ -4792,35 +4803,40 @@ static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam, static void wintw_set_title(TermWin *tw, const char *title, int codepage) { + WinGuiSeat *wgs = container_of(tw, WinGuiSeat, termwin); wchar_t *new_window_name = dup_mb_to_wc(codepage, 0, title); - if (!wcscmp(new_window_name, window_name)) { + if (!wcscmp(new_window_name, wgs->window_name)) { sfree(new_window_name); return; } - sfree(window_name); - window_name = new_window_name; - if (conf_get_bool(conf, CONF_win_name_always) || !IsIconic(wgs.term_hwnd)) - sw_SetWindowText(wgs.term_hwnd, window_name); + sfree(wgs->window_name); + wgs->window_name = new_window_name; + if (conf_get_bool(wgs->conf, CONF_win_name_always) || + !IsIconic(wgs->term_hwnd)) + sw_SetWindowText(wgs->term_hwnd, wgs->window_name); } static void wintw_set_icon_title(TermWin *tw, const char *title, int codepage) { + WinGuiSeat *wgs = container_of(tw, WinGuiSeat, termwin); wchar_t *new_icon_name = dup_mb_to_wc(codepage, 0, title); - if (!wcscmp(new_icon_name, icon_name)) { + if (!wcscmp(new_icon_name, wgs->icon_name)) { sfree(new_icon_name); return; } - sfree(icon_name); - icon_name = new_icon_name; - if (!conf_get_bool(conf, CONF_win_name_always) && IsIconic(wgs.term_hwnd)) - sw_SetWindowText(wgs.term_hwnd, icon_name); + sfree(wgs->icon_name); + wgs->icon_name = new_icon_name; + if (!conf_get_bool(wgs->conf, CONF_win_name_always) && + IsIconic(wgs->term_hwnd)) + sw_SetWindowText(wgs->term_hwnd, wgs->icon_name); } static void wintw_set_scrollbar(TermWin *tw, int total, int start, int page) { + WinGuiSeat *wgs = container_of(tw, WinGuiSeat, termwin); SCROLLINFO si; - if (!conf_get_bool(conf, is_full_screen() ? + if (!conf_get_bool(wgs->conf, is_full_screen(wgs) ? CONF_scrollbar_in_fullscreen : CONF_scrollbar)) return; @@ -4830,92 +4846,98 @@ static void wintw_set_scrollbar(TermWin *tw, int total, int start, int page) si.nMax = total - 1; si.nPage = page; si.nPos = start; - if (wgs.term_hwnd) - SetScrollInfo(wgs.term_hwnd, SB_VERT, &si, true); + if (wgs->term_hwnd) + SetScrollInfo(wgs->term_hwnd, SB_VERT, &si, true); } static bool wintw_setup_draw_ctx(TermWin *tw) { - assert(!wintw_hdc); - wintw_hdc = make_hdc(); - return wintw_hdc != NULL; + WinGuiSeat *wgs = container_of(tw, WinGuiSeat, termwin); + assert(!wgs->wintw_hdc); + wgs->wintw_hdc = make_hdc(wgs); + return wgs->wintw_hdc != NULL; } static void wintw_free_draw_ctx(TermWin *tw) { - assert(wintw_hdc); - free_hdc(wintw_hdc); - wintw_hdc = NULL; + WinGuiSeat *wgs = container_of(tw, WinGuiSeat, termwin); + assert(wgs->wintw_hdc); + free_hdc(wgs, wgs->wintw_hdc); + wgs->wintw_hdc = NULL; } /* * Set up the colour palette. */ -static void init_palette(void) +static void init_palette(WinGuiSeat *wgs) { - pal = NULL; - logpal = snew_plus(LOGPALETTE, (OSC4_NCOLOURS - 1) * sizeof(PALETTEENTRY)); - logpal->palVersion = 0x300; - logpal->palNumEntries = OSC4_NCOLOURS; + wgs->pal = NULL; + wgs->logpal = snew_plus( + LOGPALETTE, (OSC4_NCOLOURS - 1) * sizeof(PALETTEENTRY)); + wgs->logpal->palVersion = 0x300; + wgs->logpal->palNumEntries = OSC4_NCOLOURS; for (unsigned i = 0; i < OSC4_NCOLOURS; i++) - logpal->palPalEntry[i].peFlags = PC_NOCOLLAPSE; + wgs->logpal->palPalEntry[i].peFlags = PC_NOCOLLAPSE; } -static void wintw_palette_set(TermWin *win, unsigned start, +static void wintw_palette_set(TermWin *tw, unsigned start, unsigned ncolours, const rgb *colours_in) { + WinGuiSeat *wgs = container_of(tw, WinGuiSeat, termwin); assert(start <= OSC4_NCOLOURS); assert(ncolours <= OSC4_NCOLOURS - start); for (unsigned i = 0; i < ncolours; i++) { const rgb *in = &colours_in[i]; - PALETTEENTRY *out = &logpal->palPalEntry[i + start]; + PALETTEENTRY *out = &wgs->logpal->palPalEntry[i + start]; out->peRed = in->r; out->peGreen = in->g; out->peBlue = in->b; - colours[i + start] = RGB(in->r, in->g, in->b) ^ colorref_modifier; + wgs->colours[i + start] = + RGB(in->r, in->g, in->b) ^ wgs->colorref_modifier; } bool got_new_palette = false; - if (!tried_pal && conf_get_bool(conf, CONF_try_palette)) { - HDC hdc = GetDC(wgs.term_hwnd); + if (!wgs->tried_pal && conf_get_bool(wgs->conf, CONF_try_palette)) { + HDC hdc = GetDC(wgs->term_hwnd); if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) { - pal = CreatePalette(logpal); - if (pal) { - SelectPalette(hdc, pal, false); + wgs->pal = CreatePalette(wgs->logpal); + if (wgs->pal) { + SelectPalette(hdc, wgs->pal, false); RealizePalette(hdc); SelectPalette(hdc, GetStockObject(DEFAULT_PALETTE), false); /* Convert all RGB() values in colours[] into PALETTERGB(), * and ensure we stick to that later */ - colorref_modifier = PALETTERGB(0, 0, 0) ^ RGB(0, 0, 0); + wgs->colorref_modifier = PALETTERGB(0, 0, 0) ^ RGB(0, 0, 0); for (unsigned i = 0; i < OSC4_NCOLOURS; i++) - colours[i] ^= colorref_modifier; + wgs->colours[i] ^= wgs->colorref_modifier; /* Inhibit the SetPaletteEntries call below */ got_new_palette = true; } } - ReleaseDC(wgs.term_hwnd, hdc); - tried_pal = true; + ReleaseDC(wgs->term_hwnd, hdc); + wgs->tried_pal = true; } - if (pal && !got_new_palette) { + if (wgs->pal && !got_new_palette) { /* We already had a palette, so replace the changed colours in the * existing one. */ - SetPaletteEntries(pal, start, ncolours, logpal->palPalEntry + start); + SetPaletteEntries(wgs->pal, start, ncolours, + wgs->logpal->palPalEntry + start); - HDC hdc = make_hdc(); - UnrealizeObject(pal); + HDC hdc = make_hdc(wgs); + UnrealizeObject(wgs->pal); RealizePalette(hdc); - free_hdc(hdc); + free_hdc(wgs, hdc); } if (start <= OSC4_COLOUR_bg && OSC4_COLOUR_bg < start + ncolours) { /* If Default Background changes, we need to ensure any space between * the text area and the window border is redrawn. */ - InvalidateRect(wgs.term_hwnd, NULL, true); + InvalidateRect(wgs->term_hwnd, NULL, true); } } @@ -4964,6 +4986,7 @@ static void wintw_clip_write( TermWin *tw, int clipboard, wchar_t *data, int *attr, truecolour *truecolour, int len, bool must_deselect) { + WinGuiSeat *wgs = container_of(tw, WinGuiSeat, termwin); HGLOBAL clipdata, clipdata2, clipdata3; int len2; void *lock, *lock2, *lock3; @@ -4999,7 +5022,7 @@ static void wintw_clip_write( memcpy(lock, data, len * sizeof(wchar_t)); WideCharToMultiByte(CP_ACP, 0, data, len, lock2, len2, NULL, NULL); - if (conf_get_bool(conf, CONF_rtf_paste)) { + if (conf_get_bool(wgs->conf, CONF_rtf_paste)) { wchar_t unitab[256]; strbuf *rtf = strbuf_new(); unsigned char *tdata = (unsigned char *)lock2; @@ -5016,7 +5039,7 @@ static void wintw_clip_write( int palette[OSC4_NCOLOURS]; int numcolours; tree234 *rgbtree = NULL; - FontSpec *font = conf_get_fontspec(conf, CONF_font); + FontSpec *font = conf_get_fontspec(wgs->conf, CONF_font); get_unitab(CP_ACP, unitab, 0); @@ -5045,7 +5068,7 @@ static void wintw_clip_write( bgcolour = tmpcolour; } - if (bold_colours && (attr[i] & ATTR_BOLD)) { + if (wgs->bold_colours && (attr[i] & ATTR_BOLD)) { if (fgcolour < 8) /* ANSI colours */ fgcolour += 8; else if (fgcolour >= 256) /* Default colours */ @@ -5107,7 +5130,7 @@ static void wintw_clip_write( for (i = 0; i < OSC4_NCOLOURS; i++) { if (palette[i] != 0) { - const PALETTEENTRY *pe = &logpal->palPalEntry[i]; + const PALETTEENTRY *pe = &wgs->logpal->palPalEntry[i]; put_fmt(rtf, "\\red%d\\green%d\\blue%d;", pe->peRed, pe->peGreen, pe->peBlue); } @@ -5186,7 +5209,8 @@ static void wintw_clip_write( bg = tmpref; } - if (bold_colours && (attr[tindex] & ATTR_BOLD) && (fgcolour >= 0)) { + if (wgs->bold_colours && (attr[tindex] & ATTR_BOLD) && + (fgcolour >= 0)) { if (fgcolour < 8) /* ANSI colours */ fgcolour += 8; else if (fgcolour >= 256) /* Default colours */ @@ -5203,7 +5227,7 @@ static void wintw_clip_write( /* * Collect other attributes */ - if (bold_font_mode != BOLD_NONE) + if (wgs->bold_font_mode != BOLD_NONE) attrBold = attr[tindex] & ATTR_BOLD; else attrBold = 0; @@ -5222,7 +5246,8 @@ static void wintw_clip_write( bgcolour = -1; /* No coloring */ if (fgcolour >= 256) { /* Default colour */ - if (bold_colours && (fgcolour & 1) && bgcolour == -1) + if (wgs->bold_colours && (fgcolour & 1) && + bgcolour == -1) attrBold = ATTR_BOLD; /* Emphasize text with bold attribute */ fgcolour = -1; /* No coloring */ @@ -5350,9 +5375,9 @@ static void wintw_clip_write( GlobalUnlock(clipdata2); if (!must_deselect) - SendMessage(wgs.term_hwnd, WM_IGNORE_CLIP, true, 0); + SendMessage(wgs->term_hwnd, WM_IGNORE_CLIP, true, 0); - if (OpenClipboard(wgs.term_hwnd)) { + if (OpenClipboard(wgs->term_hwnd)) { EmptyClipboard(); SetClipboardData(CF_UNICODETEXT, clipdata); SetClipboardData(CF_TEXT, clipdata2); @@ -5365,7 +5390,7 @@ static void wintw_clip_write( } if (!must_deselect) - SendMessage(wgs.term_hwnd, WM_IGNORE_CLIP, false, 0); + SendMessage(wgs->term_hwnd, WM_IGNORE_CLIP, false, 0); } static DWORD WINAPI clipboard_read_threadfunc(void *param) @@ -5387,7 +5412,7 @@ static DWORD WINAPI clipboard_read_threadfunc(void *param) return 0; } -static void process_clipdata(HGLOBAL clipdata, bool unicode) +static void process_clipdata(WinGuiSeat *wgs, HGLOBAL clipdata, bool unicode) { wchar_t *clipboard_contents = NULL; size_t clipboard_length = 0; @@ -5403,7 +5428,7 @@ static void process_clipdata(HGLOBAL clipdata, bool unicode) clipboard_contents = snewn(clipboard_length + 1, wchar_t); memcpy(clipboard_contents, p, clipboard_length * sizeof(wchar_t)); clipboard_contents[clipboard_length] = L'\0'; - term_do_paste(term, clipboard_contents, clipboard_length); + term_do_paste(wgs->term, clipboard_contents, clipboard_length); } } else { char *s = GlobalLock(clipdata); @@ -5416,7 +5441,7 @@ static void process_clipdata(HGLOBAL clipdata, bool unicode) clipboard_contents, i); clipboard_length = i - 1; clipboard_contents[clipboard_length] = L'\0'; - term_do_paste(term, clipboard_contents, clipboard_length); + term_do_paste(wgs->term, clipboard_contents, clipboard_length); } } @@ -5425,6 +5450,7 @@ static void process_clipdata(HGLOBAL clipdata, bool unicode) static void wintw_clip_request_paste(TermWin *tw, int clipboard) { + WinGuiSeat *wgs = container_of(tw, WinGuiSeat, termwin); assert(clipboard == CLIP_SYSTEM); /* @@ -5445,7 +5471,7 @@ static void wintw_clip_request_paste(TermWin *tw, int clipboard) */ DWORD in_threadid; /* required for Win9x */ HANDLE hThread = CreateThread(NULL, 0, clipboard_read_threadfunc, - wgs.term_hwnd, 0, &in_threadid); + wgs->term_hwnd, 0, &in_threadid); if (hThread) CloseHandle(hThread); /* we don't need the thread handle */ } @@ -5461,9 +5487,9 @@ void modalfatalbox(const char *fmt, ...) va_start(ap, fmt); message = dupvprintf(fmt, ap); va_end(ap); - show_mouseptr(true); + show_mouseptr(NULL, true); title = dupprintf("%s Fatal Error", appname); - MessageBox(wgs.term_hwnd, message, title, + MessageBox(find_window_for_msgbox(), message, title, MB_SYSTEMMODAL | MB_ICONERROR | MB_OK); sfree(message); sfree(title); @@ -5481,19 +5507,20 @@ void nonfatal(const char *fmt, ...) va_start(ap, fmt); message = dupvprintf(fmt, ap); va_end(ap); - show_mouseptr(true); + show_mouseptr(NULL, true); title = dupprintf("%s Error", appname); - MessageBox(wgs.term_hwnd, message, title, MB_ICONERROR | MB_OK); + MessageBox(find_window_for_msgbox(), message, title, MB_ICONERROR | MB_OK); sfree(message); sfree(title); } -static bool flash_window_ex(DWORD dwFlags, UINT uCount, DWORD dwTimeout) +static bool flash_window_ex(WinGuiSeat *wgs, DWORD dwFlags, + UINT uCount, DWORD dwTimeout) { if (p_FlashWindowEx) { FLASHWINFO fi; fi.cbSize = sizeof(fi); - fi.hwnd = wgs.term_hwnd; + fi.hwnd = wgs->term_hwnd; fi.dwFlags = dwFlags; fi.uCount = uCount; fi.dwTimeout = dwTimeout; @@ -5503,18 +5530,15 @@ static bool flash_window_ex(DWORD dwFlags, UINT uCount, DWORD dwTimeout) return false; /* shrug */ } -static void flash_window(int mode); -static long next_flash; -static bool flashing = false; - /* * Timer for platforms where we must maintain window flashing manually * (e.g., Win95). */ -static void flash_window_timer(void *ctx, unsigned long now) +static void flash_window_timer(void *vctx, unsigned long now) { - if (flashing && now == next_flash) { - flash_window(1); + WinGuiSeat *wgs = (WinGuiSeat *)vctx; + if (wgs->flashing && now == wgs->next_flash) { + flash_window(wgs, 1); } } @@ -5522,23 +5546,23 @@ static void flash_window_timer(void *ctx, unsigned long now) * Manage window caption / taskbar flashing, if enabled. * 0 = stop, 1 = maintain, 2 = start */ -static void flash_window(int mode) +static void flash_window(WinGuiSeat *wgs, int mode) { - int beep_ind = conf_get_int(conf, CONF_beep_ind); + int beep_ind = conf_get_int(wgs->conf, CONF_beep_ind); if ((mode == 0) || (beep_ind == B_IND_DISABLED)) { /* stop */ - if (flashing) { - flashing = false; + if (wgs->flashing) { + wgs->flashing = false; if (p_FlashWindowEx) - flash_window_ex(FLASHW_STOP, 0, 0); + flash_window_ex(wgs, FLASHW_STOP, 0, 0); else - FlashWindow(wgs.term_hwnd, false); + FlashWindow(wgs->term_hwnd, false); } } else if (mode == 2) { /* start */ - if (!flashing) { - flashing = true; + if (!wgs->flashing) { + wgs->flashing = true; if (p_FlashWindowEx) { /* For so-called "steady" mode, we use uCount=2, which * seems to be the traditional number of flashes used @@ -5546,23 +5570,21 @@ static void flash_window(int mode) * uCount=0 appears to enable continuous flashing, per * "flashing" mode, although I haven't seen this * documented. */ - flash_window_ex(FLASHW_ALL | FLASHW_TIMER, + flash_window_ex(wgs, FLASHW_ALL | FLASHW_TIMER, (beep_ind == B_IND_FLASH ? 0 : 2), 0 /* system cursor blink rate */); /* No need to schedule timer */ } else { - FlashWindow(wgs.term_hwnd, true); - next_flash = schedule_timer(450, flash_window_timer, - wgs.term_hwnd); + FlashWindow(wgs->term_hwnd, true); + wgs->next_flash = schedule_timer(450, flash_window_timer, wgs); } } } else if ((mode == 1) && (beep_ind == B_IND_FLASH)) { /* maintain */ - if (flashing && !p_FlashWindowEx) { - FlashWindow(wgs.term_hwnd, true); /* toggle */ - next_flash = schedule_timer(450, flash_window_timer, - wgs.term_hwnd); + if (wgs->flashing && !p_FlashWindowEx) { + FlashWindow(wgs->term_hwnd, true); /* toggle */ + wgs->next_flash = schedule_timer(450, flash_window_timer, wgs); } } } @@ -5572,6 +5594,7 @@ static void flash_window(int mode) */ static void wintw_bell(TermWin *tw, int mode) { + WinGuiSeat *wgs = container_of(tw, WinGuiSeat, termwin); if (mode == BELL_DEFAULT) { /* * For MessageBeep style bells, we want to be careful of @@ -5592,20 +5615,21 @@ static void wintw_bell(TermWin *tw, int mode) */ lastbeep = GetTickCount(); } else if (mode == BELL_WAVEFILE) { - Filename *bell_wavefile = conf_get_filename(conf, CONF_bell_wavefile); + Filename *bell_wavefile = conf_get_filename( + wgs->conf, CONF_bell_wavefile); if (!p_PlaySound || !p_PlaySound(bell_wavefile->path, NULL, SND_ASYNC | SND_FILENAME)) { char *buf, *otherbuf; - show_mouseptr(true); + show_mouseptr(wgs, true); buf = dupprintf( "Unable to play sound file\n%s\nUsing default sound instead", bell_wavefile->path); otherbuf = dupprintf("%s Sound Error", appname); - MessageBox(wgs.term_hwnd, buf, otherbuf, + MessageBox(wgs->term_hwnd, buf, otherbuf, MB_OK | MB_ICONEXCLAMATION); sfree(buf); sfree(otherbuf); - conf_set_int(conf, CONF_beep, BELL_DEFAULT); + conf_set_int(wgs->conf, CONF_beep, BELL_DEFAULT); } } else if (mode == BELL_PCSPEAKER) { static long lastbeep = 0; @@ -5626,8 +5650,8 @@ static void wintw_bell(TermWin *tw, int mode) lastbeep = GetTickCount(); } /* Otherwise, either visual bell or disabled; do nothing here */ - if (!term->has_focus) { - flash_window(2); /* start */ + if (!wgs->term->has_focus) { + flash_window(wgs, 2); /* start */ } } @@ -5637,12 +5661,13 @@ static void wintw_bell(TermWin *tw, int mode) */ static void wintw_set_minimised(TermWin *tw, bool minimised) { - if (IsIconic(wgs.term_hwnd)) { + WinGuiSeat *wgs = container_of(tw, WinGuiSeat, termwin); + if (IsIconic(wgs->term_hwnd)) { if (!minimised) - ShowWindow(wgs.term_hwnd, SW_RESTORE); + ShowWindow(wgs->term_hwnd, SW_RESTORE); } else { if (minimised) - ShowWindow(wgs.term_hwnd, SW_MINIMIZE); + ShowWindow(wgs->term_hwnd, SW_MINIMIZE); } } @@ -5651,13 +5676,14 @@ static void wintw_set_minimised(TermWin *tw, bool minimised) */ static void wintw_move(TermWin *tw, int x, int y) { - int resize_action = conf_get_int(conf, CONF_resize_action); + WinGuiSeat *wgs = container_of(tw, WinGuiSeat, termwin); + int resize_action = conf_get_int(wgs->conf, CONF_resize_action); if (resize_action == RESIZE_DISABLED || resize_action == RESIZE_FONT || - IsZoomed(wgs.term_hwnd)) + IsZoomed(wgs->term_hwnd)) return; - SetWindowPos(wgs.term_hwnd, NULL, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER); + SetWindowPos(wgs->term_hwnd, NULL, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER); } /* @@ -5666,9 +5692,10 @@ static void wintw_move(TermWin *tw, int x, int y) */ static void wintw_set_zorder(TermWin *tw, bool top) { - if (conf_get_bool(conf, CONF_alwaysontop)) + WinGuiSeat *wgs = container_of(tw, WinGuiSeat, termwin); + if (conf_get_bool(wgs->conf, CONF_alwaysontop)) return; /* ignore */ - SetWindowPos(wgs.term_hwnd, top ? HWND_TOP : HWND_BOTTOM, 0, 0, 0, 0, + SetWindowPos(wgs->term_hwnd, top ? HWND_TOP : HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE); } @@ -5677,7 +5704,8 @@ static void wintw_set_zorder(TermWin *tw, bool top) */ static void wintw_refresh(TermWin *tw) { - InvalidateRect(wgs.term_hwnd, NULL, true); + WinGuiSeat *wgs = container_of(tw, WinGuiSeat, termwin); + InvalidateRect(wgs->term_hwnd, NULL, true); } /* @@ -5686,23 +5714,24 @@ static void wintw_refresh(TermWin *tw) */ static void wintw_set_maximised(TermWin *tw, bool maximised) { - if (IsZoomed(wgs.term_hwnd)) { + WinGuiSeat *wgs = container_of(tw, WinGuiSeat, termwin); + if (IsZoomed(wgs->term_hwnd)) { if (!maximised) - ShowWindow(wgs.term_hwnd, SW_RESTORE); + ShowWindow(wgs->term_hwnd, SW_RESTORE); } else { if (maximised) - ShowWindow(wgs.term_hwnd, SW_MAXIMIZE); + ShowWindow(wgs->term_hwnd, SW_MAXIMIZE); } } /* * See if we're in full-screen mode. */ -static bool is_full_screen() +static bool is_full_screen(WinGuiSeat *wgs) { - if (!IsZoomed(wgs.term_hwnd)) + if (!IsZoomed(wgs->term_hwnd)) return false; - if (GetWindowLongPtr(wgs.term_hwnd, GWL_STYLE) & WS_CAPTION) + if (GetWindowLongPtr(wgs->term_hwnd, GWL_STYLE) & WS_CAPTION) return false; return true; } @@ -5710,13 +5739,13 @@ static bool is_full_screen() /* Get the rect/size of a full screen window using the nearest available * monitor in multimon systems; default to something sensible if only * one monitor is present. */ -static bool get_fullscreen_rect(RECT *ss) +static bool get_fullscreen_rect(WinGuiSeat *wgs, RECT *ss) { #if defined(MONITOR_DEFAULTTONEAREST) && !defined(NO_MULTIMON) if (p_GetMonitorInfoA && p_MonitorFromWindow) { HMONITOR mon; MONITORINFO mi; - mon = p_MonitorFromWindow(wgs.term_hwnd, MONITOR_DEFAULTTONEAREST); + mon = p_MonitorFromWindow(wgs->term_hwnd, MONITOR_DEFAULTTONEAREST); mi.cbSize = sizeof(mi); p_GetMonitorInfoA(mon, &mi); @@ -5738,63 +5767,64 @@ static bool get_fullscreen_rect(RECT *ss) * Go full-screen. This should only be called when we are already * maximised. */ -static void make_full_screen() +static void make_full_screen(WinGuiSeat *wgs) { DWORD style; RECT ss; - assert(IsZoomed(wgs.term_hwnd)); + assert(IsZoomed(wgs->term_hwnd)); - if (is_full_screen()) + if (is_full_screen(wgs)) return; /* Remove the window furniture. */ - style = GetWindowLongPtr(wgs.term_hwnd, GWL_STYLE); + style = GetWindowLongPtr(wgs->term_hwnd, GWL_STYLE); style &= ~(WS_CAPTION | WS_BORDER | WS_THICKFRAME); - if (conf_get_bool(conf, CONF_scrollbar_in_fullscreen)) + if (conf_get_bool(wgs->conf, CONF_scrollbar_in_fullscreen)) style |= WS_VSCROLL; else style &= ~WS_VSCROLL; - SetWindowLongPtr(wgs.term_hwnd, GWL_STYLE, style); + SetWindowLongPtr(wgs->term_hwnd, GWL_STYLE, style); /* Resize ourselves to exactly cover the nearest monitor. */ - get_fullscreen_rect(&ss); - SetWindowPos(wgs.term_hwnd, HWND_TOP, ss.left, ss.top, + get_fullscreen_rect(wgs, &ss); + SetWindowPos(wgs->term_hwnd, HWND_TOP, ss.left, ss.top, ss.right - ss.left, ss.bottom - ss.top, SWP_FRAMECHANGED); /* We may have changed size as a result */ - reset_window(0); + reset_window(wgs, 0); /* Tick the menu item in the System and context menus. */ { int i; - for (i = 0; i < lenof(popup_menus); i++) - CheckMenuItem(popup_menus[i].menu, IDM_FULLSCREEN, MF_CHECKED); + for (i = 0; i < lenof(wgs->popup_menus); i++) + CheckMenuItem(wgs->popup_menus[i].menu, + IDM_FULLSCREEN, MF_CHECKED); } } /* * Clear the full-screen attributes. */ -static void clear_full_screen() +static void clear_full_screen(WinGuiSeat *wgs) { DWORD oldstyle, style; /* Reinstate the window furniture. */ - style = oldstyle = GetWindowLongPtr(wgs.term_hwnd, GWL_STYLE); + style = oldstyle = GetWindowLongPtr(wgs->term_hwnd, GWL_STYLE); style |= WS_CAPTION | WS_BORDER; - if (conf_get_int(conf, CONF_resize_action) == RESIZE_DISABLED) + if (conf_get_int(wgs->conf, CONF_resize_action) == RESIZE_DISABLED) style &= ~WS_THICKFRAME; else style |= WS_THICKFRAME; - if (conf_get_bool(conf, CONF_scrollbar)) + if (conf_get_bool(wgs->conf, CONF_scrollbar)) style |= WS_VSCROLL; else style &= ~WS_VSCROLL; if (style != oldstyle) { - SetWindowLongPtr(wgs.term_hwnd, GWL_STYLE, style); - SetWindowPos(wgs.term_hwnd, NULL, 0, 0, 0, 0, + SetWindowLongPtr(wgs->term_hwnd, GWL_STYLE, style); + SetWindowPos(wgs->term_hwnd, NULL, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED); } @@ -5802,36 +5832,39 @@ static void clear_full_screen() /* Untick the menu item in the System and context menus. */ { int i; - for (i = 0; i < lenof(popup_menus); i++) - CheckMenuItem(popup_menus[i].menu, IDM_FULLSCREEN, MF_UNCHECKED); + for (i = 0; i < lenof(wgs->popup_menus); i++) + CheckMenuItem(wgs->popup_menus[i].menu, + IDM_FULLSCREEN, MF_UNCHECKED); } } /* * Toggle full-screen mode. */ -static void flip_full_screen() +static void flip_full_screen(WinGuiSeat *wgs) { - if (is_full_screen()) { - ShowWindow(wgs.term_hwnd, SW_RESTORE); - } else if (IsZoomed(wgs.term_hwnd)) { - make_full_screen(); + if (is_full_screen(wgs)) { + ShowWindow(wgs->term_hwnd, SW_RESTORE); + } else if (IsZoomed(wgs->term_hwnd)) { + make_full_screen(wgs); } else { - SendMessage(wgs.term_hwnd, WM_FULLSCR_ON_MAX, 0, 0); - ShowWindow(wgs.term_hwnd, SW_MAXIMIZE); + SendMessage(wgs->term_hwnd, WM_FULLSCR_ON_MAX, 0, 0); + ShowWindow(wgs->term_hwnd, SW_MAXIMIZE); } } static size_t win_seat_output(Seat *seat, SeatOutputType type, const void *data, size_t len) { - return term_data(term, data, len); + WinGuiSeat *wgs = container_of(seat, WinGuiSeat, seat); + return term_data(wgs->term, data, len); } -static void wintw_unthrottle(TermWin *win, size_t bufsize) +static void wintw_unthrottle(TermWin *tw, size_t bufsize) { - if (backend) - backend_unthrottle(backend, bufsize); + WinGuiSeat *wgs = container_of(tw, WinGuiSeat, termwin); + if (wgs->backend) + backend_unthrottle(wgs->backend, bufsize); } static bool win_seat_eof(Seat *seat) @@ -5841,16 +5874,18 @@ static bool win_seat_eof(Seat *seat) static SeatPromptResult win_seat_get_userpass_input(Seat *seat, prompts_t *p) { + WinGuiSeat *wgs = container_of(seat, WinGuiSeat, seat); SeatPromptResult spr; - spr = cmdline_get_passwd_input(p, &cmdline_get_passwd_state, true); + spr = cmdline_get_passwd_input(p, &wgs->cmdline_get_passwd_state, true); if (spr.kind == SPRK_INCOMPLETE) - spr = term_get_userpass_input(term, p); + spr = term_get_userpass_input(wgs->term, p); return spr; } static void win_seat_set_trust_status(Seat *seat, bool trusted) { - term_set_trust_status(term, trusted); + WinGuiSeat *wgs = container_of(seat, WinGuiSeat, seat); + term_set_trust_status(wgs->term, trusted); } static bool win_seat_can_set_trust_status(Seat *seat) @@ -5860,14 +5895,16 @@ static bool win_seat_can_set_trust_status(Seat *seat) static bool win_seat_get_cursor_position(Seat *seat, int *x, int *y) { - term_get_cursor_position(term, x, y); + WinGuiSeat *wgs = container_of(seat, WinGuiSeat, seat); + term_get_cursor_position(wgs->term, x, y); return true; } static bool win_seat_get_window_pixel_size(Seat *seat, int *x, int *y) { + WinGuiSeat *wgs = container_of(seat, WinGuiSeat, seat); RECT r; - GetWindowRect(wgs.term_hwnd, &r); + GetWindowRect(wgs->term_hwnd, &r); *x = r.right - r.left; *y = r.bottom - r.top; return true;