From b6b95f23e563211437e51322edc9118b63a3ca40 Mon Sep 17 00:00:00 2001 From: Stefan Tauner Date: Sun, 22 Dec 2024 02:38:42 +0100 Subject: [PATCH 001/129] Treat SOS and PM terminal escape sequences like APC SOS (Start of string) and PM (privacy message) are opening delimiters defined in ECMA-48 similar to APC. With this change they are treated exactly like APC, i.e., like fake OSC sequences that are ignored and not printed. Signed-off-by: Stefan Tauner --- terminal/terminal.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/terminal/terminal.c b/terminal/terminal.c index 2db81c9a..ad309436 100644 --- a/terminal/terminal.c +++ b/terminal/terminal.c @@ -4127,9 +4127,11 @@ static void term_out(Terminal *term, bool called_from_term_data) term->esc_args[0] = 0; term->esc_nargs = 1; break; + case 'X': /* SOS: Start of String */ + case '^': /* PM: privacy message */ case '_': /* APC: application program command */ - /* APC sequences are just a string, terminated by - * ST or (I've observed in practice) ^G. That is, + /* SOS, PM, and APC sequences are just a string, terminated by + * ST or (I've observed in practice for APC) ^G. That is, * they have the same termination convention as * OSC. So we handle them by going straight into * OSC_STRING state and setting a flag indicating From 193e2ec06375dad38cdba4815cb32cf24f3e39d4 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sun, 22 Dec 2024 09:57:29 +0000 Subject: [PATCH 002/129] Rework identification of OSC sequences. I didn't like the previous patch setting a flag claiming that two kinds of thing were APC which aren't in fact APC. So I've made a little enum to distinguish them in the code. There's an outside chance we might want to handle some case of these in future, in which case this makes it easier, but more likely it's just making me feel less wrong about it. But I've also folded the two existing flags osc_is_apc and osc_w into that single enum field, which I think is an improvement. --- terminal/terminal.c | 42 ++++++++++++++++++++++-------------------- terminal/terminal.h | 11 +++++++++-- 2 files changed, 31 insertions(+), 22 deletions(-) diff --git a/terminal/terminal.c b/terminal/terminal.c index ad309436..0c52fc6e 100644 --- a/terminal/terminal.c +++ b/terminal/terminal.c @@ -3185,22 +3185,18 @@ static void toggle_mode(Terminal *term, int mode, int query, bool state) } /* - * Process an OSC sequence: set window title or icon name. + * Process an OSC or similar sequence, with a whole embedded string, + * like setting the window title or icon name. */ static void do_osc(Terminal *term) { - if (term->osc_is_apc) { - /* This OSC was really an APC, and we don't support that - * sequence at all. We only recognise it in order to ignore it - * and filter it out of input. */ - return; - } - - if (term->osc_w) { + switch (term->osc_type) { + case OSCLIKE_OSC_W: while (term->osc_strlen--) term->wordness[(unsigned char)term->osc_string[term->osc_strlen]] = term->esc_args[0]; - } else { + break; + case OSCLIKE_OSC: term->osc_string[term->osc_strlen] = '\0'; switch (term->esc_args[0]) { case 0: @@ -3242,6 +3238,11 @@ static void do_osc(Terminal *term) } break; } + break; + default: + /* APC, SOS and PM are recognised as control sequences but + * ignored. PuTTY implements no support for any of them. */ + break; } } @@ -4122,7 +4123,7 @@ static void term_out(Terminal *term, bool called_from_term_data) /* Compatibility is nasty here, xterm, linux, decterm yuk! */ compatibility(OTHER); term->termstate = SEEN_OSC; - term->osc_is_apc = false; + term->osc_type = OSCLIKE_OSC; term->osc_strlen = 0; term->esc_args[0] = 0; term->esc_nargs = 1; @@ -4130,15 +4131,16 @@ static void term_out(Terminal *term, bool called_from_term_data) case 'X': /* SOS: Start of String */ case '^': /* PM: privacy message */ case '_': /* APC: application program command */ - /* SOS, PM, and APC sequences are just a string, terminated by - * ST or (I've observed in practice for APC) ^G. That is, - * they have the same termination convention as - * OSC. So we handle them by going straight into - * OSC_STRING state and setting a flag indicating - * that it's not really an OSC. */ + /* SOS, PM, and APC sequences are just a string, terminated + * by ST or (I've observed in practice for APC) ^G. That + * is, they have the same termination convention as OSC. So + * we handle them by going straight into OSC_STRING state + * and setting a flag indicating that it's not really an + * OSC. */ compatibility(OTHER); term->termstate = SEEN_OSC; - term->osc_is_apc = true; + term->osc_type = (c == 'X' ? OSCLIKE_SOS : + c == '^' ? OSCLIKE_PM : OSCLIKE_APC); term->osc_strlen = 0; term->esc_args[0] = 0; term->esc_nargs = 1; @@ -5247,7 +5249,7 @@ static void term_out(Terminal *term, bool called_from_term_data) } break; case SEEN_OSC: - term->osc_w = false; + term->osc_type = OSCLIKE_OSC; switch (c) { case 'P': /* Linux palette sequence */ term->termstate = SEEN_OSC_P; @@ -5260,7 +5262,7 @@ static void term_out(Terminal *term, bool called_from_term_data) break; case 'W': /* word-set */ term->termstate = SEEN_OSC_W; - term->osc_w = true; + term->osc_type = OSCLIKE_OSC_W; break; case '0': case '1': diff --git a/terminal/terminal.h b/terminal/terminal.h index e5bb16ae..0e7ab771 100644 --- a/terminal/terminal.h +++ b/terminal/terminal.h @@ -73,6 +73,14 @@ struct term_utf8_decode { struct term_userpass_state; +typedef enum { + OSCLIKE_OSC, + OSCLIKE_OSC_W, + OSCLIKE_APC, + OSCLIKE_SOS, + OSCLIKE_PM, +} OscType; + struct terminal_tag { int compatibility_level; @@ -183,10 +191,9 @@ struct terminal_tag { #define ANSI_QUE(x) ANSI(x,1) #define OSC_STR_MAX 2048 - bool osc_is_apc; + OscType osc_type; int osc_strlen; char osc_string[OSC_STR_MAX + 1]; - bool osc_w; char id_string[1024]; From d96a4983be74f6450c7da3c856bc20eb8e7818ef Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Fri, 27 Dec 2024 10:07:32 +0000 Subject: [PATCH 003/129] gitcommit.cmake: work around Windows pathname aliasing. The cmake script that determines the current git head commit, in order to bake it into the binaries for development builds from a git checkout, wasn't working reliably on Windows: sometimes it reported that the source directory didn't seem to be a git repository, when in fact it was. This occurred because gitcommit.cmake starts by trying to work out _whether_ the source directory is the top level of a git worktree at all, by the technique of running `git rev-parse --show-toplevel` (to print the top-level path of the git worktree _containing_ $PWD, if any) and comparing it with ${CMAKE_SOURCE_DIR}. But the comparison was done as a plain string, which leads to problems if more than one string can represent the same actual directory. On Windows, this can occur for two reasons that I know of. One reason is related to Windows itself: if you map a network file server path to a local drive letter, then the same directory is accessible as a UNC path (e.g. \\hostname\share\subdir) and via the drive letter (e.g. N:\subdir). And it can happen that CMAKE_SOURCE_DIR and git's output disagree on which representation to use, causing the string comparison to return a false negative. (This can also affect filesystems in a WSL instance, accessed from native Windows via \\wsl$\instance\path, because Windows implements that as a network file share even though the network in question is purely in the imagination of that one machine.) The other reason is related more specifically to git, because some versions of Windows git are built on top of MSYS or MINGW or that kind of shim layer, and model Windows drive letters as subdirectories of a Unixlike VFS root. So you might also find that the two strings disagree on whether you're in C:\Users\alice\src\putty or /c/Users/alice/src/putty. I think this commit should work around both of these problems. Reading the man page for `git rev-parse` more carefully, it has an option `--show-cdup`, which returns a _relative_ path from $PWD to the top-level directory of the worktree: that is, it will be a sequence of `../../..` as long as necessary, including length zero. So you can use that to directly query whether you're at the top of a git worktree: if `git rev-parse --show-cdup` returns the empty string and a success status, then you are. (If you're deeper in a worktree it will return a non-empty string, and if you're not in a worktree at all it will return a failure status and print an error message to stderr.) --- cmake/gitcommit.cmake | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/cmake/gitcommit.cmake b/cmake/gitcommit.cmake index 0aa8a095..9119e438 100644 --- a/cmake/gitcommit.cmake +++ b/cmake/gitcommit.cmake @@ -6,34 +6,32 @@ set(commit "${DEFAULT_COMMIT}") set(TOPLEVEL_SOURCE_DIR ${CMAKE_SOURCE_DIR}) execute_process( - COMMAND ${GIT_EXECUTABLE} rev-parse --show-toplevel - OUTPUT_VARIABLE git_worktree + COMMAND ${GIT_EXECUTABLE} rev-parse --show-cdup + OUTPUT_VARIABLE path_to_top ERROR_VARIABLE stderr RESULT_VARIABLE status) -string(REGEX REPLACE "\n$" "" git_worktree "${git_worktree}") +string(REGEX REPLACE "\n$" "" path_to_top "${path_to_top}") -if(status EQUAL 0) - if(git_worktree STREQUAL CMAKE_SOURCE_DIR) - execute_process( - COMMAND ${GIT_EXECUTABLE} rev-parse HEAD - OUTPUT_VARIABLE git_commit - ERROR_VARIABLE stderr - RESULT_VARIABLE status) - if(status EQUAL 0) - string(REGEX REPLACE "\n$" "" commit "${git_commit}") - else() - if(commit STREQUAL "unavailable") - message("Unable to determine git commit: 'git rev-parse HEAD' returned status ${status} and error output:\n${stderr}\n") - endif() - endif() +# If we're at the top of a git repository, --show-cdup will print the +# empty string (followed by a newline) and return success. If we're +# lower down, it will return a sequence of "../../" that leads to the +# top; if we're higher up it will fail with an error. +if(status EQUAL 0 AND path_to_top STREQUAL "") + execute_process( + COMMAND ${GIT_EXECUTABLE} rev-parse HEAD + OUTPUT_VARIABLE git_commit + ERROR_VARIABLE stderr + RESULT_VARIABLE status) + if(status EQUAL 0) + string(REGEX REPLACE "\n$" "" commit "${git_commit}") else() if(commit STREQUAL "unavailable") - message("Unable to determine git commit: top-level source dir ${CMAKE_SOURCE_DIR} is not the root of a repository") + message("Unable to determine git commit: 'git rev-parse HEAD' returned status ${status} and error output:\n${stderr}\n") endif() endif() else() if(commit STREQUAL "unavailable") - message("Unable to determine git commit: 'git rev-parse --show-toplevel' returned status ${status} and error output:\n${stderr}\n") + message("Unable to determine git commit: top-level source dir ${CMAKE_SOURCE_DIR} is not the root of a repository") endif() endif() From e3272f19e0f3340e854c8aaaf0351a901de0e7be Mon Sep 17 00:00:00 2001 From: Jacob Nevins Date: Tue, 7 Jan 2025 21:04:43 +0000 Subject: [PATCH 004/129] It's a new year. --- LICENCE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENCE b/LICENCE index fda9c062..09155657 100644 --- a/LICENCE +++ b/LICENCE @@ -1,4 +1,4 @@ -PuTTY is copyright 1997-2024 Simon Tatham. +PuTTY is copyright 1997-2025 Simon Tatham. Portions copyright Robert de Bath, Joris van Rantwijk, Delian Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas Barry, From 6ec424059cf3a140ea5f128cb858cd566551aa96 Mon Sep 17 00:00:00 2001 From: Jacob Nevins Date: Tue, 7 Jan 2025 21:04:54 +0000 Subject: [PATCH 005/129] Windows: fix leak of a Filename. Introduced in f8e1a2b3a9. --- windows/controls.c | 1 + 1 file changed, 1 insertion(+) diff --git a/windows/controls.c b/windows/controls.c index e1fcc589..b6f559c5 100644 --- a/windows/controls.c +++ b/windows/controls.c @@ -2014,6 +2014,7 @@ bool winctrl_handle_command(struct dlgparam *dp, UINT msg, ctrl->handler(ctrl, dp, dp->data, EVENT_ACTION); c->data = NULL; } + filename_free(fn); } } break; From b088d77d580b8f7e01482aa184db6cf3b46d74eb Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Thu, 9 Jan 2025 13:01:22 +0000 Subject: [PATCH 006/129] GTK: hard-code some last-ditch fallback fonts. If the user's choice of fonts can't be instantiated during initial terminal-window setup, then we now automatically try two fallback options, "client:Monospace 10" and "server:fixed", and only give a fatal error if _no_ option allows us to open a terminal window. Previously, on Wayland, PuTTY and pterm with default configuration would completely fail to open a terminal window at all, because our default font configuration is still the trad X11 "server:fixed", and on Wayland, X11-style server-side bitmap fonts don't exist at all. Conversely, in the GTK1 build of PuTTY which we're still supporting, _client-side_ fonts aren't supported, so if a user had configured one in their normal PuTTY configuration, then the GTK1 version would similarly fail to launch. Now both of those cases should work, because the fallbacks include a client-side font _and_ a server-side one, and I hope that any usable Pango system will make "Monospace" map to _some_ locally available font, and that any remotely sensible X server has 'fixed' I think it would be even better if there was a mechanism for the Conf to specify a fallback list of fonts. For example, this might be specified via a new multifont prefix along the lines of choices:client:Monospace 10:server:fixed with the semantics that the "choices:" prefix means that the rest of the string is split up at every other colon to find a list of fonts to try to make. Then we could not only set PuTTY's default to a list of possibilities likely to find a usable font everywhere, but also, users could configure their own list of preferred fallbacks. But I haven't thought of a good answer to the design question of what should happen if a Conf font setting looks like that and the user triggers the GUI font selector! (Also, you'd need to figure out what happened if a 'choices:' string had another 'choices' in it...) --- unix/window.c | 65 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 49 insertions(+), 16 deletions(-) diff --git a/unix/window.c b/unix/window.c index 97977c3c..3316f996 100644 --- a/unix/window.c +++ b/unix/window.c @@ -4368,22 +4368,22 @@ static bool gtk_seat_get_windowid(Seat *seat, long *id) } #endif -char *setup_fonts_ucs(GtkFrontend *inst) +char *setup_fonts_ucs(GtkFrontend *inst, Conf *conf) { - bool shadowbold = conf_get_bool(inst->conf, CONF_shadowbold); - int shadowboldoffset = conf_get_int(inst->conf, CONF_shadowboldoffset); + bool shadowbold = conf_get_bool(conf, CONF_shadowbold); + int shadowboldoffset = conf_get_int(conf, CONF_shadowboldoffset); FontSpec *fs; unifont *fonts[4]; int i; - fs = conf_get_fontspec(inst->conf, CONF_font); + fs = conf_get_fontspec(conf, CONF_font); fonts[0] = multifont_create(inst->area, fs->name, false, false, shadowboldoffset, shadowbold); if (!fonts[0]) { return dupprintf("unable to load font \"%s\"", fs->name); } - fs = conf_get_fontspec(inst->conf, CONF_boldfont); + fs = conf_get_fontspec(conf, CONF_boldfont); if (shadowbold || !fs->name[0]) { fonts[1] = NULL; } else { @@ -4396,7 +4396,7 @@ char *setup_fonts_ucs(GtkFrontend *inst) } } - fs = conf_get_fontspec(inst->conf, CONF_widefont); + fs = conf_get_fontspec(conf, CONF_widefont); if (fs->name[0]) { fonts[2] = multifont_create(inst->area, fs->name, true, false, shadowboldoffset, shadowbold); @@ -4410,7 +4410,7 @@ char *setup_fonts_ucs(GtkFrontend *inst) fonts[2] = NULL; } - fs = conf_get_fontspec(inst->conf, CONF_wideboldfont); + fs = conf_get_fontspec(conf, CONF_wideboldfont); if (shadowbold || !fs->name[0]) { fonts[3] = NULL; } else { @@ -4861,7 +4861,7 @@ static void after_change_settings_dialog(void *vctx, int retval) conf_get_bool(newconf, CONF_shadowbold) || conf_get_int(oldconf, CONF_shadowboldoffset) != conf_get_int(newconf, CONF_shadowboldoffset)) { - char *errmsg = setup_fonts_ucs(inst); + char *errmsg = setup_fonts_ucs(inst, inst->conf); if (errmsg) { char *msgboxtext = dupprintf("Could not change fonts in terminal window: %s\n", @@ -4950,7 +4950,7 @@ static void change_font_size(GtkFrontend *inst, int increment) } } - errmsg = setup_fonts_ucs(inst); + errmsg = setup_fonts_ucs(inst, inst->conf); if (errmsg) goto cleanup; @@ -5350,15 +5350,48 @@ void new_session_window(Conf *conf, const char *geometry_string) inst->area = gtk_drawing_area_new(); gtk_widget_set_name(GTK_WIDGET(inst->area), "drawing-area"); + /* + * Try to create the fonts for use in the window. If this fails, + * we'll try again with some fallback settings, and only abort + * completely if we can't find any fonts at all. + */ { - char *errmsg = setup_fonts_ucs(inst); - if (errmsg) { - window_setup_error(errmsg); - sfree(errmsg); - gtk_widget_destroy(inst->area); - sfree(inst); - return; + char *errmsg_main = setup_fonts_ucs(inst, inst->conf); + if (!errmsg_main) + goto fonts_ok; + + static const char *const fallbacks[] = { + "client:Monospace 10", + "server:fixed", + }; + for (size_t i = 0; i < lenof(fallbacks); i++) { + Conf *fallback_conf = conf_new(); + do_defaults(NULL, fallback_conf); + + FontSpec *fs = fontspec_new(fallbacks[i]); + conf_set_fontspec(fallback_conf, CONF_font, fs); + fontspec_free(fs); + + char *errmsg_fallback = setup_fonts_ucs(inst, fallback_conf); + conf_free(fallback_conf); + + if (!errmsg_fallback) { + fprintf(stderr, "%s; falling back to default font '%s'\n", + errmsg_main, fallbacks[i]); + sfree(errmsg_main); + goto fonts_ok; + } + + sfree(errmsg_fallback); } + + window_setup_error(errmsg_main); + sfree(errmsg_main); + gtk_widget_destroy(inst->area); + sfree(inst); + return; + + fonts_ok:; } #if GTK_CHECK_VERSION(2,0,0) From 7f4cccde2ae53c083ababaaea19be4a9c45b7091 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Fri, 10 Jan 2025 08:15:11 +0000 Subject: [PATCH 007/129] GTK: fixes to the previous font fallback patch. I'd forgotten that I'd already chosen a default client-side font, for NOT_X_WINDOWS builds. I should have made the two defaults match! Now both default font names are defined in the header file. --- unix/platform.h | 16 +++++++++++++--- unix/window.c | 4 ++-- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/unix/platform.h b/unix/platform.h index 670febd7..413a0282 100644 --- a/unix/platform.h +++ b/unix/platform.h @@ -394,12 +394,22 @@ void setup_fd_socket(Socket *s, int infd, int outfd, int inerrfd); void fd_socket_set_psb_prefix(Socket *s, const char *prefix); /* - * Default font setting, which can vary depending on NOT_X_WINDOWS. + * Default font settings. We have a default font for each of + * client-side and server-side, so that we can use one of each as a + * fallback, and we also have a single overall default which goes into + * Conf to populate the initial state of Default Settings. + * + * The overall default varies depending on NOT_X_WINDOWS: if X is + * available then the default is xterm's traditional "fixed", but if + * it's not, so that only client-side fonts can be used at all, we + * switch to a client-side default. */ +#define DEFAULT_GTK_CLIENT_FONT "client:Monospace 12" +#define DEFAULT_GTK_SERVER_FONT "server:fixed" #ifdef NOT_X_WINDOWS -#define DEFAULT_GTK_FONT "client:Monospace 12" +#define DEFAULT_GTK_FONT DEFAULT_GTK_CLIENT_FONT #else -#define DEFAULT_GTK_FONT "server:fixed" +#define DEFAULT_GTK_FONT DEFAULT_GTK_SERVER_FONT #endif /* diff --git a/unix/window.c b/unix/window.c index 3316f996..7302dc2c 100644 --- a/unix/window.c +++ b/unix/window.c @@ -5361,8 +5361,8 @@ void new_session_window(Conf *conf, const char *geometry_string) goto fonts_ok; static const char *const fallbacks[] = { - "client:Monospace 10", - "server:fixed", + DEFAULT_GTK_CLIENT_FONT, + DEFAULT_GTK_SERVER_FONT, }; for (size_t i = 0; i < lenof(fallbacks); i++) { Conf *fallback_conf = conf_new(); From 6155365076c47a852d9d4e3e0a437787ac747d28 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Fri, 10 Jan 2025 08:23:31 +0000 Subject: [PATCH 008/129] GTK: switch the default to client-side fonts. "server:fixed" was a good default when GTK1 was common and non-X11 environments were rare. Now it's the other way round - Wayland is very common and the GTK1 configuration of PuTTY is legacy - so it's time to make the default GTK font a client-side one. Of course, anyone with an existing saved session (including Default Settings) won't be affected by this change; it only helps new users without an existing ~/.putty at all. That's why we _also_ need the fallbacks introduced by the previous couple of commits. But we can at least start making it sensible for new users. (I considered keeping the #if, and switching it round so that it tests GTK_CHECK_VERSION(2,0,0) rather than NOT_X_WINDOWS, i.e. selects the client-side default whenever client-side fonts _are_ available, instead of only when server-side fonts _aren't_. That way, in GTK1 builds, the Conf default font would _still_ be "server:fixed". But I think this is firstly too marginal to worry about, and secondly, it's more futureproof to make the default the same everywhere: if anyone still stuck on a GTK1 environment later manages to update it, then their saved settings are less likely to have had a legacy thing written into them. And the GTK1 build will still run out of the box because of the last-ditch fallback mechanism I've just added.) --- unix/platform.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/unix/platform.h b/unix/platform.h index 413a0282..fb3629ee 100644 --- a/unix/platform.h +++ b/unix/platform.h @@ -399,18 +399,18 @@ void fd_socket_set_psb_prefix(Socket *s, const char *prefix); * fallback, and we also have a single overall default which goes into * Conf to populate the initial state of Default Settings. * - * The overall default varies depending on NOT_X_WINDOWS: if X is - * available then the default is xterm's traditional "fixed", but if - * it's not, so that only client-side fonts can be used at all, we - * switch to a client-side default. + * In the past, this default varied with NOT_X_WINDOWS. But these days + * non-X11 environments like Wayland with only client-side fonts are + * common, and even an X11-capable _build_ of PuTTY is quite likely to + * find out at run time that X11 and its bitmap fonts aren't + * available. Also, a fixed-size bitmap font doesn't play nicely with + * high-DPI displays. And the GTK1 build of PuTTY, which can _only_ + * handle server-side fonts, is legacy. So the default font is + * unconditionally the client-side one. */ #define DEFAULT_GTK_CLIENT_FONT "client:Monospace 12" #define DEFAULT_GTK_SERVER_FONT "server:fixed" -#ifdef NOT_X_WINDOWS #define DEFAULT_GTK_FONT DEFAULT_GTK_CLIENT_FONT -#else -#define DEFAULT_GTK_FONT DEFAULT_GTK_SERVER_FONT -#endif /* * pty.c. From 05a13d5cf7bfb2422a85e7b8350192d201e2f89a Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sat, 25 Jan 2025 11:09:15 +0000 Subject: [PATCH 009/129] GetDlgItemText_alloc: avoid realloc loop. This rewrite, due to SATO Kentaro, uses GetWindowTextLength (which I hadn't known about) to find the correct size to allocate the buffer the first time, avoiding the need to keep growing it until a call to GetDlgItemText doesn't have to truncate the result. --- windows/utils/getdlgitemtext_alloc.c | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/windows/utils/getdlgitemtext_alloc.c b/windows/utils/getdlgitemtext_alloc.c index 8de62a3b..0fa24736 100644 --- a/windows/utils/getdlgitemtext_alloc.c +++ b/windows/utils/getdlgitemtext_alloc.c @@ -10,26 +10,18 @@ char *GetDlgItemText_alloc(HWND hwnd, int id) { - char *ret = NULL; - size_t size = 0; - - do { - sgrowarray_nm(ret, size, size); - GetDlgItemText(hwnd, id, ret, size); - } while (!memchr(ret, '\0', size-1)); - - return ret; + HWND item = GetDlgItem(hwnd, id); + size_t size = GetWindowTextLengthA(item) + 1; + char *text = snewn(size, char); + GetWindowTextA(item, text, size); + return text; } wchar_t *GetDlgItemTextW_alloc(HWND hwnd, int id) { - wchar_t *ret = NULL; - size_t size = 0; - - do { - sgrowarray_nm(ret, size, size); - GetDlgItemTextW(hwnd, id, ret, size); - } while (!wmemchr(ret, L'\0', size-1)); - - return ret; + HWND item = GetDlgItem(hwnd, id); + size_t size = GetWindowTextLengthW(item) + 1; + wchar_t *text = snewn(size, wchar_t); + GetWindowTextW(item, text, size); + return text; } From da8241cff67d36e866efddc89ebc085bdb86c4d3 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sun, 26 Jan 2025 11:41:36 +0000 Subject: [PATCH 010/129] Remove test for, and fallback impl of, wmemchr. This was introduced in commit e7acb9f6968d482, as a side effect of also wanting to call wmemchr to find a NUL wide character in the buffer returned from GetDlgItemTextW. But the previous commit has superseded that code, so now we don't use wmemchr in this code base any more. Remove the machinery that provides it, saving a now-useless cmake configure-time check. --- cmake/cmake.h.in | 1 - cmake/platforms/windows.cmake | 1 - defs.h | 5 ----- windows/CMakeLists.txt | 3 --- windows/utils/wmemchr.c | 15 --------------- 5 files changed, 25 deletions(-) delete mode 100644 windows/utils/wmemchr.c diff --git a/cmake/cmake.h.in b/cmake/cmake.h.in index cb389cb6..3d36b3d0 100644 --- a/cmake/cmake.h.in +++ b/cmake/cmake.h.in @@ -15,7 +15,6 @@ #cmakedefine01 HAVE_GETNAMEDPIPECLIENTPROCESSID #cmakedefine01 HAVE_SETDEFAULTDLLDIRECTORIES #cmakedefine01 HAVE_STRTOUMAX -#cmakedefine01 HAVE_WMEMCHR #cmakedefine01 HAVE_DWMAPI_H #cmakedefine NOT_X_WINDOWS diff --git a/cmake/platforms/windows.cmake b/cmake/platforms/windows.cmake index e87f3380..481809ec 100644 --- a/cmake/platforms/windows.cmake +++ b/cmake/platforms/windows.cmake @@ -53,7 +53,6 @@ define_negation(NO_HTMLHELP HAVE_HTMLHELP_H) check_include_files("winsock2.h;afunix.h" HAVE_AFUNIX_H) check_symbol_exists(strtoumax "inttypes.h" HAVE_STRTOUMAX) -check_symbol_exists(wmemchr "wchar.h" HAVE_WMEMCHR) check_symbol_exists(AddDllDirectory "windows.h" HAVE_ADDDLLDIRECTORY) check_symbol_exists(SetDefaultDllDirectories "windows.h" HAVE_SETDEFAULTDLLDIRECTORIES) diff --git a/defs.h b/defs.h index 0e56eb78..0ac23ee2 100644 --- a/defs.h +++ b/defs.h @@ -53,11 +53,6 @@ uintmax_t strtoumax(const char *nptr, char **endptr, int base); #define SIZEu "zu" #endif -#if !HAVE_WMEMCHR -/* Work around lack of wmemchr in older MSVC */ -wchar_t *wmemchr(const wchar_t *s, wchar_t c, size_t n); -#endif - #if defined __GNUC__ || defined __clang__ /* * On MinGW, the correct compiler format checking for vsnprintf() etc diff --git a/windows/CMakeLists.txt b/windows/CMakeLists.txt index 7d4fcadb..960a440d 100644 --- a/windows/CMakeLists.txt +++ b/windows/CMakeLists.txt @@ -42,9 +42,6 @@ add_sources_from_current_dir(utils if(NOT HAVE_STRTOUMAX) add_sources_from_current_dir(utils utils/strtoumax.c) endif() -if(NOT HAVE_WMEMCHR) - add_sources_from_current_dir(utils utils/wmemchr.c) -endif() add_sources_from_current_dir(eventloop cliloop.c handle-wait.c) add_sources_from_current_dir(console diff --git a/windows/utils/wmemchr.c b/windows/utils/wmemchr.c deleted file mode 100644 index 7ccdfe3c..00000000 --- a/windows/utils/wmemchr.c +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Work around lack of wmemchr in older MSVC libraries. - */ - -#include - -#include "defs.h" - -wchar_t *wmemchr(const wchar_t *s, wchar_t c, size_t n) -{ - for (; n != 0; s++, n--) - if (*s == c) - return (wchar_t *)s; - return NULL; -} From 267f077fcc07ff27cd3a4cad80ccece30f65bfb8 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sat, 8 Feb 2025 11:26:25 +0000 Subject: [PATCH 011/129] Reorganise the release checklist. After all these years, this checklist is _still_ hard for me to get right. In the 0.83 runup this month, I prepared everything about the RC build in advance, but nothing about the announcements, website updates etc, and had to do all of that on release day. So I've completely removed the section "Preparing to make the release", which was ambiguous about whether it's done in advance or on the day. Now all the text parts (website, wishlist, announcements) are folded into the "make a release candidate" section, in the hope that I'll remember to do them all at the same time, which should mean - people have a few days to review the text _and_ test the RC build - because they go together, I also remember to revise the text if a new RC build is needed (e.g. mention whatever extra fix it has). The "actual release procedure" section is now down to _only_ the things I have to do on the day, which is basically uploading everything, going live, and communicating the release. --- CHECKLST.txt | 80 +++++++++++++++++++++++++++------------------------- 1 file changed, 42 insertions(+), 38 deletions(-) diff --git a/CHECKLST.txt b/CHECKLST.txt index 01f57c30..81aa9e8c 100644 --- a/CHECKLST.txt +++ b/CHECKLST.txt @@ -94,6 +94,14 @@ Making a release candidate build - Make the release tag, pointing at the version-update commit we just generated. + - If the release tag is on a branch (which I expect it generally will + be), prepare a merge to main, and make sure it builds sensibly. + Even if the branch consists of nothing but cherry-picks _from_ + main, this will mean that the 'update version number' change + appears on main and the snapshots start announcing themselves as + post-X.YZ. But also, if there's anything new on the branch, this is + how it gets on to main as well. + - Make a release-candidate build from the release tag, and put the build.out and build.log files somewhere safe. Normally I store these inside the ~/src/putty/X.YZ directory, alongside the git @@ -146,24 +154,10 @@ Making a release candidate build * do some testing on a system with a completely clean slate (no prior saved session data) -Preparing to make the release ------------------------------ - - Write a release announcement (basically a summary of the changes since the last release). Check the draft version into the putty-aux repository, so the whole team can help wordsmith it if they want to. - - Update the website, in a local checkout: - * Write a release file in components/releases which identifies the - new version, a section for the Changes page, and a news - announcement for the front page. - + The one thing this can't yet contain is the release date; - that has to be put in at the last minute, when the release - goes live. Fill in 'FIXME', for the moment. - * Disable the pre-release sections of the website (if previously - enabled), by editing prerel_version() in components/Base.mc to - return undef. - - Prepare some 'what's new in this release' blurb for the Windows Store. This should be very brief - even briefer than the website news item. @@ -184,7 +178,20 @@ Preparing to make the release fixing a #vulnerability. That's how people will find the toot. * Again, commit to putty-aux for team review. - - Update the wishlist, in a local checkout: + - Prepare a website update: + * Write a release file in components/releases which identifies the + new version, a section for the Changes page, and a news + announcement for the front page. + + The one thing this can't yet contain is the release date; + that has to be put in at the last minute, when the release + goes live. Fill in 'FIXME', for the moment. + * Disable the pre-release sections of the website (if previously + enabled), by editing prerel_version() in components/Base.mc to + return undef. + * Push to the private clone of the website repo for the team to + check over. + + - Prepare a wishlist update: * If there are any last-minute wishlist entries (e.g. security vulnerabilities fixed in the new release), write entries for them. @@ -192,6 +199,22 @@ Preparing to make the release branch (so that the wishlist mechanism can't automatically mark them as fixed in the new release), add appropriate Fixed-in headers for those. + * Push to the private clone of the wishlist repo for the team to + check over. + +The actual release procedure +---------------------------- + +Once all the above preparation is done and we've decided we have a +good release candidate and a good set of announcements, wishlist +entries etc, this is the procedure for putting it all up on the web. + + - Log in to the MS Partner Center and make sure everything is in + order. If the UI has completely changed, make sure you can find + your way around the new one; if it wants you to read an enormous + document of revised T&Cs, get that out of the way in advance, so it + doesn't suddenly become a delay in the middle of the actual + release. - Sign the release in full. In the `build-X.YZ-rcN.out' directory, re-verify that the preliminary signed checksums file has a correct @@ -209,29 +232,10 @@ Preparing to make the release sh sign.sh -r putty # and enter the release key passphrase chmod -R a-w putty - - If the release is on a branch (which I expect it generally will - be), prepare a merge of that branch to main. Even if the branch - consists of nothing but cherry-picks _from_ main, this will mean - that the 'update version number' change appears on main and the - snapshots start announcing themselves as post-X.YZ. But also, if - there's anything new on the branch, this is how it gets on to main - as well. - - - Log in to the MS Partner Center and make sure everything is in - order. If the UI has completely changed, make sure you can find - your way around the new one; if it wants you to read an enormous - document of revised T&Cs, get that out of the way in advance, so it - doesn't suddenly become a delay in the middle of the actual - release. - -The actual release procedure ----------------------------- - -Once all the above preparation is done and the release has been built -locally, this is the procedure for putting it up on the web. - - - Make a final adjustment to your local website changes, filling in - the release date in components/releases/X.YZ.mi. + - Make final adjustments to the local website and wishlist changes, + filling in the release date in components/releases/X.YZ.mi, and any + missing (e.g. not previously finalised) commit hashes in wishlist + entries. Check that both look sensible locally. - Upload the release itself and its link maps to everywhere it needs to be, by running this in the build-X.YZ-rcN.out directory: From ee72268b8fea9010a61b09709a4e0ccb4ab4d146 Mon Sep 17 00:00:00 2001 From: Jacob Nevins Date: Tue, 11 Feb 2025 20:38:49 +0000 Subject: [PATCH 012/129] Docs: improve -share/-noshare docs. These options apply to many PuTTY tools, not just Plink; the indexing was wonky; and -noshare wasn't documented at all. --- doc/index.but | 2 ++ doc/plink.but | 22 ---------------------- doc/using.but | 20 ++++++++++++++++++++ 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/doc/index.but b/doc/index.but index 94e2a477..9f70d7ab 100644 --- a/doc/index.but +++ b/doc/index.but @@ -262,6 +262,8 @@ saved sessions from \IM{-i} \c{-i} command-line option \IM{-pgpfp} \c{-pgpfp} command-line option \IM{-sercfg} \c{-sercfg} command-line option +\IM{\-share} \c{\-share} command-line option +\IM{\-noshare} \c{\-noshare} command-line option \IM{removing registry entries} removing registry entries \IM{removing registry entries} registry entries, removing diff --git a/doc/plink.but b/doc/plink.but index a985218f..d83d4dd0 100644 --- a/doc/plink.but +++ b/doc/plink.but @@ -255,28 +255,6 @@ line. (This option is only meaningful with the SSH-2 protocol.) -\S2{plink-option-share} \I{-share-plink}\c{-share}: -Test and try to share an existing connection. - -This option tries to detect if an existing connection can be shared -(See \k{config-ssh-sharing} for more information about SSH connection -sharing.) and reuses that connection. - -A Plink invocation of the form: - -\c plink -share -\e iiiiiiiii - -will test whether there is currently a viable \q{upstream} for the -session in question, which can be specified using any syntax you'd -normally use with Plink to make an actual connection (a host/port -number, a bare saved session name, \c{-load}, etc). If no \q{upstream} -viable session is found and \c{-share} is specified, this connection -will be become the \q{upstream} connection for subsequent connection -sharing tries. - -(This option is only meaningful with the SSH-2 protocol.) - \S2{plink-option-shareexists} \I{-shareexists-plink}\c{-shareexists}: test for connection-sharing upstream diff --git a/doc/using.but b/doc/using.but index c595c153..ebb9d91e 100644 --- a/doc/using.but +++ b/doc/using.but @@ -1137,6 +1137,26 @@ described there are understood in the argument string, literal backslashes must be doubled (if you want \c{\\} in your command, you must put \c{\\\\} on the command line). +\S2{using-cmdline-share-noshare} \i\c{\-share}, \i\c{\-noshare}: +enable/disable connection sharing + +These options control whether SSH connection sharing is attempted. +See \k{config-ssh-sharing} for more information about SSH connection +sharing. These options are equivalent to the \q{Share SSH connections +if possible} checkbox in the GUI configuration. + +With \c{\-share}, a PuTTY tool will check to see if there's an +existing \q{upstream} for this host. If there is, then the new session +will connect via that upstream. If there isn't, the new session will +\e{become} an upstream for future connections (unless \c{\-share} +has been given as an option to the file transfer tools, PSCP and PSFTP, +which never act as upstreams). + +With \c{\-noshare}, this connection will not participate in connection +sharing (either as an upstream or a downstream). + +(This option is only meaningful with the SSH-2 protocol.) + \S2{using-cmdline-restrict-acl} \i\c{-restrict-acl}: restrict the \i{Windows process ACL} From 5814bdf52972741f431cf4efacf5ee151f22cb62 Mon Sep 17 00:00:00 2001 From: Jacob Nevins Date: Tue, 11 Feb 2025 17:42:30 +0000 Subject: [PATCH 013/129] Docs: replace long-dead link for Netcat. --- doc/using.but | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/using.but b/doc/using.but index ebb9d91e..96f5f2a7 100644 --- a/doc/using.but +++ b/doc/using.but @@ -970,7 +970,7 @@ functionality as port forwarding, so it will not work if your server administrator has disabled port forwarding. (The option is named \c{-nc} after the Unix program -\W{http://www.vulnwatch.org/netcat/}\c{nc}, short for \q{netcat}. +\W{https://en.wikipedia.org/wiki/Netcat}\c{nc}, short for \q{netcat}. The command \cq{plink host1 -nc host2:port} is very similar in functionality to \cq{plink host1 nc host2 port}, which invokes \c{nc} on the server and tells it to connect to the specified From 54648a161e50f6a8a6e2788763fe973d8b28aef6 Mon Sep 17 00:00:00 2001 From: Jacob Nevins Date: Tue, 11 Feb 2025 16:06:31 +0000 Subject: [PATCH 014/129] Docs: consistently use \- for options. (That's Halibut's non-breaking hyphen.) Triggered by noticing that the changes in 54f6fefe61 happened to come out badly in the text-only rendering, but I noticed there were many more instances in the main docs where non-breaking hyphens would help. --- doc/config.but | 8 +-- doc/errors.but | 2 +- doc/faq.but | 10 +-- doc/index.but | 98 +++++++++++++------------- doc/pageant.but | 20 +++--- doc/pgpkeys.but | 2 +- doc/plink.but | 48 ++++++------- doc/privacy.but | 2 +- doc/pscp.but | 44 ++++++------ doc/psftp.but | 54 +++++++------- doc/pubkey.but | 2 +- doc/udp.but | 2 +- doc/using.but | 182 ++++++++++++++++++++++++------------------------ 13 files changed, 237 insertions(+), 237 deletions(-) diff --git a/doc/config.but b/doc/config.but index fb836ec2..56641b5b 100644 --- a/doc/config.but +++ b/doc/config.but @@ -2006,7 +2006,7 @@ and non-SSH proxying. \b \q{SSH to proxy and use port forwarding} causes PuTTY to use the secondary SSH connection to open a port-forwarding channel to the -final destination host (similar to OpenSSH's \cw{-J} option). +final destination host (similar to OpenSSH's \cw{\-J} option). \b \q{SSH to proxy and execute a command} causes PuTTY to run an arbitrary remote command on the proxy SSH server and use that @@ -2247,7 +2247,7 @@ ability to run a shell. This feature is only available in \i{SSH protocol version 2} (since the version 1 protocol assumes you will always want to run a shell). -This feature can also be enabled using the \c{-N} command-line +This feature can also be enabled using the \c{\-N} command-line option; see \k{using-cmdline-noshell}. If you use this feature in Plink, you will not be able to terminate @@ -2639,7 +2639,7 @@ key not in that list. Another reason is if PuTTY's automated host key management is completely unavailable, e.g. because PuTTY (or Plink or PSFTP, etc) is running in a Windows environment without access to the Registry. In -that situation, you will probably want to use the \cw{-hostkey} +that situation, you will probably want to use the \cw{\-hostkey} command-line option to configure the expected host key(s); see \k{using-cmdline-hostkey}. @@ -2970,7 +2970,7 @@ by default. In rare cases you might need to turn it off in order to force authentication by some non-public-key method such as passwords. -This option can also be controlled using the \c{-noagent} +This option can also be controlled using the \c{\-noagent} command-line option. See \k{using-cmdline-agentauth}. See \k{pageant} for more information about Pageant in general. diff --git a/doc/errors.but b/doc/errors.but index ca1a53e0..85ed4bbb 100644 --- a/doc/errors.but +++ b/doc/errors.but @@ -100,7 +100,7 @@ protocol. If the server genuinely only supports SSH-1, then you need to either change the \q{SSH protocol version} setting (see \k{config-ssh-prot}), -or use the \c{-1} command-line option; in any case, you should not +or use the \c{\-1} command-line option; in any case, you should not treat the resulting connection as secure. You might start seeing this message with new versions of PuTTY (from diff --git a/doc/faq.but b/doc/faq.but index 35db12e4..dca41519 100644 --- a/doc/faq.but +++ b/doc/faq.but @@ -159,7 +159,7 @@ If you're having a specific problem with host key checking - perhaps you want an automated batch job to make use of PSCP or Plink, and the interactive host key prompt is hanging the batch process - then the right way to fix it is to add the correct host key to the Registry in -advance, or if the Registry is not available, to use the \cw{-hostkey} +advance, or if the Registry is not available, to use the \cw{\-hostkey} command-line option. That way, you retain the \e{important} feature of host key checking: the right key will be accepted and the wrong ones will not. Adding an option to turn host key checking off completely is @@ -556,7 +556,7 @@ deprecated and may be removed at some point.) \S{faq-startssh}{Question} How can I start an SSH session straight from the command line? -Use the command line \c{putty -ssh host.name}. Alternatively, create +Use the command line \c{putty \-ssh host.name}. Alternatively, create a saved session that specifies the SSH protocol, and start the saved session as shown in \k{faq-startsess}. @@ -628,7 +628,7 @@ have to use backslashes and two sets of quotes: Worse still, in a remote-to-local copy you have to specify the local file name explicitly, otherwise PSCP will complain that they don't -match (unless you specified the \c{-unsafe} option). The following +match (unless you specified the \c{\-unsafe} option). The following command will give an error message: \c c:\>pscp user@host:"\"oo er\"" . @@ -1129,7 +1129,7 @@ feature. If you are using PuTTY on a public PC, or somebody else's PC, you might want to clean this information up when you leave. You can do -that automatically, by running the command \c{putty -cleanup}. See +that automatically, by running the command \c{putty \-cleanup}. See \k{using-cleanup} in the documentation for more detail. (Note that this only removes settings for the currently logged-in user on \i{multi-user systems}.) @@ -1137,7 +1137,7 @@ this only removes settings for the currently logged-in user on If PuTTY was installed from the installer package, it will also appear in \q{Add/Remove Programs}. Current versions of the installer do not offer to remove the above-mentioned items, so if you want them -removed you should run \c{putty -cleanup} before uninstalling. +removed you should run \c{putty \-cleanup} before uninstalling. \S{faq-dsa}{Question} How come PuTTY now supports \i{DSA}, when the website used to say how insecure it was? diff --git a/doc/index.but b/doc/index.but index 9f70d7ab..226e9a34 100644 --- a/doc/index.but +++ b/doc/index.but @@ -231,37 +231,37 @@ saved sessions from \IM{QUIT special character} \cw{QUIT}, special character \IM{QUIT special character} \cw{VQUIT}, special character -\IM{-telnet} \c{-telnet} command-line option -\IM{-raw} \c{-raw} command-line option -\IM{-rlogin} \c{-rlogin} command-line option -\IM{-supdup} \c{-supdup} command-line option -\IM{-ssh} \c{-ssh} command-line option -\IM{-ssh-connection} \c{-ssh-connection} command-line option -\IM{-serial} \c{-serial} command-line option -\IM{-cleanup} \c{-cleanup} command-line option -\IM{-load} \c{-load} command-line option -\IM{-v} \c{-v} command-line option -\IM{-l} \c{-l} command-line option -\IM{-L-upper} \c{-L} command-line option -\IM{-R-upper} \c{-R} command-line option -\IM{-D-upper} \c{-D} command-line option -\IM{-m} \c{-m} command-line option -\IM{-P-upper} \c{-P} command-line option -\IM{-pw} \c{-pw} command-line option -\IM{-pwfile} \c{-pwfile} command-line option -\IM{-A-upper} \c{-A} command-line option -\IM{-a} \c{-a} command-line option -\IM{-X-upper} \c{-X} command-line option -\IM{-x} \c{-x} command-line option -\IM{-T-upper} \c{-T} command-line option -\IM{-t} \c{-t} command-line option -\IM{-C-upper} \c{-C} command-line option -\IM{-N-upper} \c{-N} command-line option -\IM{-1} \c{-1} command-line option -\IM{-2} \c{-2} command-line option -\IM{-i} \c{-i} command-line option -\IM{-pgpfp} \c{-pgpfp} command-line option -\IM{-sercfg} \c{-sercfg} command-line option +\IM{\-telnet} \c{\-telnet} command-line option +\IM{\-raw} \c{\-raw} command-line option +\IM{\-rlogin} \c{\-rlogin} command-line option +\IM{\-supdup} \c{\-supdup} command-line option +\IM{\-ssh} \c{\-ssh} command-line option +\IM{\-ssh\-connection} \c{\-ssh\-connection} command-line option +\IM{\-serial} \c{\-serial} command-line option +\IM{\-cleanup} \c{\-cleanup} command-line option +\IM{\-load} \c{\-load} command-line option +\IM{\-v} \c{\-v} command-line option +\IM{\-l} \c{\-l} command-line option +\IM{-L-upper} \c{\-L} command-line option +\IM{-R-upper} \c{\-R} command-line option +\IM{-D-upper} \c{\-D} command-line option +\IM{\-m} \c{\-m} command-line option +\IM{-P-upper} \c{\-P} command-line option +\IM{\-pw} \c{\-pw} command-line option +\IM{\-pwfile} \c{\-pwfile} command-line option +\IM{-A-upper} \c{\-A} command-line option +\IM{\-a} \c{\-a} command-line option +\IM{-X-upper} \c{\-X} command-line option +\IM{\-x} \c{\-x} command-line option +\IM{-T-upper} \c{\-T} command-line option +\IM{\-t} \c{\-t} command-line option +\IM{-C-upper} \c{\-C} command-line option +\IM{-N-upper} \c{\-N} command-line option +\IM{\-1} \c{\-1} command-line option +\IM{\-2} \c{\-2} command-line option +\IM{\-i} \c{\-i} command-line option +\IM{\-pgpfp} \c{\-pgpfp} command-line option +\IM{\-sercfg} \c{\-sercfg} command-line option \IM{\-share} \c{\-share} command-line option \IM{\-noshare} \c{\-noshare} command-line option @@ -769,22 +769,22 @@ saved sessions from \IM{SFTP} SFTP \IM{SFTP} SSH file transfer protocol -\IM{-unsafe} \c{-unsafe} PSCP command-line option -\IM{-ls-PSCP} \c{-ls} PSCP command-line option -\IM{-p-PSCP} \c{-p} PSCP command-line option -\IM{-q-PSCP} \c{-q} PSCP command-line option -\IM{-r-PSCP} \c{-r} PSCP command-line option -\IM{-batch-PSCP} \c{-batch} PSCP command-line option -\IM{-sftp} \c{-sftp} PSCP command-line option -\IM{-scp} \c{-scp} PSCP command-line option +\IM{\-unsafe} \c{\-unsafe} PSCP command-line option +\IM{-ls-PSCP} \c{\-ls} PSCP command-line option +\IM{-p-PSCP} \c{\-p} PSCP command-line option +\IM{-q-PSCP} \c{\-q} PSCP command-line option +\IM{-r-PSCP} \c{\-r} PSCP command-line option +\IM{-batch-PSCP} \c{\-batch} PSCP command-line option +\IM{\-sftp} \c{\-sftp} PSCP command-line option +\IM{\-scp} \c{\-scp} PSCP command-line option \IM{return value} return value \IM{return value} exit value -\IM{-b-PSFTP} \c{-b} PSFTP command-line option -\IM{-bc-PSFTP} \c{-bc} PSFTP command-line option -\IM{-be-PSFTP} \c{-be} PSFTP command-line option -\IM{-batch-PSFTP} \c{-batch} PSFTP command-line option +\IM{-b-PSFTP} \c{\-b} PSFTP command-line option +\IM{-bc-PSFTP} \c{\-bc} PSFTP command-line option +\IM{-be-PSFTP} \c{\-be} PSFTP command-line option +\IM{-batch-PSFTP} \c{\-batch} PSFTP command-line option \IM{spaces in filenames} spaces in filenames \IM{spaces in filenames} filenames containing spaces @@ -821,9 +821,9 @@ saved sessions from \IM{PLINK_PROTOCOL} \c{PLINK_PROTOCOL} environment variable -\IM{-batch-plink} \c{-batch} Plink command-line option -\IM{-s-plink} \c{-s} Plink command-line option -\IM{-shareexists-plink} \c{-shareexists} Plink command-line option +\IM{-batch-plink} \c{\-batch} Plink command-line option +\IM{-s-plink} \c{\-s} Plink command-line option +\IM{-shareexists-plink} \c{\-shareexists} Plink command-line option \IM{subsystem} subsystem, SSH \IM{subsystem} SSH subsystem @@ -891,9 +891,9 @@ saved sessions from \IM{authentication agent} authentication agent \IM{authentication agent} agent, authentication -\IM{-c-pageant} \c{-c} Pageant command-line option -\IM{--keylist} \c{--keylist} Pageant command-line option -\IM{--openssh-config} \c{--openssh-config} Pageant command-line option +\IM{-c-pageant} \c{\-c} Pageant command-line option +\IM{\-\-keylist} \c{\-\-keylist} Pageant command-line option +\IM{\-\-openssh\-config} \c{\-\-openssh\-config} Pageant command-line option \IM{Windows OpenSSH} Windows OpenSSH \IM{Windows OpenSSH} OpenSSH, on Windows diff --git a/doc/pageant.but b/doc/pageant.but index de6d4cb8..cf3a2955 100644 --- a/doc/pageant.but +++ b/doc/pageant.but @@ -167,7 +167,7 @@ passphrases on startup. If Pageant is already running, this syntax loads keys into the existing Pageant. -You can specify the \cq{--encrypted} option to defer decryption of +You can specify the \cq{\-\-encrypted} option to defer decryption of these keys; see \k{pageant-deferred-decryption}. \S{pageant-cmdline-command} Making Pageant run another program @@ -178,7 +178,7 @@ line. This program (perhaps a PuTTY, or a WinCVS making use of Plink, or whatever) will then be able to use the keys Pageant has loaded. -You do this by specifying the \I{-c-pageant}\c{-c} option followed +You do this by specifying the \I{-c-pageant}\c{\-c} option followed by the command, like this: \c C:\PuTTY\pageant.exe d:\main.ppk -c C:\PuTTY\putty.exe @@ -197,7 +197,7 @@ configuration, then \c{ssh.exe} should automatically use Pageant as its agent, so that you can keep your keys in one place and have both SSH clients able to use them. -The option is \i\c{--openssh-config}, and you follow it with a filename. +The option is \i\c{\-\-openssh\-config}, and you follow it with a filename. To refer to this file from your main OpenSSH configuration, you can use the \cq{Include} directive. For example, you might run Pageant @@ -238,7 +238,7 @@ original Windows Subsystem for Linux (now known as WSL 1). So if you ask Pageant to listen on one of these, then your WSL 1 processes can talk directly to Pageant. -To configure this, run Pageant with the option \c{--unix}, followed +To configure this, run Pageant with the option \c{\-\-unix}, followed with a pathname. Then, in WSL 1, set the environment variable \cw{SSH_AUTH_SOCK} to point at the WSL translation of that pathname. @@ -271,18 +271,18 @@ to. \S{pageant-cmdline-keylist} Starting with the key list visible -Start Pageant with the \i\c{--keylist} option to show the main window +Start Pageant with the \i\c{\-\-keylist} option to show the main window as soon as it starts up. \S{pageant-cmdline-restrict-acl} Restricting the \i{Windows process ACL} -Pageant supports the same \i\c{-restrict-acl} option as the other +Pageant supports the same \i\c{\-restrict\-acl} option as the other PuTTY utilities to lock down the Pageant process's access control; see \k{using-cmdline-restrict-acl} for why you might want to do this. -By default, if Pageant is started with \c{-restrict-acl}, it won't +By default, if Pageant is started with \c{\-restrict\-acl}, it won't pass this to any PuTTY sessions started from its System Tray submenu. -Use \c{-restrict-putty-acl} to change this. (Again, see +Use \c{\-restrict\-putty\-acl} to change this. (Again, see \k{using-cmdline-restrict-acl} for details.) \H{pageant-forward} Using \i{agent forwarding} @@ -298,7 +298,7 @@ agent protocol, which PuTTY does not yet support. To enable agent forwarding, first start Pageant. Then set up a PuTTY SSH session in which \q{Allow agent forwarding} is enabled (see \k{config-ssh-agentfwd}). Open the session as normal. (Alternatively, -you can use the \c{-A} command line option; see +you can use the \c{\-A} command line option; see \k{using-cmdline-agent} for details.) If this has worked, your applications on the server should now have @@ -365,7 +365,7 @@ won't ask for a passphrase. Instead, the key will be listed in the main window with \q{(encrypted)} after it. To start Pageant up in the first place with encrypted keys loaded into -it, you can use the \cq{--encrypted} option on the command line. For +it, you can use the \cq{\-\-encrypted} option on the command line. For example: \c C:\PuTTY\pageant.exe --encrypted d:\main.ppk diff --git a/doc/pgpkeys.but b/doc/pgpkeys.but index 9fcd8657..4ad4986a 100644 --- a/doc/pgpkeys.but +++ b/doc/pgpkeys.but @@ -9,7 +9,7 @@ This description is provided as both a web page on the PuTTY site, and an appendix in the PuTTY manual. As of release 0.58, all of the PuTTY executables contain fingerprint -material (usually accessed via the \i\c{-pgpfp} command-line +material (usually accessed via the \i\c{\-pgpfp} command-line option), such that if you have an executable you trust, you can use it to establish a trust path, for instance to a newer version downloaded from the Internet. diff --git a/doc/plink.but b/doc/plink.but index d83d4dd0..81e4e5f1 100644 --- a/doc/plink.but +++ b/doc/plink.but @@ -35,7 +35,7 @@ This section describes the basics of how to use Plink for interactive logins and for automated processes. Once you've got a console window to type into, you can type -\c{plink --help} to bring up a usage message. This tells you the +\c{plink \-\-help} to bring up a usage message. This tells you the version of Plink you're using, and gives you a brief summary of how to use Plink: @@ -121,8 +121,8 @@ characters appearing in your window. Interactive connections like this are not the main point of Plink. In order to connect with a different protocol, you can give the -command line options \c{-ssh}, \c{-ssh-connection}, \c{-telnet}, -\c{-rlogin}, or \c{-raw}. To make an SSH connection, for example: +command line options \c{\-ssh}, \c{\-ssh\-connection}, \c{\-telnet}, +\c{\-rlogin}, or \c{\-raw}. To make an SSH connection, for example: \c C:\>plink -ssh login.example.com \c login as: @@ -138,8 +138,8 @@ and use most of the other features of PuTTY: \c Last login: Thu Dec 6 19:25:33 2001 from :0.0 \c fred@flunky:~$ -(You can also use the \c{-load} command-line option to load a saved -session; see \k{using-cmdline-load}. If you use \c{-load}, the saved +(You can also use the \c{\-load} command-line option to load a saved +session; see \k{using-cmdline-load}. If you use \c{\-load}, the saved session exists, and it specifies a hostname, you cannot also specify a \c{host} or \c{user@host} argument - it will be treated as part of the remote command.) @@ -151,7 +151,7 @@ talk directly to a program running on the server. To do this you have to ensure Plink is \e{using} the SSH protocol. You can do this in several ways: -\b Use the \c{-ssh} option as described in +\b Use the \c{\-ssh} option as described in \k{plink-usage-interactive}. \b Set up a PuTTY saved session that describes the server you are @@ -181,8 +181,8 @@ use it; see \k{using-cmdline-hostkey}. To avoid being prompted for a user name, you can: -\b Use the \c{-l} option to specify a user name on the command line. -For example, \c{plink login.example.com -l fred}. +\b Use the \c{\-l} option to specify a user name on the command line. +For example, \c{plink login.example.com \-l fred}. \b Set up a PuTTY saved session that describes the server you are connecting to, and that also specifies the username to log in as @@ -230,32 +230,32 @@ options. Plink also supports some of its own options. The following sections describe Plink's specific command-line options. -\S2{plink-option-batch} \I{-batch-plink}\c{-batch}: disable all +\S2{plink-option-batch} \I{-batch-plink}\c{\-batch}: disable all interactive prompts -If you use the \c{-batch} option, Plink will never give an +If you use the \c{\-batch} option, Plink will never give an interactive prompt while establishing the connection. If the server's host key is invalid, for example (see \k{gs-hostkey}), then the connection will simply be abandoned instead of asking you what to do next. This may help Plink's behaviour when it is used in automated -scripts: using \c{-batch}, if something goes wrong at connection +scripts: using \c{\-batch}, if something goes wrong at connection time, the batch job will fail rather than hang. If another program is invoking Plink on your behalf, then you might -need to arrange that that program passes \c{-batch} to Plink. See +need to arrange that that program passes \c{\-batch} to Plink. See \k{plink-git} for an example involving Git. -\S2{plink-option-s} \I{-s-plink}\c{-s}: remote command is SSH subsystem +\S2{plink-option-s} \I{-s-plink}\c{\-s}: remote command is SSH subsystem -If you specify the \c{-s} option, Plink passes the specified command +If you specify the \c{\-s} option, Plink passes the specified command as the name of an SSH \q{\i{subsystem}} rather than an ordinary command line. (This option is only meaningful with the SSH-2 protocol.) -\S2{plink-option-shareexists} \I{-shareexists-plink}\c{-shareexists}: +\S2{plink-option-shareexists} \I{-shareexists-plink}\c{\-shareexists}: test for connection-sharing upstream This option does not make a new connection; instead it allows testing @@ -271,12 +271,12 @@ A Plink invocation of the form: will test whether there is currently a viable \q{upstream} for the session in question, which can be specified using any syntax you'd normally use with Plink to make an actual connection (a host/port -number, a bare saved session name, \c{-load}, etc). It returns a +number, a bare saved session name, \c{\-load}, etc). It returns a zero exit status if a usable \q{upstream} exists, nonzero otherwise. (This option is only meaningful with the SSH-2 protocol.) -\S2{plink-option-sanitise} \I{-sanitise-stderr}\I{-sanitise-stdout}\I{-no-sanitise-stderr}\I{-no-sanitise-stdout}\c{-sanitise-}\e{stream}: control output sanitisation +\S2{plink-option-sanitise} \I{\-sanitise\-stderr}\I{\-sanitise\-stdout}\I{\-no\-sanitise\-stderr}\I{\-no\-sanitise\-stdout}\c{\-sanitise\-}\e{stream}: control output sanitisation In some situations, Plink applies a sanitisation pass to the output received from the server, to strip out control characters such as @@ -301,26 +301,26 @@ But in case Plink guesses wrong about whether you want this sanitisation, you can override it in either direction, using one of these options: -\dt \c{-sanitise-stderr} +\dt \c{\-sanitise\-stderr} \dd Sanitise server data written to Plink's standard error channel, regardless of terminals and consoles and remote ptys. -\dt \c{-no-sanitise-stderr} +\dt \c{\-no\-sanitise\-stderr} \dd Do not sanitise server data written to Plink's standard error channel. -\dt \c{-sanitise-stdout} +\dt \c{\-sanitise\-stdout} \dd Sanitise server data written to Plink's standard output channel. -\dt \c{-no-sanitise-stdout} +\dt \c{\-no\-sanitise\-stdout} \dd Do not sanitise server data written to Plink's standard output channel. -\S2{plink-option-antispoof} \i{-no-antispoof}: turn off authentication spoofing protection prompt +\S2{plink-option-antispoof} \i{\-no\-antispoof}: turn off authentication spoofing protection prompt In SSH, some possible server authentication methods require user input (for example, password authentication, or entering a private key @@ -358,7 +358,7 @@ and so Plink omits the anti-spoofing prompt. But if you still find the protective prompt inconvenient, and you trust the server not to try a trick like this, you can turn it off -using the \cq{-no-antispoof} option. +using the \cq{\-no\-antispoof} option. \H{plink-batch} Using Plink in \i{batch files} and \i{scripts} @@ -394,7 +394,7 @@ This environment variable accepts a whole command line, not just an executable file name. So you can add Plink options to the end of it if you like. For example, if you're using Git in a batch-mode context, where your Git jobs are running unattended and nobody is available to -answer interactive prompts, you might also append the \cq{-batch} +answer interactive prompts, you might also append the \cq{\-batch} option (\k{plink-option-batch}): \c set GIT_SSH_COMMAND="C:\Program Files\PuTTY\plink.exe" -batch diff --git a/doc/privacy.but b/doc/privacy.but index 0f488bf6..fbd14fc1 100644 --- a/doc/privacy.but +++ b/doc/privacy.but @@ -19,7 +19,7 @@ computer, necessary for doing its own job. This information is stored in the user account of the user who runs PuTTY, so it is under your control: you can view it, change it, or delete it. -If you need to delete all of this data, you can use the \c{-cleanup} +If you need to delete all of this data, you can use the \c{\-cleanup} command-line option, as described in \k{using-cleanup}. PuTTY does not transmit your saved session data to any other site. diff --git a/doc/pscp.but b/doc/pscp.but index dd959121..1fb18df6 100644 --- a/doc/pscp.but +++ b/doc/pscp.but @@ -33,7 +33,7 @@ to include a \c{set} command like the one above. \H{pscp-usage} PSCP Usage Once you've got a console window to type into, you can type -\c{pscp -h} to bring up a usage message. This tells you the +\c{pscp \-h} to bring up a usage message. This tells you the version of PSCP you're using, and gives you a brief summary of how to use PSCP: @@ -114,7 +114,7 @@ However, in the second case (using a wildcard for multiple remote files) you may see a warning saying something like \q{warning: remote host tried to write to a file called \cq{terminal.c} when we requested a file called \cq{*.c}. If this is a wildcard, consider -upgrading to SSH-2 or using the \cq{-unsafe} option. Renaming of +upgrading to SSH-2 or using the \cq{\-unsafe} option. Renaming of this file has been disallowed}. This is due to a \I{security risk}fundamental insecurity in the old-style @@ -132,10 +132,10 @@ PSCP will attempt to use the newer \i{SFTP} protocol (part of SSH-2) where possible, which does not suffer from this security flaw. If you are talking to an SSH-2 server which supports SFTP, you will never see this warning. (You can force use of the SFTP protocol, -if available, with \c{-sftp} - see \k{pscp-usage-options-backend}.) +if available, with \c{\-sftp} - see \k{pscp-usage-options-backend}.) If you really need to use a server-side wildcard with an SSH-1 -server, you can use the \i\c{-unsafe} command line option with PSCP: +server, you can use the \i\c{\-unsafe} command line option with PSCP: \c pscp -unsafe fred@example.com:source/*.c c:\source @@ -203,9 +203,9 @@ options. (The ones not supported by PSCP are clearly marked.) PSCP also supports some of its own options. The following sections describe PSCP's specific command-line options. -\S2{pscp-usage-options-ls}\I{-ls-PSCP}\c{-ls} \I{listing files}list remote files +\S2{pscp-usage-options-ls}\I{-ls-PSCP}\c{\-ls} \I{listing files}list remote files -If the \c{-ls} option is given, no files are transferred; instead, +If the \c{\-ls} option is given, no files are transferred; instead, remote files are listed. Only a hostname specification and optional remote file specification need be given. For example: @@ -213,18 +213,18 @@ optional remote file specification need be given. For example: The SCP protocol does not contain within itself a means of listing files. If SCP is in use, this option therefore assumes that the -server responds appropriately to the command \c{ls\_-la}; +server responds appropriately to the command \c{ls\_\-la}; this may not work with all servers. If SFTP is in use, this option should work with all servers. -\S2{pscp-usage-options-p}\I{-p-PSCP}\c{-p} \i{preserve file attributes} +\S2{pscp-usage-options-p}\I{-p-PSCP}\c{\-p} \i{preserve file attributes} By default, files copied with PSCP are \i{timestamp}ed with the date and -time they were copied. The \c{-p} option preserves the original +time they were copied. The \c{\-p} option preserves the original timestamp on copied files. -\S2{pscp-usage-options-q}\I{-q-PSCP}\c{-q} quiet, don't show \i{statistics} +\S2{pscp-usage-options-q}\I{-q-PSCP}\c{\-q} quiet, don't show \i{statistics} By default, PSCP displays a meter displaying the progress of the current transfer: @@ -235,30 +235,30 @@ The fields in this display are (from left to right), filename, size (in kilobytes) of file transferred so far, estimate of how fast the file is being transferred (in kilobytes per second), estimated time that the transfer will be complete, and percentage of the file so far -transferred. The \c{-q} option to PSCP suppresses the printing of +transferred. The \c{\-q} option to PSCP suppresses the printing of these statistics. -\S2{pscp-usage-options-r}\I{-r-PSCP}\c{-r} copies directories \i{recursive}ly +\S2{pscp-usage-options-r}\I{-r-PSCP}\c{\-r} copies directories \i{recursive}ly By default, PSCP will only copy files. Any directories you specify to -copy will be skipped, as will their contents. The \c{-r} option tells +copy will be skipped, as will their contents. The \c{\-r} option tells PSCP to descend into any directories you specify, and to copy them and their contents. This allows you to use PSCP to transfer whole directory structures between machines. -\S2{pscp-usage-options-batch}\I{-batch-PSCP}\c{-batch} avoid interactive prompts +\S2{pscp-usage-options-batch}\I{-batch-PSCP}\c{\-batch} avoid interactive prompts -If you use the \c{-batch} option, PSCP will never give an +If you use the \c{\-batch} option, PSCP will never give an interactive prompt while establishing the connection. If the server's host key is invalid, for example (see \k{gs-hostkey}), then the connection will simply be abandoned instead of asking you what to do next. This may help PSCP's behaviour when it is used in automated -scripts: using \c{-batch}, if something goes wrong at connection +scripts: using \c{\-batch}, if something goes wrong at connection time, the batch job will fail rather than hang. -\S2{pscp-usage-options-backend}\i\c{-sftp}, \i\c{-scp} force use of +\S2{pscp-usage-options-backend}\i\c{\-sftp}, \i\c{\-scp} force use of particular file transfer protocol As mentioned in \k{pscp-usage-basics}, there are two different file @@ -283,15 +283,15 @@ automation, and avoids security issues with wildcard matching. Normally PSCP will attempt to use the SFTP protocol, and only fall back to the SCP protocol if SFTP is not available on the server. -The \c{-scp} option forces PSCP to use the SCP protocol or quit. +The \c{\-scp} option forces PSCP to use the SCP protocol or quit. -The \c{-sftp} option forces PSCP to use the SFTP protocol or quit. +The \c{\-sftp} option forces PSCP to use the SFTP protocol or quit. When this option is specified, PSCP looks harder for an SFTP server, which may allow use of SFTP with SSH-1 depending on server setup. -\S2{pscp-option-sanitise} \I{-sanitise-stderr}\I{-no-sanitise-stderr}\c{-no-sanitise-stderr}: control error message sanitisation +\S2{pscp-option-sanitise} \I{\-sanitise\-stderr}\I{\-no\-sanitise\-stderr}\c{\-no\-sanitise\-stderr}: control error message sanitisation -The \c{-no-sanitise-stderr} option will cause PSCP to pass through the +The \c{\-no\-sanitise\-stderr} option will cause PSCP to pass through the server's standard-error stream literally, without stripping control characters from it first. This might be useful if the server were sending coloured error messages, but it also gives the server the @@ -325,7 +325,7 @@ hostname: type \c{pscp sessionname:file localfile}, where \c{sessionname} is replaced by the name of your saved session. Secondly, you can supply the name of a private key file on the command -line, with the \c{-i} option. See \k{using-cmdline-identity} for more +line, with the \c{\-i} option. See \k{using-cmdline-identity} for more information. Thirdly, PSCP will attempt to authenticate using Pageant if Pageant diff --git a/doc/psftp.but b/doc/psftp.but index cc4bb259..623e15e8 100644 --- a/doc/psftp.but +++ b/doc/psftp.but @@ -55,14 +55,14 @@ options. (The ones not supported by PSFTP are clearly marked.) PSFTP also supports some of its own options. The following sections describe PSFTP's specific command-line options. -\S{psftp-option-b} \I{-b-PSFTP}\c{-b}: specify a file containing batch commands +\S{psftp-option-b} \I{-b-PSFTP}\c{\-b}: specify a file containing batch commands In normal operation, PSFTP is an interactive program which displays a command line and accepts commands from the keyboard. If you need to do automated tasks with PSFTP, you would probably prefer to \I{batch scripts in PSFTP}specify a set of commands in -advance and have them executed automatically. The \c{-b} option +advance and have them executed automatically. The \c{\-b} option allows you to do this. You use it with a file name containing batch commands. For example, you might create a file called \c{myscript.scr} containing lines like this: @@ -79,14 +79,14 @@ and then you could run the script by typing When you run a batch script in this way, PSFTP will abort the script if any command fails to complete successfully. To change this -behaviour, you can add the \c{-be} option (\k{psftp-option-be}). +behaviour, you can add the \c{\-be} option (\k{psftp-option-be}). PSFTP will terminate after it finishes executing the batch script. -\S{psftp-option-bc} \I{-bc-PSFTP}\c{-bc}: display batch commands as they are run +\S{psftp-option-bc} \I{-bc-PSFTP}\c{\-bc}: display batch commands as they are run -The \c{-bc} option alters what PSFTP displays while processing a -batch script specified with \c{-b}. With the \c{-bc} option, PSFTP +The \c{\-bc} option alters what PSFTP displays while processing a +batch script specified with \c{\-b}. With the \c{\-bc} option, PSFTP will display prompts and commands just as if the commands had been typed at the keyboard. So instead of seeing this: @@ -114,7 +114,7 @@ you might see this: \c drwxrwsr-x 2 fred fred 1024 Mar 13 2000 trn \c psftp> quit -\S{psftp-option-be} \I{-be-PSFTP}\c{-be}: continue batch processing on errors +\S{psftp-option-be} \I{-be-PSFTP}\c{\-be}: continue batch processing on errors When running a batch file, this additional option causes PSFTP to continue processing even if a command fails to complete successfully. @@ -122,22 +122,22 @@ continue processing even if a command fails to complete successfully. You might want this to happen if you wanted to delete a file and didn't care if it was already not present, for example. -\S{psftp-usage-options-batch} \I{-batch-PSFTP}\c{-batch}: avoid +\S{psftp-usage-options-batch} \I{-batch-PSFTP}\c{\-batch}: avoid interactive prompts -If you use the \c{-batch} option, PSFTP will never give an +If you use the \c{\-batch} option, PSFTP will never give an interactive prompt while establishing the connection. If the server's host key is invalid, for example (see \k{gs-hostkey}), then the connection will simply be abandoned instead of asking you what to do next. This may help PSFTP's behaviour when it is used in automated -scripts: using \c{-batch}, if something goes wrong at connection +scripts: using \c{\-batch}, if something goes wrong at connection time, the batch job will fail rather than hang. -\S2{psftp-option-sanitise} \I{-sanitise-stderr}\I{-no-sanitise-stderr}\c{-no-sanitise-stderr}: control error message sanitisation +\S2{psftp-option-sanitise} \I{\-sanitise\-stderr}\I{\-no\-sanitise\-stderr}\c{\-no\-sanitise\-stderr}: control error message sanitisation -The \c{-no-sanitise-stderr} option will cause PSFTP to pass through the +The \c{\-no\-sanitise\-stderr} option will cause PSFTP to pass through the server's standard-error stream literally, without stripping control characters from it first. This might be useful if the server were sending coloured error messages, but it also gives the server the @@ -317,16 +317,16 @@ specify the local file name after the remote one: This will fetch the file on the server called \c{myfile.dat}, but will save it to your local machine under the name \c{newname.dat}. -To fetch an entire directory \i{recursive}ly, you can use the \c{-r} +To fetch an entire directory \i{recursive}ly, you can use the \c{\-r} option: \c get -r mydir \c get -r mydir newname (If you want to fetch a file whose name starts with a hyphen, you -may have to use the \c{--} special argument, which stops \c{get} +may have to use the \c{\-\-} special argument, which stops \c{get} from interpreting anything as a switch after it. For example, -\cq{get -- -silly-name-}.) +\cq{get \-\- \-silly\-name\-}.) \S{psftp-cmd-put} The \c{put} command: send a file to the server @@ -345,16 +345,16 @@ specify the remote file name after the local one: This will send the local file called \c{myfile.dat}, but will store it on the server under the name \c{newname.dat}. -To send an entire directory \i{recursive}ly, you can use the \c{-r} +To send an entire directory \i{recursive}ly, you can use the \c{\-r} option: \c put -r mydir \c put -r mydir newname (If you want to send a file whose name starts with a hyphen, you may -have to use the \c{--} special argument, which stops \c{put} from -interpreting anything as a switch after it. For example, \cq{put -- --silly-name-}.) +have to use the \c{\-\-} special argument, which stops \c{put} from +interpreting anything as a switch after it. For example, \cq{put \-\- +\-silly\-name\-}.) \S{psftp-cmd-mgetput} The \c{mget} and \c{mput} commands: fetch or send multiple files @@ -374,7 +374,7 @@ that, and a second argument will be treated as an alternative name under which to store the retrieved file), or a \i{wildcard} expression matching more than one file. -The \c{-r} and \c{--} options from \c{get} are also available with +The \c{\-r} and \c{\-\-} options from \c{get} are also available with \c{mget}. \c{mput} is similar to \c{put}, with the same differences. @@ -399,7 +399,7 @@ syntax of \c{get} and \c{put}: These commands are intended mainly for resuming interrupted transfers. They assume that the remote file or directory structure has not changed in any way; if there have been changes, you may end up with -corrupted files. In particular, the \c{-r} option will not pick up +corrupted files. In particular, the \c{\-r} option will not pick up changes to files or directories already transferred in full. \S{psftp-cmd-dir} The \c{dir} command: \I{listing files}list remote files @@ -447,7 +447,7 @@ owning user), \c{g} (members of the owning group), or \c{o} (everybody else - \q{others}), or some combination of those. It can also be \c{a} (\q{all}) to affect everybody at once. -\b A \c{+} or \c{-} sign, indicating whether permissions are to be +\b A \c{+} or \c{\-} sign, indicating whether permissions are to be added or removed. \b The actual permissions being added or removed. These can be @@ -459,7 +459,7 @@ directory). So the above examples would do: -\b The first example: \c{go-rwx} removes read, write and execute +\b The first example: \c{go\-rwx} removes read, write and execute permissions for members of the owning group and everybody else (so the only permissions left are the ones for the file owner). \c{u+w} adds write permission for the file owner. @@ -470,17 +470,17 @@ all files and directories starting with \q{public}. In addition to all this, there are a few extra special cases for \i{Unix} systems. On non-Unix systems these are unlikely to be useful: -\b You can specify \c{u+s} and \c{u-s} to add or remove the Unix +\b You can specify \c{u+s} and \c{u\-s} to add or remove the Unix \i{set-user-ID bit}. This is typically only useful for special purposes; refer to your Unix documentation if you're not sure about it. -\b You can specify \c{g+s} and \c{g-s} to add or remove the Unix +\b You can specify \c{g+s} and \c{g\-s} to add or remove the Unix \i{set-group-ID bit}. On a file, this works similarly to the set-user-ID bit (see your Unix documentation again); on a directory it ensures that files created in the directory are accessible by members of the group that owns the directory. -\b You can specify \c{+t} and \c{-t} to add or remove the Unix +\b You can specify \c{+t} and \c{\-t} to add or remove the Unix \q{\i{sticky bit}}. When applied to a directory, this means that the owner of a file in that directory can delete the file (whereas normally only the owner of the \e{directory} would be allowed to). @@ -585,7 +585,7 @@ hostname: type \c{psftp sessionname}, where \c{sessionname} is replaced by the name of your saved session. Secondly, you can supply the name of a private key file on the command -line, with the \c{-i} option. See \k{using-cmdline-identity} for more +line, with the \c{\-i} option. See \k{using-cmdline-identity} for more information. Thirdly, PSFTP will attempt to authenticate using Pageant if Pageant diff --git a/doc/pubkey.but b/doc/pubkey.but index c421cedb..cdba9f8d 100644 --- a/doc/pubkey.but +++ b/doc/pubkey.but @@ -655,7 +655,7 @@ three ways: \b Select the private key in PuTTY's configuration. See \k{config-ssh-privkey} for details. -\b Specify the key file on the command line with the \c{-i} option. +\b Specify the key file on the command line with the \c{\-i} option. See \k{using-cmdline-identity} for details. \b Load the private key into Pageant (see \k{pageant}). In this case diff --git a/doc/udp.but b/doc/udp.but index 12b3392b..e8750396 100644 --- a/doc/udp.but +++ b/doc/udp.but @@ -51,7 +51,7 @@ The exceptions to that rule are due to the need for Visual Studio compatibility: \b Don't use variable-length arrays. Visual Studio doesn't support -them even now that it's adopted the rest of C99. We use \cw{-Wvla} +them even now that it's adopted the rest of C99. We use \cw{\-Wvla} when building with gcc and clang, to make it easier to avoid accidentally breaking that rule. diff --git a/doc/using.but b/doc/using.but index 96f5f2a7..2a49ab3f 100644 --- a/doc/using.but +++ b/doc/using.but @@ -646,7 +646,7 @@ window}, or a \i{Windows shortcut}). \S{using-cmdline-session} Starting a session from the command line -\I\c{-ssh}\I\c{-ssh-connection}\I\c{-telnet}\I\c{-rlogin}\I\c{-supdup}\I\c{-raw}\I\c{-serial}These +\I\c{\-ssh}\I\c{\-ssh\-connection}\I\c{\-telnet}\I\c{\-rlogin}\I\c{\-supdup}\I\c{\-raw}\I\c{\-serial}These options allow you to bypass the configuration window and launch straight into a session. @@ -670,20 +670,20 @@ To start a connection to a serial port, e.g. COM1: \c putty.exe -serial com1 In order to start an existing saved session called \c{sessionname}, -use the \c{-load} option (described in \k{using-cmdline-load}). +use the \c{\-load} option (described in \k{using-cmdline-load}). \c putty.exe -load "session name" -\S{using-cleanup} \i\c{-cleanup} +\S{using-cleanup} \i\c{\-cleanup} -If invoked with the \c{-cleanup} option, rather than running as +If invoked with the \c{\-cleanup} option, rather than running as normal, PuTTY will remove its \I{removing registry entries}registry entries and \i{random seed file} from the local machine (after confirming with the user). It will also attempt to remove information about recently launched sessions stored in the \q{jump list} on Windows 7 and up. -Note that on \i{multi-user systems}, \c{-cleanup} only removes +Note that on \i{multi-user systems}, \c{\-cleanup} only removes registry entries and files associated with the currently logged-in user. @@ -695,9 +695,9 @@ section lists the available options in all tools. Options which are specific to a particular tool are covered in the chapter about that tool. -\S2{using-cmdline-load} \i\c{-load}: load a saved session +\S2{using-cmdline-load} \i\c{\-load}: load a saved session -\I{saved sessions, loading from command line}The \c{-load} option +\I{saved sessions, loading from command line}The \c{\-load} option causes PuTTY to load configuration details out of a saved session. If these details include a host name, then this option is all you need to make PuTTY start a session. @@ -712,33 +712,33 @@ call something like (Note that PuTTY itself supports an alternative form of this option, for backwards compatibility. If you execute \i\c{putty @sessionname} -it will have the same effect as \c{putty -load "sessionname"}. With +it will have the same effect as \c{putty \-load "sessionname"}. With the \c{@} form, no double quotes are required, and the \c{@} sign must be the very first thing on the command line. This form of the option is deprecated.) -\S2{using-cmdline-protocol} Selecting a protocol: \c{-ssh}, -\c{-ssh-connection}, \c{-telnet}, \c{-rlogin}, \c{-supdup}, -\c{-raw}, \c{-serial} +\S2{using-cmdline-protocol} Selecting a protocol: \c{\-ssh}, +\c{\-ssh\-connection}, \c{\-telnet}, \c{\-rlogin}, \c{\-supdup}, +\c{\-raw}, \c{\-serial} To choose which protocol you want to connect with, you can use one of these options: -\b \i\c{-ssh} selects the SSH protocol. +\b \i\c{\-ssh} selects the SSH protocol. -\b \i\c{-ssh-connection} selects the bare ssh-connection protocol. +\b \i\c{\-ssh\-connection} selects the bare ssh-connection protocol. (This is only useful in specialised circumstances; see \k{config-psusan} for more information.) -\b \i\c{-telnet} selects the Telnet protocol. +\b \i\c{\-telnet} selects the Telnet protocol. -\b \i\c{-rlogin} selects the Rlogin protocol. +\b \i\c{\-rlogin} selects the Rlogin protocol. -\b \i\c{-supdup} selects the SUPDUP protocol. +\b \i\c{\-supdup} selects the SUPDUP protocol. -\b \i\c{-raw} selects the raw protocol. +\b \i\c{\-raw} selects the raw protocol. -\b \i\c{-serial} selects a serial connection. +\b \i\c{\-serial} selects a serial connection. Most of these options are not available in the file transfer tools PSCP and PSFTP (which only work with the SSH protocol and the bare @@ -748,26 +748,26 @@ These options are equivalent to the \i{protocol selection} buttons in the Session panel of the PuTTY configuration box (see \k{config-hostname}). -\S2{using-cmdline-v} \i\c{-v}: increase verbosity +\S2{using-cmdline-v} \i\c{\-v}: increase verbosity \I{verbose mode}Most of the PuTTY tools can be made to tell you more -about what they are doing by supplying the \c{-v} option. If you are +about what they are doing by supplying the \c{\-v} option. If you are having trouble when making a connection, or you're simply curious, you can turn this switch on and hope to find out more about what is happening. -\S2{using-cmdline-l} \i\c{-l}: specify a \i{login name} +\S2{using-cmdline-l} \i\c{\-l}: specify a \i{login name} You can specify the user name to log in as on the remote server -using the \c{-l} option. For example, \c{plink login.example.com -l +using the \c{\-l} option. For example, \c{plink login.example.com \-l fred}. These options are equivalent to the username selection box in the Connection panel of the PuTTY configuration box (see \k{config-username}). -\S2{using-cmdline-portfwd} \I{-L-upper}\c{-L}, \I{-R-upper}\c{-R} -and \I{-D-upper}\c{-D}: set up \i{port forwardings} +\S2{using-cmdline-portfwd} \I{-L-upper}\c{\-L}, \I{-R-upper}\c{\-R} +and \I{-D-upper}\c{\-D}: set up \i{port forwardings} As well as setting up port forwardings in the PuTTY configuration (see \k{config-ssh-portfwd}), you can also set up forwardings on the @@ -782,7 +782,7 @@ can write something like one of these: \c plink mysession -L 5110:popserver.example.com:110 To forward a \I{remote port forwarding}remote port to a local -destination, just use the \c{-R} option instead of \c{-L}: +destination, just use the \c{\-R} option instead of \c{\-L}: \c putty -R 5023:mytelnetserver.myhouse.org:23 -load mysession \c plink mysession -R 5023:mytelnetserver.myhouse.org:23 @@ -793,7 +793,7 @@ tunnel, prepend it to the argument: \c plink -L 127.0.0.5:23:localhost:23 myhost To set up \I{dynamic port forwarding}SOCKS-based dynamic port -forwarding on a local port, use the \c{-D} option. For this one you +forwarding on a local port, use the \c{\-D} option. For this one you only have to pass the port number: \c putty -D 4096 -load mysession @@ -804,12 +804,12 @@ For general information on port forwarding, see These options are not available in the file transfer tools PSCP and PSFTP. -\S2{using-cmdline-m} \i\c{-m}: \I{reading commands from a file}read +\S2{using-cmdline-m} \i\c{\-m}: \I{reading commands from a file}read a remote command or script from a file -The \i\c{-m} option performs a similar function to the \q{\ii{Remote +The \i\c{\-m} option performs a similar function to the \q{\ii{Remote command}} box in the SSH panel of the PuTTY configuration box (see -\k{config-command}). However, the \c{-m} option expects to be given +\k{config-command}). However, the \c{\-m} option expects to be given a local file name, and it will read a command from that file. With some servers (particularly Unix systems), you can even put @@ -822,9 +822,9 @@ routers. This option is not available in the file transfer tools PSCP and PSFTP. -\S2{using-cmdline-p} \I{-P-upper}\c{-P}: specify a \i{port number} +\S2{using-cmdline-p} \I{-P-upper}\c{\-P}: specify a \i{port number} -The \c{-P} option is used to specify the port number to connect to. If +The \c{\-P} option is used to specify the port number to connect to. If you have a Telnet server running on port 9696 of a machine instead of port 23, for example: @@ -838,29 +838,29 @@ any case.) This option is equivalent to the port number control in the Session panel of the PuTTY configuration box (see \k{config-hostname}). -\S2{using-cmdline-pw} \i\c{-pwfile} and \i\c{-pw}: specify a \i{password} +\S2{using-cmdline-pw} \i\c{\-pwfile} and \i\c{\-pw}: specify a \i{password} A simple way to automate a remote login is to supply your password on the command line. -The \c{-pwfile} option takes a file name as an argument. The first +The \c{\-pwfile} option takes a file name as an argument. The first line of text in that file will be used as your password. -The \c{-pw} option takes the password itself as an argument. This is +The \c{\-pw} option takes the password itself as an argument. This is \s{NOT SECURE} if anybody else uses the same computer, because the whole command line (including the password) is likely to show up if -another user lists the running processes. \c{-pw} is retained for -backwards compatibility only; you should use \c{-pwfile} instead. +another user lists the running processes. \c{\-pw} is retained for +backwards compatibility only; you should use \c{\-pwfile} instead. Note that these options only work when you are using the SSH protocol. Due to fundamental limitations of Telnet, Rlogin, and SUPDUP, these protocols do not support automated password authentication. -\S2{using-cmdline-agentauth} \i\c{-agent} and \i\c{-noagent}: +\S2{using-cmdline-agentauth} \i\c{\-agent} and \i\c{\-noagent}: control use of Pageant for authentication -The \c{-agent} option turns on SSH authentication using Pageant, and -\c{-noagent} turns it off. These options are only meaningful if you +The \c{\-agent} option turns on SSH authentication using Pageant, and +\c{\-noagent} turns it off. These options are only meaningful if you are using SSH. See \k{pageant} for general information on \i{Pageant}. @@ -869,10 +869,10 @@ These options are equivalent to the agent authentication checkbox in the Auth panel of the PuTTY configuration box (see \k{config-ssh-tryagent}). -\S2{using-cmdline-agent} \I{-A-upper}\c{-A} and \i\c{-a}: control \i{agent +\S2{using-cmdline-agent} \I{-A-upper}\c{\-A} and \i\c{\-a}: control \i{agent forwarding} -The \c{-A} option turns on SSH agent forwarding, and \c{-a} turns it +The \c{\-A} option turns on SSH agent forwarding, and \c{\-a} turns it off. These options are only meaningful if you are using SSH. See \k{pageant} for general information on \i{Pageant}, and @@ -886,10 +886,10 @@ Auth panel of the PuTTY configuration box (see \k{config-ssh-agentfwd}). These options are not available in the file transfer tools PSCP and PSFTP. -\S2{using-cmdline-x11} \I{-X-upper}\c{-X} and \i\c{-x}: control \i{X11 +\S2{using-cmdline-x11} \I{-X-upper}\c{\-X} and \i\c{\-x}: control \i{X11 forwarding} -The \c{-X} option turns on X11 forwarding in SSH, and \c{-x} turns +The \c{\-X} option turns on X11 forwarding in SSH, and \c{\-x} turns it off. These options are only meaningful if you are using SSH. For information on X11 forwarding, see \k{using-x-forwarding}. @@ -900,11 +900,11 @@ X11 panel of the PuTTY configuration box (see \k{config-ssh-x11}). These options are not available in the file transfer tools PSCP and PSFTP. -\S2{using-cmdline-pty} \i\c{-t} and \I{-T-upper}\c{-T}: control +\S2{using-cmdline-pty} \i\c{\-t} and \I{-T-upper}\c{\-T}: control \i{pseudo-terminal allocation} -The \c{-t} option ensures PuTTY attempts to allocate a -pseudo-terminal at the server, and \c{-T} stops it from allocating +The \c{\-t} option ensures PuTTY attempts to allocate a +pseudo-terminal at the server, and \c{\-T} stops it from allocating one. These options are only meaningful if you are using SSH. These options are equivalent to the \q{Don't allocate a @@ -914,10 +914,10 @@ configuration box (see \k{config-ssh-pty}). These options are not available in the file transfer tools PSCP and PSFTP. -\S2{using-cmdline-noshell} \I{-N-upper}\c{-N}: suppress starting a +\S2{using-cmdline-noshell} \I{-N-upper}\c{\-N}: suppress starting a \I{suppressing remote shell}shell or command -The \c{-N} option prevents PuTTY from attempting to start a shell or +The \c{\-N} option prevents PuTTY from attempting to start a shell or command on the remote server. You might want to use this option if you are only using the SSH connection for port forwarding, and your user account on the server does not have the ability to run a shell. @@ -932,16 +932,16 @@ at all} checkbox in the SSH panel of the PuTTY configuration box This option is not available in the file transfer tools PSCP and PSFTP. -\S2{using-cmdline-ncmode} \I{-nc}\c{-nc}: make a \i{remote network +\S2{using-cmdline-ncmode} \i\c{\-nc}: make a \i{remote network connection} in place of a remote shell or command -The \c{-nc} option prevents Plink (or PuTTY) from attempting to +The \c{\-nc} option prevents Plink (or PuTTY) from attempting to start a shell or command on the remote server. Instead, it will instruct the remote server to open a network connection to a host name and port number specified by you, and treat that network connection as if it were the main session. -You specify a host and port as an argument to the \c{-nc} option, +You specify a host and port as an argument to the \c{\-nc} option, with a colon separating the host name from the port number, like this: @@ -965,41 +965,41 @@ This feature is only available in SSH protocol version 2 (since the version 1 protocol assumes you will always want to run a shell). It is not available in the file transfer tools PSCP and PSFTP. It is available in PuTTY itself, although it is unlikely to be very useful -in any tool other than Plink. Also, \c{-nc} uses the same server +in any tool other than Plink. Also, \c{\-nc} uses the same server functionality as port forwarding, so it will not work if your server administrator has disabled port forwarding. -(The option is named \c{-nc} after the Unix program +(The option is named \c{\-nc} after the Unix program \W{https://en.wikipedia.org/wiki/Netcat}\c{nc}, short for \q{netcat}. The command \cq{plink host1 -nc host2:port} is very similar in functionality to \cq{plink host1 nc host2 port}, which invokes \c{nc} on the server and tells it to connect to the specified -destination. However, Plink's built-in \c{-nc} option does not +destination. However, Plink's built-in \c{\-nc} option does not depend on the \c{nc} program being installed on the server.) -\S2{using-cmdline-compress} \I{-C-upper}\c{-C}: enable \i{compression} +\S2{using-cmdline-compress} \I{-C-upper}\c{\-C}: enable \i{compression} -The \c{-C} option enables compression of the data sent across the +The \c{\-C} option enables compression of the data sent across the network. This option is only meaningful if you are using SSH. This option is equivalent to the \q{Enable compression} checkbox in the SSH panel of the PuTTY configuration box (see \k{config-ssh-comp}). -\S2{using-cmdline-sshprot} \i\c{-1} and \i\c{-2}: specify an \i{SSH +\S2{using-cmdline-sshprot} \i\c{\-1} and \i\c{\-2}: specify an \i{SSH protocol version} -The \c{-1} and \c{-2} options force PuTTY to use version \I{SSH-1}1 +The \c{\-1} and \c{\-2} options force PuTTY to use version \I{SSH-1}1 or version \I{SSH-2}2 of the SSH protocol. These options are only meaningful if you are using SSH. These options are equivalent to selecting the SSH protocol version in the SSH panel of the PuTTY configuration box (see \k{config-ssh-prot}). -\S2{using-cmdline-ipversion} \i\c{-4} and \i\c{-6}: specify an +\S2{using-cmdline-ipversion} \i\c{\-4} and \i\c{\-6}: specify an \i{Internet protocol version} -The \c{-4} and \c{-6} options force PuTTY to use the older Internet +The \c{\-4} and \c{\-6} options force PuTTY to use the older Internet protocol \i{IPv4} or the newer \i{IPv6} for most outgoing connections. @@ -1007,9 +1007,9 @@ These options are equivalent to selecting your preferred Internet protocol version as \q{IPv4} or \q{IPv6} in the Connection panel of the PuTTY configuration box (see \k{config-address-family}). -\S2{using-cmdline-identity} \i\c{-i}: specify an SSH \i{private key} +\S2{using-cmdline-identity} \i\c{\-i}: specify an SSH \i{private key} -The \c{-i} option allows you to specify the name of a private key +The \c{\-i} option allows you to specify the name of a private key file in \c{*.\i{PPK}} format which PuTTY will use to authenticate with the server. This option is only meaningful if you are using SSH. @@ -1024,9 +1024,9 @@ This option is equivalent to the \q{Private key file for authentication} box in the Auth panel of the PuTTY configuration box (see \k{config-ssh-privkey}). -\S2{using-cmdline-cert} \i\c{-cert}: specify an SSH \i{certificate} +\S2{using-cmdline-cert} \i\c{\-cert}: specify an SSH \i{certificate} -The \c{-cert} option allows you to specify the name of a certificate +The \c{\-cert} option allows you to specify the name of a certificate file containing a signed version of your public key. If you specify this option, PuTTY will present that certificate in place of the plain public key, whenever it tries to authenticate with a key that matches. @@ -1037,7 +1037,7 @@ This option is equivalent to the \q{Certificate to use with the private key} box in the Auth panel of the PuTTY configuration box (see \k{config-ssh-cert}). -\S2{using-cmdline-no-trivial-auth} \i\c{-no-trivial-auth}: disconnect +\S2{using-cmdline-no-trivial-auth} \i\c{\-no\-trivial\-auth}: disconnect if SSH authentication succeeds trivially This option causes PuTTY to abandon an SSH session if the server @@ -1046,7 +1046,7 @@ password or signature or token. See \k{config-ssh-notrivialauth} for why you might want this. -\S2{using-cmdline-loghost} \i\c{-loghost}: specify a \i{logical host +\S2{using-cmdline-loghost} \i\c{\-loghost}: specify a \i{logical host name} This option overrides PuTTY's normal SSH \I{host key cache}host key @@ -1056,7 +1056,7 @@ PuTTY thinks it's connecting to). It can be a plain host name, or a host name followed by a colon and a port number. See \k{config-loghost} for more detail on this. -\S2{using-cmdline-hostkey} \i\c{-hostkey}: \I{manually configuring +\S2{using-cmdline-hostkey} \i\c{\-hostkey}: \I{manually configuring host keys}manually specify an expected host key This option overrides PuTTY's normal SSH \I{host key cache}host key @@ -1069,13 +1069,13 @@ fingerprint, or an SSH-2 public key blob. See You can specify this option more than once if you want to configure more than one key to be accepted. -\S2{using-cmdline-pgpfp} \i\c{-pgpfp}: display \i{PGP key fingerprint}s +\S2{using-cmdline-pgpfp} \i\c{\-pgpfp}: display \i{PGP key fingerprint}s This option causes the PuTTY tools not to run as normal, but instead to display the fingerprints of the PuTTY PGP Master Keys, in order to aid with \i{verifying new versions}. See \k{pgpkeys} for more information. -\S2{using-cmdline-sercfg} \i\c{-sercfg}: specify serial port +\S2{using-cmdline-sercfg} \i\c{\-sercfg}: specify serial port \i{configuration} This option specifies the configuration parameters for the serial @@ -1096,27 +1096,27 @@ follows: none, \cq{X} for XON/XOFF, \cq{R} for RTS/CTS and \cq{D} for DSR/DTR. -For example, \cq{-sercfg 19200,8,n,1,N} denotes a baud rate of +For example, \cq{\-sercfg 19200,8,n,1,N} denotes a baud rate of 19200, 8 data bits, no parity, 1 stop bit and no flow control. -\S2{using-cmdline-sshlog} \i\c{-sessionlog}, \i\c{-sshlog}, -\i\c{-sshrawlog}: enable session logging +\S2{using-cmdline-sshlog} \i\c{\-sessionlog}, \i\c{\-sshlog}, +\i\c{\-sshrawlog}: enable session logging These options cause the PuTTY network tools to write out a \i{log file}. Each of them expects a file name as an argument, e.g. -\cq{-sshlog putty.log} causes an SSH packet log to be written to a +\cq{\-sshlog putty.log} causes an SSH packet log to be written to a file called \cq{putty.log}. The three different options select different logging modes, all available from the GUI too: -\b \c{-sessionlog} selects \q{All session output} logging mode. +\b \c{\-sessionlog} selects \q{All session output} logging mode. -\b \c{-sshlog} selects \q{SSH packets} logging mode. +\b \c{\-sshlog} selects \q{SSH packets} logging mode. -\b \c{-sshrawlog} selects \q{SSH packets and raw data} logging mode. +\b \c{\-sshrawlog} selects \q{SSH packets and raw data} logging mode. For more information on logging configuration, see \k{config-logging}. -\S2{using-cmdline-logfileexists} \i\c{-logoverwrite}, \i\c{-logappend}: +\S2{using-cmdline-logfileexists} \i\c{\-logoverwrite}, \i\c{\-logappend}: control behaviour with existing log file If logging has been enabled (in the saved configuration, or by another @@ -1124,7 +1124,7 @@ command-line option), and the specified log file already exists, these options tell the PuTTY network tools what to do so that they don't have to ask the user. See \k{config-logfileexists} for details. -\S2{using-cmdline-proxycmd} \i\c{-proxycmd}: specify a local proxy +\S2{using-cmdline-proxycmd} \i\c{\-proxycmd}: specify a local proxy command This option enables PuTTY's mode for running a \I{Local proxy}command @@ -1157,7 +1157,7 @@ sharing (either as an upstream or a downstream). (This option is only meaningful with the SSH-2 protocol.) -\S2{using-cmdline-restrict-acl} \i\c{-restrict-acl}: restrict the +\S2{using-cmdline-restrict-acl} \i\c{\-restrict\-acl}: restrict the \i{Windows process ACL} This option (on Windows only) causes PuTTY (or another PuTTY tool) to @@ -1178,13 +1178,13 @@ startup and lockdown. So it trades away noticeable convenience, and delivers less real security than you might want. However, if you do want to make that tradeoff anyway, the option is available. -A PuTTY process started with \c{-restrict-acl} will pass that on to +A PuTTY process started with \c{\-restrict\-acl} will pass that on to any processes started with Duplicate Session, New Session etc. (However, if you're invoking PuTTY tools explicitly, for instance as a proxy command, you'll need to arrange to pass them the -\c{-restrict-acl} option yourself, if that's what you want.) +\c{\-restrict\-acl} option yourself, if that's what you want.) -If Pageant is started with the \c{-restrict-acl} option, and you use +If Pageant is started with the \c{\-restrict\-acl} option, and you use it to launch a PuTTY session from its \ii{System Tray} submenu, then Pageant will \e{not} default to starting the PuTTY subprocess with a restricted ACL. This is because PuTTY is more likely to suffer reduced @@ -1194,18 +1194,18 @@ Pageant stores the more critical information (hence benefits more from the extra protection), so it's reasonable to want to run Pageant but not PuTTY with the ACL restrictions. You can force Pageant to start subsidiary PuTTY processes with a restricted ACL if you also pass the -\i\c{-restrict-putty-acl} option. +\i\c{\-restrict\-putty\-acl} option. -\S2{using-cmdline-host-ca} \i{\c{-host-ca}}: launch the +\S2{using-cmdline-host-ca} \i{\c{\-host\-ca}}: launch the \I{certificate}host CA configuration -If you start PuTTY with the \c{-host-ca} option, it will not launch a +If you start PuTTY with the \c{\-host\-ca} option, it will not launch a session at all. Instead, it will just display the configuration dialog box for host certification authorities, as described in \k{config-ssh-kex-cert}. When you dismiss that dialog box, PuTTY will terminate. -\S2{using-cmdline-legacy-stdio-prompts} \i{\c{-legacy-stdio-prompts}}: +\S2{using-cmdline-legacy-stdio-prompts} \i{\c{\-legacy\-stdio\-prompts}}: handle Windows console prompts like older versions of PuTTY This option applies to all of PSCP, PSFTP and Plink on Windows: all @@ -1245,15 +1245,15 @@ more awkward. However, we recognise that people may have customised complicated workflows around the old behaviour. So if you need to switch back to -it, you can do so by specifying \c{-legacy-stdio-prompts} on the +it, you can do so by specifying \c{\-legacy\-stdio\-prompts} on the command-line. To fully revert to the previous behaviour, you'd also need to specify -\c{-legacy-charset-handling} (see the next section). (Even without -that option, prompt handling with \c{-legacy-stdio-prompts} may not be +\c{\-legacy\-charset\-handling} (see the next section). (Even without +that option, prompt handling with \c{\-legacy\-stdio\-prompts} may not be fully Unicode-clean.) -\S2{using-cmdline-legacy-charset-handling} \i{\c{-legacy-charset-handling}}: +\S2{using-cmdline-legacy-charset-handling} \i{\c{\-legacy\-charset\-handling}}: handle character set in prompts like older versions of PuTTY This option applies to PuTTY (on all platforms), and also to all of @@ -1281,7 +1281,7 @@ start sending a different sequence of bytes to the server, denying you access (and you wouldn't even be able to see the difference, since the password is not shown when you type it). -\c{-legacy-charset-handling} reverts the PuTTY tools' behaviour to how +\c{\-legacy\-charset\-handling} reverts the PuTTY tools' behaviour to how it was previously: what you type at these prompts will be interpreted according to the \q{Remote character set} (for PuTTY) or Windows' default character set (for the Windows console tools). From 188d7c9685eb407133c6434090d87727a2fab1bf Mon Sep 17 00:00:00 2001 From: Jacob Nevins Date: Tue, 11 Feb 2025 16:54:44 +0000 Subject: [PATCH 015/129] Docs: consistent indexing of command-line options. We used to have a practice of \IM-ing every command-line option for the index, but haven't kept it up. Add these for all existing indexed command-line options, plus some related tidying. --- doc/index.but | 27 +++++++++++++++++++++++++++ doc/plink.but | 2 +- doc/using.but | 2 +- 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/doc/index.but b/doc/index.but index 226e9a34..41d18a36 100644 --- a/doc/index.but +++ b/doc/index.but @@ -259,11 +259,37 @@ saved sessions from \IM{-N-upper} \c{\-N} command-line option \IM{\-1} \c{\-1} command-line option \IM{\-2} \c{\-2} command-line option +\IM{\-4} \c{\-4} command-line option +\IM{\-6} \c{\-6} command-line option \IM{\-i} \c{\-i} command-line option \IM{\-pgpfp} \c{\-pgpfp} command-line option \IM{\-sercfg} \c{\-sercfg} command-line option \IM{\-share} \c{\-share} command-line option \IM{\-noshare} \c{\-noshare} command-line option +\IM{\-agent} \c{\-agent} command-line option +\IM{\-noagent} \c{\-noagent} command-line option +\IM{\-nc} \c{\-nc} command-line option +\IM{\-restrict\-acl} \c{\-restrict\-acl} command-line option +\IM{\-restrict\-putty\-acl} \c{\-restrict\-putty\-acl} Pageant command-line option +\IM{\-loghost} \c{\-loghost} command-line option +\IM{\-hostkey} \c{\-hostkey} command-line option +\IM{\-sessionlog} \c{\-sessionlog} command-line option +\IM{\-sshlog} \c{\-sshlog} command-line option +\IM{\-sshrawlog} \c{\-sshrawlog} command-line option +\IM{\-logoverwrite} \c{\-logoverwrite} command-line option +\IM{\-logappend} \c{\-logappend} command-line option +\IM{\-proxycmd} \c{\-proxycmd} command-line option +\IM{\-cert} \c{\-cert} command-line option +\IM{\-no\-trivial\-auth} \c{\-no\-trivial\-auth} command-line option +\IM{\-legacy\-stdio\-prompts} \c{\-legacy\-stdio\-prompts} command-line option +\IM{\-legacy\-charset\-handling} \c{\-legacy\-charset\-handling} command-line option + +\IM{\-host\-ca} \c{\-host\-ca} PuTTY command-line option + +\IM{\-sanitise\-stderr} \c{\-sanitise\-stderr} command-line option +\IM{\-sanitise\-stdout} \c{\-sanitise\-stdout} command-line option +\IM{\-no\-sanitise\-stderr} \c{\-no\-sanitise\-stderr} command-line option +\IM{\-no\-sanitise\-stdout} \c{\-no\-sanitise\-stdout} command-line option \IM{removing registry entries} removing registry entries \IM{removing registry entries} registry entries, removing @@ -824,6 +850,7 @@ saved sessions from \IM{-batch-plink} \c{\-batch} Plink command-line option \IM{-s-plink} \c{\-s} Plink command-line option \IM{-shareexists-plink} \c{\-shareexists} Plink command-line option +\IM{-no-antispoof-plink} \c{\-no\-antispoof} Plink command-line option \IM{subsystem} subsystem, SSH \IM{subsystem} SSH subsystem diff --git a/doc/plink.but b/doc/plink.but index 81e4e5f1..f1ad5f0e 100644 --- a/doc/plink.but +++ b/doc/plink.but @@ -320,7 +320,7 @@ channel. \dd Do not sanitise server data written to Plink's standard output channel. -\S2{plink-option-antispoof} \i{\-no\-antispoof}: turn off authentication spoofing protection prompt +\S2{plink-option-antispoof} \I{-no-antispoof-plink}\c{\-no\-antispoof}: turn off authentication spoofing protection prompt In SSH, some possible server authentication methods require user input (for example, password authentication, or entering a private key diff --git a/doc/using.but b/doc/using.but index 2a49ab3f..b89c6126 100644 --- a/doc/using.but +++ b/doc/using.but @@ -807,7 +807,7 @@ PSFTP. \S2{using-cmdline-m} \i\c{\-m}: \I{reading commands from a file}read a remote command or script from a file -The \i\c{\-m} option performs a similar function to the \q{\ii{Remote +The \c{\-m} option performs a similar function to the \q{\ii{Remote command}} box in the SSH panel of the PuTTY configuration box (see \k{config-command}). However, the \c{\-m} option expects to be given a local file name, and it will read a command from that file. From b205622789770e2b81482c8a79140fb4e834d37c Mon Sep 17 00:00:00 2001 From: Jacob Nevins Date: Tue, 11 Feb 2025 23:48:16 +0000 Subject: [PATCH 016/129] Docs: index some missing command-line options. In PuTTYgen and Pageant. --- doc/index.but | 9 +++++++++ doc/pageant.but | 8 ++++---- doc/pubkey.but | 12 ++++++------ 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/doc/index.but b/doc/index.but index 41d18a36..df2d31d7 100644 --- a/doc/index.but +++ b/doc/index.but @@ -918,8 +918,17 @@ saved sessions from \IM{authentication agent} authentication agent \IM{authentication agent} agent, authentication +\IM{-t-puttygen} \c{\-t} PuTTYgen command-line option +\IM{-b-puttygen} \c{\-b} PuTTYgen command-line option +\IM{--primes-puttygen} \c{\-\-primes} PuTTYgen command-line option +\IM{--strong-rsa-puttygen} \c{\-\-strong\-rsa} PuTTYgen command-line option +\IM{--ppk-param-puttygen} \c{\-\-ppk\-param} PuTTYgen command-line option +\IM{-E-upper-puttygen} \c{\-E} PuTTYgen command-line option + \IM{-c-pageant} \c{\-c} Pageant command-line option \IM{\-\-keylist} \c{\-\-keylist} Pageant command-line option +\IM{\-\-encrypted} \c{\-\-encrypted} Pageant command-line option +\IM{\-\-unix} \c{\-\-unix} Pageant command-line option \IM{\-\-openssh\-config} \c{\-\-openssh\-config} Pageant command-line option \IM{Windows OpenSSH} Windows OpenSSH diff --git a/doc/pageant.but b/doc/pageant.but index cf3a2955..a45270e3 100644 --- a/doc/pageant.but +++ b/doc/pageant.but @@ -167,7 +167,7 @@ passphrases on startup. If Pageant is already running, this syntax loads keys into the existing Pageant. -You can specify the \cq{\-\-encrypted} option to defer decryption of +You can specify the \c{\-\-encrypted} option to defer decryption of these keys; see \k{pageant-deferred-decryption}. \S{pageant-cmdline-command} Making Pageant run another program @@ -238,7 +238,7 @@ original Windows Subsystem for Linux (now known as WSL 1). So if you ask Pageant to listen on one of these, then your WSL 1 processes can talk directly to Pageant. -To configure this, run Pageant with the option \c{\-\-unix}, followed +To configure this, run Pageant with the option \i\c{\-\-unix}, followed with a pathname. Then, in WSL 1, set the environment variable \cw{SSH_AUTH_SOCK} to point at the WSL translation of that pathname. @@ -282,7 +282,7 @@ see \k{using-cmdline-restrict-acl} for why you might want to do this. By default, if Pageant is started with \c{\-restrict\-acl}, it won't pass this to any PuTTY sessions started from its System Tray submenu. -Use \c{\-restrict\-putty\-acl} to change this. (Again, see +Use \i\c{\-restrict\-putty\-acl} to change this. (Again, see \k{using-cmdline-restrict-acl} for details.) \H{pageant-forward} Using \i{agent forwarding} @@ -365,7 +365,7 @@ won't ask for a passphrase. Instead, the key will be listed in the main window with \q{(encrypted)} after it. To start Pageant up in the first place with encrypted keys loaded into -it, you can use the \cq{\-\-encrypted} option on the command line. For +it, you can use the \i\c{\-\-encrypted} option on the command line. For example: \c C:\PuTTY\pageant.exe --encrypted d:\main.ppk diff --git a/doc/pubkey.but b/doc/pubkey.but index cdba9f8d..7ff2ee12 100644 --- a/doc/pubkey.but +++ b/doc/pubkey.but @@ -539,27 +539,27 @@ organisation containing your local standards.) The options supported on the command line are: -\dt \cw{\-t} \e{keytype} +\dt \I{-t-puttygen}\cw{\-t} \e{keytype} \dd Type of key to generate. You can select \c{rsa}, \c{dsa}, \c{ecdsa}, \c{eddsa}, \c{ed25519}, \c{ed448}, or \c{rsa1}. See \k{puttygen-keytype}. -\dt \cw{\-b} \e{bits} +\dt \I{-b-puttygen}\cw{\-b} \e{bits} \dd Size of the key to generate, in bits. See \k{puttygen-strength}. -\dt \cw{\-\-primes} \e{method} +\dt \I{--primes-puttygen}\cw{\-\-primes} \e{method} \dd Method for generating prime numbers. You can select \c{probable}, \c{proven}, and \c{proven-even}. See \k{puttygen-primes}. -\dt \cw{\-\-strong-rsa} +\dt \I{--strong-rsa-puttygen}\cw{\-\-strong-rsa} \dd When generating an RSA key, make sure the prime factors of the key modulus are \q{strong primes}. See \k{puttygen-primes}. -\dt \cw{\-\-ppk-param} \e{key}\cw{=}\e{value}\cw{,}... +\dt \I{--ppk-param-puttygen}\cw{\-\-ppk-param} \e{key}\cw{=}\e{value}\cw{,}... \dd Allows setting all the same details of the PPK save file format described in \k{puttygen-save-params}. @@ -599,7 +599,7 @@ key. } -\dt \cw{\-E} \e{fptype} +\dt \I{-E-upper-puttygen}\cw{\-E} \e{fptype} \dd Algorithm to use when displaying key fingerprints. You can select \c{sha256} or \c{md5}. See \k{puttygen-fingerprint}. From 1c86360a03790c01278988ea400cfd627b69498b Mon Sep 17 00:00:00 2001 From: Jacob Nevins Date: Tue, 11 Feb 2025 23:52:24 +0000 Subject: [PATCH 017/129] Docs: clarify wording about host key staleness. I stumbled over this paragraph on a re-read. --- doc/using.but | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/doc/using.but b/doc/using.but index b89c6126..ec71c21a 100644 --- a/doc/using.but +++ b/doc/using.but @@ -184,14 +184,14 @@ new key). That key will be used for the rest of the current session; it may not actually be used for future sessions, depending on your preferences (see \k{config-ssh-hostkey-order}). -Normally, PuTTY will carry on using a host key it already knows, even -if the server offers key formats that PuTTY would otherwise prefer, -to avoid host key prompts. As a result, if you've been using a server -for some years, you may still be using an older key than a new user -would use, due to server upgrades in the meantime. The SSH protocol -unfortunately does not have organised facilities for host key migration -and rollover, but this allows you to \I{host keys, upgrading}manually -upgrade. +Normally, PuTTY will carry on using a host key it already knows for +new sessions, even if the server starts offering key formats that +PuTTY would otherwise prefer, to avoid host key prompts. As a result, +if you've been using a server for some years, you may still be using +an older type of key than a new user would use, due to server +upgrades in the meantime. The SSH protocol unfortunately does not +have organised facilities for host key migration and rollover, but +this allows you to \I{host keys, upgrading}manually upgrade. } \b \I{Break, SSH special command}Break From 50e360fc7474898b4de0e3533aff50857f2b3289 Mon Sep 17 00:00:00 2001 From: Jacob Nevins Date: Tue, 11 Feb 2025 23:56:56 +0000 Subject: [PATCH 018/129] Docs: belated updates for protocol controls. Some of our words weren't updated when the less-frequently used protocols like 'Raw' were moved to a drop-down. --- doc/using.but | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/doc/using.but b/doc/using.but index ec71c21a..5f6e92d4 100644 --- a/doc/using.but +++ b/doc/using.but @@ -577,10 +577,10 @@ detect or guess whether the service it is talking to is a real Telnet service or not; PuTTY prefers to be told for certain. In order to make a debugging connection to a service of this type, -you simply select the fourth protocol name, \I{\q{Raw} -protocol}\q{Raw}, from the \q{Protocol} buttons in the \q{Session} -configuration panel. (See \k{config-hostname}.) You can then enter a -host name and a port number, and make the connection. +select the \I{\q{Raw} protocol}\q{Raw} option from the +\q{Connection type} controls in the \q{Session} configuration panel +(it's in the drop-down). (See \k{config-hostname}.) You can then enter +a host name and a port number, and make the connection. \H{using-telnet} Connecting using the \i{Telnet} protocol @@ -744,9 +744,9 @@ Most of these options are not available in the file transfer tools PSCP and PSFTP (which only work with the SSH protocol and the bare ssh-connection protocol). -These options are equivalent to the \i{protocol selection} buttons -in the Session panel of the PuTTY configuration box (see -\k{config-hostname}). +These options are equivalent to the \i{protocol selection} controls +(\q{Connection type}) in the Session panel of the PuTTY configuration +box (see \k{config-hostname}). \S2{using-cmdline-v} \i\c{\-v}: increase verbosity From 965057d6d6c9de9fcf506c75b0a2fad22988c72b Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sat, 15 Feb 2025 15:57:53 +0000 Subject: [PATCH 019/129] Change strategy for the Arm instruction setting DIT. Colin Watson reported that a build failure occurred in the AArch64 Debian build of PuTTY 0.83: gcc now defaults to enabling branch protection using AArch64 pointer authentication, if the target architecture version supports it. Debian's base supported architecture does not, but Armv8.4-A does. So when I changed the compile flags for enable_dit.c to add -march=armv8.4-a, it didn't _just_ allow me to write the 'msr dit, %0' instruction in my asm statement; it also unexpectedly turned on pointer authentication in the containing function, which caused a SIGILL when running on a pre-Armv8.4-A CPU, because although the code correctly skipped the instruction that set DIT, it was already inside enable_dit() at that point and couldn't avoid going through the unsupported 'retaa' instruction which tries to check an auth code on the return address. An obvious approach would be to add -mbranch-protection=none to the compile flags for enable_dit.c. Another approach is to leave the _compiler_ flags alone, and change the architecture in the assembler, either via a fiddly -Wa,... option or by putting a .arch directive inside the asm statement. But both have downsides. Turning off branch protection is fine for the Debian build, but has the unwanted side effect of turning it off (in that one function) even in builds targeting a later architecture which _did_ want branch protection. And changing the assembler's architecture risks changing it _down_ instead of up, again perhaps invalidating other instructions generated by the compiler (like if some later security feature is introduced that gcc also wants to turn on by default). So instead I've taken the much simpler approach of not bothering to change the target architecture at all, and instead generating the move into DIT by hardcoding its actual instruction encoding. This meant I also had to force the input value into a specific register, but I don't think that does any harm (not _even_ wasting an extra instruction in codegen). Now we should avoid interfering with any security features the compiler wants to turn on or off: all of that should be independent of the instruction I really wanted. --- crypto/CMakeLists.txt | 11 +++++++++-- crypto/enable_dit.c | 6 +++++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/crypto/CMakeLists.txt b/crypto/CMakeLists.txt index e57bb600..cf2973ad 100644 --- a/crypto/CMakeLists.txt +++ b/crypto/CMakeLists.txt @@ -237,9 +237,16 @@ if(neon) endif() test_compile_with_flags(HAVE_ARM_DIT - GNU_FLAGS -march=armv8.4-a TEST_SOURCE " - int main(void) { asm volatile(\"msr dit, %0\" :: \"r\"(1)); }" + #ifndef __aarch64__ + #error make sure this only even tries to work on AArch64 + #endif + #include + int main(void) { + register uint64_t one asm(\"x8\"); + one = 1; + asm volatile(\".inst 0xd51b42a8\" :: \"r\"(one)); + }" ADD_SOURCES_IF_SUCCESSFUL enable_dit.c) set(HAVE_AES_NI ${HAVE_AES_NI} PARENT_SCOPE) diff --git a/crypto/enable_dit.c b/crypto/enable_dit.c index 7c9ec4b4..65e57078 100644 --- a/crypto/enable_dit.c +++ b/crypto/enable_dit.c @@ -20,5 +20,9 @@ void enable_dit(void) { if (!platform_dit_available()) return; - asm volatile("msr dit, %0" :: "r"(1)); + register uint64_t one asm("x8"); + one = 1; + // This is the binary encoding of "msr dit, x8". You can check via, e.g., + // echo "msr dit,x8" | llvm-mc -triple aarch64 -mattr=+dit -show-encoding + asm volatile(".inst 0xd51b42a8" :: "r"(one)); } From 64712be3cbc4a02bda4a92ca97e8d4f294abbe9a Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Thu, 27 Feb 2025 12:51:18 +0000 Subject: [PATCH 020/129] Non-SSH backends: delay setting trust status to false. A user reported recently that if you connect to a Telnet server via a proxy that requires authentication, and enter the auth details manually in the PuTTY terminal window, then the entire Telnet session is shown with trust sigils to its left. This happens because telnet.c calls seat_set_trust_status(false) as soon as it's called new_connection() to make the Socket. But the interactive proxy authentication dialogue hasn't happened yet, at that point. So the proxy resets the trust status to true and asks for a username and password, and then nothing ever resets it to false, because telnet.c thought it had already done that. The solution is to defer the Telnet backend's change of trust status to when we get the notification that the socket is properly connected, which arrives via plug_log(PLUGLOG_CONNECT_SUCCESS). The same bug occurs in raw.c and supdup.c, but not in rlogin.c, because Rlogin has an initial authentication exchange known to the protocol, and already delays resetting the trust status until after that has concluded. --- otherbackends/raw.c | 6 +++--- otherbackends/supdup.c | 4 +++- otherbackends/telnet.c | 6 +++--- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/otherbackends/raw.c b/otherbackends/raw.c index 9fc5e4c8..01c776e2 100644 --- a/otherbackends/raw.c +++ b/otherbackends/raw.c @@ -47,6 +47,9 @@ static void raw_log(Plug *plug, Socket *s, PlugLogType type, SockAddr *addr, raw->socket_connected = true; if (raw->ldisc) ldisc_check_sendok(raw->ldisc); + + /* No local authentication phase in this protocol */ + seat_set_trust_status(raw->seat, false); } } @@ -210,9 +213,6 @@ static char *raw_init(const BackendVtable *vt, Seat *seat, if ((err = sk_socket_error(raw->s)) != NULL) return dupstr(err); - /* No local authentication phase in this protocol */ - seat_set_trust_status(raw->seat, false); - loghost = conf_get_str(conf, CONF_loghost); if (*loghost) { char *colon; diff --git a/otherbackends/supdup.c b/otherbackends/supdup.c index f9680f30..8f814797 100644 --- a/otherbackends/supdup.c +++ b/otherbackends/supdup.c @@ -570,6 +570,9 @@ static void supdup_log(Plug *plug, Socket *s, PlugLogType type, SockAddr *addr, supdup->socket_connected = true; if (supdup->ldisc) ldisc_check_sendok(supdup->ldisc); + + /* No local authentication phase in this protocol */ + seat_set_trust_status(supdup->seat, false); } } @@ -812,7 +815,6 @@ static char *supdup_init(const BackendVtable *x, Seat *seat, * We next expect a connection message followed by %TDNOP from the server */ supdup->state = CONNECTING; - seat_set_trust_status(supdup->seat, false); /* Make sure the terminal is in UTF-8 mode. */ c_write(supdup, (unsigned char *)utf8, strlen(utf8)); diff --git a/otherbackends/telnet.c b/otherbackends/telnet.c index 2f12722c..7f1e4977 100644 --- a/otherbackends/telnet.c +++ b/otherbackends/telnet.c @@ -615,6 +615,9 @@ static void telnet_log(Plug *plug, Socket *s, PlugLogType type, SockAddr *addr, telnet->socket_connected = true; if (telnet->ldisc) ldisc_check_sendok(telnet->ldisc); + + /* No local authentication phase in this protocol */ + seat_set_trust_status(telnet->seat, false); } } @@ -765,9 +768,6 @@ static char *telnet_init(const BackendVtable *vt, Seat *seat, if ((err = sk_socket_error(telnet->s)) != NULL) return dupstr(err); - /* No local authentication phase in this protocol */ - seat_set_trust_status(telnet->seat, false); - telnet->pinger = pinger_new(telnet->conf, &telnet->backend); /* From 0ea6a31abd2bf7ae910bfd91fc24cdc9b1ec5728 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sat, 8 Mar 2025 11:36:46 +0000 Subject: [PATCH 021/129] icons: gitignore update for SVG files. --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index c663ae25..bdfcf67f 100644 --- a/.gitignore +++ b/.gitignore @@ -97,6 +97,7 @@ Makefile /icons/*.ico /icons/*.icns /icons/*.xpm +/icons/*.svg /icons/*.c /unix/empty.h /unix/plink From 58b0fbfe3a1f60f9c8d575f8d7a593b3a408b571 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sat, 8 Mar 2025 11:36:55 +0000 Subject: [PATCH 022/129] icons: HTML preview page. This is a convenient thing to look at in a web browser, via a file:// URL, which lets me see all the icons together and check they match. --- icons/preview.html | 115 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 icons/preview.html diff --git a/icons/preview.html b/icons/preview.html new file mode 100644 index 00000000..15e02a09 --- /dev/null +++ b/icons/preview.html @@ -0,0 +1,115 @@ + + + Preview page for the PuTTY icons + + + +

Preview page for the PuTTY icons

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PuTTYPuTTY cfgptermpterm cfgPSCP/PSFTPPageantPuTTYgenInstaller
16px mono
16px colour
32px mono
32px colour
48px mono
48px colour
SVG
+ + + + + + From 308a85f8a295c2ff1678fc390680b12698ea07e9 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sat, 8 Mar 2025 11:47:27 +0000 Subject: [PATCH 023/129] icons: build true-colour installer icons unconditionally. We weren't building _all_ the icons in true-colour mode, because most don't change anyway. The installer ones do, so let's build them. Works better with the preview page. --- icons/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/icons/Makefile b/icons/Makefile index 3e3ea456..ceb90e52 100644 --- a/icons/Makefile +++ b/icons/Makefile @@ -7,7 +7,7 @@ MODE = # override to -it on command line for opaque testing PAMS = $(foreach I,$(ICONS),$(foreach S,$(SIZES),$(I)-$(S).pam)) MONOPAMS = $(foreach I,$(ICONS),$(foreach S,$(SIZES),$(I)-$(S)-mono.pam)) -TRUEPAMS = $(foreach I,$(ICONS),$(foreach S,$(SIZES),$(I)-$(S)-true.pam)) +TRUEPAMS = $(foreach I,puttyins,$(foreach S,$(SIZES),$(I)-$(S)-true.pam)) PNGS = $(patsubst %.pam,%.png,$(PAMS)) MONOPNGS = $(patsubst %.pam,%.png,$(MONOPAMS)) @@ -22,7 +22,7 @@ CICONS = xpmputty.c xpmpucfg.c xpmpterm.c xpmptcfg.c base: icos cicons -all: pngs monopngs base icns svgs # truepngs currently disabled by default +all: pngs monopngs base icns svgs truepngs pngs: $(PNGS) monopngs: $(MONOPNGS) From a3cd2a57248bf7c5b58634d5a9813a050bc5364e Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sat, 8 Mar 2025 11:07:18 +0000 Subject: [PATCH 024/129] SVG icons: fix computer/monitor alignment. It looked nasty that the back corner of the monitor didn't line up exactly with the outline of the system box behind it. Now I choose the y offset between the two components to ensure it does. Also adjusted the monitor's depth so that it fits better with the new alignment. --- icons/mksvg.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/icons/mksvg.py b/icons/mksvg.py index f29ff25b..0ff7d2b7 100755 --- a/icons/mksvg.py +++ b/icons/mksvg.py @@ -276,6 +276,7 @@ def sysbox(size): toret = SVGgroup([background, hl_dark, hl_light, floppy, outline]) toret.props.sysboxheight = height toret.props.borderthickness = 1 # FIXME + toret.props.ytop = max(y for (x,y) in background_coords) return toret def monitor(size): @@ -287,7 +288,7 @@ def monitor(size): botsurround = 2*size sheight = height - surround - botsurround swidth = width - 2*surround - depth = 2*size + depth = 1.6*size highlight = surround/2 shadow = 0.5*size @@ -342,6 +343,7 @@ def monitor(size): # shadow on the top and left. I think that looks very slightly nicer. sbb = (surround+shadow, botsurround, width-surround, height-surround-shadow) toret.props.screencentre = ((sbb[0]+sbb[2])/2, (sbb[1]+sbb[3])/2) + toret.props.ybackcorner = depth return toret def computer(size): @@ -353,7 +355,7 @@ def computer(size): mb = m.bbox() sb = s.bbox() xoff = mb[0] - sb[0] + x - yoff = mb[1] - sb[1] + y + yoff = s.props.ytop - m.props.ybackcorner toret = SVGgroup([s, m], [(0,0), (xoff,yoff)]) toret.props.screencentre = (m.props.screencentre[0]+xoff, m.props.screencentre[1]+yoff) From 0a77b184812a415934821e051fb423c6c59617ca Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sat, 8 Mar 2025 11:19:54 +0000 Subject: [PATCH 025/129] SVG icons: support black-and-white mode. If I'm going to use this as a means of generating bitmap icons at large sizes, I want it to support all the same modes as the existing bitmap script. So this adds a mode to the SVG generator that produces the same black and white colour scheme as the existing monochrome bitmap icons. (Plus, who knows, the black and white SVGs might come in useful for other purposes. Printing as a logo on black-and-white printers springs to mind.) The existing monochrome icons aren't greyscale: all colours are literally either black or white, except for the cardboard box in the installer icon, which is halftoned. Here I've rendered that box as mid-grey. When I convert the rendered SVG output to an actual 1-bit (plus alpha) image, I'll have to redo that halftoning. --- icons/Makefile | 7 ++++- icons/mksvg.py | 72 +++++++++++++++++++++++++++++++--------------- icons/preview.html | 13 ++++++++- 3 files changed, 67 insertions(+), 25 deletions(-) diff --git a/icons/Makefile b/icons/Makefile index ceb90e52..3aa7ef46 100644 --- a/icons/Makefile +++ b/icons/Makefile @@ -14,6 +14,7 @@ MONOPNGS = $(patsubst %.pam,%.png,$(MONOPAMS)) TRUEPNGS = $(patsubst %.pam,%.png,$(TRUEPAMS)) SVGS = $(patsubst %,%.svg,$(ICONS)) +MONOSVGS = $(patsubst %,%-mono.svg,$(ICONS)) ICOS = putty.ico puttygen.ico pscp.ico pageant.ico pageants.ico puttycfg.ico \ puttyins.ico pterm.ico ptermcfg.ico @@ -22,12 +23,13 @@ CICONS = xpmputty.c xpmpucfg.c xpmpterm.c xpmptcfg.c base: icos cicons -all: pngs monopngs base icns svgs truepngs +all: pngs monopngs base icns svgs monosvgs truepngs pngs: $(PNGS) monopngs: $(MONOPNGS) truepngs: $(TRUEPNGS) svgs: $(SVGS) +monosvgs: $(MONOSVGS) icos: $(ICOS) icns: $(ICNS) @@ -52,6 +54,9 @@ $(TRUEPAMS): %.pam: mkicon.py $(SVGS): %.svg: mksvg.py ./mksvg.py $(patsubst %.svg,%_icon,$@) -o $@ +$(MONOSVGS): %.svg: mksvg.py + ./mksvg.py --mode=bw $(patsubst %-mono.svg,%_icon,$@) -o $@ + putty.ico: putty-16.png putty-32.png putty-48.png \ putty-16-mono.png putty-32-mono.png putty-48-mono.png ./icon.pl -4 $(filter-out %-mono.png, $^) -1 $(filter %-mono.png, $^) > $@ diff --git a/icons/mksvg.py b/icons/mksvg.py index 0ff7d2b7..5c6b71d3 100755 --- a/icons/mksvg.py +++ b/icons/mksvg.py @@ -675,9 +675,12 @@ def box(size, wantback): # Three shades of basically acceptable brown, all achieved by # halftoning between two of the Windows-16 colours. I'm quite # pleased that was feasible at all! - dark = halftone(cr, cK) - med = halftone(cr, cy) - light = halftone(cr, cY) + if not is_bw: + dark = halftone(cr, cK) + med = halftone(cr, cy) + light = halftone(cr, cY) + else: + dark = med = light = halftone(cK, cY) # We define our halftoning parity in such a way that the black # pixels along the RHS of the visible part of the box back # match up with the one-pixel black outline around the @@ -864,33 +867,53 @@ def pageant_icon(size): # Test and output functions. -cK = (0x00, 0x00, 0x00, 0xFF) -cr = (0x80, 0x00, 0x00, 0xFF) -cg = (0x00, 0x80, 0x00, 0xFF) -cy = (0x80, 0x80, 0x00, 0xFF) -cb = (0x00, 0x00, 0x80, 0xFF) -cm = (0x80, 0x00, 0x80, 0xFF) -cc = (0x00, 0x80, 0x80, 0xFF) -cP = (0xC0, 0xC0, 0xC0, 0xFF) -cw = (0x80, 0x80, 0x80, 0xFF) -cR = (0xFF, 0x00, 0x00, 0xFF) -cG = (0x00, 0xFF, 0x00, 0xFF) -cY = (0xFF, 0xFF, 0x00, 0xFF) -cB = (0x00, 0x00, 0xFF, 0xFF) -cM = (0xFF, 0x00, 0xFF, 0xFF) -cC = (0x00, 0xFF, 0xFF, 0xFF) -cW = (0xFF, 0xFF, 0xFF, 0xFF) -cD = (0x00, 0x00, 0x00, 0x80) -cT = (0x00, 0x00, 0x00, 0x00) +def setup_colours(mode): + global cK,cr,cg,cy,cb,cm,cc,cP,cw,cR,cG,cY,cB,cM,cC,cW,cD,cT,is_bw + + is_bw = mode == 'bw' + + cK = (0x00, 0x00, 0x00, 0xFF) + cW = (0xFF, 0xFF, 0xFF, 0xFF) + cT = (0x00, 0x00, 0x00, 0x00) + + if mode == 'colour': + cr = (0x80, 0x00, 0x00, 0xFF) + cg = (0x00, 0x80, 0x00, 0xFF) + cy = (0x80, 0x80, 0x00, 0xFF) + cb = (0x00, 0x00, 0x80, 0xFF) + cm = (0x80, 0x00, 0x80, 0xFF) + cc = (0x00, 0x80, 0x80, 0xFF) + cP = (0xC0, 0xC0, 0xC0, 0xFF) + cw = (0x80, 0x80, 0x80, 0xFF) + cR = (0xFF, 0x00, 0x00, 0xFF) + cG = (0x00, 0xFF, 0x00, 0xFF) + cY = (0xFF, 0xFF, 0x00, 0xFF) + cB = (0x00, 0x00, 0xFF, 0xFF) + cM = (0xFF, 0x00, 0xFF, 0xFF) + cC = (0x00, 0xFF, 0xFF, 0xFF) + cD = (0x00, 0x00, 0x00, 0x80) + elif mode == 'bw': + cr=cg=cb=cm=cc=cP=cw=cR=cG=cB=cM=cC=cD = cK + cY=cy = cW + else: + assert False, f"unexpected mode {mode!r}" def greypix(value): value = max(min(value, 1), 0) + if is_bw: + value = 1 if value > 0.3 else 0 return (int(round(0xFF*value)),) * 3 + (0xFF,) def yellowpix(value): value = max(min(value, 1), 0) - return (int(round(0xFF*value)),) * 2 + (0, 0xFF) + if is_bw: + return (int(round(0xFF*value)),) * 3 + (0xFF) + else: + return (int(round(0xFF*value)),) * 2 + (0, 0xFF) def bluepix(value): value = max(min(value, 1), 0) - return (0, 0, int(round(0xFF*value)), 0xFF) + if is_bw: + return (0, 0, 0, 0xFF) + else: + return (0, 0, int(round(0xFF*value)), 0xFF) def dark(value): value = max(min(value, 1), 0) return (0, 0, 0, int(round(0xFF*value))) @@ -928,12 +951,15 @@ def drawicon(func, width, fname): def main(): parser = argparse.ArgumentParser(description='Generate PuTTY SVG icons.') parser.add_argument("icon", help="Which icon to generate.") + parser.add_argument("--mode", choices=('colour', 'bw'), default='colour', + help="Colour mode to generate the icon in.") parser.add_argument("-s", "--size", type=int, default=48, help="Notional pixel size to base the SVG on.") parser.add_argument("-o", "--output", required=True, help="Output file name.") args = parser.parse_args() + setup_colours(args.mode) drawicon(eval(args.icon), args.size, args.output) if __name__ == '__main__': diff --git a/icons/preview.html b/icons/preview.html index 15e02a09..c01eef90 100644 --- a/icons/preview.html +++ b/icons/preview.html @@ -96,7 +96,18 @@

Preview page for the PuTTY icons

- SVG + SVG mono + + + + + + + + + + + SVG colour From feaadd90ea3d8bb0c1cd3202e70269adef16b97e Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sat, 8 Mar 2025 12:03:27 +0000 Subject: [PATCH 026/129] SVG icons: adjust the hat on the Pageant icon. It was a bit far to the right, looking at risk of falling off. Now moved it as far left as it will go without the top right corner of the computer monitor peeking out from behind it. --- icons/mksvg.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/icons/mksvg.py b/icons/mksvg.py index 5c6b71d3..0f29982b 100755 --- a/icons/mksvg.py +++ b/icons/mksvg.py @@ -844,8 +844,8 @@ def pageant_icon(size): # Determine the relative coordinates of the computer and hat. We # do this by first centring one on the other, then adjusting by # hand. - xrel = (cbb[0]+cbb[2]-hbb[0]-hbb[2])/2 + 2*size - yrel = (cbb[1]+cbb[3]-hbb[1]-hbb[3])/2 + 12*size + xrel = (cbb[0]+cbb[2]-hbb[0]-hbb[2])/2 + 0.7*size + yrel = (cbb[1]+cbb[3]-hbb[1]-hbb[3])/2 + 12.5*size both = SVGgroup([c, ht], [(0,0), (xrel,yrel)]) From 24a2ede7732eb7e29232540dee81ebc8f469d568 Mon Sep 17 00:00:00 2001 From: Jacob Nevins Date: Mon, 17 Mar 2025 23:32:38 +0000 Subject: [PATCH 027/129] Docs: mention certificates in faq-hostkeys. --- doc/faq.but | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/faq.but b/doc/faq.but index dca41519..83ad8b9b 100644 --- a/doc/faq.but +++ b/doc/faq.but @@ -171,6 +171,11 @@ we have a script called to convert them to a Windows .REG file, which can be installed ahead of time by double-clicking or using \c{REGEDIT}. +If you just manage and connect to a lot of servers with different host +keys, you could consider using a \q{certification authority}, so that +you only have to configure PuTTY once on each client machine to accept +host keys from any of your servers in future. See \k{config-ssh-kex-cert}. + \S{faq-server}{Question} Will you write an SSH server for the PuTTY suite, to go with the client? From 2b00d599d35ec7a79f407a91bf6d360df65e97e2 Mon Sep 17 00:00:00 2001 From: Johannes Altmanninger Date: Wed, 12 Mar 2025 22:04:38 +0100 Subject: [PATCH 028/129] Parse DCS commands too [ECMA-48] section 8.3.27 specifies the format of Device Control String (DCS) commands which are used for XTGETTCAP and other sequences. We don't parse DCS commands. This causes this command to wrongly output some characters: printf '\033P+q616d\033\\' Fix that by parsing DCS commands just like other OSC-like commands. (Apart from the initial characters, DCS has the same format as OSC.) We also allow 0x07 as sequence terminator which does not seem specified but a lot of people use it with OSC; it's fine because 0x07 is not allowed in the OSC/DCS payload. [ECMA-48]: https://www.ecma-international.org/wp-content/uploads/ECMA-48_2nd_edition_august_1979.pdf --- terminal/terminal.c | 8 +++++--- terminal/terminal.h | 3 ++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/terminal/terminal.c b/terminal/terminal.c index 0c52fc6e..981ff6b3 100644 --- a/terminal/terminal.c +++ b/terminal/terminal.c @@ -3240,7 +3240,7 @@ static void do_osc(Terminal *term) } break; default: - /* APC, SOS and PM are recognised as control sequences but + /* DCS, APC, SOS and PM are recognised as control sequences but * ignored. PuTTY implements no support for any of them. */ break; } @@ -4128,10 +4128,11 @@ static void term_out(Terminal *term, bool called_from_term_data) term->esc_args[0] = 0; term->esc_nargs = 1; break; + case 'P': /* DCS: Device Control String */ case 'X': /* SOS: Start of String */ case '^': /* PM: privacy message */ case '_': /* APC: application program command */ - /* SOS, PM, and APC sequences are just a string, terminated + /* DCS, SOS, PM, and APC sequences are just a string, terminated * by ST or (I've observed in practice for APC) ^G. That * is, they have the same termination convention as OSC. So * we handle them by going straight into OSC_STRING state @@ -4139,7 +4140,8 @@ static void term_out(Terminal *term, bool called_from_term_data) * OSC. */ compatibility(OTHER); term->termstate = SEEN_OSC; - term->osc_type = (c == 'X' ? OSCLIKE_SOS : + term->osc_type = (c == 'P' ? OSCLIKE_DCS : + c == 'X' ? OSCLIKE_SOS : c == '^' ? OSCLIKE_PM : OSCLIKE_APC); term->osc_strlen = 0; term->esc_args[0] = 0; diff --git a/terminal/terminal.h b/terminal/terminal.h index 0e7ab771..02967274 100644 --- a/terminal/terminal.h +++ b/terminal/terminal.h @@ -77,8 +77,9 @@ typedef enum { OSCLIKE_OSC, OSCLIKE_OSC_W, OSCLIKE_APC, - OSCLIKE_SOS, + OSCLIKE_DCS, OSCLIKE_PM, + OSCLIKE_SOS, } OscType; struct terminal_tag { From c229a5e177cf98d8fb82184dccda342b00bf3a29 Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Wed, 26 Mar 2025 23:30:02 +0000 Subject: [PATCH 029/129] Remove residual declaration of term_key() and related constants term_key() itself was removed in 2012, but its relations in putty.h somehow survived. --- putty.h | 43 ------------------------------------------- 1 file changed, 43 deletions(-) diff --git a/putty.h b/putty.h index fdcd6ca3..83d4932d 100644 --- a/putty.h +++ b/putty.h @@ -343,47 +343,6 @@ typedef enum { MA_NOTHING, MA_CLICK, MA_2CLK, MA_3CLK, MA_DRAG, MA_RELEASE, MA_MOVE } Mouse_Action; -/* Keyboard modifiers -- keys the user is actually holding down */ - -#define PKM_SHIFT 0x01 -#define PKM_CONTROL 0x02 -#define PKM_META 0x04 -#define PKM_ALT 0x08 - -/* Keyboard flags that aren't really modifiers */ -#define PKF_CAPSLOCK 0x10 -#define PKF_NUMLOCK 0x20 -#define PKF_REPEAT 0x40 - -/* Stand-alone keysyms for function keys */ - -typedef enum { - PK_NULL, /* No symbol for this key */ - /* Main keypad keys */ - PK_ESCAPE, PK_TAB, PK_BACKSPACE, PK_RETURN, PK_COMPOSE, - /* Editing keys */ - PK_HOME, PK_INSERT, PK_DELETE, PK_END, PK_PAGEUP, PK_PAGEDOWN, - /* Cursor keys */ - PK_UP, PK_DOWN, PK_RIGHT, PK_LEFT, PK_REST, - /* Numeric keypad */ /* Real one looks like: */ - PK_PF1, PK_PF2, PK_PF3, PK_PF4, /* PF1 PF2 PF3 PF4 */ - PK_KPCOMMA, PK_KPMINUS, PK_KPDECIMAL, /* 7 8 9 - */ - PK_KP0, PK_KP1, PK_KP2, PK_KP3, PK_KP4, /* 4 5 6 , */ - PK_KP5, PK_KP6, PK_KP7, PK_KP8, PK_KP9, /* 1 2 3 en- */ - PK_KPBIGPLUS, PK_KPENTER, /* 0 . ter */ - /* Top row */ - PK_F1, PK_F2, PK_F3, PK_F4, PK_F5, - PK_F6, PK_F7, PK_F8, PK_F9, PK_F10, - PK_F11, PK_F12, PK_F13, PK_F14, PK_F15, - PK_F16, PK_F17, PK_F18, PK_F19, PK_F20, - PK_PAUSE -} Key_Sym; - -#define PK_ISEDITING(k) ((k) >= PK_HOME && (k) <= PK_PAGEDOWN) -#define PK_ISCURSOR(k) ((k) >= PK_UP && (k) <= PK_REST) -#define PK_ISKEYPAD(k) ((k) >= PK_PF1 && (k) <= PK_KPENTER) -#define PK_ISFKEY(k) ((k) >= PK_F1 && (k) <= PK_F20) - enum { VT_XWINDOWS, VT_OEMANSI, VT_OEMONLY, VT_POORMAN, VT_UNICODE }; @@ -2057,8 +2016,6 @@ void term_clrsb(Terminal *); void term_mouse(Terminal *, Mouse_Button, Mouse_Button, Mouse_Action, int, int, bool, bool, bool); void term_cancel_selection_drag(Terminal *); -void term_key(Terminal *, Key_Sym, wchar_t *, size_t, unsigned int, - unsigned int); void term_lost_clipboard_ownership(Terminal *, int clipboard); void term_update(Terminal *); void term_invalidate(Terminal *); From e98071dd38a66bddb343dbd6ab4a5a6ef003492b Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Thu, 27 Mar 2025 09:31:06 +0000 Subject: [PATCH 030/129] GTK: tell the input method context about focus changes GtkIMContext has focus_in and focus_out methods for telling it when the corresponding widget gains or loses keyboard focus. It's not obvious to me why these are necessary, but PuTTY now calls them when it sees focus-in and focus-out events for the terminal window. Somehow, this has caused Hangul input to start working in PuTTY. I can't yet see what I'm typing for lack of proper preedit support, though. --- unix/window.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/unix/window.c b/unix/window.c index 7302dc2c..e3b7d61b 100644 --- a/unix/window.c +++ b/unix/window.c @@ -2518,6 +2518,12 @@ void destroy(GtkWidget *widget, gpointer data) gint focus_event(GtkWidget *widget, GdkEventFocus *event, gpointer data) { GtkFrontend *inst = (GtkFrontend *)data; +#if GTK_CHECK_VERSION(2,0,0) + if (event->in) + gtk_im_context_focus_in(inst->imc); + else + gtk_im_context_focus_out(inst->imc); +#endif term_set_focus(inst->term, event->in); term_update(inst->term); show_mouseptr(inst, true); From 5ef7f2eaf0fd75f6681c762c42efe155fe28161e Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Tue, 1 Apr 2025 01:25:43 +0100 Subject: [PATCH 031/129] Correct a comment referring to Contexts, which we no longer have --- terminal/terminal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/terminal/terminal.c b/terminal/terminal.c index 981ff6b3..898b642e 100644 --- a/terminal/terminal.c +++ b/terminal/terminal.c @@ -6026,7 +6026,7 @@ static void do_paint_draw(Terminal *term, termline *ldata, int x, int y, } /* - * Given a context, update the window. + * Update the window. */ static void do_paint(Terminal *term) { From 7f96069954dd3c903256a2ca8ae26ece0a274c51 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Thu, 3 Apr 2025 08:59:39 +0100 Subject: [PATCH 032/129] Use _Countof to implement lenof, where available. Up-to-date trunk clang has introduced a built-in operator called _Countof, which is like the 'lenof' macro in this code (returns the number of elements in a statically-declared array object) but with the safety advantage that it provokes a compile error if you accidentally use it on a pointer. In this commit I add a cmake-time check for it, and conditional on that, switch over the definition of lenof. This should add a safety check for accidental uses of lenof(pointer). When I tested it with new clang, this whole code base compiled cleanly with the new setting, so there aren't currently any such accidents. clang cites C2y as the source for _Countof: WG14 document N3369 initially proposed it under a different name, and then there was a big internet survey about naming (in which of course I voted for lenof!), and document N3469 summarises the results, which show that the name _Countof and/or countof won. Links: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3369.pdf https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3469.htm My reading of N3469 seems to say that there will _either_ be _Countof by itself, _or_ lowercase 'countof' as a new keyword, but they don't say which. They say they _don't_ intend to do the same equivocation we had with _Complex and _Bool, where you have a _Countof keyword and an optional header file defining a lowercase non-underscore macro wrapping it. But there hasn't been a new whole draft published since N3469 yet, so I don't know what will end up in it when there is. However, as of now, _Countof exists in at least one compiler, and that seems like enough reason to implement it here. If it becomes 'countof' in the real standard, then we can always change over later. (And in that case it would probably make sense to rename the macro throughout the code base to align with what will become the new standard usage.) --- charset/internal.h | 8 +++++++- cmake/cmake.h.in | 2 ++ cmake/setup.cmake | 6 ++++++ misc.h | 4 ++++ utils/tree234.c | 8 +++++++- 5 files changed, 26 insertions(+), 2 deletions(-) diff --git a/charset/internal.h b/charset/internal.h index 32d0f6d5..7fd6628f 100644 --- a/charset/internal.h +++ b/charset/internal.h @@ -6,7 +6,13 @@ #define charset_internal_h /* This invariably comes in handy */ -#define lenof(x) ( sizeof((x)) / sizeof(*(x)) ) +#ifndef lenof +#if HAVE_COUNTOF +#define lenof(x) _Countof(x) +#else +#define lenof(x) ( (sizeof((x))) / (sizeof(*(x)))) +#endif +#endif /* This is an invalid Unicode value used to indicate an error. */ #define ERROR 0xFFFFL /* Unicode value representing error */ diff --git a/cmake/cmake.h.in b/cmake/cmake.h.in index 3d36b3d0..3b64d03f 100644 --- a/cmake/cmake.h.in +++ b/cmake/cmake.h.in @@ -5,6 +5,8 @@ #cmakedefine NO_MULTIMON +#cmakedefine01 HAVE_COUNTOF + #cmakedefine01 HAVE_WINRESRC_H #cmakedefine01 HAVE_WINRES_H #cmakedefine01 HAVE_WIN_H diff --git a/cmake/setup.cmake b/cmake/setup.cmake index 1be448df..75af0eac 100644 --- a/cmake/setup.cmake +++ b/cmake/setup.cmake @@ -116,6 +116,12 @@ int main(int argc, char **argv) { free(p); }" HAVE_ALIGNED_ALLOC) +check_c_source_compiles(" +int main(int argc, char **argv) { + int a[3]; + return _Countof(a); +}" HAVE_COUNTOF) + if(PUTTY_DEBUG) add_compile_definitions(DEBUG) endif() diff --git a/misc.h b/misc.h index c64eb01b..67a1833b 100644 --- a/misc.h +++ b/misc.h @@ -353,8 +353,12 @@ const char *conf_id(int key); #endif #ifndef lenof +#if HAVE_COUNTOF +#define lenof(x) _Countof(x) +#else #define lenof(x) ( (sizeof((x))) / (sizeof(*(x)))) #endif +#endif #ifndef min #define min(x,y) ( (x) < (y) ? (x) : (y) ) diff --git a/utils/tree234.c b/utils/tree234.c index 004cfb8d..e7b3d4fc 100644 --- a/utils/tree234.c +++ b/utils/tree234.c @@ -1361,7 +1361,13 @@ int mycmp(void *av, void *bv) return strcmp(a, b); } -#define lenof(x) ( sizeof((x)) / sizeof(*(x)) ) +#ifndef lenof +#if HAVE_COUNTOF +#define lenof(x) _Countof(x) +#else +#define lenof(x) ( (sizeof((x))) / (sizeof(*(x)))) +#endif +#endif char *strings[] = { "a", "ab", "absque", "coram", "de", From f2d63388a8dcc18f065f74dbd067f92c5ccc291c Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Thu, 3 Apr 2025 20:08:06 +0100 Subject: [PATCH 033/129] Stop cursor attributes being temporary When telling front ends to paint the screen, the terminal code treats the cursor as an attribute applied to the character cell(s) it appears in. do_paint() detects changes to most such attributes by storing what it last sent to the front end in term->disptext and comparing that with what it thinks should be displayed in the window. However, before this commit the cursor was special. Its last-drawn position was recorded in special structure members and invalidated parts of the display based on those. The cursor attributes were treated as "temporary attributes" and were not saved in term->disptext. This commit regularizes this and turns the cursor attributes into normal attributes that are stored in term->disptext. This removes a bunch of special-case code in do_paint() because now the normal update code handles the cursor properly, and also removes some members from the Terminal structure. I hope it will also make future cursor-handling changes (for instance for input method pre-editing) simpler. This commit makes the required semantic changes but doesn't make the rather more pervasive change of actually renaming the attributes from TATTR_ to ATTR_. That will be in the next commit. --- putty.h | 2 +- terminal/terminal.c | 29 +---------------------------- terminal/terminal.h | 2 -- 3 files changed, 2 insertions(+), 31 deletions(-) diff --git a/putty.h b/putty.h index 83d4932d..b6b8518f 100644 --- a/putty.h +++ b/putty.h @@ -215,7 +215,7 @@ extern const int colour_indices_oscp_to_osc4[OSCP_NCOLOURS]; #define DATTR_STARTRUN 0x80000000UL /* start of redraw run */ -#define TDATTR_MASK 0xF0000000UL +#define TDATTR_MASK 0x80000000UL #define TATTR_MASK (TDATTR_MASK) #define DATTR_MASK (TDATTR_MASK) diff --git a/terminal/terminal.c b/terminal/terminal.c index 898b642e..23b9a970 100644 --- a/terminal/terminal.c +++ b/terminal/terminal.c @@ -2066,7 +2066,6 @@ Terminal *term_init(Conf *myconf, struct unicode_data *ucsdata, TermWin *win) term_copy_stuff_from_conf(term); - term->dispcursx = term->dispcursy = -1; deselect(term); term->rows = term->cols = -1; power_on(term, true); @@ -2297,7 +2296,6 @@ void term_size(Terminal *term, int newrows, int newcols, int newsavelines) } sfree(term->disptext); term->disptext = newdisp; - term->dispcursx = term->dispcursy = -1; /* Make a new alternate screen. */ newalt = newtree234(NULL); @@ -6092,27 +6090,6 @@ static void do_paint(Terminal *term) unlineptr(ldata); } - /* - * If the cursor is not where it was last time we painted, and - * its previous position is visible on screen, invalidate its - * previous position. - */ - if (term->dispcursy >= 0 && - (term->curstype != cursor || - term->dispcursy != our_curs_y || - term->dispcursx != our_curs_x)) { - termchar *dispcurs = term->disptext[term->dispcursy]->chars + - term->dispcursx; - - if (term->dispcursx > 0 && dispcurs->chr == UCSWIDE) - dispcurs[-1].attr |= ATTR_INVALID; - if (term->dispcursx < term->cols-1 && dispcurs[1].chr == UCSWIDE) - dispcurs[1].attr |= ATTR_INVALID; - dispcurs->attr |= ATTR_INVALID; - - term->curstype = 0; - } - term->dispcursx = term->dispcursy = -1; /* The normal screen data */ for (i = 0; i < term->rows; i++) { @@ -6220,12 +6197,8 @@ static void do_paint(Terminal *term) } else if (term->disptext[i]->chars[j].attr & ATTR_NARROW) tattr |= ATTR_NARROW; - if (i == our_curs_y && j == our_curs_x) { + if (i == our_curs_y && j == our_curs_x) tattr |= cursor; - term->curstype = cursor; - term->dispcursx = j; - term->dispcursy = i; - } /* FULL-TERMCHAR */ newline[j].attr = tattr; diff --git a/terminal/terminal.h b/terminal/terminal.h index 02967274..df6ba4cc 100644 --- a/terminal/terminal.h +++ b/terminal/terminal.h @@ -95,8 +95,6 @@ struct terminal_tag { ("temporary scrollback") */ termline **disptext; /* buffer of text on real screen */ - int dispcursx, dispcursy; /* location of cursor on real screen */ - int curstype; /* type of cursor on real screen */ #define VBELL_TIMEOUT (TICKSPERSEC/10) /* visual bell lasts 1/10 sec */ From 7a100534d3dbfd4ce06245fee0dcec04cd724a72 Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Thu, 3 Apr 2025 20:50:36 +0100 Subject: [PATCH 034/129] Rename cursor attributes from the TATTR_ to the ATTR_ namespace No functional change. --- putty.h | 28 ++++++++++++++-------------- terminal/terminal.c | 8 ++++---- unix/window.c | 14 +++++++------- windows/window.c | 14 +++++++------- 4 files changed, 32 insertions(+), 32 deletions(-) diff --git a/putty.h b/putty.h index b6b8518f..dbd85298 100644 --- a/putty.h +++ b/putty.h @@ -208,9 +208,6 @@ extern const int colour_indices_oscp_to_osc4[OSCP_NCOLOURS]; * ATTR_INVALID is an illegal colour combination. */ -#define TATTR_ACTCURS 0x40000000UL /* active cursor (block) */ -#define TATTR_PASCURS 0x20000000UL /* passive cursor (box) */ -#define TATTR_RIGHTCURS 0x10000000UL /* cursor-on-RHS */ #define TATTR_COMBINING 0x80000000UL /* combining characters */ #define DATTR_STARTRUN 0x80000000UL /* start of redraw run */ @@ -256,17 +253,20 @@ extern const int colour_indices_oscp_to_osc4[OSCP_NCOLOURS]; */ #define UCSWIDE 0xDFFF -#define ATTR_NARROW 0x0800000U -#define ATTR_WIDE 0x0400000U -#define ATTR_BOLD 0x0040000U -#define ATTR_UNDER 0x0080000U -#define ATTR_REVERSE 0x0100000U -#define ATTR_BLINK 0x0200000U -#define ATTR_FGMASK 0x00001FFU /* stores a colour in OSC 4 indexing */ -#define ATTR_BGMASK 0x003FE00U /* stores a colour in OSC 4 indexing */ -#define ATTR_COLOURS 0x003FFFFU -#define ATTR_DIM 0x1000000U -#define ATTR_STRIKE 0x2000000U +#define ATTR_NARROW 0x00800000U +#define ATTR_WIDE 0x00400000U +#define ATTR_BOLD 0x00040000U +#define ATTR_UNDER 0x00080000U +#define ATTR_REVERSE 0x00100000U +#define ATTR_BLINK 0x00200000U +#define ATTR_FGMASK 0x000001FFU /* stores a colour in OSC 4 indexing */ +#define ATTR_BGMASK 0x0003FE00U /* stores a colour in OSC 4 indexing */ +#define ATTR_COLOURS 0x0003FFFFU +#define ATTR_DIM 0x01000000U +#define ATTR_STRIKE 0x02000000U +#define ATTR_ACTCURS 0x40000000UL /* active cursor (block) */ +#define ATTR_PASCURS 0x20000000UL /* passive cursor (box) */ +#define ATTR_RIGHTCURS 0x10000000UL /* cursor-on-RHS */ #define ATTR_FGSHIFT 0 #define ATTR_BGSHIFT 9 diff --git a/terminal/terminal.c b/terminal/terminal.c index 23b9a970..4d1d4f5b 100644 --- a/terminal/terminal.c +++ b/terminal/terminal.c @@ -6017,7 +6017,7 @@ static void do_paint_draw(Terminal *term, termline *ldata, int x, int y, IS_REGIONAL_INDICATOR_LETTER(ch[1])) attr |= ATTR_WIDE | TATTR_COMBINING; win_draw_text(term->win, x, y, ch, ccount, attr, ldata->lattr, tc); - if (attr & (TATTR_ACTCURS | TATTR_PASCURS)) + if (attr & (ATTR_ACTCURS | ATTR_PASCURS)) win_draw_cursor(term->win, x, y, ch, ccount, attr, ldata->lattr, tc); } @@ -6053,13 +6053,13 @@ static void do_paint(Terminal *term) if (term->cursor_on) { if (term->has_focus) { if (term->cblinker || !term->blink_cur) - cursor = TATTR_ACTCURS; + cursor = ATTR_ACTCURS; else cursor = 0; } else - cursor = TATTR_PASCURS; + cursor = ATTR_PASCURS; if (term->wrapnext) - cursor |= TATTR_RIGHTCURS; + cursor |= ATTR_RIGHTCURS; } else cursor = 0; our_curs_y = term->curs.y - term->disptop; diff --git a/unix/window.c b/unix/window.c index e3b7d61b..a172c1c4 100644 --- a/unix/window.c +++ b/unix/window.c @@ -3886,7 +3886,7 @@ static void do_text_internal( nfg = ((monochrome ? ATTR_DEFFG : (attr & ATTR_FGMASK)) >> ATTR_FGSHIFT); nbg = ((monochrome ? ATTR_DEFBG : (attr & ATTR_BGMASK)) >> ATTR_BGSHIFT); - if (!!(attr & ATTR_REVERSE) ^ (monochrome && (attr & TATTR_ACTCURS))) { + if (!!(attr & ATTR_REVERSE) ^ (monochrome && (attr & ATTR_ACTCURS))) { struct optionalrgb trgb; t = nfg; @@ -3905,7 +3905,7 @@ static void do_text_internal( if (nbg < 16) nbg |= 8; else if (nbg >= 256) nbg |= 1; } - if ((attr & TATTR_ACTCURS) && !monochrome) { + if ((attr & ATTR_ACTCURS) && !monochrome) { truecolour.fg = truecolour.bg = optionalrgb_none; nfg = 260; nbg = 261; @@ -4071,13 +4071,13 @@ static void gtkwin_draw_cursor( bool active, passive; int widefactor; - if (attr & TATTR_PASCURS) { - attr &= ~TATTR_PASCURS; + if (attr & ATTR_PASCURS) { + attr &= ~ATTR_PASCURS; passive = true; } else passive = false; - if ((attr & TATTR_ACTCURS) && inst->cursor_type != CURSOR_BLOCK) { - attr &= ~TATTR_ACTCURS; + if ((attr & ATTR_ACTCURS) && inst->cursor_type != CURSOR_BLOCK) { + attr &= ~ATTR_ACTCURS; active = true; } else active = false; @@ -4138,7 +4138,7 @@ static void gtkwin_draw_cursor( length = len * widefactor * char_width; } else /* inst->cursor_type == CURSOR_VERTICAL_LINE */ { int xadjust = 0; - if (attr & TATTR_RIGHTCURS) + if (attr & ATTR_RIGHTCURS) xadjust = char_width - 1; startx = x * inst->font_width + inst->window_border + xadjust; starty = y * inst->font_height + inst->window_border; diff --git a/windows/window.c b/windows/window.c index efc028e9..e28ec652 100644 --- a/windows/window.c +++ b/windows/window.c @@ -3571,7 +3571,7 @@ static void do_text_internal( x += wgs->offset_width; y += wgs->offset_height; - if ((attr & TATTR_ACTCURS) && + if ((attr & ATTR_ACTCURS) && (wgs->cursor_type == CURSOR_BLOCK || wgs->term->big_cursor)) { truecolour.fg = truecolour.bg = optionalrgb_none; attr &= ~(ATTR_REVERSE|ATTR_BLINK|ATTR_COLOURS|ATTR_DIM); @@ -3967,14 +3967,14 @@ static void wintw_draw_cursor( lattr &= LATTR_MODE; - if ((attr & TATTR_ACTCURS) && + if ((attr & ATTR_ACTCURS) && (ctype == CURSOR_BLOCK || wgs->term->big_cursor)) { if (*text != UCSWIDE) { win_draw_text(tw, x, y, text, len, attr, lattr, truecolour); return; } ctype = CURSOR_VERTICAL_LINE; - attr |= TATTR_RIGHTCURS; + attr |= ATTR_RIGHTCURS; } fnt_width = char_width = wgs->font_width * (1 + (lattr != LATTR_NORM)); @@ -3985,7 +3985,7 @@ static void wintw_draw_cursor( x += wgs->offset_width; y += wgs->offset_height; - if ((attr & TATTR_PASCURS) && + if ((attr & ATTR_PASCURS) && (ctype == CURSOR_BLOCK || wgs->term->big_cursor)) { POINT pts[5]; HPEN oldpen; @@ -3998,7 +3998,7 @@ static void wintw_draw_cursor( Polyline(wgs->wintw_hdc, pts, 5); oldpen = SelectObject(wgs->wintw_hdc, oldpen); DeleteObject(oldpen); - } else if ((attr & (TATTR_ACTCURS | TATTR_PASCURS)) && + } else if ((attr & (ATTR_ACTCURS | ATTR_PASCURS)) && ctype != CURSOR_BLOCK) { int startx, starty, dx, dy, length, i; if (ctype == CURSOR_UNDERLINE) { @@ -4009,7 +4009,7 @@ static void wintw_draw_cursor( length = char_width; } else /* ctype == CURSOR_VERTICAL_LINE */ { int xadjust = 0; - if (attr & TATTR_RIGHTCURS) + if (attr & ATTR_RIGHTCURS) xadjust = char_width - 1; startx = x + xadjust; starty = y; @@ -4017,7 +4017,7 @@ static void wintw_draw_cursor( dy = 1; length = wgs->font_height; } - if (attr & TATTR_ACTCURS) { + if (attr & ATTR_ACTCURS) { HPEN oldpen; oldpen = SelectObject(wgs->wintw_hdc, From 6332497afb798448a5cd744aa7026822823f201b Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Fri, 4 Apr 2025 23:00:35 +0100 Subject: [PATCH 035/129] test_unicode_norm: fix display of failing tests. There was a bytes / array elements confusion in the code that prints out the input and output Unicode strings when a test fails. It was using a loop with index variable 'pos', which was used as an array index, but incremented by sizeof(a character) each time, leading to only every fourth character actually being printed. I assume this is leftover confusion from when I hadn't quite decided whether to abuse the char-based strbuf for these Unicode character buffers, or make a specialist type. Discovered when I reached for this test program just now in order to manually decompose a Unicode string. It doesn't have a convenient CLI for that, but it was a thing I already knew where to find! --- utils/unicode-norm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/utils/unicode-norm.c b/utils/unicode-norm.c index af620fd3..22f48bd4 100644 --- a/utils/unicode-norm.c +++ b/utils/unicode-norm.c @@ -341,13 +341,13 @@ static void subtest(const char *filename, int lineno, const char *subdesc, pass++; } else { printf("%s:%d: failed %s: NF%c([", filename, lineno, subdesc, nftype); - for (size_t pos = 0; pos < input->len; pos += sizeof(uchar)) + for (size_t pos = 0; pos < input->len; pos++) printf("%s%04X", pos ? " " : "", (unsigned)input->buf[pos]); printf("]) -> ["); - for (size_t pos = 0; pos < nf->len; pos += sizeof(uchar)) + for (size_t pos = 0; pos < nf->len; pos++) printf("%s%04X", pos ? " " : "", (unsigned)nf->buf[pos]); printf("] != ["); - for (size_t pos = 0; pos < expected->len; pos += sizeof(uchar)) + for (size_t pos = 0; pos < expected->len; pos++) printf("%s%04X", pos ? " " : "", (unsigned)expected->buf[pos]); printf("]\n"); fail++; From fbea30bbaf0af1226959a0ba1bb98724e456b129 Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Wed, 26 Mar 2025 20:13:54 +0000 Subject: [PATCH 036/129] GTK: trivially handle preedit signals At present, that just means logging them when KEY_EVENT_DIAGNOSTICS is defined. --- unix/window.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/unix/window.c b/unix/window.c index a172c1c4..6c0752d8 100644 --- a/unix/window.c +++ b/unix/window.c @@ -2117,6 +2117,33 @@ void input_method_commit_event(GtkIMContext *imc, gchar *str, gpointer data) show_mouseptr(inst, false); key_pressed(inst); } + +void input_method_preedit_start_event(GtkIMContext *imc, gpointer data) +{ + GtkFrontend *inst = (GtkFrontend *)data; + +#ifdef KEY_EVENT_DIAGNOSTICS + debug(" - IM preedit-start event\n"); +#endif +} + +void input_method_preedit_changed_event(GtkIMContext *imc, gpointer data) +{ + GtkFrontend *inst = (GtkFrontend *)data; + +#ifdef KEY_EVENT_DIAGNOSTICS + debug(" - IM preedit-changed event\n"); +#endif +} + +void input_method_preedit_end_event(GtkIMContext *imc, gpointer data) +{ + GtkFrontend *inst = (GtkFrontend *)data; + +#ifdef KEY_EVENT_DIAGNOSTICS + debug(" - IM preedit-end event\n"); +#endif +} #endif #define SCROLL_INCREMENT_LINES 5 @@ -5570,6 +5597,12 @@ void new_session_window(Conf *conf, const char *geometry_string) #if GTK_CHECK_VERSION(2,0,0) g_signal_connect(G_OBJECT(inst->imc), "commit", G_CALLBACK(input_method_commit_event), inst); + g_signal_connect(G_OBJECT(inst->imc), "preedit-start", + G_CALLBACK(input_method_preedit_start_event), inst); + g_signal_connect(G_OBJECT(inst->imc), "preedit-changed", + G_CALLBACK(input_method_preedit_changed_event), inst); + g_signal_connect(G_OBJECT(inst->imc), "preedit-end", + G_CALLBACK(input_method_preedit_end_event), inst); #endif if (conf_get_bool(inst->conf, CONF_scrollbar)) g_signal_connect(G_OBJECT(inst->sbar_adjust), "value_changed", From 227b9ae470d3c934f50570454db11586d6845945 Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Wed, 26 Mar 2025 20:49:00 +0000 Subject: [PATCH 037/129] GTK: also log the preedit string --- unix/window.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/unix/window.c b/unix/window.c index 6c0752d8..a6cd7eec 100644 --- a/unix/window.c +++ b/unix/window.c @@ -2130,10 +2130,27 @@ void input_method_preedit_start_event(GtkIMContext *imc, gpointer data) void input_method_preedit_changed_event(GtkIMContext *imc, gpointer data) { GtkFrontend *inst = (GtkFrontend *)data; + gint cursor_pos; + gchar *preedit_string; +#ifdef KEY_EVENT_DIAGNOSTICS + char *string_string = dupstr(""); + int i; +#endif + gtk_im_context_get_preedit_string(imc, &preedit_string, NULL, &cursor_pos); #ifdef KEY_EVENT_DIAGNOSTICS - debug(" - IM preedit-changed event\n"); + for (i = 0; preedit_string[i]; i++) { + char *old = string_string; + string_string = dupprintf("%s%s%02x", string_string, + string_string[0] ? " " : "", + (unsigned)preedit_string[i] & 0xFF); + sfree(old); + } + debug(" - IM preedit-changed event in UTF-8 = [%s] cursor_pos=%d\n", + string_string, (int)cursor_pos); + sfree(string_string); #endif + g_free(preedit_string); } void input_method_preedit_end_event(GtkIMContext *imc, gpointer data) From 194ca31cc3572497cf11feb0114a17828d3ad498 Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Sun, 30 Mar 2025 14:02:37 +0100 Subject: [PATCH 038/129] Add an API for passing pre-edit text to terminal; call from GTK The terminal code doesn't yet do anything with the text other than feed it to a debugging printf. The call uses UTF-8 and expects the terminal to copy the string because that's compatible with gtk_im_context_get_preedit_string(). --- putty.h | 1 + terminal/terminal.c | 10 ++++++++++ unix/window.c | 2 ++ 3 files changed, 13 insertions(+) diff --git a/putty.h b/putty.h index dbd85298..ce39d680 100644 --- a/putty.h +++ b/putty.h @@ -2044,6 +2044,7 @@ void term_notify_palette_changed(Terminal *term); void term_notify_window_pos(Terminal *term, int x, int y); void term_notify_window_size_pixels(Terminal *term, int x, int y); void term_palette_override(Terminal *term, unsigned osc4_index, rgb rgb); +void term_set_preedit_text(Terminal *term, char *preedit_text); typedef enum SmallKeypadKey { SKK_HOME, SKK_END, SKK_INSERT, SKK_DELETE, SKK_PGUP, SKK_PGDN, diff --git a/terminal/terminal.c b/terminal/terminal.c index 4d1d4f5b..3aac6960 100644 --- a/terminal/terminal.c +++ b/terminal/terminal.c @@ -8106,3 +8106,13 @@ void term_notify_window_size_pixels(Terminal *term, int x, int y) term->winpixsize_x = x; term->winpixsize_y = y; } + +/* + * Set the pre-edit text as required by an input method. preedit_text + * is expected to be in UTF-8. It's NULL if no pre-edit text is + * required. It's owned by the caller and must not be freed here. + */ +void term_set_preedit_text(Terminal *term, char *preedit_text) +{ + debug("Pre-edit: %s\n", preedit_text); +} diff --git a/unix/window.c b/unix/window.c index a6cd7eec..95916913 100644 --- a/unix/window.c +++ b/unix/window.c @@ -2150,6 +2150,7 @@ void input_method_preedit_changed_event(GtkIMContext *imc, gpointer data) string_string, (int)cursor_pos); sfree(string_string); #endif + term_set_preedit_text(inst->term, preedit_string); g_free(preedit_string); } @@ -2160,6 +2161,7 @@ void input_method_preedit_end_event(GtkIMContext *imc, gpointer data) #ifdef KEY_EVENT_DIAGNOSTICS debug(" - IM preedit-end event\n"); #endif + term_set_preedit_text(inst->term, NULL); } #endif From 35caff40488002c731aec3d92d98a3fc1a082d4f Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Sun, 30 Mar 2025 15:05:31 +0100 Subject: [PATCH 039/129] Decode UTF-8 in pre-edit text This is a pre-requisite to rendering it somehow. --- terminal/terminal.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/terminal/terminal.c b/terminal/terminal.c index 3aac6960..5fc20b94 100644 --- a/terminal/terminal.c +++ b/terminal/terminal.c @@ -8114,5 +8114,15 @@ void term_notify_window_size_pixels(Terminal *term, int x, int y) */ void term_set_preedit_text(Terminal *term, char *preedit_text) { - debug("Pre-edit: %s\n", preedit_text); + BinarySource src[1]; + + if (preedit_text != NULL) { + debug("Pre-edit:"); + BinarySource_BARE_INIT(src, preedit_text, strlen(preedit_text)); + while (get_avail(src)) + debug(" U+%04X", decode_utf8(src, NULL)); + debug("\n"); + } else { + debug("Pre-edit finished\n"); + } } From ab9dfc572e4759b3304c47e7914af87306f340f6 Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Sun, 30 Mar 2025 16:45:25 +0100 Subject: [PATCH 040/129] Very crude support for displaying pre-edit strings We simply pass each character to term_display_graphic_char and then put the cursor back where we found it. This works in simple cases, but is fundamentally wrong. Really we should do this in a way that doesn't touch the terminal state and just gets rendered on top of it somehow. --- terminal/terminal.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/terminal/terminal.c b/terminal/terminal.c index 5fc20b94..d945494b 100644 --- a/terminal/terminal.c +++ b/terminal/terminal.c @@ -8115,13 +8115,18 @@ void term_notify_window_size_pixels(Terminal *term, int x, int y) void term_set_preedit_text(Terminal *term, char *preedit_text) { BinarySource src[1]; + pos oldcurs = term->curs; if (preedit_text != NULL) { debug("Pre-edit:"); BinarySource_BARE_INIT(src, preedit_text, strlen(preedit_text)); - while (get_avail(src)) - debug(" U+%04X", decode_utf8(src, NULL)); + while (get_avail(src)) { + unsigned int c = decode_utf8(src, NULL); + debug(" U+%04X", c); + term_display_graphic_char(term, c); + } debug("\n"); + term->curs = oldcurs; } else { debug("Pre-edit finished\n"); } From b72fec0a52a921b747d3f09b8792c05e574d0998 Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Mon, 31 Mar 2025 10:04:18 +0100 Subject: [PATCH 041/129] Display some IM pre-edit state when painting the terminal This is approximately how it should work: term_set_preedit_text stashes data in the terminal structure and then do_paint() renders it in place of what's in the terminal buffer. Currently this only works for a single narrow character, and it copies the existing attributes under the cursor, but this might actually be enough for the UK keyboard layout in GNOME. --- terminal/terminal.c | 14 +++++++++----- terminal/terminal.h | 3 +++ 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/terminal/terminal.c b/terminal/terminal.c index d945494b..d8f5f5e9 100644 --- a/terminal/terminal.c +++ b/terminal/terminal.c @@ -6199,6 +6199,9 @@ static void do_paint(Terminal *term) if (i == our_curs_y && j == our_curs_x) tattr |= cursor; + if (term->preedit_char != -1) + tchar = term->preedit_char; + } /* FULL-TERMCHAR */ newline[j].attr = tattr; @@ -8115,19 +8118,20 @@ void term_notify_window_size_pixels(Terminal *term, int x, int y) void term_set_preedit_text(Terminal *term, char *preedit_text) { BinarySource src[1]; - pos oldcurs = term->curs; if (preedit_text != NULL) { debug("Pre-edit:"); BinarySource_BARE_INIT(src, preedit_text, strlen(preedit_text)); - while (get_avail(src)) { + if (get_avail(src)) { unsigned int c = decode_utf8(src, NULL); debug(" U+%04X", c); - term_display_graphic_char(term, c); - } + term->preedit_char = c; + } else + term->preedit_char = -1; debug("\n"); - term->curs = oldcurs; } else { debug("Pre-edit finished\n"); + term->preedit_char = -1; } + seen_disp_event(term); } diff --git a/terminal/terminal.h b/terminal/terminal.h index df6ba4cc..b9159eb6 100644 --- a/terminal/terminal.h +++ b/terminal/terminal.h @@ -442,6 +442,9 @@ struct terminal_tag { */ struct term_userpass_state *userpass_state; bool userpass_utf8_override; + + /* Input method state. */ + int preedit_char; /* -1 for none */ }; static inline bool in_utf(Terminal *term) From 3ab279fae50a64a108054537c4bd44812f953e49 Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Tue, 1 Apr 2025 23:01:46 +0100 Subject: [PATCH 042/129] Minimal viable pre-edit support Now we can cope with a single wide or narrow pre-edit character, which is good enough for the input methods that I use. When rendering the line that contains the cursor we set up a little array of termchars that contains the pre-edit text and work out where it should be displayed. Then when rendering the screen we switch between displaying text from the real terminal and from the pre-edit string as necessary. Ideally, we should support longer strings, combining characters, and setting attributes. I think the current architecture should make all of those possible, but not entirely easy. --- terminal/terminal.c | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/terminal/terminal.c b/terminal/terminal.c index d8f5f5e9..02bc421b 100644 --- a/terminal/terminal.c +++ b/terminal/terminal.c @@ -2096,6 +2096,8 @@ Terminal *term_init(Conf *myconf, struct unicode_data *ucsdata, TermWin *win) palette_reset(term, false); + term->preedit_char = -1; + return term; } @@ -6094,7 +6096,7 @@ static void do_paint(Terminal *term) /* The normal screen data */ for (i = 0; i < term->rows; i++) { termline *ldata; - termchar *lchars; + termchar *lchars, preedit_termchars[2]; bool dirty_line, dirty_run, selected; unsigned long attr = 0, cset = 0; int start = 0; @@ -6104,6 +6106,7 @@ static void do_paint(Terminal *term) bool dirtyrect; int *backward; truecolour tc; + int preedit_width = 0, preedit_start = 0, preedit_end = 0; scrpos.y = i + term->disptop; ldata = lineptr(scrpos.y); @@ -6117,6 +6120,27 @@ static void do_paint(Terminal *term) backward = NULL; } + /* Work out if and where to display pre-edit text. */ + if (i == our_curs_y && term->preedit_char != -1) { + preedit_width = term_char_width(term, term->preedit_char); + debug("preedit_width = %d\n", preedit_width); + preedit_start = our_curs_x; + preedit_end = preedit_start + preedit_width; + if (preedit_end > term->cols) { + preedit_end = term->cols; + preedit_start = preedit_end - preedit_width; + } + for (j = 0; j < preedit_width; j++) { + /* FULL-TERMCHAR */ + preedit_termchars[j].chr = !j ? term->preedit_char : UCSWIDE; + preedit_termchars[j].attr = 0; + preedit_termchars[j].truecolour.fg.enabled = false; + preedit_termchars[j].truecolour.bg.enabled = false; + preedit_termchars[j].cc_next = 0; + } + our_curs_x = preedit_start; + } + /* * First loop: work along the line deciding what we want * each character cell to look like. @@ -6124,8 +6148,12 @@ static void do_paint(Terminal *term) for (j = 0; j < term->cols; j++) { unsigned long tattr, tchar; termchar *d = lchars + j; + bool in_preedit = j >= preedit_start && j < preedit_end; scrpos.x = backward ? backward[j] : j; + if (in_preedit) + d = preedit_termchars + j - preedit_start; + tchar = d->chr; tattr = d->attr; @@ -6160,7 +6188,8 @@ static void do_paint(Terminal *term) tchar = term->ucsdata->unitab_scoacs[tchar&0xFF]; break; } - if (j < term->cols-1 && d[1].chr == UCSWIDE) + if (j < (in_preedit ? preedit_end : term->cols) - 1 + && d[1].chr == UCSWIDE) tattr |= ATTR_WIDE; /* Video reversing things */ @@ -6199,9 +6228,6 @@ static void do_paint(Terminal *term) if (i == our_curs_y && j == our_curs_x) tattr |= cursor; - if (term->preedit_char != -1) - tchar = term->preedit_char; - } /* FULL-TERMCHAR */ newline[j].attr = tattr; From f9928fb7d5ef8794bd81ea81d4c9026f4885b6f9 Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Wed, 2 Apr 2025 01:21:40 +0100 Subject: [PATCH 043/129] Initialise pre-edit character cells to basic_erase_char This ensures that they have sensible attributes (not black on black) and is simpler than initialising the fields by hand. --- terminal/terminal.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/terminal/terminal.c b/terminal/terminal.c index 02bc421b..7721a32c 100644 --- a/terminal/terminal.c +++ b/terminal/terminal.c @@ -6131,12 +6131,8 @@ static void do_paint(Terminal *term) preedit_start = preedit_end - preedit_width; } for (j = 0; j < preedit_width; j++) { - /* FULL-TERMCHAR */ + preedit_termchars[j] = term->basic_erase_char; preedit_termchars[j].chr = !j ? term->preedit_char : UCSWIDE; - preedit_termchars[j].attr = 0; - preedit_termchars[j].truecolour.fg.enabled = false; - preedit_termchars[j].truecolour.bg.enabled = false; - preedit_termchars[j].cc_next = 0; } our_curs_x = preedit_start; } From 29ac4da8fb473126c12cb1db315738d6735a6706 Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Wed, 2 Apr 2025 10:06:22 +0100 Subject: [PATCH 044/129] Support longer pre-edit text Now the pre-edit text is converted into a dynamically-allocated array of termchars in term_set_preedit_text(), which slightly simplifies do_paint(). This means that the long pre-edit generated by Ctrl+Shift+U in GNOME now displays more or less properly. I may need a better plan for what to do about cursor positioning, though. --- terminal/terminal.c | 52 +++++++++++++++++++++++++++------------------ terminal/terminal.h | 3 ++- 2 files changed, 33 insertions(+), 22 deletions(-) diff --git a/terminal/terminal.c b/terminal/terminal.c index 7721a32c..5cf726d7 100644 --- a/terminal/terminal.c +++ b/terminal/terminal.c @@ -2096,8 +2096,6 @@ Terminal *term_init(Conf *myconf, struct unicode_data *ucsdata, TermWin *win) palette_reset(term, false); - term->preedit_char = -1; - return term; } @@ -2162,6 +2160,8 @@ void term_free(Terminal *term) if (term->userpass_state) term_userpass_state_free(term->userpass_state); + sfree(term->preedit_termchars); + sfree(term); } @@ -6096,7 +6096,7 @@ static void do_paint(Terminal *term) /* The normal screen data */ for (i = 0; i < term->rows; i++) { termline *ldata; - termchar *lchars, preedit_termchars[2]; + termchar *lchars; bool dirty_line, dirty_run, selected; unsigned long attr = 0, cset = 0; int start = 0; @@ -6106,7 +6106,7 @@ static void do_paint(Terminal *term) bool dirtyrect; int *backward; truecolour tc; - int preedit_width = 0, preedit_start = 0, preedit_end = 0; + int preedit_start = 0, preedit_end = 0; scrpos.y = i + term->disptop; ldata = lineptr(scrpos.y); @@ -6121,18 +6121,13 @@ static void do_paint(Terminal *term) } /* Work out if and where to display pre-edit text. */ - if (i == our_curs_y && term->preedit_char != -1) { - preedit_width = term_char_width(term, term->preedit_char); - debug("preedit_width = %d\n", preedit_width); + if (i == our_curs_y && term->preedit_termchars != NULL) { + debug("preedit_width = %d\n", term->preedit_width); preedit_start = our_curs_x; - preedit_end = preedit_start + preedit_width; + preedit_end = preedit_start + term->preedit_width; if (preedit_end > term->cols) { preedit_end = term->cols; - preedit_start = preedit_end - preedit_width; - } - for (j = 0; j < preedit_width; j++) { - preedit_termchars[j] = term->basic_erase_char; - preedit_termchars[j].chr = !j ? term->preedit_char : UCSWIDE; + preedit_start = preedit_end - term->preedit_width; } our_curs_x = preedit_start; } @@ -6148,7 +6143,7 @@ static void do_paint(Terminal *term) scrpos.x = backward ? backward[j] : j; if (in_preedit) - d = preedit_termchars + j - preedit_start; + d = term->preedit_termchars + j - preedit_start; tchar = d->chr; tattr = d->attr; @@ -8139,21 +8134,36 @@ void term_notify_window_size_pixels(Terminal *term, int x, int y) */ void term_set_preedit_text(Terminal *term, char *preedit_text) { - BinarySource src[1]; - + sfree(term->preedit_termchars); + term->preedit_termchars = NULL; + term->preedit_width = 0; if (preedit_text != NULL) { + BinarySource src[1]; + int i; + debug("Pre-edit:"); BinarySource_BARE_INIT(src, preedit_text, strlen(preedit_text)); - if (get_avail(src)) { + while (get_avail(src)) + term->preedit_width += + term_char_width(term, decode_utf8(src, NULL)); + term->preedit_termchars = snewn(term->preedit_width, termchar); + BinarySource_REWIND(src); + for (i = 0; i < term->preedit_width; i++) { unsigned int c = decode_utf8(src, NULL); debug(" U+%04X", c); - term->preedit_char = c; - } else - term->preedit_char = -1; + if (term_char_width(term, c) >= 1) { + term->preedit_termchars[i] = term->basic_erase_char; + term->preedit_termchars[i].chr = c; + if (term_char_width(term, c) >= 2) { + term->preedit_termchars[i+1] = term->basic_erase_char; + term->preedit_termchars[i+1].chr = UCSWIDE; + i++; + } + } + } debug("\n"); } else { debug("Pre-edit finished\n"); - term->preedit_char = -1; } seen_disp_event(term); } diff --git a/terminal/terminal.h b/terminal/terminal.h index b9159eb6..a2e8f5a4 100644 --- a/terminal/terminal.h +++ b/terminal/terminal.h @@ -444,7 +444,8 @@ struct terminal_tag { bool userpass_utf8_override; /* Input method state. */ - int preedit_char; /* -1 for none */ + termchar *preedit_termchars; + int preedit_width; }; static inline bool in_utf(Terminal *term) From 3bbde58c098b0afca6c8a5c56cc1ea71f7eaafc5 Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Sat, 5 Apr 2025 15:47:52 +0100 Subject: [PATCH 045/129] Properly hide existing combining characters with pre-edit text If a character cell under the pre-edit text has a combining character, it shouldn't be combined with a character from the pre-edit text, but should be hidden instead. This also means that the pre-edit text could contain combining characters if I implemented a way to put them into it. --- terminal/terminal.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/terminal/terminal.c b/terminal/terminal.c index 5cf726d7..287355ad 100644 --- a/terminal/terminal.c +++ b/terminal/terminal.c @@ -6279,6 +6279,10 @@ static void do_paint(Terminal *term) unsigned long tattr, tchar; bool break_run, do_copy, next_run_dirty = false; termchar *d = lchars + j; + bool in_preedit = j >= preedit_start && j < preedit_end; + + if (in_preedit) + d = term->preedit_termchars + j - preedit_start; tattr = newline[j].attr; tchar = newline[j].chr; From 477688576784b5fea027a14badd1e9b97923c0be Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Sat, 5 Apr 2025 16:00:00 +0100 Subject: [PATCH 046/129] Use a little termline to store pre-edit text I think supporting combining characters in pre-edit text will be simpler if I can use add_cc, which operated on termlines. Also we have code for resizing termlines, which means I might not need to count the width of the pre-edit string accurately before allocating it. --- terminal/terminal.c | 34 +++++++++++++++------------------- terminal/terminal.h | 3 +-- 2 files changed, 16 insertions(+), 21 deletions(-) diff --git a/terminal/terminal.c b/terminal/terminal.c index 287355ad..3cebd448 100644 --- a/terminal/terminal.c +++ b/terminal/terminal.c @@ -2160,7 +2160,7 @@ void term_free(Terminal *term) if (term->userpass_state) term_userpass_state_free(term->userpass_state); - sfree(term->preedit_termchars); + freetermline(term->preedit_termline); sfree(term); } @@ -6121,13 +6121,13 @@ static void do_paint(Terminal *term) } /* Work out if and where to display pre-edit text. */ - if (i == our_curs_y && term->preedit_termchars != NULL) { - debug("preedit_width = %d\n", term->preedit_width); + if (i == our_curs_y && term->preedit_termline != NULL) { + debug("preedit_width = %d\n", term->preedit_termline->cols); preedit_start = our_curs_x; - preedit_end = preedit_start + term->preedit_width; + preedit_end = preedit_start + term->preedit_termline->cols; if (preedit_end > term->cols) { preedit_end = term->cols; - preedit_start = preedit_end - term->preedit_width; + preedit_start = preedit_end - term->preedit_termline->cols; } our_curs_x = preedit_start; } @@ -6143,7 +6143,7 @@ static void do_paint(Terminal *term) scrpos.x = backward ? backward[j] : j; if (in_preedit) - d = term->preedit_termchars + j - preedit_start; + d = term->preedit_termline->chars + j - preedit_start; tchar = d->chr; tattr = d->attr; @@ -6282,7 +6282,7 @@ static void do_paint(Terminal *term) bool in_preedit = j >= preedit_start && j < preedit_end; if (in_preedit) - d = term->preedit_termchars + j - preedit_start; + d = term->preedit_termline->chars + j - preedit_start; tattr = newline[j].attr; tchar = newline[j].chr; @@ -8138,29 +8138,25 @@ void term_notify_window_size_pixels(Terminal *term, int x, int y) */ void term_set_preedit_text(Terminal *term, char *preedit_text) { - sfree(term->preedit_termchars); - term->preedit_termchars = NULL; - term->preedit_width = 0; + freetermline(term->preedit_termline); + term->preedit_termline = NULL; if (preedit_text != NULL) { BinarySource src[1]; - int i; + int width = 0, i; debug("Pre-edit:"); BinarySource_BARE_INIT(src, preedit_text, strlen(preedit_text)); while (get_avail(src)) - term->preedit_width += - term_char_width(term, decode_utf8(src, NULL)); - term->preedit_termchars = snewn(term->preedit_width, termchar); + width += term_char_width(term, decode_utf8(src, NULL)); + term->preedit_termline = newtermline(term, width, false); BinarySource_REWIND(src); - for (i = 0; i < term->preedit_width; i++) { + for (i = 0; i < width; i++) { unsigned int c = decode_utf8(src, NULL); debug(" U+%04X", c); if (term_char_width(term, c) >= 1) { - term->preedit_termchars[i] = term->basic_erase_char; - term->preedit_termchars[i].chr = c; + term->preedit_termline->chars[i].chr = c; if (term_char_width(term, c) >= 2) { - term->preedit_termchars[i+1] = term->basic_erase_char; - term->preedit_termchars[i+1].chr = UCSWIDE; + term->preedit_termline->chars[i+1].chr = UCSWIDE; i++; } } diff --git a/terminal/terminal.h b/terminal/terminal.h index a2e8f5a4..e165a5b6 100644 --- a/terminal/terminal.h +++ b/terminal/terminal.h @@ -444,8 +444,7 @@ struct terminal_tag { bool userpass_utf8_override; /* Input method state. */ - termchar *preedit_termchars; - int preedit_width; + termline *preedit_termline; }; static inline bool in_utf(Terminal *term) From d8493c11cd6e774077b9318e801bfa99525d0c98 Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Sat, 5 Apr 2025 16:20:52 +0100 Subject: [PATCH 047/129] Construct preedit_termline incrementally This involves repeatedly resizing it as we decode characters. That's a bit inefficient (at least with the current implementation of resizeline()), but it makes it much easier to be certain that the line is actually the right length. --- terminal/terminal.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/terminal/terminal.c b/terminal/terminal.c index 3cebd448..f05877f0 100644 --- a/terminal/terminal.c +++ b/terminal/terminal.c @@ -8145,20 +8145,26 @@ void term_set_preedit_text(Terminal *term, char *preedit_text) int width = 0, i; debug("Pre-edit:"); + term->preedit_termline = newtermline(term, 0, false); BinarySource_BARE_INIT(src, preedit_text, strlen(preedit_text)); - while (get_avail(src)) - width += term_char_width(term, decode_utf8(src, NULL)); - term->preedit_termline = newtermline(term, width, false); - BinarySource_REWIND(src); - for (i = 0; i < width; i++) { + while (get_avail(src)) { unsigned int c = decode_utf8(src, NULL); debug(" U+%04X", c); - if (term_char_width(term, c) >= 1) { - term->preedit_termline->chars[i].chr = c; - if (term_char_width(term, c) >= 2) { - term->preedit_termline->chars[i+1].chr = UCSWIDE; - i++; - } + switch (term_char_width(term, c)) { + case -1: + /* Ignore control characters. */ + break; + case 1: + width += 1; + resizeline(term, term->preedit_termline, width); + term->preedit_termline->chars[width - 1].chr = c; + break; + case 2: + width += 2; + resizeline(term, term->preedit_termline, width); + term->preedit_termline->chars[width - 2].chr = c; + term->preedit_termline->chars[width - 1].chr = UCSWIDE; + break; } } debug("\n"); From 6532408ba564b3e94c0a5319b58f73915eb08fa9 Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Sat, 5 Apr 2025 18:35:57 +0100 Subject: [PATCH 048/129] Support combining characters in pre-edit strings Having the pre-edit string in a termline makes this almost trivial. --- terminal/terminal.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/terminal/terminal.c b/terminal/terminal.c index f05877f0..fff9391d 100644 --- a/terminal/terminal.c +++ b/terminal/terminal.c @@ -8154,6 +8154,16 @@ void term_set_preedit_text(Terminal *term, char *preedit_text) case -1: /* Ignore control characters. */ break; + case 0: + if (width == 0) { + width = 1; + resizeline(term, term->preedit_termline, width); + } + if (term->preedit_termline->chars[width - 1].chr == UCSWIDE) + add_cc(term->preedit_termline, width - 2, c); + else + add_cc(term->preedit_termline, width - 1, c); + break; case 1: width += 1; resizeline(term, term->preedit_termline, width); From 4f4f752e47d88fa732c31d6d09545f44e303c72d Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Sat, 5 Apr 2025 20:26:20 +0100 Subject: [PATCH 049/129] Put the cursor at the right-hand end of the pre-edit string That's the more logical location in a string more than one character long. GTK does actually tell us where it thinks the cursor should be, but we don't yet pay attention to that. --- terminal/terminal.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/terminal/terminal.c b/terminal/terminal.c index fff9391d..6c2c9306 100644 --- a/terminal/terminal.c +++ b/terminal/terminal.c @@ -6129,7 +6129,11 @@ static void do_paint(Terminal *term) preedit_end = term->cols; preedit_start = preedit_end - term->preedit_termline->cols; } - our_curs_x = preedit_start; + if (term->preedit_termline->chars[term->preedit_termline->cols - 1] + .chr == UCSWIDE) + our_curs_x = preedit_end - 2; + else + our_curs_x = preedit_end - 1; } /* From fee594798f6f81eb6489e8fb6eff68f65e3198b2 Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Sat, 5 Apr 2025 21:22:43 +0100 Subject: [PATCH 050/129] Remove recently-added debug() calls from terminal.c --- terminal/terminal.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/terminal/terminal.c b/terminal/terminal.c index 6c2c9306..0bd94ccd 100644 --- a/terminal/terminal.c +++ b/terminal/terminal.c @@ -6122,7 +6122,6 @@ static void do_paint(Terminal *term) /* Work out if and where to display pre-edit text. */ if (i == our_curs_y && term->preedit_termline != NULL) { - debug("preedit_width = %d\n", term->preedit_termline->cols); preedit_start = our_curs_x; preedit_end = preedit_start + term->preedit_termline->cols; if (preedit_end > term->cols) { @@ -8148,12 +8147,10 @@ void term_set_preedit_text(Terminal *term, char *preedit_text) BinarySource src[1]; int width = 0, i; - debug("Pre-edit:"); term->preedit_termline = newtermline(term, 0, false); BinarySource_BARE_INIT(src, preedit_text, strlen(preedit_text)); while (get_avail(src)) { unsigned int c = decode_utf8(src, NULL); - debug(" U+%04X", c); switch (term_char_width(term, c)) { case -1: /* Ignore control characters. */ @@ -8181,9 +8178,6 @@ void term_set_preedit_text(Terminal *term, char *preedit_text) break; } } - debug("\n"); - } else { - debug("Pre-edit finished\n"); } seen_disp_event(term); } From 368d74cc25c59e7531217a13310d7bd79c498b53 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sun, 6 Apr 2025 06:39:26 +0100 Subject: [PATCH 051/129] Remove two unused variables. They caused build failures at -Wall. --- terminal/terminal.c | 2 +- unix/window.c | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/terminal/terminal.c b/terminal/terminal.c index 0bd94ccd..6198a411 100644 --- a/terminal/terminal.c +++ b/terminal/terminal.c @@ -8145,7 +8145,7 @@ void term_set_preedit_text(Terminal *term, char *preedit_text) term->preedit_termline = NULL; if (preedit_text != NULL) { BinarySource src[1]; - int width = 0, i; + int width = 0; term->preedit_termline = newtermline(term, 0, false); BinarySource_BARE_INIT(src, preedit_text, strlen(preedit_text)); diff --git a/unix/window.c b/unix/window.c index 95916913..9d5b3fd3 100644 --- a/unix/window.c +++ b/unix/window.c @@ -2120,8 +2120,6 @@ void input_method_commit_event(GtkIMContext *imc, gchar *str, gpointer data) void input_method_preedit_start_event(GtkIMContext *imc, gpointer data) { - GtkFrontend *inst = (GtkFrontend *)data; - #ifdef KEY_EVENT_DIAGNOSTICS debug(" - IM preedit-start event\n"); #endif From 9fcff77767d324cc86a71d11d3fa71448f6b0f56 Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Sun, 6 Apr 2025 13:31:15 +0100 Subject: [PATCH 052/129] Set ATTR_RIGHTCURS on pre-edit cursor Currently, we display the cursor at the right-hand end of the pre-edit text. That looks good for block and underline cursors, but it's a bit weird for the vertical line, which naturally appears at the left edge of the rightmost character. Setting ATTR_RIGHTCURS fixes this and means that the vertical-line cursor appears at the right edge of the rightmost character. That also corrects a weirdness where ATTR_RIGHTCURS was leaking through from the underlying pending-wrap state of the terminal, which was definitely wrong. --- terminal/terminal.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/terminal/terminal.c b/terminal/terminal.c index 6198a411..0fad9eb8 100644 --- a/terminal/terminal.c +++ b/terminal/terminal.c @@ -6128,11 +6128,13 @@ static void do_paint(Terminal *term) preedit_end = term->cols; preedit_start = preedit_end - term->preedit_termline->cols; } + /* Show the cursor at the right end of the pre-edit text. */ if (term->preedit_termline->chars[term->preedit_termline->cols - 1] .chr == UCSWIDE) our_curs_x = preedit_end - 2; else our_curs_x = preedit_end - 1; + cursor |= ATTR_RIGHTCURS; } /* From d1ff56853324919070bd64bc666a33c8d0c24dbc Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sat, 19 Apr 2025 13:07:05 +0100 Subject: [PATCH 053/129] Add some exceptions in .gitignore. A user reports that our top-level .gitignore ignores several files that are actually part of the real git repository. This is inconvenient if you start from a downloaded tarball or zip file, and try to make it _back_ into a git repository to work with it. The blanket rule to ignore files called "Makefile" (on the theory that they're autogenerated by cmake, or in the pre-cmake days, by autotools) was also excluding two handwritten Makefiles, in 'icons' and in 'contrib/cygtermd'. And the rule about doc/*.txt, intended to exclude Halibut's plain-text output, also excluded doc/CMakeLists.txt. With these exclusions in place, if you download a PuTTY source .tar.gz, unpack it, change into the unpacked subdirectory, and run 'git init', 'git add .' and 'git commit', then 'git status --ignored' to see what files in the tarball weren't added to the repo, you'll find that the remaining ones are all in the 'doc' directory, and really _are_ Halibut outputs: all the man pages (putty.1 etc), the Windows help file putty.chm, and the plain text puttydoc.txt. --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index bdfcf67f..a42f0858 100644 --- a/.gitignore +++ b/.gitignore @@ -72,12 +72,15 @@ cmake_install.cmake /build.out /empty.h Makefile +!/contrib/cygtermd/Makefile +!/icons/Makefile /compile *.a /charset/sbcsdat.c /contrib/cygtermd/cygtermd.exe /doc/*.html /doc/*.txt +!/doc/CMakeLists.txt /doc/*.cnt /doc/*.hlp /doc/*.gid From d9a2620d01874f624d6fa9b6cfb55e2960a229d8 Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Sun, 20 Apr 2025 16:45:39 +0100 Subject: [PATCH 054/129] GTK: correct a couple of comments to reflect GTK 3's existence --- unix/unifont.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/unix/unifont.c b/unix/unifont.c index c8256794..c09db90e 100644 --- a/unix/unifont.c +++ b/unix/unifont.c @@ -1295,7 +1295,7 @@ static char *x11font_size_increment(unifont *font, int increment) #if GTK_CHECK_VERSION(2,0,0) /* ---------------------------------------------------------------------- - * Pango font implementation (for GTK 2 only). + * Pango font implementation (for GTK 2+ only). */ #if defined PANGO_PRE_1POINT4 && !defined PANGO_PRE_1POINT6 @@ -2325,7 +2325,7 @@ static char *multifont_size_increment(unifont *font, int increment) #if GTK_CHECK_VERSION(2,0,0) /* ---------------------------------------------------------------------- - * Implementation of a unified font selector. Used on GTK 2 only; + * Implementation of a unified font selector. Used on GTK 2+ only; * for GTK 1 we still use the standard font selector. */ From 5cf14b4f271023bf0af6b8c6f785afd9e5029900 Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Wed, 16 Apr 2025 22:02:56 +0100 Subject: [PATCH 055/129] GTK: slightly reword a comment to reflect Cairo documentation The Cairo documentation is clear that cairo_set_antialias() only affects shape drawing and not text rendering. To change anti-aliasing settings for font rendering you need cairo_font_options_set_antialias() instead. Therefore the comment can be a bit more certain than just describing what Cairo "appears" to do. --- unix/window.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/unix/window.c b/unix/window.c index 9d5b3fd3..6029a9f4 100644 --- a/unix/window.c +++ b/unix/window.c @@ -923,10 +923,12 @@ static void cairo_setup_draw_ctx(GtkFrontend *inst) cairo_set_line_width(inst->uctx.u.cairo.cr, 1.0); cairo_set_line_cap(inst->uctx.u.cairo.cr, CAIRO_LINE_CAP_SQUARE); cairo_set_line_join(inst->uctx.u.cairo.cr, CAIRO_LINE_JOIN_MITER); - /* This antialiasing setting appears to be ignored for Pango - * font rendering but honoured for stroking and filling paths; - * I don't quite understand the logic of that, but I won't - * complain since it's exactly what I happen to want */ + /* + * This antialiasing setting doesn't affect Pango font rendering + * but does affect stroking and filling paths; I don't quite + * understand the logic of that, but I won't complain since it's + * exactly what I happen to want. + */ cairo_set_antialias(inst->uctx.u.cairo.cr, CAIRO_ANTIALIAS_NONE); } #endif From 11f4e2d8b501e12b1b9e3bfaaa78f247d54ff072 Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Mon, 21 Apr 2025 21:16:40 +0100 Subject: [PATCH 056/129] GTK: use Cairo to read X font bitmaps from server When using an X server-side font with Cairo rendering, PuTTY takes the rather horrible approach of rendering each glyph it uses into a depth-1 Pixmap and then copying the result into a Cairo surface that it uses every time it wants to display that glyph. Heretofore, the conversion of the Pixmap into a Cairo surface was done by downloading it using XGetImage() and then manually re-arringing the bits into a suitable form for Cairo. But Cairo has a way of turning an X Drawable (including a Pixmap) into a surface, and then it's just a case of copying one surface to another using cairo_paint(). So that's what PuTTY does now and the process is a little less unpleasant than it was. --- unix/unifont.c | 73 ++++++++++++-------------------------------------- 1 file changed, 17 insertions(+), 56 deletions(-) diff --git a/unix/unifont.c b/unix/unifont.c index c09db90e..5d9eceef 100644 --- a/unix/unifont.c +++ b/unix/unifont.c @@ -27,6 +27,9 @@ #include "tree234.h" #ifndef NOT_X_WINDOWS +#ifdef DRAW_TEXT_CAIRO +#include +#endif #include #include #include @@ -131,7 +134,6 @@ static char *x11font_size_increment(unifont *font, int increment); #ifdef DRAW_TEXT_CAIRO struct cairo_cached_glyph { cairo_surface_t *surface; - unsigned char *bitmap; }; #endif @@ -165,13 +167,9 @@ typedef struct x11font_individual { * X server paraphernalia for actually downloading the glyphs. */ Pixmap pixmap; + cairo_surface_t *pixmap_surface; /* Cairo version of pixmap. */ GC gc; int pixwidth, pixheight, pixoriginx, pixoriginy; - - /* - * Paraphernalia for loading the resulting bitmaps into Cairo. - */ - int rowsize, allsize, indexflip; #endif } x11font_individual; @@ -535,6 +533,7 @@ static unifont *x11font_create(GtkWidget *widget, const char *name, xfont->fonts[i].glyphcache = NULL; xfont->fonts[i].nglyphs = 0; xfont->fonts[i].pixmap = None; + xfont->fonts[i].pixmap_surface = NULL; xfont->fonts[i].gc = None; #endif } @@ -556,13 +555,14 @@ static void x11font_destroy(unifont *font) #ifdef DRAW_TEXT_CAIRO if (xfont->fonts[i].gc != None) XFreeGC(disp, xfont->fonts[i].gc); + if (xfont->fonts[i].pixmap_surface != NULL) + cairo_surface_destroy(xfont->fonts[i].pixmap_surface); if (xfont->fonts[i].pixmap != None) XFreePixmap(disp, xfont->fonts[i].pixmap); if (xfont->fonts[i].glyphcache) { int j; for (j = 0; j < xfont->fonts[i].nglyphs; j++) { cairo_surface_destroy(xfont->fonts[i].glyphcache[j].surface); - sfree(xfont->fonts[i].glyphcache[j].bitmap); } sfree(xfont->fonts[i].glyphcache); } @@ -671,29 +671,12 @@ static void x11font_cairo_setup( xfi->pixoriginx = -xfi->xfs->min_bounds.lbearing; xfi->pixoriginy = xfi->xfs->max_bounds.ascent; - xfi->rowsize = cairo_format_stride_for_width(CAIRO_FORMAT_A1, - xfi->pixwidth); - xfi->allsize = xfi->rowsize * xfi->pixheight; - - { - /* - * Test host endianness and use it to set xfi->indexflip, - * which is XORed into our left-shift counts in order to - * implement the CAIRO_FORMAT_A1 specification, in which - * each bitmap byte is oriented LSB-first on little-endian - * platforms and MSB-first on big-endian ones. - * - * This is the same technique Cairo itself uses to test - * endianness, so hopefully it'll work in any situation - * where Cairo is usable at all. - */ - static const int endianness_test = 1; - xfi->indexflip = (*((char *) &endianness_test) == 1) ? 0 : 7; - } - xfi->pixmap = XCreatePixmap( disp, GDK_DRAWABLE_XID(gtk_widget_get_window(ctx->u.cairo.widget)), xfi->pixwidth, xfi->pixheight, 1); + xfi->pixmap_surface = cairo_xlib_surface_create_for_bitmap( + disp, xfi->pixmap, ScreenOfDisplay(disp, widgetscr), + xfi->pixwidth, xfi->pixheight); gcvals.foreground = WhitePixel(disp, widgetscr); gcvals.background = BlackPixel(disp, widgetscr); gcvals.font = xfi->xfs->fid; @@ -705,31 +688,6 @@ static void x11font_cairo_setup( static void x11font_cairo_cache_glyph( Display *disp, x11font_individual *xfi, int glyphindex) { - XImage *image; - int x, y; - unsigned char *bitmap; - const XCharStruct *xcs = x11_char_struct(xfi->xfs, glyphindex >> 8, - glyphindex & 0xFF); - - bitmap = snewn(xfi->allsize, unsigned char); - memset(bitmap, 0, xfi->allsize); - - image = XGetImage(disp, xfi->pixmap, 0, 0, - xfi->pixwidth, xfi->pixheight, AllPlanes, XYPixmap); - for (y = xfi->pixoriginy - xcs->ascent; - y < xfi->pixoriginy + xcs->descent; y++) { - for (x = xfi->pixoriginx + xcs->lbearing; - x < xfi->pixoriginx + xcs->rbearing; x++) { - unsigned long pixel = XGetPixel(image, x, y); - if (pixel) { - int byteindex = y * xfi->rowsize + x/8; - int bitindex = (x & 7) ^ xfi->indexflip; - bitmap[byteindex] |= 1U << bitindex; - } - } - } - XDestroyImage(image); - if (xfi->nglyphs <= glyphindex) { /* Round up to the next multiple of 256 on the general * principle that Unicode characters come in contiguous blocks @@ -741,13 +699,16 @@ static void x11font_cairo_cache_glyph( while (old_nglyphs < xfi->nglyphs) { xfi->glyphcache[old_nglyphs].surface = NULL; - xfi->glyphcache[old_nglyphs].bitmap = NULL; old_nglyphs++; } } - xfi->glyphcache[glyphindex].bitmap = bitmap; - xfi->glyphcache[glyphindex].surface = cairo_image_surface_create_for_data( - bitmap, CAIRO_FORMAT_A1, xfi->pixwidth, xfi->pixheight, xfi->rowsize); + cairo_surface_mark_dirty(xfi->pixmap_surface); + xfi->glyphcache[glyphindex].surface = cairo_image_surface_create( + CAIRO_FORMAT_A1, xfi->pixwidth, xfi->pixheight); + cairo_t *cr = cairo_create(xfi->glyphcache[glyphindex].surface); + cairo_set_source_surface(cr, xfi->pixmap_surface, 0, 0); + cairo_paint(cr); + cairo_destroy(cr); } static void x11font_cairo_draw_glyph(unifont_drawctx *ctx, From 429478f914201098ae13cd79e29dc1dc8ecd0aca Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Wed, 23 Apr 2025 19:52:54 +0100 Subject: [PATCH 057/129] GTK: less-fuzzy bitmap font scaling with Cairo This commit fixes a problem that Simon observed when using an X bitmap font with Cairo and making a line double-width or double-size. When using Cairo, PuTTY implements double-width and double-size by just asking Cairo to scale all its drawing operations. This works fine with outline fonts, but when using a bitmap font the results are a bit fuzzy. This appears to be because Cairo's default is to use bilinear interpolation when scaling an image, which is fine for photos but not so good for fonts. In this commit, I decompose PuTTY's cairo_mask_surface() call into its component parts so that I can set the mask pattern's filter to CAIRO_FILTER_NEAREST before using it. That solves the problem, but it suggests that maybe we should be caching the pattern rather then the surface. --- unix/unifont.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/unix/unifont.c b/unix/unifont.c index 5d9eceef..04a65ccf 100644 --- a/unix/unifont.c +++ b/unix/unifont.c @@ -716,9 +716,16 @@ static void x11font_cairo_draw_glyph(unifont_drawctx *ctx, int glyphindex) { if (xfi->glyphcache[glyphindex].surface) { - cairo_mask_surface(ctx->u.cairo.cr, - xfi->glyphcache[glyphindex].surface, - x - xfi->pixoriginx, y - xfi->pixoriginy); + cairo_pattern_t *glyph_pattern = cairo_pattern_create_for_surface( + xfi->glyphcache[glyphindex].surface); + cairo_matrix_t xfrm; + /* We really don't want bilinear interpolation of bitmap fonts. */ + cairo_pattern_set_filter(glyph_pattern, CAIRO_FILTER_NEAREST); + cairo_matrix_init_translate(&xfrm, -(x - xfi->pixoriginx), + -(y - xfi->pixoriginy)); + cairo_pattern_set_matrix(glyph_pattern, &xfrm); + cairo_mask(ctx->u.cairo.cr, glyph_pattern); + cairo_pattern_destroy(glyph_pattern); } } From c71cc50e52aca439185c09ada7788c3f226d17a4 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Thu, 24 Apr 2025 11:30:52 +0100 Subject: [PATCH 058/129] Windows: cope if caret blinking is disabled. On Windows, when a blinking cursor is enabled, PuTTY uses the system default blink time from GetCaretBlinkTime(), which can be configured in Control Panel. Control Panel allows caret blinking to be disabled entirely, in which case GetCaretBlinkTime() returns INFINITE. PuTTY wasn't handling this case; if cursor blinking was enabled in PuTTY but disabled at the system level, the terminal window would hang, blinking the cursor madly. --- doc/config.but | 4 +++- terminal/terminal.c | 5 +++-- windows/CMakeLists.txt | 1 + windows/platform.h | 4 +++- windows/utils/blink_time.c | 21 +++++++++++++++++++++ 5 files changed, 31 insertions(+), 4 deletions(-) create mode 100644 windows/utils/blink_time.c diff --git a/doc/config.but b/doc/config.but index 56641b5b..ae714db3 100644 --- a/doc/config.but +++ b/doc/config.but @@ -1091,7 +1091,9 @@ empty box when the window loses focus; an underline or a vertical line becomes dotted. The \q{\ii{Cursor blinks}} option makes the cursor blink on and off. This -works in any of the cursor modes. +works in any of the cursor modes. (On Windows, the blink rate matches +that configured in Control Panel; so this setting will have no effect +if cursor blinking has been disabled system-wide.) \S{config-font} Controlling the \i{font} used in the terminal window diff --git a/terminal/terminal.c b/terminal/terminal.c index 0fad9eb8..574e8261 100644 --- a/terminal/terminal.c +++ b/terminal/terminal.c @@ -1381,9 +1381,10 @@ static void term_schedule_tblink(Terminal *term) */ static void term_schedule_cblink(Terminal *term) { - if (term->blink_cur && term->has_focus) { + int delay = CBLINK_DELAY; + if (term->blink_cur && term->has_focus && delay > 0) { if (!term->cblink_pending) - term->next_cblink = schedule_timer(CBLINK_DELAY, term_timer, term); + term->next_cblink = schedule_timer(delay, term_timer, term); term->cblink_pending = true; } else { term->cblinker = true; /* reset when not in use */ diff --git a/windows/CMakeLists.txt b/windows/CMakeLists.txt index 960a440d..1b5c6162 100644 --- a/windows/CMakeLists.txt +++ b/windows/CMakeLists.txt @@ -5,6 +5,7 @@ add_sources_from_current_dir(utils utils/agent_named_pipe_name.c utils/arm_arch_queries.c utils/aux_match_opt.c + utils/blink_time.c utils/centre_window.c utils/cmdline_arg.c utils/cryptoapi.c diff --git a/windows/platform.h b/windows/platform.h index 10551e87..0932e02a 100644 --- a/windows/platform.h +++ b/windows/platform.h @@ -203,8 +203,10 @@ void centre_window(HWND hwnd); #define PUTTY_CHM_FILE "putty.chm" +int get_caret_blink_time(void); + #define GETTICKCOUNT GetTickCount -#define CURSORBLINK GetCaretBlinkTime() +#define CURSORBLINK get_caret_blink_time() #define TICKSPERSEC 1000 /* GetTickCount returns milliseconds */ #define DEFAULT_CODEPAGE CP_ACP diff --git a/windows/utils/blink_time.c b/windows/utils/blink_time.c new file mode 100644 index 00000000..3a7ac400 --- /dev/null +++ b/windows/utils/blink_time.c @@ -0,0 +1,21 @@ +/* + * Wrapper for GetCaretBlinkTime() which turns it into a signed integer, + * with 0 meaning "no blinking". + */ + +#include "putty.h" +#include + +int get_caret_blink_time(void) +{ + UINT blinktime = GetCaretBlinkTime(); + if (blinktime == INFINITE) + /* Windows' registry representation for 'no caret blinking' + * is the string "-1", but we may as well use 0 as the sentinel + * value, as it'd be bad to attempt blinking with period 0 + * in any case. */ + return 0; + else + /* assume this won't be so big that casting is a problem */ + return (int) blinktime; +} From 578ed46f34430a5998046a1137ef5c1db15da8ac Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Thu, 24 Apr 2025 22:13:07 +0100 Subject: [PATCH 059/129] GTK: correct a misuse of WhitePixel and BlackPixel According to the X specs, WhitePixel and BlackPixel refer to permanent entries in the default colourmap. This means that they're not necessarily appropriate for use with a Drawable with a different depth than the root window. When drawing to a Pixmap that will be used as a 1-bit alpha mask by Cairo, the correct values are simply 0 (transparent) and 1 (opaque). --- unix/unifont.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/unix/unifont.c b/unix/unifont.c index 04a65ccf..0ac77120 100644 --- a/unix/unifont.c +++ b/unix/unifont.c @@ -677,8 +677,8 @@ static void x11font_cairo_setup( xfi->pixmap_surface = cairo_xlib_surface_create_for_bitmap( disp, xfi->pixmap, ScreenOfDisplay(disp, widgetscr), xfi->pixwidth, xfi->pixheight); - gcvals.foreground = WhitePixel(disp, widgetscr); - gcvals.background = BlackPixel(disp, widgetscr); + gcvals.foreground = 1; + gcvals.background = 0; gcvals.font = xfi->xfs->fid; xfi->gc = XCreateGC(disp, xfi->pixmap, GCForeground | GCBackground | GCFont, &gcvals); From 01043ce4fc90cee578a00872a64fd69e4bb7203a Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Sat, 26 Apr 2025 14:26:02 +0100 Subject: [PATCH 060/129] GTK: simpler text scaling under Cairo Rather than constructing a transformation matrix piece by piece (with very branchy code), draw_stretch_before now just calls cairo_translate() and cairo_scale() with values that are almost-obviously correct. Also, rather than stashing and restoring the transformation matrix ourselves, it seems simpler to use cairo_save() and cairo_restore(). That requires that draw_stretch_before() and draw_stretch_after() be called strictly in pairs, but they are so that's OK. --- unix/unifont.h | 1 - unix/window.c | 37 ++++++------------------------------- 2 files changed, 6 insertions(+), 32 deletions(-) diff --git a/unix/unifont.h b/unix/unifont.h index c0f01121..6e22c257 100644 --- a/unix/unifont.h +++ b/unix/unifont.h @@ -124,7 +124,6 @@ typedef struct unifont_drawctx { * screen number when creating server-side pixmaps */ GtkWidget *widget; cairo_t *cr; - cairo_matrix_t origmatrix; #if GTK_CHECK_VERSION(3,22,0) GdkWindow *gdkwin; GdkDrawingContext *drawctx; diff --git a/unix/window.c b/unix/window.c index 6029a9f4..66da32fa 100644 --- a/unix/window.c +++ b/unix/window.c @@ -918,8 +918,6 @@ static gboolean area_configured( #ifdef DRAW_TEXT_CAIRO static void cairo_setup_draw_ctx(GtkFrontend *inst) { - cairo_get_matrix(inst->uctx.u.cairo.cr, - &inst->uctx.u.cairo.origmatrix); cairo_set_line_width(inst->uctx.u.cairo.cr, 1.0); cairo_set_line_cap(inst->uctx.u.cairo.cr, CAIRO_LINE_CAP_SQUARE); cairo_set_line_join(inst->uctx.u.cairo.cr, CAIRO_LINE_JOIN_MITER); @@ -3808,31 +3806,10 @@ static void draw_stretch_before(GtkFrontend *inst, int x, int y, { #ifdef DRAW_TEXT_CAIRO if (inst->uctx.type == DRAWTYPE_CAIRO) { - cairo_matrix_t matrix; - - matrix.xy = 0; - matrix.yx = 0; - - if (wdouble) { - matrix.xx = 2; - matrix.x0 = -x; - } else { - matrix.xx = 1; - matrix.x0 = 0; - } - - if (hdouble) { - matrix.yy = 2; - if (hbothalf) { - matrix.y0 = -(y+h); - } else { - matrix.y0 = -y; - } - } else { - matrix.yy = 1; - matrix.y0 = 0; - } - cairo_transform(inst->uctx.u.cairo.cr, &matrix); + cairo_save(inst->uctx.u.cairo.cr); + cairo_translate(inst->uctx.u.cairo.cr, + -x * wdouble, -y * hdouble - h * hbothalf); + cairo_scale(inst->uctx.u.cairo.cr, 1 + wdouble, 1 + hdouble); } #endif } @@ -3887,10 +3864,8 @@ static void draw_stretch_after(GtkFrontend *inst, int x, int y, #endif #endif /* DRAW_TEXT_GDK */ #ifdef DRAW_TEXT_CAIRO - if (inst->uctx.type == DRAWTYPE_CAIRO) { - cairo_set_matrix(inst->uctx.u.cairo.cr, - &inst->uctx.u.cairo.origmatrix); - } + if (inst->uctx.type == DRAWTYPE_CAIRO) + cairo_restore(inst->uctx.u.cairo.cr); #endif } From c93a225b979e67bc04a9443104ab5505e9299d2e Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Thu, 10 Apr 2025 10:09:07 +0100 Subject: [PATCH 061/129] GTK: use cairo_paint() to copy from backing store to screen I just found cairo_paint() while wandering the Cairo documentation. It just fills the entire clip region with data from the current source, which is precisely what draw_area() wants to do. This is simpler for us than requesting the bounding rectangle of the clipping region and then filling it, and as far as I can tell the clipping rectangle generally covers the whole window anyway. --- unix/window.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/unix/window.c b/unix/window.c index 66da32fa..1379b6ef 100644 --- a/unix/window.c +++ b/unix/window.c @@ -953,7 +953,6 @@ static gint draw_area(GtkWidget *widget, cairo_t *cr, gpointer data) * inst->surface to the window. */ if (inst->surface) { - GdkRectangle dirtyrect; cairo_surface_t *target_surface; double orig_sx, orig_sy; cairo_matrix_t m; @@ -982,12 +981,8 @@ static gint draw_area(GtkWidget *widget, cairo_t *cr, gpointer data) cairo_surface_set_device_scale(target_surface, 1.0, 1.0); cairo_translate(cr, m.x0 * (orig_sx - 1.0), m.y0 * (orig_sy - 1.0)); - gdk_cairo_get_clip_rectangle(cr, &dirtyrect); - cairo_set_source_surface(cr, inst->surface, 0, 0); - cairo_rectangle(cr, dirtyrect.x, dirtyrect.y, - dirtyrect.width, dirtyrect.height); - cairo_fill(cr); + cairo_paint(cr); cairo_surface_set_device_scale(target_surface, orig_sx, orig_sy); } From daed7200b33f710853e8d2f0792c3ede596754ef Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Sat, 19 Apr 2025 09:13:06 +0100 Subject: [PATCH 062/129] GTK: create backing Cairo surface of similar type to window Specifically, this creates the surface using gdk_window_create_similar_surface() where that's available. --- unix/window.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/unix/window.c b/unix/window.c index 1379b6ef..bbaaa854 100644 --- a/unix/window.c +++ b/unix/window.c @@ -819,8 +819,14 @@ static void drawing_area_setup(GtkFrontend *inst, int width, int height) inst->surface = NULL; } +#if GTK_CHECK_VERSION(2,22,0) + inst->surface = gdk_window_create_similar_surface( + gtk_widget_get_window(inst->area), + CAIRO_CONTENT_COLOR, inst->backing_w, inst->backing_h); +#else inst->surface = cairo_image_surface_create( CAIRO_FORMAT_ARGB32, inst->backing_w, inst->backing_h); +#endif #endif draw_backing_rect(inst); From 1ebca75a89deb456da8f39a0804cb021f72c955e Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Sun, 20 Apr 2025 11:08:59 +0100 Subject: [PATCH 063/129] GTK: make inst->pixmap and inst->surface mutually exclusive This removes the case where we draw into a Cairo surface and then copy the results into a GdkPixmap. Now, if we've got a GdkPixmap, we just draw into it directly using Cairo. This vastly reduces the number of CopyArea operations needed to draw on the screen. --- unix/unifont.h | 6 ++++-- unix/window.c | 47 +++++++++++++---------------------------------- 2 files changed, 17 insertions(+), 36 deletions(-) diff --git a/unix/unifont.h b/unix/unifont.h index 6e22c257..687bfab3 100644 --- a/unix/unifont.h +++ b/unix/unifont.h @@ -40,8 +40,10 @@ * very simple rectangle-copy operation rather than a lot of fiddly * drawing or bitmap transfer. * - * However, GTK is deprecating the use of server-side pixmaps, so we - * have to disable this mode under some circumstances. + * For preference, we use a GdkPixmap for this, because both GDK and + * Cairo can draw to one of those. If those aren't available, then we + * instead create a Cairo surface that we hope will be backed by an X + * Pixmap. */ #define NO_BACKING_PIXMAPS #endif diff --git a/unix/window.c b/unix/window.c index bbaaa854..6454b1e9 100644 --- a/unix/window.c +++ b/unix/window.c @@ -108,21 +108,11 @@ struct GtkFrontend { * re-blit an appropriate rectangle from this pixmap. */ GdkPixmap *pixmap; -#endif -#ifdef DRAW_TEXT_CAIRO +#else /* - * If we're drawing using Cairo, we cache the same image on the - * client side in a Cairo surface. - * - * In GTK2+Cairo, this happens _as well_ as having the server-side - * pixmap cache above; in GTK3+Cairo, server-side pixmaps are - * deprecated, so we _just_ have this client-side cache. In the - * latter case that means we have to transmit a big wodge of - * bitmap data over the X connection on every expose event; but - * GTK3 apparently deliberately provides no way to avoid that - * inefficiency, and at least this way we don't _also_ have to - * redo any font rendering just because the window was temporarily - * covered. + * If we're avoiding GdkPixmaps, we cache the same image in a + * Cairo surface. Under X11, that surface will probably be a + * server-side pixmap. */ cairo_surface_t *surface; #endif @@ -811,9 +801,7 @@ static void drawing_area_setup(GtkFrontend *inst, int width, int height) inst->pixmap = gdk_pixmap_new(gtk_widget_get_window(inst->area), inst->backing_w, inst->backing_h, -1); -#endif - -#ifdef DRAW_TEXT_CAIRO +#else if (inst->surface) { cairo_surface_destroy(inst->surface); inst->surface = NULL; @@ -3592,10 +3580,15 @@ static bool gtkwin_setup_draw_ctx(TermWin *tw) #ifdef DRAW_TEXT_CAIRO if (inst->uctx.type == DRAWTYPE_CAIRO) { inst->uctx.u.cairo.widget = GTK_WIDGET(inst->area); - /* If we're doing Cairo drawing, we expect inst->surface to - * exist, and we draw to that first, regardless of whether we - * subsequently copy the results to inst->pixmap. */ + /* + * If we're doing Cairo drawing, we draw to the target pixmap + * if there is one, and otherwise to the backing surface. + */ +#ifdef NO_BACKING_PIXMAPS inst->uctx.u.cairo.cr = cairo_create(inst->surface); +#else + inst->uctx.u.cairo.cr = gdk_cairo_create(inst->pixmap); +#endif cairo_scale(inst->uctx.u.cairo.cr, inst->scale, inst->scale); cairo_setup_draw_ctx(inst); } @@ -3621,20 +3614,6 @@ static void gtkwin_free_draw_ctx(TermWin *tw) static void draw_update(GtkFrontend *inst, int x, int y, int w, int h) { -#if defined DRAW_TEXT_CAIRO && !defined NO_BACKING_PIXMAPS - if (inst->uctx.type == DRAWTYPE_CAIRO) { - /* - * If inst->surface and inst->pixmap both exist, then we've - * just drawn new content to the former which we must copy to - * the latter. - */ - cairo_t *cr = gdk_cairo_create(inst->pixmap); - cairo_set_source_surface(cr, inst->surface, 0, 0); - cairo_rectangle(cr, x, y, w, h); - cairo_fill(cr); - cairo_destroy(cr); - } -#endif /* * Now we just queue a window redraw, which will cause From 8260ea2237887da874c9e11958a050e1092a5de4 Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Sun, 20 Apr 2025 12:32:50 +0100 Subject: [PATCH 064/129] GTK: disable GTK double-buffering of terminal drawing area By default, when we're asked to draw a GTK widget, GTK creates a temporary surface (a Pixmap under X) and redirects our rendering into that. Then it blits that into the actual window. This is silly for PuTTY because all that PuTTY does to render its drawing area is to blit into it from _another_ surface. So now PuTTY asks GTK not to do that. According to the GTK documentation, GTK as of 3.10 has completely restructured its drawing routines so that turning off double-buffering actually makes things worse and slower, so we turn it off only in GTK 2 Still, this now means that painting text on the screen in GTK 2 causes precisely one CopyArea operation, which is what we want. --- unix/window.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/unix/window.c b/unix/window.c index 6454b1e9..726e6678 100644 --- a/unix/window.c +++ b/unix/window.c @@ -5356,6 +5356,15 @@ void new_session_window(Conf *conf, const char *geometry_string) inst->area = gtk_drawing_area_new(); gtk_widget_set_name(GTK_WIDGET(inst->area), "drawing-area"); +#if !GTK_CHECK_VERSION(3,0,0) + /* + * PuTTY does its own double-buffering, so we don't really need + * GTK to do it as well. GTK documentation says this is probably + * a bad idea from GTK 3.10 onwards, and it's officially + * deprecated from 3.14. But it definitely helps in GTK 2. + */ + gtk_widget_set_double_buffered(GTK_WIDGET(inst->area), false); +#endif /* * Try to create the fonts for use in the window. If this fails, From 08bc6703049b7ec53b4cd64fde663e69ec3c8580 Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Sun, 20 Apr 2025 18:29:48 +0100 Subject: [PATCH 065/129] GTK: never deliberately create an image surface for Cairo rendering If gdk_window_create_similar_surface() isn't available, we now fall back to cairo_surface_create_similar(). This is relevant only on GTK between 2.00 and 2.22 with deprecated calls disabled. --- unix/window.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/unix/window.c b/unix/window.c index 726e6678..fc798211 100644 --- a/unix/window.c +++ b/unix/window.c @@ -812,8 +812,11 @@ static void drawing_area_setup(GtkFrontend *inst, int width, int height) gtk_widget_get_window(inst->area), CAIRO_CONTENT_COLOR, inst->backing_w, inst->backing_h); #else - inst->surface = cairo_image_surface_create( - CAIRO_FORMAT_ARGB32, inst->backing_w, inst->backing_h); + cairo_t *tmp_cr = gdk_cairo_create(gtk_widget_get_window(inst->area)); + inst->surface = cairo_surface_create_similar( + cairo_get_target(tmp_cr), + CAIRO_CONTENT_COLOR, inst->backing_w, inst->backing_h); + cairo_destroy(tmp_cr); #endif #endif From 9bd1b234a098e366a16a02dc87b22fb500060dd3 Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Fri, 25 Apr 2025 20:12:12 +0100 Subject: [PATCH 066/129] GTK: purely server-side X bitmap font rendering with Cairo This is a fairly radical change of how X bitmap fonts are handled when using Cairo for rendering. Before, we would download each glyph to the client on first use and then composite those glyphs into the terminal's backing surface. This worked pretty well when we were keeping an image of the whole screen on the client anyway, but once I'd pushed all the other Cairo rendering onto the X server, it meant that the character bitmaps had to be repeatedly pushed to the X server. The new arrangement just renders each string into a temporary Pixmap using the usual X text-drawing calls and then asks Cairo to paste it into the main backing Pixmap. It's tempting to draw the text straight into the backing Pixmap, but that would require dealing directly with X colour management. This way, we get to leave colours in the hands of Cairo (and hence the Render extension). There are still fragments of the old system around. Those should go in the next commit. --- unix/unifont.c | 133 ++++++++++++++++++++++--------------------------- 1 file changed, 60 insertions(+), 73 deletions(-) diff --git a/unix/unifont.c b/unix/unifont.c index 0ac77120..fdc3d7c1 100644 --- a/unix/unifont.c +++ b/unix/unifont.c @@ -685,70 +685,41 @@ static void x11font_cairo_setup( } } -static void x11font_cairo_cache_glyph( - Display *disp, x11font_individual *xfi, int glyphindex) -{ - if (xfi->nglyphs <= glyphindex) { - /* Round up to the next multiple of 256 on the general - * principle that Unicode characters come in contiguous blocks - * often used together */ - int old_nglyphs = xfi->nglyphs; - xfi->nglyphs = (glyphindex + 0x100) & ~0xFF; - xfi->glyphcache = sresize(xfi->glyphcache, xfi->nglyphs, - struct cairo_cached_glyph); - - while (old_nglyphs < xfi->nglyphs) { - xfi->glyphcache[old_nglyphs].surface = NULL; - old_nglyphs++; - } - } - cairo_surface_mark_dirty(xfi->pixmap_surface); - xfi->glyphcache[glyphindex].surface = cairo_image_surface_create( - CAIRO_FORMAT_A1, xfi->pixwidth, xfi->pixheight); - cairo_t *cr = cairo_create(xfi->glyphcache[glyphindex].surface); - cairo_set_source_surface(cr, xfi->pixmap_surface, 0, 0); - cairo_paint(cr); - cairo_destroy(cr); -} - -static void x11font_cairo_draw_glyph(unifont_drawctx *ctx, - x11font_individual *xfi, int x, int y, - int glyphindex) -{ - if (xfi->glyphcache[glyphindex].surface) { - cairo_pattern_t *glyph_pattern = cairo_pattern_create_for_surface( - xfi->glyphcache[glyphindex].surface); - cairo_matrix_t xfrm; - /* We really don't want bilinear interpolation of bitmap fonts. */ - cairo_pattern_set_filter(glyph_pattern, CAIRO_FILTER_NEAREST); - cairo_matrix_init_translate(&xfrm, -(x - xfi->pixoriginx), - -(y - xfi->pixoriginy)); - cairo_pattern_set_matrix(glyph_pattern, &xfrm); - cairo_mask(ctx->u.cairo.cr, glyph_pattern); - cairo_pattern_destroy(glyph_pattern); - } -} - static void x11font_cairo_draw_16( unifont_drawctx *ctx, x11font_individual *xfi, Display *disp, int x, int y, const void *vstring, int start, int length) { const XChar2b *string = (const XChar2b *)vstring + start; - int i; - for (i = 0; i < length; i++) { - if (x11_font_has_glyph(xfi->xfs, string[i].byte1, string[i].byte2)) { - int glyphindex = (256 * (unsigned char)string[i].byte1 + - (unsigned char)string[i].byte2); - if (glyphindex >= xfi->nglyphs || - !xfi->glyphcache[glyphindex].surface) { - XDrawImageString16(disp, xfi->pixmap, xfi->gc, - xfi->pixoriginx, xfi->pixoriginy, - string+i, 1); - x11font_cairo_cache_glyph(disp, xfi, glyphindex); - } - x11font_cairo_draw_glyph(ctx, xfi, x, y, glyphindex); - x += XTextWidth16(xfi->xfs, string+i, 1); - } + GdkWindow *widgetwin = gtk_widget_get_window(ctx->u.cairo.widget); + int widgetscr = GDK_SCREEN_XNUMBER(gdk_window_get_screen(widgetwin)); + XCharStruct bounds; + int pixwidth, pixheight, direction, font_ascent, font_descent; + Pixmap pixmap; + + XTextExtents16(xfi->xfs, string + start, length, + &direction, &font_ascent, &font_descent, &bounds); + pixwidth = bounds.rbearing - bounds.lbearing; + pixheight = bounds.ascent + bounds.descent; + if (pixwidth > 0 && pixheight > 0) { + pixmap = XCreatePixmap(disp, GDK_DRAWABLE_XID(widgetwin), + pixwidth, pixheight, 1); + XDrawImageString16(disp, pixmap, xfi->gc, + -bounds.lbearing, bounds.ascent, + string+start, length); + cairo_surface_t *surface = cairo_xlib_surface_create_for_bitmap( + disp, pixmap, ScreenOfDisplay(disp, widgetscr), + pixwidth, pixheight); + cairo_pattern_t *pattern = cairo_pattern_create_for_surface(surface); + /* We really don't want bilinear interpolation of bitmap fonts. */ + cairo_pattern_set_filter(pattern, CAIRO_FILTER_NEAREST); + cairo_matrix_t xfrm; + cairo_matrix_init_translate(&xfrm, + -x - bounds.lbearing, -y + bounds.ascent); + cairo_pattern_set_matrix(pattern, &xfrm); + cairo_mask(ctx->u.cairo.cr, pattern); + cairo_pattern_destroy(pattern); + cairo_surface_destroy(surface); + XFreePixmap(disp, pixmap); } } @@ -757,20 +728,36 @@ static void x11font_cairo_draw_8( int x, int y, const void *vstring, int start, int length) { const char *string = (const char *)vstring + start; - int i; - for (i = 0; i < length; i++) { - if (x11_font_has_glyph(xfi->xfs, 0, string[i])) { - int glyphindex = (unsigned char)string[i]; - if (glyphindex >= xfi->nglyphs || - !xfi->glyphcache[glyphindex].surface) { - XDrawImageString(disp, xfi->pixmap, xfi->gc, - xfi->pixoriginx, xfi->pixoriginy, - string+i, 1); - x11font_cairo_cache_glyph(disp, xfi, glyphindex); - } - x11font_cairo_draw_glyph(ctx, xfi, x, y, glyphindex); - x += XTextWidth(xfi->xfs, string+i, 1); - } + GdkWindow *widgetwin = gtk_widget_get_window(ctx->u.cairo.widget); + int widgetscr = GDK_SCREEN_XNUMBER(gdk_window_get_screen(widgetwin)); + XCharStruct bounds; + int pixwidth, pixheight, direction, font_ascent, font_descent; + Pixmap pixmap; + + XTextExtents(xfi->xfs, string + start, length, + &direction, &font_ascent, &font_descent, &bounds); + pixwidth = bounds.rbearing - bounds.lbearing; + pixheight = bounds.ascent + bounds.descent; + if (pixwidth > 0 && pixheight > 0) { + pixmap = XCreatePixmap(disp, GDK_DRAWABLE_XID(widgetwin), + pixwidth, pixheight, 1); + XDrawImageString(disp, pixmap, xfi->gc, + -bounds.lbearing, bounds.ascent, + string+start, length); + cairo_surface_t *surface = cairo_xlib_surface_create_for_bitmap( + disp, pixmap, ScreenOfDisplay(disp, widgetscr), + pixwidth, pixheight); + cairo_pattern_t *pattern = cairo_pattern_create_for_surface(surface); + /* We really don't want bilinear interpolation of bitmap fonts. */ + cairo_pattern_set_filter(pattern, CAIRO_FILTER_NEAREST); + cairo_matrix_t xfrm; + cairo_matrix_init_translate(&xfrm, + -x - bounds.lbearing, -y + bounds.ascent); + cairo_pattern_set_matrix(pattern, &xfrm); + cairo_mask(ctx->u.cairo.cr, pattern); + cairo_pattern_destroy(pattern); + cairo_surface_destroy(surface); + XFreePixmap(disp, pixmap); } } #endif /* DRAW_TEXT_CAIRO */ From c3e2bf980ff379e91eea94fc4a05f326b742d635 Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Fri, 25 Apr 2025 20:52:58 +0100 Subject: [PATCH 067/129] GTK: clean up old X/Cairo font rendering code This requires deferring creating the X graphics context until we have a suitable Pixmap to base it on. --- unix/unifont.c | 64 +++++++++++++------------------------------------- 1 file changed, 16 insertions(+), 48 deletions(-) diff --git a/unix/unifont.c b/unix/unifont.c index fdc3d7c1..433a5509 100644 --- a/unix/unifont.c +++ b/unix/unifont.c @@ -154,22 +154,7 @@ typedef struct x11font_individual { bool allocated; #ifdef DRAW_TEXT_CAIRO - /* - * A cache of glyph bitmaps downloaded from the X server when - * we're in Cairo rendering mode. If glyphcache itself is - * non-NULL, then entries in [0,nglyphs) are expected to be - * initialised to either NULL or a bitmap pointer. - */ - struct cairo_cached_glyph *glyphcache; - int nglyphs; - - /* - * X server paraphernalia for actually downloading the glyphs. - */ - Pixmap pixmap; - cairo_surface_t *pixmap_surface; /* Cairo version of pixmap. */ GC gc; - int pixwidth, pixheight, pixoriginx, pixoriginy; #endif } x11font_individual; @@ -530,10 +515,6 @@ static unifont *x11font_create(GtkWidget *widget, const char *name, xfont->fonts[i].xfs = NULL; xfont->fonts[i].allocated = false; #ifdef DRAW_TEXT_CAIRO - xfont->fonts[i].glyphcache = NULL; - xfont->fonts[i].nglyphs = 0; - xfont->fonts[i].pixmap = None; - xfont->fonts[i].pixmap_surface = NULL; xfont->fonts[i].gc = None; #endif } @@ -555,17 +536,6 @@ static void x11font_destroy(unifont *font) #ifdef DRAW_TEXT_CAIRO if (xfont->fonts[i].gc != None) XFreeGC(disp, xfont->fonts[i].gc); - if (xfont->fonts[i].pixmap_surface != NULL) - cairo_surface_destroy(xfont->fonts[i].pixmap_surface); - if (xfont->fonts[i].pixmap != None) - XFreePixmap(disp, xfont->fonts[i].pixmap); - if (xfont->fonts[i].glyphcache) { - int j; - for (j = 0; j < xfont->fonts[i].nglyphs; j++) { - cairo_surface_destroy(xfont->fonts[i].glyphcache[j].surface); - } - sfree(xfont->fonts[i].glyphcache); - } #endif } sfree(xfont); @@ -659,28 +629,24 @@ static void x11font_gdk_draw_8(unifont_drawctx *ctx, x11font_individual *xfi, static void x11font_cairo_setup( unifont_drawctx *ctx, x11font_individual *xfi, Display *disp) { - if (xfi->pixmap == None) { + +} + +/* + * Creating an X GC requires a Drawable, so this gets deferred until + * we first need to draw something, and hence have something to draw + * on. + */ +static void x11font_cairo_init_gc(x11font_individual *xfi, Display *disp, + Pixmap pixmap) +{ + if (xfi->gc == None) { XGCValues gcvals; - GdkWindow *widgetwin = gtk_widget_get_window(ctx->u.cairo.widget); - int widgetscr = GDK_SCREEN_XNUMBER(gdk_window_get_screen(widgetwin)); - - xfi->pixwidth = - xfi->xfs->max_bounds.rbearing - xfi->xfs->min_bounds.lbearing; - xfi->pixheight = - xfi->xfs->max_bounds.ascent + xfi->xfs->max_bounds.descent; - xfi->pixoriginx = -xfi->xfs->min_bounds.lbearing; - xfi->pixoriginy = xfi->xfs->max_bounds.ascent; - - xfi->pixmap = XCreatePixmap( - disp, GDK_DRAWABLE_XID(gtk_widget_get_window(ctx->u.cairo.widget)), - xfi->pixwidth, xfi->pixheight, 1); - xfi->pixmap_surface = cairo_xlib_surface_create_for_bitmap( - disp, xfi->pixmap, ScreenOfDisplay(disp, widgetscr), - xfi->pixwidth, xfi->pixheight); + gcvals.foreground = 1; gcvals.background = 0; gcvals.font = xfi->xfs->fid; - xfi->gc = XCreateGC(disp, xfi->pixmap, + xfi->gc = XCreateGC(disp, pixmap, GCForeground | GCBackground | GCFont, &gcvals); } } @@ -703,6 +669,7 @@ static void x11font_cairo_draw_16( if (pixwidth > 0 && pixheight > 0) { pixmap = XCreatePixmap(disp, GDK_DRAWABLE_XID(widgetwin), pixwidth, pixheight, 1); + x11font_cairo_init_gc(xfi, disp, pixmap); XDrawImageString16(disp, pixmap, xfi->gc, -bounds.lbearing, bounds.ascent, string+start, length); @@ -741,6 +708,7 @@ static void x11font_cairo_draw_8( if (pixwidth > 0 && pixheight > 0) { pixmap = XCreatePixmap(disp, GDK_DRAWABLE_XID(widgetwin), pixwidth, pixheight, 1); + x11font_cairo_init_gc(xfi, disp, pixmap); XDrawImageString(disp, pixmap, xfi->gc, -bounds.lbearing, bounds.ascent, string+start, length); From 10fdd29feaf4e23a66d1a8c66ed50911246286ec Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Sat, 26 Apr 2025 22:14:49 +0100 Subject: [PATCH 068/129] GTK: clear target Pixmap for X font rendering with Cairo CreatePixmap returns a Pixmap with undefined contents, and ImageText16 doesn't quite erase the whole rectangle covered by the text (and hence the whole Pixmap. So to be on the safe side we should make sure to erase the entire Pixmap before drawing the text. Conveniently, ImageText16 ignores the function specified in the GC, so we can set that to GXclear and avoid needing to change the GC thereafter. --- unix/unifont.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/unix/unifont.c b/unix/unifont.c index 433a5509..b7bd1e49 100644 --- a/unix/unifont.c +++ b/unix/unifont.c @@ -643,11 +643,13 @@ static void x11font_cairo_init_gc(x11font_individual *xfi, Display *disp, if (xfi->gc == None) { XGCValues gcvals; + gcvals.function = GXclear; gcvals.foreground = 1; gcvals.background = 0; gcvals.font = xfi->xfs->fid; xfi->gc = XCreateGC(disp, pixmap, - GCForeground | GCBackground | GCFont, &gcvals); + GCFunction | GCForeground | GCBackground | GCFont, + &gcvals); } } @@ -670,6 +672,7 @@ static void x11font_cairo_draw_16( pixmap = XCreatePixmap(disp, GDK_DRAWABLE_XID(widgetwin), pixwidth, pixheight, 1); x11font_cairo_init_gc(xfi, disp, pixmap); + XFillRectangle(disp, pixmap, xfi->gc, 0, 0, pixwidth, pixheight); XDrawImageString16(disp, pixmap, xfi->gc, -bounds.lbearing, bounds.ascent, string+start, length); @@ -709,6 +712,7 @@ static void x11font_cairo_draw_8( pixmap = XCreatePixmap(disp, GDK_DRAWABLE_XID(widgetwin), pixwidth, pixheight, 1); x11font_cairo_init_gc(xfi, disp, pixmap); + XFillRectangle(disp, pixmap, xfi->gc, 0, 0, pixwidth, pixheight); XDrawImageString(disp, pixmap, xfi->gc, -bounds.lbearing, bounds.ascent, string+start, length); From 82da46d22ef15a7b84af0f608520c9f7005864ee Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Sun, 27 Apr 2025 14:43:50 +0100 Subject: [PATCH 069/129] GTK: remove most of the scale-factor support Now that we use gdk_window_create_similar_surface() to make our backing surface, most of the code to handle scale factors is unnecessary and indeed slightly harmful. gdk_window_create_similar_surface() creates a surface suitable for use as backing for a window, so it already has the scale factor applied. This means that it should be sized in nominal pixels, we can paint to it in nominal pixels, and the fact that it has the same extra resolution as the actual window is entirely transparent to us. Now the only reason we pay attention to the scale factor at all is to detect changes and use them as a prompt to re-create the backing surface. --- unix/window.c | 38 ++++---------------------------------- 1 file changed, 4 insertions(+), 34 deletions(-) diff --git a/unix/window.c b/unix/window.c index fc798211..567f68c1 100644 --- a/unix/window.c +++ b/unix/window.c @@ -756,10 +756,11 @@ static void drawing_area_setup(GtkFrontend *inst, int width, int height) new_scale = 1; #endif - int new_backing_w = width * new_scale; - int new_backing_h = height * new_scale; + int new_backing_w = width; + int new_backing_h = height; - if (inst->backing_w != new_backing_w || inst->backing_h != new_backing_h) + if (inst->backing_w != new_backing_w || inst->backing_h != new_backing_h + || inst->scale != new_scale) inst->drawing_area_setup_needed = true; /* @@ -950,38 +951,8 @@ static gint draw_area(GtkWidget *widget, cairo_t *cr, gpointer data) * inst->surface to the window. */ if (inst->surface) { - cairo_surface_t *target_surface; - double orig_sx, orig_sy; - cairo_matrix_t m; - - /* - * Furtle around in the Cairo setup to force the device scale - * back to 1, so that when we blit a collection of pixels from - * our backing surface into the window, they really are - * _pixels_ and not some confusing antialiased slightly-offset - * 2x2 rectangle of pixeloids. - * - * I have no idea whether GTK expects me not to mess with the - * device scale in the cairo_surface_t backing its window, so - * I carefully put it back when I've finished. - * - * In some GTK setups, the Cairo context we're given may not - * have a zero translation offset in its matrix, in which case - * we have to adjust that to compensate for the change of - * scale, or else the old translation offset (designed for the - * old scale) will be multiplied by the new scale instead and - * put everything in the wrong place. - */ - target_surface = cairo_get_target(cr); - cairo_get_matrix(cr, &m); - cairo_surface_get_device_scale(target_surface, &orig_sx, &orig_sy); - cairo_surface_set_device_scale(target_surface, 1.0, 1.0); - cairo_translate(cr, m.x0 * (orig_sx - 1.0), m.y0 * (orig_sy - 1.0)); - cairo_set_source_surface(cr, inst->surface, 0, 0); cairo_paint(cr); - - cairo_surface_set_device_scale(target_surface, orig_sx, orig_sy); } return true; @@ -3592,7 +3563,6 @@ static bool gtkwin_setup_draw_ctx(TermWin *tw) #else inst->uctx.u.cairo.cr = gdk_cairo_create(inst->pixmap); #endif - cairo_scale(inst->uctx.u.cairo.cr, inst->scale, inst->scale); cairo_setup_draw_ctx(inst); } #endif From d1a56d67ccc1c8be985c80362a337a94adacf6e8 Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Sun, 27 Apr 2025 14:55:12 +0100 Subject: [PATCH 070/129] GTK: use C99 designated initialisers to set up XGCValues I just think it looks nicer than a pile of assignments. --- unix/unifont.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/unix/unifont.c b/unix/unifont.c index b7bd1e49..8eada4c8 100644 --- a/unix/unifont.c +++ b/unix/unifont.c @@ -641,12 +641,13 @@ static void x11font_cairo_init_gc(x11font_individual *xfi, Display *disp, Pixmap pixmap) { if (xfi->gc == None) { - XGCValues gcvals; + XGCValues gcvals = { + .function = GXclear, + .foreground = 1, + .background = 0, + .font = xfi->xfs->fid, + }; - gcvals.function = GXclear; - gcvals.foreground = 1; - gcvals.background = 0; - gcvals.font = xfi->xfs->fid; xfi->gc = XCreateGC(disp, pixmap, GCFunction | GCForeground | GCBackground | GCFont, &gcvals); From dae2febd85390bd2afb73604a210bccbf9f92924 Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Wed, 30 Apr 2025 09:56:07 +0100 Subject: [PATCH 071/129] GTK: don't try to turn off double-buffering on GTK 1 Apparently GTK 1 lacks gtk_widget_set_double_buffered(), so it should be conditional on running GTK 2. --- unix/window.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unix/window.c b/unix/window.c index 567f68c1..b3baf4af 100644 --- a/unix/window.c +++ b/unix/window.c @@ -5329,7 +5329,7 @@ void new_session_window(Conf *conf, const char *geometry_string) inst->area = gtk_drawing_area_new(); gtk_widget_set_name(GTK_WIDGET(inst->area), "drawing-area"); -#if !GTK_CHECK_VERSION(3,0,0) +#if GTK_CHECK_VERSION(2,0,0) && !GTK_CHECK_VERSION(3,0,0) /* * PuTTY does its own double-buffering, so we don't really need * GTK to do it as well. GTK documentation says this is probably From c60b2832f41fa2abbb576291efdb57dfa8819152 Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Wed, 30 Apr 2025 23:27:43 +0100 Subject: [PATCH 072/129] GTK: flush target Cairo surface in 'draw' handler In 687efc3a5da1fb85c86a3c871b00a7234b97c2e9, Simon noted that when PuTTY was running under X and using an RGB24 image surface as its backing surface, it would fail to draw on its window. Changing the backing image to ARGB32 caused the problem to go away. If you set GDK_BACKEND=x11 and GDK_RENDERING=image, then PuTTY's gdk_window_create_similar_surface() returns an RGB24 image surface, and it appears to have precisely the same problem. Dumping the surfaces to PNG files revealed that Cairo thought they had the right context. But xtruss didn't show any actual requests to write to the window. So on a hunch approximately as well-informed as Simon's, I added a call to cairo_flush(), to explicitly ask Cairo to flush its changes to the underlying surface. I would have hoped that GTK would do something like this for us, but adding that call seems to have made things work properly. Like Simon, I have no idea if this is the correct fix, but it seems like a reasonable one and the problem is no longer occurring for me. --- unix/window.c | 1 + 1 file changed, 1 insertion(+) diff --git a/unix/window.c b/unix/window.c index b3baf4af..a37b55de 100644 --- a/unix/window.c +++ b/unix/window.c @@ -953,6 +953,7 @@ static gint draw_area(GtkWidget *widget, cairo_t *cr, gpointer data) if (inst->surface) { cairo_set_source_surface(cr, inst->surface, 0, 0); cairo_paint(cr); + cairo_surface_flush(cairo_get_target(cr)); } return true; From 647d5a49d27fcce41db06ddb847b9c9a8937caee Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Wed, 30 Apr 2025 23:40:48 +0100 Subject: [PATCH 073/129] GTK: correct a comment calling Cairo surface "client-side" Our Cairo backing surface can be server-side now. Indeed I think it always is under GTK 2 where that comment applies. --- unix/window.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unix/window.c b/unix/window.c index a37b55de..f2ce224a 100644 --- a/unix/window.c +++ b/unix/window.c @@ -979,7 +979,7 @@ gint expose_area(GtkWidget *widget, GdkEventExpose *event, gpointer data) } #else /* - * Failing that, draw from the client-side Cairo surface. (We + * Failing that, draw from the backing Cairo surface. (We * should never be compiled in a context where we have _neither_ * inst->surface nor inst->pixmap.) */ From fcadb5fed1fb8cd51a97e4652f3cf12bf4c8fb9e Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Mon, 5 May 2025 13:52:40 +0100 Subject: [PATCH 074/129] GTK: use only 16-bit X text drawing calls Xlib and the X protocol provide text handling calls in versions that take both 8-bit and 16-bit character indices. They are mostly interchangable, except that of course the 8-bit calls can only access characters with codes up to 255. Heretofore, PuTTY used the 16-bit X calls when using a font in the "iso10646-1" encoding and 8-bit calls otherwise. This led to a lot of duplicate code, and in particular two large and almost identical implementations of x11font_cairo_draw*(). Now, PuTTY uses 16-bit calls throughout, even when using an 8-bit font encoding. This simplifies the code at the expense of needing an extra bit of conversion to expand the char array that we get from put_wc_to_mb() into an array of XChar2b when using an 8-bit font. --- unix/unifont.c | 156 +++++++++++++------------------------------------ 1 file changed, 40 insertions(+), 116 deletions(-) diff --git a/unix/unifont.c b/unix/unifont.c index 8eada4c8..8df1d256 100644 --- a/unix/unifont.c +++ b/unix/unifont.c @@ -173,7 +173,8 @@ struct x11font { /* * `sixteen_bit' is true iff the font object is indexed by * values larger than a byte. That is, this flag tells us - * whether we use XDrawString or XDrawString16, etc. + * whether the font is encoded in Unicode. If not, we need + * to translate text into the font character set. */ bool sixteen_bit; /* @@ -329,16 +330,10 @@ static char *x11_guess_derived_font_name(Display *disp, XFontStruct *xfs, return NULL; } -static int x11_font_width(XFontStruct *xfs, bool sixteen_bit) +static int x11_font_width(XFontStruct *xfs) { - if (sixteen_bit) { - XChar2b space; - space.byte1 = 0; - space.byte2 = '0'; - return XTextWidth16(xfs, &space, 1); - } else { - return XTextWidth(xfs, "0", 1); - } + XChar2b space = { 0, '0' }; + return XTextWidth16(xfs, &space, 1); } static const XCharStruct *x11_char_struct( @@ -488,7 +483,7 @@ static unifont *x11font_create(GtkWidget *widget, const char *name, xfont = snew(struct x11font); xfont->u.vt = &x11font_vtable; - xfont->u.width = x11_font_width(xfs, sixteen_bit); + xfont->u.width = x11_font_width(xfs); xfont->u.ascent = xfs->ascent; xfont->u.descent = xfs->descent; xfont->u.height = xfont->u.ascent + xfont->u.descent; @@ -585,20 +580,12 @@ static bool x11font_has_glyph(unifont *font, wchar_t glyph) #define GDK_DRAWABLE_XID(d) GDK_WINDOW_XID(d) /* GTK3's name for this */ #endif -static int x11font_width_16(unifont_drawctx *ctx, x11font_individual *xfi, - const void *vstring, int start, int length) +static int x11font_width(unifont_drawctx *ctx, x11font_individual *xfi, + const XChar2b *string, int start, int length) { - const XChar2b *string = (const XChar2b *)vstring; return XTextWidth16(xfi->xfs, string+start, length); } -static int x11font_width_8(unifont_drawctx *ctx, x11font_individual *xfi, - const void *vstring, int start, int length) -{ - const char *string = (const char *)vstring; - return XTextWidth(xfi->xfs, string+start, length); -} - #ifdef DRAW_TEXT_GDK static void x11font_gdk_setup(unifont_drawctx *ctx, x11font_individual *xfi, Display *disp) @@ -606,23 +593,13 @@ static void x11font_gdk_setup(unifont_drawctx *ctx, x11font_individual *xfi, XSetFont(disp, GDK_GC_XGC(ctx->u.gdk.gc), xfi->xfs->fid); } -static void x11font_gdk_draw_16(unifont_drawctx *ctx, x11font_individual *xfi, - Display *disp, int x, int y, - const void *vstring, int start, int length) +static void x11font_gdk_draw(unifont_drawctx *ctx, x11font_individual *xfi, + Display *disp, int x, int y, + const XChar2b *string, int start, int length) { - const XChar2b *string = (const XChar2b *)vstring; XDrawString16(disp, GDK_DRAWABLE_XID(ctx->u.gdk.target), GDK_GC_XGC(ctx->u.gdk.gc), x, y, string+start, length); } - -static void x11font_gdk_draw_8(unifont_drawctx *ctx, x11font_individual *xfi, - Display *disp, int x, int y, - const void *vstring, int start, int length) -{ - const char *string = (const char *)vstring; - XDrawString(disp, GDK_DRAWABLE_XID(ctx->u.gdk.target), - GDK_GC_XGC(ctx->u.gdk.gc), x, y, string+start, length); -} #endif #ifdef DRAW_TEXT_CAIRO @@ -654,11 +631,10 @@ static void x11font_cairo_init_gc(x11font_individual *xfi, Display *disp, } } -static void x11font_cairo_draw_16( +static void x11font_cairo_draw( unifont_drawctx *ctx, x11font_individual *xfi, Display *disp, - int x, int y, const void *vstring, int start, int length) + int x, int y, const XChar2b *string, int start, int length) { - const XChar2b *string = (const XChar2b *)vstring + start; GdkWindow *widgetwin = gtk_widget_get_window(ctx->u.cairo.widget); int widgetscr = GDK_SCREEN_XNUMBER(gdk_window_get_screen(widgetwin)); XCharStruct bounds; @@ -693,88 +669,35 @@ static void x11font_cairo_draw_16( XFreePixmap(disp, pixmap); } } - -static void x11font_cairo_draw_8( - unifont_drawctx *ctx, x11font_individual *xfi, Display *disp, - int x, int y, const void *vstring, int start, int length) -{ - const char *string = (const char *)vstring + start; - GdkWindow *widgetwin = gtk_widget_get_window(ctx->u.cairo.widget); - int widgetscr = GDK_SCREEN_XNUMBER(gdk_window_get_screen(widgetwin)); - XCharStruct bounds; - int pixwidth, pixheight, direction, font_ascent, font_descent; - Pixmap pixmap; - - XTextExtents(xfi->xfs, string + start, length, - &direction, &font_ascent, &font_descent, &bounds); - pixwidth = bounds.rbearing - bounds.lbearing; - pixheight = bounds.ascent + bounds.descent; - if (pixwidth > 0 && pixheight > 0) { - pixmap = XCreatePixmap(disp, GDK_DRAWABLE_XID(widgetwin), - pixwidth, pixheight, 1); - x11font_cairo_init_gc(xfi, disp, pixmap); - XFillRectangle(disp, pixmap, xfi->gc, 0, 0, pixwidth, pixheight); - XDrawImageString(disp, pixmap, xfi->gc, - -bounds.lbearing, bounds.ascent, - string+start, length); - cairo_surface_t *surface = cairo_xlib_surface_create_for_bitmap( - disp, pixmap, ScreenOfDisplay(disp, widgetscr), - pixwidth, pixheight); - cairo_pattern_t *pattern = cairo_pattern_create_for_surface(surface); - /* We really don't want bilinear interpolation of bitmap fonts. */ - cairo_pattern_set_filter(pattern, CAIRO_FILTER_NEAREST); - cairo_matrix_t xfrm; - cairo_matrix_init_translate(&xfrm, - -x - bounds.lbearing, -y + bounds.ascent); - cairo_pattern_set_matrix(pattern, &xfrm); - cairo_mask(ctx->u.cairo.cr, pattern); - cairo_pattern_destroy(pattern); - cairo_surface_destroy(surface); - XFreePixmap(disp, pixmap); - } -} #endif /* DRAW_TEXT_CAIRO */ struct x11font_drawfuncs { int (*width)(unifont_drawctx *ctx, x11font_individual *xfi, - const void *vstring, int start, int length); + const XChar2b *string, int start, int length); void (*setup)(unifont_drawctx *ctx, x11font_individual *xfi, Display *disp); void (*draw)(unifont_drawctx *ctx, x11font_individual *xfi, Display *disp, - int x, int y, const void *vstring, int start, int length); + int x, int y, const XChar2b *string, int start, int length); }; /* - * This array has two entries per compiled-in drawtype; of each pair, - * the first is for an 8-bit font and the second for 16-bit. + * This array has one entry per compiled-in drawtype. */ -static const struct x11font_drawfuncs x11font_drawfuncs[2*DRAWTYPE_NTYPES] = { +static const struct x11font_drawfuncs x11font_drawfuncs[DRAWTYPE_NTYPES] = { #ifdef DRAW_TEXT_GDK - /* gdk, 8-bit */ - { - x11font_width_8, - x11font_gdk_setup, - x11font_gdk_draw_8, - }, - /* gdk, 16-bit */ + /* gdk */ { - x11font_width_16, + x11font_width, x11font_gdk_setup, - x11font_gdk_draw_16, + x11font_gdk_draw, }, #endif #ifdef DRAW_TEXT_CAIRO - /* cairo, 8-bit */ + /* cairo */ { - x11font_width_8, + x11font_width, x11font_cairo_setup, - x11font_cairo_draw_8, - }, - /* [3] cairo, 16-bit */ - { - x11font_width_16, - x11font_cairo_setup, - x11font_cairo_draw_16, + x11font_cairo_draw, }, #endif }; @@ -830,7 +753,7 @@ static void x11font_draw_text(unifont_drawctx *ctx, unifont *font, int sfid; int shadowoffset = 0; int mult = (wide ? 2 : 1); - int index = 2 * (int)ctx->type; + int index = (int)ctx->type; wide = wide && !xfont->wide; bold = bold && !xfont->bold; @@ -857,25 +780,19 @@ static void x11font_draw_text(unifont_drawctx *ctx, unifont *font, if (!xfont->fonts[sfid].xfs) return; /* we've tried our best, but no luck */ + XChar2b *xcs; + int i, xcslen; if (xfont->sixteen_bit) { /* * This X font has 16-bit character indices, which means * we can directly use our Unicode input string. */ - XChar2b *xcs; - int i; - - xcs = snewn(len, XChar2b); - for (i = 0; i < len; i++) { + xcslen = len; + xcs = snewn(xcslen, XChar2b); + for (i = 0; i < xcslen; i++) { xcs[i].byte1 = string[i] >> 8; xcs[i].byte2 = string[i]; } - - x11font_really_draw_text(x11font_drawfuncs + index + 1, ctx, - &xfont->fonts[sfid], xfont->disp, x, y, - xcs, len, shadowoffset, - xfont->variable, cellwidth * mult); - sfree(xcs); } else { /* * This X font has 8-bit indices, so we must convert to the @@ -883,12 +800,19 @@ static void x11font_draw_text(unifont_drawctx *ctx, unifont *font, */ strbuf *sb = strbuf_new(); put_wc_to_mb(sb, xfont->real_charset, string, len, "."); - x11font_really_draw_text(x11font_drawfuncs + index + 0, ctx, - &xfont->fonts[sfid], xfont->disp, x, y, - sb->s, sb->len, shadowoffset, - xfont->variable, cellwidth * mult); + xcslen = sb->len; + xcs = snewn(xcslen, XChar2b); + for (i = 0; i < xcslen; i++) { + xcs[i].byte1 = 0; + xcs[i].byte2 = sb->s[i]; + } strbuf_free(sb); } + x11font_really_draw_text(x11font_drawfuncs + index, ctx, + &xfont->fonts[sfid], xfont->disp, x, y, + xcs, xcslen, shadowoffset, + xfont->variable, cellwidth * mult); + sfree(xcs); } static void x11font_draw_combining(unifont_drawctx *ctx, unifont *font, From a0a92da03547f321b0b293219446f4bebb7d778b Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Mon, 5 May 2025 18:39:05 +0100 Subject: [PATCH 075/129] GTK: don't try to use X fonts for characters outside BMP X fonts are indexed by 16-bit quantities, so even Unicode-capable fonts can only have characters in the Basic Multilingual Plane (BMP). PuTTY, however, tried to look up all Unicode characters in X fonts, and did so by effectively ignoring all but the low-order 16 bits of the character code. This meant that trying to display a non-BMP character could get you the corresponding character from the BMP instead, if that character was in the font. Now, x11font_has_glyph() always returns false for glyphs outside the BMP, which should mean that x11font_draw_text() never gets asked to draw them. --- unix/unifont.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/unix/unifont.c b/unix/unifont.c index 8df1d256..d8289ecd 100644 --- a/unix/unifont.c +++ b/unix/unifont.c @@ -554,10 +554,11 @@ static bool x11font_has_glyph(unifont *font, wchar_t glyph) if (xfont->sixteen_bit) { /* * This X font has 16-bit character indices, which means - * we can directly use our Unicode input value. + * we can directly use our Unicode input value as long as + * it's in the BMP. */ - return x11_font_has_glyph(xfont->fonts[0].xfs, - glyph >> 8, glyph & 0xFF); + return glyph < 0x10000 && + x11_font_has_glyph(xfont->fonts[0].xfs, glyph >> 8, glyph & 0xFF); } else { /* * This X font has 8-bit indices, so we must convert to the @@ -790,6 +791,8 @@ static void x11font_draw_text(unifont_drawctx *ctx, unifont *font, xcslen = len; xcs = snewn(xcslen, XChar2b); for (i = 0; i < xcslen; i++) { + /* We shouldn't see any character not in the font. */ + assert(string[i] < 0x10000); xcs[i].byte1 = string[i] >> 8; xcs[i].byte2 = string[i]; } From 19353dca858fb76b399a173d8a96f122b62786ca Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Mon, 5 May 2025 23:02:18 +0100 Subject: [PATCH 076/129] GTK: faster rendering of X fonts under Cairo Switching to server-side rendering of X fonts under Cairo turned out to make text rendering much slower, at least on my laptop. This appears to be because PuTTY was asking the X server to render text into a 1-bit-per-pixel (bpp) pixmap before having Cairo composite into the terminal surface. On modern X servers 1bpp pixmaps are slow, being largely un-accelerated. Happily, it is possible to get Cairo to use an 8bpp pixmap instead, and this is rather faster. It's a bit inconvenient, though, because first we have to confirm that that the X Rendering Extensions is present and find the correct picture format. That requires linking in libXrender, which means a bit of CMake faff. For now, I've make libXrender mandatory (for X11 builds), but it and the corresponding Cairo functions could be made optional fairly simply. This hasn't actually made text rendering as much faster as I'd like on my laptop. While creating 1bpp pixmaps is nearly free, creating 8bpp pixmaps takes significant time because they actually involve the GPU. So I think now I need to rework my persistent-pixmap patch to work on top of this one. --- cmake/platforms/unix.cmake | 2 +- unix/CMakeLists.txt | 10 ++++---- unix/unifont.c | 48 +++++++++++++++++++++++++++++++------- 3 files changed, 46 insertions(+), 14 deletions(-) diff --git a/cmake/platforms/unix.cmake b/cmake/platforms/unix.cmake index 4d056d0a..4ae8c313 100644 --- a/cmake/platforms/unix.cmake +++ b/cmake/platforms/unix.cmake @@ -89,7 +89,7 @@ if(GTK_FOUND) list(APPEND CMAKE_REQUIRED_INCLUDES ${GTK_INCLUDE_DIRS}) check_include_file(gdk/gdkx.h HAVE_GDK_GDKX_H) - if(X11_FOUND AND HAVE_GDK_GDKX_H) + if(X11_FOUND AND X11_Xrender_FOUND AND HAVE_GDK_GDKX_H) set(NOT_X_WINDOWS OFF PARENT_SCOPE) else() set(NOT_X_WINDOWS ON PARENT_SCOPE) diff --git a/unix/CMakeLists.txt b/unix/CMakeLists.txt index 87ee6574..df5d275d 100644 --- a/unix/CMakeLists.txt +++ b/unix/CMakeLists.txt @@ -153,7 +153,7 @@ if(GTK_FOUND) be_list(pterm pterm) target_link_libraries(pterm guiterminal eventloop settings utils ptermxpms - ${GTK_LIBRARIES} ${X11_LIBRARIES}) + ${GTK_LIBRARIES} ${X11_LIBRARIES} ${X11_Xrender_LIB}) installed_program(pterm) if(GTK_VERSION GREATER_EQUAL 3) @@ -170,7 +170,7 @@ if(GTK_FOUND) be_list(ptermapp pterm) target_link_libraries(ptermapp guiterminal eventloop settings utils ptermxpms - ${GTK_LIBRARIES} ${X11_LIBRARIES}) + ${GTK_LIBRARIES} ${X11_LIBRARIES} ${X11_Xrender_LIB}) endif() add_executable(putty @@ -181,7 +181,7 @@ if(GTK_FOUND) target_link_libraries(putty guiterminal eventloop sshclient otherbackends settings network crypto utils puttyxpms - ${GTK_LIBRARIES} ${X11_LIBRARIES}) + ${GTK_LIBRARIES} ${X11_LIBRARIES} ${X11_Xrender_LIB}) set_target_properties(putty PROPERTIES LINK_INTERFACE_MULTIPLICITY 2) installed_program(putty) @@ -196,7 +196,7 @@ if(GTK_FOUND) target_link_libraries(puttyapp guiterminal eventloop sshclient otherbackends settings network crypto utils puttyxpms - ${GTK_LIBRARIES} ${X11_LIBRARIES}) + ${GTK_LIBRARIES} ${X11_LIBRARIES} ${X11_Xrender_LIB}) endif() add_executable(puttytel @@ -213,7 +213,7 @@ if(GTK_FOUND) target_link_libraries(puttytel guiterminal eventloop otherbackends settings network utils puttyxpms - ${GTK_LIBRARIES} ${X11_LIBRARIES}) + ${GTK_LIBRARIES} ${X11_LIBRARIES} ${X11_Xrender_LIB}) add_executable(test_lineedit ${CMAKE_SOURCE_DIR}/test/test_lineedit.c diff --git a/unix/unifont.c b/unix/unifont.c index d8289ecd..6fb1e0ff 100644 --- a/unix/unifont.c +++ b/unix/unifont.c @@ -29,6 +29,8 @@ #ifndef NOT_X_WINDOWS #ifdef DRAW_TEXT_CAIRO #include +#include +#include #endif #include #include @@ -154,6 +156,7 @@ typedef struct x11font_individual { bool allocated; #ifdef DRAW_TEXT_CAIRO + XRenderPictFormat *pictformat; GC gc; #endif @@ -607,7 +610,26 @@ static void x11font_gdk_draw(unifont_drawctx *ctx, x11font_individual *xfi, static void x11font_cairo_setup( unifont_drawctx *ctx, x11font_individual *xfi, Display *disp) { - + /* + * To render X fonts under Cairo, we use the usual X font rendering + * requests to draw text into a pixmap, make a Cairo surface out + * of it, and then use that as a mask to paint the current colour + * into the terminal surface. This means that colours are + * entirely in the hands of Cairo and we don't have to think about + * X colourmaps. But we do need to be able to create that pixmap. + * + * All X servers are required to support 1bpp pixmaps, and Cairo + * can always use one of them as a mask. But on 2025's X servers, + * 1bpp font rendering is unaccelerated and hence much slower than + * on deeper drawables. So we find out if we can make an 8-bit + * alpha-only surface, and only fall back to a 1bpp pixmap if that + * fails. + * + * XRenderFindStandardFormat() will return NULL if the X Rendering + * Extension is missing or unusable, so we don't need to check + * that in advance. + */ + xfi->pictformat = XRenderFindStandardFormat(disp, PictStandardA8); } /* @@ -621,7 +643,7 @@ static void x11font_cairo_init_gc(x11font_individual *xfi, Display *disp, if (xfi->gc == None) { XGCValues gcvals = { .function = GXclear, - .foreground = 1, + .foreground = 0xffffffff, .background = 0, .font = xfi->xfs->fid, }; @@ -646,17 +668,27 @@ static void x11font_cairo_draw( &direction, &font_ascent, &font_descent, &bounds); pixwidth = bounds.rbearing - bounds.lbearing; pixheight = bounds.ascent + bounds.descent; - if (pixwidth > 0 && pixheight > 0) { - pixmap = XCreatePixmap(disp, GDK_DRAWABLE_XID(widgetwin), - pixwidth, pixheight, 1); + if (pixwidth > 0 && pixheight > 0) { + cairo_surface_t *surface; + if (xfi->pictformat != NULL) { + pixmap = XCreatePixmap(disp, GDK_DRAWABLE_XID(widgetwin), + pixwidth, pixheight, 8); + surface = cairo_xlib_surface_create_with_xrender_format( + disp, pixmap, ScreenOfDisplay(disp, widgetscr), + xfi->pictformat, pixwidth, pixheight); + } else { + pixmap = XCreatePixmap(disp, GDK_DRAWABLE_XID(widgetwin), + pixwidth, pixheight, 1); + surface = cairo_xlib_surface_create_for_bitmap( + disp, pixmap, ScreenOfDisplay(disp, widgetscr), + pixwidth, pixheight); + } x11font_cairo_init_gc(xfi, disp, pixmap); XFillRectangle(disp, pixmap, xfi->gc, 0, 0, pixwidth, pixheight); XDrawImageString16(disp, pixmap, xfi->gc, -bounds.lbearing, bounds.ascent, string+start, length); - cairo_surface_t *surface = cairo_xlib_surface_create_for_bitmap( - disp, pixmap, ScreenOfDisplay(disp, widgetscr), - pixwidth, pixheight); + cairo_surface_mark_dirty(surface); cairo_pattern_t *pattern = cairo_pattern_create_for_surface(surface); /* We really don't want bilinear interpolation of bitmap fonts. */ cairo_pattern_set_filter(pattern, CAIRO_FILTER_NEAREST); From 649c8155e78a63a2ed5aa9d878c748ce19bc9451 Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Tue, 6 May 2025 21:08:00 +0100 Subject: [PATCH 077/129] GTK: use a persistent pixmap for rendering X fonts under Cairo Instead of creating a new pixmap for each text-rendering operation, we now stash one (along with the various Cairo structures associated with it) in the xfont_individual structure. This saves the 20% or so of Xwayland's CPU time that was being spent on CreatePixmap requests. --- unix/unifont.c | 146 +++++++++++++++++++++++++++++-------------------- 1 file changed, 86 insertions(+), 60 deletions(-) diff --git a/unix/unifont.c b/unix/unifont.c index 6fb1e0ff..9b7df28c 100644 --- a/unix/unifont.c +++ b/unix/unifont.c @@ -156,7 +156,11 @@ typedef struct x11font_individual { bool allocated; #ifdef DRAW_TEXT_CAIRO - XRenderPictFormat *pictformat; + /* Cached pixmap etc for drawing into. */ + Pixmap pixmap; + int pixwidth, pixheight, pixdepth; + cairo_surface_t *surface; + cairo_pattern_t *pattern; GC gc; #endif @@ -513,6 +517,11 @@ static unifont *x11font_create(GtkWidget *widget, const char *name, xfont->fonts[i].xfs = NULL; xfont->fonts[i].allocated = false; #ifdef DRAW_TEXT_CAIRO + xfont->fonts[i].pixmap = None; + xfont->fonts[i].pixwidth = xfont->fonts[i].pixheight = 0; + xfont->fonts[i].pixdepth = 0; + xfont->fonts[i].surface = NULL; + xfont->fonts[i].pattern = NULL; xfont->fonts[i].gc = None; #endif } @@ -534,6 +543,12 @@ static void x11font_destroy(unifont *font) #ifdef DRAW_TEXT_CAIRO if (xfont->fonts[i].gc != None) XFreeGC(disp, xfont->fonts[i].gc); + if (xfont->fonts[i].pattern != NULL) + cairo_pattern_destroy(xfont->fonts[i].pattern); + if (xfont->fonts[i].surface != NULL) + cairo_surface_destroy(xfont->fonts[i].surface); + if (xfont->fonts[i].pixmap != None) + XFreePixmap(disp, xfont->fonts[i].pixmap); #endif } sfree(xfont); @@ -610,96 +625,107 @@ static void x11font_gdk_draw(unifont_drawctx *ctx, x11font_individual *xfi, static void x11font_cairo_setup( unifont_drawctx *ctx, x11font_individual *xfi, Display *disp) { - /* - * To render X fonts under Cairo, we use the usual X font rendering - * requests to draw text into a pixmap, make a Cairo surface out - * of it, and then use that as a mask to paint the current colour - * into the terminal surface. This means that colours are - * entirely in the hands of Cairo and we don't have to think about - * X colourmaps. But we do need to be able to create that pixmap. - * - * All X servers are required to support 1bpp pixmaps, and Cairo - * can always use one of them as a mask. But on 2025's X servers, - * 1bpp font rendering is unaccelerated and hence much slower than - * on deeper drawables. So we find out if we can make an 8-bit - * alpha-only surface, and only fall back to a 1bpp pixmap if that - * fails. - * - * XRenderFindStandardFormat() will return NULL if the X Rendering - * Extension is missing or unusable, so we don't need to check - * that in advance. - */ - xfi->pictformat = XRenderFindStandardFormat(disp, PictStandardA8); + } -/* - * Creating an X GC requires a Drawable, so this gets deferred until - * we first need to draw something, and hence have something to draw - * on. - */ -static void x11font_cairo_init_gc(x11font_individual *xfi, Display *disp, - Pixmap pixmap) +static void x11font_cairo_ensure_pixmap( + unifont_drawctx *ctx, x11font_individual *xfi, Display *disp, + int width, int height) { - if (xfi->gc == None) { + Pixmap newpixmap; + XRenderPictFormat *pictformat = NULL; + + if (xfi->pixmap != None + && xfi->pixwidth >= width && xfi->pixheight >= height) return; + if (xfi->pixmap == None) { + /* + * To render X fonts under Cairo, we use the usual X font + * rendering requests to draw text into a pixmap that's also a + * Cairo surface and then use that as a mask to paint the + * current colour into the terminal surface. This means that + * colours are entirely in the hands of Cairo and we don't + * have to think about X colourmaps. But we do need to be + * able to create that pixmap. + * + * All X servers are required to support 1bpp pixmaps, and + * Cairo can always use one of them as a mask. But on 2025's + * X servers, 1bpp font rendering is unaccelerated and hence + * much slower than on deeper drawables. So we find out if we + * can make an 8-bit alpha-only surface, and only fall back to + * a 1bpp pixmap if that fails. + * + * XRenderFindStandardFormat() will return NULL if the X + * Rendering Extension is missing or unusable, so we don't + * need to check that in advance. + */ + pictformat = XRenderFindStandardFormat(disp, PictStandardA8); + if (pictformat != NULL) + xfi->pixdepth = 8; + else + xfi->pixdepth = 1; + } + if (width < xfi->pixwidth) width = xfi->pixwidth; + if (height < xfi->pixheight) height = xfi->pixheight; + newpixmap = XCreatePixmap( + disp, GDK_DRAWABLE_XID(gtk_widget_get_window(ctx->u.cairo.widget)), + width, height, xfi->pixdepth); + if (xfi->pixmap != None) { + assert(xfi->surface != NULL); + cairo_xlib_surface_set_drawable(xfi->surface, newpixmap, + width, height); + XFreePixmap(disp, xfi->pixmap); + } else { + Screen *widgetscr = + GDK_SCREEN_XSCREEN(gtk_widget_get_screen(ctx->u.cairo.widget)); + if (pictformat != NULL) + xfi->surface = cairo_xlib_surface_create_with_xrender_format( + disp, newpixmap, widgetscr, pictformat, width, height); + else + xfi->surface = cairo_xlib_surface_create_for_bitmap( + disp, newpixmap, widgetscr, width, height); + xfi->pattern = cairo_pattern_create_for_surface(xfi->surface); + /* We really don't want bilinear interpolation of bitmap fonts. */ + cairo_pattern_set_filter(xfi->pattern, CAIRO_FILTER_NEAREST); XGCValues gcvals = { .function = GXclear, .foreground = 0xffffffff, .background = 0, .font = xfi->xfs->fid, }; - - xfi->gc = XCreateGC(disp, pixmap, + xfi->gc = XCreateGC(disp, newpixmap, GCFunction | GCForeground | GCBackground | GCFont, &gcvals); } + XFillRectangle(disp, newpixmap, xfi->gc, 0, 0, width, height); + xfi->pixmap = newpixmap; + xfi->pixwidth = width; + xfi->pixheight = height; } static void x11font_cairo_draw( unifont_drawctx *ctx, x11font_individual *xfi, Display *disp, int x, int y, const XChar2b *string, int start, int length) { - GdkWindow *widgetwin = gtk_widget_get_window(ctx->u.cairo.widget); - int widgetscr = GDK_SCREEN_XNUMBER(gdk_window_get_screen(widgetwin)); XCharStruct bounds; int pixwidth, pixheight, direction, font_ascent, font_descent; - Pixmap pixmap; XTextExtents16(xfi->xfs, string + start, length, &direction, &font_ascent, &font_descent, &bounds); pixwidth = bounds.rbearing - bounds.lbearing; pixheight = bounds.ascent + bounds.descent; if (pixwidth > 0 && pixheight > 0) { - cairo_surface_t *surface; - if (xfi->pictformat != NULL) { - pixmap = XCreatePixmap(disp, GDK_DRAWABLE_XID(widgetwin), - pixwidth, pixheight, 8); - surface = cairo_xlib_surface_create_with_xrender_format( - disp, pixmap, ScreenOfDisplay(disp, widgetscr), - xfi->pictformat, pixwidth, pixheight); - } else { - pixmap = XCreatePixmap(disp, GDK_DRAWABLE_XID(widgetwin), - pixwidth, pixheight, 1); - surface = cairo_xlib_surface_create_for_bitmap( - disp, pixmap, ScreenOfDisplay(disp, widgetscr), - pixwidth, pixheight); - } - x11font_cairo_init_gc(xfi, disp, pixmap); - XFillRectangle(disp, pixmap, xfi->gc, 0, 0, pixwidth, pixheight); - XDrawImageString16(disp, pixmap, xfi->gc, + x11font_cairo_ensure_pixmap(ctx, xfi, disp, pixwidth, pixheight); + XDrawImageString16(disp, xfi->pixmap, xfi->gc, -bounds.lbearing, bounds.ascent, string+start, length); - cairo_surface_mark_dirty(surface); - cairo_pattern_t *pattern = cairo_pattern_create_for_surface(surface); - /* We really don't want bilinear interpolation of bitmap fonts. */ - cairo_pattern_set_filter(pattern, CAIRO_FILTER_NEAREST); + cairo_surface_mark_dirty(xfi->surface); cairo_matrix_t xfrm; cairo_matrix_init_translate(&xfrm, -x - bounds.lbearing, -y + bounds.ascent); - cairo_pattern_set_matrix(pattern, &xfrm); - cairo_mask(ctx->u.cairo.cr, pattern); - cairo_pattern_destroy(pattern); - cairo_surface_destroy(surface); - XFreePixmap(disp, pixmap); + cairo_pattern_set_matrix(xfi->pattern, &xfrm); + cairo_mask(ctx->u.cairo.cr, xfi->pattern); + /* Clear the part of the pixmap that we used. */ + XFillRectangle(disp, xfi->pixmap, xfi->gc, 0, 0, pixwidth, pixheight); } } #endif /* DRAW_TEXT_CAIRO */ From b66ec0c25751f432745448333d95727391092f2a Mon Sep 17 00:00:00 2001 From: Ben Harris Date: Tue, 6 May 2025 22:17:45 +0100 Subject: [PATCH 078/129] GTK/x11font/Cairo: use XDrawString16 instead of XDrawImageString16 On my test case, this reduces Xwayland's CPU usage by 5-10%, though curiously in glamor_block_handler rather than the drawing routine itself. XDrawImageString16 isn't as helpful as it might be for two reasons. First, "M" type fonts (e.g. Courier Oblique) can extend beyond the rectangle erased by XDrawImageString16, and PuTTY tries to support such fonts. And second, we really want to blank the pixmap after drawing rather than before, because otherwise we have to muck around clipping the mask operation. So avoinding the XFillRectangle calls is difficult, at which point we may as well use XDrawString16. --- unix/unifont.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/unix/unifont.c b/unix/unifont.c index 9b7df28c..497fcfc6 100644 --- a/unix/unifont.c +++ b/unix/unifont.c @@ -686,16 +686,10 @@ static void x11font_cairo_ensure_pixmap( xfi->pattern = cairo_pattern_create_for_surface(xfi->surface); /* We really don't want bilinear interpolation of bitmap fonts. */ cairo_pattern_set_filter(xfi->pattern, CAIRO_FILTER_NEAREST); - XGCValues gcvals = { - .function = GXclear, - .foreground = 0xffffffff, - .background = 0, - .font = xfi->xfs->fid, - }; - xfi->gc = XCreateGC(disp, newpixmap, - GCFunction | GCForeground | GCBackground | GCFont, - &gcvals); + XGCValues gcvals = { .font = xfi->xfs->fid }; + xfi->gc = XCreateGC(disp, newpixmap, GCFont, &gcvals); } + XSetFunction(disp, xfi->gc, GXclear); XFillRectangle(disp, newpixmap, xfi->gc, 0, 0, width, height); xfi->pixmap = newpixmap; xfi->pixwidth = width; @@ -715,7 +709,8 @@ static void x11font_cairo_draw( pixheight = bounds.ascent + bounds.descent; if (pixwidth > 0 && pixheight > 0) { x11font_cairo_ensure_pixmap(ctx, xfi, disp, pixwidth, pixheight); - XDrawImageString16(disp, xfi->pixmap, xfi->gc, + XSetFunction(disp, xfi->gc, GXset); + XDrawString16(disp, xfi->pixmap, xfi->gc, -bounds.lbearing, bounds.ascent, string+start, length); cairo_surface_mark_dirty(xfi->surface); @@ -725,6 +720,7 @@ static void x11font_cairo_draw( cairo_pattern_set_matrix(xfi->pattern, &xfrm); cairo_mask(ctx->u.cairo.cr, xfi->pattern); /* Clear the part of the pixmap that we used. */ + XSetFunction(disp, xfi->gc, GXclear); XFillRectangle(disp, xfi->pixmap, xfi->gc, 0, 0, pixwidth, pixheight); } } From 91ad3af01c45cc43e2705569dc1555789f2fd3f6 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Wed, 28 May 2025 08:40:40 +0100 Subject: [PATCH 079/129] Use MSG_NOSIGNAL when sending on network sockets. This prevents send(2) from terminating the whole process with SIGPIPE if the socket has gone away. Since PuTTY manages multiple network connections (due to port forwarding and X11 forwarding), and some of the outlying tools like psusan can manage even more (multiple entire sessions running at once), you never want the whole application to die of SIGPIPE in this situation: you just want that one connection (perhaps a forwarding) to be cleanly aborted, and a failure indication sent back over another connection. Even if the main connection really does get EPIPE, you'd still prefer a sensible error message. I tried using psusan this week to forward X11 into a Podman container, by means of sharing a host directory into the container, making psusan bind to a Unix socket in that directory, and telling host PuTTY to connect to that Unix socket and speak bare ssh-connection. The X application locked up mysteriously, and when I tried to ^C it from the main host PuTTY window, psusan in the container died of SIGPIPE at this call site. (The locked-up X app was pterm, which would also be worrying if it weren't for the fact that I can't reproduce it on current main, only on 0.83. I suspect Ben's many recent GTK improvements have fixed something in this area in passing.) --- unix/network.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unix/network.c b/unix/network.c index 00848ab8..6271a706 100644 --- a/unix/network.c +++ b/unix/network.c @@ -1121,7 +1121,7 @@ void try_send(NetSocket *s) data = bufdata.ptr; len = bufdata.len; } - nsent = send(s->s, data, len, urgentflag); + nsent = send(s->s, data, len, MSG_NOSIGNAL | urgentflag); noise_ultralight(NOISE_SOURCE_IOLEN, nsent); if (nsent <= 0) { err = (nsent < 0 ? errno : 0); From 26a8ef376daf5f50c441a65691b84f87df49db9b Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Wed, 25 Jun 2025 13:02:56 +0100 Subject: [PATCH 080/129] Fix crash in utmp-stamping on Wayland. Thanks to Colin Watson for the report: if pterm is both able (appropriately setgid) and willing (given the right options) to stamp utmp, it will use $DISPLAY as the location to write into utmp, and segfault if it's not set. But in a Wayland-only system it might very well not be set. To fix this I've generalised seat_get_x_display() into seat_get_display(), so that it can also return a display id string like "wayland-0" if that's what's appropriate. So now in that situation pterm will stamp utmp with a Wayland display id in place of an X11 one. However, seat_get_x_display() was also used to retrieve an X11 display name specifically so as to populate $DISPLAY in the terminal's shell. So the new seat_get_display() has a parameter to constrain the returned display to be of a particular type, or NULL if that type isn't available. As a final fallback, in case seat_get_display(seat, SDISP_ANY) might _still_ manage to return NULL for any reason, we catch that and turn it into the empty string before stamping utmp, so that we still won't segfault. --- proxy/sshproxy.c | 2 +- pscp.c | 2 +- psftp.c | 2 +- putty.h | 20 ++++++++++++++------ ssh/server.c | 2 +- ssh/sesschan.c | 4 ++-- stubs/null-seat.c | 3 ++- unix/plink.c | 2 +- unix/pty.c | 7 +++++-- unix/window.c | 14 +++++++------- utils/tempseat.c | 6 +++--- windows/plink.c | 2 +- windows/window.c | 2 +- 13 files changed, 40 insertions(+), 28 deletions(-) diff --git a/proxy/sshproxy.c b/proxy/sshproxy.c index 0958c3cd..848b986e 100644 --- a/proxy/sshproxy.c +++ b/proxy/sshproxy.c @@ -583,7 +583,7 @@ static const SeatVtable SshProxy_seat_vt = { .prompt_descriptions = sshproxy_prompt_descriptions, .is_utf8 = nullseat_is_never_utf8, .echoedit_update = nullseat_echoedit_update, - .get_x_display = nullseat_get_x_display, + .get_display = nullseat_get_display, .get_windowid = nullseat_get_windowid, .get_window_pixel_size = nullseat_get_window_pixel_size, .stripctrl_new = sshproxy_stripctrl_new, diff --git a/pscp.c b/pscp.c index c7c4623f..1aa812eb 100644 --- a/pscp.c +++ b/pscp.c @@ -81,7 +81,7 @@ static const SeatVtable pscp_seat_vt = { .prompt_descriptions = console_prompt_descriptions, .is_utf8 = nullseat_is_never_utf8, .echoedit_update = nullseat_echoedit_update, - .get_x_display = nullseat_get_x_display, + .get_display = nullseat_get_display, .get_windowid = nullseat_get_windowid, .get_window_pixel_size = nullseat_get_window_pixel_size, .stripctrl_new = console_stripctrl_new, diff --git a/psftp.c b/psftp.c index b33e29a9..927ac688 100644 --- a/psftp.c +++ b/psftp.c @@ -62,7 +62,7 @@ static const SeatVtable psftp_seat_vt = { .prompt_descriptions = console_prompt_descriptions, .is_utf8 = nullseat_is_never_utf8, .echoedit_update = nullseat_echoedit_update, - .get_x_display = nullseat_get_x_display, + .get_display = nullseat_get_display, .get_windowid = nullseat_get_windowid, .get_window_pixel_size = nullseat_get_window_pixel_size, .stripctrl_new = console_stripctrl_new, diff --git a/putty.h b/putty.h index ce39d680..cc379f99 100644 --- a/putty.h +++ b/putty.h @@ -1070,6 +1070,11 @@ void seat_dialog_text_free(SeatDialogText *sdt); PRINTF_LIKE(3, 4) void seat_dialog_text_append( SeatDialogText *sdt, SeatDialogTextType type, const char *fmt, ...); +/* Parameter to seat_get_display */ +typedef enum SeatDisplayType { + SDISP_X11, SDISP_ANY +} SeatDisplayType; + /* * Data type 'Seat', which is an API intended to contain essentially * everything that a back end might need to talk to its client for: @@ -1299,10 +1304,13 @@ struct SeatVtable { void (*echoedit_update)(Seat *seat, bool echoing, bool editing); /* - * Return the local X display string relevant to a seat, or NULL - * if there isn't one or if the concept is meaningless. + * Return a string describing the GUI display (e.g. X11 or + * Wayland) relevant to a seat, or NULL if there isn't one or if + * the concept is meaningless. If dtype is not SDISP_ANY then only + * a display string of the requested type will be returned, or + * NULL if the available display is of a different type. */ - const char *(*get_x_display)(Seat *seat); + const char *(*get_display)(Seat *seat, SeatDisplayType dtype); /* * Return the X11 id of the X terminal window relevant to a seat, @@ -1426,8 +1434,8 @@ static inline bool seat_is_utf8(Seat *seat) { return seat->vt->is_utf8(seat); } static inline void seat_echoedit_update(Seat *seat, bool ec, bool ed) { seat->vt->echoedit_update(seat, ec, ed); } -static inline const char *seat_get_x_display(Seat *seat) -{ return seat->vt->get_x_display(seat); } +static inline const char *seat_get_display(Seat *seat, SeatDisplayType dtype) +{ return seat->vt->get_display(seat, dtype); } static inline bool seat_get_windowid(Seat *seat, long *id_out) { return seat->vt->get_windowid(seat, id_out); } static inline bool seat_get_window_pixel_size(Seat *seat, int *w, int *h) @@ -1515,7 +1523,7 @@ const SeatDialogPromptDescriptions *nullseat_prompt_descriptions(Seat *seat); bool nullseat_is_never_utf8(Seat *seat); bool nullseat_is_always_utf8(Seat *seat); void nullseat_echoedit_update(Seat *seat, bool echoing, bool editing); -const char *nullseat_get_x_display(Seat *seat); +const char *nullseat_get_display(Seat *seat, SeatDisplayType dtype); bool nullseat_get_windowid(Seat *seat, long *id_out); bool nullseat_get_window_pixel_size(Seat *seat, int *width, int *height); StripCtrlChars *nullseat_stripctrl_new( diff --git a/ssh/server.c b/ssh/server.c index 97fc5841..3ff9a59f 100644 --- a/ssh/server.c +++ b/ssh/server.c @@ -126,7 +126,7 @@ static const SeatVtable server_seat_vt = { .prompt_descriptions = nullseat_prompt_descriptions, .is_utf8 = nullseat_is_never_utf8, .echoedit_update = nullseat_echoedit_update, - .get_x_display = nullseat_get_x_display, + .get_display = nullseat_get_display, .get_windowid = nullseat_get_windowid, .get_window_pixel_size = nullseat_get_window_pixel_size, .stripctrl_new = nullseat_stripctrl_new, diff --git a/ssh/sesschan.c b/ssh/sesschan.c index cc50fd5c..504875ae 100644 --- a/ssh/sesschan.c +++ b/ssh/sesschan.c @@ -203,7 +203,7 @@ static const SeatVtable sesschan_seat_vt = { .prompt_descriptions = nullseat_prompt_descriptions, .is_utf8 = nullseat_is_never_utf8, .echoedit_update = nullseat_echoedit_update, - .get_x_display = nullseat_get_x_display, + .get_display = nullseat_get_display, .get_windowid = nullseat_get_windowid, .get_window_pixel_size = sesschan_get_window_pixel_size, .stripctrl_new = nullseat_stripctrl_new, @@ -310,7 +310,7 @@ static void sesschan_start_backend(sesschan *sess, const char *cmd) * confusingly set in the absence of that. * * (DISPLAY must also be cleared, but pty.c will do that anyway - * when our get_x_display method returns NULL.) + * when our get_display method returns NULL.) */ static const char *const env_to_unset[] = { "XAUTHORITY", "SSH_AUTH_SOCK", "SSH_AGENT_PID", diff --git a/stubs/null-seat.c b/stubs/null-seat.c index 67c25af0..e50f1668 100644 --- a/stubs/null-seat.c +++ b/stubs/null-seat.c @@ -37,7 +37,8 @@ SeatPromptResult nullseat_confirm_weak_cached_hostkey( bool nullseat_is_never_utf8(Seat *seat) { return false; } bool nullseat_is_always_utf8(Seat *seat) { return true; } void nullseat_echoedit_update(Seat *seat, bool echoing, bool editing) {} -const char *nullseat_get_x_display(Seat *seat) { return NULL; } +const char *nullseat_get_display(Seat *seat, SeatDisplayType dtype) +{ return NULL; } bool nullseat_get_windowid(Seat *seat, long *id_out) { return false; } bool nullseat_get_window_pixel_size( Seat *seat, int *width, int *height) { return false; } diff --git a/unix/plink.c b/unix/plink.c index d5db2c2a..8bae403d 100644 --- a/unix/plink.c +++ b/unix/plink.c @@ -419,7 +419,7 @@ static const SeatVtable plink_seat_vt = { .prompt_descriptions = console_prompt_descriptions, .is_utf8 = nullseat_is_never_utf8, .echoedit_update = plink_echoedit_update, - .get_x_display = nullseat_get_x_display, + .get_display = nullseat_get_display, .get_windowid = nullseat_get_windowid, .get_window_pixel_size = nullseat_get_window_pixel_size, .stripctrl_new = console_stripctrl_new, diff --git a/unix/pty.c b/unix/pty.c index 2e3ca749..9270a539 100644 --- a/unix/pty.c +++ b/unix/pty.c @@ -958,7 +958,10 @@ Backend *pty_backend_create( close(pty_utmp_helper_pipe); pty_utmp_helper_pipe = -1; } else { - const char *location = seat_get_x_display(pty->seat); + const char *location = seat_get_display(pty->seat, SDISP_ANY); + if (!location) + location = ""; + int len = strlen(location)+1, pos = 0; /* +1 to include NUL */ while (pos < len) { int ret = write(pty_utmp_helper_pipe, @@ -1133,7 +1136,7 @@ Backend *pty_backend_create( * terminal to match the display the terminal itself is * on. */ - const char *x_display = seat_get_x_display(pty->seat); + const char *x_display = seat_get_display(pty->seat, SDISP_X11); if (x_display) { char *x_display_env_var = dupprintf("DISPLAY=%s", x_display); putenv(x_display_env_var); diff --git a/unix/window.c b/unix/window.c index f2ce224a..52fe0cbb 100644 --- a/unix/window.c +++ b/unix/window.c @@ -402,7 +402,7 @@ static void gtk_seat_notify_remote_exit(Seat *seat); static void gtk_seat_update_specials_menu(Seat *seat); static void gtk_seat_set_busy_status(Seat *seat, BusyStatus status); #ifndef NOT_X_WINDOWS -static const char *gtk_seat_get_x_display(Seat *seat); +static const char *gtk_seat_get_display(Seat *seat, SeatDisplayType dtype); static bool gtk_seat_get_windowid(Seat *seat, long *id); #endif static void gtk_seat_set_trust_status(Seat *seat, bool trusted); @@ -430,10 +430,10 @@ static const SeatVtable gtk_seat_vt = { .is_utf8 = gtk_seat_is_utf8, .echoedit_update = nullseat_echoedit_update, #ifdef NOT_X_WINDOWS - .get_x_display = nullseat_get_x_display, + .get_display = nullseat_get_display, .get_windowid = nullseat_get_windowid, #else - .get_x_display = gtk_seat_get_x_display, + .get_display = gtk_seat_get_display, .get_windowid = gtk_seat_get_windowid, #endif .get_window_pixel_size = gtk_seat_get_window_pixel_size, @@ -4331,11 +4331,11 @@ void modalfatalbox(const char *p, ...) } #ifndef NOT_X_WINDOWS -static const char *gtk_seat_get_x_display(Seat *seat) +static const char *gtk_seat_get_display(Seat *seat, SeatDisplayType dtype) { - if (GDK_IS_X11_DISPLAY(gdk_display_get_default())) - return gdk_get_display(); - return NULL; + if (dtype == SDISP_X11 && !GDK_IS_X11_DISPLAY(gdk_display_get_default())) + return NULL; + return gdk_get_display(); } static bool gtk_seat_get_windowid(Seat *seat, long *id) diff --git a/utils/tempseat.c b/utils/tempseat.c index 4e4e2b13..a64d599c 100644 --- a/utils/tempseat.c +++ b/utils/tempseat.c @@ -149,10 +149,10 @@ static bool tempseat_is_utf8(Seat *seat) return seat_is_utf8(ts->realseat); } -static const char *tempseat_get_x_display(Seat *seat) +static const char *tempseat_get_display(Seat *seat, SeatDisplayType dtype) { TempSeat *ts = container_of(seat, TempSeat, seat); - return seat_get_x_display(ts->realseat); + return seat_get_display(ts->realseat, dtype); } static bool tempseat_get_windowid(Seat *seat, long *id_out) @@ -348,7 +348,7 @@ static const struct SeatVtable tempseat_vt = { .prompt_descriptions = tempseat_prompt_descriptions, .is_utf8 = tempseat_is_utf8, .echoedit_update = tempseat_echoedit_update, - .get_x_display = tempseat_get_x_display, + .get_display = tempseat_get_display, .get_windowid = tempseat_get_windowid, .get_window_pixel_size = tempseat_get_window_pixel_size, .stripctrl_new = tempseat_stripctrl_new, diff --git a/windows/plink.c b/windows/plink.c index face662f..4a25f7d7 100644 --- a/windows/plink.c +++ b/windows/plink.c @@ -107,7 +107,7 @@ static const SeatVtable plink_seat_vt = { .prompt_descriptions = console_prompt_descriptions, .is_utf8 = nullseat_is_never_utf8, .echoedit_update = plink_echoedit_update, - .get_x_display = nullseat_get_x_display, + .get_display = nullseat_get_display, .get_windowid = nullseat_get_windowid, .get_window_pixel_size = nullseat_get_window_pixel_size, .stripctrl_new = console_stripctrl_new, diff --git a/windows/window.c b/windows/window.c index e28ec652..5f8d549c 100644 --- a/windows/window.c +++ b/windows/window.c @@ -267,7 +267,7 @@ static const SeatVtable win_seat_vt = { .prompt_descriptions = win_seat_prompt_descriptions, .is_utf8 = win_seat_is_utf8, .echoedit_update = nullseat_echoedit_update, - .get_x_display = nullseat_get_x_display, + .get_display = nullseat_get_display, .get_windowid = nullseat_get_windowid, .get_window_pixel_size = win_seat_get_window_pixel_size, .stripctrl_new = win_seat_stripctrl_new, From 0c5fd787135608dc55cc13418ef37cc00236ed64 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Thu, 24 Jul 2025 08:18:10 +0100 Subject: [PATCH 081/129] GTK: stop using GDK_CURRENT_TIME. gtk_get_current_event_time() is better: it returns the X server timestamp associated with any event currently being handled. And if there isn't one, it falls back to returning GDK_CURRENT_TIME, so it doesn't do any worse than hardcoding GDK_CURRENT_TIME did. --- unix/askpass.c | 8 ++++---- unix/dialog.c | 2 +- unix/gtkcompat.h | 1 + 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/unix/askpass.c b/unix/askpass.c index bdd62519..f74fc7e6 100644 --- a/unix/askpass.c +++ b/unix/askpass.c @@ -320,13 +320,13 @@ static gboolean try_grab_keyboard(gpointer vctx) true, GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK, NULL, - GDK_CURRENT_TIME); + gtk_get_current_event_time()); #else /* * It's much simpler in GTK 1 and 2! */ ret = gdk_keyboard_grab(gtk_widget_get_window(ctx->dialog), - false, GDK_CURRENT_TIME); + false, gtk_get_current_event_time()); #endif if (ret != GDK_GRAB_SUCCESS) goto fail; @@ -527,9 +527,9 @@ static void gtk_askpass_cleanup(struct askpass_ctx *ctx) gdk_seat_ungrab(ctx->seat); #elif GTK_CHECK_VERSION(3,0,0) if (ctx->keyboard) - gdk_device_ungrab(ctx->keyboard, GDK_CURRENT_TIME); + gdk_device_ungrab(ctx->keyboard, gtk_get_current_event_time()); #else - gdk_keyboard_ungrab(GDK_CURRENT_TIME); + gdk_keyboard_ungrab(gtk_get_current_event_time()); #endif gtk_grab_remove(ctx->promptlabel); diff --git a/unix/dialog.c b/unix/dialog.c index 0838ff03..f947548b 100644 --- a/unix/dialog.c +++ b/unix/dialog.c @@ -4063,7 +4063,7 @@ static void eventlog_list_handler(dlgcontrol *ctrl, dlgparam *dp, } if (gtk_selection_owner_set(es->window, GDK_SELECTION_PRIMARY, - GDK_CURRENT_TIME)) { + gtk_get_current_event_time())) { gtk_selection_add_target(es->window, GDK_SELECTION_PRIMARY, GDK_SELECTION_TYPE_STRING, 1); gtk_selection_add_target(es->window, GDK_SELECTION_PRIMARY, diff --git a/unix/gtkcompat.h b/unix/gtkcompat.h index 02768323..3d1e756f 100644 --- a/unix/gtkcompat.h +++ b/unix/gtkcompat.h @@ -72,6 +72,7 @@ #define gtk_adjustment_get_value(a) ((a)->value) #define gtk_selection_data_get_selection(a) ((a)->selection) #define gdk_display_beep(disp) gdk_beep() +#define gtk_get_current_event_time() GDK_CURRENT_TIME #define gtk_widget_set_has_window(w, b) \ gtk1_widget_set_unset_flag(w, GTK_NO_WINDOW, !(b)) From edce58d49dfa17586b2f407fd668dd4dcc41496b Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sat, 26 Jul 2025 09:59:55 +0100 Subject: [PATCH 082/129] HTTP proxy: fix misspelled error message (and comment). A 407 response from the proxy is expected to contain at least one header naming an acceptable authentication method. The header name is "Proxy-Authenticate". But if no such header is seen, our error message incorrectly spelled the missing header name as "Proxy-Authorization". That's a braino rather than a typo: "Proxy-Authorization" is the header the _client_ sends for an actual attempt to authenticate. --- proxy/http.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proxy/http.c b/proxy/http.c index 0738e37d..e083a9da 100644 --- a/proxy/http.c +++ b/proxy/http.c @@ -492,14 +492,14 @@ static void proxy_http_process_queue(ProxyNegotiator *pn) if (s->http_status == 407) { /* * If this is going to be an auth request, we expect to - * see at least one Proxy-Authorization header offering us + * see at least one Proxy-Authenticate header offering us * auth options. Start by preloading s->next_auth with a * fallback error message, which will be used if nothing * better is available. */ http_auth_details_free(s->next_auth); s->next_auth = http_auth_details_new(); - auth_error(s->next_auth, "no Proxy-Authorization header seen in " + auth_error(s->next_auth, "no Proxy-Authenticate header seen in " "HTTP 407 Proxy Authentication Required response"); } From b7db18690b518dc0e9d668bb50c81b485ea449ba Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Fri, 25 Jul 2025 08:28:53 +0100 Subject: [PATCH 083/129] More general function to delete toplevel callbacks. For cases where you want a more subtle criterion than "cites this particular context structure". I'm going to introduce one in the next commit. --- callback.c | 21 +++++++++++++++++---- putty.h | 3 +++ 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/callback.c b/callback.c index ea647af4..dd69f028 100644 --- a/callback.c +++ b/callback.c @@ -41,7 +41,9 @@ void queue_idempotent_callback(struct IdempotentCallback *ic) queue_toplevel_callback(run_idempotent_callback, ic); } -void delete_callbacks_for_context(void *ctx) +void delete_callbacks( + bool (*delete_this_one)(void *predicate_ctx, toplevel_callback_fn_t fn, + void *callback_ctx), void *predicate_ctx) { struct callback *newhead, *newtail; @@ -49,9 +51,7 @@ void delete_callbacks_for_context(void *ctx) while (cbhead) { struct callback *cb = cbhead; cbhead = cbhead->next; - if (cb->ctx == ctx || - (cb->fn == run_idempotent_callback && - ((struct IdempotentCallback *)cb->ctx)->ctx == ctx)) { + if (delete_this_one(predicate_ctx, cb->fn, cb->ctx)) { sfree(cb); } else { if (!newhead) @@ -69,6 +69,19 @@ void delete_callbacks_for_context(void *ctx) newtail->next = NULL; } +static bool callback_is_for_context( + void *predicate_ctx, toplevel_callback_fn_t fn, void *callback_ctx) +{ + return callback_ctx == predicate_ctx || + (fn == run_idempotent_callback && + ((struct IdempotentCallback *)callback_ctx)->ctx == predicate_ctx); +} + +void delete_callbacks_for_context(void *ctx) +{ + delete_callbacks(callback_is_for_context, ctx); +} + void queue_toplevel_callback(toplevel_callback_fn_t fn, void *ctx) { struct callback *cb; diff --git a/putty.h b/putty.h index cc379f99..7f000fdb 100644 --- a/putty.h +++ b/putty.h @@ -2703,6 +2703,9 @@ unsigned long timing_last_clock(void); void queue_toplevel_callback(toplevel_callback_fn_t fn, void *ctx); bool run_toplevel_callbacks(void); bool toplevel_callback_pending(void); +void delete_callbacks( + bool (*delete_this_one)(void *predicate_ctx, toplevel_callback_fn_t fn, + void *callback_ctx), void *predicate_ctx); void delete_callbacks_for_context(void *ctx); /* From bb8894ff12f9175d8ebc2c0efe2b56a72f091878 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Thu, 24 Jul 2025 08:36:36 +0100 Subject: [PATCH 084/129] Windows: clear pending netevents when closing a socket. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I hope that this fixes http-proxy-auth-wsaenotconn, although I've only tested it on a hacked-up Python tool that mimics a web proxy only far enough to reproduce the issue, and haven't confirmed a successful connection through a working HTTP proxy. Background: the GUI network tools (both PuTTY and Pageant – anything that links with select-gui.c) use the WSAAsyncSelect method of reporting socket activity, which sends a window message to a nominated HWND when activity happens on a socket. When we receive one of those messages, we don't handle it synchronously in WndProc: instead we queue a toplevel callback, and deal with the network activity when the callbacks are next run from the main loop. This means that when we _close_ a socket, there are two possible places where unhandled notifications for the old socket might still be lurking around. They might be in our window's message queue waiting for GetMessage to retrieve them, or they might have been moved from there into the toplevel callback queue. Either way, this is a source of potential bugs, because WinSock eagerly reuses numeric socket IDs: it's entirely possible in practice to close a socket, immediately open another one, and find the new socket has reused the old one's ID. Then those unhandled notifications don't just refer to a nonexistent socket any more: instead, they misleadingly look as if they refer to the _new_ socket, and cause bugs. The case of this that comes up in practice, described in http-proxy-auth-wsaenotconn, involves an HTTP proxy sending a 407 Proxy Authentication Required response with Connection: close. In that situation, PuTTY wants to try again with authentication, but since that TCP connection is going away, it must make a fresh connection to the proxy for the retry. So it does close the socket and open a new one within the same event handler, and the old socket ID is often reused for the new socket, and a lingering FD_CLOSE notification from the old socket causes PuTTY to incorrectly believe that the proxy has slammed the _new_ connection shut. According to my diagnostics, this particular FD_CLOSE notification generally seems to have been moved from the window message queue into a pending toplevel callback. But the other failure mode is possible in principle too – perhaps more likely in cases where you close a socket in response to some other window message. So we should deal with both. In this commit, I deal with stale toplevel callbacks by using the new delete_callbacks() function introduced in the previous commit, which takes a predicate function to decide whether to delete each callback. That lets me distinguish WM_NETEVENT callbacks citing a particular socket. Dealing with stale window messages is harder, because as far as I can tell, there's no Win32 API to trawl the message queue deleting a subset of messages of this kind. (GetMessage and PeekMessage both have wMsgFilterMin and wMsgFilterMax parameters which can filter by the message type, but to narrow down to just one socket, we would also need to filter on wParam, and there's no call for that.) So instead I do a nasty bodge. Wherever we call closesocket(), select-gui.c posts itself a new custom message WM_DONE_WITH_SOCKET, which goes on to the end of the message queue, and acts as a dividing line. Any WM_NETEVENT seen for that socket id _before_ WM_DONE_WITH_SOCKET was already in the queue at the time we called closesocket(), and therefore refers to the old socket and should be ignored; but WM_NETEVENTs for the same id _after_ WM_DONE_WITH_SOCKET must refer to some new socket reusing the id, and should be handled normally. So select-gui.c keeps a tree234 of "moribund" socket ids: ones for which we've posted a WM_DONE_WITH_SOCKET message to ourself but not yet got it back, and therefore, until we do, WM_NETEVENTs should be ignored. --- windows/network.c | 22 ++++++++++++++-------- windows/pageant.c | 3 ++- windows/platform.h | 6 ++++-- windows/select-cli.c | 4 ++++ windows/select-gui.c | 39 ++++++++++++++++++++++++++++++++++++++- windows/window.c | 3 ++- 6 files changed, 64 insertions(+), 13 deletions(-) diff --git a/windows/network.c b/windows/network.c index de32aefd..131be9fd 100644 --- a/windows/network.c +++ b/windows/network.c @@ -348,6 +348,12 @@ void sk_init(void) sktree = newtree234(cmpfortree); } +static void closesocket_wrap(SOCKET skt) +{ + p_closesocket(skt); + done_with_socket(skt); +} + void sk_cleanup(void) { NetSocket *s; @@ -355,7 +361,7 @@ void sk_cleanup(void) if (sktree) { for (i = 0; (s = index234(sktree, i)) != NULL; i++) { - p_closesocket(s->s); + closesocket_wrap(s->s); } freetree234(sktree); sktree = NULL; @@ -898,7 +904,7 @@ static DWORD try_connect(NetSocket *sock) if (sock->s != INVALID_SOCKET) { do_select(sock->s, false); - p_closesocket(sock->s); + closesocket_wrap(sock->s); } { @@ -1288,14 +1294,14 @@ static Socket *sk_newlistener_internal( } if (err) { - p_closesocket(sk); + closesocket_wrap(sk); s->error = winsock_error_string(err); return &s->sock; } if (p_listen(sk, SOMAXCONN) == SOCKET_ERROR) { - p_closesocket(sk); + closesocket_wrap(sk); s->error = winsock_error_string(p_WSAGetLastError()); return &s->sock; } @@ -1304,7 +1310,7 @@ static Socket *sk_newlistener_internal( * window, or an EventSelect on an event object. */ errstr = do_select(sk, true); if (errstr) { - p_closesocket(sk); + closesocket_wrap(sk); s->error = errstr; return &s->sock; } @@ -1373,7 +1379,7 @@ static void sk_net_close(Socket *sock) del234(sktree, s); do_select(s->s, false); - p_closesocket(s->s); + closesocket_wrap(s->s); if (s->addr) sk_addr_free(s->addr); delete_callbacks_for_context(s); @@ -1726,9 +1732,9 @@ void select_result(WPARAM wParam, LPARAM lParam) if (s->localhost_only && !ipv4_is_local_addr(isa.sin_addr)) #endif { - p_closesocket(t); /* dodgy WinSock let nonlocal through */ + closesocket_wrap(t); /* dodgy WinSock let nonlocal through */ } else if (plug_accepting(s->plug, sk_net_accept, actx)) { - p_closesocket(t); /* denied or error */ + closesocket_wrap(t); /* denied or error */ } break; } diff --git a/windows/pageant.c b/windows/pageant.c index a519926f..c246e660 100644 --- a/windows/pageant.c +++ b/windows/pageant.c @@ -1370,7 +1370,8 @@ static LRESULT CALLBACK TrayWndProc(HWND hwnd, UINT message, break; } case WM_NETEVENT: - winselgui_response(wParam, lParam); + case WM_DONE_WITH_SOCKET: + winselgui_response(message, wParam, lParam); return 0; case WM_DESTROY: quit_help(hwnd); diff --git a/windows/platform.h b/windows/platform.h index 0932e02a..dcbdc739 100644 --- a/windows/platform.h +++ b/windows/platform.h @@ -271,7 +271,8 @@ const SeatDialogPromptDescriptions *win_seat_prompt_descriptions(Seat *seat); */ void write_aclip(HWND hwnd, int clipboard, char *, int); -#define WM_NETEVENT (WM_APP + 5) +#define WM_NETEVENT (WM_APP + 5) +#define WM_DONE_WITH_SOCKET (WM_APP + 8) /* * On Windows, we send MA_2CLK as the only event marking the second @@ -347,6 +348,7 @@ DECL_WINDOWS_FUNCTION(extern, int, select, * called by network.c to turn on or off WSA*Select for a given socket. */ const char *do_select(SOCKET skt, bool enable); +void done_with_socket(SOCKET skt); /* * Exports from select-{gui,cli}.c, each of which provides an @@ -354,7 +356,7 @@ const char *do_select(SOCKET skt, bool enable); */ void winselgui_set_hwnd(HWND hwnd); void winselgui_clear_hwnd(void); -void winselgui_response(WPARAM wParam, LPARAM lParam); +void winselgui_response(UINT message, WPARAM wParam, LPARAM lParam); void winselcli_setup(void); SOCKET winselcli_unique_socket(void); diff --git a/windows/select-cli.c b/windows/select-cli.c index 9bf8411e..97695cd7 100644 --- a/windows/select-cli.c +++ b/windows/select-cli.c @@ -45,6 +45,10 @@ SOCKET winselcli_unique_socket(void) return *p; } +void done_with_socket(SOCKET skt) +{ +} + const char *do_select(SOCKET skt, bool enable) { /* Check everything's been set up, for convenience of callers. */ diff --git a/windows/select-gui.c b/windows/select-gui.c index 4c37c345..e856ec89 100644 --- a/windows/select-gui.c +++ b/windows/select-gui.c @@ -5,8 +5,18 @@ */ #include "putty.h" +#include "tree234.h" + +static void wm_netevent_callback(void *vctx); static HWND winsel_hwnd = NULL; +static tree234 *moribund_sockets = NULL; + +static int moribund_socket_cmp(void *av, void *bv) +{ + uintptr_t a = (uintptr_t)av, b = (uintptr_t)bv; + return a < b ? -1 : a > b ? +1 : 0; +} void winselgui_set_hwnd(HWND hwnd) { @@ -43,6 +53,25 @@ struct wm_netevent_params { LPARAM lParam; }; +static bool callback_is_for_socket( + void *predicate_ctx, toplevel_callback_fn_t fn, void *callback_ctx) +{ + if (fn != wm_netevent_callback) + return false; + struct wm_netevent_params *params = + (struct wm_netevent_params *)callback_ctx; + return params->wParam == (WPARAM)(uintptr_t)predicate_ctx; +} + +void done_with_socket(SOCKET skt) +{ + if (!moribund_sockets) + moribund_sockets = newtree234(moribund_socket_cmp); + PostMessage(winsel_hwnd, WM_DONE_WITH_SOCKET, (WPARAM)skt, 0); + add234(moribund_sockets, (void *)skt); + delete_callbacks(callback_is_for_socket, (void *)(uintptr_t)skt); +} + static void wm_netevent_callback(void *vctx) { struct wm_netevent_params *params = (struct wm_netevent_params *)vctx; @@ -50,8 +79,16 @@ static void wm_netevent_callback(void *vctx) sfree(params); } -void winselgui_response(WPARAM wParam, LPARAM lParam) +void winselgui_response(UINT message, WPARAM wParam, LPARAM lParam) { + if (message == WM_DONE_WITH_SOCKET) { + del234(moribund_sockets, (void *)wParam); + return; + } else if (moribund_sockets && + find234(moribund_sockets, (void *)wParam, NULL)) { + return; + } + /* * To protect against re-entrancy when Windows's recv() * immediately triggers a new WSAAsyncSelect window message, we diff --git a/windows/window.c b/windows/window.c index 5f8d549c..37a20e8e 100644 --- a/windows/window.c +++ b/windows/window.c @@ -2882,7 +2882,8 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, return 0; } case WM_NETEVENT: - winselgui_response(wParam, lParam); + case WM_DONE_WITH_SOCKET: + winselgui_response(message, wParam, lParam); return 0; case WM_SETFOCUS: term_set_focus(wgs->term, true); From 3cbe8522a0339d39eaad212d050c4930b23cc767 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Thu, 31 Jul 2025 12:51:37 +0100 Subject: [PATCH 085/129] Windows: fix memory leak in the stale-netevent fix. When we delete toplevel callbacks for a defunct socket, we must also free the tiny parameter structure we allocated for each one. --- windows/select-gui.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/windows/select-gui.c b/windows/select-gui.c index e856ec89..a1c725f7 100644 --- a/windows/select-gui.c +++ b/windows/select-gui.c @@ -60,7 +60,14 @@ static bool callback_is_for_socket( return false; struct wm_netevent_params *params = (struct wm_netevent_params *)callback_ctx; - return params->wParam == (WPARAM)(uintptr_t)predicate_ctx; + if (params->wParam != (WPARAM)(uintptr_t)predicate_ctx) + return false; + + /* The 'struct wm_netevent_params' would have been freed by the + * callback function wm_netevent_callback(). Now that isn't going + * to run, so we must free it ourself. */ + sfree(callback_ctx); + return true; } void done_with_socket(SOCKET skt) From 2eee88480aedaa85079c86179743237c74643492 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Thu, 31 Jul 2025 12:49:23 +0100 Subject: [PATCH 086/129] Windows: fix stale-netevent problem in the CLI tools. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes in the CLI tools – Plink and friends – the same bug fixed by the recent commit bb8894ff12f9175: if an HTTP proxy demands authentication via a 407 response with Connection: close, then PuTTY immediately makes a second connection to the proxy, which (often) reuses the same socket id at the Win32 API layer, and then a lingering activity notification for the previous socket confuses the handling of the new one. My entire diagnosis and fix in the previous commit were completely derived from reasoning about window message queues and WSAAsyncSelect, so I jumped to the conclusion that the problem would be specific to the GUI tools, which are the ones that _use_ WSAAsyncSelect. But I didn't actually test with Plink. When I did, it turns out that for a completely different reason, cliloop.c has an isomorphic bug, causing the same symptom by a different route. In the CLI tools, instead of WSAAsyncSelect, we use WSAEventSelect, in which Windows signals an event object when socket activity happens. We respond by calling WSAEnumNetworkEvents, which tells us what kind of activity it was, as a bitmap of FD_READ, FD_WRITE, FD_CLOSE etc. Then we iterate over those bits in a particular order, processing each one with a call to select_result(). In this case, the problem wasn't anything lingering in a _queue_. It was simply that we call select_result() to process an FD_READ notification for the socket, which closes the socket and makes a new one, and then select_result() returns to the for-loop which is still iterating over the bit mask returned from WSAEnumNetworkEvents, so in the next loop iteration it tries to process the FD_CLOSE notification for the old socket, not realising that the socket went away in the meantime. I've fixed this by the brute-force technique of moving all the select_result calls out of the for-loop completely. Now cliloop.c does the same thing as select-gui.c: it schedules each instance of handling socket activity as a toplevel callback, and the callbacks don't actually _happen_ until we've completely finished handling the signalled event object. So now, when we're handling FD_READ and still have FD_CLOSE left in a queue somewhere, the queue is the toplevel callback system instead of a for-loop further up the call stack – and that means we can clear the queue via delete_callbacks() in the same way that the previous commit did it for the GUI tools. # This is the commit message #2: # fixup! Windows: fix stale-netevent problem in the CLI tools. --- windows/cliloop.c | 47 +++++++++++++++++++++++++++++++++++++++----- windows/select-cli.c | 4 ---- 2 files changed, 42 insertions(+), 9 deletions(-) diff --git a/windows/cliloop.c b/windows/cliloop.c index eced54ca..b69dbd86 100644 --- a/windows/cliloop.c +++ b/windows/cliloop.c @@ -1,5 +1,40 @@ #include "putty.h" +struct select_result_params { + /* Used to pass data to select_result_callback */ + WPARAM wParam; + LPARAM lParam; +}; + +static void select_result_callback(void *vctx) +{ + struct select_result_params *params = (struct select_result_params *)vctx; + select_result(params->wParam, params->lParam); + sfree(params); +} + +static bool callback_is_for_socket( + void *predicate_ctx, toplevel_callback_fn_t fn, void *callback_ctx) +{ + if (fn != select_result_callback) + return false; + struct select_result_params *params = + (struct select_result_params *)callback_ctx; + if (params->wParam != (WPARAM)(uintptr_t)predicate_ctx) + return false; + + /* The 'struct select_result_params' would have been freed by the + * callback function select_result_callback(). Now that isn't going + * to run, so we must free it ourself. */ + sfree(callback_ctx); + return true; +} + +void done_with_socket(SOCKET skt) +{ + delete_callbacks(callback_is_for_socket, (void *)(uintptr_t)skt); +} + void cli_main_loop(cliloop_pre_t pre, cliloop_post_t post, void *ctx) { SOCKET *sklist = NULL; @@ -82,9 +117,7 @@ void cli_main_loop(cliloop_pre_t pre, cliloop_post_t post, void *ctx) /* Now we're done enumerating; go through the list. */ for (i = 0; i < skcount; i++) { - WPARAM wp; socket = sklist[i]; - wp = (WPARAM) socket; if (!p_WSAEnumNetworkEvents(socket, NULL, &things)) { static const struct { int bit, mask; } eventtypes[] = { {FD_CONNECT_BIT, FD_CONNECT}, @@ -100,10 +133,14 @@ void cli_main_loop(cliloop_pre_t pre, cliloop_post_t post, void *ctx) for (e = 0; e < lenof(eventtypes); e++) if (things.lNetworkEvents & eventtypes[e].mask) { - LPARAM lp; int err = things.iErrorCode[eventtypes[e].bit]; - lp = WSAMAKESELECTREPLY(eventtypes[e].mask, err); - select_result(wp, lp); + struct select_result_params *params = + snew(struct select_result_params); + params->wParam = (WPARAM)socket; + params->lParam = WSAMAKESELECTREPLY( + eventtypes[e].mask, err); + queue_toplevel_callback( + select_result_callback, params); } } } diff --git a/windows/select-cli.c b/windows/select-cli.c index 97695cd7..9bf8411e 100644 --- a/windows/select-cli.c +++ b/windows/select-cli.c @@ -45,10 +45,6 @@ SOCKET winselcli_unique_socket(void) return *p; } -void done_with_socket(SOCKET skt) -{ -} - const char *do_select(SOCKET skt, bool enable) { /* Check everything's been set up, for convenience of callers. */ From 580ab2604dcb65fdb0e700e04be19ce8e671dc35 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Fri, 1 Aug 2025 12:33:04 +0100 Subject: [PATCH 087/129] HTTP proxy digest auth: tolerate multiple qop options. We were rejecting any 'Proxy-Authenticate: Digest' header from the proxy if the 'qop' setting was not exactly the string "auth", which is the only quality of protection that this code supports. However 'qop' is supposed to be a _list_ of possibilities, so we should also be happy if the proxy presents a list of more than one option, as long as "auth" is one of them. --- proxy/http.c | 42 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/proxy/http.c b/proxy/http.c index e083a9da..81af1391 100644 --- a/proxy/http.c +++ b/proxy/http.c @@ -356,9 +356,45 @@ static HttpAuthDetails *parse_http_auth_header(HttpProxyNegotiator *s) if (!get_separator(s, '=') || !get_quoted_string(s)) return auth_error(d, "parse error in Digest qop field"); - if (stricmp(s->token->s, "auth")) - return auth_error(d, "quality-of-protection type '%s' not " - "supported", s->token->s); + + /* + * RFC 7616 section 3.3: "qop" specifies one or more + * options for the "quality of protection" offered by + * the digest authentication. These options vary what + * goes into the message digest: e.g. RFC 7616 defines + * "auth-int", authentication with integrity + * protection, which includes the body of the HTTP + * request in the hash, so that even if you're + * speaking cleartext HTTP, a MITM can't replace the + * document you send without invalidating your auth + * hash. + * + * For CONNECT requests this doesn't really apply, + * because all the interesting data is transferred + * _after_ the HTTP request and response are sent, and + * by that time, the auth hash has to have been + * checked already! So the only option we support is + * plain "auth". + * + * RFC 7616 is vague on exactly how the options are + * delimited in the qop string. It just says "a quoted + * string of one or more tokens", without saying how + * the tokens are separated. But the examples in + * section 3.9.1 include qop="auth, auth-int", with + * both a comma and a space between the two tokens. So + * here we permit any combination of commas and + * whitespace as a separator. + */ + ptrlen list = ptrlen_from_strbuf(s->token); + ptrlen word; + bool ok = false; + while ((word = ptrlen_get_word(&list, ", \t")).len) + if (ptrlen_eq_string(word, "auth")) + ok = true; + if (!ok) + return auth_error(d, "quality-of-protection list \"%s\" " + "does not include our only supported " + "option \"auth\"", s->token->s); } else { /* Ignore any other auth-param */ if (!get_separator(s, '=') || From 2a5f604ffae817b4639adaac17569399c4d45de0 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sat, 16 Aug 2025 09:56:40 +0100 Subject: [PATCH 088/129] Makefile rules for icons used on putty.software. Various web design guidelines asked for an assortment of larger sizes of PNG to link to in various ways, with and without transparency. --- icons/Makefile | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/icons/Makefile b/icons/Makefile index 3aa7ef46..76564653 100644 --- a/icons/Makefile +++ b/icons/Makefile @@ -100,9 +100,16 @@ puttyins.ico: puttyins-16.png puttyins-32.png puttyins-48.png \ -4 $(filter-out %-true.png, $(filter-out %-mono.png, $^)) \ -1 $(filter %-mono.png, $^) > $@ -# Icon for the website. (This isn't linked into "make all".) -website.ico: putty-16.png +# Assorted icons for the website. (This isn't linked into "make all".) +web: website.ico web180.png web192.png web512.png +website.ico: putty-16.png putty-32.png putty-48.png ./icon.pl -4 $^ >$@ +web180.png: putty.svg + rsvg-convert -f png -b white -w 180 -h 180 -o $@ $< +web192.png: putty.svg + rsvg-convert -f png -w 192 -h 192 -o $@ $< +web512.png: putty.svg + rsvg-convert -f png -w 512 -h 512 -o $@ $< xpmputty.c: putty-16.png putty-32.png putty-48.png ./cicon.pl main_icon $^ > $@ From e952f37f02d7a25e85a3cb9f5b90de41621a58c6 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sat, 16 Aug 2025 09:57:17 +0100 Subject: [PATCH 089/129] FAQ: update website/hosting/forges section. The question about a nicer domain name, with answer "we don't want one", is very out of date now that we actually have one! Also, the section about putty.org wants updating after the recent drama. While I was there I decided the Sourceforge question was too old to live, and replaced it with some more up-to-date thoughts about forges in general and Github in particular. The new question faq-putty-org-pivot ("putty.org became weird kookery, have you been hacked or bought out?") is frequently asked in the sense that I've seen it twice in the past week or two: once in email, and once on Mastodon (though someone quickly posted the right answer in response). While I'm here, it seems a bit pointless these days for faq-link to explain the Google pagerank system to everyone. It's been a long time since Google Search was new enough that it needed explaining, and in any case, I've no idea if it's still accurate any more! --- doc/faq.but | 153 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 98 insertions(+), 55 deletions(-) diff --git a/doc/faq.but b/doc/faq.but index 83ad8b9b..85e49de9 100644 --- a/doc/faq.but +++ b/doc/faq.but @@ -1195,14 +1195,63 @@ time after its initial release on our website). \S{faq-putty-org}{Question} Is \cw{putty.org} your website? -No, it isn't. \cw{putty.org} is run by an opportunist who uses it to -advertise their own commercial SSH implementation to people looking -for our free one. We don't own that site, we can't control it, and we -don't advise anyone to use it in preference to our own site. +No, it isn't, and it never has been. We don't own it; we can't control +it; we have no responsibility for anything it does. -The real PuTTY web site, run by the PuTTY team, has always been at +\cw{putty.org} was set up by an opportunist selling a competing SSH +client for money, who initially used it to interpose adverts for their +own commercial SSH implementation in the course of providing a link to +our free one. Then in July 2025 it changed its content to host +anti-vaccine propaganda. We have no idea what it might do next. + +Since the start of PuTTY, the real PuTTY web site, run by the PuTTY +team, has always been at \W{https://www.chiark.greenend.org.uk/~sgtatham/putty/}\cw{https://www.chiark.greenend.org.uk/~sgtatham/putty/}. +We don't recommend that anyone use \cw{putty.org} as a convenient +redirector, or indeed any \e{other} convenient landing page that is +not ours. There are a few others, some set up in entirely good faith, +but you never know. + +As of August 2025, we have registered +\W{https://putty.software/}\cw{putty.software} and made that into an +\e{official} landing page. If you'd like a short easy URL, that's the +one to use, especially if we move the main website there in future. + +\S{faq-putty-org-pivot}{Question} When \cw{putty.org} replaced its +content with anti-vaccine propaganda in July 2025, was that because +you were hacked or vandalised or taken over? + +No, because \cw{putty.org} was never ours in the first place (see +\k{faq-putty-org}). It wasn't stolen from us, or bought from us. The +same person who owned it all along decided to change its content. + +\S{faq-real-website}{Question} With all these landing pages and +imitators, how can I be sure where the \e{real} PuTTY website is? + +Every release of PuTTY embeds a URL to the web site, via the \q{Visit +web site} button in the About box. + +The real website is where \e{PuTTY itself} says it is. + +If you download a cryptographically signed version of PuTTY \dash +either a Windows binary signed with Simon Tatham's Authenticode key, +or anything signed with the PuTTY team's GPG key \dash then you can +confirm that the URL embedded in that copy is the one that the +developers themselves endorse as the true web site. + +As of August 2025, \W{https://putty.software/}\cw{putty.software} is a +second web location owned by us, the PuTTY developers. That too is +endorsed by signed copies of PuTTY, via being mentioned in this FAQ +section of the help file. + +If we move the web site later \dash as of August 2025, our plan is to +move it from the chiark domain name to once the latter is generally +recognised as legitimate \dash then we will keep a redirection of some +kind at the old location, so that it continues to work. Both URLs will +continue to be legitimate places to find PuTTY, whichever is currently +preferred. + \S{faq-the}{Question} Why do the download links point to \cw{the.earth.li} and not chiark? Has your website been hacked? @@ -1217,19 +1266,20 @@ grateful to them! \S{faq-domain}{Question} Would you like me to register you a nicer domain name? -No, thank you. Even if you can find one (most of them seem to have -been registered already, by people who didn't ask whether we -actually wanted it before they applied), we're happy with the PuTTY -web site being exactly where it is. It's not hard to find (just type -\q{putty} into \W{http://www.google.com/}{google.com} and we're the -first link returned), and we don't believe the administrative hassle -of moving the site would be worth the benefit. +No, thank you. We've got one: \W{https://putty.software/}\cw{putty.software}. + +For a long time, this FAQ entry said that we were happy with the site +where it is. However, in 2025, as a result of some media attention to +\cw{putty.org}, it became clear that search engines these days seem to +prefer short whole domain names over user subdirectories on a larger +server. -In addition, if we \e{did} want a custom domain name, we would want -to run it ourselves, so we knew for certain that it would continue -to point where we wanted it, and wouldn't suddenly change or do -strange things. Having it registered for us by a third party who we -don't even know is not the best way to achieve this. +So we registered a domain name ourselves. As of August 2025, +\W{https://putty.software/}\cw{putty.software} is a small landing +page, similar to third-party redirectors except not run by a third +party. After we've got the word out and built some trust, the plan is +to move the whole PuTTY site there and turn the old chiark site into a +redirection. \S{faq-webhosting}{Question} Would you like free web hosting for the PuTTY web site? @@ -1244,28 +1294,10 @@ to PuTTY users. If your content is unrelated, or only tangentially related, to PuTTY, then the link would simply be advertising for you. -One very nice effect of the Google ranking mechanism is that by and -large, the most popular web sites get the highest rankings. This -means that when an ordinary person does a search, the top item in -the search is very likely to be a high-quality site or the site they -actually wanted, rather than the site which paid the most money for -its ranking. - -The PuTTY web site is held in high esteem by Google, for precisely -this reason: lots of people have linked to it simply because they -like PuTTY, without us ever having to ask anyone to link to us. We -feel that it would be an abuse of this esteem to use it to boost the -ranking of random advertisers' web sites. If you want your web site -to have a high Google ranking, we'd prefer that you achieve this the -way we did - by being good enough at what you do that people will -link to you simply because they like you. - -In particular, we aren't interested in trading links for money (see -above), and we \e{certainly} aren't interested in trading links for -other links (since we have no advertising on our web site, our -Google ranking is not even directly worth anything to us). If we -don't want to link to you for free, then we probably won't want to -link to you at all. +This is still true even if you offer to pay us. We aren't interested +in trading links for money, and we \e{certainly} aren't interested in +trading links for other links. If we don't want to link to you for +free, then we probably won't want to link to you at all. If you have software based on PuTTY, or specifically designed to interoperate with PuTTY, or in some other way of genuine interest to @@ -1274,24 +1306,35 @@ our Links page. And if you're running a particularly valuable mirror of the PuTTY web site, we might be interested in linking to you from our Mirrors page. -\S{faq-sourceforge}{Question} Why don't you move PuTTY to -SourceForge? - -Partly, because we don't want to move the web site location (see -\k{faq-domain}). +\S{faq-forge}{Question} Why don't you move PuTTY to Github (or some +other well known forge site)? -Also, security reasons. PuTTY is a security product, and as such it -is particularly important to guard the code and the web site against +Primarily, trust. PuTTY is a security product, and as such it is +particularly important to guard the code and the web site against unauthorised modifications which might introduce subtle security -flaws. Therefore, we prefer that the Git repository, web site and -FTP site remain where they are, under the direct control of system -administrators we know and trust personally, rather than being run -by a large organisation full of people we've never met and which is -known to have had breakins in the past. - -No offence to SourceForge; I think they do a wonderful job. But -they're not ideal for everyone, and in particular they're not ideal -for us. +flaws. Therefore, we prefer that the Git repository, web site and FTP +site remain where they are, under the direct control of system +administrators we know and trust personally. + +Large organisations seem less trustworthy to us because they have a +lot of employees, any of whom could attempt an insider attack; because +management can change or companies can be bought out, and a benign +company today could become a malicious one tomorrow. + +Github in particular already seems like a dangerously large single +point of failure. I'd rather contribute to the Internet being +distributed than contribute to it being centralised. In addition, the +Github software isn't itself free, so although you can export the +actual source repository itself at any time (every \cq{git clone} does +that), you're locked in once all your other metadata (issues, pull +requests etc) is stored in Github's format on Github's systems. + +I know that if you have a Github presence already, it would be most +convenient \e{for you} if everyone else was on Github too so that you +could interact with them all in the same easy way. Sorry about that. +But that seductive ease of use is how large companies attract a large +user base to monetise or exploit later, and we don't want to +participate in that any more than we have to. \S{faq-mailinglist1}{Question} Why can't I subscribe to the putty-bugs mailing list? From 9cb330cf4d7b2f3aa7c5fdcbb3ca64dad3dded44 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sat, 27 Sep 2025 09:25:26 +0100 Subject: [PATCH 090/129] udp.but: fix braino in example function names. Two of the wrapper functions in my example 'trait' had names appropriate to the implementation functions for a particular concrete type. Probably copy-paste with inadequate editing while I was writing it. --- doc/udp.but | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/udp.but b/doc/udp.but index e8750396..84bc5867 100644 --- a/doc/udp.but +++ b/doc/udp.but @@ -507,9 +507,9 @@ file that defined the \cw{MyAbstraction} structure types, like this: \c { return vt->new(vt); } \c static inline void myabs_free(MyAbstraction *myabs) \c { myabs->vt->free(myabs); } -\c static inline void myimpl_modify(MyAbstraction *myabs, unsigned param) +\c static inline void myabs_modify(MyAbstraction *myabs, unsigned param) \c { myabs->vt->modify(myabs, param); } -\c static inline unsigned myimpl_query(MyAbstraction *myabs, unsigned param) +\c static inline unsigned myabs_query(MyAbstraction *myabs, unsigned param) \c { return myabs->vt->query(myabs, param); } And now call sites can use those reasonably clean-looking wrapper From c4fe7b0a7a88933c4856dafe4b811deaa2dbef89 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sun, 19 Oct 2025 11:18:12 +0100 Subject: [PATCH 091/129] Add a FAQ about LLM usage, or rather, the lack thereof. It was asked this week, and I fear it won't be the last time. --- doc/faq.but | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/doc/faq.but b/doc/faq.but index 85e49de9..7a9820b2 100644 --- a/doc/faq.but +++ b/doc/faq.but @@ -1674,6 +1674,31 @@ from scratch for PuTTY. The only code we share with OpenSSH is the detector for SSH-1 CRC compensation attacks, written by CORE SDI S.A; we share no code at all with OpenSSL. +\S{faq-ai}{Question} Does PuTTY contain or use any artificial +intelligence (AI) or large language model (LLM)? + +No, it does not. PuTTY does not use any AI or LLM during its +operation. No AI or LLM code is included in PuTTY itself, and also, no +AI or LLM system elsewhere on the Internet is consulted by PuTTY when +it runs. + +PuTTY aims to be reliable, predictable and efficient in its operation. +The 2020s style of AI is bad at all of these things, \e{especially} +\q{efficient}. + +PuTTY does not collect any data from its users to communicate to any +host run by the PuTTY developers, for LLM training or for any other +purpose. (See \k{privacy} for more detailed information about what +information PuTTY \e{does} store and transmit, but the short answer +is, it only stores information necessary to do its job, and only +talks over the network to the servers you told it to connect to.) + +Of course, after you use PuTTY to connect to a server, \e{that server} +may choose to do AI-related operations, or to collect the data from +your session. PuTTY can do nothing about that (or even detect it +happening), and if you're concerned about it, you'll have to consult +whoever runs your server. + \S{faq-sillyputty}{Question} Where can I buy silly putty? You're looking at the wrong web site; the only PuTTY we know about From f9cbe226ebc0bb0269328a7b2a471e821204391f Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Thu, 23 Oct 2025 12:23:37 +0100 Subject: [PATCH 092/129] Fix pointer-handling bug in write_random_seed(). Thanks to Joshua Rogers for the report: if writing the random seed took more than one call to write(2), then we'd add the wrong value to the data pointer between calls. Happily this is very unlikely to have actually happened, because random seed files are tiny and surely write() will in practice manage to write it all first time. But still needs fixing. --- unix/storage.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unix/storage.c b/unix/storage.c index 042887f2..e7b54622 100644 --- a/unix/storage.c +++ b/unix/storage.c @@ -962,7 +962,7 @@ void write_random_seed(void *data, int len) break; } len -= ret; - data = (char *)data + len; + data = (char *)data + ret; } close(fd); From 148c3b01338592d606e5756b5f22524c70b4246c Mon Sep 17 00:00:00 2001 From: Jacob Nevins Date: Thu, 6 Nov 2025 14:19:43 +0000 Subject: [PATCH 093/129] FAQ: add link from faq-hostkeys to '-hostkey' docs. --- doc/faq.but | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/doc/faq.but b/doc/faq.but index 7a9820b2..93996050 100644 --- a/doc/faq.but +++ b/doc/faq.but @@ -160,10 +160,11 @@ you want an automated batch job to make use of PSCP or Plink, and the interactive host key prompt is hanging the batch process - then the right way to fix it is to add the correct host key to the Registry in advance, or if the Registry is not available, to use the \cw{\-hostkey} -command-line option. That way, you retain the \e{important} feature of -host key checking: the right key will be accepted and the wrong ones -will not. Adding an option to turn host key checking off completely is -the wrong solution and we will not do it. +command-line option (see \k{using-cmdline-hostkey}). That way, you +retain the \e{important} feature of host key checking: the right key +will be accepted and the wrong ones will not. Adding an option to turn +host key checking off completely is the wrong solution and we will not +do it. If you have host keys available in the common \i\c{known_hosts} format, we have a script called From 36a049664915bd9e4493bc38c585f8d27c2ec7a2 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Fri, 2 Jan 2026 10:22:15 +0000 Subject: [PATCH 094/129] Remove spurious \n in OpenSSH key import diagnostics. The output "errmsg" inconsistently had a newline in some cases and not in others. In fact it doesn't need one, so I've removed the unwanted ones. --- import.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/import.c b/import.c index 8e901bb5..3032ba6d 100644 --- a/import.c +++ b/import.c @@ -1191,7 +1191,7 @@ static struct openssh_new_key *load_openssh_new_key(BinarySource *filesrc, BinarySource_BARE_INIT_PL(src, ptrlen_from_strbuf(key->keyblob)); if (strcmp(get_asciz(src), "openssh-key-v1") != 0) { - errmsg = "new-style OpenSSH magic number missing\n"; + errmsg = "new-style OpenSSH magic number missing"; goto error; } @@ -1205,7 +1205,7 @@ static struct openssh_new_key *load_openssh_new_key(BinarySource *filesrc, key->cipher = ON_E_AES256CTR; } else { errmsg = get_err(src) ? "no cipher name found" : - "unrecognised cipher name\n"; + "unrecognised cipher name"; goto error; } @@ -1217,7 +1217,7 @@ static struct openssh_new_key *load_openssh_new_key(BinarySource *filesrc, key->kdf = ON_K_BCRYPT; } else { errmsg = get_err(src) ? "no kdf name found" : - "unrecognised kdf name\n"; + "unrecognised kdf name"; goto error; } @@ -1260,7 +1260,7 @@ static struct openssh_new_key *load_openssh_new_key(BinarySource *filesrc, key->nkeys = toint(get_uint32(src)); if (key->nkeys != 1) { errmsg = get_err(src) ? "no key count found" : - "multiple keys in new-style OpenSSH key file not supported\n"; + "multiple keys in new-style OpenSSH key file not supported"; goto error; } key->key_wanted = 0; @@ -1275,7 +1275,7 @@ static struct openssh_new_key *load_openssh_new_key(BinarySource *filesrc, */ key->private = get_string(src); if (get_err(src)) { - errmsg = "no private key container string found\n"; + errmsg = "no private key container string found"; goto error; } @@ -1371,7 +1371,7 @@ static ssh2_userkey *openssh_new_read( case ON_E_AES256CTR: if (key->private.len % 16 != 0) { errmsg = "private key container length is not a" - " multiple of AES block size\n"; + " multiple of AES block size"; goto error; } { @@ -1416,7 +1416,7 @@ static ssh2_userkey *openssh_new_read( */ alg = find_pubkey_alg_len(get_string(src)); if (!alg) { - errmsg = "private key type not recognised\n"; + errmsg = "private key type not recognised"; goto error; } From 78599038a3f78e7521c68c019993a0c34504ce37 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Fri, 2 Jan 2026 12:24:54 +0000 Subject: [PATCH 095/129] cryptsuite: remove a stray import statement. What was that doing _there_, deep in the middle of a function? I have to assume I hacked it in temporarily to go with a diagnostic print, and then took out the more obvious print statement leaving the spuriopus import behind. --- test/cryptsuite.py | 1 - 1 file changed, 1 deletion(-) diff --git a/test/cryptsuite.py b/test/cryptsuite.py index 0add9bec..eb40c22c 100755 --- a/test/cryptsuite.py +++ b/test/cryptsuite.py @@ -3148,7 +3148,6 @@ def per_base_keytype_tests(alg, run_validation_tests=False, principals = [b"doesn't matter"], valid_after = 1000, valid_before = 2000), ca_key, signflags=ca_signflags) - import base64 self_signed_ca_key = ssh_key_new_pub( alg + '-cert', ca_self_certificate) cert_pub = sign_cert_via_testcrypt( From 3fd66c6796bfcf9e9e515c915de9cf8ec9bed6a9 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Fri, 2 Jan 2026 12:25:53 +0000 Subject: [PATCH 096/129] OpenSSH key import: support aes256-gcm encrypted keys. A user reports that 1Password will choose this cipher to encrypt the 'new' non-PEM OpenSSH key file format. You can make OpenSSH itself do the same, using the option "-Z aes256-gcm@openssh.com" during key generation. I don't know _why_ 1Password chooses this, because in this context, the MAC built in to AES-GCM isn't used - the OpenSSH key file format has no MAC at all. So AES-GCM becomes just an alternative form of counter-mode encryption, with a more restricted shape of IV. This also requires a manual workaround to avoid the keystream being out of sync, because the MAC isn't there to consume the first block of it. --- import.c | 39 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/import.c b/import.c index 3032ba6d..b0cb3d91 100644 --- a/import.c +++ b/import.c @@ -1092,7 +1092,7 @@ static bool openssh_pem_write( */ typedef enum { - ON_E_NONE, ON_E_AES256CBC, ON_E_AES256CTR + ON_E_NONE, ON_E_AES256CBC, ON_E_AES256CTR, ON_E_AES256GCM } openssh_new_cipher; typedef enum { ON_K_NONE, ON_K_BCRYPT @@ -1203,6 +1203,8 @@ static struct openssh_new_key *load_openssh_new_key(BinarySource *filesrc, key->cipher = ON_E_AES256CBC; } else if (ptrlen_eq_string(str, "aes256-ctr")) { key->cipher = ON_E_AES256CTR; + } else if (ptrlen_eq_string(str, "aes256-gcm@openssh.com")) { + key->cipher = ON_E_AES256GCM; } else { errmsg = get_err(src) ? "no cipher name found" : "unrecognised cipher name"; @@ -1345,6 +1347,7 @@ static ssh2_userkey *openssh_new_read( break; case ON_E_AES256CBC: case ON_E_AES256CTR: + case ON_E_AES256GCM: keysize = 48; /* 32 byte key + 16 byte IV */ break; default: @@ -1369,6 +1372,7 @@ static ssh2_userkey *openssh_new_read( break; case ON_E_AES256CBC: case ON_E_AES256CTR: + case ON_E_AES256GCM: if (key->private.len % 16 != 0) { errmsg = "private key container length is not a" " multiple of AES block size"; @@ -1376,10 +1380,39 @@ static ssh2_userkey *openssh_new_read( } { ssh_cipher *cipher = ssh_cipher_new( - key->cipher == ON_E_AES256CBC ? - &ssh_aes256_cbc : &ssh_aes256_sdctr); + key->cipher == ON_E_AES256CBC ? &ssh_aes256_cbc : + key->cipher == ON_E_AES256GCM ? &ssh_aes256_gcm : + &ssh_aes256_sdctr); ssh_cipher_setkey(cipher, keybuf); ssh_cipher_setiv(cipher, keybuf + 32); + if (key->cipher == ON_E_AES256GCM) { + /* + * In AES-GCM, the first output cipher block for a + * block of encrypted data (with counter value 1) + * is used as part of setting up the key for the + * MAC on that block. In PuTTY's code architecture + * this cipher block is generated as part of the + * default cipher stream, and consumed by the MAC + * setup function. + * + * But in this application we're not _using_ the + * GCM MAC. So that setup function never runs. + * Therefore we must consume a cipher block by + * hand, or else our cipher stream will be offset + * by 16 bytes from where it should be. + * + * (This makes the choice of AES-GCM for + * encrypting key files rather strange, since + * without the associated MAC, it's just a variant + * of counter mode with a less general IV! But it + * does occur in the wild - apparently it's the + * default choice of 1Password.) + */ + unsigned char buf[16]; + memset(buf, 0, 16); + ssh_cipher_encrypt(cipher, buf, 16); + smemclr(buf, sizeof(buf)); + } /* Decrypt the private section in place, casting away * the const from key->private being a ptrlen */ ssh_cipher_decrypt(cipher, (char *)key->private.ptr, From 995b63a82bac4f6985958cb92943e807a9f35736 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Fri, 2 Jan 2026 12:54:11 +0000 Subject: [PATCH 097/129] It's a new year. According to source control, this is the first time *I've* remembered to update the copyright date since 2005! Every year since then, it's been Jacob, except for 2013, when apparently nobody remembered at all. --- LICENCE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENCE b/LICENCE index 09155657..6c16257d 100644 --- a/LICENCE +++ b/LICENCE @@ -1,4 +1,4 @@ -PuTTY is copyright 1997-2025 Simon Tatham. +PuTTY is copyright 1997-2026 Simon Tatham. Portions copyright Robert de Bath, Joris van Rantwijk, Delian Delchev, Andreas Schultz, Jeroen Massar, Wez Furlong, Nicolas Barry, From d222b73b675489e5c448bf4513ec84d33cf8a64e Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sun, 4 Jan 2026 19:01:14 +0000 Subject: [PATCH 098/129] Refactor icons/Makefile. Instead of typing out all the PNGs longhand that go into each .ico file, we now generate the list of file suffixes once using GNU make text processing, and then make each rule's dependencies by transforming that list. Makes it easier to add a new icon size. --- icons/Makefile | 32 ++++++++++++-------------------- 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/icons/Makefile b/icons/Makefile index 76564653..3da26f6b 100644 --- a/icons/Makefile +++ b/icons/Makefile @@ -1,7 +1,9 @@ # Makefile for the PuTTY icon suite. ICONS = putty puttycfg puttygen pscp pageant pterm ptermcfg puttyins -SIZES = 16 32 48 128 +ICOSIZES = 16 32 48 +SIZES = $(ICOSIZES) 128 +ICOSUFFIXES = $(ICOSIZES) $(patsubst %,%-mono,$(ICOSIZES)) MODE = # override to -it on command line for opaque testing @@ -57,45 +59,35 @@ $(SVGS): %.svg: mksvg.py $(MONOSVGS): %.svg: mksvg.py ./mksvg.py --mode=bw $(patsubst %-mono.svg,%_icon,$@) -o $@ -putty.ico: putty-16.png putty-32.png putty-48.png \ - putty-16-mono.png putty-32-mono.png putty-48-mono.png +putty.ico: $(patsubst %,putty-%.png,$(ICOSUFFIXES)) ./icon.pl -4 $(filter-out %-mono.png, $^) -1 $(filter %-mono.png, $^) > $@ -puttycfg.ico: puttycfg-16.png puttycfg-32.png puttycfg-48.png \ - puttycfg-16-mono.png puttycfg-32-mono.png puttycfg-48-mono.png +puttycfg.ico: $(patsubst %,puttycfg-%.png,$(ICOSUFFIXES)) ./icon.pl -4 $(filter-out %-mono.png, $^) -1 $(filter %-mono.png, $^) > $@ -puttygen.ico: puttygen-16.png puttygen-32.png puttygen-48.png \ - puttygen-16-mono.png puttygen-32-mono.png puttygen-48-mono.png +puttygen.ico: $(patsubst %,puttygen-%.png,$(ICOSUFFIXES)) ./icon.pl -4 $(filter-out %-mono.png, $^) -1 $(filter %-mono.png, $^) > $@ -pageant.ico: pageant-16.png pageant-32.png pageant-48.png \ - pageant-16-mono.png pageant-32-mono.png pageant-48-mono.png +pageant.ico: $(patsubst %,pageant-%.png,$(ICOSUFFIXES)) ./icon.pl -4 $(filter-out %-mono.png, $^) -1 $(filter %-mono.png, $^) > $@ pageants.ico: pageant-16.png pageant-16-mono.png ./icon.pl -4 $(filter-out %-mono.png, $^) -1 $(filter %-mono.png, $^) > $@ -pscp.ico: pscp-16.png pscp-32.png pscp-48.png \ - pscp-16-mono.png pscp-32-mono.png pscp-48-mono.png +pscp.ico: $(patsubst %,pscp-%.png,$(ICOSUFFIXES)) ./icon.pl -4 $(filter-out %-mono.png, $^) -1 $(filter %-mono.png, $^) > $@ -pterm.ico: pterm-16.png pterm-32.png pterm-48.png \ - pterm-16-mono.png pterm-32-mono.png pterm-48-mono.png +pterm.ico: $(patsubst %,pterm-%.png,$(ICOSUFFIXES)) ./icon.pl -4 $(filter-out %-mono.png, $^) -1 $(filter %-mono.png, $^) > $@ -ptermcfg.ico: ptermcfg-16.png ptermcfg-32.png ptermcfg-48.png \ - ptermcfg-16-mono.png ptermcfg-32-mono.png ptermcfg-48-mono.png +ptermcfg.ico: $(patsubst %,ptermcfg-%.png,$(ICOSUFFIXES)) ./icon.pl -4 $(filter-out %-mono.png, $^) -1 $(filter %-mono.png, $^) > $@ # Because the installer icon makes heavy use of brown when drawing # the cardboard box, it's worth having 8-bit versions of it in # addition to the 4- and 1-bit ones. -puttyins.ico: puttyins-16.png puttyins-32.png puttyins-48.png \ - puttyins-16-mono.png puttyins-32-mono.png \ - puttyins-48-mono.png \ - puttyins-16-true.png puttyins-32-true.png \ - puttyins-48-true.png +puttyins.ico: $(patsubst %,puttyins-%.png,$(ICOSUFFIXES)) \ + $(patsubst %,puttyins-%-true.png,$(ICOSIZES)) ./icon.pl -8 $(filter %-true.png, $^) \ -4 $(filter-out %-true.png, $(filter-out %-mono.png, $^)) \ -1 $(filter %-mono.png, $^) > $@ From 8cdd0bbfe3662f6e747b15a2127070578631aa70 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sun, 4 Jan 2026 19:03:58 +0000 Subject: [PATCH 099/129] Add 64-pixel images to the Windows .ico files. Requested by a user. I guess as screen resolutions go up, larger icons become useful. --- icons/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/icons/Makefile b/icons/Makefile index 3da26f6b..923eb31e 100644 --- a/icons/Makefile +++ b/icons/Makefile @@ -1,7 +1,7 @@ # Makefile for the PuTTY icon suite. ICONS = putty puttycfg puttygen pscp pageant pterm ptermcfg puttyins -ICOSIZES = 16 32 48 +ICOSIZES = 16 32 48 64 SIZES = $(ICOSIZES) 128 ICOSUFFIXES = $(ICOSIZES) $(patsubst %,%-mono,$(ICOSIZES)) From c494fe86d63fb2f2b2f842513e0b07c63f075186 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sat, 10 Jan 2026 08:55:28 +0000 Subject: [PATCH 100/129] Clarify the LLMs FAQ entry. I just re-read it and realised that "No AI or LLM code is included in PuTTY" can be read two ways. I meant it to be about code that _implements_ an LLM, because that was what the person asking me this question was concerned about. But the way I worded it, it could also be misread as a promise that none of PuTTY's code was _generated by_ an LLM. That wasn't what I meant, so I've clarified the language so that it's clearer that it means the former. I'd _like_ to be able to give the latter promise too! Certainly I have never used an LLM to generate code to go into PuTTY (or into anything else I've written). But I can't make the same promise on behalf of all our contributors, because I'd have no way to know. --- doc/faq.but | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/faq.but b/doc/faq.but index 93996050..b92cbc10 100644 --- a/doc/faq.but +++ b/doc/faq.but @@ -1679,9 +1679,9 @@ S.A; we share no code at all with OpenSSL. intelligence (AI) or large language model (LLM)? No, it does not. PuTTY does not use any AI or LLM during its -operation. No AI or LLM code is included in PuTTY itself, and also, no -AI or LLM system elsewhere on the Internet is consulted by PuTTY when -it runs. +operation. No code implementing an AI or LLM system is included in +PuTTY itself, and also, no AI or LLM system elsewhere on the Internet +is consulted by PuTTY when it runs. PuTTY aims to be reliable, predictable and efficient in its operation. The 2020s style of AI is bad at all of these things, \e{especially} From fd08a7754bbc94ec7fb841c4858897d8ea9f448c Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sat, 10 Jan 2026 09:15:09 +0000 Subject: [PATCH 101/129] Weed the FAQ. It's finally time to clear up some of the hilariously outdated questions, like things about PocketPC, or warnings about behaviour changes in some prehistoric version like 0.5x, or warnings about things that went wrong in Windows XP SP2. Apart from straight-up deletions, I've also updated the questions about what ports exist, including updating the status of the non-Mac-port to explain that it's not only unfinished but now also bit-rotted. And I've replaced the "why is there even a Unix PuTTY when OpenSSH exists?" with a more general "why use PuTTY when OpenSSH exists?", now that OpenSSH exists for Windows too. The terminal-types question now acknowledges that a 'putty' terminal type exists; the copy-paste question now starts 'by default' and explains that these days you can reconfigure if you prefer more Windows-like behaviour. The _two_ FAQ entries about "Out of memory" are gone, as is the text about it in errors.but. Nowadays PuTTY won't just pass an arbitrary 32-bit packet size field to malloc at all: both SSH and SFTP will cap at some idea of the maximum sensible size, and if they see a larger value than that, report some other more specific error message. It's possible that some new material might be useful. For example, I've deleted both questions about SSH-2 and SSH-1 support, but there _is_ still something to say about SSH-1 support (namely, the fact that PuTTY still provides it for talking to legacy devices with firmware SSH-1 servers). But I'm working on the principle that if in doubt I interpret "FAQ" in the literal sense: once we find out what questions people actually do ask frequently, we can put those questions back in. And, with some nostalgic regret, I've included Crazy Aaron's Putty World among the garbage-collected questions. He managed to get a link from us by sending us free samples which caught us in a whimsical mood back when PuTTY wasn't as famous as it now is, and I'm sure it proved to be a good investment for him. But even if that business is still around, it's not true any more that people run across the PuTTY web site and mistake it for actual putty. --- doc/config.but | 5 +- doc/errors.but | 27 -- doc/faq.but | 699 +++++++++++-------------------------------------- doc/index.but | 23 +- doc/using.but | 4 - 5 files changed, 156 insertions(+), 602 deletions(-) diff --git a/doc/config.but b/doc/config.but index ae714db3..f78d86b0 100644 --- a/doc/config.but +++ b/doc/config.but @@ -3202,9 +3202,8 @@ make sure it is selected before anything else. On Windows, such libraries are files with a \I{DLL}\cw{.dll} extension, and must have been built in the same way as the PuTTY executable you're running; if you have a 32-bit DLL, you must run a -32-bit version of PuTTY, and the same with 64-bit (see -\k{faq-32bit-64bit}). On Unix, shared libraries generally have a -\cw{.so} extension. +32-bit version of PuTTY, and the same with 64-bit. On Unix, shared +libraries generally have a \cw{.so} extension. \H{config-ssh-tty} The TTY panel diff --git a/doc/errors.but b/doc/errors.but index 85ed4bbb..315ac433 100644 --- a/doc/errors.but +++ b/doc/errors.but @@ -141,33 +141,6 @@ On the server, this can be worked around by disabling public-key authentication or (for Sun SSH only) by increasing \c{MaxAuthTries} in \c{sshd_config}. -\H{errors-memory} \q{\ii{Out of memory}} - -This occurs when PuTTY tries to allocate more memory than the system -can give it. This \e{may} happen for genuine reasons: if the -computer really has run out of memory, or if you have configured an -extremely large number of lines of scrollback in your terminal. -PuTTY is not able to recover from running out of memory; it will -terminate immediately after giving this error. - -However, this error can also occur when memory is not running out at -all, because PuTTY receives data in the wrong format. In SSH-2 and -also in SFTP, the server sends the length of each message before the -message itself; so PuTTY will receive the length, try to allocate -space for the message, and then receive the rest of the message. If -the length PuTTY receives is garbage, it will try to allocate a -ridiculous amount of memory, and will terminate with an \q{Out of -memory} error. - -This can happen in SSH-2, if PuTTY and the server have not enabled -encryption in the same way (see \k{faq-outofmem} in the FAQ). - -This can also happen in PSCP or PSFTP, if your \i{login scripts} on the -server generate output: the client program will be expecting an SFTP -message starting with a length, and if it receives some text from -your login scripts instead it will try to interpret them as a -message length. See \k{faq-outofmem2} for details of this. - \H{errors-internal} \q{\ii{Internal error}}, \q{\ii{Internal fault}}, \q{\ii{Assertion failed}} diff --git a/doc/faq.but b/doc/faq.but index b92cbc10..e82c7a09 100644 --- a/doc/faq.but +++ b/doc/faq.but @@ -7,8 +7,10 @@ appendix in the manual. \S{faq-what}{Question} What is PuTTY? -PuTTY is a client program for the SSH, Telnet, Rlogin, and SUPDUP -network protocols. +PuTTY is a client program for the SSH network protocol, usually used +to run terminal sessions over a network. It also supports running +terminal sessions over a serial port, and a variety of older legacy +network protocols such as Telnet, Rlogin, and SUPDUP. These protocols are all used to run a remote session on a computer, over a network. PuTTY implements the client end of that session: the @@ -23,6 +25,63 @@ displayed in the window. So you can work on the Unix machine as if you were sitting at its console, while actually sitting somewhere else. +\S{faq-why}{Question} Why use PuTTY when I could use OpenSSH? + +These days, Windows comes with a version of OpenSSH as an optional +component of the operating system, and its command prompt windows are +much more like Unix terminals than they used to be. So it's true that +if you want SSH on Windows, you can use OpenSSH in a Windows terminal, +and not have to install PuTTY at all. + +We're not going to try to persuade you that you \e{shouldn't} use +OpenSSH in preference to PuTTY. PuTTY is free software, in the \q{no +cost} sense as well as the \q{freedom} sense \dash we don't get more +money by having more users. PuTTY and OpenSSH have different feature +sets, and different ways of doing things, and it's entirely up to you +which you prefer. + +A few examples of things you might like about PuTTY: + +\b a range of built-in options to log your session to a file + +\b a range of configurable tweaks to the terminal emulation + +\b a unified saved-session system that lets you customise your +settings for a particular destination host, including the SSH-specific +settings (like authentication) \e{and} terminal and logging setup + +\b access to mid-session configuration via the GUI, instead of +stealing a key sequence from your remote terminal session. With the +OpenSSH [Return][\cw{~}][thing] system, you always have to remember +it's there even when you're not using it, to avoid triggering it with +input you meant to send to the server. In PuTTY, the corresponding +facilities (like reconfiguring port forwardings) are done using the +GUI menus, and \e{all} keystrokes typed into the window consistently +go to the server. + +\b simply, \e{different} terminal emulation from Windows's one, which +you might find works better for some remote applications. Or you might +not, of course; it will depend on what kind of machine you're +connecting to, and maybe your personal preferences. And many people +will have no opinion either way. + +\b and, of course, support for things that aren't SSH. In particular, +talking to serial ports instead of the network. + +But if none of this impresses you, and you'd rather use Windows's +version of OpenSSH, that's up to you. + +Unix, of course, has always had OpenSSH, even before the Unix version +of PuTTY existed. So this question has been relevant for much longer! +When we first wrote the Unix port of PuTTY, people asked us why it was +necessary. Partly the answer was that having the PuTTY code run on +Unix too made it easier to develop in general (Unix had a wider range +of better development and debugging facilities, and in my opinion, +still does). But the same considerations as above also apply: on Unix +too I use GUI PuTTY for my SSH connections, so that I never have to +deal with that \cw{~} business, and I use the Unix \cw{pterm} for my +local terminal sessions too. + \H{faq-support} Features supported in PuTTY \I{supported features}In general, if you want to know if PuTTY supports @@ -43,68 +102,12 @@ page}, and see if you can find the feature there. If it's on there, and not in the \q{Recently fixed} section, it probably \e{hasn't} been implemented. -\S{faq-ssh2}{Question} Does PuTTY support SSH-2? - -Yes. SSH-2 support has been available in PuTTY since version 0.50 in -2000. - -Public key authentication (both RSA and DSA) in SSH-2 was new in -version 0.52 in 2002. - -\S{faq-ssh2-keyfmt}{Question} Does PuTTY support reading OpenSSH or -\cw{ssh.com} SSH-2 private key files? - -PuTTY doesn't support this natively (see -\W{https://www.chiark.greenend.org.uk/~sgtatham/putty/wishlist/key-formats-natively.html}{the wishlist entry} -for reasons why not), but as of 0.53 -PuTTYgen can convert both OpenSSH and \cw{ssh.com} private key -files into PuTTY's format. - -\S{faq-ssh1}{Question} Does PuTTY support SSH-1? - -Yes. SSH-1 support has always been available in PuTTY. - -However, the SSH-1 protocol has many weaknesses and is no longer -considered secure; you should use SSH-2 instead if at all possible. - -As of 0.68, PuTTY will no longer fall back to SSH-1 if the server -doesn't appear to support SSH-2; you must explicitly ask for SSH-1. - -\S{faq-localecho}{Question} Does PuTTY support \i{local echo}? - -Yes. Version 0.52 has proper support for local echo. - -In version 0.51 and before, local echo could not be separated from -local line editing (where you type a line of text locally, and it is -not sent to the server until you press Return, so you have the -chance to edit it and correct mistakes \e{before} the server sees -it). New in version 0.52, local echo and local line editing are -separate options, and by default PuTTY will try to determine -automatically whether to enable them or not, based on which protocol -you have selected and also based on hints from the server. If you -have a problem with PuTTY's default choice, you can force each -option to be enabled or disabled as you choose. The controls are in -the Terminal panel, in the section marked \q{Line discipline -options}. - -\S{faq-savedsettings}{Question} Does PuTTY support storing settings, -so I don't have to change them every time? - -Yes, all of PuTTY's settings can be saved in named session profiles. -You can also change the default settings that are used for new sessions. -See \k{config-saving} in the documentation for how to do this. - \S{faq-disksettings}{Question} Does PuTTY support storing its settings in a disk file? Not at present, although \k{config-file} in the documentation gives a method of achieving the same effect. -\S{faq-fullscreen}{Question} Does PuTTY support full-screen mode, -like a DOS box? - -Yes; this was added in version 0.52, in 2002. - \S{faq-password-remember}{Question} Does PuTTY have the ability to \i{remember my password} so I don't have to type it every time? @@ -155,9 +158,9 @@ attacker must now perform a brute-force attack against at least one military-strength cipher. That insignificant host key prompt really does make \e{that} much difference. -If you're having a specific problem with host key checking - perhaps +If you're having a specific problem with host key checking \dash perhaps you want an automated batch job to make use of PSCP or Plink, and the -interactive host key prompt is hanging the batch process - then the +interactive host key prompt is hanging the batch process \dash then the right way to fix it is to add the correct host key to the Registry in advance, or if the Registry is not available, to use the \cw{\-hostkey} command-line option (see \k{using-cmdline-hostkey}). That way, you @@ -188,59 +191,35 @@ server requires all sorts of fiddly new code like interacting with OS authentication databases and the like. A special-purpose SSH server (called \i{Uppity}) can now be built from -the PuTTY source code, and indeed it is not usable as a -general-purpose server; it exists mainly as a test harness. +the PuTTY source code. But it's not usable as a general-purpose +server. Its purpose is to be a test harness. If someone else wants to use this as a basis for writing a -general-purpose SSH server, they'd be perfectly welcome to of course; -but we don't have time, and we don't have motivation. The code is -available if anyone else wants to try it. - -\S{faq-pscp-ascii}{Question} Can PSCP or PSFTP transfer files in -\i{ASCII} mode? - -Unfortunately not. - -This was a limitation of the file transfer protocols as originally -specified: the SCP and SFTP protocols had no notion of transferring -a file in anything other than binary mode. (This is still true of SCP.) - -The current draft protocol spec of SFTP proposes a means of -implementing ASCII transfer. At some point PSCP/PSFTP may implement -this proposal. +general-purpose SSH server, they'd be perfectly welcome to, of course. +But they would have to take responsibility for all of the security +hardening that hasn't been done; we don't have time for that, and we +don't have motivation. The code is available if anyone else wants to +try it. \H{faq-ports} Ports to other operating systems -The eventual goal is for PuTTY to be a multi-platform program, able -to run on at least Windows, Mac OS and Unix. - -PuTTY has been gaining a generalised porting layer, drawing a clear -line between platform-dependent and platform-independent code. The -general intention was for this porting layer to evolve naturally as -part of the process of doing the first port; a Unix port has now been -released and the plan seems to be working so far. +PuTTY is best known as a Windows tool, but it has an internal +abstraction layer that permits it to run on other systems too. Here we +discuss current, past and future possible ports. \S{faq-ports-general}{Question} What ports of PuTTY exist? -Currently, release versions of PuTTY tools only run on Windows -systems and Unix. - -As of 0.68, the supplied PuTTY executables run on versions of Windows -from XP onwards, up to and including Windows 11; and we know of no -reason why PuTTY should not continue to work on future versions of -Windows. We provide 32-bit and 64-bit Windows executables for the -common x86 processor family; see \k{faq-32bit-64bit} for discussion -of the compatibility issues around that. The 32-bit executables -require a \i{Pentium 4} or newer processor. We also provide -executables for Windows on Arm processors. +Currently, release versions of PuTTY tools only run on Windows systems +and Unix. The Windows version is provided in the form of executables, +for both x86 and Arm based Windows systems. The Unix version is +provided as source code (although at least some Linux distributions +provide it pre-built). -(We used to also provide executables for Windows for the Alpha -processor, but stopped after 0.58 due to lack of interest.) - -In the development code, a partial port to Mac OS exists (see -\k{faq-mac-port}). - -Currently PuTTY does \e{not} run on Windows CE (see \k{faq-wince}). +Our standard Windows executable builds aim to run on all versions of +Windows still in security support. Earlier versions might be supported +if it's easy, but we don't promise to test them reliably. (For +example, PuTTY 0.83 still runs on Windows XP \dash but the previous +release 0.82 didn't.) We do not have release-quality ports for any other systems at the present time. If anyone told you we had an Android port, or an iOS @@ -250,111 +229,39 @@ There are some third-party ports to various platforms, mentioned on the \W{https://www.chiark.greenend.org.uk/~sgtatham/putty/links.html}{Links page of our website}. -\S{faq-unix}{Question} \I{Unix version}Is there a port to Unix? - -There are Unix ports of most of the traditional PuTTY tools, and also -one entirely new application. - -If you look at the source release, you should find a \c{unix} -subdirectory. You need \c{cmake} to build it; see the file \c{README} -in the source distribution. This should build you: - -\b Unix ports of PuTTY, Plink, PSCP, and PSFTP, which work pretty much -the same as their Windows counterparts; - -\b Command-line versions of PuTTYgen and Pageant, whose user interface -is quite different to the Windows GUI versions; - -\b \i\c{pterm} - an \cw{xterm}-type program which supports the same -terminal emulation as PuTTY. - -If you don't have \i{Gtk}, you should still be able to build the -command-line tools. - -\S{faq-unix-why}{Question} What's the point of the Unix port? Unix -has OpenSSH. - -All sorts of little things. \c{pterm} is directly useful to anyone -who prefers PuTTY's terminal emulation to \c{xterm}'s, which at -least some people do. Unix Plink has apparently found a niche among -people who find the complexity of OpenSSL makes OpenSSH hard to -install (and who don't mind Plink not having as many features). Some -users want to generate a large number of SSH keys on Unix and then -copy them all into PuTTY, and the Unix PuTTYgen should allow them to -automate that conversion process. - -There were development advantages as well; porting PuTTY to Unix was -a valuable path-finding effort for other future ports, and also -allowed us to use the excellent Linux tool -\W{http://valgrind.kde.org/}{Valgrind} to help with debugging, which -has already improved PuTTY's stability on \e{all} platforms. - -However, if you're a Unix user and you can see no reason to switch -from OpenSSH to PuTTY/Plink, then you're probably right. We don't -expect our Unix port to be the right thing for everybody. - -\S{faq-wince}{Question} Will there be a port to Windows CE or PocketPC? +\S{faq-mac-port}{Question} Will there ever be a \I{Mac OS}Mac version of PuTTY? -We once did some work on such a port, but it only reached an early -stage, and certainly not a useful one. It's no longer being actively -worked on. +As of 2026, I doubt that the core PuTTY team will ever finish one. -\S{faq-win31}{Question} Is there a port to \i{Windows 3.1}? - -PuTTY is a 32-bit application from the ground up, so it won't run on -Windows 3.1 as a native 16-bit program; and it would be \e{very} -hard to port it to do so, because of Windows 3.1's vile memory -allocation mechanisms. - -However, it is possible in theory to compile the existing PuTTY -source in such a way that it will run under \i{Win32s} (an extension to -Windows 3.1 to let you run 32-bit programs). In order to do this -you'll need the right kind of C compiler - modern versions of Visual -C at least have stopped being backwards compatible to Win32s. Also, -the last time we tried this it didn't work very well. - -\S{faq-mac-port}{Question} Will there be a port to the \I{Mac OS}Mac? - -We hope so! - -We attempted one around 2005, written as a native Cocoa application, -but it turned out to be very slow to redraw its window for some reason -we never got to the bottom of. +We've tried more than once. Around 2005 we attempted one in the form +of a native Cocoa application, but it turned out to be very slow to +redraw its window for some reason we never got to the bottom of. In 2015, after porting the GTK front end to work with GTK 3, we began -another attempt based on making small changes to the GTK code and -building it against the OS X Quartz version of GTK 3. This doesn't -seem to have the window redrawing problem any more, so it's already -got further than the last effort, but it is still substantially -unfinished. +another attempt, based on making small changes to the GTK code and +building it against the OS X Quartz version of GTK 3. This didn't have +the speed issue, and came much closer to being finished. But +unfortunately the Quartz GTK port seems to have bit-rotted: the last +time I tried to build the Mac port, I couldn't even figure out how to +install a GTK it would build with. -If any OS X and/or GTK programming experts are keen to have a finished -version of this, we urge them to help out with some of the remaining -problems! See the TODO list in \c{unix/main-gtk-application.c} in the -source code. +If anyone were interested in picking this up and finishing it, the +TODO list in \c{unix/main-gtk-application.c} in the source code is a +good place to start, and I'd be happy to provide advice and +discussion. -\S{faq-epoc}{Question} Will there be a port to EPOC? +\S{faq-iphone}{Question} Is there a version of PuTTY for mobile operating systems? -I hope so, but given that ports aren't really progressing very fast -even on systems the developers \e{do} already know how to program -for, it might be a long time before any of us get round to learning -a new system and doing the port for that. +We don't have one ourselves, for either Android or iOS. -However, some of the work has been done by other people; see the -\W{https://www.chiark.greenend.org.uk/~sgtatham/putty/links.html}{Links page of our website} -for various third-party ports. +The last time we checked, there was a third-party SSH client for the +iPhone and iPod\_Touch called +\W{http://www.instantcocoa.com/products/pTerm/}{pTerm}, which is +apparently based on PuTTY. (This is nothing to do with our +similarly-named \c{pterm}, which is a standalone terminal emulator.) -\S{faq-iphone}{Question} Will there be a port to the iPhone? - -We have no plans to write such a port ourselves; none of us has an -iPhone, and developing and publishing applications for it looks -awkward and expensive. - -However, there is a third-party SSH client for the iPhone and -iPod\_Touch called \W{http://www.instantcocoa.com/products/pTerm/}{pTerm}, -which is apparently based on PuTTY. (This is nothing to do with our -similarly-named \c{pterm}, which is a standalone terminal emulator for -Unix systems; see \k{faq-unix}.) +We don't know of any Android SSH application based on the PuTTY code. +(There are Android SSH applications based on other implementations.) \H{faq-embedding} Embedding PuTTY in other programs @@ -371,19 +278,6 @@ general, so if anyone feels like helping, we wouldn't say no. See also \W{https://www.chiark.greenend.org.uk/~sgtatham/putty/wishlist/dll-frontend.html}{the wishlist entry}. -\S{faq-vb}{Question} Is the SSH or Telnet code available as a Visual -Basic component? - -No, it isn't. None of the PuTTY team uses Visual Basic, and none of -us has any particular need to make SSH connections from a Visual -Basic application. In addition, all the preliminary work to turn it -into a DLL would be necessary first; and furthermore, we don't even -know how to write VB components. - -If someone offers to do some of this work for us, we might consider -it, but unless that happens I can't see VB integration being -anywhere other than the very bottom of our priority list. - \S{faq-ipc}{Question} How can I use PuTTY to make an SSH connection from within another program? @@ -393,14 +287,13 @@ arrange for your primary process to be able to send data to the Plink process, and receive data from it, through pipes, then you should be able to make SSH connections from your program. -This is what CVS for Windows does, for example. - \H{faq-details} Details of PuTTY's operation \S{faq-term}{Question} What \i{terminal type} does PuTTY use? -For most purposes, PuTTY can be considered to be an \cw{xterm} -terminal. +By default, PuTTY has always announced its terminal type to SSH (and +Telnet) servers as \c{xterm}, and tried to behave close enough to +\c{xterm} itself that this works well enough. PuTTY also supports some terminal \i{control sequences} not supported by the real \cw{xterm}: notably the Linux console sequences that @@ -408,9 +301,21 @@ reconfigure the colour palette, and the title bar control sequences used by \i\cw{DECterm} (which are different from the \cw{xterm} ones; PuTTY supports both). -By default, PuTTY announces its terminal type to the server as -\c{xterm}. If you have a problem with this, you can reconfigure it -to say something else; \c{vt220} might help if you have trouble. +Since PuTTY was new, the \c{xterm} terminal type has split into many +subtypes, so you may find that you benefit from upgrading to a +terminal type such as \c{xterm-256color} to enable more features. + +In modern versions of Linux, the terminal type database also includes +a terminal type for PuTTY itself, so you could try setting the +terminal type to \cq{putty}! We didn't write that database entry, and +don't know in detail what it includes or which version of PuTTY it was +based on. + +(We are sometimes asked why PuTTY doesn't use the \cq{putty} terminal +type as default. Part of the reason is inertia. Another is that all +the world's not Linux: I still worry that some servers will be +confused by that terminal type. But perhaps one day we should switch +over.) \S{faq-settings}{Question} Where does PuTTY store its data? @@ -544,8 +449,8 @@ and cannot help you with questions of this type. \S{faq-startmax}{Question} How can I make PuTTY start up \i{maximise}d? -Create a Windows shortcut to start PuTTY from, and set it as \q{Run -Maximized}. +There's no setting built in to PuTTY for this. But you can create a +Windows shortcut to start PuTTY from, and set it as \q{Run Maximized}. \S{faq-startsess}{Question} How can I create a \i{Windows shortcut} to start a particular saved session directly? @@ -569,14 +474,25 @@ session as shown in \k{faq-startsess}. \S{faq-cutpaste}{Question} How do I \i{copy and paste} between PuTTY and other Windows applications? -Copy and paste works similarly to the X Window System. You use the -left mouse button to select text in the PuTTY window. The act of -selection \e{automatically} copies the text to the clipboard: there +By default, copy and paste works similarly to the X Window System. You +use the left mouse button to select text in the PuTTY window. The act +of selection \e{automatically} copies the text to the clipboard: there is no need to press Ctrl-Ins or Ctrl-C or anything else. In fact, -pressing Ctrl-C will send a Ctrl-C character to the other end of -your connection (just like it does the rest of the time), which may -have unpleasant effects. The \e{only} thing you need to do, to copy -text to the clipboard, is to select it. +pressing Ctrl-C will send a Ctrl-C character to the other end of your +connection (just like it does the rest of the time), which may have +unpleasant effects. The \e{only} thing you need to do, to copy text to +the clipboard, is to select it. + +This default dates from the days when PuTTY was new, and its main +target audience was \q{Unix expatriates} \dash people who mostly used +Unix desktop systems and were used to the X copy/paste mechanism, +having to use Windows instead. The aim was \q{closest thing you can +get to an xterm on Windows}. + +If you prefer a more \q{Windows native} interface for copy and paste, +via keystrokes or menu actions, with nothing happening automatically +on select, then you can reconfigure the behaviour flexibly in PuTTY's +configuration. See \k{config-selection} for details. To paste the clipboard contents into a PuTTY window, by default you click the right mouse button. If you have a three-button mouse and @@ -645,47 +561,8 @@ Instead, you need to specify the local file name in full: \c c:\>pscp user@host:"\"oo er\"" "oo er" -\S{faq-32bit-64bit}{Question} Should I run the 32-bit or the -64-bit version? - -If you're not sure, the \I{32-bit Windows}32-bit version is generally -the safe option. It will run perfectly well on all processors and on -all versions of Windows that PuTTY supports. PuTTY doesn't require to -run as a 64-bit application to work well, and having a 32-bit PuTTY on -a 64-bit system isn't likely to cause you any trouble. - -The 64-bit version (first released in 0.68) will only run if you have -a 64-bit processor \e{and} a \I{64-bit Windows}64-bit edition of -Windows (both of these things are likely to be true of any recent -Windows PC). It will run somewhat faster (in particular, the -cryptography will be faster, especially during link setup), but it -will consume slightly more memory. - -If you need to use an external \i{DLL} for GSSAPI authentication, that -DLL may only be available in a 32-bit or 64-bit form, and that will -dictate the version of PuTTY you need to use. (You will probably know -if you're doing this; see \k{config-ssh-auth-gssapi-libraries} in the -documentation.) - \H{faq-trouble} Troubleshooting -\S{faq-pscp-protocol}{Question} Why do I see \q{Fatal: Protocol -error: Expected control record} in PSCP? - -This happens because PSCP was expecting to see data from the server -that was part of the PSCP protocol exchange, and instead it saw data -that it couldn't make any sense of at all. - -This almost always happens because the \i{startup scripts} in your -account on the server machine are generating output. This is -impossible for PSCP, or any other SCP client, to work around. You -should never use startup files (\c{.bashrc}, \c{.cshrc} and so on) -which generate output in non-interactive sessions. - -This is not actually a PuTTY problem. If PSCP fails in this way, -then all other SCP clients are likely to fail in exactly the same -way. The problem is at the server end. - \S{faq-colours}{Question} I clicked on a colour in the \ii{Colours} panel, and the colour didn't change in my terminal. @@ -704,58 +581,6 @@ Clicking on \q{ANSI Green} won't turn your session green; it will only allow you to adjust the \e{shade} of green used when PuTTY is instructed by the server to display green text. -\S{faq-outofmem}{Question} After trying to establish an SSH-2 -connection, PuTTY says \q{\ii{Out of memory}} and dies. - -If this happens just while the connection is starting up, this often -indicates that for some reason the client and server have failed to -establish a session encryption key. Somehow, they have performed -calculations that should have given each of them the same key, but -have ended up with different keys; so data encrypted by one and -decrypted by the other looks like random garbage. - -This causes an \q{out of memory} error because the first encrypted -data PuTTY expects to see is the length of an SSH message. Normally -this will be something well under 100 bytes. If the decryption has -failed, PuTTY will see a completely random length in the region of -two \e{gigabytes}, and will try to allocate enough memory to store -this non-existent message. This will immediately lead to it thinking -it doesn't have enough memory, and panicking. - -If this happens to you, it is quite likely to still be a PuTTY bug -and you should report it (although it might be a bug in your SSH -server instead); but it doesn't necessarily mean you've actually run -out of memory. - -\S{faq-outofmem2}{Question} When attempting a file transfer, either -PSCP or PSFTP says \q{\ii{Out of memory}} and dies. - -This is almost always caused by your \i{login scripts} on the server -generating output. PSCP or PSFTP will receive that output when they -were expecting to see the start of a file transfer protocol, and -they will attempt to interpret the output as file-transfer protocol. -This will usually lead to an \q{out of memory} error for much the -same reasons as given in \k{faq-outofmem}. - -This is a setup problem in your account on your server, \e{not} a -PSCP/PSFTP bug. Your login scripts should \e{never} generate output -during non-interactive sessions; secure file transfer is not the -only form of remote access that will break if they do. - -On Unix, a simple fix is to ensure that all the parts of your login -script that might generate output are in \c{.profile} (if you use a -Bourne shell derivative) or \c{.login} (if you use a C shell). -Putting them in more general files such as \c{.bashrc} or \c{.cshrc} -is liable to lead to problems. - -\S{faq-psftp-slow}{Question} PSFTP transfers files much slower than PSCP. - -The throughput of PSFTP 0.54 should be much better than 0.53b and -prior; we've added code to the SFTP backend to queue several blocks -of data rather than waiting for an acknowledgement for each. (The -SCP backend did not suffer from this performance issue because SCP -is a much simpler protocol.) - \S{faq-bce}{Question} When I run full-colour applications, I see areas of black space where colour ought to be, or vice versa. @@ -764,29 +589,6 @@ erase screen} setting in the Terminal panel. If there is too much black space (the commoner situation), you should enable it, while if there is too much colour, you should disable it. (See \k{config-erase}.) -In old versions of PuTTY, this was disabled by default, and would not -take effect until you reset the terminal (see \k{faq-resetterm}). -Since 0.54, it is enabled by default, and changes take effect -immediately. - -\S{faq-resetterm}{Question} When I change some terminal settings, -nothing happens. - -Some of the terminal options (notably \ii{Auto Wrap} and -background-colour screen erase) actually represent the \e{default} -setting, rather than the currently active setting. The server can -send sequences that modify these options in mid-session, but when -the terminal is reset (by server action, or by you choosing \q{Reset -Terminal} from the System menu) the defaults are restored. - -In versions 0.53b and prior, if you change one of these options in -the middle of a session, you will find that the change does not -immediately take effect. It will only take effect once you reset -the terminal. - -In version 0.54, the behaviour has changed - changes to these -settings take effect immediately. - \S{faq-idleout}{Question} My PuTTY sessions unexpectedly close after they are \I{idle connections}idle for a while. @@ -920,176 +722,6 @@ You should still read the page} on the PuTTY website (also provided as \k{feedback} in the manual), and follow the guidelines contained in that. -\S{faq-ssh2key-ssh1conn}{Question} Why do I see \q{Couldn't load -private key from ...}? Why can PuTTYgen load my key but not PuTTY? - -It's likely that you've generated an SSH protocol 2 key with PuTTYgen, -but you're trying to use it in an SSH-1 connection. SSH-1 and SSH-2 keys -have different formats, and (at least in 0.52) PuTTY's reporting of a -key in the wrong format isn't optimal. - -To connect using SSH-2 to a server that supports both versions, you -need to change the configuration from the default (see \k{faq-ssh2}). - -\S{faq-rh8-utf8}{Question} When I'm connected to a \i{Red Hat Linux} 8.0 -system, some characters don't display properly. - -A common complaint is that hyphens in man pages show up as a-acute. - -With release 8.0, Red Hat appear to have made \i{UTF-8} the default -character set. There appears to be no way for terminal emulators such -as PuTTY to know this (as far as we know, the appropriate escape -sequence to switch into UTF-8 mode isn't sent). - -A fix is to configure sessions to RH8 systems to use UTF-8 -translation - see \k{config-charset} in the documentation. (Note that -if you use \q{Change Settings}, changes may not take place immediately -- see \k{faq-resetterm}.) - -If you really want to change the character set used by the server, the -right place is \c{/etc/sysconfig/i18n}, but this shouldn't be -necessary. - -\S{faq-screen}{Question} Since I upgraded to PuTTY 0.54, the -scrollback has stopped working when I run \c{screen}. - -PuTTY's terminal emulator has always had the policy that when the -\q{\i{alternate screen}} is in use, nothing is added to the scrollback. -This is because the usual sorts of programs which use the alternate -screen are things like text editors, which tend to scroll back and -forth in the same document a lot; so (a) they would fill up the -scrollback with a large amount of unhelpfully disordered text, and -(b) they contain their \e{own} method for the user to scroll back to -the bit they were interested in. We have generally found this policy -to do the Right Thing in almost all situations. - -Unfortunately, \c{screen} is one exception: it uses the alternate -screen, but it's still usually helpful to have PuTTY's scrollback -continue working. The simplest solution is to go to the Features -control panel and tick \q{Disable switching to alternate terminal -screen}. (See \k{config-features-altscreen} for more details.) -Alternatively, you can tell \c{screen} itself not to use the -alternate screen: the -\W{http://www4.informatik.uni-erlangen.de/~jnweiger/screen-faq.html}{\c{screen} -FAQ} suggests adding the line \cq{termcapinfo xterm ti@:te@} to your -\cw{.screenrc} file. - -The reason why this only started to be a problem in 0.54 is because -\c{screen} typically uses an unusual control sequence to switch to -the alternate screen, and previous versions of PuTTY did not support -this sequence. - -\S{faq-alternate-localhost}{Question} Since I upgraded \i{Windows XP} -to Service Pack 2, I can't use addresses like \cw{127.0.0.2}. - -Some people who ask PuTTY to listen on \i{localhost} addresses other -than \cw{127.0.0.1} to forward services such as \i{SMB} and \i{Windows -Terminal Services} have found that doing so no longer works since -they upgraded to WinXP SP2. - -This is apparently an issue with SP2 that is acknowledged by Microsoft -in MS Knowledge Base article -\W{http://support.microsoft.com/default.aspx?scid=kb;en-us;884020}{884020}. -The article links to a fix you can download. - -(\e{However}, we've been told that SP2 \e{also} fixes the bug that -means you need to use non-\cw{127.0.0.1} addresses to forward -Terminal Services in the first place.) - -\S{faq-missing-slash}{Question} PSFTP commands seem to be missing a -directory separator (slash). - -Some people have reported the following incorrect behaviour with -PSFTP: - -\c psftp> pwd -\e iii -\c Remote directory is /dir1/dir2 -\c psftp> get filename.ext -\e iiiiiiiiiiiiiiii -\c /dir1/dir2filename.ext: no such file or directory - -This is not a bug in PSFTP. There is a known bug in some versions of -portable \i{OpenSSH} -(\W{http://bugzilla.mindrot.org/show_bug.cgi?id=697}{bug 697}) that -causes these symptoms; it appears to have been introduced around -3.7.x. It manifests only on certain platforms (AIX is what has been -reported to us). - -There is a patch for OpenSSH attached to that bug; it's also fixed in -recent versions of portable OpenSSH (from around 3.8). - -\S{faq-connaborted}{Question} Do you want to hear about \q{Software -caused connection abort}? - -In the documentation for PuTTY 0.53 and 0.53b, we mentioned that we'd -like to hear about any occurrences of this error. Since the release -of PuTTY 0.54, however, we've been convinced that this error doesn't -indicate that PuTTY's doing anything wrong, and we don't need to hear -about further occurrences. See \k{errors-connaborted} for our current -documentation of this error. - -\S{faq-rekey}{Question} My SSH-2 session \I{locking up, SSH-2 -sessions}locks up for a few seconds every so often. - -Recent versions of PuTTY automatically initiate \i{repeat key -exchange} once per hour, to improve session security. If your client -or server machine is slow, you may experience this as a delay of -anything up to thirty seconds or so. - -These \I{delays, in SSH-2 sessions}delays are inconvenient, but they -are there for your protection. If they really cause you a problem, -you can choose to turn off periodic rekeying using the \q{Kex} -configuration panel (see \k{config-ssh-kex}), but be aware that you -will be sacrificing security for this. (Falling back to SSH-1 would -also remove the delays, but would lose a \e{lot} more security -still. We do not recommend it.) - -\S{faq-xpwontrun}{Question} PuTTY fails to start up. Windows claims that -\q{the application configuration is incorrect}. - -This is caused by a bug in certain versions of \i{Windows XP} which -is triggered by PuTTY 0.58. This was fixed in 0.59. The -\W{https://www.chiark.greenend.org.uk/~sgtatham/putty/wishlist/xp-wont-run}{\q{xp-wont-run}} -entry in PuTTY's wishlist has more details. - -\S{faq-system32}{Question} When I put 32-bit PuTTY in -\cw{C:\\WINDOWS\\\i{SYSTEM32}} on my \i{64-bit Windows} system, -\i{\q{Duplicate Session}} doesn't work. - -The short answer is not to put the PuTTY executables in that location. - -On 64-bit systems, \cw{C:\\WINDOWS\\SYSTEM32} is intended to contain -only 64-bit binaries; Windows' 32-bit binaries live in -\cw{C:\\WINDOWS\\SYSWOW64}. When a 32-bit PuTTY executable runs -on a 64-bit system, it cannot by default see the \q{real} -\cw{C:\\WINDOWS\\SYSTEM32} at all, because the -\W{http://msdn.microsoft.com/en-us/library/aa384187(v=vs.85).aspx}{File -System Redirector} arranges that the running program sees the -appropriate kind of binaries in \cw{SYSTEM32}. Thus, operations in -the PuTTY suite that involve it accessing its own executables, such as -\i{\q{New Session}} and \q{Duplicate Session}, will not work. - -\S{faq-iutf8}{Question} After I upgraded PuTTY to 0.68, I can no longer -connect to my embedded device or appliance. - -If your SSH server has started unexpectedly closing SSH connections -after you enter your password, and it worked before 0.68, you may have -a buggy server that objects to certain SSH protocol extensions. - -The SSH protocol recently gained a new \q{terminal mode}, \cw{IUTF8}, -which PuTTY sends by default; see \k{config-ttymodes}. This is the -first new terminal mode since the SSH-2 protocol was defined. While -servers are supposed to ignore modes they don't know about, some buggy -servers will unceremoniously close the connection if they see anything -they don't recognise. SSH servers in embedded devices, network -appliances, and the like seem to disproportionately have this bug. - -If you think you have such a server, from 0.69 onwards you can disable -sending of the \cw{IUTF8} mode: on the SSH / TTY panel, select -\cw{IUTF8} on the list, select \q{Nothing}, and press \q{Set}. (It's -not possible to disable sending this mode in 0.68.) - \S{faq-privkey-control-moved}{Question} Since 0.78, I can't find where to configure my SSH private key. @@ -1145,27 +777,6 @@ appear in \q{Add/Remove Programs}. Current versions of the installer do not offer to remove the above-mentioned items, so if you want them removed you should run \c{putty \-cleanup} before uninstalling. -\S{faq-dsa}{Question} How come PuTTY now supports \i{DSA}, when the -website used to say how insecure it was? - -DSA has a major weakness \e{if badly implemented}: it relies on a -random number generator to far too great an extent. If the random -number generator produces a number an attacker can predict, the DSA -private key is exposed - meaning that the attacker can log in as you -on all systems that accept that key. - -The PuTTY policy changed because the developers were informed of -ways to implement DSA which do not suffer nearly as badly from this -weakness, and indeed which don't need to rely on random numbers at -all. For this reason we now believe PuTTY's DSA implementation is -probably OK. - -The recently added elliptic-curve signature methods are also DSA-style -algorithms, so they have this same weakness in principle. Our ECDSA -implementation uses the same defence as DSA, while our Ed25519 -implementation uses the similar system (but different in details) that -the Ed25519 spec mandates. - \S{faq-virtuallock}{Question} Couldn't Pageant use \cw{VirtualLock()} to stop private keys being written to disk? @@ -1670,10 +1281,12 @@ relevant: \S{faq-openssh}{Question} Is PuTTY a port of \i{OpenSSH}, or based on OpenSSH or OpenSSL? -No, it isn't. PuTTY is almost completely composed of code written -from scratch for PuTTY. The only code we share with OpenSSH is the -detector for SSH-1 CRC compensation attacks, written by CORE SDI -S.A; we share no code at all with OpenSSL. +No, it isn't. PuTTY is almost completely composed of code written from +scratch for PuTTY. As of 2026, PuTTY and OpenSSH have no code in +common as far as I know. + +(In the past, there has been at least one case of both tools sharing +the same piece of third-party code, but not in up-to-date versions.) \S{faq-ai}{Question} Does PuTTY contain or use any artificial intelligence (AI) or large language model (LLM)? @@ -1700,16 +1313,6 @@ your session. PuTTY can do nothing about that (or even detect it happening), and if you're concerned about it, you'll have to consult whoever runs your server. -\S{faq-sillyputty}{Question} Where can I buy silly putty? - -You're looking at the wrong web site; the only PuTTY we know about -here is the name of a computer program. - -If you want the kind of putty you can buy as an executive toy, the -PuTTY team can personally recommend Thinking Putty, which you can -buy from Crazy Aaron's Putty World, at -\W{http://www.puttyworld.com}\cw{www.puttyworld.com}. - \S{faq-meaning}{Question} What does \q{PuTTY} mean? It's the name of a popular SSH and Telnet client. Any other meaning diff --git a/doc/index.but b/doc/index.but index df2d31d7..da38a866 100644 --- a/doc/index.but +++ b/doc/index.but @@ -366,9 +366,9 @@ saved sessions from \IM{SSH packet log} SSH packet log \IM{SSH packet log} packet log, SSH -\IM{auto wrap mode}{auto wrap} auto wrap mode -\IM{auto wrap mode}{auto wrap} wrapping, automatic -\IM{auto wrap mode}{auto wrap} line wrapping, automatic +\IM{auto wrap mode} auto wrap mode +\IM{auto wrap mode} wrapping, automatic +\IM{auto wrap mode} line wrapping, automatic \IM{control sequence}{control codes} control sequences \IM{control sequence}{control codes} terminal control sequences @@ -943,15 +943,6 @@ saved sessions from \IM{remember my password} storing passwords \IM{remember my password} password, storing -\IM{login scripts}{startup scripts} login scripts -\IM{login scripts}{startup scripts} startup scripts - -\IM{Red Hat Linux} Red Hat Linux -\IM{Red Hat Linux} Linux, Red Hat - -\IM{SMB} SMB -\IM{SMB} Windows file sharing - \IM{clean up} clean up after PuTTY \IM{clean up} uninstalling @@ -976,14 +967,6 @@ saved sessions from \IM{cascading credentials} cascading credentials \IM{cascading credentials} credentials, cascading -\IM{SYSTEM32} \cw{SYSTEM32} directory, on Windows - -\IM{32-bit Windows} 32-bit Windows -\IM{32-bit Windows} Windows, 32-bit -\IM{32-bit Windows} x86 (32-bit processor architecture) -\IM{64-bit Windows} 64-bit Windows -\IM{64-bit Windows} Windows, 64-bit - \IM{Windows process ACL} Windows process ACL \IM{Windows process ACL} process ACL (Windows) \IM{Windows process ACL} ACL, process (Windows) diff --git a/doc/using.but b/doc/using.but index 5f6e92d4..1bc230ee 100644 --- a/doc/using.but +++ b/doc/using.but @@ -507,10 +507,6 @@ available for local-to-remote forwarded ports; SSH-1 is unable to support it for remote-to-local ports, while SSH-2 can support it in theory but servers will not necessarily cooperate. -(Note that if you're using Windows XP Service Pack 2, you may need -to obtain a fix from Microsoft in order to use addresses like -\cw{127.0.0.5} - see \k{faq-alternate-localhost}.) - For more options relating to port forwarding, see \k{config-ssh-portfwd}. From c15d4d7b1acf99ae21c67f5c7c65884b9959149d Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Wed, 14 Jan 2026 12:47:23 +0000 Subject: [PATCH 102/129] Fix edge case in ecc_weierstrass_add_general doubling. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ecc_weierstrass_add_general() is the function that you call to compute P+Q if you don't know whether or not P=Q (in which case different calculations are required). It calculates the answers for both the P≠Q and P=Q cases, and selects between them (in constant time, so as not to give away whether P=Q). But we use Jacobian coordinates (two numerators and a denominator) to represent Weierstrass curve points, so a point has multiple representations, using different choices of denominator. In the case where P and Q were different representations of the same point, using different denominators, ecc_weierstrass_add_general() was doing the wrong thing, and returning something that wasn't even a valid elliptic curve point. The root cause was that we start by transforming both inputs to be over a common denominator for the P≠Q case, and we should have done the P=Q calculations relative to _that_ denominator, which is the one expected by the shared epilogue code. But instead we used the denominator of one of the input points. And if P,Q have identical _representations_, then this makes no difference, so the existing tests of adding a point to itself didn't spot the problem. This is a bug in our ECC arithmetic, but happily, not a vulnerability, because exploiting it requires work equivalent to recovering the private key. ecc_weierstrass_add_general() is used when validating an ECDSA signature: you use it to calculate (hw)G + (rw)P, where G is the group generator, P is the public key, h is derived from a hash of the message, and r,w come from the signature. So to trigger the bug you need the two addends to be the same, i.e. (hw)G = (rw)P. Cancelling w, you need hG = rP. But if an attacker trying to forge a signature was able to find any pair (h,r) at all such that hG = rP, then inverting r mod the group order and multiplying both sides by its inverse r⁻¹, you would have (r⁻¹h)G = (r⁻¹r)P = P. And that would mean r⁻¹h was precisely the private key. So if an attacker could do that at all, then they wouldn't _need_ to exploit any buggy behaviour in ecc_weierstrass_add_general(). They'd have the private key by that point, so they could use it to construct a signature that _didn't_ trigger this bug, and that PuTTY would accept with or without the bug fix. Thanks to Guido Vranken for the report. --- crypto/ecc-arithmetic.c | 48 +++++++++++++++++++++++++++++++++++++++-- crypto/ecc.h | 6 ++++++ test/cryptsuite.py | 7 ++++++ test/testcrypt-func.h | 2 ++ 4 files changed, 61 insertions(+), 2 deletions(-) diff --git a/crypto/ecc-arithmetic.c b/crypto/ecc-arithmetic.c index 6a896f92..ed2abf39 100644 --- a/crypto/ecc-arithmetic.c +++ b/crypto/ecc-arithmetic.c @@ -116,6 +116,24 @@ WeierstrassPoint *ecc_weierstrass_point_new_identity(WeierstrassCurve *wc) return wp; } +/* Used for testcrypt */ +WeierstrassPoint *ecc_weierstrass_point_change_denominator( + WeierstrassPoint *wp, mp_int *factor) +{ + WeierstrassCurve *wc = wp->wc; + WeierstrassPoint *out = ecc_weierstrass_point_new_empty(wc); + mp_int *z = monty_import(wc->mc, factor); + mp_int *z2 = monty_mul(wc->mc, z, z); + mp_int *z3 = monty_mul(wc->mc, z2, z); + out->X = monty_mul(wc->mc, wp->X, z2); + out->Y = monty_mul(wc->mc, wp->Y, z3); + out->Z = monty_mul(wc->mc, wp->Z, z); + mp_free(z); + mp_free(z2); + mp_free(z3); + return out; +} + void ecc_weierstrass_point_copy_into( WeierstrassPoint *dest, WeierstrassPoint *src) { @@ -394,9 +412,35 @@ WeierstrassPoint *ecc_weierstrass_add_general( ecc_weierstrass_add_prologue( P, Q, &Px, &Py, &Qx, &denom, &lambda_n, &lambda_d); - /* Slope if P == Q */ + /* + * Calculate what the slope of the line will be if P == Q. + * + * For this, we can't pass the _original_ P or Q to the + * tangent_slope subroutine. We've put the two input points over a + * common denominator, and we're going to use _that_ denominator + * in the epilogue function, so we need the tangent to be + * expressed relative to the same denominator. + * + * So we make a temporary point structure using the re-denominated + * version of P, as returned from add_prologue: (Px, Py, denom) + * identify the same curve point as (P->X, P->Y, P->Z). + * + * That structure temporarily borrows those mp_ints, so we don't + * need to allocate or free anything. And we don't need to smemclr + * the temporary point, because it only holds pointers - all the + * secrets are in the mp_ints, and we haven't finished with those + * yet. + */ mp_int *lambda_n_tangent, *lambda_d_tangent; - ecc_weierstrass_tangent_slope(P, &lambda_n_tangent, &lambda_d_tangent); + { + WeierstrassPoint P_redenominated; + P_redenominated.wc = wc; + P_redenominated.X = Px; + P_redenominated.Y = Py; + P_redenominated.Z = denom; + ecc_weierstrass_tangent_slope( + &P_redenominated, &lambda_n_tangent, &lambda_d_tangent); + } /* Select between those slopes depending on whether P == Q */ unsigned same_x_coord = mp_eq_integer(lambda_d, 0); diff --git a/crypto/ecc.h b/crypto/ecc.h index a6115329..bb5ba1d5 100644 --- a/crypto/ecc.h +++ b/crypto/ecc.h @@ -69,6 +69,12 @@ void ecc_weierstrass_point_free(WeierstrassPoint *point); /* Check whether a point is actually on the curve. */ unsigned ecc_weierstrass_point_valid(WeierstrassPoint *); +/* For test purposes, used by testcrypt: multiply a factor into the + * internal Jacobian-coordinates denominator, changing only the + * representation of the point and not its affine coordinates */ +WeierstrassPoint *ecc_weierstrass_point_change_denominator( + WeierstrassPoint *, mp_int *); + /* * Add two points and return their sum. This function is fully * general: it should do the right thing if the two inputs are the diff --git a/test/cryptsuite.py b/test/cryptsuite.py index eb40c22c..1ee283c2 100755 --- a/test/cryptsuite.py +++ b/test/cryptsuite.py @@ -786,6 +786,13 @@ def make_point(x, y): bogus = ecc_weierstrass_point_new(wc, int(rP.x), int(rP.y * 3)) self.assertFalse(ecc_weierstrass_point_valid(bogus)) + # Make sure add_general still correctly doubles a point if we + # add two _different_ representations of the same point to + # each other. + wP2 = ecc_weierstrass_point_change_denominator(wP, 2) + self.assertTrue(ecc_weierstrass_point_valid(wP2)) + check_point(ecc_weierstrass_add_general(wP, wP2), rP + rP) + # Re-instantiate the curve with the ability to take square # roots, and check that we can reconstruct P and Q from their # x coordinate and y parity only. diff --git a/test/testcrypt-func.h b/test/testcrypt-func.h index d1ca3f5c..650a9421 100644 --- a/test/testcrypt-func.h +++ b/test/testcrypt-func.h @@ -213,6 +213,8 @@ FUNC(val_wpoint, ecc_weierstrass_point_new, ARG(val_wcurve, curve), FUNC(val_wpoint, ecc_weierstrass_point_new_from_x, ARG(val_wcurve, curve), ARG(val_mpint, x), ARG(uint, desired_y_parity)) FUNC(val_wpoint, ecc_weierstrass_point_copy, ARG(val_wpoint, orig)) +FUNC(val_wpoint, ecc_weierstrass_point_change_denominator, ARG(val_wpoint, P), + ARG(val_mpint, z)) FUNC(uint, ecc_weierstrass_point_valid, ARG(val_wpoint, P)) FUNC(val_wpoint, ecc_weierstrass_add_general, ARG(val_wpoint, P), ARG(val_wpoint, Q)) From 4448d1a81e934b8f697d8e7bcc66219e38924259 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Fri, 23 Jan 2026 23:32:06 +0000 Subject: [PATCH 103/129] Unix: create ~/.putty/sshhostcas if necessary. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Jacob points out that Unix PuTTY contained no code to create this directory, in which records are stored for each CA you trust to sign host keys. That's embarassing! I must have created the directory manually during initial development, probably because I wrote and tested the code that loads and uses its contents before the GUI configurer. And then I never re-tested from a clean config directory, which would have made me realise that saving didn't work if the containing directory didn't already exist. (I know at least a few people have been _using_ PuTTY's certificate support since it was added – but apparently not many on Unix!) --- unix/storage.c | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/unix/storage.c b/unix/storage.c index e7b54622..23496a9e 100644 --- a/unix/storage.c +++ b/unix/storage.c @@ -691,13 +691,36 @@ host_ca *host_ca_load(const char *name) char *host_ca_save(host_ca *hca) { + char *filename, *err; + if (!*hca->name) return dupstr("CA record must have a name"); - char *filename = make_filename(INDEX_HOSTCA, hca->name); + filename = make_filename(INDEX_DIR, NULL); + if ((err = make_dir_path(filename, 0700)) != NULL) { + char *msg = dupprintf("Unable to save CA record: " + "making directory '%s': %s", filename, err); + sfree(err); + sfree(filename); + return msg; + } + sfree(filename); + + filename = make_filename(INDEX_HOSTCADIR, NULL); + if ((err = make_dir_path(filename, 0700)) != NULL) { + char *msg = dupprintf("Unable to save CA record: " + "making directory '%s': %s", filename, err); + sfree(err); + sfree(filename); + return msg; + } + sfree(filename); + + filename = make_filename(INDEX_HOSTCA, hca->name); FILE *fp = fopen(filename, "w"); if (!fp) - return dupprintf("Unable to open file '%s'", filename); + return dupprintf("Unable to save CA record: opening file '%s': %s", + filename, strerror(errno)); fprintf(fp, "PublicKey="); base64_encode_fp(fp, ptrlen_from_strbuf(hca->ca_public_key), 0); @@ -715,9 +738,10 @@ char *host_ca_save(host_ca *hca) if (fclose(fp) < 0) bad = true; - char *err = NULL; + err = NULL; if (bad) - err = dupprintf("Unable to write file '%s'", filename); + err = dupprintf("Unable to save CA record: writing file '%s': %s", + filename, strerror(errno)); sfree(filename); return err; From 5b6e89cb66d9c8f74bcc741b304cc5206699d4f6 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Fri, 30 Jan 2026 12:30:51 +0000 Subject: [PATCH 104/129] Don't accidentally interpret DCS escapes as OSC. Every piece of code that sets term->termstate to SEEN_OSC also sets term->osc_type to identify which kind of generally OSC-shaped escape sequence is being processed, such as DCS or APC or OSC proper. But the latter setting was having no effect, because immediately on arriving in the SEEN_OSC case handler, we would unconditionally reset term->osc_type back to OSCLIKE_OSC, treating them all as OSC anyway! Reported by a user, who was finding that vim was sending the DSC sequence ESC P z z ESC \ on startup, and this was resetting the window title to "z". PuTTY's _intended_ handling of DSC sequences is to consume them without messing up the display, and otherwise ignore them. It had failed to ignore this one! Added a small test of window-title setting to test_terminal.c, mostly so that it can contain a regression test for that bug. --- terminal/terminal.c | 1 - test/test_terminal.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/terminal/terminal.c b/terminal/terminal.c index 574e8261..c2cb3118 100644 --- a/terminal/terminal.c +++ b/terminal/terminal.c @@ -5252,7 +5252,6 @@ static void term_out(Terminal *term, bool called_from_term_data) } break; case SEEN_OSC: - term->osc_type = OSCLIKE_OSC; switch (c) { case 'P': /* Linux palette sequence */ term->termstate = SEEN_OSC_P; diff --git a/test/test_terminal.c b/test/test_terminal.c index 5ebc1204..e8dd8855 100644 --- a/test/test_terminal.c +++ b/test/test_terminal.c @@ -31,6 +31,7 @@ typedef struct Mock { Terminal *term; Conf *conf; struct unicode_data ucsdata[1]; + strbuf *title; strbuf *context; @@ -50,11 +51,15 @@ static void mock_set_raw_mouse_mode_pointer(TermWin *win, bool enable) {} static void mock_palette_set(TermWin *win, unsigned start, unsigned ncolours, const rgb *colours) {} static void mock_palette_get_overrides(TermWin *tw, Terminal *term) {} +static void mock_set_title(TermWin *win, const char *title, int codepage); +static void mock_set_icon_title(TermWin *win, const char *title, int cp) {} static const TermWinVtable mock_termwin_vt = { .setup_draw_ctx = mock_setup_draw_ctx, .draw_text = mock_draw_text, .draw_cursor = mock_draw_cursor, + .set_title = mock_set_title, + .set_icon_title = mock_set_icon_title, .set_raw_mouse_mode = mock_set_raw_mouse_mode, .set_raw_mouse_mode_pointer = mock_set_raw_mouse_mode_pointer, .palette_set = mock_palette_set, @@ -73,6 +78,7 @@ static Mock *mock_new(void) mk->ucsdata->line_codepage = CP_ISO8859_1; mk->context = strbuf_new(); + mk->title = strbuf_new(); mk->tw.vt = &mock_termwin_vt; @@ -84,15 +90,24 @@ static void mock_free(Mock *mk) strbuf_free(mk->context); conf_free(mk->conf); term_free(mk->term); + strbuf_free(mk->title); sfree(mk); } +static void mock_set_title(TermWin *win, const char *title, int codepage) +{ + Mock *mk = container_of(win, Mock, tw); + strbuf_clear(mk->title); + put_dataz(mk->title, title); +} + static void reset(Mock *mk) { term_pwron(mk->term, true); term_size(mk->term, 24, 80, 0); term_set_trust_status(mk->term, false); strbuf_clear(mk->context); + strbuf_clear(mk->title); } #if 0 @@ -131,7 +146,15 @@ static inline void check_iequal(Mock *mk, const char *file, int line, lhs, rhs, lhs, rhs); } +static inline void check_sequal(Mock *mk, const char *file, int line, + const char *lhs, const char *rhs) +{ + if (strcmp(lhs, rhs) != 0) + report_fail(mk, file, line, "'%s' != '%s'", lhs, rhs); +} + #define IEQUAL(lhs, rhs) check_iequal(mk, __FILE__, __LINE__, lhs, rhs) +#define SEQUAL(lhs, rhs) check_sequal(mk, __FILE__, __LINE__, lhs, rhs) static inline void term_datapl(Terminal *term, ptrlen pl) { @@ -482,6 +505,25 @@ static void test_nonwrap(Mock *mk) IEQUAL(get_termchar(mk->term, 79, 0).chr, 0xFFFD); } +static void test_wintitle(Mock *mk) +{ + reset(mk); + term_datapl(mk->term, PTRLEN_LITERAL("\033]0;foo\033\\")); + term_update(mk->term); + SEQUAL(mk->title->s, "foo"); + term_datapl(mk->term, PTRLEN_LITERAL("\033]0;bar\007")); + term_update(mk->term); + SEQUAL(mk->title->s, "bar"); + + /* Regression test for a bug in which a DCS string was + * accidentally treated as a title-setting OSC 0. We expect that + * this is not a window-title setting sequence, and leaves the + * title unchanged. */ + term_datapl(mk->term, PTRLEN_LITERAL("\033Pzz\033\\")); + term_update(mk->term); + SEQUAL(mk->title->s, "bar"); +} + int main(void) { Mock *mk = mock_new(); @@ -490,6 +532,7 @@ int main(void) test_hello_world(mk); test_wrap(mk); test_nonwrap(mk); + test_wintitle(mk); bool failed = mk->any_test_failed; mock_free(mk); From f4a99c58a162094501219232a1d1b53edc75d48a Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sun, 8 Feb 2026 15:22:17 +0000 Subject: [PATCH 105/129] Move Telnet proxy command formatting into utils. The 'utils' version of the function takes the format string as a parameter rather than extracting it from CONF_proxy_telnet_command, so that it can be reused to format things not kept in that slot. --- misc.h | 10 ++ proxy/proxy.h | 6 +- proxy/telnet.c | 173 +--------------------- utils/CMakeLists.txt | 1 + utils/format_connection_setup_command.c | 184 ++++++++++++++++++++++++ 5 files changed, 201 insertions(+), 173 deletions(-) create mode 100644 utils/format_connection_setup_command.c diff --git a/misc.h b/misc.h index 67a1833b..41784ee8 100644 --- a/misc.h +++ b/misc.h @@ -564,4 +564,14 @@ void cert_expr_builder_free(CertExprBuilder *eb); void cert_expr_builder_add(CertExprBuilder *eb, const char *wildcard); char *cert_expr_expression(CertExprBuilder *eb); +/* + * This may be reused by local-command proxies on individual + * platforms, and also pre-connection hooks. + */ +#define TELNET_CMD_MISSING_USERNAME 0x0001 +#define TELNET_CMD_MISSING_PASSWORD 0x0002 +char *format_connection_setup_command( + const char *fmt, SockAddr *addr, int port, Conf *conf, + unsigned *flags_out); + #endif diff --git a/proxy/proxy.h b/proxy/proxy.h index 72d06d49..85d6e2fd 100644 --- a/proxy/proxy.h +++ b/proxy/proxy.h @@ -108,11 +108,11 @@ prompts_t *proxy_new_prompts(ProxySocket *ps); void proxy_spr_abort(ProxyNegotiator *pn, SeatPromptResult spr); /* - * This may be reused by local-command proxies on individual + * This is a wrapper on format_connection_setup_command which gets the + * format string from CONF_proxy_telnet_command. Despite the name, it + * may also be reused by local-command proxies on individual * platforms. */ -#define TELNET_CMD_MISSING_USERNAME 0x0001 -#define TELNET_CMD_MISSING_PASSWORD 0x0002 char *format_telnet_command(SockAddr *addr, int port, Conf *conf, unsigned *flags_out); diff --git a/proxy/telnet.c b/proxy/telnet.c index 41cdf8d7..347a367c 100644 --- a/proxy/telnet.c +++ b/proxy/telnet.c @@ -15,176 +15,9 @@ char *format_telnet_command(SockAddr *addr, int port, Conf *conf, unsigned *flags_out) { - char *fmt = conf_get_str(conf, CONF_proxy_telnet_command); - int so = 0, eo = 0; - strbuf *buf = strbuf_new(); - unsigned flags = 0; - - /* we need to escape \\, \%, \r, \n, \t, \x??, \0???, - * %%, %host, %port, %user, and %pass - */ - - while (fmt[eo] != 0) { - - /* scan forward until we hit end-of-line, - * or an escape character (\ or %) */ - while (fmt[eo] != 0 && fmt[eo] != '%' && fmt[eo] != '\\') - eo++; - - /* if we hit eol, break out of our escaping loop */ - if (fmt[eo] == 0) break; - - /* if there was any unescaped text before the escape - * character, send that now */ - if (eo != so) - put_data(buf, fmt + so, eo - so); - - so = eo++; - - /* if the escape character was the last character of - * the line, we'll just stop and send it. */ - if (fmt[eo] == 0) break; - - if (fmt[so] == '\\') { - - /* we recognize \\, \%, \r, \n, \t, \x??. - * anything else, we just send unescaped (including the \). - */ - - switch (fmt[eo]) { - - case '\\': - put_byte(buf, '\\'); - eo++; - break; - - case '%': - put_byte(buf, '%'); - eo++; - break; - - case 'r': - put_byte(buf, '\r'); - eo++; - break; - - case 'n': - put_byte(buf, '\n'); - eo++; - break; - - case 't': - put_byte(buf, '\t'); - eo++; - break; - - case 'x': - case 'X': { - /* escaped hexadecimal value (ie. \xff) */ - unsigned char v = 0; - int i = 0; - - for (;;) { - eo++; - if (fmt[eo] >= '0' && fmt[eo] <= '9') - v += fmt[eo] - '0'; - else if (fmt[eo] >= 'a' && fmt[eo] <= 'f') - v += fmt[eo] - 'a' + 10; - else if (fmt[eo] >= 'A' && fmt[eo] <= 'F') - v += fmt[eo] - 'A' + 10; - else { - /* non hex character, so we abort and just - * send the whole thing unescaped (including \x) - */ - put_byte(buf, '\\'); - eo = so + 1; - break; - } - - /* we only extract two hex characters */ - if (i == 1) { - put_byte(buf, v); - eo++; - break; - } - - i++; - v <<= 4; - } - break; - } - - default: - put_data(buf, fmt + so, 2); - eo++; - break; - } - } else { - - /* % escape. we recognize %%, %host, %port, %user, %pass. - * %proxyhost, %proxyport. Anything else we just send - * unescaped (including the %). - */ - - if (fmt[eo] == '%') { - put_byte(buf, '%'); - eo++; - } - else if (strnicmp(fmt + eo, "host", 4) == 0) { - char dest[512]; - sk_getaddr(addr, dest, lenof(dest)); - put_data(buf, dest, strlen(dest)); - eo += 4; - } - else if (strnicmp(fmt + eo, "port", 4) == 0) { - put_fmt(buf, "%d", port); - eo += 4; - } - else if (strnicmp(fmt + eo, "user", 4) == 0) { - const char *username = conf_get_str(conf, CONF_proxy_username); - put_data(buf, username, strlen(username)); - eo += 4; - if (!*username) - flags |= TELNET_CMD_MISSING_USERNAME; - } - else if (strnicmp(fmt + eo, "pass", 4) == 0) { - const char *password = conf_get_str(conf, CONF_proxy_password); - put_data(buf, password, strlen(password)); - eo += 4; - if (!*password) - flags |= TELNET_CMD_MISSING_PASSWORD; - } - else if (strnicmp(fmt + eo, "proxyhost", 9) == 0) { - const char *host = conf_get_str(conf, CONF_proxy_host); - put_data(buf, host, strlen(host)); - eo += 9; - } - else if (strnicmp(fmt + eo, "proxyport", 9) == 0) { - int port = conf_get_int(conf, CONF_proxy_port); - put_fmt(buf, "%d", port); - eo += 9; - } - else { - /* we don't escape this, so send the % now, and - * don't advance eo, so that we'll consider the - * text immediately following the % as unescaped. - */ - put_byte(buf, '%'); - } - } - - /* resume scanning for additional escapes after this one. */ - so = eo; - } - - /* if there is any unescaped text at the end of the line, send it */ - if (eo != so) { - put_data(buf, fmt + so, eo - so); - } - - if (flags_out) - *flags_out = flags; - return strbuf_to_str(buf); + return format_connection_setup_command( + conf_get_str(conf, CONF_proxy_telnet_command), + addr, port, conf, flags_out); } typedef struct TelnetProxyNegotiator { diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt index 2581559e..46df7e63 100644 --- a/utils/CMakeLists.txt +++ b/utils/CMakeLists.txt @@ -35,6 +35,7 @@ add_sources_from_current_dir(utils encode_utf8.c encode_wide_string_as_utf8.c fgetline.c + format_connection_setup_command.c host_ca_new_free.c host_strchr.c host_strchr_internal.c diff --git a/utils/format_connection_setup_command.c b/utils/format_connection_setup_command.c new file mode 100644 index 00000000..adcfa7d2 --- /dev/null +++ b/utils/format_connection_setup_command.c @@ -0,0 +1,184 @@ +/* + * Formats a command line using the formatting language common to + * Telnet proxies, local proxy commands, and pre-connection hooks. + * + * Returns the formatted command, dynamically allocated. Also, + * optionally, returns flags indicating whether %user or %pass were + * referred to but not provided in the Conf. + */ + +#include "putty.h" + +char *format_connection_setup_command( + const char *fmt, SockAddr *addr, int port, Conf *conf, unsigned *flags_out) +{ + int so = 0, eo = 0; + strbuf *buf = strbuf_new(); + unsigned flags = 0; + + /* we need to escape \\, \%, \r, \n, \t, \x??, \0???, + * %%, %host, %port, %user, and %pass + */ + + while (fmt[eo] != 0) { + + /* scan forward until we hit end-of-line, + * or an escape character (\ or %) */ + while (fmt[eo] != 0 && fmt[eo] != '%' && fmt[eo] != '\\') + eo++; + + /* if we hit eol, break out of our escaping loop */ + if (fmt[eo] == 0) break; + + /* if there was any unescaped text before the escape + * character, send that now */ + if (eo != so) + put_data(buf, fmt + so, eo - so); + + so = eo++; + + /* if the escape character was the last character of + * the line, we'll just stop and send it. */ + if (fmt[eo] == 0) break; + + if (fmt[so] == '\\') { + + /* we recognize \\, \%, \r, \n, \t, \x??. + * anything else, we just send unescaped (including the \). + */ + + switch (fmt[eo]) { + + case '\\': + put_byte(buf, '\\'); + eo++; + break; + + case '%': + put_byte(buf, '%'); + eo++; + break; + + case 'r': + put_byte(buf, '\r'); + eo++; + break; + + case 'n': + put_byte(buf, '\n'); + eo++; + break; + + case 't': + put_byte(buf, '\t'); + eo++; + break; + + case 'x': + case 'X': { + /* escaped hexadecimal value (ie. \xff) */ + unsigned char v = 0; + int i = 0; + + for (;;) { + eo++; + if (fmt[eo] >= '0' && fmt[eo] <= '9') + v += fmt[eo] - '0'; + else if (fmt[eo] >= 'a' && fmt[eo] <= 'f') + v += fmt[eo] - 'a' + 10; + else if (fmt[eo] >= 'A' && fmt[eo] <= 'F') + v += fmt[eo] - 'A' + 10; + else { + /* non hex character, so we abort and just + * send the whole thing unescaped (including \x) + */ + put_byte(buf, '\\'); + eo = so + 1; + break; + } + + /* we only extract two hex characters */ + if (i == 1) { + put_byte(buf, v); + eo++; + break; + } + + i++; + v <<= 4; + } + break; + } + + default: + put_data(buf, fmt + so, 2); + eo++; + break; + } + } else { + + /* % escape. we recognize %%, %host, %port, %user, %pass. + * %proxyhost, %proxyport. Anything else we just send + * unescaped (including the %). + */ + + if (fmt[eo] == '%') { + put_byte(buf, '%'); + eo++; + } + else if (strnicmp(fmt + eo, "host", 4) == 0) { + char dest[512]; + sk_getaddr(addr, dest, lenof(dest)); + put_data(buf, dest, strlen(dest)); + eo += 4; + } + else if (strnicmp(fmt + eo, "port", 4) == 0) { + put_fmt(buf, "%d", port); + eo += 4; + } + else if (strnicmp(fmt + eo, "user", 4) == 0) { + const char *username = conf_get_str(conf, CONF_proxy_username); + put_data(buf, username, strlen(username)); + eo += 4; + if (!*username) + flags |= TELNET_CMD_MISSING_USERNAME; + } + else if (strnicmp(fmt + eo, "pass", 4) == 0) { + const char *password = conf_get_str(conf, CONF_proxy_password); + put_data(buf, password, strlen(password)); + eo += 4; + if (!*password) + flags |= TELNET_CMD_MISSING_PASSWORD; + } + else if (strnicmp(fmt + eo, "proxyhost", 9) == 0) { + const char *host = conf_get_str(conf, CONF_proxy_host); + put_data(buf, host, strlen(host)); + eo += 9; + } + else if (strnicmp(fmt + eo, "proxyport", 9) == 0) { + int port = conf_get_int(conf, CONF_proxy_port); + put_fmt(buf, "%d", port); + eo += 9; + } + else { + /* we don't escape this, so send the % now, and + * don't advance eo, so that we'll consider the + * text immediately following the % as unescaped. + */ + put_byte(buf, '%'); + } + } + + /* resume scanning for additional escapes after this one. */ + so = eo; + } + + /* if there is any unescaped text at the end of the line, send it */ + if (eo != so) { + put_data(buf, fmt + so, eo - so); + } + + if (flags_out) + *flags_out = flags; + return strbuf_to_str(buf); +} From 503d6139d5e1a7c727343e7c06c39778f18dfb25 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sat, 10 Jan 2026 09:25:18 +0000 Subject: [PATCH 106/129] New feature: a pre-connection command hook. Patch due to Jonathan Senkerik. This adds a new config feature to spawn a subprocess, on both of Windows and Unix, just before making the main outgoing network connection of the session. The idea is that you'd use it to run a tool that temporarily opens the network port you plan to connect to, such as a port knocker or similar. The subprocess is run synchronously: PuTTY waits for it to terminate before continuing with the session. Its output and exit status are logged in the Event Log, although if it fails, PuTTY will proceed with the connection attempt anyway. (You could imagine that a port knocker might leave the port open for long enough that a second connection shortly afterwards might succeed even if the knock command failed for some reason.) --- cmdline.c | 5 ++ conf.h | 5 ++ config.c | 6 ++ doc/config.but | 22 ++++++ doc/index.but | 4 + misc.h | 4 + otherbackends/raw.c | 5 ++ otherbackends/rlogin.c | 5 ++ otherbackends/supdup.c | 5 ++ otherbackends/telnet.c | 5 ++ ssh/ssh.c | 5 ++ unix/CMakeLists.txt | 1 + unix/utils/command_hook.c | 130 ++++++++++++++++++++++++++++++++ windows/CMakeLists.txt | 1 + windows/help.h | 1 + windows/utils/command_hook.c | 140 +++++++++++++++++++++++++++++++++++ 16 files changed, 344 insertions(+) create mode 100644 unix/utils/command_hook.c create mode 100644 windows/utils/command_hook.c diff --git a/cmdline.c b/cmdline.c index 5de30f7f..d625f8d2 100644 --- a/cmdline.c +++ b/cmdline.c @@ -471,6 +471,11 @@ int cmdline_process_param(CmdlineArg *arg, CmdlineArg *nextarg, SAVEABLE(0); conf_set_str(conf, CONF_loghost, value); } + if (!strcmp(p, "-preconnectcommand")) { + RETURN(2); + SAVEABLE(1); + conf_set_str(conf, CONF_pre_connect_command, value); + } if (!strcmp(p, "-hostkey")) { char *dup; RETURN(2); diff --git a/conf.h b/conf.h index 25e3333d..4a47ccc8 100644 --- a/conf.h +++ b/conf.h @@ -90,6 +90,11 @@ CONF_OPTION(loghost, /* logical host being contacted, for host key check */ DEFAULT_STR(""), SAVE_KEYWORD("LogHost"), ) +CONF_OPTION(pre_connect_command, + VALUE_TYPE(STR), + DEFAULT_STR(""), + SAVE_KEYWORD("PreConnectCommand"), +) /* Proxy options */ CONF_OPTION(proxy_exclude_list, diff --git a/config.c b/config.c index a94a4cca..9602c1d9 100644 --- a/config.c +++ b/config.c @@ -2512,6 +2512,12 @@ void setup_config_box(struct controlbox *b, bool midsession, HELPCTX(connection_loghost), conf_editbox_handler, I(CONF_loghost), ED_STR); } + + s = ctrl_getset(b, "Connection", "hooks", + "Command to run at connection event"); + ctrl_editbox(s, "Command to run before connection", NO_SHORTCUT, 100, + HELPCTX(connection_pre_hook), + conf_editbox_handler, I(CONF_pre_connect_command), ED_STR); } /* diff --git a/doc/config.but b/doc/config.but index f78d86b0..bf0d216f 100644 --- a/doc/config.but +++ b/doc/config.but @@ -1859,6 +1859,28 @@ to, which is more important than the mere means you happen to be using to contact that host. (This applies even if you're using a protocol other than SSH.) +\S{config-preconn-hook} \I{pre-connection command}\q{Command to run before connection} + +If you enter a command line in this box, then PuTTY will run that +command as a subprocess, just before making its main outgoing network +connection. + +This could be useful if you are connecting to a server which requires +a preliminary signal such as \q{port knocking} before it will accept a +connection to its SSH server port in the first place. If you have a +program that knows how to send the correct knock, you can enter its +command line in this box. + +The results of running the program will be logged in PuTTY's Event +Log. So if it terminates with an error message, the Event Log will +show the message. + +\s{NOTE} that when PuTTY runs this command as a subprocess, it will +stop responding completely while it waits for the subprocess to finish +\dash it will not even respond to the GUI. So you should make sure the +knock command completes quickly, whether it succeeds or fails, or +PuTTY will become unresponsive. + \H{config-data} The Data panel The Data panel allows you to configure various pieces of data which diff --git a/doc/index.but b/doc/index.but index da38a866..fa6d7f1c 100644 --- a/doc/index.but +++ b/doc/index.but @@ -994,3 +994,7 @@ saved sessions from \IM{Microsoft Store} Microsoft Store \IM{Microsoft Store} Windows Store + +\IM{pre-connection command} pre-connection command +\IM{pre-connection command} command, pre-connection +\IM{pre-connection command} subprocess, pre-connection diff --git a/misc.h b/misc.h index 41784ee8..b7ecee68 100644 --- a/misc.h +++ b/misc.h @@ -574,4 +574,8 @@ char *format_connection_setup_command( const char *fmt, SockAddr *addr, int port, Conf *conf, unsigned *flags_out); +/* Execute a command hook (synchronous execution with logging) */ +void execute_command_hook(LogContext *logctx, const char *command, + SockAddr *addr, int port, Conf *conf); + #endif diff --git a/otherbackends/raw.c b/otherbackends/raw.c index 01c776e2..6b4d9845 100644 --- a/otherbackends/raw.c +++ b/otherbackends/raw.c @@ -205,6 +205,11 @@ static char *raw_init(const BackendVtable *vt, Seat *seat, if (port < 0) port = 23; /* default telnet port */ + /* Execute pre-connection command hook */ + execute_command_hook(raw->logctx, + conf_get_str(raw->conf, CONF_pre_connect_command), + addr, port, raw->conf); + /* * Open socket. */ diff --git a/otherbackends/rlogin.c b/otherbackends/rlogin.c index 6efe036f..7f62b38b 100644 --- a/otherbackends/rlogin.c +++ b/otherbackends/rlogin.c @@ -290,6 +290,11 @@ static char *rlogin_init(const BackendVtable *vt, Seat *seat, if (port < 0) port = 513; /* default rlogin port */ + /* Execute pre-connection command hook */ + execute_command_hook(rlogin->logctx, + conf_get_str(rlogin->conf, CONF_pre_connect_command), + addr, port, rlogin->conf); + /* * Open socket. */ diff --git a/otherbackends/supdup.c b/otherbackends/supdup.c index 8f814797..231a8df9 100644 --- a/otherbackends/supdup.c +++ b/otherbackends/supdup.c @@ -753,6 +753,11 @@ static char *supdup_init(const BackendVtable *x, Seat *seat, if (port < 0) port = 0137; /* default supdup port */ + /* Execute pre-connection command hook */ + execute_command_hook(supdup->logctx, + conf_get_str(supdup->conf, CONF_pre_connect_command), + addr, port, supdup->conf); + /* * Open socket. */ diff --git a/otherbackends/telnet.c b/otherbackends/telnet.c index 7f1e4977..86c58b5a 100644 --- a/otherbackends/telnet.c +++ b/otherbackends/telnet.c @@ -759,6 +759,11 @@ static char *telnet_init(const BackendVtable *vt, Seat *seat, if (port < 0) port = 23; /* default telnet port */ + /* Execute pre-connection command hook */ + execute_command_hook(telnet->logctx, + conf_get_str(telnet->conf, CONF_pre_connect_command), + addr, port, telnet->conf); + /* * Open socket. */ diff --git a/ssh/ssh.c b/ssh/ssh.c index 6d72ed1c..b9e4e849 100644 --- a/ssh/ssh.c +++ b/ssh/ssh.c @@ -836,6 +836,11 @@ static char *connect_to_host( } ssh->fullhostname = dupstr(*realhost); /* save in case of GSSAPI */ + /* Execute pre-connection command hook */ + execute_command_hook(ssh->logctx, + conf_get_str(ssh->conf, CONF_pre_connect_command), + addr, port, ssh->conf); + ssh->s = new_connection(addr, *realhost, port, false, true, nodelay, keepalive, &ssh->plug, ssh->conf, &ssh->interactor); diff --git a/unix/CMakeLists.txt b/unix/CMakeLists.txt index df5d275d..b76628ba 100644 --- a/unix/CMakeLists.txt +++ b/unix/CMakeLists.txt @@ -5,6 +5,7 @@ add_sources_from_current_dir(utils utils/block_signal.c utils/cloexec.c utils/cmdline_arg.c + utils/command_hook.c utils/dputs.c utils/filename.c utils/fontspec.c diff --git a/unix/utils/command_hook.c b/unix/utils/command_hook.c new file mode 100644 index 00000000..dcb2cef8 --- /dev/null +++ b/unix/utils/command_hook.c @@ -0,0 +1,130 @@ +/* + * Unix implementation of command hook execution (synchronous with logging) + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "putty.h" + +void execute_command_hook(LogContext *logctx, const char *command_pattern, + SockAddr *addr, int port, Conf *conf) +{ + pid_t pid; + int status; + int stdout_pipe[2] = {-1, -1}; + int stderr_pipe[2] = {-1, -1}; + + if (!command_pattern || !*command_pattern) + return; + + Conf *tmpconf = conf_copy(conf); + conf_set_str(conf, CONF_proxy_username, ""); + conf_set_str(conf, CONF_proxy_password, ""); + unsigned flags; + char *command = format_connection_setup_command( + command_pattern, addr, port, tmpconf, &flags); + if (flags & (TELNET_CMD_MISSING_USERNAME | + TELNET_CMD_MISSING_PASSWORD)) { + logeventf(logctx, "Pre-connect command: references to %%user or " + "%%pass not supported"); + sfree(command); + return; + } + conf_free(tmpconf); + + /* Create pipes for capturing stdout and stderr */ + if (pipe(stdout_pipe) < 0 || pipe(stderr_pipe) < 0) { + logeventf(logctx, "Pre-connect command: failed to create pipes: %s", + strerror(errno)); + if (stdout_pipe[0] >= 0) close(stdout_pipe[0]); + if (stdout_pipe[1] >= 0) close(stdout_pipe[1]); + if (stderr_pipe[0] >= 0) close(stderr_pipe[0]); + if (stderr_pipe[1] >= 0) close(stderr_pipe[1]); + return; + } + + /* Log the command being executed */ + logeventf(logctx, "Running pre-connect command: %s", command); + + /* Fork and execute */ + pid = fork(); + if (pid == 0) { + /* Child process */ + /* Close read ends of pipes */ + close(stdout_pipe[0]); + close(stderr_pipe[0]); + + /* Redirect stdout and stderr */ + dup2(stdout_pipe[1], STDOUT_FILENO); + dup2(stderr_pipe[1], STDERR_FILENO); + close(stdout_pipe[1]); + close(stderr_pipe[1]); + + /* Execute the command through shell */ + execl("/bin/sh", "sh", "-c", command, (char *)NULL); + + /* If execl fails, exit */ + _exit(127); + } else if (pid > 0) { + char buf[512]; + ssize_t n; + bool has_output = false; + + /* Parent process - close write ends of pipes */ + close(stdout_pipe[1]); + close(stderr_pipe[1]); + stdout_pipe[1] = -1; + stderr_pipe[1] = -1; + + /* Read and log stdout */ + while ((n = read(stdout_pipe[0], buf, sizeof(buf) - 1)) > 0) { + buf[n] = '\0'; + if (!has_output) { + logevent(logctx, "Pre-connect command:"); + has_output = true; + } + logevent(logctx, buf); + } + close(stdout_pipe[0]); + + /* Read and log stderr */ + has_output = false; + while ((n = read(stderr_pipe[0], buf, sizeof(buf) - 1)) > 0) { + buf[n] = '\0'; + if (!has_output) { + logevent(logctx, "Pre-connect command stderr:"); + has_output = true; + } + logevent(logctx, buf); + } + close(stderr_pipe[0]); + + /* Wait for command to complete and log exit status */ + waitpid(pid, &status, 0); + if (WIFEXITED(status)) { + logeventf(logctx, "Pre-connect command exited with status %d", + WEXITSTATUS(status)); + } else if (WIFSIGNALED(status)) { + logeventf(logctx, "Pre-connect command killed by signal %d", + WTERMSIG(status)); + } else { + logevent(logctx, "Pre-connect command terminated abnormally"); + } + } else { + /* Fork failed */ + close(stdout_pipe[0]); + close(stdout_pipe[1]); + close(stderr_pipe[0]); + close(stderr_pipe[1]); + logeventf(logctx, "Pre-connect command: fork failed: %s", + strerror(errno)); + } + + sfree(command); +} diff --git a/windows/CMakeLists.txt b/windows/CMakeLists.txt index 1b5c6162..83db781b 100644 --- a/windows/CMakeLists.txt +++ b/windows/CMakeLists.txt @@ -8,6 +8,7 @@ add_sources_from_current_dir(utils utils/blink_time.c utils/centre_window.c utils/cmdline_arg.c + utils/command_hook.c utils/cryptoapi.c utils/defaults.c utils/dll_hijacking_protection.c diff --git a/windows/help.h b/windows/help.h index 8430da58..295a3581 100644 --- a/windows/help.h +++ b/windows/help.h @@ -87,6 +87,7 @@ typedef const char *HelpCtx; #define WINHELP_CTX_connection_ipversion "config-address-family" #define WINHELP_CTX_connection_tcpkeepalive "config-tcp-keepalives" #define WINHELP_CTX_connection_loghost "config-loghost" +#define WINHELP_CTX_connection_pre_hook "config-preconn-hook" #define WINHELP_CTX_proxy_type "config-proxy-type" #define WINHELP_CTX_proxy_main "config-proxy" #define WINHELP_CTX_proxy_exclude "config-proxy-exclude" diff --git a/windows/utils/command_hook.c b/windows/utils/command_hook.c new file mode 100644 index 00000000..bf6fb08f --- /dev/null +++ b/windows/utils/command_hook.c @@ -0,0 +1,140 @@ +/* + * Windows implementation of command hook execution (synchronous with logging) + */ + +#include + +#include "putty.h" + +static void read_and_log_pipe(HANDLE pipe, LogContext *logctx, const char *label) +{ + char buf[512]; + DWORD bytesRead; + bool has_output = false; + + while (ReadFile(pipe, buf, sizeof(buf) - 1, &bytesRead, NULL) && bytesRead > 0) { + buf[bytesRead] = '\0'; + if (!has_output) { + logeventf(logctx, "Pre-connect command %s:", label); + has_output = true; + } + logevent(logctx, buf); + } +} + +void execute_command_hook(LogContext *logctx, const char *command_pattern, + SockAddr *addr, int port, Conf *conf) +{ + STARTUPINFO si; + PROCESS_INFORMATION pi; + BOOL result; + HANDLE stdout_read = INVALID_HANDLE_VALUE; + HANDLE stdout_write = INVALID_HANDLE_VALUE; + HANDLE stderr_read = INVALID_HANDLE_VALUE; + HANDLE stderr_write = INVALID_HANDLE_VALUE; + SECURITY_ATTRIBUTES sa; + DWORD exit_code = 0; + + if (!command_pattern || !*command_pattern) + return; + + /* Format the hook command, but first, make sure %user and %pass + * aren't expanded. (Those will refer to the _proxy_ username and + * password.) */ + Conf *tmpconf = conf_copy(conf); + conf_set_str(conf, CONF_proxy_username, ""); + conf_set_str(conf, CONF_proxy_password, ""); + unsigned flags; + char *command = format_connection_setup_command( + command_pattern, addr, port, tmpconf, &flags); + if (flags & (TELNET_CMD_MISSING_USERNAME | + TELNET_CMD_MISSING_PASSWORD)) { + logeventf(logctx, "Pre-connect command: references to %%user or " + "%%pass not supported"); + sfree(command); + return; + } + conf_free(tmpconf); + + /* Set up security attributes for pipes */ + sa.nLength = sizeof(SECURITY_ATTRIBUTES); + sa.bInheritHandle = TRUE; + sa.lpSecurityDescriptor = NULL; + + /* Create pipes for capturing stdout and stderr */ + if (!CreatePipe(&stdout_read, &stdout_write, &sa, 0) || + !CreatePipe(&stderr_read, &stderr_write, &sa, 0)) { + DWORD error = GetLastError(); + if (stdout_read != INVALID_HANDLE_VALUE) CloseHandle(stdout_read); + if (stdout_write != INVALID_HANDLE_VALUE) CloseHandle(stdout_write); + if (stderr_read != INVALID_HANDLE_VALUE) CloseHandle(stderr_read); + if (stderr_write != INVALID_HANDLE_VALUE) CloseHandle(stderr_write); + logeventf(logctx, "Pre-connect command: failed to create pipes: %s", + win_strerror(error)); + return; + } + + /* Prepare startup info */ + ZeroMemory(&si, sizeof(si)); + si.cb = sizeof(si); + si.hStdOutput = stdout_write; + si.hStdError = stderr_write; + si.dwFlags |= STARTF_USESTDHANDLES; + ZeroMemory(&pi, sizeof(pi)); + + /* Log the command being executed */ + logeventf(logctx, "Running pre-connect command: %s", command); + + /* Execute the command through cmd.exe */ + result = CreateProcess( + NULL, /* No module name (use command line) */ + (char *)command,/* Command line (cast away const for Win32 API) */ + NULL, /* Process handle not inheritable */ + NULL, /* Thread handle not inheritable */ + TRUE, /* Set handle inheritance to TRUE */ + 0, /* No creation flags */ + NULL, /* Use parent's environment block */ + NULL, /* Use parent's starting directory */ + &si, /* Pointer to STARTUPINFO structure */ + &pi /* Pointer to PROCESS_INFORMATION structure */ + ); + + if (result) { + /* Close the write ends of pipes in parent */ + CloseHandle(stdout_write); + CloseHandle(stderr_write); + stdout_write = INVALID_HANDLE_VALUE; + stderr_write = INVALID_HANDLE_VALUE; + + /* Read and log stdout */ + read_and_log_pipe(stdout_read, logctx, "stdout"); + CloseHandle(stdout_read); + stdout_read = INVALID_HANDLE_VALUE; + + /* Read and log stderr */ + read_and_log_pipe(stderr_read, logctx, "stderr"); + CloseHandle(stderr_read); + stderr_read = INVALID_HANDLE_VALUE; + + /* Wait for command to complete */ + WaitForSingleObject(pi.hProcess, INFINITE); + + /* Get exit code */ + GetExitCodeProcess(pi.hProcess, &exit_code); + logeventf(logctx, "Pre-connect command exited with status %lu", + exit_code); + + /* Close process and thread handles */ + CloseHandle(pi.hProcess); + CloseHandle(pi.hThread); + } else { + /* CreateProcess failed */ + DWORD error = GetLastError(); + CloseHandle(stdout_read); + CloseHandle(stdout_write); + CloseHandle(stderr_read); + CloseHandle(stderr_write); + logeventf(logctx, "Pre-connect command: CreateProcess failed: %s", + win_strerror(error)); + } +} From 37c7e6975d08a027f090f1184a1196c9ddabf098 Mon Sep 17 00:00:00 2001 From: Jacob Nevins Date: Wed, 18 Feb 2026 23:38:25 +0000 Subject: [PATCH 107/129] Disallow -preconnectcommand in pterm. --- cmdline.c | 1 + 1 file changed, 1 insertion(+) diff --git a/cmdline.c b/cmdline.c index d625f8d2..715b1d48 100644 --- a/cmdline.c +++ b/cmdline.c @@ -473,6 +473,7 @@ int cmdline_process_param(CmdlineArg *arg, CmdlineArg *nextarg, } if (!strcmp(p, "-preconnectcommand")) { RETURN(2); + UNAVAILABLE_IN(TOOLTYPE_NONNETWORK); SAVEABLE(1); conf_set_str(conf, CONF_pre_connect_command, value); } From 1c0490dd3cc3c8432f42c46af10091a4f51e395c Mon Sep 17 00:00:00 2001 From: Jacob Nevins Date: Wed, 18 Feb 2026 23:38:43 +0000 Subject: [PATCH 108/129] Add an accelerator for pre-connect command. --- config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.c b/config.c index 9602c1d9..4c90de85 100644 --- a/config.c +++ b/config.c @@ -2515,7 +2515,7 @@ void setup_config_box(struct controlbox *b, bool midsession, s = ctrl_getset(b, "Connection", "hooks", "Command to run at connection event"); - ctrl_editbox(s, "Command to run before connection", NO_SHORTCUT, 100, + ctrl_editbox(s, "Command to run before connection", 'b', 100, HELPCTX(connection_pre_hook), conf_editbox_handler, I(CONF_pre_connect_command), ED_STR); } From 458652ddc8a405bf86635abbc618dc5c8e7a11bf Mon Sep 17 00:00:00 2001 From: Jacob Nevins Date: Wed, 18 Feb 2026 23:49:42 +0000 Subject: [PATCH 109/129] Add -preconnectcommand to usage messages. --- pscp.c | 2 ++ psftp.c | 2 ++ unix/plink.c | 2 ++ windows/plink.c | 2 ++ 4 files changed, 8 insertions(+) diff --git a/pscp.c b/pscp.c index 1aa812eb..62da303a 100644 --- a/pscp.c +++ b/pscp.c @@ -2227,6 +2227,8 @@ static void usage(void) " standard error\n"); printf(" -proxycmd command\n"); printf(" use 'command' as local proxy\n"); + printf(" -preconnectcommand command\n"); + printf(" run 'command' before making network connection\n"); printf(" -unsafe allow server-side wildcards (DANGEROUS)\n"); printf(" -sftp force use of SFTP protocol\n"); printf(" -scp force use of SCP protocol\n"); diff --git a/psftp.c b/psftp.c index 927ac688..69fc21be 100644 --- a/psftp.c +++ b/psftp.c @@ -2559,6 +2559,8 @@ static void usage(void) " standard error\n"); printf(" -proxycmd command\n"); printf(" use 'command' as local proxy\n"); + printf(" -preconnectcommand command\n"); + printf(" run 'command' before making network connection\n"); printf(" -sshlog file\n"); printf(" -sshrawlog file\n"); printf(" log protocol details to a file\n"); diff --git a/unix/plink.c b/unix/plink.c index 8bae403d..27f9fe8e 100644 --- a/unix/plink.c +++ b/unix/plink.c @@ -529,6 +529,8 @@ static void usage(void) printf(" -batch disable all interactive prompts\n"); printf(" -proxycmd command\n"); printf(" use 'command' as local proxy\n"); + printf(" -preconnectcommand command\n"); + printf(" run 'command' before making network connection\n"); printf(" -sercfg configuration-string (e.g. 19200,8,n,1,X)\n"); printf(" Specify the serial configuration (serial only)\n"); printf("The following options only apply to SSH connections:\n"); diff --git a/windows/plink.c b/windows/plink.c index 4a25f7d7..4cc787fb 100644 --- a/windows/plink.c +++ b/windows/plink.c @@ -145,6 +145,8 @@ static void usage(void) printf(" -batch disable all interactive prompts\n"); printf(" -proxycmd command\n"); printf(" use 'command' as local proxy\n"); + printf(" -preconnectcommand command\n"); + printf(" run 'command' before making network connection\n"); printf(" -sercfg configuration-string (e.g. 19200,8,n,1,X)\n"); printf(" Specify the serial configuration (serial only)\n"); printf("The following options only apply to SSH connections:\n"); From af33ecdc88fed05bfcd08a6d6d60c35775c743bd Mon Sep 17 00:00:00 2001 From: Jacob Nevins Date: Wed, 18 Feb 2026 23:39:27 +0000 Subject: [PATCH 110/129] Docs: improve pre-connect command documentation. Document %host and %port escapes. Document -preconnectcommand command-line option. Index 'port knocking'. --- doc/config.but | 9 +++++++-- doc/man-plink.but | 6 ++++++ doc/man-pscp.but | 6 ++++++ doc/man-psftp.but | 6 ++++++ doc/man-putty.but | 6 ++++++ doc/man-puttytel.but | 6 ++++++ doc/using.but | 7 +++++++ 7 files changed, 44 insertions(+), 2 deletions(-) diff --git a/doc/config.but b/doc/config.but index bf0d216f..3461bfaf 100644 --- a/doc/config.but +++ b/doc/config.but @@ -1866,11 +1866,16 @@ command as a subprocess, just before making its main outgoing network connection. This could be useful if you are connecting to a server which requires -a preliminary signal such as \q{port knocking} before it will accept a -connection to its SSH server port in the first place. If you have a +a preliminary signal such as \q{\i{port knocking}} before it will accept +a connection to its SSH server port in the first place. If you have a program that knows how to send the correct knock, you can enter its command line in this box. +In the command string, the special strings \c{%host} and \c{%port} will +be replaced by the host name and port number you want to connect to, +similar to specifying a proxy command; see \k{config-proxy-command} for +the full syntax. + The results of running the program will be logged in PuTTY's Event Log. So if it terminates with an error message, the Event Log will show the message. diff --git a/doc/man-plink.but b/doc/man-plink.but index 2a3b36c7..46347126 100644 --- a/doc/man-plink.but +++ b/doc/man-plink.but @@ -84,6 +84,12 @@ and backslash-delimited tokens, although most of them are probably not very useful in this context.) } +\dt \cw{\-preconnectcommand} \e{command} + +\dd Specify an external command to run just before making the main +network connection. The syntax of \e{command} is similar to that +for \cw{-proxycmd}. + \dt \cw{-P} \e{port} \dd Connect to port \e{port}. diff --git a/doc/man-pscp.but b/doc/man-pscp.but index 544d3a40..9315c7b6 100644 --- a/doc/man-pscp.but +++ b/doc/man-pscp.but @@ -86,6 +86,12 @@ and backslash-delimited tokens, although most of them are probably not very useful in this context.) } +\dt \cw{\-preconnectcommand} \e{command} + +\dd Specify an external command to run just before making the main +network connection. The syntax of \e{command} is similar to that +for \cw{-proxycmd}. + \dt \cw{-l} \e{user} \dd Set remote username to \e{user}. diff --git a/doc/man-psftp.but b/doc/man-psftp.but index e0b48602..1f4c118a 100644 --- a/doc/man-psftp.but +++ b/doc/man-psftp.but @@ -74,6 +74,12 @@ and backslash-delimited tokens, although most of them are probably not very useful in this context.) } +\dt \cw{\-preconnectcommand} \e{command} + +\dd Specify an external command to run just before making the main +network connection. The syntax of \e{command} is similar to that +for \cw{-proxycmd}. + \dt \cw{-l} \e{user} \dd Set remote username to \e{user}. diff --git a/doc/man-putty.but b/doc/man-putty.but index a85b4505..3d3fc501 100644 --- a/doc/man-putty.but +++ b/doc/man-putty.but @@ -210,6 +210,12 @@ and backslash-delimited tokens, although most of them are probably not very useful in this context.) } +\dt \cw{\-preconnectcommand} \e{command} + +\dd Specify an external command to run just before making the main +network connection. The syntax of \e{command} is similar to that +for \cw{-proxycmd}. + \dt \cw{\-l} \e{username} \dd Specify the username to use when logging in to the server. diff --git a/doc/man-puttytel.but b/doc/man-puttytel.but index 075eeea7..870c3292 100644 --- a/doc/man-puttytel.but +++ b/doc/man-puttytel.but @@ -186,6 +186,12 @@ and backslash-delimited tokens, although most of them are probably not very useful in this context.) } +\dt \cw{\-preconnectcommand} \e{command} + +\dd Specify an external command to run just before making the main +network connection. The syntax of \e{command} is similar to that +for \cw{-proxycmd}. + \dt \cw{\-l} \e{username} \dd Specify the username to use when logging in to the server. diff --git a/doc/using.but b/doc/using.but index 1bc230ee..d330d10d 100644 --- a/doc/using.but +++ b/doc/using.but @@ -1133,6 +1133,13 @@ described there are understood in the argument string, literal backslashes must be doubled (if you want \c{\\} in your command, you must put \c{\\\\} on the command line). +\S2{using-cmdline-preconnectcommand} \i\c{\-preconnectcommand}: +run a command before making a network connection + +This option specifies an external command to run just before opening +the main network connection. See \k{config-preconn-hook} for more +details. + \S2{using-cmdline-share-noshare} \i\c{\-share}, \i\c{\-noshare}: enable/disable connection sharing From af996b5ec27ab79bae3882071b9d6acf16044549 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Wed, 25 Feb 2026 08:29:58 +0000 Subject: [PATCH 111/129] eddsa_verify: add check for out-of-range s. The integer s in an EdDSA signature is treated as an exponent: the curve's base point is raised to that power. (OK, multiplied by it, if you use the elliptic curve notational convention rather than the general group convention.) Therefore, in principle, it doesn't make any difference if s varies by a multiple of the base point's order (which is around 2^252, therefore a larger s still fits easily within the 256-bit space for it in the signature encoding). However, RFC 8032 requires s to be strictly less than that order, so that there's a single canonical encoding for any given signature. I'm not treating this as a vulnerability because I don't believe there's any situation in SSH where canonicality of signatures is important. But it should be fixed, nonetheless. In the fix, it's OK to use an ordinary if statement to check the bound on s, because they're visible to everybody anyway: the integer s is encoded directly in the signature, and the bound we're checking it against is a well-known public integer, so nothing new is revealed by any timing side channel proving that that was the reason for the rejection. (Not even if the message being signed were secret, which it is in SSH: the validation of s doesn't depend on the message.) Thanks to Yujie Zhu for the report. --- crypto/ecc-ssh.c | 5 +++++ test/cryptsuite.py | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/crypto/ecc-ssh.c b/crypto/ecc-ssh.c index e524dfc4..fcde908d 100644 --- a/crypto/ecc-ssh.c +++ b/crypto/ecc-ssh.c @@ -1091,6 +1091,11 @@ static bool eddsa_verify(ssh_key *key, ptrlen sig, ptrlen data) if (!r) return false; mp_int *s = mp_from_bytes_le(sstr); + if (mp_cmp_hs(s, ek->curve->e.G_order)) { + ecc_edwards_point_free(r); + mp_free(s); + return false; + } mp_int *H = eddsa_signing_exponent_from_data(ek, extra, rstr, data); diff --git a/test/cryptsuite.py b/test/cryptsuite.py index 1ee283c2..30c4ebeb 100755 --- a/test/cryptsuite.py +++ b/test/cryptsuite.py @@ -93,6 +93,9 @@ def le_integer(x, nbits): def be_integer(x, nbits): return bytes(reversed(le_integer(x, nbits))) +def decode_le_integer(s): + return sum(byte << (8*i) for i,byte in enumerate(s)) + @contextlib.contextmanager def queued_random_data(nbytes, seed): hashsize = 512 // 8 @@ -3518,6 +3521,21 @@ def testMLKEMValidation(self): self.assertEqual( mlkem_decaps(params, bytes(dk_bytes), c), fail) + def testEd25519Overflow(self): + test_key = ssh_key_new_priv('ed25519', b64('AAAAC3NzaC1lZDI1NTE5AAAAIMt0/CMBL+64GQ/r/JyGxo6oHs86i9bOHhMJYbDbxEJf'), b64('AAAAIB38jy02ZWYb4EXrJG9RIljEhqidrG5DdhZvMvoeOTZs')) + test_string = b'hello, world' + good_sig = test_key.sign(test_string, 0) + self.assertTrue(test_key.verify(good_sig, test_string)) + prefixlen = 4 + len('ssh-ed25519') + 4 + self.assertEqual(len(good_sig), prefixlen + 64) + good_sstr = good_sig[prefixlen+32:] + good_s = decode_le_integer(good_sstr) + bad_s = good_s + ed25519.G_order + bad_sstr = le_integer(bad_s, 256) + bad_sig = good_sig[:prefixlen+32] + bad_sstr + self.assertEqual(len(bad_sig), len(good_sig)) + self.assertFalse(test_key.verify(bad_sig, test_string)) + class standard_test_vectors(MyTestBase): def testAES(self): def vector(cipher, key, plaintext, ciphertext): From ccd3d3715f3d6ec8eb89b9fbd20f743a00551269 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Mon, 13 Apr 2026 13:02:47 +0100 Subject: [PATCH 112/129] Centralise the call to execute_command_hook. Now there's a function new_main_connection() in proxy/newmain.c, which is called in place of new_connection() when the connection you're making is the primary one of the session (as opposed to some sub-thing like a port forwarding). So now running the pre-connect command is done inside there. This is more DRY in general, but more specifically, allows new_main_connection() to be implemented in a more sophisticated way. The new function differs in API from new_connection() in that it requires a LogContext as well as all the other parameters. --- CMakeLists.txt | 1 + network.h | 7 +++++++ otherbackends/raw.c | 10 +++------- otherbackends/rlogin.c | 11 +++-------- otherbackends/supdup.c | 11 +++-------- otherbackends/telnet.c | 11 +++-------- proxy/newmain.c | 15 +++++++++++++++ ssh/ssh.c | 11 +++-------- 8 files changed, 38 insertions(+), 39 deletions(-) create mode 100644 proxy/newmain.c diff --git a/CMakeLists.txt b/CMakeLists.txt index dad26e03..8c1945ae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,6 +43,7 @@ add_library(network STATIC proxy/socks4.c proxy/socks5.c proxy/telnet.c + proxy/newmain.c proxy/local.c proxy/interactor.c) diff --git a/network.h b/network.h index ae56ba4a..92d4eb6b 100644 --- a/network.h +++ b/network.h @@ -190,6 +190,13 @@ SockAddr *name_lookup(const char *host, int port, char **canonicalname, Conf *conf, int addressfamily, LogContext *logctx, const char *lookup_reason_for_logging); +/* A further indirection, which also takes care of running a + * pre-connection command. */ +Socket *new_main_connection( + SockAddr *addr, const char *hostname, int port, bool privport, + bool oobinline, bool nodelay, bool keepalive, Plug *plug, Conf *conf, + Interactor *itr, LogContext *logctx); + /* platform-dependent callback from new_connection() */ /* (same caveat about addr as new_connection()) */ Socket *platform_new_connection(SockAddr *addr, const char *hostname, diff --git a/otherbackends/raw.c b/otherbackends/raw.c index 6b4d9845..41dfb0eb 100644 --- a/otherbackends/raw.c +++ b/otherbackends/raw.c @@ -205,16 +205,12 @@ static char *raw_init(const BackendVtable *vt, Seat *seat, if (port < 0) port = 23; /* default telnet port */ - /* Execute pre-connection command hook */ - execute_command_hook(raw->logctx, - conf_get_str(raw->conf, CONF_pre_connect_command), - addr, port, raw->conf); - /* * Open socket. */ - raw->s = new_connection(addr, *realhost, port, false, true, nodelay, - keepalive, &raw->plug, conf, &raw->interactor); + raw->s = new_main_connection( + addr, *realhost, port, false, true, nodelay, keepalive, &raw->plug, + conf, &raw->interactor, raw->logctx); if ((err = sk_socket_error(raw->s)) != NULL) return dupstr(err); diff --git a/otherbackends/rlogin.c b/otherbackends/rlogin.c index 7f62b38b..153e2660 100644 --- a/otherbackends/rlogin.c +++ b/otherbackends/rlogin.c @@ -290,17 +290,12 @@ static char *rlogin_init(const BackendVtable *vt, Seat *seat, if (port < 0) port = 513; /* default rlogin port */ - /* Execute pre-connection command hook */ - execute_command_hook(rlogin->logctx, - conf_get_str(rlogin->conf, CONF_pre_connect_command), - addr, port, rlogin->conf); - /* * Open socket. */ - rlogin->s = new_connection(addr, *realhost, port, true, false, - nodelay, keepalive, &rlogin->plug, conf, - &rlogin->interactor); + rlogin->s = new_main_connection( + addr, *realhost, port, true, false, nodelay, keepalive, &rlogin->plug, + conf, &rlogin->interactor, rlogin->logctx); if ((err = sk_socket_error(rlogin->s)) != NULL) return dupstr(err); diff --git a/otherbackends/supdup.c b/otherbackends/supdup.c index 231a8df9..e2bcc43e 100644 --- a/otherbackends/supdup.c +++ b/otherbackends/supdup.c @@ -753,17 +753,12 @@ static char *supdup_init(const BackendVtable *x, Seat *seat, if (port < 0) port = 0137; /* default supdup port */ - /* Execute pre-connection command hook */ - execute_command_hook(supdup->logctx, - conf_get_str(supdup->conf, CONF_pre_connect_command), - addr, port, supdup->conf); - /* * Open socket. */ - supdup->s = new_connection(addr, *realhost, port, false, true, - nodelay, keepalive, &supdup->plug, supdup->conf, - &supdup->interactor); + supdup->s = new_main_connection( + addr, *realhost, port, false, true, nodelay, keepalive, &supdup->plug, + supdup->conf, &supdup->interactor, supdup->logctx); if ((err = sk_socket_error(supdup->s)) != NULL) return dupstr(err); diff --git a/otherbackends/telnet.c b/otherbackends/telnet.c index 86c58b5a..739660a7 100644 --- a/otherbackends/telnet.c +++ b/otherbackends/telnet.c @@ -759,17 +759,12 @@ static char *telnet_init(const BackendVtable *vt, Seat *seat, if (port < 0) port = 23; /* default telnet port */ - /* Execute pre-connection command hook */ - execute_command_hook(telnet->logctx, - conf_get_str(telnet->conf, CONF_pre_connect_command), - addr, port, telnet->conf); - /* * Open socket. */ - telnet->s = new_connection(addr, *realhost, port, false, true, nodelay, - keepalive, &telnet->plug, telnet->conf, - &telnet->interactor); + telnet->s = new_main_connection( + addr, *realhost, port, false, true, nodelay, keepalive, &telnet->plug, + telnet->conf, &telnet->interactor, telnet->logctx); if ((err = sk_socket_error(telnet->s)) != NULL) return dupstr(err); diff --git a/proxy/newmain.c b/proxy/newmain.c new file mode 100644 index 00000000..cb03359c --- /dev/null +++ b/proxy/newmain.c @@ -0,0 +1,15 @@ +#include "putty.h" + +Socket *new_main_connection( + SockAddr *addr, const char *hostname, int port, bool privport, + bool oobinline, bool nodelay, bool keepalive, Plug *plug, Conf *conf, + Interactor *itr, LogContext *logctx) +{ + /* Execute pre-connection command hook */ + execute_command_hook(logctx, conf_get_str(conf, CONF_pre_connect_command), + addr, port, conf); + + /* Now open the socket */ + return new_connection(addr, hostname, port, privport, oobinline, nodelay, + keepalive, plug, conf, itr); +} diff --git a/ssh/ssh.c b/ssh/ssh.c index b9e4e849..b2ab0d4a 100644 --- a/ssh/ssh.c +++ b/ssh/ssh.c @@ -836,14 +836,9 @@ static char *connect_to_host( } ssh->fullhostname = dupstr(*realhost); /* save in case of GSSAPI */ - /* Execute pre-connection command hook */ - execute_command_hook(ssh->logctx, - conf_get_str(ssh->conf, CONF_pre_connect_command), - addr, port, ssh->conf); - - ssh->s = new_connection(addr, *realhost, port, - false, true, nodelay, keepalive, - &ssh->plug, ssh->conf, &ssh->interactor); + ssh->s = new_main_connection( + addr, *realhost, port, false, true, nodelay, keepalive, + &ssh->plug, ssh->conf, &ssh->interactor, ssh->logctx); if ((err = sk_socket_error(ssh->s)) != NULL) { char *toret = dupstr(err); sk_close(ssh->s); From 1bf88ffbe8ddd85f60e601c59a77950e23ac7e74 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Tue, 14 Apr 2026 09:50:43 +0100 Subject: [PATCH 113/129] New centralised system for waiting for subprocesses. There's a new 'SubprocessWaiter' object, which you can optionally ask for as an extra result of platform_start_subprocess, and then tell it how to give you a callback when the subprocess terminates. Not yet used: the existing use of platform_start_subprocess only cared about the output pipe of the subprocess anyway, so it passes NULL as the extra output pointer, indicating that it doesn't need a waiter. --- defs.h | 2 + putty.h | 27 ++++- ssh/userauth2-client.c | 2 +- stubs/no-network.c | 10 +- unix/CMakeLists.txt | 1 + unix/local-proxy.c | 20 +++- unix/platform.h | 3 + unix/utils/subprocess_waiter.c | 162 ++++++++++++++++++++++++++++++ windows/CMakeLists.txt | 1 + windows/local-proxy.c | 23 +++-- windows/platform.h | 3 + windows/utils/subprocess_waiter.c | 73 ++++++++++++++ 12 files changed, 308 insertions(+), 19 deletions(-) create mode 100644 unix/utils/subprocess_waiter.c create mode 100644 windows/utils/subprocess_waiter.c diff --git a/defs.h b/defs.h index 0ac23ee2..6ef0bc86 100644 --- a/defs.h +++ b/defs.h @@ -211,6 +211,8 @@ typedef struct StripCtrlChars StripCtrlChars; typedef struct BidiContext BidiContext; +typedef struct SubprocessWaiter SubprocessWaiter; + /* * A small structure wrapping up a (pointer, length) pair so that it * can be conveniently passed to or from a function. diff --git a/putty.h b/putty.h index 7f000fdb..6268edb9 100644 --- a/putty.h +++ b/putty.h @@ -2732,11 +2732,28 @@ void request_callback_notifications(toplevel_callback_notify_fn_t notify, * Facility provided by the platform to spawn a parallel subprocess * and present its stdio via a Socket. * - * 'prefix' indicates the prefix that should appear on messages passed - * to plug_log to provide stderr output from the process. - */ -Socket *platform_start_subprocess(const char *cmd, Plug *plug, - const char *prefix); + * 'pfx' indicates the prefix that should appear on messages passed to + * plug_log to provide stderr output from the process. + * + * SubprocessWaiter is an opaque type that can be made to notify you + * with the exit status of the subprocess, once it has one. If you set + * 'waiter' to be non-NULL, one for this subprocess will be returned + * to you. + */ +Socket *platform_start_subprocess( + const char *cmd, Plug *plug, const char *pfx, SubprocessWaiter **waiter); + +/* API for SubprocessWaiter. On Windows, everything is + * EXITTYPE_NORMAL, because exits and signal terminations aren't + * distinguished in the API. So don't depend on this enumeration for + * anything semantic: only use it to write sensible (ish) user-facing + * messages. */ +enum { EXITTYPE_NORMAL, EXITTYPE_SIGNAL }; +typedef void (*SubprocessWaiterCallback)( + void *ctx, int exittype, uint32_t exitdata); +void subproc_waiter_set_callback( + SubprocessWaiter *waiter, SubprocessWaiterCallback cb, void *cbctx); +void subproc_waiter_free(SubprocessWaiter *waiter); /* * Define no-op macros for the jump list functions, on platforms that diff --git a/ssh/userauth2-client.c b/ssh/userauth2-client.c index 17317a44..2d7b2746 100644 --- a/ssh/userauth2-client.c +++ b/ssh/userauth2-client.c @@ -665,7 +665,7 @@ static void ssh2_userauth_process_queue(PacketProtocolLayer *ppl) if (*s->authplugin_cmd) { s->authplugin_plug.vt = &authplugin_plugvt; s->authplugin = platform_start_subprocess( - s->authplugin_cmd, &s->authplugin_plug, "plugin"); + s->authplugin_cmd, &s->authplugin_plug, "plugin", NULL); ppl_logevent("Started authentication plugin: %s", s->authplugin_cmd); } diff --git a/stubs/no-network.c b/stubs/no-network.c index df97438a..10130f70 100644 --- a/stubs/no-network.c +++ b/stubs/no-network.c @@ -131,9 +131,15 @@ Socket *new_unix_listener(SockAddr *listenaddr, Plug *plug) plug, "no actual networking in this application"); } -Socket *platform_start_subprocess(const char *cmd, Plug *plug, - const char *prefix) +void subproc_waiter_set_callback( + SubprocessWaiter *waiter, SubprocessWaiterCallback cb, void *cbctx) {} +void subproc_waiter_free(SubprocessWaiter *waiter) {} + +Socket *platform_start_subprocess( + const char *cmd, Plug *plug, const char *pfx, SubprocessWaiter **waiter) { + if (waiter) + *waiter = NULL; return new_error_socket_fmt( plug, "no actual networking in this application"); } diff --git a/unix/CMakeLists.txt b/unix/CMakeLists.txt index b76628ba..e2b5b8ea 100644 --- a/unix/CMakeLists.txt +++ b/unix/CMakeLists.txt @@ -20,6 +20,7 @@ add_sources_from_current_dir(utils utils/pgp_fingerprints.c utils/pollwrap.c utils/signal.c + utils/subprocess_waiter.c utils/x11_ignore_error.c # We want the ISO C implementation of ltime(), because we don't have # a local better alternative diff --git a/unix/local-proxy.c b/unix/local-proxy.c index 157f9207..8833f288 100644 --- a/unix/local-proxy.c +++ b/unix/local-proxy.c @@ -14,7 +14,8 @@ #include "network.h" #include "proxy/proxy.h" -char *platform_setup_local_proxy(Socket *socket, const char *cmd) +static char *start_subprocess_fd_socket( + Socket *socket, const char *cmd, SubprocessWaiter **waiter) { /* * Create the pipes to the proxy command, and spawn the proxy @@ -49,6 +50,9 @@ char *platform_setup_local_proxy(Socket *socket, const char *cmd) return dupprintf("fork: %s", strerror(errno)); } + if (waiter) + *waiter = subproc_waiter_from_pid(pid); + close(to_cmd_pipe[0]); close(from_cmd_pipe[1]); close(cmd_err_pipe[1]); @@ -58,6 +62,12 @@ char *platform_setup_local_proxy(Socket *socket, const char *cmd) return NULL; } +char *platform_setup_local_proxy(Socket *socket, const char *cmd) +{ + /* In this context, no SubprocessWaiter is needed */ + return start_subprocess_fd_socket(socket, cmd, NULL); +} + Socket *platform_new_connection(SockAddr *addr, const char *hostname, int port, bool privport, bool oobinline, bool nodelay, bool keepalive, @@ -97,14 +107,14 @@ Socket *platform_new_connection(SockAddr *addr, const char *hostname, } } -Socket *platform_start_subprocess(const char *cmd, Plug *plug, - const char *prefix) +Socket *platform_start_subprocess( + const char *cmd, Plug *plug, const char *pfx, SubprocessWaiter **waiter) { Socket *socket = make_deferred_fd_socket( null_deferred_socket_opener(), sk_nonamelookup(""), 0, plug); - char *err = platform_setup_local_proxy(socket, cmd); - fd_socket_set_psb_prefix(socket, prefix); + char *err = start_subprocess_fd_socket(socket, cmd, waiter); + fd_socket_set_psb_prefix(socket, pfx); if (err) { sk_close(socket); diff --git a/unix/platform.h b/unix/platform.h index fb3629ee..08f8cbba 100644 --- a/unix/platform.h +++ b/unix/platform.h @@ -470,6 +470,9 @@ typedef void (*cliloop_pw_check_t)(void *ctx, pollwrapper *pw); typedef bool (*cliloop_continue_t)(void *ctx, bool found_any_fd, bool ran_any_callback); +/* Unix-specific API for making a SubprocessWaiter */ +SubprocessWaiter *subproc_waiter_from_pid(pid_t pid); + void cli_main_loop(cliloop_pw_setup_t pw_setup, cliloop_pw_check_t pw_check, cliloop_continue_t cont, void *ctx); diff --git a/unix/utils/subprocess_waiter.c b/unix/utils/subprocess_waiter.c new file mode 100644 index 00000000..f6d7f1dd --- /dev/null +++ b/unix/utils/subprocess_waiter.c @@ -0,0 +1,162 @@ +/* + * Unix implementation of SubprocessWaiter. This module catches + * SIGCHLD and uses a self-pipe to do the main handling of it in the + * primary event loop thread. It expects the uxsel mechanism to exist, + * and also expects nobody else to be messing with SIGCHLD. + */ + +#include "putty.h" +#include "tree234.h" + +#include +#include + +struct SubprocessWaiter { + pid_t pid; + SubprocessWaiterCallback callback; + void *cbctx; +}; + +tree234 *waiters_by_pid; + +static int subproc_waiter_compare_by_pid(void *av, void *bv) +{ + SubprocessWaiter *a = (SubprocessWaiter *)av; + SubprocessWaiter *b = (SubprocessWaiter *)bv; + + if (a->pid < b->pid) + return -1; + else if (a->pid > b->pid) + return +1; + return 0; +} + +static int subproc_waiter_find_by_pid(void *av, void *bv) +{ + pid_t a = *(pid_t *)av; + SubprocessWaiter *b = (SubprocessWaiter *)bv; + + if (a < b->pid) + return -1; + else if (a > b->pid) + return +1; + return 0; +} + + +static int sigchld_pipe[2] = { -1, -1 }; /* obviously bogus initial val */ + +static void sigchld_handler(int signum) +{ + if (write(sigchld_pipe[1], "x", 1) <= 0) { + /* + * We check the return value of write() to inhibit a gcc + * warning, but we expect that the only plausible error is + * EAGAIN/EWOULDBLOCK if the pipe has already filled up. Even + * that isn't _very_ likely, unless >8000 subprocesses + * terminate between passes of the event loop. But if it does + * happen, there's no problem, because we respond to data in + * this pipe by waiting for all available processes, so after + * this handler is called, all we need to ensure is that _at + * least one_ notification reaches the main event loop - and + * if the pipe buffer is already full, then _a fortiori_ it's + * non-empty, so that's enough to guarantee what we want + * anyway. + * + * This is a long-winded way of explaining why we do nothing + * in this error-handling block. + */ + } +} + +static void subproc_waiter_wait(void) +{ + while (1) { + int status; + pid_t pid = waitpid(-1, &status, WNOHANG); + + if (pid <= 0) + break; /* nothing more to wait for */ + + int exittype; + uint32_t exitdata; + if (WIFEXITED(status)) { + exittype = EXITTYPE_NORMAL; + exitdata = WEXITSTATUS(status); + } else if (WIFSIGNALED(status)) { + exittype = EXITTYPE_SIGNAL; + exitdata = WTERMSIG(status); + } else { + /* We only notify for _terminations_ */ + continue; + } + + SubprocessWaiter *waiter = find234( + waiters_by_pid, &pid, subproc_waiter_find_by_pid); + if (waiter && waiter->callback) + waiter->callback(waiter->cbctx, exittype, exitdata); + } +} + +static void sigchld_select_result(int fd, int event) +{ + if (fd == sigchld_pipe[0]) { + char c[PIPE_BUF]; + + /* Empty the pipe buffer. */ + while (read(sigchld_pipe[0], c, sizeof(c)) > 0) + /* do nothing */; + + /* Now wait for all available subprocesses. */ + subproc_waiter_wait(); + } +} + +static void subproc_waiter_setup(void) +{ + static bool setup = false; + if (!setup) { + if (pipe(sigchld_pipe) < 0) { + perror("pipe"); + exit(1); + } + cloexec(sigchld_pipe[0]); + cloexec(sigchld_pipe[1]); + nonblock(sigchld_pipe[0]); + nonblock(sigchld_pipe[1]); + + putty_signal(SIGCHLD, sigchld_handler); + + waiters_by_pid = newtree234(subproc_waiter_compare_by_pid); + + uxsel_set(sigchld_pipe[0], SELECT_R, sigchld_select_result); + + setup = true; + } +} + +SubprocessWaiter *subproc_waiter_from_pid(pid_t pid) +{ + subproc_waiter_setup(); + + SubprocessWaiter *waiter = snew(SubprocessWaiter); + waiter->pid = pid; + waiter->callback = NULL; + waiter->cbctx = NULL; + SubprocessWaiter *added = add234(waiters_by_pid, waiter); + assert(added == waiter); + return waiter; +} + +void subproc_waiter_set_callback( + SubprocessWaiter *waiter, SubprocessWaiterCallback cb, void *cbctx) +{ + waiter->callback = cb; + waiter->cbctx = cbctx; +} + +void subproc_waiter_free(SubprocessWaiter *waiter) +{ + del234(waiters_by_pid, waiter); + sfree(waiter); +} diff --git a/windows/CMakeLists.txt b/windows/CMakeLists.txt index 83db781b..422f896a 100644 --- a/windows/CMakeLists.txt +++ b/windows/CMakeLists.txt @@ -38,6 +38,7 @@ add_sources_from_current_dir(utils utils/shinydialogbox.c utils/split_into_argv.c utils/split_into_argv_w.c + utils/subprocess_waiter.c utils/version.c utils/win_strerror.c unicode.c) diff --git a/windows/local-proxy.c b/windows/local-proxy.c index 55e9cbf3..7d552136 100644 --- a/windows/local-proxy.c +++ b/windows/local-proxy.c @@ -12,7 +12,8 @@ #include "network.h" #include "proxy/proxy.h" -char *platform_setup_local_proxy(Socket *socket, const char *cmd) +static char *start_subprocess_handle_socket( + Socket *socket, const char *cmd, SubprocessWaiter **waiter) { HANDLE us_to_cmd, cmd_from_us; HANDLE us_from_cmd, cmd_to_us; @@ -69,9 +70,13 @@ char *platform_setup_local_proxy(Socket *socket, const char *cmd) CREATE_NO_WINDOW | NORMAL_PRIORITY_CLASS, NULL, NULL, &si, &pi); sfree(cmd_mutable); - CloseHandle(pi.hProcess); CloseHandle(pi.hThread); + if (waiter) + *waiter = subproc_waiter_from_hprocess(pi.hProcess); + else + CloseHandle(pi.hProcess); + CloseHandle(cmd_from_us); CloseHandle(cmd_to_us); @@ -84,6 +89,12 @@ char *platform_setup_local_proxy(Socket *socket, const char *cmd) return NULL; } +char *platform_setup_local_proxy(Socket *socket, const char *cmd) +{ + /* In this context, no SubprocessWaiter is needed */ + return start_subprocess_handle_socket(socket, cmd, NULL); +} + Socket *platform_new_connection(SockAddr *addr, const char *hostname, int port, bool privport, bool oobinline, bool nodelay, bool keepalive, @@ -99,14 +110,14 @@ Socket *platform_new_connection(SockAddr *addr, const char *hostname, return socket; } -Socket *platform_start_subprocess(const char *cmd, Plug *plug, - const char *prefix) +Socket *platform_start_subprocess( + const char *cmd, Plug *plug, const char *pfx, SubprocessWaiter **waiter) { Socket *socket = make_deferred_handle_socket( null_deferred_socket_opener(), sk_nonamelookup(""), 0, plug); - char *err = platform_setup_local_proxy(socket, cmd); - handle_socket_set_psb_prefix(socket, prefix); + char *err = start_subprocess_handle_socket(socket, cmd, waiter); + handle_socket_set_psb_prefix(socket, pfx); if (err) { sk_close(socket); diff --git a/windows/platform.h b/windows/platform.h index dcbdc739..08264c3f 100644 --- a/windows/platform.h +++ b/windows/platform.h @@ -864,4 +864,7 @@ char *cmdline_arg_remainder_acp(CmdlineArg *); char *cmdline_arg_remainder_utf8(CmdlineArg *); CmdlineArg *cmdline_arg_from_utf8(CmdlineArgList *list, const char *string); +/* Windows-specific API for making a SubprocessWaiter */ +SubprocessWaiter *subproc_waiter_from_hprocess(HANDLE hprocess); + #endif /* PUTTY_WINDOWS_PLATFORM_H */ diff --git a/windows/utils/subprocess_waiter.c b/windows/utils/subprocess_waiter.c new file mode 100644 index 00000000..826f3a45 --- /dev/null +++ b/windows/utils/subprocess_waiter.c @@ -0,0 +1,73 @@ +/* + * Windows implementation of SubprocessWaiter, delegating to + * add_handle_wait to wait for the process handle. + */ + +#include "putty.h" + +struct SubprocessWaiter { + HANDLE hprocess; + HandleWait *hw; + + SubprocessWaiterCallback callback; + void *cbctx; +}; + +static void subproc_waiter_callback(void *vctx) +{ + SubprocessWaiter *waiter = (SubprocessWaiter *)vctx; + + DWORD exitstatus; + if (!GetExitCodeProcess(waiter->hprocess, &exitstatus)) + return; /* process hasn't exited yet */ + + /* Stop waiting for this handle, and close it. */ + if (waiter->hw) { + delete_handle_wait(waiter->hw); + waiter->hw = NULL; + } + + if (waiter->hprocess != INVALID_HANDLE_VALUE) { + CloseHandle(waiter->hprocess); + waiter->hprocess = INVALID_HANDLE_VALUE; + } + + /* + * As mentioned in putty.h, for Windows we count everything as + * EXITTYPE_NORMAL. + * + * If we wanted nicer error messages, we could identify a list of + * interesting exit statuses like STATUS_CONTROL_C_EXIT and + * STATUS_ACCESS_VIOLATION and give those dedicated text + * translations, but that would involve some more complicated API + * for making the text translations and at the moment I don't + * think it's especially important. + */ + waiter->callback(waiter->cbctx, EXITTYPE_NORMAL, exitstatus); +} + +SubprocessWaiter *subproc_waiter_from_hprocess(HANDLE hprocess) +{ + SubprocessWaiter *waiter = snew(SubprocessWaiter); + waiter->callback = NULL; + waiter->cbctx = NULL; + waiter->hprocess = hprocess; + waiter->hw = add_handle_wait(hprocess, subproc_waiter_callback, waiter); + return waiter; +} + +void subproc_waiter_set_callback( + SubprocessWaiter *waiter, SubprocessWaiterCallback cb, void *cbctx) +{ + waiter->callback = cb; + waiter->cbctx = cbctx; +} + +void subproc_waiter_free(SubprocessWaiter *waiter) +{ + if (waiter->hw) + delete_handle_wait(waiter->hw); + if (waiter->hprocess != INVALID_HANDLE_VALUE) + CloseHandle(waiter->hprocess); + sfree(waiter); +} From 6aab75a4ec760b3d8a2fa94260a4ebb6ca815b74 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Tue, 14 Apr 2026 16:19:41 +0100 Subject: [PATCH 114/129] HandleSocket: stop tying input and output EOF together. If a HandleSocket is used with a pair of pipes, we can send outgoing EOF by closing the output pipe, without necessarily closing the input pipe. But we were unconditionally closing both anyway. This makes no difference to usages involving named pipes; it only makes a difference with local proxy subprocesses. --- windows/handle-socket.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/windows/handle-socket.c b/windows/handle-socket.c index 47fa4e29..294e157f 100644 --- a/windows/handle-socket.c +++ b/windows/handle-socket.c @@ -118,11 +118,17 @@ static void handle_sentdata(struct handle *h, size_t new_backlog, int err, HandleSocket *hs = (HandleSocket *)handle_get_privdata(h); if (close) { - if (hs->send_H != INVALID_HANDLE_VALUE) + /* This is acknowledging, after we did handle_write_eof, that + * all the data pending on the outgoing handle send_H is done. + * So we can close it. We don't necessarily want to close + * recv_H yet, but if they're the same bidirectional handle + * like a named pipe, we have no choice. */ + if (hs->send_H != INVALID_HANDLE_VALUE) { CloseHandle(hs->send_H); - if (hs->recv_H != INVALID_HANDLE_VALUE && hs->recv_H != hs->send_H) - CloseHandle(hs->recv_H); - hs->send_H = hs->recv_H = INVALID_HANDLE_VALUE; + if (hs->recv_H == hs->send_H) + hs->recv_H = INVALID_HANDLE_VALUE; + hs->send_H = INVALID_HANDLE_VALUE; + } } if (err) { From a0659c2a614b64a05952701fdd96a7bf992efe4d Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Mon, 13 Apr 2026 14:02:44 +0100 Subject: [PATCH 115/129] Run pre-connect commands via platform_start_subprocess. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes the limitation of the previous execute_command_hook() that it blocked the whole PuTTY process while waiting for the pre-connect command to terminate. Now, if the subcommand unexpectedly takes a long time, PuTTY itself will still be responsive – you can check its Event Log to see what's going on, or close it if you realise the command is never going to succeed, or simply copy-paste stuff from the terminal window while you wait. platform_start_subprocess opens three pipes to run the command in (on both Unix and Windows), for stdin, stdout and stderr. Here, stdin is a liability: we don't have any input to give the command, so if it were to stop to try to read from stdin, it would blockk. Therefore we send an outgoing EOF immediately by closoing the pipe to the command's stdin, so that instead of blocking, it will immediately find out there's no input for it. --- doc/config.but | 6 - proxy/newmain.c | 365 ++++++++++++++++++++++++++++++++++- unix/CMakeLists.txt | 1 - unix/utils/command_hook.c | 130 ------------- windows/CMakeLists.txt | 1 - windows/utils/command_hook.c | 140 -------------- 6 files changed, 359 insertions(+), 284 deletions(-) delete mode 100644 unix/utils/command_hook.c delete mode 100644 windows/utils/command_hook.c diff --git a/doc/config.but b/doc/config.but index 3461bfaf..448ca6a8 100644 --- a/doc/config.but +++ b/doc/config.but @@ -1880,12 +1880,6 @@ The results of running the program will be logged in PuTTY's Event Log. So if it terminates with an error message, the Event Log will show the message. -\s{NOTE} that when PuTTY runs this command as a subprocess, it will -stop responding completely while it waits for the subprocess to finish -\dash it will not even respond to the GUI. So you should make sure the -knock command completes quickly, whether it succeeds or fails, or -PuTTY will become unresponsive. - \H{config-data} The Data panel The Data panel allows you to configure various pieces of data which diff --git a/proxy/newmain.c b/proxy/newmain.c index cb03359c..8289a84f 100644 --- a/proxy/newmain.c +++ b/proxy/newmain.c @@ -1,15 +1,368 @@ #include "putty.h" +typedef struct PreConnWrapper PreConnWrapper; +struct PreConnWrapper { + /* The Plug from the client who instantiated us */ + Plug *plug; + + /* Initially non-NULL, until the pre-connect command finishes */ + Socket *preconn; + SubprocessWaiter *waiter; + + /* Initially NULL, until we've run the pre-connect command */ + Socket *mainsocket; + + /* Used to collect stdout from the subprocess. (fd-socket collects + * stderr) */ + ProxyStderrBuf psb; + + /* Pending stuff to pass on to the main socket once we open it */ + bufchain writebuf, oobbuf; + bool frozen; + bool pending_eof; + + /* Parameters for calling new_connection */ + SockAddr *addr; + char *hostname; + int port; + bool privport, oobinline, nodelay, keepalive; + Conf *conf; + Interactor *itr; + + /* For logging the pre-connection command progress */ + LogContext *logctx; + + /* Our implementations of Plug and Socket */ + Socket sockimpl; + Plug cmdplugimpl, mainplugimpl; +}; + +static void preconn_open_mainsocket(void *vctx) +{ + PreConnWrapper *wr = (PreConnWrapper *)vctx; + assert(!wr->mainsocket); + + wr->mainsocket = new_connection( + wr->addr, wr->hostname, wr->port, wr->privport, wr->oobinline, + wr->nodelay, wr->keepalive, &wr->mainplugimpl, wr->conf, wr->itr); + wr->addr = NULL; /* we've transferred ownership */ + + sk_set_frozen(wr->mainsocket, wr->frozen); + + while (bufchain_size(&wr->oobbuf) > 0) { + ptrlen data = bufchain_prefix(&wr->oobbuf); + sk_write_oob(wr->mainsocket, data.ptr, data.len); + bufchain_consume(&wr->oobbuf, data.len); + } + + while (bufchain_size(&wr->writebuf) > 0) { + ptrlen data = bufchain_prefix(&wr->writebuf); + sk_write(wr->mainsocket, data.ptr, data.len); + bufchain_consume(&wr->writebuf, data.len); + } + + if (wr->pending_eof) + sk_write_eof(wr->mainsocket); + + sfree(wr->hostname); + wr->hostname = NULL; + conf_free(wr->conf); + wr->conf = NULL; +} + +static void preconn_cmdplug_log( + Plug *p, Socket *s, PlugLogType type, SockAddr *addr, + int port, const char *error_msg, int error_code) +{ + PreConnWrapper *wr = container_of(p, PreConnWrapper, cmdplugimpl); + + switch (type) { + case PLUGLOG_CONNECT_TRYING: + case PLUGLOG_CONNECT_FAILED: + case PLUGLOG_CONNECT_SUCCESS: + /* Ignore these messages from the subcommand. We don't expect + * to receive them anyway, and if we did, they'd be boring. */ + break; + case PLUGLOG_PROXY_MSG: + /* But this contains the stderr from the subcommand, so pass + * it on. */ + plug_log(wr->plug, &wr->sockimpl, type, addr, port, + error_msg, error_code); + break; + + } +} + +static void preconn_cmdplug_closing( + Plug *p, PlugCloseType type, const char *error_msg) +{ + PreConnWrapper *wr = container_of(p, PreConnWrapper, cmdplugimpl); + + switch (type) { + case PLUGCLOSE_NORMAL: + /* We don't really care when stdout from the subprocess + * closes. Our trigger for moving on to the main connection is + * the subprocess itself exiting. */ + break; + + case PLUGCLOSE_ERROR: + case PLUGCLOSE_BROKEN_PIPE: + /* But if it terminates _confusedly_, at least log that. */ + logeventf(wr->logctx, "Error reading output from " + "pre-connect command: %s", error_msg); + break; + + case PLUGCLOSE_USER_ABORT: + /* Hard to imagine how a subprocess socket might produce this, + * but if it ever does grow a means of doing so, we should + * interpret it as a request to abort the whole connection. */ + plug_closing(wr->plug, type, error_msg); + break; + } +} + +static void preconn_subproc_terminated( + void *vctx, int exittype, uint32_t exitdata) +{ + PreConnWrapper *wr = (PreConnWrapper *)vctx; + switch (exittype) { + case EXITTYPE_NORMAL: + logeventf(wr->logctx, "Pre-connect command exited with status %"PRIu32, + exitdata); + break; + case EXITTYPE_SIGNAL: + logeventf(wr->logctx, "Pre-connect command killed by signal %"PRIu32, + exitdata); + break; + } + + queue_toplevel_callback(preconn_open_mainsocket, wr); +} + +static void preconn_cmdplug_receive( + Plug *p, int urgent, const char *data, size_t len) +{ + PreConnWrapper *wr = container_of(p, PreConnWrapper, cmdplugimpl); + log_proxy_stderr(wr->plug, &wr->sockimpl, &wr->psb, data, len); +} + +static void preconn_cmdplug_sent(Plug *p, size_t bufsize) +{ +} + +static void preconn_mainplug_log( + Plug *p, Socket *s, PlugLogType type, SockAddr *addr, int port, + const char *error_msg, int error_code) +{ + PreConnWrapper *wr = container_of(p, PreConnWrapper, mainplugimpl); + plug_log(wr->plug, &wr->sockimpl, type, addr, port, + error_msg, error_code); +} + +static void preconn_mainplug_closing( + Plug *p, PlugCloseType type, const char *error_msg) +{ + PreConnWrapper *wr = container_of(p, PreConnWrapper, mainplugimpl); + plug_closing(wr->plug, type, error_msg); +} + +static void preconn_mainplug_receive( + Plug *p, int urgent, const char *data, size_t len) +{ + PreConnWrapper *wr = container_of(p, PreConnWrapper, mainplugimpl); + plug_receive(wr->plug, urgent, data, len); +} + +static void preconn_mainplug_sent(Plug *p, size_t bufsize) +{ + PreConnWrapper *wr = container_of(p, PreConnWrapper, mainplugimpl); + plug_sent(wr->plug, bufsize); +} + +static int preconn_never_accepting(Plug *p, accept_fn_t constructor, + accept_ctx_t ctx) +{ + unreachable("new_main_connection never creates a listening Socket"); +} + +static const PlugVtable preconn_cmd_plugvt = { + .log = preconn_cmdplug_log, + .closing = preconn_cmdplug_closing, + .receive = preconn_cmdplug_receive, + .sent = preconn_cmdplug_sent, + .accepting = preconn_never_accepting, +}; + +static const PlugVtable preconn_main_plugvt = { + .log = preconn_mainplug_log, + .closing = preconn_mainplug_closing, + .receive = preconn_mainplug_receive, + .sent = preconn_mainplug_sent, + .accepting = preconn_never_accepting, +}; + +static Plug *preconn_plug(Socket *s, Plug *p) +{ + PreConnWrapper *wr = container_of(s, PreConnWrapper, sockimpl); + Plug *prev = wr->plug; + if (p) + wr->plug = p; + return prev; +} + +static void preconn_close(Socket *s) +{ + PreConnWrapper *wr = container_of(s, PreConnWrapper, sockimpl); + if (wr->preconn) + sk_close(wr->preconn); + if (wr->waiter) + subproc_waiter_free(wr->waiter); + if (wr->mainsocket) + sk_close(wr->mainsocket); + if (wr->addr) + sk_addr_free(wr->addr); + if (wr->hostname) + sfree(wr->hostname); + if (wr->conf) + conf_free(wr->conf); + bufchain_clear(&wr->writebuf); + bufchain_clear(&wr->oobbuf); + delete_callbacks_for_context(wr); + sfree(wr); +} + +static size_t preconn_write(Socket *s, const void *data, size_t len) +{ + PreConnWrapper *wr = container_of(s, PreConnWrapper, sockimpl); + if (wr->mainsocket) + return sk_write(wr->mainsocket, data, len); + + bufchain_add(&wr->writebuf, data, len); + return bufchain_size(&wr->writebuf); +} + +static size_t preconn_write_oob(Socket *s, const void *data, size_t len) +{ + PreConnWrapper *wr = container_of(s, PreConnWrapper, sockimpl); + if (wr->mainsocket) + return sk_write_oob(wr->mainsocket, data, len); + + bufchain_clear(&wr->writebuf); + bufchain_clear(&wr->oobbuf); + bufchain_add(&wr->oobbuf, data, len); + return bufchain_size(&wr->oobbuf); +} + +static void preconn_write_eof(Socket *s) +{ + PreConnWrapper *wr = container_of(s, PreConnWrapper, sockimpl); + if (wr->mainsocket) { + sk_write_eof(wr->mainsocket); + } else { + wr->pending_eof = true; + } +} + +static void preconn_set_frozen(Socket *s, bool is_frozen) +{ + PreConnWrapper *wr = container_of(s, PreConnWrapper, sockimpl); + if (wr->mainsocket) { + sk_set_frozen(wr->mainsocket, is_frozen); + } else { + wr->frozen = is_frozen; + } +} + +static const char *preconn_socket_error(Socket *s) +{ + PreConnWrapper *wr = container_of(s, PreConnWrapper, sockimpl); + if (wr->mainsocket) + return sk_socket_error(wr->mainsocket); + + return NULL; +} + +static SocketEndpointInfo *preconn_endpoint_info(Socket *s, bool peer) +{ + PreConnWrapper *wr = container_of(s, PreConnWrapper, sockimpl); + if (wr->mainsocket) + return sk_endpoint_info(wr->mainsocket, peer); + + return NULL; +} + +static const SocketVtable preconn_sockvt = { + .plug = preconn_plug, + .close = preconn_close, + .write = preconn_write, + .write_oob = preconn_write_oob, + .write_eof = preconn_write_eof, + .set_frozen = preconn_set_frozen, + .socket_error = preconn_socket_error, + .endpoint_info = preconn_endpoint_info, +}; + Socket *new_main_connection( SockAddr *addr, const char *hostname, int port, bool privport, bool oobinline, bool nodelay, bool keepalive, Plug *plug, Conf *conf, Interactor *itr, LogContext *logctx) { - /* Execute pre-connection command hook */ - execute_command_hook(logctx, conf_get_str(conf, CONF_pre_connect_command), - addr, port, conf); + char *command = NULL; + + const char *template = conf_get_str(conf, CONF_pre_connect_command); + assert(template); + if (*template) { + Conf *tmpconf = conf_copy(conf); + conf_set_str(conf, CONF_proxy_username, ""); + conf_set_str(conf, CONF_proxy_password, ""); + unsigned flags; + command = format_connection_setup_command( + template, addr, port, tmpconf, &flags); + if (flags & (TELNET_CMD_MISSING_USERNAME | + TELNET_CMD_MISSING_PASSWORD)) { + logeventf(logctx, "Pre-connect command: references to %%user or " + "%%pass not supported"); + sfree(command); + command = NULL; + } + conf_free(tmpconf); + } + + if (!command) { + /* No pre-connection command: just open the main socket immediately */ + return new_connection(addr, hostname, port, privport, oobinline, + nodelay, keepalive, plug, conf, itr); + } + + PreConnWrapper *wr = snew(PreConnWrapper); + memset(wr, 0, sizeof(PreConnWrapper)); + wr->plug = plug; + wr->addr = addr; /* we now own this */ + wr->hostname = dupstr(hostname); + wr->port = port; + wr->privport = privport; + wr->oobinline = oobinline; + wr->nodelay = nodelay; + wr->keepalive = keepalive; + wr->conf = conf_copy(conf); + wr->itr = itr; + wr->logctx = logctx; + psb_init(&wr->psb); + psb_set_prefix(&wr->psb, "pre-connect command stdout"); + bufchain_init(&wr->writebuf); + bufchain_init(&wr->oobbuf); + + wr->cmdplugimpl.vt = &preconn_cmd_plugvt; + wr->mainplugimpl.vt = &preconn_main_plugvt; + wr->sockimpl.vt = &preconn_sockvt; + + logeventf(logctx, "Running pre-connect command: %s", command); + wr->preconn = platform_start_subprocess( + command, &wr->cmdplugimpl, "pre-connect command stderr", &wr->waiter); + subproc_waiter_set_callback(wr->waiter, preconn_subproc_terminated, wr); + sk_write_eof(wr->preconn); + + sfree(command); - /* Now open the socket */ - return new_connection(addr, hostname, port, privport, oobinline, nodelay, - keepalive, plug, conf, itr); + return &wr->sockimpl; } diff --git a/unix/CMakeLists.txt b/unix/CMakeLists.txt index e2b5b8ea..332c636e 100644 --- a/unix/CMakeLists.txt +++ b/unix/CMakeLists.txt @@ -5,7 +5,6 @@ add_sources_from_current_dir(utils utils/block_signal.c utils/cloexec.c utils/cmdline_arg.c - utils/command_hook.c utils/dputs.c utils/filename.c utils/fontspec.c diff --git a/unix/utils/command_hook.c b/unix/utils/command_hook.c deleted file mode 100644 index dcb2cef8..00000000 --- a/unix/utils/command_hook.c +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Unix implementation of command hook execution (synchronous with logging) - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "putty.h" - -void execute_command_hook(LogContext *logctx, const char *command_pattern, - SockAddr *addr, int port, Conf *conf) -{ - pid_t pid; - int status; - int stdout_pipe[2] = {-1, -1}; - int stderr_pipe[2] = {-1, -1}; - - if (!command_pattern || !*command_pattern) - return; - - Conf *tmpconf = conf_copy(conf); - conf_set_str(conf, CONF_proxy_username, ""); - conf_set_str(conf, CONF_proxy_password, ""); - unsigned flags; - char *command = format_connection_setup_command( - command_pattern, addr, port, tmpconf, &flags); - if (flags & (TELNET_CMD_MISSING_USERNAME | - TELNET_CMD_MISSING_PASSWORD)) { - logeventf(logctx, "Pre-connect command: references to %%user or " - "%%pass not supported"); - sfree(command); - return; - } - conf_free(tmpconf); - - /* Create pipes for capturing stdout and stderr */ - if (pipe(stdout_pipe) < 0 || pipe(stderr_pipe) < 0) { - logeventf(logctx, "Pre-connect command: failed to create pipes: %s", - strerror(errno)); - if (stdout_pipe[0] >= 0) close(stdout_pipe[0]); - if (stdout_pipe[1] >= 0) close(stdout_pipe[1]); - if (stderr_pipe[0] >= 0) close(stderr_pipe[0]); - if (stderr_pipe[1] >= 0) close(stderr_pipe[1]); - return; - } - - /* Log the command being executed */ - logeventf(logctx, "Running pre-connect command: %s", command); - - /* Fork and execute */ - pid = fork(); - if (pid == 0) { - /* Child process */ - /* Close read ends of pipes */ - close(stdout_pipe[0]); - close(stderr_pipe[0]); - - /* Redirect stdout and stderr */ - dup2(stdout_pipe[1], STDOUT_FILENO); - dup2(stderr_pipe[1], STDERR_FILENO); - close(stdout_pipe[1]); - close(stderr_pipe[1]); - - /* Execute the command through shell */ - execl("/bin/sh", "sh", "-c", command, (char *)NULL); - - /* If execl fails, exit */ - _exit(127); - } else if (pid > 0) { - char buf[512]; - ssize_t n; - bool has_output = false; - - /* Parent process - close write ends of pipes */ - close(stdout_pipe[1]); - close(stderr_pipe[1]); - stdout_pipe[1] = -1; - stderr_pipe[1] = -1; - - /* Read and log stdout */ - while ((n = read(stdout_pipe[0], buf, sizeof(buf) - 1)) > 0) { - buf[n] = '\0'; - if (!has_output) { - logevent(logctx, "Pre-connect command:"); - has_output = true; - } - logevent(logctx, buf); - } - close(stdout_pipe[0]); - - /* Read and log stderr */ - has_output = false; - while ((n = read(stderr_pipe[0], buf, sizeof(buf) - 1)) > 0) { - buf[n] = '\0'; - if (!has_output) { - logevent(logctx, "Pre-connect command stderr:"); - has_output = true; - } - logevent(logctx, buf); - } - close(stderr_pipe[0]); - - /* Wait for command to complete and log exit status */ - waitpid(pid, &status, 0); - if (WIFEXITED(status)) { - logeventf(logctx, "Pre-connect command exited with status %d", - WEXITSTATUS(status)); - } else if (WIFSIGNALED(status)) { - logeventf(logctx, "Pre-connect command killed by signal %d", - WTERMSIG(status)); - } else { - logevent(logctx, "Pre-connect command terminated abnormally"); - } - } else { - /* Fork failed */ - close(stdout_pipe[0]); - close(stdout_pipe[1]); - close(stderr_pipe[0]); - close(stderr_pipe[1]); - logeventf(logctx, "Pre-connect command: fork failed: %s", - strerror(errno)); - } - - sfree(command); -} diff --git a/windows/CMakeLists.txt b/windows/CMakeLists.txt index 422f896a..1b98a6df 100644 --- a/windows/CMakeLists.txt +++ b/windows/CMakeLists.txt @@ -8,7 +8,6 @@ add_sources_from_current_dir(utils utils/blink_time.c utils/centre_window.c utils/cmdline_arg.c - utils/command_hook.c utils/cryptoapi.c utils/defaults.c utils/dll_hijacking_protection.c diff --git a/windows/utils/command_hook.c b/windows/utils/command_hook.c deleted file mode 100644 index bf6fb08f..00000000 --- a/windows/utils/command_hook.c +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Windows implementation of command hook execution (synchronous with logging) - */ - -#include - -#include "putty.h" - -static void read_and_log_pipe(HANDLE pipe, LogContext *logctx, const char *label) -{ - char buf[512]; - DWORD bytesRead; - bool has_output = false; - - while (ReadFile(pipe, buf, sizeof(buf) - 1, &bytesRead, NULL) && bytesRead > 0) { - buf[bytesRead] = '\0'; - if (!has_output) { - logeventf(logctx, "Pre-connect command %s:", label); - has_output = true; - } - logevent(logctx, buf); - } -} - -void execute_command_hook(LogContext *logctx, const char *command_pattern, - SockAddr *addr, int port, Conf *conf) -{ - STARTUPINFO si; - PROCESS_INFORMATION pi; - BOOL result; - HANDLE stdout_read = INVALID_HANDLE_VALUE; - HANDLE stdout_write = INVALID_HANDLE_VALUE; - HANDLE stderr_read = INVALID_HANDLE_VALUE; - HANDLE stderr_write = INVALID_HANDLE_VALUE; - SECURITY_ATTRIBUTES sa; - DWORD exit_code = 0; - - if (!command_pattern || !*command_pattern) - return; - - /* Format the hook command, but first, make sure %user and %pass - * aren't expanded. (Those will refer to the _proxy_ username and - * password.) */ - Conf *tmpconf = conf_copy(conf); - conf_set_str(conf, CONF_proxy_username, ""); - conf_set_str(conf, CONF_proxy_password, ""); - unsigned flags; - char *command = format_connection_setup_command( - command_pattern, addr, port, tmpconf, &flags); - if (flags & (TELNET_CMD_MISSING_USERNAME | - TELNET_CMD_MISSING_PASSWORD)) { - logeventf(logctx, "Pre-connect command: references to %%user or " - "%%pass not supported"); - sfree(command); - return; - } - conf_free(tmpconf); - - /* Set up security attributes for pipes */ - sa.nLength = sizeof(SECURITY_ATTRIBUTES); - sa.bInheritHandle = TRUE; - sa.lpSecurityDescriptor = NULL; - - /* Create pipes for capturing stdout and stderr */ - if (!CreatePipe(&stdout_read, &stdout_write, &sa, 0) || - !CreatePipe(&stderr_read, &stderr_write, &sa, 0)) { - DWORD error = GetLastError(); - if (stdout_read != INVALID_HANDLE_VALUE) CloseHandle(stdout_read); - if (stdout_write != INVALID_HANDLE_VALUE) CloseHandle(stdout_write); - if (stderr_read != INVALID_HANDLE_VALUE) CloseHandle(stderr_read); - if (stderr_write != INVALID_HANDLE_VALUE) CloseHandle(stderr_write); - logeventf(logctx, "Pre-connect command: failed to create pipes: %s", - win_strerror(error)); - return; - } - - /* Prepare startup info */ - ZeroMemory(&si, sizeof(si)); - si.cb = sizeof(si); - si.hStdOutput = stdout_write; - si.hStdError = stderr_write; - si.dwFlags |= STARTF_USESTDHANDLES; - ZeroMemory(&pi, sizeof(pi)); - - /* Log the command being executed */ - logeventf(logctx, "Running pre-connect command: %s", command); - - /* Execute the command through cmd.exe */ - result = CreateProcess( - NULL, /* No module name (use command line) */ - (char *)command,/* Command line (cast away const for Win32 API) */ - NULL, /* Process handle not inheritable */ - NULL, /* Thread handle not inheritable */ - TRUE, /* Set handle inheritance to TRUE */ - 0, /* No creation flags */ - NULL, /* Use parent's environment block */ - NULL, /* Use parent's starting directory */ - &si, /* Pointer to STARTUPINFO structure */ - &pi /* Pointer to PROCESS_INFORMATION structure */ - ); - - if (result) { - /* Close the write ends of pipes in parent */ - CloseHandle(stdout_write); - CloseHandle(stderr_write); - stdout_write = INVALID_HANDLE_VALUE; - stderr_write = INVALID_HANDLE_VALUE; - - /* Read and log stdout */ - read_and_log_pipe(stdout_read, logctx, "stdout"); - CloseHandle(stdout_read); - stdout_read = INVALID_HANDLE_VALUE; - - /* Read and log stderr */ - read_and_log_pipe(stderr_read, logctx, "stderr"); - CloseHandle(stderr_read); - stderr_read = INVALID_HANDLE_VALUE; - - /* Wait for command to complete */ - WaitForSingleObject(pi.hProcess, INFINITE); - - /* Get exit code */ - GetExitCodeProcess(pi.hProcess, &exit_code); - logeventf(logctx, "Pre-connect command exited with status %lu", - exit_code); - - /* Close process and thread handles */ - CloseHandle(pi.hProcess); - CloseHandle(pi.hThread); - } else { - /* CreateProcess failed */ - DWORD error = GetLastError(); - CloseHandle(stdout_read); - CloseHandle(stdout_write); - CloseHandle(stderr_read); - CloseHandle(stderr_write); - logeventf(logctx, "Pre-connect command: CreateProcess failed: %s", - win_strerror(error)); - } -} From ff89d584c55f281aca40609d65f18e25c9ef20fa Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Tue, 14 Apr 2026 10:29:53 +0100 Subject: [PATCH 116/129] Refactor pty_real_select_result. (NFC) pty_real_select_result was a monolithic function which included handling the result of waitpid() (indicated by passing magic -1 values as fd and event), or actually reading data from the pty (in the absence of those special values), and cleanup functionality if either of those things indicated that it was time to finish the session. Now the magic values are gone: waitpid() results are handled in their own function. Also the shared cleanup functionality lives in the new pty_finished() routine, called from both that and the remainder of pty_real_select_result(), which now just handles _actual_ results of select() reporting activity on the pty fd. This patch is completely boring: it just moves existing code around and reindents it. The interesting change will come in the next commit; this one just separates the boring parts of the work, to make the interesting patch easier to read. --- unix/pty.c | 255 +++++++++++++++++++++++++++-------------------------- 1 file changed, 130 insertions(+), 125 deletions(-) diff --git a/unix/pty.c b/unix/pty.c index 9270a539..118c4e25 100644 --- a/unix/pty.c +++ b/unix/pty.c @@ -596,150 +596,155 @@ void pty_pre_init(void) static void pty_try_wait(void); static void pty_uxsel_setup(Pty *pty); +static void pty_finished(Pty *pty) +{ + int close_on_exit; + int i; + + for (i = 0; i < 3; i++) + if (pty->fds[i].fd >= 0) + uxsel_del(pty->fds[i].fd); + + pty_close(pty); + + pty->finished = true; + + /* + * This is a slight layering-violation sort of hack: only + * if we're not closing on exit (COE is set to Never, or to + * Only On Clean and it wasn't a clean exit) do we output a + * `terminated' message. + */ + close_on_exit = conf_get_int(pty->conf, CONF_close_on_exit); + if (close_on_exit == FORCE_OFF || + (close_on_exit == AUTO && pty->exit_code != 0)) { + char *message; + if (WIFEXITED(pty->exit_code)) { + message = dupprintf( + "\r\n[pterm: process terminated with exit code %d]\r\n", + WEXITSTATUS(pty->exit_code)); + } else if (WIFSIGNALED(pty->exit_code)) { +#if !HAVE_STRSIGNAL + message = dupprintf( + "\r\n[pterm: process terminated on signal %d]\r\n", + WTERMSIG(pty->exit_code)); +#else + message = dupprintf( + "\r\n[pterm: process terminated on signal %d (%s)]\r\n", + WTERMSIG(pty->exit_code), + strsignal(WTERMSIG(pty->exit_code))); +#endif + } else { + /* _Shouldn't_ happen, but if it does, a vague message + * is better than no message at all */ + message = dupprintf("\r\n[pterm: process terminated]\r\n"); + } + seat_stdout_pl(pty->seat, ptrlen_from_asciz(message)); + sfree(message); + } + + seat_eof(pty->seat); + seat_notify_remote_exit(pty->seat); +} + static void pty_real_select_result(Pty *pty, int fd, int event, int status) { char buf[4096]; int ret; bool finished = false; - if (event < 0) { - /* - * We've been called because our child process did - * something. `status' tells us what. - */ - if ((WIFEXITED(status) || WIFSIGNALED(status))) { - /* - * The primary child process died. - */ - pty->child_dead = true; - del234(ptys_by_pid, pty); - pty->exit_code = status; + if (event == SELECT_R) { + bool is_stdout = (fd == pty->master_o); - /* - * If this is an ordinary pty session, this is also the - * moment to terminate the whole backend. - * - * We _could_ instead keep the terminal open for remaining - * subprocesses to output to, but conventional wisdom - * seems to feel that that's the Wrong Thing for an - * xterm-alike, so we bail out now (though we don't - * necessarily _close_ the window, depending on the state - * of Close On Exit). This would be easy enough to change - * or make configurable if necessary. - */ - if (pty->master_fd >= 0) - finished = true; - } - } else { - if (event == SELECT_R) { - bool is_stdout = (fd == pty->master_o); + ret = read(fd, buf, sizeof(buf)); - ret = read(fd, buf, sizeof(buf)); + /* + * Treat EIO on a pty master as equivalent to EOF (because + * that's how the kernel seems to report the event where + * the last process connected to the other end of the pty + * went away). + */ + if (fd == pty->master_fd && ret < 0 && errno == EIO) + ret = 0; + if (ret == 0) { /* - * Treat EIO on a pty master as equivalent to EOF (because - * that's how the kernel seems to report the event where - * the last process connected to the other end of the pty - * went away). + * EOF on this input fd, so to begin with, we may as + * well close it, and remove all references to it in + * the pty's fd fields. */ - if (fd == pty->master_fd && ret < 0 && errno == EIO) - ret = 0; - - if (ret == 0) { + uxsel_del(fd); + close(fd); + if (pty->master_fd == fd) + pty->master_fd = -1; + if (pty->master_o == fd) + pty->master_o = -1; + if (pty->master_e == fd) + pty->master_e = -1; + + if (is_stdout) { /* - * EOF on this input fd, so to begin with, we may as - * well close it, and remove all references to it in - * the pty's fd fields. + * We assume a clean exit if the pty (or stdout + * pipe) has closed, but the actual child process + * hasn't. The only way I can imagine this + * happening is if it detaches itself from the pty + * and goes daemonic - in which case the expected + * usage model would precisely _not_ be for the + * pterm window to hang around! */ - uxsel_del(fd); - close(fd); - if (pty->master_fd == fd) - pty->master_fd = -1; - if (pty->master_o == fd) - pty->master_o = -1; - if (pty->master_e == fd) - pty->master_e = -1; - - if (is_stdout) { - /* - * We assume a clean exit if the pty (or stdout - * pipe) has closed, but the actual child process - * hasn't. The only way I can imagine this - * happening is if it detaches itself from the pty - * and goes daemonic - in which case the expected - * usage model would precisely _not_ be for the - * pterm window to hang around! - */ - finished = true; - pty_try_wait(); /* one last effort to collect exit code */ - if (!pty->child_dead) - pty->exit_code = 0; - } - } else if (ret < 0) { - perror("read pty master"); - exit(1); - } else if (ret > 0) { - pty->output_backlog = seat_output( - pty->seat, !is_stdout, buf, ret); - pty_uxsel_setup(pty); + finished = true; + pty_try_wait(); /* one last effort to collect exit code */ + if (!pty->child_dead) + pty->exit_code = 0; } - } else if (event == SELECT_W) { - /* - * Attempt to send data down the pty. - */ - pty_try_write(pty); + } else if (ret < 0) { + perror("read pty master"); + exit(1); + } else if (ret > 0) { + pty->output_backlog = seat_output( + pty->seat, !is_stdout, buf, ret); + pty_uxsel_setup(pty); } + } else if (event == SELECT_W) { + /* + * Attempt to send data down the pty. + */ + pty_try_write(pty); } - if (finished && !pty->finished) { - int close_on_exit; - int i; - - for (i = 0; i < 3; i++) - if (pty->fds[i].fd >= 0) - uxsel_del(pty->fds[i].fd); - - pty_close(pty); + if (finished && !pty->finished) + pty_finished(pty); +} - pty->finished = true; +static void pty_subprocess_status(Pty *pty, int status) +{ + /* + * We've been called because our child process did something. + * `status' tells us what. + */ + if (!(WIFEXITED(status) || WIFSIGNALED(status))) + return; - /* - * This is a slight layering-violation sort of hack: only - * if we're not closing on exit (COE is set to Never, or to - * Only On Clean and it wasn't a clean exit) do we output a - * `terminated' message. - */ - close_on_exit = conf_get_int(pty->conf, CONF_close_on_exit); - if (close_on_exit == FORCE_OFF || - (close_on_exit == AUTO && pty->exit_code != 0)) { - char *message; - if (WIFEXITED(pty->exit_code)) { - message = dupprintf( - "\r\n[pterm: process terminated with exit code %d]\r\n", - WEXITSTATUS(pty->exit_code)); - } else if (WIFSIGNALED(pty->exit_code)) { -#if !HAVE_STRSIGNAL - message = dupprintf( - "\r\n[pterm: process terminated on signal %d]\r\n", - WTERMSIG(pty->exit_code)); -#else - message = dupprintf( - "\r\n[pterm: process terminated on signal %d (%s)]\r\n", - WTERMSIG(pty->exit_code), - strsignal(WTERMSIG(pty->exit_code))); -#endif - } else { - /* _Shouldn't_ happen, but if it does, a vague message - * is better than no message at all */ - message = dupprintf("\r\n[pterm: process terminated]\r\n"); - } - seat_stdout_pl(pty->seat, ptrlen_from_asciz(message)); - sfree(message); - } + /* + * If we get here, the primary child process died. + */ + pty->child_dead = true; + del234(ptys_by_pid, pty); + pty->exit_code = status; - seat_eof(pty->seat); - seat_notify_remote_exit(pty->seat); - } + /* + * If this is an ordinary pty session, this is also the moment to + * terminate the whole backend. + * + * We _could_ instead keep the terminal open for remaining + * subprocesses to output to, but conventional wisdom seems to + * feel that that's the Wrong Thing for an xterm-alike, so we bail + * out now (though we don't necessarily _close_ the window, + * depending on the state of Close On Exit). This would be easy + * enough to change or make configurable if necessary. + */ + if (pty->master_fd >= 0 && !pty->finished) + pty_finished(pty); } static void pty_try_wait(void) @@ -754,7 +759,7 @@ static void pty_try_wait(void) pty = find234(ptys_by_pid, &pid, pty_find_by_pid); if (pty) - pty_real_select_result(pty, -1, -1, status); + pty_subprocess_status(pty, status); } while (pid > 0); } From 7a7da3365a6d7b74382f96fde42509d7ae81cf1d Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Tue, 14 Apr 2026 10:34:09 +0100 Subject: [PATCH 117/129] Switch unix/pty.c to use the new SubprocessWaiter. The mechanisms in there - SIGCHLD handler, self-pipe with uxsel, wait loop, tree of known subprocesses indexed by pid - are all replicated in the new centralised system, so there's no need to have two copies of them. This also extends the Unix-specific API of SubprocessWaiter to add a couple of extra 'forcibly do a thing you would have got round to later' functions. --- putty.h | 7 +- unix/platform.h | 5 + unix/pty.c | 185 ++++++++------------------------- unix/utils/subprocess_waiter.c | 13 ++- 4 files changed, 61 insertions(+), 149 deletions(-) diff --git a/putty.h b/putty.h index 6268edb9..697892cf 100644 --- a/putty.h +++ b/putty.h @@ -2747,8 +2747,11 @@ Socket *platform_start_subprocess( * EXITTYPE_NORMAL, because exits and signal terminations aren't * distinguished in the API. So don't depend on this enumeration for * anything semantic: only use it to write sensible (ish) user-facing - * messages. */ -enum { EXITTYPE_NORMAL, EXITTYPE_SIGNAL }; + * messages. + * + * EXITTYPE_WEIRD is never returned from this callback, but is + * available for callers to use as an extra value of their own. */ +enum { EXITTYPE_NORMAL, EXITTYPE_SIGNAL, EXITTYPE_WEIRD }; typedef void (*SubprocessWaiterCallback)( void *ctx, int exittype, uint32_t exitdata); void subproc_waiter_set_callback( diff --git a/unix/platform.h b/unix/platform.h index 08f8cbba..89296fc4 100644 --- a/unix/platform.h +++ b/unix/platform.h @@ -472,6 +472,11 @@ typedef bool (*cliloop_continue_t)(void *ctx, bool found_any_fd, /* Unix-specific API for making a SubprocessWaiter */ SubprocessWaiter *subproc_waiter_from_pid(pid_t pid); +/* Force setup of the SIGCHLD handler, in case we're about to fork for + * any other reason */ +void subproc_waiter_force_setup(void); +/* Force a run of the waitpid() loop even if there's been no signal */ +void subproc_waiter_force_wait(void); void cli_main_loop(cliloop_pw_setup_t pw_setup, cliloop_pw_check_t pw_check, diff --git a/unix/pty.c b/unix/pty.c index 118c4e25..32637858 100644 --- a/unix/pty.c +++ b/unix/pty.c @@ -53,12 +53,6 @@ typedef struct Pty Pty; -/* - * The pty_signal_pipe, along with the SIGCHLD handler, must be - * process-global rather than session-specific. - */ -static int pty_signal_pipe[2] = { -1, -1 }; /* obviously bogus initial val */ - typedef struct PtyFd { int fd; Pty *pty; @@ -71,6 +65,7 @@ struct Pty { int pipefds[6]; PtyFd fds[3]; int master_i, master_o, master_e; + SubprocessWaiter *waiter; Seat *seat; size_t output_backlog; @@ -78,7 +73,8 @@ struct Pty { pid_t child_pid; int term_width, term_height; bool child_dead, finished; - int exit_code; + int exittype; + uint32_t exitdata; bufchain output_data; bool pending_eof; Backend backend; @@ -118,38 +114,6 @@ static int ptyfd_find(void *av, void *bv) static tree234 *ptyfds = NULL; -/* - * We also have a tree of Pty structures themselves, sorted by child - * pid, so that when we wait() in response to the signal we know which - * backend instance is the owner of the process that caused the - * signal. - */ -static int pty_compare_by_pid(void *av, void *bv) -{ - Pty *a = (Pty *)av; - Pty *b = (Pty *)bv; - - if (a->child_pid < b->child_pid) - return -1; - else if (a->child_pid > b->child_pid) - return +1; - return 0; -} - -static int pty_find_by_pid(void *av, void *bv) -{ - pid_t a = *(pid_t *)av; - Pty *b = (Pty *)bv; - - if (a < b->child_pid) - return -1; - else if (a > b->child_pid) - return +1; - return 0; -} - -static tree234 *ptys_by_pid = NULL; - /* * If we are using pty_pre_init(), it will need to have already * allocated a pty structure, which we must then return from @@ -277,21 +241,6 @@ static void cleanup_utmp(void) } #endif -static void sigchld_handler(int signum) -{ - if (write(pty_signal_pipe[1], "x", 1) <= 0) - /* not much we can do about it */; -} - -static void pty_setup_sigchld_handler(void) -{ - static bool setup = false; - if (!setup) { - putty_signal(SIGCHLD, sigchld_handler); - setup = true; - } -} - #ifndef OMIT_UTMP static void fatal_sig_handler(int signum) { @@ -422,6 +371,7 @@ static Pty *new_pty_struct(void) memset(pty, 0, sizeof(Pty)); pty->conf = NULL; pty->pending_eof = false; + pty->exittype = -1; bufchain_init(&pty->output_data); return pty; } @@ -454,7 +404,7 @@ void pty_pre_init(void) /* set the child signal handler straight away; it needs to be set * before we ever fork. */ - pty_setup_sigchld_handler(); + subproc_waiter_force_setup(); pty->master_fd = pty->slave_fd = -1; #ifndef OMIT_UTMP pty_stamped_utmp = false; @@ -593,7 +543,6 @@ void pty_pre_init(void) } -static void pty_try_wait(void); static void pty_uxsel_setup(Pty *pty); static void pty_finished(Pty *pty) @@ -617,27 +566,30 @@ static void pty_finished(Pty *pty) */ close_on_exit = conf_get_int(pty->conf, CONF_close_on_exit); if (close_on_exit == FORCE_OFF || - (close_on_exit == AUTO && pty->exit_code != 0)) { + (close_on_exit == AUTO && pty->exittype >= 0)) { char *message; - if (WIFEXITED(pty->exit_code)) { + switch (pty->exittype) { + case EXITTYPE_NORMAL: message = dupprintf( - "\r\n[pterm: process terminated with exit code %d]\r\n", - WEXITSTATUS(pty->exit_code)); - } else if (WIFSIGNALED(pty->exit_code)) { + "\r\n[pterm: process terminated with exit code %"PRIu32"]\r\n", + pty->exitdata); + break; + case EXITTYPE_SIGNAL: #if !HAVE_STRSIGNAL message = dupprintf( - "\r\n[pterm: process terminated on signal %d]\r\n", - WTERMSIG(pty->exit_code)); + "\r\n[pterm: process terminated on signal %"PRIu32"]\r\n", + pty->exitdata); #else message = dupprintf( - "\r\n[pterm: process terminated on signal %d (%s)]\r\n", - WTERMSIG(pty->exit_code), - strsignal(WTERMSIG(pty->exit_code))); + "\r\n[pterm: process terminated on signal %"PRIu32" (%s)]\r\n", + pty->exitdata, strsignal(pty->exitdata)); #endif - } else { + break; + default: /* _Shouldn't_ happen, but if it does, a vague message * is better than no message at all */ message = dupprintf("\r\n[pterm: process terminated]\r\n"); + break; } seat_stdout_pl(pty->seat, ptrlen_from_asciz(message)); sfree(message); @@ -693,9 +645,10 @@ static void pty_real_select_result(Pty *pty, int fd, int event, int status) * pterm window to hang around! */ finished = true; - pty_try_wait(); /* one last effort to collect exit code */ + /* One last effort to collect exit code */ + subproc_waiter_force_wait(); if (!pty->child_dead) - pty->exit_code = 0; + pty->exittype = EXITTYPE_WEIRD; } } else if (ret < 0) { perror("read pty master"); @@ -716,21 +669,14 @@ static void pty_real_select_result(Pty *pty, int fd, int event, int status) pty_finished(pty); } -static void pty_subprocess_status(Pty *pty, int status) +static void pty_subprocess_terminated( + void *vctx, int exittype, uint32_t exitdata) { - /* - * We've been called because our child process did something. - * `status' tells us what. - */ - if (!(WIFEXITED(status) || WIFSIGNALED(status))) - return; + Pty *pty = (Pty *)vctx; - /* - * If we get here, the primary child process died. - */ pty->child_dead = true; - del234(ptys_by_pid, pty); - pty->exit_code = status; + pty->exittype = exittype; + pty->exitdata = exitdata; /* * If this is an ordinary pty session, this is also the moment to @@ -747,38 +693,12 @@ static void pty_subprocess_status(Pty *pty, int status) pty_finished(pty); } -static void pty_try_wait(void) -{ - Pty *pty; - pid_t pid; - int status; - - do { - pid = waitpid(-1, &status, WNOHANG); - - pty = find234(ptys_by_pid, &pid, pty_find_by_pid); - - if (pty) - pty_subprocess_status(pty, status); - } while (pid > 0); -} - void pty_select_result(int fd, int event) { - if (fd == pty_signal_pipe[0]) { - char c[1]; - - if (read(pty_signal_pipe[0], c, 1) <= 0) - /* ignore error */; - /* ignore its value; it'll be `x' */ + PtyFd *ptyfd = find234(ptyfds, &fd, ptyfd_find); - pty_try_wait(); - } else { - PtyFd *ptyfd = find234(ptyfds, &fd, ptyfd_find); - - if (ptyfd) - pty_real_select_result(ptyfd->pty, fd, event, 0); - } + if (ptyfd) + pty_real_select_result(ptyfd->pty, fd, event, 0); } static void pty_uxsel_setup_fd(Pty *pty, int fd) @@ -816,13 +736,6 @@ static void pty_uxsel_setup(Pty *pty) pty_uxsel_setup_fd(pty, pty->master_o); pty_uxsel_setup_fd(pty, pty->master_e); pty_uxsel_setup_fd(pty, pty->master_i); - - /* - * In principle this only needs calling once for all pty - * backend instances, but it's simplest just to call it every - * time; uxsel won't mind. - */ - uxsel_set(pty_signal_pipe[0], SELECT_R, pty_select_result); } static void copy_ttymodes_into_termios( @@ -900,15 +813,6 @@ Backend *pty_backend_create( pty->fds[i].pty = pty; } - if (pty_signal_pipe[0] < 0) { - if (pipe(pty_signal_pipe) < 0) { - perror("pipe"); - exit(1); - } - cloexec(pty_signal_pipe[0]); - cloexec(pty_signal_pipe[1]); - } - pty->seat = seat; pty->backend.vt = &pty_backend; @@ -995,12 +899,6 @@ Backend *pty_backend_create( got_windowid = seat_get_windowid(pty->seat, &windowid); #endif - /* - * Set up the signal handler to catch SIGCHLD, if pty_pre_init - * didn't already do it. - */ - pty_setup_sigchld_handler(); - /* * Fork and execute the command. */ @@ -1252,8 +1150,6 @@ Backend *pty_backend_create( pty->finished = false; if (pty->slave_fd > 0) close(pty->slave_fd); - if (!ptys_by_pid) - ptys_by_pid = newtree234(pty_compare_by_pid); if (pty->pipefds[0] >= 0) { close(pty->pipefds[0]); pty->pipefds[0] = -1; @@ -1266,7 +1162,9 @@ Backend *pty_backend_create( close(pty->pipefds[5]); pty->pipefds[5] = -1; } - add234(ptys_by_pid, pty); + pty->waiter = subproc_waiter_from_pid(pid); + subproc_waiter_set_callback( + pty->waiter, pty_subprocess_terminated, pty); } pty_uxsel_setup(pty); @@ -1322,14 +1220,15 @@ static void pty_free(Backend *be) pty_close(pty); - /* Either of these may fail `not found'. That's fine with us. */ - del234(ptys_by_pid, pty); + /* This may fail `not found'. That's fine with us. */ for (i = 0; i < 3; i++) if (pty->fds[i].fd >= 0) del234(ptyfds, &pty->fds[i]); bufchain_clear(&pty->output_data); + subproc_waiter_free(pty->waiter); + conf_free(pty->conf); pty->conf = NULL; @@ -1551,20 +1450,22 @@ static int pty_exitcode(Backend *be) Pty *pty = container_of(be, Pty, backend); if (!pty->finished) return -1; /* not dead yet */ - else if (WIFSIGNALED(pty->exit_code)) - return 128 + WTERMSIG(pty->exit_code); + else if (pty->exittype == EXITTYPE_SIGNAL) + return 128 + pty->exitdata; + else if (pty->exittype == EXITTYPE_NORMAL) + return pty->exitdata; else - return WEXITSTATUS(pty->exit_code); + return 127; } int pty_backend_exit_signum(Backend *be) { Pty *pty = container_of(be, Pty, backend); - if (!pty->finished || !WIFSIGNALED(pty->exit_code)) + if (!pty->finished || pty->exittype != EXITTYPE_SIGNAL) return -1; - return WTERMSIG(pty->exit_code); + return WTERMSIG(pty->exitdata); } ptrlen pty_backend_exit_signame(Backend *be, char **aux_msg) diff --git a/unix/utils/subprocess_waiter.c b/unix/utils/subprocess_waiter.c index f6d7f1dd..369c5318 100644 --- a/unix/utils/subprocess_waiter.c +++ b/unix/utils/subprocess_waiter.c @@ -69,7 +69,7 @@ static void sigchld_handler(int signum) } } -static void subproc_waiter_wait(void) +void subproc_waiter_force_wait(void) { while (1) { int status; @@ -108,11 +108,11 @@ static void sigchld_select_result(int fd, int event) /* do nothing */; /* Now wait for all available subprocesses. */ - subproc_waiter_wait(); + subproc_waiter_force_wait(); } } -static void subproc_waiter_setup(void) +void subproc_waiter_force_setup(void) { static bool setup = false; if (!setup) { @@ -129,7 +129,9 @@ static void subproc_waiter_setup(void) waiters_by_pid = newtree234(subproc_waiter_compare_by_pid); - uxsel_set(sigchld_pipe[0], SELECT_R, sigchld_select_result); + /* We don't call uxsel_set here, because this function might + * have been called too early, e.g. in pty.c. We leave that + * for subproc_waiter_from_pid. */ setup = true; } @@ -137,7 +139,8 @@ static void subproc_waiter_setup(void) SubprocessWaiter *subproc_waiter_from_pid(pid_t pid) { - subproc_waiter_setup(); + subproc_waiter_force_setup(); + uxsel_set(sigchld_pipe[0], SELECT_R, sigchld_select_result); SubprocessWaiter *waiter = snew(SubprocessWaiter); waiter->pid = pid; From 85703a848b7ae8d931c4371c16d6861f8f1087bd Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Wed, 15 Apr 2026 09:44:10 +0100 Subject: [PATCH 118/129] Add a horizontal scrollbar in the Windows Event Log. Now you can see the end of a long message without having to paste it into another application. As mentioned in the comment, this doesn't seem to be setting exactly the right scrollbar extent, but I don't know why not. Still, it's overestimating rather than underestimating, which is the better kind of error (you can still read all the text!), so this is better than nothing. --- windows/dialog.c | 45 ++++++++++++++++++++++++++++++++++++++++ windows/putty-common.rc2 | 2 +- 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/windows/dialog.c b/windows/dialog.c index 96dab3ab..e28e2747 100644 --- a/windows/dialog.c +++ b/windows/dialog.c @@ -251,6 +251,47 @@ static char *getevent(int i) static HWND logbox; HWND event_log_window(void) { return logbox; } +static void update_logbox_horizontal_extent(HWND logbox) +{ + /* Find the width of every entry in the current Event Log, and set + * the horizontal scrollbar so that you can scroll right to see + * all of them. */ + HWND listbox = GetDlgItem(logbox, IDN_LIST); + HDC hdc = GetDC(listbox); + int count = SendMessage(listbox, LB_GETCOUNT, 0, 0); + strbuf *sb = strbuf_new(); + WPARAM maxwidth = 0; + for (int i = 0; i < count; i++) { + size_t len = SendMessage(listbox, LB_GETTEXTLEN, i, 0); + strbuf_clear(sb); + SendMessage(listbox, LB_GETTEXT, i, (LPARAM)strbuf_append(sb, len)); + SIZE size; + if (GetTextExtentPoint(hdc, sb->s, sb->len, &size)) { + if (maxwidth < size.cx) + maxwidth = size.cx; + } + } + strbuf_free(sb); + ReleaseDC(listbox, hdc); + + /* + * This doesn't seem to set _exactly_ the right width. If I scroll + * the scrollbar right as far as it will go, I find I end up with + * a bit of extra space on the right of the longest piece of text. + * I don't know why that is. + * + * Testing with debug(), GetTextExtentPoint seems to be correctly + * returning the exact width in pixels of each log entry's text. + * And the docs for LB_SETHORIZONTALEXTENT say that it wants a + * width in pixels too. So I don't think it can be the usual + * problem of confusing logical dialog units and pixels. (In any + * case, on the high-DPI display where I tested, the difference + * between those is more than a factor of 2, whereas I'm seeing a + * discrepancy of only about 10%.) + */ + SendMessage(listbox, LB_SETHORIZONTALEXTENT, maxwidth, 0); +} + static INT_PTR CALLBACK LogProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { @@ -272,6 +313,8 @@ static INT_PTR CALLBACK LogProc(HWND hwnd, UINT msg, for (i = 0; i < ncircular; i++) SendDlgItemMessage(hwnd, IDN_LIST, LB_ADDSTRING, 0, (LPARAM) events_circular[(circular_first + i) % LOGEVENT_CIRCULAR_MAX]); + update_logbox_horizontal_extent(hwnd); + return 1; } case WM_COMMAND: @@ -790,6 +833,8 @@ static void win_gui_eventlog(LogPolicy *lp, const char *string) 0, (LPARAM) *location); count = SendDlgItemMessage(logbox, IDN_LIST, LB_GETCOUNT, 0, 0); SendDlgItemMessage(logbox, IDN_LIST, LB_SETTOPINDEX, count - 1, 0); + + update_logbox_horizontal_extent(logbox); } if (ninitial < LOGEVENT_INITIAL_MAX) { ninitial++; diff --git a/windows/putty-common.rc2 b/windows/putty-common.rc2 index a43e3ac1..e2fde6ba 100644 --- a/windows/putty-common.rc2 +++ b/windows/putty-common.rc2 @@ -42,7 +42,7 @@ FONT 8, "MS Shell Dlg" BEGIN DEFPUSHBUTTON "&Close", IDOK, 135, 102, 44, 14 PUSHBUTTON "C&opy", IDN_COPY, 81, 102, 44, 14 - LISTBOX IDN_LIST, 3, 3, 294, 95, LBS_HASSTRINGS | LBS_USETABSTOPS | WS_VSCROLL | LBS_EXTENDEDSEL + LISTBOX IDN_LIST, 3, 3, 294, 95, LBS_HASSTRINGS | LBS_USETABSTOPS | WS_VSCROLL | WS_HSCROLL | LBS_EXTENDEDSEL END /* No accelerators used */ From ea1038a25b54dbddc29ba46d27d330ce633a0b7b Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Wed, 15 Apr 2026 16:23:02 +0100 Subject: [PATCH 119/129] GTK: switch embedded icons to raw RGBA rather than xpm. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A test-build on current Debian sid revealed that in the latest version of GdkPixbuf, gdk_pixbuf_new_from_xpm_data() is marked as deprecated, causing build failures at -Werror. It turns out that ever since the start of GTK 2, GdkPixbuf has had a reasonably nice API call gdk_pixbuf_new_from_data() which takes a buffer of raw 32-bit RGBA pixels plus width/height/stride parameters, and moreover, uses the data in place rather than copying it – it takes ownership, but you provide a function to free it. Or if it's in the static data segment, you just don't _even_ provide a free function. Not only that, but it turns out the XPM parsing was done by a spare shared library that's not embedded in the GdkPixbuf main code, and a warning in the current docs say that that library can't be 100% relied on to be present everywhere! So using raw RGBA data seems better all round in any case, and since it isn't newly introduced, I don't need to make it conditional on a very new version of anything. We can just use that function for all GTK 2.x and 3.x builds, and use the XPM approach only on GTK 1. --- icons/Makefile | 19 +- icons/cicon.pl | 84 +- unix/CMakeLists.txt | 8 +- unix/dialog.c | 2 +- unix/platform.h | 11 +- unix/pterm-config-rgb.c | 3619 +++++++++++++++++++++++++++++++++++++++ unix/pterm-rgb.c | 3619 +++++++++++++++++++++++++++++++++++++++ unix/putty-config-rgb.c | 3619 +++++++++++++++++++++++++++++++++++++++ unix/putty-rgb.c | 3619 +++++++++++++++++++++++++++++++++++++++ unix/window.c | 96 +- 10 files changed, 14644 insertions(+), 52 deletions(-) create mode 100644 unix/pterm-config-rgb.c create mode 100644 unix/pterm-rgb.c create mode 100644 unix/putty-config-rgb.c create mode 100644 unix/putty-rgb.c diff --git a/icons/Makefile b/icons/Makefile index 923eb31e..d695a3d2 100644 --- a/icons/Makefile +++ b/icons/Makefile @@ -21,7 +21,8 @@ MONOSVGS = $(patsubst %,%-mono.svg,$(ICONS)) ICOS = putty.ico puttygen.ico pscp.ico pageant.ico pageants.ico puttycfg.ico \ puttyins.ico pterm.ico ptermcfg.ico ICNS = PuTTY.icns Pterm.icns -CICONS = xpmputty.c xpmpucfg.c xpmpterm.c xpmptcfg.c +CICONS = putty-xpm.c putty-config-xpm.c pterm-xpm.c pterm-config-xpm.c \ + putty-rgb.c putty-config-rgb.c pterm-rgb.c pterm-config-rgb.c base: icos cicons @@ -103,17 +104,25 @@ web192.png: putty.svg web512.png: putty.svg rsvg-convert -f png -w 512 -h 512 -o $@ $< -xpmputty.c: putty-16.png putty-32.png putty-48.png +putty-xpm.c: putty-16.png putty-32.png putty-48.png ./cicon.pl main_icon $^ > $@ +putty-rgb.c: putty-16.png putty-32.png putty-48.png + ./cicon.pl --rgb main_icon $^ > $@ -xpmpucfg.c: puttycfg-16.png puttycfg-32.png puttycfg-48.png +putty-config-xpm.c: puttycfg-16.png puttycfg-32.png puttycfg-48.png ./cicon.pl cfg_icon $^ > $@ +putty-config-rgb.c: puttycfg-16.png puttycfg-32.png puttycfg-48.png + ./cicon.pl --rgb cfg_icon $^ > $@ -xpmpterm.c: pterm-16.png pterm-32.png pterm-48.png +pterm-xpm.c: pterm-16.png pterm-32.png pterm-48.png ./cicon.pl main_icon $^ > $@ +pterm-rgb.c: pterm-16.png pterm-32.png pterm-48.png + ./cicon.pl --rgb main_icon $^ > $@ -xpmptcfg.c: ptermcfg-16.png ptermcfg-32.png ptermcfg-48.png +pterm-config-xpm.c: ptermcfg-16.png ptermcfg-32.png ptermcfg-48.png ./cicon.pl cfg_icon $^ > $@ +pterm-config-rgb.c: ptermcfg-16.png ptermcfg-32.png ptermcfg-48.png + ./cicon.pl --rgb cfg_icon $^ > $@ PuTTY.icns: putty-16-mono.pam putty-16.pam \ putty-32-mono.pam putty-32.pam \ diff --git a/icons/cicon.pl b/icons/cicon.pl index dd635ce1..ff10556b 100755 --- a/icons/cicon.pl +++ b/icons/cicon.pl @@ -3,26 +3,76 @@ # Given a list of input PNGs, create a C source file containing a # const array of XPMs, named by a given C identifier. +$mode = "xpm"; +if ($ARGV[0] eq "--rgb") { + $mode = "rgb"; + shift; +} + $id = shift @ARGV; $k = 0; -@xpms = (); +@images = (); + +if ($mode eq "rgb") { + push @images, "#include \"putty.h\"\n", "\n"; +} + foreach $f (@ARGV) { - # XPM format is generated directly by ImageMagick, so that's easy - # enough. We just have to adjust the declaration line so that it - # has the right name, linkage and storage class. - @lines = (); - open XPM, "convert $f xpm:- |"; - push @lines, $_ while ; - close XPM; - die "XPM from $f in unexpected format\n" unless $lines[1] =~ /^static.*\{$/; - $lines[1] = "static const char *const ${id}_$k"."[] = {\n"; - $k++; - push @xpms, @lines, "\n"; + if ($mode eq "xpm") { + # XPM format is generated directly by ImageMagick, so that's easy + # enough. We just have to adjust the declaration line so that it + # has the right name, linkage and storage class. + @lines = (); + open XPM, "convert $f xpm:- |"; + push @lines, $_ while ; + close XPM; + die "XPM from $f in unexpected format\n" + unless $lines[1] =~ /^static.*\{$/; + $lines[1] = "static const char *const ${id}_$k"."[] = {\n"; + push @images, @lines, "\n"; + } elsif ($mode eq "rgb") { + open SIZE, "-|", "identify", "-format", "%w %h", $f; + chomp($wh = ); + close SIZE; + ($w, $h) = split / /, $wh; + die "bad size from $f" unless $w > 0 && $h > 0; + open RGB, "-|", "convert", "-depth", "8", $f, "rgba:-"; + $rgbdata = ''; + 1 while read RGB, $rgbdata, 4096, length $rgbdata; + close RGB; + die "bad rgb data from $f" if length $rgbdata != 4*$w*$h; + push @images, "static const unsigned char ${id}_rgbdata_${k}[] = {\n"; + for ($i = 0; $i < $w*$h; $i++) { + push @images, sprintf " 0x%02x, 0x%02x, 0x%02x, 0x%02x,\n", + unpack "CCCC", substr $rgbdata, $i*4, 4; + } + push @images, + "};\n", + "\n", + "static const struct RgbIconImage ${id}_rgb_$k = {\n", + " .width = ${w},\n", + " .height = ${h},\n", + " .data = ${id}_rgbdata_$k,\n", + "};\n", + "\n"; + } else { + die "bad mode '$mode'"; + } + $k++; } # Now output. -foreach $line (@xpms) { print $line; } -print "const char *const *const ${id}[] = {\n"; -for ($i = 0; $i < $k; $i++) { print " ${id}_$i,\n"; } -print "};\n"; -print "const int n_${id} = $k;\n"; +foreach $line (@images) { print $line; } +if ($mode eq "xpm") { + print "const char *const *const ${id}[] = {\n"; + for ($i = 0; $i < $k; $i++) { print " ${id}_$i,\n"; } + print "};\n"; + print "const int n_${id} = $k;\n"; +} elsif ($mode eq "rgb") { + print "const struct RgbIconImage *const ${id}_rgb[] = {\n"; + for ($i = 0; $i < $k; $i++) { print " &${id}_rgb_$i,\n"; } + print "};\n"; + print "const int n_${id}_rgb = $k;\n"; +} else { + die "bad mode '$mode'"; +} diff --git a/unix/CMakeLists.txt b/unix/CMakeLists.txt index 332c636e..70ebcd5e 100644 --- a/unix/CMakeLists.txt +++ b/unix/CMakeLists.txt @@ -27,10 +27,14 @@ add_sources_from_current_dir(utils # Compiled icon pixmap files add_library(puttyxpms STATIC putty-xpm.c - putty-config-xpm.c) + putty-rgb.c + putty-config-xpm.c + putty-config-rgb.c) add_library(ptermxpms STATIC pterm-xpm.c - pterm-config-xpm.c) + pterm-rgb.c + pterm-config-xpm.c + pterm-config-rgb.c) add_sources_from_current_dir(eventloop cliloop.c uxsel.c) add_sources_from_current_dir(console diff --git a/unix/dialog.c b/unix/dialog.c index f947548b..e2989631 100644 --- a/unix/dialog.c +++ b/unix/dialog.c @@ -3289,7 +3289,7 @@ GtkWidget *create_config_box(const char *title, Conf *conf, dp->retval = -1; dp->window = window; - set_window_icon(window, cfg_icon, n_cfg_icon); + set_window_cfg_icon(window); #if !GTK_CHECK_VERSION(2,0,0) gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(treescroll), diff --git a/unix/platform.h b/unix/platform.h index 89296fc4..a7efafd9 100644 --- a/unix/platform.h +++ b/unix/platform.h @@ -186,6 +186,14 @@ void app_menu_action(GtkFrontend *frontend, enum MenuAction); extern const char *const *const main_icon[]; extern const char *const *const cfg_icon[]; extern const int n_main_icon, n_cfg_icon; +/* Same, but in raw RGB24 with a wrapper struct */ +struct RgbIconImage { + unsigned width, height; + const void *data; +}; +extern const struct RgbIconImage *const main_icon_rgb[]; +extern const struct RgbIconImage *const cfg_icon_rgb[]; +extern const int n_main_icon_rgb, n_cfg_icon_rgb; /* Things dialog.c needs from window.c */ #ifdef MAY_REFER_TO_GTK_IN_HEADERS @@ -200,8 +208,7 @@ enum DialogSlot { GtkWidget *gtk_seat_get_window(Seat *seat); void register_dialog(Seat *seat, enum DialogSlot slot, GtkWidget *dialog); void unregister_dialog(Seat *seat, enum DialogSlot slot); -void set_window_icon(GtkWidget *window, const char *const *const *icon, - int n_icon); +void set_window_cfg_icon(GtkWidget *window); extern GdkAtom compound_text_atom; #endif diff --git a/unix/pterm-config-rgb.c b/unix/pterm-config-rgb.c new file mode 100644 index 00000000..79407c8d --- /dev/null +++ b/unix/pterm-config-rgb.c @@ -0,0 +1,3619 @@ +#include "putty.h" + +static const unsigned char cfg_icon_rgbdata_0[] = { + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, +}; + +static const struct RgbIconImage cfg_icon_rgb_0 = { + .width = 16, + .height = 16, + .data = cfg_icon_rgbdata_0, +}; + +static const unsigned char cfg_icon_rgbdata_1[] = { + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, +}; + +static const struct RgbIconImage cfg_icon_rgb_1 = { + .width = 32, + .height = 32, + .data = cfg_icon_rgbdata_1, +}; + +static const unsigned char cfg_icon_rgbdata_2[] = { + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, +}; + +static const struct RgbIconImage cfg_icon_rgb_2 = { + .width = 48, + .height = 48, + .data = cfg_icon_rgbdata_2, +}; + +const struct RgbIconImage *const cfg_icon_rgb[] = { + &cfg_icon_rgb_0, + &cfg_icon_rgb_1, + &cfg_icon_rgb_2, +}; +const int n_cfg_icon_rgb = 3; diff --git a/unix/pterm-rgb.c b/unix/pterm-rgb.c new file mode 100644 index 00000000..deedf5bb --- /dev/null +++ b/unix/pterm-rgb.c @@ -0,0 +1,3619 @@ +#include "putty.h" + +static const unsigned char main_icon_rgbdata_0[] = { + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, +}; + +static const struct RgbIconImage main_icon_rgb_0 = { + .width = 16, + .height = 16, + .data = main_icon_rgbdata_0, +}; + +static const unsigned char main_icon_rgbdata_1[] = { + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, +}; + +static const struct RgbIconImage main_icon_rgb_1 = { + .width = 32, + .height = 32, + .data = main_icon_rgbdata_1, +}; + +static const unsigned char main_icon_rgbdata_2[] = { + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, +}; + +static const struct RgbIconImage main_icon_rgb_2 = { + .width = 48, + .height = 48, + .data = main_icon_rgbdata_2, +}; + +const struct RgbIconImage *const main_icon_rgb[] = { + &main_icon_rgb_0, + &main_icon_rgb_1, + &main_icon_rgb_2, +}; +const int n_main_icon_rgb = 3; diff --git a/unix/putty-config-rgb.c b/unix/putty-config-rgb.c new file mode 100644 index 00000000..5b1a2657 --- /dev/null +++ b/unix/putty-config-rgb.c @@ -0,0 +1,3619 @@ +#include "putty.h" + +static const unsigned char cfg_icon_rgbdata_0[] = { + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, +}; + +static const struct RgbIconImage cfg_icon_rgb_0 = { + .width = 16, + .height = 16, + .data = cfg_icon_rgbdata_0, +}; + +static const unsigned char cfg_icon_rgbdata_1[] = { + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, +}; + +static const struct RgbIconImage cfg_icon_rgb_1 = { + .width = 32, + .height = 32, + .data = cfg_icon_rgbdata_1, +}; + +static const unsigned char cfg_icon_rgbdata_2[] = { + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, +}; + +static const struct RgbIconImage cfg_icon_rgb_2 = { + .width = 48, + .height = 48, + .data = cfg_icon_rgbdata_2, +}; + +const struct RgbIconImage *const cfg_icon_rgb[] = { + &cfg_icon_rgb_0, + &cfg_icon_rgb_1, + &cfg_icon_rgb_2, +}; +const int n_cfg_icon_rgb = 3; diff --git a/unix/putty-rgb.c b/unix/putty-rgb.c new file mode 100644 index 00000000..113ba88d --- /dev/null +++ b/unix/putty-rgb.c @@ -0,0 +1,3619 @@ +#include "putty.h" + +static const unsigned char main_icon_rgbdata_0[] = { + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, +}; + +static const struct RgbIconImage main_icon_rgb_0 = { + .width = 16, + .height = 16, + .data = main_icon_rgbdata_0, +}; + +static const unsigned char main_icon_rgbdata_1[] = { + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, +}; + +static const struct RgbIconImage main_icon_rgb_1 = { + .width = 32, + .height = 32, + .data = main_icon_rgbdata_1, +}; + +static const unsigned char main_icon_rgbdata_2[] = { + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x80, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0x00, 0x00, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0xc0, 0xc0, 0xc0, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x80, 0x80, 0x80, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, +}; + +static const struct RgbIconImage main_icon_rgb_2 = { + .width = 48, + .height = 48, + .data = main_icon_rgbdata_2, +}; + +const struct RgbIconImage *const main_icon_rgb[] = { + &main_icon_rgb_0, + &main_icon_rgb_1, + &main_icon_rgb_2, +}; +const int n_main_icon_rgb = 3; diff --git a/unix/window.c b/unix/window.c index 52fe0cbb..006850ee 100644 --- a/unix/window.c +++ b/unix/window.c @@ -4154,12 +4154,60 @@ static void gtkwin_draw_cursor( #endif } -#if !GTK_CHECK_VERSION(2,0,0) /* - * For GTK 1, manual code to scale an in-memory XPM, producing a new - * one as output. It will be ugly, but good enough to use as a trust - * sigil. + * Handle icons embedded in the binary + */ +#if GTK_CHECK_VERSION(2,0,0) +/* + * For any GTK 2 and above, we use the raw RGB24 version of the icon + * data, and pass it to gdk_pixbuf_new_from_data(). The XPM-consuming + * function gdk_pixbuf_new_from_xpm_data() is deprecated as of + * gdk-pixbuf 2.44; new_from_data has existed since the earliest GTK + * 2, and seems better anyway because it avoids depending on _any_ + * separate .so loader module and also is apparently able to use the + * bitmap data by reference rather than allocating a separate copy. + */ + +typedef const struct RgbIconImage *const *IconCollection; + +#define N_ICONS(basename) (n_ ## basename ## _rgb) +#define ALL_ICONS(basename) (basename ## _rgb) + +#define GET_ICON_SIZE(basename, n, w, h) do { \ + w = (basename ## _rgb[n]->width); \ + h = (basename ## _rgb[n]->height); \ + } while (0) + +#define ICON_PIXBUF(rgb) gdk_pixbuf_new_from_data( \ + (rgb)->data, \ + GDK_COLORSPACE_RGB, \ + true /* alpha channel */, \ + 8 /* bits per sample */, \ + (rgb)->width, \ + (rgb)->height, \ + 4 * (rgb)->width /* row stride */, \ + NULL /* destroy */, NULL /* destroy context */) + +#else // !GTK_CHECK_VERSION(2,0,0) +/* + * For GTK 1, we use XPM, and we must provide our own code to scale an + * XPM to a different size. It will be ugly, but good enough to use as + * a trust sigil. */ + +typedef const char *const *const *IconCollection; + +#define N_ICONS(basename) (n_ ## basename) +#define ALL_ICONS(basename) (basename) + +static inline void get_icon_size(const char *const *xpm, int *w, int *h) +{ + int nfound = sscanf(xpm[0], "%d %d", w, h); + assert(nfound == 2 && "Bad compiled-in xpm data"); +} + +#define GET_ICON_SIZE(basename, n, w, h) get_icon_size(basename[n], &w, &h) + struct XpmHolder { char **strings; size_t nstrings; @@ -4206,7 +4254,7 @@ static XpmHolder *xpm_scale(const char *const *xpm, int wo, int ho) return xh; } -#endif /* !GTK_CHECK_VERSION(2,0,0) */ +#endif // GTK_CHECK_VERSION(2,0,0) static void gtkwin_draw_trust_sigil(TermWin *tw, int cx, int cy) { @@ -4234,22 +4282,20 @@ static void gtkwin_draw_trust_sigil(TermWin *tw, int cx, int cy) int best_icon_index = 0; unsigned score = UINT_MAX; - for (int i = 0; i < n_main_icon; i++) { + for (int i = 0; i < N_ICONS(main_icon); i++) { int iw, ih; - if (sscanf(main_icon[i][0], "%d %d", &iw, &ih) == 2) { - int this_excess = (iw + ih) - (w + h); - unsigned this_score = (abs(this_excess) | - (this_excess > 0 ? 0 : 0x80000000U)); - if (this_score < score) { - best_icon_index = i; - score = this_score; - } + GET_ICON_SIZE(main_icon, i, iw, ih); + int this_excess = (iw + ih) - (w + h); + unsigned this_score = (abs(this_excess) | + (this_excess > 0 ? 0 : 0x80000000U)); + if (this_score < score) { + best_icon_index = i; + score = this_score; } } #if GTK_CHECK_VERSION(2,0,0) - GdkPixbuf *icon_unscaled = gdk_pixbuf_new_from_xpm_data( - (const gchar **)main_icon[best_icon_index]); + GdkPixbuf *icon_unscaled = ICON_PIXBUF(main_icon_rgb[best_icon_index]); inst->trust_sigil_pb = gdk_pixbuf_scale_simple( icon_unscaled, w, h, GDK_INTERP_BILINEAR); g_object_unref(G_OBJECT(icon_unscaled)); @@ -5068,8 +5114,7 @@ static void update_savedsess_menu(GtkMenuItem *menuitem, gpointer data) get_sesslist(&sesslist, false); /* free up */ } -void set_window_icon(GtkWidget *window, const char *const *const *icon, - int n_icon) +static void set_window_icon(GtkWidget *window, IconCollection icon, int n_icon) { #if GTK_CHECK_VERSION(2,0,0) GList *iconlist; @@ -5084,8 +5129,7 @@ void set_window_icon(GtkWidget *window, const char *const *const *icon, gtk_widget_realize(window); #if GTK_CHECK_VERSION(2,0,0) - gtk_window_set_icon(GTK_WINDOW(window), - gdk_pixbuf_new_from_xpm_data((const gchar **)icon[0])); + gtk_window_set_icon(GTK_WINDOW(window), ICON_PIXBUF(icon[0])); #else iconpm = gdk_pixmap_create_from_xpm_d(gtk_widget_get_window(window), &iconmask, NULL, (gchar **)icon[0]); @@ -5095,15 +5139,17 @@ void set_window_icon(GtkWidget *window, const char *const *const *icon, #if GTK_CHECK_VERSION(2,0,0) iconlist = NULL; for (n = 0; n < n_icon; n++) { - iconlist = - g_list_append(iconlist, - gdk_pixbuf_new_from_xpm_data((const gchar **) - icon[n])); + iconlist = g_list_append(iconlist, ICON_PIXBUF(icon[n])); } gtk_window_set_icon_list(GTK_WINDOW(window), iconlist); #endif } +void set_window_cfg_icon(GtkWidget *window) +{ + set_window_icon(window, ALL_ICONS(cfg_icon), N_ICONS(cfg_icon)); +} + static void free_special_cmd(gpointer data) { sfree(data); } static void gtk_seat_update_specials_menu(Seat *seat) @@ -5573,7 +5619,7 @@ void new_session_window(Conf *conf, const char *geometry_string) #endif ); - set_window_icon(inst->window, main_icon, n_main_icon); + set_window_icon(inst->window, ALL_ICONS(main_icon), N_ICONS(main_icon)); gtk_widget_show(inst->window); From 3c598400e495645fec921781a1065303039a7d17 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Wed, 15 Apr 2026 17:16:00 +0100 Subject: [PATCH 120/129] Fix handling of ECONNREFUSED in GTK 1 builds (!) While testing the GTK 1 version of the code I touched in the previous commit, I tried to connect to an SSH server which has both IPv6 and v4 addresses but is refusing connections to port 22 on the v6 address. GTK2 and GTK3 PuTTY cheerfully fall back to v4; GTK1 PuTTY bombed out immediately with a 'Connection refused' message box. Turned out this was because I had performed an asynchronous connect(2) operation; called uxsel_set() to ask for only writability notifications on the socket (that being how you find out that your async connect attempt has finished); uxsel_set() dutifully called gdk_input_add() with only the GDK_INPUT_WRITE flag; and GTK1 called me back with GDK_INPUT_READ as well as GDK_INPUT_WRITE set! So network.c tried to process the readability notification first, leading to the wrong branch of the network error handling code. Easily fixed by remembering what I/O flags we actually _asked_ for, and ignoring any others that GTK chooses to set in the callback. --- unix/gtk-common.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/unix/gtk-common.c b/unix/gtk-common.c index 9d48e882..3bea1dd9 100644 --- a/unix/gtk-common.c +++ b/unix/gtk-common.c @@ -66,6 +66,7 @@ struct uxsel_id { guint watch_id; #else int id; + int flags; #endif }; @@ -93,6 +94,9 @@ gboolean fd_input_func(GIOChannel *source, GIOCondition condition, #else void fd_input_func(gpointer data, gint sourcefd, GdkInputCondition condition) { + uxsel_id *id = (uxsel_id *)data; + condition &= id->flags; + if (condition & GDK_INPUT_EXCEPTION) select_result(sourcefd, SELECT_X); if (condition & GDK_INPUT_READ) @@ -122,7 +126,8 @@ uxsel_id *uxsel_input_add(int fd, int rwx) { if (rwx & SELECT_W) flags |= GDK_INPUT_WRITE; if (rwx & SELECT_X) flags |= GDK_INPUT_EXCEPTION; assert(flags); - id->id = gdk_input_add(fd, flags, fd_input_func, NULL); + id->flags = flags; + id->id = gdk_input_add(fd, flags, fd_input_func, id); #endif return id; From cd18fb76f9d8b500b4e25e5553347b7a59eb3569 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Mon, 30 Mar 2026 20:27:29 +0100 Subject: [PATCH 121/129] Tidy up the elliptic curve multiplication tests. When you test raising a group element to a power, the power only matters mod the order of the original element. So we should be reducing our test powers mod that, rather than mod the prime used in the curve's field. Now in all three test functions we reduce mod curve.G_order. This also involved making the curve.G_order field exist at all in the Python reference implementation of the Montgomery curves. I'd left it out. But that's easy, because those curves correspond closely to the two Edwards ones and share their values of G_order. Also, testMontgomeryMultiply wasn't even reducing mod the _right_ 256-bit prime: it was using p256.p rather than curve25519.p, presumably from a copy-paste error (p256.p is used in the Weierstrass function right next to it). Now all three functions assign the test curve to a variable of the same name, so that they _deliberately_ look alike. --- test/cryptsuite.py | 30 ++++++++++++++++++------------ test/eccref.py | 2 ++ 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/test/cryptsuite.py b/test/cryptsuite.py index 30c4ebeb..09533eb6 100755 --- a/test/cryptsuite.py +++ b/test/cryptsuite.py @@ -902,42 +902,48 @@ def make_point(x, y): # standard curves, because I want to have tested those a bit too. def testWeierstrassMultiply(self): - wc = ecc_weierstrass_curve(p256.p, int(p256.a), int(p256.b), None) - wG = ecc_weierstrass_point_new(wc, int(p256.G.x), int(p256.G.y)) + curve = p256 + wc = ecc_weierstrass_curve(curve.p, int(curve.a), int(curve.b), None) + wG = ecc_weierstrass_point_new(wc, int(curve.G.x), int(curve.G.y)) self.assertTrue(ecc_weierstrass_point_valid(wG)) - ints = set(i % p256.p for i in fibonacci_scattered(10)) + ints = set(i % curve.G_order for i in fibonacci_scattered(10)) ints.remove(0) # the zero multiple isn't expected to work + ints.add(curve.G_order - 1) for i in sorted(ints): wGi = ecc_weierstrass_multiply(wG, i) x, y = ecc_weierstrass_get_affine(wGi) - rGi = p256.G * i + rGi = curve.G * i self.assertEqual(int(x), int(rGi.x)) self.assertEqual(int(y), int(rGi.y)) def testMontgomeryMultiply(self): + curve = curve25519 mc = ecc_montgomery_curve( - curve25519.p, int(curve25519.a), int(curve25519.b)) - mG = ecc_montgomery_point_new(mc, int(curve25519.G.x)) + curve.p, int(curve.a), int(curve.b)) + mG = ecc_montgomery_point_new(mc, int(curve.G.x)) - ints = set(i % p256.p for i in fibonacci_scattered(10)) + ints = set(i % curve.G_order for i in fibonacci_scattered(10)) ints.remove(0) # the zero multiple isn't expected to work + ints.add(curve.G_order - 1) for i in sorted(ints): mGi = ecc_montgomery_multiply(mG, i) x = ecc_montgomery_get_affine(mGi) - rGi = curve25519.G * i + rGi = curve.G * i self.assertEqual(int(x), int(rGi.x)) def testEdwardsMultiply(self): - ec = ecc_edwards_curve(ed25519.p, int(ed25519.d), int(ed25519.a), None) - eG = ecc_edwards_point_new(ec, int(ed25519.G.x), int(ed25519.G.y)) + curve = ed25519 + ec = ecc_edwards_curve(curve.p, int(curve.d), int(curve.a), None) + eG = ecc_edwards_point_new(ec, int(curve.G.x), int(curve.G.y)) - ints = set(i % ed25519.p for i in fibonacci_scattered(10)) + ints = set(i % curve.G_order for i in fibonacci_scattered(10)) ints.remove(0) # the zero multiple isn't expected to work + ints.add(curve.G_order - 1) for i in sorted(ints): eGi = ecc_edwards_multiply(eG, i) x, y = ecc_edwards_get_affine(eGi) - rGi = ed25519.G * i + rGi = curve.G * i self.assertEqual(int(x), int(rGi.x)) self.assertEqual(int(y), int(rGi.y)) diff --git a/test/eccref.py b/test/eccref.py index f39fa5e4..770e8f9c 100644 --- a/test/eccref.py +++ b/test/eccref.py @@ -318,9 +318,11 @@ def insert(x): curve25519 = MontgomeryCurve(2**255-19, 0x76d06, 1) curve25519.G = curve25519.cpoint(9) +curve25519.G_order = 0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed curve448 = MontgomeryCurve(2**448-2**224-1, 0x262a6, 1) curve448.G = curve448.cpoint(5) +curve448.G_order = 0x3fffffffffffffffffffffffffffffffffffffffffffffffffffffff7cca23e9c44edb49aed63690216cc2728dc58f552378c292ab5844f3 ed25519 = TwistedEdwardsCurve(2**255-19, 0x52036cee2b6ffe738cc740797779e89800700a4d4141d8ab75eb4dca135978a3, -1) ed25519.G = ed25519.point(0x216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51a,0x6666666666666666666666666666666666666666666666666666666666666658) From 7db1f655bbdd30040f983e71b36ea369a226faea Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Wed, 1 Apr 2026 08:49:53 +0100 Subject: [PATCH 122/129] ecdsa_public: reduce exponent mod the right thing! MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit During (NIST-style) ECDSA key generation, we generate a random exponent, and raise the base point to that power. So the exponent ought to be reduced mod the order of the base point. But in fact we were reducing it mod the prime order of the curve's field – the same error as I just fixed in the test suite in the previous commit. Luckily, this mistake is benign. That reduction is only precautionary in any case, and in fact never comes up, because keygen/ecdsa.c has already generated its random exponent using the _correct_ bounds. And G_order is always smaller than p, so the bogus reduction mod p never did anything. --- crypto/ecc-ssh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto/ecc-ssh.c b/crypto/ecc-ssh.c index fcde908d..3a34f8db 100644 --- a/crypto/ecc-ssh.c +++ b/crypto/ecc-ssh.c @@ -333,7 +333,7 @@ WeierstrassPoint *ecdsa_public(mp_int *private_key, const ssh_keyalg *alg) struct ec_curve *curve = extra->curve(); assert(curve->type == EC_WEIERSTRASS); - mp_int *priv_reduced = mp_mod(private_key, curve->p); + mp_int *priv_reduced = mp_mod(private_key, curve->w.G_order); WeierstrassPoint *toret = ecc_weierstrass_multiply( curve->w.G, priv_reduced); mp_free(priv_reduced); From 65b8f37c34cd80680693e813e0081cdafaf58324 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sat, 28 Mar 2026 19:25:24 +0000 Subject: [PATCH 123/129] Remove bogus assertion in ecc_weierstrass_add. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The comment next to the assertion says that it's checking for either identical inputs or mutually inverse ones: that is, input curve points with the same affine x-coordinate. But in that case we should have checked lambda_n, the _numerator_ of the slope of the line through the input points. Instead we were accidentally checking lambda_d, the denominator. ecc_weierstrass_add_general gets this right: it checks lambda_n to decide whether to use the output of the unequal-point addition formula or the doubling formula. The obvious fix is to replace the assertion with one checking lambda_n. But that doesn't work, because it's possible during legitimate operation to cause a call to ecc_weierstrass_add that would fail the fixed version of the assertion! Because of constant-time considerations, every time ecc_weierstrass_multiply consumes a bit of the exponent, it calculates both of two possible outputs of that iteration step, and then selects between them. And sometimes one of those outputs _does_ involve passing mutually inverse values to ecc_weierstrass_add. That's harmless if the result of that calculation is thrown away by the caller – except that it's not harmless if you fail an assertion and crash before getting back _to_ the caller! (With the current style of exponentiation loop, the case that would fail the 'right' assertion involves raising a point P to its own order minus 1, because we're consuming the exponent from the MSB downwards, so at every stage we choose between P^(2k) and P^(2k+1). But switching to the LSB-upwards style of repeatedly squaring to make P^{2^n} and conditionally multiplying in each of those, you'd still have the same failure, just in a different place – the failing case would involve raising P to the power of its own order with the leading 1 bit removed.) So that's why we can't replace the bogus assertion with a better one. Instead, the only thing to do is remove the assertion completely, and rely on callers to have already checked that exponents are in range (hence the precautionary fix in ecdsa_public in the previous commit). What about triggering the _actual_ wrong assertion? Guido Vranken reported this issue and included a test case that demonstrates that it's possible to trigger the bug deliberately. His example case is a P256 curve point P such that 10P and 11P have the same y-coordinate, and therefore trying to compute 21P will add those values together and fail the previous assertion. Worse, it's easy to construct a malicious P256 public key and signature such that attempting to verify that signature provokes the same crash – no matter what the message is. So this is a DoS vector for an on-path attacker, who can make PuTTY crash by substituting this fixed P256 key and signature in the cleartext initial key exchange of any SSH connection. (Only a DoS, though: PuTTY is always compiled with assertions enabled, so it won't do anything _worse_ than crash with an unhelpful message.) --- crypto/ecc-arithmetic.c | 6 ------ test/cryptsuite.py | 45 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 6 deletions(-) diff --git a/crypto/ecc-arithmetic.c b/crypto/ecc-arithmetic.c index ed2abf39..23695369 100644 --- a/crypto/ecc-arithmetic.c +++ b/crypto/ecc-arithmetic.c @@ -326,12 +326,6 @@ WeierstrassPoint *ecc_weierstrass_add(WeierstrassPoint *P, WeierstrassPoint *Q) ecc_weierstrass_add_prologue( P, Q, &Px, &Py, &Qx, &denom, &lambda_n, &lambda_d); - /* Never expect to have received two mutually inverse inputs, or - * two identical ones (which would make this a doubling). In other - * words, the two input x-coordinates (after putting over a common - * denominator) should never have been equal. */ - assert(!mp_eq_integer(lambda_n, 0)); - /* Now go to the common epilogue code. */ ecc_weierstrass_epilogue(Px, Qx, Py, denom, lambda_n, lambda_d, S); diff --git a/test/cryptsuite.py b/test/cryptsuite.py index 09533eb6..be932b80 100755 --- a/test/cryptsuite.py +++ b/test/cryptsuite.py @@ -947,6 +947,30 @@ def testEdwardsMultiply(self): self.assertEqual(int(x), int(rGi.x)) self.assertEqual(int(y), int(rGi.y)) + def testWeierstrassBogusAssertionRegression(self): + curve = p256 + wc = ecc_weierstrass_curve(curve.p, int(curve.a), int(curve.b), None) + # The point described by these coordinates has the property + # that 10*P and 11*P have the same affine y-coordinate. So + # when the Montgomery-ladder based multiply routine wants to + # make 21*P, it must add those two points, triggering a bug in + # which it failed an assertion if the two inputs to an + # addition were on the same horizontal line. + tx = 0x858d6d6329394a7720d4c9cb4dbcb38ccff10ef6faa9fc45fc0067a5021ff53e + ty = 0x32e9d51b7216745493e8ddc0d67fe15d6e39fa0e71cfc82e00045ca2763e0d74 + rP = curve.point(tx, ty) + assert (10*rP).y == (11*rP).y + + wP = ecc_weierstrass_point_new(wc, tx, ty) + self.assertTrue(ecc_weierstrass_point_valid(wP)) + + i = 21 + wPi = ecc_weierstrass_multiply(wP, i) + x, y = ecc_weierstrass_get_affine(wPi) + rPi = rP * i + self.assertEqual(int(x), int(rPi.x)) + self.assertEqual(int(y), int(rPi.y)) + class keygen(MyTestBase): def testPrimeCandidateSource(self): def inspect(pcs): @@ -3542,6 +3566,27 @@ def testEd25519Overflow(self): self.assertEqual(len(bad_sig), len(good_sig)) self.assertFalse(test_key.verify(bad_sig, test_string)) + def testWeierstrassBogusAssertionRegressionSignature(self): + # This P256 public key contains the same test point as in + # ecc.testWeierstrassBogusAssertionRegression above, which + # causes an assertion failure if raised to the power 21. + tx = 0x858d6d6329394a7720d4c9cb4dbcb38ccff10ef6faa9fc45fc0067a5021ff53e + ty = 0x32e9d51b7216745493e8ddc0d67fe15d6e39fa0e71cfc82e00045ca2763e0d74 + pubblob = ssh_string(b"ecdsa-sha2-nistp256") + ssh_string(b"nistp256") + ssh_string(b'\x04' + be_integer(tx, 256) + be_integer(ty, 256)) + pubkey = ssh_key_new_pub('p256', pubblob) + + # And this signature causes the key to be raised to the power + # 21, hence any attempt to verify the signature against + # anything provokes that assertion failure. + sig = ssh_string(b"ecdsa-sha2-nistp256") + ssh_string(ssh2_mpint(21) + ssh2_mpint(1)) + + # The message is unimportant: its hash isn't involved in the + # calculation leading to the crash. In a fixed version of the + # code, of course, we expect that this signature is totally + # bogus, but it should cleanly report failed verification + # rather than crashing. + self.assertFalse(ssh_key_verify(pubkey, sig, b'any old message')) + class standard_test_vectors(MyTestBase): def testAES(self): def vector(cipher, key, plaintext, ciphertext): From adc9c135eed96ad0641e5783a2bed71dfc4c25db Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sun, 3 May 2026 08:48:49 +0100 Subject: [PATCH 124/129] Docs: add wake-on-LAN as a use case for pre-connect commands. Ian suggested this to me the other day, and it seems worth adding to the docs. In fact it might actually be a _better_ use case than port knocking, so I've listed it first, relegating port knocking to second place. (Since a wake-up script would need to wait until the target server is sufficiently booted up to be listening for SSH, this use case benefits particularly from my rework to run the hook command asynchronously.) (cherry picked from commit b7b8389999878d19a6685ada944219d7d82a2c38) --- doc/config.but | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/doc/config.but b/doc/config.but index 448ca6a8..b00bb041 100644 --- a/doc/config.but +++ b/doc/config.but @@ -1865,11 +1865,17 @@ If you enter a command line in this box, then PuTTY will run that command as a subprocess, just before making its main outgoing network connection. -This could be useful if you are connecting to a server which requires -a preliminary signal such as \q{\i{port knocking}} before it will accept -a connection to its SSH server port in the first place. If you have a -program that knows how to send the correct knock, you can enter its -command line in this box. +This could be useful if you are connecting to a server that is usually +switched off but can be turned on remotely on demand, e.g via +wake-on-LAN. If you have a script that will perform the wake-up +action, you can enter its command line in this box. (You should also +make sure the script waits to terminate until the target machine is +switched on and actually ready to receive an SSH connection.) + +Another use might be a server which requires a preliminary signal such +as \q{\i{port knocking}} before it will accept a connection to its SSH +server port in the first place. If you have a program that knows how +to send the correct knock, you can enter its command line in this box. In the command string, the special strings \c{%host} and \c{%port} will be replaced by the host name and port number you want to connect to, From 29d8bd9b1bf47c81a45acb401e0a821644fcc036 Mon Sep 17 00:00:00 2001 From: Jacob Nevins Date: Sun, 3 May 2026 17:04:24 +0100 Subject: [PATCH 125/129] Docs: index 'wake-on-LAN', on general principles. (cherry picked from commit df256593e9716a191e9752d926064b32b5cee5a2) --- doc/config.but | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/config.but b/doc/config.but index b00bb041..855dd677 100644 --- a/doc/config.but +++ b/doc/config.but @@ -1867,7 +1867,7 @@ connection. This could be useful if you are connecting to a server that is usually switched off but can be turned on remotely on demand, e.g via -wake-on-LAN. If you have a script that will perform the wake-up +\i{wake-on-LAN}. If you have a script that will perform the wake-up action, you can enter its command line in this box. (You should also make sure the script waits to terminate until the target machine is switched on and actually ready to receive an SSH connection.) From e5242181c1a2d8bf58bedfd9b61251ca6af2ca63 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sun, 10 May 2026 14:02:55 +0100 Subject: [PATCH 126/129] Windows on Arm: use hardware SHA-512 accel if available. I have a new WoA test machine which has the necessary CPU extension, and also, the docs for IsProcessorFeaturePresent have been updated to include an id you can use to test for it. So now Arm Windows PuTTY can detect support for hardware-accelerated SHA-512, and turn it on if available. --- windows/utils/arm_arch_queries.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/windows/utils/arm_arch_queries.c b/windows/utils/arm_arch_queries.c index 87728e10..9b01809b 100644 --- a/windows/utils/arm_arch_queries.c +++ b/windows/utils/arm_arch_queries.c @@ -16,6 +16,13 @@ #define IsProcessorFeaturePresent(...) false #endif +/* This feature id is documented in IsProcessorFeaturePresent as of + * 2026-05-10, but is not in the version of MSVC I'm building with. I + * expect it will show up in a later version. */ +#ifndef PF_ARM_SHA3_INSTRUCTIONS_AVAILABLE +#define PF_ARM_SHA3_INSTRUCTIONS_AVAILABLE 64 +#endif + bool platform_aes_neon_available(void) { return IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE); @@ -38,10 +45,13 @@ bool platform_sha1_neon_available(void) bool platform_sha512_neon_available(void) { - /* As of 2020-12-24, as far as I can tell from docs.microsoft.com, - * Windows on Arm does not yet provide a PF_ARM_V8_* flag for the - * SHA-512 architecture extension. */ - return false; + /* + * Arm architecture extension nomenclature considers SHA-512 to be + * part of the same extension as SHA-3, even though it's part of + * the SHA-2 standard from NIST's point of view (and much more + * closely related to SHA-256 in design than it is to SHA-3). + */ + return IsProcessorFeaturePresent(PF_ARM_SHA3_INSTRUCTIONS_AVAILABLE); } bool platform_dit_available(void) From ba3ed53e0bf6682f89940bc2c3e83da6b1524024 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Thu, 14 May 2026 18:15:56 +0100 Subject: [PATCH 127/129] Don't call sfree after ssh_rsakex_freekey. ssh_rsakex_freekey(), given an RSAKey structure, calls freersakey() to free all the pieces dangling off it, and then finally frees the RSAKey itself. So calling ssh_rsakex_freekey() and _then_ sfree() is a double free. --- ssh/kex2-server.c | 4 +--- ssh/transport2.c | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/ssh/kex2-server.c b/ssh/kex2-server.c index 570d7750..8c3dc2f4 100644 --- a/ssh/kex2-server.c +++ b/ssh/kex2-server.c @@ -321,10 +321,8 @@ void ssh2kex_coroutine(struct ssh2_transport_state *s, bool *aborted) put_mp_ssh2(s->kex_shared_secret, K); mp_free(K); - if (s->rsa_kex_key_needs_freeing) { + if (s->rsa_kex_key_needs_freeing) ssh_rsakex_freekey(s->rsa_kex_key); - sfree(s->rsa_kex_key); - } s->rsa_kex_key = NULL; s->rsa_kex_key_needs_freeing = false; diff --git a/ssh/transport2.c b/ssh/transport2.c index 64f40560..60a99c29 100644 --- a/ssh/transport2.c +++ b/ssh/transport2.c @@ -251,10 +251,8 @@ static void ssh2_transport_free(PacketProtocolLayer *ppl) if (s->kex_shared_secret) strbuf_free(s->kex_shared_secret); if (s->dh_ctx) dh_cleanup(s->dh_ctx); - if (s->rsa_kex_key_needs_freeing) { + if (s->rsa_kex_key_needs_freeing) ssh_rsakex_freekey(s->rsa_kex_key); - sfree(s->rsa_kex_key); - } if (s->ecdh_key) ecdh_key_free(s->ecdh_key); if (s->exhash) From cda57ec785f52a9092f529b206059355646caab6 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Thu, 14 May 2026 20:21:24 +0100 Subject: [PATCH 128/129] Update version number for 0.84 release. --- Buildscr | 2 +- LATEST.VER | 2 +- doc/plink.but | 4 +++- doc/pscp.but | 4 +++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Buildscr b/Buildscr index c007da05..ed259e15 100644 --- a/Buildscr +++ b/Buildscr @@ -35,7 +35,7 @@ module putty ifeq "$(RELEASE)" "" set Ndate $(!builddate) ifneq "$(Ndate)" "" in . do echo $(Ndate) | perl -pe 's/(....)(..)(..)/$$1-$$2-$$3/' > date ifneq "$(Ndate)" "" read Date date -set Epoch 19120 # update this at every release +set Epoch 19587 # update this at every release ifneq "$(Ndate)" "" in . do echo $(Ndate) | perl -ne 'use Time::Local; /(....)(..)(..)/ and print timegm(0,0,0,$$3,$$2-1,$$1) / 86400 - $(Epoch)' > days ifneq "$(Ndate)" "" read Days days diff --git a/LATEST.VER b/LATEST.VER index 08fec888..91bc8733 100644 --- a/LATEST.VER +++ b/LATEST.VER @@ -1 +1 @@ -0.83 +0.84 diff --git a/doc/plink.but b/doc/plink.but index f1ad5f0e..33beda1f 100644 --- a/doc/plink.but +++ b/doc/plink.but @@ -41,7 +41,7 @@ use Plink: \c C:\>plink --help \c Plink: command-line connection utility -\c Release 0.83 +\c Release 0.84 \c Usage: plink [options] [user@]host [command] \c ("host" can also be a PuTTY saved session name) \c Options: @@ -58,6 +58,8 @@ use Plink: \c -batch disable all interactive prompts \c -proxycmd command \c use 'command' as local proxy +\c -preconnectcommand command +\c run 'command' before making network connection \c -sercfg configuration-string (e.g. 19200,8,n,1,X) \c Specify the serial configuration (serial only) \c The following options only apply to SSH connections: diff --git a/doc/pscp.but b/doc/pscp.but index 1fb18df6..15c834a3 100644 --- a/doc/pscp.but +++ b/doc/pscp.but @@ -39,7 +39,7 @@ use PSCP: \c C:\>pscp -h \c PuTTY Secure Copy client -\c Release 0.83 +\c Release 0.84 \c Usage: pscp [options] [user@]host:source target \c pscp [options] source [source...] [user@]host:target \c pscp [options] -ls [user@]host:filespec @@ -70,6 +70,8 @@ use PSCP: \c -no-sanitise-stderr don't strip control chars from standard error \c -proxycmd command \c use 'command' as local proxy +\c -preconnectcommand command +\c run 'command' before making network connection \c -unsafe allow server-side wildcards (DANGEROUS) \c -sftp force use of SFTP protocol \c -scp force use of SCP protocol From d6dbb4f127d62a9d2880b6fe9ec6c9c7e7524b6b Mon Sep 17 00:00:00 2001 From: Larry Li Date: Mon, 25 May 2026 12:53:39 +0800 Subject: [PATCH 129/129] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E7=89=88=E6=9C=AC?= =?UTF-8?q?=E5=8F=B7=E8=87=B3=200.84=EF=BC=8C=E4=BF=AE=E6=AD=A3=E7=89=88?= =?UTF-8?q?=E6=9D=83=E5=B9=B4=E4=BB=BD=EF=BC=8C=E7=BF=BB=E8=AF=91=E8=BF=9E?= =?UTF-8?q?=E6=8E=A5=E8=AE=BE=E7=BD=AE=E7=9B=B8=E5=85=B3=E6=96=87=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- LICENCE | 2 +- config.c | 6 +++--- readme.md | 2 +- utils/buildinfo.c | 4 ++++ version.h | 6 +++--- 5 files changed, 12 insertions(+), 8 deletions(-) diff --git a/LICENCE b/LICENCE index a9b9766c..11a5280c 100644 --- a/LICENCE +++ b/LICENCE @@ -14,4 +14,4 @@ Kuzmich, Nico Williams, Viktor Dukhovni, Josh Dersch, Lars Brinkhoff, 该软件是作为 "AS IS" 提供,没有任何保证、表示或暗示,包括但不限于适销性、适用性和不侵权。在任何情况下作者不对任何声明、损坏或其他责任负责,无论是发生在合同行为、侵权或其它任何来自软件的、与软件相关或无关的以及软件的使用。 -PuTTY 中文版的版权属于 2003-2025 李峰,保留所有权利。 +PuTTY 中文版的版权属于 2003-2026 李峰,保留所有权利。 diff --git a/config.c b/config.c index d7df13f0..11c19f14 100644 --- a/config.c +++ b/config.c @@ -2513,9 +2513,9 @@ void setup_config_box(struct controlbox *b, bool midsession, conf_editbox_handler, I(CONF_loghost), ED_STR); } - s = ctrl_getset(b, "Connection", "hooks", - "Command to run at connection event"); - ctrl_editbox(s, "Command to run before connection", 'b', 100, + s = ctrl_getset(b, "连接", "hooks", + "连接事件发生时运行的命令"); + ctrl_editbox(s, "连接前运行命令(B)", 'b', 100, HELPCTX(connection_pre_hook), conf_editbox_handler, I(CONF_pre_connect_command), ED_STR); } diff --git a/readme.md b/readme.md index f072fc2d..d6542de8 100644 --- a/readme.md +++ b/readme.md @@ -2,7 +2,7 @@ PuTTY 是自由的跨平台 Telnet/SSH 客户端,同时在 Win32 和 Unix 系统下模拟 xterm 终端。其主要作者是 Simon Tatham。 -当前版本为 0.83 测试版,请访问 [PuTTY 网站](http://www.chiark.greenend.org.uk/~sgtatham/putty/)获得更多信息。如果发现英文版本有更新,[请及时通知](https://github.com/larryli/PuTTY/issues/new)。 +当前版本为 0.84 测试版,请访问 [PuTTY 网站](http://www.chiark.greenend.org.uk/~sgtatham/putty/)获得更多信息。如果发现英文版本有更新,[请及时通知](https://github.com/larryli/PuTTY/issues/new)。 ## MIT 许可证 diff --git a/utils/buildinfo.c b/utils/buildinfo.c index bb546733..d5a8a1e8 100644 --- a/utils/buildinfo.c +++ b/utils/buildinfo.c @@ -44,6 +44,10 @@ char *buildinfo(const char *newline) * cases, two different compiler versions have the same _MSC_VER * value, and have to be distinguished by _MSC_FULL_VER. */ +#elif _MSC_VER == 1951 + put_fmt(buf, " 2026 (18.1)"); +#elif _MSC_VER == 1950 + put_fmt(buf, " 2026 (18.0)"); #elif _MSC_VER == 1944 put_fmt(buf, " 2022 (17.14)"); #elif _MSC_VER == 1943 diff --git a/version.h b/version.h index ad94b41c..d6f8cdab 100644 --- a/version.h +++ b/version.h @@ -8,6 +8,6 @@ * default stuff used for local development runs of 'make'. */ -#define TEXTVER "发布版 0.83-cn1" -#define SSHVER "-Release-0-83-CN1" -#define BINARY_VERSION 0,83,0,1 +#define TEXTVER "发布版 0.84-cn1" +#define SSHVER "-Release-0-84-CN1" +#define BINARY_VERSION 0,84,0,1