2006-04-23 18:26:03 +00:00
|
|
|
/*
|
|
|
|
* window.c - the PuTTY(tel) main program, which runs a PuTTY terminal
|
|
|
|
* emulator and backend in a window.
|
|
|
|
*/
|
|
|
|
|
1999-01-08 13:02:13 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
1999-11-22 10:07:24 +00:00
|
|
|
#include <ctype.h>
|
2000-10-09 12:53:32 +00:00
|
|
|
#include <time.h>
|
2006-08-26 10:04:46 +00:00
|
|
|
#include <limits.h>
|
2001-11-07 22:22:53 +00:00
|
|
|
#include <assert.h>
|
1999-01-08 13:02:13 +00:00
|
|
|
|
2017-02-14 23:19:13 +00:00
|
|
|
#ifdef __WINE__
|
|
|
|
#define NO_MULTIMON /* winelib doesn't have this */
|
|
|
|
#endif
|
|
|
|
|
2007-01-16 21:32:02 +00:00
|
|
|
#ifndef NO_MULTIMON
|
|
|
|
#define COMPILE_MULTIMON_STUBS
|
|
|
|
#endif
|
|
|
|
|
1999-01-08 13:02:13 +00:00
|
|
|
#include "putty.h"
|
2002-10-22 16:11:33 +00:00
|
|
|
#include "terminal.h"
|
2000-09-27 15:21:04 +00:00
|
|
|
#include "storage.h"
|
1999-01-08 13:02:13 +00:00
|
|
|
#include "win_res.h"
|
2015-11-24 22:02:24 +00:00
|
|
|
#include "winsecur.h"
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
#include "winseat.h"
|
2017-06-13 04:55:57 +00:00
|
|
|
#include "tree234.h"
|
1999-01-08 13:02:13 +00:00
|
|
|
|
2003-10-12 13:46:12 +00:00
|
|
|
#ifndef NO_MULTIMON
|
|
|
|
#include <multimon.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <imm.h>
|
|
|
|
#include <commctrl.h>
|
|
|
|
#include <richedit.h>
|
|
|
|
#include <mmsystem.h>
|
|
|
|
|
2004-11-02 22:30:24 +00:00
|
|
|
/* From MSDN: In the WM_SYSCOMMAND message, the four low-order bits of
|
|
|
|
* wParam are used by Windows, and should be masked off, so we shouldn't
|
|
|
|
* attempt to store information in them. Hence all these identifiers have
|
2004-11-02 23:06:20 +00:00
|
|
|
* the low 4 bits clear. Also, identifiers should < 0xF000. */
|
2004-11-02 22:30:24 +00:00
|
|
|
|
1999-10-28 16:29:06 +00:00
|
|
|
#define IDM_SHOWLOG 0x0010
|
|
|
|
#define IDM_NEWSESS 0x0020
|
|
|
|
#define IDM_DUPSESS 0x0030
|
2004-08-14 13:04:18 +00:00
|
|
|
#define IDM_RESTART 0x0040
|
|
|
|
#define IDM_RECONF 0x0050
|
|
|
|
#define IDM_CLRSB 0x0060
|
|
|
|
#define IDM_RESET 0x0070
|
2001-12-06 13:28:02 +00:00
|
|
|
#define IDM_HELP 0x0140
|
|
|
|
#define IDM_ABOUT 0x0150
|
|
|
|
#define IDM_SAVEDSESS 0x0160
|
|
|
|
#define IDM_COPYALL 0x0170
|
2019-09-08 19:29:00 +00:00
|
|
|
#define IDM_FULLSCREEN 0x0180
|
2017-12-10 17:16:50 +00:00
|
|
|
#define IDM_COPY 0x0190
|
|
|
|
#define IDM_PASTE 0x01A0
|
2006-02-09 23:06:57 +00:00
|
|
|
#define IDM_SPECIALSEP 0x0200
|
1999-10-28 16:29:06 +00:00
|
|
|
|
2003-04-04 20:21:05 +00:00
|
|
|
#define IDM_SPECIAL_MIN 0x0400
|
|
|
|
#define IDM_SPECIAL_MAX 0x0800
|
|
|
|
|
1999-10-28 16:29:06 +00:00
|
|
|
#define IDM_SAVED_MIN 0x1000
|
2004-11-02 23:06:20 +00:00
|
|
|
#define IDM_SAVED_MAX 0x5000
|
|
|
|
#define MENU_SAVED_STEP 16
|
2004-11-02 17:44:06 +00:00
|
|
|
/* Maximum number of sessions on saved-session submenu */
|
2004-11-02 23:06:20 +00:00
|
|
|
#define MENU_SAVED_MAX ((IDM_SAVED_MAX-IDM_SAVED_MIN) / MENU_SAVED_STEP)
|
1999-01-08 13:02:13 +00:00
|
|
|
|
2005-08-10 18:31:24 +00:00
|
|
|
#define WM_IGNORE_CLIP (WM_APP + 2)
|
|
|
|
#define WM_FULLSCR_ON_MAX (WM_APP + 3)
|
2020-01-30 06:40:21 +00:00
|
|
|
#define WM_GOT_CLIPDATA (WM_APP + 4)
|
1999-01-08 13:02:13 +00:00
|
|
|
|
2000-10-20 18:36:15 +00:00
|
|
|
/* Needed for Chinese support and apparently not always defined. */
|
|
|
|
#ifndef VK_PROCESSKEY
|
|
|
|
#define VK_PROCESSKEY 0xE5
|
|
|
|
#endif
|
|
|
|
|
2001-12-16 12:11:56 +00:00
|
|
|
/* Mouse wheel support. */
|
2001-05-13 11:19:20 +00:00
|
|
|
#ifndef WM_MOUSEWHEEL
|
2019-09-08 19:29:00 +00:00
|
|
|
#define WM_MOUSEWHEEL 0x020A /* not defined in earlier SDKs */
|
2001-12-16 12:11:56 +00:00
|
|
|
#endif
|
|
|
|
#ifndef WHEEL_DELTA
|
|
|
|
#define WHEEL_DELTA 120
|
2001-05-13 11:19:20 +00:00
|
|
|
#endif
|
|
|
|
|
2015-07-27 19:06:02 +00:00
|
|
|
/* VK_PACKET, used to send Unicode characters in WM_KEYDOWNs */
|
|
|
|
#ifndef VK_PACKET
|
|
|
|
#define VK_PACKET 0xE7
|
|
|
|
#endif
|
|
|
|
|
2003-01-25 16:22:49 +00:00
|
|
|
static Mouse_Button translate_button(Mouse_Button button);
|
2020-04-14 19:36:46 +00:00
|
|
|
static void show_mouseptr(bool show);
|
2001-05-06 14:35:20 +00:00
|
|
|
static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
|
|
|
|
static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam,
|
2019-09-08 19:29:00 +00:00
|
|
|
unsigned char *output);
|
1999-01-08 13:02:13 +00:00
|
|
|
static void init_palette(void);
|
2001-09-15 15:54:24 +00:00
|
|
|
static void init_fonts(int, int);
|
2001-05-10 08:34:20 +00:00
|
|
|
static void another_font(int);
|
|
|
|
static void deinit_fonts(void);
|
2001-11-29 21:30:59 +00:00
|
|
|
static void set_input_locale(HKL);
|
2005-04-07 01:36:28 +00:00
|
|
|
static void update_savedsess_menu(void);
|
2013-11-17 14:03:20 +00:00
|
|
|
static void init_winfuncs(void);
|
1999-01-08 13:02:13 +00:00
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
static bool is_full_screen(void);
|
2001-12-07 21:21:03 +00:00
|
|
|
static void make_full_screen(void);
|
|
|
|
static void clear_full_screen(void);
|
|
|
|
static void flip_full_screen(void);
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
static void process_clipdata(HGLOBAL clipdata, bool unicode);
|
2017-12-10 17:16:50 +00:00
|
|
|
static void setup_clipboards(Terminal *, Conf *);
|
2001-12-07 21:21:03 +00:00
|
|
|
|
2001-09-15 15:54:24 +00:00
|
|
|
/* Window layout information */
|
|
|
|
static void reset_window(int);
|
2001-10-17 21:21:03 +00:00
|
|
|
static int extra_width, extra_height;
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
static int font_width, font_height;
|
|
|
|
static bool font_dualwidth, font_varpitch;
|
2001-09-15 15:54:24 +00:00
|
|
|
static int offset_width, offset_height;
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
static bool was_zoomed = false;
|
2001-09-15 15:54:24 +00:00
|
|
|
static int prev_rows, prev_cols;
|
2019-09-08 19:29:00 +00:00
|
|
|
|
2001-05-13 14:42:17 +00:00
|
|
|
static void flash_window(int mode);
|
2001-12-20 14:18:01 +00:00
|
|
|
static void sys_cursor_update(void);
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
static bool get_fullscreen_rect(RECT * ss);
|
2000-03-17 10:34:41 +00:00
|
|
|
|
2001-12-20 14:18:01 +00:00
|
|
|
static int caret_x = -1, caret_y = -1;
|
|
|
|
|
2002-10-30 18:12:46 +00:00
|
|
|
static int kbd_codepage;
|
|
|
|
|
2018-09-11 14:02:59 +00:00
|
|
|
static Ldisc *ldisc;
|
2018-09-11 15:23:38 +00:00
|
|
|
static Backend *backend;
|
2002-10-26 10:16:19 +00:00
|
|
|
|
2003-01-14 18:28:23 +00:00
|
|
|
static struct unicode_data ucsdata;
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
static bool session_closed;
|
|
|
|
static bool reconfiguring = false;
|
2002-10-30 18:12:46 +00:00
|
|
|
|
Rework special-commands system to add an integer argument.
In order to list cross-certifiable host keys in the GUI specials menu,
the SSH backend has been inventing new values on the end of the
Telnet_Special enumeration, starting from the value TS_LOCALSTART.
This is inelegant, and also makes it awkward to break up special
handlers (e.g. to dispatch different specials to different SSH
layers), since if all you know about a special is that it's somewhere
in the TS_LOCALSTART+n space, you can't tell what _general kind_ of
thing it is. Also, if I ever need another open-ended set of specials
in future, I'll have to remember which TS_LOCALSTART+n codes are in
which set.
So here's a revamp that causes every special to take an extra integer
argument. For all previously numbered specials, this argument is
passed as zero and ignored, but there's a new main special code for
SSH host key cross-certification, in which the integer argument is an
index into the backend's list of available keys. TS_LOCALSTART is now
a thing of the past: if I need any other open-ended sets of specials
in future, I can add a new top-level code with a nicely separated
space of arguments.
While I'm at it, I've removed the legacy misnomer 'Telnet_Special'
from the code completely; the enum is now SessionSpecialCode, the
struct containing full details of a menu entry is SessionSpecial, and
the enum values now start SS_ rather than TS_.
2018-09-24 08:35:52 +00:00
|
|
|
static const SessionSpecial *specials = NULL;
|
2006-02-09 23:06:57 +00:00
|
|
|
static HMENU specials_menu = NULL;
|
|
|
|
static int n_specials = 0;
|
2003-04-04 20:21:05 +00:00
|
|
|
|
2004-11-27 13:20:21 +00:00
|
|
|
#define TIMING_TIMER_ID 1234
|
|
|
|
static long timing_next_time;
|
|
|
|
|
2003-11-19 20:48:30 +00:00
|
|
|
static struct {
|
|
|
|
HMENU menu;
|
|
|
|
} popup_menus[2];
|
|
|
|
enum { SYSMENU, CTXMENU };
|
2005-04-07 01:36:28 +00:00
|
|
|
static HMENU savedsess_menu;
|
2003-11-19 20:48:30 +00:00
|
|
|
|
2020-02-02 10:00:42 +00:00
|
|
|
static Conf *conf;
|
Remove remaining uses of the GLOBAL macro.
We now have no remaining things in header files that switch from being
a declaration to a definition depending on an awkward #define at the
point of including that header. There are still a few mutable
variables with external linkage, but at least now each one is defined
in a specific source file file appropriate to its purpose and context.
The remaining globals as of this commit were:
- 'logctx' and 'term', which never needed to be globals in the first
place, because they were never actually shared between source
files. Now 'term' is just a static in window.c, and 'logctx' is a
static in each of that and winplink.c.
- 'hinst', which still has external linkage, but is now defined
separately in each source file that sets it up (i.e. those with a
WinMain)
- osMajorVersion, osMinorVersion and osPlatformId, whose definitions
now live in winmisc.c alongside the code which sets them up.
(Actually they were defined there all along, it turns out, but
every toolchain I've built with has commoned them together with the
version defined by the GLOBAL in the header.)
- 'hwnd', which nothing was actually _using_ any more after previous
commits, so all this commit had to do was delete it.
2020-02-02 10:00:43 +00:00
|
|
|
static LogContext *logctx;
|
|
|
|
static Terminal *term;
|
2020-02-02 10:00:42 +00:00
|
|
|
|
2013-08-17 16:06:35 +00:00
|
|
|
struct wm_netevent_params {
|
|
|
|
/* Used to pass data to wm_netevent_callback */
|
|
|
|
WPARAM wParam;
|
|
|
|
LPARAM lParam;
|
|
|
|
};
|
|
|
|
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
static void conf_cache_data(void);
|
2020-02-02 10:00:43 +00:00
|
|
|
static int cursor_type;
|
|
|
|
static int vtmode;
|
2003-01-12 15:32:31 +00:00
|
|
|
|
2005-04-07 01:36:28 +00:00
|
|
|
static struct sesslist sesslist; /* for saved-session menu */
|
2002-10-30 18:12:46 +00:00
|
|
|
|
1999-01-08 13:02:13 +00:00
|
|
|
#define FONT_NORMAL 0
|
|
|
|
#define FONT_BOLD 1
|
|
|
|
#define FONT_UNDERLINE 2
|
|
|
|
#define FONT_BOLDUND 3
|
2019-09-08 19:29:00 +00:00
|
|
|
#define FONT_WIDE 0x04
|
|
|
|
#define FONT_HIGH 0x08
|
|
|
|
#define FONT_NARROW 0x10
|
2001-09-15 15:54:24 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
#define FONT_OEM 0x20
|
|
|
|
#define FONT_OEMBOLD 0x21
|
|
|
|
#define FONT_OEMUND 0x22
|
2001-05-10 08:34:20 +00:00
|
|
|
#define FONT_OEMBOLDUND 0x23
|
2001-09-15 15:54:24 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
#define FONT_MAXNO 0x40
|
|
|
|
#define FONT_SHIFT 5
|
2001-05-10 08:34:20 +00:00
|
|
|
static HFONT fonts[FONT_MAXNO];
|
2001-11-24 11:56:24 +00:00
|
|
|
static LOGFONT lfont;
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
static bool fontflag[FONT_MAXNO];
|
1999-01-08 13:02:13 +00:00
|
|
|
static enum {
|
2012-06-09 15:09:22 +00:00
|
|
|
BOLD_NONE, BOLD_SHADOW, BOLD_FONT
|
|
|
|
} bold_font_mode;
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
static bool bold_colours;
|
1999-01-08 13:02:13 +00:00
|
|
|
static enum {
|
|
|
|
UND_LINE, UND_FONT
|
|
|
|
} und_mode;
|
2020-08-13 20:08:53 +00:00
|
|
|
static int descent, font_strikethrough_y;
|
1999-01-08 13:02:13 +00:00
|
|
|
|
2021-02-07 19:59:20 +00:00
|
|
|
static COLORREF colours[OSC4_NCOLOURS];
|
1999-01-08 13:02:13 +00:00
|
|
|
static HPALETTE pal;
|
|
|
|
static LPLOGPALETTE logpal;
|
Centralise palette setup into terminal.c.
Now terminal.c makes nearly all the decisions about what the colour
palette should actually contain: it does the job of reading the
GUI-configurable colours out of Conf, and also the job of making up
the rest of the xterm-256 palette. The only exception is that TermWin
can provide a method to override some of the default colours, which on
Windows is used to implement the 'Use system colours' config option.
This saves code overall, partly because the front ends don't have to
be able to send palette data back to the Terminal any more (the
Terminal keeps the master copy and can answer palette-query escape
sequences from its own knowledge), and also because now there's only
one copy of the xterm-256 palette setup code (previously gtkwin.c and
window.c each had their own version of it).
In this rewrite, I've also introduced a multi-layered storage system
for the palette data in Terminal. One layer contains the palette
information derived from Conf; the next contains platform overrides
(currently just Windows's 'Use system colours'); the last one contains
overrides set by escape sequences in the middle of the session. The
topmost two layers can each _conditionally_ override the ones below.
As a result, if a server-side application manually resets (say) the
default fg and bg colours in mid-session to something that works well
in a particular application, those changes won't be wiped out by a
change in the Windows system colours or the Conf, which they would
have been before. Instead, changes in Conf or the system colours alter
the lower layers of the structure, but then when palette_rebuild is
called, the upper layer continues to override them, until a palette
reset (ESC]R) or terminal reset (e.g. ESC c) removes those upper-layer
changes. This seems like a more consistent strategy, in that the same
set of configuration settings will produce the same end result
regardless of what order they were applied in.
The palette-related methods in TermWin have had a total rework.
palette_get and palette_reset are both gone; palette_set can now set a
contiguous range of colours in one go; and the new
palette_get_overrides replaces window.c's old systopalette().
2021-02-07 19:59:21 +00:00
|
|
|
bool tried_pal = false;
|
|
|
|
COLORREF colorref_modifier = 0;
|
1999-01-08 13:02:13 +00:00
|
|
|
|
2000-09-29 10:32:07 +00:00
|
|
|
static HBITMAP caretbm;
|
|
|
|
|
1999-01-08 13:02:13 +00:00
|
|
|
static int dbltime, lasttime, lastact;
|
|
|
|
static Mouse_Button lastbtn;
|
|
|
|
|
2001-05-06 14:20:41 +00:00
|
|
|
/* this allows xterm-style mouse handling. */
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
static bool send_raw_mouse = false;
|
2001-05-06 14:20:41 +00:00
|
|
|
static int wheel_accumulator = 0;
|
|
|
|
|
2021-02-07 19:59:21 +00:00
|
|
|
static bool pointer_indicates_raw_mouse = false;
|
|
|
|
|
New abstraction 'Seat', to pass to backends.
This is a new vtable-based abstraction which is passed to a backend in
place of Frontend, and it implements only the subset of the Frontend
functions needed by a backend. (Many other Frontend functions still
exist, notably the wide range of things called by terminal.c providing
platform-independent operations on the GUI terminal window.)
The purpose of making it a vtable is that this opens up the
possibility of creating a backend as an internal implementation detail
of some other activity, by providing just that one backend with a
custom Seat that implements the methods differently.
For example, this refactoring should make it feasible to directly
implement an SSH proxy type, aka the 'jump host' feature supported by
OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP
mode, and then expose the main channel of that as the Socket for the
primary connection'. (Which of course you can already do by spawning
'plink -nc' as a separate proxy process, but this would permit it in
the _same_ process without anything getting confused.)
I've centralised a full set of stub methods in misc.c for the new
abstraction, which allows me to get rid of several annoying stubs in
the previous code. Also, while I'm here, I've moved a lot of
duplicated modalfatalbox() type functions from application main
program files into wincons.c / uxcons.c, which I think saves
duplication overall. (A minor visible effect is that the prefixes on
those console-based fatal error messages will now be more consistent
between applications.)
2018-10-11 18:58:42 +00:00
|
|
|
static BusyStatus busy_status = BUSY_NOT;
|
2005-02-15 17:05:58 +00:00
|
|
|
|
1999-01-08 13:02:13 +00:00
|
|
|
static char *window_name, *icon_name;
|
|
|
|
|
2000-10-30 10:16:32 +00:00
|
|
|
static int compose_state = 0;
|
|
|
|
|
2001-12-15 14:30:58 +00:00
|
|
|
static UINT wm_mousewheel = WM_MOUSEWHEEL;
|
|
|
|
|
2012-02-17 19:28:55 +00:00
|
|
|
#define IS_HIGH_VARSEL(wch1, wch2) \
|
|
|
|
((wch1) == 0xDB40 && ((wch2) >= 0xDD00 && (wch2) <= 0xDDEF))
|
|
|
|
#define IS_LOW_VARSEL(wch) \
|
|
|
|
(((wch) >= 0x180B && (wch) <= 0x180D) || /* MONGOLIAN FREE VARIATION SELECTOR */ \
|
|
|
|
((wch) >= 0xFE00 && (wch) <= 0xFE0F)) /* VARIATION SELECTOR 1-16 */
|
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
static bool wintw_setup_draw_ctx(TermWin *);
|
Remove the 'Frontend' type and replace it with a vtable.
After the recent Seat and LogContext revamps, _nearly_ all the
remaining uses of the type 'Frontend' were in terminal.c, which needs
all sorts of interactions with the GUI window the terminal lives in,
from the obvious (actually drawing text on the window, reading and
writing the clipboard) to the obscure (minimising, maximising and
moving the window in response to particular escape sequences).
All of those functions are now provided by an abstraction called
TermWin. The few remaining uses of Frontend after _that_ are internal
to a particular platform directory, so as to spread the implementation
of that particular kind of Frontend between multiple source files; so
I've renamed all of those so that they take a more specifically named
type that refers to the particular implementation rather than the
general abstraction.
So now the name 'Frontend' no longer exists in the code base at all,
and everywhere one used to be used, it's completely clear whether it
was operating in one of Frontend's three abstract roles (and if so,
which), or whether it was specific to a particular implementation.
Another type that's disappeared is 'Context', which used to be a
typedef defined to something different on each platform, describing
whatever short-lived resources were necessary to draw on the terminal
window: the front end would provide a ready-made one when calling
term_paint, and the terminal could request one with get_ctx/free_ctx
if it wanted to do proactive window updates. Now that drawing context
lives inside the TermWin itself, because there was never any need to
have two of those contexts live at the same time.
(Another minor API change is that the window-title functions - both
reading and writing - have had a missing 'const' added to their char *
parameters / return values.)
I don't expect this change to enable any particularly interesting new
functionality (in particular, I have no plans that need more than one
implementation of TermWin in the same application). But it completes
the tidying-up that began with the Seat and LogContext rework.
2018-10-25 17:44:04 +00:00
|
|
|
static void wintw_draw_text(TermWin *, int x, int y, wchar_t *text, int len,
|
|
|
|
unsigned long attrs, int lattrs, truecolour tc);
|
|
|
|
static void wintw_draw_cursor(TermWin *, int x, int y, wchar_t *text, int len,
|
|
|
|
unsigned long attrs, int lattrs, truecolour tc);
|
2019-03-10 14:37:11 +00:00
|
|
|
static void wintw_draw_trust_sigil(TermWin *, int x, int y);
|
Remove the 'Frontend' type and replace it with a vtable.
After the recent Seat and LogContext revamps, _nearly_ all the
remaining uses of the type 'Frontend' were in terminal.c, which needs
all sorts of interactions with the GUI window the terminal lives in,
from the obvious (actually drawing text on the window, reading and
writing the clipboard) to the obscure (minimising, maximising and
moving the window in response to particular escape sequences).
All of those functions are now provided by an abstraction called
TermWin. The few remaining uses of Frontend after _that_ are internal
to a particular platform directory, so as to spread the implementation
of that particular kind of Frontend between multiple source files; so
I've renamed all of those so that they take a more specifically named
type that refers to the particular implementation rather than the
general abstraction.
So now the name 'Frontend' no longer exists in the code base at all,
and everywhere one used to be used, it's completely clear whether it
was operating in one of Frontend's three abstract roles (and if so,
which), or whether it was specific to a particular implementation.
Another type that's disappeared is 'Context', which used to be a
typedef defined to something different on each platform, describing
whatever short-lived resources were necessary to draw on the terminal
window: the front end would provide a ready-made one when calling
term_paint, and the terminal could request one with get_ctx/free_ctx
if it wanted to do proactive window updates. Now that drawing context
lives inside the TermWin itself, because there was never any need to
have two of those contexts live at the same time.
(Another minor API change is that the window-title functions - both
reading and writing - have had a missing 'const' added to their char *
parameters / return values.)
I don't expect this change to enable any particularly interesting new
functionality (in particular, I have no plans that need more than one
implementation of TermWin in the same application). But it completes
the tidying-up that began with the Seat and LogContext rework.
2018-10-25 17:44:04 +00:00
|
|
|
static int wintw_char_width(TermWin *, int uc);
|
|
|
|
static void wintw_free_draw_ctx(TermWin *);
|
|
|
|
static void wintw_set_cursor_pos(TermWin *, int x, int y);
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
static void wintw_set_raw_mouse_mode(TermWin *, bool enable);
|
2021-02-07 19:59:21 +00:00
|
|
|
static void wintw_set_raw_mouse_mode_pointer(TermWin *, bool enable);
|
Remove the 'Frontend' type and replace it with a vtable.
After the recent Seat and LogContext revamps, _nearly_ all the
remaining uses of the type 'Frontend' were in terminal.c, which needs
all sorts of interactions with the GUI window the terminal lives in,
from the obvious (actually drawing text on the window, reading and
writing the clipboard) to the obscure (minimising, maximising and
moving the window in response to particular escape sequences).
All of those functions are now provided by an abstraction called
TermWin. The few remaining uses of Frontend after _that_ are internal
to a particular platform directory, so as to spread the implementation
of that particular kind of Frontend between multiple source files; so
I've renamed all of those so that they take a more specifically named
type that refers to the particular implementation rather than the
general abstraction.
So now the name 'Frontend' no longer exists in the code base at all,
and everywhere one used to be used, it's completely clear whether it
was operating in one of Frontend's three abstract roles (and if so,
which), or whether it was specific to a particular implementation.
Another type that's disappeared is 'Context', which used to be a
typedef defined to something different on each platform, describing
whatever short-lived resources were necessary to draw on the terminal
window: the front end would provide a ready-made one when calling
term_paint, and the terminal could request one with get_ctx/free_ctx
if it wanted to do proactive window updates. Now that drawing context
lives inside the TermWin itself, because there was never any need to
have two of those contexts live at the same time.
(Another minor API change is that the window-title functions - both
reading and writing - have had a missing 'const' added to their char *
parameters / return values.)
I don't expect this change to enable any particularly interesting new
functionality (in particular, I have no plans that need more than one
implementation of TermWin in the same application). But it completes
the tidying-up that began with the Seat and LogContext rework.
2018-10-25 17:44:04 +00:00
|
|
|
static void wintw_set_scrollbar(TermWin *, int total, int start, int page);
|
|
|
|
static void wintw_bell(TermWin *, int mode);
|
|
|
|
static void wintw_clip_write(
|
|
|
|
TermWin *, int clipboard, wchar_t *text, int *attrs,
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
truecolour *colours, int len, bool must_deselect);
|
Remove the 'Frontend' type and replace it with a vtable.
After the recent Seat and LogContext revamps, _nearly_ all the
remaining uses of the type 'Frontend' were in terminal.c, which needs
all sorts of interactions with the GUI window the terminal lives in,
from the obvious (actually drawing text on the window, reading and
writing the clipboard) to the obscure (minimising, maximising and
moving the window in response to particular escape sequences).
All of those functions are now provided by an abstraction called
TermWin. The few remaining uses of Frontend after _that_ are internal
to a particular platform directory, so as to spread the implementation
of that particular kind of Frontend between multiple source files; so
I've renamed all of those so that they take a more specifically named
type that refers to the particular implementation rather than the
general abstraction.
So now the name 'Frontend' no longer exists in the code base at all,
and everywhere one used to be used, it's completely clear whether it
was operating in one of Frontend's three abstract roles (and if so,
which), or whether it was specific to a particular implementation.
Another type that's disappeared is 'Context', which used to be a
typedef defined to something different on each platform, describing
whatever short-lived resources were necessary to draw on the terminal
window: the front end would provide a ready-made one when calling
term_paint, and the terminal could request one with get_ctx/free_ctx
if it wanted to do proactive window updates. Now that drawing context
lives inside the TermWin itself, because there was never any need to
have two of those contexts live at the same time.
(Another minor API change is that the window-title functions - both
reading and writing - have had a missing 'const' added to their char *
parameters / return values.)
I don't expect this change to enable any particularly interesting new
functionality (in particular, I have no plans that need more than one
implementation of TermWin in the same application). But it completes
the tidying-up that began with the Seat and LogContext rework.
2018-10-25 17:44:04 +00:00
|
|
|
static void wintw_clip_request_paste(TermWin *, int clipboard);
|
|
|
|
static void wintw_refresh(TermWin *);
|
|
|
|
static void wintw_request_resize(TermWin *, int w, int h);
|
|
|
|
static void wintw_set_title(TermWin *, const char *title);
|
|
|
|
static void wintw_set_icon_title(TermWin *, const char *icontitle);
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
static void wintw_set_minimised(TermWin *, bool minimised);
|
|
|
|
static void wintw_set_maximised(TermWin *, bool maximised);
|
Remove the 'Frontend' type and replace it with a vtable.
After the recent Seat and LogContext revamps, _nearly_ all the
remaining uses of the type 'Frontend' were in terminal.c, which needs
all sorts of interactions with the GUI window the terminal lives in,
from the obvious (actually drawing text on the window, reading and
writing the clipboard) to the obscure (minimising, maximising and
moving the window in response to particular escape sequences).
All of those functions are now provided by an abstraction called
TermWin. The few remaining uses of Frontend after _that_ are internal
to a particular platform directory, so as to spread the implementation
of that particular kind of Frontend between multiple source files; so
I've renamed all of those so that they take a more specifically named
type that refers to the particular implementation rather than the
general abstraction.
So now the name 'Frontend' no longer exists in the code base at all,
and everywhere one used to be used, it's completely clear whether it
was operating in one of Frontend's three abstract roles (and if so,
which), or whether it was specific to a particular implementation.
Another type that's disappeared is 'Context', which used to be a
typedef defined to something different on each platform, describing
whatever short-lived resources were necessary to draw on the terminal
window: the front end would provide a ready-made one when calling
term_paint, and the terminal could request one with get_ctx/free_ctx
if it wanted to do proactive window updates. Now that drawing context
lives inside the TermWin itself, because there was never any need to
have two of those contexts live at the same time.
(Another minor API change is that the window-title functions - both
reading and writing - have had a missing 'const' added to their char *
parameters / return values.)
I don't expect this change to enable any particularly interesting new
functionality (in particular, I have no plans that need more than one
implementation of TermWin in the same application). But it completes
the tidying-up that began with the Seat and LogContext rework.
2018-10-25 17:44:04 +00:00
|
|
|
static void wintw_move(TermWin *, int x, int y);
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
static void wintw_set_zorder(TermWin *, bool top);
|
Centralise palette setup into terminal.c.
Now terminal.c makes nearly all the decisions about what the colour
palette should actually contain: it does the job of reading the
GUI-configurable colours out of Conf, and also the job of making up
the rest of the xterm-256 palette. The only exception is that TermWin
can provide a method to override some of the default colours, which on
Windows is used to implement the 'Use system colours' config option.
This saves code overall, partly because the front ends don't have to
be able to send palette data back to the Terminal any more (the
Terminal keeps the master copy and can answer palette-query escape
sequences from its own knowledge), and also because now there's only
one copy of the xterm-256 palette setup code (previously gtkwin.c and
window.c each had their own version of it).
In this rewrite, I've also introduced a multi-layered storage system
for the palette data in Terminal. One layer contains the palette
information derived from Conf; the next contains platform overrides
(currently just Windows's 'Use system colours'); the last one contains
overrides set by escape sequences in the middle of the session. The
topmost two layers can each _conditionally_ override the ones below.
As a result, if a server-side application manually resets (say) the
default fg and bg colours in mid-session to something that works well
in a particular application, those changes won't be wiped out by a
change in the Windows system colours or the Conf, which they would
have been before. Instead, changes in Conf or the system colours alter
the lower layers of the structure, but then when palette_rebuild is
called, the upper layer continues to override them, until a palette
reset (ESC]R) or terminal reset (e.g. ESC c) removes those upper-layer
changes. This seems like a more consistent strategy, in that the same
set of configuration settings will produce the same end result
regardless of what order they were applied in.
The palette-related methods in TermWin have had a total rework.
palette_get and palette_reset are both gone; palette_set can now set a
contiguous range of colours in one go; and the new
palette_get_overrides replaces window.c's old systopalette().
2021-02-07 19:59:21 +00:00
|
|
|
static void wintw_palette_set(TermWin *, unsigned, unsigned, const rgb *);
|
|
|
|
static void wintw_palette_get_overrides(TermWin *);
|
Remove the 'Frontend' type and replace it with a vtable.
After the recent Seat and LogContext revamps, _nearly_ all the
remaining uses of the type 'Frontend' were in terminal.c, which needs
all sorts of interactions with the GUI window the terminal lives in,
from the obvious (actually drawing text on the window, reading and
writing the clipboard) to the obscure (minimising, maximising and
moving the window in response to particular escape sequences).
All of those functions are now provided by an abstraction called
TermWin. The few remaining uses of Frontend after _that_ are internal
to a particular platform directory, so as to spread the implementation
of that particular kind of Frontend between multiple source files; so
I've renamed all of those so that they take a more specifically named
type that refers to the particular implementation rather than the
general abstraction.
So now the name 'Frontend' no longer exists in the code base at all,
and everywhere one used to be used, it's completely clear whether it
was operating in one of Frontend's three abstract roles (and if so,
which), or whether it was specific to a particular implementation.
Another type that's disappeared is 'Context', which used to be a
typedef defined to something different on each platform, describing
whatever short-lived resources were necessary to draw on the terminal
window: the front end would provide a ready-made one when calling
term_paint, and the terminal could request one with get_ctx/free_ctx
if it wanted to do proactive window updates. Now that drawing context
lives inside the TermWin itself, because there was never any need to
have two of those contexts live at the same time.
(Another minor API change is that the window-title functions - both
reading and writing - have had a missing 'const' added to their char *
parameters / return values.)
I don't expect this change to enable any particularly interesting new
functionality (in particular, I have no plans that need more than one
implementation of TermWin in the same application). But it completes
the tidying-up that began with the Seat and LogContext rework.
2018-10-25 17:44:04 +00:00
|
|
|
|
|
|
|
static const TermWinVtable windows_termwin_vt = {
|
Change vtable defs to use C99 designated initialisers.
This is a sweeping change applied across the whole code base by a spot
of Emacs Lisp. Now, everywhere I declare a vtable filled with function
pointers (and the occasional const data member), all the members of
the vtable structure are initialised by name using the '.fieldname =
value' syntax introduced in C99.
We were already using this syntax for a handful of things in the new
key-generation progress report system, so it's not new to the code
base as a whole.
The advantage is that now, when a vtable only declares a subset of the
available fields, I can initialise the rest to NULL or zero just by
leaving them out. This is most dramatic in a couple of the outlying
vtables in things like psocks (which has a ConnectionLayerVtable
containing only one non-NULL method), but less dramatically, it means
that the new 'flags' field in BackendVtable can be completely left out
of every backend definition except for the SUPDUP one which defines it
to a nonzero value. Similarly, the test_for_upstream method only used
by SSH doesn't have to be mentioned in the rest of the backends;
network Plugs for listening sockets don't have to explicitly null out
'receive' and 'sent', and vice versa for 'accepting', and so on.
While I'm at it, I've normalised the declarations so they don't use
the unnecessarily verbose 'struct' keyword. Also a handful of them
weren't const; now they are.
2020-03-10 21:06:29 +00:00
|
|
|
.setup_draw_ctx = wintw_setup_draw_ctx,
|
|
|
|
.draw_text = wintw_draw_text,
|
|
|
|
.draw_cursor = wintw_draw_cursor,
|
|
|
|
.draw_trust_sigil = wintw_draw_trust_sigil,
|
|
|
|
.char_width = wintw_char_width,
|
|
|
|
.free_draw_ctx = wintw_free_draw_ctx,
|
|
|
|
.set_cursor_pos = wintw_set_cursor_pos,
|
|
|
|
.set_raw_mouse_mode = wintw_set_raw_mouse_mode,
|
2021-02-07 19:59:21 +00:00
|
|
|
.set_raw_mouse_mode_pointer = wintw_set_raw_mouse_mode_pointer,
|
Change vtable defs to use C99 designated initialisers.
This is a sweeping change applied across the whole code base by a spot
of Emacs Lisp. Now, everywhere I declare a vtable filled with function
pointers (and the occasional const data member), all the members of
the vtable structure are initialised by name using the '.fieldname =
value' syntax introduced in C99.
We were already using this syntax for a handful of things in the new
key-generation progress report system, so it's not new to the code
base as a whole.
The advantage is that now, when a vtable only declares a subset of the
available fields, I can initialise the rest to NULL or zero just by
leaving them out. This is most dramatic in a couple of the outlying
vtables in things like psocks (which has a ConnectionLayerVtable
containing only one non-NULL method), but less dramatically, it means
that the new 'flags' field in BackendVtable can be completely left out
of every backend definition except for the SUPDUP one which defines it
to a nonzero value. Similarly, the test_for_upstream method only used
by SSH doesn't have to be mentioned in the rest of the backends;
network Plugs for listening sockets don't have to explicitly null out
'receive' and 'sent', and vice versa for 'accepting', and so on.
While I'm at it, I've normalised the declarations so they don't use
the unnecessarily verbose 'struct' keyword. Also a handful of them
weren't const; now they are.
2020-03-10 21:06:29 +00:00
|
|
|
.set_scrollbar = wintw_set_scrollbar,
|
|
|
|
.bell = wintw_bell,
|
|
|
|
.clip_write = wintw_clip_write,
|
|
|
|
.clip_request_paste = wintw_clip_request_paste,
|
|
|
|
.refresh = wintw_refresh,
|
|
|
|
.request_resize = wintw_request_resize,
|
|
|
|
.set_title = wintw_set_title,
|
|
|
|
.set_icon_title = wintw_set_icon_title,
|
|
|
|
.set_minimised = wintw_set_minimised,
|
|
|
|
.set_maximised = wintw_set_maximised,
|
|
|
|
.move = wintw_move,
|
|
|
|
.set_zorder = wintw_set_zorder,
|
|
|
|
.palette_set = wintw_palette_set,
|
Centralise palette setup into terminal.c.
Now terminal.c makes nearly all the decisions about what the colour
palette should actually contain: it does the job of reading the
GUI-configurable colours out of Conf, and also the job of making up
the rest of the xterm-256 palette. The only exception is that TermWin
can provide a method to override some of the default colours, which on
Windows is used to implement the 'Use system colours' config option.
This saves code overall, partly because the front ends don't have to
be able to send palette data back to the Terminal any more (the
Terminal keeps the master copy and can answer palette-query escape
sequences from its own knowledge), and also because now there's only
one copy of the xterm-256 palette setup code (previously gtkwin.c and
window.c each had their own version of it).
In this rewrite, I've also introduced a multi-layered storage system
for the palette data in Terminal. One layer contains the palette
information derived from Conf; the next contains platform overrides
(currently just Windows's 'Use system colours'); the last one contains
overrides set by escape sequences in the middle of the session. The
topmost two layers can each _conditionally_ override the ones below.
As a result, if a server-side application manually resets (say) the
default fg and bg colours in mid-session to something that works well
in a particular application, those changes won't be wiped out by a
change in the Windows system colours or the Conf, which they would
have been before. Instead, changes in Conf or the system colours alter
the lower layers of the structure, but then when palette_rebuild is
called, the upper layer continues to override them, until a palette
reset (ESC]R) or terminal reset (e.g. ESC c) removes those upper-layer
changes. This seems like a more consistent strategy, in that the same
set of configuration settings will produce the same end result
regardless of what order they were applied in.
The palette-related methods in TermWin have had a total rework.
palette_get and palette_reset are both gone; palette_set can now set a
contiguous range of colours in one go; and the new
palette_get_overrides replaces window.c's old systopalette().
2021-02-07 19:59:21 +00:00
|
|
|
.palette_get_overrides = wintw_palette_get_overrides,
|
Remove the 'Frontend' type and replace it with a vtable.
After the recent Seat and LogContext revamps, _nearly_ all the
remaining uses of the type 'Frontend' were in terminal.c, which needs
all sorts of interactions with the GUI window the terminal lives in,
from the obvious (actually drawing text on the window, reading and
writing the clipboard) to the obscure (minimising, maximising and
moving the window in response to particular escape sequences).
All of those functions are now provided by an abstraction called
TermWin. The few remaining uses of Frontend after _that_ are internal
to a particular platform directory, so as to spread the implementation
of that particular kind of Frontend between multiple source files; so
I've renamed all of those so that they take a more specifically named
type that refers to the particular implementation rather than the
general abstraction.
So now the name 'Frontend' no longer exists in the code base at all,
and everywhere one used to be used, it's completely clear whether it
was operating in one of Frontend's three abstract roles (and if so,
which), or whether it was specific to a particular implementation.
Another type that's disappeared is 'Context', which used to be a
typedef defined to something different on each platform, describing
whatever short-lived resources were necessary to draw on the terminal
window: the front end would provide a ready-made one when calling
term_paint, and the terminal could request one with get_ctx/free_ctx
if it wanted to do proactive window updates. Now that drawing context
lives inside the TermWin itself, because there was never any need to
have two of those contexts live at the same time.
(Another minor API change is that the window-title functions - both
reading and writing - have had a missing 'const' added to their char *
parameters / return values.)
I don't expect this change to enable any particularly interesting new
functionality (in particular, I have no plans that need more than one
implementation of TermWin in the same application). But it completes
the tidying-up that began with the Seat and LogContext rework.
2018-10-25 17:44:04 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static TermWin wintw[1];
|
|
|
|
static HDC wintw_hdc;
|
|
|
|
|
2019-03-30 15:44:01 +00:00
|
|
|
static HICON trust_icon = INVALID_HANDLE_VALUE;
|
2019-03-10 14:37:11 +00:00
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
const bool share_can_be_downstream = true;
|
|
|
|
const bool share_can_be_upstream = true;
|
2013-11-17 14:05:41 +00:00
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
static bool is_utf8(void)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
New abstraction 'Seat', to pass to backends.
This is a new vtable-based abstraction which is passed to a backend in
place of Frontend, and it implements only the subset of the Frontend
functions needed by a backend. (Many other Frontend functions still
exist, notably the wide range of things called by terminal.c providing
platform-independent operations on the GUI terminal window.)
The purpose of making it a vtable is that this opens up the
possibility of creating a backend as an internal implementation detail
of some other activity, by providing just that one backend with a
custom Seat that implements the methods differently.
For example, this refactoring should make it feasible to directly
implement an SSH proxy type, aka the 'jump host' feature supported by
OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP
mode, and then expose the main channel of that as the Socket for the
primary connection'. (Which of course you can already do by spawning
'plink -nc' as a separate proxy process, but this would permit it in
the _same_ process without anything getting confused.)
I've centralised a full set of stub methods in misc.c for the new
abstraction, which allows me to get rid of several annoying stubs in
the previous code. Also, while I'm here, I've moved a lot of
duplicated modalfatalbox() type functions from application main
program files into wincons.c / uxcons.c, which I think saves
duplication overall. (A minor visible effect is that the prefixes on
those console-based fatal error messages will now be more consistent
between applications.)
2018-10-11 18:58:42 +00:00
|
|
|
return ucsdata.line_codepage == CP_UTF8;
|
2001-05-06 14:35:20 +00:00
|
|
|
}
|
2000-09-22 13:10:19 +00:00
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
static bool win_seat_is_utf8(Seat *seat)
|
2016-05-03 07:43:09 +00:00
|
|
|
{
|
Remove the 'Frontend' type and replace it with a vtable.
After the recent Seat and LogContext revamps, _nearly_ all the
remaining uses of the type 'Frontend' were in terminal.c, which needs
all sorts of interactions with the GUI window the terminal lives in,
from the obvious (actually drawing text on the window, reading and
writing the clipboard) to the obscure (minimising, maximising and
moving the window in response to particular escape sequences).
All of those functions are now provided by an abstraction called
TermWin. The few remaining uses of Frontend after _that_ are internal
to a particular platform directory, so as to spread the implementation
of that particular kind of Frontend between multiple source files; so
I've renamed all of those so that they take a more specifically named
type that refers to the particular implementation rather than the
general abstraction.
So now the name 'Frontend' no longer exists in the code base at all,
and everywhere one used to be used, it's completely clear whether it
was operating in one of Frontend's three abstract roles (and if so,
which), or whether it was specific to a particular implementation.
Another type that's disappeared is 'Context', which used to be a
typedef defined to something different on each platform, describing
whatever short-lived resources were necessary to draw on the terminal
window: the front end would provide a ready-made one when calling
term_paint, and the terminal could request one with get_ctx/free_ctx
if it wanted to do proactive window updates. Now that drawing context
lives inside the TermWin itself, because there was never any need to
have two of those contexts live at the same time.
(Another minor API change is that the window-title functions - both
reading and writing - have had a missing 'const' added to their char *
parameters / return values.)
I don't expect this change to enable any particularly interesting new
functionality (in particular, I have no plans that need more than one
implementation of TermWin in the same application). But it completes
the tidying-up that began with the Seat and LogContext rework.
2018-10-25 17:44:04 +00:00
|
|
|
return is_utf8();
|
2016-05-03 07:43:09 +00:00
|
|
|
}
|
|
|
|
|
2021-02-02 18:54:39 +00:00
|
|
|
static char *win_seat_get_ttymode(Seat *seat, const char *mode)
|
2005-04-21 13:57:08 +00:00
|
|
|
{
|
|
|
|
return term_get_ttymode(term, mode);
|
|
|
|
}
|
|
|
|
|
2021-02-02 18:54:39 +00:00
|
|
|
static StripCtrlChars *win_seat_stripctrl_new(
|
2019-03-07 08:19:38 +00:00
|
|
|
Seat *seat, BinarySink *bs_out, SeatInteractionContext sic)
|
2019-03-05 21:13:00 +00:00
|
|
|
{
|
2019-03-07 08:19:38 +00:00
|
|
|
return stripctrl_new_term(bs_out, false, 0, term);
|
2019-03-05 21:13:00 +00:00
|
|
|
}
|
|
|
|
|
2019-02-06 20:42:44 +00:00
|
|
|
static size_t win_seat_output(
|
|
|
|
Seat *seat, bool is_stderr, const void *, size_t);
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
static bool win_seat_eof(Seat *seat);
|
New abstraction 'Seat', to pass to backends.
This is a new vtable-based abstraction which is passed to a backend in
place of Frontend, and it implements only the subset of the Frontend
functions needed by a backend. (Many other Frontend functions still
exist, notably the wide range of things called by terminal.c providing
platform-independent operations on the GUI terminal window.)
The purpose of making it a vtable is that this opens up the
possibility of creating a backend as an internal implementation detail
of some other activity, by providing just that one backend with a
custom Seat that implements the methods differently.
For example, this refactoring should make it feasible to directly
implement an SSH proxy type, aka the 'jump host' feature supported by
OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP
mode, and then expose the main channel of that as the Socket for the
primary connection'. (Which of course you can already do by spawning
'plink -nc' as a separate proxy process, but this would permit it in
the _same_ process without anything getting confused.)
I've centralised a full set of stub methods in misc.c for the new
abstraction, which allows me to get rid of several annoying stubs in
the previous code. Also, while I'm here, I've moved a lot of
duplicated modalfatalbox() type functions from application main
program files into wincons.c / uxcons.c, which I think saves
duplication overall. (A minor visible effect is that the prefixes on
those console-based fatal error messages will now be more consistent
between applications.)
2018-10-11 18:58:42 +00:00
|
|
|
static int win_seat_get_userpass_input(
|
|
|
|
Seat *seat, prompts_t *p, bufchain *input);
|
|
|
|
static void win_seat_notify_remote_exit(Seat *seat);
|
|
|
|
static void win_seat_connection_fatal(Seat *seat, const char *msg);
|
|
|
|
static void win_seat_update_specials_menu(Seat *seat);
|
|
|
|
static void win_seat_set_busy_status(Seat *seat, BusyStatus status);
|
2019-03-10 14:42:11 +00:00
|
|
|
static bool win_seat_set_trust_status(Seat *seat, bool trusted);
|
2019-04-04 19:17:24 +00:00
|
|
|
static bool win_seat_get_cursor_position(Seat *seat, int *x, int *y);
|
2021-02-07 19:59:21 +00:00
|
|
|
static bool win_seat_get_window_pixel_size(Seat *seat, int *x, int *y);
|
New abstraction 'Seat', to pass to backends.
This is a new vtable-based abstraction which is passed to a backend in
place of Frontend, and it implements only the subset of the Frontend
functions needed by a backend. (Many other Frontend functions still
exist, notably the wide range of things called by terminal.c providing
platform-independent operations on the GUI terminal window.)
The purpose of making it a vtable is that this opens up the
possibility of creating a backend as an internal implementation detail
of some other activity, by providing just that one backend with a
custom Seat that implements the methods differently.
For example, this refactoring should make it feasible to directly
implement an SSH proxy type, aka the 'jump host' feature supported by
OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP
mode, and then expose the main channel of that as the Socket for the
primary connection'. (Which of course you can already do by spawning
'plink -nc' as a separate proxy process, but this would permit it in
the _same_ process without anything getting confused.)
I've centralised a full set of stub methods in misc.c for the new
abstraction, which allows me to get rid of several annoying stubs in
the previous code. Also, while I'm here, I've moved a lot of
duplicated modalfatalbox() type functions from application main
program files into wincons.c / uxcons.c, which I think saves
duplication overall. (A minor visible effect is that the prefixes on
those console-based fatal error messages will now be more consistent
between applications.)
2018-10-11 18:58:42 +00:00
|
|
|
|
|
|
|
static const SeatVtable win_seat_vt = {
|
Change vtable defs to use C99 designated initialisers.
This is a sweeping change applied across the whole code base by a spot
of Emacs Lisp. Now, everywhere I declare a vtable filled with function
pointers (and the occasional const data member), all the members of
the vtable structure are initialised by name using the '.fieldname =
value' syntax introduced in C99.
We were already using this syntax for a handful of things in the new
key-generation progress report system, so it's not new to the code
base as a whole.
The advantage is that now, when a vtable only declares a subset of the
available fields, I can initialise the rest to NULL or zero just by
leaving them out. This is most dramatic in a couple of the outlying
vtables in things like psocks (which has a ConnectionLayerVtable
containing only one non-NULL method), but less dramatically, it means
that the new 'flags' field in BackendVtable can be completely left out
of every backend definition except for the SUPDUP one which defines it
to a nonzero value. Similarly, the test_for_upstream method only used
by SSH doesn't have to be mentioned in the rest of the backends;
network Plugs for listening sockets don't have to explicitly null out
'receive' and 'sent', and vice versa for 'accepting', and so on.
While I'm at it, I've normalised the declarations so they don't use
the unnecessarily verbose 'struct' keyword. Also a handful of them
weren't const; now they are.
2020-03-10 21:06:29 +00:00
|
|
|
.output = win_seat_output,
|
|
|
|
.eof = win_seat_eof,
|
|
|
|
.get_userpass_input = win_seat_get_userpass_input,
|
|
|
|
.notify_remote_exit = win_seat_notify_remote_exit,
|
|
|
|
.connection_fatal = win_seat_connection_fatal,
|
|
|
|
.update_specials_menu = win_seat_update_specials_menu,
|
|
|
|
.get_ttymode = win_seat_get_ttymode,
|
|
|
|
.set_busy_status = win_seat_set_busy_status,
|
|
|
|
.verify_ssh_host_key = win_seat_verify_ssh_host_key,
|
|
|
|
.confirm_weak_crypto_primitive = win_seat_confirm_weak_crypto_primitive,
|
|
|
|
.confirm_weak_cached_hostkey = win_seat_confirm_weak_cached_hostkey,
|
|
|
|
.is_utf8 = win_seat_is_utf8,
|
|
|
|
.echoedit_update = nullseat_echoedit_update,
|
|
|
|
.get_x_display = nullseat_get_x_display,
|
|
|
|
.get_windowid = nullseat_get_windowid,
|
|
|
|
.get_window_pixel_size = win_seat_get_window_pixel_size,
|
|
|
|
.stripctrl_new = win_seat_stripctrl_new,
|
|
|
|
.set_trust_status = win_seat_set_trust_status,
|
|
|
|
.verbose = nullseat_verbose_yes,
|
|
|
|
.interactive = nullseat_interactive_yes,
|
|
|
|
.get_cursor_position = win_seat_get_cursor_position,
|
New abstraction 'Seat', to pass to backends.
This is a new vtable-based abstraction which is passed to a backend in
place of Frontend, and it implements only the subset of the Frontend
functions needed by a backend. (Many other Frontend functions still
exist, notably the wide range of things called by terminal.c providing
platform-independent operations on the GUI terminal window.)
The purpose of making it a vtable is that this opens up the
possibility of creating a backend as an internal implementation detail
of some other activity, by providing just that one backend with a
custom Seat that implements the methods differently.
For example, this refactoring should make it feasible to directly
implement an SSH proxy type, aka the 'jump host' feature supported by
OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP
mode, and then expose the main channel of that as the Socket for the
primary connection'. (Which of course you can already do by spawning
'plink -nc' as a separate proxy process, but this would permit it in
the _same_ process without anything getting confused.)
I've centralised a full set of stub methods in misc.c for the new
abstraction, which allows me to get rid of several annoying stubs in
the previous code. Also, while I'm here, I've moved a lot of
duplicated modalfatalbox() type functions from application main
program files into wincons.c / uxcons.c, which I think saves
duplication overall. (A minor visible effect is that the prefixes on
those console-based fatal error messages will now be more consistent
between applications.)
2018-10-11 18:58:42 +00:00
|
|
|
};
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
static WinGuiSeat wgs = { .seat.vt = &win_seat_vt,
|
|
|
|
.logpolicy.vt = &win_gui_logpolicy_vt };
|
New abstraction 'Seat', to pass to backends.
This is a new vtable-based abstraction which is passed to a backend in
place of Frontend, and it implements only the subset of the Frontend
functions needed by a backend. (Many other Frontend functions still
exist, notably the wide range of things called by terminal.c providing
platform-independent operations on the GUI terminal window.)
The purpose of making it a vtable is that this opens up the
possibility of creating a backend as an internal implementation detail
of some other activity, by providing just that one backend with a
custom Seat that implements the methods differently.
For example, this refactoring should make it feasible to directly
implement an SSH proxy type, aka the 'jump host' feature supported by
OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP
mode, and then expose the main channel of that as the Socket for the
primary connection'. (Which of course you can already do by spawning
'plink -nc' as a separate proxy process, but this would permit it in
the _same_ process without anything getting confused.)
I've centralised a full set of stub methods in misc.c for the new
abstraction, which allows me to get rid of several annoying stubs in
the previous code. Also, while I'm here, I've moved a lot of
duplicated modalfatalbox() type functions from application main
program files into wincons.c / uxcons.c, which I think saves
duplication overall. (A minor visible effect is that the prefixes on
those console-based fatal error messages will now be more consistent
between applications.)
2018-10-11 18:58:42 +00:00
|
|
|
|
2004-08-14 13:04:18 +00:00
|
|
|
static void start_backend(void)
|
|
|
|
{
|
2018-10-05 06:03:46 +00:00
|
|
|
const struct BackendVtable *vt;
|
2020-04-18 12:28:33 +00:00
|
|
|
char *error, *realhost;
|
2004-08-14 13:04:18 +00:00
|
|
|
int i;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Select protocol. This is farmed out into a table in a
|
|
|
|
* separate file to enable an ssh-free variant.
|
|
|
|
*/
|
2018-09-11 15:23:38 +00:00
|
|
|
vt = backend_vt_from_proto(conf_get_int(conf, CONF_protocol));
|
|
|
|
if (!vt) {
|
2019-09-08 19:29:00 +00:00
|
|
|
char *str = dupprintf("%s Internal Error", appname);
|
|
|
|
MessageBox(NULL, "Unsupported protocol number found",
|
|
|
|
str, MB_OK | MB_ICONEXCLAMATION);
|
|
|
|
sfree(str);
|
|
|
|
cleanup_exit(1);
|
2004-08-14 13:04:18 +00:00
|
|
|
}
|
|
|
|
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
seat_set_trust_status(&wgs.seat, true);
|
|
|
|
error = backend_init(vt, &wgs.seat, &backend, logctx, conf,
|
2018-09-11 15:23:38 +00:00
|
|
|
conf_get_str(conf, CONF_host),
|
|
|
|
conf_get_int(conf, CONF_port),
|
|
|
|
&realhost,
|
2018-10-29 19:57:31 +00:00
|
|
|
conf_get_bool(conf, CONF_tcp_nodelay),
|
|
|
|
conf_get_bool(conf, CONF_tcp_keepalives));
|
2004-08-14 13:04:18 +00:00
|
|
|
if (error) {
|
2019-09-08 19:29:00 +00:00
|
|
|
char *str = dupprintf("%s Error", appname);
|
2018-12-08 21:03:51 +00:00
|
|
|
char *msg = dupprintf("Unable to open connection to\n%s\n%s",
|
|
|
|
conf_dest(conf), error);
|
2020-04-18 12:28:33 +00:00
|
|
|
sfree(error);
|
2019-09-08 19:29:00 +00:00
|
|
|
MessageBox(NULL, msg, str, MB_ICONERROR | MB_OK);
|
|
|
|
sfree(str);
|
|
|
|
sfree(msg);
|
|
|
|
exit(0);
|
2004-08-14 13:04:18 +00:00
|
|
|
}
|
2021-02-07 19:59:20 +00:00
|
|
|
term_setup_window_titles(term, realhost);
|
2004-08-14 13:04:18 +00:00
|
|
|
sfree(realhost);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Connect the terminal to the backend for resize purposes.
|
|
|
|
*/
|
2018-09-11 15:23:38 +00:00
|
|
|
term_provide_backend(term, backend);
|
2004-08-14 13:04:18 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Set up a line discipline.
|
|
|
|
*/
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
ldisc = ldisc_create(conf, term, backend, &wgs.seat);
|
2004-08-14 13:04:18 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Destroy the Restart Session menu item. (This will return
|
|
|
|
* failure if it's already absent, as it will be the very first
|
|
|
|
* time we call this function. We ignore that, because as long
|
|
|
|
* 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++) {
|
2019-09-08 19:29:00 +00:00
|
|
|
DeleteMenu(popup_menus[i].menu, IDM_RESTART, MF_BYCOMMAND);
|
2004-08-14 13:04:18 +00:00
|
|
|
}
|
|
|
|
|
2018-10-29 19:50:29 +00:00
|
|
|
session_closed = false;
|
2004-08-14 13:04:18 +00:00
|
|
|
}
|
|
|
|
|
2013-08-17 16:06:18 +00:00
|
|
|
static void close_session(void *ignored_context)
|
2004-08-14 13:04:18 +00:00
|
|
|
{
|
2018-12-08 21:03:51 +00:00
|
|
|
char *newtitle;
|
2004-08-14 13:04:18 +00:00
|
|
|
int i;
|
|
|
|
|
2018-10-29 19:50:29 +00:00
|
|
|
session_closed = true;
|
2018-12-08 21:03:51 +00:00
|
|
|
newtitle = dupprintf("%s (inactive)", appname);
|
|
|
|
win_set_icon_title(wintw, newtitle);
|
|
|
|
win_set_title(wintw, newtitle);
|
|
|
|
sfree(newtitle);
|
2004-08-14 13:04:18 +00:00
|
|
|
|
|
|
|
if (ldisc) {
|
2019-09-08 19:29:00 +00:00
|
|
|
ldisc_free(ldisc);
|
|
|
|
ldisc = NULL;
|
2004-08-14 13:04:18 +00:00
|
|
|
}
|
2018-09-11 15:23:38 +00:00
|
|
|
if (backend) {
|
|
|
|
backend_free(backend);
|
|
|
|
backend = NULL;
|
|
|
|
term_provide_backend(term, NULL);
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
seat_update_specials_menu(&wgs.seat);
|
2004-08-14 13:04:18 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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++) {
|
2019-09-08 19:29:00 +00:00
|
|
|
DeleteMenu(popup_menus[i].menu, IDM_RESTART, MF_BYCOMMAND);
|
|
|
|
InsertMenu(popup_menus[i].menu, IDM_DUPSESS, MF_BYCOMMAND | MF_ENABLED,
|
|
|
|
IDM_RESTART, "&Restart Session");
|
2004-08-14 13:04:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-30 06:40:22 +00:00
|
|
|
const unsigned cmdline_tooltype =
|
|
|
|
TOOLTYPE_HOST_ARG |
|
|
|
|
TOOLTYPE_PORT_ARG |
|
|
|
|
TOOLTYPE_NO_VERBOSE_OPTION;
|
|
|
|
|
Remove remaining uses of the GLOBAL macro.
We now have no remaining things in header files that switch from being
a declaration to a definition depending on an awkward #define at the
point of including that header. There are still a few mutable
variables with external linkage, but at least now each one is defined
in a specific source file file appropriate to its purpose and context.
The remaining globals as of this commit were:
- 'logctx' and 'term', which never needed to be globals in the first
place, because they were never actually shared between source
files. Now 'term' is just a static in window.c, and 'logctx' is a
static in each of that and winplink.c.
- 'hinst', which still has external linkage, but is now defined
separately in each source file that sets it up (i.e. those with a
WinMain)
- osMajorVersion, osMinorVersion and osPlatformId, whose definitions
now live in winmisc.c alongside the code which sets them up.
(Actually they were defined there all along, it turns out, but
every toolchain I've built with has commoned them together with the
version defined by the GLOBAL in the header.)
- 'hwnd', which nothing was actually _using_ any more after previous
commits, so all this commit had to do was delete it.
2020-02-02 10:00:43 +00:00
|
|
|
HINSTANCE hinst;
|
|
|
|
|
2001-05-06 14:35:20 +00:00
|
|
|
int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
|
|
|
|
{
|
1999-01-08 13:02:13 +00:00
|
|
|
MSG msg;
|
2010-12-23 17:32:28 +00:00
|
|
|
HRESULT hr;
|
1999-01-08 13:02:13 +00:00
|
|
|
int guess_width, guess_height;
|
|
|
|
|
2016-07-18 19:02:32 +00:00
|
|
|
dll_hijacking_protection();
|
|
|
|
|
2000-10-18 15:36:32 +00:00
|
|
|
hinst = inst;
|
1999-11-03 14:08:26 +00:00
|
|
|
|
2000-10-23 10:32:37 +00:00
|
|
|
sk_init();
|
1999-01-08 13:02:13 +00:00
|
|
|
|
2017-03-13 21:42:44 +00:00
|
|
|
init_common_controls();
|
1999-01-08 13:02:13 +00:00
|
|
|
|
2016-08-29 15:55:42 +00:00
|
|
|
/* Set Explicit App User Model Id so that jump lists don't cause
|
|
|
|
PuTTY to hang on to removable media. */
|
|
|
|
|
|
|
|
set_explicit_app_user_model_id();
|
|
|
|
|
2000-10-12 12:56:33 +00:00
|
|
|
/* Ensure a Maximize setting in Explorer doesn't maximise the
|
|
|
|
* config box. */
|
|
|
|
defuse_showwindow();
|
|
|
|
|
2018-06-03 14:05:44 +00:00
|
|
|
init_winver();
|
2001-08-04 15:15:07 +00:00
|
|
|
|
2001-12-15 14:30:58 +00:00
|
|
|
/*
|
|
|
|
* If we're running a version of Windows that doesn't support
|
|
|
|
* WM_MOUSEWHEEL, find out what message number we should be
|
|
|
|
* using instead.
|
|
|
|
*/
|
2018-06-03 14:05:44 +00:00
|
|
|
if (osMajorVersion < 4 ||
|
2019-09-08 19:29:00 +00:00
|
|
|
(osMajorVersion == 4 && osPlatformId != VER_PLATFORM_WIN32_NT))
|
|
|
|
wm_mousewheel = RegisterWindowMessage("MSWHEEL_ROLLMSG");
|
2001-12-15 14:30:58 +00:00
|
|
|
|
2006-12-17 11:16:07 +00:00
|
|
|
init_help();
|
2001-12-06 13:28:02 +00:00
|
|
|
|
2013-11-17 14:03:20 +00:00
|
|
|
init_winfuncs();
|
2007-01-16 20:54:58 +00:00
|
|
|
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
conf = conf_new();
|
|
|
|
|
2010-12-23 17:32:28 +00:00
|
|
|
/*
|
|
|
|
* Initialize COM.
|
|
|
|
*/
|
|
|
|
hr = CoInitialize(NULL);
|
|
|
|
if (hr != S_OK && hr != S_FALSE) {
|
|
|
|
char *str = dupprintf("%s Fatal Error", appname);
|
2019-09-08 19:29:00 +00:00
|
|
|
MessageBox(NULL, "Failed to initialize COM subsystem",
|
|
|
|
str, MB_OK | MB_ICONEXCLAMATION);
|
|
|
|
sfree(str);
|
|
|
|
return 1;
|
2010-12-23 17:32:28 +00:00
|
|
|
}
|
|
|
|
|
1999-01-08 13:02:13 +00:00
|
|
|
/*
|
|
|
|
* Process the command line.
|
|
|
|
*/
|
|
|
|
{
|
2019-09-08 19:29:00 +00:00
|
|
|
char *p;
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool special_launchable_argument = false;
|
1999-01-08 13:02:13 +00:00
|
|
|
|
2020-02-02 10:00:42 +00:00
|
|
|
settings_set_default_protocol(be_default_protocol);
|
2019-09-08 19:29:00 +00:00
|
|
|
/* Find the appropriate default port. */
|
|
|
|
{
|
2018-10-05 06:03:46 +00:00
|
|
|
const struct BackendVtable *vt =
|
2020-02-02 10:00:42 +00:00
|
|
|
backend_vt_from_proto(be_default_protocol);
|
|
|
|
settings_set_default_port(0); /* illegal */
|
2018-09-11 15:23:38 +00:00
|
|
|
if (vt)
|
2020-02-02 10:00:42 +00:00
|
|
|
settings_set_default_port(vt->default_port);
|
2019-09-08 19:29:00 +00:00
|
|
|
}
|
|
|
|
conf_set_int(conf, CONF_logtype, LGTYP_NONE);
|
|
|
|
|
|
|
|
do_defaults(NULL, conf);
|
|
|
|
|
|
|
|
p = cmdline;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Process a couple of command-line options which are more
|
|
|
|
* easily dealt with before the line is broken up into words.
|
|
|
|
* These are the old-fashioned but convenient @sessionname and
|
|
|
|
* the internal-use-only &sharedmemoryhandle, plus the &R
|
|
|
|
* prefix for -restrict-acl, all of which are used by PuTTYs
|
|
|
|
* auto-launching each other via System-menu options.
|
|
|
|
*/
|
|
|
|
while (*p && isspace(*p))
|
|
|
|
p++;
|
Pass -restrict-acl, if given, through to sub-PuTTYs.
This change applies to every situation when GUI PuTTY knowingly spawns
another GUI PuTTY, to wit, the System menu options 'New Session',
'Duplicate Session' and the 'Saved Sessions' submenu.
(Literally speaking, what we actually pass through to the sub-PuTTY's
command line is not the "-restrict-acl" option itself, but a special
prefix "&R", which has the same meaning but which lives in the special
pre-argv-splitting command-line namespace like the magic options used
for Duplicate Session and the old '@sessionname' prefix which the
Saved Sessions submenu still uses. Otherwise, by the time we split up
argv and recognised -restrict-acl, it would be too late to parse those
other options.)
One case in which PuTTY spawns a subprocess and this change _doesn't_
apply is when the subprocess is a proxy command which happens to be a
Plink. Recognising Plink commands in that situation would be fragile
and unreliable, and in any case if the user wants a proxy Plink to be
ACL-restricted, they are in control of its exact command line so they
can add -restrict-acl themselves.
2017-02-04 07:57:36 +00:00
|
|
|
if (*p == '&' && p[1] == 'R' &&
|
|
|
|
(!p[2] || p[2] == '@' || p[2] == '&')) {
|
|
|
|
/* &R restrict-acl prefix */
|
|
|
|
restrict_process_acl();
|
|
|
|
p += 2;
|
|
|
|
}
|
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
if (*p == '@') {
|
2010-12-23 17:32:28 +00:00
|
|
|
/*
|
|
|
|
* An initial @ means that the whole of the rest of the
|
|
|
|
* command line should be treated as the name of a saved
|
|
|
|
* session, with _no quoting or escaping_. This makes it a
|
|
|
|
* very convenient means of automated saved-session
|
|
|
|
* launching, via IDM_SAVEDSESS or Windows 7 jump lists.
|
|
|
|
*/
|
2019-09-08 19:29:00 +00:00
|
|
|
int i = strlen(p);
|
|
|
|
while (i > 1 && isspace(p[i - 1]))
|
|
|
|
i--;
|
|
|
|
p[i] = '\0';
|
|
|
|
do_defaults(p + 1, conf);
|
2020-02-02 10:00:42 +00:00
|
|
|
if (!conf_launchable(conf) && !do_config(conf)) {
|
2019-09-08 19:29:00 +00:00
|
|
|
cleanup_exit(0);
|
|
|
|
}
|
2018-10-29 19:50:29 +00:00
|
|
|
special_launchable_argument = true;
|
2019-09-08 19:29:00 +00:00
|
|
|
} else if (*p == '&') {
|
|
|
|
/*
|
|
|
|
* An initial & means we've been given a command line
|
|
|
|
* containing the hex value of a HANDLE for a file
|
|
|
|
* mapping object, which we must then interpret as a
|
|
|
|
* serialised Conf.
|
|
|
|
*/
|
|
|
|
HANDLE filemap;
|
|
|
|
void *cp;
|
|
|
|
unsigned cpsize;
|
|
|
|
if (sscanf(p + 1, "%p:%u", &filemap, &cpsize) == 2 &&
|
|
|
|
(cp = MapViewOfFile(filemap, FILE_MAP_READ,
|
|
|
|
0, 0, cpsize)) != NULL) {
|
2018-05-28 14:36:15 +00:00
|
|
|
BinarySource src[1];
|
|
|
|
BinarySource_BARE_INIT(src, cp, cpsize);
|
2019-09-08 19:29:00 +00:00
|
|
|
if (!conf_deserialise(conf, src))
|
2018-05-28 14:36:15 +00:00
|
|
|
modalfatalbox("Serialised configuration data was invalid");
|
2019-09-08 19:29:00 +00:00
|
|
|
UnmapViewOfFile(cp);
|
|
|
|
CloseHandle(filemap);
|
2020-02-02 10:00:42 +00:00
|
|
|
} else if (!do_config(conf)) {
|
2019-09-08 19:29:00 +00:00
|
|
|
cleanup_exit(0);
|
|
|
|
}
|
2018-10-29 19:50:29 +00:00
|
|
|
special_launchable_argument = true;
|
2019-09-08 19:29:00 +00:00
|
|
|
} else if (!*p) {
|
Pass -restrict-acl, if given, through to sub-PuTTYs.
This change applies to every situation when GUI PuTTY knowingly spawns
another GUI PuTTY, to wit, the System menu options 'New Session',
'Duplicate Session' and the 'Saved Sessions' submenu.
(Literally speaking, what we actually pass through to the sub-PuTTY's
command line is not the "-restrict-acl" option itself, but a special
prefix "&R", which has the same meaning but which lives in the special
pre-argv-splitting command-line namespace like the magic options used
for Duplicate Session and the old '@sessionname' prefix which the
Saved Sessions submenu still uses. Otherwise, by the time we split up
argv and recognised -restrict-acl, it would be too late to parse those
other options.)
One case in which PuTTY spawns a subprocess and this change _doesn't_
apply is when the subprocess is a proxy command which happens to be a
Plink. Recognising Plink commands in that situation would be fragile
and unreliable, and in any case if the user wants a proxy Plink to be
ACL-restricted, they are in control of its exact command line so they
can add -restrict-acl themselves.
2017-02-04 07:57:36 +00:00
|
|
|
/* Do-nothing case for an empty command line - or rather,
|
|
|
|
* for a command line that's empty _after_ we strip off
|
|
|
|
* the &R prefix. */
|
|
|
|
} else {
|
2019-09-08 19:29:00 +00:00
|
|
|
/*
|
|
|
|
* Otherwise, break up the command line and deal with
|
|
|
|
* it sensibly.
|
|
|
|
*/
|
|
|
|
int argc, i;
|
|
|
|
char **argv;
|
|
|
|
|
|
|
|
split_into_argv(cmdline, &argc, &argv, NULL);
|
|
|
|
|
|
|
|
for (i = 0; i < argc; i++) {
|
|
|
|
char *p = argv[i];
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = cmdline_process_param(p, i+1<argc?argv[i+1]:NULL,
|
|
|
|
1, conf);
|
|
|
|
if (ret == -2) {
|
|
|
|
cmdline_error("option \"%s\" requires an argument", p);
|
|
|
|
} else if (ret == 2) {
|
|
|
|
i++; /* skip next argument */
|
|
|
|
} else if (ret == 1) {
|
|
|
|
continue; /* nothing further needs doing */
|
|
|
|
} else if (!strcmp(p, "-cleanup")) {
|
|
|
|
/*
|
|
|
|
* `putty -cleanup'. Remove all registry
|
|
|
|
* entries associated with PuTTY, and also find
|
|
|
|
* and delete the random seed file.
|
|
|
|
*/
|
|
|
|
char *s1, *s2;
|
|
|
|
s1 = dupprintf("This procedure will remove ALL Registry entries\n"
|
|
|
|
"associated with %s, and will also remove\n"
|
|
|
|
"the random seed file. (This only affects the\n"
|
|
|
|
"currently logged-in user.)\n"
|
|
|
|
"\n"
|
|
|
|
"THIS PROCESS WILL DESTROY YOUR SAVED SESSIONS.\n"
|
|
|
|
"Are you really sure you want to continue?",
|
|
|
|
appname);
|
|
|
|
s2 = dupprintf("%s Warning", appname);
|
2020-02-02 10:00:42 +00:00
|
|
|
if (message_box(NULL, s1, s2,
|
2019-09-08 19:29:00 +00:00
|
|
|
MB_YESNO | MB_ICONWARNING | MB_DEFBUTTON2,
|
|
|
|
HELPCTXID(option_cleanup)) == IDYES) {
|
|
|
|
cleanup_all();
|
|
|
|
}
|
|
|
|
sfree(s1);
|
|
|
|
sfree(s2);
|
|
|
|
exit(0);
|
|
|
|
} else if (!strcmp(p, "-pgpfp")) {
|
2020-02-02 10:00:42 +00:00
|
|
|
pgp_fingerprints_msgbox(NULL);
|
2019-09-08 19:29:00 +00:00
|
|
|
exit(1);
|
|
|
|
} else if (*p != '-') {
|
|
|
|
cmdline_error("unexpected argument \"%s\"", p);
|
|
|
|
} else {
|
|
|
|
cmdline_error("unknown option \"%s\"", p);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
cmdline_run_saved(conf);
|
|
|
|
|
|
|
|
/*
|
Centralise PuTTY and Plink's non-option argument handling.
This is another piece of long-overdue refactoring similar to the
recent commit e3796cb77. But where that one dealt with normalisation
of stuff already stored _in_ a Conf by whatever means (including, in
particular, handling a user typing 'username@host.name' into the
Hostname box of the GUI session dialog box), this one deals with
handling argv entries and putting them into the Conf.
This isn't exactly a pure no-functional-change-at-all refactoring. On
the other hand, it isn't a full-on cleanup that completely
rationalises all the user-visible behaviour as well as the code
structure. It's somewhere in between: I've preserved all the behaviour
quirks that I could imagine a reason for having intended, but taken
the opportunity to _not_ faithfully replicate anything I thought was
clearly just a bug.
So, for example, the following inconsistency is carefully preserved:
the command 'plink -load session nextword' treats 'nextword' as a host
name if the loaded session hasn't provided a hostname already, and
otherwise treats 'nextword' as the remote command to execute on the
already-specified remote host, but the same combination of arguments
to GUI PuTTY will _always_ treat 'nextword' as a hostname, overriding
a hostname (if any) in the saved session. That makes some sense to me
because of the different shapes of the overall command lines.
On the other hand, there are two behaviour changes I know of as a
result of this commit: a third argument to GUI PuTTY (after a hostname
and port) now provokes an error message instead of being silently
ignored, and in Plink, if you combine a -P option (specifying a port
number) with the historical comma-separated protocol selection prefix
on the hostname argument (which I'd completely forgotten even existed
until this piece of work), then the -P will now override the selected
protocol's default port number, whereas previously the default port
would win. For example, 'plink -P 12345 telnet,hostname' will now
connect via Telnet to port 12345 instead of to port 23.
There may be scope for removing or rethinking some of the command-
line syntax quirks in the wake of this change. If we do decide to do
anything like that, then hopefully having it all in one place will
make it easier to remove or change things consistently across the
tools.
2017-12-07 19:59:43 +00:00
|
|
|
* Bring up the config dialog if the command line hasn't
|
|
|
|
* (explicitly) specified a launchable configuration.
|
|
|
|
*/
|
|
|
|
if (!(special_launchable_argument || cmdline_host_ok(conf))) {
|
2020-02-02 10:00:42 +00:00
|
|
|
if (!do_config(conf))
|
Centralise PuTTY and Plink's non-option argument handling.
This is another piece of long-overdue refactoring similar to the
recent commit e3796cb77. But where that one dealt with normalisation
of stuff already stored _in_ a Conf by whatever means (including, in
particular, handling a user typing 'username@host.name' into the
Hostname box of the GUI session dialog box), this one deals with
handling argv entries and putting them into the Conf.
This isn't exactly a pure no-functional-change-at-all refactoring. On
the other hand, it isn't a full-on cleanup that completely
rationalises all the user-visible behaviour as well as the code
structure. It's somewhere in between: I've preserved all the behaviour
quirks that I could imagine a reason for having intended, but taken
the opportunity to _not_ faithfully replicate anything I thought was
clearly just a bug.
So, for example, the following inconsistency is carefully preserved:
the command 'plink -load session nextword' treats 'nextword' as a host
name if the loaded session hasn't provided a hostname already, and
otherwise treats 'nextword' as the remote command to execute on the
already-specified remote host, but the same combination of arguments
to GUI PuTTY will _always_ treat 'nextword' as a hostname, overriding
a hostname (if any) in the saved session. That makes some sense to me
because of the different shapes of the overall command lines.
On the other hand, there are two behaviour changes I know of as a
result of this commit: a third argument to GUI PuTTY (after a hostname
and port) now provokes an error message instead of being silently
ignored, and in Plink, if you combine a -P option (specifying a port
number) with the historical comma-separated protocol selection prefix
on the hostname argument (which I'd completely forgotten even existed
until this piece of work), then the -P will now override the selected
protocol's default port number, whereas previously the default port
would win. For example, 'plink -P 12345 telnet,hostname' will now
connect via Telnet to port 12345 instead of to port 23.
There may be scope for removing or rethinking some of the command-
line syntax quirks in the wake of this change. If we do decide to do
anything like that, then hopefully having it all in one place will
make it easier to remove or change things consistently across the
tools.
2017-12-07 19:59:43 +00:00
|
|
|
cleanup_exit(0);
|
2019-09-08 19:29:00 +00:00
|
|
|
}
|
2002-08-04 21:18:56 +00:00
|
|
|
|
2017-12-03 14:35:03 +00:00
|
|
|
prepare_session(conf);
|
1999-01-08 13:02:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!prev) {
|
2015-07-27 19:06:02 +00:00
|
|
|
WNDCLASSW wndclass;
|
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
wndclass.style = 0;
|
|
|
|
wndclass.lpfnWndProc = WndProc;
|
|
|
|
wndclass.cbClsExtra = 0;
|
|
|
|
wndclass.cbWndExtra = 0;
|
|
|
|
wndclass.hInstance = inst;
|
|
|
|
wndclass.hIcon = LoadIcon(inst, MAKEINTRESOURCE(IDI_MAINICON));
|
|
|
|
wndclass.hCursor = LoadCursor(NULL, IDC_IBEAM);
|
|
|
|
wndclass.hbrBackground = NULL;
|
|
|
|
wndclass.lpszMenuName = NULL;
|
|
|
|
wndclass.lpszClassName = dup_mb_to_wc(DEFAULT_CODEPAGE, 0, appname);
|
|
|
|
|
|
|
|
RegisterClassW(&wndclass);
|
1999-01-08 13:02:13 +00:00
|
|
|
}
|
|
|
|
|
2003-01-14 18:28:23 +00:00
|
|
|
memset(&ucsdata, 0, sizeof(ucsdata));
|
|
|
|
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
conf_cache_data();
|
|
|
|
|
1999-01-08 13:02:13 +00:00
|
|
|
/*
|
|
|
|
* Guess some defaults for the window size. This all gets
|
|
|
|
* updated later, so we don't really care too much. However, we
|
|
|
|
* do want the font width/height guesses to correspond to a
|
|
|
|
* large font rather than a small one...
|
|
|
|
*/
|
2001-05-06 14:35:20 +00:00
|
|
|
|
1999-01-08 13:02:13 +00:00
|
|
|
font_width = 10;
|
|
|
|
font_height = 20;
|
|
|
|
extra_width = 25;
|
|
|
|
extra_height = 28;
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
guess_width = extra_width + font_width * conf_get_int(conf, CONF_width);
|
|
|
|
guess_height = extra_height + font_height*conf_get_int(conf, CONF_height);
|
1999-01-08 13:02:13 +00:00
|
|
|
{
|
2019-09-08 19:29:00 +00:00
|
|
|
RECT r;
|
|
|
|
get_fullscreen_rect(&r);
|
|
|
|
if (guess_width > r.right - r.left)
|
|
|
|
guess_width = r.right - r.left;
|
|
|
|
if (guess_height > r.bottom - r.top)
|
|
|
|
guess_height = r.bottom - r.top;
|
1999-01-08 13:02:13 +00:00
|
|
|
}
|
|
|
|
|
2000-07-26 12:13:51 +00:00
|
|
|
{
|
2019-09-08 19:29:00 +00:00
|
|
|
int winmode = WS_OVERLAPPEDWINDOW | WS_VSCROLL;
|
|
|
|
int exwinmode = 0;
|
2020-02-14 12:49:56 +00:00
|
|
|
const struct BackendVtable *vt =
|
|
|
|
backend_vt_from_proto(be_default_protocol);
|
|
|
|
bool resize_forbidden = false;
|
|
|
|
if (vt && vt->flags & BACKEND_RESIZE_FORBIDDEN)
|
|
|
|
resize_forbidden = true;
|
2015-07-27 19:06:02 +00:00
|
|
|
wchar_t *uappname = dup_mb_to_wc(DEFAULT_CODEPAGE, 0, appname);
|
2019-09-08 19:29:00 +00:00
|
|
|
if (!conf_get_bool(conf, CONF_scrollbar))
|
|
|
|
winmode &= ~(WS_VSCROLL);
|
2020-02-14 12:49:56 +00:00
|
|
|
if (conf_get_int(conf, CONF_resize_action) == RESIZE_DISABLED ||
|
|
|
|
resize_forbidden)
|
2019-09-08 19:29:00 +00:00
|
|
|
winmode &= ~(WS_THICKFRAME | WS_MAXIMIZEBOX);
|
|
|
|
if (conf_get_bool(conf, CONF_alwaysontop))
|
|
|
|
exwinmode |= WS_EX_TOPMOST;
|
|
|
|
if (conf_get_bool(conf, CONF_sunken_edge))
|
|
|
|
exwinmode |= WS_EX_CLIENTEDGE;
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
wgs.term_hwnd = CreateWindowExW(
|
|
|
|
exwinmode, uappname, uappname, winmode, CW_USEDEFAULT,
|
|
|
|
CW_USEDEFAULT, guess_width, guess_height, NULL, NULL, inst, NULL);
|
2015-07-27 19:06:02 +00:00
|
|
|
sfree(uappname);
|
2001-05-06 14:35:20 +00:00
|
|
|
}
|
1999-01-08 13:02:13 +00:00
|
|
|
|
2012-05-13 15:59:24 +00:00
|
|
|
/*
|
|
|
|
* Initialise the fonts, simultaneously correcting the guesses
|
|
|
|
* for font_{width,height}.
|
|
|
|
*/
|
|
|
|
init_fonts(0,0);
|
|
|
|
|
Centralise palette setup into terminal.c.
Now terminal.c makes nearly all the decisions about what the colour
palette should actually contain: it does the job of reading the
GUI-configurable colours out of Conf, and also the job of making up
the rest of the xterm-256 palette. The only exception is that TermWin
can provide a method to override some of the default colours, which on
Windows is used to implement the 'Use system colours' config option.
This saves code overall, partly because the front ends don't have to
be able to send palette data back to the Terminal any more (the
Terminal keeps the master copy and can answer palette-query escape
sequences from its own knowledge), and also because now there's only
one copy of the xterm-256 palette setup code (previously gtkwin.c and
window.c each had their own version of it).
In this rewrite, I've also introduced a multi-layered storage system
for the palette data in Terminal. One layer contains the palette
information derived from Conf; the next contains platform overrides
(currently just Windows's 'Use system colours'); the last one contains
overrides set by escape sequences in the middle of the session. The
topmost two layers can each _conditionally_ override the ones below.
As a result, if a server-side application manually resets (say) the
default fg and bg colours in mid-session to something that works well
in a particular application, those changes won't be wiped out by a
change in the Windows system colours or the Conf, which they would
have been before. Instead, changes in Conf or the system colours alter
the lower layers of the structure, but then when palette_rebuild is
called, the upper layer continues to override them, until a palette
reset (ESC]R) or terminal reset (e.g. ESC c) removes those upper-layer
changes. This seems like a more consistent strategy, in that the same
set of configuration settings will produce the same end result
regardless of what order they were applied in.
The palette-related methods in TermWin have had a total rework.
palette_get and palette_reset are both gone; palette_set can now set a
contiguous range of colours in one go; and the new
palette_get_overrides replaces window.c's old systopalette().
2021-02-07 19:59:21 +00:00
|
|
|
/*
|
|
|
|
* Prepare a logical palette.
|
|
|
|
*/
|
|
|
|
init_palette();
|
|
|
|
|
2004-11-27 19:41:24 +00:00
|
|
|
/*
|
|
|
|
* Initialise the terminal. (We have to do this _after_
|
|
|
|
* creating the window, since the terminal is the first thing
|
|
|
|
* which will call schedule_timer(), which will in turn call
|
2004-11-29 16:58:02 +00:00
|
|
|
* timer_change_notify() which will expect hwnd to exist.)
|
2004-11-27 19:41:24 +00:00
|
|
|
*/
|
Remove the 'Frontend' type and replace it with a vtable.
After the recent Seat and LogContext revamps, _nearly_ all the
remaining uses of the type 'Frontend' were in terminal.c, which needs
all sorts of interactions with the GUI window the terminal lives in,
from the obvious (actually drawing text on the window, reading and
writing the clipboard) to the obscure (minimising, maximising and
moving the window in response to particular escape sequences).
All of those functions are now provided by an abstraction called
TermWin. The few remaining uses of Frontend after _that_ are internal
to a particular platform directory, so as to spread the implementation
of that particular kind of Frontend between multiple source files; so
I've renamed all of those so that they take a more specifically named
type that refers to the particular implementation rather than the
general abstraction.
So now the name 'Frontend' no longer exists in the code base at all,
and everywhere one used to be used, it's completely clear whether it
was operating in one of Frontend's three abstract roles (and if so,
which), or whether it was specific to a particular implementation.
Another type that's disappeared is 'Context', which used to be a
typedef defined to something different on each platform, describing
whatever short-lived resources were necessary to draw on the terminal
window: the front end would provide a ready-made one when calling
term_paint, and the terminal could request one with get_ctx/free_ctx
if it wanted to do proactive window updates. Now that drawing context
lives inside the TermWin itself, because there was never any need to
have two of those contexts live at the same time.
(Another minor API change is that the window-title functions - both
reading and writing - have had a missing 'const' added to their char *
parameters / return values.)
I don't expect this change to enable any particularly interesting new
functionality (in particular, I have no plans that need more than one
implementation of TermWin in the same application). But it completes
the tidying-up that began with the Seat and LogContext rework.
2018-10-25 17:44:04 +00:00
|
|
|
wintw->vt = &windows_termwin_vt;
|
|
|
|
term = term_init(conf, &ucsdata, wintw);
|
2017-12-10 17:16:50 +00:00
|
|
|
setup_clipboards(term, conf);
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
logctx = log_init(&wgs.logpolicy, conf);
|
2004-11-27 19:41:24 +00:00
|
|
|
term_provide_logctx(term, logctx);
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
term_size(term, conf_get_int(conf, CONF_height),
|
2019-09-08 19:29:00 +00:00
|
|
|
conf_get_int(conf, CONF_width),
|
|
|
|
conf_get_int(conf, CONF_savelines));
|
2004-11-27 19:41:24 +00:00
|
|
|
|
1999-01-08 13:02:13 +00:00
|
|
|
/*
|
|
|
|
* Correct the guesses for extra_{width,height}.
|
|
|
|
*/
|
|
|
|
{
|
2019-09-08 19:29:00 +00:00
|
|
|
RECT cr, wr;
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
GetWindowRect(wgs.term_hwnd, &wr);
|
|
|
|
GetClientRect(wgs.term_hwnd, &cr);
|
2019-09-08 19:29:00 +00:00
|
|
|
offset_width = offset_height = conf_get_int(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;
|
1999-01-08 13:02:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Resize the window, now we know what size we _really_ want it
|
|
|
|
* to be.
|
|
|
|
*/
|
2002-10-22 16:11:33 +00:00
|
|
|
guess_width = extra_width + font_width * term->cols;
|
|
|
|
guess_height = extra_height + font_height * term->rows;
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
SetWindowPos(wgs.term_hwnd, NULL, 0, 0, guess_width, guess_height,
|
2019-09-08 19:29:00 +00:00
|
|
|
SWP_NOMOVE | SWP_NOREDRAW | SWP_NOZORDER);
|
1999-01-08 13:02:13 +00:00
|
|
|
|
2000-09-29 10:32:07 +00:00
|
|
|
/*
|
|
|
|
* Set up a caret bitmap, with no content.
|
|
|
|
*/
|
|
|
|
{
|
2019-09-08 19:29:00 +00:00
|
|
|
char *bits;
|
|
|
|
int size = (font_width + 15) / 16 * 2 * font_height;
|
|
|
|
bits = snewn(size, char);
|
|
|
|
memset(bits, 0, size);
|
|
|
|
caretbm = CreateBitmap(font_width, font_height, 1, 1, bits);
|
|
|
|
sfree(bits);
|
2000-09-29 10:32:07 +00:00
|
|
|
}
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
CreateCaret(wgs.term_hwnd, caretbm, font_width, font_height);
|
2000-09-29 10:32:07 +00:00
|
|
|
|
1999-01-08 13:02:13 +00:00
|
|
|
/*
|
|
|
|
* Initialise the scroll bar.
|
|
|
|
*/
|
|
|
|
{
|
2019-09-08 19:29:00 +00:00
|
|
|
SCROLLINFO si;
|
|
|
|
|
|
|
|
si.cbSize = sizeof(si);
|
|
|
|
si.fMask = SIF_ALL | SIF_DISABLENOSCROLL;
|
|
|
|
si.nMin = 0;
|
|
|
|
si.nMax = term->rows - 1;
|
|
|
|
si.nPage = term->rows;
|
|
|
|
si.nPos = 0;
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
SetScrollInfo(wgs.term_hwnd, SB_VERT, &si, false);
|
1999-01-08 13:02:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Prepare the mouse handler.
|
|
|
|
*/
|
|
|
|
lastact = MA_NOTHING;
|
2001-05-06 14:20:41 +00:00
|
|
|
lastbtn = MBT_NOTHING;
|
1999-01-08 13:02:13 +00:00
|
|
|
dbltime = GetDoubleClickTime();
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set up the session-control options on the system menu.
|
|
|
|
*/
|
|
|
|
{
|
2019-09-08 19:29:00 +00:00
|
|
|
HMENU m;
|
|
|
|
int j;
|
|
|
|
char *str;
|
|
|
|
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
popup_menus[SYSMENU].menu = GetSystemMenu(wgs.term_hwnd, false);
|
2019-09-08 19:29:00 +00:00
|
|
|
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");
|
|
|
|
|
|
|
|
savedsess_menu = CreateMenu();
|
|
|
|
get_sesslist(&sesslist, true);
|
|
|
|
update_savedsess_menu();
|
|
|
|
|
|
|
|
for (j = 0; j < lenof(popup_menus); j++) {
|
|
|
|
m = popup_menus[j].menu;
|
|
|
|
|
|
|
|
AppendMenu(m, MF_SEPARATOR, 0, 0);
|
|
|
|
AppendMenu(m, MF_ENABLED, IDM_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,
|
|
|
|
"Sa&ved Sessions");
|
|
|
|
AppendMenu(m, MF_ENABLED, IDM_RECONF, "Chan&ge Settings...");
|
|
|
|
AppendMenu(m, MF_SEPARATOR, 0, 0);
|
|
|
|
AppendMenu(m, MF_ENABLED, IDM_COPYALL, "C&opy All to Clipboard");
|
|
|
|
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)
|
|
|
|
== RESIZE_DISABLED) ? MF_GRAYED : MF_ENABLED,
|
|
|
|
IDM_FULLSCREEN, "&Full Screen");
|
|
|
|
AppendMenu(m, MF_SEPARATOR, 0, 0);
|
|
|
|
if (has_help())
|
|
|
|
AppendMenu(m, MF_ENABLED, IDM_HELP, "&Help");
|
|
|
|
str = dupprintf("&About %s", appname);
|
|
|
|
AppendMenu(m, MF_ENABLED, IDM_ABOUT, str);
|
|
|
|
sfree(str);
|
|
|
|
}
|
1999-01-08 13:02:13 +00:00
|
|
|
}
|
|
|
|
|
2020-02-02 10:00:42 +00:00
|
|
|
if (restricted_acl()) {
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
lp_eventlog(&wgs.logpolicy, "Running with restricted process ACL");
|
2017-02-11 00:44:00 +00:00
|
|
|
}
|
|
|
|
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
winselgui_set_hwnd(wgs.term_hwnd);
|
2004-10-17 14:44:27 +00:00
|
|
|
start_backend();
|
2003-04-04 20:21:05 +00:00
|
|
|
|
2001-11-29 21:30:59 +00:00
|
|
|
/*
|
|
|
|
* Set up the initial input locale.
|
|
|
|
*/
|
|
|
|
set_input_locale(GetKeyboardLayout(0));
|
|
|
|
|
2001-01-07 18:24:59 +00:00
|
|
|
/*
|
2001-12-14 14:57:50 +00:00
|
|
|
* Finally show the window!
|
2001-01-07 18:24:59 +00:00
|
|
|
*/
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
ShowWindow(wgs.term_hwnd, show);
|
|
|
|
SetForegroundWindow(wgs.term_hwnd);
|
2001-01-07 18:24:59 +00:00
|
|
|
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
term_set_focus(term, GetForegroundWindow() == wgs.term_hwnd);
|
|
|
|
UpdateWindow(wgs.term_hwnd);
|
1999-01-08 13:02:13 +00:00
|
|
|
|
2006-08-25 22:10:16 +00:00
|
|
|
while (1) {
|
2019-09-08 19:29:00 +00:00
|
|
|
HANDLE *handles;
|
|
|
|
int nhandles, n;
|
2013-09-15 14:05:31 +00:00
|
|
|
DWORD timeout;
|
|
|
|
|
2013-11-11 23:01:47 +00:00
|
|
|
if (toplevel_callback_pending() ||
|
|
|
|
PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {
|
2013-10-25 17:44:02 +00:00
|
|
|
/*
|
|
|
|
* If we have anything we'd like to do immediately, set
|
|
|
|
* the timeout for MsgWaitForMultipleObjects to zero so
|
|
|
|
* that we'll only do a quick check of our handles and
|
|
|
|
* then get on with whatever that was.
|
|
|
|
*
|
|
|
|
* One such option is a pending toplevel callback. The
|
|
|
|
* other is a non-empty Windows message queue, which you'd
|
|
|
|
* think we could leave to MsgWaitForMultipleObjects to
|
|
|
|
* check for us along with all the handles, but in fact we
|
|
|
|
* can't because once PeekMessage in one iteration of this
|
|
|
|
* loop has removed a message from the queue, the whole
|
|
|
|
* queue is considered uninteresting by the next
|
|
|
|
* invocation of MWFMO. So we check ourselves whether the
|
|
|
|
* message queue is non-empty, and if so, set this timeout
|
|
|
|
* to zero to ensure MWFMO doesn't block.
|
|
|
|
*/
|
2013-09-15 14:05:31 +00:00
|
|
|
timeout = 0;
|
|
|
|
} else {
|
|
|
|
timeout = INFINITE;
|
|
|
|
/* The messages seem unreliable; especially if we're being tricky */
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
term_set_focus(term, GetForegroundWindow() == wgs.term_hwnd);
|
2013-09-15 14:05:31 +00:00
|
|
|
}
|
2006-08-25 22:10:16 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
handles = handle_get_events(&nhandles);
|
2006-08-25 22:10:16 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
n = MsgWaitForMultipleObjects(nhandles, handles, false,
|
2013-09-15 14:05:31 +00:00
|
|
|
timeout, QS_ALLINPUT);
|
2006-08-25 22:10:16 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
if ((unsigned)(n - WAIT_OBJECT_0) < (unsigned)nhandles) {
|
|
|
|
handle_got_event(handles[n - WAIT_OBJECT_0]);
|
|
|
|
sfree(handles);
|
|
|
|
} else
|
|
|
|
sfree(handles);
|
2006-08-25 22:10:16 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) {
|
|
|
|
if (msg.message == WM_QUIT)
|
|
|
|
goto finished; /* two-level break */
|
2006-08-25 22:10:16 +00:00
|
|
|
|
2020-02-02 10:00:42 +00:00
|
|
|
HWND logbox = event_log_window();
|
2019-09-08 19:29:00 +00:00
|
|
|
if (!(IsWindow(logbox) && IsDialogMessage(logbox, &msg)))
|
|
|
|
DispatchMessageW(&msg);
|
2015-03-07 17:10:36 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* WM_NETEVENT messages seem to jump ahead of others in
|
|
|
|
* the message queue. I'm not sure why; the docs for
|
|
|
|
* PeekMessage mention that messages are prioritised in
|
|
|
|
* some way, but I'm unclear on which priorities go where.
|
|
|
|
*
|
|
|
|
* Anyway, in practice I observe that WM_NETEVENT seems to
|
|
|
|
* jump to the head of the queue, which means that if we
|
|
|
|
* were to only process one message every time round this
|
|
|
|
* loop, we'd get nothing but NETEVENTs if the server
|
|
|
|
* flooded us with data, and stop responding to any other
|
|
|
|
* kind of window message. So instead, we keep on round
|
|
|
|
* this loop until we've consumed at least one message
|
|
|
|
* that _isn't_ a NETEVENT, or run out of messages
|
|
|
|
* completely (whichever comes first). And we don't go to
|
|
|
|
* run_toplevel_callbacks (which is where the netevents
|
|
|
|
* are actually processed, causing fresh NETEVENT messages
|
|
|
|
* to appear) until we've done this.
|
|
|
|
*/
|
|
|
|
if (msg.message != WM_NETEVENT)
|
|
|
|
break;
|
2019-09-08 19:29:00 +00:00
|
|
|
}
|
2001-11-25 18:39:57 +00:00
|
|
|
|
2013-09-15 14:05:31 +00:00
|
|
|
run_toplevel_callbacks();
|
1999-01-08 13:02:13 +00:00
|
|
|
}
|
|
|
|
|
2006-08-25 22:10:16 +00:00
|
|
|
finished:
|
2019-09-08 19:29:00 +00:00
|
|
|
cleanup_exit(msg.wParam); /* this doesn't return... */
|
|
|
|
return msg.wParam; /* ... but optimiser doesn't know */
|
2002-03-06 20:13:22 +00:00
|
|
|
}
|
|
|
|
|
2017-12-10 17:16:50 +00:00
|
|
|
static void setup_clipboards(Terminal *term, Conf *conf)
|
|
|
|
{
|
|
|
|
assert(term->mouse_select_clipboards[0] == CLIP_LOCAL);
|
|
|
|
|
|
|
|
term->n_mouse_select_clipboards = 1;
|
|
|
|
|
2018-10-29 19:57:31 +00:00
|
|
|
if (conf_get_bool(conf, CONF_mouseautocopy)) {
|
2017-12-10 17:16:50 +00:00
|
|
|
term->mouse_select_clipboards[
|
|
|
|
term->n_mouse_select_clipboards++] = CLIP_SYSTEM;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (conf_get_int(conf, CONF_mousepaste)) {
|
|
|
|
case CLIPUI_IMPLICIT:
|
|
|
|
term->mouse_paste_clipboard = CLIP_LOCAL;
|
|
|
|
break;
|
|
|
|
case CLIPUI_EXPLICIT:
|
|
|
|
term->mouse_paste_clipboard = CLIP_SYSTEM;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
term->mouse_paste_clipboard = CLIP_NULL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-03-06 20:13:22 +00:00
|
|
|
/*
|
|
|
|
* Clean up and exit.
|
|
|
|
*/
|
|
|
|
void cleanup_exit(int code)
|
|
|
|
{
|
1999-01-08 13:02:13 +00:00
|
|
|
/*
|
|
|
|
* Clean up.
|
|
|
|
*/
|
2001-05-10 08:34:20 +00:00
|
|
|
deinit_fonts();
|
1999-01-08 13:02:13 +00:00
|
|
|
sfree(logpal);
|
|
|
|
if (pal)
|
2019-09-08 19:29:00 +00:00
|
|
|
DeleteObject(pal);
|
2002-03-06 20:13:22 +00:00
|
|
|
sk_cleanup();
|
1999-01-08 13:02:13 +00:00
|
|
|
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
if (conf_get_int(conf, CONF_protocol) == PROT_SSH) {
|
2019-09-08 19:29:00 +00:00
|
|
|
random_save_seed();
|
2000-03-24 09:45:49 +00:00
|
|
|
}
|
2006-12-17 11:16:07 +00:00
|
|
|
shutdown_help();
|
1999-01-08 13:02:13 +00:00
|
|
|
|
2010-12-23 17:32:28 +00:00
|
|
|
/* Clean up COM. */
|
|
|
|
CoUninitialize();
|
|
|
|
|
2002-03-06 20:13:22 +00:00
|
|
|
exit(code);
|
1999-01-08 13:02:13 +00:00
|
|
|
}
|
|
|
|
|
2005-04-07 01:36:28 +00:00
|
|
|
/*
|
|
|
|
* Refresh the saved-session submenu from `sesslist'.
|
|
|
|
*/
|
|
|
|
static void update_savedsess_menu(void)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
while (DeleteMenu(savedsess_menu, 0, MF_BYPOSITION)) ;
|
|
|
|
/* skip sesslist.sessions[0] == Default Settings */
|
|
|
|
for (i = 1;
|
2019-09-08 19:29:00 +00:00
|
|
|
i < ((sesslist.nsessions <= MENU_SAVED_MAX+1) ? sesslist.nsessions
|
|
|
|
: MENU_SAVED_MAX+1);
|
|
|
|
i++)
|
|
|
|
AppendMenu(savedsess_menu, MF_ENABLED,
|
|
|
|
IDM_SAVED_MIN + (i-1)*MENU_SAVED_STEP,
|
|
|
|
sesslist.sessions[i]);
|
2009-09-13 23:29:11 +00:00
|
|
|
if (sesslist.nsessions <= 1)
|
2019-09-08 19:29:00 +00:00
|
|
|
AppendMenu(savedsess_menu, MF_GRAYED, IDM_SAVED_MIN, "(No sessions)");
|
2005-04-07 01:36:28 +00:00
|
|
|
}
|
|
|
|
|
2003-04-04 20:21:05 +00:00
|
|
|
/*
|
|
|
|
* Update the Special Commands submenu.
|
|
|
|
*/
|
New abstraction 'Seat', to pass to backends.
This is a new vtable-based abstraction which is passed to a backend in
place of Frontend, and it implements only the subset of the Frontend
functions needed by a backend. (Many other Frontend functions still
exist, notably the wide range of things called by terminal.c providing
platform-independent operations on the GUI terminal window.)
The purpose of making it a vtable is that this opens up the
possibility of creating a backend as an internal implementation detail
of some other activity, by providing just that one backend with a
custom Seat that implements the methods differently.
For example, this refactoring should make it feasible to directly
implement an SSH proxy type, aka the 'jump host' feature supported by
OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP
mode, and then expose the main channel of that as the Socket for the
primary connection'. (Which of course you can already do by spawning
'plink -nc' as a separate proxy process, but this would permit it in
the _same_ process without anything getting confused.)
I've centralised a full set of stub methods in misc.c for the new
abstraction, which allows me to get rid of several annoying stubs in
the previous code. Also, while I'm here, I've moved a lot of
duplicated modalfatalbox() type functions from application main
program files into wincons.c / uxcons.c, which I think saves
duplication overall. (A minor visible effect is that the prefixes on
those console-based fatal error messages will now be more consistent
between applications.)
2018-10-11 18:58:42 +00:00
|
|
|
static void win_seat_update_specials_menu(Seat *seat)
|
2003-04-04 20:21:05 +00:00
|
|
|
{
|
2006-02-09 23:06:57 +00:00
|
|
|
HMENU new_menu;
|
2003-11-19 20:48:30 +00:00
|
|
|
int i, j;
|
2003-04-04 20:21:05 +00:00
|
|
|
|
2018-09-11 15:23:38 +00:00
|
|
|
if (backend)
|
|
|
|
specials = backend_get_specials(backend);
|
2004-08-14 13:04:18 +00:00
|
|
|
else
|
2019-09-08 19:29:00 +00:00
|
|
|
specials = NULL;
|
2004-08-14 13:04:18 +00:00
|
|
|
|
2003-04-04 20:21:05 +00:00
|
|
|
if (specials) {
|
2019-09-08 19:29:00 +00:00
|
|
|
/* 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;
|
|
|
|
int nesting = 1;
|
|
|
|
new_menu = CreatePopupMenu();
|
|
|
|
for (i = 0; nesting > 0; i++) {
|
|
|
|
assert(IDM_SPECIAL_MIN + 0x10 * i < IDM_SPECIAL_MAX);
|
|
|
|
switch (specials[i].code) {
|
|
|
|
case SS_SEP:
|
|
|
|
AppendMenu(new_menu, MF_SEPARATOR, 0, 0);
|
|
|
|
break;
|
|
|
|
case SS_SUBMENU:
|
|
|
|
assert(nesting < 2);
|
|
|
|
nesting++;
|
|
|
|
saved_menu = new_menu; /* XXX lame stacking */
|
|
|
|
new_menu = CreatePopupMenu();
|
|
|
|
AppendMenu(saved_menu, MF_POPUP | MF_ENABLED,
|
|
|
|
(UINT_PTR) new_menu, specials[i].name);
|
|
|
|
break;
|
|
|
|
case SS_EXITMENU:
|
|
|
|
nesting--;
|
|
|
|
if (nesting) {
|
|
|
|
new_menu = saved_menu; /* XXX lame stacking */
|
|
|
|
saved_menu = NULL;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
AppendMenu(new_menu, MF_ENABLED, IDM_SPECIAL_MIN + 0x10 * i,
|
|
|
|
specials[i].name);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* Squirrel the highest special. */
|
|
|
|
n_specials = i - 1;
|
2004-10-17 21:22:22 +00:00
|
|
|
} else {
|
2019-09-08 19:29:00 +00:00
|
|
|
new_menu = NULL;
|
|
|
|
n_specials = 0;
|
2004-10-17 21:22:22 +00:00
|
|
|
}
|
2004-08-14 13:04:18 +00:00
|
|
|
|
|
|
|
for (j = 0; j < lenof(popup_menus); j++) {
|
2019-09-08 19:29:00 +00:00
|
|
|
if (specials_menu) {
|
|
|
|
/* XXX does this free up all submenus? */
|
|
|
|
DeleteMenu(popup_menus[j].menu, (UINT_PTR)specials_menu,
|
2016-04-02 13:10:27 +00:00
|
|
|
MF_BYCOMMAND);
|
2019-09-08 19:29:00 +00:00
|
|
|
DeleteMenu(popup_menus[j].menu, IDM_SPECIALSEP, MF_BYCOMMAND);
|
|
|
|
}
|
|
|
|
if (new_menu) {
|
|
|
|
InsertMenu(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,
|
|
|
|
MF_BYCOMMAND | MF_SEPARATOR, IDM_SPECIALSEP, 0);
|
|
|
|
}
|
2003-04-04 20:21:05 +00:00
|
|
|
}
|
2006-02-10 20:57:40 +00:00
|
|
|
specials_menu = new_menu;
|
2003-04-04 20:21:05 +00:00
|
|
|
}
|
|
|
|
|
2005-02-15 17:05:58 +00:00
|
|
|
static void update_mouse_pointer(void)
|
|
|
|
{
|
2018-06-03 20:48:08 +00:00
|
|
|
LPTSTR curstype = NULL;
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool force_visible = false;
|
|
|
|
static bool forced_visible = false;
|
2005-02-15 17:05:58 +00:00
|
|
|
switch (busy_status) {
|
|
|
|
case BUSY_NOT:
|
2021-02-07 19:59:21 +00:00
|
|
|
if (pointer_indicates_raw_mouse)
|
2019-09-08 19:29:00 +00:00
|
|
|
curstype = IDC_ARROW;
|
|
|
|
else
|
|
|
|
curstype = IDC_IBEAM;
|
|
|
|
break;
|
2005-02-15 17:05:58 +00:00
|
|
|
case BUSY_WAITING:
|
2019-09-08 19:29:00 +00:00
|
|
|
curstype = IDC_APPSTARTING; /* this may be an abuse */
|
|
|
|
force_visible = true;
|
|
|
|
break;
|
2005-02-15 17:05:58 +00:00
|
|
|
case BUSY_CPU:
|
2019-09-08 19:29:00 +00:00
|
|
|
curstype = IDC_WAIT;
|
|
|
|
force_visible = true;
|
|
|
|
break;
|
2005-02-15 17:05:58 +00:00
|
|
|
default:
|
2019-09-08 19:29:00 +00:00
|
|
|
unreachable("Bad busy_status");
|
2005-02-15 17:05:58 +00:00
|
|
|
}
|
|
|
|
{
|
2019-09-08 19:29:00 +00:00
|
|
|
HCURSOR cursor = LoadCursor(NULL, curstype);
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
SetClassLongPtr(wgs.term_hwnd, GCLP_HCURSOR, (LONG_PTR)cursor);
|
2019-09-08 19:29:00 +00:00
|
|
|
SetCursor(cursor); /* force redraw of cursor at current posn */
|
2005-02-15 17:05:58 +00:00
|
|
|
}
|
|
|
|
if (force_visible != forced_visible) {
|
2019-09-08 19:29:00 +00:00
|
|
|
/* We want some cursor shapes to be visible always.
|
|
|
|
* Along with show_mouseptr(), this manages the ShowCursor()
|
|
|
|
* counter such that if we switch back to a non-force_visible
|
|
|
|
* cursor, the previous visibility state is restored. */
|
|
|
|
ShowCursor(force_visible);
|
|
|
|
forced_visible = force_visible;
|
2005-02-15 17:05:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
New abstraction 'Seat', to pass to backends.
This is a new vtable-based abstraction which is passed to a backend in
place of Frontend, and it implements only the subset of the Frontend
functions needed by a backend. (Many other Frontend functions still
exist, notably the wide range of things called by terminal.c providing
platform-independent operations on the GUI terminal window.)
The purpose of making it a vtable is that this opens up the
possibility of creating a backend as an internal implementation detail
of some other activity, by providing just that one backend with a
custom Seat that implements the methods differently.
For example, this refactoring should make it feasible to directly
implement an SSH proxy type, aka the 'jump host' feature supported by
OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP
mode, and then expose the main channel of that as the Socket for the
primary connection'. (Which of course you can already do by spawning
'plink -nc' as a separate proxy process, but this would permit it in
the _same_ process without anything getting confused.)
I've centralised a full set of stub methods in misc.c for the new
abstraction, which allows me to get rid of several annoying stubs in
the previous code. Also, while I'm here, I've moved a lot of
duplicated modalfatalbox() type functions from application main
program files into wincons.c / uxcons.c, which I think saves
duplication overall. (A minor visible effect is that the prefixes on
those console-based fatal error messages will now be more consistent
between applications.)
2018-10-11 18:58:42 +00:00
|
|
|
static void win_seat_set_busy_status(Seat *seat, BusyStatus status)
|
2005-02-15 17:05:58 +00:00
|
|
|
{
|
|
|
|
busy_status = status;
|
|
|
|
update_mouse_pointer();
|
|
|
|
}
|
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
static void wintw_set_raw_mouse_mode(TermWin *tw, bool activate)
|
2001-05-06 14:20:41 +00:00
|
|
|
{
|
|
|
|
send_raw_mouse = activate;
|
2021-02-07 19:59:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void wintw_set_raw_mouse_mode_pointer(TermWin *tw, bool activate)
|
|
|
|
{
|
|
|
|
pointer_indicates_raw_mouse = activate;
|
2005-02-15 17:05:58 +00:00
|
|
|
update_mouse_pointer();
|
2001-05-06 14:20:41 +00:00
|
|
|
}
|
|
|
|
|
2000-09-22 11:04:57 +00:00
|
|
|
/*
|
|
|
|
* Print a message box and close the connection.
|
|
|
|
*/
|
New abstraction 'Seat', to pass to backends.
This is a new vtable-based abstraction which is passed to a backend in
place of Frontend, and it implements only the subset of the Frontend
functions needed by a backend. (Many other Frontend functions still
exist, notably the wide range of things called by terminal.c providing
platform-independent operations on the GUI terminal window.)
The purpose of making it a vtable is that this opens up the
possibility of creating a backend as an internal implementation detail
of some other activity, by providing just that one backend with a
custom Seat that implements the methods differently.
For example, this refactoring should make it feasible to directly
implement an SSH proxy type, aka the 'jump host' feature supported by
OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP
mode, and then expose the main channel of that as the Socket for the
primary connection'. (Which of course you can already do by spawning
'plink -nc' as a separate proxy process, but this would permit it in
the _same_ process without anything getting confused.)
I've centralised a full set of stub methods in misc.c for the new
abstraction, which allows me to get rid of several annoying stubs in
the previous code. Also, while I'm here, I've moved a lot of
duplicated modalfatalbox() type functions from application main
program files into wincons.c / uxcons.c, which I think saves
duplication overall. (A minor visible effect is that the prefixes on
those console-based fatal error messages will now be more consistent
between applications.)
2018-10-11 18:58:42 +00:00
|
|
|
static void win_seat_connection_fatal(Seat *seat, const char *msg)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
2018-12-08 21:03:51 +00:00
|
|
|
char *title = dupprintf("%s Fatal Error", appname);
|
2020-04-14 19:36:46 +00:00
|
|
|
show_mouseptr(true);
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
MessageBox(wgs.term_hwnd, msg, title, MB_ICONERROR | MB_OK);
|
2018-12-08 21:03:51 +00:00
|
|
|
sfree(title);
|
2003-05-04 14:14:10 +00:00
|
|
|
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
if (conf_get_int(conf, CONF_close_on_exit) == FORCE_ON)
|
2019-09-08 19:29:00 +00:00
|
|
|
PostQuitMessage(1);
|
2000-09-22 11:04:57 +00:00
|
|
|
else {
|
2019-09-08 19:29:00 +00:00
|
|
|
queue_toplevel_callback(close_session, NULL);
|
2000-09-22 11:04:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-08-04 21:18:56 +00:00
|
|
|
/*
|
|
|
|
* Report an error at the command-line parsing stage.
|
|
|
|
*/
|
2015-05-15 10:15:42 +00:00
|
|
|
void cmdline_error(const char *fmt, ...)
|
2002-08-04 21:18:56 +00:00
|
|
|
{
|
|
|
|
va_list ap;
|
2018-12-08 21:03:51 +00:00
|
|
|
char *message, *title;
|
2002-08-04 21:18:56 +00:00
|
|
|
|
|
|
|
va_start(ap, fmt);
|
2018-12-08 21:03:51 +00:00
|
|
|
message = dupvprintf(fmt, ap);
|
2002-08-04 21:18:56 +00:00
|
|
|
va_end(ap);
|
2018-12-08 21:03:51 +00:00
|
|
|
title = dupprintf("%s Command Line Error", appname);
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
MessageBox(wgs.term_hwnd, message, title, MB_ICONERROR | MB_OK);
|
2018-12-08 21:03:51 +00:00
|
|
|
sfree(message);
|
|
|
|
sfree(title);
|
2002-08-04 21:18:56 +00:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
2000-03-17 10:34:41 +00:00
|
|
|
/*
|
|
|
|
* Actually do the job requested by a WM_NETEVENT
|
|
|
|
*/
|
2013-08-17 16:06:35 +00:00
|
|
|
static void wm_netevent_callback(void *vctx)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
2013-08-17 16:06:35 +00:00
|
|
|
struct wm_netevent_params *params = (struct wm_netevent_params *)vctx;
|
|
|
|
select_result(params->wParam, params->lParam);
|
|
|
|
sfree(vctx);
|
2000-03-17 10:34:41 +00:00
|
|
|
}
|
|
|
|
|
Centralise palette setup into terminal.c.
Now terminal.c makes nearly all the decisions about what the colour
palette should actually contain: it does the job of reading the
GUI-configurable colours out of Conf, and also the job of making up
the rest of the xterm-256 palette. The only exception is that TermWin
can provide a method to override some of the default colours, which on
Windows is used to implement the 'Use system colours' config option.
This saves code overall, partly because the front ends don't have to
be able to send palette data back to the Terminal any more (the
Terminal keeps the master copy and can answer palette-query escape
sequences from its own knowledge), and also because now there's only
one copy of the xterm-256 palette setup code (previously gtkwin.c and
window.c each had their own version of it).
In this rewrite, I've also introduced a multi-layered storage system
for the palette data in Terminal. One layer contains the palette
information derived from Conf; the next contains platform overrides
(currently just Windows's 'Use system colours'); the last one contains
overrides set by escape sequences in the middle of the session. The
topmost two layers can each _conditionally_ override the ones below.
As a result, if a server-side application manually resets (say) the
default fg and bg colours in mid-session to something that works well
in a particular application, those changes won't be wiped out by a
change in the Windows system colours or the Conf, which they would
have been before. Instead, changes in Conf or the system colours alter
the lower layers of the structure, but then when palette_rebuild is
called, the upper layer continues to override them, until a palette
reset (ESC]R) or terminal reset (e.g. ESC c) removes those upper-layer
changes. This seems like a more consistent strategy, in that the same
set of configuration settings will produce the same end result
regardless of what order they were applied in.
The palette-related methods in TermWin have had a total rework.
palette_get and palette_reset are both gone; palette_set can now set a
contiguous range of colours in one go; and the new
palette_get_overrides replaces window.c's old systopalette().
2021-02-07 19:59:21 +00:00
|
|
|
static inline rgb rgb_from_colorref(COLORREF cr)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
Centralise palette setup into terminal.c.
Now terminal.c makes nearly all the decisions about what the colour
palette should actually contain: it does the job of reading the
GUI-configurable colours out of Conf, and also the job of making up
the rest of the xterm-256 palette. The only exception is that TermWin
can provide a method to override some of the default colours, which on
Windows is used to implement the 'Use system colours' config option.
This saves code overall, partly because the front ends don't have to
be able to send palette data back to the Terminal any more (the
Terminal keeps the master copy and can answer palette-query escape
sequences from its own knowledge), and also because now there's only
one copy of the xterm-256 palette setup code (previously gtkwin.c and
window.c each had their own version of it).
In this rewrite, I've also introduced a multi-layered storage system
for the palette data in Terminal. One layer contains the palette
information derived from Conf; the next contains platform overrides
(currently just Windows's 'Use system colours'); the last one contains
overrides set by escape sequences in the middle of the session. The
topmost two layers can each _conditionally_ override the ones below.
As a result, if a server-side application manually resets (say) the
default fg and bg colours in mid-session to something that works well
in a particular application, those changes won't be wiped out by a
change in the Windows system colours or the Conf, which they would
have been before. Instead, changes in Conf or the system colours alter
the lower layers of the structure, but then when palette_rebuild is
called, the upper layer continues to override them, until a palette
reset (ESC]R) or terminal reset (e.g. ESC c) removes those upper-layer
changes. This seems like a more consistent strategy, in that the same
set of configuration settings will produce the same end result
regardless of what order they were applied in.
The palette-related methods in TermWin have had a total rework.
palette_get and palette_reset are both gone; palette_set can now set a
contiguous range of colours in one go; and the new
palette_get_overrides replaces window.c's old systopalette().
2021-02-07 19:59:21 +00:00
|
|
|
rgb toret;
|
|
|
|
toret.r = GetRValue(cr);
|
|
|
|
toret.g = GetGValue(cr);
|
|
|
|
toret.b = GetBValue(cr);
|
|
|
|
return toret;
|
2003-09-03 20:14:38 +00:00
|
|
|
}
|
|
|
|
|
Centralise palette setup into terminal.c.
Now terminal.c makes nearly all the decisions about what the colour
palette should actually contain: it does the job of reading the
GUI-configurable colours out of Conf, and also the job of making up
the rest of the xterm-256 palette. The only exception is that TermWin
can provide a method to override some of the default colours, which on
Windows is used to implement the 'Use system colours' config option.
This saves code overall, partly because the front ends don't have to
be able to send palette data back to the Terminal any more (the
Terminal keeps the master copy and can answer palette-query escape
sequences from its own knowledge), and also because now there's only
one copy of the xterm-256 palette setup code (previously gtkwin.c and
window.c each had their own version of it).
In this rewrite, I've also introduced a multi-layered storage system
for the palette data in Terminal. One layer contains the palette
information derived from Conf; the next contains platform overrides
(currently just Windows's 'Use system colours'); the last one contains
overrides set by escape sequences in the middle of the session. The
topmost two layers can each _conditionally_ override the ones below.
As a result, if a server-side application manually resets (say) the
default fg and bg colours in mid-session to something that works well
in a particular application, those changes won't be wiped out by a
change in the Windows system colours or the Conf, which they would
have been before. Instead, changes in Conf or the system colours alter
the lower layers of the structure, but then when palette_rebuild is
called, the upper layer continues to override them, until a palette
reset (ESC]R) or terminal reset (e.g. ESC c) removes those upper-layer
changes. This seems like a more consistent strategy, in that the same
set of configuration settings will produce the same end result
regardless of what order they were applied in.
The palette-related methods in TermWin have had a total rework.
palette_get and palette_reset are both gone; palette_set can now set a
contiguous range of colours in one go; and the new
palette_get_overrides replaces window.c's old systopalette().
2021-02-07 19:59:21 +00:00
|
|
|
static void wintw_palette_get_overrides(TermWin *tw)
|
2003-09-03 20:14:38 +00:00
|
|
|
{
|
Centralise palette setup into terminal.c.
Now terminal.c makes nearly all the decisions about what the colour
palette should actually contain: it does the job of reading the
GUI-configurable colours out of Conf, and also the job of making up
the rest of the xterm-256 palette. The only exception is that TermWin
can provide a method to override some of the default colours, which on
Windows is used to implement the 'Use system colours' config option.
This saves code overall, partly because the front ends don't have to
be able to send palette data back to the Terminal any more (the
Terminal keeps the master copy and can answer palette-query escape
sequences from its own knowledge), and also because now there's only
one copy of the xterm-256 palette setup code (previously gtkwin.c and
window.c each had their own version of it).
In this rewrite, I've also introduced a multi-layered storage system
for the palette data in Terminal. One layer contains the palette
information derived from Conf; the next contains platform overrides
(currently just Windows's 'Use system colours'); the last one contains
overrides set by escape sequences in the middle of the session. The
topmost two layers can each _conditionally_ override the ones below.
As a result, if a server-side application manually resets (say) the
default fg and bg colours in mid-session to something that works well
in a particular application, those changes won't be wiped out by a
change in the Windows system colours or the Conf, which they would
have been before. Instead, changes in Conf or the system colours alter
the lower layers of the structure, but then when palette_rebuild is
called, the upper layer continues to override them, until a palette
reset (ESC]R) or terminal reset (e.g. ESC c) removes those upper-layer
changes. This seems like a more consistent strategy, in that the same
set of configuration settings will produce the same end result
regardless of what order they were applied in.
The palette-related methods in TermWin have had a total rework.
palette_get and palette_reset are both gone; palette_set can now set a
contiguous range of colours in one go; and the new
palette_get_overrides replaces window.c's old systopalette().
2021-02-07 19:59:21 +00:00
|
|
|
if (conf_get_bool(conf, CONF_system_colour)) {
|
|
|
|
rgb rgb;
|
1999-01-08 13:02:13 +00:00
|
|
|
|
Centralise palette setup into terminal.c.
Now terminal.c makes nearly all the decisions about what the colour
palette should actually contain: it does the job of reading the
GUI-configurable colours out of Conf, and also the job of making up
the rest of the xterm-256 palette. The only exception is that TermWin
can provide a method to override some of the default colours, which on
Windows is used to implement the 'Use system colours' config option.
This saves code overall, partly because the front ends don't have to
be able to send palette data back to the Terminal any more (the
Terminal keeps the master copy and can answer palette-query escape
sequences from its own knowledge), and also because now there's only
one copy of the xterm-256 palette setup code (previously gtkwin.c and
window.c each had their own version of it).
In this rewrite, I've also introduced a multi-layered storage system
for the palette data in Terminal. One layer contains the palette
information derived from Conf; the next contains platform overrides
(currently just Windows's 'Use system colours'); the last one contains
overrides set by escape sequences in the middle of the session. The
topmost two layers can each _conditionally_ override the ones below.
As a result, if a server-side application manually resets (say) the
default fg and bg colours in mid-session to something that works well
in a particular application, those changes won't be wiped out by a
change in the Windows system colours or the Conf, which they would
have been before. Instead, changes in Conf or the system colours alter
the lower layers of the structure, but then when palette_rebuild is
called, the upper layer continues to override them, until a palette
reset (ESC]R) or terminal reset (e.g. ESC c) removes those upper-layer
changes. This seems like a more consistent strategy, in that the same
set of configuration settings will produce the same end result
regardless of what order they were applied in.
The palette-related methods in TermWin have had a total rework.
palette_get and palette_reset are both gone; palette_set can now set a
contiguous range of colours in one go; and the new
palette_get_overrides replaces window.c's old systopalette().
2021-02-07 19:59:21 +00:00
|
|
|
rgb = rgb_from_colorref(GetSysColor(COLOR_WINDOWTEXT));
|
|
|
|
term_palette_override(term, OSC4_COLOUR_fg, rgb);
|
|
|
|
term_palette_override(term, OSC4_COLOUR_fg_bold, rgb);
|
2017-10-05 19:43:02 +00:00
|
|
|
|
Centralise palette setup into terminal.c.
Now terminal.c makes nearly all the decisions about what the colour
palette should actually contain: it does the job of reading the
GUI-configurable colours out of Conf, and also the job of making up
the rest of the xterm-256 palette. The only exception is that TermWin
can provide a method to override some of the default colours, which on
Windows is used to implement the 'Use system colours' config option.
This saves code overall, partly because the front ends don't have to
be able to send palette data back to the Terminal any more (the
Terminal keeps the master copy and can answer palette-query escape
sequences from its own knowledge), and also because now there's only
one copy of the xterm-256 palette setup code (previously gtkwin.c and
window.c each had their own version of it).
In this rewrite, I've also introduced a multi-layered storage system
for the palette data in Terminal. One layer contains the palette
information derived from Conf; the next contains platform overrides
(currently just Windows's 'Use system colours'); the last one contains
overrides set by escape sequences in the middle of the session. The
topmost two layers can each _conditionally_ override the ones below.
As a result, if a server-side application manually resets (say) the
default fg and bg colours in mid-session to something that works well
in a particular application, those changes won't be wiped out by a
change in the Windows system colours or the Conf, which they would
have been before. Instead, changes in Conf or the system colours alter
the lower layers of the structure, but then when palette_rebuild is
called, the upper layer continues to override them, until a palette
reset (ESC]R) or terminal reset (e.g. ESC c) removes those upper-layer
changes. This seems like a more consistent strategy, in that the same
set of configuration settings will produce the same end result
regardless of what order they were applied in.
The palette-related methods in TermWin have had a total rework.
palette_get and palette_reset are both gone; palette_set can now set a
contiguous range of colours in one go; and the new
palette_get_overrides replaces window.c's old systopalette().
2021-02-07 19:59:21 +00:00
|
|
|
rgb = rgb_from_colorref(GetSysColor(COLOR_WINDOW));
|
|
|
|
term_palette_override(term, OSC4_COLOUR_bg, rgb);
|
|
|
|
term_palette_override(term, OSC4_COLOUR_bg_bold, rgb);
|
|
|
|
|
|
|
|
rgb = rgb_from_colorref(GetSysColor(COLOR_HIGHLIGHTTEXT));
|
|
|
|
term_palette_override(term, OSC4_COLOUR_cursor_fg, rgb);
|
|
|
|
|
|
|
|
rgb = rgb_from_colorref(GetSysColor(COLOR_HIGHLIGHT));
|
|
|
|
term_palette_override(term, OSC4_COLOUR_cursor_bg, rgb);
|
1999-01-08 13:02:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-05-22 10:36:50 +00:00
|
|
|
/*
|
|
|
|
* This is a wrapper to ExtTextOut() to force Windows to display
|
|
|
|
* the precise glyphs we give it. Otherwise it would do its own
|
|
|
|
* bidi and Arabic shaping, and we would end up uncertain which
|
|
|
|
* characters it had put where.
|
|
|
|
*/
|
|
|
|
static void exact_textout(HDC hdc, int x, int y, CONST RECT *lprc,
|
2019-09-08 19:29:00 +00:00
|
|
|
unsigned short *lpString, UINT cbCount,
|
|
|
|
CONST INT *lpDx, bool opaque)
|
2004-05-22 10:36:50 +00:00
|
|
|
{
|
2005-03-30 19:33:24 +00:00
|
|
|
#ifdef __LCC__
|
|
|
|
/*
|
|
|
|
* The LCC include files apparently don't supply the
|
|
|
|
* GCP_RESULTSW type, but we can make do with GCP_RESULTS
|
|
|
|
* proper: the differences aren't important to us (the only
|
|
|
|
* variable-width string parameter is one we don't use anyway).
|
|
|
|
*/
|
|
|
|
GCP_RESULTS gcpr;
|
|
|
|
#else
|
2004-05-22 10:36:50 +00:00
|
|
|
GCP_RESULTSW gcpr;
|
2005-03-30 19:33:24 +00:00
|
|
|
#endif
|
2004-05-22 10:36:50 +00:00
|
|
|
char *buffer = snewn(cbCount*2+2, char);
|
|
|
|
char *classbuffer = snewn(cbCount, char);
|
|
|
|
memset(&gcpr, 0, sizeof(gcpr));
|
|
|
|
memset(buffer, 0, cbCount*2+2);
|
|
|
|
memset(classbuffer, GCPCLASS_NEUTRAL, cbCount);
|
|
|
|
|
|
|
|
gcpr.lStructSize = sizeof(gcpr);
|
|
|
|
gcpr.lpGlyphs = (void *)buffer;
|
2007-01-10 00:46:45 +00:00
|
|
|
gcpr.lpClass = (void *)classbuffer;
|
2004-05-22 10:36:50 +00:00
|
|
|
gcpr.nGlyphs = cbCount;
|
|
|
|
GetCharacterPlacementW(hdc, lpString, cbCount, 0, &gcpr,
|
2019-09-08 19:29:00 +00:00
|
|
|
FLI_MASK | GCP_CLASSIN | GCP_DIACRITIC);
|
2004-05-22 10:36:50 +00:00
|
|
|
|
2004-10-14 16:42:43 +00:00
|
|
|
ExtTextOut(hdc, x, y,
|
2019-09-08 19:29:00 +00:00
|
|
|
ETO_GLYPH_INDEX | ETO_CLIPPED | (opaque ? ETO_OPAQUE : 0),
|
|
|
|
lprc, buffer, cbCount, lpDx);
|
2004-05-22 10:36:50 +00:00
|
|
|
}
|
|
|
|
|
2006-11-18 15:10:48 +00:00
|
|
|
/*
|
|
|
|
* The exact_textout() wrapper, unfortunately, destroys the useful
|
|
|
|
* Windows `font linking' behaviour: automatic handling of Unicode
|
|
|
|
* code points not supported in this font by falling back to a font
|
|
|
|
* which does contain them. Therefore, we adopt a multi-layered
|
|
|
|
* approach: for any potentially-bidi text, we use exact_textout(),
|
|
|
|
* and for everything else we use a simple ExtTextOut as we did
|
|
|
|
* before exact_textout() was introduced.
|
|
|
|
*/
|
|
|
|
static void general_textout(HDC hdc, int x, int y, CONST RECT *lprc,
|
2019-09-08 19:29:00 +00:00
|
|
|
unsigned short *lpString, UINT cbCount,
|
|
|
|
CONST INT *lpDx, bool opaque)
|
2006-11-18 15:10:48 +00:00
|
|
|
{
|
|
|
|
int i, j, xp, xn;
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
int bkmode = 0;
|
|
|
|
bool got_bkmode = false;
|
2006-11-18 15:10:48 +00:00
|
|
|
|
|
|
|
xp = xn = x;
|
|
|
|
|
2007-01-09 18:24:07 +00:00
|
|
|
for (i = 0; i < (int)cbCount ;) {
|
2019-09-08 19:29:00 +00:00
|
|
|
bool rtl = is_rtl(lpString[i]);
|
|
|
|
|
|
|
|
xn += lpDx[i];
|
|
|
|
|
|
|
|
for (j = i+1; j < (int)cbCount; j++) {
|
|
|
|
if (rtl != is_rtl(lpString[j]))
|
|
|
|
break;
|
|
|
|
xn += lpDx[j];
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Now [i,j) indicates a maximal substring of lpString
|
|
|
|
* which should be displayed using the same textout
|
|
|
|
* function.
|
|
|
|
*/
|
|
|
|
if (rtl) {
|
|
|
|
exact_textout(hdc, xp, y, lprc, lpString+i, j-i,
|
2010-12-29 16:00:58 +00:00
|
|
|
font_varpitch ? NULL : lpDx+i, opaque);
|
2019-09-08 19:29:00 +00:00
|
|
|
} else {
|
|
|
|
ExtTextOutW(hdc, xp, y, ETO_CLIPPED | (opaque ? ETO_OPAQUE : 0),
|
|
|
|
lprc, lpString+i, j-i,
|
2010-12-29 16:00:58 +00:00
|
|
|
font_varpitch ? NULL : lpDx+i);
|
2019-09-08 19:29:00 +00:00
|
|
|
}
|
2006-11-18 15:10:48 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
i = j;
|
|
|
|
xp = xn;
|
2010-12-30 00:06:43 +00:00
|
|
|
|
|
|
|
bkmode = GetBkMode(hdc);
|
2018-10-29 19:50:29 +00:00
|
|
|
got_bkmode = true;
|
2010-12-30 00:06:43 +00:00
|
|
|
SetBkMode(hdc, TRANSPARENT);
|
2018-10-29 19:50:29 +00:00
|
|
|
opaque = false;
|
2006-11-18 15:10:48 +00:00
|
|
|
}
|
|
|
|
|
2010-12-30 00:06:43 +00:00
|
|
|
if (got_bkmode)
|
|
|
|
SetBkMode(hdc, bkmode);
|
2006-11-18 15:10:48 +00:00
|
|
|
}
|
|
|
|
|
2010-12-29 14:11:25 +00:00
|
|
|
static int get_font_width(HDC hdc, const TEXTMETRIC *tm)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
/* Note that the TMPF_FIXED_PITCH bit is defined upside down :-( */
|
|
|
|
if (!(tm->tmPitchAndFamily & TMPF_FIXED_PITCH)) {
|
|
|
|
ret = tm->tmAveCharWidth;
|
|
|
|
} else {
|
|
|
|
#define FIRST '0'
|
|
|
|
#define LAST '9'
|
|
|
|
ABCFLOAT widths[LAST-FIRST + 1];
|
|
|
|
int j;
|
|
|
|
|
2018-10-29 19:50:29 +00:00
|
|
|
font_varpitch = true;
|
|
|
|
font_dualwidth = true;
|
2010-12-29 14:11:25 +00:00
|
|
|
if (GetCharABCWidthsFloat(hdc, FIRST, LAST, widths)) {
|
|
|
|
ret = 0;
|
|
|
|
for (j = 0; j < lenof(widths); j++) {
|
|
|
|
int width = (int)(0.5 + widths[j].abcfA +
|
|
|
|
widths[j].abcfB + widths[j].abcfC);
|
|
|
|
if (ret < width)
|
|
|
|
ret = width;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
ret = tm->tmMaxCharWidth;
|
|
|
|
}
|
|
|
|
#undef FIRST
|
|
|
|
#undef LAST
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
1999-01-08 13:02:13 +00:00
|
|
|
/*
|
2001-05-10 08:34:20 +00:00
|
|
|
* Initialise all the fonts we will need initially. There may be as many as
|
2010-07-30 19:45:40 +00:00
|
|
|
* three or as few as one. The other (potentially) twenty-one fonts are done
|
2001-05-10 08:34:20 +00:00
|
|
|
* if/when they are needed.
|
|
|
|
*
|
|
|
|
* We also:
|
1999-01-08 13:02:13 +00:00
|
|
|
*
|
|
|
|
* - check the font width and height, correcting our guesses if
|
|
|
|
* necessary.
|
|
|
|
*
|
|
|
|
* - verify that the bold font is the same width as the ordinary
|
|
|
|
* one, and engage shadow bolding if not.
|
2019-09-08 19:29:00 +00:00
|
|
|
*
|
1999-01-08 13:02:13 +00:00
|
|
|
* - verify that the underlined font is the same width as the
|
|
|
|
* ordinary one (manual underlining by means of line drawing can
|
|
|
|
* be done in a pinch).
|
2019-03-30 15:44:01 +00:00
|
|
|
*
|
|
|
|
* - find a trust sigil icon that will look OK with the chosen font.
|
1999-01-08 13:02:13 +00:00
|
|
|
*/
|
2001-09-15 15:54:24 +00:00
|
|
|
static void init_fonts(int pick_width, int pick_height)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
1999-01-08 13:02:13 +00:00
|
|
|
TEXTMETRIC tm;
|
2020-08-13 20:08:53 +00:00
|
|
|
OUTLINETEXTMETRIC otm;
|
2001-05-10 08:34:20 +00:00
|
|
|
CPINFO cpinfo;
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
FontSpec *font;
|
2001-05-10 08:34:20 +00:00
|
|
|
int fontsize[3];
|
2000-03-11 14:15:24 +00:00
|
|
|
int i;
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
int quality;
|
1999-01-08 13:02:13 +00:00
|
|
|
HDC hdc;
|
|
|
|
int fw_dontcare, fw_bold;
|
|
|
|
|
2001-05-10 08:34:20 +00:00
|
|
|
for (i = 0; i < FONT_MAXNO; i++)
|
2019-09-08 19:29:00 +00:00
|
|
|
fonts[i] = NULL;
|
1999-01-08 13:02:13 +00:00
|
|
|
|
2012-06-09 15:09:22 +00:00
|
|
|
bold_font_mode = conf_get_int(conf, CONF_bold_style) & 1 ?
|
2019-09-08 19:29:00 +00:00
|
|
|
BOLD_FONT : BOLD_NONE;
|
2018-10-29 19:50:29 +00:00
|
|
|
bold_colours = conf_get_int(conf, CONF_bold_style) & 2 ? true : false;
|
2001-09-15 15:54:24 +00:00
|
|
|
und_mode = UND_FONT;
|
|
|
|
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
font = conf_get_fontspec(conf, CONF_font);
|
|
|
|
if (font->isbold) {
|
2019-09-08 19:29:00 +00:00
|
|
|
fw_dontcare = FW_BOLD;
|
|
|
|
fw_bold = FW_HEAVY;
|
2001-05-06 14:35:20 +00:00
|
|
|
} else {
|
2019-09-08 19:29:00 +00:00
|
|
|
fw_dontcare = FW_DONTCARE;
|
|
|
|
fw_bold = FW_BOLD;
|
1999-01-08 13:02:13 +00:00
|
|
|
}
|
|
|
|
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
hdc = GetDC(wgs.term_hwnd);
|
2000-03-11 14:15:24 +00:00
|
|
|
|
2001-09-15 15:54:24 +00:00
|
|
|
if (pick_height)
|
2019-09-08 19:29:00 +00:00
|
|
|
font_height = pick_height;
|
2001-09-15 15:54:24 +00:00
|
|
|
else {
|
2019-09-08 19:29:00 +00:00
|
|
|
font_height = font->height;
|
|
|
|
if (font_height > 0) {
|
|
|
|
font_height =
|
|
|
|
-MulDiv(font_height, GetDeviceCaps(hdc, LOGPIXELSY), 72);
|
|
|
|
}
|
2001-03-12 12:24:07 +00:00
|
|
|
}
|
2000-03-17 10:34:41 +00:00
|
|
|
font_width = pick_width;
|
2000-03-11 14:15:24 +00:00
|
|
|
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
quality = conf_get_int(conf, CONF_font_quality);
|
1999-01-08 13:02:13 +00:00
|
|
|
#define f(i,c,w,u) \
|
2018-10-29 19:50:29 +00:00
|
|
|
fonts[i] = CreateFont (font_height, font_width, 0, 0, w, false, u, false, \
|
2019-09-08 19:29:00 +00:00
|
|
|
c, OUT_DEFAULT_PRECIS, \
|
|
|
|
CLIP_DEFAULT_PRECIS, FONT_QUALITY(quality), \
|
|
|
|
FIXED_PITCH | FF_DONTCARE, font->name)
|
2000-03-11 14:15:24 +00:00
|
|
|
|
2018-10-29 19:50:29 +00:00
|
|
|
f(FONT_NORMAL, font->charset, fw_dontcare, false);
|
2000-03-11 14:15:24 +00:00
|
|
|
|
2001-05-10 08:34:20 +00:00
|
|
|
SelectObject(hdc, fonts[FONT_NORMAL]);
|
|
|
|
GetTextMetrics(hdc, &tm);
|
2020-08-13 20:08:53 +00:00
|
|
|
if (GetOutlineTextMetrics(hdc, sizeof(otm), &otm))
|
|
|
|
font_strikethrough_y = tm.tmAscent - otm.otmsStrikeoutPosition;
|
|
|
|
else
|
|
|
|
font_strikethrough_y = tm.tmAscent - (tm.tmAscent * 3 / 8);
|
2001-09-15 15:54:24 +00:00
|
|
|
|
2005-03-21 01:05:38 +00:00
|
|
|
GetObject(fonts[FONT_NORMAL], sizeof(LOGFONT), &lfont);
|
|
|
|
|
2010-12-29 14:11:25 +00:00
|
|
|
/* Note that the TMPF_FIXED_PITCH bit is defined upside down :-( */
|
|
|
|
if (!(tm.tmPitchAndFamily & TMPF_FIXED_PITCH)) {
|
2018-10-29 19:50:29 +00:00
|
|
|
font_varpitch = false;
|
2010-12-29 14:11:25 +00:00
|
|
|
font_dualwidth = (tm.tmAveCharWidth != tm.tmMaxCharWidth);
|
|
|
|
} else {
|
2018-10-29 19:50:29 +00:00
|
|
|
font_varpitch = true;
|
|
|
|
font_dualwidth = true;
|
2010-12-29 14:11:25 +00:00
|
|
|
}
|
2001-09-15 15:54:24 +00:00
|
|
|
if (pick_width == 0 || pick_height == 0) {
|
2019-09-08 19:29:00 +00:00
|
|
|
font_height = tm.tmHeight;
|
2010-12-29 14:11:25 +00:00
|
|
|
font_width = get_font_width(hdc, &tm);
|
2001-09-15 15:54:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef RDB_DEBUG_PATCH
|
Start using C99 variadic macros.
In the past, I've had a lot of macros which you call with double
parentheses, along the lines of debug(("format string", params)), so
that the inner parens protect the commas and permit the macro to treat
the whole printf-style argument list as one macro argument.
That's all very well, but it's a bit inconvenient (it doesn't leave
you any way to implement such a macro by prepending another argument
to the list), and now this code base's rules allow C99isms, I can
switch all those macros to using a single pair of parens, using the
C99 ability to say '...' in the parameter list of the #define and get
at the corresponding suffix of the arguments as __VA_ARGS__.
So I'm doing it. I've made the following printf-style macros variadic:
bpp_logevent, ppl_logevent, ppl_printf and debug.
While I'm here, I've also fixed up a collection of conditioned-out
calls to debug() in the Windows front end which were clearly expecting
a macro with a different calling syntax, because they had an integer
parameter first. If I ever have a need to condition those back in,
they should actually work now.
2018-12-08 20:32:31 +00:00
|
|
|
debug("Primary font H=%d, AW=%d, MW=%d\n",
|
|
|
|
tm.tmHeight, tm.tmAveCharWidth, tm.tmMaxCharWidth);
|
2001-09-15 15:54:24 +00:00
|
|
|
#endif
|
2000-03-11 14:15:24 +00:00
|
|
|
|
2001-05-10 08:34:20 +00:00
|
|
|
{
|
2019-09-08 19:29:00 +00:00
|
|
|
CHARSETINFO info;
|
|
|
|
DWORD cset = tm.tmCharSet;
|
|
|
|
memset(&info, 0xFF, sizeof(info));
|
|
|
|
|
|
|
|
/* !!! Yes the next line is right */
|
|
|
|
if (cset == OEM_CHARSET)
|
|
|
|
ucsdata.font_codepage = GetOEMCP();
|
|
|
|
else
|
|
|
|
if (TranslateCharsetInfo ((DWORD *)(ULONG_PTR)cset,
|
2017-02-05 11:19:12 +00:00
|
|
|
&info, TCI_SRCCHARSET))
|
2019-09-08 19:29:00 +00:00
|
|
|
ucsdata.font_codepage = info.ciACP;
|
|
|
|
else
|
|
|
|
ucsdata.font_codepage = -1;
|
2001-05-06 14:35:20 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
GetCPInfo(ucsdata.font_codepage, &cpinfo);
|
|
|
|
ucsdata.dbcs_screenfont = (cpinfo.MaxCharSize > 1);
|
2001-05-10 08:34:20 +00:00
|
|
|
}
|
2000-03-11 14:15:24 +00:00
|
|
|
|
2018-10-29 19:50:29 +00:00
|
|
|
f(FONT_UNDERLINE, font->charset, fw_dontcare, true);
|
2000-03-11 14:15:24 +00:00
|
|
|
|
2001-05-10 08:34:20 +00:00
|
|
|
/*
|
|
|
|
* Some fonts, e.g. 9-pt Courier, draw their underlines
|
|
|
|
* outside their character cell. We successfully prevent
|
|
|
|
* screen corruption by clipping the text output, but then
|
|
|
|
* we lose the underline completely. Here we try to work
|
|
|
|
* out whether this is such a font, and if it is, we set a
|
|
|
|
* flag that causes underlines to be drawn by hand.
|
|
|
|
*
|
|
|
|
* Having tried other more sophisticated approaches (such
|
|
|
|
* as examining the TEXTMETRIC structure or requesting the
|
|
|
|
* height of a string), I think we'll do this the brute
|
|
|
|
* force way: we create a small bitmap, draw an underlined
|
|
|
|
* space on it, and test to see whether any pixels are
|
|
|
|
* foreground-coloured. (Since we expect the underline to
|
|
|
|
* go all the way across the character cell, we only search
|
|
|
|
* down a single column of the bitmap, half way across.)
|
|
|
|
*/
|
|
|
|
{
|
2019-09-08 19:29:00 +00:00
|
|
|
HDC und_dc;
|
|
|
|
HBITMAP und_bm, und_oldbm;
|
|
|
|
int i;
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool gotit;
|
2019-09-08 19:29:00 +00:00
|
|
|
COLORREF c;
|
|
|
|
|
|
|
|
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]);
|
|
|
|
SetTextAlign(und_dc, TA_TOP | TA_LEFT | TA_NOUPDATECP);
|
|
|
|
SetTextColor(und_dc, RGB(255, 255, 255));
|
|
|
|
SetBkColor(und_dc, RGB(0, 0, 0));
|
|
|
|
SetBkMode(und_dc, OPAQUE);
|
|
|
|
ExtTextOut(und_dc, 0, 0, ETO_OPAQUE, NULL, " ", 1, NULL);
|
|
|
|
gotit = false;
|
|
|
|
for (i = 0; i < font_height; i++) {
|
|
|
|
c = GetPixel(und_dc, font_width / 2, i);
|
|
|
|
if (c != RGB(0, 0, 0))
|
|
|
|
gotit = true;
|
|
|
|
}
|
|
|
|
SelectObject(und_dc, und_oldbm);
|
|
|
|
DeleteObject(und_bm);
|
|
|
|
DeleteDC(und_dc);
|
|
|
|
if (!gotit) {
|
|
|
|
und_mode = UND_LINE;
|
|
|
|
DeleteObject(fonts[FONT_UNDERLINE]);
|
|
|
|
fonts[FONT_UNDERLINE] = 0;
|
|
|
|
}
|
2001-05-10 08:34:20 +00:00
|
|
|
}
|
2000-03-11 14:15:24 +00:00
|
|
|
|
2012-06-09 15:09:22 +00:00
|
|
|
if (bold_font_mode == BOLD_FONT) {
|
2019-09-08 19:29:00 +00:00
|
|
|
f(FONT_BOLD, font->charset, fw_bold, false);
|
1999-01-08 13:02:13 +00:00
|
|
|
}
|
|
|
|
#undef f
|
|
|
|
|
2000-03-11 14:15:24 +00:00
|
|
|
descent = tm.tmAscent + 1;
|
|
|
|
if (descent >= font_height)
|
2019-09-08 19:29:00 +00:00
|
|
|
descent = font_height - 1;
|
1999-01-08 13:02:13 +00:00
|
|
|
|
2001-05-10 08:34:20 +00:00
|
|
|
for (i = 0; i < 3; i++) {
|
2019-09-08 19:29:00 +00:00
|
|
|
if (fonts[i]) {
|
|
|
|
if (SelectObject(hdc, fonts[i]) && GetTextMetrics(hdc, &tm))
|
|
|
|
fontsize[i] = get_font_width(hdc, &tm) + 256 * tm.tmHeight;
|
|
|
|
else
|
|
|
|
fontsize[i] = -i;
|
|
|
|
} else
|
|
|
|
fontsize[i] = -i;
|
1999-01-08 13:02:13 +00:00
|
|
|
}
|
|
|
|
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
ReleaseDC(wgs.term_hwnd, hdc);
|
1999-01-08 13:02:13 +00:00
|
|
|
|
2019-03-31 22:47:03 +00:00
|
|
|
if (trust_icon != INVALID_HANDLE_VALUE) {
|
2019-09-08 19:29:00 +00:00
|
|
|
DestroyIcon(trust_icon);
|
2019-03-31 22:47:03 +00:00
|
|
|
}
|
2019-03-30 15:44:01 +00:00
|
|
|
trust_icon = LoadImage(hinst, MAKEINTRESOURCE(IDI_MAINICON),
|
2019-09-08 19:29:00 +00:00
|
|
|
IMAGE_ICON, font_width*2, font_height,
|
|
|
|
LR_DEFAULTCOLOR);
|
2019-03-30 15:44:01 +00:00
|
|
|
|
2001-05-10 08:34:20 +00:00
|
|
|
if (fontsize[FONT_UNDERLINE] != fontsize[FONT_NORMAL]) {
|
2019-09-08 19:29:00 +00:00
|
|
|
und_mode = UND_LINE;
|
|
|
|
DeleteObject(fonts[FONT_UNDERLINE]);
|
|
|
|
fonts[FONT_UNDERLINE] = 0;
|
1999-01-08 13:02:13 +00:00
|
|
|
}
|
|
|
|
|
2012-06-09 15:09:22 +00:00
|
|
|
if (bold_font_mode == BOLD_FONT &&
|
2019-09-08 19:29:00 +00:00
|
|
|
fontsize[FONT_BOLD] != fontsize[FONT_NORMAL]) {
|
|
|
|
bold_font_mode = BOLD_SHADOW;
|
|
|
|
DeleteObject(fonts[FONT_BOLD]);
|
|
|
|
fonts[FONT_BOLD] = 0;
|
1999-01-08 13:02:13 +00:00
|
|
|
}
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
fontflag[0] = true;
|
|
|
|
fontflag[1] = true;
|
|
|
|
fontflag[2] = true;
|
2001-05-10 08:34:20 +00:00
|
|
|
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
init_ucs(conf, &ucsdata);
|
2001-05-10 08:34:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void another_font(int fontno)
|
|
|
|
{
|
|
|
|
int basefont;
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
int fw_dontcare, fw_bold, quality;
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
int c, w, x;
|
|
|
|
bool u;
|
2001-05-10 08:34:20 +00:00
|
|
|
char *s;
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
FontSpec *font;
|
2001-05-10 08:34:20 +00:00
|
|
|
|
|
|
|
if (fontno < 0 || fontno >= FONT_MAXNO || fontflag[fontno])
|
2019-09-08 19:29:00 +00:00
|
|
|
return;
|
2001-05-10 08:34:20 +00:00
|
|
|
|
|
|
|
basefont = (fontno & ~(FONT_BOLDUND));
|
|
|
|
if (basefont != fontno && !fontflag[basefont])
|
2019-09-08 19:29:00 +00:00
|
|
|
another_font(basefont);
|
2000-03-11 14:15:24 +00:00
|
|
|
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
font = conf_get_fontspec(conf, CONF_font);
|
|
|
|
|
|
|
|
if (font->isbold) {
|
2019-09-08 19:29:00 +00:00
|
|
|
fw_dontcare = FW_BOLD;
|
|
|
|
fw_bold = FW_HEAVY;
|
2001-05-10 08:34:20 +00:00
|
|
|
} else {
|
2019-09-08 19:29:00 +00:00
|
|
|
fw_dontcare = FW_DONTCARE;
|
|
|
|
fw_bold = FW_BOLD;
|
2001-05-10 08:34:20 +00:00
|
|
|
}
|
|
|
|
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
c = font->charset;
|
2001-05-10 08:34:20 +00:00
|
|
|
w = fw_dontcare;
|
2018-10-29 19:50:29 +00:00
|
|
|
u = false;
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
s = font->name;
|
2001-05-10 08:34:20 +00:00
|
|
|
x = font_width;
|
|
|
|
|
|
|
|
if (fontno & FONT_WIDE)
|
2019-09-08 19:29:00 +00:00
|
|
|
x *= 2;
|
2001-05-10 08:34:20 +00:00
|
|
|
if (fontno & FONT_NARROW)
|
2019-09-08 19:29:00 +00:00
|
|
|
x = (x+1)/2;
|
2001-05-10 08:34:20 +00:00
|
|
|
if (fontno & FONT_OEM)
|
2019-09-08 19:29:00 +00:00
|
|
|
c = OEM_CHARSET;
|
2001-05-10 08:34:20 +00:00
|
|
|
if (fontno & FONT_BOLD)
|
2019-09-08 19:29:00 +00:00
|
|
|
w = fw_bold;
|
2001-05-10 08:34:20 +00:00
|
|
|
if (fontno & FONT_UNDERLINE)
|
2019-09-08 19:29:00 +00:00
|
|
|
u = true;
|
2001-05-10 08:34:20 +00:00
|
|
|
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
quality = conf_get_int(conf, CONF_font_quality);
|
|
|
|
|
2001-05-10 08:34:20 +00:00
|
|
|
fonts[fontno] =
|
2019-09-08 19:29:00 +00:00
|
|
|
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);
|
2001-05-10 08:34:20 +00:00
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
fontflag[fontno] = true;
|
2001-05-10 08:34:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void deinit_fonts(void)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < FONT_MAXNO; i++) {
|
2019-09-08 19:29:00 +00:00
|
|
|
if (fonts[i])
|
|
|
|
DeleteObject(fonts[i]);
|
|
|
|
fonts[i] = 0;
|
|
|
|
fontflag[i] = false;
|
1999-01-08 13:02:13 +00:00
|
|
|
}
|
2019-03-30 15:44:01 +00:00
|
|
|
|
2019-03-31 22:47:03 +00:00
|
|
|
if (trust_icon != INVALID_HANDLE_VALUE) {
|
2019-09-08 19:29:00 +00:00
|
|
|
DestroyIcon(trust_icon);
|
2019-03-31 22:47:03 +00:00
|
|
|
}
|
2019-03-30 15:44:01 +00:00
|
|
|
trust_icon = INVALID_HANDLE_VALUE;
|
1999-01-08 13:02:13 +00:00
|
|
|
}
|
|
|
|
|
Remove the 'Frontend' type and replace it with a vtable.
After the recent Seat and LogContext revamps, _nearly_ all the
remaining uses of the type 'Frontend' were in terminal.c, which needs
all sorts of interactions with the GUI window the terminal lives in,
from the obvious (actually drawing text on the window, reading and
writing the clipboard) to the obscure (minimising, maximising and
moving the window in response to particular escape sequences).
All of those functions are now provided by an abstraction called
TermWin. The few remaining uses of Frontend after _that_ are internal
to a particular platform directory, so as to spread the implementation
of that particular kind of Frontend between multiple source files; so
I've renamed all of those so that they take a more specifically named
type that refers to the particular implementation rather than the
general abstraction.
So now the name 'Frontend' no longer exists in the code base at all,
and everywhere one used to be used, it's completely clear whether it
was operating in one of Frontend's three abstract roles (and if so,
which), or whether it was specific to a particular implementation.
Another type that's disappeared is 'Context', which used to be a
typedef defined to something different on each platform, describing
whatever short-lived resources were necessary to draw on the terminal
window: the front end would provide a ready-made one when calling
term_paint, and the terminal could request one with get_ctx/free_ctx
if it wanted to do proactive window updates. Now that drawing context
lives inside the TermWin itself, because there was never any need to
have two of those contexts live at the same time.
(Another minor API change is that the window-title functions - both
reading and writing - have had a missing 'const' added to their char *
parameters / return values.)
I don't expect this change to enable any particularly interesting new
functionality (in particular, I have no plans that need more than one
implementation of TermWin in the same application). But it completes
the tidying-up that began with the Seat and LogContext rework.
2018-10-25 17:44:04 +00:00
|
|
|
static void wintw_request_resize(TermWin *tw, int w, int h)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
2020-02-14 12:49:56 +00:00
|
|
|
const struct BackendVtable *vt;
|
2000-03-17 10:34:41 +00:00
|
|
|
int width, height;
|
2000-07-26 12:13:51 +00:00
|
|
|
|
2017-04-15 08:06:22 +00:00
|
|
|
/* If the window is maximized suppress resizing attempts */
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
if (IsZoomed(wgs.term_hwnd)) {
|
2019-09-08 19:29:00 +00:00
|
|
|
if (conf_get_int(conf, CONF_resize_action) == RESIZE_TERM)
|
|
|
|
return;
|
2001-09-15 15:54:24 +00:00
|
|
|
}
|
2001-05-06 14:35:20 +00:00
|
|
|
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
if (conf_get_int(conf, CONF_resize_action) == RESIZE_DISABLED) return;
|
2020-02-14 12:49:56 +00:00
|
|
|
vt = backend_vt_from_proto(be_default_protocol);
|
|
|
|
if (vt && vt->flags & BACKEND_RESIZE_FORBIDDEN)
|
|
|
|
return;
|
2002-10-22 16:11:33 +00:00
|
|
|
if (h == term->rows && w == term->cols) return;
|
2001-09-15 15:54:24 +00:00
|
|
|
|
|
|
|
/* Sanity checks ... */
|
|
|
|
{
|
2019-09-08 19:29:00 +00:00
|
|
|
static int first_time = 1;
|
|
|
|
static RECT ss;
|
|
|
|
|
|
|
|
switch (first_time) {
|
|
|
|
case 1:
|
|
|
|
/* Get the size of the screen */
|
|
|
|
if (get_fullscreen_rect(&ss))
|
|
|
|
/* first_time = 0 */ ;
|
|
|
|
else {
|
|
|
|
first_time = 2;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 0:
|
|
|
|
/* Make sure the values are sane */
|
|
|
|
width = (ss.right - ss.left - extra_width) / 4;
|
|
|
|
height = (ss.bottom - ss.top - extra_height) / 6;
|
|
|
|
|
|
|
|
if (w > width || h > height)
|
|
|
|
return;
|
|
|
|
if (w < 15)
|
|
|
|
w = 15;
|
|
|
|
if (h < 1)
|
|
|
|
h = 1;
|
|
|
|
}
|
2000-07-26 12:13:51 +00:00
|
|
|
}
|
2000-03-17 10:34:41 +00:00
|
|
|
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
term_size(term, h, w, conf_get_int(conf, CONF_savelines));
|
2001-09-15 15:54:24 +00:00
|
|
|
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
if (conf_get_int(conf, CONF_resize_action) != RESIZE_FONT &&
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
!IsZoomed(wgs.term_hwnd)) {
|
2019-09-08 19:29:00 +00:00
|
|
|
width = extra_width + font_width * w;
|
|
|
|
height = extra_height + font_height * h;
|
1999-01-08 13:02:13 +00:00
|
|
|
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
SetWindowPos(wgs.term_hwnd, NULL, 0, 0, width, height,
|
2019-09-08 19:29:00 +00:00
|
|
|
SWP_NOACTIVATE | SWP_NOCOPYBITS |
|
|
|
|
SWP_NOMOVE | SWP_NOZORDER);
|
2001-09-15 15:54:24 +00:00
|
|
|
} else
|
2019-09-08 19:29:00 +00:00
|
|
|
reset_window(0);
|
2001-09-15 15:54:24 +00:00
|
|
|
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
InvalidateRect(wgs.term_hwnd, NULL, true);
|
2001-09-15 15:54:24 +00:00
|
|
|
}
|
|
|
|
|
2021-02-12 17:50:47 +00:00
|
|
|
static void recompute_window_offset(void)
|
|
|
|
{
|
|
|
|
RECT 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;
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-09-15 15:54:24 +00:00
|
|
|
static void reset_window(int reinit) {
|
|
|
|
/*
|
2019-09-08 19:29:00 +00:00
|
|
|
* This function decides how to resize or redraw when the
|
|
|
|
* user changes something.
|
2001-09-15 15:54:24 +00:00
|
|
|
*
|
|
|
|
* This function doesn't like to change the terminal size but if the
|
|
|
|
* font size is locked that may be it's only soluion.
|
|
|
|
*/
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
int win_width, win_height, resize_action, window_border;
|
2001-09-15 15:54:24 +00:00
|
|
|
RECT cr, wr;
|
|
|
|
|
|
|
|
#ifdef RDB_DEBUG_PATCH
|
Start using C99 variadic macros.
In the past, I've had a lot of macros which you call with double
parentheses, along the lines of debug(("format string", params)), so
that the inner parens protect the commas and permit the macro to treat
the whole printf-style argument list as one macro argument.
That's all very well, but it's a bit inconvenient (it doesn't leave
you any way to implement such a macro by prepending another argument
to the list), and now this code base's rules allow C99isms, I can
switch all those macros to using a single pair of parens, using the
C99 ability to say '...' in the parameter list of the #define and get
at the corresponding suffix of the arguments as __VA_ARGS__.
So I'm doing it. I've made the following printf-style macros variadic:
bpp_logevent, ppl_logevent, ppl_printf and debug.
While I'm here, I've also fixed up a collection of conditioned-out
calls to debug() in the Windows front end which were clearly expecting
a macro with a different calling syntax, because they had an integer
parameter first. If I ever have a need to condition those back in,
they should actually work now.
2018-12-08 20:32:31 +00:00
|
|
|
debug("reset_window()\n");
|
2001-09-15 15:54:24 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
/* Current window sizes ... */
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
GetWindowRect(wgs.term_hwnd, &wr);
|
|
|
|
GetClientRect(wgs.term_hwnd, &cr);
|
2001-09-15 15:54:24 +00:00
|
|
|
|
|
|
|
win_width = cr.right - cr.left;
|
|
|
|
win_height = cr.bottom - cr.top;
|
|
|
|
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
resize_action = conf_get_int(conf, CONF_resize_action);
|
|
|
|
window_border = conf_get_int(conf, CONF_window_border);
|
|
|
|
|
|
|
|
if (resize_action == RESIZE_DISABLED)
|
2019-09-08 19:29:00 +00:00
|
|
|
reinit = 2;
|
2001-11-25 18:39:57 +00:00
|
|
|
|
2001-09-15 15:54:24 +00:00
|
|
|
/* Are we being forced to reload the fonts ? */
|
|
|
|
if (reinit>1) {
|
|
|
|
#ifdef RDB_DEBUG_PATCH
|
2019-09-08 19:29:00 +00:00
|
|
|
debug("reset_window() -- Forced deinit\n");
|
2001-09-15 15:54:24 +00:00
|
|
|
#endif
|
2019-09-08 19:29:00 +00:00
|
|
|
deinit_fonts();
|
|
|
|
init_fonts(0,0);
|
2001-09-15 15:54:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Oh, looks like we're minimised */
|
|
|
|
if (win_width == 0 || win_height == 0)
|
2019-09-08 19:29:00 +00:00
|
|
|
return;
|
2001-09-15 15:54:24 +00:00
|
|
|
|
|
|
|
/* Is the window out of position ? */
|
2021-02-12 17:50:47 +00:00
|
|
|
if (!reinit) {
|
|
|
|
recompute_window_offset();
|
2001-09-15 15:54:24 +00:00
|
|
|
#ifdef RDB_DEBUG_PATCH
|
2019-09-08 19:29:00 +00:00
|
|
|
debug("reset_window() -> Reposition terminal\n");
|
2001-09-15 15:54:24 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
if (IsZoomed(wgs.term_hwnd)) {
|
2019-09-08 19:29:00 +00:00
|
|
|
/* We're fullscreen, this means we must not change the size of
|
|
|
|
* the window so it's the font size or the terminal itself.
|
|
|
|
*/
|
|
|
|
|
|
|
|
extra_width = wr.right - wr.left - cr.right + cr.left;
|
|
|
|
extra_height = wr.bottom - wr.top - cr.bottom + cr.top;
|
|
|
|
|
|
|
|
if (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;
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
InvalidateRect(wgs.term_hwnd, NULL, true);
|
2001-09-15 15:54:24 +00:00
|
|
|
#ifdef RDB_DEBUG_PATCH
|
2019-09-08 19:29:00 +00:00
|
|
|
debug("reset_window() -> Z font resize to (%d, %d)\n",
|
Start using C99 variadic macros.
In the past, I've had a lot of macros which you call with double
parentheses, along the lines of debug(("format string", params)), so
that the inner parens protect the commas and permit the macro to treat
the whole printf-style argument list as one macro argument.
That's all very well, but it's a bit inconvenient (it doesn't leave
you any way to implement such a macro by prepending another argument
to the list), and now this code base's rules allow C99isms, I can
switch all those macros to using a single pair of parens, using the
C99 ability to say '...' in the parameter list of the #define and get
at the corresponding suffix of the arguments as __VA_ARGS__.
So I'm doing it. I've made the following printf-style macros variadic:
bpp_logevent, ppl_logevent, ppl_printf and debug.
While I'm here, I've also fixed up a collection of conditioned-out
calls to debug() in the Windows front end which were clearly expecting
a macro with a different calling syntax, because they had an integer
parameter first. If I ever have a need to condition those back in,
they should actually work now.
2018-12-08 20:32:31 +00:00
|
|
|
font_width, font_height);
|
2001-09-15 15:54:24 +00:00
|
|
|
#endif
|
2019-09-08 19:29:00 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (font_width * term->cols != win_width ||
|
|
|
|
font_height * 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;
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
InvalidateRect(wgs.term_hwnd, NULL, true);
|
2001-09-15 15:54:24 +00:00
|
|
|
#ifdef RDB_DEBUG_PATCH
|
2019-09-08 19:29:00 +00:00
|
|
|
debug("reset_window() -> Zoomed term_size\n");
|
2001-09-15 15:54:24 +00:00
|
|
|
#endif
|
2019-09-08 19:29:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
2001-09-15 15:54:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Hmm, a force re-init means we should ignore the current window
|
|
|
|
* so we resize to the default font size.
|
|
|
|
*/
|
|
|
|
if (reinit>0) {
|
|
|
|
#ifdef RDB_DEBUG_PATCH
|
2019-09-08 19:29:00 +00:00
|
|
|
debug("reset_window() -> Forced re-init\n");
|
2001-09-15 15:54:24 +00:00
|
|
|
#endif
|
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
offset_width = offset_height = window_border;
|
|
|
|
extra_width = wr.right - wr.left - cr.right + cr.left + offset_width*2;
|
|
|
|
extra_height = wr.bottom - wr.top - cr.bottom + cr.top +offset_height*2;
|
|
|
|
|
|
|
|
if (win_width != font_width*term->cols + offset_width*2 ||
|
|
|
|
win_height != font_height*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.
|
|
|
|
*/
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
SetWindowPos(wgs.term_hwnd, NULL, 0, 0,
|
2019-09-08 19:29:00 +00:00
|
|
|
font_width*term->cols + extra_width,
|
|
|
|
font_height*term->rows + extra_height,
|
|
|
|
SWP_NOMOVE | SWP_NOZORDER);
|
|
|
|
}
|
|
|
|
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
InvalidateRect(wgs.term_hwnd, NULL, true);
|
2019-09-08 19:29:00 +00:00
|
|
|
return;
|
2001-09-15 15:54:24 +00:00
|
|
|
}
|
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
/* Okay the user doesn't want us to change the font so we try the
|
2001-09-15 15:54:24 +00:00
|
|
|
* window. But that may be too big for the screen which forces us
|
|
|
|
* to change the terminal.
|
|
|
|
*/
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
if ((resize_action == RESIZE_TERM && reinit<=0) ||
|
|
|
|
(resize_action == RESIZE_EITHER && reinit<0) ||
|
2019-09-08 19:29:00 +00:00
|
|
|
reinit>0) {
|
|
|
|
offset_width = offset_height = window_border;
|
|
|
|
extra_width = wr.right - wr.left - cr.right + cr.left + offset_width*2;
|
|
|
|
extra_height = wr.bottom - wr.top - cr.bottom + cr.top +offset_height*2;
|
|
|
|
|
|
|
|
if (win_width != font_width*term->cols + offset_width*2 ||
|
|
|
|
win_height != font_height*term->rows + offset_height*2) {
|
|
|
|
|
|
|
|
static RECT ss;
|
|
|
|
int width, height;
|
|
|
|
|
|
|
|
get_fullscreen_rect(&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 (resize_action == RESIZE_EITHER) {
|
|
|
|
/* Make the font the biggest we can */
|
|
|
|
if (term->cols > width)
|
|
|
|
font_width = (ss.right - ss.left - extra_width)
|
|
|
|
/ term->cols;
|
|
|
|
if (term->rows > height)
|
|
|
|
font_height = (ss.bottom - ss.top - extra_height)
|
|
|
|
/ term->rows;
|
|
|
|
|
|
|
|
deinit_fonts();
|
|
|
|
init_fonts(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));
|
2001-09-15 15:54:24 +00:00
|
|
|
#ifdef RDB_DEBUG_PATCH
|
2019-09-08 19:29:00 +00:00
|
|
|
debug("reset_window() -> term resize to (%d,%d)\n",
|
Start using C99 variadic macros.
In the past, I've had a lot of macros which you call with double
parentheses, along the lines of debug(("format string", params)), so
that the inner parens protect the commas and permit the macro to treat
the whole printf-style argument list as one macro argument.
That's all very well, but it's a bit inconvenient (it doesn't leave
you any way to implement such a macro by prepending another argument
to the list), and now this code base's rules allow C99isms, I can
switch all those macros to using a single pair of parens, using the
C99 ability to say '...' in the parameter list of the #define and get
at the corresponding suffix of the arguments as __VA_ARGS__.
So I'm doing it. I've made the following printf-style macros variadic:
bpp_logevent, ppl_logevent, ppl_printf and debug.
While I'm here, I've also fixed up a collection of conditioned-out
calls to debug() in the Windows front end which were clearly expecting
a macro with a different calling syntax, because they had an integer
parameter first. If I ever have a need to condition those back in,
they should actually work now.
2018-12-08 20:32:31 +00:00
|
|
|
height, width);
|
2001-09-15 15:54:24 +00:00
|
|
|
#endif
|
2019-09-08 19:29:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
SetWindowPos(wgs.term_hwnd, NULL, 0, 0,
|
2019-09-08 19:29:00 +00:00
|
|
|
font_width*term->cols + extra_width,
|
|
|
|
font_height*term->rows + extra_height,
|
|
|
|
SWP_NOMOVE | SWP_NOZORDER);
|
|
|
|
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
InvalidateRect(wgs.term_hwnd, NULL, true);
|
2001-09-15 15:54:24 +00:00
|
|
|
#ifdef RDB_DEBUG_PATCH
|
2019-09-08 19:29:00 +00:00
|
|
|
debug("reset_window() -> window resize to (%d,%d)\n",
|
Start using C99 variadic macros.
In the past, I've had a lot of macros which you call with double
parentheses, along the lines of debug(("format string", params)), so
that the inner parens protect the commas and permit the macro to treat
the whole printf-style argument list as one macro argument.
That's all very well, but it's a bit inconvenient (it doesn't leave
you any way to implement such a macro by prepending another argument
to the list), and now this code base's rules allow C99isms, I can
switch all those macros to using a single pair of parens, using the
C99 ability to say '...' in the parameter list of the #define and get
at the corresponding suffix of the arguments as __VA_ARGS__.
So I'm doing it. I've made the following printf-style macros variadic:
bpp_logevent, ppl_logevent, ppl_printf and debug.
While I'm here, I've also fixed up a collection of conditioned-out
calls to debug() in the Windows front end which were clearly expecting
a macro with a different calling syntax, because they had an integer
parameter first. If I ever have a need to condition those back in,
they should actually work now.
2018-12-08 20:32:31 +00:00
|
|
|
font_width*term->cols + extra_width,
|
|
|
|
font_height*term->rows + extra_height);
|
2001-09-15 15:54:24 +00:00
|
|
|
#endif
|
2019-09-08 19:29:00 +00:00
|
|
|
}
|
|
|
|
return;
|
2001-09-15 15:54:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* We're allowed to or must change the font but do we want to ? */
|
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
if (font_width != (win_width-window_border*2)/term->cols ||
|
|
|
|
font_height != (win_height-window_border*2)/term->rows) {
|
2001-09-15 15:54:24 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
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;
|
2001-09-15 15:54:24 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
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;
|
2001-09-15 15:54:24 +00:00
|
|
|
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
InvalidateRect(wgs.term_hwnd, NULL, true);
|
2001-09-15 15:54:24 +00:00
|
|
|
#ifdef RDB_DEBUG_PATCH
|
2019-09-08 19:29:00 +00:00
|
|
|
debug("reset_window() -> font resize to (%d,%d)\n",
|
Start using C99 variadic macros.
In the past, I've had a lot of macros which you call with double
parentheses, along the lines of debug(("format string", params)), so
that the inner parens protect the commas and permit the macro to treat
the whole printf-style argument list as one macro argument.
That's all very well, but it's a bit inconvenient (it doesn't leave
you any way to implement such a macro by prepending another argument
to the list), and now this code base's rules allow C99isms, I can
switch all those macros to using a single pair of parens, using the
C99 ability to say '...' in the parameter list of the #define and get
at the corresponding suffix of the arguments as __VA_ARGS__.
So I'm doing it. I've made the following printf-style macros variadic:
bpp_logevent, ppl_logevent, ppl_printf and debug.
While I'm here, I've also fixed up a collection of conditioned-out
calls to debug() in the Windows front end which were clearly expecting
a macro with a different calling syntax, because they had an integer
parameter first. If I ever have a need to condition those back in,
they should actually work now.
2018-12-08 20:32:31 +00:00
|
|
|
font_width, font_height);
|
2001-09-15 15:54:24 +00:00
|
|
|
#endif
|
|
|
|
}
|
1999-01-08 13:02:13 +00:00
|
|
|
}
|
|
|
|
|
2001-11-29 21:30:59 +00:00
|
|
|
static void set_input_locale(HKL kl)
|
|
|
|
{
|
|
|
|
char lbuf[20];
|
|
|
|
|
|
|
|
GetLocaleInfo(LOWORD(kl), LOCALE_IDEFAULTANSICODEPAGE,
|
2019-09-08 19:29:00 +00:00
|
|
|
lbuf, sizeof(lbuf));
|
2001-11-29 21:30:59 +00:00
|
|
|
|
|
|
|
kbd_codepage = atoi(lbuf);
|
|
|
|
}
|
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
static void click(Mouse_Button b, int x, int y,
|
|
|
|
bool shift, bool ctrl, bool alt)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
1999-01-22 09:35:08 +00:00
|
|
|
int thistime = GetMessageTime();
|
|
|
|
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
if (send_raw_mouse &&
|
2019-09-08 19:29:00 +00:00
|
|
|
!(shift && conf_get_bool(conf, CONF_mouse_override))) {
|
|
|
|
lastbtn = MBT_NOTHING;
|
|
|
|
term_mouse(term, b, translate_button(b), MA_CLICK,
|
|
|
|
x, y, shift, ctrl, alt);
|
|
|
|
return;
|
2001-05-06 14:20:41 +00:00
|
|
|
}
|
|
|
|
|
1999-01-22 09:35:08 +00:00
|
|
|
if (lastbtn == b && thistime - lasttime < dbltime) {
|
2019-09-08 19:29:00 +00:00
|
|
|
lastact = (lastact == MA_CLICK ? MA_2CLK :
|
|
|
|
lastact == MA_2CLK ? MA_3CLK :
|
|
|
|
lastact == MA_3CLK ? MA_CLICK : MA_NOTHING);
|
1999-01-08 13:02:13 +00:00
|
|
|
} else {
|
2019-09-08 19:29:00 +00:00
|
|
|
lastbtn = b;
|
|
|
|
lastact = MA_CLICK;
|
1999-01-08 13:02:13 +00:00
|
|
|
}
|
|
|
|
if (lastact != MA_NOTHING)
|
2019-09-08 19:29:00 +00:00
|
|
|
term_mouse(term, b, translate_button(b), lastact,
|
|
|
|
x, y, shift, ctrl, alt);
|
1999-01-22 09:35:08 +00:00
|
|
|
lasttime = thistime;
|
1999-01-08 13:02:13 +00:00
|
|
|
}
|
|
|
|
|
2001-05-06 14:20:41 +00:00
|
|
|
/*
|
|
|
|
* Translate a raw mouse button designation (LEFT, MIDDLE, RIGHT)
|
|
|
|
* into a cooked one (SELECT, EXTEND, PASTE).
|
|
|
|
*/
|
2003-01-25 16:22:49 +00:00
|
|
|
static Mouse_Button translate_button(Mouse_Button button)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
2001-05-06 14:20:41 +00:00
|
|
|
if (button == MBT_LEFT)
|
2019-09-08 19:29:00 +00:00
|
|
|
return MBT_SELECT;
|
2001-05-06 14:20:41 +00:00
|
|
|
if (button == MBT_MIDDLE)
|
2019-09-08 19:29:00 +00:00
|
|
|
return conf_get_int(conf, CONF_mouse_is_xterm) == 1 ?
|
|
|
|
MBT_PASTE : MBT_EXTEND;
|
2001-05-06 14:20:41 +00:00
|
|
|
if (button == MBT_RIGHT)
|
2019-09-08 19:29:00 +00:00
|
|
|
return conf_get_int(conf, CONF_mouse_is_xterm) == 1 ?
|
|
|
|
MBT_EXTEND : MBT_PASTE;
|
|
|
|
return 0; /* shouldn't happen */
|
2001-05-06 14:20:41 +00:00
|
|
|
}
|
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
static void show_mouseptr(bool show)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
2005-02-15 17:05:58 +00:00
|
|
|
/* NB that the counter in ShowCursor() is also frobbed by
|
|
|
|
* update_mouse_pointer() */
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
static bool cursor_visible = true;
|
2018-10-29 19:57:31 +00:00
|
|
|
if (!conf_get_bool(conf, CONF_hide_mouseptr))
|
2019-09-08 19:29:00 +00:00
|
|
|
show = true; /* override if this feature disabled */
|
2001-01-22 16:38:43 +00:00
|
|
|
if (cursor_visible && !show)
|
2019-09-08 19:29:00 +00:00
|
|
|
ShowCursor(false);
|
2001-01-22 16:38:43 +00:00
|
|
|
else if (!cursor_visible && show)
|
2019-09-08 19:29:00 +00:00
|
|
|
ShowCursor(true);
|
2001-01-22 16:38:43 +00:00
|
|
|
cursor_visible = show;
|
|
|
|
}
|
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
static bool is_alt_pressed(void)
|
2001-10-31 18:50:09 +00:00
|
|
|
{
|
|
|
|
BYTE keystate[256];
|
|
|
|
int r = GetKeyboardState(keystate);
|
|
|
|
if (!r)
|
2019-09-08 19:29:00 +00:00
|
|
|
return false;
|
2001-10-31 18:50:09 +00:00
|
|
|
if (keystate[VK_MENU] & 0x80)
|
2019-09-08 19:29:00 +00:00
|
|
|
return true;
|
2001-10-31 18:50:09 +00:00
|
|
|
if (keystate[VK_RMENU] & 0x80)
|
2019-09-08 19:29:00 +00:00
|
|
|
return true;
|
2018-10-29 19:50:29 +00:00
|
|
|
return false;
|
2001-10-31 18:50:09 +00:00
|
|
|
}
|
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
static bool resizing;
|
2001-11-25 15:21:25 +00:00
|
|
|
|
New abstraction 'Seat', to pass to backends.
This is a new vtable-based abstraction which is passed to a backend in
place of Frontend, and it implements only the subset of the Frontend
functions needed by a backend. (Many other Frontend functions still
exist, notably the wide range of things called by terminal.c providing
platform-independent operations on the GUI terminal window.)
The purpose of making it a vtable is that this opens up the
possibility of creating a backend as an internal implementation detail
of some other activity, by providing just that one backend with a
custom Seat that implements the methods differently.
For example, this refactoring should make it feasible to directly
implement an SSH proxy type, aka the 'jump host' feature supported by
OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP
mode, and then expose the main channel of that as the Socket for the
primary connection'. (Which of course you can already do by spawning
'plink -nc' as a separate proxy process, but this would permit it in
the _same_ process without anything getting confused.)
I've centralised a full set of stub methods in misc.c for the new
abstraction, which allows me to get rid of several annoying stubs in
the previous code. Also, while I'm here, I've moved a lot of
duplicated modalfatalbox() type functions from application main
program files into wincons.c / uxcons.c, which I think saves
duplication overall. (A minor visible effect is that the prefixes on
those console-based fatal error messages will now be more consistent
between applications.)
2018-10-11 18:58:42 +00:00
|
|
|
static void win_seat_notify_remote_exit(Seat *seat)
|
2006-08-26 10:04:46 +00:00
|
|
|
{
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
int exitcode, close_on_exit;
|
2006-08-26 10:04:46 +00:00
|
|
|
|
|
|
|
if (!session_closed &&
|
2018-09-11 15:23:38 +00:00
|
|
|
(exitcode = backend_exitcode(backend)) >= 0) {
|
2019-09-08 19:29:00 +00:00
|
|
|
close_on_exit = conf_get_int(conf, CONF_close_on_exit);
|
|
|
|
/* Abnormal exits will already have set session_closed and taken
|
|
|
|
* appropriate action. */
|
|
|
|
if (close_on_exit == FORCE_ON ||
|
|
|
|
(close_on_exit == AUTO && exitcode != INT_MAX)) {
|
|
|
|
PostQuitMessage(0);
|
|
|
|
} else {
|
2013-08-17 16:06:18 +00:00
|
|
|
queue_toplevel_callback(close_session, NULL);
|
2019-09-08 19:29:00 +00:00
|
|
|
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. */
|
2020-04-14 19:36:46 +00:00
|
|
|
if (exitcode != INT_MAX) {
|
|
|
|
show_mouseptr(true);
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
MessageBox(wgs.term_hwnd, "Connection closed by remote host",
|
2019-09-08 19:29:00 +00:00
|
|
|
appname, MB_OK | MB_ICONINFORMATION);
|
2020-04-14 19:36:46 +00:00
|
|
|
}
|
2019-09-08 19:29:00 +00:00
|
|
|
}
|
2006-08-26 10:04:46 +00:00
|
|
|
}
|
|
|
|
}
|
2004-11-27 13:20:21 +00:00
|
|
|
|
2012-09-18 21:42:48 +00:00
|
|
|
void timer_change_notify(unsigned long next)
|
2004-11-27 13:20:21 +00:00
|
|
|
{
|
2012-09-18 21:42:48 +00:00
|
|
|
unsigned long now = GETTICKCOUNT();
|
|
|
|
long ticks;
|
|
|
|
if (now - next < INT_MAX)
|
2019-09-08 19:29:00 +00:00
|
|
|
ticks = 0;
|
2012-09-18 21:42:48 +00:00
|
|
|
else
|
2019-09-08 19:29:00 +00:00
|
|
|
ticks = next - now;
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
KillTimer(wgs.term_hwnd, TIMING_TIMER_ID);
|
|
|
|
SetTimer(wgs.term_hwnd, TIMING_TIMER_ID, ticks, NULL);
|
2004-11-27 13:20:21 +00:00
|
|
|
timing_next_time = next;
|
|
|
|
}
|
|
|
|
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
static void conf_cache_data(void)
|
|
|
|
{
|
|
|
|
/* 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);
|
|
|
|
}
|
|
|
|
|
2017-12-10 17:16:50 +00:00
|
|
|
static const int clips_system[] = { CLIP_SYSTEM };
|
|
|
|
|
Remove the 'Frontend' type and replace it with a vtable.
After the recent Seat and LogContext revamps, _nearly_ all the
remaining uses of the type 'Frontend' were in terminal.c, which needs
all sorts of interactions with the GUI window the terminal lives in,
from the obvious (actually drawing text on the window, reading and
writing the clipboard) to the obscure (minimising, maximising and
moving the window in response to particular escape sequences).
All of those functions are now provided by an abstraction called
TermWin. The few remaining uses of Frontend after _that_ are internal
to a particular platform directory, so as to spread the implementation
of that particular kind of Frontend between multiple source files; so
I've renamed all of those so that they take a more specifically named
type that refers to the particular implementation rather than the
general abstraction.
So now the name 'Frontend' no longer exists in the code base at all,
and everywhere one used to be used, it's completely clear whether it
was operating in one of Frontend's three abstract roles (and if so,
which), or whether it was specific to a particular implementation.
Another type that's disappeared is 'Context', which used to be a
typedef defined to something different on each platform, describing
whatever short-lived resources were necessary to draw on the terminal
window: the front end would provide a ready-made one when calling
term_paint, and the terminal could request one with get_ctx/free_ctx
if it wanted to do proactive window updates. Now that drawing context
lives inside the TermWin itself, because there was never any need to
have two of those contexts live at the same time.
(Another minor API change is that the window-title functions - both
reading and writing - have had a missing 'const' added to their char *
parameters / return values.)
I don't expect this change to enable any particularly interesting new
functionality (in particular, I have no plans that need more than one
implementation of TermWin in the same application). But it completes
the tidying-up that began with the Seat and LogContext rework.
2018-10-25 17:44:04 +00:00
|
|
|
static HDC make_hdc(void)
|
|
|
|
{
|
|
|
|
HDC hdc;
|
|
|
|
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
if (!wgs.term_hwnd)
|
Remove the 'Frontend' type and replace it with a vtable.
After the recent Seat and LogContext revamps, _nearly_ all the
remaining uses of the type 'Frontend' were in terminal.c, which needs
all sorts of interactions with the GUI window the terminal lives in,
from the obvious (actually drawing text on the window, reading and
writing the clipboard) to the obscure (minimising, maximising and
moving the window in response to particular escape sequences).
All of those functions are now provided by an abstraction called
TermWin. The few remaining uses of Frontend after _that_ are internal
to a particular platform directory, so as to spread the implementation
of that particular kind of Frontend between multiple source files; so
I've renamed all of those so that they take a more specifically named
type that refers to the particular implementation rather than the
general abstraction.
So now the name 'Frontend' no longer exists in the code base at all,
and everywhere one used to be used, it's completely clear whether it
was operating in one of Frontend's three abstract roles (and if so,
which), or whether it was specific to a particular implementation.
Another type that's disappeared is 'Context', which used to be a
typedef defined to something different on each platform, describing
whatever short-lived resources were necessary to draw on the terminal
window: the front end would provide a ready-made one when calling
term_paint, and the terminal could request one with get_ctx/free_ctx
if it wanted to do proactive window updates. Now that drawing context
lives inside the TermWin itself, because there was never any need to
have two of those contexts live at the same time.
(Another minor API change is that the window-title functions - both
reading and writing - have had a missing 'const' added to their char *
parameters / return values.)
I don't expect this change to enable any particularly interesting new
functionality (in particular, I have no plans that need more than one
implementation of TermWin in the same application). But it completes
the tidying-up that began with the Seat and LogContext rework.
2018-10-25 17:44:04 +00:00
|
|
|
return NULL;
|
|
|
|
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
hdc = GetDC(wgs.term_hwnd);
|
Remove the 'Frontend' type and replace it with a vtable.
After the recent Seat and LogContext revamps, _nearly_ all the
remaining uses of the type 'Frontend' were in terminal.c, which needs
all sorts of interactions with the GUI window the terminal lives in,
from the obvious (actually drawing text on the window, reading and
writing the clipboard) to the obscure (minimising, maximising and
moving the window in response to particular escape sequences).
All of those functions are now provided by an abstraction called
TermWin. The few remaining uses of Frontend after _that_ are internal
to a particular platform directory, so as to spread the implementation
of that particular kind of Frontend between multiple source files; so
I've renamed all of those so that they take a more specifically named
type that refers to the particular implementation rather than the
general abstraction.
So now the name 'Frontend' no longer exists in the code base at all,
and everywhere one used to be used, it's completely clear whether it
was operating in one of Frontend's three abstract roles (and if so,
which), or whether it was specific to a particular implementation.
Another type that's disappeared is 'Context', which used to be a
typedef defined to something different on each platform, describing
whatever short-lived resources were necessary to draw on the terminal
window: the front end would provide a ready-made one when calling
term_paint, and the terminal could request one with get_ctx/free_ctx
if it wanted to do proactive window updates. Now that drawing context
lives inside the TermWin itself, because there was never any need to
have two of those contexts live at the same time.
(Another minor API change is that the window-title functions - both
reading and writing - have had a missing 'const' added to their char *
parameters / return values.)
I don't expect this change to enable any particularly interesting new
functionality (in particular, I have no plans that need more than one
implementation of TermWin in the same application). But it completes
the tidying-up that began with the Seat and LogContext rework.
2018-10-25 17:44:04 +00:00
|
|
|
if (!hdc)
|
|
|
|
return NULL;
|
|
|
|
|
2018-10-29 19:50:29 +00:00
|
|
|
SelectPalette(hdc, pal, false);
|
Remove the 'Frontend' type and replace it with a vtable.
After the recent Seat and LogContext revamps, _nearly_ all the
remaining uses of the type 'Frontend' were in terminal.c, which needs
all sorts of interactions with the GUI window the terminal lives in,
from the obvious (actually drawing text on the window, reading and
writing the clipboard) to the obscure (minimising, maximising and
moving the window in response to particular escape sequences).
All of those functions are now provided by an abstraction called
TermWin. The few remaining uses of Frontend after _that_ are internal
to a particular platform directory, so as to spread the implementation
of that particular kind of Frontend between multiple source files; so
I've renamed all of those so that they take a more specifically named
type that refers to the particular implementation rather than the
general abstraction.
So now the name 'Frontend' no longer exists in the code base at all,
and everywhere one used to be used, it's completely clear whether it
was operating in one of Frontend's three abstract roles (and if so,
which), or whether it was specific to a particular implementation.
Another type that's disappeared is 'Context', which used to be a
typedef defined to something different on each platform, describing
whatever short-lived resources were necessary to draw on the terminal
window: the front end would provide a ready-made one when calling
term_paint, and the terminal could request one with get_ctx/free_ctx
if it wanted to do proactive window updates. Now that drawing context
lives inside the TermWin itself, because there was never any need to
have two of those contexts live at the same time.
(Another minor API change is that the window-title functions - both
reading and writing - have had a missing 'const' added to their char *
parameters / return values.)
I don't expect this change to enable any particularly interesting new
functionality (in particular, I have no plans that need more than one
implementation of TermWin in the same application). But it completes
the tidying-up that began with the Seat and LogContext rework.
2018-10-25 17:44:04 +00:00
|
|
|
return hdc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void free_hdc(HDC hdc)
|
|
|
|
{
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
assert(wgs.term_hwnd);
|
2018-10-29 19:50:29 +00:00
|
|
|
SelectPalette(hdc, GetStockObject(DEFAULT_PALETTE), false);
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
ReleaseDC(wgs.term_hwnd, hdc);
|
Remove the 'Frontend' type and replace it with a vtable.
After the recent Seat and LogContext revamps, _nearly_ all the
remaining uses of the type 'Frontend' were in terminal.c, which needs
all sorts of interactions with the GUI window the terminal lives in,
from the obvious (actually drawing text on the window, reading and
writing the clipboard) to the obscure (minimising, maximising and
moving the window in response to particular escape sequences).
All of those functions are now provided by an abstraction called
TermWin. The few remaining uses of Frontend after _that_ are internal
to a particular platform directory, so as to spread the implementation
of that particular kind of Frontend between multiple source files; so
I've renamed all of those so that they take a more specifically named
type that refers to the particular implementation rather than the
general abstraction.
So now the name 'Frontend' no longer exists in the code base at all,
and everywhere one used to be used, it's completely clear whether it
was operating in one of Frontend's three abstract roles (and if so,
which), or whether it was specific to a particular implementation.
Another type that's disappeared is 'Context', which used to be a
typedef defined to something different on each platform, describing
whatever short-lived resources were necessary to draw on the terminal
window: the front end would provide a ready-made one when calling
term_paint, and the terminal could request one with get_ctx/free_ctx
if it wanted to do proactive window updates. Now that drawing context
lives inside the TermWin itself, because there was never any need to
have two of those contexts live at the same time.
(Another minor API change is that the window-title functions - both
reading and writing - have had a missing 'const' added to their char *
parameters / return values.)
I don't expect this change to enable any particularly interesting new
functionality (in particular, I have no plans that need more than one
implementation of TermWin in the same application). But it completes
the tidying-up that began with the Seat and LogContext rework.
2018-10-25 17:44:04 +00:00
|
|
|
}
|
|
|
|
|
Windows: make the need_backend_resize mechanism consistent.
There were three separate clauses in the WM_SIZE message handler which
potentially called term_size() to resize the actual Terminal object.
Two of them (for maximisation and normal non-maximised resizing drags)
first checked if an interactive resize was in progress, and if so,
instead set the need_backend_resize, to defer the term_size call to
the end of the interactive operation. But the third, for
_un_-maximising a window, didn't have that check.
As a result, if you start with a maximised window, drag its title bar
downward from the top of the screen (which unmaximises it), and
without letting go, drag it back up again (which maximises it), the
effect would be that you'd get one call to term_size in the middle of
the drag, and a second at the end. This isn't what I intended, and it
can also cause a redraw failure in full-screen applications on the
server (such as a terminal-based text editor - I reproduced this with
emacs), in which after the second term_size the terminal doesn't
manage to redraw itself.
Now I've pulled out the common logic that was in two of those three
pieces of code (and should have been in all three) into a subroutine
wm_size_resize_term, and arranged to call that in all three cases.
This fixes the inconsistency, and also fixes the emacs redraw problem
in the edge case I describe above.
2021-02-07 19:59:21 +00:00
|
|
|
static bool need_backend_resize = false;
|
|
|
|
|
|
|
|
static void wm_size_resize_term(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 w = (width - border_size*2) / font_width;
|
|
|
|
int h = (height - border_size*2) / font_height;
|
|
|
|
|
|
|
|
if (w < 1) w = 1;
|
|
|
|
if (h < 1) h = 1;
|
|
|
|
|
|
|
|
if (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
|
|
|
|
* the size back and forth indecisively without wiping out any
|
|
|
|
* actual terminal contents, and secondly, the Terminal
|
|
|
|
* doesn't call back->size in turn for each increment of the
|
|
|
|
* resizing drag, so we don't spam the server with huge
|
|
|
|
* numbers of resize events.
|
|
|
|
*/
|
|
|
|
need_backend_resize = true;
|
|
|
|
conf_set_int(conf, CONF_height, h);
|
|
|
|
conf_set_int(conf, CONF_width, w);
|
|
|
|
} else {
|
|
|
|
term_size(term, h, w,
|
|
|
|
conf_get_int(conf, CONF_savelines));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-05-06 14:35:20 +00:00
|
|
|
static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
|
2019-09-08 19:29:00 +00:00
|
|
|
WPARAM wParam, LPARAM lParam)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
1999-01-08 13:02:13 +00:00
|
|
|
HDC hdc;
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
static bool ignore_clip = false;
|
|
|
|
static bool fullscr_on_max = false;
|
|
|
|
static bool processed_resize = false;
|
2004-07-25 19:52:07 +00:00
|
|
|
static UINT last_mousemove = 0;
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
int resize_action;
|
1999-01-08 13:02:13 +00:00
|
|
|
|
|
|
|
switch (message) {
|
2000-03-17 10:34:41 +00:00
|
|
|
case WM_TIMER:
|
2019-09-08 19:29:00 +00:00
|
|
|
if ((UINT_PTR)wParam == TIMING_TIMER_ID) {
|
|
|
|
unsigned long next;
|
|
|
|
|
|
|
|
KillTimer(hwnd, TIMING_TIMER_ID);
|
|
|
|
if (run_timers(timing_next_time, &next)) {
|
|
|
|
timer_change_notify(next);
|
|
|
|
} else {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
1999-01-08 13:02:13 +00:00
|
|
|
case WM_CREATE:
|
2019-09-08 19:29:00 +00:00
|
|
|
break;
|
Formatting change to braces around one case of a switch.
Sometimes, within a switch statement, you want to declare local
variables specific to the handler for one particular case. Until now
I've mostly been writing this in the form
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED:
{
declare variables;
do stuff;
}
break;
}
which is ugly because the two pieces of essentially similar code
appear at different indent levels, and also inconvenient because you
have less horizontal space available to write the complicated case
handler in - particuarly undesirable because _complicated_ case
handlers are the ones most likely to need all the space they can get!
After encountering a rather nicer idiom in the LLVM source code, and
after a bit of hackery this morning figuring out how to persuade
Emacs's auto-indent to do what I wanted with it, I've decided to move
to an idiom in which the open brace comes right after the case
statement, and the code within it is indented the same as it would
have been without the brace. Then the whole case handler (including
the break) lives inside those braces, and you get something that looks
more like this:
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED: {
declare variables;
do stuff;
break;
}
}
This commit is a big-bang change that reformats all the complicated
case handlers I could find into the new layout. This is particularly
nice in the Pageant main function, in which almost _every_ case
handler had a bundle of variables and was long and complicated. (In
fact that's what motivated me to get round to this.) Some of the
innermost parts of the terminal escape-sequence handling are also
breathing a bit easier now the horizontal pressure on them is
relieved.
(Also, in a few cases, I was able to remove the extra braces
completely, because the only variable local to the case handler was a
loop variable which our new C99 policy allows me to move into the
initialiser clause of its for statement.)
Viewed with whitespace ignored, this is not too disruptive a change.
Downstream patches that conflict with it may need to be reapplied
using --ignore-whitespace or similar.
2020-02-16 07:49:52 +00:00
|
|
|
case WM_CLOSE: {
|
2021-02-21 14:17:03 +00:00
|
|
|
char *title, *msg, *additional = NULL;
|
Formatting change to braces around one case of a switch.
Sometimes, within a switch statement, you want to declare local
variables specific to the handler for one particular case. Until now
I've mostly been writing this in the form
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED:
{
declare variables;
do stuff;
}
break;
}
which is ugly because the two pieces of essentially similar code
appear at different indent levels, and also inconvenient because you
have less horizontal space available to write the complicated case
handler in - particuarly undesirable because _complicated_ case
handlers are the ones most likely to need all the space they can get!
After encountering a rather nicer idiom in the LLVM source code, and
after a bit of hackery this morning figuring out how to persuade
Emacs's auto-indent to do what I wanted with it, I've decided to move
to an idiom in which the open brace comes right after the case
statement, and the code within it is indented the same as it would
have been without the brace. Then the whole case handler (including
the break) lives inside those braces, and you get something that looks
more like this:
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED: {
declare variables;
do stuff;
break;
}
}
This commit is a big-bang change that reformats all the complicated
case handlers I could find into the new layout. This is particularly
nice in the Pageant main function, in which almost _every_ case
handler had a bundle of variables and was long and complicated. (In
fact that's what motivated me to get round to this.) Some of the
innermost parts of the terminal escape-sequence handling are also
breathing a bit easier now the horizontal pressure on them is
relieved.
(Also, in a few cases, I was able to remove the extra braces
completely, because the only variable local to the case handler was a
loop variable which our new C99 policy allows me to move into the
initialiser clause of its for statement.)
Viewed with whitespace ignored, this is not too disruptive a change.
Downstream patches that conflict with it may need to be reapplied
using --ignore-whitespace or similar.
2020-02-16 07:49:52 +00:00
|
|
|
show_mouseptr(true);
|
2021-02-21 14:17:03 +00:00
|
|
|
title = dupprintf("%s Exit Confirmation", appname);
|
|
|
|
if (backend && backend->vt->close_warn_text) {
|
|
|
|
additional = backend->vt->close_warn_text(backend);
|
|
|
|
}
|
|
|
|
msg = dupprintf("Are you sure you want to close this session?%s%s",
|
|
|
|
additional ? "\n" : "",
|
|
|
|
additional ? additional : "");
|
Formatting change to braces around one case of a switch.
Sometimes, within a switch statement, you want to declare local
variables specific to the handler for one particular case. Until now
I've mostly been writing this in the form
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED:
{
declare variables;
do stuff;
}
break;
}
which is ugly because the two pieces of essentially similar code
appear at different indent levels, and also inconvenient because you
have less horizontal space available to write the complicated case
handler in - particuarly undesirable because _complicated_ case
handlers are the ones most likely to need all the space they can get!
After encountering a rather nicer idiom in the LLVM source code, and
after a bit of hackery this morning figuring out how to persuade
Emacs's auto-indent to do what I wanted with it, I've decided to move
to an idiom in which the open brace comes right after the case
statement, and the code within it is indented the same as it would
have been without the brace. Then the whole case handler (including
the break) lives inside those braces, and you get something that looks
more like this:
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED: {
declare variables;
do stuff;
break;
}
}
This commit is a big-bang change that reformats all the complicated
case handlers I could find into the new layout. This is particularly
nice in the Pageant main function, in which almost _every_ case
handler had a bundle of variables and was long and complicated. (In
fact that's what motivated me to get round to this.) Some of the
innermost parts of the terminal escape-sequence handling are also
breathing a bit easier now the horizontal pressure on them is
relieved.
(Also, in a few cases, I was able to remove the extra braces
completely, because the only variable local to the case handler was a
loop variable which our new C99 policy allows me to move into the
initialiser clause of its for statement.)
Viewed with whitespace ignored, this is not too disruptive a change.
Downstream patches that conflict with it may need to be reapplied
using --ignore-whitespace or similar.
2020-02-16 07:49:52 +00:00
|
|
|
if (session_closed || !conf_get_bool(conf, CONF_warn_on_close) ||
|
2021-02-21 14:17:03 +00:00
|
|
|
MessageBox(hwnd, msg, title,
|
|
|
|
MB_ICONWARNING | MB_OKCANCEL | MB_DEFBUTTON1)
|
Formatting change to braces around one case of a switch.
Sometimes, within a switch statement, you want to declare local
variables specific to the handler for one particular case. Until now
I've mostly been writing this in the form
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED:
{
declare variables;
do stuff;
}
break;
}
which is ugly because the two pieces of essentially similar code
appear at different indent levels, and also inconvenient because you
have less horizontal space available to write the complicated case
handler in - particuarly undesirable because _complicated_ case
handlers are the ones most likely to need all the space they can get!
After encountering a rather nicer idiom in the LLVM source code, and
after a bit of hackery this morning figuring out how to persuade
Emacs's auto-indent to do what I wanted with it, I've decided to move
to an idiom in which the open brace comes right after the case
statement, and the code within it is indented the same as it would
have been without the brace. Then the whole case handler (including
the break) lives inside those braces, and you get something that looks
more like this:
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED: {
declare variables;
do stuff;
break;
}
}
This commit is a big-bang change that reformats all the complicated
case handlers I could find into the new layout. This is particularly
nice in the Pageant main function, in which almost _every_ case
handler had a bundle of variables and was long and complicated. (In
fact that's what motivated me to get round to this.) Some of the
innermost parts of the terminal escape-sequence handling are also
breathing a bit easier now the horizontal pressure on them is
relieved.
(Also, in a few cases, I was able to remove the extra braces
completely, because the only variable local to the case handler was a
loop variable which our new C99 policy allows me to move into the
initialiser clause of its for statement.)
Viewed with whitespace ignored, this is not too disruptive a change.
Downstream patches that conflict with it may need to be reapplied
using --ignore-whitespace or similar.
2020-02-16 07:49:52 +00:00
|
|
|
== IDOK)
|
|
|
|
DestroyWindow(hwnd);
|
2021-02-21 14:17:03 +00:00
|
|
|
sfree(title);
|
|
|
|
sfree(msg);
|
|
|
|
sfree(additional);
|
2019-09-08 19:29:00 +00:00
|
|
|
return 0;
|
Formatting change to braces around one case of a switch.
Sometimes, within a switch statement, you want to declare local
variables specific to the handler for one particular case. Until now
I've mostly been writing this in the form
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED:
{
declare variables;
do stuff;
}
break;
}
which is ugly because the two pieces of essentially similar code
appear at different indent levels, and also inconvenient because you
have less horizontal space available to write the complicated case
handler in - particuarly undesirable because _complicated_ case
handlers are the ones most likely to need all the space they can get!
After encountering a rather nicer idiom in the LLVM source code, and
after a bit of hackery this morning figuring out how to persuade
Emacs's auto-indent to do what I wanted with it, I've decided to move
to an idiom in which the open brace comes right after the case
statement, and the code within it is indented the same as it would
have been without the brace. Then the whole case handler (including
the break) lives inside those braces, and you get something that looks
more like this:
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED: {
declare variables;
do stuff;
break;
}
}
This commit is a big-bang change that reformats all the complicated
case handlers I could find into the new layout. This is particularly
nice in the Pageant main function, in which almost _every_ case
handler had a bundle of variables and was long and complicated. (In
fact that's what motivated me to get round to this.) Some of the
innermost parts of the terminal escape-sequence handling are also
breathing a bit easier now the horizontal pressure on them is
relieved.
(Also, in a few cases, I was able to remove the extra braces
completely, because the only variable local to the case handler was a
loop variable which our new C99 policy allows me to move into the
initialiser clause of its for statement.)
Viewed with whitespace ignored, this is not too disruptive a change.
Downstream patches that conflict with it may need to be reapplied
using --ignore-whitespace or similar.
2020-02-16 07:49:52 +00:00
|
|
|
}
|
1999-01-08 13:02:13 +00:00
|
|
|
case WM_DESTROY:
|
2019-09-08 19:29:00 +00:00
|
|
|
show_mouseptr(true);
|
|
|
|
PostQuitMessage(0);
|
|
|
|
return 0;
|
2005-04-07 01:36:28 +00:00
|
|
|
case WM_INITMENUPOPUP:
|
2019-09-08 19:29:00 +00:00
|
|
|
if ((HMENU)wParam == savedsess_menu) {
|
|
|
|
/* About to pop up Saved Sessions sub-menu.
|
|
|
|
* Refresh the session list. */
|
|
|
|
get_sesslist(&sesslist, false); /* free */
|
|
|
|
get_sesslist(&sesslist, true);
|
|
|
|
update_savedsess_menu();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
break;
|
2003-11-19 20:48:30 +00:00
|
|
|
case WM_COMMAND:
|
1999-10-28 16:29:06 +00:00
|
|
|
case WM_SYSCOMMAND:
|
2019-09-08 19:29:00 +00:00
|
|
|
switch (wParam & ~0xF) { /* low 4 bits reserved to Windows */
|
|
|
|
case IDM_SHOWLOG:
|
|
|
|
showeventlog(hwnd);
|
|
|
|
break;
|
|
|
|
case IDM_NEWSESS:
|
|
|
|
case IDM_DUPSESS:
|
Formatting change to braces around one case of a switch.
Sometimes, within a switch statement, you want to declare local
variables specific to the handler for one particular case. Until now
I've mostly been writing this in the form
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED:
{
declare variables;
do stuff;
}
break;
}
which is ugly because the two pieces of essentially similar code
appear at different indent levels, and also inconvenient because you
have less horizontal space available to write the complicated case
handler in - particuarly undesirable because _complicated_ case
handlers are the ones most likely to need all the space they can get!
After encountering a rather nicer idiom in the LLVM source code, and
after a bit of hackery this morning figuring out how to persuade
Emacs's auto-indent to do what I wanted with it, I've decided to move
to an idiom in which the open brace comes right after the case
statement, and the code within it is indented the same as it would
have been without the brace. Then the whole case handler (including
the break) lives inside those braces, and you get something that looks
more like this:
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED: {
declare variables;
do stuff;
break;
}
}
This commit is a big-bang change that reformats all the complicated
case handlers I could find into the new layout. This is particularly
nice in the Pageant main function, in which almost _every_ case
handler had a bundle of variables and was long and complicated. (In
fact that's what motivated me to get round to this.) Some of the
innermost parts of the terminal escape-sequence handling are also
breathing a bit easier now the horizontal pressure on them is
relieved.
(Also, in a few cases, I was able to remove the extra braces
completely, because the only variable local to the case handler was a
loop variable which our new C99 policy allows me to move into the
initialiser clause of its for statement.)
Viewed with whitespace ignored, this is not too disruptive a change.
Downstream patches that conflict with it may need to be reapplied
using --ignore-whitespace or similar.
2020-02-16 07:49:52 +00:00
|
|
|
case IDM_SAVEDSESS: {
|
|
|
|
char b[2048];
|
|
|
|
char *cl;
|
|
|
|
const char *argprefix;
|
|
|
|
bool inherit_handles;
|
|
|
|
STARTUPINFO si;
|
|
|
|
PROCESS_INFORMATION pi;
|
|
|
|
HANDLE filemap = NULL;
|
|
|
|
|
|
|
|
if (restricted_acl())
|
|
|
|
argprefix = "&R";
|
|
|
|
else
|
|
|
|
argprefix = "";
|
|
|
|
|
|
|
|
if (wParam == IDM_DUPSESS) {
|
|
|
|
/*
|
|
|
|
* Allocate a file-mapping memory chunk for the
|
|
|
|
* config structure.
|
|
|
|
*/
|
|
|
|
SECURITY_ATTRIBUTES sa;
|
|
|
|
strbuf *serbuf;
|
|
|
|
void *p;
|
|
|
|
int size;
|
|
|
|
|
|
|
|
serbuf = strbuf_new();
|
|
|
|
conf_serialise(BinarySink_UPCAST(serbuf), conf);
|
|
|
|
size = serbuf->len;
|
|
|
|
|
|
|
|
sa.nLength = sizeof(sa);
|
|
|
|
sa.lpSecurityDescriptor = NULL;
|
|
|
|
sa.bInheritHandle = true;
|
|
|
|
filemap = CreateFileMapping(INVALID_HANDLE_VALUE,
|
|
|
|
&sa,
|
|
|
|
PAGE_READWRITE,
|
|
|
|
0, size, NULL);
|
|
|
|
if (filemap && filemap != INVALID_HANDLE_VALUE) {
|
|
|
|
p = MapViewOfFile(filemap, FILE_MAP_WRITE, 0, 0, size);
|
|
|
|
if (p) {
|
|
|
|
memcpy(p, serbuf->s, size);
|
|
|
|
UnmapViewOfFile(p);
|
2019-09-08 19:29:00 +00:00
|
|
|
}
|
Formatting change to braces around one case of a switch.
Sometimes, within a switch statement, you want to declare local
variables specific to the handler for one particular case. Until now
I've mostly been writing this in the form
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED:
{
declare variables;
do stuff;
}
break;
}
which is ugly because the two pieces of essentially similar code
appear at different indent levels, and also inconvenient because you
have less horizontal space available to write the complicated case
handler in - particuarly undesirable because _complicated_ case
handlers are the ones most likely to need all the space they can get!
After encountering a rather nicer idiom in the LLVM source code, and
after a bit of hackery this morning figuring out how to persuade
Emacs's auto-indent to do what I wanted with it, I've decided to move
to an idiom in which the open brace comes right after the case
statement, and the code within it is indented the same as it would
have been without the brace. Then the whole case handler (including
the break) lives inside those braces, and you get something that looks
more like this:
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED: {
declare variables;
do stuff;
break;
}
}
This commit is a big-bang change that reformats all the complicated
case handlers I could find into the new layout. This is particularly
nice in the Pageant main function, in which almost _every_ case
handler had a bundle of variables and was long and complicated. (In
fact that's what motivated me to get round to this.) Some of the
innermost parts of the terminal escape-sequence handling are also
breathing a bit easier now the horizontal pressure on them is
relieved.
(Also, in a few cases, I was able to remove the extra braces
completely, because the only variable local to the case handler was a
loop variable which our new C99 policy allows me to move into the
initialiser clause of its for statement.)
Viewed with whitespace ignored, this is not too disruptive a change.
Downstream patches that conflict with it may need to be reapplied
using --ignore-whitespace or similar.
2020-02-16 07:49:52 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
strbuf_free(serbuf);
|
|
|
|
inherit_handles = true;
|
|
|
|
cl = dupprintf("putty %s&%p:%u", argprefix,
|
|
|
|
filemap, (unsigned)size);
|
|
|
|
} else if (wParam == IDM_SAVEDSESS) {
|
|
|
|
unsigned int sessno = ((lParam - IDM_SAVED_MIN)
|
|
|
|
/ MENU_SAVED_STEP) + 1;
|
|
|
|
if (sessno < (unsigned)sesslist.nsessions) {
|
|
|
|
const char *session = sesslist.sessions[sessno];
|
|
|
|
cl = dupprintf("putty %s@%s", argprefix, session);
|
|
|
|
inherit_handles = false;
|
|
|
|
} else
|
|
|
|
break;
|
|
|
|
} else /* IDM_NEWSESS */ {
|
|
|
|
cl = dupprintf("putty%s%s",
|
|
|
|
*argprefix ? " " : "",
|
|
|
|
argprefix);
|
|
|
|
inherit_handles = false;
|
2019-09-08 19:29:00 +00:00
|
|
|
}
|
Formatting change to braces around one case of a switch.
Sometimes, within a switch statement, you want to declare local
variables specific to the handler for one particular case. Until now
I've mostly been writing this in the form
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED:
{
declare variables;
do stuff;
}
break;
}
which is ugly because the two pieces of essentially similar code
appear at different indent levels, and also inconvenient because you
have less horizontal space available to write the complicated case
handler in - particuarly undesirable because _complicated_ case
handlers are the ones most likely to need all the space they can get!
After encountering a rather nicer idiom in the LLVM source code, and
after a bit of hackery this morning figuring out how to persuade
Emacs's auto-indent to do what I wanted with it, I've decided to move
to an idiom in which the open brace comes right after the case
statement, and the code within it is indented the same as it would
have been without the brace. Then the whole case handler (including
the break) lives inside those braces, and you get something that looks
more like this:
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED: {
declare variables;
do stuff;
break;
}
}
This commit is a big-bang change that reformats all the complicated
case handlers I could find into the new layout. This is particularly
nice in the Pageant main function, in which almost _every_ case
handler had a bundle of variables and was long and complicated. (In
fact that's what motivated me to get round to this.) Some of the
innermost parts of the terminal escape-sequence handling are also
breathing a bit easier now the horizontal pressure on them is
relieved.
(Also, in a few cases, I was able to remove the extra braces
completely, because the only variable local to the case handler was a
loop variable which our new C99 policy allows me to move into the
initialiser clause of its for statement.)
Viewed with whitespace ignored, this is not too disruptive a change.
Downstream patches that conflict with it may need to be reapplied
using --ignore-whitespace or similar.
2020-02-16 07:49:52 +00:00
|
|
|
|
|
|
|
GetModuleFileName(NULL, b, sizeof(b) - 1);
|
|
|
|
si.cb = sizeof(si);
|
|
|
|
si.lpReserved = NULL;
|
|
|
|
si.lpDesktop = NULL;
|
|
|
|
si.lpTitle = NULL;
|
|
|
|
si.dwFlags = 0;
|
|
|
|
si.cbReserved2 = 0;
|
|
|
|
si.lpReserved2 = NULL;
|
|
|
|
CreateProcess(b, cl, NULL, NULL, inherit_handles,
|
|
|
|
NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi);
|
|
|
|
CloseHandle(pi.hProcess);
|
|
|
|
CloseHandle(pi.hThread);
|
|
|
|
|
|
|
|
if (filemap)
|
|
|
|
CloseHandle(filemap);
|
|
|
|
sfree(cl);
|
2019-09-08 19:29:00 +00:00
|
|
|
break;
|
Formatting change to braces around one case of a switch.
Sometimes, within a switch statement, you want to declare local
variables specific to the handler for one particular case. Until now
I've mostly been writing this in the form
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED:
{
declare variables;
do stuff;
}
break;
}
which is ugly because the two pieces of essentially similar code
appear at different indent levels, and also inconvenient because you
have less horizontal space available to write the complicated case
handler in - particuarly undesirable because _complicated_ case
handlers are the ones most likely to need all the space they can get!
After encountering a rather nicer idiom in the LLVM source code, and
after a bit of hackery this morning figuring out how to persuade
Emacs's auto-indent to do what I wanted with it, I've decided to move
to an idiom in which the open brace comes right after the case
statement, and the code within it is indented the same as it would
have been without the brace. Then the whole case handler (including
the break) lives inside those braces, and you get something that looks
more like this:
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED: {
declare variables;
do stuff;
break;
}
}
This commit is a big-bang change that reformats all the complicated
case handlers I could find into the new layout. This is particularly
nice in the Pageant main function, in which almost _every_ case
handler had a bundle of variables and was long and complicated. (In
fact that's what motivated me to get round to this.) Some of the
innermost parts of the terminal escape-sequence handling are also
breathing a bit easier now the horizontal pressure on them is
relieved.
(Also, in a few cases, I was able to remove the extra braces
completely, because the only variable local to the case handler was a
loop variable which our new C99 policy allows me to move into the
initialiser clause of its for statement.)
Viewed with whitespace ignored, this is not too disruptive a change.
Downstream patches that conflict with it may need to be reapplied
using --ignore-whitespace or similar.
2020-02-16 07:49:52 +00:00
|
|
|
}
|
2019-09-08 19:29:00 +00:00
|
|
|
case IDM_RESTART:
|
2018-09-11 15:23:38 +00:00
|
|
|
if (!backend) {
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
lp_eventlog(&wgs.logpolicy, "----- Session restarted -----");
|
2019-09-08 19:29:00 +00:00
|
|
|
term_pwron(term, false);
|
|
|
|
start_backend();
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
Formatting change to braces around one case of a switch.
Sometimes, within a switch statement, you want to declare local
variables specific to the handler for one particular case. Until now
I've mostly been writing this in the form
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED:
{
declare variables;
do stuff;
}
break;
}
which is ugly because the two pieces of essentially similar code
appear at different indent levels, and also inconvenient because you
have less horizontal space available to write the complicated case
handler in - particuarly undesirable because _complicated_ case
handlers are the ones most likely to need all the space they can get!
After encountering a rather nicer idiom in the LLVM source code, and
after a bit of hackery this morning figuring out how to persuade
Emacs's auto-indent to do what I wanted with it, I've decided to move
to an idiom in which the open brace comes right after the case
statement, and the code within it is indented the same as it would
have been without the brace. Then the whole case handler (including
the break) lives inside those braces, and you get something that looks
more like this:
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED: {
declare variables;
do stuff;
break;
}
}
This commit is a big-bang change that reformats all the complicated
case handlers I could find into the new layout. This is particularly
nice in the Pageant main function, in which almost _every_ case
handler had a bundle of variables and was long and complicated. (In
fact that's what motivated me to get round to this.) Some of the
innermost parts of the terminal escape-sequence handling are also
breathing a bit easier now the horizontal pressure on them is
relieved.
(Also, in a few cases, I was able to remove the extra braces
completely, because the only variable local to the case handler was a
loop variable which our new C99 policy allows me to move into the
initialiser clause of its for statement.)
Viewed with whitespace ignored, this is not too disruptive a change.
Downstream patches that conflict with it may need to be reapplied
using --ignore-whitespace or similar.
2020-02-16 07:49:52 +00:00
|
|
|
case IDM_RECONF: {
|
|
|
|
Conf *prev_conf;
|
|
|
|
int init_lvl = 1;
|
|
|
|
bool reconfig_result;
|
2019-09-08 19:29:00 +00:00
|
|
|
|
Formatting change to braces around one case of a switch.
Sometimes, within a switch statement, you want to declare local
variables specific to the handler for one particular case. Until now
I've mostly been writing this in the form
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED:
{
declare variables;
do stuff;
}
break;
}
which is ugly because the two pieces of essentially similar code
appear at different indent levels, and also inconvenient because you
have less horizontal space available to write the complicated case
handler in - particuarly undesirable because _complicated_ case
handlers are the ones most likely to need all the space they can get!
After encountering a rather nicer idiom in the LLVM source code, and
after a bit of hackery this morning figuring out how to persuade
Emacs's auto-indent to do what I wanted with it, I've decided to move
to an idiom in which the open brace comes right after the case
statement, and the code within it is indented the same as it would
have been without the brace. Then the whole case handler (including
the break) lives inside those braces, and you get something that looks
more like this:
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED: {
declare variables;
do stuff;
break;
}
}
This commit is a big-bang change that reformats all the complicated
case handlers I could find into the new layout. This is particularly
nice in the Pageant main function, in which almost _every_ case
handler had a bundle of variables and was long and complicated. (In
fact that's what motivated me to get round to this.) Some of the
innermost parts of the terminal escape-sequence handling are also
breathing a bit easier now the horizontal pressure on them is
relieved.
(Also, in a few cases, I was able to remove the extra braces
completely, because the only variable local to the case handler was a
loop variable which our new C99 policy allows me to move into the
initialiser clause of its for statement.)
Viewed with whitespace ignored, this is not too disruptive a change.
Downstream patches that conflict with it may need to be reapplied
using --ignore-whitespace or similar.
2020-02-16 07:49:52 +00:00
|
|
|
if (reconfiguring)
|
|
|
|
break;
|
|
|
|
else
|
|
|
|
reconfiguring = true;
|
2019-09-08 19:29:00 +00:00
|
|
|
|
2021-02-07 19:59:20 +00:00
|
|
|
term_pre_reconfig(term, conf);
|
Formatting change to braces around one case of a switch.
Sometimes, within a switch statement, you want to declare local
variables specific to the handler for one particular case. Until now
I've mostly been writing this in the form
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED:
{
declare variables;
do stuff;
}
break;
}
which is ugly because the two pieces of essentially similar code
appear at different indent levels, and also inconvenient because you
have less horizontal space available to write the complicated case
handler in - particuarly undesirable because _complicated_ case
handlers are the ones most likely to need all the space they can get!
After encountering a rather nicer idiom in the LLVM source code, and
after a bit of hackery this morning figuring out how to persuade
Emacs's auto-indent to do what I wanted with it, I've decided to move
to an idiom in which the open brace comes right after the case
statement, and the code within it is indented the same as it would
have been without the brace. Then the whole case handler (including
the break) lives inside those braces, and you get something that looks
more like this:
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED: {
declare variables;
do stuff;
break;
}
}
This commit is a big-bang change that reformats all the complicated
case handlers I could find into the new layout. This is particularly
nice in the Pageant main function, in which almost _every_ case
handler had a bundle of variables and was long and complicated. (In
fact that's what motivated me to get round to this.) Some of the
innermost parts of the terminal escape-sequence handling are also
breathing a bit easier now the horizontal pressure on them is
relieved.
(Also, in a few cases, I was able to remove the extra braces
completely, because the only variable local to the case handler was a
loop variable which our new C99 policy allows me to move into the
initialiser clause of its for statement.)
Viewed with whitespace ignored, this is not too disruptive a change.
Downstream patches that conflict with it may need to be reapplied
using --ignore-whitespace or similar.
2020-02-16 07:49:52 +00:00
|
|
|
prev_conf = conf_copy(conf);
|
2019-09-08 19:29:00 +00:00
|
|
|
|
Formatting change to braces around one case of a switch.
Sometimes, within a switch statement, you want to declare local
variables specific to the handler for one particular case. Until now
I've mostly been writing this in the form
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED:
{
declare variables;
do stuff;
}
break;
}
which is ugly because the two pieces of essentially similar code
appear at different indent levels, and also inconvenient because you
have less horizontal space available to write the complicated case
handler in - particuarly undesirable because _complicated_ case
handlers are the ones most likely to need all the space they can get!
After encountering a rather nicer idiom in the LLVM source code, and
after a bit of hackery this morning figuring out how to persuade
Emacs's auto-indent to do what I wanted with it, I've decided to move
to an idiom in which the open brace comes right after the case
statement, and the code within it is indented the same as it would
have been without the brace. Then the whole case handler (including
the break) lives inside those braces, and you get something that looks
more like this:
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED: {
declare variables;
do stuff;
break;
}
}
This commit is a big-bang change that reformats all the complicated
case handlers I could find into the new layout. This is particularly
nice in the Pageant main function, in which almost _every_ case
handler had a bundle of variables and was long and complicated. (In
fact that's what motivated me to get round to this.) Some of the
innermost parts of the terminal escape-sequence handling are also
breathing a bit easier now the horizontal pressure on them is
relieved.
(Also, in a few cases, I was able to remove the extra braces
completely, because the only variable local to the case handler was a
loop variable which our new C99 policy allows me to move into the
initialiser clause of its for statement.)
Viewed with whitespace ignored, this is not too disruptive a change.
Downstream patches that conflict with it may need to be reapplied
using --ignore-whitespace or similar.
2020-02-16 07:49:52 +00:00
|
|
|
reconfig_result = do_reconfig(
|
|
|
|
hwnd, conf, backend ? backend_cfg_info(backend) : 0);
|
|
|
|
reconfiguring = false;
|
|
|
|
if (!reconfig_result) {
|
|
|
|
conf_free(prev_conf);
|
|
|
|
break;
|
|
|
|
}
|
2019-09-08 19:29:00 +00:00
|
|
|
|
Formatting change to braces around one case of a switch.
Sometimes, within a switch statement, you want to declare local
variables specific to the handler for one particular case. Until now
I've mostly been writing this in the form
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED:
{
declare variables;
do stuff;
}
break;
}
which is ugly because the two pieces of essentially similar code
appear at different indent levels, and also inconvenient because you
have less horizontal space available to write the complicated case
handler in - particuarly undesirable because _complicated_ case
handlers are the ones most likely to need all the space they can get!
After encountering a rather nicer idiom in the LLVM source code, and
after a bit of hackery this morning figuring out how to persuade
Emacs's auto-indent to do what I wanted with it, I've decided to move
to an idiom in which the open brace comes right after the case
statement, and the code within it is indented the same as it would
have been without the brace. Then the whole case handler (including
the break) lives inside those braces, and you get something that looks
more like this:
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED: {
declare variables;
do stuff;
break;
}
}
This commit is a big-bang change that reformats all the complicated
case handlers I could find into the new layout. This is particularly
nice in the Pageant main function, in which almost _every_ case
handler had a bundle of variables and was long and complicated. (In
fact that's what motivated me to get round to this.) Some of the
innermost parts of the terminal escape-sequence handling are also
breathing a bit easier now the horizontal pressure on them is
relieved.
(Also, in a few cases, I was able to remove the extra braces
completely, because the only variable local to the case handler was a
loop variable which our new C99 policy allows me to move into the
initialiser clause of its for statement.)
Viewed with whitespace ignored, this is not too disruptive a change.
Downstream patches that conflict with it may need to be reapplied
using --ignore-whitespace or similar.
2020-02-16 07:49:52 +00:00
|
|
|
conf_cache_data();
|
2019-09-08 19:29:00 +00:00
|
|
|
|
Formatting change to braces around one case of a switch.
Sometimes, within a switch statement, you want to declare local
variables specific to the handler for one particular case. Until now
I've mostly been writing this in the form
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED:
{
declare variables;
do stuff;
}
break;
}
which is ugly because the two pieces of essentially similar code
appear at different indent levels, and also inconvenient because you
have less horizontal space available to write the complicated case
handler in - particuarly undesirable because _complicated_ case
handlers are the ones most likely to need all the space they can get!
After encountering a rather nicer idiom in the LLVM source code, and
after a bit of hackery this morning figuring out how to persuade
Emacs's auto-indent to do what I wanted with it, I've decided to move
to an idiom in which the open brace comes right after the case
statement, and the code within it is indented the same as it would
have been without the brace. Then the whole case handler (including
the break) lives inside those braces, and you get something that looks
more like this:
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED: {
declare variables;
do stuff;
break;
}
}
This commit is a big-bang change that reformats all the complicated
case handlers I could find into the new layout. This is particularly
nice in the Pageant main function, in which almost _every_ case
handler had a bundle of variables and was long and complicated. (In
fact that's what motivated me to get round to this.) Some of the
innermost parts of the terminal escape-sequence handling are also
breathing a bit easier now the horizontal pressure on them is
relieved.
(Also, in a few cases, I was able to remove the extra braces
completely, because the only variable local to the case handler was a
loop variable which our new C99 policy allows me to move into the
initialiser clause of its for statement.)
Viewed with whitespace ignored, this is not too disruptive a change.
Downstream patches that conflict with it may need to be reapplied
using --ignore-whitespace or similar.
2020-02-16 07:49:52 +00:00
|
|
|
resize_action = conf_get_int(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,
|
|
|
|
MF_BYCOMMAND |
|
|
|
|
(resize_action == RESIZE_DISABLED
|
|
|
|
? MF_GRAYED : MF_ENABLED));
|
|
|
|
/* Gracefully unzoom if necessary */
|
|
|
|
if (IsZoomed(hwnd) && (resize_action == RESIZE_DISABLED))
|
|
|
|
ShowWindow(hwnd, SW_RESTORE);
|
|
|
|
}
|
2001-01-07 18:24:59 +00:00
|
|
|
|
Formatting change to braces around one case of a switch.
Sometimes, within a switch statement, you want to declare local
variables specific to the handler for one particular case. Until now
I've mostly been writing this in the form
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED:
{
declare variables;
do stuff;
}
break;
}
which is ugly because the two pieces of essentially similar code
appear at different indent levels, and also inconvenient because you
have less horizontal space available to write the complicated case
handler in - particuarly undesirable because _complicated_ case
handlers are the ones most likely to need all the space they can get!
After encountering a rather nicer idiom in the LLVM source code, and
after a bit of hackery this morning figuring out how to persuade
Emacs's auto-indent to do what I wanted with it, I've decided to move
to an idiom in which the open brace comes right after the case
statement, and the code within it is indented the same as it would
have been without the brace. Then the whole case handler (including
the break) lives inside those braces, and you get something that looks
more like this:
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED: {
declare variables;
do stuff;
break;
}
}
This commit is a big-bang change that reformats all the complicated
case handlers I could find into the new layout. This is particularly
nice in the Pageant main function, in which almost _every_ case
handler had a bundle of variables and was long and complicated. (In
fact that's what motivated me to get round to this.) Some of the
innermost parts of the terminal escape-sequence handling are also
breathing a bit easier now the horizontal pressure on them is
relieved.
(Also, in a few cases, I was able to remove the extra braces
completely, because the only variable local to the case handler was a
loop variable which our new C99 policy allows me to move into the
initialiser clause of its for statement.)
Viewed with whitespace ignored, this is not too disruptive a change.
Downstream patches that conflict with it may need to be reapplied
using --ignore-whitespace or similar.
2020-02-16 07:49:52 +00:00
|
|
|
/* Pass new config data to the logging module */
|
|
|
|
log_reconfig(logctx, conf);
|
2019-09-08 19:29:00 +00:00
|
|
|
|
Formatting change to braces around one case of a switch.
Sometimes, within a switch statement, you want to declare local
variables specific to the handler for one particular case. Until now
I've mostly been writing this in the form
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED:
{
declare variables;
do stuff;
}
break;
}
which is ugly because the two pieces of essentially similar code
appear at different indent levels, and also inconvenient because you
have less horizontal space available to write the complicated case
handler in - particuarly undesirable because _complicated_ case
handlers are the ones most likely to need all the space they can get!
After encountering a rather nicer idiom in the LLVM source code, and
after a bit of hackery this morning figuring out how to persuade
Emacs's auto-indent to do what I wanted with it, I've decided to move
to an idiom in which the open brace comes right after the case
statement, and the code within it is indented the same as it would
have been without the brace. Then the whole case handler (including
the break) lives inside those braces, and you get something that looks
more like this:
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED: {
declare variables;
do stuff;
break;
}
}
This commit is a big-bang change that reformats all the complicated
case handlers I could find into the new layout. This is particularly
nice in the Pageant main function, in which almost _every_ case
handler had a bundle of variables and was long and complicated. (In
fact that's what motivated me to get round to this.) Some of the
innermost parts of the terminal escape-sequence handling are also
breathing a bit easier now the horizontal pressure on them is
relieved.
(Also, in a few cases, I was able to remove the extra braces
completely, because the only variable local to the case handler was a
loop variable which our new C99 policy allows me to move into the
initialiser clause of its for statement.)
Viewed with whitespace ignored, this is not too disruptive a change.
Downstream patches that conflict with it may need to be reapplied
using --ignore-whitespace or similar.
2020-02-16 07:49:52 +00:00
|
|
|
sfree(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);
|
|
|
|
}
|
Centralise palette setup into terminal.c.
Now terminal.c makes nearly all the decisions about what the colour
palette should actually contain: it does the job of reading the
GUI-configurable colours out of Conf, and also the job of making up
the rest of the xterm-256 palette. The only exception is that TermWin
can provide a method to override some of the default colours, which on
Windows is used to implement the 'Use system colours' config option.
This saves code overall, partly because the front ends don't have to
be able to send palette data back to the Terminal any more (the
Terminal keeps the master copy and can answer palette-query escape
sequences from its own knowledge), and also because now there's only
one copy of the xterm-256 palette setup code (previously gtkwin.c and
window.c each had their own version of it).
In this rewrite, I've also introduced a multi-layered storage system
for the palette data in Terminal. One layer contains the palette
information derived from Conf; the next contains platform overrides
(currently just Windows's 'Use system colours'); the last one contains
overrides set by escape sequences in the middle of the session. The
topmost two layers can each _conditionally_ override the ones below.
As a result, if a server-side application manually resets (say) the
default fg and bg colours in mid-session to something that works well
in a particular application, those changes won't be wiped out by a
change in the Windows system colours or the Conf, which they would
have been before. Instead, changes in Conf or the system colours alter
the lower layers of the structure, but then when palette_rebuild is
called, the upper layer continues to override them, until a palette
reset (ESC]R) or terminal reset (e.g. ESC c) removes those upper-layer
changes. This seems like a more consistent strategy, in that the same
set of configuration settings will produce the same end result
regardless of what order they were applied in.
The palette-related methods in TermWin have had a total rework.
palette_get and palette_reset are both gone; palette_set can now set a
contiguous range of colours in one go; and the new
palette_get_overrides replaces window.c's old systopalette().
2021-02-07 19:59:21 +00:00
|
|
|
|
|
|
|
if (conf_get_bool(conf, CONF_system_colour) !=
|
|
|
|
conf_get_bool(prev_conf, CONF_system_colour))
|
|
|
|
term_notify_palette_overrides_changed(term);
|
|
|
|
|
|
|
|
/* Pass new config data to the terminal */
|
|
|
|
term_reconfig(term, conf);
|
|
|
|
setup_clipboards(term, conf);
|
|
|
|
|
|
|
|
/* Reinitialise the colour palette, in case the terminal
|
|
|
|
* just read new settings out of Conf */
|
Formatting change to braces around one case of a switch.
Sometimes, within a switch statement, you want to declare local
variables specific to the handler for one particular case. Until now
I've mostly been writing this in the form
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED:
{
declare variables;
do stuff;
}
break;
}
which is ugly because the two pieces of essentially similar code
appear at different indent levels, and also inconvenient because you
have less horizontal space available to write the complicated case
handler in - particuarly undesirable because _complicated_ case
handlers are the ones most likely to need all the space they can get!
After encountering a rather nicer idiom in the LLVM source code, and
after a bit of hackery this morning figuring out how to persuade
Emacs's auto-indent to do what I wanted with it, I've decided to move
to an idiom in which the open brace comes right after the case
statement, and the code within it is indented the same as it would
have been without the brace. Then the whole case handler (including
the break) lives inside those braces, and you get something that looks
more like this:
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED: {
declare variables;
do stuff;
break;
}
}
This commit is a big-bang change that reformats all the complicated
case handlers I could find into the new layout. This is particularly
nice in the Pageant main function, in which almost _every_ case
handler had a bundle of variables and was long and complicated. (In
fact that's what motivated me to get round to this.) Some of the
innermost parts of the terminal escape-sequence handling are also
breathing a bit easier now the horizontal pressure on them is
relieved.
(Also, in a few cases, I was able to remove the extra braces
completely, because the only variable local to the case handler was a
loop variable which our new C99 policy allows me to move into the
initialiser clause of its for statement.)
Viewed with whitespace ignored, this is not too disruptive a change.
Downstream patches that conflict with it may need to be reapplied
using --ignore-whitespace or similar.
2020-02-16 07:49:52 +00:00
|
|
|
if (pal)
|
|
|
|
DeleteObject(pal);
|
|
|
|
logpal = NULL;
|
|
|
|
pal = NULL;
|
|
|
|
init_palette();
|
|
|
|
|
|
|
|
/* Pass new config data to the back end */
|
|
|
|
if (backend)
|
|
|
|
backend_reconfig(backend, conf);
|
|
|
|
|
|
|
|
/* Screen size changed ? */
|
|
|
|
if (conf_get_int(conf, CONF_height) !=
|
|
|
|
conf_get_int(prev_conf, CONF_height) ||
|
|
|
|
conf_get_int(conf, CONF_width) !=
|
|
|
|
conf_get_int(prev_conf, CONF_width) ||
|
|
|
|
conf_get_int(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));
|
2019-09-08 19:29:00 +00:00
|
|
|
|
Formatting change to braces around one case of a switch.
Sometimes, within a switch statement, you want to declare local
variables specific to the handler for one particular case. Until now
I've mostly been writing this in the form
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED:
{
declare variables;
do stuff;
}
break;
}
which is ugly because the two pieces of essentially similar code
appear at different indent levels, and also inconvenient because you
have less horizontal space available to write the complicated case
handler in - particuarly undesirable because _complicated_ case
handlers are the ones most likely to need all the space they can get!
After encountering a rather nicer idiom in the LLVM source code, and
after a bit of hackery this morning figuring out how to persuade
Emacs's auto-indent to do what I wanted with it, I've decided to move
to an idiom in which the open brace comes right after the case
statement, and the code within it is indented the same as it would
have been without the brace. Then the whole case handler (including
the break) lives inside those braces, and you get something that looks
more like this:
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED: {
declare variables;
do stuff;
break;
}
}
This commit is a big-bang change that reformats all the complicated
case handlers I could find into the new layout. This is particularly
nice in the Pageant main function, in which almost _every_ case
handler had a bundle of variables and was long and complicated. (In
fact that's what motivated me to get round to this.) Some of the
innermost parts of the terminal escape-sequence handling are also
breathing a bit easier now the horizontal pressure on them is
relieved.
(Also, in a few cases, I was able to remove the extra braces
completely, because the only variable local to the case handler was a
loop variable which our new C99 policy allows me to move into the
initialiser clause of its for statement.)
Viewed with whitespace ignored, this is not too disruptive a change.
Downstream patches that conflict with it may need to be reapplied
using --ignore-whitespace or similar.
2020-02-16 07:49:52 +00:00
|
|
|
/* Enable or disable the scroll bar, etc */
|
|
|
|
{
|
|
|
|
LONG nflg, flag = GetWindowLongPtr(hwnd, GWL_STYLE);
|
|
|
|
LONG nexflag, exflag =
|
|
|
|
GetWindowLongPtr(hwnd, GWL_EXSTYLE);
|
|
|
|
|
|
|
|
nexflag = exflag;
|
|
|
|
if (conf_get_bool(conf, CONF_alwaysontop) !=
|
|
|
|
conf_get_bool(prev_conf, CONF_alwaysontop)) {
|
|
|
|
if (conf_get_bool(conf, CONF_alwaysontop)) {
|
|
|
|
nexflag |= WS_EX_TOPMOST;
|
|
|
|
SetWindowPos(hwnd, HWND_TOPMOST, 0, 0, 0, 0,
|
|
|
|
SWP_NOMOVE | SWP_NOSIZE);
|
|
|
|
} else {
|
|
|
|
nexflag &= ~(WS_EX_TOPMOST);
|
|
|
|
SetWindowPos(hwnd, HWND_NOTOPMOST, 0, 0, 0, 0,
|
|
|
|
SWP_NOMOVE | SWP_NOSIZE);
|
2019-09-08 19:29:00 +00:00
|
|
|
}
|
Formatting change to braces around one case of a switch.
Sometimes, within a switch statement, you want to declare local
variables specific to the handler for one particular case. Until now
I've mostly been writing this in the form
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED:
{
declare variables;
do stuff;
}
break;
}
which is ugly because the two pieces of essentially similar code
appear at different indent levels, and also inconvenient because you
have less horizontal space available to write the complicated case
handler in - particuarly undesirable because _complicated_ case
handlers are the ones most likely to need all the space they can get!
After encountering a rather nicer idiom in the LLVM source code, and
after a bit of hackery this morning figuring out how to persuade
Emacs's auto-indent to do what I wanted with it, I've decided to move
to an idiom in which the open brace comes right after the case
statement, and the code within it is indented the same as it would
have been without the brace. Then the whole case handler (including
the break) lives inside those braces, and you get something that looks
more like this:
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED: {
declare variables;
do stuff;
break;
}
}
This commit is a big-bang change that reformats all the complicated
case handlers I could find into the new layout. This is particularly
nice in the Pageant main function, in which almost _every_ case
handler had a bundle of variables and was long and complicated. (In
fact that's what motivated me to get round to this.) Some of the
innermost parts of the terminal escape-sequence handling are also
breathing a bit easier now the horizontal pressure on them is
relieved.
(Also, in a few cases, I was able to remove the extra braces
completely, because the only variable local to the case handler was a
loop variable which our new C99 policy allows me to move into the
initialiser clause of its for statement.)
Viewed with whitespace ignored, this is not too disruptive a change.
Downstream patches that conflict with it may need to be reapplied
using --ignore-whitespace or similar.
2020-02-16 07:49:52 +00:00
|
|
|
}
|
|
|
|
if (conf_get_bool(conf, CONF_sunken_edge))
|
|
|
|
nexflag |= WS_EX_CLIENTEDGE;
|
|
|
|
else
|
|
|
|
nexflag &= ~(WS_EX_CLIENTEDGE);
|
|
|
|
|
|
|
|
nflg = flag;
|
|
|
|
if (conf_get_bool(conf, is_full_screen() ?
|
|
|
|
CONF_scrollbar_in_fullscreen :
|
|
|
|
CONF_scrollbar))
|
|
|
|
nflg |= WS_VSCROLL;
|
|
|
|
else
|
|
|
|
nflg &= ~WS_VSCROLL;
|
|
|
|
|
|
|
|
if (resize_action == RESIZE_DISABLED ||
|
|
|
|
is_full_screen())
|
|
|
|
nflg &= ~WS_THICKFRAME;
|
|
|
|
else
|
|
|
|
nflg |= WS_THICKFRAME;
|
|
|
|
|
|
|
|
if (resize_action == RESIZE_DISABLED)
|
|
|
|
nflg &= ~WS_MAXIMIZEBOX;
|
|
|
|
else
|
|
|
|
nflg |= WS_MAXIMIZEBOX;
|
|
|
|
|
|
|
|
if (nflg != flag || nexflag != exflag) {
|
|
|
|
if (nflg != flag)
|
|
|
|
SetWindowLongPtr(hwnd, GWL_STYLE, nflg);
|
|
|
|
if (nexflag != exflag)
|
|
|
|
SetWindowLongPtr(hwnd, GWL_EXSTYLE, nexflag);
|
|
|
|
|
|
|
|
SetWindowPos(hwnd, NULL, 0, 0, 0, 0,
|
|
|
|
SWP_NOACTIVATE | SWP_NOCOPYBITS |
|
|
|
|
SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER |
|
|
|
|
SWP_FRAMECHANGED);
|
|
|
|
|
|
|
|
init_lvl = 2;
|
|
|
|
}
|
|
|
|
}
|
2019-09-08 19:29:00 +00:00
|
|
|
|
Formatting change to braces around one case of a switch.
Sometimes, within a switch statement, you want to declare local
variables specific to the handler for one particular case. Until now
I've mostly been writing this in the form
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED:
{
declare variables;
do stuff;
}
break;
}
which is ugly because the two pieces of essentially similar code
appear at different indent levels, and also inconvenient because you
have less horizontal space available to write the complicated case
handler in - particuarly undesirable because _complicated_ case
handlers are the ones most likely to need all the space they can get!
After encountering a rather nicer idiom in the LLVM source code, and
after a bit of hackery this morning figuring out how to persuade
Emacs's auto-indent to do what I wanted with it, I've decided to move
to an idiom in which the open brace comes right after the case
statement, and the code within it is indented the same as it would
have been without the brace. Then the whole case handler (including
the break) lives inside those braces, and you get something that looks
more like this:
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED: {
declare variables;
do stuff;
break;
}
}
This commit is a big-bang change that reformats all the complicated
case handlers I could find into the new layout. This is particularly
nice in the Pageant main function, in which almost _every_ case
handler had a bundle of variables and was long and complicated. (In
fact that's what motivated me to get round to this.) Some of the
innermost parts of the terminal escape-sequence handling are also
breathing a bit easier now the horizontal pressure on them is
relieved.
(Also, in a few cases, I was able to remove the extra braces
completely, because the only variable local to the case handler was a
loop variable which our new C99 policy allows me to move into the
initialiser clause of its for statement.)
Viewed with whitespace ignored, this is not too disruptive a change.
Downstream patches that conflict with it may need to be reapplied
using --ignore-whitespace or similar.
2020-02-16 07:49:52 +00:00
|
|
|
/* Oops */
|
|
|
|
if (resize_action == RESIZE_DISABLED && IsZoomed(hwnd)) {
|
|
|
|
force_normal(hwnd);
|
|
|
|
init_lvl = 2;
|
|
|
|
}
|
2019-09-08 19:29:00 +00:00
|
|
|
|
Formatting change to braces around one case of a switch.
Sometimes, within a switch statement, you want to declare local
variables specific to the handler for one particular case. Until now
I've mostly been writing this in the form
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED:
{
declare variables;
do stuff;
}
break;
}
which is ugly because the two pieces of essentially similar code
appear at different indent levels, and also inconvenient because you
have less horizontal space available to write the complicated case
handler in - particuarly undesirable because _complicated_ case
handlers are the ones most likely to need all the space they can get!
After encountering a rather nicer idiom in the LLVM source code, and
after a bit of hackery this morning figuring out how to persuade
Emacs's auto-indent to do what I wanted with it, I've decided to move
to an idiom in which the open brace comes right after the case
statement, and the code within it is indented the same as it would
have been without the brace. Then the whole case handler (including
the break) lives inside those braces, and you get something that looks
more like this:
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED: {
declare variables;
do stuff;
break;
}
}
This commit is a big-bang change that reformats all the complicated
case handlers I could find into the new layout. This is particularly
nice in the Pageant main function, in which almost _every_ case
handler had a bundle of variables and was long and complicated. (In
fact that's what motivated me to get round to this.) Some of the
innermost parts of the terminal escape-sequence handling are also
breathing a bit easier now the horizontal pressure on them is
relieved.
(Also, in a few cases, I was able to remove the extra braces
completely, because the only variable local to the case handler was a
loop variable which our new C99 policy allows me to move into the
initialiser clause of its for statement.)
Viewed with whitespace ignored, this is not too disruptive a change.
Downstream patches that conflict with it may need to be reapplied
using --ignore-whitespace or similar.
2020-02-16 07:49:52 +00:00
|
|
|
{
|
|
|
|
FontSpec *font = conf_get_fontspec(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),
|
|
|
|
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(prev_conf, CONF_font_quality) ||
|
|
|
|
conf_get_int(conf, CONF_vtmode) !=
|
|
|
|
conf_get_int(prev_conf, CONF_vtmode) ||
|
|
|
|
conf_get_int(conf, CONF_bold_style) !=
|
|
|
|
conf_get_int(prev_conf, CONF_bold_style) ||
|
|
|
|
resize_action == RESIZE_DISABLED ||
|
|
|
|
resize_action == RESIZE_EITHER ||
|
|
|
|
resize_action != conf_get_int(prev_conf,
|
|
|
|
CONF_resize_action))
|
|
|
|
init_lvl = 2;
|
|
|
|
}
|
2019-09-08 19:29:00 +00:00
|
|
|
|
Formatting change to braces around one case of a switch.
Sometimes, within a switch statement, you want to declare local
variables specific to the handler for one particular case. Until now
I've mostly been writing this in the form
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED:
{
declare variables;
do stuff;
}
break;
}
which is ugly because the two pieces of essentially similar code
appear at different indent levels, and also inconvenient because you
have less horizontal space available to write the complicated case
handler in - particuarly undesirable because _complicated_ case
handlers are the ones most likely to need all the space they can get!
After encountering a rather nicer idiom in the LLVM source code, and
after a bit of hackery this morning figuring out how to persuade
Emacs's auto-indent to do what I wanted with it, I've decided to move
to an idiom in which the open brace comes right after the case
statement, and the code within it is indented the same as it would
have been without the brace. Then the whole case handler (including
the break) lives inside those braces, and you get something that looks
more like this:
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED: {
declare variables;
do stuff;
break;
}
}
This commit is a big-bang change that reformats all the complicated
case handlers I could find into the new layout. This is particularly
nice in the Pageant main function, in which almost _every_ case
handler had a bundle of variables and was long and complicated. (In
fact that's what motivated me to get round to this.) Some of the
innermost parts of the terminal escape-sequence handling are also
breathing a bit easier now the horizontal pressure on them is
relieved.
(Also, in a few cases, I was able to remove the extra braces
completely, because the only variable local to the case handler was a
loop variable which our new C99 policy allows me to move into the
initialiser clause of its for statement.)
Viewed with whitespace ignored, this is not too disruptive a change.
Downstream patches that conflict with it may need to be reapplied
using --ignore-whitespace or similar.
2020-02-16 07:49:52 +00:00
|
|
|
InvalidateRect(hwnd, NULL, true);
|
|
|
|
reset_window(init_lvl);
|
2019-09-08 19:29:00 +00:00
|
|
|
|
Formatting change to braces around one case of a switch.
Sometimes, within a switch statement, you want to declare local
variables specific to the handler for one particular case. Until now
I've mostly been writing this in the form
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED:
{
declare variables;
do stuff;
}
break;
}
which is ugly because the two pieces of essentially similar code
appear at different indent levels, and also inconvenient because you
have less horizontal space available to write the complicated case
handler in - particuarly undesirable because _complicated_ case
handlers are the ones most likely to need all the space they can get!
After encountering a rather nicer idiom in the LLVM source code, and
after a bit of hackery this morning figuring out how to persuade
Emacs's auto-indent to do what I wanted with it, I've decided to move
to an idiom in which the open brace comes right after the case
statement, and the code within it is indented the same as it would
have been without the brace. Then the whole case handler (including
the break) lives inside those braces, and you get something that looks
more like this:
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED: {
declare variables;
do stuff;
break;
}
}
This commit is a big-bang change that reformats all the complicated
case handlers I could find into the new layout. This is particularly
nice in the Pageant main function, in which almost _every_ case
handler had a bundle of variables and was long and complicated. (In
fact that's what motivated me to get round to this.) Some of the
innermost parts of the terminal escape-sequence handling are also
breathing a bit easier now the horizontal pressure on them is
relieved.
(Also, in a few cases, I was able to remove the extra braces
completely, because the only variable local to the case handler was a
loop variable which our new C99 policy allows me to move into the
initialiser clause of its for statement.)
Viewed with whitespace ignored, this is not too disruptive a change.
Downstream patches that conflict with it may need to be reapplied
using --ignore-whitespace or similar.
2020-02-16 07:49:52 +00:00
|
|
|
conf_free(prev_conf);
|
2019-09-08 19:29:00 +00:00
|
|
|
break;
|
Formatting change to braces around one case of a switch.
Sometimes, within a switch statement, you want to declare local
variables specific to the handler for one particular case. Until now
I've mostly been writing this in the form
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED:
{
declare variables;
do stuff;
}
break;
}
which is ugly because the two pieces of essentially similar code
appear at different indent levels, and also inconvenient because you
have less horizontal space available to write the complicated case
handler in - particuarly undesirable because _complicated_ case
handlers are the ones most likely to need all the space they can get!
After encountering a rather nicer idiom in the LLVM source code, and
after a bit of hackery this morning figuring out how to persuade
Emacs's auto-indent to do what I wanted with it, I've decided to move
to an idiom in which the open brace comes right after the case
statement, and the code within it is indented the same as it would
have been without the brace. Then the whole case handler (including
the break) lives inside those braces, and you get something that looks
more like this:
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED: {
declare variables;
do stuff;
break;
}
}
This commit is a big-bang change that reformats all the complicated
case handlers I could find into the new layout. This is particularly
nice in the Pageant main function, in which almost _every_ case
handler had a bundle of variables and was long and complicated. (In
fact that's what motivated me to get round to this.) Some of the
innermost parts of the terminal escape-sequence handling are also
breathing a bit easier now the horizontal pressure on them is
relieved.
(Also, in a few cases, I was able to remove the extra braces
completely, because the only variable local to the case handler was a
loop variable which our new C99 policy allows me to move into the
initialiser clause of its for statement.)
Viewed with whitespace ignored, this is not too disruptive a change.
Downstream patches that conflict with it may need to be reapplied
using --ignore-whitespace or similar.
2020-02-16 07:49:52 +00:00
|
|
|
}
|
2019-09-08 19:29:00 +00:00
|
|
|
case IDM_COPYALL:
|
2017-12-10 17:16:50 +00:00
|
|
|
term_copyall(term, clips_system, lenof(clips_system));
|
2019-09-08 19:29:00 +00:00
|
|
|
break;
|
|
|
|
case IDM_COPY:
|
2017-12-10 17:16:50 +00:00
|
|
|
term_request_copy(term, clips_system, lenof(clips_system));
|
2019-09-08 19:29:00 +00:00
|
|
|
break;
|
|
|
|
case IDM_PASTE:
|
|
|
|
term_request_paste(term, CLIP_SYSTEM);
|
|
|
|
break;
|
|
|
|
case IDM_CLRSB:
|
|
|
|
term_clrsb(term);
|
|
|
|
break;
|
|
|
|
case IDM_RESET:
|
|
|
|
term_pwron(term, true);
|
|
|
|
if (ldisc)
|
|
|
|
ldisc_echoedit_update(ldisc);
|
|
|
|
break;
|
|
|
|
case IDM_ABOUT:
|
|
|
|
showabout(hwnd);
|
|
|
|
break;
|
|
|
|
case IDM_HELP:
|
|
|
|
launch_help(hwnd, NULL);
|
|
|
|
break;
|
|
|
|
case SC_MOUSEMENU:
|
|
|
|
/*
|
|
|
|
* We get this if the System menu has been activated
|
|
|
|
* using the mouse.
|
|
|
|
*/
|
|
|
|
show_mouseptr(true);
|
|
|
|
break;
|
2001-09-07 21:39:03 +00:00
|
|
|
case SC_KEYMENU:
|
2019-09-08 19:29:00 +00:00
|
|
|
/*
|
|
|
|
* We get this if the System menu has been activated
|
|
|
|
* using the keyboard. This might happen from within
|
|
|
|
* TranslateKey, in which case it really wants to be
|
|
|
|
* followed by a `space' character to actually _bring
|
|
|
|
* the menu up_ rather than just sitting there in
|
|
|
|
* `ready to appear' state.
|
|
|
|
*/
|
|
|
|
show_mouseptr(true); /* make sure pointer is visible */
|
|
|
|
if( lParam == 0 )
|
|
|
|
PostMessage(hwnd, WM_CHAR, ' ', 0);
|
|
|
|
break;
|
|
|
|
case IDM_FULLSCREEN:
|
|
|
|
flip_full_screen();
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
if (wParam >= IDM_SAVED_MIN && wParam < IDM_SAVED_MAX) {
|
|
|
|
SendMessage(hwnd, WM_SYSCOMMAND, IDM_SAVEDSESS, wParam);
|
|
|
|
}
|
|
|
|
if (wParam >= IDM_SPECIAL_MIN && wParam <= IDM_SPECIAL_MAX) {
|
|
|
|
int i = (wParam - IDM_SPECIAL_MIN) / 0x10;
|
|
|
|
/*
|
|
|
|
* Ensure we haven't been sent a bogus SYSCOMMAND
|
|
|
|
* which would cause us to reference invalid memory
|
|
|
|
* and crash. Perhaps I'm just too paranoid here.
|
|
|
|
*/
|
|
|
|
if (i >= n_specials)
|
|
|
|
break;
|
2018-09-11 15:23:38 +00:00
|
|
|
if (backend)
|
Rework special-commands system to add an integer argument.
In order to list cross-certifiable host keys in the GUI specials menu,
the SSH backend has been inventing new values on the end of the
Telnet_Special enumeration, starting from the value TS_LOCALSTART.
This is inelegant, and also makes it awkward to break up special
handlers (e.g. to dispatch different specials to different SSH
layers), since if all you know about a special is that it's somewhere
in the TS_LOCALSTART+n space, you can't tell what _general kind_ of
thing it is. Also, if I ever need another open-ended set of specials
in future, I'll have to remember which TS_LOCALSTART+n codes are in
which set.
So here's a revamp that causes every special to take an extra integer
argument. For all previously numbered specials, this argument is
passed as zero and ignored, but there's a new main special code for
SSH host key cross-certification, in which the integer argument is an
index into the backend's list of available keys. TS_LOCALSTART is now
a thing of the past: if I need any other open-ended sets of specials
in future, I can add a new top-level code with a nicely separated
space of arguments.
While I'm at it, I've removed the legacy misnomer 'Telnet_Special'
from the code completely; the enum is now SessionSpecialCode, the
struct containing full details of a menu entry is SessionSpecial, and
the enum values now start SS_ rather than TS_.
2018-09-24 08:35:52 +00:00
|
|
|
backend_special(
|
|
|
|
backend, specials[i].code, specials[i].arg);
|
2019-09-08 19:29:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
1999-01-08 13:10:19 +00:00
|
|
|
|
|
|
|
#define X_POS(l) ((int)(short)LOWORD(l))
|
|
|
|
#define Y_POS(l) ((int)(short)HIWORD(l))
|
|
|
|
|
2001-09-15 15:54:24 +00:00
|
|
|
#define TO_CHR_X(x) ((((x)<0 ? (x)-font_width+1 : (x))-offset_width) / font_width)
|
|
|
|
#define TO_CHR_Y(y) ((((y)<0 ? (y)-font_height+1: (y))-offset_height) / font_height)
|
1999-01-08 13:02:13 +00:00
|
|
|
case WM_LBUTTONDOWN:
|
|
|
|
case WM_MBUTTONDOWN:
|
|
|
|
case WM_RBUTTONDOWN:
|
2001-05-06 14:20:41 +00:00
|
|
|
case WM_LBUTTONUP:
|
|
|
|
case WM_MBUTTONUP:
|
1999-01-08 13:02:13 +00:00
|
|
|
case WM_RBUTTONUP:
|
2019-09-08 19:29:00 +00:00
|
|
|
if (message == WM_RBUTTONDOWN &&
|
|
|
|
((wParam & MK_CONTROL) ||
|
|
|
|
(conf_get_int(conf, CONF_mouse_is_xterm) == 2))) {
|
|
|
|
POINT cursorpos;
|
|
|
|
|
|
|
|
show_mouseptr(true); /* make sure pointer is visible */
|
|
|
|
GetCursorPos(&cursorpos);
|
|
|
|
TrackPopupMenu(popup_menus[CTXMENU].menu,
|
|
|
|
TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RIGHTBUTTON,
|
|
|
|
cursorpos.x, cursorpos.y,
|
|
|
|
0, hwnd, NULL);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
{
|
|
|
|
int button;
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool press;
|
2001-10-31 18:50:09 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
switch (message) {
|
|
|
|
case WM_LBUTTONDOWN:
|
|
|
|
button = MBT_LEFT;
|
|
|
|
wParam |= MK_LBUTTON;
|
|
|
|
press = true;
|
|
|
|
break;
|
|
|
|
case WM_MBUTTONDOWN:
|
|
|
|
button = MBT_MIDDLE;
|
|
|
|
wParam |= MK_MBUTTON;
|
|
|
|
press = true;
|
|
|
|
break;
|
|
|
|
case WM_RBUTTONDOWN:
|
|
|
|
button = MBT_RIGHT;
|
|
|
|
wParam |= MK_RBUTTON;
|
|
|
|
press = true;
|
|
|
|
break;
|
|
|
|
case WM_LBUTTONUP:
|
|
|
|
button = MBT_LEFT;
|
|
|
|
wParam &= ~MK_LBUTTON;
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
press = false;
|
2019-09-08 19:29:00 +00:00
|
|
|
break;
|
|
|
|
case WM_MBUTTONUP:
|
|
|
|
button = MBT_MIDDLE;
|
|
|
|
wParam &= ~MK_MBUTTON;
|
|
|
|
press = false;
|
|
|
|
break;
|
|
|
|
case WM_RBUTTONUP:
|
|
|
|
button = MBT_RIGHT;
|
|
|
|
wParam &= ~MK_RBUTTON;
|
|
|
|
press = false;
|
|
|
|
break;
|
|
|
|
default: /* shouldn't happen */
|
|
|
|
button = 0;
|
|
|
|
press = false;
|
|
|
|
}
|
|
|
|
show_mouseptr(true);
|
|
|
|
/*
|
|
|
|
* Special case: in full-screen mode, if the left
|
|
|
|
* button is clicked in the very top left corner of the
|
|
|
|
* window, we put up the System menu instead of doing
|
|
|
|
* selection.
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
bool mouse_on_hotspot = false;
|
|
|
|
POINT pt;
|
|
|
|
|
|
|
|
GetCursorPos(&pt);
|
2004-01-20 19:41:43 +00:00
|
|
|
#ifndef NO_MULTIMON
|
2019-09-08 19:29:00 +00:00
|
|
|
{
|
|
|
|
HMONITOR mon;
|
|
|
|
MONITORINFO mi;
|
|
|
|
|
|
|
|
mon = MonitorFromPoint(pt, MONITOR_DEFAULTTONULL);
|
|
|
|
|
|
|
|
if (mon != NULL) {
|
|
|
|
mi.cbSize = sizeof(MONITORINFO);
|
|
|
|
GetMonitorInfo(mon, &mi);
|
|
|
|
|
|
|
|
if (mi.rcMonitor.left == pt.x &&
|
|
|
|
mi.rcMonitor.top == pt.y) {
|
|
|
|
mouse_on_hotspot = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2004-01-20 19:41:43 +00:00
|
|
|
#else
|
2019-09-08 19:29:00 +00:00
|
|
|
if (pt.x == 0 && pt.y == 0) {
|
|
|
|
mouse_on_hotspot = true;
|
|
|
|
}
|
2004-01-20 19:41:43 +00:00
|
|
|
#endif
|
2019-09-08 19:29:00 +00:00
|
|
|
if (is_full_screen() && press &&
|
|
|
|
button == MBT_LEFT && mouse_on_hotspot) {
|
|
|
|
SendMessage(hwnd, WM_SYSCOMMAND, SC_MOUSEMENU,
|
|
|
|
MAKELPARAM(pt.x, pt.y));
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (press) {
|
|
|
|
click(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)),
|
|
|
|
TO_CHR_Y(Y_POS(lParam)), wParam & MK_SHIFT,
|
|
|
|
wParam & MK_CONTROL, is_alt_pressed());
|
|
|
|
if (!(wParam & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON)))
|
|
|
|
ReleaseCapture();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
Formatting change to braces around one case of a switch.
Sometimes, within a switch statement, you want to declare local
variables specific to the handler for one particular case. Until now
I've mostly been writing this in the form
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED:
{
declare variables;
do stuff;
}
break;
}
which is ugly because the two pieces of essentially similar code
appear at different indent levels, and also inconvenient because you
have less horizontal space available to write the complicated case
handler in - particuarly undesirable because _complicated_ case
handlers are the ones most likely to need all the space they can get!
After encountering a rather nicer idiom in the LLVM source code, and
after a bit of hackery this morning figuring out how to persuade
Emacs's auto-indent to do what I wanted with it, I've decided to move
to an idiom in which the open brace comes right after the case
statement, and the code within it is indented the same as it would
have been without the brace. Then the whole case handler (including
the break) lives inside those braces, and you get something that looks
more like this:
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED: {
declare variables;
do stuff;
break;
}
}
This commit is a big-bang change that reformats all the complicated
case handlers I could find into the new layout. This is particularly
nice in the Pageant main function, in which almost _every_ case
handler had a bundle of variables and was long and complicated. (In
fact that's what motivated me to get round to this.) Some of the
innermost parts of the terminal escape-sequence handling are also
breathing a bit easier now the horizontal pressure on them is
relieved.
(Also, in a few cases, I was able to remove the extra braces
completely, because the only variable local to the case handler was a
loop variable which our new C99 policy allows me to move into the
initialiser clause of its for statement.)
Viewed with whitespace ignored, this is not too disruptive a change.
Downstream patches that conflict with it may need to be reapplied
using --ignore-whitespace or similar.
2020-02-16 07:49:52 +00:00
|
|
|
case WM_MOUSEMOVE: {
|
|
|
|
/*
|
|
|
|
* Windows seems to like to occasionally send MOUSEMOVE
|
|
|
|
* events even if the mouse hasn't moved. Don't unhide
|
|
|
|
* the mouse pointer in this case.
|
|
|
|
*/
|
|
|
|
static WPARAM wp = 0;
|
|
|
|
static LPARAM lp = 0;
|
|
|
|
if (wParam != wp || lParam != lp ||
|
|
|
|
last_mousemove != WM_MOUSEMOVE) {
|
|
|
|
show_mouseptr(true);
|
|
|
|
wp = wParam; lp = lParam;
|
|
|
|
last_mousemove = WM_MOUSEMOVE;
|
2019-09-08 19:29:00 +00:00
|
|
|
}
|
|
|
|
/*
|
|
|
|
* Add the mouse position and message time to the random
|
|
|
|
* number noise.
|
|
|
|
*/
|
|
|
|
noise_ultralight(NOISE_SOURCE_MOUSEPOS, lParam);
|
|
|
|
|
|
|
|
if (wParam & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON) &&
|
|
|
|
GetCapture() == hwnd) {
|
|
|
|
Mouse_Button b;
|
|
|
|
if (wParam & MK_LBUTTON)
|
|
|
|
b = MBT_LEFT;
|
|
|
|
else if (wParam & MK_MBUTTON)
|
|
|
|
b = MBT_MIDDLE;
|
|
|
|
else
|
|
|
|
b = MBT_RIGHT;
|
|
|
|
term_mouse(term, b, translate_button(b), MA_DRAG,
|
|
|
|
TO_CHR_X(X_POS(lParam)),
|
|
|
|
TO_CHR_Y(Y_POS(lParam)), wParam & MK_SHIFT,
|
|
|
|
wParam & MK_CONTROL, is_alt_pressed());
|
|
|
|
}
|
|
|
|
return 0;
|
Formatting change to braces around one case of a switch.
Sometimes, within a switch statement, you want to declare local
variables specific to the handler for one particular case. Until now
I've mostly been writing this in the form
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED:
{
declare variables;
do stuff;
}
break;
}
which is ugly because the two pieces of essentially similar code
appear at different indent levels, and also inconvenient because you
have less horizontal space available to write the complicated case
handler in - particuarly undesirable because _complicated_ case
handlers are the ones most likely to need all the space they can get!
After encountering a rather nicer idiom in the LLVM source code, and
after a bit of hackery this morning figuring out how to persuade
Emacs's auto-indent to do what I wanted with it, I've decided to move
to an idiom in which the open brace comes right after the case
statement, and the code within it is indented the same as it would
have been without the brace. Then the whole case handler (including
the break) lives inside those braces, and you get something that looks
more like this:
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED: {
declare variables;
do stuff;
break;
}
}
This commit is a big-bang change that reformats all the complicated
case handlers I could find into the new layout. This is particularly
nice in the Pageant main function, in which almost _every_ case
handler had a bundle of variables and was long and complicated. (In
fact that's what motivated me to get round to this.) Some of the
innermost parts of the terminal escape-sequence handling are also
breathing a bit easier now the horizontal pressure on them is
relieved.
(Also, in a few cases, I was able to remove the extra braces
completely, because the only variable local to the case handler was a
loop variable which our new C99 policy allows me to move into the
initialiser clause of its for statement.)
Viewed with whitespace ignored, this is not too disruptive a change.
Downstream patches that conflict with it may need to be reapplied
using --ignore-whitespace or similar.
2020-02-16 07:49:52 +00:00
|
|
|
}
|
|
|
|
case WM_NCMOUSEMOVE: {
|
|
|
|
static WPARAM wp = 0;
|
|
|
|
static LPARAM lp = 0;
|
|
|
|
if (wParam != wp || lParam != lp ||
|
|
|
|
last_mousemove != WM_NCMOUSEMOVE) {
|
|
|
|
show_mouseptr(true);
|
|
|
|
wp = wParam; lp = lParam;
|
|
|
|
last_mousemove = WM_NCMOUSEMOVE;
|
2019-09-08 19:29:00 +00:00
|
|
|
}
|
|
|
|
noise_ultralight(NOISE_SOURCE_MOUSEPOS, lParam);
|
|
|
|
break;
|
Formatting change to braces around one case of a switch.
Sometimes, within a switch statement, you want to declare local
variables specific to the handler for one particular case. Until now
I've mostly been writing this in the form
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED:
{
declare variables;
do stuff;
}
break;
}
which is ugly because the two pieces of essentially similar code
appear at different indent levels, and also inconvenient because you
have less horizontal space available to write the complicated case
handler in - particuarly undesirable because _complicated_ case
handlers are the ones most likely to need all the space they can get!
After encountering a rather nicer idiom in the LLVM source code, and
after a bit of hackery this morning figuring out how to persuade
Emacs's auto-indent to do what I wanted with it, I've decided to move
to an idiom in which the open brace comes right after the case
statement, and the code within it is indented the same as it would
have been without the brace. Then the whole case handler (including
the break) lives inside those braces, and you get something that looks
more like this:
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED: {
declare variables;
do stuff;
break;
}
}
This commit is a big-bang change that reformats all the complicated
case handlers I could find into the new layout. This is particularly
nice in the Pageant main function, in which almost _every_ case
handler had a bundle of variables and was long and complicated. (In
fact that's what motivated me to get round to this.) Some of the
innermost parts of the terminal escape-sequence handling are also
breathing a bit easier now the horizontal pressure on them is
relieved.
(Also, in a few cases, I was able to remove the extra braces
completely, because the only variable local to the case handler was a
loop variable which our new C99 policy allows me to move into the
initialiser clause of its for statement.)
Viewed with whitespace ignored, this is not too disruptive a change.
Downstream patches that conflict with it may need to be reapplied
using --ignore-whitespace or similar.
2020-02-16 07:49:52 +00:00
|
|
|
}
|
1999-01-08 13:02:13 +00:00
|
|
|
case WM_IGNORE_CLIP:
|
2019-09-08 19:29:00 +00:00
|
|
|
ignore_clip = wParam; /* don't panic on DESTROYCLIPBOARD */
|
|
|
|
break;
|
1999-01-08 13:02:13 +00:00
|
|
|
case WM_DESTROYCLIPBOARD:
|
2019-09-08 19:29:00 +00:00
|
|
|
if (!ignore_clip)
|
|
|
|
term_lost_clipboard_ownership(term, CLIP_SYSTEM);
|
|
|
|
ignore_clip = false;
|
|
|
|
return 0;
|
Formatting change to braces around one case of a switch.
Sometimes, within a switch statement, you want to declare local
variables specific to the handler for one particular case. Until now
I've mostly been writing this in the form
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED:
{
declare variables;
do stuff;
}
break;
}
which is ugly because the two pieces of essentially similar code
appear at different indent levels, and also inconvenient because you
have less horizontal space available to write the complicated case
handler in - particuarly undesirable because _complicated_ case
handlers are the ones most likely to need all the space they can get!
After encountering a rather nicer idiom in the LLVM source code, and
after a bit of hackery this morning figuring out how to persuade
Emacs's auto-indent to do what I wanted with it, I've decided to move
to an idiom in which the open brace comes right after the case
statement, and the code within it is indented the same as it would
have been without the brace. Then the whole case handler (including
the break) lives inside those braces, and you get something that looks
more like this:
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED: {
declare variables;
do stuff;
break;
}
}
This commit is a big-bang change that reformats all the complicated
case handlers I could find into the new layout. This is particularly
nice in the Pageant main function, in which almost _every_ case
handler had a bundle of variables and was long and complicated. (In
fact that's what motivated me to get round to this.) Some of the
innermost parts of the terminal escape-sequence handling are also
breathing a bit easier now the horizontal pressure on them is
relieved.
(Also, in a few cases, I was able to remove the extra braces
completely, because the only variable local to the case handler was a
loop variable which our new C99 policy allows me to move into the
initialiser clause of its for statement.)
Viewed with whitespace ignored, this is not too disruptive a change.
Downstream patches that conflict with it may need to be reapplied
using --ignore-whitespace or similar.
2020-02-16 07:49:52 +00:00
|
|
|
case WM_PAINT: {
|
|
|
|
PAINTSTRUCT p;
|
|
|
|
|
|
|
|
HideCaret(hwnd);
|
|
|
|
hdc = BeginPaint(hwnd, &p);
|
|
|
|
if (pal) {
|
|
|
|
SelectPalette(hdc, pal, true);
|
|
|
|
RealizePalette(hdc);
|
2019-09-08 19:29:00 +00:00
|
|
|
}
|
Formatting change to braces around one case of a switch.
Sometimes, within a switch statement, you want to declare local
variables specific to the handler for one particular case. Until now
I've mostly been writing this in the form
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED:
{
declare variables;
do stuff;
}
break;
}
which is ugly because the two pieces of essentially similar code
appear at different indent levels, and also inconvenient because you
have less horizontal space available to write the complicated case
handler in - particuarly undesirable because _complicated_ case
handlers are the ones most likely to need all the space they can get!
After encountering a rather nicer idiom in the LLVM source code, and
after a bit of hackery this morning figuring out how to persuade
Emacs's auto-indent to do what I wanted with it, I've decided to move
to an idiom in which the open brace comes right after the case
statement, and the code within it is indented the same as it would
have been without the brace. Then the whole case handler (including
the break) lives inside those braces, and you get something that looks
more like this:
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED: {
declare variables;
do stuff;
break;
}
}
This commit is a big-bang change that reformats all the complicated
case handlers I could find into the new layout. This is particularly
nice in the Pageant main function, in which almost _every_ case
handler had a bundle of variables and was long and complicated. (In
fact that's what motivated me to get round to this.) Some of the
innermost parts of the terminal escape-sequence handling are also
breathing a bit easier now the horizontal pressure on them is
relieved.
(Also, in a few cases, I was able to remove the extra braces
completely, because the only variable local to the case handler was a
loop variable which our new C99 policy allows me to move into the
initialiser clause of its for statement.)
Viewed with whitespace ignored, this is not too disruptive a change.
Downstream patches that conflict with it may need to be reapplied
using --ignore-whitespace or similar.
2020-02-16 07:49:52 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* We have to be careful about term_paint(). It will
|
|
|
|
* set a bunch of character cells to INVALID and then
|
|
|
|
* call do_paint(), which will redraw those cells and
|
|
|
|
* _then mark them as done_. This may not be accurate:
|
|
|
|
* when painting in WM_PAINT context we are restricted
|
|
|
|
* to the rectangle which has just been exposed - so if
|
|
|
|
* that only covers _part_ of a character cell and the
|
|
|
|
* rest of it was already visible, that remainder will
|
|
|
|
* not be redrawn at all. Accordingly, we must not
|
|
|
|
* paint any character cell in a WM_PAINT context which
|
|
|
|
* already has a pending update due to terminal output.
|
|
|
|
* The simplest solution to this - and many, many
|
|
|
|
* thanks to Hung-Te Lin for working all this out - is
|
|
|
|
* not to do any actual painting at _all_ if there's a
|
|
|
|
* pending terminal update: just mark the relevant
|
|
|
|
* character cells as INVALID and wait for the
|
|
|
|
* scheduled full update to sort it out.
|
|
|
|
*
|
|
|
|
* I have a suspicion this isn't the _right_ solution.
|
|
|
|
* An alternative approach would be to have terminal.c
|
|
|
|
* separately track what _should_ be on the terminal
|
|
|
|
* screen and what _is_ on the terminal screen, and
|
|
|
|
* have two completely different types of redraw (one
|
|
|
|
* for full updates, which syncs the former with the
|
|
|
|
* terminal itself, and one for WM_PAINT which syncs
|
|
|
|
* the latter with the former); yet another possibility
|
|
|
|
* would be to have the Windows front end do what the
|
|
|
|
* GTK one already does, and maintain a bitmap of the
|
|
|
|
* current terminal appearance so that WM_PAINT becomes
|
|
|
|
* completely trivial. However, this should do for now.
|
|
|
|
*/
|
|
|
|
assert(!wintw_hdc);
|
|
|
|
wintw_hdc = hdc;
|
|
|
|
term_paint(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;
|
|
|
|
|
|
|
|
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)
|
2013-08-17 16:06:35 +00:00
|
|
|
{
|
Formatting change to braces around one case of a switch.
Sometimes, within a switch statement, you want to declare local
variables specific to the handler for one particular case. Until now
I've mostly been writing this in the form
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED:
{
declare variables;
do stuff;
}
break;
}
which is ugly because the two pieces of essentially similar code
appear at different indent levels, and also inconvenient because you
have less horizontal space available to write the complicated case
handler in - particuarly undesirable because _complicated_ case
handlers are the ones most likely to need all the space they can get!
After encountering a rather nicer idiom in the LLVM source code, and
after a bit of hackery this morning figuring out how to persuade
Emacs's auto-indent to do what I wanted with it, I've decided to move
to an idiom in which the open brace comes right after the case
statement, and the code within it is indented the same as it would
have been without the brace. Then the whole case handler (including
the break) lives inside those braces, and you get something that looks
more like this:
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED: {
declare variables;
do stuff;
break;
}
}
This commit is a big-bang change that reformats all the complicated
case handlers I could find into the new layout. This is particularly
nice in the Pageant main function, in which almost _every_ case
handler had a bundle of variables and was long and complicated. (In
fact that's what motivated me to get round to this.) Some of the
innermost parts of the terminal escape-sequence handling are also
breathing a bit easier now the horizontal pressure on them is
relieved.
(Also, in a few cases, I was able to remove the extra braces
completely, because the only variable local to the case handler was a
loop variable which our new C99 policy allows me to move into the
initialiser clause of its for statement.)
Viewed with whitespace ignored, this is not too disruptive a change.
Downstream patches that conflict with it may need to be reapplied
using --ignore-whitespace or similar.
2020-02-16 07:49:52 +00:00
|
|
|
HBRUSH fillcolour, oldbrush;
|
|
|
|
HPEN edge, oldpen;
|
|
|
|
fillcolour = CreateSolidBrush (
|
|
|
|
colours[ATTR_DEFBG>>ATTR_BGSHIFT]);
|
|
|
|
oldbrush = SelectObject(hdc, fillcolour);
|
|
|
|
edge = CreatePen(PS_SOLID, 0,
|
|
|
|
colours[ATTR_DEFBG>>ATTR_BGSHIFT]);
|
|
|
|
oldpen = SelectObject(hdc, edge);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Jordan Russell reports that this apparently
|
|
|
|
* ineffectual IntersectClipRect() call masks a
|
|
|
|
* Windows NT/2K bug causing strange display
|
|
|
|
* problems when the PuTTY window is taller than
|
|
|
|
* the primary monitor. It seems harmless enough...
|
|
|
|
*/
|
|
|
|
IntersectClipRect(hdc,
|
|
|
|
p.rcPaint.left, p.rcPaint.top,
|
|
|
|
p.rcPaint.right, p.rcPaint.bottom);
|
|
|
|
|
|
|
|
ExcludeClipRect(hdc,
|
|
|
|
offset_width, offset_height,
|
|
|
|
offset_width+font_width*term->cols,
|
|
|
|
offset_height+font_height*term->rows);
|
|
|
|
|
|
|
|
Rectangle(hdc, p.rcPaint.left, p.rcPaint.top,
|
|
|
|
p.rcPaint.right, p.rcPaint.bottom);
|
|
|
|
|
|
|
|
/* SelectClipRgn(hdc, NULL); */
|
|
|
|
|
|
|
|
SelectObject(hdc, oldbrush);
|
|
|
|
DeleteObject(fillcolour);
|
|
|
|
SelectObject(hdc, oldpen);
|
|
|
|
DeleteObject(edge);
|
2013-08-17 16:06:35 +00:00
|
|
|
}
|
Formatting change to braces around one case of a switch.
Sometimes, within a switch statement, you want to declare local
variables specific to the handler for one particular case. Until now
I've mostly been writing this in the form
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED:
{
declare variables;
do stuff;
}
break;
}
which is ugly because the two pieces of essentially similar code
appear at different indent levels, and also inconvenient because you
have less horizontal space available to write the complicated case
handler in - particuarly undesirable because _complicated_ case
handlers are the ones most likely to need all the space they can get!
After encountering a rather nicer idiom in the LLVM source code, and
after a bit of hackery this morning figuring out how to persuade
Emacs's auto-indent to do what I wanted with it, I've decided to move
to an idiom in which the open brace comes right after the case
statement, and the code within it is indented the same as it would
have been without the brace. Then the whole case handler (including
the break) lives inside those braces, and you get something that looks
more like this:
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED: {
declare variables;
do stuff;
break;
}
}
This commit is a big-bang change that reformats all the complicated
case handlers I could find into the new layout. This is particularly
nice in the Pageant main function, in which almost _every_ case
handler had a bundle of variables and was long and complicated. (In
fact that's what motivated me to get round to this.) Some of the
innermost parts of the terminal escape-sequence handling are also
breathing a bit easier now the horizontal pressure on them is
relieved.
(Also, in a few cases, I was able to remove the extra braces
completely, because the only variable local to the case handler was a
loop variable which our new C99 policy allows me to move into the
initialiser clause of its for statement.)
Viewed with whitespace ignored, this is not too disruptive a change.
Downstream patches that conflict with it may need to be reapplied
using --ignore-whitespace or similar.
2020-02-16 07:49:52 +00:00
|
|
|
SelectObject(hdc, GetStockObject(SYSTEM_FONT));
|
|
|
|
SelectObject(hdc, GetStockObject(WHITE_PEN));
|
|
|
|
EndPaint(hwnd, &p);
|
|
|
|
ShowCaret(hwnd);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
case WM_NETEVENT: {
|
|
|
|
/*
|
|
|
|
* To protect against re-entrancy when Windows's recv()
|
|
|
|
* immediately triggers a new WSAAsyncSelect window
|
|
|
|
* message, we don't call select_result directly from this
|
|
|
|
* handler but instead wait until we're back out at the
|
|
|
|
* top level of the message loop.
|
|
|
|
*/
|
|
|
|
struct wm_netevent_params *params =
|
|
|
|
snew(struct wm_netevent_params);
|
|
|
|
params->wParam = wParam;
|
|
|
|
params->lParam = lParam;
|
|
|
|
queue_toplevel_callback(wm_netevent_callback, params);
|
2019-09-08 19:29:00 +00:00
|
|
|
return 0;
|
Formatting change to braces around one case of a switch.
Sometimes, within a switch statement, you want to declare local
variables specific to the handler for one particular case. Until now
I've mostly been writing this in the form
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED:
{
declare variables;
do stuff;
}
break;
}
which is ugly because the two pieces of essentially similar code
appear at different indent levels, and also inconvenient because you
have less horizontal space available to write the complicated case
handler in - particuarly undesirable because _complicated_ case
handlers are the ones most likely to need all the space they can get!
After encountering a rather nicer idiom in the LLVM source code, and
after a bit of hackery this morning figuring out how to persuade
Emacs's auto-indent to do what I wanted with it, I've decided to move
to an idiom in which the open brace comes right after the case
statement, and the code within it is indented the same as it would
have been without the brace. Then the whole case handler (including
the break) lives inside those braces, and you get something that looks
more like this:
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED: {
declare variables;
do stuff;
break;
}
}
This commit is a big-bang change that reformats all the complicated
case handlers I could find into the new layout. This is particularly
nice in the Pageant main function, in which almost _every_ case
handler had a bundle of variables and was long and complicated. (In
fact that's what motivated me to get round to this.) Some of the
innermost parts of the terminal escape-sequence handling are also
breathing a bit easier now the horizontal pressure on them is
relieved.
(Also, in a few cases, I was able to remove the extra braces
completely, because the only variable local to the case handler was a
loop variable which our new C99 policy allows me to move into the
initialiser clause of its for statement.)
Viewed with whitespace ignored, this is not too disruptive a change.
Downstream patches that conflict with it may need to be reapplied
using --ignore-whitespace or similar.
2020-02-16 07:49:52 +00:00
|
|
|
}
|
1999-01-08 13:02:13 +00:00
|
|
|
case WM_SETFOCUS:
|
2019-09-08 19:29:00 +00:00
|
|
|
term_set_focus(term, true);
|
|
|
|
CreateCaret(hwnd, caretbm, font_width, font_height);
|
|
|
|
ShowCaret(hwnd);
|
|
|
|
flash_window(0); /* stop */
|
|
|
|
compose_state = 0;
|
|
|
|
term_update(term);
|
|
|
|
break;
|
1999-01-08 13:02:13 +00:00
|
|
|
case WM_KILLFOCUS:
|
2019-09-08 19:29:00 +00:00
|
|
|
show_mouseptr(true);
|
|
|
|
term_set_focus(term, false);
|
|
|
|
DestroyCaret();
|
|
|
|
caret_x = caret_y = -1; /* ensure caret is replaced next time */
|
|
|
|
term_update(term);
|
|
|
|
break;
|
1999-11-03 14:08:26 +00:00
|
|
|
case WM_ENTERSIZEMOVE:
|
2001-09-15 15:54:24 +00:00
|
|
|
#ifdef RDB_DEBUG_PATCH
|
2019-09-08 19:29:00 +00:00
|
|
|
debug("WM_ENTERSIZEMOVE\n");
|
2001-09-15 15:54:24 +00:00
|
|
|
#endif
|
2019-09-08 19:29:00 +00:00
|
|
|
EnableSizeTip(true);
|
|
|
|
resizing = true;
|
|
|
|
need_backend_resize = false;
|
|
|
|
break;
|
1999-11-03 14:08:26 +00:00
|
|
|
case WM_EXITSIZEMOVE:
|
2019-09-08 19:29:00 +00:00
|
|
|
EnableSizeTip(false);
|
|
|
|
resizing = false;
|
2001-09-15 15:54:24 +00:00
|
|
|
#ifdef RDB_DEBUG_PATCH
|
2019-09-08 19:29:00 +00:00
|
|
|
debug("WM_EXITSIZEMOVE\n");
|
2001-09-15 15:54:24 +00:00
|
|
|
#endif
|
2019-09-08 19:29:00 +00:00
|
|
|
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));
|
|
|
|
InvalidateRect(hwnd, NULL, true);
|
|
|
|
}
|
2021-02-15 19:47:50 +00:00
|
|
|
recompute_window_offset();
|
2019-09-08 19:29:00 +00:00
|
|
|
break;
|
1999-01-08 13:02:13 +00:00
|
|
|
case WM_SIZING:
|
2019-09-08 19:29:00 +00:00
|
|
|
/*
|
|
|
|
* This does two jobs:
|
|
|
|
* 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);
|
|
|
|
if (resize_action == RESIZE_TERM ||
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
(resize_action == RESIZE_EITHER && !is_alt_pressed())) {
|
2019-09-08 19:29:00 +00:00
|
|
|
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)) {
|
|
|
|
/*
|
|
|
|
* Great! It seems that both the terminal size and the
|
|
|
|
* font size have been changed and the user is now dragging.
|
|
|
|
*
|
|
|
|
* It will now be difficult to get back to the configured
|
|
|
|
* font size!
|
|
|
|
*
|
|
|
|
* 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);
|
|
|
|
|
|
|
|
InvalidateRect(hwnd, NULL, true);
|
|
|
|
need_backend_resize = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
width = r->right - r->left - extra_width;
|
|
|
|
height = r->bottom - r->top - extra_height;
|
|
|
|
w = (width + font_width / 2) / font_width;
|
|
|
|
if (w < 1)
|
|
|
|
w = 1;
|
|
|
|
h = (height + font_height / 2) / font_height;
|
|
|
|
if (h < 1)
|
|
|
|
h = 1;
|
|
|
|
UpdateSizeTip(hwnd, w, h);
|
|
|
|
ew = width - w * font_width;
|
|
|
|
eh = height - h * font_height;
|
|
|
|
if (ew != 0) {
|
|
|
|
if (wParam == WMSZ_LEFT ||
|
|
|
|
wParam == WMSZ_BOTTOMLEFT || wParam == WMSZ_TOPLEFT)
|
|
|
|
r->left += ew;
|
|
|
|
else
|
|
|
|
r->right -= ew;
|
|
|
|
}
|
|
|
|
if (eh != 0) {
|
|
|
|
if (wParam == WMSZ_TOP ||
|
|
|
|
wParam == WMSZ_TOPRIGHT || wParam == WMSZ_TOPLEFT)
|
|
|
|
r->top += eh;
|
|
|
|
else
|
|
|
|
r->bottom -= eh;
|
|
|
|
}
|
|
|
|
if (ew || eh)
|
|
|
|
return 1;
|
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
} else {
|
|
|
|
int width, height, w, h, rv = 0;
|
|
|
|
int window_border = conf_get_int(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;
|
|
|
|
|
|
|
|
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)
|
|
|
|
rv = 1;
|
|
|
|
|
|
|
|
if (wParam == WMSZ_LEFT ||
|
|
|
|
wParam == WMSZ_BOTTOMLEFT || wParam == WMSZ_TOPLEFT)
|
|
|
|
r->left = r->right - w*term->cols - ex_width;
|
|
|
|
else
|
|
|
|
r->right = r->left + w*term->cols + ex_width;
|
|
|
|
|
|
|
|
if (r->bottom != r->top + h*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;
|
|
|
|
else
|
|
|
|
r->bottom = r->top + h*term->rows + ex_height;
|
|
|
|
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
/* break; (never reached) */
|
2001-12-07 21:21:03 +00:00
|
|
|
case WM_FULLSCR_ON_MAX:
|
2019-09-08 19:29:00 +00:00
|
|
|
fullscr_on_max = true;
|
|
|
|
break;
|
2001-12-20 14:18:01 +00:00
|
|
|
case WM_MOVE:
|
2021-02-07 19:59:21 +00:00
|
|
|
term_notify_window_pos(term, LOWORD(lParam), HIWORD(lParam));
|
2019-09-08 19:29:00 +00:00
|
|
|
sys_cursor_update();
|
|
|
|
break;
|
1999-01-08 13:02:13 +00:00
|
|
|
case WM_SIZE:
|
2019-09-08 19:29:00 +00:00
|
|
|
resize_action = conf_get_int(conf, CONF_resize_action);
|
2001-09-15 15:54:24 +00:00
|
|
|
#ifdef RDB_DEBUG_PATCH
|
2019-09-08 19:29:00 +00:00
|
|
|
debug("WM_SIZE %s (%d,%d)\n",
|
Start using C99 variadic macros.
In the past, I've had a lot of macros which you call with double
parentheses, along the lines of debug(("format string", params)), so
that the inner parens protect the commas and permit the macro to treat
the whole printf-style argument list as one macro argument.
That's all very well, but it's a bit inconvenient (it doesn't leave
you any way to implement such a macro by prepending another argument
to the list), and now this code base's rules allow C99isms, I can
switch all those macros to using a single pair of parens, using the
C99 ability to say '...' in the parameter list of the #define and get
at the corresponding suffix of the arguments as __VA_ARGS__.
So I'm doing it. I've made the following printf-style macros variadic:
bpp_logevent, ppl_logevent, ppl_printf and debug.
While I'm here, I've also fixed up a collection of conditioned-out
calls to debug() in the Windows front end which were clearly expecting
a macro with a different calling syntax, because they had an integer
parameter first. If I ever have a need to condition those back in,
they should actually work now.
2018-12-08 20:32:31 +00:00
|
|
|
(wParam == SIZE_MINIMIZED) ? "SIZE_MINIMIZED":
|
|
|
|
(wParam == SIZE_MAXIMIZED) ? "SIZE_MAXIMIZED":
|
|
|
|
(wParam == SIZE_RESTORED && resizing) ? "to":
|
|
|
|
(wParam == SIZE_RESTORED) ? "SIZE_RESTORED":
|
|
|
|
"...",
|
|
|
|
LOWORD(lParam), HIWORD(lParam));
|
2001-09-15 15:54:24 +00:00
|
|
|
#endif
|
2021-02-07 19:59:20 +00:00
|
|
|
term_notify_minimised(term, wParam == SIZE_MINIMIZED);
|
2021-02-07 19:59:21 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* WM_SIZE's lParam tells us the size of the client area.
|
|
|
|
* But historic PuTTY practice is that we want to tell the
|
|
|
|
* terminal the size of the overall window.
|
|
|
|
*/
|
|
|
|
RECT r;
|
|
|
|
GetWindowRect(hwnd, &r);
|
|
|
|
term_notify_window_size_pixels(
|
|
|
|
term, r.right - r.left, r.bottom - r.top);
|
|
|
|
}
|
2019-09-08 19:29:00 +00:00
|
|
|
if (wParam == SIZE_MINIMIZED)
|
|
|
|
SetWindowText(hwnd,
|
|
|
|
conf_get_bool(conf, CONF_win_name_always) ?
|
|
|
|
window_name : icon_name);
|
|
|
|
if (wParam == SIZE_RESTORED || wParam == SIZE_MAXIMIZED)
|
|
|
|
SetWindowText(hwnd, window_name);
|
2010-12-27 12:58:39 +00:00
|
|
|
if (wParam == SIZE_RESTORED) {
|
2018-10-29 19:50:29 +00:00
|
|
|
processed_resize = false;
|
2001-12-11 18:47:55 +00:00
|
|
|
clear_full_screen();
|
2010-12-27 12:58:39 +00:00
|
|
|
if (processed_resize) {
|
|
|
|
/*
|
|
|
|
* Inhibit normal processing of this WM_SIZE; a
|
|
|
|
* secondary one was triggered just now by
|
|
|
|
* clear_full_screen which contained the correct
|
|
|
|
* client area size.
|
|
|
|
*/
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
2001-12-11 18:47:55 +00:00
|
|
|
if (wParam == SIZE_MAXIMIZED && fullscr_on_max) {
|
2018-10-29 19:50:29 +00:00
|
|
|
fullscr_on_max = false;
|
|
|
|
processed_resize = false;
|
2002-03-13 22:15:14 +00:00
|
|
|
make_full_screen();
|
2010-12-27 12:58:39 +00:00
|
|
|
if (processed_resize) {
|
|
|
|
/*
|
|
|
|
* Inhibit normal processing of this WM_SIZE; a
|
|
|
|
* secondary one was triggered just now by
|
|
|
|
* make_full_screen which contained the correct client
|
|
|
|
* area size.
|
|
|
|
*/
|
|
|
|
return 0;
|
|
|
|
}
|
2001-12-11 18:47:55 +00:00
|
|
|
}
|
2001-09-15 15:54:24 +00:00
|
|
|
|
2018-10-29 19:50:29 +00:00
|
|
|
processed_resize = true;
|
2010-12-27 12:58:39 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
if (resize_action == RESIZE_DISABLED) {
|
|
|
|
/* A resize, well it better be a minimize. */
|
|
|
|
reset_window(-1);
|
|
|
|
} else {
|
Windows: fix resizing of a maximised window.
The RESIZE_EITHER resizing mode responds to a window resize by
changing the logical terminal size if the window is shown normally, or
by changing the font size to keep the terminal size the same if the
resize is a transition between normal and maximised state.
But a user pointed out that it's also possible for a window to receive
a WM_SIZE message while _remaining_ in maximised state, and that
PuTTY's resize logic didn't allow for that possibility. It occurs when
there's a change in the amount of available screen space for the
window to be maximised _in_: e.g. when the video resolution is
reconfigured, or when you reconnect to a Remote Desktop session using
a client window of a different size, or even when you toggle the
'Automatically hide the taskbar' option in the Windows taskbar settings.
In that situation, the right thing seems to be for PuTTY to continue
to go with the policy of changing the font size rather than the
logical terminal size. In other words, we prefer to change the font
size when the resize is _from_ maximised state, _to_ maximised state,
_or both_.
That's easily implemented by removing the check of the 'was_zoomed'
flag, in the case where we've received a WM_SIZE message with the
state SIZE_MAXIMIZED: once we know the transition is _to_ maximised
state, it doesn't matter whether or not it was also _from_ it. (But we
still set the was_zoomed flag to the most recent maximised status, so
that we can recognise transitions _out_ of maximised mode.)
2019-09-08 12:40:14 +00:00
|
|
|
if (wParam == SIZE_MAXIMIZED) {
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
was_zoomed = true;
|
2010-12-22 15:49:33 +00:00
|
|
|
prev_rows = term->rows;
|
|
|
|
prev_cols = term->cols;
|
Windows: make the need_backend_resize mechanism consistent.
There were three separate clauses in the WM_SIZE message handler which
potentially called term_size() to resize the actual Terminal object.
Two of them (for maximisation and normal non-maximised resizing drags)
first checked if an interactive resize was in progress, and if so,
instead set the need_backend_resize, to defer the term_size call to
the end of the interactive operation. But the third, for
_un_-maximising a window, didn't have that check.
As a result, if you start with a maximised window, drag its title bar
downward from the top of the screen (which unmaximises it), and
without letting go, drag it back up again (which maximises it), the
effect would be that you'd get one call to term_size in the middle of
the drag, and a second at the end. This isn't what I intended, and it
can also cause a redraw failure in full-screen applications on the
server (such as a terminal-based text editor - I reproduced this with
emacs), in which after the second term_size the terminal doesn't
manage to redraw itself.
Now I've pulled out the common logic that was in two of those three
pieces of code (and should have been in all three) into a subroutine
wm_size_resize_term, and arranged to call that in all three cases.
This fixes the inconsistency, and also fixes the emacs redraw problem
in the edge case I describe above.
2021-02-07 19:59:21 +00:00
|
|
|
if (resize_action == RESIZE_TERM)
|
|
|
|
wm_size_resize_term(lParam, false);
|
2010-12-22 15:49:33 +00:00
|
|
|
reset_window(0);
|
|
|
|
} else if (wParam == SIZE_RESTORED && was_zoomed) {
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
was_zoomed = false;
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
if (resize_action == RESIZE_TERM) {
|
Windows: make the need_backend_resize mechanism consistent.
There were three separate clauses in the WM_SIZE message handler which
potentially called term_size() to resize the actual Terminal object.
Two of them (for maximisation and normal non-maximised resizing drags)
first checked if an interactive resize was in progress, and if so,
instead set the need_backend_resize, to defer the term_size call to
the end of the interactive operation. But the third, for
_un_-maximising a window, didn't have that check.
As a result, if you start with a maximised window, drag its title bar
downward from the top of the screen (which unmaximises it), and
without letting go, drag it back up again (which maximises it), the
effect would be that you'd get one call to term_size in the middle of
the drag, and a second at the end. This isn't what I intended, and it
can also cause a redraw failure in full-screen applications on the
server (such as a terminal-based text editor - I reproduced this with
emacs), in which after the second term_size the terminal doesn't
manage to redraw itself.
Now I've pulled out the common logic that was in two of those three
pieces of code (and should have been in all three) into a subroutine
wm_size_resize_term, and arranged to call that in all three cases.
This fixes the inconsistency, and also fixes the emacs redraw problem
in the edge case I describe above.
2021-02-07 19:59:21 +00:00
|
|
|
wm_size_resize_term(lParam, true);
|
2010-12-23 15:44:20 +00:00
|
|
|
reset_window(2);
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
} else if (resize_action != RESIZE_FONT)
|
2010-12-22 15:49:33 +00:00
|
|
|
reset_window(2);
|
|
|
|
else
|
|
|
|
reset_window(0);
|
|
|
|
} else if (wParam == SIZE_MINIMIZED) {
|
|
|
|
/* do nothing */
|
2019-09-08 19:29:00 +00:00
|
|
|
} else if (resize_action == RESIZE_TERM ||
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
(resize_action == RESIZE_EITHER &&
|
2010-12-23 17:16:19 +00:00
|
|
|
!is_alt_pressed())) {
|
Windows: make the need_backend_resize mechanism consistent.
There were three separate clauses in the WM_SIZE message handler which
potentially called term_size() to resize the actual Terminal object.
Two of them (for maximisation and normal non-maximised resizing drags)
first checked if an interactive resize was in progress, and if so,
instead set the need_backend_resize, to defer the term_size call to
the end of the interactive operation. But the third, for
_un_-maximising a window, didn't have that check.
As a result, if you start with a maximised window, drag its title bar
downward from the top of the screen (which unmaximises it), and
without letting go, drag it back up again (which maximises it), the
effect would be that you'd get one call to term_size in the middle of
the drag, and a second at the end. This isn't what I intended, and it
can also cause a redraw failure in full-screen applications on the
server (such as a terminal-based text editor - I reproduced this with
emacs), in which after the second term_size the terminal doesn't
manage to redraw itself.
Now I've pulled out the common logic that was in two of those three
pieces of code (and should have been in all three) into a subroutine
wm_size_resize_term, and arranged to call that in all three cases.
This fixes the inconsistency, and also fixes the emacs redraw problem
in the edge case I describe above.
2021-02-07 19:59:21 +00:00
|
|
|
wm_size_resize_term(lParam, true);
|
2021-02-12 17:50:47 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Sometimes, we can get a spontaneous resize event
|
|
|
|
* outside a WM_SIZING interactive drag which wants to
|
|
|
|
* set us to a new specific SIZE_RESTORED size. An
|
|
|
|
* example is what happens if you press Windows+Right
|
|
|
|
* and then Windows+Up: the first operation fits the
|
|
|
|
* window to the right-hand half of the screen, and
|
|
|
|
* the second one changes that for the top right
|
|
|
|
* quadrant. In that situation, if we've responded
|
|
|
|
* here by resizing the terminal, we may still need to
|
|
|
|
* recompute the border around the window and do a
|
|
|
|
* full redraw to clear the new border.
|
|
|
|
*/
|
|
|
|
if (!resizing)
|
|
|
|
recompute_window_offset();
|
2010-12-22 15:49:33 +00:00
|
|
|
} else {
|
|
|
|
reset_window(0);
|
2019-09-08 19:29:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
sys_cursor_update();
|
|
|
|
return 0;
|
1999-01-08 13:02:13 +00:00
|
|
|
case WM_VSCROLL:
|
2019-09-08 19:29:00 +00:00
|
|
|
switch (LOWORD(wParam)) {
|
|
|
|
case SB_BOTTOM:
|
|
|
|
term_scroll(term, -1, 0);
|
|
|
|
break;
|
|
|
|
case SB_TOP:
|
|
|
|
term_scroll(term, +1, 0);
|
|
|
|
break;
|
|
|
|
case SB_LINEDOWN:
|
|
|
|
term_scroll(term, 0, +1);
|
|
|
|
break;
|
|
|
|
case SB_LINEUP:
|
|
|
|
term_scroll(term, 0, -1);
|
|
|
|
break;
|
|
|
|
case SB_PAGEDOWN:
|
|
|
|
term_scroll(term, 0, +term->rows / 2);
|
|
|
|
break;
|
|
|
|
case SB_PAGEUP:
|
|
|
|
term_scroll(term, 0, -term->rows / 2);
|
|
|
|
break;
|
|
|
|
case SB_THUMBPOSITION:
|
Formatting change to braces around one case of a switch.
Sometimes, within a switch statement, you want to declare local
variables specific to the handler for one particular case. Until now
I've mostly been writing this in the form
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED:
{
declare variables;
do stuff;
}
break;
}
which is ugly because the two pieces of essentially similar code
appear at different indent levels, and also inconvenient because you
have less horizontal space available to write the complicated case
handler in - particuarly undesirable because _complicated_ case
handlers are the ones most likely to need all the space they can get!
After encountering a rather nicer idiom in the LLVM source code, and
after a bit of hackery this morning figuring out how to persuade
Emacs's auto-indent to do what I wanted with it, I've decided to move
to an idiom in which the open brace comes right after the case
statement, and the code within it is indented the same as it would
have been without the brace. Then the whole case handler (including
the break) lives inside those braces, and you get something that looks
more like this:
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED: {
declare variables;
do stuff;
break;
}
}
This commit is a big-bang change that reformats all the complicated
case handlers I could find into the new layout. This is particularly
nice in the Pageant main function, in which almost _every_ case
handler had a bundle of variables and was long and complicated. (In
fact that's what motivated me to get round to this.) Some of the
innermost parts of the terminal escape-sequence handling are also
breathing a bit easier now the horizontal pressure on them is
relieved.
(Also, in a few cases, I was able to remove the extra braces
completely, because the only variable local to the case handler was a
loop variable which our new C99 policy allows me to move into the
initialiser clause of its for statement.)
Viewed with whitespace ignored, this is not too disruptive a change.
Downstream patches that conflict with it may need to be reapplied
using --ignore-whitespace or similar.
2020-02-16 07:49:52 +00:00
|
|
|
case SB_THUMBTRACK: {
|
2019-09-08 19:29:00 +00:00
|
|
|
/*
|
|
|
|
* Use GetScrollInfo instead of HIWORD(wParam) to get
|
|
|
|
* 32-bit scroll position.
|
|
|
|
*/
|
Formatting change to braces around one case of a switch.
Sometimes, within a switch statement, you want to declare local
variables specific to the handler for one particular case. Until now
I've mostly been writing this in the form
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED:
{
declare variables;
do stuff;
}
break;
}
which is ugly because the two pieces of essentially similar code
appear at different indent levels, and also inconvenient because you
have less horizontal space available to write the complicated case
handler in - particuarly undesirable because _complicated_ case
handlers are the ones most likely to need all the space they can get!
After encountering a rather nicer idiom in the LLVM source code, and
after a bit of hackery this morning figuring out how to persuade
Emacs's auto-indent to do what I wanted with it, I've decided to move
to an idiom in which the open brace comes right after the case
statement, and the code within it is indented the same as it would
have been without the brace. Then the whole case handler (including
the break) lives inside those braces, and you get something that looks
more like this:
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED: {
declare variables;
do stuff;
break;
}
}
This commit is a big-bang change that reformats all the complicated
case handlers I could find into the new layout. This is particularly
nice in the Pageant main function, in which almost _every_ case
handler had a bundle of variables and was long and complicated. (In
fact that's what motivated me to get round to this.) Some of the
innermost parts of the terminal escape-sequence handling are also
breathing a bit easier now the horizontal pressure on them is
relieved.
(Also, in a few cases, I was able to remove the extra braces
completely, because the only variable local to the case handler was a
loop variable which our new C99 policy allows me to move into the
initialiser clause of its for statement.)
Viewed with whitespace ignored, this is not too disruptive a change.
Downstream patches that conflict with it may need to be reapplied
using --ignore-whitespace or similar.
2020-02-16 07:49:52 +00:00
|
|
|
SCROLLINFO si;
|
2019-09-08 19:29:00 +00:00
|
|
|
|
Formatting change to braces around one case of a switch.
Sometimes, within a switch statement, you want to declare local
variables specific to the handler for one particular case. Until now
I've mostly been writing this in the form
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED:
{
declare variables;
do stuff;
}
break;
}
which is ugly because the two pieces of essentially similar code
appear at different indent levels, and also inconvenient because you
have less horizontal space available to write the complicated case
handler in - particuarly undesirable because _complicated_ case
handlers are the ones most likely to need all the space they can get!
After encountering a rather nicer idiom in the LLVM source code, and
after a bit of hackery this morning figuring out how to persuade
Emacs's auto-indent to do what I wanted with it, I've decided to move
to an idiom in which the open brace comes right after the case
statement, and the code within it is indented the same as it would
have been without the brace. Then the whole case handler (including
the break) lives inside those braces, and you get something that looks
more like this:
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED: {
declare variables;
do stuff;
break;
}
}
This commit is a big-bang change that reformats all the complicated
case handlers I could find into the new layout. This is particularly
nice in the Pageant main function, in which almost _every_ case
handler had a bundle of variables and was long and complicated. (In
fact that's what motivated me to get round to this.) Some of the
innermost parts of the terminal escape-sequence handling are also
breathing a bit easier now the horizontal pressure on them is
relieved.
(Also, in a few cases, I was able to remove the extra braces
completely, because the only variable local to the case handler was a
loop variable which our new C99 policy allows me to move into the
initialiser clause of its for statement.)
Viewed with whitespace ignored, this is not too disruptive a change.
Downstream patches that conflict with it may need to be reapplied
using --ignore-whitespace or similar.
2020-02-16 07:49:52 +00:00
|
|
|
si.cbSize = sizeof(si);
|
|
|
|
si.fMask = SIF_TRACKPOS;
|
|
|
|
if (GetScrollInfo(hwnd, SB_VERT, &si) == 0)
|
|
|
|
si.nTrackPos = HIWORD(wParam);
|
|
|
|
term_scroll(term, 1, si.nTrackPos);
|
2019-09-08 19:29:00 +00:00
|
|
|
break;
|
Formatting change to braces around one case of a switch.
Sometimes, within a switch statement, you want to declare local
variables specific to the handler for one particular case. Until now
I've mostly been writing this in the form
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED:
{
declare variables;
do stuff;
}
break;
}
which is ugly because the two pieces of essentially similar code
appear at different indent levels, and also inconvenient because you
have less horizontal space available to write the complicated case
handler in - particuarly undesirable because _complicated_ case
handlers are the ones most likely to need all the space they can get!
After encountering a rather nicer idiom in the LLVM source code, and
after a bit of hackery this morning figuring out how to persuade
Emacs's auto-indent to do what I wanted with it, I've decided to move
to an idiom in which the open brace comes right after the case
statement, and the code within it is indented the same as it would
have been without the brace. Then the whole case handler (including
the break) lives inside those braces, and you get something that looks
more like this:
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED: {
declare variables;
do stuff;
break;
}
}
This commit is a big-bang change that reformats all the complicated
case handlers I could find into the new layout. This is particularly
nice in the Pageant main function, in which almost _every_ case
handler had a bundle of variables and was long and complicated. (In
fact that's what motivated me to get round to this.) Some of the
innermost parts of the terminal escape-sequence handling are also
breathing a bit easier now the horizontal pressure on them is
relieved.
(Also, in a few cases, I was able to remove the extra braces
completely, because the only variable local to the case handler was a
loop variable which our new C99 policy allows me to move into the
initialiser clause of its for statement.)
Viewed with whitespace ignored, this is not too disruptive a change.
Downstream patches that conflict with it may need to be reapplied
using --ignore-whitespace or similar.
2020-02-16 07:49:52 +00:00
|
|
|
}
|
2019-09-08 19:29:00 +00:00
|
|
|
}
|
|
|
|
break;
|
2001-05-06 14:35:20 +00:00
|
|
|
case WM_PALETTECHANGED:
|
2019-09-08 19:29:00 +00:00
|
|
|
if ((HWND) wParam != hwnd && pal != NULL) {
|
|
|
|
HDC hdc = make_hdc();
|
|
|
|
if (hdc) {
|
|
|
|
if (RealizePalette(hdc) > 0)
|
|
|
|
UpdateColors(hdc);
|
|
|
|
free_hdc(hdc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
1999-01-08 13:02:13 +00:00
|
|
|
case WM_QUERYNEWPALETTE:
|
2019-09-08 19:29:00 +00:00
|
|
|
if (pal != NULL) {
|
|
|
|
HDC hdc = make_hdc();
|
|
|
|
if (hdc) {
|
|
|
|
if (RealizePalette(hdc) > 0)
|
|
|
|
UpdateColors(hdc);
|
|
|
|
free_hdc(hdc);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
1999-01-08 13:02:13 +00:00
|
|
|
case WM_KEYDOWN:
|
|
|
|
case WM_SYSKEYDOWN:
|
2000-07-26 12:13:51 +00:00
|
|
|
case WM_KEYUP:
|
|
|
|
case WM_SYSKEYUP:
|
2019-09-08 19:29:00 +00:00
|
|
|
/*
|
|
|
|
* Add the scan code and keypress timing to the random
|
|
|
|
* number noise.
|
|
|
|
*/
|
|
|
|
noise_ultralight(NOISE_SOURCE_KEY, lParam);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We don't do TranslateMessage since it disassociates the
|
|
|
|
* resulting CHAR message from the KEYDOWN that sparked it,
|
|
|
|
* which we occasionally don't want. Instead, we process
|
|
|
|
* KEYDOWN, and call the Win32 translator functions so that
|
|
|
|
* we get the translations under _our_ control.
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
unsigned char buf[20];
|
|
|
|
int len;
|
|
|
|
|
|
|
|
if (wParam == VK_PROCESSKEY || /* IME PROCESS key */
|
|
|
|
wParam == VK_PACKET) { /* 'this key is a Unicode char' */
|
|
|
|
if (message == WM_KEYDOWN) {
|
|
|
|
MSG m;
|
|
|
|
m.hwnd = hwnd;
|
|
|
|
m.message = WM_KEYDOWN;
|
|
|
|
m.wParam = wParam;
|
|
|
|
m.lParam = lParam & 0xdfff;
|
|
|
|
TranslateMessage(&m);
|
|
|
|
} else break; /* pass to Windows for default processing */
|
|
|
|
} else {
|
|
|
|
len = TranslateKey(message, wParam, lParam, buf);
|
|
|
|
if (len == -1)
|
|
|
|
return DefWindowProcW(hwnd, message, wParam, lParam);
|
|
|
|
|
|
|
|
if (len != 0) {
|
|
|
|
/*
|
|
|
|
* We need not bother about stdin backlogs
|
|
|
|
* here, because in GUI PuTTY we can't do
|
|
|
|
* anything about it anyway; there's no means
|
|
|
|
* of asking Windows to hold off on KEYDOWN
|
|
|
|
* messages. We _have_ to buffer everything
|
|
|
|
* we're sent.
|
|
|
|
*/
|
|
|
|
term_keyinput(term, -1, buf, len);
|
|
|
|
show_mouseptr(false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
case WM_INPUTLANGCHANGE:
|
|
|
|
/* wParam == Font number */
|
|
|
|
/* lParam == Locale */
|
|
|
|
set_input_locale((HKL)lParam);
|
|
|
|
sys_cursor_update();
|
|
|
|
break;
|
Formatting change to braces around one case of a switch.
Sometimes, within a switch statement, you want to declare local
variables specific to the handler for one particular case. Until now
I've mostly been writing this in the form
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED:
{
declare variables;
do stuff;
}
break;
}
which is ugly because the two pieces of essentially similar code
appear at different indent levels, and also inconvenient because you
have less horizontal space available to write the complicated case
handler in - particuarly undesirable because _complicated_ case
handlers are the ones most likely to need all the space they can get!
After encountering a rather nicer idiom in the LLVM source code, and
after a bit of hackery this morning figuring out how to persuade
Emacs's auto-indent to do what I wanted with it, I've decided to move
to an idiom in which the open brace comes right after the case
statement, and the code within it is indented the same as it would
have been without the brace. Then the whole case handler (including
the break) lives inside those braces, and you get something that looks
more like this:
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED: {
declare variables;
do stuff;
break;
}
}
This commit is a big-bang change that reformats all the complicated
case handlers I could find into the new layout. This is particularly
nice in the Pageant main function, in which almost _every_ case
handler had a bundle of variables and was long and complicated. (In
fact that's what motivated me to get round to this.) Some of the
innermost parts of the terminal escape-sequence handling are also
breathing a bit easier now the horizontal pressure on them is
relieved.
(Also, in a few cases, I was able to remove the extra braces
completely, because the only variable local to the case handler was a
loop variable which our new C99 policy allows me to move into the
initialiser clause of its for statement.)
Viewed with whitespace ignored, this is not too disruptive a change.
Downstream patches that conflict with it may need to be reapplied
using --ignore-whitespace or similar.
2020-02-16 07:49:52 +00:00
|
|
|
case WM_IME_STARTCOMPOSITION: {
|
|
|
|
HIMC hImc = ImmGetContext(hwnd);
|
|
|
|
ImmSetCompositionFont(hImc, &lfont);
|
|
|
|
ImmReleaseContext(hwnd, hImc);
|
2019-09-08 19:29:00 +00:00
|
|
|
break;
|
Formatting change to braces around one case of a switch.
Sometimes, within a switch statement, you want to declare local
variables specific to the handler for one particular case. Until now
I've mostly been writing this in the form
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED:
{
declare variables;
do stuff;
}
break;
}
which is ugly because the two pieces of essentially similar code
appear at different indent levels, and also inconvenient because you
have less horizontal space available to write the complicated case
handler in - particuarly undesirable because _complicated_ case
handlers are the ones most likely to need all the space they can get!
After encountering a rather nicer idiom in the LLVM source code, and
after a bit of hackery this morning figuring out how to persuade
Emacs's auto-indent to do what I wanted with it, I've decided to move
to an idiom in which the open brace comes right after the case
statement, and the code within it is indented the same as it would
have been without the brace. Then the whole case handler (including
the break) lives inside those braces, and you get something that looks
more like this:
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED: {
declare variables;
do stuff;
break;
}
}
This commit is a big-bang change that reformats all the complicated
case handlers I could find into the new layout. This is particularly
nice in the Pageant main function, in which almost _every_ case
handler had a bundle of variables and was long and complicated. (In
fact that's what motivated me to get round to this.) Some of the
innermost parts of the terminal escape-sequence handling are also
breathing a bit easier now the horizontal pressure on them is
relieved.
(Also, in a few cases, I was able to remove the extra braces
completely, because the only variable local to the case handler was a
loop variable which our new C99 policy allows me to move into the
initialiser clause of its for statement.)
Viewed with whitespace ignored, this is not too disruptive a change.
Downstream patches that conflict with it may need to be reapplied
using --ignore-whitespace or similar.
2020-02-16 07:49:52 +00:00
|
|
|
}
|
|
|
|
case WM_IME_COMPOSITION: {
|
|
|
|
HIMC hIMC;
|
|
|
|
int n;
|
|
|
|
char *buff;
|
|
|
|
|
|
|
|
if (osPlatformId == VER_PLATFORM_WIN32_WINDOWS ||
|
|
|
|
osPlatformId == VER_PLATFORM_WIN32s)
|
|
|
|
break; /* no Unicode */
|
|
|
|
|
|
|
|
if ((lParam & GCS_RESULTSTR) == 0) /* Composition unfinished. */
|
|
|
|
break; /* fall back to DefWindowProc */
|
|
|
|
|
|
|
|
hIMC = ImmGetContext(hwnd);
|
|
|
|
n = ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, NULL, 0);
|
|
|
|
|
|
|
|
if (n > 0) {
|
|
|
|
int i;
|
|
|
|
buff = snewn(n, char);
|
|
|
|
ImmGetCompositionStringW(hIMC, GCS_RESULTSTR, buff, n);
|
|
|
|
/*
|
|
|
|
* Jaeyoun Chung reports that Korean character
|
|
|
|
* input doesn't work correctly if we do a single
|
|
|
|
* term_keyinputw covering the whole of buff. So
|
|
|
|
* instead we send the characters one by one.
|
|
|
|
*/
|
|
|
|
/* don't divide SURROGATE PAIR */
|
|
|
|
if (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);
|
|
|
|
i += 2;
|
|
|
|
continue;
|
2019-09-08 19:29:00 +00:00
|
|
|
}
|
Formatting change to braces around one case of a switch.
Sometimes, within a switch statement, you want to declare local
variables specific to the handler for one particular case. Until now
I've mostly been writing this in the form
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED:
{
declare variables;
do stuff;
}
break;
}
which is ugly because the two pieces of essentially similar code
appear at different indent levels, and also inconvenient because you
have less horizontal space available to write the complicated case
handler in - particuarly undesirable because _complicated_ case
handlers are the ones most likely to need all the space they can get!
After encountering a rather nicer idiom in the LLVM source code, and
after a bit of hackery this morning figuring out how to persuade
Emacs's auto-indent to do what I wanted with it, I've decided to move
to an idiom in which the open brace comes right after the case
statement, and the code within it is indented the same as it would
have been without the brace. Then the whole case handler (including
the break) lives inside those braces, and you get something that looks
more like this:
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED: {
declare variables;
do stuff;
break;
}
}
This commit is a big-bang change that reformats all the complicated
case handlers I could find into the new layout. This is particularly
nice in the Pageant main function, in which almost _every_ case
handler had a bundle of variables and was long and complicated. (In
fact that's what motivated me to get round to this.) Some of the
innermost parts of the terminal escape-sequence handling are also
breathing a bit easier now the horizontal pressure on them is
relieved.
(Also, in a few cases, I was able to remove the extra braces
completely, because the only variable local to the case handler was a
loop variable which our new C99 policy allows me to move into the
initialiser clause of its for statement.)
Viewed with whitespace ignored, this is not too disruptive a change.
Downstream patches that conflict with it may need to be reapplied
using --ignore-whitespace or similar.
2020-02-16 07:49:52 +00:00
|
|
|
}
|
|
|
|
term_keyinputw(
|
|
|
|
term, (unsigned short *)(buff+i), 1);
|
2019-09-08 19:29:00 +00:00
|
|
|
}
|
Formatting change to braces around one case of a switch.
Sometimes, within a switch statement, you want to declare local
variables specific to the handler for one particular case. Until now
I've mostly been writing this in the form
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED:
{
declare variables;
do stuff;
}
break;
}
which is ugly because the two pieces of essentially similar code
appear at different indent levels, and also inconvenient because you
have less horizontal space available to write the complicated case
handler in - particuarly undesirable because _complicated_ case
handlers are the ones most likely to need all the space they can get!
After encountering a rather nicer idiom in the LLVM source code, and
after a bit of hackery this morning figuring out how to persuade
Emacs's auto-indent to do what I wanted with it, I've decided to move
to an idiom in which the open brace comes right after the case
statement, and the code within it is indented the same as it would
have been without the brace. Then the whole case handler (including
the break) lives inside those braces, and you get something that looks
more like this:
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED: {
declare variables;
do stuff;
break;
}
}
This commit is a big-bang change that reformats all the complicated
case handlers I could find into the new layout. This is particularly
nice in the Pageant main function, in which almost _every_ case
handler had a bundle of variables and was long and complicated. (In
fact that's what motivated me to get round to this.) Some of the
innermost parts of the terminal escape-sequence handling are also
breathing a bit easier now the horizontal pressure on them is
relieved.
(Also, in a few cases, I was able to remove the extra braces
completely, because the only variable local to the case handler was a
loop variable which our new C99 policy allows me to move into the
initialiser clause of its for statement.)
Viewed with whitespace ignored, this is not too disruptive a change.
Downstream patches that conflict with it may need to be reapplied
using --ignore-whitespace or similar.
2020-02-16 07:49:52 +00:00
|
|
|
}
|
|
|
|
free(buff);
|
2019-09-08 19:29:00 +00:00
|
|
|
}
|
Formatting change to braces around one case of a switch.
Sometimes, within a switch statement, you want to declare local
variables specific to the handler for one particular case. Until now
I've mostly been writing this in the form
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED:
{
declare variables;
do stuff;
}
break;
}
which is ugly because the two pieces of essentially similar code
appear at different indent levels, and also inconvenient because you
have less horizontal space available to write the complicated case
handler in - particuarly undesirable because _complicated_ case
handlers are the ones most likely to need all the space they can get!
After encountering a rather nicer idiom in the LLVM source code, and
after a bit of hackery this morning figuring out how to persuade
Emacs's auto-indent to do what I wanted with it, I've decided to move
to an idiom in which the open brace comes right after the case
statement, and the code within it is indented the same as it would
have been without the brace. Then the whole case handler (including
the break) lives inside those braces, and you get something that looks
more like this:
switch (discriminant) {
case SIMPLE:
do stuff;
break;
case COMPLICATED: {
declare variables;
do stuff;
break;
}
}
This commit is a big-bang change that reformats all the complicated
case handlers I could find into the new layout. This is particularly
nice in the Pageant main function, in which almost _every_ case
handler had a bundle of variables and was long and complicated. (In
fact that's what motivated me to get round to this.) Some of the
innermost parts of the terminal escape-sequence handling are also
breathing a bit easier now the horizontal pressure on them is
relieved.
(Also, in a few cases, I was able to remove the extra braces
completely, because the only variable local to the case handler was a
loop variable which our new C99 policy allows me to move into the
initialiser clause of its for statement.)
Viewed with whitespace ignored, this is not too disruptive a change.
Downstream patches that conflict with it may need to be reapplied
using --ignore-whitespace or similar.
2020-02-16 07:49:52 +00:00
|
|
|
ImmReleaseContext(hwnd, hIMC);
|
|
|
|
return 1;
|
|
|
|
}
|
2001-08-04 15:15:07 +00:00
|
|
|
|
2001-05-10 08:34:20 +00:00
|
|
|
case WM_IME_CHAR:
|
2019-09-08 19:29:00 +00:00
|
|
|
if (wParam & 0xFF00) {
|
|
|
|
char buf[2];
|
2000-10-20 18:36:15 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
buf[1] = wParam;
|
|
|
|
buf[0] = wParam >> 8;
|
Refactor terminal input to remove ldiscucs.c.
The functions that previously lived in it now live in terminal.c
itself; they've been renamed term_keyinput and term_keyinputw, and
their function is to add data to the terminal's user input buffer from
a char or wchar_t string respectively.
They sit more comfortably in terminal.c anyway, because their whole
point is to translate into the character encoding that the terminal is
currently configured to use. Also, making them part of the terminal
code means they can also take care of calling term_seen_key_event(),
which simplifies most of the call sites in the GTK and Windows front
ends.
Generation of text _inside_ terminal.c, from responses to query escape
sequences, is therefore not done by calling those external entry
points: we send those responses directly to the ldisc, so that they
don't count as keypresses for all the user-facing purposes like bell
overload handling and scrollback reset. To make _that_ convenient,
I've arranged that most of the code that previously lived in
lpage_send and luni_send is now in separate translation functions, so
those can still be called from situations where you're not going to do
the default thing with the translated data.
(However, pasted data _does_ still count as close enough to a keypress
to call term_seen_key_event - but it clears the 'interactive' flag
when the data is passed on to the line discipline, which tweaks a
minor detail of control-char handling in line ending mode but mostly
just means pastes aren't interrupted.)
2019-06-17 19:13:55 +00:00
|
|
|
term_keyinput(term, kbd_codepage, buf, 2);
|
2019-09-08 19:29:00 +00:00
|
|
|
} else {
|
|
|
|
char c = (unsigned char) wParam;
|
|
|
|
term_seen_key_event(term);
|
Refactor terminal input to remove ldiscucs.c.
The functions that previously lived in it now live in terminal.c
itself; they've been renamed term_keyinput and term_keyinputw, and
their function is to add data to the terminal's user input buffer from
a char or wchar_t string respectively.
They sit more comfortably in terminal.c anyway, because their whole
point is to translate into the character encoding that the terminal is
currently configured to use. Also, making them part of the terminal
code means they can also take care of calling term_seen_key_event(),
which simplifies most of the call sites in the GTK and Windows front
ends.
Generation of text _inside_ terminal.c, from responses to query escape
sequences, is therefore not done by calling those external entry
points: we send those responses directly to the ldisc, so that they
don't count as keypresses for all the user-facing purposes like bell
overload handling and scrollback reset. To make _that_ convenient,
I've arranged that most of the code that previously lived in
lpage_send and luni_send is now in separate translation functions, so
those can still be called from situations where you're not going to do
the default thing with the translated data.
(However, pasted data _does_ still count as close enough to a keypress
to call term_seen_key_event - but it clears the 'interactive' flag
when the data is passed on to the line discipline, which tweaks a
minor detail of control-char handling in line ending mode but mostly
just means pastes aren't interrupted.)
2019-06-17 19:13:55 +00:00
|
|
|
term_keyinput(term, kbd_codepage, &c, 1);
|
2019-09-08 19:29:00 +00:00
|
|
|
}
|
|
|
|
return (0);
|
1999-01-08 13:02:13 +00:00
|
|
|
case WM_CHAR:
|
|
|
|
case WM_SYSCHAR:
|
2019-09-08 19:29:00 +00:00
|
|
|
/*
|
|
|
|
* Nevertheless, we are prepared to deal with WM_CHAR
|
|
|
|
* messages, should they crop up. So if someone wants to
|
|
|
|
* post the things to us as part of a macro manoeuvre,
|
|
|
|
* we're ready to cope.
|
|
|
|
*/
|
|
|
|
{
|
2015-07-27 19:06:02 +00:00
|
|
|
static wchar_t pending_surrogate = 0;
|
2019-09-08 19:29:00 +00:00
|
|
|
wchar_t c = wParam;
|
2015-07-27 19:06:02 +00:00
|
|
|
|
|
|
|
if (IS_HIGH_SURROGATE(c)) {
|
|
|
|
pending_surrogate = c;
|
|
|
|
} else if (IS_SURROGATE_PAIR(pending_surrogate, c)) {
|
|
|
|
wchar_t pair[2];
|
|
|
|
pair[0] = pending_surrogate;
|
|
|
|
pair[1] = c;
|
Refactor terminal input to remove ldiscucs.c.
The functions that previously lived in it now live in terminal.c
itself; they've been renamed term_keyinput and term_keyinputw, and
their function is to add data to the terminal's user input buffer from
a char or wchar_t string respectively.
They sit more comfortably in terminal.c anyway, because their whole
point is to translate into the character encoding that the terminal is
currently configured to use. Also, making them part of the terminal
code means they can also take care of calling term_seen_key_event(),
which simplifies most of the call sites in the GTK and Windows front
ends.
Generation of text _inside_ terminal.c, from responses to query escape
sequences, is therefore not done by calling those external entry
points: we send those responses directly to the ldisc, so that they
don't count as keypresses for all the user-facing purposes like bell
overload handling and scrollback reset. To make _that_ convenient,
I've arranged that most of the code that previously lived in
lpage_send and luni_send is now in separate translation functions, so
those can still be called from situations where you're not going to do
the default thing with the translated data.
(However, pasted data _does_ still count as close enough to a keypress
to call term_seen_key_event - but it clears the 'interactive' flag
when the data is passed on to the line discipline, which tweaks a
minor detail of control-char handling in line ending mode but mostly
just means pastes aren't interrupted.)
2019-06-17 19:13:55 +00:00
|
|
|
term_keyinputw(term, pair, 2);
|
2015-07-27 19:06:02 +00:00
|
|
|
} else if (!IS_SURROGATE(c)) {
|
Refactor terminal input to remove ldiscucs.c.
The functions that previously lived in it now live in terminal.c
itself; they've been renamed term_keyinput and term_keyinputw, and
their function is to add data to the terminal's user input buffer from
a char or wchar_t string respectively.
They sit more comfortably in terminal.c anyway, because their whole
point is to translate into the character encoding that the terminal is
currently configured to use. Also, making them part of the terminal
code means they can also take care of calling term_seen_key_event(),
which simplifies most of the call sites in the GTK and Windows front
ends.
Generation of text _inside_ terminal.c, from responses to query escape
sequences, is therefore not done by calling those external entry
points: we send those responses directly to the ldisc, so that they
don't count as keypresses for all the user-facing purposes like bell
overload handling and scrollback reset. To make _that_ convenient,
I've arranged that most of the code that previously lived in
lpage_send and luni_send is now in separate translation functions, so
those can still be called from situations where you're not going to do
the default thing with the translated data.
(However, pasted data _does_ still count as close enough to a keypress
to call term_seen_key_event - but it clears the 'interactive' flag
when the data is passed on to the line discipline, which tweaks a
minor detail of control-char handling in line ending mode but mostly
just means pastes aren't interrupted.)
2019-06-17 19:13:55 +00:00
|
|
|
term_keyinputw(term, &c, 1);
|
2015-07-27 19:06:02 +00:00
|
|
|
}
|
2019-09-08 19:29:00 +00:00
|
|
|
}
|
|
|
|
return 0;
|
2004-08-27 12:24:08 +00:00
|
|
|
case WM_SYSCOLORCHANGE:
|
2019-09-08 19:29:00 +00:00
|
|
|
if (conf_get_bool(conf, CONF_system_colour)) {
|
|
|
|
/* Refresh palette from system colours. */
|
Centralise palette setup into terminal.c.
Now terminal.c makes nearly all the decisions about what the colour
palette should actually contain: it does the job of reading the
GUI-configurable colours out of Conf, and also the job of making up
the rest of the xterm-256 palette. The only exception is that TermWin
can provide a method to override some of the default colours, which on
Windows is used to implement the 'Use system colours' config option.
This saves code overall, partly because the front ends don't have to
be able to send palette data back to the Terminal any more (the
Terminal keeps the master copy and can answer palette-query escape
sequences from its own knowledge), and also because now there's only
one copy of the xterm-256 palette setup code (previously gtkwin.c and
window.c each had their own version of it).
In this rewrite, I've also introduced a multi-layered storage system
for the palette data in Terminal. One layer contains the palette
information derived from Conf; the next contains platform overrides
(currently just Windows's 'Use system colours'); the last one contains
overrides set by escape sequences in the middle of the session. The
topmost two layers can each _conditionally_ override the ones below.
As a result, if a server-side application manually resets (say) the
default fg and bg colours in mid-session to something that works well
in a particular application, those changes won't be wiped out by a
change in the Windows system colours or the Conf, which they would
have been before. Instead, changes in Conf or the system colours alter
the lower layers of the structure, but then when palette_rebuild is
called, the upper layer continues to override them, until a palette
reset (ESC]R) or terminal reset (e.g. ESC c) removes those upper-layer
changes. This seems like a more consistent strategy, in that the same
set of configuration settings will produce the same end result
regardless of what order they were applied in.
The palette-related methods in TermWin have had a total rework.
palette_get and palette_reset are both gone; palette_set can now set a
contiguous range of colours in one go; and the new
palette_get_overrides replaces window.c's old systopalette().
2021-02-07 19:59:21 +00:00
|
|
|
term_notify_palette_overrides_changed(term);
|
2019-09-08 19:29:00 +00:00
|
|
|
init_palette();
|
|
|
|
/* Force a repaint of the terminal window. */
|
|
|
|
term_invalidate(term);
|
|
|
|
}
|
|
|
|
break;
|
2008-11-28 18:28:23 +00:00
|
|
|
case WM_GOT_CLIPDATA:
|
2019-09-08 19:29:00 +00:00
|
|
|
process_clipdata((HGLOBAL)lParam, wParam);
|
|
|
|
return 0;
|
2001-12-15 14:30:58 +00:00
|
|
|
default:
|
2019-09-08 19:29:00 +00:00
|
|
|
if (message == wm_mousewheel || message == WM_MOUSEWHEEL) {
|
|
|
|
bool shift_pressed = false, control_pressed = false;
|
|
|
|
|
|
|
|
if (message == WM_MOUSEWHEEL) {
|
|
|
|
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;
|
|
|
|
if (GetKeyboardState(keys)!=0) {
|
|
|
|
shift_pressed=keys[VK_SHIFT]&0x80;
|
|
|
|
control_pressed=keys[VK_CONTROL]&0x80;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* process events when the threshold is reached */
|
|
|
|
while (abs(wheel_accumulator) >= WHEEL_DELTA) {
|
|
|
|
int b;
|
|
|
|
|
|
|
|
/* reduce amount for next time */
|
|
|
|
if (wheel_accumulator > 0) {
|
|
|
|
b = MBT_WHEEL_UP;
|
|
|
|
wheel_accumulator -= WHEEL_DELTA;
|
|
|
|
} else if (wheel_accumulator < 0) {
|
|
|
|
b = MBT_WHEEL_DOWN;
|
|
|
|
wheel_accumulator += WHEEL_DELTA;
|
|
|
|
} else
|
|
|
|
break;
|
|
|
|
|
|
|
|
if (send_raw_mouse &&
|
|
|
|
!(conf_get_bool(conf, CONF_mouse_override) &&
|
2012-10-02 19:31:33 +00:00
|
|
|
shift_pressed)) {
|
2019-09-08 19:29:00 +00:00
|
|
|
/* Mouse wheel position is in screen coordinates for
|
|
|
|
* some reason */
|
|
|
|
POINT p;
|
|
|
|
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),
|
|
|
|
MA_CLICK,
|
|
|
|
TO_CHR_X(p.x),
|
|
|
|
TO_CHR_Y(p.y), shift_pressed,
|
|
|
|
control_pressed, is_alt_pressed());
|
|
|
|
} /* else: not sure when this can fail */
|
|
|
|
} else {
|
|
|
|
/* trigger a scroll */
|
|
|
|
term_scroll(term, 0,
|
|
|
|
b == MBT_WHEEL_UP ?
|
|
|
|
-term->rows / 2 : term->rows / 2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
1999-01-08 13:02:13 +00:00
|
|
|
}
|
|
|
|
|
2005-03-20 22:28:13 +00:00
|
|
|
/*
|
|
|
|
* Any messages we don't process completely above are passed through to
|
|
|
|
* DefWindowProc() for default processing.
|
|
|
|
*/
|
2015-07-27 19:06:02 +00:00
|
|
|
return DefWindowProcW(hwnd, message, wParam, lParam);
|
1999-01-08 13:02:13 +00:00
|
|
|
}
|
|
|
|
|
2000-09-25 16:17:53 +00:00
|
|
|
/*
|
|
|
|
* Move the system caret. (We maintain one, even though it's
|
|
|
|
* invisible, for the benefit of blind people: apparently some
|
|
|
|
* helper software tracks the system caret, so we should arrange to
|
|
|
|
* have one.)
|
|
|
|
*/
|
Remove the 'Frontend' type and replace it with a vtable.
After the recent Seat and LogContext revamps, _nearly_ all the
remaining uses of the type 'Frontend' were in terminal.c, which needs
all sorts of interactions with the GUI window the terminal lives in,
from the obvious (actually drawing text on the window, reading and
writing the clipboard) to the obscure (minimising, maximising and
moving the window in response to particular escape sequences).
All of those functions are now provided by an abstraction called
TermWin. The few remaining uses of Frontend after _that_ are internal
to a particular platform directory, so as to spread the implementation
of that particular kind of Frontend between multiple source files; so
I've renamed all of those so that they take a more specifically named
type that refers to the particular implementation rather than the
general abstraction.
So now the name 'Frontend' no longer exists in the code base at all,
and everywhere one used to be used, it's completely clear whether it
was operating in one of Frontend's three abstract roles (and if so,
which), or whether it was specific to a particular implementation.
Another type that's disappeared is 'Context', which used to be a
typedef defined to something different on each platform, describing
whatever short-lived resources were necessary to draw on the terminal
window: the front end would provide a ready-made one when calling
term_paint, and the terminal could request one with get_ctx/free_ctx
if it wanted to do proactive window updates. Now that drawing context
lives inside the TermWin itself, because there was never any need to
have two of those contexts live at the same time.
(Another minor API change is that the window-title functions - both
reading and writing - have had a missing 'const' added to their char *
parameters / return values.)
I don't expect this change to enable any particularly interesting new
functionality (in particular, I have no plans that need more than one
implementation of TermWin in the same application). But it completes
the tidying-up that began with the Seat and LogContext rework.
2018-10-25 17:44:04 +00:00
|
|
|
static void wintw_set_cursor_pos(TermWin *tw, int x, int y)
|
2001-12-20 14:18:01 +00:00
|
|
|
{
|
|
|
|
int cx, cy;
|
|
|
|
|
2002-10-22 16:11:33 +00:00
|
|
|
if (!term->has_focus) return;
|
2001-12-20 14:18:01 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Avoid gratuitously re-updating the cursor position and IMM
|
|
|
|
* window if there's no actual change required.
|
|
|
|
*/
|
|
|
|
cx = x * font_width + offset_width;
|
|
|
|
cy = y * font_height + offset_height;
|
|
|
|
if (cx == caret_x && cy == caret_y)
|
2019-09-08 19:29:00 +00:00
|
|
|
return;
|
2001-12-20 14:18:01 +00:00
|
|
|
caret_x = cx;
|
|
|
|
caret_y = cy;
|
|
|
|
|
|
|
|
sys_cursor_update();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void sys_cursor_update(void)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
2001-08-04 15:15:07 +00:00
|
|
|
COMPOSITIONFORM cf;
|
|
|
|
HIMC hIMC;
|
|
|
|
|
2002-10-22 16:11:33 +00:00
|
|
|
if (!term->has_focus) return;
|
2001-12-20 14:18:01 +00:00
|
|
|
|
|
|
|
if (caret_x < 0 || caret_y < 0)
|
2019-09-08 19:29:00 +00:00
|
|
|
return;
|
2001-12-20 14:18:01 +00:00
|
|
|
|
|
|
|
SetCaretPos(caret_x, caret_y);
|
2001-08-04 15:15:07 +00:00
|
|
|
|
|
|
|
/* IMM calls on Win98 and beyond only */
|
2018-06-03 14:05:44 +00:00
|
|
|
if (osPlatformId == VER_PLATFORM_WIN32s) return; /* 3.11 */
|
2019-09-08 19:29:00 +00:00
|
|
|
|
2018-06-03 14:05:44 +00:00
|
|
|
if (osPlatformId == VER_PLATFORM_WIN32_WINDOWS &&
|
|
|
|
osMinorVersion == 0) return; /* 95 */
|
2001-08-04 15:15:07 +00:00
|
|
|
|
|
|
|
/* we should have the IMM functions */
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
hIMC = ImmGetContext(wgs.term_hwnd);
|
2001-08-04 15:15:07 +00:00
|
|
|
cf.dwStyle = CFS_POINT;
|
2001-12-20 14:18:01 +00:00
|
|
|
cf.ptCurrentPos.x = caret_x;
|
|
|
|
cf.ptCurrentPos.y = caret_y;
|
2001-08-04 15:15:07 +00:00
|
|
|
ImmSetCompositionWindow(hIMC, &cf);
|
|
|
|
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
ImmReleaseContext(wgs.term_hwnd, hIMC);
|
2000-09-25 16:17:53 +00:00
|
|
|
}
|
|
|
|
|
2020-08-13 20:08:53 +00:00
|
|
|
static void draw_horizontal_line_on_text(int y, int lattr, RECT line_box,
|
|
|
|
COLORREF colour)
|
|
|
|
{
|
|
|
|
if (lattr == LATTR_TOP || lattr == LATTR_BOT) {
|
|
|
|
y *= 2;
|
|
|
|
if (lattr == LATTR_BOT)
|
|
|
|
y -= font_height;
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
DeleteObject(oldpen);
|
|
|
|
}
|
|
|
|
|
1999-01-08 13:02:13 +00:00
|
|
|
/*
|
|
|
|
* Draw a line of text in the window, at given character
|
|
|
|
* coordinates, in given attributes.
|
|
|
|
*
|
|
|
|
* We are allowed to fiddle with the contents of `text'.
|
|
|
|
*/
|
Remove the 'Frontend' type and replace it with a vtable.
After the recent Seat and LogContext revamps, _nearly_ all the
remaining uses of the type 'Frontend' were in terminal.c, which needs
all sorts of interactions with the GUI window the terminal lives in,
from the obvious (actually drawing text on the window, reading and
writing the clipboard) to the obscure (minimising, maximising and
moving the window in response to particular escape sequences).
All of those functions are now provided by an abstraction called
TermWin. The few remaining uses of Frontend after _that_ are internal
to a particular platform directory, so as to spread the implementation
of that particular kind of Frontend between multiple source files; so
I've renamed all of those so that they take a more specifically named
type that refers to the particular implementation rather than the
general abstraction.
So now the name 'Frontend' no longer exists in the code base at all,
and everywhere one used to be used, it's completely clear whether it
was operating in one of Frontend's three abstract roles (and if so,
which), or whether it was specific to a particular implementation.
Another type that's disappeared is 'Context', which used to be a
typedef defined to something different on each platform, describing
whatever short-lived resources were necessary to draw on the terminal
window: the front end would provide a ready-made one when calling
term_paint, and the terminal could request one with get_ctx/free_ctx
if it wanted to do proactive window updates. Now that drawing context
lives inside the TermWin itself, because there was never any need to
have two of those contexts live at the same time.
(Another minor API change is that the window-title functions - both
reading and writing - have had a missing 'const' added to their char *
parameters / return values.)
I don't expect this change to enable any particularly interesting new
functionality (in particular, I have no plans that need more than one
implementation of TermWin in the same application). But it completes
the tidying-up that began with the Seat and LogContext rework.
2018-10-25 17:44:04 +00:00
|
|
|
static void do_text_internal(
|
|
|
|
int x, int y, wchar_t *text, int len,
|
|
|
|
unsigned long attr, int lattr, truecolour truecolour)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
1999-01-08 13:02:13 +00:00
|
|
|
COLORREF fg, bg, t;
|
|
|
|
int nfg, nbg, nfont;
|
2000-03-17 10:34:41 +00:00
|
|
|
RECT line_box;
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
bool force_manual_underline = false;
|
Re-engineering of terminal emulator, phase 1.
The active terminal screen is no longer an array of `unsigned long'
encoding 16-bit Unicode plus 16 attribute bits. Now it's an array of
`termchar' structures, which currently have 32-bit Unicode and 32
attribute bits but which will probably expand further in future.
To prevent bloat of the memory footprint, I've introduced a mostly
RLE-like compression scheme for storing scrollback: each line is
compressed into a compact (but hard to modify) form when it moves
into the term->scrollback tree, and is temporarily decompressed when
the user wants to scroll back over it. My initial tests suggest that
this compression averages about 1/4 of the previous (32 bits per
character cell) data size in typical output, which means this is an
improvement even without counting the new ability to extend the
information stored in each character cell.
Another beneficial side effect is that the insane format in which
Unicode was passed to front ends through do_text() has now been
rendered sane.
Testing is incomplete; this _may_ still have instabilities. Windows
and Unix front ends both seem to work as far as I've looked, but I
haven't yet looked very hard. The Mac front end I've edited (it
seemed obvious how to change it) but I can't compile or test it.
As an immediate functional effect, the terminal emulator now
supports full 32-bit Unicode to whatever extent the host platform
allows it to. For example, if you output a 4-or-more-byte UTF-8
character in Unix pterm, it will not display it properly, but it
will correctly paste it back out in a UTF8_STRING selection. Windows
is more restricted, sadly.
[originally from svn r4609]
2004-10-13 11:50:16 +00:00
|
|
|
int fnt_width, char_width;
|
2001-05-10 08:34:20 +00:00
|
|
|
int text_adjust = 0;
|
2010-12-29 14:11:25 +00:00
|
|
|
int xoffset = 0;
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
int maxlen, remaining;
|
|
|
|
bool opaque;
|
|
|
|
bool is_cursor = false;
|
2010-12-29 23:48:54 +00:00
|
|
|
static int *lpDx = NULL;
|
New array-growing macros: sgrowarray and sgrowarrayn.
The idea of these is that they centralise the common idiom along the
lines of
if (logical_array_len >= physical_array_size) {
physical_array_size = logical_array_len * 5 / 4 + 256;
array = sresize(array, physical_array_size, ElementType);
}
which happens at a zillion call sites throughout this code base, with
different random choices of the geometric factor and additive
constant, sometimes forgetting them completely, and generally doing a
lot of repeated work.
The new macro sgrowarray(array,size,n) has the semantics: here are the
array pointer and its physical size for you to modify, now please
ensure that the nth element exists, so I can write into it. And
sgrowarrayn(array,size,n,m) is the same except that it ensures that
the array has size at least n+m (so sgrowarray is just the special
case where m=1).
Now that this is a single centralised implementation that will be used
everywhere, I've also gone to more effort in the implementation, with
careful overflow checks that would have been painful to put at all the
previous call sites.
This commit also switches over every use of sresize(), apart from a
few where I really didn't think it would gain anything. A consequence
of that is that a lot of array-size variables have to have their types
changed to size_t, because the macros require that (they address-take
the size to pass to the underlying function).
2019-02-28 20:07:30 +00:00
|
|
|
static size_t lpDx_len = 0;
|
2010-12-29 23:48:54 +00:00
|
|
|
int *lpDx_maybe;
|
2012-02-17 19:28:55 +00:00
|
|
|
int len2; /* for SURROGATE PAIR */
|
2001-05-10 08:34:20 +00:00
|
|
|
|
Re-engineering of terminal emulator, phase 1.
The active terminal screen is no longer an array of `unsigned long'
encoding 16-bit Unicode plus 16 attribute bits. Now it's an array of
`termchar' structures, which currently have 32-bit Unicode and 32
attribute bits but which will probably expand further in future.
To prevent bloat of the memory footprint, I've introduced a mostly
RLE-like compression scheme for storing scrollback: each line is
compressed into a compact (but hard to modify) form when it moves
into the term->scrollback tree, and is temporarily decompressed when
the user wants to scroll back over it. My initial tests suggest that
this compression averages about 1/4 of the previous (32 bits per
character cell) data size in typical output, which means this is an
improvement even without counting the new ability to extend the
information stored in each character cell.
Another beneficial side effect is that the insane format in which
Unicode was passed to front ends through do_text() has now been
rendered sane.
Testing is incomplete; this _may_ still have instabilities. Windows
and Unix front ends both seem to work as far as I've looked, but I
haven't yet looked very hard. The Mac front end I've edited (it
seemed obvious how to change it) but I can't compile or test it.
As an immediate functional effect, the terminal emulator now
supports full 32-bit Unicode to whatever extent the host platform
allows it to. For example, if you output a 4-or-more-byte UTF-8
character in Unix pterm, it will not display it properly, but it
will correctly paste it back out in a UTF8_STRING selection. Windows
is more restricted, sadly.
[originally from svn r4609]
2004-10-13 11:50:16 +00:00
|
|
|
lattr &= LATTR_MODE;
|
|
|
|
|
|
|
|
char_width = fnt_width = font_width * (1 + (lattr != LATTR_NORM));
|
|
|
|
|
2001-05-10 08:34:20 +00:00
|
|
|
if (attr & ATTR_WIDE)
|
2019-09-08 19:29:00 +00:00
|
|
|
char_width *= 2;
|
2000-03-17 10:34:41 +00:00
|
|
|
|
2001-09-15 15:54:24 +00:00
|
|
|
/* Only want the left half of double width lines */
|
2002-10-22 16:11:33 +00:00
|
|
|
if (lattr != LATTR_NORM && x*2 >= term->cols)
|
2019-09-08 19:29:00 +00:00
|
|
|
return;
|
2001-09-15 15:54:24 +00:00
|
|
|
|
2000-07-26 12:13:51 +00:00
|
|
|
x *= fnt_width;
|
1999-01-08 13:02:13 +00:00
|
|
|
y *= font_height;
|
2001-09-15 15:54:24 +00:00
|
|
|
x += offset_width;
|
|
|
|
y += offset_height;
|
1999-01-08 13:02:13 +00:00
|
|
|
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
if ((attr & TATTR_ACTCURS) && (cursor_type == 0 || term->big_cursor)) {
|
2017-10-05 19:30:04 +00:00
|
|
|
truecolour.fg = truecolour.bg = optionalrgb_none;
|
2019-09-08 19:29:00 +00:00
|
|
|
attr &= ~(ATTR_REVERSE|ATTR_BLINK|ATTR_COLOURS|ATTR_DIM);
|
|
|
|
/* cursor fg and bg */
|
|
|
|
attr |= (260 << ATTR_FGSHIFT) | (261 << ATTR_BGSHIFT);
|
2018-10-29 19:50:29 +00:00
|
|
|
is_cursor = true;
|
1999-01-08 13:02:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
nfont = 0;
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
if (vtmode == VT_POORMAN && lattr != LATTR_NORM) {
|
2019-09-08 19:29:00 +00:00
|
|
|
/* Assume a poorman font is borken in other ways too. */
|
|
|
|
lattr = LATTR_WIDE;
|
2001-05-10 08:34:20 +00:00
|
|
|
} else
|
2019-09-08 19:29:00 +00:00
|
|
|
switch (lattr) {
|
|
|
|
case LATTR_NORM:
|
|
|
|
break;
|
|
|
|
case LATTR_WIDE:
|
|
|
|
nfont |= FONT_WIDE;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
nfont |= FONT_WIDE + FONT_HIGH;
|
|
|
|
break;
|
|
|
|
}
|
2001-09-15 15:54:24 +00:00
|
|
|
if (attr & ATTR_NARROW)
|
2019-09-08 19:29:00 +00:00
|
|
|
nfont |= FONT_NARROW;
|
2001-05-10 08:34:20 +00:00
|
|
|
|
2012-04-22 14:22:10 +00:00
|
|
|
#ifdef USES_VTLINE_HACK
|
2001-05-10 08:34:20 +00:00
|
|
|
/* Special hack for the VT100 linedraw glyphs. */
|
Re-engineering of terminal emulator, phase 1.
The active terminal screen is no longer an array of `unsigned long'
encoding 16-bit Unicode plus 16 attribute bits. Now it's an array of
`termchar' structures, which currently have 32-bit Unicode and 32
attribute bits but which will probably expand further in future.
To prevent bloat of the memory footprint, I've introduced a mostly
RLE-like compression scheme for storing scrollback: each line is
compressed into a compact (but hard to modify) form when it moves
into the term->scrollback tree, and is temporarily decompressed when
the user wants to scroll back over it. My initial tests suggest that
this compression averages about 1/4 of the previous (32 bits per
character cell) data size in typical output, which means this is an
improvement even without counting the new ability to extend the
information stored in each character cell.
Another beneficial side effect is that the insane format in which
Unicode was passed to front ends through do_text() has now been
rendered sane.
Testing is incomplete; this _may_ still have instabilities. Windows
and Unix front ends both seem to work as far as I've looked, but I
haven't yet looked very hard. The Mac front end I've edited (it
seemed obvious how to change it) but I can't compile or test it.
As an immediate functional effect, the terminal emulator now
supports full 32-bit Unicode to whatever extent the host platform
allows it to. For example, if you output a 4-or-more-byte UTF-8
character in Unix pterm, it will not display it properly, but it
will correctly paste it back out in a UTF8_STRING selection. Windows
is more restricted, sadly.
[originally from svn r4609]
2004-10-13 11:50:16 +00:00
|
|
|
if (text[0] >= 0x23BA && text[0] <= 0x23BD) {
|
2019-09-08 19:29:00 +00:00
|
|
|
switch ((unsigned char) (text[0])) {
|
|
|
|
case 0xBA:
|
|
|
|
text_adjust = -2 * font_height / 5;
|
|
|
|
break;
|
|
|
|
case 0xBB:
|
|
|
|
text_adjust = -1 * font_height / 5;
|
|
|
|
break;
|
|
|
|
case 0xBC:
|
|
|
|
text_adjust = font_height / 5;
|
|
|
|
break;
|
|
|
|
case 0xBD:
|
|
|
|
text_adjust = 2 * font_height / 5;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (lattr == LATTR_TOP || lattr == LATTR_BOT)
|
|
|
|
text_adjust *= 2;
|
|
|
|
text[0] = ucsdata.unitab_xterm['q'];
|
|
|
|
if (attr & ATTR_UNDER) {
|
|
|
|
attr &= ~ATTR_UNDER;
|
|
|
|
force_manual_underline = true;
|
|
|
|
}
|
1999-01-08 13:02:13 +00:00
|
|
|
}
|
2012-04-22 14:22:10 +00:00
|
|
|
#endif
|
1999-01-08 13:02:13 +00:00
|
|
|
|
2001-05-10 08:34:20 +00:00
|
|
|
/* Anything left as an original character set is unprintable. */
|
2012-02-17 19:28:55 +00:00
|
|
|
if (DIRECT_CHAR(text[0]) &&
|
|
|
|
(len < 2 || !IS_SURROGATE_PAIR(text[0], text[1]))) {
|
2019-09-08 19:29:00 +00:00
|
|
|
int i;
|
|
|
|
for (i = 0; i < len; i++)
|
|
|
|
text[i] = 0xFFFD;
|
2001-05-10 08:34:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* OEM CP */
|
Re-engineering of terminal emulator, phase 1.
The active terminal screen is no longer an array of `unsigned long'
encoding 16-bit Unicode plus 16 attribute bits. Now it's an array of
`termchar' structures, which currently have 32-bit Unicode and 32
attribute bits but which will probably expand further in future.
To prevent bloat of the memory footprint, I've introduced a mostly
RLE-like compression scheme for storing scrollback: each line is
compressed into a compact (but hard to modify) form when it moves
into the term->scrollback tree, and is temporarily decompressed when
the user wants to scroll back over it. My initial tests suggest that
this compression averages about 1/4 of the previous (32 bits per
character cell) data size in typical output, which means this is an
improvement even without counting the new ability to extend the
information stored in each character cell.
Another beneficial side effect is that the insane format in which
Unicode was passed to front ends through do_text() has now been
rendered sane.
Testing is incomplete; this _may_ still have instabilities. Windows
and Unix front ends both seem to work as far as I've looked, but I
haven't yet looked very hard. The Mac front end I've edited (it
seemed obvious how to change it) but I can't compile or test it.
As an immediate functional effect, the terminal emulator now
supports full 32-bit Unicode to whatever extent the host platform
allows it to. For example, if you output a 4-or-more-byte UTF-8
character in Unix pterm, it will not display it properly, but it
will correctly paste it back out in a UTF8_STRING selection. Windows
is more restricted, sadly.
[originally from svn r4609]
2004-10-13 11:50:16 +00:00
|
|
|
if ((text[0] & CSET_MASK) == CSET_OEMCP)
|
2019-09-08 19:29:00 +00:00
|
|
|
nfont |= FONT_OEM;
|
2001-05-10 08:34:20 +00:00
|
|
|
|
2003-01-27 23:03:31 +00:00
|
|
|
nfg = ((attr & ATTR_FGMASK) >> ATTR_FGSHIFT);
|
|
|
|
nbg = ((attr & ATTR_BGMASK) >> ATTR_BGSHIFT);
|
2012-06-09 15:09:22 +00:00
|
|
|
if (bold_font_mode == BOLD_FONT && (attr & ATTR_BOLD))
|
2019-09-08 19:29:00 +00:00
|
|
|
nfont |= FONT_BOLD;
|
1999-01-08 13:02:13 +00:00
|
|
|
if (und_mode == UND_FONT && (attr & ATTR_UNDER))
|
2019-09-08 19:29:00 +00:00
|
|
|
nfont |= FONT_UNDERLINE;
|
2001-05-10 08:34:20 +00:00
|
|
|
another_font(nfont);
|
2001-05-06 14:35:20 +00:00
|
|
|
if (!fonts[nfont]) {
|
2019-09-08 19:29:00 +00:00
|
|
|
if (nfont & FONT_UNDERLINE)
|
|
|
|
force_manual_underline = true;
|
|
|
|
/* Don't do the same for manual bold, it could be bad news. */
|
2000-03-17 10:34:41 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
nfont &= ~(FONT_BOLD | FONT_UNDERLINE);
|
2000-03-17 10:34:41 +00:00
|
|
|
}
|
2001-05-10 08:34:20 +00:00
|
|
|
another_font(nfont);
|
|
|
|
if (!fonts[nfont])
|
2019-09-08 19:29:00 +00:00
|
|
|
nfont = FONT_NORMAL;
|
1999-01-08 13:02:13 +00:00
|
|
|
if (attr & ATTR_REVERSE) {
|
2017-10-08 12:49:54 +00:00
|
|
|
struct optionalrgb trgb;
|
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
t = nfg;
|
|
|
|
nfg = nbg;
|
|
|
|
nbg = t;
|
2017-10-08 12:49:54 +00:00
|
|
|
|
|
|
|
trgb = truecolour.fg;
|
|
|
|
truecolour.fg = truecolour.bg;
|
|
|
|
truecolour.bg = trgb;
|
1999-01-08 13:02:13 +00:00
|
|
|
}
|
2012-06-09 15:09:22 +00:00
|
|
|
if (bold_colours && (attr & ATTR_BOLD) && !is_cursor) {
|
2019-09-08 19:29:00 +00:00
|
|
|
if (nfg < 16) nfg |= 8;
|
|
|
|
else if (nfg >= 256) nfg |= 1;
|
2004-11-28 15:13:34 +00:00
|
|
|
}
|
2012-06-09 15:09:22 +00:00
|
|
|
if (bold_colours && (attr & ATTR_BLINK)) {
|
2019-09-08 19:29:00 +00:00
|
|
|
if (nbg < 16) nbg |= 8;
|
|
|
|
else if (nbg >= 256) nbg |= 1;
|
2004-11-28 15:13:34 +00:00
|
|
|
}
|
2017-10-05 19:30:09 +00:00
|
|
|
if (!pal && truecolour.fg.enabled)
|
2019-09-08 19:29:00 +00:00
|
|
|
fg = RGB(truecolour.fg.r, truecolour.fg.g, truecolour.fg.b);
|
2017-09-30 16:32:32 +00:00
|
|
|
else
|
2019-09-08 19:29:00 +00:00
|
|
|
fg = colours[nfg];
|
2017-09-30 16:32:32 +00:00
|
|
|
|
2017-10-05 19:30:09 +00:00
|
|
|
if (!pal && truecolour.bg.enabled)
|
2019-09-08 19:29:00 +00:00
|
|
|
bg = RGB(truecolour.bg.r, truecolour.bg.g, truecolour.bg.b);
|
2017-09-30 16:32:32 +00:00
|
|
|
else
|
2019-09-08 19:29:00 +00:00
|
|
|
bg = colours[nbg];
|
2017-09-30 16:32:32 +00:00
|
|
|
|
2017-10-05 20:02:56 +00:00
|
|
|
if (!pal && (attr & ATTR_DIM)) {
|
|
|
|
fg = RGB(GetRValue(fg) * 2 / 3,
|
|
|
|
GetGValue(fg) * 2 / 3,
|
|
|
|
GetBValue(fg) * 2 / 3);
|
|
|
|
}
|
|
|
|
|
Remove the 'Frontend' type and replace it with a vtable.
After the recent Seat and LogContext revamps, _nearly_ all the
remaining uses of the type 'Frontend' were in terminal.c, which needs
all sorts of interactions with the GUI window the terminal lives in,
from the obvious (actually drawing text on the window, reading and
writing the clipboard) to the obscure (minimising, maximising and
moving the window in response to particular escape sequences).
All of those functions are now provided by an abstraction called
TermWin. The few remaining uses of Frontend after _that_ are internal
to a particular platform directory, so as to spread the implementation
of that particular kind of Frontend between multiple source files; so
I've renamed all of those so that they take a more specifically named
type that refers to the particular implementation rather than the
general abstraction.
So now the name 'Frontend' no longer exists in the code base at all,
and everywhere one used to be used, it's completely clear whether it
was operating in one of Frontend's three abstract roles (and if so,
which), or whether it was specific to a particular implementation.
Another type that's disappeared is 'Context', which used to be a
typedef defined to something different on each platform, describing
whatever short-lived resources were necessary to draw on the terminal
window: the front end would provide a ready-made one when calling
term_paint, and the terminal could request one with get_ctx/free_ctx
if it wanted to do proactive window updates. Now that drawing context
lives inside the TermWin itself, because there was never any need to
have two of those contexts live at the same time.
(Another minor API change is that the window-title functions - both
reading and writing - have had a missing 'const' added to their char *
parameters / return values.)
I don't expect this change to enable any particularly interesting new
functionality (in particular, I have no plans that need more than one
implementation of TermWin in the same application). But it completes
the tidying-up that began with the Seat and LogContext rework.
2018-10-25 17:44:04 +00:00
|
|
|
SelectObject(wintw_hdc, fonts[nfont]);
|
|
|
|
SetTextColor(wintw_hdc, fg);
|
|
|
|
SetBkColor(wintw_hdc, bg);
|
2004-10-14 16:42:43 +00:00
|
|
|
if (attr & TATTR_COMBINING)
|
2019-09-08 19:29:00 +00:00
|
|
|
SetBkMode(wintw_hdc, TRANSPARENT);
|
2004-10-14 16:42:43 +00:00
|
|
|
else
|
2019-09-08 19:29:00 +00:00
|
|
|
SetBkMode(wintw_hdc, OPAQUE);
|
2001-05-06 14:35:20 +00:00
|
|
|
line_box.left = x;
|
|
|
|
line_box.top = y;
|
2001-05-10 08:34:20 +00:00
|
|
|
line_box.right = x + char_width * len;
|
2001-05-06 14:35:20 +00:00
|
|
|
line_box.bottom = y + font_height;
|
2012-02-17 19:28:55 +00:00
|
|
|
/* adjust line_box.right for SURROGATE PAIR & VARIATION SELECTOR */
|
|
|
|
{
|
2019-09-08 19:29:00 +00:00
|
|
|
int i;
|
|
|
|
int rc_width = 0;
|
|
|
|
for (i = 0; i < len ; i++) {
|
|
|
|
if (i+1 < len && IS_HIGH_VARSEL(text[i], text[i+1])) {
|
|
|
|
i++;
|
|
|
|
} else if (i+1 < len && IS_SURROGATE_PAIR(text[i], text[i+1])) {
|
|
|
|
rc_width += char_width;
|
|
|
|
i++;
|
|
|
|
} else if (IS_LOW_VARSEL(text[i])) {
|
|
|
|
/* do nothing */
|
2012-02-17 19:28:55 +00:00
|
|
|
} else {
|
2019-09-08 19:29:00 +00:00
|
|
|
rc_width += char_width;
|
2012-02-17 19:28:55 +00:00
|
|
|
}
|
2019-09-08 19:29:00 +00:00
|
|
|
}
|
|
|
|
line_box.right = line_box.left + rc_width;
|
2012-02-17 19:28:55 +00:00
|
|
|
}
|
2001-05-10 08:34:20 +00:00
|
|
|
|
2001-09-15 15:54:24 +00:00
|
|
|
/* Only want the left half of double width lines */
|
2002-10-22 16:11:33 +00:00
|
|
|
if (line_box.right > font_width*term->cols+offset_width)
|
2019-09-08 19:29:00 +00:00
|
|
|
line_box.right = font_width*term->cols+offset_width;
|
2001-09-15 15:54:24 +00:00
|
|
|
|
2010-12-29 14:11:25 +00:00
|
|
|
if (font_varpitch) {
|
|
|
|
/*
|
|
|
|
* If we're using a variable-pitch font, we unconditionally
|
|
|
|
* draw the glyphs one at a time and centre them in their
|
|
|
|
* character cells (which means in particular that we must
|
2010-12-29 23:48:54 +00:00
|
|
|
* disable the lpDx mechanism). This gives slightly odd but
|
2010-12-29 14:11:25 +00:00
|
|
|
* generally reasonable results.
|
|
|
|
*/
|
|
|
|
xoffset = char_width / 2;
|
Remove the 'Frontend' type and replace it with a vtable.
After the recent Seat and LogContext revamps, _nearly_ all the
remaining uses of the type 'Frontend' were in terminal.c, which needs
all sorts of interactions with the GUI window the terminal lives in,
from the obvious (actually drawing text on the window, reading and
writing the clipboard) to the obscure (minimising, maximising and
moving the window in response to particular escape sequences).
All of those functions are now provided by an abstraction called
TermWin. The few remaining uses of Frontend after _that_ are internal
to a particular platform directory, so as to spread the implementation
of that particular kind of Frontend between multiple source files; so
I've renamed all of those so that they take a more specifically named
type that refers to the particular implementation rather than the
general abstraction.
So now the name 'Frontend' no longer exists in the code base at all,
and everywhere one used to be used, it's completely clear whether it
was operating in one of Frontend's three abstract roles (and if so,
which), or whether it was specific to a particular implementation.
Another type that's disappeared is 'Context', which used to be a
typedef defined to something different on each platform, describing
whatever short-lived resources were necessary to draw on the terminal
window: the front end would provide a ready-made one when calling
term_paint, and the terminal could request one with get_ctx/free_ctx
if it wanted to do proactive window updates. Now that drawing context
lives inside the TermWin itself, because there was never any need to
have two of those contexts live at the same time.
(Another minor API change is that the window-title functions - both
reading and writing - have had a missing 'const' added to their char *
parameters / return values.)
I don't expect this change to enable any particularly interesting new
functionality (in particular, I have no plans that need more than one
implementation of TermWin in the same application). But it completes
the tidying-up that began with the Seat and LogContext rework.
2018-10-25 17:44:04 +00:00
|
|
|
SetTextAlign(wintw_hdc, TA_TOP | TA_CENTER | TA_NOUPDATECP);
|
2010-12-29 23:48:54 +00:00
|
|
|
lpDx_maybe = NULL;
|
2010-12-29 14:11:25 +00:00
|
|
|
maxlen = 1;
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* In a fixed-pitch font, we draw the whole string in one go
|
|
|
|
* in the normal way.
|
|
|
|
*/
|
|
|
|
xoffset = 0;
|
Remove the 'Frontend' type and replace it with a vtable.
After the recent Seat and LogContext revamps, _nearly_ all the
remaining uses of the type 'Frontend' were in terminal.c, which needs
all sorts of interactions with the GUI window the terminal lives in,
from the obvious (actually drawing text on the window, reading and
writing the clipboard) to the obscure (minimising, maximising and
moving the window in response to particular escape sequences).
All of those functions are now provided by an abstraction called
TermWin. The few remaining uses of Frontend after _that_ are internal
to a particular platform directory, so as to spread the implementation
of that particular kind of Frontend between multiple source files; so
I've renamed all of those so that they take a more specifically named
type that refers to the particular implementation rather than the
general abstraction.
So now the name 'Frontend' no longer exists in the code base at all,
and everywhere one used to be used, it's completely clear whether it
was operating in one of Frontend's three abstract roles (and if so,
which), or whether it was specific to a particular implementation.
Another type that's disappeared is 'Context', which used to be a
typedef defined to something different on each platform, describing
whatever short-lived resources were necessary to draw on the terminal
window: the front end would provide a ready-made one when calling
term_paint, and the terminal could request one with get_ctx/free_ctx
if it wanted to do proactive window updates. Now that drawing context
lives inside the TermWin itself, because there was never any need to
have two of those contexts live at the same time.
(Another minor API change is that the window-title functions - both
reading and writing - have had a missing 'const' added to their char *
parameters / return values.)
I don't expect this change to enable any particularly interesting new
functionality (in particular, I have no plans that need more than one
implementation of TermWin in the same application). But it completes
the tidying-up that began with the Seat and LogContext rework.
2018-10-25 17:44:04 +00:00
|
|
|
SetTextAlign(wintw_hdc, TA_TOP | TA_LEFT | TA_NOUPDATECP);
|
2010-12-29 23:48:54 +00:00
|
|
|
lpDx_maybe = lpDx;
|
2010-12-29 14:11:25 +00:00
|
|
|
maxlen = len;
|
|
|
|
}
|
|
|
|
|
2018-10-29 19:50:29 +00:00
|
|
|
opaque = true; /* start by erasing the rectangle */
|
2010-12-29 14:11:25 +00:00
|
|
|
for (remaining = len; remaining > 0;
|
2012-02-17 19:28:55 +00:00
|
|
|
text += len, remaining -= len, x += char_width * len2) {
|
2010-12-29 14:11:25 +00:00
|
|
|
len = (maxlen < remaining ? maxlen : remaining);
|
2012-02-17 19:28:55 +00:00
|
|
|
/* don't divide SURROGATE PAIR and VARIATION SELECTOR */
|
|
|
|
len2 = len;
|
|
|
|
if (maxlen == 1) {
|
|
|
|
if (remaining >= 1 && IS_SURROGATE_PAIR(text[0], text[1]))
|
|
|
|
len++;
|
|
|
|
if (remaining-len >= 1 && IS_LOW_VARSEL(text[len]))
|
|
|
|
len++;
|
|
|
|
else if (remaining-len >= 2 &&
|
|
|
|
IS_HIGH_VARSEL(text[len], text[len+1]))
|
|
|
|
len += 2;
|
|
|
|
}
|
2010-12-29 14:11:25 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
if (len > lpDx_len) {
|
New array-growing macros: sgrowarray and sgrowarrayn.
The idea of these is that they centralise the common idiom along the
lines of
if (logical_array_len >= physical_array_size) {
physical_array_size = logical_array_len * 5 / 4 + 256;
array = sresize(array, physical_array_size, ElementType);
}
which happens at a zillion call sites throughout this code base, with
different random choices of the geometric factor and additive
constant, sometimes forgetting them completely, and generally doing a
lot of repeated work.
The new macro sgrowarray(array,size,n) has the semantics: here are the
array pointer and its physical size for you to modify, now please
ensure that the nth element exists, so I can write into it. And
sgrowarrayn(array,size,n,m) is the same except that it ensures that
the array has size at least n+m (so sgrowarray is just the special
case where m=1).
Now that this is a single centralised implementation that will be used
everywhere, I've also gone to more effort in the implementation, with
careful overflow checks that would have been painful to put at all the
previous call sites.
This commit also switches over every use of sresize(), apart from a
few where I really didn't think it would gain anything. A consequence
of that is that a lot of array-size variables have to have their types
changed to size_t, because the macros require that (they address-take
the size to pass to the underlying function).
2019-02-28 20:07:30 +00:00
|
|
|
sgrowarray(lpDx, lpDx_len, len);
|
2019-09-08 19:29:00 +00:00
|
|
|
if (lpDx_maybe) lpDx_maybe = lpDx;
|
|
|
|
}
|
2012-05-13 15:59:22 +00:00
|
|
|
|
2010-12-29 23:48:54 +00:00
|
|
|
{
|
|
|
|
int i;
|
2012-02-17 19:28:55 +00:00
|
|
|
/* only last char has dx width in SURROGATE PAIR and
|
|
|
|
* VARIATION sequence */
|
|
|
|
for (i = 0; i < len; i++) {
|
2010-12-29 23:48:54 +00:00
|
|
|
lpDx[i] = char_width;
|
2012-02-17 19:28:55 +00:00
|
|
|
if (i+1 < len && IS_HIGH_VARSEL(text[i], text[i+1])) {
|
|
|
|
if (i > 0) lpDx[i-1] = 0;
|
|
|
|
lpDx[i] = 0;
|
|
|
|
i++;
|
|
|
|
lpDx[i] = char_width;
|
|
|
|
} else if (i+1 < len && IS_SURROGATE_PAIR(text[i],text[i+1])) {
|
|
|
|
lpDx[i] = 0;
|
|
|
|
i++;
|
|
|
|
lpDx[i] = char_width;
|
|
|
|
} else if (IS_LOW_VARSEL(text[i])) {
|
|
|
|
if (i > 0) lpDx[i-1] = 0;
|
|
|
|
lpDx[i] = char_width;
|
|
|
|
}
|
|
|
|
}
|
2010-12-29 23:48:54 +00:00
|
|
|
}
|
|
|
|
|
2010-12-29 14:11:25 +00:00
|
|
|
/* We're using a private area for direct to font. (512 chars.) */
|
|
|
|
if (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;
|
|
|
|
static int uni_len = 0;
|
|
|
|
int nlen, mptr;
|
|
|
|
if (len > uni_len) {
|
|
|
|
sfree(uni_buf);
|
|
|
|
uni_len = len;
|
|
|
|
uni_buf = snewn(uni_len, wchar_t);
|
|
|
|
}
|
Re-engineering of terminal emulator, phase 1.
The active terminal screen is no longer an array of `unsigned long'
encoding 16-bit Unicode plus 16 attribute bits. Now it's an array of
`termchar' structures, which currently have 32-bit Unicode and 32
attribute bits but which will probably expand further in future.
To prevent bloat of the memory footprint, I've introduced a mostly
RLE-like compression scheme for storing scrollback: each line is
compressed into a compact (but hard to modify) form when it moves
into the term->scrollback tree, and is temporarily decompressed when
the user wants to scroll back over it. My initial tests suggest that
this compression averages about 1/4 of the previous (32 bits per
character cell) data size in typical output, which means this is an
improvement even without counting the new ability to extend the
information stored in each character cell.
Another beneficial side effect is that the insane format in which
Unicode was passed to front ends through do_text() has now been
rendered sane.
Testing is incomplete; this _may_ still have instabilities. Windows
and Unix front ends both seem to work as far as I've looked, but I
haven't yet looked very hard. The Mac front end I've edited (it
seemed obvious how to change it) but I can't compile or test it.
As an immediate functional effect, the terminal emulator now
supports full 32-bit Unicode to whatever extent the host platform
allows it to. For example, if you output a 4-or-more-byte UTF-8
character in Unix pterm, it will not display it properly, but it
will correctly paste it back out in a UTF8_STRING selection. Windows
is more restricted, sadly.
[originally from svn r4609]
2004-10-13 11:50:16 +00:00
|
|
|
|
2010-12-29 14:11:25 +00:00
|
|
|
for(nlen = mptr = 0; mptr<len; mptr++) {
|
|
|
|
uni_buf[nlen] = 0xFFFD;
|
|
|
|
if (IsDBCSLeadByteEx(ucsdata.font_codepage,
|
|
|
|
(BYTE) text[mptr])) {
|
|
|
|
char dbcstext[2];
|
|
|
|
dbcstext[0] = text[mptr] & 0xFF;
|
|
|
|
dbcstext[1] = text[mptr+1] & 0xFF;
|
2010-12-29 23:48:54 +00:00
|
|
|
lpDx[nlen] += char_width;
|
2010-12-29 14:11:25 +00:00
|
|
|
MultiByteToWideChar(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);
|
|
|
|
}
|
|
|
|
nlen++;
|
|
|
|
}
|
|
|
|
if (nlen <= 0)
|
2019-09-08 19:29:00 +00:00
|
|
|
return; /* Eeek! */
|
2010-12-29 14:11:25 +00:00
|
|
|
|
Remove the 'Frontend' type and replace it with a vtable.
After the recent Seat and LogContext revamps, _nearly_ all the
remaining uses of the type 'Frontend' were in terminal.c, which needs
all sorts of interactions with the GUI window the terminal lives in,
from the obvious (actually drawing text on the window, reading and
writing the clipboard) to the obscure (minimising, maximising and
moving the window in response to particular escape sequences).
All of those functions are now provided by an abstraction called
TermWin. The few remaining uses of Frontend after _that_ are internal
to a particular platform directory, so as to spread the implementation
of that particular kind of Frontend between multiple source files; so
I've renamed all of those so that they take a more specifically named
type that refers to the particular implementation rather than the
general abstraction.
So now the name 'Frontend' no longer exists in the code base at all,
and everywhere one used to be used, it's completely clear whether it
was operating in one of Frontend's three abstract roles (and if so,
which), or whether it was specific to a particular implementation.
Another type that's disappeared is 'Context', which used to be a
typedef defined to something different on each platform, describing
whatever short-lived resources were necessary to draw on the terminal
window: the front end would provide a ready-made one when calling
term_paint, and the terminal could request one with get_ctx/free_ctx
if it wanted to do proactive window updates. Now that drawing context
lives inside the TermWin itself, because there was never any need to
have two of those contexts live at the same time.
(Another minor API change is that the window-title functions - both
reading and writing - have had a missing 'const' added to their char *
parameters / return values.)
I don't expect this change to enable any particularly interesting new
functionality (in particular, I have no plans that need more than one
implementation of TermWin in the same application). But it completes
the tidying-up that began with the Seat and LogContext rework.
2018-10-25 17:44:04 +00:00
|
|
|
ExtTextOutW(wintw_hdc, x + xoffset,
|
2010-12-29 14:11:25 +00:00
|
|
|
y - font_height * (lattr == LATTR_BOT) + text_adjust,
|
|
|
|
ETO_CLIPPED | (opaque ? ETO_OPAQUE : 0),
|
|
|
|
&line_box, uni_buf, nlen,
|
2010-12-29 23:48:54 +00:00
|
|
|
lpDx_maybe);
|
2012-06-09 15:09:22 +00:00
|
|
|
if (bold_font_mode == BOLD_SHADOW && (attr & ATTR_BOLD)) {
|
Remove the 'Frontend' type and replace it with a vtable.
After the recent Seat and LogContext revamps, _nearly_ all the
remaining uses of the type 'Frontend' were in terminal.c, which needs
all sorts of interactions with the GUI window the terminal lives in,
from the obvious (actually drawing text on the window, reading and
writing the clipboard) to the obscure (minimising, maximising and
moving the window in response to particular escape sequences).
All of those functions are now provided by an abstraction called
TermWin. The few remaining uses of Frontend after _that_ are internal
to a particular platform directory, so as to spread the implementation
of that particular kind of Frontend between multiple source files; so
I've renamed all of those so that they take a more specifically named
type that refers to the particular implementation rather than the
general abstraction.
So now the name 'Frontend' no longer exists in the code base at all,
and everywhere one used to be used, it's completely clear whether it
was operating in one of Frontend's three abstract roles (and if so,
which), or whether it was specific to a particular implementation.
Another type that's disappeared is 'Context', which used to be a
typedef defined to something different on each platform, describing
whatever short-lived resources were necessary to draw on the terminal
window: the front end would provide a ready-made one when calling
term_paint, and the terminal could request one with get_ctx/free_ctx
if it wanted to do proactive window updates. Now that drawing context
lives inside the TermWin itself, because there was never any need to
have two of those contexts live at the same time.
(Another minor API change is that the window-title functions - both
reading and writing - have had a missing 'const' added to their char *
parameters / return values.)
I don't expect this change to enable any particularly interesting new
functionality (in particular, I have no plans that need more than one
implementation of TermWin in the same application). But it completes
the tidying-up that began with the Seat and LogContext rework.
2018-10-25 17:44:04 +00:00
|
|
|
SetBkMode(wintw_hdc, TRANSPARENT);
|
|
|
|
ExtTextOutW(wintw_hdc, x + xoffset - 1,
|
2010-12-29 14:11:25 +00:00
|
|
|
y - font_height * (lattr ==
|
|
|
|
LATTR_BOT) + text_adjust,
|
2010-12-29 23:48:54 +00:00
|
|
|
ETO_CLIPPED, &line_box, uni_buf, nlen, lpDx_maybe);
|
2010-12-29 14:11:25 +00:00
|
|
|
}
|
Re-engineering of terminal emulator, phase 1.
The active terminal screen is no longer an array of `unsigned long'
encoding 16-bit Unicode plus 16 attribute bits. Now it's an array of
`termchar' structures, which currently have 32-bit Unicode and 32
attribute bits but which will probably expand further in future.
To prevent bloat of the memory footprint, I've introduced a mostly
RLE-like compression scheme for storing scrollback: each line is
compressed into a compact (but hard to modify) form when it moves
into the term->scrollback tree, and is temporarily decompressed when
the user wants to scroll back over it. My initial tests suggest that
this compression averages about 1/4 of the previous (32 bits per
character cell) data size in typical output, which means this is an
improvement even without counting the new ability to extend the
information stored in each character cell.
Another beneficial side effect is that the insane format in which
Unicode was passed to front ends through do_text() has now been
rendered sane.
Testing is incomplete; this _may_ still have instabilities. Windows
and Unix front ends both seem to work as far as I've looked, but I
haven't yet looked very hard. The Mac front end I've edited (it
seemed obvious how to change it) but I can't compile or test it.
As an immediate functional effect, the terminal emulator now
supports full 32-bit Unicode to whatever extent the host platform
allows it to. For example, if you output a 4-or-more-byte UTF-8
character in Unix pterm, it will not display it properly, but it
will correctly paste it back out in a UTF8_STRING selection. Windows
is more restricted, sadly.
[originally from svn r4609]
2004-10-13 11:50:16 +00:00
|
|
|
|
2010-12-29 23:48:54 +00:00
|
|
|
lpDx[0] = -1;
|
2010-12-29 14:11:25 +00:00
|
|
|
} else if (DIRECT_FONT(text[0])) {
|
|
|
|
static char *directbuf = NULL;
|
New array-growing macros: sgrowarray and sgrowarrayn.
The idea of these is that they centralise the common idiom along the
lines of
if (logical_array_len >= physical_array_size) {
physical_array_size = logical_array_len * 5 / 4 + 256;
array = sresize(array, physical_array_size, ElementType);
}
which happens at a zillion call sites throughout this code base, with
different random choices of the geometric factor and additive
constant, sometimes forgetting them completely, and generally doing a
lot of repeated work.
The new macro sgrowarray(array,size,n) has the semantics: here are the
array pointer and its physical size for you to modify, now please
ensure that the nth element exists, so I can write into it. And
sgrowarrayn(array,size,n,m) is the same except that it ensures that
the array has size at least n+m (so sgrowarray is just the special
case where m=1).
Now that this is a single centralised implementation that will be used
everywhere, I've also gone to more effort in the implementation, with
careful overflow checks that would have been painful to put at all the
previous call sites.
This commit also switches over every use of sresize(), apart from a
few where I really didn't think it would gain anything. A consequence
of that is that a lot of array-size variables have to have their types
changed to size_t, because the macros require that (they address-take
the size to pass to the underlying function).
2019-02-28 20:07:30 +00:00
|
|
|
static size_t directlen = 0;
|
2001-05-10 08:34:20 +00:00
|
|
|
|
New array-growing macros: sgrowarray and sgrowarrayn.
The idea of these is that they centralise the common idiom along the
lines of
if (logical_array_len >= physical_array_size) {
physical_array_size = logical_array_len * 5 / 4 + 256;
array = sresize(array, physical_array_size, ElementType);
}
which happens at a zillion call sites throughout this code base, with
different random choices of the geometric factor and additive
constant, sometimes forgetting them completely, and generally doing a
lot of repeated work.
The new macro sgrowarray(array,size,n) has the semantics: here are the
array pointer and its physical size for you to modify, now please
ensure that the nth element exists, so I can write into it. And
sgrowarrayn(array,size,n,m) is the same except that it ensures that
the array has size at least n+m (so sgrowarray is just the special
case where m=1).
Now that this is a single centralised implementation that will be used
everywhere, I've also gone to more effort in the implementation, with
careful overflow checks that would have been painful to put at all the
previous call sites.
This commit also switches over every use of sresize(), apart from a
few where I really didn't think it would gain anything. A consequence
of that is that a lot of array-size variables have to have their types
changed to size_t, because the macros require that (they address-take
the size to pass to the underlying function).
2019-02-28 20:07:30 +00:00
|
|
|
sgrowarray(directbuf, directlen, len);
|
|
|
|
for (size_t i = 0; i < len; i++)
|
2010-12-29 14:11:25 +00:00
|
|
|
directbuf[i] = text[i] & 0xFF;
|
|
|
|
|
Remove the 'Frontend' type and replace it with a vtable.
After the recent Seat and LogContext revamps, _nearly_ all the
remaining uses of the type 'Frontend' were in terminal.c, which needs
all sorts of interactions with the GUI window the terminal lives in,
from the obvious (actually drawing text on the window, reading and
writing the clipboard) to the obscure (minimising, maximising and
moving the window in response to particular escape sequences).
All of those functions are now provided by an abstraction called
TermWin. The few remaining uses of Frontend after _that_ are internal
to a particular platform directory, so as to spread the implementation
of that particular kind of Frontend between multiple source files; so
I've renamed all of those so that they take a more specifically named
type that refers to the particular implementation rather than the
general abstraction.
So now the name 'Frontend' no longer exists in the code base at all,
and everywhere one used to be used, it's completely clear whether it
was operating in one of Frontend's three abstract roles (and if so,
which), or whether it was specific to a particular implementation.
Another type that's disappeared is 'Context', which used to be a
typedef defined to something different on each platform, describing
whatever short-lived resources were necessary to draw on the terminal
window: the front end would provide a ready-made one when calling
term_paint, and the terminal could request one with get_ctx/free_ctx
if it wanted to do proactive window updates. Now that drawing context
lives inside the TermWin itself, because there was never any need to
have two of those contexts live at the same time.
(Another minor API change is that the window-title functions - both
reading and writing - have had a missing 'const' added to their char *
parameters / return values.)
I don't expect this change to enable any particularly interesting new
functionality (in particular, I have no plans that need more than one
implementation of TermWin in the same application). But it completes
the tidying-up that began with the Seat and LogContext rework.
2018-10-25 17:44:04 +00:00
|
|
|
ExtTextOut(wintw_hdc, x + xoffset,
|
2010-12-29 14:11:25 +00:00
|
|
|
y - font_height * (lattr == LATTR_BOT) + text_adjust,
|
|
|
|
ETO_CLIPPED | (opaque ? ETO_OPAQUE : 0),
|
2010-12-29 23:48:54 +00:00
|
|
|
&line_box, directbuf, len, lpDx_maybe);
|
2012-06-09 15:09:22 +00:00
|
|
|
if (bold_font_mode == BOLD_SHADOW && (attr & ATTR_BOLD)) {
|
Remove the 'Frontend' type and replace it with a vtable.
After the recent Seat and LogContext revamps, _nearly_ all the
remaining uses of the type 'Frontend' were in terminal.c, which needs
all sorts of interactions with the GUI window the terminal lives in,
from the obvious (actually drawing text on the window, reading and
writing the clipboard) to the obscure (minimising, maximising and
moving the window in response to particular escape sequences).
All of those functions are now provided by an abstraction called
TermWin. The few remaining uses of Frontend after _that_ are internal
to a particular platform directory, so as to spread the implementation
of that particular kind of Frontend between multiple source files; so
I've renamed all of those so that they take a more specifically named
type that refers to the particular implementation rather than the
general abstraction.
So now the name 'Frontend' no longer exists in the code base at all,
and everywhere one used to be used, it's completely clear whether it
was operating in one of Frontend's three abstract roles (and if so,
which), or whether it was specific to a particular implementation.
Another type that's disappeared is 'Context', which used to be a
typedef defined to something different on each platform, describing
whatever short-lived resources were necessary to draw on the terminal
window: the front end would provide a ready-made one when calling
term_paint, and the terminal could request one with get_ctx/free_ctx
if it wanted to do proactive window updates. Now that drawing context
lives inside the TermWin itself, because there was never any need to
have two of those contexts live at the same time.
(Another minor API change is that the window-title functions - both
reading and writing - have had a missing 'const' added to their char *
parameters / return values.)
I don't expect this change to enable any particularly interesting new
functionality (in particular, I have no plans that need more than one
implementation of TermWin in the same application). But it completes
the tidying-up that began with the Seat and LogContext rework.
2018-10-25 17:44:04 +00:00
|
|
|
SetBkMode(wintw_hdc, TRANSPARENT);
|
2010-12-29 14:11:25 +00:00
|
|
|
|
|
|
|
/* GRR: This draws the character outside its box and
|
|
|
|
* can leave 'droppings' even with the clip box! I
|
|
|
|
* suppose I could loop it one character at a time ...
|
|
|
|
* yuk.
|
2019-09-08 19:29:00 +00:00
|
|
|
*
|
2010-12-29 14:11:25 +00:00
|
|
|
* Or ... I could do a test print with "W", and use +1
|
|
|
|
* or -1 for this shift depending on if the leftmost
|
|
|
|
* column is blank...
|
|
|
|
*/
|
Remove the 'Frontend' type and replace it with a vtable.
After the recent Seat and LogContext revamps, _nearly_ all the
remaining uses of the type 'Frontend' were in terminal.c, which needs
all sorts of interactions with the GUI window the terminal lives in,
from the obvious (actually drawing text on the window, reading and
writing the clipboard) to the obscure (minimising, maximising and
moving the window in response to particular escape sequences).
All of those functions are now provided by an abstraction called
TermWin. The few remaining uses of Frontend after _that_ are internal
to a particular platform directory, so as to spread the implementation
of that particular kind of Frontend between multiple source files; so
I've renamed all of those so that they take a more specifically named
type that refers to the particular implementation rather than the
general abstraction.
So now the name 'Frontend' no longer exists in the code base at all,
and everywhere one used to be used, it's completely clear whether it
was operating in one of Frontend's three abstract roles (and if so,
which), or whether it was specific to a particular implementation.
Another type that's disappeared is 'Context', which used to be a
typedef defined to something different on each platform, describing
whatever short-lived resources were necessary to draw on the terminal
window: the front end would provide a ready-made one when calling
term_paint, and the terminal could request one with get_ctx/free_ctx
if it wanted to do proactive window updates. Now that drawing context
lives inside the TermWin itself, because there was never any need to
have two of those contexts live at the same time.
(Another minor API change is that the window-title functions - both
reading and writing - have had a missing 'const' added to their char *
parameters / return values.)
I don't expect this change to enable any particularly interesting new
functionality (in particular, I have no plans that need more than one
implementation of TermWin in the same application). But it completes
the tidying-up that began with the Seat and LogContext rework.
2018-10-25 17:44:04 +00:00
|
|
|
ExtTextOut(wintw_hdc, x + xoffset - 1,
|
2010-12-29 14:11:25 +00:00
|
|
|
y - font_height * (lattr ==
|
|
|
|
LATTR_BOT) + text_adjust,
|
2010-12-29 23:48:54 +00:00
|
|
|
ETO_CLIPPED, &line_box, directbuf, len, lpDx_maybe);
|
2010-12-29 14:11:25 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
/* And 'normal' unicode characters */
|
|
|
|
static WCHAR *wbuf = NULL;
|
|
|
|
static int wlen = 0;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (wlen < len) {
|
|
|
|
sfree(wbuf);
|
|
|
|
wlen = len;
|
|
|
|
wbuf = snewn(wlen, WCHAR);
|
|
|
|
}
|
2004-10-14 16:42:43 +00:00
|
|
|
|
2010-12-29 14:11:25 +00:00
|
|
|
for (i = 0; i < len; i++)
|
|
|
|
wbuf[i] = text[i];
|
|
|
|
|
|
|
|
/* print Glyphs as they are, without Windows' Shaping*/
|
Remove the 'Frontend' type and replace it with a vtable.
After the recent Seat and LogContext revamps, _nearly_ all the
remaining uses of the type 'Frontend' were in terminal.c, which needs
all sorts of interactions with the GUI window the terminal lives in,
from the obvious (actually drawing text on the window, reading and
writing the clipboard) to the obscure (minimising, maximising and
moving the window in response to particular escape sequences).
All of those functions are now provided by an abstraction called
TermWin. The few remaining uses of Frontend after _that_ are internal
to a particular platform directory, so as to spread the implementation
of that particular kind of Frontend between multiple source files; so
I've renamed all of those so that they take a more specifically named
type that refers to the particular implementation rather than the
general abstraction.
So now the name 'Frontend' no longer exists in the code base at all,
and everywhere one used to be used, it's completely clear whether it
was operating in one of Frontend's three abstract roles (and if so,
which), or whether it was specific to a particular implementation.
Another type that's disappeared is 'Context', which used to be a
typedef defined to something different on each platform, describing
whatever short-lived resources were necessary to draw on the terminal
window: the front end would provide a ready-made one when calling
term_paint, and the terminal could request one with get_ctx/free_ctx
if it wanted to do proactive window updates. Now that drawing context
lives inside the TermWin itself, because there was never any need to
have two of those contexts live at the same time.
(Another minor API change is that the window-title functions - both
reading and writing - have had a missing 'const' added to their char *
parameters / return values.)
I don't expect this change to enable any particularly interesting new
functionality (in particular, I have no plans that need more than one
implementation of TermWin in the same application). But it completes
the tidying-up that began with the Seat and LogContext rework.
2018-10-25 17:44:04 +00:00
|
|
|
general_textout(wintw_hdc, x + xoffset,
|
2010-12-29 14:11:25 +00:00
|
|
|
y - font_height * (lattr==LATTR_BOT) + text_adjust,
|
2010-12-29 23:48:54 +00:00
|
|
|
&line_box, wbuf, len, lpDx,
|
2010-12-29 14:11:25 +00:00
|
|
|
opaque && !(attr & TATTR_COMBINING));
|
|
|
|
|
|
|
|
/* And the shadow bold hack. */
|
2012-06-09 15:09:22 +00:00
|
|
|
if (bold_font_mode == BOLD_SHADOW && (attr & ATTR_BOLD)) {
|
Remove the 'Frontend' type and replace it with a vtable.
After the recent Seat and LogContext revamps, _nearly_ all the
remaining uses of the type 'Frontend' were in terminal.c, which needs
all sorts of interactions with the GUI window the terminal lives in,
from the obvious (actually drawing text on the window, reading and
writing the clipboard) to the obscure (minimising, maximising and
moving the window in response to particular escape sequences).
All of those functions are now provided by an abstraction called
TermWin. The few remaining uses of Frontend after _that_ are internal
to a particular platform directory, so as to spread the implementation
of that particular kind of Frontend between multiple source files; so
I've renamed all of those so that they take a more specifically named
type that refers to the particular implementation rather than the
general abstraction.
So now the name 'Frontend' no longer exists in the code base at all,
and everywhere one used to be used, it's completely clear whether it
was operating in one of Frontend's three abstract roles (and if so,
which), or whether it was specific to a particular implementation.
Another type that's disappeared is 'Context', which used to be a
typedef defined to something different on each platform, describing
whatever short-lived resources were necessary to draw on the terminal
window: the front end would provide a ready-made one when calling
term_paint, and the terminal could request one with get_ctx/free_ctx
if it wanted to do proactive window updates. Now that drawing context
lives inside the TermWin itself, because there was never any need to
have two of those contexts live at the same time.
(Another minor API change is that the window-title functions - both
reading and writing - have had a missing 'const' added to their char *
parameters / return values.)
I don't expect this change to enable any particularly interesting new
functionality (in particular, I have no plans that need more than one
implementation of TermWin in the same application). But it completes
the tidying-up that began with the Seat and LogContext rework.
2018-10-25 17:44:04 +00:00
|
|
|
SetBkMode(wintw_hdc, TRANSPARENT);
|
|
|
|
ExtTextOutW(wintw_hdc, x + xoffset - 1,
|
2010-12-29 14:11:25 +00:00
|
|
|
y - font_height * (lattr ==
|
|
|
|
LATTR_BOT) + text_adjust,
|
2010-12-29 23:48:54 +00:00
|
|
|
ETO_CLIPPED, &line_box, wbuf, len, lpDx_maybe);
|
2010-12-29 14:11:25 +00:00
|
|
|
}
|
|
|
|
}
|
2004-10-14 16:42:43 +00:00
|
|
|
|
2010-12-29 14:11:25 +00:00
|
|
|
/*
|
|
|
|
* If we're looping round again, stop erasing the background
|
|
|
|
* rectangle.
|
|
|
|
*/
|
Remove the 'Frontend' type and replace it with a vtable.
After the recent Seat and LogContext revamps, _nearly_ all the
remaining uses of the type 'Frontend' were in terminal.c, which needs
all sorts of interactions with the GUI window the terminal lives in,
from the obvious (actually drawing text on the window, reading and
writing the clipboard) to the obscure (minimising, maximising and
moving the window in response to particular escape sequences).
All of those functions are now provided by an abstraction called
TermWin. The few remaining uses of Frontend after _that_ are internal
to a particular platform directory, so as to spread the implementation
of that particular kind of Frontend between multiple source files; so
I've renamed all of those so that they take a more specifically named
type that refers to the particular implementation rather than the
general abstraction.
So now the name 'Frontend' no longer exists in the code base at all,
and everywhere one used to be used, it's completely clear whether it
was operating in one of Frontend's three abstract roles (and if so,
which), or whether it was specific to a particular implementation.
Another type that's disappeared is 'Context', which used to be a
typedef defined to something different on each platform, describing
whatever short-lived resources were necessary to draw on the terminal
window: the front end would provide a ready-made one when calling
term_paint, and the terminal could request one with get_ctx/free_ctx
if it wanted to do proactive window updates. Now that drawing context
lives inside the TermWin itself, because there was never any need to
have two of those contexts live at the same time.
(Another minor API change is that the window-title functions - both
reading and writing - have had a missing 'const' added to their char *
parameters / return values.)
I don't expect this change to enable any particularly interesting new
functionality (in particular, I have no plans that need more than one
implementation of TermWin in the same application). But it completes
the tidying-up that began with the Seat and LogContext rework.
2018-10-25 17:44:04 +00:00
|
|
|
SetBkMode(wintw_hdc, TRANSPARENT);
|
2018-10-29 19:50:29 +00:00
|
|
|
opaque = false;
|
1999-01-08 13:02:13 +00:00
|
|
|
}
|
2020-08-13 20:08:53 +00:00
|
|
|
|
2001-05-10 08:34:20 +00:00
|
|
|
if (lattr != LATTR_TOP && (force_manual_underline ||
|
2020-08-13 20:08:53 +00:00
|
|
|
(und_mode == UND_LINE && (attr & ATTR_UNDER))))
|
|
|
|
draw_horizontal_line_on_text(descent, lattr, line_box, fg);
|
2019-09-08 19:29:00 +00:00
|
|
|
|
2020-08-13 20:08:53 +00:00
|
|
|
if (attr & ATTR_STRIKE)
|
|
|
|
draw_horizontal_line_on_text(font_strikethrough_y, lattr, line_box, fg);
|
2001-05-10 08:34:20 +00:00
|
|
|
}
|
|
|
|
|
2004-10-14 16:42:43 +00:00
|
|
|
/*
|
|
|
|
* Wrapper that handles combining characters.
|
|
|
|
*/
|
Remove the 'Frontend' type and replace it with a vtable.
After the recent Seat and LogContext revamps, _nearly_ all the
remaining uses of the type 'Frontend' were in terminal.c, which needs
all sorts of interactions with the GUI window the terminal lives in,
from the obvious (actually drawing text on the window, reading and
writing the clipboard) to the obscure (minimising, maximising and
moving the window in response to particular escape sequences).
All of those functions are now provided by an abstraction called
TermWin. The few remaining uses of Frontend after _that_ are internal
to a particular platform directory, so as to spread the implementation
of that particular kind of Frontend between multiple source files; so
I've renamed all of those so that they take a more specifically named
type that refers to the particular implementation rather than the
general abstraction.
So now the name 'Frontend' no longer exists in the code base at all,
and everywhere one used to be used, it's completely clear whether it
was operating in one of Frontend's three abstract roles (and if so,
which), or whether it was specific to a particular implementation.
Another type that's disappeared is 'Context', which used to be a
typedef defined to something different on each platform, describing
whatever short-lived resources were necessary to draw on the terminal
window: the front end would provide a ready-made one when calling
term_paint, and the terminal could request one with get_ctx/free_ctx
if it wanted to do proactive window updates. Now that drawing context
lives inside the TermWin itself, because there was never any need to
have two of those contexts live at the same time.
(Another minor API change is that the window-title functions - both
reading and writing - have had a missing 'const' added to their char *
parameters / return values.)
I don't expect this change to enable any particularly interesting new
functionality (in particular, I have no plans that need more than one
implementation of TermWin in the same application). But it completes
the tidying-up that began with the Seat and LogContext rework.
2018-10-25 17:44:04 +00:00
|
|
|
static void wintw_draw_text(
|
|
|
|
TermWin *tw, int x, int y, wchar_t *text, int len,
|
|
|
|
unsigned long attr, int lattr, truecolour truecolour)
|
2004-10-14 16:42:43 +00:00
|
|
|
{
|
|
|
|
if (attr & TATTR_COMBINING) {
|
2019-09-08 19:29:00 +00:00
|
|
|
unsigned long a = 0;
|
|
|
|
int len0 = 1;
|
2012-02-17 19:28:55 +00:00
|
|
|
/* don't divide SURROGATE PAIR and VARIATION SELECTOR */
|
2019-09-08 19:29:00 +00:00
|
|
|
if (len >= 2 && IS_SURROGATE_PAIR(text[0], text[1]))
|
|
|
|
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);
|
|
|
|
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);
|
|
|
|
text += len0+2;
|
|
|
|
len -= len0+2;
|
|
|
|
a = TATTR_COMBINING;
|
|
|
|
} else {
|
2012-02-17 19:28:55 +00:00
|
|
|
attr &= ~TATTR_COMBINING;
|
|
|
|
}
|
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
while (len--) {
|
|
|
|
if (len >= 1 && IS_SURROGATE_PAIR(text[0], text[1])) {
|
|
|
|
do_text_internal(x, y, text, 2, attr | a, lattr, truecolour);
|
|
|
|
len--;
|
|
|
|
text++;
|
|
|
|
} else
|
Remove the 'Frontend' type and replace it with a vtable.
After the recent Seat and LogContext revamps, _nearly_ all the
remaining uses of the type 'Frontend' were in terminal.c, which needs
all sorts of interactions with the GUI window the terminal lives in,
from the obvious (actually drawing text on the window, reading and
writing the clipboard) to the obscure (minimising, maximising and
moving the window in response to particular escape sequences).
All of those functions are now provided by an abstraction called
TermWin. The few remaining uses of Frontend after _that_ are internal
to a particular platform directory, so as to spread the implementation
of that particular kind of Frontend between multiple source files; so
I've renamed all of those so that they take a more specifically named
type that refers to the particular implementation rather than the
general abstraction.
So now the name 'Frontend' no longer exists in the code base at all,
and everywhere one used to be used, it's completely clear whether it
was operating in one of Frontend's three abstract roles (and if so,
which), or whether it was specific to a particular implementation.
Another type that's disappeared is 'Context', which used to be a
typedef defined to something different on each platform, describing
whatever short-lived resources were necessary to draw on the terminal
window: the front end would provide a ready-made one when calling
term_paint, and the terminal could request one with get_ctx/free_ctx
if it wanted to do proactive window updates. Now that drawing context
lives inside the TermWin itself, because there was never any need to
have two of those contexts live at the same time.
(Another minor API change is that the window-title functions - both
reading and writing - have had a missing 'const' added to their char *
parameters / return values.)
I don't expect this change to enable any particularly interesting new
functionality (in particular, I have no plans that need more than one
implementation of TermWin in the same application). But it completes
the tidying-up that began with the Seat and LogContext rework.
2018-10-25 17:44:04 +00:00
|
|
|
do_text_internal(x, y, text, 1, attr | a, lattr, truecolour);
|
2012-02-17 19:28:55 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
text++;
|
|
|
|
a = TATTR_COMBINING;
|
|
|
|
}
|
2004-10-14 16:42:43 +00:00
|
|
|
} else
|
2019-09-08 19:29:00 +00:00
|
|
|
do_text_internal(x, y, text, len, attr, lattr, truecolour);
|
2004-10-14 16:42:43 +00:00
|
|
|
}
|
|
|
|
|
Remove the 'Frontend' type and replace it with a vtable.
After the recent Seat and LogContext revamps, _nearly_ all the
remaining uses of the type 'Frontend' were in terminal.c, which needs
all sorts of interactions with the GUI window the terminal lives in,
from the obvious (actually drawing text on the window, reading and
writing the clipboard) to the obscure (minimising, maximising and
moving the window in response to particular escape sequences).
All of those functions are now provided by an abstraction called
TermWin. The few remaining uses of Frontend after _that_ are internal
to a particular platform directory, so as to spread the implementation
of that particular kind of Frontend between multiple source files; so
I've renamed all of those so that they take a more specifically named
type that refers to the particular implementation rather than the
general abstraction.
So now the name 'Frontend' no longer exists in the code base at all,
and everywhere one used to be used, it's completely clear whether it
was operating in one of Frontend's three abstract roles (and if so,
which), or whether it was specific to a particular implementation.
Another type that's disappeared is 'Context', which used to be a
typedef defined to something different on each platform, describing
whatever short-lived resources were necessary to draw on the terminal
window: the front end would provide a ready-made one when calling
term_paint, and the terminal could request one with get_ctx/free_ctx
if it wanted to do proactive window updates. Now that drawing context
lives inside the TermWin itself, because there was never any need to
have two of those contexts live at the same time.
(Another minor API change is that the window-title functions - both
reading and writing - have had a missing 'const' added to their char *
parameters / return values.)
I don't expect this change to enable any particularly interesting new
functionality (in particular, I have no plans that need more than one
implementation of TermWin in the same application). But it completes
the tidying-up that began with the Seat and LogContext rework.
2018-10-25 17:44:04 +00:00
|
|
|
static void wintw_draw_cursor(
|
|
|
|
TermWin *tw, int x, int y, wchar_t *text, int len,
|
|
|
|
unsigned long attr, int lattr, truecolour truecolour)
|
2001-05-10 08:34:20 +00:00
|
|
|
{
|
|
|
|
int fnt_width;
|
|
|
|
int char_width;
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
int ctype = cursor_type;
|
2001-05-10 08:34:20 +00:00
|
|
|
|
2004-11-11 09:40:50 +00:00
|
|
|
lattr &= LATTR_MODE;
|
|
|
|
|
2002-10-22 16:11:33 +00:00
|
|
|
if ((attr & TATTR_ACTCURS) && (ctype == 0 || term->big_cursor)) {
|
2019-09-08 19:29:00 +00:00
|
|
|
if (*text != UCSWIDE) {
|
|
|
|
win_draw_text(tw, x, y, text, len, attr, lattr, truecolour);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ctype = 2;
|
|
|
|
attr |= TATTR_RIGHTCURS;
|
2001-05-10 08:34:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fnt_width = char_width = font_width * (1 + (lattr != LATTR_NORM));
|
|
|
|
if (attr & ATTR_WIDE)
|
2019-09-08 19:29:00 +00:00
|
|
|
char_width *= 2;
|
2001-05-10 08:34:20 +00:00
|
|
|
x *= fnt_width;
|
|
|
|
y *= font_height;
|
2001-09-15 15:54:24 +00:00
|
|
|
x += offset_width;
|
|
|
|
y += offset_height;
|
2001-05-10 08:34:20 +00:00
|
|
|
|
2002-10-22 16:11:33 +00:00
|
|
|
if ((attr & TATTR_PASCURS) && (ctype == 0 || term->big_cursor)) {
|
2019-09-08 19:29:00 +00:00
|
|
|
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);
|
|
|
|
DeleteObject(oldpen);
|
2001-05-10 08:34:20 +00:00
|
|
|
} else if ((attr & (TATTR_ACTCURS | TATTR_PASCURS)) && ctype != 0) {
|
2019-09-08 19:29:00 +00:00
|
|
|
int startx, starty, dx, dy, length, i;
|
|
|
|
if (ctype == 1) {
|
|
|
|
startx = x;
|
|
|
|
starty = y + descent;
|
|
|
|
dx = 1;
|
|
|
|
dy = 0;
|
|
|
|
length = char_width;
|
|
|
|
} else {
|
|
|
|
int xadjust = 0;
|
|
|
|
if (attr & TATTR_RIGHTCURS)
|
|
|
|
xadjust = char_width - 1;
|
|
|
|
startx = x + xadjust;
|
|
|
|
starty = y;
|
|
|
|
dx = 0;
|
|
|
|
dy = 1;
|
|
|
|
length = font_height;
|
|
|
|
}
|
|
|
|
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);
|
|
|
|
DeleteObject(oldpen);
|
|
|
|
} else {
|
|
|
|
for (i = 0; i < length; i++) {
|
|
|
|
if (i % 2 == 0) {
|
|
|
|
SetPixel(wintw_hdc, startx, starty, colours[261]);
|
|
|
|
}
|
|
|
|
startx += dx;
|
|
|
|
starty += dy;
|
|
|
|
}
|
|
|
|
}
|
2001-01-17 16:57:33 +00:00
|
|
|
}
|
1999-01-08 13:02:13 +00:00
|
|
|
}
|
|
|
|
|
2019-03-10 14:37:11 +00:00
|
|
|
static void wintw_draw_trust_sigil(TermWin *tw, int x, int y)
|
|
|
|
{
|
|
|
|
x *= font_width;
|
|
|
|
y *= font_height;
|
|
|
|
x += offset_width;
|
|
|
|
y += offset_height;
|
|
|
|
|
2019-03-30 15:44:01 +00:00
|
|
|
DrawIconEx(wintw_hdc, x, y, trust_icon, font_width * 2, font_height,
|
2019-03-10 14:37:11 +00:00
|
|
|
0, NULL, DI_NORMAL);
|
|
|
|
}
|
|
|
|
|
2001-09-15 15:54:24 +00:00
|
|
|
/* This function gets the actual width of a character in the normal font.
|
|
|
|
*/
|
Remove the 'Frontend' type and replace it with a vtable.
After the recent Seat and LogContext revamps, _nearly_ all the
remaining uses of the type 'Frontend' were in terminal.c, which needs
all sorts of interactions with the GUI window the terminal lives in,
from the obvious (actually drawing text on the window, reading and
writing the clipboard) to the obscure (minimising, maximising and
moving the window in response to particular escape sequences).
All of those functions are now provided by an abstraction called
TermWin. The few remaining uses of Frontend after _that_ are internal
to a particular platform directory, so as to spread the implementation
of that particular kind of Frontend between multiple source files; so
I've renamed all of those so that they take a more specifically named
type that refers to the particular implementation rather than the
general abstraction.
So now the name 'Frontend' no longer exists in the code base at all,
and everywhere one used to be used, it's completely clear whether it
was operating in one of Frontend's three abstract roles (and if so,
which), or whether it was specific to a particular implementation.
Another type that's disappeared is 'Context', which used to be a
typedef defined to something different on each platform, describing
whatever short-lived resources were necessary to draw on the terminal
window: the front end would provide a ready-made one when calling
term_paint, and the terminal could request one with get_ctx/free_ctx
if it wanted to do proactive window updates. Now that drawing context
lives inside the TermWin itself, because there was never any need to
have two of those contexts live at the same time.
(Another minor API change is that the window-title functions - both
reading and writing - have had a missing 'const' added to their char *
parameters / return values.)
I don't expect this change to enable any particularly interesting new
functionality (in particular, I have no plans that need more than one
implementation of TermWin in the same application). But it completes
the tidying-up that began with the Seat and LogContext rework.
2018-10-25 17:44:04 +00:00
|
|
|
static int wintw_char_width(TermWin *tw, int uc)
|
|
|
|
{
|
2001-09-15 15:54:24 +00:00
|
|
|
int ibuf = 0;
|
|
|
|
|
|
|
|
/* If the font max is the same as the font ave width then this
|
|
|
|
* function is a no-op.
|
|
|
|
*/
|
|
|
|
if (!font_dualwidth) return 1;
|
|
|
|
|
|
|
|
switch (uc & CSET_MASK) {
|
Re-engineering of terminal emulator, phase 1.
The active terminal screen is no longer an array of `unsigned long'
encoding 16-bit Unicode plus 16 attribute bits. Now it's an array of
`termchar' structures, which currently have 32-bit Unicode and 32
attribute bits but which will probably expand further in future.
To prevent bloat of the memory footprint, I've introduced a mostly
RLE-like compression scheme for storing scrollback: each line is
compressed into a compact (but hard to modify) form when it moves
into the term->scrollback tree, and is temporarily decompressed when
the user wants to scroll back over it. My initial tests suggest that
this compression averages about 1/4 of the previous (32 bits per
character cell) data size in typical output, which means this is an
improvement even without counting the new ability to extend the
information stored in each character cell.
Another beneficial side effect is that the insane format in which
Unicode was passed to front ends through do_text() has now been
rendered sane.
Testing is incomplete; this _may_ still have instabilities. Windows
and Unix front ends both seem to work as far as I've looked, but I
haven't yet looked very hard. The Mac front end I've edited (it
seemed obvious how to change it) but I can't compile or test it.
As an immediate functional effect, the terminal emulator now
supports full 32-bit Unicode to whatever extent the host platform
allows it to. For example, if you output a 4-or-more-byte UTF-8
character in Unix pterm, it will not display it properly, but it
will correctly paste it back out in a UTF8_STRING selection. Windows
is more restricted, sadly.
[originally from svn r4609]
2004-10-13 11:50:16 +00:00
|
|
|
case CSET_ASCII:
|
2019-09-08 19:29:00 +00:00
|
|
|
uc = ucsdata.unitab_line[uc & 0xFF];
|
|
|
|
break;
|
Re-engineering of terminal emulator, phase 1.
The active terminal screen is no longer an array of `unsigned long'
encoding 16-bit Unicode plus 16 attribute bits. Now it's an array of
`termchar' structures, which currently have 32-bit Unicode and 32
attribute bits but which will probably expand further in future.
To prevent bloat of the memory footprint, I've introduced a mostly
RLE-like compression scheme for storing scrollback: each line is
compressed into a compact (but hard to modify) form when it moves
into the term->scrollback tree, and is temporarily decompressed when
the user wants to scroll back over it. My initial tests suggest that
this compression averages about 1/4 of the previous (32 bits per
character cell) data size in typical output, which means this is an
improvement even without counting the new ability to extend the
information stored in each character cell.
Another beneficial side effect is that the insane format in which
Unicode was passed to front ends through do_text() has now been
rendered sane.
Testing is incomplete; this _may_ still have instabilities. Windows
and Unix front ends both seem to work as far as I've looked, but I
haven't yet looked very hard. The Mac front end I've edited (it
seemed obvious how to change it) but I can't compile or test it.
As an immediate functional effect, the terminal emulator now
supports full 32-bit Unicode to whatever extent the host platform
allows it to. For example, if you output a 4-or-more-byte UTF-8
character in Unix pterm, it will not display it properly, but it
will correctly paste it back out in a UTF8_STRING selection. Windows
is more restricted, sadly.
[originally from svn r4609]
2004-10-13 11:50:16 +00:00
|
|
|
case CSET_LINEDRW:
|
2019-09-08 19:29:00 +00:00
|
|
|
uc = ucsdata.unitab_xterm[uc & 0xFF];
|
|
|
|
break;
|
Re-engineering of terminal emulator, phase 1.
The active terminal screen is no longer an array of `unsigned long'
encoding 16-bit Unicode plus 16 attribute bits. Now it's an array of
`termchar' structures, which currently have 32-bit Unicode and 32
attribute bits but which will probably expand further in future.
To prevent bloat of the memory footprint, I've introduced a mostly
RLE-like compression scheme for storing scrollback: each line is
compressed into a compact (but hard to modify) form when it moves
into the term->scrollback tree, and is temporarily decompressed when
the user wants to scroll back over it. My initial tests suggest that
this compression averages about 1/4 of the previous (32 bits per
character cell) data size in typical output, which means this is an
improvement even without counting the new ability to extend the
information stored in each character cell.
Another beneficial side effect is that the insane format in which
Unicode was passed to front ends through do_text() has now been
rendered sane.
Testing is incomplete; this _may_ still have instabilities. Windows
and Unix front ends both seem to work as far as I've looked, but I
haven't yet looked very hard. The Mac front end I've edited (it
seemed obvious how to change it) but I can't compile or test it.
As an immediate functional effect, the terminal emulator now
supports full 32-bit Unicode to whatever extent the host platform
allows it to. For example, if you output a 4-or-more-byte UTF-8
character in Unix pterm, it will not display it properly, but it
will correctly paste it back out in a UTF8_STRING selection. Windows
is more restricted, sadly.
[originally from svn r4609]
2004-10-13 11:50:16 +00:00
|
|
|
case CSET_SCOACS:
|
2019-09-08 19:29:00 +00:00
|
|
|
uc = ucsdata.unitab_scoacs[uc & 0xFF];
|
|
|
|
break;
|
2001-09-15 15:54:24 +00:00
|
|
|
}
|
|
|
|
if (DIRECT_FONT(uc)) {
|
2019-09-08 19:29:00 +00:00
|
|
|
if (ucsdata.dbcs_screenfont) return 1;
|
2001-09-15 15:54:24 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
/* Speedup, I know of no font where ascii is the wrong width */
|
|
|
|
if ((uc&~CSET_MASK) >= ' ' && (uc&~CSET_MASK)<= '~')
|
|
|
|
return 1;
|
2001-09-15 15:54:24 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
if ( (uc & CSET_MASK) == CSET_ACP ) {
|
|
|
|
SelectObject(wintw_hdc, fonts[FONT_NORMAL]);
|
|
|
|
} else if ( (uc & CSET_MASK) == CSET_OEMCP ) {
|
|
|
|
another_font(FONT_OEM);
|
|
|
|
if (!fonts[FONT_OEM]) return 0;
|
2001-09-15 15:54:24 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
SelectObject(wintw_hdc, fonts[FONT_OEM]);
|
|
|
|
} else
|
|
|
|
return 0;
|
2001-09-15 15:54:24 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
if (GetCharWidth32(wintw_hdc, uc & ~CSET_MASK,
|
Remove the 'Frontend' type and replace it with a vtable.
After the recent Seat and LogContext revamps, _nearly_ all the
remaining uses of the type 'Frontend' were in terminal.c, which needs
all sorts of interactions with the GUI window the terminal lives in,
from the obvious (actually drawing text on the window, reading and
writing the clipboard) to the obscure (minimising, maximising and
moving the window in response to particular escape sequences).
All of those functions are now provided by an abstraction called
TermWin. The few remaining uses of Frontend after _that_ are internal
to a particular platform directory, so as to spread the implementation
of that particular kind of Frontend between multiple source files; so
I've renamed all of those so that they take a more specifically named
type that refers to the particular implementation rather than the
general abstraction.
So now the name 'Frontend' no longer exists in the code base at all,
and everywhere one used to be used, it's completely clear whether it
was operating in one of Frontend's three abstract roles (and if so,
which), or whether it was specific to a particular implementation.
Another type that's disappeared is 'Context', which used to be a
typedef defined to something different on each platform, describing
whatever short-lived resources were necessary to draw on the terminal
window: the front end would provide a ready-made one when calling
term_paint, and the terminal could request one with get_ctx/free_ctx
if it wanted to do proactive window updates. Now that drawing context
lives inside the TermWin itself, because there was never any need to
have two of those contexts live at the same time.
(Another minor API change is that the window-title functions - both
reading and writing - have had a missing 'const' added to their char *
parameters / return values.)
I don't expect this change to enable any particularly interesting new
functionality (in particular, I have no plans that need more than one
implementation of TermWin in the same application). But it completes
the tidying-up that began with the Seat and LogContext rework.
2018-10-25 17:44:04 +00:00
|
|
|
uc & ~CSET_MASK, &ibuf) != 1 &&
|
2019-09-08 19:29:00 +00:00
|
|
|
GetCharWidth(wintw_hdc, uc & ~CSET_MASK,
|
Remove the 'Frontend' type and replace it with a vtable.
After the recent Seat and LogContext revamps, _nearly_ all the
remaining uses of the type 'Frontend' were in terminal.c, which needs
all sorts of interactions with the GUI window the terminal lives in,
from the obvious (actually drawing text on the window, reading and
writing the clipboard) to the obscure (minimising, maximising and
moving the window in response to particular escape sequences).
All of those functions are now provided by an abstraction called
TermWin. The few remaining uses of Frontend after _that_ are internal
to a particular platform directory, so as to spread the implementation
of that particular kind of Frontend between multiple source files; so
I've renamed all of those so that they take a more specifically named
type that refers to the particular implementation rather than the
general abstraction.
So now the name 'Frontend' no longer exists in the code base at all,
and everywhere one used to be used, it's completely clear whether it
was operating in one of Frontend's three abstract roles (and if so,
which), or whether it was specific to a particular implementation.
Another type that's disappeared is 'Context', which used to be a
typedef defined to something different on each platform, describing
whatever short-lived resources were necessary to draw on the terminal
window: the front end would provide a ready-made one when calling
term_paint, and the terminal could request one with get_ctx/free_ctx
if it wanted to do proactive window updates. Now that drawing context
lives inside the TermWin itself, because there was never any need to
have two of those contexts live at the same time.
(Another minor API change is that the window-title functions - both
reading and writing - have had a missing 'const' added to their char *
parameters / return values.)
I don't expect this change to enable any particularly interesting new
functionality (in particular, I have no plans that need more than one
implementation of TermWin in the same application). But it completes
the tidying-up that began with the Seat and LogContext rework.
2018-10-25 17:44:04 +00:00
|
|
|
uc & ~CSET_MASK, &ibuf) != 1)
|
2019-09-08 19:29:00 +00:00
|
|
|
return 0;
|
2001-09-15 15:54:24 +00:00
|
|
|
} else {
|
2019-09-08 19:29:00 +00:00
|
|
|
/* 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)
|
|
|
|
/* Okay that one worked */ ;
|
|
|
|
else if (GetCharWidthW(wintw_hdc, uc, uc, &ibuf) == 1)
|
|
|
|
/* This should work on 9x too, but it's "less accurate" */ ;
|
|
|
|
else
|
|
|
|
return 0;
|
2001-09-15 15:54:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ibuf += font_width / 2 -1;
|
|
|
|
ibuf /= font_width;
|
|
|
|
|
|
|
|
return ibuf;
|
|
|
|
}
|
|
|
|
|
2013-11-17 14:03:20 +00:00
|
|
|
DECL_WINDOWS_FUNCTION(static, BOOL, FlashWindowEx, (PFLASHWINFO));
|
|
|
|
DECL_WINDOWS_FUNCTION(static, BOOL, ToUnicodeEx,
|
|
|
|
(UINT, UINT, const BYTE *, LPWSTR, int, UINT, HKL));
|
2017-03-13 21:24:06 +00:00
|
|
|
DECL_WINDOWS_FUNCTION(static, BOOL, PlaySound, (LPCTSTR, HMODULE, DWORD));
|
2013-11-17 14:03:20 +00:00
|
|
|
|
|
|
|
static void init_winfuncs(void)
|
|
|
|
{
|
|
|
|
HMODULE user32_module = load_system32_dll("user32.dll");
|
2017-03-13 21:24:06 +00:00
|
|
|
HMODULE winmm_module = load_system32_dll("winmm.dll");
|
2013-11-17 14:03:20 +00:00
|
|
|
GET_WINDOWS_FUNCTION(user32_module, FlashWindowEx);
|
2017-04-29 11:07:37 +00:00
|
|
|
GET_WINDOWS_FUNCTION(user32_module, ToUnicodeEx);
|
2017-03-13 21:24:06 +00:00
|
|
|
GET_WINDOWS_FUNCTION_PP(winmm_module, PlaySound);
|
2013-11-17 14:03:20 +00:00
|
|
|
}
|
|
|
|
|
1999-01-08 13:02:13 +00:00
|
|
|
/*
|
2000-07-26 12:13:51 +00:00
|
|
|
* Translate a WM_(SYS)?KEY(UP|DOWN) message into a string of ASCII
|
2007-02-18 14:02:39 +00:00
|
|
|
* codes. Returns number of bytes used, zero to drop the message,
|
|
|
|
* -1 to forward the message to Windows, or another negative number
|
|
|
|
* to indicate a NUL-terminated "special" string.
|
1999-01-08 13:02:13 +00:00
|
|
|
*/
|
2000-10-20 18:36:15 +00:00
|
|
|
static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam,
|
2019-09-08 19:29:00 +00:00
|
|
|
unsigned char *output)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
1999-01-08 13:02:13 +00:00
|
|
|
BYTE keystate[256];
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
int scan, shift_state;
|
|
|
|
bool left_alt = false, key_down;
|
Centralise key escape sequences into terminal.c.
A long time ago, in commit 4d77b6567, I moved the generation of the
arrow-key escape sequences into a function format_arrow_key(). Mostly
the reason for that was a special purpose I had in mind at the time
which involved auto-generating the same sequences in response to
things other than a keypress, but I always thought it would be nice to
centralise a lot more of PuTTY's complicated keyboard handling in the
same way - at least the handling of the function keys and their
numerous static and dynamic config options.
In this year's general spirit of tidying up and refactoring, I think
it's finally time. So here I introduce three more centralised
functions for dealing with the numbered function keys, the small
keypad (Ins, Home, PgUp etc) and the numeric keypad. Lots of horrible
and duplicated code from the key handling functions in window.c and
gtkwin.c is now more sensibly centralised: each platform keyboard
handler concerns itself with the local format of a keyboard event and
platform-specific enumeration of key codes, and once it's decided what
the logical key press actually _is_, it hands off to the new functions
in terminal.c to generate the appropriate escape code.
Mostly this is intended to be a refactoring without functional change,
leaving the keyboard handling how it's always been. But in cases where
the Windows and GTK handlers were accidentally inconsistent, I've
fixed the inconsistency rather than carefully keeping both sides how
they were. Known consistency fixes:
- swapping the arrow keys between normal (ESC [ A) and application
(ESC O A) is now done by pressing Ctrl with them, and _not_ by
pressing Shift. That was how it was always supposed to work, and
how it's worked on GTK all along, but on Windows it's been done by
Shift as well since 2010, due to a bug at the call site of
format_arrow_key() introduced when I originally wrote that function.
- in Xterm function key mode plus application keypad mode, the /*-
keys on the numeric keypad now send ESC O {o,j,m} in place of ESC O
{Q,R,S}. That's how the Windows keyboard handler has worked all
along (it was a deliberate behaviour tweak for the Xterm-like
function key mode, because in that mode ESC O {Q,R,S} are generated
by F2-F4). But the GTK keyboard handler omitted that particular
special case and was still sending ESC O {Q,R,S} for those keys in
all application keypad modes.
- also in Xterm function key mode plus app keypad mode, we only
generates the app-keypad escape sequences if Num Lock is on; with
Num Lock off, the numeric keypad becomes arrow keys and
Home/End/etc, just as it would in non-app-keypad mode. Windows has
done this all along, but again, GTK lacked that special case.
2018-12-08 08:25:32 +00:00
|
|
|
int r, i;
|
2001-05-06 14:35:20 +00:00
|
|
|
unsigned char *p = output;
|
2001-05-10 08:34:20 +00:00
|
|
|
static int alt_sum = 0;
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
int funky_type = conf_get_int(conf, CONF_funky_type);
|
2018-10-29 19:57:31 +00:00
|
|
|
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);
|
2019-04-15 19:43:10 +00:00
|
|
|
char keypad_key = '\0';
|
1999-01-08 13:02:13 +00:00
|
|
|
|
2001-01-07 18:28:01 +00:00
|
|
|
HKL kbd_layout = GetKeyboardLayout(0);
|
|
|
|
|
2013-07-20 11:31:24 +00:00
|
|
|
static wchar_t keys_unicode[3];
|
2000-10-07 08:10:32 +00:00
|
|
|
static int compose_char = 0;
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
static WPARAM compose_keycode = 0;
|
2001-05-06 14:35:20 +00:00
|
|
|
|
2000-07-26 12:13:51 +00:00
|
|
|
r = GetKeyboardState(keystate);
|
2001-05-06 14:35:20 +00:00
|
|
|
if (!r)
|
2019-09-08 19:29:00 +00:00
|
|
|
memset(keystate, 0, sizeof(keystate));
|
2001-05-06 14:35:20 +00:00
|
|
|
else {
|
2000-10-09 12:53:32 +00:00
|
|
|
#if 0
|
2001-05-10 08:34:20 +00:00
|
|
|
#define SHOW_TOASCII_RESULT
|
2019-09-08 19:29:00 +00:00
|
|
|
{ /* Tell us all about key events */
|
|
|
|
static BYTE oldstate[256];
|
|
|
|
static int first = 1;
|
|
|
|
static int scan;
|
|
|
|
int ch;
|
|
|
|
if (first)
|
|
|
|
memcpy(oldstate, keystate, sizeof(oldstate));
|
|
|
|
first = 0;
|
|
|
|
|
|
|
|
if ((HIWORD(lParam) & (KF_UP | KF_REPEAT)) == KF_REPEAT) {
|
|
|
|
debug("+");
|
|
|
|
} else if ((HIWORD(lParam) & KF_UP)
|
|
|
|
&& scan == (HIWORD(lParam) & 0xFF)) {
|
|
|
|
debug(". U");
|
|
|
|
} else {
|
|
|
|
debug(".\n");
|
|
|
|
if (wParam >= VK_F1 && wParam <= VK_F20)
|
|
|
|
debug("K_F%d", wParam + 1 - VK_F1);
|
|
|
|
else
|
|
|
|
switch (wParam) {
|
|
|
|
case VK_SHIFT:
|
|
|
|
debug("SHIFT");
|
|
|
|
break;
|
|
|
|
case VK_CONTROL:
|
|
|
|
debug("CTRL");
|
|
|
|
break;
|
|
|
|
case VK_MENU:
|
|
|
|
debug("ALT");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
debug("VK_%02x", wParam);
|
|
|
|
}
|
|
|
|
if (message == WM_SYSKEYDOWN || message == WM_SYSKEYUP)
|
|
|
|
debug("*");
|
|
|
|
debug(", S%02x", scan = (HIWORD(lParam) & 0xFF));
|
|
|
|
|
|
|
|
ch = MapVirtualKeyEx(wParam, 2, kbd_layout);
|
|
|
|
if (ch >= ' ' && ch <= '~')
|
|
|
|
debug(", '%c'", ch);
|
|
|
|
else if (ch)
|
|
|
|
debug(", $%02x", ch);
|
|
|
|
|
|
|
|
if (keys_unicode[0])
|
|
|
|
debug(", KB0=%04x", keys_unicode[0]);
|
|
|
|
if (keys_unicode[1])
|
|
|
|
debug(", KB1=%04x", keys_unicode[1]);
|
|
|
|
if (keys_unicode[2])
|
|
|
|
debug(", KB2=%04x", keys_unicode[2]);
|
|
|
|
|
|
|
|
if ((keystate[VK_SHIFT] & 0x80) != 0)
|
|
|
|
debug(", S");
|
|
|
|
if ((keystate[VK_CONTROL] & 0x80) != 0)
|
|
|
|
debug(", C");
|
|
|
|
if ((HIWORD(lParam) & KF_EXTENDED))
|
|
|
|
debug(", E");
|
|
|
|
if ((HIWORD(lParam) & KF_UP))
|
|
|
|
debug(", U");
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((HIWORD(lParam) & (KF_UP | KF_REPEAT)) == KF_REPEAT);
|
|
|
|
else if ((HIWORD(lParam) & KF_UP))
|
|
|
|
oldstate[wParam & 0xFF] ^= 0x80;
|
|
|
|
else
|
|
|
|
oldstate[wParam & 0xFF] ^= 0x81;
|
|
|
|
|
|
|
|
for (ch = 0; ch < 256; ch++)
|
|
|
|
if (oldstate[ch] != keystate[ch])
|
|
|
|
debug(", M%02x=%02x", ch, keystate[ch]);
|
|
|
|
|
|
|
|
memcpy(oldstate, keystate, sizeof(oldstate));
|
|
|
|
}
|
2000-10-09 12:53:32 +00:00
|
|
|
#endif
|
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
if (wParam == VK_MENU && (HIWORD(lParam) & KF_EXTENDED)) {
|
|
|
|
keystate[VK_RMENU] = keystate[VK_MENU];
|
|
|
|
}
|
2001-01-07 14:30:00 +00:00
|
|
|
|
2000-07-26 12:13:51 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
/* Nastyness with NUMLock - Shift-NUMLock is left alone though */
|
|
|
|
if ((funky_type == FUNKY_VT400 ||
|
|
|
|
(funky_type <= FUNKY_LINUX && term->app_keypad_keys &&
|
|
|
|
!no_applic_k))
|
|
|
|
&& wParam == VK_NUMLOCK && !(keystate[VK_SHIFT] & 0x80)) {
|
2000-07-26 12:13:51 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
wParam = VK_EXECUTE;
|
2000-07-26 12:13:51 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
/* UnToggle NUMLock */
|
|
|
|
if ((HIWORD(lParam) & (KF_UP | KF_REPEAT)) == 0)
|
|
|
|
keystate[VK_NUMLOCK] ^= 1;
|
|
|
|
}
|
2000-07-26 12:13:51 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
/* And write back the 'adjusted' state */
|
|
|
|
SetKeyboardState(keystate);
|
2000-07-26 12:13:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Disable Auto repeat if required */
|
2002-10-22 16:11:33 +00:00
|
|
|
if (term->repeat_off &&
|
2019-09-08 19:29:00 +00:00
|
|
|
(HIWORD(lParam) & (KF_UP | KF_REPEAT)) == KF_REPEAT)
|
|
|
|
return 0;
|
2000-07-26 12:13:51 +00:00
|
|
|
|
2001-05-06 14:35:20 +00:00
|
|
|
if ((HIWORD(lParam) & KF_ALTDOWN) && (keystate[VK_RMENU] & 0x80) == 0)
|
2019-09-08 19:29:00 +00:00
|
|
|
left_alt = true;
|
2000-07-26 12:13:51 +00:00
|
|
|
|
2001-05-06 14:35:20 +00:00
|
|
|
key_down = ((HIWORD(lParam) & KF_UP) == 0);
|
2000-07-26 12:13:51 +00:00
|
|
|
|
2001-04-09 12:52:43 +00:00
|
|
|
/* Make sure Ctrl-ALT is not the same as AltGr for ToAscii unless told. */
|
2001-05-06 14:35:20 +00:00
|
|
|
if (left_alt && (keystate[VK_CONTROL] & 0x80)) {
|
2019-09-08 19:29:00 +00:00
|
|
|
if (ctrlaltkeys)
|
|
|
|
keystate[VK_MENU] = 0;
|
|
|
|
else {
|
|
|
|
keystate[VK_RMENU] = 0x80;
|
|
|
|
left_alt = false;
|
|
|
|
}
|
2001-04-09 12:52:43 +00:00
|
|
|
}
|
2000-07-26 12:13:51 +00:00
|
|
|
|
|
|
|
scan = (HIWORD(lParam) & (KF_UP | KF_EXTENDED | 0xFF));
|
2001-05-06 14:35:20 +00:00
|
|
|
shift_state = ((keystate[VK_SHIFT] & 0x80) != 0)
|
2019-09-08 19:29:00 +00:00
|
|
|
+ ((keystate[VK_CONTROL] & 0x80) != 0) * 2;
|
1999-01-08 13:02:13 +00:00
|
|
|
|
2001-04-09 12:52:43 +00:00
|
|
|
/* Note if AltGr was pressed and if it was used as a compose key */
|
|
|
|
if (!compose_state) {
|
2019-09-08 19:29:00 +00:00
|
|
|
compose_keycode = 0x100;
|
|
|
|
if (conf_get_bool(conf, CONF_compose_key)) {
|
|
|
|
if (wParam == VK_MENU && (HIWORD(lParam) & KF_EXTENDED))
|
|
|
|
compose_keycode = wParam;
|
|
|
|
}
|
|
|
|
if (wParam == VK_APPS)
|
|
|
|
compose_keycode = wParam;
|
2001-04-09 12:52:43 +00:00
|
|
|
}
|
|
|
|
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
if (wParam == compose_keycode) {
|
2019-09-08 19:29:00 +00:00
|
|
|
if (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;
|
|
|
|
else
|
|
|
|
compose_state = 0;
|
2001-05-06 14:35:20 +00:00
|
|
|
} else if (compose_state == 1 && wParam != VK_CONTROL)
|
2019-09-08 19:29:00 +00:00
|
|
|
compose_state = 0;
|
2001-04-09 12:52:43 +00:00
|
|
|
|
2001-05-06 14:35:20 +00:00
|
|
|
if (compose_state > 1 && left_alt)
|
2019-09-08 19:29:00 +00:00
|
|
|
compose_state = 0;
|
1999-03-12 17:14:06 +00:00
|
|
|
|
2000-07-26 12:13:51 +00:00
|
|
|
/* Sanitize the number pad if not using a PC NumPad */
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
if (left_alt || (term->app_keypad_keys && !no_applic_k
|
2019-09-08 19:29:00 +00:00
|
|
|
&& funky_type != FUNKY_XTERM)
|
|
|
|
|| funky_type == FUNKY_VT400 || nethack_keypad || compose_state) {
|
|
|
|
if ((HIWORD(lParam) & KF_EXTENDED) == 0) {
|
|
|
|
int nParam = 0;
|
|
|
|
switch (wParam) {
|
|
|
|
case VK_INSERT:
|
|
|
|
nParam = VK_NUMPAD0;
|
|
|
|
break;
|
|
|
|
case VK_END:
|
|
|
|
nParam = VK_NUMPAD1;
|
|
|
|
break;
|
|
|
|
case VK_DOWN:
|
|
|
|
nParam = VK_NUMPAD2;
|
|
|
|
break;
|
|
|
|
case VK_NEXT:
|
|
|
|
nParam = VK_NUMPAD3;
|
|
|
|
break;
|
|
|
|
case VK_LEFT:
|
|
|
|
nParam = VK_NUMPAD4;
|
|
|
|
break;
|
|
|
|
case VK_CLEAR:
|
|
|
|
nParam = VK_NUMPAD5;
|
|
|
|
break;
|
|
|
|
case VK_RIGHT:
|
|
|
|
nParam = VK_NUMPAD6;
|
|
|
|
break;
|
|
|
|
case VK_HOME:
|
|
|
|
nParam = VK_NUMPAD7;
|
|
|
|
break;
|
|
|
|
case VK_UP:
|
|
|
|
nParam = VK_NUMPAD8;
|
|
|
|
break;
|
|
|
|
case VK_PRIOR:
|
|
|
|
nParam = VK_NUMPAD9;
|
|
|
|
break;
|
|
|
|
case VK_DELETE:
|
|
|
|
nParam = VK_DECIMAL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (nParam) {
|
|
|
|
if (keystate[VK_NUMLOCK] & 1)
|
|
|
|
shift_state |= 1;
|
|
|
|
wParam = nParam;
|
|
|
|
}
|
|
|
|
}
|
1999-11-09 11:19:34 +00:00
|
|
|
}
|
|
|
|
|
2000-07-26 12:13:51 +00:00
|
|
|
/* If a key is pressed and AltGr is not active */
|
2001-05-06 14:35:20 +00:00
|
|
|
if (key_down && (keystate[VK_RMENU] & 0x80) == 0 && !compose_state) {
|
2019-09-08 19:29:00 +00:00
|
|
|
/* 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) {
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
SendMessage(wgs.term_hwnd, WM_VSCROLL, SB_PAGEUP, 0);
|
2019-09-08 19:29:00 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2017-11-03 14:31:10 +00:00
|
|
|
if (wParam == VK_PRIOR && shift_state == 3) { /* ctrl-shift-pageup */
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
SendMessage(wgs.term_hwnd, WM_VSCROLL, SB_TOP, 0);
|
2017-11-03 14:31:10 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (wParam == VK_NEXT && shift_state == 3) { /* ctrl-shift-pagedown */
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
SendMessage(wgs.term_hwnd, WM_VSCROLL, SB_BOTTOM, 0);
|
2017-11-03 14:31:10 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
if (wParam == VK_PRIOR && shift_state == 2) {
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
SendMessage(wgs.term_hwnd, WM_VSCROLL, SB_LINEUP, 0);
|
2019-09-08 19:29:00 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (wParam == VK_NEXT && shift_state == 1) {
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
SendMessage(wgs.term_hwnd, WM_VSCROLL, SB_PAGEDOWN, 0);
|
2019-09-08 19:29:00 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (wParam == VK_NEXT && shift_state == 2) {
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
SendMessage(wgs.term_hwnd, WM_VSCROLL, SB_LINEDOWN, 0);
|
2019-09-08 19:29:00 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if ((wParam == VK_PRIOR || wParam == VK_NEXT) && shift_state == 3) {
|
|
|
|
term_scroll_to_selection(term, (wParam == VK_PRIOR ? 0 : 1));
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (wParam == VK_INSERT && shift_state == 2) {
|
2017-12-10 17:16:50 +00:00
|
|
|
switch (conf_get_int(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));
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2019-09-08 19:29:00 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (wParam == VK_INSERT && shift_state == 1) {
|
2017-12-10 17:16:50 +00:00
|
|
|
switch (conf_get_int(conf, CONF_ctrlshiftins)) {
|
|
|
|
case CLIPUI_IMPLICIT:
|
|
|
|
term_request_paste(term, CLIP_LOCAL);
|
|
|
|
break;
|
|
|
|
case CLIPUI_EXPLICIT:
|
|
|
|
term_request_paste(term, CLIP_SYSTEM);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2019-09-08 19:29:00 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (wParam == 'C' && shift_state == 3) {
|
2017-12-10 17:16:50 +00:00
|
|
|
switch (conf_get_int(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));
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2019-09-08 19:29:00 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (wParam == 'V' && shift_state == 3) {
|
2017-12-10 17:16:50 +00:00
|
|
|
switch (conf_get_int(conf, CONF_ctrlshiftcv)) {
|
|
|
|
case CLIPUI_IMPLICIT:
|
|
|
|
term_request_paste(term, CLIP_LOCAL);
|
|
|
|
break;
|
|
|
|
case CLIPUI_EXPLICIT:
|
|
|
|
term_request_paste(term, CLIP_SYSTEM);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2019-09-08 19:29:00 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (left_alt && wParam == VK_F4 && conf_get_bool(conf, CONF_alt_f4)) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (left_alt && wParam == VK_SPACE && conf_get_bool(conf,
|
2018-10-29 19:57:31 +00:00
|
|
|
CONF_alt_space)) {
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
SendMessage(wgs.term_hwnd, WM_SYSCOMMAND, SC_KEYMENU, 0);
|
2019-09-08 19:29:00 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (left_alt && wParam == VK_RETURN &&
|
|
|
|
conf_get_bool(conf, CONF_fullscreenonaltenter) &&
|
|
|
|
(conf_get_int(conf, CONF_resize_action) != RESIZE_DISABLED)) {
|
|
|
|
if ((HIWORD(lParam) & (KF_UP | KF_REPEAT)) != KF_REPEAT)
|
|
|
|
flip_full_screen();
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
/* Control-Numlock for app-keypad mode switch */
|
|
|
|
if (wParam == VK_PAUSE && shift_state == 2) {
|
|
|
|
term->app_keypad_keys = !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++ = 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++ = 0;
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
if (wParam == VK_TAB && shift_state == 1) { /* Shift tab */
|
|
|
|
*p++ = 0x1B;
|
|
|
|
*p++ = '[';
|
|
|
|
*p++ = 'Z';
|
|
|
|
return p - output;
|
|
|
|
}
|
|
|
|
if (wParam == VK_SPACE && shift_state == 2) { /* Ctrl-Space */
|
|
|
|
*p++ = 0;
|
|
|
|
return p - output;
|
|
|
|
}
|
|
|
|
if (wParam == VK_SPACE && shift_state == 3) { /* Ctrl-Shift-Space */
|
|
|
|
*p++ = 160;
|
|
|
|
return p - output;
|
|
|
|
}
|
|
|
|
if (wParam == VK_CANCEL && shift_state == 2) { /* Ctrl-Break */
|
2018-09-11 15:23:38 +00:00
|
|
|
if (backend)
|
Rework special-commands system to add an integer argument.
In order to list cross-certifiable host keys in the GUI specials menu,
the SSH backend has been inventing new values on the end of the
Telnet_Special enumeration, starting from the value TS_LOCALSTART.
This is inelegant, and also makes it awkward to break up special
handlers (e.g. to dispatch different specials to different SSH
layers), since if all you know about a special is that it's somewhere
in the TS_LOCALSTART+n space, you can't tell what _general kind_ of
thing it is. Also, if I ever need another open-ended set of specials
in future, I'll have to remember which TS_LOCALSTART+n codes are in
which set.
So here's a revamp that causes every special to take an extra integer
argument. For all previously numbered specials, this argument is
passed as zero and ignored, but there's a new main special code for
SSH host key cross-certification, in which the integer argument is an
index into the backend's list of available keys. TS_LOCALSTART is now
a thing of the past: if I need any other open-ended sets of specials
in future, I can add a new top-level code with a nicely separated
space of arguments.
While I'm at it, I've removed the legacy misnomer 'Telnet_Special'
from the code completely; the enum is now SessionSpecialCode, the
struct containing full details of a menu entry is SessionSpecial, and
the enum values now start SS_ rather than TS_.
2018-09-24 08:35:52 +00:00
|
|
|
backend_special(backend, SS_BRK, 0);
|
2019-09-08 19:29:00 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (wParam == VK_PAUSE) { /* Break/Pause */
|
|
|
|
*p++ = 26;
|
|
|
|
*p++ = 0;
|
|
|
|
return -2;
|
|
|
|
}
|
|
|
|
/* Control-2 to Control-8 are special */
|
|
|
|
if (shift_state == 2 && wParam >= '2' && wParam <= '8') {
|
|
|
|
*p++ = "\000\033\034\035\036\037\177"[wParam - '2'];
|
|
|
|
return p - output;
|
|
|
|
}
|
|
|
|
if (shift_state == 2 && (wParam == 0xBD || wParam == 0xBF)) {
|
|
|
|
*p++ = 0x1F;
|
|
|
|
return p - output;
|
|
|
|
}
|
|
|
|
if (shift_state == 2 && (wParam == 0xDF || wParam == 0xDC)) {
|
|
|
|
*p++ = 0x1C;
|
|
|
|
return p - output;
|
|
|
|
}
|
|
|
|
if (shift_state == 3 && wParam == 0xDE) {
|
|
|
|
*p++ = 0x1E; /* Ctrl-~ == Ctrl-^ in xterm at least */
|
|
|
|
return p - output;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (wParam) {
|
Centralise key escape sequences into terminal.c.
A long time ago, in commit 4d77b6567, I moved the generation of the
arrow-key escape sequences into a function format_arrow_key(). Mostly
the reason for that was a special purpose I had in mind at the time
which involved auto-generating the same sequences in response to
things other than a keypress, but I always thought it would be nice to
centralise a lot more of PuTTY's complicated keyboard handling in the
same way - at least the handling of the function keys and their
numerous static and dynamic config options.
In this year's general spirit of tidying up and refactoring, I think
it's finally time. So here I introduce three more centralised
functions for dealing with the numbered function keys, the small
keypad (Ins, Home, PgUp etc) and the numeric keypad. Lots of horrible
and duplicated code from the key handling functions in window.c and
gtkwin.c is now more sensibly centralised: each platform keyboard
handler concerns itself with the local format of a keyboard event and
platform-specific enumeration of key codes, and once it's decided what
the logical key press actually _is_, it hands off to the new functions
in terminal.c to generate the appropriate escape code.
Mostly this is intended to be a refactoring without functional change,
leaving the keyboard handling how it's always been. But in cases where
the Windows and GTK handlers were accidentally inconsistent, I've
fixed the inconsistency rather than carefully keeping both sides how
they were. Known consistency fixes:
- swapping the arrow keys between normal (ESC [ A) and application
(ESC O A) is now done by pressing Ctrl with them, and _not_ by
pressing Shift. That was how it was always supposed to work, and
how it's worked on GTK all along, but on Windows it's been done by
Shift as well since 2010, due to a bug at the call site of
format_arrow_key() introduced when I originally wrote that function.
- in Xterm function key mode plus application keypad mode, the /*-
keys on the numeric keypad now send ESC O {o,j,m} in place of ESC O
{Q,R,S}. That's how the Windows keyboard handler has worked all
along (it was a deliberate behaviour tweak for the Xterm-like
function key mode, because in that mode ESC O {Q,R,S} are generated
by F2-F4). But the GTK keyboard handler omitted that particular
special case and was still sending ESC O {Q,R,S} for those keys in
all application keypad modes.
- also in Xterm function key mode plus app keypad mode, we only
generates the app-keypad escape sequences if Num Lock is on; with
Num Lock off, the numeric keypad becomes arrow keys and
Home/End/etc, just as it would in non-app-keypad mode. Windows has
done this all along, but again, GTK lacked that special case.
2018-12-08 08:25:32 +00:00
|
|
|
case VK_NUMPAD0: keypad_key = '0'; goto numeric_keypad;
|
|
|
|
case VK_NUMPAD1: keypad_key = '1'; goto numeric_keypad;
|
|
|
|
case VK_NUMPAD2: keypad_key = '2'; goto numeric_keypad;
|
|
|
|
case VK_NUMPAD3: keypad_key = '3'; goto numeric_keypad;
|
|
|
|
case VK_NUMPAD4: keypad_key = '4'; goto numeric_keypad;
|
|
|
|
case VK_NUMPAD5: keypad_key = '5'; goto numeric_keypad;
|
|
|
|
case VK_NUMPAD6: keypad_key = '6'; goto numeric_keypad;
|
|
|
|
case VK_NUMPAD7: keypad_key = '7'; goto numeric_keypad;
|
|
|
|
case VK_NUMPAD8: keypad_key = '8'; goto numeric_keypad;
|
|
|
|
case VK_NUMPAD9: keypad_key = '9'; goto numeric_keypad;
|
|
|
|
case VK_DECIMAL: keypad_key = '.'; goto numeric_keypad;
|
|
|
|
case VK_ADD: keypad_key = '+'; goto numeric_keypad;
|
|
|
|
case VK_SUBTRACT: keypad_key = '-'; goto numeric_keypad;
|
|
|
|
case VK_MULTIPLY: keypad_key = '*'; goto numeric_keypad;
|
|
|
|
case VK_DIVIDE: keypad_key = '/'; goto numeric_keypad;
|
|
|
|
case VK_EXECUTE: keypad_key = 'G'; goto numeric_keypad;
|
|
|
|
/* also the case for VK_RETURN below can sometimes come here */
|
|
|
|
numeric_keypad:
|
|
|
|
/* Left Alt overrides all numeric keypad usage to act as
|
|
|
|
* numeric character code input */
|
|
|
|
if (left_alt) {
|
|
|
|
if (keypad_key >= '0' && keypad_key <= '9')
|
|
|
|
alt_sum = alt_sum * 10 + keypad_key - '0';
|
|
|
|
else
|
|
|
|
alt_sum = 0;
|
|
|
|
break;
|
|
|
|
}
|
2000-03-13 14:45:32 +00:00
|
|
|
|
Remove ASCII fallback in format_numeric_keypad_key().
TranslateKey() on Windows passed all numeric-keypad key events to this
function in terminal.c, and accepted whatever it gave back. That
included the handling for the trivial case of the numeric keypad, when
Num Lock is on and application keypad mode hasn't overridden it, so
that the keypad should be returning actual digits. In that case,
format_numeric_keypad_key() itself was returning the same ASCII
character I had passed in to it as a keypad identifier, and
TranslateKey was returning that in turn as the final translation.
Unfortunately, that means that with Num Lock on, the numeric keypad
translates into what _I_ used as the logical keypad codes inside the
source code, not what the local keyboard layout thinks are the right
codes. In particular, the key I identified as keypad '.' would render
as '.' even on a German keyboard where it ought to produce ','.
Fixed by removing the fallback case in format_numeric_keypad_key()
itself, so now it returns the empty string if it didn't produce an
escape sequence as its translation. Instead, the special case is in
window.c, which checks for a zero-length output string and handles it
by falling through to the keyboard-layout specific ToUnicode code
further down TranslateKey().
On the GTK side, no change is needed here: the GTK keyboard handler
does things in the opposite order, by trying the local input method
_first_ (unless it can see a reason up front to override it), and only
calling format_numeric_keypad_key() if that didn't provide a
translation. So the fallback ASCII translation in the latter was
already not used.
2019-04-06 09:45:40 +00:00
|
|
|
{
|
|
|
|
int nchars = format_numeric_keypad_key(
|
|
|
|
(char *)p, term, keypad_key,
|
|
|
|
shift_state & 1, shift_state & 2);
|
|
|
|
if (!nchars) {
|
2019-04-15 19:43:10 +00:00
|
|
|
/*
|
|
|
|
* If we didn't get an escape sequence out of the
|
Remove ASCII fallback in format_numeric_keypad_key().
TranslateKey() on Windows passed all numeric-keypad key events to this
function in terminal.c, and accepted whatever it gave back. That
included the handling for the trivial case of the numeric keypad, when
Num Lock is on and application keypad mode hasn't overridden it, so
that the keypad should be returning actual digits. In that case,
format_numeric_keypad_key() itself was returning the same ASCII
character I had passed in to it as a keypad identifier, and
TranslateKey was returning that in turn as the final translation.
Unfortunately, that means that with Num Lock on, the numeric keypad
translates into what _I_ used as the logical keypad codes inside the
source code, not what the local keyboard layout thinks are the right
codes. In particular, the key I identified as keypad '.' would render
as '.' even on a German keyboard where it ought to produce ','.
Fixed by removing the fallback case in format_numeric_keypad_key()
itself, so now it returns the empty string if it didn't produce an
escape sequence as its translation. Instead, the special case is in
window.c, which checks for a zero-length output string and handles it
by falling through to the keyboard-layout specific ToUnicode code
further down TranslateKey().
On the GTK side, no change is needed here: the GTK keyboard handler
does things in the opposite order, by trying the local input method
_first_ (unless it can see a reason up front to override it), and only
calling format_numeric_keypad_key() if that didn't provide a
translation. So the fallback ASCII translation in the latter was
already not used.
2019-04-06 09:45:40 +00:00
|
|
|
* numeric keypad key, then that must be because
|
|
|
|
* we're in Num Lock mode without application
|
|
|
|
* keypad enabled. In that situation we leave this
|
|
|
|
* keypress to the ToUnicode/ToAsciiEx handler
|
|
|
|
* below, which will translate it according to the
|
|
|
|
* appropriate keypad layout (e.g. so that what a
|
|
|
|
* Brit thinks of as keypad '.' can become ',' in
|
2019-04-15 19:43:10 +00:00
|
|
|
* the German layout).
|
|
|
|
*
|
|
|
|
* An exception is the keypad Return key: if we
|
|
|
|
* didn't get an escape sequence for that, we
|
|
|
|
* treat it like ordinary Return, taking into
|
|
|
|
* account Telnet special new line codes and
|
|
|
|
* config options.
|
|
|
|
*/
|
|
|
|
if (keypad_key == '\r')
|
|
|
|
goto ordinary_return_key;
|
Remove ASCII fallback in format_numeric_keypad_key().
TranslateKey() on Windows passed all numeric-keypad key events to this
function in terminal.c, and accepted whatever it gave back. That
included the handling for the trivial case of the numeric keypad, when
Num Lock is on and application keypad mode hasn't overridden it, so
that the keypad should be returning actual digits. In that case,
format_numeric_keypad_key() itself was returning the same ASCII
character I had passed in to it as a keypad identifier, and
TranslateKey was returning that in turn as the final translation.
Unfortunately, that means that with Num Lock on, the numeric keypad
translates into what _I_ used as the logical keypad codes inside the
source code, not what the local keyboard layout thinks are the right
codes. In particular, the key I identified as keypad '.' would render
as '.' even on a German keyboard where it ought to produce ','.
Fixed by removing the fallback case in format_numeric_keypad_key()
itself, so now it returns the empty string if it didn't produce an
escape sequence as its translation. Instead, the special case is in
window.c, which checks for a zero-length output string and handles it
by falling through to the keyboard-layout specific ToUnicode code
further down TranslateKey().
On the GTK side, no change is needed here: the GTK keyboard handler
does things in the opposite order, by trying the local input method
_first_ (unless it can see a reason up front to override it), and only
calling format_numeric_keypad_key() if that didn't provide a
translation. So the fallback ASCII translation in the latter was
already not used.
2019-04-06 09:45:40 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
p += nchars;
|
|
|
|
return p - output;
|
|
|
|
}
|
Centralise key escape sequences into terminal.c.
A long time ago, in commit 4d77b6567, I moved the generation of the
arrow-key escape sequences into a function format_arrow_key(). Mostly
the reason for that was a special purpose I had in mind at the time
which involved auto-generating the same sequences in response to
things other than a keypress, but I always thought it would be nice to
centralise a lot more of PuTTY's complicated keyboard handling in the
same way - at least the handling of the function keys and their
numerous static and dynamic config options.
In this year's general spirit of tidying up and refactoring, I think
it's finally time. So here I introduce three more centralised
functions for dealing with the numbered function keys, the small
keypad (Ins, Home, PgUp etc) and the numeric keypad. Lots of horrible
and duplicated code from the key handling functions in window.c and
gtkwin.c is now more sensibly centralised: each platform keyboard
handler concerns itself with the local format of a keyboard event and
platform-specific enumeration of key codes, and once it's decided what
the logical key press actually _is_, it hands off to the new functions
in terminal.c to generate the appropriate escape code.
Mostly this is intended to be a refactoring without functional change,
leaving the keyboard handling how it's always been. But in cases where
the Windows and GTK handlers were accidentally inconsistent, I've
fixed the inconsistency rather than carefully keeping both sides how
they were. Known consistency fixes:
- swapping the arrow keys between normal (ESC [ A) and application
(ESC O A) is now done by pressing Ctrl with them, and _not_ by
pressing Shift. That was how it was always supposed to work, and
how it's worked on GTK all along, but on Windows it's been done by
Shift as well since 2010, due to a bug at the call site of
format_arrow_key() introduced when I originally wrote that function.
- in Xterm function key mode plus application keypad mode, the /*-
keys on the numeric keypad now send ESC O {o,j,m} in place of ESC O
{Q,R,S}. That's how the Windows keyboard handler has worked all
along (it was a deliberate behaviour tweak for the Xterm-like
function key mode, because in that mode ESC O {Q,R,S} are generated
by F2-F4). But the GTK keyboard handler omitted that particular
special case and was still sending ESC O {Q,R,S} for those keys in
all application keypad modes.
- also in Xterm function key mode plus app keypad mode, we only
generates the app-keypad escape sequences if Num Lock is on; with
Num Lock off, the numeric keypad becomes arrow keys and
Home/End/etc, just as it would in non-app-keypad mode. Windows has
done this all along, but again, GTK lacked that special case.
2018-12-08 08:25:32 +00:00
|
|
|
|
|
|
|
int fkey_number;
|
2019-09-08 19:29:00 +00:00
|
|
|
case VK_F1: fkey_number = 1; goto numbered_function_key;
|
|
|
|
case VK_F2: fkey_number = 2; goto numbered_function_key;
|
|
|
|
case VK_F3: fkey_number = 3; goto numbered_function_key;
|
|
|
|
case VK_F4: fkey_number = 4; goto numbered_function_key;
|
|
|
|
case VK_F5: fkey_number = 5; goto numbered_function_key;
|
|
|
|
case VK_F6: fkey_number = 6; goto numbered_function_key;
|
|
|
|
case VK_F7: fkey_number = 7; goto numbered_function_key;
|
|
|
|
case VK_F8: fkey_number = 8; goto numbered_function_key;
|
|
|
|
case VK_F9: fkey_number = 9; goto numbered_function_key;
|
|
|
|
case VK_F10: fkey_number = 10; goto numbered_function_key;
|
|
|
|
case VK_F11: fkey_number = 11; goto numbered_function_key;
|
|
|
|
case VK_F12: fkey_number = 12; goto numbered_function_key;
|
|
|
|
case VK_F13: fkey_number = 13; goto numbered_function_key;
|
|
|
|
case VK_F14: fkey_number = 14; goto numbered_function_key;
|
|
|
|
case VK_F15: fkey_number = 15; goto numbered_function_key;
|
|
|
|
case VK_F16: fkey_number = 16; goto numbered_function_key;
|
|
|
|
case VK_F17: fkey_number = 17; goto numbered_function_key;
|
|
|
|
case VK_F18: fkey_number = 18; goto numbered_function_key;
|
|
|
|
case VK_F19: fkey_number = 19; goto numbered_function_key;
|
|
|
|
case VK_F20: fkey_number = 20; goto numbered_function_key;
|
Centralise key escape sequences into terminal.c.
A long time ago, in commit 4d77b6567, I moved the generation of the
arrow-key escape sequences into a function format_arrow_key(). Mostly
the reason for that was a special purpose I had in mind at the time
which involved auto-generating the same sequences in response to
things other than a keypress, but I always thought it would be nice to
centralise a lot more of PuTTY's complicated keyboard handling in the
same way - at least the handling of the function keys and their
numerous static and dynamic config options.
In this year's general spirit of tidying up and refactoring, I think
it's finally time. So here I introduce three more centralised
functions for dealing with the numbered function keys, the small
keypad (Ins, Home, PgUp etc) and the numeric keypad. Lots of horrible
and duplicated code from the key handling functions in window.c and
gtkwin.c is now more sensibly centralised: each platform keyboard
handler concerns itself with the local format of a keyboard event and
platform-specific enumeration of key codes, and once it's decided what
the logical key press actually _is_, it hands off to the new functions
in terminal.c to generate the appropriate escape code.
Mostly this is intended to be a refactoring without functional change,
leaving the keyboard handling how it's always been. But in cases where
the Windows and GTK handlers were accidentally inconsistent, I've
fixed the inconsistency rather than carefully keeping both sides how
they were. Known consistency fixes:
- swapping the arrow keys between normal (ESC [ A) and application
(ESC O A) is now done by pressing Ctrl with them, and _not_ by
pressing Shift. That was how it was always supposed to work, and
how it's worked on GTK all along, but on Windows it's been done by
Shift as well since 2010, due to a bug at the call site of
format_arrow_key() introduced when I originally wrote that function.
- in Xterm function key mode plus application keypad mode, the /*-
keys on the numeric keypad now send ESC O {o,j,m} in place of ESC O
{Q,R,S}. That's how the Windows keyboard handler has worked all
along (it was a deliberate behaviour tweak for the Xterm-like
function key mode, because in that mode ESC O {Q,R,S} are generated
by F2-F4). But the GTK keyboard handler omitted that particular
special case and was still sending ESC O {Q,R,S} for those keys in
all application keypad modes.
- also in Xterm function key mode plus app keypad mode, we only
generates the app-keypad escape sequences if Num Lock is on; with
Num Lock off, the numeric keypad becomes arrow keys and
Home/End/etc, just as it would in non-app-keypad mode. Windows has
done this all along, but again, GTK lacked that special case.
2018-12-08 08:25:32 +00:00
|
|
|
numbered_function_key:
|
|
|
|
p += format_function_key((char *)p, term, fkey_number,
|
|
|
|
shift_state & 1, shift_state & 2);
|
|
|
|
return p - output;
|
|
|
|
|
|
|
|
SmallKeypadKey sk_key;
|
2019-09-08 19:29:00 +00:00
|
|
|
case VK_HOME: sk_key = SKK_HOME; goto small_keypad_key;
|
|
|
|
case VK_END: sk_key = SKK_END; goto small_keypad_key;
|
|
|
|
case VK_INSERT: sk_key = SKK_INSERT; goto small_keypad_key;
|
|
|
|
case VK_DELETE: sk_key = SKK_DELETE; goto small_keypad_key;
|
|
|
|
case VK_PRIOR: sk_key = SKK_PGUP; goto small_keypad_key;
|
|
|
|
case VK_NEXT: sk_key = SKK_PGDN; goto small_keypad_key;
|
Centralise key escape sequences into terminal.c.
A long time ago, in commit 4d77b6567, I moved the generation of the
arrow-key escape sequences into a function format_arrow_key(). Mostly
the reason for that was a special purpose I had in mind at the time
which involved auto-generating the same sequences in response to
things other than a keypress, but I always thought it would be nice to
centralise a lot more of PuTTY's complicated keyboard handling in the
same way - at least the handling of the function keys and their
numerous static and dynamic config options.
In this year's general spirit of tidying up and refactoring, I think
it's finally time. So here I introduce three more centralised
functions for dealing with the numbered function keys, the small
keypad (Ins, Home, PgUp etc) and the numeric keypad. Lots of horrible
and duplicated code from the key handling functions in window.c and
gtkwin.c is now more sensibly centralised: each platform keyboard
handler concerns itself with the local format of a keyboard event and
platform-specific enumeration of key codes, and once it's decided what
the logical key press actually _is_, it hands off to the new functions
in terminal.c to generate the appropriate escape code.
Mostly this is intended to be a refactoring without functional change,
leaving the keyboard handling how it's always been. But in cases where
the Windows and GTK handlers were accidentally inconsistent, I've
fixed the inconsistency rather than carefully keeping both sides how
they were. Known consistency fixes:
- swapping the arrow keys between normal (ESC [ A) and application
(ESC O A) is now done by pressing Ctrl with them, and _not_ by
pressing Shift. That was how it was always supposed to work, and
how it's worked on GTK all along, but on Windows it's been done by
Shift as well since 2010, due to a bug at the call site of
format_arrow_key() introduced when I originally wrote that function.
- in Xterm function key mode plus application keypad mode, the /*-
keys on the numeric keypad now send ESC O {o,j,m} in place of ESC O
{Q,R,S}. That's how the Windows keyboard handler has worked all
along (it was a deliberate behaviour tweak for the Xterm-like
function key mode, because in that mode ESC O {Q,R,S} are generated
by F2-F4). But the GTK keyboard handler omitted that particular
special case and was still sending ESC O {Q,R,S} for those keys in
all application keypad modes.
- also in Xterm function key mode plus app keypad mode, we only
generates the app-keypad escape sequences if Num Lock is on; with
Num Lock off, the numeric keypad becomes arrow keys and
Home/End/etc, just as it would in non-app-keypad mode. Windows has
done this all along, but again, GTK lacked that special case.
2018-12-08 08:25:32 +00:00
|
|
|
small_keypad_key:
|
|
|
|
/* These keys don't generate terminal input with Ctrl */
|
|
|
|
if (shift_state & 2)
|
|
|
|
break;
|
2000-10-07 08:10:32 +00:00
|
|
|
|
Centralise key escape sequences into terminal.c.
A long time ago, in commit 4d77b6567, I moved the generation of the
arrow-key escape sequences into a function format_arrow_key(). Mostly
the reason for that was a special purpose I had in mind at the time
which involved auto-generating the same sequences in response to
things other than a keypress, but I always thought it would be nice to
centralise a lot more of PuTTY's complicated keyboard handling in the
same way - at least the handling of the function keys and their
numerous static and dynamic config options.
In this year's general spirit of tidying up and refactoring, I think
it's finally time. So here I introduce three more centralised
functions for dealing with the numbered function keys, the small
keypad (Ins, Home, PgUp etc) and the numeric keypad. Lots of horrible
and duplicated code from the key handling functions in window.c and
gtkwin.c is now more sensibly centralised: each platform keyboard
handler concerns itself with the local format of a keyboard event and
platform-specific enumeration of key codes, and once it's decided what
the logical key press actually _is_, it hands off to the new functions
in terminal.c to generate the appropriate escape code.
Mostly this is intended to be a refactoring without functional change,
leaving the keyboard handling how it's always been. But in cases where
the Windows and GTK handlers were accidentally inconsistent, I've
fixed the inconsistency rather than carefully keeping both sides how
they were. Known consistency fixes:
- swapping the arrow keys between normal (ESC [ A) and application
(ESC O A) is now done by pressing Ctrl with them, and _not_ by
pressing Shift. That was how it was always supposed to work, and
how it's worked on GTK all along, but on Windows it's been done by
Shift as well since 2010, due to a bug at the call site of
format_arrow_key() introduced when I originally wrote that function.
- in Xterm function key mode plus application keypad mode, the /*-
keys on the numeric keypad now send ESC O {o,j,m} in place of ESC O
{Q,R,S}. That's how the Windows keyboard handler has worked all
along (it was a deliberate behaviour tweak for the Xterm-like
function key mode, because in that mode ESC O {Q,R,S} are generated
by F2-F4). But the GTK keyboard handler omitted that particular
special case and was still sending ESC O {Q,R,S} for those keys in
all application keypad modes.
- also in Xterm function key mode plus app keypad mode, we only
generates the app-keypad escape sequences if Num Lock is on; with
Num Lock off, the numeric keypad becomes arrow keys and
Home/End/etc, just as it would in non-app-keypad mode. Windows has
done this all along, but again, GTK lacked that special case.
2018-12-08 08:25:32 +00:00
|
|
|
p += format_small_keypad_key((char *)p, term, sk_key);
|
|
|
|
return p - output;
|
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
char xkey;
|
Centralise key escape sequences into terminal.c.
A long time ago, in commit 4d77b6567, I moved the generation of the
arrow-key escape sequences into a function format_arrow_key(). Mostly
the reason for that was a special purpose I had in mind at the time
which involved auto-generating the same sequences in response to
things other than a keypress, but I always thought it would be nice to
centralise a lot more of PuTTY's complicated keyboard handling in the
same way - at least the handling of the function keys and their
numerous static and dynamic config options.
In this year's general spirit of tidying up and refactoring, I think
it's finally time. So here I introduce three more centralised
functions for dealing with the numbered function keys, the small
keypad (Ins, Home, PgUp etc) and the numeric keypad. Lots of horrible
and duplicated code from the key handling functions in window.c and
gtkwin.c is now more sensibly centralised: each platform keyboard
handler concerns itself with the local format of a keyboard event and
platform-specific enumeration of key codes, and once it's decided what
the logical key press actually _is_, it hands off to the new functions
in terminal.c to generate the appropriate escape code.
Mostly this is intended to be a refactoring without functional change,
leaving the keyboard handling how it's always been. But in cases where
the Windows and GTK handlers were accidentally inconsistent, I've
fixed the inconsistency rather than carefully keeping both sides how
they were. Known consistency fixes:
- swapping the arrow keys between normal (ESC [ A) and application
(ESC O A) is now done by pressing Ctrl with them, and _not_ by
pressing Shift. That was how it was always supposed to work, and
how it's worked on GTK all along, but on Windows it's been done by
Shift as well since 2010, due to a bug at the call site of
format_arrow_key() introduced when I originally wrote that function.
- in Xterm function key mode plus application keypad mode, the /*-
keys on the numeric keypad now send ESC O {o,j,m} in place of ESC O
{Q,R,S}. That's how the Windows keyboard handler has worked all
along (it was a deliberate behaviour tweak for the Xterm-like
function key mode, because in that mode ESC O {Q,R,S} are generated
by F2-F4). But the GTK keyboard handler omitted that particular
special case and was still sending ESC O {Q,R,S} for those keys in
all application keypad modes.
- also in Xterm function key mode plus app keypad mode, we only
generates the app-keypad escape sequences if Num Lock is on; with
Num Lock off, the numeric keypad becomes arrow keys and
Home/End/etc, just as it would in non-app-keypad mode. Windows has
done this all along, but again, GTK lacked that special case.
2018-12-08 08:25:32 +00:00
|
|
|
case VK_UP: xkey = 'A'; goto arrow_key;
|
|
|
|
case VK_DOWN: xkey = 'B'; goto arrow_key;
|
|
|
|
case VK_RIGHT: xkey = 'C'; goto arrow_key;
|
|
|
|
case VK_LEFT: xkey = 'D'; goto arrow_key;
|
|
|
|
case VK_CLEAR: xkey = 'G'; goto arrow_key; /* close enough */
|
|
|
|
arrow_key:
|
|
|
|
p += format_arrow_key((char *)p, term, xkey, shift_state & 2);
|
|
|
|
return p - output;
|
|
|
|
|
|
|
|
case VK_RETURN:
|
|
|
|
if (HIWORD(lParam) & KF_EXTENDED) {
|
|
|
|
keypad_key = '\r';
|
|
|
|
goto numeric_keypad;
|
|
|
|
}
|
2019-04-15 19:43:10 +00:00
|
|
|
ordinary_return_key:
|
|
|
|
if (shift_state == 0 && term->cr_lf_return) {
|
|
|
|
*p++ = '\r';
|
|
|
|
*p++ = '\n';
|
|
|
|
return p - output;
|
|
|
|
} else {
|
|
|
|
*p++ = 0x0D;
|
|
|
|
*p++ = 0;
|
|
|
|
return -2;
|
|
|
|
}
|
2019-09-08 19:29:00 +00:00
|
|
|
}
|
1999-03-12 17:14:06 +00:00
|
|
|
}
|
1999-01-08 13:02:13 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
/* Okay we've done everything interesting; let windows deal with
|
2000-07-26 12:13:51 +00:00
|
|
|
* the boring stuff */
|
|
|
|
{
|
2019-09-08 19:29:00 +00:00
|
|
|
bool capsOn = false;
|
|
|
|
|
|
|
|
/* helg: clear CAPS LOCK state if caps lock switches to cyrillic */
|
|
|
|
if(keystate[VK_CAPITAL] != 0 &&
|
|
|
|
conf_get_bool(conf, CONF_xlat_capslockcyr)) {
|
|
|
|
capsOn= !left_alt;
|
|
|
|
keystate[VK_CAPITAL] = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* XXX how do we know what the max size of the keys array should
|
|
|
|
* be is? There's indication on MS' website of an Inquire/InquireEx
|
|
|
|
* functioning returning a KBINFO structure which tells us. */
|
|
|
|
if (osPlatformId == VER_PLATFORM_WIN32_NT && p_ToUnicodeEx) {
|
|
|
|
r = p_ToUnicodeEx(wParam, scan, keystate, keys_unicode,
|
2013-11-17 14:03:20 +00:00
|
|
|
lenof(keys_unicode), 0, kbd_layout);
|
2019-09-08 19:29:00 +00:00
|
|
|
} else {
|
|
|
|
/* XXX 'keys' parameter is declared in MSDN documentation as
|
|
|
|
* 'LPWORD lpChar'.
|
|
|
|
* The experience of a French user indicates that on
|
|
|
|
* Win98, WORD[] should be passed in, but on Win2K, it should
|
|
|
|
* be BYTE[]. German WinXP and my Win2K with "US International"
|
|
|
|
* driver corroborate this.
|
|
|
|
* Experimentally I've conditionalised the behaviour on the
|
|
|
|
* Win9x/NT split, but I suspect it's worse than that.
|
|
|
|
* See wishlist item `win-dead-keys' for more horrible detail
|
|
|
|
* and speculations. */
|
|
|
|
int i;
|
|
|
|
static WORD keys[3];
|
|
|
|
static BYTE keysb[3];
|
|
|
|
r = ToAsciiEx(wParam, scan, keystate, keys, 0, kbd_layout);
|
|
|
|
if (r > 0) {
|
|
|
|
for (i = 0; i < r; i++) {
|
|
|
|
keysb[i] = (BYTE)keys[i];
|
|
|
|
}
|
|
|
|
MultiByteToWideChar(CP_ACP, 0, (LPCSTR)keysb, r,
|
2013-07-20 11:31:24 +00:00
|
|
|
keys_unicode, lenof(keys_unicode));
|
2019-09-08 19:29:00 +00:00
|
|
|
}
|
|
|
|
}
|
2001-05-10 08:34:20 +00:00
|
|
|
#ifdef SHOW_TOASCII_RESULT
|
2019-09-08 19:29:00 +00:00
|
|
|
if (r == 1 && !key_down) {
|
|
|
|
if (alt_sum) {
|
|
|
|
if (in_utf(term) || ucsdata.dbcs_screenfont)
|
|
|
|
debug(", (U+%04x)", alt_sum);
|
|
|
|
else
|
|
|
|
debug(", LCH(%d)", alt_sum);
|
|
|
|
} else {
|
|
|
|
debug(", ACH(%d)", keys_unicode[0]);
|
|
|
|
}
|
|
|
|
} else if (r > 0) {
|
|
|
|
int r1;
|
|
|
|
debug(", ASC(");
|
|
|
|
for (r1 = 0; r1 < r; r1++) {
|
|
|
|
debug("%s%d", r1 ? "," : "", keys_unicode[r1]);
|
|
|
|
}
|
|
|
|
debug(")");
|
|
|
|
}
|
2001-05-10 08:34:20 +00:00
|
|
|
#endif
|
2019-09-08 19:29:00 +00:00
|
|
|
if (r > 0) {
|
|
|
|
WCHAR keybuf;
|
|
|
|
|
|
|
|
p = output;
|
|
|
|
for (i = 0; i < r; i++) {
|
|
|
|
wchar_t wch = keys_unicode[i];
|
|
|
|
|
|
|
|
if (compose_state == 2 && wch >= ' ' && wch < 0x80) {
|
|
|
|
compose_char = wch;
|
|
|
|
compose_state++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (compose_state == 3 && wch >= ' ' && wch < 0x80) {
|
|
|
|
int nc;
|
|
|
|
compose_state = 0;
|
|
|
|
|
|
|
|
if ((nc = check_compose(compose_char, wch)) == -1) {
|
|
|
|
MessageBeep(MB_ICONHAND);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
keybuf = nc;
|
Refactor terminal input to remove ldiscucs.c.
The functions that previously lived in it now live in terminal.c
itself; they've been renamed term_keyinput and term_keyinputw, and
their function is to add data to the terminal's user input buffer from
a char or wchar_t string respectively.
They sit more comfortably in terminal.c anyway, because their whole
point is to translate into the character encoding that the terminal is
currently configured to use. Also, making them part of the terminal
code means they can also take care of calling term_seen_key_event(),
which simplifies most of the call sites in the GTK and Windows front
ends.
Generation of text _inside_ terminal.c, from responses to query escape
sequences, is therefore not done by calling those external entry
points: we send those responses directly to the ldisc, so that they
don't count as keypresses for all the user-facing purposes like bell
overload handling and scrollback reset. To make _that_ convenient,
I've arranged that most of the code that previously lived in
lpage_send and luni_send is now in separate translation functions, so
those can still be called from situations where you're not going to do
the default thing with the translated data.
(However, pasted data _does_ still count as close enough to a keypress
to call term_seen_key_event - but it clears the 'interactive' flag
when the data is passed on to the line discipline, which tweaks a
minor detail of control-char handling in line ending mode but mostly
just means pastes aren't interrupted.)
2019-06-17 19:13:55 +00:00
|
|
|
term_keyinputw(term, &keybuf, 1);
|
2019-09-08 19:29:00 +00:00
|
|
|
continue;
|
|
|
|
}
|
1999-01-08 13:02:13 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
compose_state = 0;
|
1999-01-08 13:02:13 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
if (!key_down) {
|
|
|
|
if (alt_sum) {
|
|
|
|
if (in_utf(term) || ucsdata.dbcs_screenfont) {
|
|
|
|
keybuf = alt_sum;
|
Refactor terminal input to remove ldiscucs.c.
The functions that previously lived in it now live in terminal.c
itself; they've been renamed term_keyinput and term_keyinputw, and
their function is to add data to the terminal's user input buffer from
a char or wchar_t string respectively.
They sit more comfortably in terminal.c anyway, because their whole
point is to translate into the character encoding that the terminal is
currently configured to use. Also, making them part of the terminal
code means they can also take care of calling term_seen_key_event(),
which simplifies most of the call sites in the GTK and Windows front
ends.
Generation of text _inside_ terminal.c, from responses to query escape
sequences, is therefore not done by calling those external entry
points: we send those responses directly to the ldisc, so that they
don't count as keypresses for all the user-facing purposes like bell
overload handling and scrollback reset. To make _that_ convenient,
I've arranged that most of the code that previously lived in
lpage_send and luni_send is now in separate translation functions, so
those can still be called from situations where you're not going to do
the default thing with the translated data.
(However, pasted data _does_ still count as close enough to a keypress
to call term_seen_key_event - but it clears the 'interactive' flag
when the data is passed on to the line discipline, which tweaks a
minor detail of control-char handling in line ending mode but mostly
just means pastes aren't interrupted.)
2019-06-17 19:13:55 +00:00
|
|
|
term_keyinputw(term, &keybuf, 1);
|
2019-09-08 19:29:00 +00:00
|
|
|
} else {
|
|
|
|
char ch = (char) alt_sum;
|
|
|
|
/*
|
|
|
|
* We need not bother about stdin
|
|
|
|
* backlogs here, because in GUI PuTTY
|
|
|
|
* we can't do anything about it
|
|
|
|
* anyway; there's no means of asking
|
|
|
|
* Windows to hold off on KEYDOWN
|
|
|
|
* messages. We _have_ to buffer
|
|
|
|
* everything we're sent.
|
|
|
|
*/
|
|
|
|
term_keyinput(term, -1, &ch, 1);
|
|
|
|
}
|
|
|
|
alt_sum = 0;
|
|
|
|
} else {
|
|
|
|
term_keyinputw(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);
|
|
|
|
} else {
|
|
|
|
WCHAR cbuf[2];
|
|
|
|
cbuf[0] = '\033';
|
|
|
|
cbuf[1] = wch;
|
|
|
|
term_keyinputw(term, cbuf +!left_alt, 1+!!left_alt);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
show_mouseptr(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* This is so the ALT-Numpad and dead keys work correctly. */
|
|
|
|
keys_unicode[0] = 0;
|
|
|
|
|
|
|
|
return p - output;
|
|
|
|
}
|
|
|
|
/* If we're definitely not building up an ALT-54321 then clear it */
|
|
|
|
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))
|
|
|
|
keys_unicode[0] = 10;
|
1999-01-08 13:02:13 +00:00
|
|
|
}
|
|
|
|
|
2001-09-07 21:39:03 +00:00
|
|
|
/*
|
|
|
|
* ALT alone may or may not want to bring up the System menu.
|
|
|
|
* If it's not meant to, we return 0 on presses or releases of
|
|
|
|
* ALT, to show that we've swallowed the keystroke. Otherwise
|
|
|
|
* we return -1, which means Windows will give the keystroke
|
|
|
|
* its default handling (i.e. bring up the System menu).
|
|
|
|
*/
|
2018-10-29 19:57:31 +00:00
|
|
|
if (wParam == VK_MENU && !conf_get_bool(conf, CONF_alt_only))
|
2019-09-08 19:29:00 +00:00
|
|
|
return 0;
|
1999-01-08 13:02:13 +00:00
|
|
|
|
2000-07-26 12:13:51 +00:00
|
|
|
return -1;
|
1999-01-08 13:02:13 +00:00
|
|
|
}
|
|
|
|
|
Remove the 'Frontend' type and replace it with a vtable.
After the recent Seat and LogContext revamps, _nearly_ all the
remaining uses of the type 'Frontend' were in terminal.c, which needs
all sorts of interactions with the GUI window the terminal lives in,
from the obvious (actually drawing text on the window, reading and
writing the clipboard) to the obscure (minimising, maximising and
moving the window in response to particular escape sequences).
All of those functions are now provided by an abstraction called
TermWin. The few remaining uses of Frontend after _that_ are internal
to a particular platform directory, so as to spread the implementation
of that particular kind of Frontend between multiple source files; so
I've renamed all of those so that they take a more specifically named
type that refers to the particular implementation rather than the
general abstraction.
So now the name 'Frontend' no longer exists in the code base at all,
and everywhere one used to be used, it's completely clear whether it
was operating in one of Frontend's three abstract roles (and if so,
which), or whether it was specific to a particular implementation.
Another type that's disappeared is 'Context', which used to be a
typedef defined to something different on each platform, describing
whatever short-lived resources were necessary to draw on the terminal
window: the front end would provide a ready-made one when calling
term_paint, and the terminal could request one with get_ctx/free_ctx
if it wanted to do proactive window updates. Now that drawing context
lives inside the TermWin itself, because there was never any need to
have two of those contexts live at the same time.
(Another minor API change is that the window-title functions - both
reading and writing - have had a missing 'const' added to their char *
parameters / return values.)
I don't expect this change to enable any particularly interesting new
functionality (in particular, I have no plans that need more than one
implementation of TermWin in the same application). But it completes
the tidying-up that began with the Seat and LogContext rework.
2018-10-25 17:44:04 +00:00
|
|
|
static void wintw_set_title(TermWin *tw, const char *title)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
|
|
|
sfree(window_name);
|
2021-01-21 19:57:38 +00:00
|
|
|
window_name = dupstr(title);
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
if (conf_get_bool(conf, CONF_win_name_always) || !IsIconic(wgs.term_hwnd))
|
|
|
|
SetWindowText(wgs.term_hwnd, title);
|
1999-01-08 13:02:13 +00:00
|
|
|
}
|
|
|
|
|
Remove the 'Frontend' type and replace it with a vtable.
After the recent Seat and LogContext revamps, _nearly_ all the
remaining uses of the type 'Frontend' were in terminal.c, which needs
all sorts of interactions with the GUI window the terminal lives in,
from the obvious (actually drawing text on the window, reading and
writing the clipboard) to the obscure (minimising, maximising and
moving the window in response to particular escape sequences).
All of those functions are now provided by an abstraction called
TermWin. The few remaining uses of Frontend after _that_ are internal
to a particular platform directory, so as to spread the implementation
of that particular kind of Frontend between multiple source files; so
I've renamed all of those so that they take a more specifically named
type that refers to the particular implementation rather than the
general abstraction.
So now the name 'Frontend' no longer exists in the code base at all,
and everywhere one used to be used, it's completely clear whether it
was operating in one of Frontend's three abstract roles (and if so,
which), or whether it was specific to a particular implementation.
Another type that's disappeared is 'Context', which used to be a
typedef defined to something different on each platform, describing
whatever short-lived resources were necessary to draw on the terminal
window: the front end would provide a ready-made one when calling
term_paint, and the terminal could request one with get_ctx/free_ctx
if it wanted to do proactive window updates. Now that drawing context
lives inside the TermWin itself, because there was never any need to
have two of those contexts live at the same time.
(Another minor API change is that the window-title functions - both
reading and writing - have had a missing 'const' added to their char *
parameters / return values.)
I don't expect this change to enable any particularly interesting new
functionality (in particular, I have no plans that need more than one
implementation of TermWin in the same application). But it completes
the tidying-up that began with the Seat and LogContext rework.
2018-10-25 17:44:04 +00:00
|
|
|
static void wintw_set_icon_title(TermWin *tw, const char *title)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
|
|
|
sfree(icon_name);
|
2021-01-21 19:57:38 +00:00
|
|
|
icon_name = dupstr(title);
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
if (!conf_get_bool(conf, CONF_win_name_always) && IsIconic(wgs.term_hwnd))
|
|
|
|
SetWindowText(wgs.term_hwnd, title);
|
1999-01-08 13:02:13 +00:00
|
|
|
}
|
|
|
|
|
Remove the 'Frontend' type and replace it with a vtable.
After the recent Seat and LogContext revamps, _nearly_ all the
remaining uses of the type 'Frontend' were in terminal.c, which needs
all sorts of interactions with the GUI window the terminal lives in,
from the obvious (actually drawing text on the window, reading and
writing the clipboard) to the obscure (minimising, maximising and
moving the window in response to particular escape sequences).
All of those functions are now provided by an abstraction called
TermWin. The few remaining uses of Frontend after _that_ are internal
to a particular platform directory, so as to spread the implementation
of that particular kind of Frontend between multiple source files; so
I've renamed all of those so that they take a more specifically named
type that refers to the particular implementation rather than the
general abstraction.
So now the name 'Frontend' no longer exists in the code base at all,
and everywhere one used to be used, it's completely clear whether it
was operating in one of Frontend's three abstract roles (and if so,
which), or whether it was specific to a particular implementation.
Another type that's disappeared is 'Context', which used to be a
typedef defined to something different on each platform, describing
whatever short-lived resources were necessary to draw on the terminal
window: the front end would provide a ready-made one when calling
term_paint, and the terminal could request one with get_ctx/free_ctx
if it wanted to do proactive window updates. Now that drawing context
lives inside the TermWin itself, because there was never any need to
have two of those contexts live at the same time.
(Another minor API change is that the window-title functions - both
reading and writing - have had a missing 'const' added to their char *
parameters / return values.)
I don't expect this change to enable any particularly interesting new
functionality (in particular, I have no plans that need more than one
implementation of TermWin in the same application). But it completes
the tidying-up that began with the Seat and LogContext rework.
2018-10-25 17:44:04 +00:00
|
|
|
static void wintw_set_scrollbar(TermWin *tw, int total, int start, int page)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
1999-01-08 13:02:13 +00:00
|
|
|
SCROLLINFO si;
|
2000-07-26 12:13:51 +00:00
|
|
|
|
2018-10-29 19:57:31 +00:00
|
|
|
if (!conf_get_bool(conf, is_full_screen() ?
|
|
|
|
CONF_scrollbar_in_fullscreen : CONF_scrollbar))
|
2019-09-08 19:29:00 +00:00
|
|
|
return;
|
2000-07-26 12:13:51 +00:00
|
|
|
|
1999-01-08 13:02:13 +00:00
|
|
|
si.cbSize = sizeof(si);
|
2000-07-26 12:13:51 +00:00
|
|
|
si.fMask = SIF_ALL | SIF_DISABLENOSCROLL;
|
1999-01-08 13:02:13 +00:00
|
|
|
si.nMin = 0;
|
|
|
|
si.nMax = total - 1;
|
|
|
|
si.nPage = page;
|
|
|
|
si.nPos = start;
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
if (wgs.term_hwnd)
|
|
|
|
SetScrollInfo(wgs.term_hwnd, SB_VERT, &si, true);
|
1999-01-08 13:02:13 +00:00
|
|
|
}
|
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
static bool wintw_setup_draw_ctx(TermWin *tw)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
Remove the 'Frontend' type and replace it with a vtable.
After the recent Seat and LogContext revamps, _nearly_ all the
remaining uses of the type 'Frontend' were in terminal.c, which needs
all sorts of interactions with the GUI window the terminal lives in,
from the obvious (actually drawing text on the window, reading and
writing the clipboard) to the obscure (minimising, maximising and
moving the window in response to particular escape sequences).
All of those functions are now provided by an abstraction called
TermWin. The few remaining uses of Frontend after _that_ are internal
to a particular platform directory, so as to spread the implementation
of that particular kind of Frontend between multiple source files; so
I've renamed all of those so that they take a more specifically named
type that refers to the particular implementation rather than the
general abstraction.
So now the name 'Frontend' no longer exists in the code base at all,
and everywhere one used to be used, it's completely clear whether it
was operating in one of Frontend's three abstract roles (and if so,
which), or whether it was specific to a particular implementation.
Another type that's disappeared is 'Context', which used to be a
typedef defined to something different on each platform, describing
whatever short-lived resources were necessary to draw on the terminal
window: the front end would provide a ready-made one when calling
term_paint, and the terminal could request one with get_ctx/free_ctx
if it wanted to do proactive window updates. Now that drawing context
lives inside the TermWin itself, because there was never any need to
have two of those contexts live at the same time.
(Another minor API change is that the window-title functions - both
reading and writing - have had a missing 'const' added to their char *
parameters / return values.)
I don't expect this change to enable any particularly interesting new
functionality (in particular, I have no plans that need more than one
implementation of TermWin in the same application). But it completes
the tidying-up that began with the Seat and LogContext rework.
2018-10-25 17:44:04 +00:00
|
|
|
assert(!wintw_hdc);
|
|
|
|
wintw_hdc = make_hdc();
|
|
|
|
return wintw_hdc != NULL;
|
1999-01-08 13:02:13 +00:00
|
|
|
}
|
|
|
|
|
Remove the 'Frontend' type and replace it with a vtable.
After the recent Seat and LogContext revamps, _nearly_ all the
remaining uses of the type 'Frontend' were in terminal.c, which needs
all sorts of interactions with the GUI window the terminal lives in,
from the obvious (actually drawing text on the window, reading and
writing the clipboard) to the obscure (minimising, maximising and
moving the window in response to particular escape sequences).
All of those functions are now provided by an abstraction called
TermWin. The few remaining uses of Frontend after _that_ are internal
to a particular platform directory, so as to spread the implementation
of that particular kind of Frontend between multiple source files; so
I've renamed all of those so that they take a more specifically named
type that refers to the particular implementation rather than the
general abstraction.
So now the name 'Frontend' no longer exists in the code base at all,
and everywhere one used to be used, it's completely clear whether it
was operating in one of Frontend's three abstract roles (and if so,
which), or whether it was specific to a particular implementation.
Another type that's disappeared is 'Context', which used to be a
typedef defined to something different on each platform, describing
whatever short-lived resources were necessary to draw on the terminal
window: the front end would provide a ready-made one when calling
term_paint, and the terminal could request one with get_ctx/free_ctx
if it wanted to do proactive window updates. Now that drawing context
lives inside the TermWin itself, because there was never any need to
have two of those contexts live at the same time.
(Another minor API change is that the window-title functions - both
reading and writing - have had a missing 'const' added to their char *
parameters / return values.)
I don't expect this change to enable any particularly interesting new
functionality (in particular, I have no plans that need more than one
implementation of TermWin in the same application). But it completes
the tidying-up that began with the Seat and LogContext rework.
2018-10-25 17:44:04 +00:00
|
|
|
static void wintw_free_draw_ctx(TermWin *tw)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
Remove the 'Frontend' type and replace it with a vtable.
After the recent Seat and LogContext revamps, _nearly_ all the
remaining uses of the type 'Frontend' were in terminal.c, which needs
all sorts of interactions with the GUI window the terminal lives in,
from the obvious (actually drawing text on the window, reading and
writing the clipboard) to the obscure (minimising, maximising and
moving the window in response to particular escape sequences).
All of those functions are now provided by an abstraction called
TermWin. The few remaining uses of Frontend after _that_ are internal
to a particular platform directory, so as to spread the implementation
of that particular kind of Frontend between multiple source files; so
I've renamed all of those so that they take a more specifically named
type that refers to the particular implementation rather than the
general abstraction.
So now the name 'Frontend' no longer exists in the code base at all,
and everywhere one used to be used, it's completely clear whether it
was operating in one of Frontend's three abstract roles (and if so,
which), or whether it was specific to a particular implementation.
Another type that's disappeared is 'Context', which used to be a
typedef defined to something different on each platform, describing
whatever short-lived resources were necessary to draw on the terminal
window: the front end would provide a ready-made one when calling
term_paint, and the terminal could request one with get_ctx/free_ctx
if it wanted to do proactive window updates. Now that drawing context
lives inside the TermWin itself, because there was never any need to
have two of those contexts live at the same time.
(Another minor API change is that the window-title functions - both
reading and writing - have had a missing 'const' added to their char *
parameters / return values.)
I don't expect this change to enable any particularly interesting new
functionality (in particular, I have no plans that need more than one
implementation of TermWin in the same application). But it completes
the tidying-up that began with the Seat and LogContext rework.
2018-10-25 17:44:04 +00:00
|
|
|
assert(wintw_hdc);
|
|
|
|
free_hdc(wintw_hdc);
|
|
|
|
wintw_hdc = NULL;
|
1999-01-08 13:02:13 +00:00
|
|
|
}
|
|
|
|
|
Centralise palette setup into terminal.c.
Now terminal.c makes nearly all the decisions about what the colour
palette should actually contain: it does the job of reading the
GUI-configurable colours out of Conf, and also the job of making up
the rest of the xterm-256 palette. The only exception is that TermWin
can provide a method to override some of the default colours, which on
Windows is used to implement the 'Use system colours' config option.
This saves code overall, partly because the front ends don't have to
be able to send palette data back to the Terminal any more (the
Terminal keeps the master copy and can answer palette-query escape
sequences from its own knowledge), and also because now there's only
one copy of the xterm-256 palette setup code (previously gtkwin.c and
window.c each had their own version of it).
In this rewrite, I've also introduced a multi-layered storage system
for the palette data in Terminal. One layer contains the palette
information derived from Conf; the next contains platform overrides
(currently just Windows's 'Use system colours'); the last one contains
overrides set by escape sequences in the middle of the session. The
topmost two layers can each _conditionally_ override the ones below.
As a result, if a server-side application manually resets (say) the
default fg and bg colours in mid-session to something that works well
in a particular application, those changes won't be wiped out by a
change in the Windows system colours or the Conf, which they would
have been before. Instead, changes in Conf or the system colours alter
the lower layers of the structure, but then when palette_rebuild is
called, the upper layer continues to override them, until a palette
reset (ESC]R) or terminal reset (e.g. ESC c) removes those upper-layer
changes. This seems like a more consistent strategy, in that the same
set of configuration settings will produce the same end result
regardless of what order they were applied in.
The palette-related methods in TermWin have had a total rework.
palette_get and palette_reset are both gone; palette_set can now set a
contiguous range of colours in one go; and the new
palette_get_overrides replaces window.c's old systopalette().
2021-02-07 19:59:21 +00:00
|
|
|
/*
|
|
|
|
* Set up the colour palette.
|
|
|
|
*/
|
|
|
|
static void init_palette(void)
|
2017-10-05 19:43:02 +00:00
|
|
|
{
|
Centralise palette setup into terminal.c.
Now terminal.c makes nearly all the decisions about what the colour
palette should actually contain: it does the job of reading the
GUI-configurable colours out of Conf, and also the job of making up
the rest of the xterm-256 palette. The only exception is that TermWin
can provide a method to override some of the default colours, which on
Windows is used to implement the 'Use system colours' config option.
This saves code overall, partly because the front ends don't have to
be able to send palette data back to the Terminal any more (the
Terminal keeps the master copy and can answer palette-query escape
sequences from its own knowledge), and also because now there's only
one copy of the xterm-256 palette setup code (previously gtkwin.c and
window.c each had their own version of it).
In this rewrite, I've also introduced a multi-layered storage system
for the palette data in Terminal. One layer contains the palette
information derived from Conf; the next contains platform overrides
(currently just Windows's 'Use system colours'); the last one contains
overrides set by escape sequences in the middle of the session. The
topmost two layers can each _conditionally_ override the ones below.
As a result, if a server-side application manually resets (say) the
default fg and bg colours in mid-session to something that works well
in a particular application, those changes won't be wiped out by a
change in the Windows system colours or the Conf, which they would
have been before. Instead, changes in Conf or the system colours alter
the lower layers of the structure, but then when palette_rebuild is
called, the upper layer continues to override them, until a palette
reset (ESC]R) or terminal reset (e.g. ESC c) removes those upper-layer
changes. This seems like a more consistent strategy, in that the same
set of configuration settings will produce the same end result
regardless of what order they were applied in.
The palette-related methods in TermWin have had a total rework.
palette_get and palette_reset are both gone; palette_set can now set a
contiguous range of colours in one go; and the new
palette_get_overrides replaces window.c's old systopalette().
2021-02-07 19:59:21 +00:00
|
|
|
pal = NULL;
|
|
|
|
logpal = snew_plus(LOGPALETTE, (OSC4_NCOLOURS - 1) * sizeof(PALETTEENTRY));
|
|
|
|
logpal->palVersion = 0x300;
|
|
|
|
logpal->palNumEntries = OSC4_NCOLOURS;
|
|
|
|
for (unsigned i = 0; i < OSC4_NCOLOURS; i++)
|
|
|
|
logpal->palPalEntry[i].peFlags = PC_NOCOLLAPSE;
|
1999-01-08 13:02:13 +00:00
|
|
|
}
|
|
|
|
|
Centralise palette setup into terminal.c.
Now terminal.c makes nearly all the decisions about what the colour
palette should actually contain: it does the job of reading the
GUI-configurable colours out of Conf, and also the job of making up
the rest of the xterm-256 palette. The only exception is that TermWin
can provide a method to override some of the default colours, which on
Windows is used to implement the 'Use system colours' config option.
This saves code overall, partly because the front ends don't have to
be able to send palette data back to the Terminal any more (the
Terminal keeps the master copy and can answer palette-query escape
sequences from its own knowledge), and also because now there's only
one copy of the xterm-256 palette setup code (previously gtkwin.c and
window.c each had their own version of it).
In this rewrite, I've also introduced a multi-layered storage system
for the palette data in Terminal. One layer contains the palette
information derived from Conf; the next contains platform overrides
(currently just Windows's 'Use system colours'); the last one contains
overrides set by escape sequences in the middle of the session. The
topmost two layers can each _conditionally_ override the ones below.
As a result, if a server-side application manually resets (say) the
default fg and bg colours in mid-session to something that works well
in a particular application, those changes won't be wiped out by a
change in the Windows system colours or the Conf, which they would
have been before. Instead, changes in Conf or the system colours alter
the lower layers of the structure, but then when palette_rebuild is
called, the upper layer continues to override them, until a palette
reset (ESC]R) or terminal reset (e.g. ESC c) removes those upper-layer
changes. This seems like a more consistent strategy, in that the same
set of configuration settings will produce the same end result
regardless of what order they were applied in.
The palette-related methods in TermWin have had a total rework.
palette_get and palette_reset are both gone; palette_set can now set a
contiguous range of colours in one go; and the new
palette_get_overrides replaces window.c's old systopalette().
2021-02-07 19:59:21 +00:00
|
|
|
static void wintw_palette_set(TermWin *win, unsigned start,
|
|
|
|
unsigned ncolours, const rgb *colours_in)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
Centralise palette setup into terminal.c.
Now terminal.c makes nearly all the decisions about what the colour
palette should actually contain: it does the job of reading the
GUI-configurable colours out of Conf, and also the job of making up
the rest of the xterm-256 palette. The only exception is that TermWin
can provide a method to override some of the default colours, which on
Windows is used to implement the 'Use system colours' config option.
This saves code overall, partly because the front ends don't have to
be able to send palette data back to the Terminal any more (the
Terminal keeps the master copy and can answer palette-query escape
sequences from its own knowledge), and also because now there's only
one copy of the xterm-256 palette setup code (previously gtkwin.c and
window.c each had their own version of it).
In this rewrite, I've also introduced a multi-layered storage system
for the palette data in Terminal. One layer contains the palette
information derived from Conf; the next contains platform overrides
(currently just Windows's 'Use system colours'); the last one contains
overrides set by escape sequences in the middle of the session. The
topmost two layers can each _conditionally_ override the ones below.
As a result, if a server-side application manually resets (say) the
default fg and bg colours in mid-session to something that works well
in a particular application, those changes won't be wiped out by a
change in the Windows system colours or the Conf, which they would
have been before. Instead, changes in Conf or the system colours alter
the lower layers of the structure, but then when palette_rebuild is
called, the upper layer continues to override them, until a palette
reset (ESC]R) or terminal reset (e.g. ESC c) removes those upper-layer
changes. This seems like a more consistent strategy, in that the same
set of configuration settings will produce the same end result
regardless of what order they were applied in.
The palette-related methods in TermWin have had a total rework.
palette_get and palette_reset are both gone; palette_set can now set a
contiguous range of colours in one go; and the new
palette_get_overrides replaces window.c's old systopalette().
2021-02-07 19:59:21 +00:00
|
|
|
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];
|
|
|
|
out->peRed = in->r;
|
|
|
|
out->peGreen = in->g;
|
|
|
|
out->peBlue = in->b;
|
|
|
|
colours[i + start] = RGB(in->r, in->g, in->b) ^ colorref_modifier;
|
1999-01-08 13:02:13 +00:00
|
|
|
}
|
|
|
|
|
Centralise palette setup into terminal.c.
Now terminal.c makes nearly all the decisions about what the colour
palette should actually contain: it does the job of reading the
GUI-configurable colours out of Conf, and also the job of making up
the rest of the xterm-256 palette. The only exception is that TermWin
can provide a method to override some of the default colours, which on
Windows is used to implement the 'Use system colours' config option.
This saves code overall, partly because the front ends don't have to
be able to send palette data back to the Terminal any more (the
Terminal keeps the master copy and can answer palette-query escape
sequences from its own knowledge), and also because now there's only
one copy of the xterm-256 palette setup code (previously gtkwin.c and
window.c each had their own version of it).
In this rewrite, I've also introduced a multi-layered storage system
for the palette data in Terminal. One layer contains the palette
information derived from Conf; the next contains platform overrides
(currently just Windows's 'Use system colours'); the last one contains
overrides set by escape sequences in the middle of the session. The
topmost two layers can each _conditionally_ override the ones below.
As a result, if a server-side application manually resets (say) the
default fg and bg colours in mid-session to something that works well
in a particular application, those changes won't be wiped out by a
change in the Windows system colours or the Conf, which they would
have been before. Instead, changes in Conf or the system colours alter
the lower layers of the structure, but then when palette_rebuild is
called, the upper layer continues to override them, until a palette
reset (ESC]R) or terminal reset (e.g. ESC c) removes those upper-layer
changes. This seems like a more consistent strategy, in that the same
set of configuration settings will produce the same end result
regardless of what order they were applied in.
The palette-related methods in TermWin have had a total rework.
palette_get and palette_reset are both gone; palette_set can now set a
contiguous range of colours in one go; and the new
palette_get_overrides replaces window.c's old systopalette().
2021-02-07 19:59:21 +00:00
|
|
|
bool got_new_palette = false;
|
|
|
|
|
|
|
|
if (!tried_pal && conf_get_bool(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);
|
|
|
|
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);
|
|
|
|
for (unsigned i = 0; i < OSC4_NCOLOURS; i++)
|
|
|
|
colours[i] ^= colorref_modifier;
|
|
|
|
|
|
|
|
/* Inhibit the SetPaletteEntries call below */
|
|
|
|
got_new_palette = true;
|
|
|
|
}
|
2019-09-08 19:29:00 +00:00
|
|
|
}
|
Centralise palette setup into terminal.c.
Now terminal.c makes nearly all the decisions about what the colour
palette should actually contain: it does the job of reading the
GUI-configurable colours out of Conf, and also the job of making up
the rest of the xterm-256 palette. The only exception is that TermWin
can provide a method to override some of the default colours, which on
Windows is used to implement the 'Use system colours' config option.
This saves code overall, partly because the front ends don't have to
be able to send palette data back to the Terminal any more (the
Terminal keeps the master copy and can answer palette-query escape
sequences from its own knowledge), and also because now there's only
one copy of the xterm-256 palette setup code (previously gtkwin.c and
window.c each had their own version of it).
In this rewrite, I've also introduced a multi-layered storage system
for the palette data in Terminal. One layer contains the palette
information derived from Conf; the next contains platform overrides
(currently just Windows's 'Use system colours'); the last one contains
overrides set by escape sequences in the middle of the session. The
topmost two layers can each _conditionally_ override the ones below.
As a result, if a server-side application manually resets (say) the
default fg and bg colours in mid-session to something that works well
in a particular application, those changes won't be wiped out by a
change in the Windows system colours or the Conf, which they would
have been before. Instead, changes in Conf or the system colours alter
the lower layers of the structure, but then when palette_rebuild is
called, the upper layer continues to override them, until a palette
reset (ESC]R) or terminal reset (e.g. ESC c) removes those upper-layer
changes. This seems like a more consistent strategy, in that the same
set of configuration settings will produce the same end result
regardless of what order they were applied in.
The palette-related methods in TermWin have had a total rework.
palette_get and palette_reset are both gone; palette_set can now set a
contiguous range of colours in one go; and the new
palette_get_overrides replaces window.c's old systopalette().
2021-02-07 19:59:21 +00:00
|
|
|
ReleaseDC(wgs.term_hwnd, hdc);
|
|
|
|
tried_pal = true;
|
1999-01-08 13:02:13 +00:00
|
|
|
}
|
|
|
|
|
Centralise palette setup into terminal.c.
Now terminal.c makes nearly all the decisions about what the colour
palette should actually contain: it does the job of reading the
GUI-configurable colours out of Conf, and also the job of making up
the rest of the xterm-256 palette. The only exception is that TermWin
can provide a method to override some of the default colours, which on
Windows is used to implement the 'Use system colours' config option.
This saves code overall, partly because the front ends don't have to
be able to send palette data back to the Terminal any more (the
Terminal keeps the master copy and can answer palette-query escape
sequences from its own knowledge), and also because now there's only
one copy of the xterm-256 palette setup code (previously gtkwin.c and
window.c each had their own version of it).
In this rewrite, I've also introduced a multi-layered storage system
for the palette data in Terminal. One layer contains the palette
information derived from Conf; the next contains platform overrides
(currently just Windows's 'Use system colours'); the last one contains
overrides set by escape sequences in the middle of the session. The
topmost two layers can each _conditionally_ override the ones below.
As a result, if a server-side application manually resets (say) the
default fg and bg colours in mid-session to something that works well
in a particular application, those changes won't be wiped out by a
change in the Windows system colours or the Conf, which they would
have been before. Instead, changes in Conf or the system colours alter
the lower layers of the structure, but then when palette_rebuild is
called, the upper layer continues to override them, until a palette
reset (ESC]R) or terminal reset (e.g. ESC c) removes those upper-layer
changes. This seems like a more consistent strategy, in that the same
set of configuration settings will produce the same end result
regardless of what order they were applied in.
The palette-related methods in TermWin have had a total rework.
palette_get and palette_reset are both gone; palette_set can now set a
contiguous range of colours in one go; and the new
palette_get_overrides replaces window.c's old systopalette().
2021-02-07 19:59:21 +00:00
|
|
|
if (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);
|
|
|
|
|
|
|
|
HDC hdc = make_hdc();
|
|
|
|
UnrealizeObject(pal);
|
2019-09-08 19:29:00 +00:00
|
|
|
RealizePalette(hdc);
|
|
|
|
free_hdc(hdc);
|
Centralise palette setup into terminal.c.
Now terminal.c makes nearly all the decisions about what the colour
palette should actually contain: it does the job of reading the
GUI-configurable colours out of Conf, and also the job of making up
the rest of the xterm-256 palette. The only exception is that TermWin
can provide a method to override some of the default colours, which on
Windows is used to implement the 'Use system colours' config option.
This saves code overall, partly because the front ends don't have to
be able to send palette data back to the Terminal any more (the
Terminal keeps the master copy and can answer palette-query escape
sequences from its own knowledge), and also because now there's only
one copy of the xterm-256 palette setup code (previously gtkwin.c and
window.c each had their own version of it).
In this rewrite, I've also introduced a multi-layered storage system
for the palette data in Terminal. One layer contains the palette
information derived from Conf; the next contains platform overrides
(currently just Windows's 'Use system colours'); the last one contains
overrides set by escape sequences in the middle of the session. The
topmost two layers can each _conditionally_ override the ones below.
As a result, if a server-side application manually resets (say) the
default fg and bg colours in mid-session to something that works well
in a particular application, those changes won't be wiped out by a
change in the Windows system colours or the Conf, which they would
have been before. Instead, changes in Conf or the system colours alter
the lower layers of the structure, but then when palette_rebuild is
called, the upper layer continues to override them, until a palette
reset (ESC]R) or terminal reset (e.g. ESC c) removes those upper-layer
changes. This seems like a more consistent strategy, in that the same
set of configuration settings will produce the same end result
regardless of what order they were applied in.
The palette-related methods in TermWin have had a total rework.
palette_get and palette_reset are both gone; palette_set can now set a
contiguous range of colours in one go; and the new
palette_get_overrides replaces window.c's old systopalette().
2021-02-07 19:59:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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. */
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
InvalidateRect(wgs.term_hwnd, NULL, true);
|
1999-01-08 13:02:13 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
void write_aclip(int clipboard, char *data, int len, bool must_deselect)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
1999-01-08 13:02:13 +00:00
|
|
|
HGLOBAL clipdata;
|
|
|
|
void *lock;
|
|
|
|
|
2017-12-09 12:00:13 +00:00
|
|
|
if (clipboard != CLIP_SYSTEM)
|
|
|
|
return;
|
|
|
|
|
2001-05-06 14:35:20 +00:00
|
|
|
clipdata = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, len + 1);
|
1999-01-08 13:02:13 +00:00
|
|
|
if (!clipdata)
|
2019-09-08 19:29:00 +00:00
|
|
|
return;
|
2001-05-06 14:35:20 +00:00
|
|
|
lock = GlobalLock(clipdata);
|
1999-01-08 13:02:13 +00:00
|
|
|
if (!lock)
|
2019-09-08 19:29:00 +00:00
|
|
|
return;
|
2001-05-06 14:35:20 +00:00
|
|
|
memcpy(lock, data, len);
|
|
|
|
((unsigned char *) lock)[len] = 0;
|
|
|
|
GlobalUnlock(clipdata);
|
1999-01-08 13:02:13 +00:00
|
|
|
|
2000-10-06 12:32:25 +00:00
|
|
|
if (!must_deselect)
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
SendMessage(wgs.term_hwnd, WM_IGNORE_CLIP, true, 0);
|
2000-10-06 12:32:25 +00:00
|
|
|
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
if (OpenClipboard(wgs.term_hwnd)) {
|
2019-09-08 19:29:00 +00:00
|
|
|
EmptyClipboard();
|
|
|
|
SetClipboardData(CF_TEXT, clipdata);
|
|
|
|
CloseClipboard();
|
1999-01-08 13:02:13 +00:00
|
|
|
} else
|
2019-09-08 19:29:00 +00:00
|
|
|
GlobalFree(clipdata);
|
2000-10-06 12:32:25 +00:00
|
|
|
|
|
|
|
if (!must_deselect)
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
SendMessage(wgs.term_hwnd, WM_IGNORE_CLIP, false, 0);
|
1999-01-08 13:02:13 +00:00
|
|
|
}
|
|
|
|
|
2017-06-13 04:55:57 +00:00
|
|
|
typedef struct _rgbindex {
|
|
|
|
int index;
|
|
|
|
COLORREF ref;
|
|
|
|
} rgbindex;
|
|
|
|
|
|
|
|
int cmpCOLORREF(void *va, void *vb)
|
|
|
|
{
|
|
|
|
COLORREF a = ((rgbindex *)va)->ref;
|
|
|
|
COLORREF b = ((rgbindex *)vb)->ref;
|
|
|
|
return (a < b) ? -1 : (a > b) ? +1 : 0;
|
|
|
|
}
|
|
|
|
|
2001-05-10 08:34:20 +00:00
|
|
|
/*
|
|
|
|
* Note: unlike write_aclip() this will not append a nul.
|
|
|
|
*/
|
Remove the 'Frontend' type and replace it with a vtable.
After the recent Seat and LogContext revamps, _nearly_ all the
remaining uses of the type 'Frontend' were in terminal.c, which needs
all sorts of interactions with the GUI window the terminal lives in,
from the obvious (actually drawing text on the window, reading and
writing the clipboard) to the obscure (minimising, maximising and
moving the window in response to particular escape sequences).
All of those functions are now provided by an abstraction called
TermWin. The few remaining uses of Frontend after _that_ are internal
to a particular platform directory, so as to spread the implementation
of that particular kind of Frontend between multiple source files; so
I've renamed all of those so that they take a more specifically named
type that refers to the particular implementation rather than the
general abstraction.
So now the name 'Frontend' no longer exists in the code base at all,
and everywhere one used to be used, it's completely clear whether it
was operating in one of Frontend's three abstract roles (and if so,
which), or whether it was specific to a particular implementation.
Another type that's disappeared is 'Context', which used to be a
typedef defined to something different on each platform, describing
whatever short-lived resources were necessary to draw on the terminal
window: the front end would provide a ready-made one when calling
term_paint, and the terminal could request one with get_ctx/free_ctx
if it wanted to do proactive window updates. Now that drawing context
lives inside the TermWin itself, because there was never any need to
have two of those contexts live at the same time.
(Another minor API change is that the window-title functions - both
reading and writing - have had a missing 'const' added to their char *
parameters / return values.)
I don't expect this change to enable any particularly interesting new
functionality (in particular, I have no plans that need more than one
implementation of TermWin in the same application). But it completes
the tidying-up that began with the Seat and LogContext rework.
2018-10-25 17:44:04 +00:00
|
|
|
static void wintw_clip_write(
|
|
|
|
TermWin *tw, int clipboard, wchar_t *data, int *attr,
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
truecolour *truecolour, int len, bool must_deselect)
|
2001-05-10 08:34:20 +00:00
|
|
|
{
|
2001-11-07 22:22:53 +00:00
|
|
|
HGLOBAL clipdata, clipdata2, clipdata3;
|
2001-05-10 08:34:20 +00:00
|
|
|
int len2;
|
2001-11-07 22:22:53 +00:00
|
|
|
void *lock, *lock2, *lock3;
|
2001-05-10 08:34:20 +00:00
|
|
|
|
2017-12-09 12:00:13 +00:00
|
|
|
if (clipboard != CLIP_SYSTEM)
|
|
|
|
return;
|
|
|
|
|
2001-05-10 08:34:20 +00:00
|
|
|
len2 = WideCharToMultiByte(CP_ACP, 0, data, len, 0, 0, NULL, NULL);
|
|
|
|
|
|
|
|
clipdata = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE,
|
2019-09-08 19:29:00 +00:00
|
|
|
len * sizeof(wchar_t));
|
2001-05-10 08:34:20 +00:00
|
|
|
clipdata2 = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, len2);
|
|
|
|
|
2001-12-11 18:47:35 +00:00
|
|
|
if (!clipdata || !clipdata2) {
|
2019-09-08 19:29:00 +00:00
|
|
|
if (clipdata)
|
|
|
|
GlobalFree(clipdata);
|
|
|
|
if (clipdata2)
|
|
|
|
GlobalFree(clipdata2);
|
|
|
|
return;
|
2001-05-10 08:34:20 +00:00
|
|
|
}
|
2013-07-22 07:11:54 +00:00
|
|
|
if (!(lock = GlobalLock(clipdata))) {
|
|
|
|
GlobalFree(clipdata);
|
|
|
|
GlobalFree(clipdata2);
|
2019-09-08 19:29:00 +00:00
|
|
|
return;
|
2013-07-22 07:11:54 +00:00
|
|
|
}
|
|
|
|
if (!(lock2 = GlobalLock(clipdata2))) {
|
|
|
|
GlobalUnlock(clipdata);
|
|
|
|
GlobalFree(clipdata);
|
|
|
|
GlobalFree(clipdata2);
|
2019-09-08 19:29:00 +00:00
|
|
|
return;
|
2013-07-22 07:11:54 +00:00
|
|
|
}
|
2001-05-10 08:34:20 +00:00
|
|
|
|
|
|
|
memcpy(lock, data, len * sizeof(wchar_t));
|
|
|
|
WideCharToMultiByte(CP_ACP, 0, data, len, lock2, len2, NULL, NULL);
|
|
|
|
|
2018-10-29 19:57:31 +00:00
|
|
|
if (conf_get_bool(conf, CONF_rtf_paste)) {
|
2019-09-08 19:29:00 +00:00
|
|
|
wchar_t unitab[256];
|
|
|
|
strbuf *rtf = strbuf_new();
|
|
|
|
unsigned char *tdata = (unsigned char *)lock2;
|
|
|
|
wchar_t *udata = (wchar_t *)lock;
|
|
|
|
int uindex = 0, tindex = 0;
|
|
|
|
int multilen, blen, alen, totallen, i;
|
|
|
|
char before[16], after[4];
|
|
|
|
int fgcolour, lastfgcolour = -1;
|
|
|
|
int bgcolour, lastbgcolour = -1;
|
|
|
|
COLORREF fg, lastfg = -1;
|
|
|
|
COLORREF bg, lastbg = -1;
|
|
|
|
int attrBold, lastAttrBold = 0;
|
|
|
|
int attrUnder, lastAttrUnder = 0;
|
2021-02-07 19:59:20 +00:00
|
|
|
int palette[OSC4_NCOLOURS];
|
2019-09-08 19:29:00 +00:00
|
|
|
int numcolours;
|
|
|
|
tree234 *rgbtree = NULL;
|
|
|
|
FontSpec *font = conf_get_fontspec(conf, CONF_font);
|
|
|
|
|
|
|
|
get_unitab(CP_ACP, unitab, 0);
|
|
|
|
|
|
|
|
strbuf_catf(
|
2019-02-11 06:58:07 +00:00
|
|
|
rtf, "{\\rtf1\\ansi\\deff0{\\fonttbl\\f0\\fmodern %s;}\\f0\\fs%d",
|
|
|
|
font->name, font->height*2);
|
2006-02-13 22:18:17 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
/*
|
|
|
|
* Add colour palette
|
|
|
|
* {\colortbl ;\red255\green0\blue0;\red0\green0\blue128;}
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* First - Determine all colours in use
|
|
|
|
* o Foregound and background colours share the same palette
|
|
|
|
*/
|
|
|
|
if (attr) {
|
|
|
|
memset(palette, 0, sizeof(palette));
|
|
|
|
for (i = 0; i < (len-1); i++) {
|
|
|
|
fgcolour = ((attr[i] & ATTR_FGMASK) >> ATTR_FGSHIFT);
|
|
|
|
bgcolour = ((attr[i] & ATTR_BGMASK) >> ATTR_BGSHIFT);
|
|
|
|
|
|
|
|
if (attr[i] & ATTR_REVERSE) {
|
|
|
|
int tmpcolour = fgcolour; /* Swap foreground and background */
|
|
|
|
fgcolour = bgcolour;
|
|
|
|
bgcolour = tmpcolour;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bold_colours && (attr[i] & ATTR_BOLD)) {
|
|
|
|
if (fgcolour < 8) /* ANSI colours */
|
|
|
|
fgcolour += 8;
|
|
|
|
else if (fgcolour >= 256) /* Default colours */
|
|
|
|
fgcolour ++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((attr[i] & ATTR_BLINK)) {
|
|
|
|
if (bgcolour < 8) /* ANSI colours */
|
|
|
|
bgcolour += 8;
|
|
|
|
else if (bgcolour >= 256) /* Default colours */
|
|
|
|
bgcolour ++;
|
|
|
|
}
|
|
|
|
|
|
|
|
palette[fgcolour]++;
|
|
|
|
palette[bgcolour]++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (truecolour) {
|
|
|
|
rgbtree = newtree234(cmpCOLORREF);
|
|
|
|
for (i = 0; i < (len-1); i++) {
|
|
|
|
if (truecolour[i].fg.enabled) {
|
|
|
|
rgbindex *rgbp = snew(rgbindex);
|
|
|
|
rgbp->ref = RGB(truecolour[i].fg.r,
|
|
|
|
truecolour[i].fg.g,
|
|
|
|
truecolour[i].fg.b);
|
|
|
|
if (add234(rgbtree, rgbp) != rgbp)
|
|
|
|
sfree(rgbp);
|
|
|
|
}
|
|
|
|
if (truecolour[i].bg.enabled) {
|
|
|
|
rgbindex *rgbp = snew(rgbindex);
|
|
|
|
rgbp->ref = RGB(truecolour[i].bg.r,
|
|
|
|
truecolour[i].bg.g,
|
|
|
|
truecolour[i].bg.b);
|
|
|
|
if (add234(rgbtree, rgbp) != rgbp)
|
|
|
|
sfree(rgbp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Next - Create a reduced palette
|
|
|
|
*/
|
|
|
|
numcolours = 0;
|
2021-02-07 19:59:20 +00:00
|
|
|
for (i = 0; i < OSC4_NCOLOURS; i++) {
|
2019-09-08 19:29:00 +00:00
|
|
|
if (palette[i] != 0)
|
|
|
|
palette[i] = ++numcolours;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rgbtree) {
|
|
|
|
rgbindex *rgbp;
|
|
|
|
for (i = 0; (rgbp = index234(rgbtree, i)) != NULL; i++)
|
|
|
|
rgbp->index = ++numcolours;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Finally - Write the colour table
|
|
|
|
*/
|
|
|
|
put_datapl(rtf, PTRLEN_LITERAL("{\\colortbl ;"));
|
|
|
|
|
2021-02-07 19:59:20 +00:00
|
|
|
for (i = 0; i < OSC4_NCOLOURS; i++) {
|
2019-09-08 19:29:00 +00:00
|
|
|
if (palette[i] != 0) {
|
Centralise palette setup into terminal.c.
Now terminal.c makes nearly all the decisions about what the colour
palette should actually contain: it does the job of reading the
GUI-configurable colours out of Conf, and also the job of making up
the rest of the xterm-256 palette. The only exception is that TermWin
can provide a method to override some of the default colours, which on
Windows is used to implement the 'Use system colours' config option.
This saves code overall, partly because the front ends don't have to
be able to send palette data back to the Terminal any more (the
Terminal keeps the master copy and can answer palette-query escape
sequences from its own knowledge), and also because now there's only
one copy of the xterm-256 palette setup code (previously gtkwin.c and
window.c each had their own version of it).
In this rewrite, I've also introduced a multi-layered storage system
for the palette data in Terminal. One layer contains the palette
information derived from Conf; the next contains platform overrides
(currently just Windows's 'Use system colours'); the last one contains
overrides set by escape sequences in the middle of the session. The
topmost two layers can each _conditionally_ override the ones below.
As a result, if a server-side application manually resets (say) the
default fg and bg colours in mid-session to something that works well
in a particular application, those changes won't be wiped out by a
change in the Windows system colours or the Conf, which they would
have been before. Instead, changes in Conf or the system colours alter
the lower layers of the structure, but then when palette_rebuild is
called, the upper layer continues to override them, until a palette
reset (ESC]R) or terminal reset (e.g. ESC c) removes those upper-layer
changes. This seems like a more consistent strategy, in that the same
set of configuration settings will produce the same end result
regardless of what order they were applied in.
The palette-related methods in TermWin have had a total rework.
palette_get and palette_reset are both gone; palette_set can now set a
contiguous range of colours in one go; and the new
palette_get_overrides replaces window.c's old systopalette().
2021-02-07 19:59:21 +00:00
|
|
|
const PALETTEENTRY *pe = &logpal->palPalEntry[i];
|
2019-02-11 06:58:07 +00:00
|
|
|
strbuf_catf(rtf, "\\red%d\\green%d\\blue%d;",
|
Centralise palette setup into terminal.c.
Now terminal.c makes nearly all the decisions about what the colour
palette should actually contain: it does the job of reading the
GUI-configurable colours out of Conf, and also the job of making up
the rest of the xterm-256 palette. The only exception is that TermWin
can provide a method to override some of the default colours, which on
Windows is used to implement the 'Use system colours' config option.
This saves code overall, partly because the front ends don't have to
be able to send palette data back to the Terminal any more (the
Terminal keeps the master copy and can answer palette-query escape
sequences from its own knowledge), and also because now there's only
one copy of the xterm-256 palette setup code (previously gtkwin.c and
window.c each had their own version of it).
In this rewrite, I've also introduced a multi-layered storage system
for the palette data in Terminal. One layer contains the palette
information derived from Conf; the next contains platform overrides
(currently just Windows's 'Use system colours'); the last one contains
overrides set by escape sequences in the middle of the session. The
topmost two layers can each _conditionally_ override the ones below.
As a result, if a server-side application manually resets (say) the
default fg and bg colours in mid-session to something that works well
in a particular application, those changes won't be wiped out by a
change in the Windows system colours or the Conf, which they would
have been before. Instead, changes in Conf or the system colours alter
the lower layers of the structure, but then when palette_rebuild is
called, the upper layer continues to override them, until a palette
reset (ESC]R) or terminal reset (e.g. ESC c) removes those upper-layer
changes. This seems like a more consistent strategy, in that the same
set of configuration settings will produce the same end result
regardless of what order they were applied in.
The palette-related methods in TermWin have had a total rework.
palette_get and palette_reset are both gone; palette_set can now set a
contiguous range of colours in one go; and the new
palette_get_overrides replaces window.c's old systopalette().
2021-02-07 19:59:21 +00:00
|
|
|
pe->peRed, pe->peGreen, pe->peBlue);
|
2019-09-08 19:29:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (rgbtree) {
|
|
|
|
rgbindex *rgbp;
|
|
|
|
for (i = 0; (rgbp = index234(rgbtree, i)) != NULL; i++)
|
2019-02-11 06:58:07 +00:00
|
|
|
strbuf_catf(rtf, "\\red%d\\green%d\\blue%d;",
|
|
|
|
GetRValue(rgbp->ref), GetGValue(rgbp->ref),
|
|
|
|
GetBValue(rgbp->ref));
|
2019-09-08 19:29:00 +00:00
|
|
|
}
|
|
|
|
put_datapl(rtf, PTRLEN_LITERAL("}"));
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We want to construct a piece of RTF that specifies the
|
|
|
|
* same Unicode text. To do this we will read back in
|
|
|
|
* parallel from the Unicode data in `udata' and the
|
|
|
|
* non-Unicode data in `tdata'. For each character in
|
|
|
|
* `tdata' which becomes the right thing in `udata' when
|
|
|
|
* looked up in `unitab', we just copy straight over from
|
|
|
|
* tdata. For each one that doesn't, we must WCToMB it
|
|
|
|
* individually and produce a \u escape sequence.
|
|
|
|
*
|
|
|
|
* It would probably be more robust to just bite the bullet
|
|
|
|
* and WCToMB each individual Unicode character one by one,
|
|
|
|
* then MBToWC each one back to see if it was an accurate
|
|
|
|
* translation; but that strikes me as a horrifying number
|
|
|
|
* of Windows API calls so I want to see if this faster way
|
|
|
|
* will work. If it screws up badly we can always revert to
|
|
|
|
* the simple and slow way.
|
|
|
|
*/
|
|
|
|
while (tindex < len2 && uindex < len &&
|
|
|
|
tdata[tindex] && udata[uindex]) {
|
|
|
|
if (tindex + 1 < len2 &&
|
|
|
|
tdata[tindex] == '\r' &&
|
|
|
|
tdata[tindex+1] == '\n') {
|
|
|
|
tindex++;
|
|
|
|
uindex++;
|
2006-02-13 22:18:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set text attributes
|
|
|
|
*/
|
|
|
|
if (attr) {
|
|
|
|
/*
|
|
|
|
* Determine foreground and background colours
|
|
|
|
*/
|
2019-09-08 19:29:00 +00:00
|
|
|
if (truecolour && truecolour[tindex].fg.enabled) {
|
|
|
|
fgcolour = -1;
|
|
|
|
fg = RGB(truecolour[tindex].fg.r,
|
|
|
|
truecolour[tindex].fg.g,
|
|
|
|
truecolour[tindex].fg.b);
|
|
|
|
} else {
|
|
|
|
fgcolour = ((attr[tindex] & ATTR_FGMASK) >> ATTR_FGSHIFT);
|
|
|
|
fg = -1;
|
2006-02-13 22:18:17 +00:00
|
|
|
}
|
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
if (truecolour && truecolour[tindex].bg.enabled) {
|
|
|
|
bgcolour = -1;
|
|
|
|
bg = RGB(truecolour[tindex].bg.r,
|
|
|
|
truecolour[tindex].bg.g,
|
|
|
|
truecolour[tindex].bg.b);
|
|
|
|
} else {
|
|
|
|
bgcolour = ((attr[tindex] & ATTR_BGMASK) >> ATTR_BGSHIFT);
|
|
|
|
bg = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (attr[tindex] & ATTR_REVERSE) {
|
|
|
|
int tmpcolour = fgcolour; /* Swap foreground and background */
|
|
|
|
fgcolour = bgcolour;
|
|
|
|
bgcolour = tmpcolour;
|
|
|
|
|
|
|
|
COLORREF tmpref = fg;
|
|
|
|
fg = bg;
|
|
|
|
bg = tmpref;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bold_colours && (attr[tindex] & ATTR_BOLD) && (fgcolour >= 0)) {
|
|
|
|
if (fgcolour < 8) /* ANSI colours */
|
|
|
|
fgcolour += 8;
|
|
|
|
else if (fgcolour >= 256) /* Default colours */
|
|
|
|
fgcolour ++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((attr[tindex] & ATTR_BLINK) && (bgcolour >= 0)) {
|
|
|
|
if (bgcolour < 8) /* ANSI colours */
|
|
|
|
bgcolour += 8;
|
|
|
|
else if (bgcolour >= 256) /* Default colours */
|
|
|
|
bgcolour ++;
|
2006-02-13 22:18:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Collect other attributes
|
|
|
|
*/
|
2019-09-08 19:29:00 +00:00
|
|
|
if (bold_font_mode != BOLD_NONE)
|
|
|
|
attrBold = attr[tindex] & ATTR_BOLD;
|
|
|
|
else
|
|
|
|
attrBold = 0;
|
|
|
|
|
|
|
|
attrUnder = attr[tindex] & ATTR_UNDER;
|
2006-02-13 22:18:17 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Reverse video
|
2019-09-08 19:29:00 +00:00
|
|
|
* o If video isn't reversed, ignore colour attributes for default foregound
|
|
|
|
* or background.
|
|
|
|
* o Special case where bolded text is displayed using the default foregound
|
|
|
|
* and background colours - force to bolded RTF.
|
2006-02-13 22:18:17 +00:00
|
|
|
*/
|
2019-09-08 19:29:00 +00:00
|
|
|
if (!(attr[tindex] & ATTR_REVERSE)) {
|
|
|
|
if (bgcolour >= 256) /* Default color */
|
|
|
|
bgcolour = -1; /* No coloring */
|
2006-02-13 22:18:17 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
if (fgcolour >= 256) { /* Default colour */
|
|
|
|
if (bold_colours && (fgcolour & 1) && bgcolour == -1)
|
|
|
|
attrBold = ATTR_BOLD; /* Emphasize text with bold attribute */
|
2006-02-13 22:18:17 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
fgcolour = -1; /* No coloring */
|
|
|
|
}
|
|
|
|
}
|
2006-02-13 22:18:17 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Write RTF text attributes
|
|
|
|
*/
|
2019-09-08 19:29:00 +00:00
|
|
|
if ((lastfgcolour != fgcolour) || (lastfg != fg)) {
|
|
|
|
lastfgcolour = fgcolour;
|
|
|
|
lastfg = fg;
|
2019-02-11 06:58:07 +00:00
|
|
|
if (fg == -1) {
|
|
|
|
strbuf_catf(rtf, "\\cf%d ",
|
|
|
|
(fgcolour >= 0) ? palette[fgcolour] : 0);
|
|
|
|
} else {
|
2019-09-08 19:29:00 +00:00
|
|
|
rgbindex rgb, *rgbp;
|
|
|
|
rgb.ref = fg;
|
|
|
|
if ((rgbp = find234(rgbtree, &rgb, NULL)) != NULL)
|
|
|
|
strbuf_catf(rtf, "\\cf%d ", rgbp->index);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((lastbgcolour != bgcolour) || (lastbg != bg)) {
|
|
|
|
lastbgcolour = bgcolour;
|
|
|
|
lastbg = bg;
|
|
|
|
if (bg == -1)
|
|
|
|
strbuf_catf(rtf, "\\highlight%d ",
|
2019-02-11 06:58:07 +00:00
|
|
|
(bgcolour >= 0) ? palette[bgcolour] : 0);
|
2019-09-08 19:29:00 +00:00
|
|
|
else {
|
|
|
|
rgbindex rgb, *rgbp;
|
|
|
|
rgb.ref = bg;
|
|
|
|
if ((rgbp = find234(rgbtree, &rgb, NULL)) != NULL)
|
|
|
|
strbuf_catf(rtf, "\\highlight%d ", rgbp->index);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lastAttrBold != attrBold) {
|
|
|
|
lastAttrBold = attrBold;
|
|
|
|
put_datapl(rtf, attrBold ?
|
2019-02-11 06:58:07 +00:00
|
|
|
PTRLEN_LITERAL("\\b ") :
|
|
|
|
PTRLEN_LITERAL("\\b0 "));
|
2019-09-08 19:29:00 +00:00
|
|
|
}
|
2006-02-13 22:18:17 +00:00
|
|
|
|
|
|
|
if (lastAttrUnder != attrUnder) {
|
|
|
|
lastAttrUnder = attrUnder;
|
2019-09-08 19:29:00 +00:00
|
|
|
put_datapl(rtf, attrUnder ?
|
2019-02-11 06:58:07 +00:00
|
|
|
PTRLEN_LITERAL("\\ul ") :
|
|
|
|
PTRLEN_LITERAL("\\ulnone "));
|
2006-02-13 22:18:17 +00:00
|
|
|
}
|
2019-09-08 19:29:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (unitab[tdata[tindex]] == udata[uindex]) {
|
|
|
|
multilen = 1;
|
|
|
|
before[0] = '\0';
|
|
|
|
after[0] = '\0';
|
|
|
|
blen = alen = 0;
|
|
|
|
} else {
|
|
|
|
multilen = WideCharToMultiByte(CP_ACP, 0, unitab+uindex, 1,
|
|
|
|
NULL, 0, NULL, NULL);
|
|
|
|
if (multilen != 1) {
|
|
|
|
blen = sprintf(before, "{\\uc%d\\u%d", (int)multilen,
|
|
|
|
(int)udata[uindex]);
|
|
|
|
alen = 1; strcpy(after, "}");
|
|
|
|
} else {
|
2020-06-16 16:43:55 +00:00
|
|
|
blen = sprintf(before, "\\u%d", (int)udata[uindex]);
|
2019-09-08 19:29:00 +00:00
|
|
|
alen = 0; after[0] = '\0';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
assert(tindex + multilen <= len2);
|
|
|
|
totallen = blen + alen;
|
|
|
|
for (i = 0; i < multilen; i++) {
|
|
|
|
if (tdata[tindex+i] == '\\' ||
|
|
|
|
tdata[tindex+i] == '{' ||
|
|
|
|
tdata[tindex+i] == '}')
|
|
|
|
totallen += 2;
|
|
|
|
else if (tdata[tindex+i] == 0x0D || tdata[tindex+i] == 0x0A)
|
|
|
|
totallen += 6; /* \par\r\n */
|
|
|
|
else if (tdata[tindex+i] > 0x7E || tdata[tindex+i] < 0x20)
|
|
|
|
totallen += 4;
|
|
|
|
else
|
|
|
|
totallen++;
|
|
|
|
}
|
|
|
|
|
|
|
|
put_data(rtf, before, blen);
|
|
|
|
for (i = 0; i < multilen; i++) {
|
|
|
|
if (tdata[tindex+i] == '\\' ||
|
|
|
|
tdata[tindex+i] == '{' ||
|
|
|
|
tdata[tindex+i] == '}') {
|
2019-02-11 06:58:07 +00:00
|
|
|
put_byte(rtf, '\\');
|
|
|
|
put_byte(rtf, tdata[tindex+i]);
|
2019-09-08 19:29:00 +00:00
|
|
|
} else if (tdata[tindex+i] == 0x0D || tdata[tindex+i] == 0x0A) {
|
2019-02-11 06:58:07 +00:00
|
|
|
put_datapl(rtf, PTRLEN_LITERAL("\\par\r\n"));
|
2019-09-08 19:29:00 +00:00
|
|
|
} else if (tdata[tindex+i] > 0x7E || tdata[tindex+i] < 0x20) {
|
2019-02-11 06:58:07 +00:00
|
|
|
strbuf_catf(rtf, "\\'%02x", tdata[tindex+i]);
|
2019-09-08 19:29:00 +00:00
|
|
|
} else {
|
2019-02-11 06:58:07 +00:00
|
|
|
put_byte(rtf, tdata[tindex+i]);
|
2019-09-08 19:29:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
put_data(rtf, after, alen);
|
2001-11-07 22:22:53 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
tindex += multilen;
|
|
|
|
uindex++;
|
|
|
|
}
|
2001-11-07 22:22:53 +00:00
|
|
|
|
2019-02-11 06:58:07 +00:00
|
|
|
put_datapl(rtf, PTRLEN_LITERAL("}\0\0")); /* Terminate RTF stream */
|
2001-11-07 22:22:53 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
clipdata3 = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, rtf->len);
|
|
|
|
if (clipdata3 && (lock3 = GlobalLock(clipdata3)) != NULL) {
|
|
|
|
memcpy(lock3, rtf->u, rtf->len);
|
|
|
|
GlobalUnlock(clipdata3);
|
|
|
|
}
|
|
|
|
strbuf_free(rtf);
|
|
|
|
|
|
|
|
if (rgbtree) {
|
|
|
|
rgbindex *rgbp;
|
|
|
|
while ((rgbp = delpos234(rgbtree, 0)) != NULL)
|
|
|
|
sfree(rgbp);
|
|
|
|
freetree234(rgbtree);
|
|
|
|
}
|
2001-11-07 22:22:53 +00:00
|
|
|
} else
|
2019-09-08 19:29:00 +00:00
|
|
|
clipdata3 = NULL;
|
2001-11-07 22:22:53 +00:00
|
|
|
|
2001-05-10 08:34:20 +00:00
|
|
|
GlobalUnlock(clipdata);
|
|
|
|
GlobalUnlock(clipdata2);
|
|
|
|
|
|
|
|
if (!must_deselect)
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
SendMessage(wgs.term_hwnd, WM_IGNORE_CLIP, true, 0);
|
2001-05-10 08:34:20 +00:00
|
|
|
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
if (OpenClipboard(wgs.term_hwnd)) {
|
2019-09-08 19:29:00 +00:00
|
|
|
EmptyClipboard();
|
|
|
|
SetClipboardData(CF_UNICODETEXT, clipdata);
|
|
|
|
SetClipboardData(CF_TEXT, clipdata2);
|
|
|
|
if (clipdata3)
|
|
|
|
SetClipboardData(RegisterClipboardFormat(CF_RTF), clipdata3);
|
|
|
|
CloseClipboard();
|
2001-05-10 08:34:20 +00:00
|
|
|
} else {
|
2019-09-08 19:29:00 +00:00
|
|
|
GlobalFree(clipdata);
|
|
|
|
GlobalFree(clipdata2);
|
2001-05-10 08:34:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!must_deselect)
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
SendMessage(wgs.term_hwnd, WM_IGNORE_CLIP, false, 0);
|
2001-05-10 08:34:20 +00:00
|
|
|
}
|
|
|
|
|
2008-11-28 18:28:23 +00:00
|
|
|
static DWORD WINAPI clipboard_read_threadfunc(void *param)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
2008-11-28 18:28:23 +00:00
|
|
|
HWND hwnd = (HWND)param;
|
|
|
|
HGLOBAL clipdata;
|
1999-01-08 13:02:13 +00:00
|
|
|
|
2008-11-28 18:28:23 +00:00
|
|
|
if (OpenClipboard(NULL)) {
|
2019-09-08 19:29:00 +00:00
|
|
|
if ((clipdata = GetClipboardData(CF_UNICODETEXT))) {
|
|
|
|
SendMessage(hwnd, WM_GOT_CLIPDATA,
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
(WPARAM)true, (LPARAM)clipdata);
|
2019-09-08 19:29:00 +00:00
|
|
|
} else if ((clipdata = GetClipboardData(CF_TEXT))) {
|
|
|
|
SendMessage(hwnd, WM_GOT_CLIPDATA,
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
(WPARAM)false, (LPARAM)clipdata);
|
2019-09-08 19:29:00 +00:00
|
|
|
}
|
|
|
|
CloseClipboard();
|
2008-11-28 18:28:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
static void process_clipdata(HGLOBAL clipdata, bool unicode)
|
2008-11-28 18:28:23 +00:00
|
|
|
{
|
Stop front ends remembering the data of their last paste.
Previously, both the Unix and Windows front ends would respond to a
paste action by retrieving data from the system clipboard, converting
it appropriately, _storing_ it in a persistent dynamic data block
inside the front end, and then calling term_do_paste(term), which in
turn would call back to the front end via get_clip() to retrieve the
current contents of that stored data block.
But, as far as I can tell, this was a completely pointless mechanism,
because after a data block was written into this storage area, it
would be immediately used for exactly one paste, and then never
accessed again until the next paste action caused it to be freed and
replaced with a new chunk of pasted data.
So why on earth was it stored persistently at all, and why that
callback mechanism from frontend to terminal back to frontend to
retrieve it for the actual paste action? I have no idea. This change
removes the entire system and replaces it with the completely obvious
alternative: the character-set-converted version of paste data is
allocated in a _local_ variable in the frontend paste functions,
passed directly to term_do_paste which now takes (buffer,length)
parameters, and freed immediately afterwards. get_clip() is gone.
2017-12-09 08:41:03 +00:00
|
|
|
wchar_t *clipboard_contents = NULL;
|
|
|
|
size_t clipboard_length = 0;
|
2008-11-28 18:28:23 +00:00
|
|
|
|
|
|
|
if (unicode) {
|
2019-09-08 19:29:00 +00:00
|
|
|
wchar_t *p = GlobalLock(clipdata);
|
|
|
|
wchar_t *p2;
|
|
|
|
|
|
|
|
if (p) {
|
|
|
|
/* Unwilling to rely on Windows having wcslen() */
|
|
|
|
for (p2 = p; *p2; p2++);
|
|
|
|
clipboard_length = p2 - p;
|
|
|
|
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);
|
|
|
|
}
|
2008-11-28 18:28:23 +00:00
|
|
|
} else {
|
2019-09-08 19:29:00 +00:00
|
|
|
char *s = GlobalLock(clipdata);
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (s) {
|
|
|
|
i = MultiByteToWideChar(CP_ACP, 0, s, strlen(s) + 1, 0, 0);
|
|
|
|
clipboard_contents = snewn(i, wchar_t);
|
|
|
|
MultiByteToWideChar(CP_ACP, 0, s, strlen(s) + 1,
|
|
|
|
clipboard_contents, i);
|
|
|
|
clipboard_length = i - 1;
|
|
|
|
clipboard_contents[clipboard_length] = L'\0';
|
|
|
|
term_do_paste(term, clipboard_contents, clipboard_length);
|
|
|
|
}
|
1999-01-08 13:02:13 +00:00
|
|
|
}
|
|
|
|
|
Stop front ends remembering the data of their last paste.
Previously, both the Unix and Windows front ends would respond to a
paste action by retrieving data from the system clipboard, converting
it appropriately, _storing_ it in a persistent dynamic data block
inside the front end, and then calling term_do_paste(term), which in
turn would call back to the front end via get_clip() to retrieve the
current contents of that stored data block.
But, as far as I can tell, this was a completely pointless mechanism,
because after a data block was written into this storage area, it
would be immediately used for exactly one paste, and then never
accessed again until the next paste action caused it to be freed and
replaced with a new chunk of pasted data.
So why on earth was it stored persistently at all, and why that
callback mechanism from frontend to terminal back to frontend to
retrieve it for the actual paste action? I have no idea. This change
removes the entire system and replaces it with the completely obvious
alternative: the character-set-converted version of paste data is
allocated in a _local_ variable in the frontend paste functions,
passed directly to term_do_paste which now takes (buffer,length)
parameters, and freed immediately afterwards. get_clip() is gone.
2017-12-09 08:41:03 +00:00
|
|
|
sfree(clipboard_contents);
|
2008-11-28 18:28:23 +00:00
|
|
|
}
|
|
|
|
|
Remove the 'Frontend' type and replace it with a vtable.
After the recent Seat and LogContext revamps, _nearly_ all the
remaining uses of the type 'Frontend' were in terminal.c, which needs
all sorts of interactions with the GUI window the terminal lives in,
from the obvious (actually drawing text on the window, reading and
writing the clipboard) to the obscure (minimising, maximising and
moving the window in response to particular escape sequences).
All of those functions are now provided by an abstraction called
TermWin. The few remaining uses of Frontend after _that_ are internal
to a particular platform directory, so as to spread the implementation
of that particular kind of Frontend between multiple source files; so
I've renamed all of those so that they take a more specifically named
type that refers to the particular implementation rather than the
general abstraction.
So now the name 'Frontend' no longer exists in the code base at all,
and everywhere one used to be used, it's completely clear whether it
was operating in one of Frontend's three abstract roles (and if so,
which), or whether it was specific to a particular implementation.
Another type that's disappeared is 'Context', which used to be a
typedef defined to something different on each platform, describing
whatever short-lived resources were necessary to draw on the terminal
window: the front end would provide a ready-made one when calling
term_paint, and the terminal could request one with get_ctx/free_ctx
if it wanted to do proactive window updates. Now that drawing context
lives inside the TermWin itself, because there was never any need to
have two of those contexts live at the same time.
(Another minor API change is that the window-title functions - both
reading and writing - have had a missing 'const' added to their char *
parameters / return values.)
I don't expect this change to enable any particularly interesting new
functionality (in particular, I have no plans that need more than one
implementation of TermWin in the same application). But it completes
the tidying-up that began with the Seat and LogContext rework.
2018-10-25 17:44:04 +00:00
|
|
|
static void wintw_clip_request_paste(TermWin *tw, int clipboard)
|
2008-11-28 18:28:23 +00:00
|
|
|
{
|
2017-12-09 12:00:13 +00:00
|
|
|
assert(clipboard == CLIP_SYSTEM);
|
|
|
|
|
2008-11-28 18:28:23 +00:00
|
|
|
/*
|
|
|
|
* I always thought pasting was synchronous in Windows; the
|
|
|
|
* clipboard access functions certainly _look_ synchronous,
|
|
|
|
* unlike the X ones. But in fact it seems that in some
|
|
|
|
* situations the contents of the clipboard might not be
|
|
|
|
* immediately available, and the clipboard-reading functions
|
|
|
|
* may block. This leads to trouble if the application
|
|
|
|
* delivering the clipboard data has to get hold of it by -
|
|
|
|
* for example - talking over a network connection which is
|
|
|
|
* forwarded through this very PuTTY.
|
|
|
|
*
|
|
|
|
* Hence, we spawn a subthread to read the clipboard, and do
|
|
|
|
* our paste when it's finished. The thread will send a
|
|
|
|
* message back to our main window when it terminates, and
|
|
|
|
* that tells us it's OK to paste.
|
|
|
|
*/
|
|
|
|
DWORD in_threadid; /* required for Win9x */
|
|
|
|
CreateThread(NULL, 0, clipboard_read_threadfunc,
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
wgs.term_hwnd, 0, &in_threadid);
|
2008-11-28 18:28:23 +00:00
|
|
|
}
|
|
|
|
|
2002-10-09 18:09:42 +00:00
|
|
|
/*
|
|
|
|
* Print a modal (Really Bad) message box and perform a fatal exit.
|
|
|
|
*/
|
2015-05-15 10:15:42 +00:00
|
|
|
void modalfatalbox(const char *fmt, ...)
|
2002-10-09 18:09:42 +00:00
|
|
|
{
|
|
|
|
va_list ap;
|
2018-12-08 21:03:51 +00:00
|
|
|
char *message, *title;
|
2002-10-09 18:09:42 +00:00
|
|
|
|
|
|
|
va_start(ap, fmt);
|
2018-12-08 21:03:51 +00:00
|
|
|
message = dupvprintf(fmt, ap);
|
2002-10-09 18:09:42 +00:00
|
|
|
va_end(ap);
|
2020-04-14 19:36:46 +00:00
|
|
|
show_mouseptr(true);
|
2018-12-08 21:03:51 +00:00
|
|
|
title = dupprintf("%s Fatal Error", appname);
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
MessageBox(wgs.term_hwnd, message, title,
|
|
|
|
MB_SYSTEMMODAL | MB_ICONERROR | MB_OK);
|
2018-12-08 21:03:51 +00:00
|
|
|
sfree(message);
|
|
|
|
sfree(title);
|
2002-10-09 18:09:42 +00:00
|
|
|
cleanup_exit(1);
|
|
|
|
}
|
|
|
|
|
2013-07-19 17:44:28 +00:00
|
|
|
/*
|
|
|
|
* Print a message box and don't close the connection.
|
|
|
|
*/
|
2015-05-15 10:15:42 +00:00
|
|
|
void nonfatal(const char *fmt, ...)
|
2013-07-19 17:44:28 +00:00
|
|
|
{
|
|
|
|
va_list ap;
|
2018-12-08 21:03:51 +00:00
|
|
|
char *message, *title;
|
2013-07-19 17:44:28 +00:00
|
|
|
|
|
|
|
va_start(ap, fmt);
|
2018-12-08 21:03:51 +00:00
|
|
|
message = dupvprintf(fmt, ap);
|
2013-07-19 17:44:28 +00:00
|
|
|
va_end(ap);
|
2020-04-14 19:36:46 +00:00
|
|
|
show_mouseptr(true);
|
2018-12-08 21:03:51 +00:00
|
|
|
title = dupprintf("%s Error", appname);
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
MessageBox(wgs.term_hwnd, message, title, MB_ICONERROR | MB_OK);
|
2018-12-08 21:03:51 +00:00
|
|
|
sfree(message);
|
|
|
|
sfree(title);
|
2013-07-19 17:44:28 +00:00
|
|
|
}
|
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
static bool flash_window_ex(DWORD dwFlags, UINT uCount, DWORD dwTimeout)
|
2007-01-16 20:54:58 +00:00
|
|
|
{
|
|
|
|
if (p_FlashWindowEx) {
|
2019-09-08 19:29:00 +00:00
|
|
|
FLASHWINFO fi;
|
|
|
|
fi.cbSize = sizeof(fi);
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
fi.hwnd = wgs.term_hwnd;
|
2019-09-08 19:29:00 +00:00
|
|
|
fi.dwFlags = dwFlags;
|
|
|
|
fi.uCount = uCount;
|
|
|
|
fi.dwTimeout = dwTimeout;
|
|
|
|
return (*p_FlashWindowEx)(&fi);
|
2007-01-16 20:54:58 +00:00
|
|
|
}
|
|
|
|
else
|
2019-09-08 19:29:00 +00:00
|
|
|
return false; /* shrug */
|
2007-01-16 20:54:58 +00:00
|
|
|
}
|
|
|
|
|
2004-11-27 13:20:21 +00:00
|
|
|
static void flash_window(int mode);
|
|
|
|
static long next_flash;
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
static bool flashing = false;
|
2004-11-27 13:20:21 +00:00
|
|
|
|
2007-01-16 20:54:58 +00:00
|
|
|
/*
|
|
|
|
* Timer for platforms where we must maintain window flashing manually
|
|
|
|
* (e.g., Win95).
|
|
|
|
*/
|
2012-09-18 21:42:48 +00:00
|
|
|
static void flash_window_timer(void *ctx, unsigned long now)
|
2004-11-27 13:20:21 +00:00
|
|
|
{
|
2012-09-18 21:42:48 +00:00
|
|
|
if (flashing && now == next_flash) {
|
2019-09-08 19:29:00 +00:00
|
|
|
flash_window(1);
|
2004-11-27 13:20:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-05-13 14:42:17 +00:00
|
|
|
/*
|
|
|
|
* Manage window caption / taskbar flashing, if enabled.
|
|
|
|
* 0 = stop, 1 = maintain, 2 = start
|
|
|
|
*/
|
|
|
|
static void flash_window(int mode)
|
|
|
|
{
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
int beep_ind = conf_get_int(conf, CONF_beep_ind);
|
|
|
|
if ((mode == 0) || (beep_ind == B_IND_DISABLED)) {
|
2019-09-08 19:29:00 +00:00
|
|
|
/* stop */
|
|
|
|
if (flashing) {
|
|
|
|
flashing = false;
|
|
|
|
if (p_FlashWindowEx)
|
|
|
|
flash_window_ex(FLASHW_STOP, 0, 0);
|
|
|
|
else
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
FlashWindow(wgs.term_hwnd, false);
|
2019-09-08 19:29:00 +00:00
|
|
|
}
|
2001-05-13 14:42:17 +00:00
|
|
|
|
|
|
|
} else if (mode == 2) {
|
2019-09-08 19:29:00 +00:00
|
|
|
/* start */
|
|
|
|
if (!flashing) {
|
|
|
|
flashing = true;
|
|
|
|
if (p_FlashWindowEx) {
|
|
|
|
/* For so-called "steady" mode, we use uCount=2, which
|
|
|
|
* seems to be the traditional number of flashes used
|
|
|
|
* by user notifications (e.g., by Explorer).
|
|
|
|
* uCount=0 appears to enable continuous flashing, per
|
|
|
|
* "flashing" mode, although I haven't seen this
|
|
|
|
* documented. */
|
|
|
|
flash_window_ex(FLASHW_ALL | FLASHW_TIMER,
|
|
|
|
(beep_ind == B_IND_FLASH ? 0 : 2),
|
|
|
|
0 /* system cursor blink rate */);
|
|
|
|
/* No need to schedule timer */
|
|
|
|
} else {
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
FlashWindow(wgs.term_hwnd, true);
|
|
|
|
next_flash = schedule_timer(450, flash_window_timer,
|
|
|
|
wgs.term_hwnd);
|
2019-09-08 19:29:00 +00:00
|
|
|
}
|
|
|
|
}
|
2001-05-13 14:42:17 +00:00
|
|
|
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
} else if ((mode == 1) && (beep_ind == B_IND_FLASH)) {
|
2019-09-08 19:29:00 +00:00
|
|
|
/* maintain */
|
|
|
|
if (flashing && !p_FlashWindowEx) {
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
FlashWindow(wgs.term_hwnd, true); /* toggle */
|
|
|
|
next_flash = schedule_timer(450, flash_window_timer,
|
|
|
|
wgs.term_hwnd);
|
2019-09-08 19:29:00 +00:00
|
|
|
}
|
2001-05-13 14:42:17 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-01-08 13:02:13 +00:00
|
|
|
/*
|
|
|
|
* Beep.
|
|
|
|
*/
|
Remove the 'Frontend' type and replace it with a vtable.
After the recent Seat and LogContext revamps, _nearly_ all the
remaining uses of the type 'Frontend' were in terminal.c, which needs
all sorts of interactions with the GUI window the terminal lives in,
from the obvious (actually drawing text on the window, reading and
writing the clipboard) to the obscure (minimising, maximising and
moving the window in response to particular escape sequences).
All of those functions are now provided by an abstraction called
TermWin. The few remaining uses of Frontend after _that_ are internal
to a particular platform directory, so as to spread the implementation
of that particular kind of Frontend between multiple source files; so
I've renamed all of those so that they take a more specifically named
type that refers to the particular implementation rather than the
general abstraction.
So now the name 'Frontend' no longer exists in the code base at all,
and everywhere one used to be used, it's completely clear whether it
was operating in one of Frontend's three abstract roles (and if so,
which), or whether it was specific to a particular implementation.
Another type that's disappeared is 'Context', which used to be a
typedef defined to something different on each platform, describing
whatever short-lived resources were necessary to draw on the terminal
window: the front end would provide a ready-made one when calling
term_paint, and the terminal could request one with get_ctx/free_ctx
if it wanted to do proactive window updates. Now that drawing context
lives inside the TermWin itself, because there was never any need to
have two of those contexts live at the same time.
(Another minor API change is that the window-title functions - both
reading and writing - have had a missing 'const' added to their char *
parameters / return values.)
I don't expect this change to enable any particularly interesting new
functionality (in particular, I have no plans that need more than one
implementation of TermWin in the same application). But it completes
the tidying-up that began with the Seat and LogContext rework.
2018-10-25 17:44:04 +00:00
|
|
|
static void wintw_bell(TermWin *tw, int mode)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
2001-04-14 11:37:47 +00:00
|
|
|
if (mode == BELL_DEFAULT) {
|
2019-09-08 19:29:00 +00:00
|
|
|
/*
|
|
|
|
* For MessageBeep style bells, we want to be careful of
|
|
|
|
* timing, because they don't have the nice property of
|
|
|
|
* PlaySound bells that each one cancels the previous
|
|
|
|
* active one. So we limit the rate to one per 50ms or so.
|
|
|
|
*/
|
|
|
|
static long lastbeep = 0;
|
|
|
|
long beepdiff;
|
|
|
|
|
|
|
|
beepdiff = GetTickCount() - lastbeep;
|
|
|
|
if (beepdiff >= 0 && beepdiff < 50)
|
|
|
|
return;
|
|
|
|
MessageBeep(MB_OK);
|
|
|
|
/*
|
|
|
|
* The above MessageBeep call takes time, so we record the
|
|
|
|
* time _after_ it finishes rather than before it starts.
|
|
|
|
*/
|
|
|
|
lastbeep = GetTickCount();
|
2001-04-14 11:37:47 +00:00
|
|
|
} else if (mode == BELL_WAVEFILE) {
|
2019-09-08 19:29:00 +00:00
|
|
|
Filename *bell_wavefile = conf_get_filename(conf, CONF_bell_wavefile);
|
|
|
|
if (!p_PlaySound || !p_PlaySound(bell_wavefile->path, NULL,
|
2017-03-13 21:24:06 +00:00
|
|
|
SND_ASYNC | SND_FILENAME)) {
|
2018-12-08 21:03:51 +00:00
|
|
|
char *buf, *otherbuf;
|
2020-04-14 19:36:46 +00:00
|
|
|
show_mouseptr(true);
|
2018-12-08 21:03:51 +00:00
|
|
|
buf = dupprintf(
|
|
|
|
"Unable to play sound file\n%s\nUsing default sound instead",
|
|
|
|
bell_wavefile->path);
|
|
|
|
otherbuf = dupprintf("%s Sound Error", appname);
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
MessageBox(wgs.term_hwnd, buf, otherbuf,
|
|
|
|
MB_OK | MB_ICONEXCLAMATION);
|
2018-12-08 21:03:51 +00:00
|
|
|
sfree(buf);
|
|
|
|
sfree(otherbuf);
|
2019-09-08 19:29:00 +00:00
|
|
|
conf_set_int(conf, CONF_beep, BELL_DEFAULT);
|
|
|
|
}
|
2003-05-24 12:31:32 +00:00
|
|
|
} else if (mode == BELL_PCSPEAKER) {
|
2019-09-08 19:29:00 +00:00
|
|
|
static long lastbeep = 0;
|
|
|
|
long beepdiff;
|
|
|
|
|
|
|
|
beepdiff = GetTickCount() - lastbeep;
|
|
|
|
if (beepdiff >= 0 && beepdiff < 50)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We must beep in different ways depending on whether this
|
|
|
|
* is a 95-series or NT-series OS.
|
|
|
|
*/
|
|
|
|
if (osPlatformId == VER_PLATFORM_WIN32_NT)
|
|
|
|
Beep(800, 100);
|
|
|
|
else
|
|
|
|
MessageBeep(-1);
|
|
|
|
lastbeep = GetTickCount();
|
2001-04-14 11:37:47 +00:00
|
|
|
}
|
2001-05-13 14:42:17 +00:00
|
|
|
/* Otherwise, either visual bell or disabled; do nothing here */
|
2002-10-22 16:11:33 +00:00
|
|
|
if (!term->has_focus) {
|
2019-09-08 19:29:00 +00:00
|
|
|
flash_window(2); /* start */
|
2001-05-13 14:42:17 +00:00
|
|
|
}
|
1999-01-08 13:02:13 +00:00
|
|
|
}
|
2001-09-13 18:24:51 +00:00
|
|
|
|
2001-11-25 15:21:25 +00:00
|
|
|
/*
|
|
|
|
* Minimise or restore the window in response to a server-side
|
|
|
|
* request.
|
|
|
|
*/
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
static void wintw_set_minimised(TermWin *tw, bool minimised)
|
2001-11-25 15:21:25 +00:00
|
|
|
{
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
if (IsIconic(wgs.term_hwnd)) {
|
2019-09-08 19:29:00 +00:00
|
|
|
if (!minimised)
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
ShowWindow(wgs.term_hwnd, SW_RESTORE);
|
2001-11-25 15:21:25 +00:00
|
|
|
} else {
|
2019-09-08 19:29:00 +00:00
|
|
|
if (minimised)
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
ShowWindow(wgs.term_hwnd, SW_MINIMIZE);
|
2001-11-25 15:21:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Move the window in response to a server-side request.
|
|
|
|
*/
|
Remove the 'Frontend' type and replace it with a vtable.
After the recent Seat and LogContext revamps, _nearly_ all the
remaining uses of the type 'Frontend' were in terminal.c, which needs
all sorts of interactions with the GUI window the terminal lives in,
from the obvious (actually drawing text on the window, reading and
writing the clipboard) to the obscure (minimising, maximising and
moving the window in response to particular escape sequences).
All of those functions are now provided by an abstraction called
TermWin. The few remaining uses of Frontend after _that_ are internal
to a particular platform directory, so as to spread the implementation
of that particular kind of Frontend between multiple source files; so
I've renamed all of those so that they take a more specifically named
type that refers to the particular implementation rather than the
general abstraction.
So now the name 'Frontend' no longer exists in the code base at all,
and everywhere one used to be used, it's completely clear whether it
was operating in one of Frontend's three abstract roles (and if so,
which), or whether it was specific to a particular implementation.
Another type that's disappeared is 'Context', which used to be a
typedef defined to something different on each platform, describing
whatever short-lived resources were necessary to draw on the terminal
window: the front end would provide a ready-made one when calling
term_paint, and the terminal could request one with get_ctx/free_ctx
if it wanted to do proactive window updates. Now that drawing context
lives inside the TermWin itself, because there was never any need to
have two of those contexts live at the same time.
(Another minor API change is that the window-title functions - both
reading and writing - have had a missing 'const' added to their char *
parameters / return values.)
I don't expect this change to enable any particularly interesting new
functionality (in particular, I have no plans that need more than one
implementation of TermWin in the same application). But it completes
the tidying-up that began with the Seat and LogContext rework.
2018-10-25 17:44:04 +00:00
|
|
|
static void wintw_move(TermWin *tw, int x, int y)
|
2001-11-25 15:21:25 +00:00
|
|
|
{
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
int resize_action = conf_get_int(conf, CONF_resize_action);
|
2019-09-08 19:29:00 +00:00
|
|
|
if (resize_action == RESIZE_DISABLED ||
|
|
|
|
resize_action == RESIZE_FONT ||
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
IsZoomed(wgs.term_hwnd))
|
2002-01-08 09:56:06 +00:00
|
|
|
return;
|
|
|
|
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
SetWindowPos(wgs.term_hwnd, NULL, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
|
2001-11-25 15:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Move the window to the top or bottom of the z-order in response
|
|
|
|
* to a server-side request.
|
|
|
|
*/
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
static void wintw_set_zorder(TermWin *tw, bool top)
|
2001-11-25 15:21:25 +00:00
|
|
|
{
|
2018-10-29 19:57:31 +00:00
|
|
|
if (conf_get_bool(conf, CONF_alwaysontop))
|
2019-09-08 19:29:00 +00:00
|
|
|
return; /* ignore */
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
SetWindowPos(wgs.term_hwnd, top ? HWND_TOP : HWND_BOTTOM, 0, 0, 0, 0,
|
2019-09-08 19:29:00 +00:00
|
|
|
SWP_NOMOVE | SWP_NOSIZE);
|
2001-11-25 15:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Refresh the window in response to a server-side request.
|
|
|
|
*/
|
Remove the 'Frontend' type and replace it with a vtable.
After the recent Seat and LogContext revamps, _nearly_ all the
remaining uses of the type 'Frontend' were in terminal.c, which needs
all sorts of interactions with the GUI window the terminal lives in,
from the obvious (actually drawing text on the window, reading and
writing the clipboard) to the obscure (minimising, maximising and
moving the window in response to particular escape sequences).
All of those functions are now provided by an abstraction called
TermWin. The few remaining uses of Frontend after _that_ are internal
to a particular platform directory, so as to spread the implementation
of that particular kind of Frontend between multiple source files; so
I've renamed all of those so that they take a more specifically named
type that refers to the particular implementation rather than the
general abstraction.
So now the name 'Frontend' no longer exists in the code base at all,
and everywhere one used to be used, it's completely clear whether it
was operating in one of Frontend's three abstract roles (and if so,
which), or whether it was specific to a particular implementation.
Another type that's disappeared is 'Context', which used to be a
typedef defined to something different on each platform, describing
whatever short-lived resources were necessary to draw on the terminal
window: the front end would provide a ready-made one when calling
term_paint, and the terminal could request one with get_ctx/free_ctx
if it wanted to do proactive window updates. Now that drawing context
lives inside the TermWin itself, because there was never any need to
have two of those contexts live at the same time.
(Another minor API change is that the window-title functions - both
reading and writing - have had a missing 'const' added to their char *
parameters / return values.)
I don't expect this change to enable any particularly interesting new
functionality (in particular, I have no plans that need more than one
implementation of TermWin in the same application). But it completes
the tidying-up that began with the Seat and LogContext rework.
2018-10-25 17:44:04 +00:00
|
|
|
static void wintw_refresh(TermWin *tw)
|
2001-11-25 15:21:25 +00:00
|
|
|
{
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
InvalidateRect(wgs.term_hwnd, NULL, true);
|
2001-11-25 15:21:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Maximise or restore the window in response to a server-side
|
|
|
|
* request.
|
|
|
|
*/
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
static void wintw_set_maximised(TermWin *tw, bool maximised)
|
2001-11-25 15:21:25 +00:00
|
|
|
{
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
if (IsZoomed(wgs.term_hwnd)) {
|
Remove the 'Frontend' type and replace it with a vtable.
After the recent Seat and LogContext revamps, _nearly_ all the
remaining uses of the type 'Frontend' were in terminal.c, which needs
all sorts of interactions with the GUI window the terminal lives in,
from the obvious (actually drawing text on the window, reading and
writing the clipboard) to the obscure (minimising, maximising and
moving the window in response to particular escape sequences).
All of those functions are now provided by an abstraction called
TermWin. The few remaining uses of Frontend after _that_ are internal
to a particular platform directory, so as to spread the implementation
of that particular kind of Frontend between multiple source files; so
I've renamed all of those so that they take a more specifically named
type that refers to the particular implementation rather than the
general abstraction.
So now the name 'Frontend' no longer exists in the code base at all,
and everywhere one used to be used, it's completely clear whether it
was operating in one of Frontend's three abstract roles (and if so,
which), or whether it was specific to a particular implementation.
Another type that's disappeared is 'Context', which used to be a
typedef defined to something different on each platform, describing
whatever short-lived resources were necessary to draw on the terminal
window: the front end would provide a ready-made one when calling
term_paint, and the terminal could request one with get_ctx/free_ctx
if it wanted to do proactive window updates. Now that drawing context
lives inside the TermWin itself, because there was never any need to
have two of those contexts live at the same time.
(Another minor API change is that the window-title functions - both
reading and writing - have had a missing 'const' added to their char *
parameters / return values.)
I don't expect this change to enable any particularly interesting new
functionality (in particular, I have no plans that need more than one
implementation of TermWin in the same application). But it completes
the tidying-up that began with the Seat and LogContext rework.
2018-10-25 17:44:04 +00:00
|
|
|
if (!maximised)
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
ShowWindow(wgs.term_hwnd, SW_RESTORE);
|
2001-11-25 15:21:25 +00:00
|
|
|
} else {
|
2019-09-08 19:29:00 +00:00
|
|
|
if (maximised)
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
ShowWindow(wgs.term_hwnd, SW_MAXIMIZE);
|
2001-11-25 15:21:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-12-07 21:21:03 +00:00
|
|
|
/*
|
|
|
|
* See if we're in full-screen mode.
|
|
|
|
*/
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
static bool is_full_screen()
|
2001-12-07 21:21:03 +00:00
|
|
|
{
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
if (!IsZoomed(wgs.term_hwnd))
|
2019-09-08 19:29:00 +00:00
|
|
|
return false;
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
if (GetWindowLongPtr(wgs.term_hwnd, GWL_STYLE) & WS_CAPTION)
|
2019-09-08 19:29:00 +00:00
|
|
|
return false;
|
2018-10-29 19:50:29 +00:00
|
|
|
return true;
|
2001-12-07 21:21:03 +00:00
|
|
|
}
|
|
|
|
|
2002-03-13 22:15:14 +00:00
|
|
|
/* 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. */
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
static bool get_fullscreen_rect(RECT * ss)
|
2002-03-13 22:15:14 +00:00
|
|
|
{
|
2003-12-16 18:28:43 +00:00
|
|
|
#if defined(MONITOR_DEFAULTTONEAREST) && !defined(NO_MULTIMON)
|
2019-09-08 19:29:00 +00:00
|
|
|
HMONITOR mon;
|
|
|
|
MONITORINFO mi;
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
mon = MonitorFromWindow(wgs.term_hwnd, MONITOR_DEFAULTTONEAREST);
|
2019-09-08 19:29:00 +00:00
|
|
|
mi.cbSize = sizeof(mi);
|
|
|
|
GetMonitorInfo(mon, &mi);
|
|
|
|
|
|
|
|
/* structure copy */
|
|
|
|
*ss = mi.rcMonitor;
|
|
|
|
return true;
|
2002-03-13 22:15:14 +00:00
|
|
|
#else
|
|
|
|
/* could also use code like this:
|
2019-09-08 19:29:00 +00:00
|
|
|
ss->left = ss->top = 0;
|
|
|
|
ss->right = GetSystemMetrics(SM_CXSCREEN);
|
|
|
|
ss->bottom = GetSystemMetrics(SM_CYSCREEN);
|
|
|
|
*/
|
|
|
|
return GetClientRect(GetDesktopWindow(), ss);
|
2002-03-13 22:15:14 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-12-07 21:21:03 +00:00
|
|
|
/*
|
|
|
|
* Go full-screen. This should only be called when we are already
|
|
|
|
* maximised.
|
|
|
|
*/
|
2004-01-20 20:35:27 +00:00
|
|
|
static void make_full_screen()
|
2001-12-07 21:21:03 +00:00
|
|
|
{
|
|
|
|
DWORD style;
|
2019-09-08 19:29:00 +00:00
|
|
|
RECT ss;
|
2001-12-07 21:21:03 +00:00
|
|
|
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
assert(IsZoomed(wgs.term_hwnd));
|
2001-12-07 21:21:03 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
if (is_full_screen())
|
|
|
|
return;
|
|
|
|
|
2001-12-07 21:21:03 +00:00
|
|
|
/* Remove the window furniture. */
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
style = GetWindowLongPtr(wgs.term_hwnd, GWL_STYLE);
|
2001-12-07 21:21:03 +00:00
|
|
|
style &= ~(WS_CAPTION | WS_BORDER | WS_THICKFRAME);
|
2018-10-29 19:57:31 +00:00
|
|
|
if (conf_get_bool(conf, CONF_scrollbar_in_fullscreen))
|
2019-09-08 19:29:00 +00:00
|
|
|
style |= WS_VSCROLL;
|
2001-12-07 21:21:03 +00:00
|
|
|
else
|
2019-09-08 19:29:00 +00:00
|
|
|
style &= ~WS_VSCROLL;
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
SetWindowLongPtr(wgs.term_hwnd, GWL_STYLE, style);
|
2001-12-07 21:21:03 +00:00
|
|
|
|
|
|
|
/* Resize ourselves to exactly cover the nearest monitor. */
|
2019-09-08 19:29:00 +00:00
|
|
|
get_fullscreen_rect(&ss);
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
SetWindowPos(wgs.term_hwnd, HWND_TOP, ss.left, ss.top,
|
|
|
|
ss.right - ss.left, ss.bottom - ss.top, SWP_FRAMECHANGED);
|
2001-12-07 21:21:03 +00:00
|
|
|
|
2006-03-29 17:55:40 +00:00
|
|
|
/* We may have changed size as a result */
|
|
|
|
|
|
|
|
reset_window(0);
|
|
|
|
|
2009-08-15 17:45:17 +00:00
|
|
|
/* Tick the menu item in the System and context menus. */
|
|
|
|
{
|
2019-09-08 19:29:00 +00:00
|
|
|
int i;
|
|
|
|
for (i = 0; i < lenof(popup_menus); i++)
|
|
|
|
CheckMenuItem(popup_menus[i].menu, IDM_FULLSCREEN, MF_CHECKED);
|
2009-08-15 17:45:17 +00:00
|
|
|
}
|
2001-12-07 21:21:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Clear the full-screen attributes.
|
|
|
|
*/
|
2004-01-20 20:35:27 +00:00
|
|
|
static void clear_full_screen()
|
2001-12-07 21:21:03 +00:00
|
|
|
{
|
|
|
|
DWORD oldstyle, style;
|
|
|
|
|
|
|
|
/* Reinstate the window furniture. */
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
style = oldstyle = GetWindowLongPtr(wgs.term_hwnd, GWL_STYLE);
|
2001-12-11 18:47:55 +00:00
|
|
|
style |= WS_CAPTION | WS_BORDER;
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 18:52:21 +00:00
|
|
|
if (conf_get_int(conf, CONF_resize_action) == RESIZE_DISABLED)
|
2001-12-11 18:47:55 +00:00
|
|
|
style &= ~WS_THICKFRAME;
|
|
|
|
else
|
|
|
|
style |= WS_THICKFRAME;
|
2018-10-29 19:57:31 +00:00
|
|
|
if (conf_get_bool(conf, CONF_scrollbar))
|
2019-09-08 19:29:00 +00:00
|
|
|
style |= WS_VSCROLL;
|
2001-12-07 21:21:03 +00:00
|
|
|
else
|
2019-09-08 19:29:00 +00:00
|
|
|
style &= ~WS_VSCROLL;
|
2001-12-07 21:21:03 +00:00
|
|
|
if (style != oldstyle) {
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
SetWindowLongPtr(wgs.term_hwnd, GWL_STYLE, style);
|
|
|
|
SetWindowPos(wgs.term_hwnd, NULL, 0, 0, 0, 0,
|
2019-09-08 19:29:00 +00:00
|
|
|
SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER |
|
|
|
|
SWP_FRAMECHANGED);
|
2001-12-07 21:21:03 +00:00
|
|
|
}
|
|
|
|
|
2009-08-15 17:45:17 +00:00
|
|
|
/* Untick the menu item in the System and context menus. */
|
|
|
|
{
|
2019-09-08 19:29:00 +00:00
|
|
|
int i;
|
|
|
|
for (i = 0; i < lenof(popup_menus); i++)
|
|
|
|
CheckMenuItem(popup_menus[i].menu, IDM_FULLSCREEN, MF_UNCHECKED);
|
2009-08-15 17:45:17 +00:00
|
|
|
}
|
2001-12-07 21:21:03 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Toggle full-screen mode.
|
|
|
|
*/
|
2004-01-20 20:35:27 +00:00
|
|
|
static void flip_full_screen()
|
2001-12-07 21:21:03 +00:00
|
|
|
{
|
|
|
|
if (is_full_screen()) {
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
ShowWindow(wgs.term_hwnd, SW_RESTORE);
|
|
|
|
} else if (IsZoomed(wgs.term_hwnd)) {
|
2019-09-08 19:29:00 +00:00
|
|
|
make_full_screen();
|
2001-12-07 21:21:03 +00:00
|
|
|
} else {
|
GUI PuTTY: stop using the global 'hwnd'.
This was the difficult part of cleaning up that global variable. The
main Windows PuTTY GUI is split between source files, so that _does_
actually need to refer to the main window from multiple places.
But all the places where windlg.c needed to use 'hwnd' are seat
methods, so they were already receiving a Seat pointer as a parameter.
In other words, the methods of the Windows GUI Seat were already split
between source files. So it seems only fair that they should be able
to share knowledge of the seat's data as well.
Hence, I've created a small 'WinGuiSeat' structure which both window.c
and windlg.c can see the layout of, and put the main terminal window
handle in there. Then the seat methods implemented in windlg.c, like
win_seat_verify_ssh_host_key, can use container_of to turn the Seat
pointer parameter back into the address of that structure, just as the
methods in window.c can do (even though they currently don't need to).
(Who knows: now that it _exists_, perhaps that structure can be
gradually expanded in future to turn it into a proper encapsulation of
all the Windows frontend's state, like we should have had all
along...)
I've also moved the Windows GUI LogPolicy implementation into the same
object (i.e. WinGuiSeat implements both traits at once). That allows
win_gui_logging_error to recover the same WinGuiSeat from its input
LogPolicy pointer, which means it can get from there to the Seat facet
of the same object, so that I don't need the extern variable
'win_seat' any more either.
2020-02-02 10:00:43 +00:00
|
|
|
SendMessage(wgs.term_hwnd, WM_FULLSCR_ON_MAX, 0, 0);
|
|
|
|
ShowWindow(wgs.term_hwnd, SW_MAXIMIZE);
|
2001-12-07 21:21:03 +00:00
|
|
|
}
|
|
|
|
}
|
2002-10-24 14:12:55 +00:00
|
|
|
|
2019-02-06 20:42:44 +00:00
|
|
|
static size_t win_seat_output(Seat *seat, bool is_stderr,
|
|
|
|
const void *data, size_t len)
|
Rationalisation of the system of frontend handles. Most modular bits
of PuTTY (terminal, backend, logctx etc) take a `void *' handle
passed to them from the frontend, and used as a context for all
their callbacks. Most of these point at the frontend structure
itself (on platforms where this is meaningful), except that the
handle passed to the backend has always pointed at the terminal
because from_backend() was implemented in terminal.c. This has
finally bitten Unix PuTTY, because both backend and logctx have
been passing their respective and very different frontend handles to
logevent(), so I've fixed it.
from_backend() is now a function supplied by the _frontend_ itself,
in all cases, and the frontend handle passed to backends must be the
same as that passed to everything else. What was from_backend() in
terminal.c is now called term_data(), and the typical implementation
of from_backend() in a GUI frontend will just extract the terminal
handle from the frontend structure and delegate to that.
This appears to work on Unix and Windows, but has most likely broken
the Mac build.
[originally from svn r3100]
2003-04-11 18:36:27 +00:00
|
|
|
{
|
|
|
|
return term_data(term, is_stderr, data, len);
|
|
|
|
}
|
2003-04-28 13:59:32 +00:00
|
|
|
|
Convert a lot of 'int' variables to 'bool'.
My normal habit these days, in new code, is to treat int and bool as
_almost_ completely separate types. I'm still willing to use C's
implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine,
no need to spell it out as blob.len != 0), but generally, if a
variable is going to be conceptually a boolean, I like to declare it
bool and assign to it using 'true' or 'false' rather than 0 or 1.
PuTTY is an exception, because it predates the C99 bool, and I've
stuck to its existing coding style even when adding new code to it.
But it's been annoying me more and more, so now that I've decided C99
bool is an acceptable thing to require from our toolchain in the first
place, here's a quite thorough trawl through the source doing
'boolification'. Many variables and function parameters are now typed
as bool rather than int; many assignments of 0 or 1 to those variables
are now spelled 'true' or 'false'.
I managed this thorough conversion with the help of a custom clang
plugin that I wrote to trawl the AST and apply heuristics to point out
where things might want changing. So I've even managed to do a decent
job on parts of the code I haven't looked at in years!
To make the plugin's work easier, I pushed platform front ends
generally in the direction of using standard 'bool' in preference to
platform-specific boolean types like Windows BOOL or GTK's gboolean;
I've left the platform booleans in places they _have_ to be for the
platform APIs to work right, but variables only used by my own code
have been converted wherever I found them.
In a few places there are int values that look very like booleans in
_most_ of the places they're used, but have a rarely-used third value,
or a distinction between different nonzero values that most users
don't care about. In these cases, I've _removed_ uses of 'true' and
'false' for the return values, to emphasise that there's something
more subtle going on than a simple boolean answer:
- the 'multisel' field in dialog.h's list box structure, for which
the GTK front end in particular recognises a difference between 1
and 2 but nearly everything else treats as boolean
- the 'urgent' parameter to plug_receive, where 1 vs 2 tells you
something about the specific location of the urgent pointer, but
most clients only care about 0 vs 'something nonzero'
- the return value of wc_match, where -1 indicates a syntax error in
the wildcard.
- the return values from SSH-1 RSA-key loading functions, which use
-1 for 'wrong passphrase' and 0 for all other failures (so any
caller which already knows it's not loading an _encrypted private_
key can treat them as boolean)
- term->esc_query, and the 'query' parameter in toggle_mode in
terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h,
but can also hold -1 for some other intervening character that we
don't support.
In a few places there's an integer that I haven't turned into a bool
even though it really _can_ only take values 0 or 1 (and, as above,
tried to make the call sites consistent in not calling those values
true and false), on the grounds that I thought it would make it more
confusing to imply that the 0 value was in some sense 'negative' or
bad and the 1 positive or good:
- the return value of plug_accepting uses the POSIXish convention of
0=success and nonzero=error; I think if I made it bool then I'd
also want to reverse its sense, and that's a job for a separate
piece of work.
- the 'screen' parameter to lineptr() in terminal.c, where 0 and 1
represent the default and alternate screens. There's no obvious
reason why one of those should be considered 'true' or 'positive'
or 'success' - they're just indices - so I've left it as int.
ssh_scp_recv had particularly confusing semantics for its previous int
return value: its call sites used '<= 0' to check for error, but it
never actually returned a negative number, just 0 or 1. Now the
function and its call sites agree that it's a bool.
In a couple of places I've renamed variables called 'ret', because I
don't like that name any more - it's unclear whether it means the
return value (in preparation) for the _containing_ function or the
return value received from a subroutine call, and occasionally I've
accidentally used the same variable for both and introduced a bug. So
where one of those got in my way, I've renamed it to 'toret' or 'retd'
(the latter short for 'returned') in line with my usual modern
practice, but I haven't done a thorough job of finding all of them.
Finally, one amusing side effect of doing this is that I've had to
separate quite a few chained assignments. It used to be perfectly fine
to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a
the 'true' defined by stdbool.h, that idiom provokes a warning from
gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 19:23:19 +00:00
|
|
|
static bool win_seat_eof(Seat *seat)
|
2011-09-13 11:44:03 +00:00
|
|
|
{
|
2018-10-29 19:50:29 +00:00
|
|
|
return true; /* do respond to incoming EOF with outgoing */
|
2011-09-13 11:44:03 +00:00
|
|
|
}
|
|
|
|
|
New abstraction 'Seat', to pass to backends.
This is a new vtable-based abstraction which is passed to a backend in
place of Frontend, and it implements only the subset of the Frontend
functions needed by a backend. (Many other Frontend functions still
exist, notably the wide range of things called by terminal.c providing
platform-independent operations on the GUI terminal window.)
The purpose of making it a vtable is that this opens up the
possibility of creating a backend as an internal implementation detail
of some other activity, by providing just that one backend with a
custom Seat that implements the methods differently.
For example, this refactoring should make it feasible to directly
implement an SSH proxy type, aka the 'jump host' feature supported by
OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP
mode, and then expose the main channel of that as the Socket for the
primary connection'. (Which of course you can already do by spawning
'plink -nc' as a separate proxy process, but this would permit it in
the _same_ process without anything getting confused.)
I've centralised a full set of stub methods in misc.c for the new
abstraction, which allows me to get rid of several annoying stubs in
the previous code. Also, while I'm here, I've moved a lot of
duplicated modalfatalbox() type functions from application main
program files into wincons.c / uxcons.c, which I think saves
duplication overall. (A minor visible effect is that the prefixes on
those console-based fatal error messages will now be more consistent
between applications.)
2018-10-11 18:58:42 +00:00
|
|
|
static int win_seat_get_userpass_input(
|
|
|
|
Seat *seat, prompts_t *p, bufchain *input)
|
2005-10-30 20:24:09 +00:00
|
|
|
{
|
|
|
|
int ret;
|
2018-05-18 06:22:56 +00:00
|
|
|
ret = cmdline_get_passwd_input(p);
|
2005-10-30 20:24:09 +00:00
|
|
|
if (ret == -1)
|
2019-09-08 19:29:00 +00:00
|
|
|
ret = term_get_userpass_input(term, p, input);
|
2005-10-30 20:24:09 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2019-03-10 14:42:11 +00:00
|
|
|
static bool win_seat_set_trust_status(Seat *seat, bool trusted)
|
|
|
|
{
|
|
|
|
term_set_trust_status(term, trusted);
|
|
|
|
return true;
|
|
|
|
}
|
2019-04-04 19:17:24 +00:00
|
|
|
|
|
|
|
static bool win_seat_get_cursor_position(Seat *seat, int *x, int *y)
|
|
|
|
{
|
|
|
|
term_get_cursor_position(term, x, y);
|
|
|
|
return true;
|
|
|
|
}
|
2021-02-07 19:59:21 +00:00
|
|
|
|
|
|
|
static bool win_seat_get_window_pixel_size(Seat *seat, int *x, int *y)
|
|
|
|
{
|
|
|
|
RECT r;
|
|
|
|
GetWindowRect(wgs.term_hwnd, &r);
|
|
|
|
*x = r.right - r.left;
|
|
|
|
*y = r.bottom - r.top;
|
|
|
|
return true;
|
|
|
|
}
|