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
|
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
#define PUTTY_DO_GLOBALS /* actually _define_ globals */
|
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"
|
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);
|
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);
|
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 conftopalette(void);
|
2003-09-03 20:14:38 +00:00
|
|
|
static void systopalette(void);
|
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
|
|
|
|
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);
|
|
|
|
int cursor_type;
|
|
|
|
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;
|
|
|
|
static int descent;
|
|
|
|
|
2004-12-19 23:15:17 +00:00
|
|
|
#define NCFGCOLOURS 22
|
2004-11-28 15:13:34 +00:00
|
|
|
#define NEXTCOLOURS 240
|
|
|
|
#define NALLCOLOURS (NCFGCOLOURS + NEXTCOLOURS)
|
|
|
|
static COLORREF colours[NALLCOLOURS];
|
2017-10-05 19:43:02 +00:00
|
|
|
struct rgb {
|
|
|
|
int r, g, b;
|
|
|
|
} colours_rgb[NALLCOLOURS];
|
1999-01-08 13:02:13 +00:00
|
|
|
static HPALETTE pal;
|
|
|
|
static LPLOGPALETTE logpal;
|
2004-11-28 15:13:34 +00:00
|
|
|
static RGBTRIPLE defpal[NALLCOLOURS];
|
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;
|
|
|
|
|
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);
|
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 bool wintw_is_minimised(TermWin *);
|
|
|
|
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);
|
|
|
|
static bool wintw_palette_get(TermWin *, int n, int *r, int *g, int *b);
|
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_palette_set(TermWin *, int n, int r, int g, int b);
|
|
|
|
static void wintw_palette_reset(TermWin *);
|
|
|
|
static void wintw_get_pos(TermWin *, int *x, int *y);
|
|
|
|
static void wintw_get_pixels(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 const char *wintw_get_title(TermWin *, bool icon);
|
|
|
|
static bool wintw_is_utf8(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 = {
|
|
|
|
wintw_setup_draw_ctx,
|
|
|
|
wintw_draw_text,
|
|
|
|
wintw_draw_cursor,
|
2019-03-10 14:37:11 +00:00
|
|
|
wintw_draw_trust_sigil,
|
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_char_width,
|
|
|
|
wintw_free_draw_ctx,
|
|
|
|
wintw_set_cursor_pos,
|
|
|
|
wintw_set_raw_mouse_mode,
|
|
|
|
wintw_set_scrollbar,
|
|
|
|
wintw_bell,
|
|
|
|
wintw_clip_write,
|
|
|
|
wintw_clip_request_paste,
|
|
|
|
wintw_refresh,
|
|
|
|
wintw_request_resize,
|
|
|
|
wintw_set_title,
|
|
|
|
wintw_set_icon_title,
|
|
|
|
wintw_set_minimised,
|
|
|
|
wintw_is_minimised,
|
|
|
|
wintw_set_maximised,
|
|
|
|
wintw_move,
|
|
|
|
wintw_set_zorder,
|
|
|
|
wintw_palette_get,
|
|
|
|
wintw_palette_set,
|
|
|
|
wintw_palette_reset,
|
|
|
|
wintw_get_pos,
|
|
|
|
wintw_get_pixels,
|
|
|
|
wintw_get_title,
|
|
|
|
wintw_is_utf8,
|
|
|
|
};
|
|
|
|
|
|
|
|
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 wintw_is_utf8(TermWin *tw)
|
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();
|
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
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
|
|
|
char *win_seat_get_ttymode(Seat *seat, const char *mode)
|
2005-04-21 13:57:08 +00:00
|
|
|
{
|
|
|
|
return term_get_ttymode(term, 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
|
|
|
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
|
|
|
{
|
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
|
|
|
win_get_pixels(wintw, x, y);
|
2018-10-29 19:50:29 +00:00
|
|
|
return true;
|
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
|
|
|
}
|
|
|
|
|
2019-03-07 08:19:38 +00:00
|
|
|
StripCtrlChars *win_seat_stripctrl_new(
|
|
|
|
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);
|
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 = {
|
|
|
|
win_seat_output,
|
|
|
|
win_seat_eof,
|
|
|
|
win_seat_get_userpass_input,
|
|
|
|
win_seat_notify_remote_exit,
|
|
|
|
win_seat_connection_fatal,
|
|
|
|
win_seat_update_specials_menu,
|
|
|
|
win_seat_get_ttymode,
|
|
|
|
win_seat_set_busy_status,
|
|
|
|
win_seat_verify_ssh_host_key,
|
|
|
|
win_seat_confirm_weak_crypto_primitive,
|
|
|
|
win_seat_confirm_weak_cached_hostkey,
|
|
|
|
win_seat_is_utf8,
|
|
|
|
nullseat_echoedit_update,
|
|
|
|
nullseat_get_x_display,
|
|
|
|
nullseat_get_windowid,
|
2018-10-13 06:37:24 +00:00
|
|
|
win_seat_get_window_pixel_size,
|
2019-03-05 21:13:00 +00:00
|
|
|
win_seat_stripctrl_new,
|
2019-03-10 14:42:11 +00:00
|
|
|
win_seat_set_trust_status,
|
Remove FLAG_VERBOSE.
The global 'int flags' has always been an ugly feature of this code
base, and I suddenly thought that perhaps it's time to start throwing
it out, one flag at a time, until it's totally unused.
My first target is FLAG_VERBOSE. This was usually set by cmdline.c
when it saw a -v option on the program's command line, except that GUI
PuTTY itself sets it unconditionally on startup. And then various bits
of the code would check it in order to decide whether to print a given
message.
In the current system of front-end abstraction traits, there's no
_one_ place that I can move it to. But there are two: every place that
checked FLAG_VERBOSE has access to either a Seat or a LogPolicy. So
now each of those traits has a query method for 'do I want verbose
messages?'.
A good effect of this is that subsidiary Seats, like the ones used in
Uppity for the main SSH server module itself and the server end of
shell channels, now get to have their own verbosity setting instead of
inheriting the one global one. In fact I don't expect any code using
those Seats to be generating any messages at all, but if that changes
later, we'll have a way to control it. (Who knows, perhaps logging in
Uppity might become a thing.)
As part of this cleanup, I've added a new flag to cmdline_tooltype,
called TOOLTYPE_NO_VERBOSE_OPTION. The unconditionally-verbose tools
now set that, and it has the effect of making cmdline.c disallow -v
completely. So where 'putty -v' would previously have been silently
ignored ("I was already verbose"), it's now an error, reminding you
that that option doesn't actually do anything.
Finally, the 'default_logpolicy' provided by uxcons.c and wincons.c
(with identical definitions) has had to move into a new file of its
own, because now it has to ask cmdline.c for the verbosity setting as
well as asking console.c for the rest of its methods. So there's a new
file clicons.c which can only be included by programs that link
against both cmdline.c _and_ one of the *cons.c, and I've renamed the
logpolicy to reflect that.
2020-01-30 06:40:21 +00:00
|
|
|
nullseat_verbose_yes,
|
2020-01-30 06:40:21 +00:00
|
|
|
nullseat_interactive_yes,
|
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
|
|
|
};
|
2018-11-03 10:06:33 +00:00
|
|
|
static Seat win_seat_impl = { &win_seat_vt };
|
|
|
|
Seat *const win_seat = &win_seat_impl;
|
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;
|
2004-08-14 13:04:18 +00:00
|
|
|
const char *error;
|
2018-12-08 21:03:51 +00:00
|
|
|
const char *title;
|
2004-08-14 13:04:18 +00:00
|
|
|
char *realhost;
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2019-03-20 15:07:32 +00:00
|
|
|
seat_set_trust_status(win_seat, true);
|
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
|
|
|
error = backend_init(vt, win_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);
|
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
|
|
|
}
|
|
|
|
window_name = icon_name = NULL;
|
2018-12-08 21:03:51 +00:00
|
|
|
char *title_to_free = NULL;
|
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
|
|
|
title = conf_get_str(conf, CONF_wintitle);
|
|
|
|
if (!*title) {
|
2019-09-08 19:29:00 +00:00
|
|
|
title_to_free = dupprintf("%s - %s", realhost, appname);
|
|
|
|
title = title_to_free;
|
2004-08-14 13:04:18 +00:00
|
|
|
}
|
|
|
|
sfree(realhost);
|
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
|
|
|
win_set_title(wintw, title);
|
|
|
|
win_set_icon_title(wintw, title);
|
2004-08-14 13:04:18 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
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
|
|
|
ldisc = ldisc_create(conf, term, backend, win_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;
|
2018-12-08 21:03:51 +00:00
|
|
|
|
|
|
|
sfree(title_to_free);
|
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);
|
2019-09-08 19:29:00 +00:00
|
|
|
seat_update_specials_menu(win_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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Remove FLAG_VERBOSE.
The global 'int flags' has always been an ugly feature of this code
base, and I suddenly thought that perhaps it's time to start throwing
it out, one flag at a time, until it's totally unused.
My first target is FLAG_VERBOSE. This was usually set by cmdline.c
when it saw a -v option on the program's command line, except that GUI
PuTTY itself sets it unconditionally on startup. And then various bits
of the code would check it in order to decide whether to print a given
message.
In the current system of front-end abstraction traits, there's no
_one_ place that I can move it to. But there are two: every place that
checked FLAG_VERBOSE has access to either a Seat or a LogPolicy. So
now each of those traits has a query method for 'do I want verbose
messages?'.
A good effect of this is that subsidiary Seats, like the ones used in
Uppity for the main SSH server module itself and the server end of
shell channels, now get to have their own verbosity setting instead of
inheriting the one global one. In fact I don't expect any code using
those Seats to be generating any messages at all, but if that changes
later, we'll have a way to control it. (Who knows, perhaps logging in
Uppity might become a thing.)
As part of this cleanup, I've added a new flag to cmdline_tooltype,
called TOOLTYPE_NO_VERBOSE_OPTION. The unconditionally-verbose tools
now set that, and it has the effect of making cmdline.c disallow -v
completely. So where 'putty -v' would previously have been silently
ignored ("I was already verbose"), it's now an error, reminding you
that that option doesn't actually do anything.
Finally, the 'default_logpolicy' provided by uxcons.c and wincons.c
(with identical definitions) has had to move into a new file of its
own, because now it has to ask cmdline.c for the verbosity setting as
well as asking console.c for the rest of its methods. So there's a new
file clicons.c which can only be included by programs that link
against both cmdline.c _and_ one of the *cons.c, and I've renamed the
logpolicy to reflect that.
2020-01-30 06:40:21 +00:00
|
|
|
extern LogPolicy win_gui_logpolicy[1]; /* defined in windlg.c */
|
|
|
|
|
2020-01-30 06:40:22 +00:00
|
|
|
const unsigned cmdline_tooltype =
|
|
|
|
TOOLTYPE_HOST_ARG |
|
|
|
|
TOOLTYPE_PORT_ARG |
|
|
|
|
TOOLTYPE_NO_VERBOSE_OPTION;
|
|
|
|
|
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;
|
2005-03-01 01:16:57 +00:00
|
|
|
hwnd = NULL;
|
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();
|
2018-10-29 19:50:29 +00:00
|
|
|
restricted_acl = true;
|
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
|
|
|
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);
|
|
|
|
if (!conf_launchable(conf) && !do_config()) {
|
|
|
|
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);
|
|
|
|
} else if (!do_config()) {
|
|
|
|
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);
|
|
|
|
if (message_box(s1, s2,
|
|
|
|
MB_YESNO | MB_ICONWARNING | MB_DEFBUTTON2,
|
|
|
|
HELPCTXID(option_cleanup)) == IDYES) {
|
|
|
|
cleanup_all();
|
|
|
|
}
|
|
|
|
sfree(s1);
|
|
|
|
sfree(s2);
|
|
|
|
exit(0);
|
|
|
|
} else if (!strcmp(p, "-pgpfp")) {
|
|
|
|
pgp_fingerprints();
|
|
|
|
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))) {
|
|
|
|
if (!do_config())
|
|
|
|
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();
|
|
|
|
|
|
|
|
conftopalette();
|
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;
|
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);
|
|
|
|
if (conf_get_int(conf, CONF_resize_action) == RESIZE_DISABLED)
|
|
|
|
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;
|
|
|
|
hwnd = CreateWindowExW(exwinmode, uappname, uappname,
|
2015-07-27 19:06:02 +00:00
|
|
|
winmode, CW_USEDEFAULT, CW_USEDEFAULT,
|
|
|
|
guess_width, guess_height,
|
|
|
|
NULL, NULL, inst, NULL);
|
|
|
|
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);
|
|
|
|
|
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);
|
Remove FLAG_VERBOSE.
The global 'int flags' has always been an ugly feature of this code
base, and I suddenly thought that perhaps it's time to start throwing
it out, one flag at a time, until it's totally unused.
My first target is FLAG_VERBOSE. This was usually set by cmdline.c
when it saw a -v option on the program's command line, except that GUI
PuTTY itself sets it unconditionally on startup. And then various bits
of the code would check it in order to decide whether to print a given
message.
In the current system of front-end abstraction traits, there's no
_one_ place that I can move it to. But there are two: every place that
checked FLAG_VERBOSE has access to either a Seat or a LogPolicy. So
now each of those traits has a query method for 'do I want verbose
messages?'.
A good effect of this is that subsidiary Seats, like the ones used in
Uppity for the main SSH server module itself and the server end of
shell channels, now get to have their own verbosity setting instead of
inheriting the one global one. In fact I don't expect any code using
those Seats to be generating any messages at all, but if that changes
later, we'll have a way to control it. (Who knows, perhaps logging in
Uppity might become a thing.)
As part of this cleanup, I've added a new flag to cmdline_tooltype,
called TOOLTYPE_NO_VERBOSE_OPTION. The unconditionally-verbose tools
now set that, and it has the effect of making cmdline.c disallow -v
completely. So where 'putty -v' would previously have been silently
ignored ("I was already verbose"), it's now an error, reminding you
that that option doesn't actually do anything.
Finally, the 'default_logpolicy' provided by uxcons.c and wincons.c
(with identical definitions) has had to move into a new file of its
own, because now it has to ask cmdline.c for the verbosity setting as
well as asking console.c for the rest of its methods. So there's a new
file clicons.c which can only be included by programs that link
against both cmdline.c _and_ one of the *cons.c, and I've renamed the
logpolicy to reflect that.
2020-01-30 06:40:21 +00:00
|
|
|
logctx = log_init(win_gui_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;
|
|
|
|
GetWindowRect(hwnd, &wr);
|
|
|
|
GetClientRect(hwnd, &cr);
|
|
|
|
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;
|
2001-05-06 14:35:20 +00:00
|
|
|
SetWindowPos(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
|
|
|
}
|
2001-01-07 16:35:44 +00:00
|
|
|
CreateCaret(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;
|
|
|
|
SetScrollInfo(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;
|
|
|
|
|
|
|
|
popup_menus[SYSMENU].menu = GetSystemMenu(hwnd, false);
|
|
|
|
popup_menus[CTXMENU].menu = CreatePopupMenu();
|
|
|
|
AppendMenu(popup_menus[CTXMENU].menu, MF_ENABLED, IDM_COPY, "&Copy");
|
|
|
|
AppendMenu(popup_menus[CTXMENU].menu, MF_ENABLED, IDM_PASTE, "&Paste");
|
|
|
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2017-02-11 00:44:00 +00:00
|
|
|
if (restricted_acl) {
|
Remove FLAG_VERBOSE.
The global 'int flags' has always been an ugly feature of this code
base, and I suddenly thought that perhaps it's time to start throwing
it out, one flag at a time, until it's totally unused.
My first target is FLAG_VERBOSE. This was usually set by cmdline.c
when it saw a -v option on the program's command line, except that GUI
PuTTY itself sets it unconditionally on startup. And then various bits
of the code would check it in order to decide whether to print a given
message.
In the current system of front-end abstraction traits, there's no
_one_ place that I can move it to. But there are two: every place that
checked FLAG_VERBOSE has access to either a Seat or a LogPolicy. So
now each of those traits has a query method for 'do I want verbose
messages?'.
A good effect of this is that subsidiary Seats, like the ones used in
Uppity for the main SSH server module itself and the server end of
shell channels, now get to have their own verbosity setting instead of
inheriting the one global one. In fact I don't expect any code using
those Seats to be generating any messages at all, but if that changes
later, we'll have a way to control it. (Who knows, perhaps logging in
Uppity might become a thing.)
As part of this cleanup, I've added a new flag to cmdline_tooltype,
called TOOLTYPE_NO_VERBOSE_OPTION. The unconditionally-verbose tools
now set that, and it has the effect of making cmdline.c disallow -v
completely. So where 'putty -v' would previously have been silently
ignored ("I was already verbose"), it's now an error, reminding you
that that option doesn't actually do anything.
Finally, the 'default_logpolicy' provided by uxcons.c and wincons.c
(with identical definitions) has had to move into a new file of its
own, because now it has to ask cmdline.c for the verbosity setting as
well as asking console.c for the rest of its methods. So there's a new
file clicons.c which can only be included by programs that link
against both cmdline.c _and_ one of the *cons.c, and I've renamed the
logpolicy to reflect that.
2020-01-30 06:40:21 +00:00
|
|
|
lp_eventlog(win_gui_logpolicy, "Running with restricted process ACL");
|
2017-02-11 00:44:00 +00:00
|
|
|
}
|
|
|
|
|
2020-01-01 11:10:22 +00:00
|
|
|
winselgui_set_hwnd(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
|
|
|
*/
|
2001-12-14 14:57:50 +00:00
|
|
|
ShowWindow(hwnd, show);
|
|
|
|
SetForegroundWindow(hwnd);
|
2001-01-07 18:24:59 +00:00
|
|
|
|
1999-01-08 13:02:13 +00:00
|
|
|
/*
|
|
|
|
* Set the palette up.
|
|
|
|
*/
|
|
|
|
pal = NULL;
|
|
|
|
logpal = NULL;
|
|
|
|
init_palette();
|
|
|
|
|
2004-11-27 19:34:45 +00:00
|
|
|
term_set_focus(term, GetForegroundWindow() == hwnd);
|
2001-05-06 14:35:20 +00:00
|
|
|
UpdateWindow(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 */
|
|
|
|
term_set_focus(term, GetForegroundWindow() == hwnd);
|
|
|
|
}
|
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
|
|
|
|
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:
|
2019-09-08 19:29:00 +00:00
|
|
|
if (send_raw_mouse)
|
|
|
|
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);
|
|
|
|
SetClassLongPtr(hwnd, GCLP_HCURSOR, (LONG_PTR)cursor);
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
2001-05-06 14:20:41 +00:00
|
|
|
/*
|
|
|
|
* set or clear the "raw mouse message" 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 void wintw_set_raw_mouse_mode(TermWin *tw, bool activate)
|
2001-05-06 14:20:41 +00:00
|
|
|
{
|
2018-10-29 19:57:31 +00:00
|
|
|
activate = activate && !conf_get_bool(conf, CONF_no_mouse_rep);
|
2001-05-06 14:20:41 +00:00
|
|
|
send_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);
|
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
|
|
|
MessageBox(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);
|
|
|
|
MessageBox(hwnd, message, title, MB_ICONERROR | MB_OK);
|
|
|
|
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
|
|
|
}
|
|
|
|
|
1999-01-08 13:02:13 +00:00
|
|
|
/*
|
|
|
|
* Copy the colour palette from the configuration data into defpal.
|
|
|
|
* This is non-trivial because the colour indices are different.
|
|
|
|
*/
|
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 conftopalette(void)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
1999-01-08 13:02:13 +00:00
|
|
|
int i;
|
|
|
|
static const int ww[] = {
|
2019-09-08 19:29:00 +00:00
|
|
|
256, 257, 258, 259, 260, 261,
|
|
|
|
0, 8, 1, 9, 2, 10, 3, 11,
|
|
|
|
4, 12, 5, 13, 6, 14, 7, 15
|
1999-01-08 13:02:13 +00:00
|
|
|
};
|
|
|
|
|
2004-11-28 15:13:34 +00:00
|
|
|
for (i = 0; i < 22; i++) {
|
2019-09-08 19:29:00 +00:00
|
|
|
int w = ww[i];
|
|
|
|
defpal[w].rgbtRed = conf_get_int_int(conf, CONF_colours, i*3+0);
|
|
|
|
defpal[w].rgbtGreen = conf_get_int_int(conf, CONF_colours, i*3+1);
|
|
|
|
defpal[w].rgbtBlue = conf_get_int_int(conf, CONF_colours, i*3+2);
|
2004-11-28 15:13:34 +00:00
|
|
|
}
|
|
|
|
for (i = 0; i < NEXTCOLOURS; i++) {
|
2019-09-08 19:29:00 +00:00
|
|
|
if (i < 216) {
|
|
|
|
int r = i / 36, g = (i / 6) % 6, b = i % 6;
|
|
|
|
defpal[i+16].rgbtRed = r ? r * 40 + 55 : 0;
|
|
|
|
defpal[i+16].rgbtGreen = g ? g * 40 + 55 : 0;
|
|
|
|
defpal[i+16].rgbtBlue = b ? b * 40 + 55 : 0;
|
|
|
|
} else {
|
|
|
|
int shade = i - 216;
|
|
|
|
shade = shade * 10 + 8;
|
|
|
|
defpal[i+16].rgbtRed = defpal[i+16].rgbtGreen =
|
|
|
|
defpal[i+16].rgbtBlue = shade;
|
|
|
|
}
|
1999-01-08 13:02:13 +00:00
|
|
|
}
|
2003-09-03 20:14:38 +00:00
|
|
|
|
|
|
|
/* Override with system colours if appropriate */
|
2018-10-29 19:57:31 +00:00
|
|
|
if (conf_get_bool(conf, CONF_system_colour))
|
2003-09-03 20:14:38 +00:00
|
|
|
systopalette();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Override bit of defpal with colours from the system.
|
|
|
|
* (NB that this takes a copy the system colours at the time this is called,
|
|
|
|
* so subsequent colour scheme changes don't take effect. To fix that we'd
|
|
|
|
* probably want to be using GetSysColorBrush() and the like.)
|
|
|
|
*/
|
|
|
|
static void systopalette(void)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
static const struct { int nIndex; int norm; int bold; } or[] =
|
|
|
|
{
|
2019-09-08 19:29:00 +00:00
|
|
|
{ COLOR_WINDOWTEXT, 256, 257 }, /* Default Foreground */
|
|
|
|
{ COLOR_WINDOW, 258, 259 }, /* Default Background */
|
|
|
|
{ COLOR_HIGHLIGHTTEXT, 260, 260 }, /* Cursor Text */
|
|
|
|
{ COLOR_HIGHLIGHT, 261, 261 }, /* Cursor Colour */
|
2003-09-03 20:14:38 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
for (i = 0; i < (sizeof(or)/sizeof(or[0])); i++) {
|
2019-09-08 19:29:00 +00:00
|
|
|
COLORREF colour = GetSysColor(or[i].nIndex);
|
|
|
|
defpal[or[i].norm].rgbtRed =
|
|
|
|
defpal[or[i].bold].rgbtRed = GetRValue(colour);
|
|
|
|
defpal[or[i].norm].rgbtGreen =
|
|
|
|
defpal[or[i].bold].rgbtGreen = GetGValue(colour);
|
|
|
|
defpal[or[i].norm].rgbtBlue =
|
|
|
|
defpal[or[i].bold].rgbtBlue = GetBValue(colour);
|
2003-09-03 20:14:38 +00:00
|
|
|
}
|
1999-01-08 13:02:13 +00:00
|
|
|
}
|
|
|
|
|
2017-10-05 19:43:02 +00:00
|
|
|
static void internal_set_colour(int i, int r, int g, int b)
|
|
|
|
{
|
|
|
|
assert(i >= 0);
|
|
|
|
assert(i < NALLCOLOURS);
|
|
|
|
if (pal)
|
|
|
|
colours[i] = PALETTERGB(r, g, b);
|
|
|
|
else
|
|
|
|
colours[i] = RGB(r, g, b);
|
|
|
|
colours_rgb[i].r = r;
|
|
|
|
colours_rgb[i].g = g;
|
|
|
|
colours_rgb[i].b = b;
|
|
|
|
}
|
|
|
|
|
1999-01-08 13:02:13 +00:00
|
|
|
/*
|
|
|
|
* Set up the colour palette.
|
|
|
|
*/
|
2001-05-06 14:35:20 +00:00
|
|
|
static void init_palette(void)
|
|
|
|
{
|
1999-01-08 13:02:13 +00:00
|
|
|
int i;
|
2001-05-06 14:35:20 +00:00
|
|
|
HDC hdc = GetDC(hwnd);
|
1999-01-08 13:02:13 +00:00
|
|
|
if (hdc) {
|
2019-09-08 19:29:00 +00:00
|
|
|
if (conf_get_bool(conf, CONF_try_palette) &&
|
|
|
|
GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) {
|
|
|
|
/*
|
|
|
|
* This is a genuine case where we must use smalloc
|
|
|
|
* because the snew macros can't cope.
|
|
|
|
*/
|
|
|
|
logpal = smalloc(sizeof(*logpal)
|
|
|
|
- sizeof(logpal->palPalEntry)
|
|
|
|
+ NALLCOLOURS * sizeof(PALETTEENTRY));
|
|
|
|
logpal->palVersion = 0x300;
|
|
|
|
logpal->palNumEntries = NALLCOLOURS;
|
|
|
|
for (i = 0; i < NALLCOLOURS; i++) {
|
|
|
|
logpal->palPalEntry[i].peRed = defpal[i].rgbtRed;
|
|
|
|
logpal->palPalEntry[i].peGreen = defpal[i].rgbtGreen;
|
|
|
|
logpal->palPalEntry[i].peBlue = defpal[i].rgbtBlue;
|
|
|
|
logpal->palPalEntry[i].peFlags = PC_NOCOLLAPSE;
|
|
|
|
}
|
|
|
|
pal = CreatePalette(logpal);
|
|
|
|
if (pal) {
|
|
|
|
SelectPalette(hdc, pal, false);
|
|
|
|
RealizePalette(hdc);
|
|
|
|
SelectPalette(hdc, GetStockObject(DEFAULT_PALETTE), false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ReleaseDC(hwnd, hdc);
|
1999-01-08 13:02:13 +00:00
|
|
|
}
|
2017-10-05 19:43:02 +00:00
|
|
|
for (i = 0; i < NALLCOLOURS; i++)
|
|
|
|
internal_set_colour(i, defpal[i].rgbtRed,
|
|
|
|
defpal[i].rgbtGreen, defpal[i].rgbtBlue);
|
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;
|
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
|
|
|
}
|
|
|
|
|
2000-03-11 14:15:24 +00:00
|
|
|
hdc = GetDC(hwnd);
|
|
|
|
|
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);
|
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
|
|
|
}
|
|
|
|
|
2001-05-06 14:35:20 +00:00
|
|
|
ReleaseDC(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
|
|
|
{
|
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 */
|
2001-09-15 15:54:24 +00:00
|
|
|
if (IsZoomed(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;
|
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 &&
|
2019-09-08 19:29:00 +00:00
|
|
|
!IsZoomed(hwnd)) {
|
|
|
|
width = extra_width + font_width * w;
|
|
|
|
height = extra_height + font_height * h;
|
1999-01-08 13:02:13 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
SetWindowPos(hwnd, NULL, 0, 0, width, height,
|
|
|
|
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
|
|
|
|
2018-10-29 19:50:29 +00:00
|
|
|
InvalidateRect(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 ... */
|
|
|
|
GetWindowRect(hwnd, &wr);
|
|
|
|
GetClientRect(hwnd, &cr);
|
|
|
|
|
|
|
|
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 ? */
|
2019-09-08 19:29:00 +00:00
|
|
|
if ( !reinit &&
|
|
|
|
(offset_width != (win_width-font_width*term->cols)/2 ||
|
|
|
|
offset_height != (win_height-font_height*term->rows)/2) ){
|
|
|
|
offset_width = (win_width-font_width*term->cols)/2;
|
|
|
|
offset_height = (win_height-font_height*term->rows)/2;
|
|
|
|
InvalidateRect(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() -> Reposition terminal\n");
|
2001-09-15 15:54:24 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2001-11-04 16:41:26 +00:00
|
|
|
if (IsZoomed(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;
|
|
|
|
InvalidateRect(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;
|
|
|
|
InvalidateRect(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.
|
|
|
|
*/
|
|
|
|
SetWindowPos(hwnd, NULL, 0, 0,
|
|
|
|
font_width*term->cols + extra_width,
|
|
|
|
font_height*term->rows + extra_height,
|
|
|
|
SWP_NOMOVE | SWP_NOZORDER);
|
|
|
|
}
|
|
|
|
|
|
|
|
InvalidateRect(hwnd, NULL, true);
|
|
|
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SetWindowPos(hwnd, NULL, 0, 0,
|
|
|
|
font_width*term->cols + extra_width,
|
|
|
|
font_height*term->rows + extra_height,
|
|
|
|
SWP_NOMOVE | SWP_NOZORDER);
|
|
|
|
|
|
|
|
InvalidateRect(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
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
InvalidateRect(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. */
|
|
|
|
if (exitcode != INT_MAX)
|
|
|
|
MessageBox(hwnd, "Connection closed by remote host",
|
|
|
|
appname, MB_OK | MB_ICONINFORMATION);
|
|
|
|
}
|
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;
|
2004-11-27 13:20:21 +00:00
|
|
|
KillTimer(hwnd, TIMING_TIMER_ID);
|
|
|
|
SetTimer(hwnd, TIMING_TIMER_ID, ticks, NULL);
|
|
|
|
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;
|
|
|
|
|
|
|
|
if (!hwnd)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
hdc = GetDC(hwnd);
|
|
|
|
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)
|
|
|
|
{
|
|
|
|
assert(hwnd);
|
2018-10-29 19:50:29 +00:00
|
|
|
SelectPalette(hdc, GetStockObject(DEFAULT_PALETTE), 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
|
|
|
ReleaseDC(hwnd, hdc);
|
|
|
|
}
|
|
|
|
|
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 need_backend_resize = 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;
|
1999-11-04 13:44:21 +00:00
|
|
|
case WM_CLOSE:
|
2019-09-08 19:29:00 +00:00
|
|
|
{
|
|
|
|
char *str;
|
|
|
|
show_mouseptr(true);
|
|
|
|
str = dupprintf("%s Exit Confirmation", appname);
|
|
|
|
if (session_closed || !conf_get_bool(conf, CONF_warn_on_close) ||
|
|
|
|
MessageBox(hwnd,
|
|
|
|
"Are you sure you want to close this session?",
|
|
|
|
str, MB_ICONWARNING | MB_OKCANCEL | MB_DEFBUTTON1)
|
|
|
|
== IDOK)
|
|
|
|
DestroyWindow(hwnd);
|
|
|
|
sfree(str);
|
|
|
|
}
|
|
|
|
return 0;
|
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:
|
|
|
|
case IDM_SAVEDSESS:
|
|
|
|
{
|
|
|
|
char b[2048];
|
|
|
|
char *cl;
|
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
|
|
|
const char *argprefix;
|
2019-09-08 19:29:00 +00:00
|
|
|
bool inherit_handles;
|
|
|
|
STARTUPINFO si;
|
|
|
|
PROCESS_INFORMATION pi;
|
|
|
|
HANDLE filemap = NULL;
|
1999-01-08 13:02:13 +00:00
|
|
|
|
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 (restricted_acl)
|
|
|
|
argprefix = "&R";
|
|
|
|
else
|
|
|
|
argprefix = "";
|
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
if (wParam == IDM_DUPSESS) {
|
|
|
|
/*
|
|
|
|
* Allocate a file-mapping memory chunk for the
|
|
|
|
* config structure.
|
|
|
|
*/
|
|
|
|
SECURITY_ATTRIBUTES sa;
|
2018-05-24 09:48:20 +00:00
|
|
|
strbuf *serbuf;
|
2019-09-08 19:29:00 +00:00
|
|
|
void *p;
|
|
|
|
int size;
|
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
|
|
|
|
2018-05-24 09:48:20 +00:00
|
|
|
serbuf = strbuf_new();
|
2019-09-08 19:29:00 +00:00
|
|
|
conf_serialise(BinarySink_UPCAST(serbuf), conf);
|
2018-05-24 09:48:20 +00:00
|
|
|
size = serbuf->len;
|
1999-01-08 13:02:13 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
2018-05-24 09:48:20 +00:00
|
|
|
|
|
|
|
strbuf_free(serbuf);
|
2019-09-08 19:29:00 +00:00
|
|
|
inherit_handles = true;
|
|
|
|
cl = dupprintf("putty %s&%p:%u", argprefix,
|
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
|
|
|
filemap, (unsigned)size);
|
2019-09-08 19:29:00 +00:00
|
|
|
} 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 */ {
|
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
|
|
|
cl = dupprintf("putty%s%s",
|
|
|
|
*argprefix ? " " : "",
|
|
|
|
argprefix);
|
2019-09-08 19:29:00 +00:00
|
|
|
inherit_handles = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
2012-10-10 18:29:16 +00:00
|
|
|
CloseHandle(pi.hProcess);
|
|
|
|
CloseHandle(pi.hThread);
|
1999-01-08 13:02:13 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
if (filemap)
|
|
|
|
CloseHandle(filemap);
|
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
|
|
|
sfree(cl);
|
2019-09-08 19:29:00 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case IDM_RESTART:
|
2018-09-11 15:23:38 +00:00
|
|
|
if (!backend) {
|
Remove FLAG_VERBOSE.
The global 'int flags' has always been an ugly feature of this code
base, and I suddenly thought that perhaps it's time to start throwing
it out, one flag at a time, until it's totally unused.
My first target is FLAG_VERBOSE. This was usually set by cmdline.c
when it saw a -v option on the program's command line, except that GUI
PuTTY itself sets it unconditionally on startup. And then various bits
of the code would check it in order to decide whether to print a given
message.
In the current system of front-end abstraction traits, there's no
_one_ place that I can move it to. But there are two: every place that
checked FLAG_VERBOSE has access to either a Seat or a LogPolicy. So
now each of those traits has a query method for 'do I want verbose
messages?'.
A good effect of this is that subsidiary Seats, like the ones used in
Uppity for the main SSH server module itself and the server end of
shell channels, now get to have their own verbosity setting instead of
inheriting the one global one. In fact I don't expect any code using
those Seats to be generating any messages at all, but if that changes
later, we'll have a way to control it. (Who knows, perhaps logging in
Uppity might become a thing.)
As part of this cleanup, I've added a new flag to cmdline_tooltype,
called TOOLTYPE_NO_VERBOSE_OPTION. The unconditionally-verbose tools
now set that, and it has the effect of making cmdline.c disallow -v
completely. So where 'putty -v' would previously have been silently
ignored ("I was already verbose"), it's now an error, reminding you
that that option doesn't actually do anything.
Finally, the 'default_logpolicy' provided by uxcons.c and wincons.c
(with identical definitions) has had to move into a new file of its
own, because now it has to ask cmdline.c for the verbosity setting as
well as asking console.c for the rest of its methods. So there's a new
file clicons.c which can only be included by programs that link
against both cmdline.c _and_ one of the *cons.c, and I've renamed the
logpolicy to reflect that.
2020-01-30 06:40:21 +00:00
|
|
|
lp_eventlog(win_gui_logpolicy,
|
Refactor the LogContext type.
LogContext is now the owner of the logevent() function that back ends
and so forth are constantly calling. Previously, logevent was owned by
the Frontend, which would store the message into its list for the GUI
Event Log dialog (or print it to standard error, or whatever) and then
pass it _back_ to LogContext to write to the currently open log file.
Now it's the other way round: LogContext gets the message from the
back end first, writes it to its log file if it feels so inclined, and
communicates it back to the front end.
This means that lots of parts of the back end system no longer need to
have a pointer to a full-on Frontend; the only thing they needed it
for was logging, so now they just have a LogContext (which many of
them had to have anyway, e.g. for logging SSH packets or session
traffic).
LogContext itself also doesn't get a full Frontend pointer any more:
it now talks back to the front end via a little vtable of its own
called LogPolicy, which contains the method that passes Event Log
entries through, the old askappend() function that decides whether to
truncate a pre-existing log file, and an emergency function for
printing an especially prominent message if the log file can't be
created. One minor nice effect of this is that console and GUI apps
can implement that last function subtly differently, so that Unix
console apps can write it with a plain \n instead of the \r\n
(harmless but inelegant) that the old centralised implementation
generated.
One other consequence of this is that the LogContext has to be
provided to backend_init() so that it's available to backends from the
instant of creation, rather than being provided via a separate API
call a couple of function calls later, because backends have typically
started doing things that need logging (like making network
connections) before the call to backend_provide_logctx. Fortunately,
there's no case in the whole code base where we don't already have
logctx by the time we make a backend (so I don't actually remember why
I ever delayed providing one). So that shortens the backend API by one
function, which is always nice.
While I'm tidying up, I've also moved the printf-style logeventf() and
the handy logevent_and_free() into logging.c, instead of having copies
of them scattered around other places. This has also let me remove
some stub functions from a couple of outlying applications like
Pageant. Finally, I've removed the pointless "_tag" at the end of
LogContext's official struct name.
2018-10-10 18:26:18 +00:00
|
|
|
"----- Session restarted -----");
|
2019-09-08 19:29:00 +00:00
|
|
|
term_pwron(term, false);
|
|
|
|
start_backend();
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
case IDM_RECONF:
|
|
|
|
{
|
|
|
|
Conf *prev_conf;
|
|
|
|
int init_lvl = 1;
|
|
|
|
bool reconfig_result;
|
|
|
|
|
|
|
|
if (reconfiguring)
|
|
|
|
break;
|
|
|
|
else
|
|
|
|
reconfiguring = true;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copy the current window title into the stored
|
|
|
|
* previous configuration, so that doing nothing to
|
|
|
|
* the window title field in the config box doesn't
|
|
|
|
* reset the title to its startup state.
|
|
|
|
*/
|
|
|
|
conf_set_str(conf, CONF_wintitle, window_name);
|
|
|
|
|
|
|
|
prev_conf = conf_copy(conf);
|
|
|
|
|
|
|
|
reconfig_result =
|
2018-09-11 15:23:38 +00:00
|
|
|
do_reconfig(hwnd, backend ? backend_cfg_info(backend) : 0);
|
2019-09-08 19:29:00 +00:00
|
|
|
reconfiguring = false;
|
|
|
|
if (!reconfig_result) {
|
2013-07-22 07:11:54 +00:00
|
|
|
conf_free(prev_conf);
|
2019-09-08 19:29:00 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
conf_cache_data();
|
|
|
|
|
|
|
|
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 |
|
2020-01-26 14:39:40 +00:00
|
|
|
(resize_action == RESIZE_DISABLED
|
|
|
|
? MF_GRAYED : MF_ENABLED));
|
2019-09-08 19:29:00 +00:00
|
|
|
/* Gracefully unzoom if necessary */
|
|
|
|
if (IsZoomed(hwnd) && (resize_action == RESIZE_DISABLED))
|
|
|
|
ShowWindow(hwnd, SW_RESTORE);
|
2013-07-22 07:11:54 +00:00
|
|
|
}
|
2001-01-07 18:24:59 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
/* Pass new config data to the logging module */
|
|
|
|
log_reconfig(logctx, conf);
|
|
|
|
|
|
|
|
sfree(logpal);
|
|
|
|
/*
|
|
|
|
* Flush the line discipline's edit buffer in the
|
|
|
|
* case where local editing has just been disabled.
|
|
|
|
*/
|
|
|
|
if (ldisc) {
|
2014-08-27 22:25:37 +00:00
|
|
|
ldisc_configure(ldisc, conf);
|
2019-09-08 19:29:00 +00:00
|
|
|
ldisc_echoedit_update(ldisc);
|
2014-08-27 22:25:37 +00:00
|
|
|
}
|
2019-09-08 19:29:00 +00:00
|
|
|
if (pal)
|
|
|
|
DeleteObject(pal);
|
|
|
|
logpal = NULL;
|
|
|
|
pal = NULL;
|
|
|
|
conftopalette();
|
|
|
|
init_palette();
|
|
|
|
|
|
|
|
/* Pass new config data to the terminal */
|
|
|
|
term_reconfig(term, conf);
|
2017-12-10 17:16:50 +00:00
|
|
|
setup_clipboards(term, conf);
|
2002-03-06 23:04:20 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
/* Pass new config data to the back end */
|
2018-09-11 15:23:38 +00:00
|
|
|
if (backend)
|
|
|
|
backend_reconfig(backend, conf);
|
2003-01-12 14:48:29 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
/* 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));
|
|
|
|
|
|
|
|
/* 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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
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() ?
|
2018-10-29 19:57:31 +00:00
|
|
|
CONF_scrollbar_in_fullscreen :
|
|
|
|
CONF_scrollbar))
|
2019-09-08 19:29:00 +00:00
|
|
|
nflg |= WS_VSCROLL;
|
|
|
|
else
|
|
|
|
nflg &= ~WS_VSCROLL;
|
2001-12-11 18:47:55 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
if (resize_action == RESIZE_DISABLED ||
|
2001-12-11 18:47:55 +00:00
|
|
|
is_full_screen())
|
2019-09-08 19:29:00 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Oops */
|
|
|
|
if (resize_action == RESIZE_DISABLED && IsZoomed(hwnd)) {
|
|
|
|
force_normal(hwnd);
|
|
|
|
init_lvl = 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
win_set_title(wintw, conf_get_str(conf, CONF_wintitle));
|
|
|
|
if (IsIconic(hwnd)) {
|
|
|
|
SetWindowText(hwnd,
|
|
|
|
conf_get_bool(conf, CONF_win_name_always) ?
|
|
|
|
window_name : icon_name);
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
FontSpec *font = conf_get_fontspec(conf, CONF_font);
|
|
|
|
FontSpec *prev_font = conf_get_fontspec(prev_conf,
|
2011-10-01 17:38:59 +00:00
|
|
|
CONF_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
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
InvalidateRect(hwnd, NULL, true);
|
|
|
|
reset_window(init_lvl);
|
|
|
|
|
|
|
|
conf_free(prev_conf);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
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;
|
1999-01-08 13:02:13 +00:00
|
|
|
case WM_MOUSEMOVE:
|
2019-09-08 19:29:00 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* 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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
* 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;
|
2001-03-02 09:25:14 +00:00
|
|
|
case WM_NCMOUSEMOVE:
|
2019-09-08 19:29:00 +00:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
noise_ultralight(NOISE_SOURCE_MOUSEPOS, lParam);
|
|
|
|
break;
|
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;
|
1999-01-08 13:02:13 +00:00
|
|
|
case WM_PAINT:
|
2019-09-08 19:29:00 +00:00
|
|
|
{
|
|
|
|
PAINTSTRUCT p;
|
|
|
|
|
|
|
|
HideCaret(hwnd);
|
|
|
|
hdc = BeginPaint(hwnd, &p);
|
|
|
|
if (pal) {
|
|
|
|
SelectPalette(hdc, pal, true);
|
|
|
|
RealizePalette(hdc);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We have to be careful about term_paint(). It will
|
|
|
|
* set a bunch of character cells to INVALID and then
|
|
|
|
* call do_paint(), which will redraw those cells and
|
|
|
|
* _then mark them as done_. This may not be accurate:
|
|
|
|
* when painting in WM_PAINT context we are restricted
|
|
|
|
* to the rectangle which has just been exposed - so if
|
|
|
|
* that only covers _part_ of a character cell and the
|
|
|
|
* rest of it was already visible, that remainder will
|
|
|
|
* not be redrawn at all. Accordingly, we must not
|
|
|
|
* paint any character cell in a WM_PAINT context which
|
|
|
|
* already has a pending update due to terminal output.
|
|
|
|
* The simplest solution to this - and many, many
|
|
|
|
* thanks to Hung-Te Lin for working all this out - is
|
|
|
|
* not to do any actual painting at _all_ if there's a
|
|
|
|
* pending terminal update: just mark the relevant
|
|
|
|
* character cells as INVALID and wait for the
|
|
|
|
* scheduled full update to sort it out.
|
|
|
|
*
|
|
|
|
* I have a suspicion this isn't the _right_ solution.
|
|
|
|
* An alternative approach would be to have terminal.c
|
|
|
|
* separately track what _should_ be on the terminal
|
|
|
|
* screen and what _is_ on the terminal screen, and
|
|
|
|
* have two completely different types of redraw (one
|
|
|
|
* for full updates, which syncs the former with the
|
|
|
|
* terminal itself, and one for WM_PAINT which syncs
|
|
|
|
* the latter with the former); yet another possibility
|
|
|
|
* would be to have the Windows front end do what the
|
|
|
|
* GTK one already does, and maintain a bitmap of the
|
|
|
|
* current terminal appearance so that WM_PAINT becomes
|
|
|
|
* completely trivial. However, this should do for now.
|
|
|
|
*/
|
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 = hdc;
|
2019-09-08 19:29:00 +00:00
|
|
|
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);
|
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_hdc = NULL;
|
2001-09-15 15:54:24 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
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)
|
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
SelectObject(hdc, GetStockObject(SYSTEM_FONT));
|
|
|
|
SelectObject(hdc, GetStockObject(WHITE_PEN));
|
|
|
|
EndPaint(hwnd, &p);
|
|
|
|
ShowCaret(hwnd);
|
|
|
|
}
|
|
|
|
return 0;
|
1999-01-08 13:02:13 +00:00
|
|
|
case WM_NETEVENT:
|
2013-08-17 16:06:35 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* 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;
|
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);
|
|
|
|
}
|
|
|
|
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:
|
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
|
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 {
|
2001-09-15 15:54:24 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
int width, height, w, h;
|
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 window_border = conf_get_int(conf, CONF_window_border);
|
1999-01-08 13:02:13 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
width = LOWORD(lParam);
|
|
|
|
height = HIWORD(lParam);
|
2001-09-15 15:54:24 +00:00
|
|
|
|
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;
|
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) {
|
2010-12-22 15:49:33 +00:00
|
|
|
w = width / font_width;
|
|
|
|
if (w < 1) w = 1;
|
|
|
|
h = height / font_height;
|
|
|
|
if (h < 1) h = 1;
|
|
|
|
|
2012-02-05 10:08:20 +00:00
|
|
|
if (resizing) {
|
|
|
|
/*
|
|
|
|
* As below, if we're in the middle of an
|
|
|
|
* interactive resize we don't call
|
|
|
|
* back->size. In Windows 7, this case can
|
|
|
|
* arise in maximisation as well via the Aero
|
|
|
|
* snap UI.
|
|
|
|
*/
|
2018-10-29 19:50:29 +00:00
|
|
|
need_backend_resize = true;
|
2012-02-05 10:08:20 +00:00
|
|
|
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));
|
|
|
|
}
|
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) {
|
|
|
|
w = (width-window_border*2) / font_width;
|
2010-12-22 16:14:11 +00:00
|
|
|
if (w < 1) w = 1;
|
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
|
|
|
h = (height-window_border*2) / font_height;
|
2010-12-22 16:14:11 +00:00
|
|
|
if (h < 1) h = 1;
|
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));
|
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())) {
|
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
|
|
|
w = (width-window_border*2) / font_width;
|
2010-12-22 15:49:33 +00:00
|
|
|
if (w < 1) w = 1;
|
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
|
|
|
h = (height-window_border*2) / font_height;
|
2010-12-22 15:49:33 +00:00
|
|
|
if (h < 1) h = 1;
|
|
|
|
|
|
|
|
if (resizing) {
|
|
|
|
/*
|
|
|
|
* Don't call back->size in mid-resize. (To
|
|
|
|
* prevent massive numbers of resize events
|
|
|
|
* getting sent down the connection during an NT
|
|
|
|
* opaque drag.)
|
|
|
|
*/
|
2019-09-08 19:29:00 +00:00
|
|
|
need_backend_resize = true;
|
|
|
|
conf_set_int(conf, CONF_height, h);
|
|
|
|
conf_set_int(conf, CONF_width, w);
|
2010-12-22 15:49:33 +00:00
|
|
|
} else {
|
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));
|
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:
|
|
|
|
case SB_THUMBTRACK:
|
|
|
|
/*
|
|
|
|
* Use GetScrollInfo instead of HIWORD(wParam) to get
|
|
|
|
* 32-bit scroll position.
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
SCROLLINFO si;
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
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;
|
|
|
|
case WM_IME_STARTCOMPOSITION:
|
|
|
|
{
|
|
|
|
HIMC hImc = ImmGetContext(hwnd);
|
|
|
|
ImmSetCompositionFont(hImc, &lfont);
|
|
|
|
ImmReleaseContext(hwnd, hImc);
|
|
|
|
}
|
|
|
|
break;
|
2001-08-04 15:15:07 +00:00
|
|
|
case WM_IME_COMPOSITION:
|
2019-09-08 19:29:00 +00:00
|
|
|
{
|
|
|
|
HIMC hIMC;
|
|
|
|
int n;
|
|
|
|
char *buff;
|
2001-12-15 11:10:19 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
if (osPlatformId == VER_PLATFORM_WIN32_WINDOWS ||
|
|
|
|
osPlatformId == VER_PLATFORM_WIN32s)
|
2018-06-03 14:05:44 +00:00
|
|
|
break; /* no Unicode */
|
2001-08-04 15:15:07 +00:00
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
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) {
|
2012-02-17 19:28:55 +00:00
|
|
|
for (i = 0; i < n; i += 2) {
|
2019-09-08 19:29:00 +00:00
|
|
|
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)) {
|
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, (unsigned short *)(buff+i), 2);
|
2019-09-08 19:29:00 +00:00
|
|
|
i += 2;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
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, (unsigned short *)(buff+i), 1);
|
2012-02-17 19:28:55 +00:00
|
|
|
}
|
2019-09-08 19:29:00 +00:00
|
|
|
}
|
|
|
|
free(buff);
|
|
|
|
}
|
|
|
|
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. */
|
|
|
|
/* XXX actually this zaps the entire palette. */
|
|
|
|
systopalette();
|
|
|
|
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 */
|
|
|
|
hIMC = ImmGetContext(hwnd);
|
|
|
|
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);
|
|
|
|
|
|
|
|
ImmReleaseContext(hwnd, hIMC);
|
2000-09-25 16:17:53 +00:00
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
2001-05-10 08:34:20 +00:00
|
|
|
if (lattr != LATTR_TOP && (force_manual_underline ||
|
2019-09-08 19:29:00 +00:00
|
|
|
(und_mode == UND_LINE
|
|
|
|
&& (attr & ATTR_UNDER)))) {
|
|
|
|
HPEN oldpen;
|
|
|
|
int dec = descent;
|
|
|
|
if (lattr == LATTR_BOT)
|
|
|
|
dec = dec * 2 - font_height;
|
|
|
|
|
|
|
|
oldpen = SelectObject(wintw_hdc, CreatePen(PS_SOLID, 0, fg));
|
|
|
|
MoveToEx(wintw_hdc, line_box.left, line_box.top + dec, NULL);
|
|
|
|
LineTo(wintw_hdc, line_box.right, line_box.top + dec);
|
|
|
|
oldpen = SelectObject(wintw_hdc, oldpen);
|
|
|
|
DeleteObject(oldpen);
|
1999-01-08 13:02:13 +00:00
|
|
|
}
|
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) {
|
|
|
|
SendMessage(hwnd, WM_VSCROLL, SB_PAGEUP, 0);
|
|
|
|
return 0;
|
|
|
|
}
|
2017-11-03 14:31:10 +00:00
|
|
|
if (wParam == VK_PRIOR && shift_state == 3) { /* ctrl-shift-pageup */
|
|
|
|
SendMessage(hwnd, WM_VSCROLL, SB_TOP, 0);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (wParam == VK_NEXT && shift_state == 3) { /* ctrl-shift-pagedown */
|
|
|
|
SendMessage(hwnd, WM_VSCROLL, SB_BOTTOM, 0);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2019-09-08 19:29:00 +00:00
|
|
|
if (wParam == VK_PRIOR && shift_state == 2) {
|
|
|
|
SendMessage(hwnd, WM_VSCROLL, SB_LINEUP, 0);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (wParam == VK_NEXT && shift_state == 1) {
|
|
|
|
SendMessage(hwnd, WM_VSCROLL, SB_PAGEDOWN, 0);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (wParam == VK_NEXT && shift_state == 2) {
|
|
|
|
SendMessage(hwnd, WM_VSCROLL, SB_LINEDOWN, 0);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if ((wParam == VK_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)) {
|
2019-09-08 19:29:00 +00:00
|
|
|
SendMessage(hwnd, WM_SYSCOMMAND, SC_KEYMENU, 0);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (left_alt && wParam == VK_RETURN &&
|
|
|
|
conf_get_bool(conf, CONF_fullscreenonaltenter) &&
|
|
|
|
(conf_get_int(conf, CONF_resize_action) != RESIZE_DISABLED)) {
|
|
|
|
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);
|
2003-03-29 16:14:26 +00:00
|
|
|
window_name = snewn(1 + strlen(title), char);
|
2001-05-06 14:35:20 +00:00
|
|
|
strcpy(window_name, title);
|
2018-10-29 19:57:31 +00:00
|
|
|
if (conf_get_bool(conf, CONF_win_name_always) || !IsIconic(hwnd))
|
2019-09-08 19:29:00 +00:00
|
|
|
SetWindowText(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);
|
2003-03-29 16:14:26 +00:00
|
|
|
icon_name = snewn(1 + strlen(title), char);
|
2001-05-06 14:35:20 +00:00
|
|
|
strcpy(icon_name, title);
|
2018-10-29 19:57:31 +00:00
|
|
|
if (!conf_get_bool(conf, CONF_win_name_always) && IsIconic(hwnd))
|
2019-09-08 19:29:00 +00:00
|
|
|
SetWindowText(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;
|
1999-02-09 15:39:08 +00:00
|
|
|
if (hwnd)
|
2019-09-08 19:29:00 +00:00
|
|
|
SetScrollInfo(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
|
|
|
}
|
|
|
|
|
2001-05-06 14:35:20 +00:00
|
|
|
static void real_palette_set(int n, int r, int g, int b)
|
|
|
|
{
|
2017-10-05 19:43:02 +00:00
|
|
|
internal_set_colour(n, r, g, b);
|
1999-01-08 13:02:13 +00:00
|
|
|
if (pal) {
|
2019-09-08 19:29:00 +00:00
|
|
|
logpal->palPalEntry[n].peRed = r;
|
|
|
|
logpal->palPalEntry[n].peGreen = g;
|
|
|
|
logpal->palPalEntry[n].peBlue = b;
|
|
|
|
logpal->palPalEntry[n].peFlags = PC_NOCOLLAPSE;
|
|
|
|
SetPaletteEntries(pal, 0, NALLCOLOURS, logpal->palPalEntry);
|
2017-10-05 19:43:02 +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_palette_get(TermWin *tw, int n, int *r, int *g, int *b)
|
2017-10-05 19:43:02 +00:00
|
|
|
{
|
|
|
|
if (n < 0 || n >= NALLCOLOURS)
|
2019-09-08 19:29:00 +00:00
|
|
|
return false;
|
2017-10-05 19:43:02 +00:00
|
|
|
*r = colours_rgb[n].r;
|
|
|
|
*g = colours_rgb[n].g;
|
|
|
|
*b = colours_rgb[n].b;
|
2018-10-29 19:50:29 +00:00
|
|
|
return true;
|
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_palette_set(TermWin *tw, int n, int r, int g, int b)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
2004-11-28 15:13:34 +00:00
|
|
|
if (n >= 16)
|
2019-09-08 19:29:00 +00:00
|
|
|
n += 256 - 16;
|
2013-07-22 07:12:26 +00:00
|
|
|
if (n >= NALLCOLOURS)
|
2019-09-08 19:29:00 +00:00
|
|
|
return;
|
2004-11-28 15:13:34 +00:00
|
|
|
real_palette_set(n, r, g, b);
|
1999-01-08 13:02:13 +00:00
|
|
|
if (pal) {
|
2019-09-08 19:29:00 +00:00
|
|
|
HDC hdc = make_hdc();
|
|
|
|
UnrealizeObject(pal);
|
|
|
|
RealizePalette(hdc);
|
|
|
|
free_hdc(hdc);
|
2006-02-25 14:13:46 +00:00
|
|
|
} else {
|
2019-09-08 19:29:00 +00:00
|
|
|
if (n == (ATTR_DEFBG>>ATTR_BGSHIFT))
|
|
|
|
/* If Default Background changes, we need to ensure any
|
|
|
|
* space between the text area and the window border is
|
|
|
|
* redrawn. */
|
|
|
|
InvalidateRect(hwnd, NULL, true);
|
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_palette_reset(TermWin *tw)
|
2001-05-06 14:35:20 +00:00
|
|
|
{
|
1999-01-08 13:02:13 +00:00
|
|
|
int i;
|
|
|
|
|
2004-11-28 15:13:34 +00:00
|
|
|
/* And this */
|
|
|
|
for (i = 0; i < NALLCOLOURS; i++) {
|
2017-10-05 19:43:02 +00:00
|
|
|
internal_set_colour(i, defpal[i].rgbtRed,
|
|
|
|
defpal[i].rgbtGreen, defpal[i].rgbtBlue);
|
2019-09-08 19:29:00 +00:00
|
|
|
if (pal) {
|
|
|
|
logpal->palPalEntry[i].peRed = defpal[i].rgbtRed;
|
|
|
|
logpal->palPalEntry[i].peGreen = defpal[i].rgbtGreen;
|
|
|
|
logpal->palPalEntry[i].peBlue = defpal[i].rgbtBlue;
|
|
|
|
logpal->palPalEntry[i].peFlags = 0;
|
|
|
|
}
|
1999-01-08 13:02:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (pal) {
|
2019-09-08 19:29:00 +00:00
|
|
|
HDC hdc;
|
|
|
|
SetPaletteEntries(pal, 0, NALLCOLOURS, logpal->palPalEntry);
|
|
|
|
hdc = make_hdc();
|
|
|
|
RealizePalette(hdc);
|
|
|
|
free_hdc(hdc);
|
2006-02-25 14:13:46 +00:00
|
|
|
} else {
|
2019-09-08 19:29:00 +00:00
|
|
|
/* Default Background may have changed. Ensure any space between
|
|
|
|
* text area and window border is redrawn. */
|
|
|
|
InvalidateRect(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)
|
2019-09-08 19:29:00 +00:00
|
|
|
SendMessage(hwnd, WM_IGNORE_CLIP, true, 0);
|
2000-10-06 12:32:25 +00:00
|
|
|
|
2001-05-06 14:35:20 +00:00
|
|
|
if (OpenClipboard(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)
|
2019-09-08 19:29:00 +00:00
|
|
|
SendMessage(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;
|
|
|
|
int palette[NALLCOLOURS];
|
|
|
|
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;
|
|
|
|
for (i = 0; i < NALLCOLOURS; i++) {
|
|
|
|
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 ;"));
|
|
|
|
|
|
|
|
for (i = 0; i < NALLCOLOURS; i++) {
|
|
|
|
if (palette[i] != 0) {
|
2019-02-11 06:58:07 +00:00
|
|
|
strbuf_catf(rtf, "\\red%d\\green%d\\blue%d;",
|
|
|
|
defpal[i].rgbtRed, defpal[i].rgbtGreen,
|
|
|
|
defpal[i].rgbtBlue);
|
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 {
|
|
|
|
blen = sprintf(before, "\\u%d", udata[uindex]);
|
|
|
|
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)
|
2019-09-08 19:29:00 +00:00
|
|
|
SendMessage(hwnd, WM_IGNORE_CLIP, true, 0);
|
2001-05-10 08:34:20 +00:00
|
|
|
|
|
|
|
if (OpenClipboard(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)
|
2019-09-08 19:29:00 +00:00
|
|
|
SendMessage(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,
|
2019-09-08 19:29:00 +00:00
|
|
|
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);
|
2018-12-08 21:03:51 +00:00
|
|
|
title = dupprintf("%s Fatal Error", appname);
|
|
|
|
MessageBox(hwnd, message, title, MB_SYSTEMMODAL | MB_ICONERROR | MB_OK);
|
|
|
|
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);
|
2018-12-08 21:03:51 +00:00
|
|
|
title = dupprintf("%s Error", appname);
|
|
|
|
MessageBox(hwnd, message, title, MB_ICONERROR | MB_OK);
|
|
|
|
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);
|
|
|
|
fi.hwnd = hwnd;
|
|
|
|
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
|
|
|
|
FlashWindow(hwnd, false);
|
|
|
|
}
|
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 {
|
|
|
|
FlashWindow(hwnd, true);
|
|
|
|
next_flash = schedule_timer(450, flash_window_timer, hwnd);
|
|
|
|
}
|
|
|
|
}
|
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) {
|
|
|
|
FlashWindow(hwnd, true); /* toggle */
|
|
|
|
next_flash = schedule_timer(450, flash_window_timer, hwnd);
|
|
|
|
}
|
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;
|
|
|
|
buf = dupprintf(
|
|
|
|
"Unable to play sound file\n%s\nUsing default sound instead",
|
|
|
|
bell_wavefile->path);
|
|
|
|
otherbuf = dupprintf("%s Sound Error", appname);
|
|
|
|
MessageBox(hwnd, buf, otherbuf, MB_OK | MB_ICONEXCLAMATION);
|
|
|
|
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
|
|
|
{
|
|
|
|
if (IsIconic(hwnd)) {
|
2019-09-08 19:29:00 +00:00
|
|
|
if (!minimised)
|
|
|
|
ShowWindow(hwnd, SW_RESTORE);
|
2001-11-25 15:21:25 +00:00
|
|
|
} else {
|
2019-09-08 19:29:00 +00:00
|
|
|
if (minimised)
|
|
|
|
ShowWindow(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 ||
|
|
|
|
IsZoomed(hwnd))
|
2002-01-08 09:56:06 +00:00
|
|
|
return;
|
|
|
|
|
2001-11-25 15:21:25 +00:00
|
|
|
SetWindowPos(hwnd, NULL, x, y, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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 */
|
2001-11-25 15:21:25 +00:00
|
|
|
SetWindowPos(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
|
|
|
{
|
2018-10-29 19:50:29 +00:00
|
|
|
InvalidateRect(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
|
|
|
{
|
2001-12-07 21:21:03 +00:00
|
|
|
if (IsZoomed(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)
|
2019-09-08 19:29:00 +00:00
|
|
|
ShowWindow(hwnd, SW_RESTORE);
|
2001-11-25 15:21:25 +00:00
|
|
|
} else {
|
2019-09-08 19:29:00 +00:00
|
|
|
if (maximised)
|
|
|
|
ShowWindow(hwnd, SW_MAXIMIZE);
|
2001-11-25 15:21:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Report whether the window is iconic, for terminal reports.
|
|
|
|
*/
|
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_is_minimised(TermWin *tw)
|
2001-11-25 15:21:25 +00:00
|
|
|
{
|
|
|
|
return IsIconic(hwnd);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Report the window's position, for terminal reports.
|
|
|
|
*/
|
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_get_pos(TermWin *tw, int *x, int *y)
|
2001-11-25 15:21:25 +00:00
|
|
|
{
|
|
|
|
RECT r;
|
|
|
|
GetWindowRect(hwnd, &r);
|
|
|
|
*x = r.left;
|
|
|
|
*y = r.top;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Report the window's pixel size, for terminal reports.
|
|
|
|
*/
|
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_get_pixels(TermWin *tw, int *x, int *y)
|
2001-11-25 15:21:25 +00:00
|
|
|
{
|
|
|
|
RECT r;
|
|
|
|
GetWindowRect(hwnd, &r);
|
|
|
|
*x = r.right - r.left;
|
|
|
|
*y = r.bottom - r.top;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Return the window or icon title.
|
|
|
|
*/
|
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 const char *wintw_get_title(TermWin *tw, bool icon)
|
2001-11-25 15:21:25 +00:00
|
|
|
{
|
|
|
|
return icon ? icon_name : window_name;
|
|
|
|
}
|
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
|
|
|
{
|
|
|
|
if (!IsZoomed(hwnd))
|
2019-09-08 19:29:00 +00:00
|
|
|
return false;
|
2005-05-21 14:16:43 +00:00
|
|
|
if (GetWindowLongPtr(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;
|
|
|
|
mon = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
|
|
|
|
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
|
|
|
|
|
|
|
assert(IsZoomed(hwnd));
|
|
|
|
|
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. */
|
2005-05-21 14:16:43 +00:00
|
|
|
style = GetWindowLongPtr(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;
|
2005-05-21 14:16:43 +00:00
|
|
|
SetWindowLongPtr(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);
|
2002-03-13 22:15:14 +00:00
|
|
|
SetWindowPos(hwnd, HWND_TOP, ss.left, ss.top,
|
2019-09-08 19:29:00 +00:00
|
|
|
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. */
|
2005-05-21 14:16:43 +00:00
|
|
|
style = oldstyle = GetWindowLongPtr(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) {
|
2019-09-08 19:29:00 +00:00
|
|
|
SetWindowLongPtr(hwnd, GWL_STYLE, style);
|
|
|
|
SetWindowPos(hwnd, NULL, 0, 0, 0, 0,
|
|
|
|
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()) {
|
2019-09-08 19:29:00 +00:00
|
|
|
ShowWindow(hwnd, SW_RESTORE);
|
2001-12-07 21:21:03 +00:00
|
|
|
} else if (IsZoomed(hwnd)) {
|
2019-09-08 19:29:00 +00:00
|
|
|
make_full_screen();
|
2001-12-07 21:21:03 +00:00
|
|
|
} else {
|
2019-09-08 19:29:00 +00:00
|
|
|
SendMessage(hwnd, WM_FULLSCR_ON_MAX, 0, 0);
|
|
|
|
ShowWindow(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;
|
|
|
|
}
|