putty/unix/gtkwin.c

5337 строки
169 KiB
C
Исходник Обычный вид История

/*
* gtkwin.c: the main code that runs a PuTTY terminal emulator and
* backend in a GTK window.
*/
#define _GNU_SOURCE
#include <string.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <stdio.h>
#include <time.h>
#include <errno.h>
#include <locale.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <gtk/gtk.h>
#if !GTK_CHECK_VERSION(3,0,0)
#include <gdk/gdkkeysyms.h>
#endif
#if GTK_CHECK_VERSION(2,0,0)
#include <gtk/gtkimmodule.h>
#endif
#define PUTTY_DO_GLOBALS /* actually _define_ globals */
#define MAY_REFER_TO_GTK_IN_HEADERS
#include "putty.h"
#include "terminal.h"
#include "gtkcompat.h"
#include "gtkfont.h"
#include "gtkmisc.h"
#ifndef NOT_X_WINDOWS
#include <gdk/gdkx.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#endif
#include "x11misc.h"
/* Colours come in two flavours: configurable, and xterm-extended. */
#define NEXTCOLOURS 240 /* 216 colour-cube plus 24 shades of grey */
#define NALLCOLOURS (NCFGCOLOURS + NEXTCOLOURS)
GdkAtom compound_text_atom, utf8_string_atom;
GdkAtom clipboard_atom
#if GTK_CHECK_VERSION(2,0,0) /* GTK1 will have to fill this in at startup */
= GDK_SELECTION_CLIPBOARD
#endif
;
#ifdef JUST_USE_GTK_CLIPBOARD_UTF8
/*
* Because calling gtk_clipboard_set_with_data triggers a call to the
* clipboard_clear function from the last time, we need to arrange a
* way to distinguish a real call to clipboard_clear for the _new_
* instance of the clipboard data from the leftover call for the
* outgoing one. We do this by setting the user data field in our
* gtk_clipboard_set_with_data() call, instead of the obvious pointer
* to 'inst', to one of these.
*/
struct clipboard_data_instance {
char *pasteout_data_utf8;
int pasteout_data_utf8_len;
struct clipboard_state *state;
struct clipboard_data_instance *next, *prev;
};
#endif
Initial support for clipboard on OS X. Rather than trying to get my existing hugely complicated X-style clipboard code to somehow work with the Quartz GTK back end, I've written an entirely new and much simpler alternative clipboard handler usnig the higher-leve GtkClipboard interface. It assumes all clipboard text can be converted to and from UTF-8 sensibly (which isn't a good assumption on all front ends, but on OS X I think it's reasonable), and it talks to GDK_SELECTION_CLIPBOARD rather than PRIMARY, which is the only clipboard OS X has. I had to do a fiddly thing to cope with the fact that each call to gtk_clipboard_set_with_data caused a call to the clipboard clear function left over from the previous set of data, so I had to avoid mistaking that for a clipboard-clear for the _new_ data and immediately deselecting it. I did that by allocating a distinct placeholder object in memory for each instance of the copy operation, so that I can tell whether a clipboard-clear is for the current copy or a previous one. This is only very basic support which demonstrates successful copying and pasting is at least possible. For a sensible OS X implementation we'll need a more believable means of generating a paste UI action (it's quite easy to find a Mac on which neither Shift-Ins nor the third mouse button even exists!). Also, after the trouble I had with the clipboard-clear event, it's a bit annoying to find that it _doesn't_ seem to get called when another application becomes the clipboard owner. That may just be something we have to put up with, if I can't find any reason why it's failing.
2015-09-02 23:37:33 +03:00
struct clipboard_state {
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst;
int clipboard;
GdkAtom atom;
#ifdef JUST_USE_GTK_CLIPBOARD_UTF8
GtkClipboard *gtkclipboard;
struct clipboard_data_instance *current_cdi;
#else
char *pasteout_data, *pasteout_data_ctext, *pasteout_data_utf8;
int pasteout_data_len, pasteout_data_ctext_len, pasteout_data_utf8_len;
#endif
};
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
struct GtkFrontend {
GtkWidget *window, *area, *sbar;
gboolean sbar_visible;
Stop using the GTK "configure-event" signal. I've been using that signal since the very first commit of this source file, as a combined way to be notified when the size of the drawing area changes (typically due to user window resizing actions) and also when the drawing area is first created and available to be drawn on. Unfortunately, testing on Ubuntu 18.04, I ran into an oddity, in which the call to gtk_widget_show(inst->window) in new_session_window() has the side effect of delivering a spurious configure_event on the drawing area with size 1x46 pixels. This causes the terminal to resize itself to 1 column wide, and the mistake isn't rectified until a followup configure-event arrives after new_session_window returns to the GTK main loop. But that means terminal output can occur between those two configure events (the connection-sharing "Reusing a shared connection to host.name" is a good example), and when it does, it gets embarrassingly wrapped at one character per line down the left column. I briefly tried to bodge around this by trying to heuristically guess which configure events were real and which were spurious, but I have no faith in that strategy continuing to work. I think a better approach is to abandon configure-event completely, and move to a system in which the two purposes I was using it for are handled by two _different_ GTK signals, namely "size-allocate" (for knowing when we get resized) and "realize" (for knowing when the drawing area physically exists for us to start setting up Cairo or GDK machinery). The result seems to have fixed the silly one-column wrapping bug, and retained the ability to handle window resizes, on every GTK version I have conveniently available to test on, including GTK 3 both before and after these spurious configures started to happen.
2018-05-10 22:22:02 +03:00
gboolean drawing_area_got_size, drawing_area_realised;
gboolean drawing_area_setup_needed;
GtkBox *hbox;
GtkAdjustment *sbar_adjust;
GtkWidget *menu, *specialsmenu, *specialsitem1, *specialsitem2,
*restartitem;
GtkWidget *sessionsmenu;
Basic support for running under GDK Wayland back end. GTK 3 PuTTY/pterm has always assumed that if it was compiled with _support_ for talking to the raw X11 layer underneath GTK and GDK, then it was entitled to expect that raw X11 layer to exist at all times, i.e. that GDK_DISPLAY_XDISPLAY would return a meaningful X display that it could do useful things with. So if you ran it over the GDK Wayland backend, it would immediately segfault. Modern GTK applications need to cope with multiple GDK backends at run time. It's fine for GTK PuTTY to _contain_ the code to find and use underlying X11 primitives like the display and the X window id, but it should be prepared to find that it's running on Wayland (or something else again!) so those functions don't return anything useful - in which case it should degrade gracefully to the subset of functionality that can be accessed through backend-independent GTK calls. Accordingly, I've centralised the use of GDK_DISPLAY_XDISPLAY into a support function get_x_display() in gtkmisc.c, which starts by checking that there actually is one first. All previous direct uses of GDK_*_XDISPLAY now go via that function, and check the result for NULL afterwards. (To save faffing about calling that function too many times, I'm also caching the display pointer in more places, and passing it as an extra argument to various subfunctions, mostly in gtkfont.c.) Similarly, the get_windowid() function that retrieves the window id to put in the environment of pterm's child process has to be prepared for there not to be a window id. This isn't a complete fix for all Wayland-related problems. The other one I'm currently aware of is that the default font is "server:fixed", which is a bad default now that it won't be available on all backends. And I expect that further problems will show up with more testing. But it's a start.
2018-05-09 11:18:20 +03:00
#ifndef NOT_X_WINDOWS
Display *disp;
#endif
#ifndef NO_BACKING_PIXMAPS
Use a Cairo image surface as a client-side cache. In any DRAWTYPE_CAIRO mode, we now do all our Cairo drawing to a Cairo image surface which lives on the client; then we either blit directly from that to the window (if we're in GTK3 mode, or GTK2 without deprecated pieces of API), or else we blit from the Cairo surface to the server-side pixmap and then from there to the actual window. In DRAWTYPE_GDK mode, nothing much has changed: we still draw directly to the server-side pixmap using the GDK drawing API, then blit from there to the window. But there is one change, namely that the blit is no longer done proactively - instead, we queue a redraw of the affected rectangle, and wait until we're called back by the expose handler. The main aim of all this is to arrange that the only time we ever draw to the real window is in response to expose/draw events. The experimental GTK3 OS X port stopped working a week or two ago (I presume in response to an OS update) with the symptoms that attempts to draw on the window outside the context of a "draw" event handler just didn't seem to work any more; this change fixes it. In addition to that benefit, this change also has obvious performance advantages in principle. No more expensive text rendering in response to an expose event - just re-copy to the window from the bitmap we already have, from wherever it's stored that's nearest. Moreover, this seems to have fixed the significant performance problem with X server-side fonts under GTK. I didn't expect _that_! I'd guessed that the approach of downloading character bitmaps and rendering them manually via Cairo was just inherently slow for some reason. I've no real idea _why_ this change improves matters so much; my best guess is that perhaps there's an overhead in each drawing operation to a GDK Cairo surface, so we win by doing lots of operations to a much faster image surface and then batching them up into one GDK Cairo operation. But whyever it is, I'm certainly not complaining! (In fact, it now seems to be noticeably _faster_, at least on my usual local X displays, to draw server-side fonts using that technique than using the old GDK approach. I may yet decide to switch over...)
2015-09-24 16:08:25 +03:00
/*
* Server-side pixmap which we use to cache the terminal window's
* contents. When we draw text in the terminal, we draw it to this
* pixmap first, and then blit from there to the actual window;
* this way, X expose events can be handled with an absolute
* minimum of network traffic, by just sending a command to
* re-blit an appropriate rectangle from this pixmap.
*/
GdkPixmap *pixmap;
#endif
Use a Cairo image surface as a client-side cache. In any DRAWTYPE_CAIRO mode, we now do all our Cairo drawing to a Cairo image surface which lives on the client; then we either blit directly from that to the window (if we're in GTK3 mode, or GTK2 without deprecated pieces of API), or else we blit from the Cairo surface to the server-side pixmap and then from there to the actual window. In DRAWTYPE_GDK mode, nothing much has changed: we still draw directly to the server-side pixmap using the GDK drawing API, then blit from there to the window. But there is one change, namely that the blit is no longer done proactively - instead, we queue a redraw of the affected rectangle, and wait until we're called back by the expose handler. The main aim of all this is to arrange that the only time we ever draw to the real window is in response to expose/draw events. The experimental GTK3 OS X port stopped working a week or two ago (I presume in response to an OS update) with the symptoms that attempts to draw on the window outside the context of a "draw" event handler just didn't seem to work any more; this change fixes it. In addition to that benefit, this change also has obvious performance advantages in principle. No more expensive text rendering in response to an expose event - just re-copy to the window from the bitmap we already have, from wherever it's stored that's nearest. Moreover, this seems to have fixed the significant performance problem with X server-side fonts under GTK. I didn't expect _that_! I'd guessed that the approach of downloading character bitmaps and rendering them manually via Cairo was just inherently slow for some reason. I've no real idea _why_ this change improves matters so much; my best guess is that perhaps there's an overhead in each drawing operation to a GDK Cairo surface, so we win by doing lots of operations to a much faster image surface and then batching them up into one GDK Cairo operation. But whyever it is, I'm certainly not complaining! (In fact, it now seems to be noticeably _faster_, at least on my usual local X displays, to draw server-side fonts using that technique than using the old GDK approach. I may yet decide to switch over...)
2015-09-24 16:08:25 +03:00
#ifdef DRAW_TEXT_CAIRO
/*
* 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.
*/
cairo_surface_t *surface;
#endif
#if GTK_CHECK_VERSION(2,0,0)
GtkIMContext *imc;
#endif
unifont *fonts[4]; /* normal, bold, wide, widebold */
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
int xpos, ypos, gravity;
bool gotpos;
GdkCursor *rawcursor, *textcursor, *blankcursor, *waitcursor, *currcursor;
GdkColor cols[NALLCOLOURS];
#if !GTK_CHECK_VERSION(3,0,0)
GdkColormap *colmap;
#endif
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
bool direct_to_font;
struct clipboard_state clipstates[N_CLIPBOARDS];
#ifdef JUST_USE_GTK_CLIPBOARD_UTF8
/* Remember all clipboard_data_instance structures currently
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
* associated with this GtkFrontend, in case they're still around
* when it gets destroyed */
struct clipboard_data_instance cdi_headtail;
#endif
int clipboard_ctrlshiftins, clipboard_ctrlshiftcv;
int font_width, font_height;
GTK 3: be aware of the window's scale factor. In GTK 3.10 and above, high-DPI support is arranged by each window having a property called a 'scale factor', which translates logical pixels as seen by most of the GTK API (widget and window sizes and positions, coordinates in the "draw" event, etc) into the physical pixels on the screen. This is handled more or less transparently, except that one side effect is that your Cairo-based drawing code had better be able to cope with that scaling without getting confused. PuTTY's isn't, because we do all our serious drawing on a separate Cairo surface we made ourselves, and then blit subrectangles of that to the window during updates. This has two bad consequences. Firstly, our surface has a size derived from what GTK told us the drawing area size is, i.e. corresponding to GTK's _logical_ pixels, so when the scale factor is (say) 2, our drawing takes place at half size and then gets scaled up by the final blit in the draw event, making it look blurry and unpleasant. Secondly, those final blits seem to end up offset by half a pixel, so that a second blit over the same subrectangle doesn't _quite_ completely wipe out the previously blitted data - so there's a ghostly rectangle left behind everywhere the cursor has been. It's not that GTK doesn't _let_ you find out the scale factor; it's just that it's in an out-of-the-way piece of API that you have to call specially. So now we do: our backing surface is now created at a pixel resolution matching the screen's real pixels, and we translate GTK's scale factor into an ordinary cairo_scale() before we commence drawing. So we still end up drawing the same text at the same size - and this strategy also means that non-text elements like cursor outlines and underlining will be scaled up with the screen DPI rather than stubbornly staying one physical pixel thick - but now it's nice and sharp at full screen resolution, and the subrectangle blits in the draw event are back to affecting the exact set of pixels we expect them to. One silly consequence is that, immediately after removing the last one, I've installed a handler for the GTK "configure-event" signal! That's because the GTK 3 docs claim that that's how you get notified that your scale factor has changed at run time (e.g. if you reconfigure the scale factor of a whole monitor in the GNOME settings dialog). Actually in practice I seem to find out via the "draw" event before "configure" bothers to tell me, but now I've got a usefully idempotent function for 'check whether the scale factor has changed and sort it out if so', I don't see any harm in calling it from anywhere it _might_ be useful.
2018-05-11 09:53:05 +03:00
int width, height, scale;
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
bool ignore_sbar;
bool mouseptr_visible;
New abstraction 'Seat', to pass to backends. This is a new vtable-based abstraction which is passed to a backend in place of Frontend, and it implements only the subset of the Frontend functions needed by a backend. (Many other Frontend functions still exist, notably the wide range of things called by terminal.c providing platform-independent operations on the GUI terminal window.) The purpose of making it a vtable is that this opens up the possibility of creating a backend as an internal implementation detail of some other activity, by providing just that one backend with a custom Seat that implements the methods differently. For example, this refactoring should make it feasible to directly implement an SSH proxy type, aka the 'jump host' feature supported by OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP mode, and then expose the main channel of that as the Socket for the primary connection'. (Which of course you can already do by spawning 'plink -nc' as a separate proxy process, but this would permit it in the _same_ process without anything getting confused.) I've centralised a full set of stub methods in misc.c for the new abstraction, which allows me to get rid of several annoying stubs in the previous code. Also, while I'm here, I've moved a lot of duplicated modalfatalbox() type functions from application main program files into wincons.c / uxcons.c, which I think saves duplication overall. (A minor visible effect is that the prefixes on those console-based fatal error messages will now be more consistent between applications.)
2018-10-11 21:58:42 +03:00
BusyStatus busy_status;
int alt_keycode;
int alt_digits;
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
char *wintitle;
char *icontitle;
int master_fd, master_func_id;
Ldisc *ldisc;
Backend *backend;
Terminal *term;
LogContext *logctx;
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
bool exited;
struct unicode_data ucsdata;
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
Conf *conf;
eventlog_stuff *eventlogstuff;
guint32 input_event_time; /* Timestamp of the most recent input event. */
GtkWidget *dialogs[DIALOG_SLOT_LIMIT];
#if GTK_CHECK_VERSION(3,4,0)
gdouble cumulative_scroll;
#endif
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
/* Cached things out of conf that we refer to a lot */
int bold_style;
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
int window_border;
int cursor_type;
Refactor the GTK drawing system to do both GDK and Cairo. We're going to have to use Cairo in the GTK3 port, because that's all GTK3 supports; but we still need old-style GDK for GTK1 support, and also for performance reasons in GTK2 (see below). Hence, this change completely restructures GTK PuTTY's drawing code so that there's a central 'drawing context' structure which contains a type code indicating GDK or Cairo, and then either some GDK gubbins or some Cairo gubbins as appropriate; all actual drawing is abstracted through a set of routines which test the type code in that structure and do one thing or another. And because the type code is tested at run time, both sets of drawing primitives can be compiled in at once, and where possible, they will be. X server-side bitmap fonts are still supported in the Cairo world, but because Cairo drawing is entirely client-side, they have to work by cheekily downloading each glyph bitmap from the server when it's first needed, and building up a client-side cache of 'cairo_surface_t's containing the bitmaps with which we then draw on the window. This technique works, but it's rather slow; hence, even in GTK2, we keep the GDK drawing back end compiled in, and switch over to it when the main selected font is a bitmap one. One visible effect of the new Cairo routines is in the double-width and double-height text you can get by sending ESC # 3, ESC # 4 and ESC # 6 escape sequences. In GDK, that's always been done by a really horrible process of manually scaling the bitmap, server-side, column by column and row by row, causing each pixel to be exactly doubled or quadrupled. But in Cairo, we can just set a transformation matrix, and then that takes effect _before_ the scalable fonts are rendered - so the results are visibly nicer, and use all the available resolution. (Sadly, if you're using a server-side bitmap font as your primary one, then the GDK backend will be selected for all drawing in the terminal as a whole - so in that situation, even fallback characters absent from the primary font and rendered by Pango will get the old GDK scaling treatment. It's only if your main font is scalable, so that the Cairo backend is selected, that DW/DH characters will come out looking nice.)
2015-08-15 23:05:56 +03:00
int drawtype;
int meta_mod_mask;
#ifdef OSX_META_KEY_CONFIG
int system_mod_mask;
#endif
bool send_raw_mouse;
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
unifont_drawctx uctx;
Refactor the LogContext type. LogContext is now the owner of the logevent() function that back ends and so forth are constantly calling. Previously, logevent was owned by the Frontend, which would store the message into its list for the GUI Event Log dialog (or print it to standard error, or whatever) and then pass it _back_ to LogContext to write to the currently open log file. Now it's the other way round: LogContext gets the message from the back end first, writes it to its log file if it feels so inclined, and communicates it back to the front end. This means that lots of parts of the back end system no longer need to have a pointer to a full-on Frontend; the only thing they needed it for was logging, so now they just have a LogContext (which many of them had to have anyway, e.g. for logging SSH packets or session traffic). LogContext itself also doesn't get a full Frontend pointer any more: it now talks back to the front end via a little vtable of its own called LogPolicy, which contains the method that passes Event Log entries through, the old askappend() function that decides whether to truncate a pre-existing log file, and an emergency function for printing an especially prominent message if the log file can't be created. One minor nice effect of this is that console and GUI apps can implement that last function subtly differently, so that Unix console apps can write it with a plain \n instead of the \r\n (harmless but inelegant) that the old centralised implementation generated. One other consequence of this is that the LogContext has to be provided to backend_init() so that it's available to backends from the instant of creation, rather than being provided via a separate API call a couple of function calls later, because backends have typically started doing things that need logging (like making network connections) before the call to backend_provide_logctx. Fortunately, there's no case in the whole code base where we don't already have logctx by the time we make a backend (so I don't actually remember why I ever delayed providing one). So that shortens the backend API by one function, which is always nice. While I'm tidying up, I've also moved the printf-style logeventf() and the handy logevent_and_free() into logging.c, instead of having copies of them scattered around other places. This has also let me remove some stub functions from a couple of outlying applications like Pageant. Finally, I've removed the pointless "_tag" at the end of LogContext's official struct name.
2018-10-10 21:26:18 +03:00
New abstraction 'Seat', to pass to backends. This is a new vtable-based abstraction which is passed to a backend in place of Frontend, and it implements only the subset of the Frontend functions needed by a backend. (Many other Frontend functions still exist, notably the wide range of things called by terminal.c providing platform-independent operations on the GUI terminal window.) The purpose of making it a vtable is that this opens up the possibility of creating a backend as an internal implementation detail of some other activity, by providing just that one backend with a custom Seat that implements the methods differently. For example, this refactoring should make it feasible to directly implement an SSH proxy type, aka the 'jump host' feature supported by OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP mode, and then expose the main channel of that as the Socket for the primary connection'. (Which of course you can already do by spawning 'plink -nc' as a separate proxy process, but this would permit it in the _same_ process without anything getting confused.) I've centralised a full set of stub methods in misc.c for the new abstraction, which allows me to get rid of several annoying stubs in the previous code. Also, while I'm here, I've moved a lot of duplicated modalfatalbox() type functions from application main program files into wincons.c / uxcons.c, which I think saves duplication overall. (A minor visible effect is that the prefixes on those console-based fatal error messages will now be more consistent between applications.)
2018-10-11 21:58:42 +03:00
Seat seat;
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
TermWin termwin;
Refactor the LogContext type. LogContext is now the owner of the logevent() function that back ends and so forth are constantly calling. Previously, logevent was owned by the Frontend, which would store the message into its list for the GUI Event Log dialog (or print it to standard error, or whatever) and then pass it _back_ to LogContext to write to the currently open log file. Now it's the other way round: LogContext gets the message from the back end first, writes it to its log file if it feels so inclined, and communicates it back to the front end. This means that lots of parts of the back end system no longer need to have a pointer to a full-on Frontend; the only thing they needed it for was logging, so now they just have a LogContext (which many of them had to have anyway, e.g. for logging SSH packets or session traffic). LogContext itself also doesn't get a full Frontend pointer any more: it now talks back to the front end via a little vtable of its own called LogPolicy, which contains the method that passes Event Log entries through, the old askappend() function that decides whether to truncate a pre-existing log file, and an emergency function for printing an especially prominent message if the log file can't be created. One minor nice effect of this is that console and GUI apps can implement that last function subtly differently, so that Unix console apps can write it with a plain \n instead of the \r\n (harmless but inelegant) that the old centralised implementation generated. One other consequence of this is that the LogContext has to be provided to backend_init() so that it's available to backends from the instant of creation, rather than being provided via a separate API call a couple of function calls later, because backends have typically started doing things that need logging (like making network connections) before the call to backend_provide_logctx. Fortunately, there's no case in the whole code base where we don't already have logctx by the time we make a backend (so I don't actually remember why I ever delayed providing one). So that shortens the backend API by one function, which is always nice. While I'm tidying up, I've also moved the printf-style logeventf() and the handy logevent_and_free() into logging.c, instead of having copies of them scattered around other places. This has also let me remove some stub functions from a couple of outlying applications like Pageant. Finally, I've removed the pointless "_tag" at the end of LogContext's official struct name.
2018-10-10 21:26:18 +03:00
LogPolicy logpolicy;
};
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
static void cache_conf_values(GtkFrontend *inst)
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
{
inst->bold_style = conf_get_int(inst->conf, CONF_bold_style);
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
inst->window_border = conf_get_int(inst->conf, CONF_window_border);
inst->cursor_type = conf_get_int(inst->conf, CONF_cursor_type);
#ifdef OSX_META_KEY_CONFIG
inst->meta_mod_mask = 0;
if (conf_get_bool(inst->conf, CONF_osx_option_meta))
inst->meta_mod_mask |= GDK_MOD1_MASK;
if (conf_get_bool(inst->conf, CONF_osx_command_meta))
inst->meta_mod_mask |= GDK_MOD2_MASK;
inst->system_mod_mask = GDK_MOD2_MASK & ~inst->meta_mod_mask;
#else
inst->meta_mod_mask = GDK_MOD1_MASK;
#endif
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
}
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
static void start_backend(GtkFrontend *inst);
static void exit_callback(void *vinst);
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
static void destroy_inst_connection(GtkFrontend *inst);
static void delete_inst(GtkFrontend *inst);
static void post_fatal_message_box_toplevel(void *vctx)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = (GtkFrontend *)vctx;
gtk_widget_destroy(inst->window);
}
static void post_fatal_message_box(void *vctx, int result)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = (GtkFrontend *)vctx;
New abstraction 'Seat', to pass to backends. This is a new vtable-based abstraction which is passed to a backend in place of Frontend, and it implements only the subset of the Frontend functions needed by a backend. (Many other Frontend functions still exist, notably the wide range of things called by terminal.c providing platform-independent operations on the GUI terminal window.) The purpose of making it a vtable is that this opens up the possibility of creating a backend as an internal implementation detail of some other activity, by providing just that one backend with a custom Seat that implements the methods differently. For example, this refactoring should make it feasible to directly implement an SSH proxy type, aka the 'jump host' feature supported by OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP mode, and then expose the main channel of that as the Socket for the primary connection'. (Which of course you can already do by spawning 'plink -nc' as a separate proxy process, but this would permit it in the _same_ process without anything getting confused.) I've centralised a full set of stub methods in misc.c for the new abstraction, which allows me to get rid of several annoying stubs in the previous code. Also, while I'm here, I've moved a lot of duplicated modalfatalbox() type functions from application main program files into wincons.c / uxcons.c, which I think saves duplication overall. (A minor visible effect is that the prefixes on those console-based fatal error messages will now be more consistent between applications.)
2018-10-11 21:58:42 +03:00
unregister_dialog(&inst->seat, DIALOG_SLOT_CONNECTION_FATAL);
queue_toplevel_callback(post_fatal_message_box_toplevel, inst);
}
static void common_connfatal_message_box(
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst, const char *msg, post_dialog_fn_t postfn)
{
char *title = dupcat(appname, " Fatal Error", NULL);
GtkWidget *dialog = create_message_box(
inst->window, title, msg,
string_width("REASONABLY LONG LINE OF TEXT FOR BASIC SANITY"),
false, &buttons_ok, postfn, inst);
New abstraction 'Seat', to pass to backends. This is a new vtable-based abstraction which is passed to a backend in place of Frontend, and it implements only the subset of the Frontend functions needed by a backend. (Many other Frontend functions still exist, notably the wide range of things called by terminal.c providing platform-independent operations on the GUI terminal window.) The purpose of making it a vtable is that this opens up the possibility of creating a backend as an internal implementation detail of some other activity, by providing just that one backend with a custom Seat that implements the methods differently. For example, this refactoring should make it feasible to directly implement an SSH proxy type, aka the 'jump host' feature supported by OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP mode, and then expose the main channel of that as the Socket for the primary connection'. (Which of course you can already do by spawning 'plink -nc' as a separate proxy process, but this would permit it in the _same_ process without anything getting confused.) I've centralised a full set of stub methods in misc.c for the new abstraction, which allows me to get rid of several annoying stubs in the previous code. Also, while I'm here, I've moved a lot of duplicated modalfatalbox() type functions from application main program files into wincons.c / uxcons.c, which I think saves duplication overall. (A minor visible effect is that the prefixes on those console-based fatal error messages will now be more consistent between applications.)
2018-10-11 21:58:42 +03:00
register_dialog(&inst->seat, DIALOG_SLOT_CONNECTION_FATAL, dialog);
sfree(title);
}
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
void fatal_message_box(GtkFrontend *inst, const char *msg)
{
common_connfatal_message_box(inst, msg, post_fatal_message_box);
}
static void connection_fatal_callback(void *vctx)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = (GtkFrontend *)vctx;
destroy_inst_connection(inst);
}
static void post_nonfatal_message_box(void *vctx, int result)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = (GtkFrontend *)vctx;
New abstraction 'Seat', to pass to backends. This is a new vtable-based abstraction which is passed to a backend in place of Frontend, and it implements only the subset of the Frontend functions needed by a backend. (Many other Frontend functions still exist, notably the wide range of things called by terminal.c providing platform-independent operations on the GUI terminal window.) The purpose of making it a vtable is that this opens up the possibility of creating a backend as an internal implementation detail of some other activity, by providing just that one backend with a custom Seat that implements the methods differently. For example, this refactoring should make it feasible to directly implement an SSH proxy type, aka the 'jump host' feature supported by OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP mode, and then expose the main channel of that as the Socket for the primary connection'. (Which of course you can already do by spawning 'plink -nc' as a separate proxy process, but this would permit it in the _same_ process without anything getting confused.) I've centralised a full set of stub methods in misc.c for the new abstraction, which allows me to get rid of several annoying stubs in the previous code. Also, while I'm here, I've moved a lot of duplicated modalfatalbox() type functions from application main program files into wincons.c / uxcons.c, which I think saves duplication overall. (A minor visible effect is that the prefixes on those console-based fatal error messages will now be more consistent between applications.)
2018-10-11 21:58:42 +03:00
unregister_dialog(&inst->seat, DIALOG_SLOT_CONNECTION_FATAL);
}
New abstraction 'Seat', to pass to backends. This is a new vtable-based abstraction which is passed to a backend in place of Frontend, and it implements only the subset of the Frontend functions needed by a backend. (Many other Frontend functions still exist, notably the wide range of things called by terminal.c providing platform-independent operations on the GUI terminal window.) The purpose of making it a vtable is that this opens up the possibility of creating a backend as an internal implementation detail of some other activity, by providing just that one backend with a custom Seat that implements the methods differently. For example, this refactoring should make it feasible to directly implement an SSH proxy type, aka the 'jump host' feature supported by OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP mode, and then expose the main channel of that as the Socket for the primary connection'. (Which of course you can already do by spawning 'plink -nc' as a separate proxy process, but this would permit it in the _same_ process without anything getting confused.) I've centralised a full set of stub methods in misc.c for the new abstraction, which allows me to get rid of several annoying stubs in the previous code. Also, while I'm here, I've moved a lot of duplicated modalfatalbox() type functions from application main program files into wincons.c / uxcons.c, which I think saves duplication overall. (A minor visible effect is that the prefixes on those console-based fatal error messages will now be more consistent between applications.)
2018-10-11 21:58:42 +03:00
static void gtk_seat_connection_fatal(Seat *seat, const char *msg)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = container_of(seat, GtkFrontend, seat);
if (conf_get_int(inst->conf, CONF_close_on_exit) == FORCE_ON) {
fatal_message_box(inst, msg);
} else {
common_connfatal_message_box(inst, msg, post_nonfatal_message_box);
}
inst->exited = true; /* suppress normal exit handling */
queue_toplevel_callback(connection_fatal_callback, inst);
}
/*
* Default settings that are specific to pterm.
*/
FontSpec *platform_default_fontspec(const char *name)
{
if (!strcmp(name, "Font"))
return fontspec_new(DEFAULT_GTK_FONT);
else
return fontspec_new("");
}
Filename *platform_default_filename(const char *name)
{
if (!strcmp(name, "LogFileName"))
return filename_from_str("putty.log");
else
return filename_from_str("");
}
char *platform_default_s(const char *name)
{
if (!strcmp(name, "SerialLine"))
return dupstr("/dev/ttyS0");
return NULL;
}
bool platform_default_b(const char *name, bool def)
{
if (!strcmp(name, "WinNameAlways")) {
/* X natively supports icon titles, so use 'em by default */
return false;
}
return def;
}
int platform_default_i(const char *name, int def)
{
if (!strcmp(name, "CloseOnExit"))
return 2; /* maps to FORCE_ON after painful rearrangement :-( */
return def;
}
New abstraction 'Seat', to pass to backends. This is a new vtable-based abstraction which is passed to a backend in place of Frontend, and it implements only the subset of the Frontend functions needed by a backend. (Many other Frontend functions still exist, notably the wide range of things called by terminal.c providing platform-independent operations on the GUI terminal window.) The purpose of making it a vtable is that this opens up the possibility of creating a backend as an internal implementation detail of some other activity, by providing just that one backend with a custom Seat that implements the methods differently. For example, this refactoring should make it feasible to directly implement an SSH proxy type, aka the 'jump host' feature supported by OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP mode, and then expose the main channel of that as the Socket for the primary connection'. (Which of course you can already do by spawning 'plink -nc' as a separate proxy process, but this would permit it in the _same_ process without anything getting confused.) I've centralised a full set of stub methods in misc.c for the new abstraction, which allows me to get rid of several annoying stubs in the previous code. Also, while I'm here, I've moved a lot of duplicated modalfatalbox() type functions from application main program files into wincons.c / uxcons.c, which I think saves duplication overall. (A minor visible effect is that the prefixes on those console-based fatal error messages will now be more consistent between applications.)
2018-10-11 21:58:42 +03:00
static char *gtk_seat_get_ttymode(Seat *seat, const char *mode)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = container_of(seat, GtkFrontend, seat);
return term_get_ttymode(inst->term, mode);
}
static size_t gtk_seat_output(Seat *seat, bool is_stderr,
const void *data, size_t len)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = container_of(seat, GtkFrontend, seat);
return term_data(inst->term, is_stderr, data, len);
}
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
static bool gtk_seat_eof(Seat *seat)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
/* GtkFrontend *inst = container_of(seat, GtkFrontend, seat); */
return true; /* do respond to incoming EOF with outgoing */
}
New abstraction 'Seat', to pass to backends. This is a new vtable-based abstraction which is passed to a backend in place of Frontend, and it implements only the subset of the Frontend functions needed by a backend. (Many other Frontend functions still exist, notably the wide range of things called by terminal.c providing platform-independent operations on the GUI terminal window.) The purpose of making it a vtable is that this opens up the possibility of creating a backend as an internal implementation detail of some other activity, by providing just that one backend with a custom Seat that implements the methods differently. For example, this refactoring should make it feasible to directly implement an SSH proxy type, aka the 'jump host' feature supported by OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP mode, and then expose the main channel of that as the Socket for the primary connection'. (Which of course you can already do by spawning 'plink -nc' as a separate proxy process, but this would permit it in the _same_ process without anything getting confused.) I've centralised a full set of stub methods in misc.c for the new abstraction, which allows me to get rid of several annoying stubs in the previous code. Also, while I'm here, I've moved a lot of duplicated modalfatalbox() type functions from application main program files into wincons.c / uxcons.c, which I think saves duplication overall. (A minor visible effect is that the prefixes on those console-based fatal error messages will now be more consistent between applications.)
2018-10-11 21:58:42 +03:00
static int gtk_seat_get_userpass_input(Seat *seat, prompts_t *p,
bufchain *input)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = container_of(seat, GtkFrontend, seat);
int ret;
ret = cmdline_get_passwd_input(p);
if (ret == -1)
ret = term_get_userpass_input(inst->term, p, input);
return ret;
}
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
static bool gtk_seat_is_utf8(Seat *seat)
New abstraction 'Seat', to pass to backends. This is a new vtable-based abstraction which is passed to a backend in place of Frontend, and it implements only the subset of the Frontend functions needed by a backend. (Many other Frontend functions still exist, notably the wide range of things called by terminal.c providing platform-independent operations on the GUI terminal window.) The purpose of making it a vtable is that this opens up the possibility of creating a backend as an internal implementation detail of some other activity, by providing just that one backend with a custom Seat that implements the methods differently. For example, this refactoring should make it feasible to directly implement an SSH proxy type, aka the 'jump host' feature supported by OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP mode, and then expose the main channel of that as the Socket for the primary connection'. (Which of course you can already do by spawning 'plink -nc' as a separate proxy process, but this would permit it in the _same_ process without anything getting confused.) I've centralised a full set of stub methods in misc.c for the new abstraction, which allows me to get rid of several annoying stubs in the previous code. Also, while I'm here, I've moved a lot of duplicated modalfatalbox() type functions from application main program files into wincons.c / uxcons.c, which I think saves duplication overall. (A minor visible effect is that the prefixes on those console-based fatal error messages will now be more consistent between applications.)
2018-10-11 21:58:42 +03:00
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = container_of(seat, GtkFrontend, seat);
return win_is_utf8(&inst->termwin);
New abstraction 'Seat', to pass to backends. This is a new vtable-based abstraction which is passed to a backend in place of Frontend, and it implements only the subset of the Frontend functions needed by a backend. (Many other Frontend functions still exist, notably the wide range of things called by terminal.c providing platform-independent operations on the GUI terminal window.) The purpose of making it a vtable is that this opens up the possibility of creating a backend as an internal implementation detail of some other activity, by providing just that one backend with a custom Seat that implements the methods differently. For example, this refactoring should make it feasible to directly implement an SSH proxy type, aka the 'jump host' feature supported by OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP mode, and then expose the main channel of that as the Socket for the primary connection'. (Which of course you can already do by spawning 'plink -nc' as a separate proxy process, but this would permit it in the _same_ process without anything getting confused.) I've centralised a full set of stub methods in misc.c for the new abstraction, which allows me to get rid of several annoying stubs in the previous code. Also, while I'm here, I've moved a lot of duplicated modalfatalbox() type functions from application main program files into wincons.c / uxcons.c, which I think saves duplication overall. (A minor visible effect is that the prefixes on those console-based fatal error messages will now be more consistent between applications.)
2018-10-11 21:58:42 +03:00
}
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
static bool gtk_seat_get_window_pixel_size(Seat *seat, int *w, int *h)
New abstraction 'Seat', to pass to backends. This is a new vtable-based abstraction which is passed to a backend in place of Frontend, and it implements only the subset of the Frontend functions needed by a backend. (Many other Frontend functions still exist, notably the wide range of things called by terminal.c providing platform-independent operations on the GUI terminal window.) The purpose of making it a vtable is that this opens up the possibility of creating a backend as an internal implementation detail of some other activity, by providing just that one backend with a custom Seat that implements the methods differently. For example, this refactoring should make it feasible to directly implement an SSH proxy type, aka the 'jump host' feature supported by OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP mode, and then expose the main channel of that as the Socket for the primary connection'. (Which of course you can already do by spawning 'plink -nc' as a separate proxy process, but this would permit it in the _same_ process without anything getting confused.) I've centralised a full set of stub methods in misc.c for the new abstraction, which allows me to get rid of several annoying stubs in the previous code. Also, while I'm here, I've moved a lot of duplicated modalfatalbox() type functions from application main program files into wincons.c / uxcons.c, which I think saves duplication overall. (A minor visible effect is that the prefixes on those console-based fatal error messages will now be more consistent between applications.)
2018-10-11 21:58:42 +03:00
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = container_of(seat, GtkFrontend, seat);
win_get_pixels(&inst->termwin, w, h);
return true;
New abstraction 'Seat', to pass to backends. This is a new vtable-based abstraction which is passed to a backend in place of Frontend, and it implements only the subset of the Frontend functions needed by a backend. (Many other Frontend functions still exist, notably the wide range of things called by terminal.c providing platform-independent operations on the GUI terminal window.) The purpose of making it a vtable is that this opens up the possibility of creating a backend as an internal implementation detail of some other activity, by providing just that one backend with a custom Seat that implements the methods differently. For example, this refactoring should make it feasible to directly implement an SSH proxy type, aka the 'jump host' feature supported by OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP mode, and then expose the main channel of that as the Socket for the primary connection'. (Which of course you can already do by spawning 'plink -nc' as a separate proxy process, but this would permit it in the _same_ process without anything getting confused.) I've centralised a full set of stub methods in misc.c for the new abstraction, which allows me to get rid of several annoying stubs in the previous code. Also, while I'm here, I've moved a lot of duplicated modalfatalbox() type functions from application main program files into wincons.c / uxcons.c, which I think saves duplication overall. (A minor visible effect is that the prefixes on those console-based fatal error messages will now be more consistent between applications.)
2018-10-11 21:58:42 +03:00
}
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);
static const char *gtk_seat_get_x_display(Seat *seat);
#ifndef NOT_X_WINDOWS
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
static bool gtk_seat_get_windowid(Seat *seat, long *id);
New abstraction 'Seat', to pass to backends. This is a new vtable-based abstraction which is passed to a backend in place of Frontend, and it implements only the subset of the Frontend functions needed by a backend. (Many other Frontend functions still exist, notably the wide range of things called by terminal.c providing platform-independent operations on the GUI terminal window.) The purpose of making it a vtable is that this opens up the possibility of creating a backend as an internal implementation detail of some other activity, by providing just that one backend with a custom Seat that implements the methods differently. For example, this refactoring should make it feasible to directly implement an SSH proxy type, aka the 'jump host' feature supported by OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP mode, and then expose the main channel of that as the Socket for the primary connection'. (Which of course you can already do by spawning 'plink -nc' as a separate proxy process, but this would permit it in the _same_ process without anything getting confused.) I've centralised a full set of stub methods in misc.c for the new abstraction, which allows me to get rid of several annoying stubs in the previous code. Also, while I'm here, I've moved a lot of duplicated modalfatalbox() type functions from application main program files into wincons.c / uxcons.c, which I think saves duplication overall. (A minor visible effect is that the prefixes on those console-based fatal error messages will now be more consistent between applications.)
2018-10-11 21:58:42 +03:00
#endif
static const SeatVtable gtk_seat_vt = {
gtk_seat_output,
gtk_seat_eof,
gtk_seat_get_userpass_input,
gtk_seat_notify_remote_exit,
gtk_seat_connection_fatal,
gtk_seat_update_specials_menu,
gtk_seat_get_ttymode,
gtk_seat_set_busy_status,
gtk_seat_verify_ssh_host_key,
gtk_seat_confirm_weak_crypto_primitive,
gtk_seat_confirm_weak_cached_hostkey,
gtk_seat_is_utf8,
nullseat_echoedit_update,
gtk_seat_get_x_display,
#ifdef NOT_X_WINDOWS
nullseat_get_windowid,
#else
gtk_seat_get_windowid,
#endif
gtk_seat_get_window_pixel_size,
New abstraction 'Seat', to pass to backends. This is a new vtable-based abstraction which is passed to a backend in place of Frontend, and it implements only the subset of the Frontend functions needed by a backend. (Many other Frontend functions still exist, notably the wide range of things called by terminal.c providing platform-independent operations on the GUI terminal window.) The purpose of making it a vtable is that this opens up the possibility of creating a backend as an internal implementation detail of some other activity, by providing just that one backend with a custom Seat that implements the methods differently. For example, this refactoring should make it feasible to directly implement an SSH proxy type, aka the 'jump host' feature supported by OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP mode, and then expose the main channel of that as the Socket for the primary connection'. (Which of course you can already do by spawning 'plink -nc' as a separate proxy process, but this would permit it in the _same_ process without anything getting confused.) I've centralised a full set of stub methods in misc.c for the new abstraction, which allows me to get rid of several annoying stubs in the previous code. Also, while I'm here, I've moved a lot of duplicated modalfatalbox() type functions from application main program files into wincons.c / uxcons.c, which I think saves duplication overall. (A minor visible effect is that the prefixes on those console-based fatal error messages will now be more consistent between applications.)
2018-10-11 21:58:42 +03:00
};
Refactor the LogContext type. LogContext is now the owner of the logevent() function that back ends and so forth are constantly calling. Previously, logevent was owned by the Frontend, which would store the message into its list for the GUI Event Log dialog (or print it to standard error, or whatever) and then pass it _back_ to LogContext to write to the currently open log file. Now it's the other way round: LogContext gets the message from the back end first, writes it to its log file if it feels so inclined, and communicates it back to the front end. This means that lots of parts of the back end system no longer need to have a pointer to a full-on Frontend; the only thing they needed it for was logging, so now they just have a LogContext (which many of them had to have anyway, e.g. for logging SSH packets or session traffic). LogContext itself also doesn't get a full Frontend pointer any more: it now talks back to the front end via a little vtable of its own called LogPolicy, which contains the method that passes Event Log entries through, the old askappend() function that decides whether to truncate a pre-existing log file, and an emergency function for printing an especially prominent message if the log file can't be created. One minor nice effect of this is that console and GUI apps can implement that last function subtly differently, so that Unix console apps can write it with a plain \n instead of the \r\n (harmless but inelegant) that the old centralised implementation generated. One other consequence of this is that the LogContext has to be provided to backend_init() so that it's available to backends from the instant of creation, rather than being provided via a separate API call a couple of function calls later, because backends have typically started doing things that need logging (like making network connections) before the call to backend_provide_logctx. Fortunately, there's no case in the whole code base where we don't already have logctx by the time we make a backend (so I don't actually remember why I ever delayed providing one). So that shortens the backend API by one function, which is always nice. While I'm tidying up, I've also moved the printf-style logeventf() and the handy logevent_and_free() into logging.c, instead of having copies of them scattered around other places. This has also let me remove some stub functions from a couple of outlying applications like Pageant. Finally, I've removed the pointless "_tag" at the end of LogContext's official struct name.
2018-10-10 21:26:18 +03:00
static void gtk_eventlog(LogPolicy *lp, const char *string)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = container_of(lp, GtkFrontend, logpolicy);
logevent_dlg(inst->eventlogstuff, string);
}
Refactor the LogContext type. LogContext is now the owner of the logevent() function that back ends and so forth are constantly calling. Previously, logevent was owned by the Frontend, which would store the message into its list for the GUI Event Log dialog (or print it to standard error, or whatever) and then pass it _back_ to LogContext to write to the currently open log file. Now it's the other way round: LogContext gets the message from the back end first, writes it to its log file if it feels so inclined, and communicates it back to the front end. This means that lots of parts of the back end system no longer need to have a pointer to a full-on Frontend; the only thing they needed it for was logging, so now they just have a LogContext (which many of them had to have anyway, e.g. for logging SSH packets or session traffic). LogContext itself also doesn't get a full Frontend pointer any more: it now talks back to the front end via a little vtable of its own called LogPolicy, which contains the method that passes Event Log entries through, the old askappend() function that decides whether to truncate a pre-existing log file, and an emergency function for printing an especially prominent message if the log file can't be created. One minor nice effect of this is that console and GUI apps can implement that last function subtly differently, so that Unix console apps can write it with a plain \n instead of the \r\n (harmless but inelegant) that the old centralised implementation generated. One other consequence of this is that the LogContext has to be provided to backend_init() so that it's available to backends from the instant of creation, rather than being provided via a separate API call a couple of function calls later, because backends have typically started doing things that need logging (like making network connections) before the call to backend_provide_logctx. Fortunately, there's no case in the whole code base where we don't already have logctx by the time we make a backend (so I don't actually remember why I ever delayed providing one). So that shortens the backend API by one function, which is always nice. While I'm tidying up, I've also moved the printf-style logeventf() and the handy logevent_and_free() into logging.c, instead of having copies of them scattered around other places. This has also let me remove some stub functions from a couple of outlying applications like Pageant. Finally, I've removed the pointless "_tag" at the end of LogContext's official struct name.
2018-10-10 21:26:18 +03:00
static int gtk_askappend(LogPolicy *lp, Filename *filename,
void (*callback)(void *ctx, int result), void *ctx)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = container_of(lp, GtkFrontend, logpolicy);
New abstraction 'Seat', to pass to backends. This is a new vtable-based abstraction which is passed to a backend in place of Frontend, and it implements only the subset of the Frontend functions needed by a backend. (Many other Frontend functions still exist, notably the wide range of things called by terminal.c providing platform-independent operations on the GUI terminal window.) The purpose of making it a vtable is that this opens up the possibility of creating a backend as an internal implementation detail of some other activity, by providing just that one backend with a custom Seat that implements the methods differently. For example, this refactoring should make it feasible to directly implement an SSH proxy type, aka the 'jump host' feature supported by OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP mode, and then expose the main channel of that as the Socket for the primary connection'. (Which of course you can already do by spawning 'plink -nc' as a separate proxy process, but this would permit it in the _same_ process without anything getting confused.) I've centralised a full set of stub methods in misc.c for the new abstraction, which allows me to get rid of several annoying stubs in the previous code. Also, while I'm here, I've moved a lot of duplicated modalfatalbox() type functions from application main program files into wincons.c / uxcons.c, which I think saves duplication overall. (A minor visible effect is that the prefixes on those console-based fatal error messages will now be more consistent between applications.)
2018-10-11 21:58:42 +03:00
return gtkdlg_askappend(&inst->seat, filename, callback, ctx);
Refactor the LogContext type. LogContext is now the owner of the logevent() function that back ends and so forth are constantly calling. Previously, logevent was owned by the Frontend, which would store the message into its list for the GUI Event Log dialog (or print it to standard error, or whatever) and then pass it _back_ to LogContext to write to the currently open log file. Now it's the other way round: LogContext gets the message from the back end first, writes it to its log file if it feels so inclined, and communicates it back to the front end. This means that lots of parts of the back end system no longer need to have a pointer to a full-on Frontend; the only thing they needed it for was logging, so now they just have a LogContext (which many of them had to have anyway, e.g. for logging SSH packets or session traffic). LogContext itself also doesn't get a full Frontend pointer any more: it now talks back to the front end via a little vtable of its own called LogPolicy, which contains the method that passes Event Log entries through, the old askappend() function that decides whether to truncate a pre-existing log file, and an emergency function for printing an especially prominent message if the log file can't be created. One minor nice effect of this is that console and GUI apps can implement that last function subtly differently, so that Unix console apps can write it with a plain \n instead of the \r\n (harmless but inelegant) that the old centralised implementation generated. One other consequence of this is that the LogContext has to be provided to backend_init() so that it's available to backends from the instant of creation, rather than being provided via a separate API call a couple of function calls later, because backends have typically started doing things that need logging (like making network connections) before the call to backend_provide_logctx. Fortunately, there's no case in the whole code base where we don't already have logctx by the time we make a backend (so I don't actually remember why I ever delayed providing one). So that shortens the backend API by one function, which is always nice. While I'm tidying up, I've also moved the printf-style logeventf() and the handy logevent_and_free() into logging.c, instead of having copies of them scattered around other places. This has also let me remove some stub functions from a couple of outlying applications like Pageant. Finally, I've removed the pointless "_tag" at the end of LogContext's official struct name.
2018-10-10 21:26:18 +03:00
}
static void gtk_logging_error(LogPolicy *lp, const char *event)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = container_of(lp, GtkFrontend, logpolicy);
Refactor the LogContext type. LogContext is now the owner of the logevent() function that back ends and so forth are constantly calling. Previously, logevent was owned by the Frontend, which would store the message into its list for the GUI Event Log dialog (or print it to standard error, or whatever) and then pass it _back_ to LogContext to write to the currently open log file. Now it's the other way round: LogContext gets the message from the back end first, writes it to its log file if it feels so inclined, and communicates it back to the front end. This means that lots of parts of the back end system no longer need to have a pointer to a full-on Frontend; the only thing they needed it for was logging, so now they just have a LogContext (which many of them had to have anyway, e.g. for logging SSH packets or session traffic). LogContext itself also doesn't get a full Frontend pointer any more: it now talks back to the front end via a little vtable of its own called LogPolicy, which contains the method that passes Event Log entries through, the old askappend() function that decides whether to truncate a pre-existing log file, and an emergency function for printing an especially prominent message if the log file can't be created. One minor nice effect of this is that console and GUI apps can implement that last function subtly differently, so that Unix console apps can write it with a plain \n instead of the \r\n (harmless but inelegant) that the old centralised implementation generated. One other consequence of this is that the LogContext has to be provided to backend_init() so that it's available to backends from the instant of creation, rather than being provided via a separate API call a couple of function calls later, because backends have typically started doing things that need logging (like making network connections) before the call to backend_provide_logctx. Fortunately, there's no case in the whole code base where we don't already have logctx by the time we make a backend (so I don't actually remember why I ever delayed providing one). So that shortens the backend API by one function, which is always nice. While I'm tidying up, I've also moved the printf-style logeventf() and the handy logevent_and_free() into logging.c, instead of having copies of them scattered around other places. This has also let me remove some stub functions from a couple of outlying applications like Pageant. Finally, I've removed the pointless "_tag" at the end of LogContext's official struct name.
2018-10-10 21:26:18 +03:00
/* Send 'can't open log file' errors to the terminal window.
* (Marked as stderr, although terminal.c won't care.) */
New abstraction 'Seat', to pass to backends. This is a new vtable-based abstraction which is passed to a backend in place of Frontend, and it implements only the subset of the Frontend functions needed by a backend. (Many other Frontend functions still exist, notably the wide range of things called by terminal.c providing platform-independent operations on the GUI terminal window.) The purpose of making it a vtable is that this opens up the possibility of creating a backend as an internal implementation detail of some other activity, by providing just that one backend with a custom Seat that implements the methods differently. For example, this refactoring should make it feasible to directly implement an SSH proxy type, aka the 'jump host' feature supported by OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP mode, and then expose the main channel of that as the Socket for the primary connection'. (Which of course you can already do by spawning 'plink -nc' as a separate proxy process, but this would permit it in the _same_ process without anything getting confused.) I've centralised a full set of stub methods in misc.c for the new abstraction, which allows me to get rid of several annoying stubs in the previous code. Also, while I'm here, I've moved a lot of duplicated modalfatalbox() type functions from application main program files into wincons.c / uxcons.c, which I think saves duplication overall. (A minor visible effect is that the prefixes on those console-based fatal error messages will now be more consistent between applications.)
2018-10-11 21:58:42 +03:00
seat_stderr(&inst->seat, event, strlen(event));
seat_stderr(&inst->seat, "\r\n", 2);
Refactor the LogContext type. LogContext is now the owner of the logevent() function that back ends and so forth are constantly calling. Previously, logevent was owned by the Frontend, which would store the message into its list for the GUI Event Log dialog (or print it to standard error, or whatever) and then pass it _back_ to LogContext to write to the currently open log file. Now it's the other way round: LogContext gets the message from the back end first, writes it to its log file if it feels so inclined, and communicates it back to the front end. This means that lots of parts of the back end system no longer need to have a pointer to a full-on Frontend; the only thing they needed it for was logging, so now they just have a LogContext (which many of them had to have anyway, e.g. for logging SSH packets or session traffic). LogContext itself also doesn't get a full Frontend pointer any more: it now talks back to the front end via a little vtable of its own called LogPolicy, which contains the method that passes Event Log entries through, the old askappend() function that decides whether to truncate a pre-existing log file, and an emergency function for printing an especially prominent message if the log file can't be created. One minor nice effect of this is that console and GUI apps can implement that last function subtly differently, so that Unix console apps can write it with a plain \n instead of the \r\n (harmless but inelegant) that the old centralised implementation generated. One other consequence of this is that the LogContext has to be provided to backend_init() so that it's available to backends from the instant of creation, rather than being provided via a separate API call a couple of function calls later, because backends have typically started doing things that need logging (like making network connections) before the call to backend_provide_logctx. Fortunately, there's no case in the whole code base where we don't already have logctx by the time we make a backend (so I don't actually remember why I ever delayed providing one). So that shortens the backend API by one function, which is always nice. While I'm tidying up, I've also moved the printf-style logeventf() and the handy logevent_and_free() into logging.c, instead of having copies of them scattered around other places. This has also let me remove some stub functions from a couple of outlying applications like Pageant. Finally, I've removed the pointless "_tag" at the end of LogContext's official struct name.
2018-10-10 21:26:18 +03:00
}
static const LogPolicyVtable gtk_logpolicy_vt = {
gtk_eventlog,
gtk_askappend,
gtk_logging_error,
};
/*
* Translate a raw mouse button designation (LEFT, MIDDLE, RIGHT)
* into a cooked one (SELECT, EXTEND, PASTE).
*
* In Unix, this is not configurable; the X button arrangement is
* rock-solid across all applications, everyone has a three-button
* mouse or a means of faking it, and there is no need to switch
* buttons around at all.
*/
static Mouse_Button translate_button(Mouse_Button button)
{
if (button == MBT_LEFT)
return MBT_SELECT;
if (button == MBT_MIDDLE)
return MBT_PASTE;
if (button == MBT_RIGHT)
return MBT_EXTEND;
return 0; /* shouldn't happen */
}
/*
* Return the top-level GtkWindow associated with a particular
* front end instance.
*/
New abstraction 'Seat', to pass to backends. This is a new vtable-based abstraction which is passed to a backend in place of Frontend, and it implements only the subset of the Frontend functions needed by a backend. (Many other Frontend functions still exist, notably the wide range of things called by terminal.c providing platform-independent operations on the GUI terminal window.) The purpose of making it a vtable is that this opens up the possibility of creating a backend as an internal implementation detail of some other activity, by providing just that one backend with a custom Seat that implements the methods differently. For example, this refactoring should make it feasible to directly implement an SSH proxy type, aka the 'jump host' feature supported by OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP mode, and then expose the main channel of that as the Socket for the primary connection'. (Which of course you can already do by spawning 'plink -nc' as a separate proxy process, but this would permit it in the _same_ process without anything getting confused.) I've centralised a full set of stub methods in misc.c for the new abstraction, which allows me to get rid of several annoying stubs in the previous code. Also, while I'm here, I've moved a lot of duplicated modalfatalbox() type functions from application main program files into wincons.c / uxcons.c, which I think saves duplication overall. (A minor visible effect is that the prefixes on those console-based fatal error messages will now be more consistent between applications.)
2018-10-11 21:58:42 +03:00
GtkWidget *gtk_seat_get_window(Seat *seat)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = container_of(seat, GtkFrontend, seat);
return inst->window;
}
/*
* Set and clear a pointer to a dialog box created as a result of the
* network code wanting to ask an asynchronous user question (e.g.
* 'what about this dodgy host key, then?').
*/
New abstraction 'Seat', to pass to backends. This is a new vtable-based abstraction which is passed to a backend in place of Frontend, and it implements only the subset of the Frontend functions needed by a backend. (Many other Frontend functions still exist, notably the wide range of things called by terminal.c providing platform-independent operations on the GUI terminal window.) The purpose of making it a vtable is that this opens up the possibility of creating a backend as an internal implementation detail of some other activity, by providing just that one backend with a custom Seat that implements the methods differently. For example, this refactoring should make it feasible to directly implement an SSH proxy type, aka the 'jump host' feature supported by OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP mode, and then expose the main channel of that as the Socket for the primary connection'. (Which of course you can already do by spawning 'plink -nc' as a separate proxy process, but this would permit it in the _same_ process without anything getting confused.) I've centralised a full set of stub methods in misc.c for the new abstraction, which allows me to get rid of several annoying stubs in the previous code. Also, while I'm here, I've moved a lot of duplicated modalfatalbox() type functions from application main program files into wincons.c / uxcons.c, which I think saves duplication overall. (A minor visible effect is that the prefixes on those console-based fatal error messages will now be more consistent between applications.)
2018-10-11 21:58:42 +03:00
void register_dialog(Seat *seat, enum DialogSlot slot, GtkWidget *dialog)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst;
New abstraction 'Seat', to pass to backends. This is a new vtable-based abstraction which is passed to a backend in place of Frontend, and it implements only the subset of the Frontend functions needed by a backend. (Many other Frontend functions still exist, notably the wide range of things called by terminal.c providing platform-independent operations on the GUI terminal window.) The purpose of making it a vtable is that this opens up the possibility of creating a backend as an internal implementation detail of some other activity, by providing just that one backend with a custom Seat that implements the methods differently. For example, this refactoring should make it feasible to directly implement an SSH proxy type, aka the 'jump host' feature supported by OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP mode, and then expose the main channel of that as the Socket for the primary connection'. (Which of course you can already do by spawning 'plink -nc' as a separate proxy process, but this would permit it in the _same_ process without anything getting confused.) I've centralised a full set of stub methods in misc.c for the new abstraction, which allows me to get rid of several annoying stubs in the previous code. Also, while I'm here, I've moved a lot of duplicated modalfatalbox() type functions from application main program files into wincons.c / uxcons.c, which I think saves duplication overall. (A minor visible effect is that the prefixes on those console-based fatal error messages will now be more consistent between applications.)
2018-10-11 21:58:42 +03:00
assert(seat->vt == &gtk_seat_vt);
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
inst = container_of(seat, GtkFrontend, seat);
assert(slot < DIALOG_SLOT_LIMIT);
assert(!inst->dialogs[slot]);
inst->dialogs[slot] = dialog;
}
New abstraction 'Seat', to pass to backends. This is a new vtable-based abstraction which is passed to a backend in place of Frontend, and it implements only the subset of the Frontend functions needed by a backend. (Many other Frontend functions still exist, notably the wide range of things called by terminal.c providing platform-independent operations on the GUI terminal window.) The purpose of making it a vtable is that this opens up the possibility of creating a backend as an internal implementation detail of some other activity, by providing just that one backend with a custom Seat that implements the methods differently. For example, this refactoring should make it feasible to directly implement an SSH proxy type, aka the 'jump host' feature supported by OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP mode, and then expose the main channel of that as the Socket for the primary connection'. (Which of course you can already do by spawning 'plink -nc' as a separate proxy process, but this would permit it in the _same_ process without anything getting confused.) I've centralised a full set of stub methods in misc.c for the new abstraction, which allows me to get rid of several annoying stubs in the previous code. Also, while I'm here, I've moved a lot of duplicated modalfatalbox() type functions from application main program files into wincons.c / uxcons.c, which I think saves duplication overall. (A minor visible effect is that the prefixes on those console-based fatal error messages will now be more consistent between applications.)
2018-10-11 21:58:42 +03:00
void unregister_dialog(Seat *seat, enum DialogSlot slot)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst;
New abstraction 'Seat', to pass to backends. This is a new vtable-based abstraction which is passed to a backend in place of Frontend, and it implements only the subset of the Frontend functions needed by a backend. (Many other Frontend functions still exist, notably the wide range of things called by terminal.c providing platform-independent operations on the GUI terminal window.) The purpose of making it a vtable is that this opens up the possibility of creating a backend as an internal implementation detail of some other activity, by providing just that one backend with a custom Seat that implements the methods differently. For example, this refactoring should make it feasible to directly implement an SSH proxy type, aka the 'jump host' feature supported by OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP mode, and then expose the main channel of that as the Socket for the primary connection'. (Which of course you can already do by spawning 'plink -nc' as a separate proxy process, but this would permit it in the _same_ process without anything getting confused.) I've centralised a full set of stub methods in misc.c for the new abstraction, which allows me to get rid of several annoying stubs in the previous code. Also, while I'm here, I've moved a lot of duplicated modalfatalbox() type functions from application main program files into wincons.c / uxcons.c, which I think saves duplication overall. (A minor visible effect is that the prefixes on those console-based fatal error messages will now be more consistent between applications.)
2018-10-11 21:58:42 +03:00
assert(seat->vt == &gtk_seat_vt);
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
inst = container_of(seat, GtkFrontend, seat);
assert(slot < DIALOG_SLOT_LIMIT);
assert(inst->dialogs[slot]);
inst->dialogs[slot] = NULL;
}
/*
* Minimise or restore the window in response to a server-side
* request.
*/
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
static void gtkwin_set_minimised(TermWin *tw, bool minimised)
{
/*
* GTK 1.2 doesn't know how to do this.
*/
#if GTK_CHECK_VERSION(2,0,0)
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = container_of(tw, GtkFrontend, termwin);
if (minimised)
gtk_window_iconify(GTK_WINDOW(inst->window));
else
gtk_window_deiconify(GTK_WINDOW(inst->window));
#endif
}
/*
* Move the window in response to a server-side request.
*/
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
static void gtkwin_move(TermWin *tw, int x, int y)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = container_of(tw, GtkFrontend, termwin);
/*
* I assume that when the GTK version of this call is available
* we should use it. Not sure how it differs from the GDK one,
* though.
*/
#if GTK_CHECK_VERSION(2,0,0)
/* in case we reset this at startup due to a geometry string */
gtk_window_set_gravity(GTK_WINDOW(inst->window), GDK_GRAVITY_NORTH_EAST);
gtk_window_move(GTK_WINDOW(inst->window), x, y);
#else
gdk_window_move(gtk_widget_get_window(inst->window), x, y);
#endif
}
/*
* Move the window to the top or bottom of the z-order in response
* to a server-side request.
*/
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
static void gtkwin_set_zorder(TermWin *tw, bool top)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = container_of(tw, GtkFrontend, termwin);
if (top)
gdk_window_raise(gtk_widget_get_window(inst->window));
else
gdk_window_lower(gtk_widget_get_window(inst->window));
}
/*
* Refresh the window in response to a server-side request.
*/
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
static void gtkwin_refresh(TermWin *tw)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = container_of(tw, GtkFrontend, termwin);
term_invalidate(inst->term);
}
/*
* Maximise or restore the window in response to a server-side
* request.
*/
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
static void gtkwin_set_maximised(TermWin *tw, bool maximised)
{
/*
* GTK 1.2 doesn't know how to do this.
*/
#if GTK_CHECK_VERSION(2,0,0)
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = container_of(tw, GtkFrontend, termwin);
if (maximised)
gtk_window_maximize(GTK_WINDOW(inst->window));
else
gtk_window_unmaximize(GTK_WINDOW(inst->window));
#endif
}
/*
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
* Report whether the window is minimised, for terminal reports.
*/
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
static bool gtkwin_is_minimised(TermWin *tw)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = container_of(tw, GtkFrontend, termwin);
return !gdk_window_is_viewable(gtk_widget_get_window(inst->window));
}
/*
* Report the window's position, for terminal reports.
*/
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
static void gtkwin_get_pos(TermWin *tw, int *x, int *y)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = container_of(tw, GtkFrontend, termwin);
/*
* I assume that when the GTK version of this call is available
* we should use it. Not sure how it differs from the GDK one,
* though.
*/
#if GTK_CHECK_VERSION(2,0,0)
gtk_window_get_position(GTK_WINDOW(inst->window), x, y);
#else
gdk_window_get_position(gtk_widget_get_window(inst->window), x, y);
#endif
}
/*
* Report the window's pixel size, for terminal reports.
*/
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
static void gtkwin_get_pixels(TermWin *tw, int *x, int *y)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = container_of(tw, GtkFrontend, termwin);
/*
* I assume that when the GTK version of this call is available
* we should use it. Not sure how it differs from the GDK one,
* though.
*/
#if GTK_CHECK_VERSION(2,0,0)
gtk_window_get_size(GTK_WINDOW(inst->window), x, y);
#else
gdk_window_get_size(gtk_widget_get_window(inst->window), x, y);
#endif
}
/*
* Find out whether a dialog box already exists for this window in a
* particular DialogSlot. If it does, uniconify it (if we can) and
* raise it, so that the user realises they've already been asked this
* question.
*/
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
static bool find_and_raise_dialog(GtkFrontend *inst, enum DialogSlot slot)
{
GtkWidget *dialog = inst->dialogs[slot];
if (!dialog)
return false;
#if GTK_CHECK_VERSION(2,0,0)
gtk_window_deiconify(GTK_WINDOW(dialog));
#endif
gdk_window_raise(gtk_widget_get_window(dialog));
return true;
}
/*
* Return the window or icon title.
*/
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
static const char *gtkwin_get_title(TermWin *tw, bool icon)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = container_of(tw, GtkFrontend, termwin);
return icon ? inst->icontitle : inst->wintitle;
}
static void warn_on_close_callback(void *vctx, int result)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = (GtkFrontend *)vctx;
New abstraction 'Seat', to pass to backends. This is a new vtable-based abstraction which is passed to a backend in place of Frontend, and it implements only the subset of the Frontend functions needed by a backend. (Many other Frontend functions still exist, notably the wide range of things called by terminal.c providing platform-independent operations on the GUI terminal window.) The purpose of making it a vtable is that this opens up the possibility of creating a backend as an internal implementation detail of some other activity, by providing just that one backend with a custom Seat that implements the methods differently. For example, this refactoring should make it feasible to directly implement an SSH proxy type, aka the 'jump host' feature supported by OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP mode, and then expose the main channel of that as the Socket for the primary connection'. (Which of course you can already do by spawning 'plink -nc' as a separate proxy process, but this would permit it in the _same_ process without anything getting confused.) I've centralised a full set of stub methods in misc.c for the new abstraction, which allows me to get rid of several annoying stubs in the previous code. Also, while I'm here, I've moved a lot of duplicated modalfatalbox() type functions from application main program files into wincons.c / uxcons.c, which I think saves duplication overall. (A minor visible effect is that the prefixes on those console-based fatal error messages will now be more consistent between applications.)
2018-10-11 21:58:42 +03:00
unregister_dialog(&inst->seat, DIALOG_SLOT_WARN_ON_CLOSE);
if (result)
gtk_widget_destroy(inst->window);
}
/*
* Handle the 'delete window' event (e.g. user clicking the WM close
* button). The return value false means the window should close, and
* true means it shouldn't.
*
* (That's counterintuitive, but really, in GTK terms, true means 'I
* have done everything necessary to handle this event, so the default
* handler need not do anything', i.e. 'suppress default handler',
* i.e. 'do not close the window'.)
*/
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
gint delete_window(GtkWidget *widget, GdkEvent *event, GtkFrontend *inst)
{
if (!inst->exited && conf_get_bool(inst->conf, CONF_warn_on_close)) {
/*
* We're not going to exit right now. We must put up a
* warn-on-close dialog, unless one already exists, in which
* case we'll just re-emphasise that one.
*/
if (!find_and_raise_dialog(inst, DIALOG_SLOT_WARN_ON_CLOSE)) {
char *title = dupcat(appname, " Exit Confirmation", NULL);
GtkWidget *dialog = create_message_box(
inst->window, title,
"Are you sure you want to close this session?",
string_width("Most of the width of the above text"),
false, &buttons_yn, warn_on_close_callback, inst);
New abstraction 'Seat', to pass to backends. This is a new vtable-based abstraction which is passed to a backend in place of Frontend, and it implements only the subset of the Frontend functions needed by a backend. (Many other Frontend functions still exist, notably the wide range of things called by terminal.c providing platform-independent operations on the GUI terminal window.) The purpose of making it a vtable is that this opens up the possibility of creating a backend as an internal implementation detail of some other activity, by providing just that one backend with a custom Seat that implements the methods differently. For example, this refactoring should make it feasible to directly implement an SSH proxy type, aka the 'jump host' feature supported by OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP mode, and then expose the main channel of that as the Socket for the primary connection'. (Which of course you can already do by spawning 'plink -nc' as a separate proxy process, but this would permit it in the _same_ process without anything getting confused.) I've centralised a full set of stub methods in misc.c for the new abstraction, which allows me to get rid of several annoying stubs in the previous code. Also, while I'm here, I've moved a lot of duplicated modalfatalbox() type functions from application main program files into wincons.c / uxcons.c, which I think saves duplication overall. (A minor visible effect is that the prefixes on those console-based fatal error messages will now be more consistent between applications.)
2018-10-11 21:58:42 +03:00
register_dialog(&inst->seat, DIALOG_SLOT_WARN_ON_CLOSE, dialog);
sfree(title);
}
return true;
}
return false;
}
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
static void update_mouseptr(GtkFrontend *inst)
{
switch (inst->busy_status) {
case BUSY_NOT:
if (!inst->mouseptr_visible) {
gdk_window_set_cursor(gtk_widget_get_window(inst->area),
inst->blankcursor);
} else if (inst->send_raw_mouse) {
gdk_window_set_cursor(gtk_widget_get_window(inst->area),
inst->rawcursor);
} else {
gdk_window_set_cursor(gtk_widget_get_window(inst->area),
inst->textcursor);
}
break;
case BUSY_WAITING: /* XXX can we do better? */
case BUSY_CPU:
/* We always display these cursors. */
gdk_window_set_cursor(gtk_widget_get_window(inst->area),
inst->waitcursor);
break;
default:
unreachable("Bad busy_status");
}
}
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
static void show_mouseptr(GtkFrontend *inst, bool show)
{
if (!conf_get_bool(inst->conf, CONF_hide_mouseptr))
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
show = true;
inst->mouseptr_visible = show;
update_mouseptr(inst);
}
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
static void draw_backing_rect(GtkFrontend *inst);
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
static void drawing_area_setup(GtkFrontend *inst, int width, int height)
{
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
int w, h, new_scale;
bool need_size = false;
/*
* See if the terminal size has changed.
*/
Stop using the GTK "configure-event" signal. I've been using that signal since the very first commit of this source file, as a combined way to be notified when the size of the drawing area changes (typically due to user window resizing actions) and also when the drawing area is first created and available to be drawn on. Unfortunately, testing on Ubuntu 18.04, I ran into an oddity, in which the call to gtk_widget_show(inst->window) in new_session_window() has the side effect of delivering a spurious configure_event on the drawing area with size 1x46 pixels. This causes the terminal to resize itself to 1 column wide, and the mistake isn't rectified until a followup configure-event arrives after new_session_window returns to the GTK main loop. But that means terminal output can occur between those two configure events (the connection-sharing "Reusing a shared connection to host.name" is a good example), and when it does, it gets embarrassingly wrapped at one character per line down the left column. I briefly tried to bodge around this by trying to heuristically guess which configure events were real and which were spurious, but I have no faith in that strategy continuing to work. I think a better approach is to abandon configure-event completely, and move to a system in which the two purposes I was using it for are handled by two _different_ GTK signals, namely "size-allocate" (for knowing when we get resized) and "realize" (for knowing when the drawing area physically exists for us to start setting up Cairo or GDK machinery). The result seems to have fixed the silly one-column wrapping bug, and retained the ability to handle window resizes, on every GTK version I have conveniently available to test on, including GTK 3 both before and after these spurious configures started to happen.
2018-05-10 22:22:02 +03:00
w = (width - 2*inst->window_border) / inst->font_width;
h = (height - 2*inst->window_border) / inst->font_height;
if (w != inst->width || h != inst->height) {
/*
* Update conf.
*/
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
inst->width = w;
inst->height = h;
conf_set_int(inst->conf, CONF_width, inst->width);
conf_set_int(inst->conf, CONF_height, inst->height);
/*
* We'll need to tell terminal.c about the resize below.
*/
need_size = true;
/*
* And we must refresh the window's backing image.
*/
inst->drawing_area_setup_needed = true;
}
GTK 3: be aware of the window's scale factor. In GTK 3.10 and above, high-DPI support is arranged by each window having a property called a 'scale factor', which translates logical pixels as seen by most of the GTK API (widget and window sizes and positions, coordinates in the "draw" event, etc) into the physical pixels on the screen. This is handled more or less transparently, except that one side effect is that your Cairo-based drawing code had better be able to cope with that scaling without getting confused. PuTTY's isn't, because we do all our serious drawing on a separate Cairo surface we made ourselves, and then blit subrectangles of that to the window during updates. This has two bad consequences. Firstly, our surface has a size derived from what GTK told us the drawing area size is, i.e. corresponding to GTK's _logical_ pixels, so when the scale factor is (say) 2, our drawing takes place at half size and then gets scaled up by the final blit in the draw event, making it look blurry and unpleasant. Secondly, those final blits seem to end up offset by half a pixel, so that a second blit over the same subrectangle doesn't _quite_ completely wipe out the previously blitted data - so there's a ghostly rectangle left behind everywhere the cursor has been. It's not that GTK doesn't _let_ you find out the scale factor; it's just that it's in an out-of-the-way piece of API that you have to call specially. So now we do: our backing surface is now created at a pixel resolution matching the screen's real pixels, and we translate GTK's scale factor into an ordinary cairo_scale() before we commence drawing. So we still end up drawing the same text at the same size - and this strategy also means that non-text elements like cursor outlines and underlining will be scaled up with the screen DPI rather than stubbornly staying one physical pixel thick - but now it's nice and sharp at full screen resolution, and the subrectangle blits in the draw event are back to affecting the exact set of pixels we expect them to. One silly consequence is that, immediately after removing the last one, I've installed a handler for the GTK "configure-event" signal! That's because the GTK 3 docs claim that that's how you get notified that your scale factor has changed at run time (e.g. if you reconfigure the scale factor of a whole monitor in the GNOME settings dialog). Actually in practice I seem to find out via the "draw" event before "configure" bothers to tell me, but now I've got a usefully idempotent function for 'check whether the scale factor has changed and sort it out if so', I don't see any harm in calling it from anywhere it _might_ be useful.
2018-05-11 09:53:05 +03:00
#if GTK_CHECK_VERSION(3,10,0)
new_scale = gtk_widget_get_scale_factor(inst->area);
if (new_scale != inst->scale)
inst->drawing_area_setup_needed = true;
GTK 3: be aware of the window's scale factor. In GTK 3.10 and above, high-DPI support is arranged by each window having a property called a 'scale factor', which translates logical pixels as seen by most of the GTK API (widget and window sizes and positions, coordinates in the "draw" event, etc) into the physical pixels on the screen. This is handled more or less transparently, except that one side effect is that your Cairo-based drawing code had better be able to cope with that scaling without getting confused. PuTTY's isn't, because we do all our serious drawing on a separate Cairo surface we made ourselves, and then blit subrectangles of that to the window during updates. This has two bad consequences. Firstly, our surface has a size derived from what GTK told us the drawing area size is, i.e. corresponding to GTK's _logical_ pixels, so when the scale factor is (say) 2, our drawing takes place at half size and then gets scaled up by the final blit in the draw event, making it look blurry and unpleasant. Secondly, those final blits seem to end up offset by half a pixel, so that a second blit over the same subrectangle doesn't _quite_ completely wipe out the previously blitted data - so there's a ghostly rectangle left behind everywhere the cursor has been. It's not that GTK doesn't _let_ you find out the scale factor; it's just that it's in an out-of-the-way piece of API that you have to call specially. So now we do: our backing surface is now created at a pixel resolution matching the screen's real pixels, and we translate GTK's scale factor into an ordinary cairo_scale() before we commence drawing. So we still end up drawing the same text at the same size - and this strategy also means that non-text elements like cursor outlines and underlining will be scaled up with the screen DPI rather than stubbornly staying one physical pixel thick - but now it's nice and sharp at full screen resolution, and the subrectangle blits in the draw event are back to affecting the exact set of pixels we expect them to. One silly consequence is that, immediately after removing the last one, I've installed a handler for the GTK "configure-event" signal! That's because the GTK 3 docs claim that that's how you get notified that your scale factor has changed at run time (e.g. if you reconfigure the scale factor of a whole monitor in the GNOME settings dialog). Actually in practice I seem to find out via the "draw" event before "configure" bothers to tell me, but now I've got a usefully idempotent function for 'check whether the scale factor has changed and sort it out if so', I don't see any harm in calling it from anywhere it _might_ be useful.
2018-05-11 09:53:05 +03:00
#else
new_scale = 1;
#endif
/*
* This event might be spurious; some GTK setups have been known
* to call it when nothing at all has changed. Check if we have
* any reason to proceed.
*/
if (!inst->drawing_area_setup_needed)
Stop using the GTK "configure-event" signal. I've been using that signal since the very first commit of this source file, as a combined way to be notified when the size of the drawing area changes (typically due to user window resizing actions) and also when the drawing area is first created and available to be drawn on. Unfortunately, testing on Ubuntu 18.04, I ran into an oddity, in which the call to gtk_widget_show(inst->window) in new_session_window() has the side effect of delivering a spurious configure_event on the drawing area with size 1x46 pixels. This causes the terminal to resize itself to 1 column wide, and the mistake isn't rectified until a followup configure-event arrives after new_session_window returns to the GTK main loop. But that means terminal output can occur between those two configure events (the connection-sharing "Reusing a shared connection to host.name" is a good example), and when it does, it gets embarrassingly wrapped at one character per line down the left column. I briefly tried to bodge around this by trying to heuristically guess which configure events were real and which were spurious, but I have no faith in that strategy continuing to work. I think a better approach is to abandon configure-event completely, and move to a system in which the two purposes I was using it for are handled by two _different_ GTK signals, namely "size-allocate" (for knowing when we get resized) and "realize" (for knowing when the drawing area physically exists for us to start setting up Cairo or GDK machinery). The result seems to have fixed the silly one-column wrapping bug, and retained the ability to handle window resizes, on every GTK version I have conveniently available to test on, including GTK 3 both before and after these spurious configures started to happen.
2018-05-10 22:22:02 +03:00
return;
inst->drawing_area_setup_needed = false;
GTK 3: be aware of the window's scale factor. In GTK 3.10 and above, high-DPI support is arranged by each window having a property called a 'scale factor', which translates logical pixels as seen by most of the GTK API (widget and window sizes and positions, coordinates in the "draw" event, etc) into the physical pixels on the screen. This is handled more or less transparently, except that one side effect is that your Cairo-based drawing code had better be able to cope with that scaling without getting confused. PuTTY's isn't, because we do all our serious drawing on a separate Cairo surface we made ourselves, and then blit subrectangles of that to the window during updates. This has two bad consequences. Firstly, our surface has a size derived from what GTK told us the drawing area size is, i.e. corresponding to GTK's _logical_ pixels, so when the scale factor is (say) 2, our drawing takes place at half size and then gets scaled up by the final blit in the draw event, making it look blurry and unpleasant. Secondly, those final blits seem to end up offset by half a pixel, so that a second blit over the same subrectangle doesn't _quite_ completely wipe out the previously blitted data - so there's a ghostly rectangle left behind everywhere the cursor has been. It's not that GTK doesn't _let_ you find out the scale factor; it's just that it's in an out-of-the-way piece of API that you have to call specially. So now we do: our backing surface is now created at a pixel resolution matching the screen's real pixels, and we translate GTK's scale factor into an ordinary cairo_scale() before we commence drawing. So we still end up drawing the same text at the same size - and this strategy also means that non-text elements like cursor outlines and underlining will be scaled up with the screen DPI rather than stubbornly staying one physical pixel thick - but now it's nice and sharp at full screen resolution, and the subrectangle blits in the draw event are back to affecting the exact set of pixels we expect them to. One silly consequence is that, immediately after removing the last one, I've installed a handler for the GTK "configure-event" signal! That's because the GTK 3 docs claim that that's how you get notified that your scale factor has changed at run time (e.g. if you reconfigure the scale factor of a whole monitor in the GNOME settings dialog). Actually in practice I seem to find out via the "draw" event before "configure" bothers to tell me, but now I've got a usefully idempotent function for 'check whether the scale factor has changed and sort it out if so', I don't see any harm in calling it from anywhere it _might_ be useful.
2018-05-11 09:53:05 +03:00
inst->scale = new_scale;
Use a Cairo image surface as a client-side cache. In any DRAWTYPE_CAIRO mode, we now do all our Cairo drawing to a Cairo image surface which lives on the client; then we either blit directly from that to the window (if we're in GTK3 mode, or GTK2 without deprecated pieces of API), or else we blit from the Cairo surface to the server-side pixmap and then from there to the actual window. In DRAWTYPE_GDK mode, nothing much has changed: we still draw directly to the server-side pixmap using the GDK drawing API, then blit from there to the window. But there is one change, namely that the blit is no longer done proactively - instead, we queue a redraw of the affected rectangle, and wait until we're called back by the expose handler. The main aim of all this is to arrange that the only time we ever draw to the real window is in response to expose/draw events. The experimental GTK3 OS X port stopped working a week or two ago (I presume in response to an OS update) with the symptoms that attempts to draw on the window outside the context of a "draw" event handler just didn't seem to work any more; this change fixes it. In addition to that benefit, this change also has obvious performance advantages in principle. No more expensive text rendering in response to an expose event - just re-copy to the window from the bitmap we already have, from wherever it's stored that's nearest. Moreover, this seems to have fixed the significant performance problem with X server-side fonts under GTK. I didn't expect _that_! I'd guessed that the approach of downloading character bitmaps and rendering them manually via Cairo was just inherently slow for some reason. I've no real idea _why_ this change improves matters so much; my best guess is that perhaps there's an overhead in each drawing operation to a GDK Cairo surface, so we win by doing lots of operations to a much faster image surface and then batching them up into one GDK Cairo operation. But whyever it is, I'm certainly not complaining! (In fact, it now seems to be noticeably _faster_, at least on my usual local X displays, to draw server-side fonts using that technique than using the old GDK approach. I may yet decide to switch over...)
2015-09-24 16:08:25 +03:00
{
int backing_w = w * inst->font_width + 2*inst->window_border;
int backing_h = h * inst->font_height + 2*inst->window_border;
GTK 3: be aware of the window's scale factor. In GTK 3.10 and above, high-DPI support is arranged by each window having a property called a 'scale factor', which translates logical pixels as seen by most of the GTK API (widget and window sizes and positions, coordinates in the "draw" event, etc) into the physical pixels on the screen. This is handled more or less transparently, except that one side effect is that your Cairo-based drawing code had better be able to cope with that scaling without getting confused. PuTTY's isn't, because we do all our serious drawing on a separate Cairo surface we made ourselves, and then blit subrectangles of that to the window during updates. This has two bad consequences. Firstly, our surface has a size derived from what GTK told us the drawing area size is, i.e. corresponding to GTK's _logical_ pixels, so when the scale factor is (say) 2, our drawing takes place at half size and then gets scaled up by the final blit in the draw event, making it look blurry and unpleasant. Secondly, those final blits seem to end up offset by half a pixel, so that a second blit over the same subrectangle doesn't _quite_ completely wipe out the previously blitted data - so there's a ghostly rectangle left behind everywhere the cursor has been. It's not that GTK doesn't _let_ you find out the scale factor; it's just that it's in an out-of-the-way piece of API that you have to call specially. So now we do: our backing surface is now created at a pixel resolution matching the screen's real pixels, and we translate GTK's scale factor into an ordinary cairo_scale() before we commence drawing. So we still end up drawing the same text at the same size - and this strategy also means that non-text elements like cursor outlines and underlining will be scaled up with the screen DPI rather than stubbornly staying one physical pixel thick - but now it's nice and sharp at full screen resolution, and the subrectangle blits in the draw event are back to affecting the exact set of pixels we expect them to. One silly consequence is that, immediately after removing the last one, I've installed a handler for the GTK "configure-event" signal! That's because the GTK 3 docs claim that that's how you get notified that your scale factor has changed at run time (e.g. if you reconfigure the scale factor of a whole monitor in the GNOME settings dialog). Actually in practice I seem to find out via the "draw" event before "configure" bothers to tell me, but now I've got a usefully idempotent function for 'check whether the scale factor has changed and sort it out if so', I don't see any harm in calling it from anywhere it _might_ be useful.
2018-05-11 09:53:05 +03:00
backing_w *= inst->scale;
backing_h *= inst->scale;
#ifndef NO_BACKING_PIXMAPS
Use a Cairo image surface as a client-side cache. In any DRAWTYPE_CAIRO mode, we now do all our Cairo drawing to a Cairo image surface which lives on the client; then we either blit directly from that to the window (if we're in GTK3 mode, or GTK2 without deprecated pieces of API), or else we blit from the Cairo surface to the server-side pixmap and then from there to the actual window. In DRAWTYPE_GDK mode, nothing much has changed: we still draw directly to the server-side pixmap using the GDK drawing API, then blit from there to the window. But there is one change, namely that the blit is no longer done proactively - instead, we queue a redraw of the affected rectangle, and wait until we're called back by the expose handler. The main aim of all this is to arrange that the only time we ever draw to the real window is in response to expose/draw events. The experimental GTK3 OS X port stopped working a week or two ago (I presume in response to an OS update) with the symptoms that attempts to draw on the window outside the context of a "draw" event handler just didn't seem to work any more; this change fixes it. In addition to that benefit, this change also has obvious performance advantages in principle. No more expensive text rendering in response to an expose event - just re-copy to the window from the bitmap we already have, from wherever it's stored that's nearest. Moreover, this seems to have fixed the significant performance problem with X server-side fonts under GTK. I didn't expect _that_! I'd guessed that the approach of downloading character bitmaps and rendering them manually via Cairo was just inherently slow for some reason. I've no real idea _why_ this change improves matters so much; my best guess is that perhaps there's an overhead in each drawing operation to a GDK Cairo surface, so we win by doing lots of operations to a much faster image surface and then batching them up into one GDK Cairo operation. But whyever it is, I'm certainly not complaining! (In fact, it now seems to be noticeably _faster_, at least on my usual local X displays, to draw server-side fonts using that technique than using the old GDK approach. I may yet decide to switch over...)
2015-09-24 16:08:25 +03:00
if (inst->pixmap) {
gdk_pixmap_unref(inst->pixmap);
inst->pixmap = NULL;
}
Stop using the GTK "configure-event" signal. I've been using that signal since the very first commit of this source file, as a combined way to be notified when the size of the drawing area changes (typically due to user window resizing actions) and also when the drawing area is first created and available to be drawn on. Unfortunately, testing on Ubuntu 18.04, I ran into an oddity, in which the call to gtk_widget_show(inst->window) in new_session_window() has the side effect of delivering a spurious configure_event on the drawing area with size 1x46 pixels. This causes the terminal to resize itself to 1 column wide, and the mistake isn't rectified until a followup configure-event arrives after new_session_window returns to the GTK main loop. But that means terminal output can occur between those two configure events (the connection-sharing "Reusing a shared connection to host.name" is a good example), and when it does, it gets embarrassingly wrapped at one character per line down the left column. I briefly tried to bodge around this by trying to heuristically guess which configure events were real and which were spurious, but I have no faith in that strategy continuing to work. I think a better approach is to abandon configure-event completely, and move to a system in which the two purposes I was using it for are handled by two _different_ GTK signals, namely "size-allocate" (for knowing when we get resized) and "realize" (for knowing when the drawing area physically exists for us to start setting up Cairo or GDK machinery). The result seems to have fixed the silly one-column wrapping bug, and retained the ability to handle window resizes, on every GTK version I have conveniently available to test on, including GTK 3 both before and after these spurious configures started to happen.
2018-05-10 22:22:02 +03:00
inst->pixmap = gdk_pixmap_new(gtk_widget_get_window(inst->area),
Use a Cairo image surface as a client-side cache. In any DRAWTYPE_CAIRO mode, we now do all our Cairo drawing to a Cairo image surface which lives on the client; then we either blit directly from that to the window (if we're in GTK3 mode, or GTK2 without deprecated pieces of API), or else we blit from the Cairo surface to the server-side pixmap and then from there to the actual window. In DRAWTYPE_GDK mode, nothing much has changed: we still draw directly to the server-side pixmap using the GDK drawing API, then blit from there to the window. But there is one change, namely that the blit is no longer done proactively - instead, we queue a redraw of the affected rectangle, and wait until we're called back by the expose handler. The main aim of all this is to arrange that the only time we ever draw to the real window is in response to expose/draw events. The experimental GTK3 OS X port stopped working a week or two ago (I presume in response to an OS update) with the symptoms that attempts to draw on the window outside the context of a "draw" event handler just didn't seem to work any more; this change fixes it. In addition to that benefit, this change also has obvious performance advantages in principle. No more expensive text rendering in response to an expose event - just re-copy to the window from the bitmap we already have, from wherever it's stored that's nearest. Moreover, this seems to have fixed the significant performance problem with X server-side fonts under GTK. I didn't expect _that_! I'd guessed that the approach of downloading character bitmaps and rendering them manually via Cairo was just inherently slow for some reason. I've no real idea _why_ this change improves matters so much; my best guess is that perhaps there's an overhead in each drawing operation to a GDK Cairo surface, so we win by doing lots of operations to a much faster image surface and then batching them up into one GDK Cairo operation. But whyever it is, I'm certainly not complaining! (In fact, it now seems to be noticeably _faster_, at least on my usual local X displays, to draw server-side fonts using that technique than using the old GDK approach. I may yet decide to switch over...)
2015-09-24 16:08:25 +03:00
backing_w, backing_h, -1);
#endif
Use a Cairo image surface as a client-side cache. In any DRAWTYPE_CAIRO mode, we now do all our Cairo drawing to a Cairo image surface which lives on the client; then we either blit directly from that to the window (if we're in GTK3 mode, or GTK2 without deprecated pieces of API), or else we blit from the Cairo surface to the server-side pixmap and then from there to the actual window. In DRAWTYPE_GDK mode, nothing much has changed: we still draw directly to the server-side pixmap using the GDK drawing API, then blit from there to the window. But there is one change, namely that the blit is no longer done proactively - instead, we queue a redraw of the affected rectangle, and wait until we're called back by the expose handler. The main aim of all this is to arrange that the only time we ever draw to the real window is in response to expose/draw events. The experimental GTK3 OS X port stopped working a week or two ago (I presume in response to an OS update) with the symptoms that attempts to draw on the window outside the context of a "draw" event handler just didn't seem to work any more; this change fixes it. In addition to that benefit, this change also has obvious performance advantages in principle. No more expensive text rendering in response to an expose event - just re-copy to the window from the bitmap we already have, from wherever it's stored that's nearest. Moreover, this seems to have fixed the significant performance problem with X server-side fonts under GTK. I didn't expect _that_! I'd guessed that the approach of downloading character bitmaps and rendering them manually via Cairo was just inherently slow for some reason. I've no real idea _why_ this change improves matters so much; my best guess is that perhaps there's an overhead in each drawing operation to a GDK Cairo surface, so we win by doing lots of operations to a much faster image surface and then batching them up into one GDK Cairo operation. But whyever it is, I'm certainly not complaining! (In fact, it now seems to be noticeably _faster_, at least on my usual local X displays, to draw server-side fonts using that technique than using the old GDK approach. I may yet decide to switch over...)
2015-09-24 16:08:25 +03:00
#ifdef DRAW_TEXT_CAIRO
if (inst->surface) {
cairo_surface_destroy(inst->surface);
inst->surface = NULL;
}
Change Cairo image surface type from RGB24 to ARGB32. This seems to work around a GTK 3.22 display bug that Colin Watson and I have both observed on Ubuntu (though I found that proxying the X server, e.g. by SSH X forwarding or xtruss, inhibited the bug). The effect of the bug was that the terminal window would appear completely black and nothing would ever be displayed in it, though the terminal session was still actually running and keystrokes would be sent to it. But changing the call to cairo_set_source_surface() to some other cairo_set_source_foo caused successful drawing of whatever other source I selected; the problem seemed specific to the image surface. Also, when I popped up the Ctrl-right-click menu over the terminal window, the menu didn't disappear when dismissed, i.e. the drawing area's redraw operation was not drawing in black, but failing to draw _anything_. That led me to hypothesise that the draw event handler for the terminal drawing area might somehow be accidentally inventing 0 rather than 255 for the implicit alpha channel when using our RGB-type image surface as a source; so I tried setting the surface type to one with an explicit alpha channel in the hope that there would no longer be a need to make up any alpha value at all. And indeed, that seems to solve the problem for me, so I might as well commit it. However, I don't know the full details of what the previous problem was, so this is only an empirical workaround. If it turns out I was making some other mistake without which a RGB source surface would have worked for me, then I should probably revert this and do whatever other fix turns out to be a better plan.
2017-03-08 01:57:54 +03:00
inst->surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
Use a Cairo image surface as a client-side cache. In any DRAWTYPE_CAIRO mode, we now do all our Cairo drawing to a Cairo image surface which lives on the client; then we either blit directly from that to the window (if we're in GTK3 mode, or GTK2 without deprecated pieces of API), or else we blit from the Cairo surface to the server-side pixmap and then from there to the actual window. In DRAWTYPE_GDK mode, nothing much has changed: we still draw directly to the server-side pixmap using the GDK drawing API, then blit from there to the window. But there is one change, namely that the blit is no longer done proactively - instead, we queue a redraw of the affected rectangle, and wait until we're called back by the expose handler. The main aim of all this is to arrange that the only time we ever draw to the real window is in response to expose/draw events. The experimental GTK3 OS X port stopped working a week or two ago (I presume in response to an OS update) with the symptoms that attempts to draw on the window outside the context of a "draw" event handler just didn't seem to work any more; this change fixes it. In addition to that benefit, this change also has obvious performance advantages in principle. No more expensive text rendering in response to an expose event - just re-copy to the window from the bitmap we already have, from wherever it's stored that's nearest. Moreover, this seems to have fixed the significant performance problem with X server-side fonts under GTK. I didn't expect _that_! I'd guessed that the approach of downloading character bitmaps and rendering them manually via Cairo was just inherently slow for some reason. I've no real idea _why_ this change improves matters so much; my best guess is that perhaps there's an overhead in each drawing operation to a GDK Cairo surface, so we win by doing lots of operations to a much faster image surface and then batching them up into one GDK Cairo operation. But whyever it is, I'm certainly not complaining! (In fact, it now seems to be noticeably _faster_, at least on my usual local X displays, to draw server-side fonts using that technique than using the old GDK approach. I may yet decide to switch over...)
2015-09-24 16:08:25 +03:00
backing_w, backing_h);
#endif
}
draw_backing_rect(inst);
if (need_size && inst->term) {
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
term_size(inst->term, h, w, conf_get_int(inst->conf, CONF_savelines));
}
if (inst->term)
term_invalidate(inst->term);
#if GTK_CHECK_VERSION(2,0,0)
Stop using the GTK "configure-event" signal. I've been using that signal since the very first commit of this source file, as a combined way to be notified when the size of the drawing area changes (typically due to user window resizing actions) and also when the drawing area is first created and available to be drawn on. Unfortunately, testing on Ubuntu 18.04, I ran into an oddity, in which the call to gtk_widget_show(inst->window) in new_session_window() has the side effect of delivering a spurious configure_event on the drawing area with size 1x46 pixels. This causes the terminal to resize itself to 1 column wide, and the mistake isn't rectified until a followup configure-event arrives after new_session_window returns to the GTK main loop. But that means terminal output can occur between those two configure events (the connection-sharing "Reusing a shared connection to host.name" is a good example), and when it does, it gets embarrassingly wrapped at one character per line down the left column. I briefly tried to bodge around this by trying to heuristically guess which configure events were real and which were spurious, but I have no faith in that strategy continuing to work. I think a better approach is to abandon configure-event completely, and move to a system in which the two purposes I was using it for are handled by two _different_ GTK signals, namely "size-allocate" (for knowing when we get resized) and "realize" (for knowing when the drawing area physically exists for us to start setting up Cairo or GDK machinery). The result seems to have fixed the silly one-column wrapping bug, and retained the ability to handle window resizes, on every GTK version I have conveniently available to test on, including GTK 3 both before and after these spurious configures started to happen.
2018-05-10 22:22:02 +03:00
gtk_im_context_set_client_window(
inst->imc, gtk_widget_get_window(inst->area));
#endif
Stop using the GTK "configure-event" signal. I've been using that signal since the very first commit of this source file, as a combined way to be notified when the size of the drawing area changes (typically due to user window resizing actions) and also when the drawing area is first created and available to be drawn on. Unfortunately, testing on Ubuntu 18.04, I ran into an oddity, in which the call to gtk_widget_show(inst->window) in new_session_window() has the side effect of delivering a spurious configure_event on the drawing area with size 1x46 pixels. This causes the terminal to resize itself to 1 column wide, and the mistake isn't rectified until a followup configure-event arrives after new_session_window returns to the GTK main loop. But that means terminal output can occur between those two configure events (the connection-sharing "Reusing a shared connection to host.name" is a good example), and when it does, it gets embarrassingly wrapped at one character per line down the left column. I briefly tried to bodge around this by trying to heuristically guess which configure events were real and which were spurious, but I have no faith in that strategy continuing to work. I think a better approach is to abandon configure-event completely, and move to a system in which the two purposes I was using it for are handled by two _different_ GTK signals, namely "size-allocate" (for knowing when we get resized) and "realize" (for knowing when the drawing area physically exists for us to start setting up Cairo or GDK machinery). The result seems to have fixed the silly one-column wrapping bug, and retained the ability to handle window resizes, on every GTK version I have conveniently available to test on, including GTK 3 both before and after these spurious configures started to happen.
2018-05-10 22:22:02 +03:00
}
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
static void drawing_area_setup_simple(GtkFrontend *inst)
{
/*
* Wrapper on drawing_area_setup which fetches the width and
* height of the drawing area. We go directly to the inner version
* in the case where a new size allocation comes in (just in case
* GTK hasn't installed it in the normal place yet).
*/
#if GTK_CHECK_VERSION(2,0,0)
GdkRectangle alloc;
gtk_widget_get_allocation(inst->area, &alloc);
#else
GtkAllocation alloc = inst->area->allocation;
#endif
drawing_area_setup(inst, alloc.width, alloc.height);
}
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
static void area_realised(GtkWidget *widget, GtkFrontend *inst)
Stop using the GTK "configure-event" signal. I've been using that signal since the very first commit of this source file, as a combined way to be notified when the size of the drawing area changes (typically due to user window resizing actions) and also when the drawing area is first created and available to be drawn on. Unfortunately, testing on Ubuntu 18.04, I ran into an oddity, in which the call to gtk_widget_show(inst->window) in new_session_window() has the side effect of delivering a spurious configure_event on the drawing area with size 1x46 pixels. This causes the terminal to resize itself to 1 column wide, and the mistake isn't rectified until a followup configure-event arrives after new_session_window returns to the GTK main loop. But that means terminal output can occur between those two configure events (the connection-sharing "Reusing a shared connection to host.name" is a good example), and when it does, it gets embarrassingly wrapped at one character per line down the left column. I briefly tried to bodge around this by trying to heuristically guess which configure events were real and which were spurious, but I have no faith in that strategy continuing to work. I think a better approach is to abandon configure-event completely, and move to a system in which the two purposes I was using it for are handled by two _different_ GTK signals, namely "size-allocate" (for knowing when we get resized) and "realize" (for knowing when the drawing area physically exists for us to start setting up Cairo or GDK machinery). The result seems to have fixed the silly one-column wrapping bug, and retained the ability to handle window resizes, on every GTK version I have conveniently available to test on, including GTK 3 both before and after these spurious configures started to happen.
2018-05-10 22:22:02 +03:00
{
inst->drawing_area_realised = true;
Stop using the GTK "configure-event" signal. I've been using that signal since the very first commit of this source file, as a combined way to be notified when the size of the drawing area changes (typically due to user window resizing actions) and also when the drawing area is first created and available to be drawn on. Unfortunately, testing on Ubuntu 18.04, I ran into an oddity, in which the call to gtk_widget_show(inst->window) in new_session_window() has the side effect of delivering a spurious configure_event on the drawing area with size 1x46 pixels. This causes the terminal to resize itself to 1 column wide, and the mistake isn't rectified until a followup configure-event arrives after new_session_window returns to the GTK main loop. But that means terminal output can occur between those two configure events (the connection-sharing "Reusing a shared connection to host.name" is a good example), and when it does, it gets embarrassingly wrapped at one character per line down the left column. I briefly tried to bodge around this by trying to heuristically guess which configure events were real and which were spurious, but I have no faith in that strategy continuing to work. I think a better approach is to abandon configure-event completely, and move to a system in which the two purposes I was using it for are handled by two _different_ GTK signals, namely "size-allocate" (for knowing when we get resized) and "realize" (for knowing when the drawing area physically exists for us to start setting up Cairo or GDK machinery). The result seems to have fixed the silly one-column wrapping bug, and retained the ability to handle window resizes, on every GTK version I have conveniently available to test on, including GTK 3 both before and after these spurious configures started to happen.
2018-05-10 22:22:02 +03:00
if (inst->drawing_area_realised && inst->drawing_area_got_size &&
inst->drawing_area_setup_needed)
drawing_area_setup_simple(inst);
Stop using the GTK "configure-event" signal. I've been using that signal since the very first commit of this source file, as a combined way to be notified when the size of the drawing area changes (typically due to user window resizing actions) and also when the drawing area is first created and available to be drawn on. Unfortunately, testing on Ubuntu 18.04, I ran into an oddity, in which the call to gtk_widget_show(inst->window) in new_session_window() has the side effect of delivering a spurious configure_event on the drawing area with size 1x46 pixels. This causes the terminal to resize itself to 1 column wide, and the mistake isn't rectified until a followup configure-event arrives after new_session_window returns to the GTK main loop. But that means terminal output can occur between those two configure events (the connection-sharing "Reusing a shared connection to host.name" is a good example), and when it does, it gets embarrassingly wrapped at one character per line down the left column. I briefly tried to bodge around this by trying to heuristically guess which configure events were real and which were spurious, but I have no faith in that strategy continuing to work. I think a better approach is to abandon configure-event completely, and move to a system in which the two purposes I was using it for are handled by two _different_ GTK signals, namely "size-allocate" (for knowing when we get resized) and "realize" (for knowing when the drawing area physically exists for us to start setting up Cairo or GDK machinery). The result seems to have fixed the silly one-column wrapping bug, and retained the ability to handle window resizes, on every GTK version I have conveniently available to test on, including GTK 3 both before and after these spurious configures started to happen.
2018-05-10 22:22:02 +03:00
}
static void area_size_allocate(
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkWidget *widget, GdkRectangle *alloc, GtkFrontend *inst)
Stop using the GTK "configure-event" signal. I've been using that signal since the very first commit of this source file, as a combined way to be notified when the size of the drawing area changes (typically due to user window resizing actions) and also when the drawing area is first created and available to be drawn on. Unfortunately, testing on Ubuntu 18.04, I ran into an oddity, in which the call to gtk_widget_show(inst->window) in new_session_window() has the side effect of delivering a spurious configure_event on the drawing area with size 1x46 pixels. This causes the terminal to resize itself to 1 column wide, and the mistake isn't rectified until a followup configure-event arrives after new_session_window returns to the GTK main loop. But that means terminal output can occur between those two configure events (the connection-sharing "Reusing a shared connection to host.name" is a good example), and when it does, it gets embarrassingly wrapped at one character per line down the left column. I briefly tried to bodge around this by trying to heuristically guess which configure events were real and which were spurious, but I have no faith in that strategy continuing to work. I think a better approach is to abandon configure-event completely, and move to a system in which the two purposes I was using it for are handled by two _different_ GTK signals, namely "size-allocate" (for knowing when we get resized) and "realize" (for knowing when the drawing area physically exists for us to start setting up Cairo or GDK machinery). The result seems to have fixed the silly one-column wrapping bug, and retained the ability to handle window resizes, on every GTK version I have conveniently available to test on, including GTK 3 both before and after these spurious configures started to happen.
2018-05-10 22:22:02 +03:00
{
inst->drawing_area_got_size = true;
Stop using the GTK "configure-event" signal. I've been using that signal since the very first commit of this source file, as a combined way to be notified when the size of the drawing area changes (typically due to user window resizing actions) and also when the drawing area is first created and available to be drawn on. Unfortunately, testing on Ubuntu 18.04, I ran into an oddity, in which the call to gtk_widget_show(inst->window) in new_session_window() has the side effect of delivering a spurious configure_event on the drawing area with size 1x46 pixels. This causes the terminal to resize itself to 1 column wide, and the mistake isn't rectified until a followup configure-event arrives after new_session_window returns to the GTK main loop. But that means terminal output can occur between those two configure events (the connection-sharing "Reusing a shared connection to host.name" is a good example), and when it does, it gets embarrassingly wrapped at one character per line down the left column. I briefly tried to bodge around this by trying to heuristically guess which configure events were real and which were spurious, but I have no faith in that strategy continuing to work. I think a better approach is to abandon configure-event completely, and move to a system in which the two purposes I was using it for are handled by two _different_ GTK signals, namely "size-allocate" (for knowing when we get resized) and "realize" (for knowing when the drawing area physically exists for us to start setting up Cairo or GDK machinery). The result seems to have fixed the silly one-column wrapping bug, and retained the ability to handle window resizes, on every GTK version I have conveniently available to test on, including GTK 3 both before and after these spurious configures started to happen.
2018-05-10 22:22:02 +03:00
if (inst->drawing_area_realised && inst->drawing_area_got_size)
drawing_area_setup(inst, alloc->width, alloc->height);
}
GTK 3: be aware of the window's scale factor. In GTK 3.10 and above, high-DPI support is arranged by each window having a property called a 'scale factor', which translates logical pixels as seen by most of the GTK API (widget and window sizes and positions, coordinates in the "draw" event, etc) into the physical pixels on the screen. This is handled more or less transparently, except that one side effect is that your Cairo-based drawing code had better be able to cope with that scaling without getting confused. PuTTY's isn't, because we do all our serious drawing on a separate Cairo surface we made ourselves, and then blit subrectangles of that to the window during updates. This has two bad consequences. Firstly, our surface has a size derived from what GTK told us the drawing area size is, i.e. corresponding to GTK's _logical_ pixels, so when the scale factor is (say) 2, our drawing takes place at half size and then gets scaled up by the final blit in the draw event, making it look blurry and unpleasant. Secondly, those final blits seem to end up offset by half a pixel, so that a second blit over the same subrectangle doesn't _quite_ completely wipe out the previously blitted data - so there's a ghostly rectangle left behind everywhere the cursor has been. It's not that GTK doesn't _let_ you find out the scale factor; it's just that it's in an out-of-the-way piece of API that you have to call specially. So now we do: our backing surface is now created at a pixel resolution matching the screen's real pixels, and we translate GTK's scale factor into an ordinary cairo_scale() before we commence drawing. So we still end up drawing the same text at the same size - and this strategy also means that non-text elements like cursor outlines and underlining will be scaled up with the screen DPI rather than stubbornly staying one physical pixel thick - but now it's nice and sharp at full screen resolution, and the subrectangle blits in the draw event are back to affecting the exact set of pixels we expect them to. One silly consequence is that, immediately after removing the last one, I've installed a handler for the GTK "configure-event" signal! That's because the GTK 3 docs claim that that's how you get notified that your scale factor has changed at run time (e.g. if you reconfigure the scale factor of a whole monitor in the GNOME settings dialog). Actually in practice I seem to find out via the "draw" event before "configure" bothers to tell me, but now I've got a usefully idempotent function for 'check whether the scale factor has changed and sort it out if so', I don't see any harm in calling it from anywhere it _might_ be useful.
2018-05-11 09:53:05 +03:00
#if GTK_CHECK_VERSION(3,10,0)
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
static void area_check_scale(GtkFrontend *inst)
GTK 3: be aware of the window's scale factor. In GTK 3.10 and above, high-DPI support is arranged by each window having a property called a 'scale factor', which translates logical pixels as seen by most of the GTK API (widget and window sizes and positions, coordinates in the "draw" event, etc) into the physical pixels on the screen. This is handled more or less transparently, except that one side effect is that your Cairo-based drawing code had better be able to cope with that scaling without getting confused. PuTTY's isn't, because we do all our serious drawing on a separate Cairo surface we made ourselves, and then blit subrectangles of that to the window during updates. This has two bad consequences. Firstly, our surface has a size derived from what GTK told us the drawing area size is, i.e. corresponding to GTK's _logical_ pixels, so when the scale factor is (say) 2, our drawing takes place at half size and then gets scaled up by the final blit in the draw event, making it look blurry and unpleasant. Secondly, those final blits seem to end up offset by half a pixel, so that a second blit over the same subrectangle doesn't _quite_ completely wipe out the previously blitted data - so there's a ghostly rectangle left behind everywhere the cursor has been. It's not that GTK doesn't _let_ you find out the scale factor; it's just that it's in an out-of-the-way piece of API that you have to call specially. So now we do: our backing surface is now created at a pixel resolution matching the screen's real pixels, and we translate GTK's scale factor into an ordinary cairo_scale() before we commence drawing. So we still end up drawing the same text at the same size - and this strategy also means that non-text elements like cursor outlines and underlining will be scaled up with the screen DPI rather than stubbornly staying one physical pixel thick - but now it's nice and sharp at full screen resolution, and the subrectangle blits in the draw event are back to affecting the exact set of pixels we expect them to. One silly consequence is that, immediately after removing the last one, I've installed a handler for the GTK "configure-event" signal! That's because the GTK 3 docs claim that that's how you get notified that your scale factor has changed at run time (e.g. if you reconfigure the scale factor of a whole monitor in the GNOME settings dialog). Actually in practice I seem to find out via the "draw" event before "configure" bothers to tell me, but now I've got a usefully idempotent function for 'check whether the scale factor has changed and sort it out if so', I don't see any harm in calling it from anywhere it _might_ be useful.
2018-05-11 09:53:05 +03:00
{
if (!inst->drawing_area_setup_needed &&
GTK 3: be aware of the window's scale factor. In GTK 3.10 and above, high-DPI support is arranged by each window having a property called a 'scale factor', which translates logical pixels as seen by most of the GTK API (widget and window sizes and positions, coordinates in the "draw" event, etc) into the physical pixels on the screen. This is handled more or less transparently, except that one side effect is that your Cairo-based drawing code had better be able to cope with that scaling without getting confused. PuTTY's isn't, because we do all our serious drawing on a separate Cairo surface we made ourselves, and then blit subrectangles of that to the window during updates. This has two bad consequences. Firstly, our surface has a size derived from what GTK told us the drawing area size is, i.e. corresponding to GTK's _logical_ pixels, so when the scale factor is (say) 2, our drawing takes place at half size and then gets scaled up by the final blit in the draw event, making it look blurry and unpleasant. Secondly, those final blits seem to end up offset by half a pixel, so that a second blit over the same subrectangle doesn't _quite_ completely wipe out the previously blitted data - so there's a ghostly rectangle left behind everywhere the cursor has been. It's not that GTK doesn't _let_ you find out the scale factor; it's just that it's in an out-of-the-way piece of API that you have to call specially. So now we do: our backing surface is now created at a pixel resolution matching the screen's real pixels, and we translate GTK's scale factor into an ordinary cairo_scale() before we commence drawing. So we still end up drawing the same text at the same size - and this strategy also means that non-text elements like cursor outlines and underlining will be scaled up with the screen DPI rather than stubbornly staying one physical pixel thick - but now it's nice and sharp at full screen resolution, and the subrectangle blits in the draw event are back to affecting the exact set of pixels we expect them to. One silly consequence is that, immediately after removing the last one, I've installed a handler for the GTK "configure-event" signal! That's because the GTK 3 docs claim that that's how you get notified that your scale factor has changed at run time (e.g. if you reconfigure the scale factor of a whole monitor in the GNOME settings dialog). Actually in practice I seem to find out via the "draw" event before "configure" bothers to tell me, but now I've got a usefully idempotent function for 'check whether the scale factor has changed and sort it out if so', I don't see any harm in calling it from anywhere it _might_ be useful.
2018-05-11 09:53:05 +03:00
inst->scale != gtk_widget_get_scale_factor(inst->area)) {
drawing_area_setup_simple(inst);
if (inst->term) {
term_invalidate(inst->term);
term_update(inst->term);
}
}
}
#endif
#if GTK_CHECK_VERSION(3,10,0)
static gboolean area_configured(
GtkWidget *widget, GdkEventConfigure *event, gpointer data)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = (GtkFrontend *)data;
GTK 3: be aware of the window's scale factor. In GTK 3.10 and above, high-DPI support is arranged by each window having a property called a 'scale factor', which translates logical pixels as seen by most of the GTK API (widget and window sizes and positions, coordinates in the "draw" event, etc) into the physical pixels on the screen. This is handled more or less transparently, except that one side effect is that your Cairo-based drawing code had better be able to cope with that scaling without getting confused. PuTTY's isn't, because we do all our serious drawing on a separate Cairo surface we made ourselves, and then blit subrectangles of that to the window during updates. This has two bad consequences. Firstly, our surface has a size derived from what GTK told us the drawing area size is, i.e. corresponding to GTK's _logical_ pixels, so when the scale factor is (say) 2, our drawing takes place at half size and then gets scaled up by the final blit in the draw event, making it look blurry and unpleasant. Secondly, those final blits seem to end up offset by half a pixel, so that a second blit over the same subrectangle doesn't _quite_ completely wipe out the previously blitted data - so there's a ghostly rectangle left behind everywhere the cursor has been. It's not that GTK doesn't _let_ you find out the scale factor; it's just that it's in an out-of-the-way piece of API that you have to call specially. So now we do: our backing surface is now created at a pixel resolution matching the screen's real pixels, and we translate GTK's scale factor into an ordinary cairo_scale() before we commence drawing. So we still end up drawing the same text at the same size - and this strategy also means that non-text elements like cursor outlines and underlining will be scaled up with the screen DPI rather than stubbornly staying one physical pixel thick - but now it's nice and sharp at full screen resolution, and the subrectangle blits in the draw event are back to affecting the exact set of pixels we expect them to. One silly consequence is that, immediately after removing the last one, I've installed a handler for the GTK "configure-event" signal! That's because the GTK 3 docs claim that that's how you get notified that your scale factor has changed at run time (e.g. if you reconfigure the scale factor of a whole monitor in the GNOME settings dialog). Actually in practice I seem to find out via the "draw" event before "configure" bothers to tell me, but now I've got a usefully idempotent function for 'check whether the scale factor has changed and sort it out if so', I don't see any harm in calling it from anywhere it _might_ be useful.
2018-05-11 09:53:05 +03:00
area_check_scale(inst);
return false;
GTK 3: be aware of the window's scale factor. In GTK 3.10 and above, high-DPI support is arranged by each window having a property called a 'scale factor', which translates logical pixels as seen by most of the GTK API (widget and window sizes and positions, coordinates in the "draw" event, etc) into the physical pixels on the screen. This is handled more or less transparently, except that one side effect is that your Cairo-based drawing code had better be able to cope with that scaling without getting confused. PuTTY's isn't, because we do all our serious drawing on a separate Cairo surface we made ourselves, and then blit subrectangles of that to the window during updates. This has two bad consequences. Firstly, our surface has a size derived from what GTK told us the drawing area size is, i.e. corresponding to GTK's _logical_ pixels, so when the scale factor is (say) 2, our drawing takes place at half size and then gets scaled up by the final blit in the draw event, making it look blurry and unpleasant. Secondly, those final blits seem to end up offset by half a pixel, so that a second blit over the same subrectangle doesn't _quite_ completely wipe out the previously blitted data - so there's a ghostly rectangle left behind everywhere the cursor has been. It's not that GTK doesn't _let_ you find out the scale factor; it's just that it's in an out-of-the-way piece of API that you have to call specially. So now we do: our backing surface is now created at a pixel resolution matching the screen's real pixels, and we translate GTK's scale factor into an ordinary cairo_scale() before we commence drawing. So we still end up drawing the same text at the same size - and this strategy also means that non-text elements like cursor outlines and underlining will be scaled up with the screen DPI rather than stubbornly staying one physical pixel thick - but now it's nice and sharp at full screen resolution, and the subrectangle blits in the draw event are back to affecting the exact set of pixels we expect them to. One silly consequence is that, immediately after removing the last one, I've installed a handler for the GTK "configure-event" signal! That's because the GTK 3 docs claim that that's how you get notified that your scale factor has changed at run time (e.g. if you reconfigure the scale factor of a whole monitor in the GNOME settings dialog). Actually in practice I seem to find out via the "draw" event before "configure" bothers to tell me, but now I've got a usefully idempotent function for 'check whether the scale factor has changed and sort it out if so', I don't see any harm in calling it from anywhere it _might_ be useful.
2018-05-11 09:53:05 +03:00
}
#endif
#ifdef DRAW_TEXT_CAIRO
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
static void cairo_setup_draw_ctx(GtkFrontend *inst)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
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);
/* 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 */
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
cairo_set_antialias(inst->uctx.u.cairo.cr, CAIRO_ANTIALIAS_NONE);
}
#endif
#if GTK_CHECK_VERSION(3,0,0)
static gint draw_area(GtkWidget *widget, cairo_t *cr, gpointer data)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = (GtkFrontend *)data;
GTK 3: be aware of the window's scale factor. In GTK 3.10 and above, high-DPI support is arranged by each window having a property called a 'scale factor', which translates logical pixels as seen by most of the GTK API (widget and window sizes and positions, coordinates in the "draw" event, etc) into the physical pixels on the screen. This is handled more or less transparently, except that one side effect is that your Cairo-based drawing code had better be able to cope with that scaling without getting confused. PuTTY's isn't, because we do all our serious drawing on a separate Cairo surface we made ourselves, and then blit subrectangles of that to the window during updates. This has two bad consequences. Firstly, our surface has a size derived from what GTK told us the drawing area size is, i.e. corresponding to GTK's _logical_ pixels, so when the scale factor is (say) 2, our drawing takes place at half size and then gets scaled up by the final blit in the draw event, making it look blurry and unpleasant. Secondly, those final blits seem to end up offset by half a pixel, so that a second blit over the same subrectangle doesn't _quite_ completely wipe out the previously blitted data - so there's a ghostly rectangle left behind everywhere the cursor has been. It's not that GTK doesn't _let_ you find out the scale factor; it's just that it's in an out-of-the-way piece of API that you have to call specially. So now we do: our backing surface is now created at a pixel resolution matching the screen's real pixels, and we translate GTK's scale factor into an ordinary cairo_scale() before we commence drawing. So we still end up drawing the same text at the same size - and this strategy also means that non-text elements like cursor outlines and underlining will be scaled up with the screen DPI rather than stubbornly staying one physical pixel thick - but now it's nice and sharp at full screen resolution, and the subrectangle blits in the draw event are back to affecting the exact set of pixels we expect them to. One silly consequence is that, immediately after removing the last one, I've installed a handler for the GTK "configure-event" signal! That's because the GTK 3 docs claim that that's how you get notified that your scale factor has changed at run time (e.g. if you reconfigure the scale factor of a whole monitor in the GNOME settings dialog). Actually in practice I seem to find out via the "draw" event before "configure" bothers to tell me, but now I've got a usefully idempotent function for 'check whether the scale factor has changed and sort it out if so', I don't see any harm in calling it from anywhere it _might_ be useful.
2018-05-11 09:53:05 +03:00
#if GTK_CHECK_VERSION(3,10,0)
/*
* This may be the first we hear of the window scale having
* changed, in which case we must hastily reconstruct our backing
* surface before we copy the wrong one into the newly resized
* real window.
*/
area_check_scale(inst);
#endif
Use a Cairo image surface as a client-side cache. In any DRAWTYPE_CAIRO mode, we now do all our Cairo drawing to a Cairo image surface which lives on the client; then we either blit directly from that to the window (if we're in GTK3 mode, or GTK2 without deprecated pieces of API), or else we blit from the Cairo surface to the server-side pixmap and then from there to the actual window. In DRAWTYPE_GDK mode, nothing much has changed: we still draw directly to the server-side pixmap using the GDK drawing API, then blit from there to the window. But there is one change, namely that the blit is no longer done proactively - instead, we queue a redraw of the affected rectangle, and wait until we're called back by the expose handler. The main aim of all this is to arrange that the only time we ever draw to the real window is in response to expose/draw events. The experimental GTK3 OS X port stopped working a week or two ago (I presume in response to an OS update) with the symptoms that attempts to draw on the window outside the context of a "draw" event handler just didn't seem to work any more; this change fixes it. In addition to that benefit, this change also has obvious performance advantages in principle. No more expensive text rendering in response to an expose event - just re-copy to the window from the bitmap we already have, from wherever it's stored that's nearest. Moreover, this seems to have fixed the significant performance problem with X server-side fonts under GTK. I didn't expect _that_! I'd guessed that the approach of downloading character bitmaps and rendering them manually via Cairo was just inherently slow for some reason. I've no real idea _why_ this change improves matters so much; my best guess is that perhaps there's an overhead in each drawing operation to a GDK Cairo surface, so we win by doing lots of operations to a much faster image surface and then batching them up into one GDK Cairo operation. But whyever it is, I'm certainly not complaining! (In fact, it now seems to be noticeably _faster_, at least on my usual local X displays, to draw server-side fonts using that technique than using the old GDK approach. I may yet decide to switch over...)
2015-09-24 16:08:25 +03:00
/*
* GTK3 window redraw: we always expect Cairo to be enabled, so
* that inst->surface exists, and pixmaps to be disabled, so that
* inst->pixmap does not exist. Hence, we just blit from
* inst->surface to the window.
*/
if (inst->surface) {
GdkRectangle dirtyrect;
GTK 3: be aware of the window's scale factor. In GTK 3.10 and above, high-DPI support is arranged by each window having a property called a 'scale factor', which translates logical pixels as seen by most of the GTK API (widget and window sizes and positions, coordinates in the "draw" event, etc) into the physical pixels on the screen. This is handled more or less transparently, except that one side effect is that your Cairo-based drawing code had better be able to cope with that scaling without getting confused. PuTTY's isn't, because we do all our serious drawing on a separate Cairo surface we made ourselves, and then blit subrectangles of that to the window during updates. This has two bad consequences. Firstly, our surface has a size derived from what GTK told us the drawing area size is, i.e. corresponding to GTK's _logical_ pixels, so when the scale factor is (say) 2, our drawing takes place at half size and then gets scaled up by the final blit in the draw event, making it look blurry and unpleasant. Secondly, those final blits seem to end up offset by half a pixel, so that a second blit over the same subrectangle doesn't _quite_ completely wipe out the previously blitted data - so there's a ghostly rectangle left behind everywhere the cursor has been. It's not that GTK doesn't _let_ you find out the scale factor; it's just that it's in an out-of-the-way piece of API that you have to call specially. So now we do: our backing surface is now created at a pixel resolution matching the screen's real pixels, and we translate GTK's scale factor into an ordinary cairo_scale() before we commence drawing. So we still end up drawing the same text at the same size - and this strategy also means that non-text elements like cursor outlines and underlining will be scaled up with the screen DPI rather than stubbornly staying one physical pixel thick - but now it's nice and sharp at full screen resolution, and the subrectangle blits in the draw event are back to affecting the exact set of pixels we expect them to. One silly consequence is that, immediately after removing the last one, I've installed a handler for the GTK "configure-event" signal! That's because the GTK 3 docs claim that that's how you get notified that your scale factor has changed at run time (e.g. if you reconfigure the scale factor of a whole monitor in the GNOME settings dialog). Actually in practice I seem to find out via the "draw" event before "configure" bothers to tell me, but now I've got a usefully idempotent function for 'check whether the scale factor has changed and sort it out if so', I don't see any harm in calling it from anywhere it _might_ be useful.
2018-05-11 09:53:05 +03:00
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));
gdk_cairo_get_clip_rectangle(cr, &dirtyrect);
Use a Cairo image surface as a client-side cache. In any DRAWTYPE_CAIRO mode, we now do all our Cairo drawing to a Cairo image surface which lives on the client; then we either blit directly from that to the window (if we're in GTK3 mode, or GTK2 without deprecated pieces of API), or else we blit from the Cairo surface to the server-side pixmap and then from there to the actual window. In DRAWTYPE_GDK mode, nothing much has changed: we still draw directly to the server-side pixmap using the GDK drawing API, then blit from there to the window. But there is one change, namely that the blit is no longer done proactively - instead, we queue a redraw of the affected rectangle, and wait until we're called back by the expose handler. The main aim of all this is to arrange that the only time we ever draw to the real window is in response to expose/draw events. The experimental GTK3 OS X port stopped working a week or two ago (I presume in response to an OS update) with the symptoms that attempts to draw on the window outside the context of a "draw" event handler just didn't seem to work any more; this change fixes it. In addition to that benefit, this change also has obvious performance advantages in principle. No more expensive text rendering in response to an expose event - just re-copy to the window from the bitmap we already have, from wherever it's stored that's nearest. Moreover, this seems to have fixed the significant performance problem with X server-side fonts under GTK. I didn't expect _that_! I'd guessed that the approach of downloading character bitmaps and rendering them manually via Cairo was just inherently slow for some reason. I've no real idea _why_ this change improves matters so much; my best guess is that perhaps there's an overhead in each drawing operation to a GDK Cairo surface, so we win by doing lots of operations to a much faster image surface and then batching them up into one GDK Cairo operation. But whyever it is, I'm certainly not complaining! (In fact, it now seems to be noticeably _faster_, at least on my usual local X displays, to draw server-side fonts using that technique than using the old GDK approach. I may yet decide to switch over...)
2015-09-24 16:08:25 +03:00
cairo_set_source_surface(cr, inst->surface, 0, 0);
cairo_rectangle(cr, dirtyrect.x, dirtyrect.y,
dirtyrect.width, dirtyrect.height);
cairo_fill(cr);
GTK 3: be aware of the window's scale factor. In GTK 3.10 and above, high-DPI support is arranged by each window having a property called a 'scale factor', which translates logical pixels as seen by most of the GTK API (widget and window sizes and positions, coordinates in the "draw" event, etc) into the physical pixels on the screen. This is handled more or less transparently, except that one side effect is that your Cairo-based drawing code had better be able to cope with that scaling without getting confused. PuTTY's isn't, because we do all our serious drawing on a separate Cairo surface we made ourselves, and then blit subrectangles of that to the window during updates. This has two bad consequences. Firstly, our surface has a size derived from what GTK told us the drawing area size is, i.e. corresponding to GTK's _logical_ pixels, so when the scale factor is (say) 2, our drawing takes place at half size and then gets scaled up by the final blit in the draw event, making it look blurry and unpleasant. Secondly, those final blits seem to end up offset by half a pixel, so that a second blit over the same subrectangle doesn't _quite_ completely wipe out the previously blitted data - so there's a ghostly rectangle left behind everywhere the cursor has been. It's not that GTK doesn't _let_ you find out the scale factor; it's just that it's in an out-of-the-way piece of API that you have to call specially. So now we do: our backing surface is now created at a pixel resolution matching the screen's real pixels, and we translate GTK's scale factor into an ordinary cairo_scale() before we commence drawing. So we still end up drawing the same text at the same size - and this strategy also means that non-text elements like cursor outlines and underlining will be scaled up with the screen DPI rather than stubbornly staying one physical pixel thick - but now it's nice and sharp at full screen resolution, and the subrectangle blits in the draw event are back to affecting the exact set of pixels we expect them to. One silly consequence is that, immediately after removing the last one, I've installed a handler for the GTK "configure-event" signal! That's because the GTK 3 docs claim that that's how you get notified that your scale factor has changed at run time (e.g. if you reconfigure the scale factor of a whole monitor in the GNOME settings dialog). Actually in practice I seem to find out via the "draw" event before "configure" bothers to tell me, but now I've got a usefully idempotent function for 'check whether the scale factor has changed and sort it out if so', I don't see any harm in calling it from anywhere it _might_ be useful.
2018-05-11 09:53:05 +03:00
cairo_surface_set_device_scale(target_surface, orig_sx, orig_sy);
}
return true;
}
#else
gint expose_area(GtkWidget *widget, GdkEventExpose *event, gpointer data)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = (GtkFrontend *)data;
#ifndef NO_BACKING_PIXMAPS
/*
Use a Cairo image surface as a client-side cache. In any DRAWTYPE_CAIRO mode, we now do all our Cairo drawing to a Cairo image surface which lives on the client; then we either blit directly from that to the window (if we're in GTK3 mode, or GTK2 without deprecated pieces of API), or else we blit from the Cairo surface to the server-side pixmap and then from there to the actual window. In DRAWTYPE_GDK mode, nothing much has changed: we still draw directly to the server-side pixmap using the GDK drawing API, then blit from there to the window. But there is one change, namely that the blit is no longer done proactively - instead, we queue a redraw of the affected rectangle, and wait until we're called back by the expose handler. The main aim of all this is to arrange that the only time we ever draw to the real window is in response to expose/draw events. The experimental GTK3 OS X port stopped working a week or two ago (I presume in response to an OS update) with the symptoms that attempts to draw on the window outside the context of a "draw" event handler just didn't seem to work any more; this change fixes it. In addition to that benefit, this change also has obvious performance advantages in principle. No more expensive text rendering in response to an expose event - just re-copy to the window from the bitmap we already have, from wherever it's stored that's nearest. Moreover, this seems to have fixed the significant performance problem with X server-side fonts under GTK. I didn't expect _that_! I'd guessed that the approach of downloading character bitmaps and rendering them manually via Cairo was just inherently slow for some reason. I've no real idea _why_ this change improves matters so much; my best guess is that perhaps there's an overhead in each drawing operation to a GDK Cairo surface, so we win by doing lots of operations to a much faster image surface and then batching them up into one GDK Cairo operation. But whyever it is, I'm certainly not complaining! (In fact, it now seems to be noticeably _faster_, at least on my usual local X displays, to draw server-side fonts using that technique than using the old GDK approach. I may yet decide to switch over...)
2015-09-24 16:08:25 +03:00
* Draw to the exposed part of the window from the server-side
* backing pixmap.
*/
if (inst->pixmap) {
gdk_draw_pixmap(gtk_widget_get_window(widget),
(gtk_widget_get_style(widget)->fg_gc
[gtk_widget_get_state(widget)]),
inst->pixmap,
event->area.x, event->area.y,
event->area.x, event->area.y,
event->area.width, event->area.height);
}
#else
Use a Cairo image surface as a client-side cache. In any DRAWTYPE_CAIRO mode, we now do all our Cairo drawing to a Cairo image surface which lives on the client; then we either blit directly from that to the window (if we're in GTK3 mode, or GTK2 without deprecated pieces of API), or else we blit from the Cairo surface to the server-side pixmap and then from there to the actual window. In DRAWTYPE_GDK mode, nothing much has changed: we still draw directly to the server-side pixmap using the GDK drawing API, then blit from there to the window. But there is one change, namely that the blit is no longer done proactively - instead, we queue a redraw of the affected rectangle, and wait until we're called back by the expose handler. The main aim of all this is to arrange that the only time we ever draw to the real window is in response to expose/draw events. The experimental GTK3 OS X port stopped working a week or two ago (I presume in response to an OS update) with the symptoms that attempts to draw on the window outside the context of a "draw" event handler just didn't seem to work any more; this change fixes it. In addition to that benefit, this change also has obvious performance advantages in principle. No more expensive text rendering in response to an expose event - just re-copy to the window from the bitmap we already have, from wherever it's stored that's nearest. Moreover, this seems to have fixed the significant performance problem with X server-side fonts under GTK. I didn't expect _that_! I'd guessed that the approach of downloading character bitmaps and rendering them manually via Cairo was just inherently slow for some reason. I've no real idea _why_ this change improves matters so much; my best guess is that perhaps there's an overhead in each drawing operation to a GDK Cairo surface, so we win by doing lots of operations to a much faster image surface and then batching them up into one GDK Cairo operation. But whyever it is, I'm certainly not complaining! (In fact, it now seems to be noticeably _faster_, at least on my usual local X displays, to draw server-side fonts using that technique than using the old GDK approach. I may yet decide to switch over...)
2015-09-24 16:08:25 +03:00
/*
* Failing that, draw from the client-side Cairo surface. (We
* should never be compiled in a context where we have _neither_
* inst->surface nor inst->pixmap.)
*/
if (inst->surface) {
cairo_t *cr = gdk_cairo_create(gtk_widget_get_window(widget));
cairo_set_source_surface(cr, inst->surface, 0, 0);
cairo_rectangle(cr, event->area.x, event->area.y,
event->area.width, event->area.height);
cairo_fill(cr);
cairo_destroy(cr);
}
#endif
return true;
}
#endif
#define KEY_PRESSED(k) \
(inst->keystate[(k) / 32] & (1 << ((k) % 32)))
#ifdef KEY_EVENT_DIAGNOSTICS
char *dup_keyval_name(guint keyval)
{
const char *name = gdk_keyval_name(keyval);
if (name)
return dupstr(name);
else
return dupprintf("UNKNOWN[%u]", (unsigned)keyval);
}
#endif
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
static void change_font_size(GtkFrontend *inst, int increment);
static void key_pressed(GtkFrontend *inst);
gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = (GtkFrontend *)data;
char output[256];
wchar_t ucsoutput[2];
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
int ucsval, start, end, output_charset;
bool special, use_ucsoutput;
bool nethack_mode, app_keypad_mode;
Centralise key escape sequences into terminal.c. A long time ago, in commit 4d77b6567, I moved the generation of the arrow-key escape sequences into a function format_arrow_key(). Mostly the reason for that was a special purpose I had in mind at the time which involved auto-generating the same sequences in response to things other than a keypress, but I always thought it would be nice to centralise a lot more of PuTTY's complicated keyboard handling in the same way - at least the handling of the function keys and their numerous static and dynamic config options. In this year's general spirit of tidying up and refactoring, I think it's finally time. So here I introduce three more centralised functions for dealing with the numbered function keys, the small keypad (Ins, Home, PgUp etc) and the numeric keypad. Lots of horrible and duplicated code from the key handling functions in window.c and gtkwin.c is now more sensibly centralised: each platform keyboard handler concerns itself with the local format of a keyboard event and platform-specific enumeration of key codes, and once it's decided what the logical key press actually _is_, it hands off to the new functions in terminal.c to generate the appropriate escape code. Mostly this is intended to be a refactoring without functional change, leaving the keyboard handling how it's always been. But in cases where the Windows and GTK handlers were accidentally inconsistent, I've fixed the inconsistency rather than carefully keeping both sides how they were. Known consistency fixes: - swapping the arrow keys between normal (ESC [ A) and application (ESC O A) is now done by pressing Ctrl with them, and _not_ by pressing Shift. That was how it was always supposed to work, and how it's worked on GTK all along, but on Windows it's been done by Shift as well since 2010, due to a bug at the call site of format_arrow_key() introduced when I originally wrote that function. - in Xterm function key mode plus application keypad mode, the /*- keys on the numeric keypad now send ESC O {o,j,m} in place of ESC O {Q,R,S}. That's how the Windows keyboard handler has worked all along (it was a deliberate behaviour tweak for the Xterm-like function key mode, because in that mode ESC O {Q,R,S} are generated by F2-F4). But the GTK keyboard handler omitted that particular special case and was still sending ESC O {Q,R,S} for those keys in all application keypad modes. - also in Xterm function key mode plus app keypad mode, we only generates the app-keypad escape sequences if Num Lock is on; with Num Lock off, the numeric keypad becomes arrow keys and Home/End/etc, just as it would in non-app-keypad mode. Windows has done this all along, but again, GTK lacked that special case.
2018-12-08 11:25:32 +03:00
bool force_format_numeric_keypad = false;
bool generated_something = false;
Centralise key escape sequences into terminal.c. A long time ago, in commit 4d77b6567, I moved the generation of the arrow-key escape sequences into a function format_arrow_key(). Mostly the reason for that was a special purpose I had in mind at the time which involved auto-generating the same sequences in response to things other than a keypress, but I always thought it would be nice to centralise a lot more of PuTTY's complicated keyboard handling in the same way - at least the handling of the function keys and their numerous static and dynamic config options. In this year's general spirit of tidying up and refactoring, I think it's finally time. So here I introduce three more centralised functions for dealing with the numbered function keys, the small keypad (Ins, Home, PgUp etc) and the numeric keypad. Lots of horrible and duplicated code from the key handling functions in window.c and gtkwin.c is now more sensibly centralised: each platform keyboard handler concerns itself with the local format of a keyboard event and platform-specific enumeration of key codes, and once it's decided what the logical key press actually _is_, it hands off to the new functions in terminal.c to generate the appropriate escape code. Mostly this is intended to be a refactoring without functional change, leaving the keyboard handling how it's always been. But in cases where the Windows and GTK handlers were accidentally inconsistent, I've fixed the inconsistency rather than carefully keeping both sides how they were. Known consistency fixes: - swapping the arrow keys between normal (ESC [ A) and application (ESC O A) is now done by pressing Ctrl with them, and _not_ by pressing Shift. That was how it was always supposed to work, and how it's worked on GTK all along, but on Windows it's been done by Shift as well since 2010, due to a bug at the call site of format_arrow_key() introduced when I originally wrote that function. - in Xterm function key mode plus application keypad mode, the /*- keys on the numeric keypad now send ESC O {o,j,m} in place of ESC O {Q,R,S}. That's how the Windows keyboard handler has worked all along (it was a deliberate behaviour tweak for the Xterm-like function key mode, because in that mode ESC O {Q,R,S} are generated by F2-F4). But the GTK keyboard handler omitted that particular special case and was still sending ESC O {Q,R,S} for those keys in all application keypad modes. - also in Xterm function key mode plus app keypad mode, we only generates the app-keypad escape sequences if Num Lock is on; with Num Lock off, the numeric keypad becomes arrow keys and Home/End/etc, just as it would in non-app-keypad mode. Windows has done this all along, but again, GTK lacked that special case.
2018-12-08 11:25:32 +03:00
char num_keypad_key = '\0';
noise_ultralight(NOISE_SOURCE_KEY, event->keyval);
#ifdef OSX_META_KEY_CONFIG
if (event->state & inst->system_mod_mask)
return false; /* let GTK process OS X Command key */
#endif
/* Remember the timestamp. */
inst->input_event_time = event->time;
/* By default, nothing is generated. */
end = start = 0;
special = use_ucsoutput = false;
output_charset = CS_ISO8859_1;
#ifdef KEY_EVENT_DIAGNOSTICS
{
char *type_string, *state_string, *keyval_string, *string_string;
type_string = (event->type == GDK_KEY_PRESS ? dupstr("PRESS") :
event->type == GDK_KEY_RELEASE ? dupstr("RELEASE") :
dupprintf("UNKNOWN[%d]", (int)event->type));
{
static const struct {
int mod_bit;
const char *name;
} mod_bits[] = {
{GDK_SHIFT_MASK, "SHIFT"},
{GDK_LOCK_MASK, "LOCK"},
{GDK_CONTROL_MASK, "CONTROL"},
{GDK_MOD1_MASK, "MOD1"},
{GDK_MOD2_MASK, "MOD2"},
{GDK_MOD3_MASK, "MOD3"},
{GDK_MOD4_MASK, "MOD4"},
{GDK_MOD5_MASK, "MOD5"},
{GDK_SUPER_MASK, "SUPER"},
{GDK_HYPER_MASK, "HYPER"},
{GDK_META_MASK, "META"},
};
int i;
int val = event->state;
state_string = dupstr("");
for (i = 0; i < lenof(mod_bits); i++) {
if (val & mod_bits[i].mod_bit) {
char *old = state_string;
state_string = dupcat(state_string,
state_string[0] ? "|" : "",
mod_bits[i].name,
(char *)NULL);
sfree(old);
val &= ~mod_bits[i].mod_bit;
}
}
if (val || !state_string[0]) {
char *old = state_string;
state_string = dupprintf("%s%s%d", state_string,
state_string[0] ? "|" : "", val);
sfree(old);
}
}
keyval_string = dup_keyval_name(event->keyval);
string_string = dupstr("");
{
int i;
for (i = 0; event->string[i]; i++) {
char *old = string_string;
string_string = dupprintf("%s%s%02x", string_string,
string_string[0] ? " " : "",
(unsigned)event->string[i] & 0xFF);
sfree(old);
}
}
debug("key_event: type=%s keyval=%s state=%s "
"hardware_keycode=%d is_modifier=%s string=[%s]\n",
type_string, keyval_string, state_string,
(int)event->hardware_keycode,
event->is_modifier ? "true" : "false",
string_string);
sfree(type_string);
sfree(state_string);
sfree(keyval_string);
sfree(string_string);
}
#endif /* KEY_EVENT_DIAGNOSTICS */
/*
* If Alt is being released after typing an Alt+numberpad
* sequence, we should generate the code that was typed.
*
* Note that we only do this if more than one key was actually
* pressed - I don't think Alt+NumPad4 should be ^D or that
* Alt+NumPad3 should be ^C, for example. There's no serious
* inconvenience in having to type a zero before a single-digit
* character code.
*/
if (event->type == GDK_KEY_RELEASE) {
if ((event->keyval == GDK_KEY_Meta_L ||
event->keyval == GDK_KEY_Meta_R ||
event->keyval == GDK_KEY_Alt_L ||
event->keyval == GDK_KEY_Alt_R) &&
inst->alt_keycode >= 0 && inst->alt_digits > 1) {
#ifdef KEY_EVENT_DIAGNOSTICS
debug(" - modifier release terminates Alt+numberpad input, "
"keycode = %d\n", inst->alt_keycode);
#endif
/*
* FIXME: we might usefully try to do something clever here
* about interpreting the generated key code in a way that's
* appropriate to the line code page.
*/
output[0] = inst->alt_keycode;
end = 1;
goto done;
}
#if GTK_CHECK_VERSION(2,0,0)
#ifdef KEY_EVENT_DIAGNOSTICS
debug(" - key release, passing to IM\n");
#endif
if (gtk_im_context_filter_keypress(inst->imc, event)) {
#ifdef KEY_EVENT_DIAGNOSTICS
debug(" - key release accepted by IM\n");
#endif
return true;
} else {
#ifdef KEY_EVENT_DIAGNOSTICS
debug(" - key release not accepted by IM\n");
#endif
}
#endif
}
if (event->type == GDK_KEY_PRESS) {
/*
* If Alt has just been pressed, we start potentially
* accumulating an Alt+numberpad code. We do this by
* setting alt_keycode to -1 (nothing yet but plausible).
*/
if ((event->keyval == GDK_KEY_Meta_L ||
event->keyval == GDK_KEY_Meta_R ||
event->keyval == GDK_KEY_Alt_L ||
event->keyval == GDK_KEY_Alt_R)) {
#ifdef KEY_EVENT_DIAGNOSTICS
debug(" - modifier press potentially begins Alt+numberpad "
"input\n");
#endif
inst->alt_keycode = -1;
inst->alt_digits = 0;
goto done; /* this generates nothing else */
}
/*
* If we're seeing a numberpad key press with Meta down,
* consider adding it to alt_keycode if that's sensible.
* Anything _else_ with Meta down cancels any possibility
* of an ALT keycode: we set alt_keycode to -2.
*/
if ((event->state & inst->meta_mod_mask) && inst->alt_keycode != -2) {
int digit = -1;
switch (event->keyval) {
case GDK_KEY_KP_0: case GDK_KEY_KP_Insert: digit = 0; break;
case GDK_KEY_KP_1: case GDK_KEY_KP_End: digit = 1; break;
case GDK_KEY_KP_2: case GDK_KEY_KP_Down: digit = 2; break;
case GDK_KEY_KP_3: case GDK_KEY_KP_Page_Down: digit = 3; break;
case GDK_KEY_KP_4: case GDK_KEY_KP_Left: digit = 4; break;
case GDK_KEY_KP_5: case GDK_KEY_KP_Begin: digit = 5; break;
case GDK_KEY_KP_6: case GDK_KEY_KP_Right: digit = 6; break;
case GDK_KEY_KP_7: case GDK_KEY_KP_Home: digit = 7; break;
case GDK_KEY_KP_8: case GDK_KEY_KP_Up: digit = 8; break;
case GDK_KEY_KP_9: case GDK_KEY_KP_Page_Up: digit = 9; break;
}
if (digit < 0)
inst->alt_keycode = -2; /* it's invalid */
else {
#ifdef KEY_EVENT_DIAGNOSTICS
int old_keycode = inst->alt_keycode;
#endif
if (inst->alt_keycode == -1)
inst->alt_keycode = digit; /* one-digit code */
else
inst->alt_keycode = inst->alt_keycode * 10 + digit;
inst->alt_digits++;
#ifdef KEY_EVENT_DIAGNOSTICS
debug(" - Alt+numberpad digit %d added to keycode %d"
" gives %d\n", digit, old_keycode, inst->alt_keycode);
#endif
/* Having used this digit, we now do nothing more with it. */
goto done;
}
}
if (event->keyval == GDK_KEY_greater &&
(event->state & GDK_CONTROL_MASK)) {
#ifdef KEY_EVENT_DIAGNOSTICS
debug(" - Ctrl->: increase font size\n");
#endif
change_font_size(inst, +1);
return true;
}
if (event->keyval == GDK_KEY_less &&
(event->state & GDK_CONTROL_MASK)) {
#ifdef KEY_EVENT_DIAGNOSTICS
debug(" - Ctrl-<: increase font size\n");
#endif
change_font_size(inst, -1);
return true;
}
/*
* Shift-PgUp and Shift-PgDn don't even generate keystrokes
* at all.
*/
if (event->keyval == GDK_KEY_Page_Up &&
((event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) ==
(GDK_CONTROL_MASK | GDK_SHIFT_MASK))) {
#ifdef KEY_EVENT_DIAGNOSTICS
debug(" - Ctrl-Shift-PgUp scroll\n");
#endif
term_scroll(inst->term, 1, 0);
return true;
}
if (event->keyval == GDK_KEY_Page_Up &&
(event->state & GDK_SHIFT_MASK)) {
#ifdef KEY_EVENT_DIAGNOSTICS
debug(" - Shift-PgUp scroll\n");
#endif
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
term_scroll(inst->term, 0, -inst->height/2);
return true;
}
if (event->keyval == GDK_KEY_Page_Up &&
(event->state & GDK_CONTROL_MASK)) {
#ifdef KEY_EVENT_DIAGNOSTICS
debug(" - Ctrl-PgUp scroll\n");
#endif
term_scroll(inst->term, 0, -1);
return true;
}
if (event->keyval == GDK_KEY_Page_Down &&
((event->state & (GDK_CONTROL_MASK | GDK_SHIFT_MASK)) ==
(GDK_CONTROL_MASK | GDK_SHIFT_MASK))) {
#ifdef KEY_EVENT_DIAGNOSTICS
debug(" - Ctrl-shift-PgDn scroll\n");
#endif
term_scroll(inst->term, -1, 0);
return true;
}
if (event->keyval == GDK_KEY_Page_Down &&
(event->state & GDK_SHIFT_MASK)) {
#ifdef KEY_EVENT_DIAGNOSTICS
debug(" - Shift-PgDn scroll\n");
#endif
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
term_scroll(inst->term, 0, +inst->height/2);
return true;
}
if (event->keyval == GDK_KEY_Page_Down &&
(event->state & GDK_CONTROL_MASK)) {
#ifdef KEY_EVENT_DIAGNOSTICS
debug(" - Ctrl-PgDn scroll\n");
#endif
term_scroll(inst->term, 0, +1);
return true;
}
/*
* Neither do Shift-Ins or Ctrl-Ins (if enabled).
*/
if (event->keyval == GDK_KEY_Insert &&
(event->state & GDK_SHIFT_MASK)) {
int cfgval = conf_get_int(inst->conf, CONF_ctrlshiftins);
switch (cfgval) {
case CLIPUI_IMPLICIT:
#ifdef KEY_EVENT_DIAGNOSTICS
debug(" - Shift-Insert: paste from PRIMARY\n");
#endif
term_request_paste(inst->term, CLIP_PRIMARY);
return true;
case CLIPUI_EXPLICIT:
#ifdef KEY_EVENT_DIAGNOSTICS
debug(" - Shift-Insert: paste from CLIPBOARD\n");
#endif
term_request_paste(inst->term, CLIP_CLIPBOARD);
return true;
case CLIPUI_CUSTOM:
#ifdef KEY_EVENT_DIAGNOSTICS
debug(" - Shift-Insert: paste from custom clipboard\n");
#endif
term_request_paste(inst->term, inst->clipboard_ctrlshiftins);
return true;
default:
#ifdef KEY_EVENT_DIAGNOSTICS
debug(" - Shift-Insert: no paste action\n");
#endif
break;
}
}
if (event->keyval == GDK_KEY_Insert &&
(event->state & GDK_CONTROL_MASK)) {
static const int clips_clipboard[] = { CLIP_CLIPBOARD };
int cfgval = conf_get_int(inst->conf, CONF_ctrlshiftins);
switch (cfgval) {
case CLIPUI_IMPLICIT:
/* do nothing; re-copy to PRIMARY is not needed */
#ifdef KEY_EVENT_DIAGNOSTICS
debug(" - Ctrl-Insert: non-copy to PRIMARY\n");
#endif
return true;
case CLIPUI_EXPLICIT:
#ifdef KEY_EVENT_DIAGNOSTICS
debug(" - Ctrl-Insert: copy to CLIPBOARD\n");
#endif
term_request_copy(inst->term,
clips_clipboard, lenof(clips_clipboard));
return true;
case CLIPUI_CUSTOM:
#ifdef KEY_EVENT_DIAGNOSTICS
debug(" - Ctrl-Insert: copy to custom clipboard\n");
#endif
term_request_copy(inst->term,
&inst->clipboard_ctrlshiftins, 1);
return true;
default:
#ifdef KEY_EVENT_DIAGNOSTICS
debug(" - Ctrl-Insert: no copy action\n");
#endif
break;
}
}
/*
* Another pair of copy-paste keys.
*/
if ((event->state & GDK_SHIFT_MASK) &&
(event->state & GDK_CONTROL_MASK) &&
(event->keyval == GDK_KEY_C || event->keyval == GDK_KEY_c ||
event->keyval == GDK_KEY_V || event->keyval == GDK_KEY_v)) {
int cfgval = conf_get_int(inst->conf, CONF_ctrlshiftcv);
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
bool paste = (event->keyval == GDK_KEY_V ||
event->keyval == GDK_KEY_v);
switch (cfgval) {
case CLIPUI_IMPLICIT:
if (paste) {
#ifdef KEY_EVENT_DIAGNOSTICS
debug(" - Ctrl-Shift-V: paste from PRIMARY\n");
#endif
term_request_paste(inst->term, CLIP_PRIMARY);
} else {
#ifdef KEY_EVENT_DIAGNOSTICS
debug(" - Ctrl-Shift-C: non-copy to PRIMARY\n");
#endif
}
return true;
case CLIPUI_EXPLICIT:
if (paste) {
#ifdef KEY_EVENT_DIAGNOSTICS
debug(" - Ctrl-Shift-V: paste from CLIPBOARD\n");
#endif
term_request_paste(inst->term, CLIP_CLIPBOARD);
} else {
static const int clips[] = { CLIP_CLIPBOARD };
#ifdef KEY_EVENT_DIAGNOSTICS
debug(" - Ctrl-Shift-C: copy to CLIPBOARD\n");
#endif
term_request_copy(inst->term, clips, lenof(clips));
}
return true;
case CLIPUI_CUSTOM:
if (paste) {
#ifdef KEY_EVENT_DIAGNOSTICS
debug(" - Ctrl-Shift-V: paste from custom clipboard\n");
#endif
term_request_paste(inst->term,
inst->clipboard_ctrlshiftcv);
} else {
#ifdef KEY_EVENT_DIAGNOSTICS
debug(" - Ctrl-Shift-C: copy to custom clipboard\n");
#endif
term_request_copy(inst->term,
&inst->clipboard_ctrlshiftcv, 1);
}
return true;
}
}
special = false;
use_ucsoutput = false;
nethack_mode = conf_get_bool(inst->conf, CONF_nethack_keypad);
app_keypad_mode = (inst->term->app_keypad_keys &&
!conf_get_bool(inst->conf, CONF_no_applic_k));
/* ALT+things gives leading Escape. */
output[0] = '\033';
#if !GTK_CHECK_VERSION(2,0,0)
/*
* In vanilla X, and hence also GDK 1.2, the string received
* as part of a keyboard event is assumed to be in
* ISO-8859-1. (Seems woefully shortsighted in i18n terms,
* but it's true: see the man page for XLookupString(3) for
* confirmation.)
*/
output_charset = CS_ISO8859_1;
strncpy(output+1, event->string, lenof(output)-1);
#else /* !GTK_CHECK_VERSION(2,0,0) */
/*
* Most things can now be passed to
* gtk_im_context_filter_keypress without breaking anything
* below this point. An exception is the numeric keypad if
* we're in Nethack or application mode: the IM will eat
* numeric keypad presses if Num Lock is on, but we don't want
* it to.
*/
Centralise key escape sequences into terminal.c. A long time ago, in commit 4d77b6567, I moved the generation of the arrow-key escape sequences into a function format_arrow_key(). Mostly the reason for that was a special purpose I had in mind at the time which involved auto-generating the same sequences in response to things other than a keypress, but I always thought it would be nice to centralise a lot more of PuTTY's complicated keyboard handling in the same way - at least the handling of the function keys and their numerous static and dynamic config options. In this year's general spirit of tidying up and refactoring, I think it's finally time. So here I introduce three more centralised functions for dealing with the numbered function keys, the small keypad (Ins, Home, PgUp etc) and the numeric keypad. Lots of horrible and duplicated code from the key handling functions in window.c and gtkwin.c is now more sensibly centralised: each platform keyboard handler concerns itself with the local format of a keyboard event and platform-specific enumeration of key codes, and once it's decided what the logical key press actually _is_, it hands off to the new functions in terminal.c to generate the appropriate escape code. Mostly this is intended to be a refactoring without functional change, leaving the keyboard handling how it's always been. But in cases where the Windows and GTK handlers were accidentally inconsistent, I've fixed the inconsistency rather than carefully keeping both sides how they were. Known consistency fixes: - swapping the arrow keys between normal (ESC [ A) and application (ESC O A) is now done by pressing Ctrl with them, and _not_ by pressing Shift. That was how it was always supposed to work, and how it's worked on GTK all along, but on Windows it's been done by Shift as well since 2010, due to a bug at the call site of format_arrow_key() introduced when I originally wrote that function. - in Xterm function key mode plus application keypad mode, the /*- keys on the numeric keypad now send ESC O {o,j,m} in place of ESC O {Q,R,S}. That's how the Windows keyboard handler has worked all along (it was a deliberate behaviour tweak for the Xterm-like function key mode, because in that mode ESC O {Q,R,S} are generated by F2-F4). But the GTK keyboard handler omitted that particular special case and was still sending ESC O {Q,R,S} for those keys in all application keypad modes. - also in Xterm function key mode plus app keypad mode, we only generates the app-keypad escape sequences if Num Lock is on; with Num Lock off, the numeric keypad becomes arrow keys and Home/End/etc, just as it would in non-app-keypad mode. Windows has done this all along, but again, GTK lacked that special case.
2018-12-08 11:25:32 +03:00
bool numeric = false;
switch (event->keyval) {
case GDK_KEY_Num_Lock: num_keypad_key = 'G'; break;
case GDK_KEY_KP_Divide: num_keypad_key = '/'; break;
case GDK_KEY_KP_Multiply: num_keypad_key = '*'; break;
case GDK_KEY_KP_Subtract: num_keypad_key = '-'; break;
case GDK_KEY_KP_Add: num_keypad_key = '+'; break;
case GDK_KEY_KP_Enter: num_keypad_key = '\r'; break;
case GDK_KEY_KP_0: num_keypad_key = '0'; numeric = true; break;
case GDK_KEY_KP_Insert: num_keypad_key = '0'; break;
case GDK_KEY_KP_1: num_keypad_key = '1'; numeric = true; break;
case GDK_KEY_KP_End: num_keypad_key = '1'; break;
case GDK_KEY_KP_2: num_keypad_key = '2'; numeric = true; break;
case GDK_KEY_KP_Down: num_keypad_key = '2'; break;
case GDK_KEY_KP_3: num_keypad_key = '3'; numeric = true; break;
case GDK_KEY_KP_Page_Down: num_keypad_key = '3'; break;
case GDK_KEY_KP_4: num_keypad_key = '4'; numeric = true; break;
case GDK_KEY_KP_Left: num_keypad_key = '4'; break;
case GDK_KEY_KP_5: num_keypad_key = '5'; numeric = true; break;
case GDK_KEY_KP_Begin: num_keypad_key = '5'; break;
case GDK_KEY_KP_6: num_keypad_key = '6'; numeric = true; break;
case GDK_KEY_KP_Right: num_keypad_key = '6'; break;
case GDK_KEY_KP_7: num_keypad_key = '7'; numeric = true; break;
case GDK_KEY_KP_Home: num_keypad_key = '7'; break;
case GDK_KEY_KP_8: num_keypad_key = '8'; numeric = true; break;
case GDK_KEY_KP_Up: num_keypad_key = '8'; break;
case GDK_KEY_KP_9: num_keypad_key = '9'; numeric = true; break;
case GDK_KEY_KP_Page_Up: num_keypad_key = '9'; break;
case GDK_KEY_KP_Decimal: num_keypad_key = '.'; numeric = true; break;
case GDK_KEY_KP_Delete: num_keypad_key = '.'; break;
}
if ((app_keypad_mode && num_keypad_key &&
(numeric || inst->term->funky_type != FUNKY_XTERM)) ||
(nethack_mode && num_keypad_key >= '1' && num_keypad_key <= '9')) {
/* In these modes, we override the keypad handling:
* regardless of Num Lock, the keys are handled by
* format_numeric_keypad_key below. */
force_format_numeric_keypad = true;
} else {
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
bool try_filter = true;
#ifdef META_MANUAL_MASK
if (event->state & META_MANUAL_MASK & inst->meta_mod_mask) {
/*
* If this key event had a Meta modifier bit set which
* is also in META_MANUAL_MASK, that means passing
* such an event to the GtkIMContext will be unhelpful
* (it will eat the keystroke and turn it into
* something not what we wanted).
*/
#ifdef KEY_EVENT_DIAGNOSTICS
debug(" - Meta modifier requiring manual intervention, "
"suppressing IM filtering\n");
#endif
try_filter = false;
}
#endif
if (try_filter) {
#ifdef KEY_EVENT_DIAGNOSTICS
debug(" - general key press, passing to IM\n");
#endif
if (gtk_im_context_filter_keypress(inst->imc, event)) {
#ifdef KEY_EVENT_DIAGNOSTICS
debug(" - key press accepted by IM\n");
#endif
return true;
} else {
#ifdef KEY_EVENT_DIAGNOSTICS
debug(" - key press not accepted by IM\n");
#endif
}
}
}
/*
* GDK 2.0 arranges to have done some translation for us: in
* GDK 2.0, event->string is encoded in the current locale.
*
* So we use the standard C library function mbstowcs() to
* convert from the current locale into Unicode; from there
* we can convert to whatever PuTTY is currently working in.
* (In fact I convert straight back to UTF-8 from
* wide-character Unicode, for the sake of simplicity: that
* way we can still use exactly the same code to manipulate
* the string, such as prefixing ESC.)
*/
output_charset = CS_UTF8;
{
wchar_t widedata[32];
const wchar_t *wp;
int wlen;
int ulen;
wlen = mb_to_wc(DEFAULT_CODEPAGE, 0,
event->string, strlen(event->string),
widedata, lenof(widedata)-1);
#ifdef KEY_EVENT_DIAGNOSTICS
{
char *string_string = dupstr("");
int i;
for (i = 0; i < wlen; i++) {
char *old = string_string;
string_string = dupprintf("%s%s%04x", string_string,
string_string[0] ? " " : "",
(unsigned)widedata[i]);
sfree(old);
}
debug(" - string translated into Unicode = [%s]\n",
string_string);
sfree(string_string);
}
#endif
wp = widedata;
ulen = charset_from_unicode(&wp, &wlen, output+1, lenof(output)-2,
CS_UTF8, NULL, NULL, 0);
#ifdef KEY_EVENT_DIAGNOSTICS
{
char *string_string = dupstr("");
int i;
for (i = 0; i < ulen; i++) {
char *old = string_string;
string_string = dupprintf("%s%s%02x", string_string,
string_string[0] ? " " : "",
(unsigned)output[i+1] & 0xFF);
sfree(old);
}
debug(" - string translated into UTF-8 = [%s]\n",
string_string);
sfree(string_string);
}
#endif
output[1+ulen] = '\0';
}
#endif /* !GTK_CHECK_VERSION(2,0,0) */
if (!output[1] &&
(ucsval = keysym_to_unicode(event->keyval)) >= 0) {
ucsoutput[0] = '\033';
ucsoutput[1] = ucsval;
#ifdef KEY_EVENT_DIAGNOSTICS
debug(" - keysym_to_unicode gave %04x\n",
(unsigned)ucsoutput[1]);
#endif
use_ucsoutput = true;
end = 2;
} else {
output[lenof(output)-1] = '\0';
end = strlen(output);
}
if (event->state & inst->meta_mod_mask) {
start = 0;
if (end == 1) end = 0;
#ifdef META_MANUAL_MASK
if (event->state & META_MANUAL_MASK) {
/*
* Key events which have a META_MANUAL_MASK meta bit
* set may have a keyval reflecting that, e.g. on OS X
* the Option key acts as an AltGr-like modifier and
* causes different Unicode characters to be output.
*
* To work around this, we clear the dangerous
* modifier bit and retranslate from the hardware
* keycode as if the key had been pressed without that
* modifier. Then we prefix Esc to *that*.
*/
guint new_keyval;
GdkModifierType consumed;
if (gdk_keymap_translate_keyboard_state
(gdk_keymap_get_for_display(gdk_display_get_default()),
event->hardware_keycode, event->state & ~META_MANUAL_MASK,
0, &new_keyval, NULL, NULL, &consumed)) {
ucsoutput[0] = '\033';
ucsoutput[1] = gdk_keyval_to_unicode(new_keyval);
#ifdef KEY_EVENT_DIAGNOSTICS
{
char *keyval_name = dup_keyval_name(new_keyval);
debug(" - retranslation for manual Meta: "
"new keyval = %s, Unicode = %04x\n",
keyval_name, (unsigned)ucsoutput[1]);
sfree(keyval_name);
}
#endif
use_ucsoutput = true;
end = 2;
}
}
#endif
} else
start = 1;
/* Control-` is the same as Control-\ (unless gtk has a better idea) */
if (!output[1] && event->keyval == '`' &&
(event->state & GDK_CONTROL_MASK)) {
#ifdef KEY_EVENT_DIAGNOSTICS
debug(" - Ctrl-` special case, translating as 1c\n");
#endif
output[1] = '\x1C';
use_ucsoutput = false;
end = 2;
}
/* Some GTK backends (e.g. Quartz) do not change event->string
* in response to the Control modifier. So we do it ourselves
* here, if it's not already happened.
*
* The translations below are in line with X11 policy as far
* as I know. */
if ((event->state & GDK_CONTROL_MASK) && end == 2) {
#ifdef KEY_EVENT_DIAGNOSTICS
int orig = output[1];
#endif
if (output[1] >= '3' && output[1] <= '7') {
/* ^3,...,^7 map to 0x1B,...,0x1F */
output[1] += '\x1B' - '3';
} else if (output[1] == '2' || output[1] == ' ') {
/* ^2 and ^Space are both ^@, i.e. \0 */
output[1] = '\0';
} else if (output[1] == '8') {
/* ^8 is DEL */
output[1] = '\x7F';
} else if (output[1] == '/') {
/* ^/ is the same as ^_ */
output[1] = '\x1F';
} else if (output[1] >= 0x40 && output[1] < 0x7F) {
/* Everything anywhere near the alphabetics just gets
* masked. */
output[1] &= 0x1F;
}
/* Anything else, e.g. '0', is unchanged. */
#ifdef KEY_EVENT_DIAGNOSTICS
if (orig == output[1])
debug(" - manual Ctrl key handling did nothing\n");
else
debug(" - manual Ctrl key handling: %02x -> %02x\n",
(unsigned)orig, (unsigned)output[1]);
#endif
}
/* Control-Break sends a Break special to the backend */
if (event->keyval == GDK_KEY_Break &&
(event->state & GDK_CONTROL_MASK)) {
#ifdef KEY_EVENT_DIAGNOSTICS
debug(" - Ctrl-Break special case, sending SS_BRK\n");
#endif
if (inst->backend)
backend_special(inst->backend, SS_BRK, 0);
return true;
}
/* We handle Return ourselves, because it needs to be flagged as
* special to ldisc. */
if (event->keyval == GDK_KEY_Return) {
#ifdef KEY_EVENT_DIAGNOSTICS
debug(" - Return special case, translating as 0d + special\n");
#endif
output[1] = '\015';
use_ucsoutput = false;
end = 2;
special = true;
}
/* Control-2, Control-Space and Control-@ are NUL */
if (!output[1] &&
(event->keyval == ' ' || event->keyval == '2' ||
event->keyval == '@') &&
(event->state & (GDK_SHIFT_MASK |
GDK_CONTROL_MASK)) == GDK_CONTROL_MASK) {
#ifdef KEY_EVENT_DIAGNOSTICS
debug(" - Ctrl-{space,2,@} special case, translating as 00\n");
#endif
output[1] = '\0';
use_ucsoutput = false;
end = 2;
}
/* Control-Shift-Space is 160 (ISO8859 nonbreaking space) */
if (!output[1] && event->keyval == ' ' &&
(event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK)) ==
(GDK_SHIFT_MASK | GDK_CONTROL_MASK)) {
#ifdef KEY_EVENT_DIAGNOSTICS
debug(" - Ctrl-Shift-space special case, translating as 00a0\n");
#endif
output[1] = '\240';
output_charset = CS_ISO8859_1;
use_ucsoutput = false;
end = 2;
}
/* We don't let GTK tell us what Backspace is! We know better. */
if (event->keyval == GDK_KEY_BackSpace &&
!(event->state & GDK_SHIFT_MASK)) {
output[1] = conf_get_bool(inst->conf, CONF_bksp_is_delete) ?
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
'\x7F' : '\x08';
#ifdef KEY_EVENT_DIAGNOSTICS
debug(" - Backspace, translating as %02x\n",
(unsigned)output[1]);
#endif
use_ucsoutput = false;
end = 2;
special = true;
}
/* For Shift Backspace, do opposite of what is configured. */
if (event->keyval == GDK_KEY_BackSpace &&
(event->state & GDK_SHIFT_MASK)) {
output[1] = conf_get_bool(inst->conf, CONF_bksp_is_delete) ?
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
'\x08' : '\x7F';
#ifdef KEY_EVENT_DIAGNOSTICS
debug(" - Shift-Backspace, translating as %02x\n",
(unsigned)output[1]);
#endif
use_ucsoutput = false;
end = 2;
special = true;
}
/* Shift-Tab is ESC [ Z */
if (event->keyval == GDK_KEY_ISO_Left_Tab ||
(event->keyval == GDK_KEY_Tab &&
(event->state & GDK_SHIFT_MASK))) {
#ifdef KEY_EVENT_DIAGNOSTICS
debug(" - Shift-Tab, translating as ESC [ Z\n");
#endif
end = 1 + sprintf(output+1, "\033[Z");
use_ucsoutput = false;
}
/* And normal Tab is Tab, if the keymap hasn't already told us.
* (Curiously, at least one version of the MacOS 10.5 X server
* doesn't translate Tab for us. */
if (event->keyval == GDK_KEY_Tab && end <= 1) {
#ifdef KEY_EVENT_DIAGNOSTICS
debug(" - Tab, translating as 09\n");
#endif
output[1] = '\t';
end = 2;
}
Centralise key escape sequences into terminal.c. A long time ago, in commit 4d77b6567, I moved the generation of the arrow-key escape sequences into a function format_arrow_key(). Mostly the reason for that was a special purpose I had in mind at the time which involved auto-generating the same sequences in response to things other than a keypress, but I always thought it would be nice to centralise a lot more of PuTTY's complicated keyboard handling in the same way - at least the handling of the function keys and their numerous static and dynamic config options. In this year's general spirit of tidying up and refactoring, I think it's finally time. So here I introduce three more centralised functions for dealing with the numbered function keys, the small keypad (Ins, Home, PgUp etc) and the numeric keypad. Lots of horrible and duplicated code from the key handling functions in window.c and gtkwin.c is now more sensibly centralised: each platform keyboard handler concerns itself with the local format of a keyboard event and platform-specific enumeration of key codes, and once it's decided what the logical key press actually _is_, it hands off to the new functions in terminal.c to generate the appropriate escape code. Mostly this is intended to be a refactoring without functional change, leaving the keyboard handling how it's always been. But in cases where the Windows and GTK handlers were accidentally inconsistent, I've fixed the inconsistency rather than carefully keeping both sides how they were. Known consistency fixes: - swapping the arrow keys between normal (ESC [ A) and application (ESC O A) is now done by pressing Ctrl with them, and _not_ by pressing Shift. That was how it was always supposed to work, and how it's worked on GTK all along, but on Windows it's been done by Shift as well since 2010, due to a bug at the call site of format_arrow_key() introduced when I originally wrote that function. - in Xterm function key mode plus application keypad mode, the /*- keys on the numeric keypad now send ESC O {o,j,m} in place of ESC O {Q,R,S}. That's how the Windows keyboard handler has worked all along (it was a deliberate behaviour tweak for the Xterm-like function key mode, because in that mode ESC O {Q,R,S} are generated by F2-F4). But the GTK keyboard handler omitted that particular special case and was still sending ESC O {Q,R,S} for those keys in all application keypad modes. - also in Xterm function key mode plus app keypad mode, we only generates the app-keypad escape sequences if Num Lock is on; with Num Lock off, the numeric keypad becomes arrow keys and Home/End/etc, just as it would in non-app-keypad mode. Windows has done this all along, but again, GTK lacked that special case.
2018-12-08 11:25:32 +03:00
if (num_keypad_key && force_format_numeric_keypad) {
end = 1 + format_numeric_keypad_key(
output+1, inst->term, num_keypad_key,
event->state & GDK_SHIFT_MASK,
event->state & GDK_CONTROL_MASK);
#ifdef KEY_EVENT_DIAGNOSTICS
debug(" - numeric keypad key");
#endif
Centralise key escape sequences into terminal.c. A long time ago, in commit 4d77b6567, I moved the generation of the arrow-key escape sequences into a function format_arrow_key(). Mostly the reason for that was a special purpose I had in mind at the time which involved auto-generating the same sequences in response to things other than a keypress, but I always thought it would be nice to centralise a lot more of PuTTY's complicated keyboard handling in the same way - at least the handling of the function keys and their numerous static and dynamic config options. In this year's general spirit of tidying up and refactoring, I think it's finally time. So here I introduce three more centralised functions for dealing with the numbered function keys, the small keypad (Ins, Home, PgUp etc) and the numeric keypad. Lots of horrible and duplicated code from the key handling functions in window.c and gtkwin.c is now more sensibly centralised: each platform keyboard handler concerns itself with the local format of a keyboard event and platform-specific enumeration of key codes, and once it's decided what the logical key press actually _is_, it hands off to the new functions in terminal.c to generate the appropriate escape code. Mostly this is intended to be a refactoring without functional change, leaving the keyboard handling how it's always been. But in cases where the Windows and GTK handlers were accidentally inconsistent, I've fixed the inconsistency rather than carefully keeping both sides how they were. Known consistency fixes: - swapping the arrow keys between normal (ESC [ A) and application (ESC O A) is now done by pressing Ctrl with them, and _not_ by pressing Shift. That was how it was always supposed to work, and how it's worked on GTK all along, but on Windows it's been done by Shift as well since 2010, due to a bug at the call site of format_arrow_key() introduced when I originally wrote that function. - in Xterm function key mode plus application keypad mode, the /*- keys on the numeric keypad now send ESC O {o,j,m} in place of ESC O {Q,R,S}. That's how the Windows keyboard handler has worked all along (it was a deliberate behaviour tweak for the Xterm-like function key mode, because in that mode ESC O {Q,R,S} are generated by F2-F4). But the GTK keyboard handler omitted that particular special case and was still sending ESC O {Q,R,S} for those keys in all application keypad modes. - also in Xterm function key mode plus app keypad mode, we only generates the app-keypad escape sequences if Num Lock is on; with Num Lock off, the numeric keypad becomes arrow keys and Home/End/etc, just as it would in non-app-keypad mode. Windows has done this all along, but again, GTK lacked that special case.
2018-12-08 11:25:32 +03:00
use_ucsoutput = false;
goto done;
}
Centralise key escape sequences into terminal.c. A long time ago, in commit 4d77b6567, I moved the generation of the arrow-key escape sequences into a function format_arrow_key(). Mostly the reason for that was a special purpose I had in mind at the time which involved auto-generating the same sequences in response to things other than a keypress, but I always thought it would be nice to centralise a lot more of PuTTY's complicated keyboard handling in the same way - at least the handling of the function keys and their numerous static and dynamic config options. In this year's general spirit of tidying up and refactoring, I think it's finally time. So here I introduce three more centralised functions for dealing with the numbered function keys, the small keypad (Ins, Home, PgUp etc) and the numeric keypad. Lots of horrible and duplicated code from the key handling functions in window.c and gtkwin.c is now more sensibly centralised: each platform keyboard handler concerns itself with the local format of a keyboard event and platform-specific enumeration of key codes, and once it's decided what the logical key press actually _is_, it hands off to the new functions in terminal.c to generate the appropriate escape code. Mostly this is intended to be a refactoring without functional change, leaving the keyboard handling how it's always been. But in cases where the Windows and GTK handlers were accidentally inconsistent, I've fixed the inconsistency rather than carefully keeping both sides how they were. Known consistency fixes: - swapping the arrow keys between normal (ESC [ A) and application (ESC O A) is now done by pressing Ctrl with them, and _not_ by pressing Shift. That was how it was always supposed to work, and how it's worked on GTK all along, but on Windows it's been done by Shift as well since 2010, due to a bug at the call site of format_arrow_key() introduced when I originally wrote that function. - in Xterm function key mode plus application keypad mode, the /*- keys on the numeric keypad now send ESC O {o,j,m} in place of ESC O {Q,R,S}. That's how the Windows keyboard handler has worked all along (it was a deliberate behaviour tweak for the Xterm-like function key mode, because in that mode ESC O {Q,R,S} are generated by F2-F4). But the GTK keyboard handler omitted that particular special case and was still sending ESC O {Q,R,S} for those keys in all application keypad modes. - also in Xterm function key mode plus app keypad mode, we only generates the app-keypad escape sequences if Num Lock is on; with Num Lock off, the numeric keypad becomes arrow keys and Home/End/etc, just as it would in non-app-keypad mode. Windows has done this all along, but again, GTK lacked that special case.
2018-12-08 11:25:32 +03:00
switch (event->keyval) {
int fkey_number;
case GDK_KEY_F1: fkey_number = 1; goto numbered_function_key;
case GDK_KEY_F2: fkey_number = 2; goto numbered_function_key;
case GDK_KEY_F3: fkey_number = 3; goto numbered_function_key;
case GDK_KEY_F4: fkey_number = 4; goto numbered_function_key;
case GDK_KEY_F5: fkey_number = 5; goto numbered_function_key;
case GDK_KEY_F6: fkey_number = 6; goto numbered_function_key;
case GDK_KEY_F7: fkey_number = 7; goto numbered_function_key;
case GDK_KEY_F8: fkey_number = 8; goto numbered_function_key;
case GDK_KEY_F9: fkey_number = 9; goto numbered_function_key;
case GDK_KEY_F10: fkey_number = 10; goto numbered_function_key;
case GDK_KEY_F11: fkey_number = 11; goto numbered_function_key;
case GDK_KEY_F12: fkey_number = 12; goto numbered_function_key;
case GDK_KEY_F13: fkey_number = 13; goto numbered_function_key;
case GDK_KEY_F14: fkey_number = 14; goto numbered_function_key;
case GDK_KEY_F15: fkey_number = 15; goto numbered_function_key;
case GDK_KEY_F16: fkey_number = 16; goto numbered_function_key;
case GDK_KEY_F17: fkey_number = 17; goto numbered_function_key;
case GDK_KEY_F18: fkey_number = 18; goto numbered_function_key;
case GDK_KEY_F19: fkey_number = 19; goto numbered_function_key;
case GDK_KEY_F20: fkey_number = 20; goto numbered_function_key;
numbered_function_key:
end = 1 + format_function_key(output+1, inst->term, fkey_number,
event->state & GDK_SHIFT_MASK,
event->state & GDK_CONTROL_MASK);
#ifdef KEY_EVENT_DIAGNOSTICS
debug(" - function key F%d", fkey_number);
Centralise key escape sequences into terminal.c. A long time ago, in commit 4d77b6567, I moved the generation of the arrow-key escape sequences into a function format_arrow_key(). Mostly the reason for that was a special purpose I had in mind at the time which involved auto-generating the same sequences in response to things other than a keypress, but I always thought it would be nice to centralise a lot more of PuTTY's complicated keyboard handling in the same way - at least the handling of the function keys and their numerous static and dynamic config options. In this year's general spirit of tidying up and refactoring, I think it's finally time. So here I introduce three more centralised functions for dealing with the numbered function keys, the small keypad (Ins, Home, PgUp etc) and the numeric keypad. Lots of horrible and duplicated code from the key handling functions in window.c and gtkwin.c is now more sensibly centralised: each platform keyboard handler concerns itself with the local format of a keyboard event and platform-specific enumeration of key codes, and once it's decided what the logical key press actually _is_, it hands off to the new functions in terminal.c to generate the appropriate escape code. Mostly this is intended to be a refactoring without functional change, leaving the keyboard handling how it's always been. But in cases where the Windows and GTK handlers were accidentally inconsistent, I've fixed the inconsistency rather than carefully keeping both sides how they were. Known consistency fixes: - swapping the arrow keys between normal (ESC [ A) and application (ESC O A) is now done by pressing Ctrl with them, and _not_ by pressing Shift. That was how it was always supposed to work, and how it's worked on GTK all along, but on Windows it's been done by Shift as well since 2010, due to a bug at the call site of format_arrow_key() introduced when I originally wrote that function. - in Xterm function key mode plus application keypad mode, the /*- keys on the numeric keypad now send ESC O {o,j,m} in place of ESC O {Q,R,S}. That's how the Windows keyboard handler has worked all along (it was a deliberate behaviour tweak for the Xterm-like function key mode, because in that mode ESC O {Q,R,S} are generated by F2-F4). But the GTK keyboard handler omitted that particular special case and was still sending ESC O {Q,R,S} for those keys in all application keypad modes. - also in Xterm function key mode plus app keypad mode, we only generates the app-keypad escape sequences if Num Lock is on; with Num Lock off, the numeric keypad becomes arrow keys and Home/End/etc, just as it would in non-app-keypad mode. Windows has done this all along, but again, GTK lacked that special case.
2018-12-08 11:25:32 +03:00
#endif
use_ucsoutput = false;
goto done;
Centralise key escape sequences into terminal.c. A long time ago, in commit 4d77b6567, I moved the generation of the arrow-key escape sequences into a function format_arrow_key(). Mostly the reason for that was a special purpose I had in mind at the time which involved auto-generating the same sequences in response to things other than a keypress, but I always thought it would be nice to centralise a lot more of PuTTY's complicated keyboard handling in the same way - at least the handling of the function keys and their numerous static and dynamic config options. In this year's general spirit of tidying up and refactoring, I think it's finally time. So here I introduce three more centralised functions for dealing with the numbered function keys, the small keypad (Ins, Home, PgUp etc) and the numeric keypad. Lots of horrible and duplicated code from the key handling functions in window.c and gtkwin.c is now more sensibly centralised: each platform keyboard handler concerns itself with the local format of a keyboard event and platform-specific enumeration of key codes, and once it's decided what the logical key press actually _is_, it hands off to the new functions in terminal.c to generate the appropriate escape code. Mostly this is intended to be a refactoring without functional change, leaving the keyboard handling how it's always been. But in cases where the Windows and GTK handlers were accidentally inconsistent, I've fixed the inconsistency rather than carefully keeping both sides how they were. Known consistency fixes: - swapping the arrow keys between normal (ESC [ A) and application (ESC O A) is now done by pressing Ctrl with them, and _not_ by pressing Shift. That was how it was always supposed to work, and how it's worked on GTK all along, but on Windows it's been done by Shift as well since 2010, due to a bug at the call site of format_arrow_key() introduced when I originally wrote that function. - in Xterm function key mode plus application keypad mode, the /*- keys on the numeric keypad now send ESC O {o,j,m} in place of ESC O {Q,R,S}. That's how the Windows keyboard handler has worked all along (it was a deliberate behaviour tweak for the Xterm-like function key mode, because in that mode ESC O {Q,R,S} are generated by F2-F4). But the GTK keyboard handler omitted that particular special case and was still sending ESC O {Q,R,S} for those keys in all application keypad modes. - also in Xterm function key mode plus app keypad mode, we only generates the app-keypad escape sequences if Num Lock is on; with Num Lock off, the numeric keypad becomes arrow keys and Home/End/etc, just as it would in non-app-keypad mode. Windows has done this all along, but again, GTK lacked that special case.
2018-12-08 11:25:32 +03:00
SmallKeypadKey sk_key;
case GDK_KEY_Home: case GDK_KEY_KP_Home:
sk_key = SKK_HOME; goto small_keypad_key;
case GDK_KEY_Insert: case GDK_KEY_KP_Insert:
sk_key = SKK_INSERT; goto small_keypad_key;
case GDK_KEY_Delete: case GDK_KEY_KP_Delete:
sk_key = SKK_DELETE; goto small_keypad_key;
case GDK_KEY_End: case GDK_KEY_KP_End:
sk_key = SKK_END; goto small_keypad_key;
case GDK_KEY_Page_Up: case GDK_KEY_KP_Page_Up:
sk_key = SKK_PGUP; goto small_keypad_key;
case GDK_KEY_Page_Down: case GDK_KEY_KP_Page_Down:
sk_key = SKK_PGDN; goto small_keypad_key;
small_keypad_key:
/* These keys don't generate terminal input with Ctrl */
if (event->state & GDK_CONTROL_MASK)
break;
Centralise key escape sequences into terminal.c. A long time ago, in commit 4d77b6567, I moved the generation of the arrow-key escape sequences into a function format_arrow_key(). Mostly the reason for that was a special purpose I had in mind at the time which involved auto-generating the same sequences in response to things other than a keypress, but I always thought it would be nice to centralise a lot more of PuTTY's complicated keyboard handling in the same way - at least the handling of the function keys and their numerous static and dynamic config options. In this year's general spirit of tidying up and refactoring, I think it's finally time. So here I introduce three more centralised functions for dealing with the numbered function keys, the small keypad (Ins, Home, PgUp etc) and the numeric keypad. Lots of horrible and duplicated code from the key handling functions in window.c and gtkwin.c is now more sensibly centralised: each platform keyboard handler concerns itself with the local format of a keyboard event and platform-specific enumeration of key codes, and once it's decided what the logical key press actually _is_, it hands off to the new functions in terminal.c to generate the appropriate escape code. Mostly this is intended to be a refactoring without functional change, leaving the keyboard handling how it's always been. But in cases where the Windows and GTK handlers were accidentally inconsistent, I've fixed the inconsistency rather than carefully keeping both sides how they were. Known consistency fixes: - swapping the arrow keys between normal (ESC [ A) and application (ESC O A) is now done by pressing Ctrl with them, and _not_ by pressing Shift. That was how it was always supposed to work, and how it's worked on GTK all along, but on Windows it's been done by Shift as well since 2010, due to a bug at the call site of format_arrow_key() introduced when I originally wrote that function. - in Xterm function key mode plus application keypad mode, the /*- keys on the numeric keypad now send ESC O {o,j,m} in place of ESC O {Q,R,S}. That's how the Windows keyboard handler has worked all along (it was a deliberate behaviour tweak for the Xterm-like function key mode, because in that mode ESC O {Q,R,S} are generated by F2-F4). But the GTK keyboard handler omitted that particular special case and was still sending ESC O {Q,R,S} for those keys in all application keypad modes. - also in Xterm function key mode plus app keypad mode, we only generates the app-keypad escape sequences if Num Lock is on; with Num Lock off, the numeric keypad becomes arrow keys and Home/End/etc, just as it would in non-app-keypad mode. Windows has done this all along, but again, GTK lacked that special case.
2018-12-08 11:25:32 +03:00
end = 1 + format_small_keypad_key(output+1, inst->term, sk_key);
#ifdef KEY_EVENT_DIAGNOSTICS
debug(" - small keypad key");
#endif
Centralise key escape sequences into terminal.c. A long time ago, in commit 4d77b6567, I moved the generation of the arrow-key escape sequences into a function format_arrow_key(). Mostly the reason for that was a special purpose I had in mind at the time which involved auto-generating the same sequences in response to things other than a keypress, but I always thought it would be nice to centralise a lot more of PuTTY's complicated keyboard handling in the same way - at least the handling of the function keys and their numerous static and dynamic config options. In this year's general spirit of tidying up and refactoring, I think it's finally time. So here I introduce three more centralised functions for dealing with the numbered function keys, the small keypad (Ins, Home, PgUp etc) and the numeric keypad. Lots of horrible and duplicated code from the key handling functions in window.c and gtkwin.c is now more sensibly centralised: each platform keyboard handler concerns itself with the local format of a keyboard event and platform-specific enumeration of key codes, and once it's decided what the logical key press actually _is_, it hands off to the new functions in terminal.c to generate the appropriate escape code. Mostly this is intended to be a refactoring without functional change, leaving the keyboard handling how it's always been. But in cases where the Windows and GTK handlers were accidentally inconsistent, I've fixed the inconsistency rather than carefully keeping both sides how they were. Known consistency fixes: - swapping the arrow keys between normal (ESC [ A) and application (ESC O A) is now done by pressing Ctrl with them, and _not_ by pressing Shift. That was how it was always supposed to work, and how it's worked on GTK all along, but on Windows it's been done by Shift as well since 2010, due to a bug at the call site of format_arrow_key() introduced when I originally wrote that function. - in Xterm function key mode plus application keypad mode, the /*- keys on the numeric keypad now send ESC O {o,j,m} in place of ESC O {Q,R,S}. That's how the Windows keyboard handler has worked all along (it was a deliberate behaviour tweak for the Xterm-like function key mode, because in that mode ESC O {Q,R,S} are generated by F2-F4). But the GTK keyboard handler omitted that particular special case and was still sending ESC O {Q,R,S} for those keys in all application keypad modes. - also in Xterm function key mode plus app keypad mode, we only generates the app-keypad escape sequences if Num Lock is on; with Num Lock off, the numeric keypad becomes arrow keys and Home/End/etc, just as it would in non-app-keypad mode. Windows has done this all along, but again, GTK lacked that special case.
2018-12-08 11:25:32 +03:00
use_ucsoutput = false;
goto done;
Centralise key escape sequences into terminal.c. A long time ago, in commit 4d77b6567, I moved the generation of the arrow-key escape sequences into a function format_arrow_key(). Mostly the reason for that was a special purpose I had in mind at the time which involved auto-generating the same sequences in response to things other than a keypress, but I always thought it would be nice to centralise a lot more of PuTTY's complicated keyboard handling in the same way - at least the handling of the function keys and their numerous static and dynamic config options. In this year's general spirit of tidying up and refactoring, I think it's finally time. So here I introduce three more centralised functions for dealing with the numbered function keys, the small keypad (Ins, Home, PgUp etc) and the numeric keypad. Lots of horrible and duplicated code from the key handling functions in window.c and gtkwin.c is now more sensibly centralised: each platform keyboard handler concerns itself with the local format of a keyboard event and platform-specific enumeration of key codes, and once it's decided what the logical key press actually _is_, it hands off to the new functions in terminal.c to generate the appropriate escape code. Mostly this is intended to be a refactoring without functional change, leaving the keyboard handling how it's always been. But in cases where the Windows and GTK handlers were accidentally inconsistent, I've fixed the inconsistency rather than carefully keeping both sides how they were. Known consistency fixes: - swapping the arrow keys between normal (ESC [ A) and application (ESC O A) is now done by pressing Ctrl with them, and _not_ by pressing Shift. That was how it was always supposed to work, and how it's worked on GTK all along, but on Windows it's been done by Shift as well since 2010, due to a bug at the call site of format_arrow_key() introduced when I originally wrote that function. - in Xterm function key mode plus application keypad mode, the /*- keys on the numeric keypad now send ESC O {o,j,m} in place of ESC O {Q,R,S}. That's how the Windows keyboard handler has worked all along (it was a deliberate behaviour tweak for the Xterm-like function key mode, because in that mode ESC O {Q,R,S} are generated by F2-F4). But the GTK keyboard handler omitted that particular special case and was still sending ESC O {Q,R,S} for those keys in all application keypad modes. - also in Xterm function key mode plus app keypad mode, we only generates the app-keypad escape sequences if Num Lock is on; with Num Lock off, the numeric keypad becomes arrow keys and Home/End/etc, just as it would in non-app-keypad mode. Windows has done this all along, but again, GTK lacked that special case.
2018-12-08 11:25:32 +03:00
int xkey;
case GDK_KEY_Up: case GDK_KEY_KP_Up:
xkey = 'A'; goto arrow_key;
case GDK_KEY_Down: case GDK_KEY_KP_Down:
xkey = 'B'; goto arrow_key;
case GDK_KEY_Right: case GDK_KEY_KP_Right:
xkey = 'C'; goto arrow_key;
case GDK_KEY_Left: case GDK_KEY_KP_Left:
xkey = 'D'; goto arrow_key;
case GDK_KEY_Begin: case GDK_KEY_KP_Begin:
xkey = 'G'; goto arrow_key;
arrow_key:
end = 1 + format_arrow_key(output+1, inst->term, xkey,
event->state & GDK_CONTROL_MASK);
#ifdef KEY_EVENT_DIAGNOSTICS
debug(" - arrow key");
Centralise key escape sequences into terminal.c. A long time ago, in commit 4d77b6567, I moved the generation of the arrow-key escape sequences into a function format_arrow_key(). Mostly the reason for that was a special purpose I had in mind at the time which involved auto-generating the same sequences in response to things other than a keypress, but I always thought it would be nice to centralise a lot more of PuTTY's complicated keyboard handling in the same way - at least the handling of the function keys and their numerous static and dynamic config options. In this year's general spirit of tidying up and refactoring, I think it's finally time. So here I introduce three more centralised functions for dealing with the numbered function keys, the small keypad (Ins, Home, PgUp etc) and the numeric keypad. Lots of horrible and duplicated code from the key handling functions in window.c and gtkwin.c is now more sensibly centralised: each platform keyboard handler concerns itself with the local format of a keyboard event and platform-specific enumeration of key codes, and once it's decided what the logical key press actually _is_, it hands off to the new functions in terminal.c to generate the appropriate escape code. Mostly this is intended to be a refactoring without functional change, leaving the keyboard handling how it's always been. But in cases where the Windows and GTK handlers were accidentally inconsistent, I've fixed the inconsistency rather than carefully keeping both sides how they were. Known consistency fixes: - swapping the arrow keys between normal (ESC [ A) and application (ESC O A) is now done by pressing Ctrl with them, and _not_ by pressing Shift. That was how it was always supposed to work, and how it's worked on GTK all along, but on Windows it's been done by Shift as well since 2010, due to a bug at the call site of format_arrow_key() introduced when I originally wrote that function. - in Xterm function key mode plus application keypad mode, the /*- keys on the numeric keypad now send ESC O {o,j,m} in place of ESC O {Q,R,S}. That's how the Windows keyboard handler has worked all along (it was a deliberate behaviour tweak for the Xterm-like function key mode, because in that mode ESC O {Q,R,S} are generated by F2-F4). But the GTK keyboard handler omitted that particular special case and was still sending ESC O {Q,R,S} for those keys in all application keypad modes. - also in Xterm function key mode plus app keypad mode, we only generates the app-keypad escape sequences if Num Lock is on; with Num Lock off, the numeric keypad becomes arrow keys and Home/End/etc, just as it would in non-app-keypad mode. Windows has done this all along, but again, GTK lacked that special case.
2018-12-08 11:25:32 +03:00
#endif
use_ucsoutput = false;
goto done;
}
Centralise key escape sequences into terminal.c. A long time ago, in commit 4d77b6567, I moved the generation of the arrow-key escape sequences into a function format_arrow_key(). Mostly the reason for that was a special purpose I had in mind at the time which involved auto-generating the same sequences in response to things other than a keypress, but I always thought it would be nice to centralise a lot more of PuTTY's complicated keyboard handling in the same way - at least the handling of the function keys and their numerous static and dynamic config options. In this year's general spirit of tidying up and refactoring, I think it's finally time. So here I introduce three more centralised functions for dealing with the numbered function keys, the small keypad (Ins, Home, PgUp etc) and the numeric keypad. Lots of horrible and duplicated code from the key handling functions in window.c and gtkwin.c is now more sensibly centralised: each platform keyboard handler concerns itself with the local format of a keyboard event and platform-specific enumeration of key codes, and once it's decided what the logical key press actually _is_, it hands off to the new functions in terminal.c to generate the appropriate escape code. Mostly this is intended to be a refactoring without functional change, leaving the keyboard handling how it's always been. But in cases where the Windows and GTK handlers were accidentally inconsistent, I've fixed the inconsistency rather than carefully keeping both sides how they were. Known consistency fixes: - swapping the arrow keys between normal (ESC [ A) and application (ESC O A) is now done by pressing Ctrl with them, and _not_ by pressing Shift. That was how it was always supposed to work, and how it's worked on GTK all along, but on Windows it's been done by Shift as well since 2010, due to a bug at the call site of format_arrow_key() introduced when I originally wrote that function. - in Xterm function key mode plus application keypad mode, the /*- keys on the numeric keypad now send ESC O {o,j,m} in place of ESC O {Q,R,S}. That's how the Windows keyboard handler has worked all along (it was a deliberate behaviour tweak for the Xterm-like function key mode, because in that mode ESC O {Q,R,S} are generated by F2-F4). But the GTK keyboard handler omitted that particular special case and was still sending ESC O {Q,R,S} for those keys in all application keypad modes. - also in Xterm function key mode plus app keypad mode, we only generates the app-keypad escape sequences if Num Lock is on; with Num Lock off, the numeric keypad becomes arrow keys and Home/End/etc, just as it would in non-app-keypad mode. Windows has done this all along, but again, GTK lacked that special case.
2018-12-08 11:25:32 +03:00
if (num_keypad_key) {
end = 1 + format_numeric_keypad_key(
output+1, inst->term, num_keypad_key,
event->state & GDK_SHIFT_MASK,
event->state & GDK_CONTROL_MASK);
#ifdef KEY_EVENT_DIAGNOSTICS
debug(" - numeric keypad key");
#endif
Centralise key escape sequences into terminal.c. A long time ago, in commit 4d77b6567, I moved the generation of the arrow-key escape sequences into a function format_arrow_key(). Mostly the reason for that was a special purpose I had in mind at the time which involved auto-generating the same sequences in response to things other than a keypress, but I always thought it would be nice to centralise a lot more of PuTTY's complicated keyboard handling in the same way - at least the handling of the function keys and their numerous static and dynamic config options. In this year's general spirit of tidying up and refactoring, I think it's finally time. So here I introduce three more centralised functions for dealing with the numbered function keys, the small keypad (Ins, Home, PgUp etc) and the numeric keypad. Lots of horrible and duplicated code from the key handling functions in window.c and gtkwin.c is now more sensibly centralised: each platform keyboard handler concerns itself with the local format of a keyboard event and platform-specific enumeration of key codes, and once it's decided what the logical key press actually _is_, it hands off to the new functions in terminal.c to generate the appropriate escape code. Mostly this is intended to be a refactoring without functional change, leaving the keyboard handling how it's always been. But in cases where the Windows and GTK handlers were accidentally inconsistent, I've fixed the inconsistency rather than carefully keeping both sides how they were. Known consistency fixes: - swapping the arrow keys between normal (ESC [ A) and application (ESC O A) is now done by pressing Ctrl with them, and _not_ by pressing Shift. That was how it was always supposed to work, and how it's worked on GTK all along, but on Windows it's been done by Shift as well since 2010, due to a bug at the call site of format_arrow_key() introduced when I originally wrote that function. - in Xterm function key mode plus application keypad mode, the /*- keys on the numeric keypad now send ESC O {o,j,m} in place of ESC O {Q,R,S}. That's how the Windows keyboard handler has worked all along (it was a deliberate behaviour tweak for the Xterm-like function key mode, because in that mode ESC O {Q,R,S} are generated by F2-F4). But the GTK keyboard handler omitted that particular special case and was still sending ESC O {Q,R,S} for those keys in all application keypad modes. - also in Xterm function key mode plus app keypad mode, we only generates the app-keypad escape sequences if Num Lock is on; with Num Lock off, the numeric keypad becomes arrow keys and Home/End/etc, just as it would in non-app-keypad mode. Windows has done this all along, but again, GTK lacked that special case.
2018-12-08 11:25:32 +03:00
use_ucsoutput = false;
goto done;
}
Centralise key escape sequences into terminal.c. A long time ago, in commit 4d77b6567, I moved the generation of the arrow-key escape sequences into a function format_arrow_key(). Mostly the reason for that was a special purpose I had in mind at the time which involved auto-generating the same sequences in response to things other than a keypress, but I always thought it would be nice to centralise a lot more of PuTTY's complicated keyboard handling in the same way - at least the handling of the function keys and their numerous static and dynamic config options. In this year's general spirit of tidying up and refactoring, I think it's finally time. So here I introduce three more centralised functions for dealing with the numbered function keys, the small keypad (Ins, Home, PgUp etc) and the numeric keypad. Lots of horrible and duplicated code from the key handling functions in window.c and gtkwin.c is now more sensibly centralised: each platform keyboard handler concerns itself with the local format of a keyboard event and platform-specific enumeration of key codes, and once it's decided what the logical key press actually _is_, it hands off to the new functions in terminal.c to generate the appropriate escape code. Mostly this is intended to be a refactoring without functional change, leaving the keyboard handling how it's always been. But in cases where the Windows and GTK handlers were accidentally inconsistent, I've fixed the inconsistency rather than carefully keeping both sides how they were. Known consistency fixes: - swapping the arrow keys between normal (ESC [ A) and application (ESC O A) is now done by pressing Ctrl with them, and _not_ by pressing Shift. That was how it was always supposed to work, and how it's worked on GTK all along, but on Windows it's been done by Shift as well since 2010, due to a bug at the call site of format_arrow_key() introduced when I originally wrote that function. - in Xterm function key mode plus application keypad mode, the /*- keys on the numeric keypad now send ESC O {o,j,m} in place of ESC O {Q,R,S}. That's how the Windows keyboard handler has worked all along (it was a deliberate behaviour tweak for the Xterm-like function key mode, because in that mode ESC O {Q,R,S} are generated by F2-F4). But the GTK keyboard handler omitted that particular special case and was still sending ESC O {Q,R,S} for those keys in all application keypad modes. - also in Xterm function key mode plus app keypad mode, we only generates the app-keypad escape sequences if Num Lock is on; with Num Lock off, the numeric keypad becomes arrow keys and Home/End/etc, just as it would in non-app-keypad mode. Windows has done this all along, but again, GTK lacked that special case.
2018-12-08 11:25:32 +03:00
goto done;
}
done:
if (end-start > 0) {
if (special) {
#ifdef KEY_EVENT_DIAGNOSTICS
char *string_string = dupstr("");
int i;
for (i = start; i < end; i++) {
char *old = string_string;
string_string = dupprintf("%s%s%02x", string_string,
string_string[0] ? " " : "",
(unsigned)output[i] & 0xFF);
sfree(old);
}
debug(" - final output, special, generic encoding = [%s]\n",
charset_to_localenc(output_charset), string_string);
sfree(string_string);
#endif
/*
* For special control characters, the character set
* should never matter.
*/
output[end] = '\0'; /* NUL-terminate */
generated_something = true;
if (inst->ldisc)
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
ldisc_send(inst->ldisc, output+start, -2, true);
} else if (!inst->direct_to_font) {
if (!use_ucsoutput) {
#ifdef KEY_EVENT_DIAGNOSTICS
char *string_string = dupstr("");
int i;
for (i = start; i < end; i++) {
char *old = string_string;
string_string = dupprintf("%s%s%02x", string_string,
string_string[0] ? " " : "",
(unsigned)output[i] & 0xFF);
sfree(old);
}
debug(" - final output in %s = [%s]\n",
charset_to_localenc(output_charset), string_string);
sfree(string_string);
#endif
generated_something = true;
if (inst->ldisc)
lpage_send(inst->ldisc, output_charset, output+start,
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
end-start, true);
} else {
#ifdef KEY_EVENT_DIAGNOSTICS
char *string_string = dupstr("");
int i;
for (i = start; i < end; i++) {
char *old = string_string;
string_string = dupprintf("%s%s%04x", string_string,
string_string[0] ? " " : "",
(unsigned)ucsoutput[i]);
sfree(old);
}
debug(" - final output in Unicode = [%s]\n",
string_string);
sfree(string_string);
#endif
/*
* We generated our own Unicode key data from the
* keysym, so use that instead.
*/
generated_something = true;
if (inst->ldisc)
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
luni_send(inst->ldisc, ucsoutput+start, end-start, true);
}
} else {
/*
* In direct-to-font mode, we just send the string
* exactly as we received it.
*/
#ifdef KEY_EVENT_DIAGNOSTICS
char *string_string = dupstr("");
int i;
for (i = start; i < end; i++) {
char *old = string_string;
string_string = dupprintf("%s%s%02x", string_string,
string_string[0] ? " " : "",
(unsigned)output[i] & 0xFF);
sfree(old);
}
debug(" - final output in direct-to-font encoding = [%s]\n",
string_string);
sfree(string_string);
#endif
generated_something = true;
if (inst->ldisc)
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
ldisc_send(inst->ldisc, output+start, end-start, true);
}
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
show_mouseptr(inst, false);
term_seen_key_event(inst->term);
}
if (generated_something)
key_pressed(inst);
return true;
}
#if GTK_CHECK_VERSION(2,0,0)
void input_method_commit_event(GtkIMContext *imc, gchar *str, gpointer data)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = (GtkFrontend *)data;
#ifdef KEY_EVENT_DIAGNOSTICS
char *string_string = dupstr("");
int i;
for (i = 0; str[i]; i++) {
char *old = string_string;
string_string = dupprintf("%s%s%02x", string_string,
string_string[0] ? " " : "",
(unsigned)str[i] & 0xFF);
sfree(old);
}
debug(" - IM commit event in UTF-8 = [%s]\n", string_string);
sfree(string_string);
#endif
if (inst->ldisc)
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
lpage_send(inst->ldisc, CS_UTF8, str, strlen(str), true);
show_mouseptr(inst, false);
term_seen_key_event(inst->term);
key_pressed(inst);
}
#endif
#define SCROLL_INCREMENT_LINES 5
#if GTK_CHECK_VERSION(3,4,0)
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
gboolean scroll_internal(GtkFrontend *inst, gdouble delta, guint state,
gdouble ex, gdouble ey)
{
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
int x, y;
bool shift, ctrl, alt, raw_mouse_mode;
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
show_mouseptr(inst, true);
shift = state & GDK_SHIFT_MASK;
ctrl = state & GDK_CONTROL_MASK;
alt = state & inst->meta_mod_mask;
x = (ex - inst->window_border) / inst->font_width;
y = (ey - inst->window_border) / inst->font_height;
raw_mouse_mode = (inst->send_raw_mouse &&
!(shift && conf_get_bool(inst->conf,
CONF_mouse_override)));
inst->cumulative_scroll += delta * SCROLL_INCREMENT_LINES;
if (!raw_mouse_mode) {
int scroll_lines = (int)inst->cumulative_scroll; /* rounds toward 0 */
if (scroll_lines) {
term_scroll(inst->term, 0, scroll_lines);
inst->cumulative_scroll -= scroll_lines;
}
return true;
} else {
int scroll_events = (int)(inst->cumulative_scroll /
SCROLL_INCREMENT_LINES);
if (scroll_events) {
int button;
inst->cumulative_scroll -= scroll_events * SCROLL_INCREMENT_LINES;
if (scroll_events > 0) {
button = MBT_WHEEL_DOWN;
} else {
button = MBT_WHEEL_UP;
scroll_events = -scroll_events;
}
while (scroll_events-- > 0) {
term_mouse(inst->term, button, translate_button(button),
MA_CLICK, x, y, shift, ctrl, alt);
}
}
return true;
}
}
#endif
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
static gboolean button_internal(GtkFrontend *inst, GdkEventButton *event)
{
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
bool shift, ctrl, alt, raw_mouse_mode;
int x, y, button, act;
/* Remember the timestamp. */
inst->input_event_time = event->time;
noise_ultralight(NOISE_SOURCE_MOUSEBUTTON, event->button);
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
show_mouseptr(inst, true);
shift = event->state & GDK_SHIFT_MASK;
ctrl = event->state & GDK_CONTROL_MASK;
alt = event->state & inst->meta_mod_mask;
raw_mouse_mode = (inst->send_raw_mouse &&
!(shift && conf_get_bool(inst->conf,
CONF_mouse_override)));
if (!raw_mouse_mode) {
if (event->button == 4 && event->type == GDK_BUTTON_PRESS) {
term_scroll(inst->term, 0, -SCROLL_INCREMENT_LINES);
return true;
}
if (event->button == 5 && event->type == GDK_BUTTON_PRESS) {
term_scroll(inst->term, 0, +SCROLL_INCREMENT_LINES);
return true;
}
}
if (event->button == 3 && ctrl) {
#if GTK_CHECK_VERSION(3,22,0)
gtk_menu_popup_at_pointer(GTK_MENU(inst->menu), (GdkEvent *)event);
#else
gtk_menu_popup(GTK_MENU(inst->menu), NULL, NULL, NULL, NULL,
event->button, event->time);
#endif
return true;
}
if (event->button == 1)
button = MBT_LEFT;
else if (event->button == 2)
button = MBT_MIDDLE;
else if (event->button == 3)
button = MBT_RIGHT;
else if (event->button == 4)
button = MBT_WHEEL_UP;
else if (event->button == 5)
button = MBT_WHEEL_DOWN;
else
return false; /* don't even know what button! */
switch (event->type) {
case GDK_BUTTON_PRESS: act = MA_CLICK; break;
case GDK_BUTTON_RELEASE: act = MA_RELEASE; break;
case GDK_2BUTTON_PRESS: act = MA_2CLK; break;
case GDK_3BUTTON_PRESS: act = MA_3CLK; break;
default: return false; /* don't know this event type */
}
if (raw_mouse_mode && act != MA_CLICK && act != MA_RELEASE)
return true; /* we ignore these in raw mouse mode */
x = (event->x - inst->window_border) / inst->font_width;
y = (event->y - inst->window_border) / inst->font_height;
term_mouse(inst->term, button, translate_button(button), act,
x, y, shift, ctrl, alt);
return true;
}
gboolean button_event(GtkWidget *widget, GdkEventButton *event, gpointer data)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = (GtkFrontend *)data;
return button_internal(inst, event);
}
#if GTK_CHECK_VERSION(2,0,0)
/*
* In GTK 2, mouse wheel events have become a new type of event.
* This handler translates them back into button-4 and button-5
* presses so that I don't have to change my old code too much :-)
*/
gboolean scroll_event(GtkWidget *widget, GdkEventScroll *event, gpointer data)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = (GtkFrontend *)data;
#if GTK_CHECK_VERSION(3,4,0)
gdouble dx, dy;
if (gdk_event_get_scroll_deltas((GdkEvent *)event, &dx, &dy)) {
return scroll_internal(inst, dy, event->state, event->x, event->y);
} else
return false;
#else
guint button;
GdkEventButton *event_button;
gboolean ret;
if (event->direction == GDK_SCROLL_UP)
button = 4;
else if (event->direction == GDK_SCROLL_DOWN)
button = 5;
else
return false;
event_button = (GdkEventButton *)gdk_event_new(GDK_BUTTON_PRESS);
event_button->window = g_object_ref(event->window);
event_button->send_event = event->send_event;
event_button->time = event->time;
event_button->x = event->x;
event_button->y = event->y;
event_button->axes = NULL;
event_button->state = event->state;
event_button->button = button;
event_button->device = g_object_ref(event->device);
event_button->x_root = event->x_root;
event_button->y_root = event->y_root;
ret = button_internal(inst, event_button);
gdk_event_free((GdkEvent *)event_button);
return ret;
#endif
}
#endif
gint motion_event(GtkWidget *widget, GdkEventMotion *event, gpointer data)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = (GtkFrontend *)data;
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
bool shift, ctrl, alt;
int x, y, button;
/* Remember the timestamp. */
inst->input_event_time = event->time;
noise_ultralight(NOISE_SOURCE_MOUSEPOS,
((uint32_t)event->x << 16) | (uint32_t)event->y);
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
show_mouseptr(inst, true);
shift = event->state & GDK_SHIFT_MASK;
ctrl = event->state & GDK_CONTROL_MASK;
alt = event->state & inst->meta_mod_mask;
if (event->state & GDK_BUTTON1_MASK)
button = MBT_LEFT;
else if (event->state & GDK_BUTTON2_MASK)
button = MBT_MIDDLE;
else if (event->state & GDK_BUTTON3_MASK)
button = MBT_RIGHT;
else
return false; /* don't even know what button! */
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
x = (event->x - inst->window_border) / inst->font_width;
y = (event->y - inst->window_border) / inst->font_height;
term_mouse(inst->term, button, translate_button(button), MA_DRAG,
x, y, shift, ctrl, alt);
return true;
}
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
static void key_pressed(GtkFrontend *inst)
{
/*
* If our child process has exited but not closed, terminate on
* any keypress.
*
* This is a UI feature specific to GTK PuTTY, because GTK PuTTY
* will (at least sometimes) be running under X, and under X the
* window manager is sometimes absent (very occasionally on
* purpose, more usually temporarily because it's crashed). So
* it's useful to have a way to close an application window
* without depending on protocols like WM_DELETE_WINDOW that are
* typically generated by the WM (e.g. in response to a close
* button in the window frame).
*/
if (inst->exited)
gtk_widget_destroy(inst->window);
}
static void exit_callback(void *vctx)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = (GtkFrontend *)vctx;
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
int exitcode, close_on_exit;
if (!inst->exited &&
(exitcode = backend_exitcode(inst->backend)) >= 0) {
destroy_inst_connection(inst);
close_on_exit = conf_get_int(inst->conf, CONF_close_on_exit);
if (close_on_exit == FORCE_ON ||
(close_on_exit == AUTO && exitcode == 0)) {
gtk_widget_destroy(inst->window);
}
}
}
New abstraction 'Seat', to pass to backends. This is a new vtable-based abstraction which is passed to a backend in place of Frontend, and it implements only the subset of the Frontend functions needed by a backend. (Many other Frontend functions still exist, notably the wide range of things called by terminal.c providing platform-independent operations on the GUI terminal window.) The purpose of making it a vtable is that this opens up the possibility of creating a backend as an internal implementation detail of some other activity, by providing just that one backend with a custom Seat that implements the methods differently. For example, this refactoring should make it feasible to directly implement an SSH proxy type, aka the 'jump host' feature supported by OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP mode, and then expose the main channel of that as the Socket for the primary connection'. (Which of course you can already do by spawning 'plink -nc' as a separate proxy process, but this would permit it in the _same_ process without anything getting confused.) I've centralised a full set of stub methods in misc.c for the new abstraction, which allows me to get rid of several annoying stubs in the previous code. Also, while I'm here, I've moved a lot of duplicated modalfatalbox() type functions from application main program files into wincons.c / uxcons.c, which I think saves duplication overall. (A minor visible effect is that the prefixes on those console-based fatal error messages will now be more consistent between applications.)
2018-10-11 21:58:42 +03:00
static void gtk_seat_notify_remote_exit(Seat *seat)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = container_of(seat, GtkFrontend, seat);
queue_toplevel_callback(exit_callback, inst);
}
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
static void destroy_inst_connection(GtkFrontend *inst)
{
inst->exited = true;
if (inst->ldisc) {
ldisc_free(inst->ldisc);
inst->ldisc = NULL;
}
if (inst->backend) {
backend_free(inst->backend);
inst->backend = NULL;
}
if (inst->term)
term_provide_backend(inst->term, NULL);
if (inst->menu) {
New abstraction 'Seat', to pass to backends. This is a new vtable-based abstraction which is passed to a backend in place of Frontend, and it implements only the subset of the Frontend functions needed by a backend. (Many other Frontend functions still exist, notably the wide range of things called by terminal.c providing platform-independent operations on the GUI terminal window.) The purpose of making it a vtable is that this opens up the possibility of creating a backend as an internal implementation detail of some other activity, by providing just that one backend with a custom Seat that implements the methods differently. For example, this refactoring should make it feasible to directly implement an SSH proxy type, aka the 'jump host' feature supported by OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP mode, and then expose the main channel of that as the Socket for the primary connection'. (Which of course you can already do by spawning 'plink -nc' as a separate proxy process, but this would permit it in the _same_ process without anything getting confused.) I've centralised a full set of stub methods in misc.c for the new abstraction, which allows me to get rid of several annoying stubs in the previous code. Also, while I'm here, I've moved a lot of duplicated modalfatalbox() type functions from application main program files into wincons.c / uxcons.c, which I think saves duplication overall. (A minor visible effect is that the prefixes on those console-based fatal error messages will now be more consistent between applications.)
2018-10-11 21:58:42 +03:00
seat_update_specials_menu(&inst->seat);
gtk_widget_set_sensitive(inst->restartitem, true);
}
}
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
static void delete_inst(GtkFrontend *inst)
{
int dialog_slot;
for (dialog_slot = 0; dialog_slot < DIALOG_SLOT_LIMIT; dialog_slot++) {
if (inst->dialogs[dialog_slot]) {
gtk_widget_destroy(inst->dialogs[dialog_slot]);
inst->dialogs[dialog_slot] = NULL;
}
}
if (inst->window) {
gtk_widget_destroy(inst->window);
inst->window = NULL;
}
if (inst->menu) {
gtk_widget_destroy(inst->menu);
inst->menu = NULL;
}
destroy_inst_connection(inst);
if (inst->term) {
term_free(inst->term);
inst->term = NULL;
}
if (inst->conf) {
conf_free(inst->conf);
inst->conf = NULL;
}
if (inst->logctx) {
log_free(inst->logctx);
inst->logctx = NULL;
}
#ifdef JUST_USE_GTK_CLIPBOARD_UTF8
/*
* Clear up any in-flight clipboard_data_instances. We can't
* actually _free_ them, but we detach them from the inst that's
* about to be destroyed.
*/
while (inst->cdi_headtail.next != &inst->cdi_headtail) {
struct clipboard_data_instance *cdi = inst->cdi_headtail.next;
cdi->state = NULL;
cdi->next->prev = cdi->prev;
cdi->prev->next = cdi->next;
cdi->next = cdi->prev = cdi;
}
#endif
/*
* Delete any top-level callbacks associated with inst, which
* would otherwise become stale-pointer dereferences waiting to
* happen. We do this last, because some of the above cleanups
* (notably shutting down the backend) might themelves queue such
* callbacks, so we need to make sure they don't do that _after_
* we're supposed to have cleaned everything up.
*/
delete_callbacks_for_context(inst);
eventlogstuff_free(inst->eventlogstuff);
sfree(inst);
}
void destroy(GtkWidget *widget, gpointer data)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = (GtkFrontend *)data;
inst->window = NULL;
delete_inst(inst);
session_window_closed();
}
gint focus_event(GtkWidget *widget, GdkEventFocus *event, gpointer data)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = (GtkFrontend *)data;
term_set_focus(inst->term, event->in);
term_update(inst->term);
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
show_mouseptr(inst, true);
return false;
}
New abstraction 'Seat', to pass to backends. This is a new vtable-based abstraction which is passed to a backend in place of Frontend, and it implements only the subset of the Frontend functions needed by a backend. (Many other Frontend functions still exist, notably the wide range of things called by terminal.c providing platform-independent operations on the GUI terminal window.) The purpose of making it a vtable is that this opens up the possibility of creating a backend as an internal implementation detail of some other activity, by providing just that one backend with a custom Seat that implements the methods differently. For example, this refactoring should make it feasible to directly implement an SSH proxy type, aka the 'jump host' feature supported by OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP mode, and then expose the main channel of that as the Socket for the primary connection'. (Which of course you can already do by spawning 'plink -nc' as a separate proxy process, but this would permit it in the _same_ process without anything getting confused.) I've centralised a full set of stub methods in misc.c for the new abstraction, which allows me to get rid of several annoying stubs in the previous code. Also, while I'm here, I've moved a lot of duplicated modalfatalbox() type functions from application main program files into wincons.c / uxcons.c, which I think saves duplication overall. (A minor visible effect is that the prefixes on those console-based fatal error messages will now be more consistent between applications.)
2018-10-11 21:58:42 +03:00
static void gtk_seat_set_busy_status(Seat *seat, BusyStatus status)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = container_of(seat, GtkFrontend, seat);
inst->busy_status = status;
update_mouseptr(inst);
}
/*
* set or clear the "raw mouse message" mode
*/
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
static void gtkwin_set_raw_mouse_mode(TermWin *tw, bool activate)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = container_of(tw, GtkFrontend, termwin);
activate = activate && !conf_get_bool(inst->conf, CONF_no_mouse_rep);
inst->send_raw_mouse = activate;
update_mouseptr(inst);
}
#if GTK_CHECK_VERSION(2,0,0)
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
static void compute_whole_window_size(GtkFrontend *inst,
int wchars, int hchars,
int *wpix, int *hpix);
#endif
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
static void gtkwin_request_resize(TermWin *tw, int w, int h)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = container_of(tw, GtkFrontend, termwin);
#if !GTK_CHECK_VERSION(3,0,0)
int large_x, large_y;
int offset_x, offset_y;
int area_x, area_y;
GtkRequisition inner, outer;
/*
* This is a heinous hack dreamed up by the gnome-terminal
* people to get around a limitation in gtk. The problem is
* that in order to set the size correctly we really need to be
* calling gtk_window_resize - but that needs to know the size
* of the _whole window_, not the drawing area. So what we do
* is to set an artificially huge size request on the drawing
* area, recompute the resulting size request on the window,
* and look at the difference between the two. That gives us
* the x and y offsets we need to translate drawing area size
* into window size for real, and then we call
* gtk_window_resize.
*/
/*
* We start by retrieving the current size of the whole window.
* Adding a bit to _that_ will give us a value we can use as a
* bogus size request which guarantees to be bigger than the
* current size of the drawing area.
*/
win_get_pixels(&inst->termwin, &large_x, &large_y);
large_x += 32;
large_y += 32;
gtk_widget_set_size_request(inst->area, large_x, large_y);
gtk_widget_size_request(inst->area, &inner);
gtk_widget_size_request(inst->window, &outer);
offset_x = outer.width - inner.width;
offset_y = outer.height - inner.height;
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
area_x = inst->font_width * w + 2*inst->window_border;
area_y = inst->font_height * h + 2*inst->window_border;
/*
* Now we must set the size request on the drawing area back to
* something sensible before we commit the real resize. Best
* way to do this, I think, is to set it to what the size is
* really going to end up being.
*/
gtk_widget_set_size_request(inst->area, area_x, area_y);
#if GTK_CHECK_VERSION(2,0,0)
gtk_window_resize(GTK_WINDOW(inst->window),
area_x + offset_x, area_y + offset_y);
#else
gtk_drawing_area_size(GTK_DRAWING_AREA(inst->area), area_x, area_y);
/*
* I can no longer remember what this call to
* gtk_container_dequeue_resize_handler is for. It was
* introduced in r3092 with no comment, and the commit log
* message was uninformative. I'm _guessing_ its purpose is to
* prevent gratuitous resize processing on the window given
* that we're about to resize it anyway, but I have no idea
* why that's so incredibly vital.
*
* I've tried removing the call, and nothing seems to go
* wrong. I've backtracked to r3092 and tried removing the
* call there, and still nothing goes wrong. So I'm going to
* adopt the working hypothesis that it's superfluous; I won't
* actually remove it from the GTK 1.2 code, but I won't
* attempt to replicate its functionality in the GTK 2 code
* above.
*/
gtk_container_dequeue_resize_handler(GTK_CONTAINER(inst->window));
gdk_window_resize(gtk_widget_get_window(inst->window),
area_x + offset_x, area_y + offset_y);
#endif
#else /* GTK_CHECK_VERSION(3,0,0) */
int wp, hp;
compute_whole_window_size(inst, w, h, &wp, &hp);
gtk_window_resize(GTK_WINDOW(inst->window), wp, hp);
#endif
}
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
static void real_palette_set(GtkFrontend *inst, int n, int r, int g, int b)
{
inst->cols[n].red = r * 0x0101;
inst->cols[n].green = g * 0x0101;
inst->cols[n].blue = b * 0x0101;
#if !GTK_CHECK_VERSION(3,0,0)
{
gboolean success[1];
gdk_colormap_free_colors(inst->colmap, inst->cols + n, 1);
gdk_colormap_alloc_colors(inst->colmap, inst->cols + n, 1,
false, true, success);
if (!success[0])
g_error("%s: couldn't allocate colour %d (#%02x%02x%02x)\n",
appname, n, r, g, b);
}
#endif
}
#if GTK_CHECK_VERSION(3,0,0)
char *colour_to_css(const GdkColor *col)
{
GdkRGBA rgba;
rgba.red = col->red / 65535.0;
rgba.green = col->green / 65535.0;
rgba.blue = col->blue / 65535.0;
rgba.alpha = 1.0;
return gdk_rgba_to_string(&rgba);
}
#endif
void set_gtk_widget_background(GtkWidget *widget, const GdkColor *col)
{
#if GTK_CHECK_VERSION(3,0,0)
GtkCssProvider *provider = gtk_css_provider_new();
char *col_css = colour_to_css(col);
char *data = dupprintf(
"#drawing-area, #top-level { background-color: %s; }\n", col_css);
gtk_css_provider_load_from_data(provider, data, -1, NULL);
GtkStyleContext *context = gtk_widget_get_style_context(widget);
gtk_style_context_add_provider(context, GTK_STYLE_PROVIDER(provider),
GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
free(data);
free(col_css);
#else
if (gtk_widget_get_window(widget)) {
/* For GTK1, which doesn't have a 'const' on
* gdk_window_set_background's second parameter type. */
GdkColor col_mutable = *col;
gdk_window_set_background(gtk_widget_get_window(widget), &col_mutable);
}
#endif
}
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
void set_window_background(GtkFrontend *inst)
{
if (inst->area)
set_gtk_widget_background(GTK_WIDGET(inst->area), &inst->cols[258]);
if (inst->window)
set_gtk_widget_background(GTK_WIDGET(inst->window), &inst->cols[258]);
}
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
static void gtkwin_palette_set(TermWin *tw, int n, int r, int g, int b)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = container_of(tw, GtkFrontend, termwin);
if (n >= 16)
n += 256 - 16;
if (n >= NALLCOLOURS)
return;
real_palette_set(inst, n, r, g, b);
if (n == 258) {
/* Default Background changed. Ensure space between text area and
* window border is redrawn */
set_window_background(inst);
draw_backing_rect(inst);
gtk_widget_queue_draw(inst->area);
}
}
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
static bool gtkwin_palette_get(TermWin *tw, int n, int *r, int *g, int *b)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = container_of(tw, GtkFrontend, termwin);
if (n < 0 || n >= NALLCOLOURS)
return false;
*r = inst->cols[n].red >> 8;
*g = inst->cols[n].green >> 8;
*b = inst->cols[n].blue >> 8;
return true;
}
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
static void gtkwin_palette_reset(TermWin *tw)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = container_of(tw, GtkFrontend, termwin);
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
/* This maps colour indices in inst->conf to those used in inst->cols. */
static const int ww[] = {
256, 257, 258, 259, 260, 261,
0, 8, 1, 9, 2, 10, 3, 11,
4, 12, 5, 13, 6, 14, 7, 15
};
int i;
assert(lenof(ww) == NCFGCOLOURS);
#if !GTK_CHECK_VERSION(3,0,0)
if (!inst->colmap) {
inst->colmap = gdk_colormap_get_system();
} else {
gdk_colormap_free_colors(inst->colmap, inst->cols, NALLCOLOURS);
}
#endif
for (i = 0; i < NCFGCOLOURS; i++) {
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
inst->cols[ww[i]].red =
conf_get_int_int(inst->conf, CONF_colours, i*3+0) * 0x0101;
inst->cols[ww[i]].green =
conf_get_int_int(inst->conf, CONF_colours, i*3+1) * 0x0101;
inst->cols[ww[i]].blue =
conf_get_int_int(inst->conf, CONF_colours, i*3+2) * 0x0101;
}
for (i = 0; i < NEXTCOLOURS; i++) {
if (i < 216) {
int r = i / 36, g = (i / 6) % 6, b = i % 6;
inst->cols[i+16].red = r ? r * 0x2828 + 0x3737 : 0;
inst->cols[i+16].green = g ? g * 0x2828 + 0x3737 : 0;
inst->cols[i+16].blue = b ? b * 0x2828 + 0x3737 : 0;
} else {
int shade = i - 216;
shade = shade * 0x0a0a + 0x0808;
inst->cols[i+16].red = inst->cols[i+16].green =
inst->cols[i+16].blue = shade;
}
}
#if !GTK_CHECK_VERSION(3,0,0)
{
gboolean success[NALLCOLOURS];
gdk_colormap_alloc_colors(inst->colmap, inst->cols, NALLCOLOURS,
false, true, success);
for (i = 0; i < NALLCOLOURS; i++) {
if (!success[i])
g_error("%s: couldn't allocate colour %d (#%02x%02x%02x)\n",
appname, i,
conf_get_int_int(inst->conf, CONF_colours, i*3+0),
conf_get_int_int(inst->conf, CONF_colours, i*3+1),
conf_get_int_int(inst->conf, CONF_colours, i*3+2));
}
}
#endif
/* Since Default Background may have changed, ensure that space
* between text area and window border is refreshed. */
set_window_background(inst);
if (inst->area && gtk_widget_get_window(inst->area)) {
draw_backing_rect(inst);
gtk_widget_queue_draw(inst->area);
}
}
static struct clipboard_state *clipboard_from_atom(
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst, GdkAtom atom)
{
int i;
for (i = 0; i < N_CLIPBOARDS; i++) {
struct clipboard_state *state = &inst->clipstates[i];
if (state->inst == inst && state->atom == atom)
return state;
}
return NULL;
}
Initial support for clipboard on OS X. Rather than trying to get my existing hugely complicated X-style clipboard code to somehow work with the Quartz GTK back end, I've written an entirely new and much simpler alternative clipboard handler usnig the higher-leve GtkClipboard interface. It assumes all clipboard text can be converted to and from UTF-8 sensibly (which isn't a good assumption on all front ends, but on OS X I think it's reasonable), and it talks to GDK_SELECTION_CLIPBOARD rather than PRIMARY, which is the only clipboard OS X has. I had to do a fiddly thing to cope with the fact that each call to gtk_clipboard_set_with_data caused a call to the clipboard clear function left over from the previous set of data, so I had to avoid mistaking that for a clipboard-clear for the _new_ data and immediately deselecting it. I did that by allocating a distinct placeholder object in memory for each instance of the copy operation, so that I can tell whether a clipboard-clear is for the current copy or a previous one. This is only very basic support which demonstrates successful copying and pasting is at least possible. For a sensible OS X implementation we'll need a more believable means of generating a paste UI action (it's quite easy to find a Mac on which neither Shift-Ins nor the third mouse button even exists!). Also, after the trouble I had with the clipboard-clear event, it's a bit annoying to find that it _doesn't_ seem to get called when another application becomes the clipboard owner. That may just be something we have to put up with, if I can't find any reason why it's failing.
2015-09-02 23:37:33 +03:00
#ifdef JUST_USE_GTK_CLIPBOARD_UTF8
/* ----------------------------------------------------------------------
* Clipboard handling, using the high-level GtkClipboard interface in
* as hands-off a way as possible. We write and read the clipboard as
* UTF-8 text, and let GTK deal with converting to any other text
* formats it feels like.
*/
Initial support for clipboard on OS X. Rather than trying to get my existing hugely complicated X-style clipboard code to somehow work with the Quartz GTK back end, I've written an entirely new and much simpler alternative clipboard handler usnig the higher-leve GtkClipboard interface. It assumes all clipboard text can be converted to and from UTF-8 sensibly (which isn't a good assumption on all front ends, but on OS X I think it's reasonable), and it talks to GDK_SELECTION_CLIPBOARD rather than PRIMARY, which is the only clipboard OS X has. I had to do a fiddly thing to cope with the fact that each call to gtk_clipboard_set_with_data caused a call to the clipboard clear function left over from the previous set of data, so I had to avoid mistaking that for a clipboard-clear for the _new_ data and immediately deselecting it. I did that by allocating a distinct placeholder object in memory for each instance of the copy operation, so that I can tell whether a clipboard-clear is for the current copy or a previous one. This is only very basic support which demonstrates successful copying and pasting is at least possible. For a sensible OS X implementation we'll need a more believable means of generating a paste UI action (it's quite easy to find a Mac on which neither Shift-Ins nor the third mouse button even exists!). Also, after the trouble I had with the clipboard-clear event, it's a bit annoying to find that it _doesn't_ seem to get called when another application becomes the clipboard owner. That may just be something we have to put up with, if I can't find any reason why it's failing.
2015-09-02 23:37:33 +03:00
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
void set_clipboard_atom(GtkFrontend *inst, int clipboard, GdkAtom atom)
{
struct clipboard_state *state = &inst->clipstates[clipboard];
state->inst = inst;
state->clipboard = clipboard;
state->atom = atom;
if (state->atom != GDK_NONE) {
state->gtkclipboard = gtk_clipboard_get_for_display(
gdk_display_get_default(), state->atom);
g_object_set_data(G_OBJECT(state->gtkclipboard), "user-data", state);
} else {
state->gtkclipboard = NULL;
}
}
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
int init_clipboard(GtkFrontend *inst)
{
set_clipboard_atom(inst, CLIP_PRIMARY, GDK_SELECTION_PRIMARY);
set_clipboard_atom(inst, CLIP_CLIPBOARD, clipboard_atom);
return true;
Initial support for clipboard on OS X. Rather than trying to get my existing hugely complicated X-style clipboard code to somehow work with the Quartz GTK back end, I've written an entirely new and much simpler alternative clipboard handler usnig the higher-leve GtkClipboard interface. It assumes all clipboard text can be converted to and from UTF-8 sensibly (which isn't a good assumption on all front ends, but on OS X I think it's reasonable), and it talks to GDK_SELECTION_CLIPBOARD rather than PRIMARY, which is the only clipboard OS X has. I had to do a fiddly thing to cope with the fact that each call to gtk_clipboard_set_with_data caused a call to the clipboard clear function left over from the previous set of data, so I had to avoid mistaking that for a clipboard-clear for the _new_ data and immediately deselecting it. I did that by allocating a distinct placeholder object in memory for each instance of the copy operation, so that I can tell whether a clipboard-clear is for the current copy or a previous one. This is only very basic support which demonstrates successful copying and pasting is at least possible. For a sensible OS X implementation we'll need a more believable means of generating a paste UI action (it's quite easy to find a Mac on which neither Shift-Ins nor the third mouse button even exists!). Also, after the trouble I had with the clipboard-clear event, it's a bit annoying to find that it _doesn't_ seem to get called when another application becomes the clipboard owner. That may just be something we have to put up with, if I can't find any reason why it's failing.
2015-09-02 23:37:33 +03:00
}
static void clipboard_provide_data(GtkClipboard *clipboard,
GtkSelectionData *selection_data,
guint info, gpointer data)
{
struct clipboard_data_instance *cdi =
(struct clipboard_data_instance *)data;
if (cdi->state && cdi->state->current_cdi == cdi) {
Initial support for clipboard on OS X. Rather than trying to get my existing hugely complicated X-style clipboard code to somehow work with the Quartz GTK back end, I've written an entirely new and much simpler alternative clipboard handler usnig the higher-leve GtkClipboard interface. It assumes all clipboard text can be converted to and from UTF-8 sensibly (which isn't a good assumption on all front ends, but on OS X I think it's reasonable), and it talks to GDK_SELECTION_CLIPBOARD rather than PRIMARY, which is the only clipboard OS X has. I had to do a fiddly thing to cope with the fact that each call to gtk_clipboard_set_with_data caused a call to the clipboard clear function left over from the previous set of data, so I had to avoid mistaking that for a clipboard-clear for the _new_ data and immediately deselecting it. I did that by allocating a distinct placeholder object in memory for each instance of the copy operation, so that I can tell whether a clipboard-clear is for the current copy or a previous one. This is only very basic support which demonstrates successful copying and pasting is at least possible. For a sensible OS X implementation we'll need a more believable means of generating a paste UI action (it's quite easy to find a Mac on which neither Shift-Ins nor the third mouse button even exists!). Also, after the trouble I had with the clipboard-clear event, it's a bit annoying to find that it _doesn't_ seem to get called when another application becomes the clipboard owner. That may just be something we have to put up with, if I can't find any reason why it's failing.
2015-09-02 23:37:33 +03:00
gtk_selection_data_set_text(selection_data, cdi->pasteout_data_utf8,
cdi->pasteout_data_utf8_len);
}
}
static void clipboard_clear(GtkClipboard *clipboard, gpointer data)
{
struct clipboard_data_instance *cdi =
(struct clipboard_data_instance *)data;
if (cdi->state && cdi->state->current_cdi == cdi) {
if (cdi->state->inst && cdi->state->inst->term) {
term_lost_clipboard_ownership(cdi->state->inst->term,
cdi->state->clipboard);
}
cdi->state->current_cdi = NULL;
Initial support for clipboard on OS X. Rather than trying to get my existing hugely complicated X-style clipboard code to somehow work with the Quartz GTK back end, I've written an entirely new and much simpler alternative clipboard handler usnig the higher-leve GtkClipboard interface. It assumes all clipboard text can be converted to and from UTF-8 sensibly (which isn't a good assumption on all front ends, but on OS X I think it's reasonable), and it talks to GDK_SELECTION_CLIPBOARD rather than PRIMARY, which is the only clipboard OS X has. I had to do a fiddly thing to cope with the fact that each call to gtk_clipboard_set_with_data caused a call to the clipboard clear function left over from the previous set of data, so I had to avoid mistaking that for a clipboard-clear for the _new_ data and immediately deselecting it. I did that by allocating a distinct placeholder object in memory for each instance of the copy operation, so that I can tell whether a clipboard-clear is for the current copy or a previous one. This is only very basic support which demonstrates successful copying and pasting is at least possible. For a sensible OS X implementation we'll need a more believable means of generating a paste UI action (it's quite easy to find a Mac on which neither Shift-Ins nor the third mouse button even exists!). Also, after the trouble I had with the clipboard-clear event, it's a bit annoying to find that it _doesn't_ seem to get called when another application becomes the clipboard owner. That may just be something we have to put up with, if I can't find any reason why it's failing.
2015-09-02 23:37:33 +03:00
}
sfree(cdi->pasteout_data_utf8);
cdi->next->prev = cdi->prev;
cdi->prev->next = cdi->next;
Initial support for clipboard on OS X. Rather than trying to get my existing hugely complicated X-style clipboard code to somehow work with the Quartz GTK back end, I've written an entirely new and much simpler alternative clipboard handler usnig the higher-leve GtkClipboard interface. It assumes all clipboard text can be converted to and from UTF-8 sensibly (which isn't a good assumption on all front ends, but on OS X I think it's reasonable), and it talks to GDK_SELECTION_CLIPBOARD rather than PRIMARY, which is the only clipboard OS X has. I had to do a fiddly thing to cope with the fact that each call to gtk_clipboard_set_with_data caused a call to the clipboard clear function left over from the previous set of data, so I had to avoid mistaking that for a clipboard-clear for the _new_ data and immediately deselecting it. I did that by allocating a distinct placeholder object in memory for each instance of the copy operation, so that I can tell whether a clipboard-clear is for the current copy or a previous one. This is only very basic support which demonstrates successful copying and pasting is at least possible. For a sensible OS X implementation we'll need a more believable means of generating a paste UI action (it's quite easy to find a Mac on which neither Shift-Ins nor the third mouse button even exists!). Also, after the trouble I had with the clipboard-clear event, it's a bit annoying to find that it _doesn't_ seem to get called when another application becomes the clipboard owner. That may just be something we have to put up with, if I can't find any reason why it's failing.
2015-09-02 23:37:33 +03:00
sfree(cdi);
}
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
static void gtkwin_clip_write(
TermWin *tw, int clipboard, wchar_t *data, int *attr,
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
truecolour *truecolour, int len, bool must_deselect)
Initial support for clipboard on OS X. Rather than trying to get my existing hugely complicated X-style clipboard code to somehow work with the Quartz GTK back end, I've written an entirely new and much simpler alternative clipboard handler usnig the higher-leve GtkClipboard interface. It assumes all clipboard text can be converted to and from UTF-8 sensibly (which isn't a good assumption on all front ends, but on OS X I think it's reasonable), and it talks to GDK_SELECTION_CLIPBOARD rather than PRIMARY, which is the only clipboard OS X has. I had to do a fiddly thing to cope with the fact that each call to gtk_clipboard_set_with_data caused a call to the clipboard clear function left over from the previous set of data, so I had to avoid mistaking that for a clipboard-clear for the _new_ data and immediately deselecting it. I did that by allocating a distinct placeholder object in memory for each instance of the copy operation, so that I can tell whether a clipboard-clear is for the current copy or a previous one. This is only very basic support which demonstrates successful copying and pasting is at least possible. For a sensible OS X implementation we'll need a more believable means of generating a paste UI action (it's quite easy to find a Mac on which neither Shift-Ins nor the third mouse button even exists!). Also, after the trouble I had with the clipboard-clear event, it's a bit annoying to find that it _doesn't_ seem to get called when another application becomes the clipboard owner. That may just be something we have to put up with, if I can't find any reason why it's failing.
2015-09-02 23:37:33 +03:00
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = container_of(tw, GtkFrontend, termwin);
struct clipboard_state *state = &inst->clipstates[clipboard];
Initial support for clipboard on OS X. Rather than trying to get my existing hugely complicated X-style clipboard code to somehow work with the Quartz GTK back end, I've written an entirely new and much simpler alternative clipboard handler usnig the higher-leve GtkClipboard interface. It assumes all clipboard text can be converted to and from UTF-8 sensibly (which isn't a good assumption on all front ends, but on OS X I think it's reasonable), and it talks to GDK_SELECTION_CLIPBOARD rather than PRIMARY, which is the only clipboard OS X has. I had to do a fiddly thing to cope with the fact that each call to gtk_clipboard_set_with_data caused a call to the clipboard clear function left over from the previous set of data, so I had to avoid mistaking that for a clipboard-clear for the _new_ data and immediately deselecting it. I did that by allocating a distinct placeholder object in memory for each instance of the copy operation, so that I can tell whether a clipboard-clear is for the current copy or a previous one. This is only very basic support which demonstrates successful copying and pasting is at least possible. For a sensible OS X implementation we'll need a more believable means of generating a paste UI action (it's quite easy to find a Mac on which neither Shift-Ins nor the third mouse button even exists!). Also, after the trouble I had with the clipboard-clear event, it's a bit annoying to find that it _doesn't_ seem to get called when another application becomes the clipboard owner. That may just be something we have to put up with, if I can't find any reason why it's failing.
2015-09-02 23:37:33 +03:00
struct clipboard_data_instance *cdi;
if (inst->direct_to_font) {
/* In this clipboard mode, we just can't paste if we're in
* direct-to-font mode. Fortunately, that shouldn't be
* important, because we'll only use this clipboard handling
* code on systems where that kind of font doesn't exist
* anyway. */
return;
}
if (!state->gtkclipboard)
return;
Initial support for clipboard on OS X. Rather than trying to get my existing hugely complicated X-style clipboard code to somehow work with the Quartz GTK back end, I've written an entirely new and much simpler alternative clipboard handler usnig the higher-leve GtkClipboard interface. It assumes all clipboard text can be converted to and from UTF-8 sensibly (which isn't a good assumption on all front ends, but on OS X I think it's reasonable), and it talks to GDK_SELECTION_CLIPBOARD rather than PRIMARY, which is the only clipboard OS X has. I had to do a fiddly thing to cope with the fact that each call to gtk_clipboard_set_with_data caused a call to the clipboard clear function left over from the previous set of data, so I had to avoid mistaking that for a clipboard-clear for the _new_ data and immediately deselecting it. I did that by allocating a distinct placeholder object in memory for each instance of the copy operation, so that I can tell whether a clipboard-clear is for the current copy or a previous one. This is only very basic support which demonstrates successful copying and pasting is at least possible. For a sensible OS X implementation we'll need a more believable means of generating a paste UI action (it's quite easy to find a Mac on which neither Shift-Ins nor the third mouse button even exists!). Also, after the trouble I had with the clipboard-clear event, it's a bit annoying to find that it _doesn't_ seem to get called when another application becomes the clipboard owner. That may just be something we have to put up with, if I can't find any reason why it's failing.
2015-09-02 23:37:33 +03:00
cdi = snew(struct clipboard_data_instance);
cdi->state = state;
state->current_cdi = cdi;
Initial support for clipboard on OS X. Rather than trying to get my existing hugely complicated X-style clipboard code to somehow work with the Quartz GTK back end, I've written an entirely new and much simpler alternative clipboard handler usnig the higher-leve GtkClipboard interface. It assumes all clipboard text can be converted to and from UTF-8 sensibly (which isn't a good assumption on all front ends, but on OS X I think it's reasonable), and it talks to GDK_SELECTION_CLIPBOARD rather than PRIMARY, which is the only clipboard OS X has. I had to do a fiddly thing to cope with the fact that each call to gtk_clipboard_set_with_data caused a call to the clipboard clear function left over from the previous set of data, so I had to avoid mistaking that for a clipboard-clear for the _new_ data and immediately deselecting it. I did that by allocating a distinct placeholder object in memory for each instance of the copy operation, so that I can tell whether a clipboard-clear is for the current copy or a previous one. This is only very basic support which demonstrates successful copying and pasting is at least possible. For a sensible OS X implementation we'll need a more believable means of generating a paste UI action (it's quite easy to find a Mac on which neither Shift-Ins nor the third mouse button even exists!). Also, after the trouble I had with the clipboard-clear event, it's a bit annoying to find that it _doesn't_ seem to get called when another application becomes the clipboard owner. That may just be something we have to put up with, if I can't find any reason why it's failing.
2015-09-02 23:37:33 +03:00
cdi->pasteout_data_utf8 = snewn(len*6, char);
cdi->prev = inst->cdi_headtail.prev;
cdi->next = &inst->cdi_headtail;
cdi->next->prev = cdi;
cdi->prev->next = cdi;
Initial support for clipboard on OS X. Rather than trying to get my existing hugely complicated X-style clipboard code to somehow work with the Quartz GTK back end, I've written an entirely new and much simpler alternative clipboard handler usnig the higher-leve GtkClipboard interface. It assumes all clipboard text can be converted to and from UTF-8 sensibly (which isn't a good assumption on all front ends, but on OS X I think it's reasonable), and it talks to GDK_SELECTION_CLIPBOARD rather than PRIMARY, which is the only clipboard OS X has. I had to do a fiddly thing to cope with the fact that each call to gtk_clipboard_set_with_data caused a call to the clipboard clear function left over from the previous set of data, so I had to avoid mistaking that for a clipboard-clear for the _new_ data and immediately deselecting it. I did that by allocating a distinct placeholder object in memory for each instance of the copy operation, so that I can tell whether a clipboard-clear is for the current copy or a previous one. This is only very basic support which demonstrates successful copying and pasting is at least possible. For a sensible OS X implementation we'll need a more believable means of generating a paste UI action (it's quite easy to find a Mac on which neither Shift-Ins nor the third mouse button even exists!). Also, after the trouble I had with the clipboard-clear event, it's a bit annoying to find that it _doesn't_ seem to get called when another application becomes the clipboard owner. That may just be something we have to put up with, if I can't find any reason why it's failing.
2015-09-02 23:37:33 +03:00
{
const wchar_t *tmp = data;
int tmplen = len;
cdi->pasteout_data_utf8_len =
charset_from_unicode(&tmp, &tmplen, cdi->pasteout_data_utf8,
len*6, CS_UTF8, NULL, NULL, 0);
}
/*
* It would be nice to just call gtk_clipboard_set_text() in place
* of all of the faffing below. Unfortunately, that won't give me
* access to the clipboard-clear event, which we use to visually
* deselect text in the terminal.
*/
{
GtkTargetList *targetlist;
GtkTargetEntry *targettable;
gint n_targets;
targetlist = gtk_target_list_new(NULL, 0);
gtk_target_list_add_text_targets(targetlist, 0);
targettable = gtk_target_table_new_from_list(targetlist, &n_targets);
gtk_clipboard_set_with_data(state->gtkclipboard, targettable,
n_targets, clipboard_provide_data,
clipboard_clear, cdi);
Initial support for clipboard on OS X. Rather than trying to get my existing hugely complicated X-style clipboard code to somehow work with the Quartz GTK back end, I've written an entirely new and much simpler alternative clipboard handler usnig the higher-leve GtkClipboard interface. It assumes all clipboard text can be converted to and from UTF-8 sensibly (which isn't a good assumption on all front ends, but on OS X I think it's reasonable), and it talks to GDK_SELECTION_CLIPBOARD rather than PRIMARY, which is the only clipboard OS X has. I had to do a fiddly thing to cope with the fact that each call to gtk_clipboard_set_with_data caused a call to the clipboard clear function left over from the previous set of data, so I had to avoid mistaking that for a clipboard-clear for the _new_ data and immediately deselecting it. I did that by allocating a distinct placeholder object in memory for each instance of the copy operation, so that I can tell whether a clipboard-clear is for the current copy or a previous one. This is only very basic support which demonstrates successful copying and pasting is at least possible. For a sensible OS X implementation we'll need a more believable means of generating a paste UI action (it's quite easy to find a Mac on which neither Shift-Ins nor the third mouse button even exists!). Also, after the trouble I had with the clipboard-clear event, it's a bit annoying to find that it _doesn't_ seem to get called when another application becomes the clipboard owner. That may just be something we have to put up with, if I can't find any reason why it's failing.
2015-09-02 23:37:33 +03:00
gtk_target_table_free(targettable, n_targets);
gtk_target_list_unref(targetlist);
}
}
static void clipboard_text_received(GtkClipboard *clipboard,
const gchar *text, gpointer data)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = (GtkFrontend *)data;
wchar_t *paste;
int paste_len;
Initial support for clipboard on OS X. Rather than trying to get my existing hugely complicated X-style clipboard code to somehow work with the Quartz GTK back end, I've written an entirely new and much simpler alternative clipboard handler usnig the higher-leve GtkClipboard interface. It assumes all clipboard text can be converted to and from UTF-8 sensibly (which isn't a good assumption on all front ends, but on OS X I think it's reasonable), and it talks to GDK_SELECTION_CLIPBOARD rather than PRIMARY, which is the only clipboard OS X has. I had to do a fiddly thing to cope with the fact that each call to gtk_clipboard_set_with_data caused a call to the clipboard clear function left over from the previous set of data, so I had to avoid mistaking that for a clipboard-clear for the _new_ data and immediately deselecting it. I did that by allocating a distinct placeholder object in memory for each instance of the copy operation, so that I can tell whether a clipboard-clear is for the current copy or a previous one. This is only very basic support which demonstrates successful copying and pasting is at least possible. For a sensible OS X implementation we'll need a more believable means of generating a paste UI action (it's quite easy to find a Mac on which neither Shift-Ins nor the third mouse button even exists!). Also, after the trouble I had with the clipboard-clear event, it's a bit annoying to find that it _doesn't_ seem to get called when another application becomes the clipboard owner. That may just be something we have to put up with, if I can't find any reason why it's failing.
2015-09-02 23:37:33 +03:00
int length;
if (!text)
return;
length = strlen(text);
paste = snewn(length, wchar_t);
paste_len = mb_to_wc(CS_UTF8, 0, text, length, paste, length);
Initial support for clipboard on OS X. Rather than trying to get my existing hugely complicated X-style clipboard code to somehow work with the Quartz GTK back end, I've written an entirely new and much simpler alternative clipboard handler usnig the higher-leve GtkClipboard interface. It assumes all clipboard text can be converted to and from UTF-8 sensibly (which isn't a good assumption on all front ends, but on OS X I think it's reasonable), and it talks to GDK_SELECTION_CLIPBOARD rather than PRIMARY, which is the only clipboard OS X has. I had to do a fiddly thing to cope with the fact that each call to gtk_clipboard_set_with_data caused a call to the clipboard clear function left over from the previous set of data, so I had to avoid mistaking that for a clipboard-clear for the _new_ data and immediately deselecting it. I did that by allocating a distinct placeholder object in memory for each instance of the copy operation, so that I can tell whether a clipboard-clear is for the current copy or a previous one. This is only very basic support which demonstrates successful copying and pasting is at least possible. For a sensible OS X implementation we'll need a more believable means of generating a paste UI action (it's quite easy to find a Mac on which neither Shift-Ins nor the third mouse button even exists!). Also, after the trouble I had with the clipboard-clear event, it's a bit annoying to find that it _doesn't_ seem to get called when another application becomes the clipboard owner. That may just be something we have to put up with, if I can't find any reason why it's failing.
2015-09-02 23:37:33 +03:00
term_do_paste(inst->term, paste, paste_len);
Initial support for clipboard on OS X. Rather than trying to get my existing hugely complicated X-style clipboard code to somehow work with the Quartz GTK back end, I've written an entirely new and much simpler alternative clipboard handler usnig the higher-leve GtkClipboard interface. It assumes all clipboard text can be converted to and from UTF-8 sensibly (which isn't a good assumption on all front ends, but on OS X I think it's reasonable), and it talks to GDK_SELECTION_CLIPBOARD rather than PRIMARY, which is the only clipboard OS X has. I had to do a fiddly thing to cope with the fact that each call to gtk_clipboard_set_with_data caused a call to the clipboard clear function left over from the previous set of data, so I had to avoid mistaking that for a clipboard-clear for the _new_ data and immediately deselecting it. I did that by allocating a distinct placeholder object in memory for each instance of the copy operation, so that I can tell whether a clipboard-clear is for the current copy or a previous one. This is only very basic support which demonstrates successful copying and pasting is at least possible. For a sensible OS X implementation we'll need a more believable means of generating a paste UI action (it's quite easy to find a Mac on which neither Shift-Ins nor the third mouse button even exists!). Also, after the trouble I had with the clipboard-clear event, it's a bit annoying to find that it _doesn't_ seem to get called when another application becomes the clipboard owner. That may just be something we have to put up with, if I can't find any reason why it's failing.
2015-09-02 23:37:33 +03:00
sfree(paste);
}
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
static void gtkwin_clip_request_paste(TermWin *tw, int clipboard)
Initial support for clipboard on OS X. Rather than trying to get my existing hugely complicated X-style clipboard code to somehow work with the Quartz GTK back end, I've written an entirely new and much simpler alternative clipboard handler usnig the higher-leve GtkClipboard interface. It assumes all clipboard text can be converted to and from UTF-8 sensibly (which isn't a good assumption on all front ends, but on OS X I think it's reasonable), and it talks to GDK_SELECTION_CLIPBOARD rather than PRIMARY, which is the only clipboard OS X has. I had to do a fiddly thing to cope with the fact that each call to gtk_clipboard_set_with_data caused a call to the clipboard clear function left over from the previous set of data, so I had to avoid mistaking that for a clipboard-clear for the _new_ data and immediately deselecting it. I did that by allocating a distinct placeholder object in memory for each instance of the copy operation, so that I can tell whether a clipboard-clear is for the current copy or a previous one. This is only very basic support which demonstrates successful copying and pasting is at least possible. For a sensible OS X implementation we'll need a more believable means of generating a paste UI action (it's quite easy to find a Mac on which neither Shift-Ins nor the third mouse button even exists!). Also, after the trouble I had with the clipboard-clear event, it's a bit annoying to find that it _doesn't_ seem to get called when another application becomes the clipboard owner. That may just be something we have to put up with, if I can't find any reason why it's failing.
2015-09-02 23:37:33 +03:00
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = container_of(tw, GtkFrontend, termwin);
struct clipboard_state *state = &inst->clipstates[clipboard];
if (!state->gtkclipboard)
return;
gtk_clipboard_request_text(state->gtkclipboard,
clipboard_text_received, inst);
Initial support for clipboard on OS X. Rather than trying to get my existing hugely complicated X-style clipboard code to somehow work with the Quartz GTK back end, I've written an entirely new and much simpler alternative clipboard handler usnig the higher-leve GtkClipboard interface. It assumes all clipboard text can be converted to and from UTF-8 sensibly (which isn't a good assumption on all front ends, but on OS X I think it's reasonable), and it talks to GDK_SELECTION_CLIPBOARD rather than PRIMARY, which is the only clipboard OS X has. I had to do a fiddly thing to cope with the fact that each call to gtk_clipboard_set_with_data caused a call to the clipboard clear function left over from the previous set of data, so I had to avoid mistaking that for a clipboard-clear for the _new_ data and immediately deselecting it. I did that by allocating a distinct placeholder object in memory for each instance of the copy operation, so that I can tell whether a clipboard-clear is for the current copy or a previous one. This is only very basic support which demonstrates successful copying and pasting is at least possible. For a sensible OS X implementation we'll need a more believable means of generating a paste UI action (it's quite easy to find a Mac on which neither Shift-Ins nor the third mouse button even exists!). Also, after the trouble I had with the clipboard-clear event, it's a bit annoying to find that it _doesn't_ seem to get called when another application becomes the clipboard owner. That may just be something we have to put up with, if I can't find any reason why it's failing.
2015-09-02 23:37:33 +03:00
}
#else /* JUST_USE_GTK_CLIPBOARD_UTF8 */
/* ----------------------------------------------------------------------
* Clipboard handling for X, using the low-level gtk_selection_*
* interface, handling conversions to fiddly things like compound text
* ourselves, and storing in X cut buffers too.
*
* This version of the clipboard code has to be kept around for GTK1,
* which doesn't have the higher-level GtkClipboard interface at all.
* And since it works on GTK2 and GTK3 too and has had a good few
* years of shakedown and bug fixing, we might as well keep using it
* where it's applicable.
*
* It's _possible_ that we might be able to replicate all the
* important wrinkles of this code in GtkClipboard. (In particular,
* cut buffers or local analogue look as if they might be accessible
* via gtk_clipboard_set_can_store(), and delivering text in
* non-Unicode formats only in the direct-to-font case ought to be
* possible if we can figure out the right set of things to put in the
* GtkTargetList.) But that work can wait until there's a need for it!
*/
/* Store the data in a cut-buffer. */
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
static void store_cutbuffer(GtkFrontend *inst, char *ptr, int len)
{
#ifndef NOT_X_WINDOWS
Basic support for running under GDK Wayland back end. GTK 3 PuTTY/pterm has always assumed that if it was compiled with _support_ for talking to the raw X11 layer underneath GTK and GDK, then it was entitled to expect that raw X11 layer to exist at all times, i.e. that GDK_DISPLAY_XDISPLAY would return a meaningful X display that it could do useful things with. So if you ran it over the GDK Wayland backend, it would immediately segfault. Modern GTK applications need to cope with multiple GDK backends at run time. It's fine for GTK PuTTY to _contain_ the code to find and use underlying X11 primitives like the display and the X window id, but it should be prepared to find that it's running on Wayland (or something else again!) so those functions don't return anything useful - in which case it should degrade gracefully to the subset of functionality that can be accessed through backend-independent GTK calls. Accordingly, I've centralised the use of GDK_DISPLAY_XDISPLAY into a support function get_x_display() in gtkmisc.c, which starts by checking that there actually is one first. All previous direct uses of GDK_*_XDISPLAY now go via that function, and check the result for NULL afterwards. (To save faffing about calling that function too many times, I'm also caching the display pointer in more places, and passing it as an extra argument to various subfunctions, mostly in gtkfont.c.) Similarly, the get_windowid() function that retrieves the window id to put in the environment of pterm's child process has to be prepared for there not to be a window id. This isn't a complete fix for all Wayland-related problems. The other one I'm currently aware of is that the default font is "server:fixed", which is a bad default now that it won't be available on all backends. And I expect that further problems will show up with more testing. But it's a start.
2018-05-09 11:18:20 +03:00
if (inst->disp) {
/* ICCCM says we must rotate the buffers before storing to buffer 0. */
XRotateBuffers(inst->disp, 1);
XStoreBytes(inst->disp, ptr, len);
}
#endif
}
/* Retrieve data from a cut-buffer.
* Returned data needs to be freed with XFree().
*/
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
static char *retrieve_cutbuffer(GtkFrontend *inst, int *nbytes)
{
#ifndef NOT_X_WINDOWS
Basic support for running under GDK Wayland back end. GTK 3 PuTTY/pterm has always assumed that if it was compiled with _support_ for talking to the raw X11 layer underneath GTK and GDK, then it was entitled to expect that raw X11 layer to exist at all times, i.e. that GDK_DISPLAY_XDISPLAY would return a meaningful X display that it could do useful things with. So if you ran it over the GDK Wayland backend, it would immediately segfault. Modern GTK applications need to cope with multiple GDK backends at run time. It's fine for GTK PuTTY to _contain_ the code to find and use underlying X11 primitives like the display and the X window id, but it should be prepared to find that it's running on Wayland (or something else again!) so those functions don't return anything useful - in which case it should degrade gracefully to the subset of functionality that can be accessed through backend-independent GTK calls. Accordingly, I've centralised the use of GDK_DISPLAY_XDISPLAY into a support function get_x_display() in gtkmisc.c, which starts by checking that there actually is one first. All previous direct uses of GDK_*_XDISPLAY now go via that function, and check the result for NULL afterwards. (To save faffing about calling that function too many times, I'm also caching the display pointer in more places, and passing it as an extra argument to various subfunctions, mostly in gtkfont.c.) Similarly, the get_windowid() function that retrieves the window id to put in the environment of pterm's child process has to be prepared for there not to be a window id. This isn't a complete fix for all Wayland-related problems. The other one I'm currently aware of is that the default font is "server:fixed", which is a bad default now that it won't be available on all backends. And I expect that further problems will show up with more testing. But it's a start.
2018-05-09 11:18:20 +03:00
char *ptr;
if (!inst->disp) {
*nbytes = 0;
return NULL;
}
ptr = XFetchBytes(inst->disp, nbytes);
if (*nbytes <= 0 && ptr != 0) {
XFree(ptr);
ptr = 0;
}
return ptr;
#else
Basic support for running under GDK Wayland back end. GTK 3 PuTTY/pterm has always assumed that if it was compiled with _support_ for talking to the raw X11 layer underneath GTK and GDK, then it was entitled to expect that raw X11 layer to exist at all times, i.e. that GDK_DISPLAY_XDISPLAY would return a meaningful X display that it could do useful things with. So if you ran it over the GDK Wayland backend, it would immediately segfault. Modern GTK applications need to cope with multiple GDK backends at run time. It's fine for GTK PuTTY to _contain_ the code to find and use underlying X11 primitives like the display and the X window id, but it should be prepared to find that it's running on Wayland (or something else again!) so those functions don't return anything useful - in which case it should degrade gracefully to the subset of functionality that can be accessed through backend-independent GTK calls. Accordingly, I've centralised the use of GDK_DISPLAY_XDISPLAY into a support function get_x_display() in gtkmisc.c, which starts by checking that there actually is one first. All previous direct uses of GDK_*_XDISPLAY now go via that function, and check the result for NULL afterwards. (To save faffing about calling that function too many times, I'm also caching the display pointer in more places, and passing it as an extra argument to various subfunctions, mostly in gtkfont.c.) Similarly, the get_windowid() function that retrieves the window id to put in the environment of pterm's child process has to be prepared for there not to be a window id. This isn't a complete fix for all Wayland-related problems. The other one I'm currently aware of is that the default font is "server:fixed", which is a bad default now that it won't be available on all backends. And I expect that further problems will show up with more testing. But it's a start.
2018-05-09 11:18:20 +03:00
*nbytes = 0;
return NULL;
#endif
}
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
static void gtkwin_clip_write(
TermWin *tw, int clipboard, wchar_t *data, int *attr,
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
truecolour *truecolour, int len, bool must_deselect)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = container_of(tw, GtkFrontend, termwin);
struct clipboard_state *state = &inst->clipstates[clipboard];
if (state->pasteout_data)
sfree(state->pasteout_data);
if (state->pasteout_data_ctext)
sfree(state->pasteout_data_ctext);
if (state->pasteout_data_utf8)
sfree(state->pasteout_data_utf8);
/*
* Set up UTF-8 and compound text paste data. This only happens
* if we aren't in direct-to-font mode using the D800 hack.
*/
if (!inst->direct_to_font) {
const wchar_t *tmp = data;
int tmplen = len;
#ifndef NOT_X_WINDOWS
XTextProperty tp;
char *list[1];
#endif
state->pasteout_data_utf8 = snewn(len*6, char);
state->pasteout_data_utf8_len = len*6;
state->pasteout_data_utf8_len =
charset_from_unicode(&tmp, &tmplen, state->pasteout_data_utf8,
state->pasteout_data_utf8_len,
CS_UTF8, NULL, NULL, 0);
if (state->pasteout_data_utf8_len == 0) {
sfree(state->pasteout_data_utf8);
state->pasteout_data_utf8 = NULL;
} else {
state->pasteout_data_utf8 =
sresize(state->pasteout_data_utf8,
state->pasteout_data_utf8_len + 1, char);
state->pasteout_data_utf8[state->pasteout_data_utf8_len] = '\0';
}
/*
* Now let Xlib convert our UTF-8 data into compound text.
*/
#ifndef NOT_X_WINDOWS
list[0] = state->pasteout_data_utf8;
Basic support for running under GDK Wayland back end. GTK 3 PuTTY/pterm has always assumed that if it was compiled with _support_ for talking to the raw X11 layer underneath GTK and GDK, then it was entitled to expect that raw X11 layer to exist at all times, i.e. that GDK_DISPLAY_XDISPLAY would return a meaningful X display that it could do useful things with. So if you ran it over the GDK Wayland backend, it would immediately segfault. Modern GTK applications need to cope with multiple GDK backends at run time. It's fine for GTK PuTTY to _contain_ the code to find and use underlying X11 primitives like the display and the X window id, but it should be prepared to find that it's running on Wayland (or something else again!) so those functions don't return anything useful - in which case it should degrade gracefully to the subset of functionality that can be accessed through backend-independent GTK calls. Accordingly, I've centralised the use of GDK_DISPLAY_XDISPLAY into a support function get_x_display() in gtkmisc.c, which starts by checking that there actually is one first. All previous direct uses of GDK_*_XDISPLAY now go via that function, and check the result for NULL afterwards. (To save faffing about calling that function too many times, I'm also caching the display pointer in more places, and passing it as an extra argument to various subfunctions, mostly in gtkfont.c.) Similarly, the get_windowid() function that retrieves the window id to put in the environment of pterm's child process has to be prepared for there not to be a window id. This isn't a complete fix for all Wayland-related problems. The other one I'm currently aware of is that the default font is "server:fixed", which is a bad default now that it won't be available on all backends. And I expect that further problems will show up with more testing. But it's a start.
2018-05-09 11:18:20 +03:00
if (inst->disp && Xutf8TextListToTextProperty(
inst->disp, list, 1, XCompoundTextStyle, &tp) == 0) {
state->pasteout_data_ctext = snewn(tp.nitems+1, char);
memcpy(state->pasteout_data_ctext, tp.value, tp.nitems);
state->pasteout_data_ctext_len = tp.nitems;
XFree(tp.value);
} else
#endif
{
state->pasteout_data_ctext = NULL;
state->pasteout_data_ctext_len = 0;
}
} else {
state->pasteout_data_utf8 = NULL;
state->pasteout_data_utf8_len = 0;
state->pasteout_data_ctext = NULL;
state->pasteout_data_ctext_len = 0;
}
state->pasteout_data = snewn(len*6, char);
state->pasteout_data_len = len*6;
state->pasteout_data_len = wc_to_mb(inst->ucsdata.line_codepage, 0,
data, len, state->pasteout_data,
state->pasteout_data_len,
NULL, NULL);
if (state->pasteout_data_len == 0) {
sfree(state->pasteout_data);
state->pasteout_data = NULL;
} else {
state->pasteout_data =
sresize(state->pasteout_data, state->pasteout_data_len, char);
}
/* The legacy X cut buffers go with PRIMARY, not any other clipboard */
if (state->atom == GDK_SELECTION_PRIMARY)
Basic support for running under GDK Wayland back end. GTK 3 PuTTY/pterm has always assumed that if it was compiled with _support_ for talking to the raw X11 layer underneath GTK and GDK, then it was entitled to expect that raw X11 layer to exist at all times, i.e. that GDK_DISPLAY_XDISPLAY would return a meaningful X display that it could do useful things with. So if you ran it over the GDK Wayland backend, it would immediately segfault. Modern GTK applications need to cope with multiple GDK backends at run time. It's fine for GTK PuTTY to _contain_ the code to find and use underlying X11 primitives like the display and the X window id, but it should be prepared to find that it's running on Wayland (or something else again!) so those functions don't return anything useful - in which case it should degrade gracefully to the subset of functionality that can be accessed through backend-independent GTK calls. Accordingly, I've centralised the use of GDK_DISPLAY_XDISPLAY into a support function get_x_display() in gtkmisc.c, which starts by checking that there actually is one first. All previous direct uses of GDK_*_XDISPLAY now go via that function, and check the result for NULL afterwards. (To save faffing about calling that function too many times, I'm also caching the display pointer in more places, and passing it as an extra argument to various subfunctions, mostly in gtkfont.c.) Similarly, the get_windowid() function that retrieves the window id to put in the environment of pterm's child process has to be prepared for there not to be a window id. This isn't a complete fix for all Wayland-related problems. The other one I'm currently aware of is that the default font is "server:fixed", which is a bad default now that it won't be available on all backends. And I expect that further problems will show up with more testing. But it's a start.
2018-05-09 11:18:20 +03:00
store_cutbuffer(inst, state->pasteout_data, state->pasteout_data_len);
if (gtk_selection_owner_set(inst->area, state->atom,
inst->input_event_time)) {
#if GTK_CHECK_VERSION(2,0,0)
gtk_selection_clear_targets(inst->area, state->atom);
#endif
gtk_selection_add_target(inst->area, state->atom,
GDK_SELECTION_TYPE_STRING, 1);
if (state->pasteout_data_ctext)
gtk_selection_add_target(inst->area, state->atom,
compound_text_atom, 1);
if (state->pasteout_data_utf8)
gtk_selection_add_target(inst->area, state->atom,
utf8_string_atom, 1);
}
if (must_deselect)
term_lost_clipboard_ownership(inst->term, clipboard);
}
Initial support for clipboard on OS X. Rather than trying to get my existing hugely complicated X-style clipboard code to somehow work with the Quartz GTK back end, I've written an entirely new and much simpler alternative clipboard handler usnig the higher-leve GtkClipboard interface. It assumes all clipboard text can be converted to and from UTF-8 sensibly (which isn't a good assumption on all front ends, but on OS X I think it's reasonable), and it talks to GDK_SELECTION_CLIPBOARD rather than PRIMARY, which is the only clipboard OS X has. I had to do a fiddly thing to cope with the fact that each call to gtk_clipboard_set_with_data caused a call to the clipboard clear function left over from the previous set of data, so I had to avoid mistaking that for a clipboard-clear for the _new_ data and immediately deselecting it. I did that by allocating a distinct placeholder object in memory for each instance of the copy operation, so that I can tell whether a clipboard-clear is for the current copy or a previous one. This is only very basic support which demonstrates successful copying and pasting is at least possible. For a sensible OS X implementation we'll need a more believable means of generating a paste UI action (it's quite easy to find a Mac on which neither Shift-Ins nor the third mouse button even exists!). Also, after the trouble I had with the clipboard-clear event, it's a bit annoying to find that it _doesn't_ seem to get called when another application becomes the clipboard owner. That may just be something we have to put up with, if I can't find any reason why it's failing.
2015-09-02 23:37:33 +03:00
static void selection_get(GtkWidget *widget, GtkSelectionData *seldata,
guint info, guint time_stamp, gpointer data)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = (GtkFrontend *)data;
GdkAtom target = gtk_selection_data_get_target(seldata);
struct clipboard_state *state = clipboard_from_atom(
inst, gtk_selection_data_get_selection(seldata));
if (!state)
return;
if (target == utf8_string_atom)
gtk_selection_data_set(seldata, target, 8,
(unsigned char *)state->pasteout_data_utf8,
state->pasteout_data_utf8_len);
else if (target == compound_text_atom)
gtk_selection_data_set(seldata, target, 8,
(unsigned char *)state->pasteout_data_ctext,
state->pasteout_data_ctext_len);
else
gtk_selection_data_set(seldata, target, 8,
(unsigned char *)state->pasteout_data,
state->pasteout_data_len);
}
Initial support for clipboard on OS X. Rather than trying to get my existing hugely complicated X-style clipboard code to somehow work with the Quartz GTK back end, I've written an entirely new and much simpler alternative clipboard handler usnig the higher-leve GtkClipboard interface. It assumes all clipboard text can be converted to and from UTF-8 sensibly (which isn't a good assumption on all front ends, but on OS X I think it's reasonable), and it talks to GDK_SELECTION_CLIPBOARD rather than PRIMARY, which is the only clipboard OS X has. I had to do a fiddly thing to cope with the fact that each call to gtk_clipboard_set_with_data caused a call to the clipboard clear function left over from the previous set of data, so I had to avoid mistaking that for a clipboard-clear for the _new_ data and immediately deselecting it. I did that by allocating a distinct placeholder object in memory for each instance of the copy operation, so that I can tell whether a clipboard-clear is for the current copy or a previous one. This is only very basic support which demonstrates successful copying and pasting is at least possible. For a sensible OS X implementation we'll need a more believable means of generating a paste UI action (it's quite easy to find a Mac on which neither Shift-Ins nor the third mouse button even exists!). Also, after the trouble I had with the clipboard-clear event, it's a bit annoying to find that it _doesn't_ seem to get called when another application becomes the clipboard owner. That may just be something we have to put up with, if I can't find any reason why it's failing.
2015-09-02 23:37:33 +03:00
static gint selection_clear(GtkWidget *widget, GdkEventSelection *seldata,
gpointer data)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = (GtkFrontend *)data;
struct clipboard_state *state = clipboard_from_atom(
inst, seldata->selection);
if (!state)
return true;
term_lost_clipboard_ownership(inst->term, state->clipboard);
if (state->pasteout_data)
sfree(state->pasteout_data);
if (state->pasteout_data_ctext)
sfree(state->pasteout_data_ctext);
if (state->pasteout_data_utf8)
sfree(state->pasteout_data_utf8);
state->pasteout_data = NULL;
state->pasteout_data_len = 0;
state->pasteout_data_ctext = NULL;
state->pasteout_data_ctext_len = 0;
state->pasteout_data_utf8 = NULL;
state->pasteout_data_utf8_len = 0;
return true;
}
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
static void gtkwin_clip_request_paste(TermWin *tw, int clipboard)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = container_of(tw, GtkFrontend, termwin);
struct clipboard_state *state = &inst->clipstates[clipboard];
/*
* In Unix, pasting is asynchronous: all we can do at the
* moment is to call gtk_selection_convert(), and when the data
* comes back _then_ we can call term_do_paste().
*/
if (!inst->direct_to_font) {
/*
* First we attempt to retrieve the selection as a UTF-8
* string (which we will convert to the correct code page
* before sending to the session, of course). If that
* fails, selection_received() will be informed and will
* fall back to an ordinary string.
*/
gtk_selection_convert(inst->area, state->atom, utf8_string_atom,
inst->input_event_time);
} else {
/*
* If we're in direct-to-font mode, we disable UTF-8
* pasting, and go straight to ordinary string data.
*/
gtk_selection_convert(inst->area, state->atom,
GDK_SELECTION_TYPE_STRING,
inst->input_event_time);
}
}
Initial support for clipboard on OS X. Rather than trying to get my existing hugely complicated X-style clipboard code to somehow work with the Quartz GTK back end, I've written an entirely new and much simpler alternative clipboard handler usnig the higher-leve GtkClipboard interface. It assumes all clipboard text can be converted to and from UTF-8 sensibly (which isn't a good assumption on all front ends, but on OS X I think it's reasonable), and it talks to GDK_SELECTION_CLIPBOARD rather than PRIMARY, which is the only clipboard OS X has. I had to do a fiddly thing to cope with the fact that each call to gtk_clipboard_set_with_data caused a call to the clipboard clear function left over from the previous set of data, so I had to avoid mistaking that for a clipboard-clear for the _new_ data and immediately deselecting it. I did that by allocating a distinct placeholder object in memory for each instance of the copy operation, so that I can tell whether a clipboard-clear is for the current copy or a previous one. This is only very basic support which demonstrates successful copying and pasting is at least possible. For a sensible OS X implementation we'll need a more believable means of generating a paste UI action (it's quite easy to find a Mac on which neither Shift-Ins nor the third mouse button even exists!). Also, after the trouble I had with the clipboard-clear event, it's a bit annoying to find that it _doesn't_ seem to get called when another application becomes the clipboard owner. That may just be something we have to put up with, if I can't find any reason why it's failing.
2015-09-02 23:37:33 +03:00
static void selection_received(GtkWidget *widget, GtkSelectionData *seldata,
guint time, gpointer data)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = (GtkFrontend *)data;
char *text;
int length;
#ifndef NOT_X_WINDOWS
char **list;
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
bool free_list_required = false;
bool free_required = false;
#endif
int charset;
GdkAtom seldata_target = gtk_selection_data_get_target(seldata);
GdkAtom seldata_type = gtk_selection_data_get_data_type(seldata);
const guchar *seldata_data = gtk_selection_data_get_data(seldata);
gint seldata_length = gtk_selection_data_get_length(seldata);
wchar_t *paste;
int paste_len;
struct clipboard_state *state = clipboard_from_atom(
inst, gtk_selection_data_get_selection(seldata));
if (!state)
return;
if (seldata_target == utf8_string_atom && seldata_length <= 0) {
/*
* Failed to get a UTF-8 selection string. Try compound
* text next.
*/
gtk_selection_convert(inst->area, state->atom,
compound_text_atom,
inst->input_event_time);
return;
}
if (seldata_target == compound_text_atom && seldata_length <= 0) {
/*
* Failed to get UTF-8 or compound text. Try an ordinary
* string.
*/
gtk_selection_convert(inst->area, state->atom,
GDK_SELECTION_TYPE_STRING,
inst->input_event_time);
return;
}
/*
* If we have data, but it's not of a type we can deal with,
* we have to ignore the data.
*/
if (seldata_length > 0 &&
seldata_type != GDK_SELECTION_TYPE_STRING &&
seldata_type != compound_text_atom &&
seldata_type != utf8_string_atom)
return;
/*
* If we have no data, try looking in a cut buffer.
*/
if (seldata_length <= 0) {
#ifndef NOT_X_WINDOWS
Basic support for running under GDK Wayland back end. GTK 3 PuTTY/pterm has always assumed that if it was compiled with _support_ for talking to the raw X11 layer underneath GTK and GDK, then it was entitled to expect that raw X11 layer to exist at all times, i.e. that GDK_DISPLAY_XDISPLAY would return a meaningful X display that it could do useful things with. So if you ran it over the GDK Wayland backend, it would immediately segfault. Modern GTK applications need to cope with multiple GDK backends at run time. It's fine for GTK PuTTY to _contain_ the code to find and use underlying X11 primitives like the display and the X window id, but it should be prepared to find that it's running on Wayland (or something else again!) so those functions don't return anything useful - in which case it should degrade gracefully to the subset of functionality that can be accessed through backend-independent GTK calls. Accordingly, I've centralised the use of GDK_DISPLAY_XDISPLAY into a support function get_x_display() in gtkmisc.c, which starts by checking that there actually is one first. All previous direct uses of GDK_*_XDISPLAY now go via that function, and check the result for NULL afterwards. (To save faffing about calling that function too many times, I'm also caching the display pointer in more places, and passing it as an extra argument to various subfunctions, mostly in gtkfont.c.) Similarly, the get_windowid() function that retrieves the window id to put in the environment of pterm's child process has to be prepared for there not to be a window id. This isn't a complete fix for all Wayland-related problems. The other one I'm currently aware of is that the default font is "server:fixed", which is a bad default now that it won't be available on all backends. And I expect that further problems will show up with more testing. But it's a start.
2018-05-09 11:18:20 +03:00
text = retrieve_cutbuffer(inst, &length);
if (length == 0)
return;
/* Xterm is rumoured to expect Latin-1, though I havn't checked the
* source, so use that as a de-facto standard. */
charset = CS_ISO8859_1;
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
free_required = true;
#else
return;
#endif
} else {
/*
* Convert COMPOUND_TEXT into UTF-8.
*/
if (seldata_type == compound_text_atom) {
#ifndef NOT_X_WINDOWS
XTextProperty tp;
int ret, count;
tp.value = (unsigned char *)seldata_data;
tp.encoding = (Atom) seldata_type;
tp.format = gtk_selection_data_get_format(seldata);
tp.nitems = seldata_length;
Basic support for running under GDK Wayland back end. GTK 3 PuTTY/pterm has always assumed that if it was compiled with _support_ for talking to the raw X11 layer underneath GTK and GDK, then it was entitled to expect that raw X11 layer to exist at all times, i.e. that GDK_DISPLAY_XDISPLAY would return a meaningful X display that it could do useful things with. So if you ran it over the GDK Wayland backend, it would immediately segfault. Modern GTK applications need to cope with multiple GDK backends at run time. It's fine for GTK PuTTY to _contain_ the code to find and use underlying X11 primitives like the display and the X window id, but it should be prepared to find that it's running on Wayland (or something else again!) so those functions don't return anything useful - in which case it should degrade gracefully to the subset of functionality that can be accessed through backend-independent GTK calls. Accordingly, I've centralised the use of GDK_DISPLAY_XDISPLAY into a support function get_x_display() in gtkmisc.c, which starts by checking that there actually is one first. All previous direct uses of GDK_*_XDISPLAY now go via that function, and check the result for NULL afterwards. (To save faffing about calling that function too many times, I'm also caching the display pointer in more places, and passing it as an extra argument to various subfunctions, mostly in gtkfont.c.) Similarly, the get_windowid() function that retrieves the window id to put in the environment of pterm's child process has to be prepared for there not to be a window id. This isn't a complete fix for all Wayland-related problems. The other one I'm currently aware of is that the default font is "server:fixed", which is a bad default now that it won't be available on all backends. And I expect that further problems will show up with more testing. But it's a start.
2018-05-09 11:18:20 +03:00
ret = inst->disp == NULL ? -1 :
Xutf8TextPropertyToTextList(inst->disp, &tp, &list, &count);
if (ret == 0 && count == 1) {
text = list[0];
length = strlen(list[0]);
charset = CS_UTF8;
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
free_list_required = true;
} else
#endif
{
/*
* Compound text failed; fall back to STRING.
*/
gtk_selection_convert(inst->area, state->atom,
GDK_SELECTION_TYPE_STRING,
inst->input_event_time);
return;
}
} else {
text = (char *)seldata_data;
length = seldata_length;
charset = (seldata_type == utf8_string_atom ?
CS_UTF8 : inst->ucsdata.line_codepage);
}
}
paste = snewn(length, wchar_t);
paste_len = mb_to_wc(charset, 0, text, length, paste, length);
term_do_paste(inst->term, paste, paste_len);
sfree(paste);
#ifndef NOT_X_WINDOWS
if (free_list_required)
XFreeStringList(list);
if (free_required)
XFree(text);
#endif
}
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
static void init_one_clipboard(GtkFrontend *inst, int clipboard)
{
struct clipboard_state *state = &inst->clipstates[clipboard];
state->inst = inst;
state->clipboard = clipboard;
}
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
void set_clipboard_atom(GtkFrontend *inst, int clipboard, GdkAtom atom)
{
struct clipboard_state *state = &inst->clipstates[clipboard];
state->inst = inst;
state->clipboard = clipboard;
state->atom = atom;
}
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
void init_clipboard(GtkFrontend *inst)
Initial support for clipboard on OS X. Rather than trying to get my existing hugely complicated X-style clipboard code to somehow work with the Quartz GTK back end, I've written an entirely new and much simpler alternative clipboard handler usnig the higher-leve GtkClipboard interface. It assumes all clipboard text can be converted to and from UTF-8 sensibly (which isn't a good assumption on all front ends, but on OS X I think it's reasonable), and it talks to GDK_SELECTION_CLIPBOARD rather than PRIMARY, which is the only clipboard OS X has. I had to do a fiddly thing to cope with the fact that each call to gtk_clipboard_set_with_data caused a call to the clipboard clear function left over from the previous set of data, so I had to avoid mistaking that for a clipboard-clear for the _new_ data and immediately deselecting it. I did that by allocating a distinct placeholder object in memory for each instance of the copy operation, so that I can tell whether a clipboard-clear is for the current copy or a previous one. This is only very basic support which demonstrates successful copying and pasting is at least possible. For a sensible OS X implementation we'll need a more believable means of generating a paste UI action (it's quite easy to find a Mac on which neither Shift-Ins nor the third mouse button even exists!). Also, after the trouble I had with the clipboard-clear event, it's a bit annoying to find that it _doesn't_ seem to get called when another application becomes the clipboard owner. That may just be something we have to put up with, if I can't find any reason why it's failing.
2015-09-02 23:37:33 +03:00
{
#ifndef NOT_X_WINDOWS
/*
* Ensure that all the cut buffers exist - according to the ICCCM,
* we must do this before we start using cut buffers.
*/
Basic support for running under GDK Wayland back end. GTK 3 PuTTY/pterm has always assumed that if it was compiled with _support_ for talking to the raw X11 layer underneath GTK and GDK, then it was entitled to expect that raw X11 layer to exist at all times, i.e. that GDK_DISPLAY_XDISPLAY would return a meaningful X display that it could do useful things with. So if you ran it over the GDK Wayland backend, it would immediately segfault. Modern GTK applications need to cope with multiple GDK backends at run time. It's fine for GTK PuTTY to _contain_ the code to find and use underlying X11 primitives like the display and the X window id, but it should be prepared to find that it's running on Wayland (or something else again!) so those functions don't return anything useful - in which case it should degrade gracefully to the subset of functionality that can be accessed through backend-independent GTK calls. Accordingly, I've centralised the use of GDK_DISPLAY_XDISPLAY into a support function get_x_display() in gtkmisc.c, which starts by checking that there actually is one first. All previous direct uses of GDK_*_XDISPLAY now go via that function, and check the result for NULL afterwards. (To save faffing about calling that function too many times, I'm also caching the display pointer in more places, and passing it as an extra argument to various subfunctions, mostly in gtkfont.c.) Similarly, the get_windowid() function that retrieves the window id to put in the environment of pterm's child process has to be prepared for there not to be a window id. This isn't a complete fix for all Wayland-related problems. The other one I'm currently aware of is that the default font is "server:fixed", which is a bad default now that it won't be available on all backends. And I expect that further problems will show up with more testing. But it's a start.
2018-05-09 11:18:20 +03:00
if (inst->disp) {
unsigned char empty[] = "";
x11_ignore_error(inst->disp, BadMatch);
XChangeProperty(inst->disp, GDK_ROOT_WINDOW(), XA_CUT_BUFFER0,
XA_STRING, 8, PropModeAppend, empty, 0);
x11_ignore_error(inst->disp, BadMatch);
XChangeProperty(inst->disp, GDK_ROOT_WINDOW(), XA_CUT_BUFFER1,
XA_STRING, 8, PropModeAppend, empty, 0);
x11_ignore_error(inst->disp, BadMatch);
XChangeProperty(inst->disp, GDK_ROOT_WINDOW(), XA_CUT_BUFFER2,
XA_STRING, 8, PropModeAppend, empty, 0);
x11_ignore_error(inst->disp, BadMatch);
XChangeProperty(inst->disp, GDK_ROOT_WINDOW(), XA_CUT_BUFFER3,
XA_STRING, 8, PropModeAppend, empty, 0);
x11_ignore_error(inst->disp, BadMatch);
XChangeProperty(inst->disp, GDK_ROOT_WINDOW(), XA_CUT_BUFFER4,
XA_STRING, 8, PropModeAppend, empty, 0);
x11_ignore_error(inst->disp, BadMatch);
XChangeProperty(inst->disp, GDK_ROOT_WINDOW(), XA_CUT_BUFFER5,
XA_STRING, 8, PropModeAppend, empty, 0);
x11_ignore_error(inst->disp, BadMatch);
XChangeProperty(inst->disp, GDK_ROOT_WINDOW(), XA_CUT_BUFFER6,
XA_STRING, 8, PropModeAppend, empty, 0);
x11_ignore_error(inst->disp, BadMatch);
XChangeProperty(inst->disp, GDK_ROOT_WINDOW(), XA_CUT_BUFFER7,
XA_STRING, 8, PropModeAppend, empty, 0);
}
Initial support for clipboard on OS X. Rather than trying to get my existing hugely complicated X-style clipboard code to somehow work with the Quartz GTK back end, I've written an entirely new and much simpler alternative clipboard handler usnig the higher-leve GtkClipboard interface. It assumes all clipboard text can be converted to and from UTF-8 sensibly (which isn't a good assumption on all front ends, but on OS X I think it's reasonable), and it talks to GDK_SELECTION_CLIPBOARD rather than PRIMARY, which is the only clipboard OS X has. I had to do a fiddly thing to cope with the fact that each call to gtk_clipboard_set_with_data caused a call to the clipboard clear function left over from the previous set of data, so I had to avoid mistaking that for a clipboard-clear for the _new_ data and immediately deselecting it. I did that by allocating a distinct placeholder object in memory for each instance of the copy operation, so that I can tell whether a clipboard-clear is for the current copy or a previous one. This is only very basic support which demonstrates successful copying and pasting is at least possible. For a sensible OS X implementation we'll need a more believable means of generating a paste UI action (it's quite easy to find a Mac on which neither Shift-Ins nor the third mouse button even exists!). Also, after the trouble I had with the clipboard-clear event, it's a bit annoying to find that it _doesn't_ seem to get called when another application becomes the clipboard owner. That may just be something we have to put up with, if I can't find any reason why it's failing.
2015-09-02 23:37:33 +03:00
#endif
inst->clipstates[CLIP_PRIMARY].atom = GDK_SELECTION_PRIMARY;
inst->clipstates[CLIP_CLIPBOARD].atom = clipboard_atom;
init_one_clipboard(inst, CLIP_PRIMARY);
init_one_clipboard(inst, CLIP_CLIPBOARD);
Initial support for clipboard on OS X. Rather than trying to get my existing hugely complicated X-style clipboard code to somehow work with the Quartz GTK back end, I've written an entirely new and much simpler alternative clipboard handler usnig the higher-leve GtkClipboard interface. It assumes all clipboard text can be converted to and from UTF-8 sensibly (which isn't a good assumption on all front ends, but on OS X I think it's reasonable), and it talks to GDK_SELECTION_CLIPBOARD rather than PRIMARY, which is the only clipboard OS X has. I had to do a fiddly thing to cope with the fact that each call to gtk_clipboard_set_with_data caused a call to the clipboard clear function left over from the previous set of data, so I had to avoid mistaking that for a clipboard-clear for the _new_ data and immediately deselecting it. I did that by allocating a distinct placeholder object in memory for each instance of the copy operation, so that I can tell whether a clipboard-clear is for the current copy or a previous one. This is only very basic support which demonstrates successful copying and pasting is at least possible. For a sensible OS X implementation we'll need a more believable means of generating a paste UI action (it's quite easy to find a Mac on which neither Shift-Ins nor the third mouse button even exists!). Also, after the trouble I had with the clipboard-clear event, it's a bit annoying to find that it _doesn't_ seem to get called when another application becomes the clipboard owner. That may just be something we have to put up with, if I can't find any reason why it's failing.
2015-09-02 23:37:33 +03:00
g_signal_connect(G_OBJECT(inst->area), "selection_received",
G_CALLBACK(selection_received), inst);
g_signal_connect(G_OBJECT(inst->area), "selection_get",
G_CALLBACK(selection_get), inst);
g_signal_connect(G_OBJECT(inst->area), "selection_clear_event",
G_CALLBACK(selection_clear), inst);
}
/*
* End of selection/clipboard handling.
* ----------------------------------------------------------------------
*/
#endif /* JUST_USE_GTK_CLIPBOARD_UTF8 */
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
static void set_window_titles(GtkFrontend *inst)
{
/*
* We must always call set_icon_name after calling set_title,
* since set_title will write both names. Irritating, but such
* is life.
*/
gtk_window_set_title(GTK_WINDOW(inst->window), inst->wintitle);
if (!conf_get_bool(inst->conf, CONF_win_name_always))
gdk_window_set_icon_name(gtk_widget_get_window(inst->window),
inst->icontitle);
}
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
static void gtkwin_set_title(TermWin *tw, const char *title)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = container_of(tw, GtkFrontend, termwin);
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
sfree(inst->wintitle);
inst->wintitle = dupstr(title);
set_window_titles(inst);
}
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
static void gtkwin_set_icon_title(TermWin *tw, const char *title)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = container_of(tw, GtkFrontend, termwin);
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
sfree(inst->icontitle);
inst->icontitle = dupstr(title);
set_window_titles(inst);
}
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
void set_title_and_icon(GtkFrontend *inst, char *title, char *icon)
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
{
sfree(inst->wintitle);
inst->wintitle = dupstr(title);
sfree(inst->icontitle);
inst->icontitle = dupstr(icon);
set_window_titles(inst);
}
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
static void gtkwin_set_scrollbar(TermWin *tw, int total, int start, int page)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = container_of(tw, GtkFrontend, termwin);
if (!conf_get_bool(inst->conf, CONF_scrollbar))
return;
inst->ignore_sbar = true;
gtk_adjustment_set_lower(inst->sbar_adjust, 0);
gtk_adjustment_set_upper(inst->sbar_adjust, total);
gtk_adjustment_set_value(inst->sbar_adjust, start);
gtk_adjustment_set_page_size(inst->sbar_adjust, page);
gtk_adjustment_set_step_increment(inst->sbar_adjust, 1);
gtk_adjustment_set_page_increment(inst->sbar_adjust, page/2);
#if !GTK_CHECK_VERSION(3,18,0)
gtk_adjustment_changed(inst->sbar_adjust);
#endif
inst->ignore_sbar = false;
}
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
void scrollbar_moved(GtkAdjustment *adj, GtkFrontend *inst)
{
if (!conf_get_bool(inst->conf, CONF_scrollbar))
return;
if (!inst->ignore_sbar)
term_scroll(inst->term, 1, (int)gtk_adjustment_get_value(adj));
}
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
static void show_scrollbar(GtkFrontend *inst, gboolean visible)
{
inst->sbar_visible = visible;
if (visible)
gtk_widget_show(inst->sbar);
else
gtk_widget_hide(inst->sbar);
}
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
static void gtkwin_set_cursor_pos(TermWin *tw, int x, int y)
{
/*
* This is meaningless under X.
*/
}
/*
* This is still called when mode==BELL_VISUAL, even though the
* visual bell is handled entirely within terminal.c, because we
* may want to perform additional actions on any kind of bell (for
* example, taskbar flashing in Windows).
*/
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
static void gtkwin_bell(TermWin *tw, int mode)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
/* GtkFrontend *inst = container_of(tw, GtkFrontend, termwin); */
if (mode == BELL_DEFAULT)
gdk_display_beep(gdk_display_get_default());
}
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
static int gtkwin_char_width(TermWin *tw, int uc)
{
/*
* In this front end, double-width characters are handled using a
* separate font, so this can safely just return 1 always.
*/
return 1;
}
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
static bool gtkwin_setup_draw_ctx(TermWin *tw)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = container_of(tw, GtkFrontend, termwin);
if (!gtk_widget_get_window(inst->area))
return false;
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
inst->uctx.type = inst->drawtype;
Refactor the GTK drawing system to do both GDK and Cairo. We're going to have to use Cairo in the GTK3 port, because that's all GTK3 supports; but we still need old-style GDK for GTK1 support, and also for performance reasons in GTK2 (see below). Hence, this change completely restructures GTK PuTTY's drawing code so that there's a central 'drawing context' structure which contains a type code indicating GDK or Cairo, and then either some GDK gubbins or some Cairo gubbins as appropriate; all actual drawing is abstracted through a set of routines which test the type code in that structure and do one thing or another. And because the type code is tested at run time, both sets of drawing primitives can be compiled in at once, and where possible, they will be. X server-side bitmap fonts are still supported in the Cairo world, but because Cairo drawing is entirely client-side, they have to work by cheekily downloading each glyph bitmap from the server when it's first needed, and building up a client-side cache of 'cairo_surface_t's containing the bitmaps with which we then draw on the window. This technique works, but it's rather slow; hence, even in GTK2, we keep the GDK drawing back end compiled in, and switch over to it when the main selected font is a bitmap one. One visible effect of the new Cairo routines is in the double-width and double-height text you can get by sending ESC # 3, ESC # 4 and ESC # 6 escape sequences. In GDK, that's always been done by a really horrible process of manually scaling the bitmap, server-side, column by column and row by row, causing each pixel to be exactly doubled or quadrupled. But in Cairo, we can just set a transformation matrix, and then that takes effect _before_ the scalable fonts are rendered - so the results are visibly nicer, and use all the available resolution. (Sadly, if you're using a server-side bitmap font as your primary one, then the GDK backend will be selected for all drawing in the terminal as a whole - so in that situation, even fallback characters absent from the primary font and rendered by Pango will get the old GDK scaling treatment. It's only if your main font is scalable, so that the Cairo backend is selected, that DW/DH characters will come out looking nice.)
2015-08-15 23:05:56 +03:00
#ifdef DRAW_TEXT_GDK
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
if (inst->uctx.type == DRAWTYPE_GDK) {
Use a Cairo image surface as a client-side cache. In any DRAWTYPE_CAIRO mode, we now do all our Cairo drawing to a Cairo image surface which lives on the client; then we either blit directly from that to the window (if we're in GTK3 mode, or GTK2 without deprecated pieces of API), or else we blit from the Cairo surface to the server-side pixmap and then from there to the actual window. In DRAWTYPE_GDK mode, nothing much has changed: we still draw directly to the server-side pixmap using the GDK drawing API, then blit from there to the window. But there is one change, namely that the blit is no longer done proactively - instead, we queue a redraw of the affected rectangle, and wait until we're called back by the expose handler. The main aim of all this is to arrange that the only time we ever draw to the real window is in response to expose/draw events. The experimental GTK3 OS X port stopped working a week or two ago (I presume in response to an OS update) with the symptoms that attempts to draw on the window outside the context of a "draw" event handler just didn't seem to work any more; this change fixes it. In addition to that benefit, this change also has obvious performance advantages in principle. No more expensive text rendering in response to an expose event - just re-copy to the window from the bitmap we already have, from wherever it's stored that's nearest. Moreover, this seems to have fixed the significant performance problem with X server-side fonts under GTK. I didn't expect _that_! I'd guessed that the approach of downloading character bitmaps and rendering them manually via Cairo was just inherently slow for some reason. I've no real idea _why_ this change improves matters so much; my best guess is that perhaps there's an overhead in each drawing operation to a GDK Cairo surface, so we win by doing lots of operations to a much faster image surface and then batching them up into one GDK Cairo operation. But whyever it is, I'm certainly not complaining! (In fact, it now seems to be noticeably _faster_, at least on my usual local X displays, to draw server-side fonts using that technique than using the old GDK approach. I may yet decide to switch over...)
2015-09-24 16:08:25 +03:00
/* If we're doing GDK-based drawing, then we also expect
* inst->pixmap to exist. */
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
inst->uctx.u.gdk.target = inst->pixmap;
inst->uctx.u.gdk.gc = gdk_gc_new(gtk_widget_get_window(inst->area));
Refactor the GTK drawing system to do both GDK and Cairo. We're going to have to use Cairo in the GTK3 port, because that's all GTK3 supports; but we still need old-style GDK for GTK1 support, and also for performance reasons in GTK2 (see below). Hence, this change completely restructures GTK PuTTY's drawing code so that there's a central 'drawing context' structure which contains a type code indicating GDK or Cairo, and then either some GDK gubbins or some Cairo gubbins as appropriate; all actual drawing is abstracted through a set of routines which test the type code in that structure and do one thing or another. And because the type code is tested at run time, both sets of drawing primitives can be compiled in at once, and where possible, they will be. X server-side bitmap fonts are still supported in the Cairo world, but because Cairo drawing is entirely client-side, they have to work by cheekily downloading each glyph bitmap from the server when it's first needed, and building up a client-side cache of 'cairo_surface_t's containing the bitmaps with which we then draw on the window. This technique works, but it's rather slow; hence, even in GTK2, we keep the GDK drawing back end compiled in, and switch over to it when the main selected font is a bitmap one. One visible effect of the new Cairo routines is in the double-width and double-height text you can get by sending ESC # 3, ESC # 4 and ESC # 6 escape sequences. In GDK, that's always been done by a really horrible process of manually scaling the bitmap, server-side, column by column and row by row, causing each pixel to be exactly doubled or quadrupled. But in Cairo, we can just set a transformation matrix, and then that takes effect _before_ the scalable fonts are rendered - so the results are visibly nicer, and use all the available resolution. (Sadly, if you're using a server-side bitmap font as your primary one, then the GDK backend will be selected for all drawing in the terminal as a whole - so in that situation, even fallback characters absent from the primary font and rendered by Pango will get the old GDK scaling treatment. It's only if your main font is scalable, so that the Cairo backend is selected, that DW/DH characters will come out looking nice.)
2015-08-15 23:05:56 +03:00
}
#endif
#ifdef DRAW_TEXT_CAIRO
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
if (inst->uctx.type == DRAWTYPE_CAIRO) {
inst->uctx.u.cairo.widget = GTK_WIDGET(inst->area);
Use a Cairo image surface as a client-side cache. In any DRAWTYPE_CAIRO mode, we now do all our Cairo drawing to a Cairo image surface which lives on the client; then we either blit directly from that to the window (if we're in GTK3 mode, or GTK2 without deprecated pieces of API), or else we blit from the Cairo surface to the server-side pixmap and then from there to the actual window. In DRAWTYPE_GDK mode, nothing much has changed: we still draw directly to the server-side pixmap using the GDK drawing API, then blit from there to the window. But there is one change, namely that the blit is no longer done proactively - instead, we queue a redraw of the affected rectangle, and wait until we're called back by the expose handler. The main aim of all this is to arrange that the only time we ever draw to the real window is in response to expose/draw events. The experimental GTK3 OS X port stopped working a week or two ago (I presume in response to an OS update) with the symptoms that attempts to draw on the window outside the context of a "draw" event handler just didn't seem to work any more; this change fixes it. In addition to that benefit, this change also has obvious performance advantages in principle. No more expensive text rendering in response to an expose event - just re-copy to the window from the bitmap we already have, from wherever it's stored that's nearest. Moreover, this seems to have fixed the significant performance problem with X server-side fonts under GTK. I didn't expect _that_! I'd guessed that the approach of downloading character bitmaps and rendering them manually via Cairo was just inherently slow for some reason. I've no real idea _why_ this change improves matters so much; my best guess is that perhaps there's an overhead in each drawing operation to a GDK Cairo surface, so we win by doing lots of operations to a much faster image surface and then batching them up into one GDK Cairo operation. But whyever it is, I'm certainly not complaining! (In fact, it now seems to be noticeably _faster_, at least on my usual local X displays, to draw server-side fonts using that technique than using the old GDK approach. I may yet decide to switch over...)
2015-09-24 16:08:25 +03:00
/* 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. */
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
inst->uctx.u.cairo.cr = cairo_create(inst->surface);
cairo_scale(inst->uctx.u.cairo.cr, inst->scale, inst->scale);
cairo_setup_draw_ctx(inst);
Refactor the GTK drawing system to do both GDK and Cairo. We're going to have to use Cairo in the GTK3 port, because that's all GTK3 supports; but we still need old-style GDK for GTK1 support, and also for performance reasons in GTK2 (see below). Hence, this change completely restructures GTK PuTTY's drawing code so that there's a central 'drawing context' structure which contains a type code indicating GDK or Cairo, and then either some GDK gubbins or some Cairo gubbins as appropriate; all actual drawing is abstracted through a set of routines which test the type code in that structure and do one thing or another. And because the type code is tested at run time, both sets of drawing primitives can be compiled in at once, and where possible, they will be. X server-side bitmap fonts are still supported in the Cairo world, but because Cairo drawing is entirely client-side, they have to work by cheekily downloading each glyph bitmap from the server when it's first needed, and building up a client-side cache of 'cairo_surface_t's containing the bitmaps with which we then draw on the window. This technique works, but it's rather slow; hence, even in GTK2, we keep the GDK drawing back end compiled in, and switch over to it when the main selected font is a bitmap one. One visible effect of the new Cairo routines is in the double-width and double-height text you can get by sending ESC # 3, ESC # 4 and ESC # 6 escape sequences. In GDK, that's always been done by a really horrible process of manually scaling the bitmap, server-side, column by column and row by row, causing each pixel to be exactly doubled or quadrupled. But in Cairo, we can just set a transformation matrix, and then that takes effect _before_ the scalable fonts are rendered - so the results are visibly nicer, and use all the available resolution. (Sadly, if you're using a server-side bitmap font as your primary one, then the GDK backend will be selected for all drawing in the terminal as a whole - so in that situation, even fallback characters absent from the primary font and rendered by Pango will get the old GDK scaling treatment. It's only if your main font is scalable, so that the Cairo backend is selected, that DW/DH characters will come out looking nice.)
2015-08-15 23:05:56 +03:00
}
#endif
return true;
}
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
static void gtkwin_free_draw_ctx(TermWin *tw)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = container_of(tw, GtkFrontend, termwin);
Refactor the GTK drawing system to do both GDK and Cairo. We're going to have to use Cairo in the GTK3 port, because that's all GTK3 supports; but we still need old-style GDK for GTK1 support, and also for performance reasons in GTK2 (see below). Hence, this change completely restructures GTK PuTTY's drawing code so that there's a central 'drawing context' structure which contains a type code indicating GDK or Cairo, and then either some GDK gubbins or some Cairo gubbins as appropriate; all actual drawing is abstracted through a set of routines which test the type code in that structure and do one thing or another. And because the type code is tested at run time, both sets of drawing primitives can be compiled in at once, and where possible, they will be. X server-side bitmap fonts are still supported in the Cairo world, but because Cairo drawing is entirely client-side, they have to work by cheekily downloading each glyph bitmap from the server when it's first needed, and building up a client-side cache of 'cairo_surface_t's containing the bitmaps with which we then draw on the window. This technique works, but it's rather slow; hence, even in GTK2, we keep the GDK drawing back end compiled in, and switch over to it when the main selected font is a bitmap one. One visible effect of the new Cairo routines is in the double-width and double-height text you can get by sending ESC # 3, ESC # 4 and ESC # 6 escape sequences. In GDK, that's always been done by a really horrible process of manually scaling the bitmap, server-side, column by column and row by row, causing each pixel to be exactly doubled or quadrupled. But in Cairo, we can just set a transformation matrix, and then that takes effect _before_ the scalable fonts are rendered - so the results are visibly nicer, and use all the available resolution. (Sadly, if you're using a server-side bitmap font as your primary one, then the GDK backend will be selected for all drawing in the terminal as a whole - so in that situation, even fallback characters absent from the primary font and rendered by Pango will get the old GDK scaling treatment. It's only if your main font is scalable, so that the Cairo backend is selected, that DW/DH characters will come out looking nice.)
2015-08-15 23:05:56 +03:00
#ifdef DRAW_TEXT_GDK
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
if (inst->uctx.type == DRAWTYPE_GDK) {
gdk_gc_unref(inst->uctx.u.gdk.gc);
Refactor the GTK drawing system to do both GDK and Cairo. We're going to have to use Cairo in the GTK3 port, because that's all GTK3 supports; but we still need old-style GDK for GTK1 support, and also for performance reasons in GTK2 (see below). Hence, this change completely restructures GTK PuTTY's drawing code so that there's a central 'drawing context' structure which contains a type code indicating GDK or Cairo, and then either some GDK gubbins or some Cairo gubbins as appropriate; all actual drawing is abstracted through a set of routines which test the type code in that structure and do one thing or another. And because the type code is tested at run time, both sets of drawing primitives can be compiled in at once, and where possible, they will be. X server-side bitmap fonts are still supported in the Cairo world, but because Cairo drawing is entirely client-side, they have to work by cheekily downloading each glyph bitmap from the server when it's first needed, and building up a client-side cache of 'cairo_surface_t's containing the bitmaps with which we then draw on the window. This technique works, but it's rather slow; hence, even in GTK2, we keep the GDK drawing back end compiled in, and switch over to it when the main selected font is a bitmap one. One visible effect of the new Cairo routines is in the double-width and double-height text you can get by sending ESC # 3, ESC # 4 and ESC # 6 escape sequences. In GDK, that's always been done by a really horrible process of manually scaling the bitmap, server-side, column by column and row by row, causing each pixel to be exactly doubled or quadrupled. But in Cairo, we can just set a transformation matrix, and then that takes effect _before_ the scalable fonts are rendered - so the results are visibly nicer, and use all the available resolution. (Sadly, if you're using a server-side bitmap font as your primary one, then the GDK backend will be selected for all drawing in the terminal as a whole - so in that situation, even fallback characters absent from the primary font and rendered by Pango will get the old GDK scaling treatment. It's only if your main font is scalable, so that the Cairo backend is selected, that DW/DH characters will come out looking nice.)
2015-08-15 23:05:56 +03:00
}
#endif
#ifdef DRAW_TEXT_CAIRO
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
if (inst->uctx.type == DRAWTYPE_CAIRO) {
cairo_destroy(inst->uctx.u.cairo.cr);
Refactor the GTK drawing system to do both GDK and Cairo. We're going to have to use Cairo in the GTK3 port, because that's all GTK3 supports; but we still need old-style GDK for GTK1 support, and also for performance reasons in GTK2 (see below). Hence, this change completely restructures GTK PuTTY's drawing code so that there's a central 'drawing context' structure which contains a type code indicating GDK or Cairo, and then either some GDK gubbins or some Cairo gubbins as appropriate; all actual drawing is abstracted through a set of routines which test the type code in that structure and do one thing or another. And because the type code is tested at run time, both sets of drawing primitives can be compiled in at once, and where possible, they will be. X server-side bitmap fonts are still supported in the Cairo world, but because Cairo drawing is entirely client-side, they have to work by cheekily downloading each glyph bitmap from the server when it's first needed, and building up a client-side cache of 'cairo_surface_t's containing the bitmaps with which we then draw on the window. This technique works, but it's rather slow; hence, even in GTK2, we keep the GDK drawing back end compiled in, and switch over to it when the main selected font is a bitmap one. One visible effect of the new Cairo routines is in the double-width and double-height text you can get by sending ESC # 3, ESC # 4 and ESC # 6 escape sequences. In GDK, that's always been done by a really horrible process of manually scaling the bitmap, server-side, column by column and row by row, causing each pixel to be exactly doubled or quadrupled. But in Cairo, we can just set a transformation matrix, and then that takes effect _before_ the scalable fonts are rendered - so the results are visibly nicer, and use all the available resolution. (Sadly, if you're using a server-side bitmap font as your primary one, then the GDK backend will be selected for all drawing in the terminal as a whole - so in that situation, even fallback characters absent from the primary font and rendered by Pango will get the old GDK scaling treatment. It's only if your main font is scalable, so that the Cairo backend is selected, that DW/DH characters will come out looking nice.)
2015-08-15 23:05:56 +03:00
}
#endif
}
Refactor the GTK drawing system to do both GDK and Cairo. We're going to have to use Cairo in the GTK3 port, because that's all GTK3 supports; but we still need old-style GDK for GTK1 support, and also for performance reasons in GTK2 (see below). Hence, this change completely restructures GTK PuTTY's drawing code so that there's a central 'drawing context' structure which contains a type code indicating GDK or Cairo, and then either some GDK gubbins or some Cairo gubbins as appropriate; all actual drawing is abstracted through a set of routines which test the type code in that structure and do one thing or another. And because the type code is tested at run time, both sets of drawing primitives can be compiled in at once, and where possible, they will be. X server-side bitmap fonts are still supported in the Cairo world, but because Cairo drawing is entirely client-side, they have to work by cheekily downloading each glyph bitmap from the server when it's first needed, and building up a client-side cache of 'cairo_surface_t's containing the bitmaps with which we then draw on the window. This technique works, but it's rather slow; hence, even in GTK2, we keep the GDK drawing back end compiled in, and switch over to it when the main selected font is a bitmap one. One visible effect of the new Cairo routines is in the double-width and double-height text you can get by sending ESC # 3, ESC # 4 and ESC # 6 escape sequences. In GDK, that's always been done by a really horrible process of manually scaling the bitmap, server-side, column by column and row by row, causing each pixel to be exactly doubled or quadrupled. But in Cairo, we can just set a transformation matrix, and then that takes effect _before_ the scalable fonts are rendered - so the results are visibly nicer, and use all the available resolution. (Sadly, if you're using a server-side bitmap font as your primary one, then the GDK backend will be selected for all drawing in the terminal as a whole - so in that situation, even fallback characters absent from the primary font and rendered by Pango will get the old GDK scaling treatment. It's only if your main font is scalable, so that the Cairo backend is selected, that DW/DH characters will come out looking nice.)
2015-08-15 23:05:56 +03:00
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
static void draw_update(GtkFrontend *inst, int x, int y, int w, int h)
Refactor the GTK drawing system to do both GDK and Cairo. We're going to have to use Cairo in the GTK3 port, because that's all GTK3 supports; but we still need old-style GDK for GTK1 support, and also for performance reasons in GTK2 (see below). Hence, this change completely restructures GTK PuTTY's drawing code so that there's a central 'drawing context' structure which contains a type code indicating GDK or Cairo, and then either some GDK gubbins or some Cairo gubbins as appropriate; all actual drawing is abstracted through a set of routines which test the type code in that structure and do one thing or another. And because the type code is tested at run time, both sets of drawing primitives can be compiled in at once, and where possible, they will be. X server-side bitmap fonts are still supported in the Cairo world, but because Cairo drawing is entirely client-side, they have to work by cheekily downloading each glyph bitmap from the server when it's first needed, and building up a client-side cache of 'cairo_surface_t's containing the bitmaps with which we then draw on the window. This technique works, but it's rather slow; hence, even in GTK2, we keep the GDK drawing back end compiled in, and switch over to it when the main selected font is a bitmap one. One visible effect of the new Cairo routines is in the double-width and double-height text you can get by sending ESC # 3, ESC # 4 and ESC # 6 escape sequences. In GDK, that's always been done by a really horrible process of manually scaling the bitmap, server-side, column by column and row by row, causing each pixel to be exactly doubled or quadrupled. But in Cairo, we can just set a transformation matrix, and then that takes effect _before_ the scalable fonts are rendered - so the results are visibly nicer, and use all the available resolution. (Sadly, if you're using a server-side bitmap font as your primary one, then the GDK backend will be selected for all drawing in the terminal as a whole - so in that situation, even fallback characters absent from the primary font and rendered by Pango will get the old GDK scaling treatment. It's only if your main font is scalable, so that the Cairo backend is selected, that DW/DH characters will come out looking nice.)
2015-08-15 23:05:56 +03:00
{
Use a Cairo image surface as a client-side cache. In any DRAWTYPE_CAIRO mode, we now do all our Cairo drawing to a Cairo image surface which lives on the client; then we either blit directly from that to the window (if we're in GTK3 mode, or GTK2 without deprecated pieces of API), or else we blit from the Cairo surface to the server-side pixmap and then from there to the actual window. In DRAWTYPE_GDK mode, nothing much has changed: we still draw directly to the server-side pixmap using the GDK drawing API, then blit from there to the window. But there is one change, namely that the blit is no longer done proactively - instead, we queue a redraw of the affected rectangle, and wait until we're called back by the expose handler. The main aim of all this is to arrange that the only time we ever draw to the real window is in response to expose/draw events. The experimental GTK3 OS X port stopped working a week or two ago (I presume in response to an OS update) with the symptoms that attempts to draw on the window outside the context of a "draw" event handler just didn't seem to work any more; this change fixes it. In addition to that benefit, this change also has obvious performance advantages in principle. No more expensive text rendering in response to an expose event - just re-copy to the window from the bitmap we already have, from wherever it's stored that's nearest. Moreover, this seems to have fixed the significant performance problem with X server-side fonts under GTK. I didn't expect _that_! I'd guessed that the approach of downloading character bitmaps and rendering them manually via Cairo was just inherently slow for some reason. I've no real idea _why_ this change improves matters so much; my best guess is that perhaps there's an overhead in each drawing operation to a GDK Cairo surface, so we win by doing lots of operations to a much faster image surface and then batching them up into one GDK Cairo operation. But whyever it is, I'm certainly not complaining! (In fact, it now seems to be noticeably _faster_, at least on my usual local X displays, to draw server-side fonts using that technique than using the old GDK approach. I may yet decide to switch over...)
2015-09-24 16:08:25 +03:00
#if defined DRAW_TEXT_CAIRO && !defined NO_BACKING_PIXMAPS
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
if (inst->uctx.type == DRAWTYPE_CAIRO) {
Use a Cairo image surface as a client-side cache. In any DRAWTYPE_CAIRO mode, we now do all our Cairo drawing to a Cairo image surface which lives on the client; then we either blit directly from that to the window (if we're in GTK3 mode, or GTK2 without deprecated pieces of API), or else we blit from the Cairo surface to the server-side pixmap and then from there to the actual window. In DRAWTYPE_GDK mode, nothing much has changed: we still draw directly to the server-side pixmap using the GDK drawing API, then blit from there to the window. But there is one change, namely that the blit is no longer done proactively - instead, we queue a redraw of the affected rectangle, and wait until we're called back by the expose handler. The main aim of all this is to arrange that the only time we ever draw to the real window is in response to expose/draw events. The experimental GTK3 OS X port stopped working a week or two ago (I presume in response to an OS update) with the symptoms that attempts to draw on the window outside the context of a "draw" event handler just didn't seem to work any more; this change fixes it. In addition to that benefit, this change also has obvious performance advantages in principle. No more expensive text rendering in response to an expose event - just re-copy to the window from the bitmap we already have, from wherever it's stored that's nearest. Moreover, this seems to have fixed the significant performance problem with X server-side fonts under GTK. I didn't expect _that_! I'd guessed that the approach of downloading character bitmaps and rendering them manually via Cairo was just inherently slow for some reason. I've no real idea _why_ this change improves matters so much; my best guess is that perhaps there's an overhead in each drawing operation to a GDK Cairo surface, so we win by doing lots of operations to a much faster image surface and then batching them up into one GDK Cairo operation. But whyever it is, I'm certainly not complaining! (In fact, it now seems to be noticeably _faster_, at least on my usual local X displays, to draw server-side fonts using that technique than using the old GDK approach. I may yet decide to switch over...)
2015-09-24 16:08:25 +03:00
/*
* 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.
*/
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
cairo_t *cr = gdk_cairo_create(inst->pixmap);
cairo_set_source_surface(cr, inst->surface, 0, 0);
Use a Cairo image surface as a client-side cache. In any DRAWTYPE_CAIRO mode, we now do all our Cairo drawing to a Cairo image surface which lives on the client; then we either blit directly from that to the window (if we're in GTK3 mode, or GTK2 without deprecated pieces of API), or else we blit from the Cairo surface to the server-side pixmap and then from there to the actual window. In DRAWTYPE_GDK mode, nothing much has changed: we still draw directly to the server-side pixmap using the GDK drawing API, then blit from there to the window. But there is one change, namely that the blit is no longer done proactively - instead, we queue a redraw of the affected rectangle, and wait until we're called back by the expose handler. The main aim of all this is to arrange that the only time we ever draw to the real window is in response to expose/draw events. The experimental GTK3 OS X port stopped working a week or two ago (I presume in response to an OS update) with the symptoms that attempts to draw on the window outside the context of a "draw" event handler just didn't seem to work any more; this change fixes it. In addition to that benefit, this change also has obvious performance advantages in principle. No more expensive text rendering in response to an expose event - just re-copy to the window from the bitmap we already have, from wherever it's stored that's nearest. Moreover, this seems to have fixed the significant performance problem with X server-side fonts under GTK. I didn't expect _that_! I'd guessed that the approach of downloading character bitmaps and rendering them manually via Cairo was just inherently slow for some reason. I've no real idea _why_ this change improves matters so much; my best guess is that perhaps there's an overhead in each drawing operation to a GDK Cairo surface, so we win by doing lots of operations to a much faster image surface and then batching them up into one GDK Cairo operation. But whyever it is, I'm certainly not complaining! (In fact, it now seems to be noticeably _faster_, at least on my usual local X displays, to draw server-side fonts using that technique than using the old GDK approach. I may yet decide to switch over...)
2015-09-24 16:08:25 +03:00
cairo_rectangle(cr, x, y, w, h);
cairo_fill(cr);
cairo_destroy(cr);
Refactor the GTK drawing system to do both GDK and Cairo. We're going to have to use Cairo in the GTK3 port, because that's all GTK3 supports; but we still need old-style GDK for GTK1 support, and also for performance reasons in GTK2 (see below). Hence, this change completely restructures GTK PuTTY's drawing code so that there's a central 'drawing context' structure which contains a type code indicating GDK or Cairo, and then either some GDK gubbins or some Cairo gubbins as appropriate; all actual drawing is abstracted through a set of routines which test the type code in that structure and do one thing or another. And because the type code is tested at run time, both sets of drawing primitives can be compiled in at once, and where possible, they will be. X server-side bitmap fonts are still supported in the Cairo world, but because Cairo drawing is entirely client-side, they have to work by cheekily downloading each glyph bitmap from the server when it's first needed, and building up a client-side cache of 'cairo_surface_t's containing the bitmaps with which we then draw on the window. This technique works, but it's rather slow; hence, even in GTK2, we keep the GDK drawing back end compiled in, and switch over to it when the main selected font is a bitmap one. One visible effect of the new Cairo routines is in the double-width and double-height text you can get by sending ESC # 3, ESC # 4 and ESC # 6 escape sequences. In GDK, that's always been done by a really horrible process of manually scaling the bitmap, server-side, column by column and row by row, causing each pixel to be exactly doubled or quadrupled. But in Cairo, we can just set a transformation matrix, and then that takes effect _before_ the scalable fonts are rendered - so the results are visibly nicer, and use all the available resolution. (Sadly, if you're using a server-side bitmap font as your primary one, then the GDK backend will be selected for all drawing in the terminal as a whole - so in that situation, even fallback characters absent from the primary font and rendered by Pango will get the old GDK scaling treatment. It's only if your main font is scalable, so that the Cairo backend is selected, that DW/DH characters will come out looking nice.)
2015-08-15 23:05:56 +03:00
}
#endif
Use a Cairo image surface as a client-side cache. In any DRAWTYPE_CAIRO mode, we now do all our Cairo drawing to a Cairo image surface which lives on the client; then we either blit directly from that to the window (if we're in GTK3 mode, or GTK2 without deprecated pieces of API), or else we blit from the Cairo surface to the server-side pixmap and then from there to the actual window. In DRAWTYPE_GDK mode, nothing much has changed: we still draw directly to the server-side pixmap using the GDK drawing API, then blit from there to the window. But there is one change, namely that the blit is no longer done proactively - instead, we queue a redraw of the affected rectangle, and wait until we're called back by the expose handler. The main aim of all this is to arrange that the only time we ever draw to the real window is in response to expose/draw events. The experimental GTK3 OS X port stopped working a week or two ago (I presume in response to an OS update) with the symptoms that attempts to draw on the window outside the context of a "draw" event handler just didn't seem to work any more; this change fixes it. In addition to that benefit, this change also has obvious performance advantages in principle. No more expensive text rendering in response to an expose event - just re-copy to the window from the bitmap we already have, from wherever it's stored that's nearest. Moreover, this seems to have fixed the significant performance problem with X server-side fonts under GTK. I didn't expect _that_! I'd guessed that the approach of downloading character bitmaps and rendering them manually via Cairo was just inherently slow for some reason. I've no real idea _why_ this change improves matters so much; my best guess is that perhaps there's an overhead in each drawing operation to a GDK Cairo surface, so we win by doing lots of operations to a much faster image surface and then batching them up into one GDK Cairo operation. But whyever it is, I'm certainly not complaining! (In fact, it now seems to be noticeably _faster_, at least on my usual local X displays, to draw server-side fonts using that technique than using the old GDK approach. I may yet decide to switch over...)
2015-09-24 16:08:25 +03:00
/*
* Now we just queue a window redraw, which will cause
* inst->surface or inst->pixmap (whichever is appropriate for our
* compile mode) to be copied to the real window when we receive
* the resulting "expose" or "draw" event.
*
* Amazingly, this one API call is actually valid in all versions
* of GTK :-)
*/
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
gtk_widget_queue_draw_area(inst->area, x, y, w, h);
Refactor the GTK drawing system to do both GDK and Cairo. We're going to have to use Cairo in the GTK3 port, because that's all GTK3 supports; but we still need old-style GDK for GTK1 support, and also for performance reasons in GTK2 (see below). Hence, this change completely restructures GTK PuTTY's drawing code so that there's a central 'drawing context' structure which contains a type code indicating GDK or Cairo, and then either some GDK gubbins or some Cairo gubbins as appropriate; all actual drawing is abstracted through a set of routines which test the type code in that structure and do one thing or another. And because the type code is tested at run time, both sets of drawing primitives can be compiled in at once, and where possible, they will be. X server-side bitmap fonts are still supported in the Cairo world, but because Cairo drawing is entirely client-side, they have to work by cheekily downloading each glyph bitmap from the server when it's first needed, and building up a client-side cache of 'cairo_surface_t's containing the bitmaps with which we then draw on the window. This technique works, but it's rather slow; hence, even in GTK2, we keep the GDK drawing back end compiled in, and switch over to it when the main selected font is a bitmap one. One visible effect of the new Cairo routines is in the double-width and double-height text you can get by sending ESC # 3, ESC # 4 and ESC # 6 escape sequences. In GDK, that's always been done by a really horrible process of manually scaling the bitmap, server-side, column by column and row by row, causing each pixel to be exactly doubled or quadrupled. But in Cairo, we can just set a transformation matrix, and then that takes effect _before_ the scalable fonts are rendered - so the results are visibly nicer, and use all the available resolution. (Sadly, if you're using a server-side bitmap font as your primary one, then the GDK backend will be selected for all drawing in the terminal as a whole - so in that situation, even fallback characters absent from the primary font and rendered by Pango will get the old GDK scaling treatment. It's only if your main font is scalable, so that the Cairo backend is selected, that DW/DH characters will come out looking nice.)
2015-08-15 23:05:56 +03:00
}
#ifdef DRAW_TEXT_CAIRO
static void cairo_set_source_rgb_dim(cairo_t *cr, double r, double g, double b,
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
bool dim)
{
if (dim)
cairo_set_source_rgb(cr, r * 2 / 3, g * 2 / 3, b * 2 / 3);
else
cairo_set_source_rgb(cr, r, g, b);
}
#endif
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
static void draw_set_colour(GtkFrontend *inst, int col, bool dim)
Refactor the GTK drawing system to do both GDK and Cairo. We're going to have to use Cairo in the GTK3 port, because that's all GTK3 supports; but we still need old-style GDK for GTK1 support, and also for performance reasons in GTK2 (see below). Hence, this change completely restructures GTK PuTTY's drawing code so that there's a central 'drawing context' structure which contains a type code indicating GDK or Cairo, and then either some GDK gubbins or some Cairo gubbins as appropriate; all actual drawing is abstracted through a set of routines which test the type code in that structure and do one thing or another. And because the type code is tested at run time, both sets of drawing primitives can be compiled in at once, and where possible, they will be. X server-side bitmap fonts are still supported in the Cairo world, but because Cairo drawing is entirely client-side, they have to work by cheekily downloading each glyph bitmap from the server when it's first needed, and building up a client-side cache of 'cairo_surface_t's containing the bitmaps with which we then draw on the window. This technique works, but it's rather slow; hence, even in GTK2, we keep the GDK drawing back end compiled in, and switch over to it when the main selected font is a bitmap one. One visible effect of the new Cairo routines is in the double-width and double-height text you can get by sending ESC # 3, ESC # 4 and ESC # 6 escape sequences. In GDK, that's always been done by a really horrible process of manually scaling the bitmap, server-side, column by column and row by row, causing each pixel to be exactly doubled or quadrupled. But in Cairo, we can just set a transformation matrix, and then that takes effect _before_ the scalable fonts are rendered - so the results are visibly nicer, and use all the available resolution. (Sadly, if you're using a server-side bitmap font as your primary one, then the GDK backend will be selected for all drawing in the terminal as a whole - so in that situation, even fallback characters absent from the primary font and rendered by Pango will get the old GDK scaling treatment. It's only if your main font is scalable, so that the Cairo backend is selected, that DW/DH characters will come out looking nice.)
2015-08-15 23:05:56 +03:00
{
#ifdef DRAW_TEXT_GDK
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
if (inst->uctx.type == DRAWTYPE_GDK) {
if (dim) {
#if GTK_CHECK_VERSION(2,0,0)
GdkColor color;
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
color.red = inst->cols[col].red * 2 / 3;
color.green = inst->cols[col].green * 2 / 3;
color.blue = inst->cols[col].blue * 2 / 3;
gdk_gc_set_rgb_fg_color(inst->uctx.u.gdk.gc, &color);
#else
/* Poor GTK1 fallback */
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
gdk_gc_set_foreground(inst->uctx.u.gdk.gc, &inst->cols[col]);
#endif
} else {
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
gdk_gc_set_foreground(inst->uctx.u.gdk.gc, &inst->cols[col]);
}
Refactor the GTK drawing system to do both GDK and Cairo. We're going to have to use Cairo in the GTK3 port, because that's all GTK3 supports; but we still need old-style GDK for GTK1 support, and also for performance reasons in GTK2 (see below). Hence, this change completely restructures GTK PuTTY's drawing code so that there's a central 'drawing context' structure which contains a type code indicating GDK or Cairo, and then either some GDK gubbins or some Cairo gubbins as appropriate; all actual drawing is abstracted through a set of routines which test the type code in that structure and do one thing or another. And because the type code is tested at run time, both sets of drawing primitives can be compiled in at once, and where possible, they will be. X server-side bitmap fonts are still supported in the Cairo world, but because Cairo drawing is entirely client-side, they have to work by cheekily downloading each glyph bitmap from the server when it's first needed, and building up a client-side cache of 'cairo_surface_t's containing the bitmaps with which we then draw on the window. This technique works, but it's rather slow; hence, even in GTK2, we keep the GDK drawing back end compiled in, and switch over to it when the main selected font is a bitmap one. One visible effect of the new Cairo routines is in the double-width and double-height text you can get by sending ESC # 3, ESC # 4 and ESC # 6 escape sequences. In GDK, that's always been done by a really horrible process of manually scaling the bitmap, server-side, column by column and row by row, causing each pixel to be exactly doubled or quadrupled. But in Cairo, we can just set a transformation matrix, and then that takes effect _before_ the scalable fonts are rendered - so the results are visibly nicer, and use all the available resolution. (Sadly, if you're using a server-side bitmap font as your primary one, then the GDK backend will be selected for all drawing in the terminal as a whole - so in that situation, even fallback characters absent from the primary font and rendered by Pango will get the old GDK scaling treatment. It's only if your main font is scalable, so that the Cairo backend is selected, that DW/DH characters will come out looking nice.)
2015-08-15 23:05:56 +03:00
}
#endif
#ifdef DRAW_TEXT_CAIRO
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
if (inst->uctx.type == DRAWTYPE_CAIRO) {
cairo_set_source_rgb_dim(inst->uctx.u.cairo.cr,
inst->cols[col].red / 65535.0,
inst->cols[col].green / 65535.0,
inst->cols[col].blue / 65535.0, dim);
Refactor the GTK drawing system to do both GDK and Cairo. We're going to have to use Cairo in the GTK3 port, because that's all GTK3 supports; but we still need old-style GDK for GTK1 support, and also for performance reasons in GTK2 (see below). Hence, this change completely restructures GTK PuTTY's drawing code so that there's a central 'drawing context' structure which contains a type code indicating GDK or Cairo, and then either some GDK gubbins or some Cairo gubbins as appropriate; all actual drawing is abstracted through a set of routines which test the type code in that structure and do one thing or another. And because the type code is tested at run time, both sets of drawing primitives can be compiled in at once, and where possible, they will be. X server-side bitmap fonts are still supported in the Cairo world, but because Cairo drawing is entirely client-side, they have to work by cheekily downloading each glyph bitmap from the server when it's first needed, and building up a client-side cache of 'cairo_surface_t's containing the bitmaps with which we then draw on the window. This technique works, but it's rather slow; hence, even in GTK2, we keep the GDK drawing back end compiled in, and switch over to it when the main selected font is a bitmap one. One visible effect of the new Cairo routines is in the double-width and double-height text you can get by sending ESC # 3, ESC # 4 and ESC # 6 escape sequences. In GDK, that's always been done by a really horrible process of manually scaling the bitmap, server-side, column by column and row by row, causing each pixel to be exactly doubled or quadrupled. But in Cairo, we can just set a transformation matrix, and then that takes effect _before_ the scalable fonts are rendered - so the results are visibly nicer, and use all the available resolution. (Sadly, if you're using a server-side bitmap font as your primary one, then the GDK backend will be selected for all drawing in the terminal as a whole - so in that situation, even fallback characters absent from the primary font and rendered by Pango will get the old GDK scaling treatment. It's only if your main font is scalable, so that the Cairo backend is selected, that DW/DH characters will come out looking nice.)
2015-08-15 23:05:56 +03:00
}
#endif
}
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
static void draw_set_colour_rgb(GtkFrontend *inst, optionalrgb orgb, bool dim)
{
#ifdef DRAW_TEXT_GDK
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
if (inst->uctx.type == DRAWTYPE_GDK) {
#if GTK_CHECK_VERSION(2,0,0)
GdkColor color;
color.red = orgb.r * 256;
color.green = orgb.g * 256;
color.blue = orgb.b * 256;
if (dim) {
color.red = color.red * 2 / 3;
color.green = color.green * 2 / 3;
color.blue = color.blue * 2 / 3;
}
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
gdk_gc_set_rgb_fg_color(inst->uctx.u.gdk.gc, &color);
#else
/* Poor GTK1 fallback */
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
gdk_gc_set_foreground(inst->uctx.u.gdk.gc, &inst->cols[256]);
#endif
}
#endif
#ifdef DRAW_TEXT_CAIRO
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
if (inst->uctx.type == DRAWTYPE_CAIRO) {
cairo_set_source_rgb_dim(inst->uctx.u.cairo.cr, orgb.r / 255.0,
orgb.g / 255.0, orgb.b / 255.0, dim);
}
#endif
}
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
static void draw_rectangle(GtkFrontend *inst, bool filled,
Refactor the GTK drawing system to do both GDK and Cairo. We're going to have to use Cairo in the GTK3 port, because that's all GTK3 supports; but we still need old-style GDK for GTK1 support, and also for performance reasons in GTK2 (see below). Hence, this change completely restructures GTK PuTTY's drawing code so that there's a central 'drawing context' structure which contains a type code indicating GDK or Cairo, and then either some GDK gubbins or some Cairo gubbins as appropriate; all actual drawing is abstracted through a set of routines which test the type code in that structure and do one thing or another. And because the type code is tested at run time, both sets of drawing primitives can be compiled in at once, and where possible, they will be. X server-side bitmap fonts are still supported in the Cairo world, but because Cairo drawing is entirely client-side, they have to work by cheekily downloading each glyph bitmap from the server when it's first needed, and building up a client-side cache of 'cairo_surface_t's containing the bitmaps with which we then draw on the window. This technique works, but it's rather slow; hence, even in GTK2, we keep the GDK drawing back end compiled in, and switch over to it when the main selected font is a bitmap one. One visible effect of the new Cairo routines is in the double-width and double-height text you can get by sending ESC # 3, ESC # 4 and ESC # 6 escape sequences. In GDK, that's always been done by a really horrible process of manually scaling the bitmap, server-side, column by column and row by row, causing each pixel to be exactly doubled or quadrupled. But in Cairo, we can just set a transformation matrix, and then that takes effect _before_ the scalable fonts are rendered - so the results are visibly nicer, and use all the available resolution. (Sadly, if you're using a server-side bitmap font as your primary one, then the GDK backend will be selected for all drawing in the terminal as a whole - so in that situation, even fallback characters absent from the primary font and rendered by Pango will get the old GDK scaling treatment. It's only if your main font is scalable, so that the Cairo backend is selected, that DW/DH characters will come out looking nice.)
2015-08-15 23:05:56 +03:00
int x, int y, int w, int h)
{
#ifdef DRAW_TEXT_GDK
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
if (inst->uctx.type == DRAWTYPE_GDK) {
gdk_draw_rectangle(inst->uctx.u.gdk.target, inst->uctx.u.gdk.gc,
Refactor the GTK drawing system to do both GDK and Cairo. We're going to have to use Cairo in the GTK3 port, because that's all GTK3 supports; but we still need old-style GDK for GTK1 support, and also for performance reasons in GTK2 (see below). Hence, this change completely restructures GTK PuTTY's drawing code so that there's a central 'drawing context' structure which contains a type code indicating GDK or Cairo, and then either some GDK gubbins or some Cairo gubbins as appropriate; all actual drawing is abstracted through a set of routines which test the type code in that structure and do one thing or another. And because the type code is tested at run time, both sets of drawing primitives can be compiled in at once, and where possible, they will be. X server-side bitmap fonts are still supported in the Cairo world, but because Cairo drawing is entirely client-side, they have to work by cheekily downloading each glyph bitmap from the server when it's first needed, and building up a client-side cache of 'cairo_surface_t's containing the bitmaps with which we then draw on the window. This technique works, but it's rather slow; hence, even in GTK2, we keep the GDK drawing back end compiled in, and switch over to it when the main selected font is a bitmap one. One visible effect of the new Cairo routines is in the double-width and double-height text you can get by sending ESC # 3, ESC # 4 and ESC # 6 escape sequences. In GDK, that's always been done by a really horrible process of manually scaling the bitmap, server-side, column by column and row by row, causing each pixel to be exactly doubled or quadrupled. But in Cairo, we can just set a transformation matrix, and then that takes effect _before_ the scalable fonts are rendered - so the results are visibly nicer, and use all the available resolution. (Sadly, if you're using a server-side bitmap font as your primary one, then the GDK backend will be selected for all drawing in the terminal as a whole - so in that situation, even fallback characters absent from the primary font and rendered by Pango will get the old GDK scaling treatment. It's only if your main font is scalable, so that the Cairo backend is selected, that DW/DH characters will come out looking nice.)
2015-08-15 23:05:56 +03:00
filled, x, y, w, h);
}
#endif
#ifdef DRAW_TEXT_CAIRO
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
if (inst->uctx.type == DRAWTYPE_CAIRO) {
cairo_new_path(inst->uctx.u.cairo.cr);
Refactor the GTK drawing system to do both GDK and Cairo. We're going to have to use Cairo in the GTK3 port, because that's all GTK3 supports; but we still need old-style GDK for GTK1 support, and also for performance reasons in GTK2 (see below). Hence, this change completely restructures GTK PuTTY's drawing code so that there's a central 'drawing context' structure which contains a type code indicating GDK or Cairo, and then either some GDK gubbins or some Cairo gubbins as appropriate; all actual drawing is abstracted through a set of routines which test the type code in that structure and do one thing or another. And because the type code is tested at run time, both sets of drawing primitives can be compiled in at once, and where possible, they will be. X server-side bitmap fonts are still supported in the Cairo world, but because Cairo drawing is entirely client-side, they have to work by cheekily downloading each glyph bitmap from the server when it's first needed, and building up a client-side cache of 'cairo_surface_t's containing the bitmaps with which we then draw on the window. This technique works, but it's rather slow; hence, even in GTK2, we keep the GDK drawing back end compiled in, and switch over to it when the main selected font is a bitmap one. One visible effect of the new Cairo routines is in the double-width and double-height text you can get by sending ESC # 3, ESC # 4 and ESC # 6 escape sequences. In GDK, that's always been done by a really horrible process of manually scaling the bitmap, server-side, column by column and row by row, causing each pixel to be exactly doubled or quadrupled. But in Cairo, we can just set a transformation matrix, and then that takes effect _before_ the scalable fonts are rendered - so the results are visibly nicer, and use all the available resolution. (Sadly, if you're using a server-side bitmap font as your primary one, then the GDK backend will be selected for all drawing in the terminal as a whole - so in that situation, even fallback characters absent from the primary font and rendered by Pango will get the old GDK scaling treatment. It's only if your main font is scalable, so that the Cairo backend is selected, that DW/DH characters will come out looking nice.)
2015-08-15 23:05:56 +03:00
if (filled) {
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
cairo_rectangle(inst->uctx.u.cairo.cr, x, y, w, h);
cairo_fill(inst->uctx.u.cairo.cr);
Refactor the GTK drawing system to do both GDK and Cairo. We're going to have to use Cairo in the GTK3 port, because that's all GTK3 supports; but we still need old-style GDK for GTK1 support, and also for performance reasons in GTK2 (see below). Hence, this change completely restructures GTK PuTTY's drawing code so that there's a central 'drawing context' structure which contains a type code indicating GDK or Cairo, and then either some GDK gubbins or some Cairo gubbins as appropriate; all actual drawing is abstracted through a set of routines which test the type code in that structure and do one thing or another. And because the type code is tested at run time, both sets of drawing primitives can be compiled in at once, and where possible, they will be. X server-side bitmap fonts are still supported in the Cairo world, but because Cairo drawing is entirely client-side, they have to work by cheekily downloading each glyph bitmap from the server when it's first needed, and building up a client-side cache of 'cairo_surface_t's containing the bitmaps with which we then draw on the window. This technique works, but it's rather slow; hence, even in GTK2, we keep the GDK drawing back end compiled in, and switch over to it when the main selected font is a bitmap one. One visible effect of the new Cairo routines is in the double-width and double-height text you can get by sending ESC # 3, ESC # 4 and ESC # 6 escape sequences. In GDK, that's always been done by a really horrible process of manually scaling the bitmap, server-side, column by column and row by row, causing each pixel to be exactly doubled or quadrupled. But in Cairo, we can just set a transformation matrix, and then that takes effect _before_ the scalable fonts are rendered - so the results are visibly nicer, and use all the available resolution. (Sadly, if you're using a server-side bitmap font as your primary one, then the GDK backend will be selected for all drawing in the terminal as a whole - so in that situation, even fallback characters absent from the primary font and rendered by Pango will get the old GDK scaling treatment. It's only if your main font is scalable, so that the Cairo backend is selected, that DW/DH characters will come out looking nice.)
2015-08-15 23:05:56 +03:00
} else {
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
cairo_rectangle(inst->uctx.u.cairo.cr,
Refactor the GTK drawing system to do both GDK and Cairo. We're going to have to use Cairo in the GTK3 port, because that's all GTK3 supports; but we still need old-style GDK for GTK1 support, and also for performance reasons in GTK2 (see below). Hence, this change completely restructures GTK PuTTY's drawing code so that there's a central 'drawing context' structure which contains a type code indicating GDK or Cairo, and then either some GDK gubbins or some Cairo gubbins as appropriate; all actual drawing is abstracted through a set of routines which test the type code in that structure and do one thing or another. And because the type code is tested at run time, both sets of drawing primitives can be compiled in at once, and where possible, they will be. X server-side bitmap fonts are still supported in the Cairo world, but because Cairo drawing is entirely client-side, they have to work by cheekily downloading each glyph bitmap from the server when it's first needed, and building up a client-side cache of 'cairo_surface_t's containing the bitmaps with which we then draw on the window. This technique works, but it's rather slow; hence, even in GTK2, we keep the GDK drawing back end compiled in, and switch over to it when the main selected font is a bitmap one. One visible effect of the new Cairo routines is in the double-width and double-height text you can get by sending ESC # 3, ESC # 4 and ESC # 6 escape sequences. In GDK, that's always been done by a really horrible process of manually scaling the bitmap, server-side, column by column and row by row, causing each pixel to be exactly doubled or quadrupled. But in Cairo, we can just set a transformation matrix, and then that takes effect _before_ the scalable fonts are rendered - so the results are visibly nicer, and use all the available resolution. (Sadly, if you're using a server-side bitmap font as your primary one, then the GDK backend will be selected for all drawing in the terminal as a whole - so in that situation, even fallback characters absent from the primary font and rendered by Pango will get the old GDK scaling treatment. It's only if your main font is scalable, so that the Cairo backend is selected, that DW/DH characters will come out looking nice.)
2015-08-15 23:05:56 +03:00
x + 0.5, y + 0.5, w, h);
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
cairo_close_path(inst->uctx.u.cairo.cr);
cairo_stroke(inst->uctx.u.cairo.cr);
Refactor the GTK drawing system to do both GDK and Cairo. We're going to have to use Cairo in the GTK3 port, because that's all GTK3 supports; but we still need old-style GDK for GTK1 support, and also for performance reasons in GTK2 (see below). Hence, this change completely restructures GTK PuTTY's drawing code so that there's a central 'drawing context' structure which contains a type code indicating GDK or Cairo, and then either some GDK gubbins or some Cairo gubbins as appropriate; all actual drawing is abstracted through a set of routines which test the type code in that structure and do one thing or another. And because the type code is tested at run time, both sets of drawing primitives can be compiled in at once, and where possible, they will be. X server-side bitmap fonts are still supported in the Cairo world, but because Cairo drawing is entirely client-side, they have to work by cheekily downloading each glyph bitmap from the server when it's first needed, and building up a client-side cache of 'cairo_surface_t's containing the bitmaps with which we then draw on the window. This technique works, but it's rather slow; hence, even in GTK2, we keep the GDK drawing back end compiled in, and switch over to it when the main selected font is a bitmap one. One visible effect of the new Cairo routines is in the double-width and double-height text you can get by sending ESC # 3, ESC # 4 and ESC # 6 escape sequences. In GDK, that's always been done by a really horrible process of manually scaling the bitmap, server-side, column by column and row by row, causing each pixel to be exactly doubled or quadrupled. But in Cairo, we can just set a transformation matrix, and then that takes effect _before_ the scalable fonts are rendered - so the results are visibly nicer, and use all the available resolution. (Sadly, if you're using a server-side bitmap font as your primary one, then the GDK backend will be selected for all drawing in the terminal as a whole - so in that situation, even fallback characters absent from the primary font and rendered by Pango will get the old GDK scaling treatment. It's only if your main font is scalable, so that the Cairo backend is selected, that DW/DH characters will come out looking nice.)
2015-08-15 23:05:56 +03:00
}
}
#endif
}
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
static void draw_clip(GtkFrontend *inst, int x, int y, int w, int h)
Refactor the GTK drawing system to do both GDK and Cairo. We're going to have to use Cairo in the GTK3 port, because that's all GTK3 supports; but we still need old-style GDK for GTK1 support, and also for performance reasons in GTK2 (see below). Hence, this change completely restructures GTK PuTTY's drawing code so that there's a central 'drawing context' structure which contains a type code indicating GDK or Cairo, and then either some GDK gubbins or some Cairo gubbins as appropriate; all actual drawing is abstracted through a set of routines which test the type code in that structure and do one thing or another. And because the type code is tested at run time, both sets of drawing primitives can be compiled in at once, and where possible, they will be. X server-side bitmap fonts are still supported in the Cairo world, but because Cairo drawing is entirely client-side, they have to work by cheekily downloading each glyph bitmap from the server when it's first needed, and building up a client-side cache of 'cairo_surface_t's containing the bitmaps with which we then draw on the window. This technique works, but it's rather slow; hence, even in GTK2, we keep the GDK drawing back end compiled in, and switch over to it when the main selected font is a bitmap one. One visible effect of the new Cairo routines is in the double-width and double-height text you can get by sending ESC # 3, ESC # 4 and ESC # 6 escape sequences. In GDK, that's always been done by a really horrible process of manually scaling the bitmap, server-side, column by column and row by row, causing each pixel to be exactly doubled or quadrupled. But in Cairo, we can just set a transformation matrix, and then that takes effect _before_ the scalable fonts are rendered - so the results are visibly nicer, and use all the available resolution. (Sadly, if you're using a server-side bitmap font as your primary one, then the GDK backend will be selected for all drawing in the terminal as a whole - so in that situation, even fallback characters absent from the primary font and rendered by Pango will get the old GDK scaling treatment. It's only if your main font is scalable, so that the Cairo backend is selected, that DW/DH characters will come out looking nice.)
2015-08-15 23:05:56 +03:00
{
#ifdef DRAW_TEXT_GDK
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
if (inst->uctx.type == DRAWTYPE_GDK) {
Refactor the GTK drawing system to do both GDK and Cairo. We're going to have to use Cairo in the GTK3 port, because that's all GTK3 supports; but we still need old-style GDK for GTK1 support, and also for performance reasons in GTK2 (see below). Hence, this change completely restructures GTK PuTTY's drawing code so that there's a central 'drawing context' structure which contains a type code indicating GDK or Cairo, and then either some GDK gubbins or some Cairo gubbins as appropriate; all actual drawing is abstracted through a set of routines which test the type code in that structure and do one thing or another. And because the type code is tested at run time, both sets of drawing primitives can be compiled in at once, and where possible, they will be. X server-side bitmap fonts are still supported in the Cairo world, but because Cairo drawing is entirely client-side, they have to work by cheekily downloading each glyph bitmap from the server when it's first needed, and building up a client-side cache of 'cairo_surface_t's containing the bitmaps with which we then draw on the window. This technique works, but it's rather slow; hence, even in GTK2, we keep the GDK drawing back end compiled in, and switch over to it when the main selected font is a bitmap one. One visible effect of the new Cairo routines is in the double-width and double-height text you can get by sending ESC # 3, ESC # 4 and ESC # 6 escape sequences. In GDK, that's always been done by a really horrible process of manually scaling the bitmap, server-side, column by column and row by row, causing each pixel to be exactly doubled or quadrupled. But in Cairo, we can just set a transformation matrix, and then that takes effect _before_ the scalable fonts are rendered - so the results are visibly nicer, and use all the available resolution. (Sadly, if you're using a server-side bitmap font as your primary one, then the GDK backend will be selected for all drawing in the terminal as a whole - so in that situation, even fallback characters absent from the primary font and rendered by Pango will get the old GDK scaling treatment. It's only if your main font is scalable, so that the Cairo backend is selected, that DW/DH characters will come out looking nice.)
2015-08-15 23:05:56 +03:00
GdkRectangle r;
r.x = x;
r.y = y;
r.width = w;
r.height = h;
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
gdk_gc_set_clip_rectangle(inst->uctx.u.gdk.gc, &r);
Refactor the GTK drawing system to do both GDK and Cairo. We're going to have to use Cairo in the GTK3 port, because that's all GTK3 supports; but we still need old-style GDK for GTK1 support, and also for performance reasons in GTK2 (see below). Hence, this change completely restructures GTK PuTTY's drawing code so that there's a central 'drawing context' structure which contains a type code indicating GDK or Cairo, and then either some GDK gubbins or some Cairo gubbins as appropriate; all actual drawing is abstracted through a set of routines which test the type code in that structure and do one thing or another. And because the type code is tested at run time, both sets of drawing primitives can be compiled in at once, and where possible, they will be. X server-side bitmap fonts are still supported in the Cairo world, but because Cairo drawing is entirely client-side, they have to work by cheekily downloading each glyph bitmap from the server when it's first needed, and building up a client-side cache of 'cairo_surface_t's containing the bitmaps with which we then draw on the window. This technique works, but it's rather slow; hence, even in GTK2, we keep the GDK drawing back end compiled in, and switch over to it when the main selected font is a bitmap one. One visible effect of the new Cairo routines is in the double-width and double-height text you can get by sending ESC # 3, ESC # 4 and ESC # 6 escape sequences. In GDK, that's always been done by a really horrible process of manually scaling the bitmap, server-side, column by column and row by row, causing each pixel to be exactly doubled or quadrupled. But in Cairo, we can just set a transformation matrix, and then that takes effect _before_ the scalable fonts are rendered - so the results are visibly nicer, and use all the available resolution. (Sadly, if you're using a server-side bitmap font as your primary one, then the GDK backend will be selected for all drawing in the terminal as a whole - so in that situation, even fallback characters absent from the primary font and rendered by Pango will get the old GDK scaling treatment. It's only if your main font is scalable, so that the Cairo backend is selected, that DW/DH characters will come out looking nice.)
2015-08-15 23:05:56 +03:00
}
#endif
#ifdef DRAW_TEXT_CAIRO
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
if (inst->uctx.type == DRAWTYPE_CAIRO) {
cairo_reset_clip(inst->uctx.u.cairo.cr);
cairo_new_path(inst->uctx.u.cairo.cr);
cairo_rectangle(inst->uctx.u.cairo.cr, x, y, w, h);
cairo_clip(inst->uctx.u.cairo.cr);
Refactor the GTK drawing system to do both GDK and Cairo. We're going to have to use Cairo in the GTK3 port, because that's all GTK3 supports; but we still need old-style GDK for GTK1 support, and also for performance reasons in GTK2 (see below). Hence, this change completely restructures GTK PuTTY's drawing code so that there's a central 'drawing context' structure which contains a type code indicating GDK or Cairo, and then either some GDK gubbins or some Cairo gubbins as appropriate; all actual drawing is abstracted through a set of routines which test the type code in that structure and do one thing or another. And because the type code is tested at run time, both sets of drawing primitives can be compiled in at once, and where possible, they will be. X server-side bitmap fonts are still supported in the Cairo world, but because Cairo drawing is entirely client-side, they have to work by cheekily downloading each glyph bitmap from the server when it's first needed, and building up a client-side cache of 'cairo_surface_t's containing the bitmaps with which we then draw on the window. This technique works, but it's rather slow; hence, even in GTK2, we keep the GDK drawing back end compiled in, and switch over to it when the main selected font is a bitmap one. One visible effect of the new Cairo routines is in the double-width and double-height text you can get by sending ESC # 3, ESC # 4 and ESC # 6 escape sequences. In GDK, that's always been done by a really horrible process of manually scaling the bitmap, server-side, column by column and row by row, causing each pixel to be exactly doubled or quadrupled. But in Cairo, we can just set a transformation matrix, and then that takes effect _before_ the scalable fonts are rendered - so the results are visibly nicer, and use all the available resolution. (Sadly, if you're using a server-side bitmap font as your primary one, then the GDK backend will be selected for all drawing in the terminal as a whole - so in that situation, even fallback characters absent from the primary font and rendered by Pango will get the old GDK scaling treatment. It's only if your main font is scalable, so that the Cairo backend is selected, that DW/DH characters will come out looking nice.)
2015-08-15 23:05:56 +03:00
}
#endif
}
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
static void draw_point(GtkFrontend *inst, int x, int y)
Refactor the GTK drawing system to do both GDK and Cairo. We're going to have to use Cairo in the GTK3 port, because that's all GTK3 supports; but we still need old-style GDK for GTK1 support, and also for performance reasons in GTK2 (see below). Hence, this change completely restructures GTK PuTTY's drawing code so that there's a central 'drawing context' structure which contains a type code indicating GDK or Cairo, and then either some GDK gubbins or some Cairo gubbins as appropriate; all actual drawing is abstracted through a set of routines which test the type code in that structure and do one thing or another. And because the type code is tested at run time, both sets of drawing primitives can be compiled in at once, and where possible, they will be. X server-side bitmap fonts are still supported in the Cairo world, but because Cairo drawing is entirely client-side, they have to work by cheekily downloading each glyph bitmap from the server when it's first needed, and building up a client-side cache of 'cairo_surface_t's containing the bitmaps with which we then draw on the window. This technique works, but it's rather slow; hence, even in GTK2, we keep the GDK drawing back end compiled in, and switch over to it when the main selected font is a bitmap one. One visible effect of the new Cairo routines is in the double-width and double-height text you can get by sending ESC # 3, ESC # 4 and ESC # 6 escape sequences. In GDK, that's always been done by a really horrible process of manually scaling the bitmap, server-side, column by column and row by row, causing each pixel to be exactly doubled or quadrupled. But in Cairo, we can just set a transformation matrix, and then that takes effect _before_ the scalable fonts are rendered - so the results are visibly nicer, and use all the available resolution. (Sadly, if you're using a server-side bitmap font as your primary one, then the GDK backend will be selected for all drawing in the terminal as a whole - so in that situation, even fallback characters absent from the primary font and rendered by Pango will get the old GDK scaling treatment. It's only if your main font is scalable, so that the Cairo backend is selected, that DW/DH characters will come out looking nice.)
2015-08-15 23:05:56 +03:00
{
#ifdef DRAW_TEXT_GDK
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
if (inst->uctx.type == DRAWTYPE_GDK) {
gdk_draw_point(inst->uctx.u.gdk.target, inst->uctx.u.gdk.gc, x, y);
Refactor the GTK drawing system to do both GDK and Cairo. We're going to have to use Cairo in the GTK3 port, because that's all GTK3 supports; but we still need old-style GDK for GTK1 support, and also for performance reasons in GTK2 (see below). Hence, this change completely restructures GTK PuTTY's drawing code so that there's a central 'drawing context' structure which contains a type code indicating GDK or Cairo, and then either some GDK gubbins or some Cairo gubbins as appropriate; all actual drawing is abstracted through a set of routines which test the type code in that structure and do one thing or another. And because the type code is tested at run time, both sets of drawing primitives can be compiled in at once, and where possible, they will be. X server-side bitmap fonts are still supported in the Cairo world, but because Cairo drawing is entirely client-side, they have to work by cheekily downloading each glyph bitmap from the server when it's first needed, and building up a client-side cache of 'cairo_surface_t's containing the bitmaps with which we then draw on the window. This technique works, but it's rather slow; hence, even in GTK2, we keep the GDK drawing back end compiled in, and switch over to it when the main selected font is a bitmap one. One visible effect of the new Cairo routines is in the double-width and double-height text you can get by sending ESC # 3, ESC # 4 and ESC # 6 escape sequences. In GDK, that's always been done by a really horrible process of manually scaling the bitmap, server-side, column by column and row by row, causing each pixel to be exactly doubled or quadrupled. But in Cairo, we can just set a transformation matrix, and then that takes effect _before_ the scalable fonts are rendered - so the results are visibly nicer, and use all the available resolution. (Sadly, if you're using a server-side bitmap font as your primary one, then the GDK backend will be selected for all drawing in the terminal as a whole - so in that situation, even fallback characters absent from the primary font and rendered by Pango will get the old GDK scaling treatment. It's only if your main font is scalable, so that the Cairo backend is selected, that DW/DH characters will come out looking nice.)
2015-08-15 23:05:56 +03:00
}
#endif
#ifdef DRAW_TEXT_CAIRO
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
if (inst->uctx.type == DRAWTYPE_CAIRO) {
cairo_new_path(inst->uctx.u.cairo.cr);
cairo_rectangle(inst->uctx.u.cairo.cr, x, y, 1, 1);
cairo_fill(inst->uctx.u.cairo.cr);
Refactor the GTK drawing system to do both GDK and Cairo. We're going to have to use Cairo in the GTK3 port, because that's all GTK3 supports; but we still need old-style GDK for GTK1 support, and also for performance reasons in GTK2 (see below). Hence, this change completely restructures GTK PuTTY's drawing code so that there's a central 'drawing context' structure which contains a type code indicating GDK or Cairo, and then either some GDK gubbins or some Cairo gubbins as appropriate; all actual drawing is abstracted through a set of routines which test the type code in that structure and do one thing or another. And because the type code is tested at run time, both sets of drawing primitives can be compiled in at once, and where possible, they will be. X server-side bitmap fonts are still supported in the Cairo world, but because Cairo drawing is entirely client-side, they have to work by cheekily downloading each glyph bitmap from the server when it's first needed, and building up a client-side cache of 'cairo_surface_t's containing the bitmaps with which we then draw on the window. This technique works, but it's rather slow; hence, even in GTK2, we keep the GDK drawing back end compiled in, and switch over to it when the main selected font is a bitmap one. One visible effect of the new Cairo routines is in the double-width and double-height text you can get by sending ESC # 3, ESC # 4 and ESC # 6 escape sequences. In GDK, that's always been done by a really horrible process of manually scaling the bitmap, server-side, column by column and row by row, causing each pixel to be exactly doubled or quadrupled. But in Cairo, we can just set a transformation matrix, and then that takes effect _before_ the scalable fonts are rendered - so the results are visibly nicer, and use all the available resolution. (Sadly, if you're using a server-side bitmap font as your primary one, then the GDK backend will be selected for all drawing in the terminal as a whole - so in that situation, even fallback characters absent from the primary font and rendered by Pango will get the old GDK scaling treatment. It's only if your main font is scalable, so that the Cairo backend is selected, that DW/DH characters will come out looking nice.)
2015-08-15 23:05:56 +03:00
}
#endif
}
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
static void draw_line(GtkFrontend *inst, int x0, int y0, int x1, int y1)
Refactor the GTK drawing system to do both GDK and Cairo. We're going to have to use Cairo in the GTK3 port, because that's all GTK3 supports; but we still need old-style GDK for GTK1 support, and also for performance reasons in GTK2 (see below). Hence, this change completely restructures GTK PuTTY's drawing code so that there's a central 'drawing context' structure which contains a type code indicating GDK or Cairo, and then either some GDK gubbins or some Cairo gubbins as appropriate; all actual drawing is abstracted through a set of routines which test the type code in that structure and do one thing or another. And because the type code is tested at run time, both sets of drawing primitives can be compiled in at once, and where possible, they will be. X server-side bitmap fonts are still supported in the Cairo world, but because Cairo drawing is entirely client-side, they have to work by cheekily downloading each glyph bitmap from the server when it's first needed, and building up a client-side cache of 'cairo_surface_t's containing the bitmaps with which we then draw on the window. This technique works, but it's rather slow; hence, even in GTK2, we keep the GDK drawing back end compiled in, and switch over to it when the main selected font is a bitmap one. One visible effect of the new Cairo routines is in the double-width and double-height text you can get by sending ESC # 3, ESC # 4 and ESC # 6 escape sequences. In GDK, that's always been done by a really horrible process of manually scaling the bitmap, server-side, column by column and row by row, causing each pixel to be exactly doubled or quadrupled. But in Cairo, we can just set a transformation matrix, and then that takes effect _before_ the scalable fonts are rendered - so the results are visibly nicer, and use all the available resolution. (Sadly, if you're using a server-side bitmap font as your primary one, then the GDK backend will be selected for all drawing in the terminal as a whole - so in that situation, even fallback characters absent from the primary font and rendered by Pango will get the old GDK scaling treatment. It's only if your main font is scalable, so that the Cairo backend is selected, that DW/DH characters will come out looking nice.)
2015-08-15 23:05:56 +03:00
{
#ifdef DRAW_TEXT_GDK
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
if (inst->uctx.type == DRAWTYPE_GDK) {
gdk_draw_line(inst->uctx.u.gdk.target, inst->uctx.u.gdk.gc,
Refactor the GTK drawing system to do both GDK and Cairo. We're going to have to use Cairo in the GTK3 port, because that's all GTK3 supports; but we still need old-style GDK for GTK1 support, and also for performance reasons in GTK2 (see below). Hence, this change completely restructures GTK PuTTY's drawing code so that there's a central 'drawing context' structure which contains a type code indicating GDK or Cairo, and then either some GDK gubbins or some Cairo gubbins as appropriate; all actual drawing is abstracted through a set of routines which test the type code in that structure and do one thing or another. And because the type code is tested at run time, both sets of drawing primitives can be compiled in at once, and where possible, they will be. X server-side bitmap fonts are still supported in the Cairo world, but because Cairo drawing is entirely client-side, they have to work by cheekily downloading each glyph bitmap from the server when it's first needed, and building up a client-side cache of 'cairo_surface_t's containing the bitmaps with which we then draw on the window. This technique works, but it's rather slow; hence, even in GTK2, we keep the GDK drawing back end compiled in, and switch over to it when the main selected font is a bitmap one. One visible effect of the new Cairo routines is in the double-width and double-height text you can get by sending ESC # 3, ESC # 4 and ESC # 6 escape sequences. In GDK, that's always been done by a really horrible process of manually scaling the bitmap, server-side, column by column and row by row, causing each pixel to be exactly doubled or quadrupled. But in Cairo, we can just set a transformation matrix, and then that takes effect _before_ the scalable fonts are rendered - so the results are visibly nicer, and use all the available resolution. (Sadly, if you're using a server-side bitmap font as your primary one, then the GDK backend will be selected for all drawing in the terminal as a whole - so in that situation, even fallback characters absent from the primary font and rendered by Pango will get the old GDK scaling treatment. It's only if your main font is scalable, so that the Cairo backend is selected, that DW/DH characters will come out looking nice.)
2015-08-15 23:05:56 +03:00
x0, y0, x1, y1);
}
#endif
#ifdef DRAW_TEXT_CAIRO
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
if (inst->uctx.type == DRAWTYPE_CAIRO) {
cairo_new_path(inst->uctx.u.cairo.cr);
cairo_move_to(inst->uctx.u.cairo.cr, x0 + 0.5, y0 + 0.5);
cairo_line_to(inst->uctx.u.cairo.cr, x1 + 0.5, y1 + 0.5);
cairo_stroke(inst->uctx.u.cairo.cr);
Refactor the GTK drawing system to do both GDK and Cairo. We're going to have to use Cairo in the GTK3 port, because that's all GTK3 supports; but we still need old-style GDK for GTK1 support, and also for performance reasons in GTK2 (see below). Hence, this change completely restructures GTK PuTTY's drawing code so that there's a central 'drawing context' structure which contains a type code indicating GDK or Cairo, and then either some GDK gubbins or some Cairo gubbins as appropriate; all actual drawing is abstracted through a set of routines which test the type code in that structure and do one thing or another. And because the type code is tested at run time, both sets of drawing primitives can be compiled in at once, and where possible, they will be. X server-side bitmap fonts are still supported in the Cairo world, but because Cairo drawing is entirely client-side, they have to work by cheekily downloading each glyph bitmap from the server when it's first needed, and building up a client-side cache of 'cairo_surface_t's containing the bitmaps with which we then draw on the window. This technique works, but it's rather slow; hence, even in GTK2, we keep the GDK drawing back end compiled in, and switch over to it when the main selected font is a bitmap one. One visible effect of the new Cairo routines is in the double-width and double-height text you can get by sending ESC # 3, ESC # 4 and ESC # 6 escape sequences. In GDK, that's always been done by a really horrible process of manually scaling the bitmap, server-side, column by column and row by row, causing each pixel to be exactly doubled or quadrupled. But in Cairo, we can just set a transformation matrix, and then that takes effect _before_ the scalable fonts are rendered - so the results are visibly nicer, and use all the available resolution. (Sadly, if you're using a server-side bitmap font as your primary one, then the GDK backend will be selected for all drawing in the terminal as a whole - so in that situation, even fallback characters absent from the primary font and rendered by Pango will get the old GDK scaling treatment. It's only if your main font is scalable, so that the Cairo backend is selected, that DW/DH characters will come out looking nice.)
2015-08-15 23:05:56 +03:00
}
#endif
}
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
static void draw_stretch_before(GtkFrontend *inst, int x, int y,
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
int w, bool wdouble,
int h, bool hdouble, bool hbothalf)
Refactor the GTK drawing system to do both GDK and Cairo. We're going to have to use Cairo in the GTK3 port, because that's all GTK3 supports; but we still need old-style GDK for GTK1 support, and also for performance reasons in GTK2 (see below). Hence, this change completely restructures GTK PuTTY's drawing code so that there's a central 'drawing context' structure which contains a type code indicating GDK or Cairo, and then either some GDK gubbins or some Cairo gubbins as appropriate; all actual drawing is abstracted through a set of routines which test the type code in that structure and do one thing or another. And because the type code is tested at run time, both sets of drawing primitives can be compiled in at once, and where possible, they will be. X server-side bitmap fonts are still supported in the Cairo world, but because Cairo drawing is entirely client-side, they have to work by cheekily downloading each glyph bitmap from the server when it's first needed, and building up a client-side cache of 'cairo_surface_t's containing the bitmaps with which we then draw on the window. This technique works, but it's rather slow; hence, even in GTK2, we keep the GDK drawing back end compiled in, and switch over to it when the main selected font is a bitmap one. One visible effect of the new Cairo routines is in the double-width and double-height text you can get by sending ESC # 3, ESC # 4 and ESC # 6 escape sequences. In GDK, that's always been done by a really horrible process of manually scaling the bitmap, server-side, column by column and row by row, causing each pixel to be exactly doubled or quadrupled. But in Cairo, we can just set a transformation matrix, and then that takes effect _before_ the scalable fonts are rendered - so the results are visibly nicer, and use all the available resolution. (Sadly, if you're using a server-side bitmap font as your primary one, then the GDK backend will be selected for all drawing in the terminal as a whole - so in that situation, even fallback characters absent from the primary font and rendered by Pango will get the old GDK scaling treatment. It's only if your main font is scalable, so that the Cairo backend is selected, that DW/DH characters will come out looking nice.)
2015-08-15 23:05:56 +03:00
{
#ifdef DRAW_TEXT_CAIRO
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
if (inst->uctx.type == DRAWTYPE_CAIRO) {
Refactor the GTK drawing system to do both GDK and Cairo. We're going to have to use Cairo in the GTK3 port, because that's all GTK3 supports; but we still need old-style GDK for GTK1 support, and also for performance reasons in GTK2 (see below). Hence, this change completely restructures GTK PuTTY's drawing code so that there's a central 'drawing context' structure which contains a type code indicating GDK or Cairo, and then either some GDK gubbins or some Cairo gubbins as appropriate; all actual drawing is abstracted through a set of routines which test the type code in that structure and do one thing or another. And because the type code is tested at run time, both sets of drawing primitives can be compiled in at once, and where possible, they will be. X server-side bitmap fonts are still supported in the Cairo world, but because Cairo drawing is entirely client-side, they have to work by cheekily downloading each glyph bitmap from the server when it's first needed, and building up a client-side cache of 'cairo_surface_t's containing the bitmaps with which we then draw on the window. This technique works, but it's rather slow; hence, even in GTK2, we keep the GDK drawing back end compiled in, and switch over to it when the main selected font is a bitmap one. One visible effect of the new Cairo routines is in the double-width and double-height text you can get by sending ESC # 3, ESC # 4 and ESC # 6 escape sequences. In GDK, that's always been done by a really horrible process of manually scaling the bitmap, server-side, column by column and row by row, causing each pixel to be exactly doubled or quadrupled. But in Cairo, we can just set a transformation matrix, and then that takes effect _before_ the scalable fonts are rendered - so the results are visibly nicer, and use all the available resolution. (Sadly, if you're using a server-side bitmap font as your primary one, then the GDK backend will be selected for all drawing in the terminal as a whole - so in that situation, even fallback characters absent from the primary font and rendered by Pango will get the old GDK scaling treatment. It's only if your main font is scalable, so that the Cairo backend is selected, that DW/DH characters will come out looking nice.)
2015-08-15 23:05:56 +03:00
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;
}
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
cairo_transform(inst->uctx.u.cairo.cr, &matrix);
Refactor the GTK drawing system to do both GDK and Cairo. We're going to have to use Cairo in the GTK3 port, because that's all GTK3 supports; but we still need old-style GDK for GTK1 support, and also for performance reasons in GTK2 (see below). Hence, this change completely restructures GTK PuTTY's drawing code so that there's a central 'drawing context' structure which contains a type code indicating GDK or Cairo, and then either some GDK gubbins or some Cairo gubbins as appropriate; all actual drawing is abstracted through a set of routines which test the type code in that structure and do one thing or another. And because the type code is tested at run time, both sets of drawing primitives can be compiled in at once, and where possible, they will be. X server-side bitmap fonts are still supported in the Cairo world, but because Cairo drawing is entirely client-side, they have to work by cheekily downloading each glyph bitmap from the server when it's first needed, and building up a client-side cache of 'cairo_surface_t's containing the bitmaps with which we then draw on the window. This technique works, but it's rather slow; hence, even in GTK2, we keep the GDK drawing back end compiled in, and switch over to it when the main selected font is a bitmap one. One visible effect of the new Cairo routines is in the double-width and double-height text you can get by sending ESC # 3, ESC # 4 and ESC # 6 escape sequences. In GDK, that's always been done by a really horrible process of manually scaling the bitmap, server-side, column by column and row by row, causing each pixel to be exactly doubled or quadrupled. But in Cairo, we can just set a transformation matrix, and then that takes effect _before_ the scalable fonts are rendered - so the results are visibly nicer, and use all the available resolution. (Sadly, if you're using a server-side bitmap font as your primary one, then the GDK backend will be selected for all drawing in the terminal as a whole - so in that situation, even fallback characters absent from the primary font and rendered by Pango will get the old GDK scaling treatment. It's only if your main font is scalable, so that the Cairo backend is selected, that DW/DH characters will come out looking nice.)
2015-08-15 23:05:56 +03:00
}
#endif
}
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
static void draw_stretch_after(GtkFrontend *inst, int x, int y,
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
int w, bool wdouble,
int h, bool hdouble, bool hbothalf)
Refactor the GTK drawing system to do both GDK and Cairo. We're going to have to use Cairo in the GTK3 port, because that's all GTK3 supports; but we still need old-style GDK for GTK1 support, and also for performance reasons in GTK2 (see below). Hence, this change completely restructures GTK PuTTY's drawing code so that there's a central 'drawing context' structure which contains a type code indicating GDK or Cairo, and then either some GDK gubbins or some Cairo gubbins as appropriate; all actual drawing is abstracted through a set of routines which test the type code in that structure and do one thing or another. And because the type code is tested at run time, both sets of drawing primitives can be compiled in at once, and where possible, they will be. X server-side bitmap fonts are still supported in the Cairo world, but because Cairo drawing is entirely client-side, they have to work by cheekily downloading each glyph bitmap from the server when it's first needed, and building up a client-side cache of 'cairo_surface_t's containing the bitmaps with which we then draw on the window. This technique works, but it's rather slow; hence, even in GTK2, we keep the GDK drawing back end compiled in, and switch over to it when the main selected font is a bitmap one. One visible effect of the new Cairo routines is in the double-width and double-height text you can get by sending ESC # 3, ESC # 4 and ESC # 6 escape sequences. In GDK, that's always been done by a really horrible process of manually scaling the bitmap, server-side, column by column and row by row, causing each pixel to be exactly doubled or quadrupled. But in Cairo, we can just set a transformation matrix, and then that takes effect _before_ the scalable fonts are rendered - so the results are visibly nicer, and use all the available resolution. (Sadly, if you're using a server-side bitmap font as your primary one, then the GDK backend will be selected for all drawing in the terminal as a whole - so in that situation, even fallback characters absent from the primary font and rendered by Pango will get the old GDK scaling treatment. It's only if your main font is scalable, so that the Cairo backend is selected, that DW/DH characters will come out looking nice.)
2015-08-15 23:05:56 +03:00
{
#ifdef DRAW_TEXT_GDK
#ifndef NO_BACKING_PIXMAPS
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
if (inst->uctx.type == DRAWTYPE_GDK) {
Refactor the GTK drawing system to do both GDK and Cairo. We're going to have to use Cairo in the GTK3 port, because that's all GTK3 supports; but we still need old-style GDK for GTK1 support, and also for performance reasons in GTK2 (see below). Hence, this change completely restructures GTK PuTTY's drawing code so that there's a central 'drawing context' structure which contains a type code indicating GDK or Cairo, and then either some GDK gubbins or some Cairo gubbins as appropriate; all actual drawing is abstracted through a set of routines which test the type code in that structure and do one thing or another. And because the type code is tested at run time, both sets of drawing primitives can be compiled in at once, and where possible, they will be. X server-side bitmap fonts are still supported in the Cairo world, but because Cairo drawing is entirely client-side, they have to work by cheekily downloading each glyph bitmap from the server when it's first needed, and building up a client-side cache of 'cairo_surface_t's containing the bitmaps with which we then draw on the window. This technique works, but it's rather slow; hence, even in GTK2, we keep the GDK drawing back end compiled in, and switch over to it when the main selected font is a bitmap one. One visible effect of the new Cairo routines is in the double-width and double-height text you can get by sending ESC # 3, ESC # 4 and ESC # 6 escape sequences. In GDK, that's always been done by a really horrible process of manually scaling the bitmap, server-side, column by column and row by row, causing each pixel to be exactly doubled or quadrupled. But in Cairo, we can just set a transformation matrix, and then that takes effect _before_ the scalable fonts are rendered - so the results are visibly nicer, and use all the available resolution. (Sadly, if you're using a server-side bitmap font as your primary one, then the GDK backend will be selected for all drawing in the terminal as a whole - so in that situation, even fallback characters absent from the primary font and rendered by Pango will get the old GDK scaling treatment. It's only if your main font is scalable, so that the Cairo backend is selected, that DW/DH characters will come out looking nice.)
2015-08-15 23:05:56 +03:00
/*
* I can't find any plausible StretchBlt equivalent in the X
* server, so I'm going to do this the slow and painful way.
* This will involve repeated calls to gdk_draw_pixmap() to
* stretch the text horizontally. It's O(N^2) in time and O(N)
* in network bandwidth, but you try thinking of a better way.
* :-(
*/
int i;
if (wdouble) {
for (i = 0; i < w; i++) {
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
gdk_draw_pixmap(inst->uctx.u.gdk.target,
inst->uctx.u.gdk.gc,
inst->uctx.u.gdk.target,
Refactor the GTK drawing system to do both GDK and Cairo. We're going to have to use Cairo in the GTK3 port, because that's all GTK3 supports; but we still need old-style GDK for GTK1 support, and also for performance reasons in GTK2 (see below). Hence, this change completely restructures GTK PuTTY's drawing code so that there's a central 'drawing context' structure which contains a type code indicating GDK or Cairo, and then either some GDK gubbins or some Cairo gubbins as appropriate; all actual drawing is abstracted through a set of routines which test the type code in that structure and do one thing or another. And because the type code is tested at run time, both sets of drawing primitives can be compiled in at once, and where possible, they will be. X server-side bitmap fonts are still supported in the Cairo world, but because Cairo drawing is entirely client-side, they have to work by cheekily downloading each glyph bitmap from the server when it's first needed, and building up a client-side cache of 'cairo_surface_t's containing the bitmaps with which we then draw on the window. This technique works, but it's rather slow; hence, even in GTK2, we keep the GDK drawing back end compiled in, and switch over to it when the main selected font is a bitmap one. One visible effect of the new Cairo routines is in the double-width and double-height text you can get by sending ESC # 3, ESC # 4 and ESC # 6 escape sequences. In GDK, that's always been done by a really horrible process of manually scaling the bitmap, server-side, column by column and row by row, causing each pixel to be exactly doubled or quadrupled. But in Cairo, we can just set a transformation matrix, and then that takes effect _before_ the scalable fonts are rendered - so the results are visibly nicer, and use all the available resolution. (Sadly, if you're using a server-side bitmap font as your primary one, then the GDK backend will be selected for all drawing in the terminal as a whole - so in that situation, even fallback characters absent from the primary font and rendered by Pango will get the old GDK scaling treatment. It's only if your main font is scalable, so that the Cairo backend is selected, that DW/DH characters will come out looking nice.)
2015-08-15 23:05:56 +03:00
x + 2*i, y,
x + 2*i+1, y,
w - i, h);
}
w *= 2;
}
if (hdouble) {
int dt, db;
/* Now stretch vertically, in the same way. */
if (hbothalf)
dt = 0, db = 1;
else
dt = 1, db = 0;
for (i = 0; i < h; i += 2) {
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
gdk_draw_pixmap(inst->uctx.u.gdk.target,
inst->uctx.u.gdk.gc,
inst->uctx.u.gdk.target,
Refactor the GTK drawing system to do both GDK and Cairo. We're going to have to use Cairo in the GTK3 port, because that's all GTK3 supports; but we still need old-style GDK for GTK1 support, and also for performance reasons in GTK2 (see below). Hence, this change completely restructures GTK PuTTY's drawing code so that there's a central 'drawing context' structure which contains a type code indicating GDK or Cairo, and then either some GDK gubbins or some Cairo gubbins as appropriate; all actual drawing is abstracted through a set of routines which test the type code in that structure and do one thing or another. And because the type code is tested at run time, both sets of drawing primitives can be compiled in at once, and where possible, they will be. X server-side bitmap fonts are still supported in the Cairo world, but because Cairo drawing is entirely client-side, they have to work by cheekily downloading each glyph bitmap from the server when it's first needed, and building up a client-side cache of 'cairo_surface_t's containing the bitmaps with which we then draw on the window. This technique works, but it's rather slow; hence, even in GTK2, we keep the GDK drawing back end compiled in, and switch over to it when the main selected font is a bitmap one. One visible effect of the new Cairo routines is in the double-width and double-height text you can get by sending ESC # 3, ESC # 4 and ESC # 6 escape sequences. In GDK, that's always been done by a really horrible process of manually scaling the bitmap, server-side, column by column and row by row, causing each pixel to be exactly doubled or quadrupled. But in Cairo, we can just set a transformation matrix, and then that takes effect _before_ the scalable fonts are rendered - so the results are visibly nicer, and use all the available resolution. (Sadly, if you're using a server-side bitmap font as your primary one, then the GDK backend will be selected for all drawing in the terminal as a whole - so in that situation, even fallback characters absent from the primary font and rendered by Pango will get the old GDK scaling treatment. It's only if your main font is scalable, so that the Cairo backend is selected, that DW/DH characters will come out looking nice.)
2015-08-15 23:05:56 +03:00
x, y + dt*i + db,
x, y + dt*(i+1),
w, h-i-1);
}
}
}
#else
#error No way to implement stretching in GDK without a reliable backing pixmap
Refactor the GTK drawing system to do both GDK and Cairo. We're going to have to use Cairo in the GTK3 port, because that's all GTK3 supports; but we still need old-style GDK for GTK1 support, and also for performance reasons in GTK2 (see below). Hence, this change completely restructures GTK PuTTY's drawing code so that there's a central 'drawing context' structure which contains a type code indicating GDK or Cairo, and then either some GDK gubbins or some Cairo gubbins as appropriate; all actual drawing is abstracted through a set of routines which test the type code in that structure and do one thing or another. And because the type code is tested at run time, both sets of drawing primitives can be compiled in at once, and where possible, they will be. X server-side bitmap fonts are still supported in the Cairo world, but because Cairo drawing is entirely client-side, they have to work by cheekily downloading each glyph bitmap from the server when it's first needed, and building up a client-side cache of 'cairo_surface_t's containing the bitmaps with which we then draw on the window. This technique works, but it's rather slow; hence, even in GTK2, we keep the GDK drawing back end compiled in, and switch over to it when the main selected font is a bitmap one. One visible effect of the new Cairo routines is in the double-width and double-height text you can get by sending ESC # 3, ESC # 4 and ESC # 6 escape sequences. In GDK, that's always been done by a really horrible process of manually scaling the bitmap, server-side, column by column and row by row, causing each pixel to be exactly doubled or quadrupled. But in Cairo, we can just set a transformation matrix, and then that takes effect _before_ the scalable fonts are rendered - so the results are visibly nicer, and use all the available resolution. (Sadly, if you're using a server-side bitmap font as your primary one, then the GDK backend will be selected for all drawing in the terminal as a whole - so in that situation, even fallback characters absent from the primary font and rendered by Pango will get the old GDK scaling treatment. It's only if your main font is scalable, so that the Cairo backend is selected, that DW/DH characters will come out looking nice.)
2015-08-15 23:05:56 +03:00
#endif
#endif /* DRAW_TEXT_GDK */
Refactor the GTK drawing system to do both GDK and Cairo. We're going to have to use Cairo in the GTK3 port, because that's all GTK3 supports; but we still need old-style GDK for GTK1 support, and also for performance reasons in GTK2 (see below). Hence, this change completely restructures GTK PuTTY's drawing code so that there's a central 'drawing context' structure which contains a type code indicating GDK or Cairo, and then either some GDK gubbins or some Cairo gubbins as appropriate; all actual drawing is abstracted through a set of routines which test the type code in that structure and do one thing or another. And because the type code is tested at run time, both sets of drawing primitives can be compiled in at once, and where possible, they will be. X server-side bitmap fonts are still supported in the Cairo world, but because Cairo drawing is entirely client-side, they have to work by cheekily downloading each glyph bitmap from the server when it's first needed, and building up a client-side cache of 'cairo_surface_t's containing the bitmaps with which we then draw on the window. This technique works, but it's rather slow; hence, even in GTK2, we keep the GDK drawing back end compiled in, and switch over to it when the main selected font is a bitmap one. One visible effect of the new Cairo routines is in the double-width and double-height text you can get by sending ESC # 3, ESC # 4 and ESC # 6 escape sequences. In GDK, that's always been done by a really horrible process of manually scaling the bitmap, server-side, column by column and row by row, causing each pixel to be exactly doubled or quadrupled. But in Cairo, we can just set a transformation matrix, and then that takes effect _before_ the scalable fonts are rendered - so the results are visibly nicer, and use all the available resolution. (Sadly, if you're using a server-side bitmap font as your primary one, then the GDK backend will be selected for all drawing in the terminal as a whole - so in that situation, even fallback characters absent from the primary font and rendered by Pango will get the old GDK scaling treatment. It's only if your main font is scalable, so that the Cairo backend is selected, that DW/DH characters will come out looking nice.)
2015-08-15 23:05:56 +03:00
#ifdef DRAW_TEXT_CAIRO
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
if (inst->uctx.type == DRAWTYPE_CAIRO) {
cairo_set_matrix(inst->uctx.u.cairo.cr,
&inst->uctx.u.cairo.origmatrix);
Refactor the GTK drawing system to do both GDK and Cairo. We're going to have to use Cairo in the GTK3 port, because that's all GTK3 supports; but we still need old-style GDK for GTK1 support, and also for performance reasons in GTK2 (see below). Hence, this change completely restructures GTK PuTTY's drawing code so that there's a central 'drawing context' structure which contains a type code indicating GDK or Cairo, and then either some GDK gubbins or some Cairo gubbins as appropriate; all actual drawing is abstracted through a set of routines which test the type code in that structure and do one thing or another. And because the type code is tested at run time, both sets of drawing primitives can be compiled in at once, and where possible, they will be. X server-side bitmap fonts are still supported in the Cairo world, but because Cairo drawing is entirely client-side, they have to work by cheekily downloading each glyph bitmap from the server when it's first needed, and building up a client-side cache of 'cairo_surface_t's containing the bitmaps with which we then draw on the window. This technique works, but it's rather slow; hence, even in GTK2, we keep the GDK drawing back end compiled in, and switch over to it when the main selected font is a bitmap one. One visible effect of the new Cairo routines is in the double-width and double-height text you can get by sending ESC # 3, ESC # 4 and ESC # 6 escape sequences. In GDK, that's always been done by a really horrible process of manually scaling the bitmap, server-side, column by column and row by row, causing each pixel to be exactly doubled or quadrupled. But in Cairo, we can just set a transformation matrix, and then that takes effect _before_ the scalable fonts are rendered - so the results are visibly nicer, and use all the available resolution. (Sadly, if you're using a server-side bitmap font as your primary one, then the GDK backend will be selected for all drawing in the terminal as a whole - so in that situation, even fallback characters absent from the primary font and rendered by Pango will get the old GDK scaling treatment. It's only if your main font is scalable, so that the Cairo backend is selected, that DW/DH characters will come out looking nice.)
2015-08-15 23:05:56 +03:00
}
#endif
}
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
static void draw_backing_rect(GtkFrontend *inst)
Refactor the GTK drawing system to do both GDK and Cairo. We're going to have to use Cairo in the GTK3 port, because that's all GTK3 supports; but we still need old-style GDK for GTK1 support, and also for performance reasons in GTK2 (see below). Hence, this change completely restructures GTK PuTTY's drawing code so that there's a central 'drawing context' structure which contains a type code indicating GDK or Cairo, and then either some GDK gubbins or some Cairo gubbins as appropriate; all actual drawing is abstracted through a set of routines which test the type code in that structure and do one thing or another. And because the type code is tested at run time, both sets of drawing primitives can be compiled in at once, and where possible, they will be. X server-side bitmap fonts are still supported in the Cairo world, but because Cairo drawing is entirely client-side, they have to work by cheekily downloading each glyph bitmap from the server when it's first needed, and building up a client-side cache of 'cairo_surface_t's containing the bitmaps with which we then draw on the window. This technique works, but it's rather slow; hence, even in GTK2, we keep the GDK drawing back end compiled in, and switch over to it when the main selected font is a bitmap one. One visible effect of the new Cairo routines is in the double-width and double-height text you can get by sending ESC # 3, ESC # 4 and ESC # 6 escape sequences. In GDK, that's always been done by a really horrible process of manually scaling the bitmap, server-side, column by column and row by row, causing each pixel to be exactly doubled or quadrupled. But in Cairo, we can just set a transformation matrix, and then that takes effect _before_ the scalable fonts are rendered - so the results are visibly nicer, and use all the available resolution. (Sadly, if you're using a server-side bitmap font as your primary one, then the GDK backend will be selected for all drawing in the terminal as a whole - so in that situation, even fallback characters absent from the primary font and rendered by Pango will get the old GDK scaling treatment. It's only if your main font is scalable, so that the Cairo backend is selected, that DW/DH characters will come out looking nice.)
2015-08-15 23:05:56 +03:00
{
Stop using the GTK "configure-event" signal. I've been using that signal since the very first commit of this source file, as a combined way to be notified when the size of the drawing area changes (typically due to user window resizing actions) and also when the drawing area is first created and available to be drawn on. Unfortunately, testing on Ubuntu 18.04, I ran into an oddity, in which the call to gtk_widget_show(inst->window) in new_session_window() has the side effect of delivering a spurious configure_event on the drawing area with size 1x46 pixels. This causes the terminal to resize itself to 1 column wide, and the mistake isn't rectified until a followup configure-event arrives after new_session_window returns to the GTK main loop. But that means terminal output can occur between those two configure events (the connection-sharing "Reusing a shared connection to host.name" is a good example), and when it does, it gets embarrassingly wrapped at one character per line down the left column. I briefly tried to bodge around this by trying to heuristically guess which configure events were real and which were spurious, but I have no faith in that strategy continuing to work. I think a better approach is to abandon configure-event completely, and move to a system in which the two purposes I was using it for are handled by two _different_ GTK signals, namely "size-allocate" (for knowing when we get resized) and "realize" (for knowing when the drawing area physically exists for us to start setting up Cairo or GDK machinery). The result seems to have fixed the silly one-column wrapping bug, and retained the ability to handle window resizes, on every GTK version I have conveniently available to test on, including GTK 3 both before and after these spurious configures started to happen.
2018-05-10 22:22:02 +03:00
int w, h;
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
if (!win_setup_draw_ctx(&inst->termwin))
Stop using the GTK "configure-event" signal. I've been using that signal since the very first commit of this source file, as a combined way to be notified when the size of the drawing area changes (typically due to user window resizing actions) and also when the drawing area is first created and available to be drawn on. Unfortunately, testing on Ubuntu 18.04, I ran into an oddity, in which the call to gtk_widget_show(inst->window) in new_session_window() has the side effect of delivering a spurious configure_event on the drawing area with size 1x46 pixels. This causes the terminal to resize itself to 1 column wide, and the mistake isn't rectified until a followup configure-event arrives after new_session_window returns to the GTK main loop. But that means terminal output can occur between those two configure events (the connection-sharing "Reusing a shared connection to host.name" is a good example), and when it does, it gets embarrassingly wrapped at one character per line down the left column. I briefly tried to bodge around this by trying to heuristically guess which configure events were real and which were spurious, but I have no faith in that strategy continuing to work. I think a better approach is to abandon configure-event completely, and move to a system in which the two purposes I was using it for are handled by two _different_ GTK signals, namely "size-allocate" (for knowing when we get resized) and "realize" (for knowing when the drawing area physically exists for us to start setting up Cairo or GDK machinery). The result seems to have fixed the silly one-column wrapping bug, and retained the ability to handle window resizes, on every GTK version I have conveniently available to test on, including GTK 3 both before and after these spurious configures started to happen.
2018-05-10 22:22:02 +03:00
return;
w = inst->width * inst->font_width + 2*inst->window_border;
h = inst->height * inst->font_height + 2*inst->window_border;
draw_set_colour(inst, 258, false);
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
draw_rectangle(inst, true, 0, 0, w, h);
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
draw_update(inst, 0, 0, w, h);
win_free_draw_ctx(&inst->termwin);
Refactor the GTK drawing system to do both GDK and Cairo. We're going to have to use Cairo in the GTK3 port, because that's all GTK3 supports; but we still need old-style GDK for GTK1 support, and also for performance reasons in GTK2 (see below). Hence, this change completely restructures GTK PuTTY's drawing code so that there's a central 'drawing context' structure which contains a type code indicating GDK or Cairo, and then either some GDK gubbins or some Cairo gubbins as appropriate; all actual drawing is abstracted through a set of routines which test the type code in that structure and do one thing or another. And because the type code is tested at run time, both sets of drawing primitives can be compiled in at once, and where possible, they will be. X server-side bitmap fonts are still supported in the Cairo world, but because Cairo drawing is entirely client-side, they have to work by cheekily downloading each glyph bitmap from the server when it's first needed, and building up a client-side cache of 'cairo_surface_t's containing the bitmaps with which we then draw on the window. This technique works, but it's rather slow; hence, even in GTK2, we keep the GDK drawing back end compiled in, and switch over to it when the main selected font is a bitmap one. One visible effect of the new Cairo routines is in the double-width and double-height text you can get by sending ESC # 3, ESC # 4 and ESC # 6 escape sequences. In GDK, that's always been done by a really horrible process of manually scaling the bitmap, server-side, column by column and row by row, causing each pixel to be exactly doubled or quadrupled. But in Cairo, we can just set a transformation matrix, and then that takes effect _before_ the scalable fonts are rendered - so the results are visibly nicer, and use all the available resolution. (Sadly, if you're using a server-side bitmap font as your primary one, then the GDK backend will be selected for all drawing in the terminal as a whole - so in that situation, even fallback characters absent from the primary font and rendered by Pango will get the old GDK scaling treatment. It's only if your main font is scalable, so that the Cairo backend is selected, that DW/DH characters will come out looking nice.)
2015-08-15 23:05:56 +03:00
}
/*
* Draw a line of text in the window, at given character
* coordinates, in given attributes.
*
* We are allowed to fiddle with the contents of `text'.
*/
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
static void do_text_internal(
GtkFrontend *inst, int x, int y, wchar_t *text, int len,
unsigned long attr, int lattr, truecolour truecolour)
{
int ncombining;
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
int nfg, nbg, t, fontid, rlen, widefactor;
bool bold;
bool monochrome =
gdk_visual_get_depth(gtk_widget_get_visual(inst->area)) == 1;
if (attr & TATTR_COMBINING) {
ncombining = len;
len = 1;
} else
ncombining = 1;
if (monochrome)
truecolour.fg = truecolour.bg = optionalrgb_none;
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))) {
struct optionalrgb trgb;
t = nfg;
nfg = nbg;
nbg = t;
trgb = truecolour.fg;
truecolour.fg = truecolour.bg;
truecolour.bg = trgb;
}
if ((inst->bold_style & 2) && (attr & ATTR_BOLD)) {
if (nfg < 16) nfg |= 8;
else if (nfg >= 256) nfg |= 1;
}
if ((inst->bold_style & 2) && (attr & ATTR_BLINK)) {
if (nbg < 16) nbg |= 8;
else if (nbg >= 256) nbg |= 1;
}
if ((attr & TATTR_ACTCURS) && !monochrome) {
truecolour.fg = truecolour.bg = optionalrgb_none;
nfg = 260;
nbg = 261;
attr &= ~ATTR_DIM; /* don't dim the cursor */
}
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
fontid = 0;
if (attr & ATTR_WIDE) {
widefactor = 2;
fontid |= 2;
} else {
widefactor = 1;
}
if ((attr & ATTR_BOLD) && (inst->bold_style & 1)) {
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
bold = true;
fontid |= 1;
} else {
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
bold = false;
}
if (!inst->fonts[fontid]) {
int i;
/*
* Fall back through font ids with subsets of this one's
* set bits, in order.
*/
for (i = fontid; i-- > 0 ;) {
if (i & ~fontid)
continue; /* some other bit is set */
if (inst->fonts[i]) {
fontid = i;
break;
}
}
assert(inst->fonts[fontid]); /* we should at least have hit zero */
}
Re-engineering of terminal emulator, phase 1. The active terminal screen is no longer an array of `unsigned long' encoding 16-bit Unicode plus 16 attribute bits. Now it's an array of `termchar' structures, which currently have 32-bit Unicode and 32 attribute bits but which will probably expand further in future. To prevent bloat of the memory footprint, I've introduced a mostly RLE-like compression scheme for storing scrollback: each line is compressed into a compact (but hard to modify) form when it moves into the term->scrollback tree, and is temporarily decompressed when the user wants to scroll back over it. My initial tests suggest that this compression averages about 1/4 of the previous (32 bits per character cell) data size in typical output, which means this is an improvement even without counting the new ability to extend the information stored in each character cell. Another beneficial side effect is that the insane format in which Unicode was passed to front ends through do_text() has now been rendered sane. Testing is incomplete; this _may_ still have instabilities. Windows and Unix front ends both seem to work as far as I've looked, but I haven't yet looked very hard. The Mac front end I've edited (it seemed obvious how to change it) but I can't compile or test it. As an immediate functional effect, the terminal emulator now supports full 32-bit Unicode to whatever extent the host platform allows it to. For example, if you output a 4-or-more-byte UTF-8 character in Unix pterm, it will not display it properly, but it will correctly paste it back out in a UTF8_STRING selection. Windows is more restricted, sadly. [originally from svn r4609]
2004-10-13 15:50:16 +04:00
if ((lattr & LATTR_MODE) != LATTR_NORM) {
x *= 2;
if (x >= inst->term->cols)
return;
if (x + len*2*widefactor > inst->term->cols)
len = (inst->term->cols-x)/2/widefactor;/* trim to LH half */
rlen = len * 2;
} else
rlen = len;
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
draw_clip(inst,
x*inst->font_width+inst->window_border,
y*inst->font_height+inst->window_border,
rlen*widefactor*inst->font_width,
inst->font_height);
Refactor the GTK drawing system to do both GDK and Cairo. We're going to have to use Cairo in the GTK3 port, because that's all GTK3 supports; but we still need old-style GDK for GTK1 support, and also for performance reasons in GTK2 (see below). Hence, this change completely restructures GTK PuTTY's drawing code so that there's a central 'drawing context' structure which contains a type code indicating GDK or Cairo, and then either some GDK gubbins or some Cairo gubbins as appropriate; all actual drawing is abstracted through a set of routines which test the type code in that structure and do one thing or another. And because the type code is tested at run time, both sets of drawing primitives can be compiled in at once, and where possible, they will be. X server-side bitmap fonts are still supported in the Cairo world, but because Cairo drawing is entirely client-side, they have to work by cheekily downloading each glyph bitmap from the server when it's first needed, and building up a client-side cache of 'cairo_surface_t's containing the bitmaps with which we then draw on the window. This technique works, but it's rather slow; hence, even in GTK2, we keep the GDK drawing back end compiled in, and switch over to it when the main selected font is a bitmap one. One visible effect of the new Cairo routines is in the double-width and double-height text you can get by sending ESC # 3, ESC # 4 and ESC # 6 escape sequences. In GDK, that's always been done by a really horrible process of manually scaling the bitmap, server-side, column by column and row by row, causing each pixel to be exactly doubled or quadrupled. But in Cairo, we can just set a transformation matrix, and then that takes effect _before_ the scalable fonts are rendered - so the results are visibly nicer, and use all the available resolution. (Sadly, if you're using a server-side bitmap font as your primary one, then the GDK backend will be selected for all drawing in the terminal as a whole - so in that situation, even fallback characters absent from the primary font and rendered by Pango will get the old GDK scaling treatment. It's only if your main font is scalable, so that the Cairo backend is selected, that DW/DH characters will come out looking nice.)
2015-08-15 23:05:56 +03:00
if ((lattr & LATTR_MODE) != LATTR_NORM) {
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
draw_stretch_before(inst,
Refactor the GTK drawing system to do both GDK and Cairo. We're going to have to use Cairo in the GTK3 port, because that's all GTK3 supports; but we still need old-style GDK for GTK1 support, and also for performance reasons in GTK2 (see below). Hence, this change completely restructures GTK PuTTY's drawing code so that there's a central 'drawing context' structure which contains a type code indicating GDK or Cairo, and then either some GDK gubbins or some Cairo gubbins as appropriate; all actual drawing is abstracted through a set of routines which test the type code in that structure and do one thing or another. And because the type code is tested at run time, both sets of drawing primitives can be compiled in at once, and where possible, they will be. X server-side bitmap fonts are still supported in the Cairo world, but because Cairo drawing is entirely client-side, they have to work by cheekily downloading each glyph bitmap from the server when it's first needed, and building up a client-side cache of 'cairo_surface_t's containing the bitmaps with which we then draw on the window. This technique works, but it's rather slow; hence, even in GTK2, we keep the GDK drawing back end compiled in, and switch over to it when the main selected font is a bitmap one. One visible effect of the new Cairo routines is in the double-width and double-height text you can get by sending ESC # 3, ESC # 4 and ESC # 6 escape sequences. In GDK, that's always been done by a really horrible process of manually scaling the bitmap, server-side, column by column and row by row, causing each pixel to be exactly doubled or quadrupled. But in Cairo, we can just set a transformation matrix, and then that takes effect _before_ the scalable fonts are rendered - so the results are visibly nicer, and use all the available resolution. (Sadly, if you're using a server-side bitmap font as your primary one, then the GDK backend will be selected for all drawing in the terminal as a whole - so in that situation, even fallback characters absent from the primary font and rendered by Pango will get the old GDK scaling treatment. It's only if your main font is scalable, so that the Cairo backend is selected, that DW/DH characters will come out looking nice.)
2015-08-15 23:05:56 +03:00
x*inst->font_width+inst->window_border,
y*inst->font_height+inst->window_border,
rlen*widefactor*inst->font_width, true,
Refactor the GTK drawing system to do both GDK and Cairo. We're going to have to use Cairo in the GTK3 port, because that's all GTK3 supports; but we still need old-style GDK for GTK1 support, and also for performance reasons in GTK2 (see below). Hence, this change completely restructures GTK PuTTY's drawing code so that there's a central 'drawing context' structure which contains a type code indicating GDK or Cairo, and then either some GDK gubbins or some Cairo gubbins as appropriate; all actual drawing is abstracted through a set of routines which test the type code in that structure and do one thing or another. And because the type code is tested at run time, both sets of drawing primitives can be compiled in at once, and where possible, they will be. X server-side bitmap fonts are still supported in the Cairo world, but because Cairo drawing is entirely client-side, they have to work by cheekily downloading each glyph bitmap from the server when it's first needed, and building up a client-side cache of 'cairo_surface_t's containing the bitmaps with which we then draw on the window. This technique works, but it's rather slow; hence, even in GTK2, we keep the GDK drawing back end compiled in, and switch over to it when the main selected font is a bitmap one. One visible effect of the new Cairo routines is in the double-width and double-height text you can get by sending ESC # 3, ESC # 4 and ESC # 6 escape sequences. In GDK, that's always been done by a really horrible process of manually scaling the bitmap, server-side, column by column and row by row, causing each pixel to be exactly doubled or quadrupled. But in Cairo, we can just set a transformation matrix, and then that takes effect _before_ the scalable fonts are rendered - so the results are visibly nicer, and use all the available resolution. (Sadly, if you're using a server-side bitmap font as your primary one, then the GDK backend will be selected for all drawing in the terminal as a whole - so in that situation, even fallback characters absent from the primary font and rendered by Pango will get the old GDK scaling treatment. It's only if your main font is scalable, so that the Cairo backend is selected, that DW/DH characters will come out looking nice.)
2015-08-15 23:05:56 +03:00
inst->font_height,
((lattr & LATTR_MODE) != LATTR_WIDE),
((lattr & LATTR_MODE) == LATTR_BOT));
}
if (truecolour.bg.enabled)
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
draw_set_colour_rgb(inst, truecolour.bg, attr & ATTR_DIM);
else
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
draw_set_colour(inst, nbg, attr & ATTR_DIM);
draw_rectangle(inst, true,
Refactor the GTK drawing system to do both GDK and Cairo. We're going to have to use Cairo in the GTK3 port, because that's all GTK3 supports; but we still need old-style GDK for GTK1 support, and also for performance reasons in GTK2 (see below). Hence, this change completely restructures GTK PuTTY's drawing code so that there's a central 'drawing context' structure which contains a type code indicating GDK or Cairo, and then either some GDK gubbins or some Cairo gubbins as appropriate; all actual drawing is abstracted through a set of routines which test the type code in that structure and do one thing or another. And because the type code is tested at run time, both sets of drawing primitives can be compiled in at once, and where possible, they will be. X server-side bitmap fonts are still supported in the Cairo world, but because Cairo drawing is entirely client-side, they have to work by cheekily downloading each glyph bitmap from the server when it's first needed, and building up a client-side cache of 'cairo_surface_t's containing the bitmaps with which we then draw on the window. This technique works, but it's rather slow; hence, even in GTK2, we keep the GDK drawing back end compiled in, and switch over to it when the main selected font is a bitmap one. One visible effect of the new Cairo routines is in the double-width and double-height text you can get by sending ESC # 3, ESC # 4 and ESC # 6 escape sequences. In GDK, that's always been done by a really horrible process of manually scaling the bitmap, server-side, column by column and row by row, causing each pixel to be exactly doubled or quadrupled. But in Cairo, we can just set a transformation matrix, and then that takes effect _before_ the scalable fonts are rendered - so the results are visibly nicer, and use all the available resolution. (Sadly, if you're using a server-side bitmap font as your primary one, then the GDK backend will be selected for all drawing in the terminal as a whole - so in that situation, even fallback characters absent from the primary font and rendered by Pango will get the old GDK scaling treatment. It's only if your main font is scalable, so that the Cairo backend is selected, that DW/DH characters will come out looking nice.)
2015-08-15 23:05:56 +03:00
x*inst->font_width+inst->window_border,
y*inst->font_height+inst->window_border,
rlen*widefactor*inst->font_width, inst->font_height);
if (truecolour.fg.enabled)
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
draw_set_colour_rgb(inst, truecolour.fg, attr & ATTR_DIM);
else
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
draw_set_colour(inst, nfg, attr & ATTR_DIM);
if (ncombining > 1) {
assert(len == 1);
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
unifont_draw_combining(&inst->uctx, inst->fonts[fontid],
x*inst->font_width+inst->window_border,
(y*inst->font_height+inst->window_border+
inst->fonts[0]->ascent),
text, ncombining, widefactor > 1,
bold, inst->font_width);
} else {
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
unifont_draw_text(&inst->uctx, inst->fonts[fontid],
x*inst->font_width+inst->window_border,
(y*inst->font_height+inst->window_border+
inst->fonts[0]->ascent),
text, len, widefactor > 1,
bold, inst->font_width);
}
if (attr & ATTR_UNDER) {
int uheight = inst->fonts[0]->ascent + 1;
if (uheight >= inst->font_height)
uheight = inst->font_height - 1;
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
draw_line(inst, x*inst->font_width+inst->window_border,
Refactor the GTK drawing system to do both GDK and Cairo. We're going to have to use Cairo in the GTK3 port, because that's all GTK3 supports; but we still need old-style GDK for GTK1 support, and also for performance reasons in GTK2 (see below). Hence, this change completely restructures GTK PuTTY's drawing code so that there's a central 'drawing context' structure which contains a type code indicating GDK or Cairo, and then either some GDK gubbins or some Cairo gubbins as appropriate; all actual drawing is abstracted through a set of routines which test the type code in that structure and do one thing or another. And because the type code is tested at run time, both sets of drawing primitives can be compiled in at once, and where possible, they will be. X server-side bitmap fonts are still supported in the Cairo world, but because Cairo drawing is entirely client-side, they have to work by cheekily downloading each glyph bitmap from the server when it's first needed, and building up a client-side cache of 'cairo_surface_t's containing the bitmaps with which we then draw on the window. This technique works, but it's rather slow; hence, even in GTK2, we keep the GDK drawing back end compiled in, and switch over to it when the main selected font is a bitmap one. One visible effect of the new Cairo routines is in the double-width and double-height text you can get by sending ESC # 3, ESC # 4 and ESC # 6 escape sequences. In GDK, that's always been done by a really horrible process of manually scaling the bitmap, server-side, column by column and row by row, causing each pixel to be exactly doubled or quadrupled. But in Cairo, we can just set a transformation matrix, and then that takes effect _before_ the scalable fonts are rendered - so the results are visibly nicer, and use all the available resolution. (Sadly, if you're using a server-side bitmap font as your primary one, then the GDK backend will be selected for all drawing in the terminal as a whole - so in that situation, even fallback characters absent from the primary font and rendered by Pango will get the old GDK scaling treatment. It's only if your main font is scalable, so that the Cairo backend is selected, that DW/DH characters will come out looking nice.)
2015-08-15 23:05:56 +03:00
y*inst->font_height + uheight + inst->window_border,
(x+len)*widefactor*inst->font_width-1+inst->window_border,
y*inst->font_height + uheight + inst->window_border);
}
Re-engineering of terminal emulator, phase 1. The active terminal screen is no longer an array of `unsigned long' encoding 16-bit Unicode plus 16 attribute bits. Now it's an array of `termchar' structures, which currently have 32-bit Unicode and 32 attribute bits but which will probably expand further in future. To prevent bloat of the memory footprint, I've introduced a mostly RLE-like compression scheme for storing scrollback: each line is compressed into a compact (but hard to modify) form when it moves into the term->scrollback tree, and is temporarily decompressed when the user wants to scroll back over it. My initial tests suggest that this compression averages about 1/4 of the previous (32 bits per character cell) data size in typical output, which means this is an improvement even without counting the new ability to extend the information stored in each character cell. Another beneficial side effect is that the insane format in which Unicode was passed to front ends through do_text() has now been rendered sane. Testing is incomplete; this _may_ still have instabilities. Windows and Unix front ends both seem to work as far as I've looked, but I haven't yet looked very hard. The Mac front end I've edited (it seemed obvious how to change it) but I can't compile or test it. As an immediate functional effect, the terminal emulator now supports full 32-bit Unicode to whatever extent the host platform allows it to. For example, if you output a 4-or-more-byte UTF-8 character in Unix pterm, it will not display it properly, but it will correctly paste it back out in a UTF8_STRING selection. Windows is more restricted, sadly. [originally from svn r4609]
2004-10-13 15:50:16 +04:00
if ((lattr & LATTR_MODE) != LATTR_NORM) {
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
draw_stretch_after(inst,
Refactor the GTK drawing system to do both GDK and Cairo. We're going to have to use Cairo in the GTK3 port, because that's all GTK3 supports; but we still need old-style GDK for GTK1 support, and also for performance reasons in GTK2 (see below). Hence, this change completely restructures GTK PuTTY's drawing code so that there's a central 'drawing context' structure which contains a type code indicating GDK or Cairo, and then either some GDK gubbins or some Cairo gubbins as appropriate; all actual drawing is abstracted through a set of routines which test the type code in that structure and do one thing or another. And because the type code is tested at run time, both sets of drawing primitives can be compiled in at once, and where possible, they will be. X server-side bitmap fonts are still supported in the Cairo world, but because Cairo drawing is entirely client-side, they have to work by cheekily downloading each glyph bitmap from the server when it's first needed, and building up a client-side cache of 'cairo_surface_t's containing the bitmaps with which we then draw on the window. This technique works, but it's rather slow; hence, even in GTK2, we keep the GDK drawing back end compiled in, and switch over to it when the main selected font is a bitmap one. One visible effect of the new Cairo routines is in the double-width and double-height text you can get by sending ESC # 3, ESC # 4 and ESC # 6 escape sequences. In GDK, that's always been done by a really horrible process of manually scaling the bitmap, server-side, column by column and row by row, causing each pixel to be exactly doubled or quadrupled. But in Cairo, we can just set a transformation matrix, and then that takes effect _before_ the scalable fonts are rendered - so the results are visibly nicer, and use all the available resolution. (Sadly, if you're using a server-side bitmap font as your primary one, then the GDK backend will be selected for all drawing in the terminal as a whole - so in that situation, even fallback characters absent from the primary font and rendered by Pango will get the old GDK scaling treatment. It's only if your main font is scalable, so that the Cairo backend is selected, that DW/DH characters will come out looking nice.)
2015-08-15 23:05:56 +03:00
x*inst->font_width+inst->window_border,
y*inst->font_height+inst->window_border,
rlen*widefactor*inst->font_width, true,
Refactor the GTK drawing system to do both GDK and Cairo. We're going to have to use Cairo in the GTK3 port, because that's all GTK3 supports; but we still need old-style GDK for GTK1 support, and also for performance reasons in GTK2 (see below). Hence, this change completely restructures GTK PuTTY's drawing code so that there's a central 'drawing context' structure which contains a type code indicating GDK or Cairo, and then either some GDK gubbins or some Cairo gubbins as appropriate; all actual drawing is abstracted through a set of routines which test the type code in that structure and do one thing or another. And because the type code is tested at run time, both sets of drawing primitives can be compiled in at once, and where possible, they will be. X server-side bitmap fonts are still supported in the Cairo world, but because Cairo drawing is entirely client-side, they have to work by cheekily downloading each glyph bitmap from the server when it's first needed, and building up a client-side cache of 'cairo_surface_t's containing the bitmaps with which we then draw on the window. This technique works, but it's rather slow; hence, even in GTK2, we keep the GDK drawing back end compiled in, and switch over to it when the main selected font is a bitmap one. One visible effect of the new Cairo routines is in the double-width and double-height text you can get by sending ESC # 3, ESC # 4 and ESC # 6 escape sequences. In GDK, that's always been done by a really horrible process of manually scaling the bitmap, server-side, column by column and row by row, causing each pixel to be exactly doubled or quadrupled. But in Cairo, we can just set a transformation matrix, and then that takes effect _before_ the scalable fonts are rendered - so the results are visibly nicer, and use all the available resolution. (Sadly, if you're using a server-side bitmap font as your primary one, then the GDK backend will be selected for all drawing in the terminal as a whole - so in that situation, even fallback characters absent from the primary font and rendered by Pango will get the old GDK scaling treatment. It's only if your main font is scalable, so that the Cairo backend is selected, that DW/DH characters will come out looking nice.)
2015-08-15 23:05:56 +03:00
inst->font_height,
((lattr & LATTR_MODE) != LATTR_WIDE),
((lattr & LATTR_MODE) == LATTR_BOT));
}
}
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
static void gtkwin_draw_text(
TermWin *tw, int x, int y, wchar_t *text, int len,
unsigned long attr, int lattr, truecolour truecolour)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = container_of(tw, GtkFrontend, termwin);
int widefactor;
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
do_text_internal(inst, x, y, text, len, attr, lattr, truecolour);
if (attr & ATTR_WIDE) {
widefactor = 2;
} else {
widefactor = 1;
}
Re-engineering of terminal emulator, phase 1. The active terminal screen is no longer an array of `unsigned long' encoding 16-bit Unicode plus 16 attribute bits. Now it's an array of `termchar' structures, which currently have 32-bit Unicode and 32 attribute bits but which will probably expand further in future. To prevent bloat of the memory footprint, I've introduced a mostly RLE-like compression scheme for storing scrollback: each line is compressed into a compact (but hard to modify) form when it moves into the term->scrollback tree, and is temporarily decompressed when the user wants to scroll back over it. My initial tests suggest that this compression averages about 1/4 of the previous (32 bits per character cell) data size in typical output, which means this is an improvement even without counting the new ability to extend the information stored in each character cell. Another beneficial side effect is that the insane format in which Unicode was passed to front ends through do_text() has now been rendered sane. Testing is incomplete; this _may_ still have instabilities. Windows and Unix front ends both seem to work as far as I've looked, but I haven't yet looked very hard. The Mac front end I've edited (it seemed obvious how to change it) but I can't compile or test it. As an immediate functional effect, the terminal emulator now supports full 32-bit Unicode to whatever extent the host platform allows it to. For example, if you output a 4-or-more-byte UTF-8 character in Unix pterm, it will not display it properly, but it will correctly paste it back out in a UTF8_STRING selection. Windows is more restricted, sadly. [originally from svn r4609]
2004-10-13 15:50:16 +04:00
if ((lattr & LATTR_MODE) != LATTR_NORM) {
x *= 2;
if (x >= inst->term->cols)
return;
if (x + len*2*widefactor > inst->term->cols)
len = (inst->term->cols-x)/2/widefactor;/* trim to LH half */
len *= 2;
}
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
draw_update(inst,
Refactor the GTK drawing system to do both GDK and Cairo. We're going to have to use Cairo in the GTK3 port, because that's all GTK3 supports; but we still need old-style GDK for GTK1 support, and also for performance reasons in GTK2 (see below). Hence, this change completely restructures GTK PuTTY's drawing code so that there's a central 'drawing context' structure which contains a type code indicating GDK or Cairo, and then either some GDK gubbins or some Cairo gubbins as appropriate; all actual drawing is abstracted through a set of routines which test the type code in that structure and do one thing or another. And because the type code is tested at run time, both sets of drawing primitives can be compiled in at once, and where possible, they will be. X server-side bitmap fonts are still supported in the Cairo world, but because Cairo drawing is entirely client-side, they have to work by cheekily downloading each glyph bitmap from the server when it's first needed, and building up a client-side cache of 'cairo_surface_t's containing the bitmaps with which we then draw on the window. This technique works, but it's rather slow; hence, even in GTK2, we keep the GDK drawing back end compiled in, and switch over to it when the main selected font is a bitmap one. One visible effect of the new Cairo routines is in the double-width and double-height text you can get by sending ESC # 3, ESC # 4 and ESC # 6 escape sequences. In GDK, that's always been done by a really horrible process of manually scaling the bitmap, server-side, column by column and row by row, causing each pixel to be exactly doubled or quadrupled. But in Cairo, we can just set a transformation matrix, and then that takes effect _before_ the scalable fonts are rendered - so the results are visibly nicer, and use all the available resolution. (Sadly, if you're using a server-side bitmap font as your primary one, then the GDK backend will be selected for all drawing in the terminal as a whole - so in that situation, even fallback characters absent from the primary font and rendered by Pango will get the old GDK scaling treatment. It's only if your main font is scalable, so that the Cairo backend is selected, that DW/DH characters will come out looking nice.)
2015-08-15 23:05:56 +03:00
x*inst->font_width+inst->window_border,
y*inst->font_height+inst->window_border,
len*widefactor*inst->font_width, inst->font_height);
}
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
static void gtkwin_draw_cursor(
TermWin *tw, int x, int y, wchar_t *text, int len,
unsigned long attr, int lattr, truecolour truecolour)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = container_of(tw, GtkFrontend, termwin);
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
bool active, passive;
int widefactor;
if (attr & TATTR_PASCURS) {
attr &= ~TATTR_PASCURS;
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
passive = true;
} else
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
passive = false;
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
if ((attr & TATTR_ACTCURS) && inst->cursor_type != 0) {
attr &= ~TATTR_ACTCURS;
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
active = true;
} else
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
active = false;
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
do_text_internal(inst, x, y, text, len, attr, lattr, truecolour);
if (attr & TATTR_COMBINING)
len = 1;
if (attr & ATTR_WIDE) {
widefactor = 2;
} else {
widefactor = 1;
}
Re-engineering of terminal emulator, phase 1. The active terminal screen is no longer an array of `unsigned long' encoding 16-bit Unicode plus 16 attribute bits. Now it's an array of `termchar' structures, which currently have 32-bit Unicode and 32 attribute bits but which will probably expand further in future. To prevent bloat of the memory footprint, I've introduced a mostly RLE-like compression scheme for storing scrollback: each line is compressed into a compact (but hard to modify) form when it moves into the term->scrollback tree, and is temporarily decompressed when the user wants to scroll back over it. My initial tests suggest that this compression averages about 1/4 of the previous (32 bits per character cell) data size in typical output, which means this is an improvement even without counting the new ability to extend the information stored in each character cell. Another beneficial side effect is that the insane format in which Unicode was passed to front ends through do_text() has now been rendered sane. Testing is incomplete; this _may_ still have instabilities. Windows and Unix front ends both seem to work as far as I've looked, but I haven't yet looked very hard. The Mac front end I've edited (it seemed obvious how to change it) but I can't compile or test it. As an immediate functional effect, the terminal emulator now supports full 32-bit Unicode to whatever extent the host platform allows it to. For example, if you output a 4-or-more-byte UTF-8 character in Unix pterm, it will not display it properly, but it will correctly paste it back out in a UTF8_STRING selection. Windows is more restricted, sadly. [originally from svn r4609]
2004-10-13 15:50:16 +04:00
if ((lattr & LATTR_MODE) != LATTR_NORM) {
x *= 2;
if (x >= inst->term->cols)
return;
if (x + len*2*widefactor > inst->term->cols)
len = (inst->term->cols-x)/2/widefactor;/* trim to LH half */
len *= 2;
}
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
if (inst->cursor_type == 0) {
/*
* An active block cursor will already have been done by
* the above do_text call, so we only need to do anything
* if it's passive.
*/
if (passive) {
draw_set_colour(inst, 261, false);
draw_rectangle(inst, false,
Refactor the GTK drawing system to do both GDK and Cairo. We're going to have to use Cairo in the GTK3 port, because that's all GTK3 supports; but we still need old-style GDK for GTK1 support, and also for performance reasons in GTK2 (see below). Hence, this change completely restructures GTK PuTTY's drawing code so that there's a central 'drawing context' structure which contains a type code indicating GDK or Cairo, and then either some GDK gubbins or some Cairo gubbins as appropriate; all actual drawing is abstracted through a set of routines which test the type code in that structure and do one thing or another. And because the type code is tested at run time, both sets of drawing primitives can be compiled in at once, and where possible, they will be. X server-side bitmap fonts are still supported in the Cairo world, but because Cairo drawing is entirely client-side, they have to work by cheekily downloading each glyph bitmap from the server when it's first needed, and building up a client-side cache of 'cairo_surface_t's containing the bitmaps with which we then draw on the window. This technique works, but it's rather slow; hence, even in GTK2, we keep the GDK drawing back end compiled in, and switch over to it when the main selected font is a bitmap one. One visible effect of the new Cairo routines is in the double-width and double-height text you can get by sending ESC # 3, ESC # 4 and ESC # 6 escape sequences. In GDK, that's always been done by a really horrible process of manually scaling the bitmap, server-side, column by column and row by row, causing each pixel to be exactly doubled or quadrupled. But in Cairo, we can just set a transformation matrix, and then that takes effect _before_ the scalable fonts are rendered - so the results are visibly nicer, and use all the available resolution. (Sadly, if you're using a server-side bitmap font as your primary one, then the GDK backend will be selected for all drawing in the terminal as a whole - so in that situation, even fallback characters absent from the primary font and rendered by Pango will get the old GDK scaling treatment. It's only if your main font is scalable, so that the Cairo backend is selected, that DW/DH characters will come out looking nice.)
2015-08-15 23:05:56 +03:00
x*inst->font_width+inst->window_border,
y*inst->font_height+inst->window_border,
len*widefactor*inst->font_width-1,
inst->font_height-1);
}
} else {
int uheight;
int startx, starty, dx, dy, length, i;
int char_width;
Re-engineering of terminal emulator, phase 1. The active terminal screen is no longer an array of `unsigned long' encoding 16-bit Unicode plus 16 attribute bits. Now it's an array of `termchar' structures, which currently have 32-bit Unicode and 32 attribute bits but which will probably expand further in future. To prevent bloat of the memory footprint, I've introduced a mostly RLE-like compression scheme for storing scrollback: each line is compressed into a compact (but hard to modify) form when it moves into the term->scrollback tree, and is temporarily decompressed when the user wants to scroll back over it. My initial tests suggest that this compression averages about 1/4 of the previous (32 bits per character cell) data size in typical output, which means this is an improvement even without counting the new ability to extend the information stored in each character cell. Another beneficial side effect is that the insane format in which Unicode was passed to front ends through do_text() has now been rendered sane. Testing is incomplete; this _may_ still have instabilities. Windows and Unix front ends both seem to work as far as I've looked, but I haven't yet looked very hard. The Mac front end I've edited (it seemed obvious how to change it) but I can't compile or test it. As an immediate functional effect, the terminal emulator now supports full 32-bit Unicode to whatever extent the host platform allows it to. For example, if you output a 4-or-more-byte UTF-8 character in Unix pterm, it will not display it properly, but it will correctly paste it back out in a UTF8_STRING selection. Windows is more restricted, sadly. [originally from svn r4609]
2004-10-13 15:50:16 +04:00
if ((attr & ATTR_WIDE) || (lattr & LATTR_MODE) != LATTR_NORM)
char_width = 2*inst->font_width;
else
char_width = inst->font_width;
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
if (inst->cursor_type == 1) {
uheight = inst->fonts[0]->ascent + 1;
if (uheight >= inst->font_height)
uheight = inst->font_height - 1;
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
startx = x * inst->font_width + inst->window_border;
starty = y * inst->font_height + inst->window_border + uheight;
dx = 1;
dy = 0;
length = len * widefactor * char_width;
} else {
int xadjust = 0;
if (attr & TATTR_RIGHTCURS)
xadjust = char_width - 1;
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
startx = x * inst->font_width + inst->window_border + xadjust;
starty = y * inst->font_height + inst->window_border;
dx = 0;
dy = 1;
length = inst->font_height;
}
draw_set_colour(inst, 261, false);
if (passive) {
for (i = 0; i < length; i++) {
if (i % 2 == 0) {
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
draw_point(inst, startx, starty);
}
startx += dx;
starty += dy;
}
} else if (active) {
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
draw_line(inst, startx, starty,
Refactor the GTK drawing system to do both GDK and Cairo. We're going to have to use Cairo in the GTK3 port, because that's all GTK3 supports; but we still need old-style GDK for GTK1 support, and also for performance reasons in GTK2 (see below). Hence, this change completely restructures GTK PuTTY's drawing code so that there's a central 'drawing context' structure which contains a type code indicating GDK or Cairo, and then either some GDK gubbins or some Cairo gubbins as appropriate; all actual drawing is abstracted through a set of routines which test the type code in that structure and do one thing or another. And because the type code is tested at run time, both sets of drawing primitives can be compiled in at once, and where possible, they will be. X server-side bitmap fonts are still supported in the Cairo world, but because Cairo drawing is entirely client-side, they have to work by cheekily downloading each glyph bitmap from the server when it's first needed, and building up a client-side cache of 'cairo_surface_t's containing the bitmaps with which we then draw on the window. This technique works, but it's rather slow; hence, even in GTK2, we keep the GDK drawing back end compiled in, and switch over to it when the main selected font is a bitmap one. One visible effect of the new Cairo routines is in the double-width and double-height text you can get by sending ESC # 3, ESC # 4 and ESC # 6 escape sequences. In GDK, that's always been done by a really horrible process of manually scaling the bitmap, server-side, column by column and row by row, causing each pixel to be exactly doubled or quadrupled. But in Cairo, we can just set a transformation matrix, and then that takes effect _before_ the scalable fonts are rendered - so the results are visibly nicer, and use all the available resolution. (Sadly, if you're using a server-side bitmap font as your primary one, then the GDK backend will be selected for all drawing in the terminal as a whole - so in that situation, even fallback characters absent from the primary font and rendered by Pango will get the old GDK scaling treatment. It's only if your main font is scalable, so that the Cairo backend is selected, that DW/DH characters will come out looking nice.)
2015-08-15 23:05:56 +03:00
startx + (length-1) * dx, starty + (length-1) * dy);
} /* else no cursor (e.g., blinked off) */
}
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
draw_update(inst,
Refactor the GTK drawing system to do both GDK and Cairo. We're going to have to use Cairo in the GTK3 port, because that's all GTK3 supports; but we still need old-style GDK for GTK1 support, and also for performance reasons in GTK2 (see below). Hence, this change completely restructures GTK PuTTY's drawing code so that there's a central 'drawing context' structure which contains a type code indicating GDK or Cairo, and then either some GDK gubbins or some Cairo gubbins as appropriate; all actual drawing is abstracted through a set of routines which test the type code in that structure and do one thing or another. And because the type code is tested at run time, both sets of drawing primitives can be compiled in at once, and where possible, they will be. X server-side bitmap fonts are still supported in the Cairo world, but because Cairo drawing is entirely client-side, they have to work by cheekily downloading each glyph bitmap from the server when it's first needed, and building up a client-side cache of 'cairo_surface_t's containing the bitmaps with which we then draw on the window. This technique works, but it's rather slow; hence, even in GTK2, we keep the GDK drawing back end compiled in, and switch over to it when the main selected font is a bitmap one. One visible effect of the new Cairo routines is in the double-width and double-height text you can get by sending ESC # 3, ESC # 4 and ESC # 6 escape sequences. In GDK, that's always been done by a really horrible process of manually scaling the bitmap, server-side, column by column and row by row, causing each pixel to be exactly doubled or quadrupled. But in Cairo, we can just set a transformation matrix, and then that takes effect _before_ the scalable fonts are rendered - so the results are visibly nicer, and use all the available resolution. (Sadly, if you're using a server-side bitmap font as your primary one, then the GDK backend will be selected for all drawing in the terminal as a whole - so in that situation, even fallback characters absent from the primary font and rendered by Pango will get the old GDK scaling treatment. It's only if your main font is scalable, so that the Cairo backend is selected, that DW/DH characters will come out looking nice.)
2015-08-15 23:05:56 +03:00
x*inst->font_width+inst->window_border,
y*inst->font_height+inst->window_border,
len*widefactor*inst->font_width, inst->font_height);
#if GTK_CHECK_VERSION(2,0,0)
{
GdkRectangle cursorrect;
cursorrect.x = x*inst->font_width+inst->window_border;
cursorrect.y = y*inst->font_height+inst->window_border;
cursorrect.width = len*widefactor*inst->font_width;
cursorrect.height = inst->font_height;
gtk_im_context_set_cursor_location(inst->imc, &cursorrect);
}
#endif
}
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GdkCursor *make_mouse_ptr(GtkFrontend *inst, int cursor_val)
{
if (cursor_val == -1) {
#if GTK_CHECK_VERSION(2,16,0)
cursor_val = GDK_BLANK_CURSOR;
#else
/*
* Work around absence of GDK_BLANK_CURSOR by inventing a
* blank pixmap.
*/
GdkCursor *ret;
GdkColor bg = { 0, 0, 0, 0 };
GdkPixmap *pm = gdk_pixmap_new(NULL, 1, 1, 1);
GdkGC *gc = gdk_gc_new(pm);
gdk_gc_set_foreground(gc, &bg);
gdk_draw_rectangle(pm, gc, 1, 0, 0, 1, 1);
gdk_gc_unref(gc);
ret = gdk_cursor_new_from_pixmap(pm, pm, &bg, &bg, 1, 1);
gdk_pixmap_unref(pm);
return ret;
#endif
}
return gdk_cursor_new(cursor_val);
}
void modalfatalbox(const char *p, ...)
{
va_list ap;
fprintf(stderr, "FATAL ERROR: ");
va_start(ap, p);
vfprintf(stderr, p, ap);
va_end(ap);
fputc('\n', stderr);
exit(1);
}
New abstraction 'Seat', to pass to backends. This is a new vtable-based abstraction which is passed to a backend in place of Frontend, and it implements only the subset of the Frontend functions needed by a backend. (Many other Frontend functions still exist, notably the wide range of things called by terminal.c providing platform-independent operations on the GUI terminal window.) The purpose of making it a vtable is that this opens up the possibility of creating a backend as an internal implementation detail of some other activity, by providing just that one backend with a custom Seat that implements the methods differently. For example, this refactoring should make it feasible to directly implement an SSH proxy type, aka the 'jump host' feature supported by OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP mode, and then expose the main channel of that as the Socket for the primary connection'. (Which of course you can already do by spawning 'plink -nc' as a separate proxy process, but this would permit it in the _same_ process without anything getting confused.) I've centralised a full set of stub methods in misc.c for the new abstraction, which allows me to get rid of several annoying stubs in the previous code. Also, while I'm here, I've moved a lot of duplicated modalfatalbox() type functions from application main program files into wincons.c / uxcons.c, which I think saves duplication overall. (A minor visible effect is that the prefixes on those console-based fatal error messages will now be more consistent between applications.)
2018-10-11 21:58:42 +03:00
static const char *gtk_seat_get_x_display(Seat *seat)
{
return gdk_get_display();
}
#ifndef NOT_X_WINDOWS
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
static bool gtk_seat_get_windowid(Seat *seat, long *id)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = container_of(seat, GtkFrontend, seat);
Basic support for running under GDK Wayland back end. GTK 3 PuTTY/pterm has always assumed that if it was compiled with _support_ for talking to the raw X11 layer underneath GTK and GDK, then it was entitled to expect that raw X11 layer to exist at all times, i.e. that GDK_DISPLAY_XDISPLAY would return a meaningful X display that it could do useful things with. So if you ran it over the GDK Wayland backend, it would immediately segfault. Modern GTK applications need to cope with multiple GDK backends at run time. It's fine for GTK PuTTY to _contain_ the code to find and use underlying X11 primitives like the display and the X window id, but it should be prepared to find that it's running on Wayland (or something else again!) so those functions don't return anything useful - in which case it should degrade gracefully to the subset of functionality that can be accessed through backend-independent GTK calls. Accordingly, I've centralised the use of GDK_DISPLAY_XDISPLAY into a support function get_x_display() in gtkmisc.c, which starts by checking that there actually is one first. All previous direct uses of GDK_*_XDISPLAY now go via that function, and check the result for NULL afterwards. (To save faffing about calling that function too many times, I'm also caching the display pointer in more places, and passing it as an extra argument to various subfunctions, mostly in gtkfont.c.) Similarly, the get_windowid() function that retrieves the window id to put in the environment of pterm's child process has to be prepared for there not to be a window id. This isn't a complete fix for all Wayland-related problems. The other one I'm currently aware of is that the default font is "server:fixed", which is a bad default now that it won't be available on all backends. And I expect that further problems will show up with more testing. But it's a start.
2018-05-09 11:18:20 +03:00
GdkWindow *window = gtk_widget_get_window(inst->area);
if (!GDK_IS_X11_WINDOW(window))
return false;
Basic support for running under GDK Wayland back end. GTK 3 PuTTY/pterm has always assumed that if it was compiled with _support_ for talking to the raw X11 layer underneath GTK and GDK, then it was entitled to expect that raw X11 layer to exist at all times, i.e. that GDK_DISPLAY_XDISPLAY would return a meaningful X display that it could do useful things with. So if you ran it over the GDK Wayland backend, it would immediately segfault. Modern GTK applications need to cope with multiple GDK backends at run time. It's fine for GTK PuTTY to _contain_ the code to find and use underlying X11 primitives like the display and the X window id, but it should be prepared to find that it's running on Wayland (or something else again!) so those functions don't return anything useful - in which case it should degrade gracefully to the subset of functionality that can be accessed through backend-independent GTK calls. Accordingly, I've centralised the use of GDK_DISPLAY_XDISPLAY into a support function get_x_display() in gtkmisc.c, which starts by checking that there actually is one first. All previous direct uses of GDK_*_XDISPLAY now go via that function, and check the result for NULL afterwards. (To save faffing about calling that function too many times, I'm also caching the display pointer in more places, and passing it as an extra argument to various subfunctions, mostly in gtkfont.c.) Similarly, the get_windowid() function that retrieves the window id to put in the environment of pterm's child process has to be prepared for there not to be a window id. This isn't a complete fix for all Wayland-related problems. The other one I'm currently aware of is that the default font is "server:fixed", which is a bad default now that it won't be available on all backends. And I expect that further problems will show up with more testing. But it's a start.
2018-05-09 11:18:20 +03:00
*id = GDK_WINDOW_XID(window);
return true;
}
#endif
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
static bool gtkwin_is_utf8(TermWin *tw)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = container_of(tw, GtkFrontend, termwin);
return inst->ucsdata.line_codepage == CS_UTF8;
}
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
char *setup_fonts_ucs(GtkFrontend *inst)
{
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
bool shadowbold = conf_get_bool(inst->conf, CONF_shadowbold);
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
int shadowboldoffset = conf_get_int(inst->conf, CONF_shadowboldoffset);
FontSpec *fs;
unifont *fonts[4];
int i;
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
fs = conf_get_fontspec(inst->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);
}
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
fs = conf_get_fontspec(inst->conf, CONF_boldfont);
if (shadowbold || !fs->name[0]) {
fonts[1] = NULL;
} else {
fonts[1] = multifont_create(inst->area, fs->name, false, true,
shadowboldoffset, shadowbold);
if (!fonts[1]) {
if (fonts[0])
unifont_destroy(fonts[0]);
return dupprintf("unable to load bold font \"%s\"", fs->name);
}
}
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
fs = conf_get_fontspec(inst->conf, CONF_widefont);
if (fs->name[0]) {
fonts[2] = multifont_create(inst->area, fs->name, true, false,
shadowboldoffset, shadowbold);
if (!fonts[2]) {
for (i = 0; i < 2; i++)
if (fonts[i])
unifont_destroy(fonts[i]);
return dupprintf("unable to load wide font \"%s\"", fs->name);
}
} else {
fonts[2] = NULL;
}
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
fs = conf_get_fontspec(inst->conf, CONF_wideboldfont);
if (shadowbold || !fs->name[0]) {
fonts[3] = NULL;
} else {
fonts[3] = multifont_create(inst->area, fs->name, true, true,
shadowboldoffset, shadowbold);
if (!fonts[3]) {
for (i = 0; i < 3; i++)
if (fonts[i])
unifont_destroy(fonts[i]);
return dupprintf("unable to load wide bold font \"%s\"", fs->name);
}
}
/*
* Now we've got past all the possible error conditions, we can
* actually update our state.
*/
for (i = 0; i < 4; i++) {
if (inst->fonts[i])
unifont_destroy(inst->fonts[i]);
inst->fonts[i] = fonts[i];
}
if (inst->font_width != inst->fonts[0]->width ||
inst->font_height != inst->fonts[0]->height) {
inst->font_width = inst->fonts[0]->width;
inst->font_height = inst->fonts[0]->height;
/*
* The font size has changed, so force the next call to
* drawing_area_setup to regenerate the backing surface.
*/
inst->drawing_area_setup_needed = true;
}
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
inst->direct_to_font = init_ucs(&inst->ucsdata,
conf_get_str(inst->conf, CONF_line_codepage),
conf_get_bool(inst->conf, CONF_utf8_override),
inst->fonts[0]->public_charset,
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
conf_get_int(inst->conf, CONF_vtmode));
Refactor the GTK drawing system to do both GDK and Cairo. We're going to have to use Cairo in the GTK3 port, because that's all GTK3 supports; but we still need old-style GDK for GTK1 support, and also for performance reasons in GTK2 (see below). Hence, this change completely restructures GTK PuTTY's drawing code so that there's a central 'drawing context' structure which contains a type code indicating GDK or Cairo, and then either some GDK gubbins or some Cairo gubbins as appropriate; all actual drawing is abstracted through a set of routines which test the type code in that structure and do one thing or another. And because the type code is tested at run time, both sets of drawing primitives can be compiled in at once, and where possible, they will be. X server-side bitmap fonts are still supported in the Cairo world, but because Cairo drawing is entirely client-side, they have to work by cheekily downloading each glyph bitmap from the server when it's first needed, and building up a client-side cache of 'cairo_surface_t's containing the bitmaps with which we then draw on the window. This technique works, but it's rather slow; hence, even in GTK2, we keep the GDK drawing back end compiled in, and switch over to it when the main selected font is a bitmap one. One visible effect of the new Cairo routines is in the double-width and double-height text you can get by sending ESC # 3, ESC # 4 and ESC # 6 escape sequences. In GDK, that's always been done by a really horrible process of manually scaling the bitmap, server-side, column by column and row by row, causing each pixel to be exactly doubled or quadrupled. But in Cairo, we can just set a transformation matrix, and then that takes effect _before_ the scalable fonts are rendered - so the results are visibly nicer, and use all the available resolution. (Sadly, if you're using a server-side bitmap font as your primary one, then the GDK backend will be selected for all drawing in the terminal as a whole - so in that situation, even fallback characters absent from the primary font and rendered by Pango will get the old GDK scaling treatment. It's only if your main font is scalable, so that the Cairo backend is selected, that DW/DH characters will come out looking nice.)
2015-08-15 23:05:56 +03:00
inst->drawtype = inst->fonts[0]->preferred_drawtype;
return NULL;
}
#if GTK_CHECK_VERSION(3,0,0)
struct find_app_menu_bar_ctx {
GtkWidget *area, *menubar;
};
static void find_app_menu_bar(GtkWidget *widget, gpointer data)
{
struct find_app_menu_bar_ctx *ctx = (struct find_app_menu_bar_ctx *)data;
if (widget != ctx->area && GTK_IS_MENU_BAR(widget))
ctx->menubar = widget;
}
#endif
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
static void compute_geom_hints(GtkFrontend *inst, GdkGeometry *geom)
{
/*
* Unused fields in geom.
*/
geom->max_width = geom->max_height = -1;
geom->min_aspect = geom->max_aspect = 0;
/*
* Set up the geometry fields we care about, with reference to
* just the drawing area. We'll correct for other widgets in a
* moment.
*/
geom->min_width = inst->font_width + 2*inst->window_border;
geom->min_height = inst->font_height + 2*inst->window_border;
geom->base_width = 2*inst->window_border;
geom->base_height = 2*inst->window_border;
geom->width_inc = inst->font_width;
geom->height_inc = inst->font_height;
/*
* If we've got a scrollbar visible, then we must include its
* width as part of the base and min width, and also ensure that
* our window's minimum height is at least the height required by
* the scrollbar.
*
* In the latter case, we must also take care to arrange that
* (geom->min_height - geom->base_height) is an integer multiple of
* geom->height_inc, because if it's not, then some window managers
* (we know of xfwm4) get confused, with the effect that they
* resize our window to a height based on min_height instead of
* base_height, which we then round down and the window ends up
* too short.
*/
if (inst->sbar_visible) {
GtkRequisition req;
int min_sb_height;
#if GTK_CHECK_VERSION(3,0,0)
gtk_widget_get_preferred_size(inst->sbar, &req, NULL);
#else
gtk_widget_size_request(inst->sbar, &req);
#endif
/* Compute rounded-up scrollbar height. */
min_sb_height = req.height;
min_sb_height += geom->height_inc - 1;
min_sb_height -= ((min_sb_height - geom->base_height%geom->height_inc)
% geom->height_inc);
geom->min_width += req.width;
geom->base_width += req.width;
if (geom->min_height < min_sb_height)
geom->min_height = min_sb_height;
}
#if GTK_CHECK_VERSION(3,0,0)
/*
* And if we're running a gtkapp.c based program and
* GtkApplicationWindow has given us a menu bar inside the window,
* then we must take that into account as well.
*
* In its unbounded wisdom, GtkApplicationWindow doesn't actually
* give us a direct function call to _find_ the menu bar widget.
* Fortunately, we can find it by enumerating the children of the
* top-level window and looking for one we didn't put there
* ourselves.
*/
{
struct find_app_menu_bar_ctx actx, *ctx = &actx;
ctx->area = inst->area;
ctx->menubar = NULL;
gtk_container_foreach(GTK_CONTAINER(inst->window),
find_app_menu_bar, ctx);
if (ctx->menubar) {
GtkRequisition req;
int min_menu_width;
gtk_widget_get_preferred_size(ctx->menubar, NULL, &req);
/*
* This time, the height adjustment is easy (the menu bar
* sits above everything), but we have to take care with
* the _width_ to ensure we keep min_width and base_width
* congruent modulo width_inc.
*/
geom->min_height += req.height;
geom->base_height += req.height;
min_menu_width = req.width;
min_menu_width += geom->width_inc - 1;
min_menu_width -=
((min_menu_width - geom->base_width%geom->width_inc)
% geom->width_inc);
if (geom->min_width < min_menu_width)
geom->min_width = min_menu_width;
}
}
#endif
}
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
void set_geom_hints(GtkFrontend *inst)
{
GdkGeometry geom;
gint flags = GDK_HINT_MIN_SIZE | GDK_HINT_BASE_SIZE | GDK_HINT_RESIZE_INC;
compute_geom_hints(inst, &geom);
#if GTK_CHECK_VERSION(2,0,0)
if (inst->gotpos)
flags |= GDK_HINT_USER_POS;
#endif
gtk_window_set_geometry_hints(GTK_WINDOW(inst->window),
NULL, &geom, flags);
}
#if GTK_CHECK_VERSION(2,0,0)
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
static void compute_whole_window_size(GtkFrontend *inst,
int wchars, int hchars,
int *wpix, int *hpix)
{
GdkGeometry geom;
compute_geom_hints(inst, &geom);
if (wpix) *wpix = geom.base_width + wchars * geom.width_inc;
if (hpix) *hpix = geom.base_height + hchars * geom.height_inc;
}
#endif
void clear_scrollback_menuitem(GtkMenuItem *item, gpointer data)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = (GtkFrontend *)data;
term_clrsb(inst->term);
}
void reset_terminal_menuitem(GtkMenuItem *item, gpointer data)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = (GtkFrontend *)data;
term_pwron(inst->term, true);
if (inst->ldisc)
ldisc_echoedit_update(inst->ldisc);
}
void copy_clipboard_menuitem(GtkMenuItem *item, gpointer data)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = (GtkFrontend *)data;
static const int clips[] = { MENU_CLIPBOARD };
term_request_copy(inst->term, clips, lenof(clips));
}
void paste_clipboard_menuitem(GtkMenuItem *item, gpointer data)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = (GtkFrontend *)data;
term_request_paste(inst->term, MENU_CLIPBOARD);
}
void copy_all_menuitem(GtkMenuItem *item, gpointer data)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = (GtkFrontend *)data;
static const int clips[] = { COPYALL_CLIPBOARDS };
term_copyall(inst->term, clips, lenof(clips));
}
void special_menuitem(GtkMenuItem *item, gpointer data)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = (GtkFrontend *)data;
SessionSpecial *sc = g_object_get_data(G_OBJECT(item), "user-data");
if (inst->backend)
backend_special(inst->backend, sc->code, sc->arg);
}
void about_menuitem(GtkMenuItem *item, gpointer data)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = (GtkFrontend *)data;
about_box(inst->window);
}
void event_log_menuitem(GtkMenuItem *item, gpointer data)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = (GtkFrontend *)data;
showeventlog(inst->eventlogstuff, inst->window);
}
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
void setup_clipboards(GtkFrontend *inst, Terminal *term, Conf *conf)
{
assert(term->mouse_select_clipboards[0] == CLIP_LOCAL);
term->n_mouse_select_clipboards = 1;
term->mouse_select_clipboards[
term->n_mouse_select_clipboards++] = MOUSE_SELECT_CLIPBOARD;
if (conf_get_bool(conf, CONF_mouseautocopy)) {
term->mouse_select_clipboards[
term->n_mouse_select_clipboards++] = CLIP_CLIPBOARD;
}
set_clipboard_atom(inst, CLIP_CUSTOM_1, GDK_NONE);
set_clipboard_atom(inst, CLIP_CUSTOM_2, GDK_NONE);
set_clipboard_atom(inst, CLIP_CUSTOM_3, GDK_NONE);
switch (conf_get_int(conf, CONF_mousepaste)) {
case CLIPUI_IMPLICIT:
term->mouse_paste_clipboard = MOUSE_PASTE_CLIPBOARD;
break;
case CLIPUI_EXPLICIT:
term->mouse_paste_clipboard = CLIP_CLIPBOARD;
break;
case CLIPUI_CUSTOM:
term->mouse_paste_clipboard = CLIP_CUSTOM_1;
set_clipboard_atom(inst, CLIP_CUSTOM_1,
gdk_atom_intern(
conf_get_str(conf, CONF_mousepaste_custom),
false));
break;
default:
term->mouse_paste_clipboard = CLIP_NULL;
break;
}
if (conf_get_int(conf, CONF_ctrlshiftins) == CLIPUI_CUSTOM) {
GdkAtom atom = gdk_atom_intern(
conf_get_str(conf, CONF_ctrlshiftins_custom), false);
struct clipboard_state *state = clipboard_from_atom(inst, atom);
if (state) {
inst->clipboard_ctrlshiftins = state->clipboard;
} else {
inst->clipboard_ctrlshiftins = CLIP_CUSTOM_2;
set_clipboard_atom(inst, CLIP_CUSTOM_2, atom);
}
}
if (conf_get_int(conf, CONF_ctrlshiftcv) == CLIPUI_CUSTOM) {
GdkAtom atom = gdk_atom_intern(
conf_get_str(conf, CONF_ctrlshiftcv_custom), false);
struct clipboard_state *state = clipboard_from_atom(inst, atom);
if (state) {
inst->clipboard_ctrlshiftins = state->clipboard;
} else {
inst->clipboard_ctrlshiftcv = CLIP_CUSTOM_3;
set_clipboard_atom(inst, CLIP_CUSTOM_3, atom);
}
}
}
struct after_change_settings_dialog_ctx {
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst;
Conf *newconf;
};
static void after_change_settings_dialog(void *vctx, int retval);
void change_settings_menuitem(GtkMenuItem *item, gpointer data)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = (GtkFrontend *)data;
struct after_change_settings_dialog_ctx *ctx;
GtkWidget *dialog;
char *title;
if (find_and_raise_dialog(inst, DIALOG_SLOT_RECONFIGURE))
return;
title = dupcat(appname, " Reconfiguration", NULL);
ctx = snew(struct after_change_settings_dialog_ctx);
ctx->inst = inst;
ctx->newconf = conf_copy(inst->conf);
dialog = create_config_box(
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
title, ctx->newconf, true,
inst->backend ? backend_cfg_info(inst->backend) : 0,
after_change_settings_dialog, ctx);
New abstraction 'Seat', to pass to backends. This is a new vtable-based abstraction which is passed to a backend in place of Frontend, and it implements only the subset of the Frontend functions needed by a backend. (Many other Frontend functions still exist, notably the wide range of things called by terminal.c providing platform-independent operations on the GUI terminal window.) The purpose of making it a vtable is that this opens up the possibility of creating a backend as an internal implementation detail of some other activity, by providing just that one backend with a custom Seat that implements the methods differently. For example, this refactoring should make it feasible to directly implement an SSH proxy type, aka the 'jump host' feature supported by OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP mode, and then expose the main channel of that as the Socket for the primary connection'. (Which of course you can already do by spawning 'plink -nc' as a separate proxy process, but this would permit it in the _same_ process without anything getting confused.) I've centralised a full set of stub methods in misc.c for the new abstraction, which allows me to get rid of several annoying stubs in the previous code. Also, while I'm here, I've moved a lot of duplicated modalfatalbox() type functions from application main program files into wincons.c / uxcons.c, which I think saves duplication overall. (A minor visible effect is that the prefixes on those console-based fatal error messages will now be more consistent between applications.)
2018-10-11 21:58:42 +03:00
register_dialog(&inst->seat, DIALOG_SLOT_RECONFIGURE, dialog);
sfree(title);
}
static void after_change_settings_dialog(void *vctx, int retval)
{
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
/* This maps colour indices in inst->conf to those used in inst->cols. */
static const int ww[] = {
256, 257, 258, 259, 260, 261,
0, 8, 1, 9, 2, 10, 3, 11,
4, 12, 5, 13, 6, 14, 7, 15
};
struct after_change_settings_dialog_ctx ctx =
*(struct after_change_settings_dialog_ctx *)vctx;
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = ctx.inst;
Conf *oldconf = inst->conf, *newconf = ctx.newconf;
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
int i, j;
bool need_size;
sfree(vctx); /* we've copied this already */
if (retval < 0) {
/* If the dialog box was aborted without giving a result
* (probably because the whole session window closed), we have
* nothing further to do. */
return;
}
assert(lenof(ww) == NCFGCOLOURS);
New abstraction 'Seat', to pass to backends. This is a new vtable-based abstraction which is passed to a backend in place of Frontend, and it implements only the subset of the Frontend functions needed by a backend. (Many other Frontend functions still exist, notably the wide range of things called by terminal.c providing platform-independent operations on the GUI terminal window.) The purpose of making it a vtable is that this opens up the possibility of creating a backend as an internal implementation detail of some other activity, by providing just that one backend with a custom Seat that implements the methods differently. For example, this refactoring should make it feasible to directly implement an SSH proxy type, aka the 'jump host' feature supported by OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP mode, and then expose the main channel of that as the Socket for the primary connection'. (Which of course you can already do by spawning 'plink -nc' as a separate proxy process, but this would permit it in the _same_ process without anything getting confused.) I've centralised a full set of stub methods in misc.c for the new abstraction, which allows me to get rid of several annoying stubs in the previous code. Also, while I'm here, I've moved a lot of duplicated modalfatalbox() type functions from application main program files into wincons.c / uxcons.c, which I think saves duplication overall. (A minor visible effect is that the prefixes on those console-based fatal error messages will now be more consistent between applications.)
2018-10-11 21:58:42 +03:00
unregister_dialog(&inst->seat, DIALOG_SLOT_RECONFIGURE);
if (retval) {
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
inst->conf = newconf;
/* Pass new config data to the logging module */
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
log_reconfig(inst->logctx, inst->conf);
/*
* Flush the line discipline's edit buffer in the case
* where local editing has just been disabled.
*/
if (inst->ldisc) {
ldisc_configure(inst->ldisc, inst->conf);
ldisc_echoedit_update(inst->ldisc);
}
/* Pass new config data to the terminal */
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
term_reconfig(inst->term, inst->conf);
setup_clipboards(inst, inst->term, inst->conf);
/* Pass new config data to the back end */
if (inst->backend)
backend_reconfig(inst->backend, inst->conf);
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
cache_conf_values(inst);
/*
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
* Just setting inst->conf is sufficient to cause colour
* setting changes to appear on the next ESC]R palette
* reset. But we should also check whether any colour
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
* settings have been changed, and revert the ones that have
* to the new default, on the assumption that the user is
* most likely to want an immediate update.
*/
for (i = 0; i < NCFGCOLOURS; i++) {
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
for (j = 0; j < 3; j++)
if (conf_get_int_int(oldconf, CONF_colours, i*3+j) !=
conf_get_int_int(newconf, CONF_colours, i*3+j))
break;
if (j < 3) {
real_palette_set(inst, ww[i],
conf_get_int_int(newconf,CONF_colours,i*3+0),
conf_get_int_int(newconf,CONF_colours,i*3+1),
conf_get_int_int(newconf,CONF_colours,i*3+2));
/*
* If the default background has changed, we must
* repaint the space in between the window border
* and the text area.
*/
if (ww[i] == 258) {
set_window_background(inst);
draw_backing_rect(inst);
}
}
}
need_size = false;
/*
* If the scrollbar needs to be shown, hidden, or moved
* from one end to the other of the window, do so now.
*/
if (conf_get_bool(oldconf, CONF_scrollbar) !=
conf_get_bool(newconf, CONF_scrollbar)) {
show_scrollbar(inst, conf_get_bool(newconf, CONF_scrollbar));
need_size = true;
}
if (conf_get_bool(oldconf, CONF_scrollbar_on_left) !=
conf_get_bool(newconf, CONF_scrollbar_on_left)) {
gtk_box_reorder_child(inst->hbox, inst->sbar,
conf_get_bool(newconf, CONF_scrollbar_on_left)
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
? 0 : 1);
}
/*
* Change the window title, if required.
*/
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
if (strcmp(conf_get_str(oldconf, CONF_wintitle),
conf_get_str(newconf, CONF_wintitle)))
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
win_set_title(&inst->termwin,
conf_get_str(newconf, CONF_wintitle));
set_window_titles(inst);
/*
* Redo the whole tangled fonts and Unicode mess if
* necessary.
*/
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
if (strcmp(conf_get_fontspec(oldconf, CONF_font)->name,
conf_get_fontspec(newconf, CONF_font)->name) ||
strcmp(conf_get_fontspec(oldconf, CONF_boldfont)->name,
conf_get_fontspec(newconf, CONF_boldfont)->name) ||
strcmp(conf_get_fontspec(oldconf, CONF_widefont)->name,
conf_get_fontspec(newconf, CONF_widefont)->name) ||
strcmp(conf_get_fontspec(oldconf, CONF_wideboldfont)->name,
conf_get_fontspec(newconf, CONF_wideboldfont)->name) ||
strcmp(conf_get_str(oldconf, CONF_line_codepage),
conf_get_str(newconf, CONF_line_codepage)) ||
conf_get_bool(oldconf, CONF_utf8_override) !=
conf_get_bool(newconf, CONF_utf8_override) ||
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
conf_get_int(oldconf, CONF_vtmode) !=
conf_get_int(newconf, CONF_vtmode) ||
conf_get_bool(oldconf, CONF_shadowbold) !=
conf_get_bool(newconf, CONF_shadowbold) ||
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
conf_get_int(oldconf, CONF_shadowboldoffset) !=
conf_get_int(newconf, CONF_shadowboldoffset)) {
char *errmsg = setup_fonts_ucs(inst);
if (errmsg) {
char *msgboxtext =
dupprintf("Could not change fonts in terminal window: %s\n",
errmsg);
create_message_box(
inst->window, "Font setup error", msgboxtext,
string_width("Could not change fonts in terminal window:"),
false, &buttons_ok, trivial_post_dialog_fn, NULL);
sfree(msgboxtext);
sfree(errmsg);
} else {
need_size = true;
}
}
/*
* Resize the window.
*/
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
if (conf_get_int(oldconf, CONF_width) !=
conf_get_int(newconf, CONF_width) ||
conf_get_int(oldconf, CONF_height) !=
conf_get_int(newconf, CONF_height) ||
conf_get_int(oldconf, CONF_window_border) !=
conf_get_int(newconf, CONF_window_border) ||
need_size) {
set_geom_hints(inst);
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
win_request_resize(&inst->termwin,
conf_get_int(newconf, CONF_width),
conf_get_int(newconf, CONF_height));
} else {
/*
* The above will have caused a call to term_size() for
* us if it happened. If the user has fiddled with only
* the scrollback size, the above will not have
* happened and we will need an explicit term_size()
* here.
*/
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
if (conf_get_int(oldconf, CONF_savelines) !=
conf_get_int(newconf, CONF_savelines))
term_size(inst->term, inst->term->rows, inst->term->cols,
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
conf_get_int(newconf, CONF_savelines));
}
term_invalidate(inst->term);
/*
* We do an explicit full redraw here to ensure the window
* border has been redrawn as well as the text area.
*/
gtk_widget_queue_draw(inst->area);
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
conf_free(oldconf);
} else {
conf_free(newconf);
}
}
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
static void change_font_size(GtkFrontend *inst, int increment)
{
static const int conf_keys[lenof(inst->fonts)] = {
CONF_font, CONF_boldfont, CONF_widefont, CONF_wideboldfont,
};
FontSpec *oldfonts[lenof(inst->fonts)];
FontSpec *newfonts[lenof(inst->fonts)];
char *errmsg = NULL;
int i;
for (i = 0; i < lenof(newfonts); i++)
oldfonts[i] = newfonts[i] = NULL;
for (i = 0; i < lenof(inst->fonts); i++) {
if (inst->fonts[i]) {
char *newname = unifont_size_increment(inst->fonts[i], increment);
if (!newname)
goto cleanup;
newfonts[i] = fontspec_new(newname);
sfree(newname);
}
}
for (i = 0; i < lenof(newfonts); i++) {
if (newfonts[i]) {
oldfonts[i] = fontspec_copy(
conf_get_fontspec(inst->conf, conf_keys[i]));
conf_set_fontspec(inst->conf, conf_keys[i], newfonts[i]);
}
}
errmsg = setup_fonts_ucs(inst);
if (errmsg)
goto cleanup;
/* Success, so suppress putting everything back */
for (i = 0; i < lenof(newfonts); i++) {
if (oldfonts[i]) {
fontspec_free(oldfonts[i]);
oldfonts[i] = NULL;
}
}
set_geom_hints(inst);
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
win_request_resize(&inst->termwin, conf_get_int(inst->conf, CONF_width),
conf_get_int(inst->conf, CONF_height));
term_invalidate(inst->term);
gtk_widget_queue_draw(inst->area);
cleanup:
for (i = 0; i < lenof(oldfonts); i++) {
if (oldfonts[i]) {
conf_set_fontspec(inst->conf, conf_keys[i], oldfonts[i]);
fontspec_free(oldfonts[i]);
}
if (newfonts[i])
fontspec_free(newfonts[i]);
}
sfree(errmsg);
}
void dup_session_menuitem(GtkMenuItem *item, gpointer gdata)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = (GtkFrontend *)gdata;
Divide the whole of gtkwin.c into three parts. This lays further groundwork for the OS X GTK3 port, which is going to have to deal with multiple sessions sharing the same process. gtkwin.c was a bit too monolithic for this, since it included some process-global runtime state (timers, toplevel callbacks), some process startup stuff (gtk_init, gtk_main, argv processing) and some per-session-window stuff. The per-session stuff remains in gtkwin.c, with the top-level function now being new_session_window() taking a Conf. The new gtkmain.c contains the outer skeleton of pt_main(), handling argv processing and one-off startup stuff like setlocale; and the new gtkcomm.c contains the pieces of PuTTY infrastructure like timers and uxsel that are shared between multiple sessions rather than reinstantiated per session, which have been rewritten to use global variables rather than fields in 'inst' (since it's now clear to me that they'll have to apply to all the insts in existence at once). There are still some lurking assumptions of one-session-per-process, e.g. the use of gtk_main_quit when a session finishes, and the fact that the config box insists on running as a separate invocation of gtk_main so that one session's preliminary config box can't coexist with another session already active. But this should make it possible to at least write an OS X app good enough to start testing with, even if it doesn't get everything quite right yet. This change is almost entirely rearranging existing code, so it shouldn't be seriously destabilising. But two noticeable actual changes have happened, both pleasantly simplifying: Firstly, the global-variables rewrite of gtkcomm.c has allowed the post_main edifice to become a great deal simpler. Most of its complexity was about remembering what 'inst' it had to call back to, and in fact the right answer is that it shouldn't be calling back to one at all. So now the post_main() called by gtkdlg.c has become the same function as the old inst_post_main() that actually did the work, instead of the two having to be connected by a piece of ugly plumbing. Secondly, a piece of code that's vanished completely in this refactoring is the temporary blocking of SIGCHLD around most of the session setup code. This turns out to have been introduced in 2002, _before_ I switched to using the intra-process signal pipe strategy for SIGCHLD handling in 2003. So I now expect that we should be robust in any case against receiving SIGCHLD at an inconvenient moment, and hence there's no need to block it.
2016-03-23 00:24:30 +03:00
launch_duplicate_session(inst->conf);
}
void new_session_menuitem(GtkMenuItem *item, gpointer data)
{
Divide the whole of gtkwin.c into three parts. This lays further groundwork for the OS X GTK3 port, which is going to have to deal with multiple sessions sharing the same process. gtkwin.c was a bit too monolithic for this, since it included some process-global runtime state (timers, toplevel callbacks), some process startup stuff (gtk_init, gtk_main, argv processing) and some per-session-window stuff. The per-session stuff remains in gtkwin.c, with the top-level function now being new_session_window() taking a Conf. The new gtkmain.c contains the outer skeleton of pt_main(), handling argv processing and one-off startup stuff like setlocale; and the new gtkcomm.c contains the pieces of PuTTY infrastructure like timers and uxsel that are shared between multiple sessions rather than reinstantiated per session, which have been rewritten to use global variables rather than fields in 'inst' (since it's now clear to me that they'll have to apply to all the insts in existence at once). There are still some lurking assumptions of one-session-per-process, e.g. the use of gtk_main_quit when a session finishes, and the fact that the config box insists on running as a separate invocation of gtk_main so that one session's preliminary config box can't coexist with another session already active. But this should make it possible to at least write an OS X app good enough to start testing with, even if it doesn't get everything quite right yet. This change is almost entirely rearranging existing code, so it shouldn't be seriously destabilising. But two noticeable actual changes have happened, both pleasantly simplifying: Firstly, the global-variables rewrite of gtkcomm.c has allowed the post_main edifice to become a great deal simpler. Most of its complexity was about remembering what 'inst' it had to call back to, and in fact the right answer is that it shouldn't be calling back to one at all. So now the post_main() called by gtkdlg.c has become the same function as the old inst_post_main() that actually did the work, instead of the two having to be connected by a piece of ugly plumbing. Secondly, a piece of code that's vanished completely in this refactoring is the temporary blocking of SIGCHLD around most of the session setup code. This turns out to have been introduced in 2002, _before_ I switched to using the intra-process signal pipe strategy for SIGCHLD handling in 2003. So I now expect that we should be robust in any case against receiving SIGCHLD at an inconvenient moment, and hence there's no need to block it.
2016-03-23 00:24:30 +03:00
launch_new_session();
}
void restart_session_menuitem(GtkMenuItem *item, gpointer data)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = (GtkFrontend *)data;
if (!inst->backend) {
Refactor the LogContext type. LogContext is now the owner of the logevent() function that back ends and so forth are constantly calling. Previously, logevent was owned by the Frontend, which would store the message into its list for the GUI Event Log dialog (or print it to standard error, or whatever) and then pass it _back_ to LogContext to write to the currently open log file. Now it's the other way round: LogContext gets the message from the back end first, writes it to its log file if it feels so inclined, and communicates it back to the front end. This means that lots of parts of the back end system no longer need to have a pointer to a full-on Frontend; the only thing they needed it for was logging, so now they just have a LogContext (which many of them had to have anyway, e.g. for logging SSH packets or session traffic). LogContext itself also doesn't get a full Frontend pointer any more: it now talks back to the front end via a little vtable of its own called LogPolicy, which contains the method that passes Event Log entries through, the old askappend() function that decides whether to truncate a pre-existing log file, and an emergency function for printing an especially prominent message if the log file can't be created. One minor nice effect of this is that console and GUI apps can implement that last function subtly differently, so that Unix console apps can write it with a plain \n instead of the \r\n (harmless but inelegant) that the old centralised implementation generated. One other consequence of this is that the LogContext has to be provided to backend_init() so that it's available to backends from the instant of creation, rather than being provided via a separate API call a couple of function calls later, because backends have typically started doing things that need logging (like making network connections) before the call to backend_provide_logctx. Fortunately, there's no case in the whole code base where we don't already have logctx by the time we make a backend (so I don't actually remember why I ever delayed providing one). So that shortens the backend API by one function, which is always nice. While I'm tidying up, I've also moved the printf-style logeventf() and the handy logevent_and_free() into logging.c, instead of having copies of them scattered around other places. This has also let me remove some stub functions from a couple of outlying applications like Pageant. Finally, I've removed the pointless "_tag" at the end of LogContext's official struct name.
2018-10-10 21:26:18 +03:00
logevent(inst->logctx, "----- Session restarted -----");
term_pwron(inst->term, false);
start_backend(inst);
inst->exited = false;
}
}
void saved_session_menuitem(GtkMenuItem *item, gpointer data)
{
char *str = (char *)g_object_get_data(G_OBJECT(item), "user-data");
Divide the whole of gtkwin.c into three parts. This lays further groundwork for the OS X GTK3 port, which is going to have to deal with multiple sessions sharing the same process. gtkwin.c was a bit too monolithic for this, since it included some process-global runtime state (timers, toplevel callbacks), some process startup stuff (gtk_init, gtk_main, argv processing) and some per-session-window stuff. The per-session stuff remains in gtkwin.c, with the top-level function now being new_session_window() taking a Conf. The new gtkmain.c contains the outer skeleton of pt_main(), handling argv processing and one-off startup stuff like setlocale; and the new gtkcomm.c contains the pieces of PuTTY infrastructure like timers and uxsel that are shared between multiple sessions rather than reinstantiated per session, which have been rewritten to use global variables rather than fields in 'inst' (since it's now clear to me that they'll have to apply to all the insts in existence at once). There are still some lurking assumptions of one-session-per-process, e.g. the use of gtk_main_quit when a session finishes, and the fact that the config box insists on running as a separate invocation of gtk_main so that one session's preliminary config box can't coexist with another session already active. But this should make it possible to at least write an OS X app good enough to start testing with, even if it doesn't get everything quite right yet. This change is almost entirely rearranging existing code, so it shouldn't be seriously destabilising. But two noticeable actual changes have happened, both pleasantly simplifying: Firstly, the global-variables rewrite of gtkcomm.c has allowed the post_main edifice to become a great deal simpler. Most of its complexity was about remembering what 'inst' it had to call back to, and in fact the right answer is that it shouldn't be calling back to one at all. So now the post_main() called by gtkdlg.c has become the same function as the old inst_post_main() that actually did the work, instead of the two having to be connected by a piece of ugly plumbing. Secondly, a piece of code that's vanished completely in this refactoring is the temporary blocking of SIGCHLD around most of the session setup code. This turns out to have been introduced in 2002, _before_ I switched to using the intra-process signal pipe strategy for SIGCHLD handling in 2003. So I now expect that we should be robust in any case against receiving SIGCHLD at an inconvenient moment, and hence there's no need to block it.
2016-03-23 00:24:30 +03:00
launch_saved_session(str);
}
void saved_session_freedata(GtkMenuItem *item, gpointer data)
{
char *str = (char *)g_object_get_data(G_OBJECT(item), "user-data");
sfree(str);
}
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
void app_menu_action(GtkFrontend *frontend, enum MenuAction action)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = (GtkFrontend *)frontend;
switch (action) {
case MA_COPY:
copy_clipboard_menuitem(NULL, inst);
break;
case MA_PASTE:
paste_clipboard_menuitem(NULL, inst);
break;
case MA_COPY_ALL:
copy_all_menuitem(NULL, inst);
break;
case MA_DUPLICATE_SESSION:
dup_session_menuitem(NULL, inst);
break;
case MA_RESTART_SESSION:
restart_session_menuitem(NULL, inst);
break;
case MA_CHANGE_SETTINGS:
change_settings_menuitem(NULL, inst);
break;
case MA_CLEAR_SCROLLBACK:
clear_scrollback_menuitem(NULL, inst);
break;
case MA_RESET_TERMINAL:
reset_terminal_menuitem(NULL, inst);
break;
case MA_EVENT_LOG:
event_log_menuitem(NULL, inst);
break;
}
}
static void update_savedsess_menu(GtkMenuItem *menuitem, gpointer data)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = (GtkFrontend *)data;
struct sesslist sesslist;
int i;
gtk_container_foreach(GTK_CONTAINER(inst->sessionsmenu),
(GtkCallback)gtk_widget_destroy, NULL);
get_sesslist(&sesslist, true);
/* skip sesslist.sessions[0] == Default Settings */
for (i = 1; i < sesslist.nsessions; i++) {
GtkWidget *menuitem =
gtk_menu_item_new_with_label(sesslist.sessions[i]);
gtk_container_add(GTK_CONTAINER(inst->sessionsmenu), menuitem);
gtk_widget_show(menuitem);
g_object_set_data(G_OBJECT(menuitem), "user-data",
dupstr(sesslist.sessions[i]));
g_signal_connect(G_OBJECT(menuitem), "activate",
G_CALLBACK(saved_session_menuitem),
inst);
g_signal_connect(G_OBJECT(menuitem), "destroy",
G_CALLBACK(saved_session_freedata),
inst);
}
if (sesslist.nsessions <= 1) {
GtkWidget *menuitem =
gtk_menu_item_new_with_label("(No sessions)");
gtk_widget_set_sensitive(menuitem, false);
gtk_container_add(GTK_CONTAINER(inst->sessionsmenu), menuitem);
gtk_widget_show(menuitem);
}
get_sesslist(&sesslist, false); /* free up */
}
void set_window_icon(GtkWidget *window, const char *const *const *icon,
int n_icon)
{
#if GTK_CHECK_VERSION(2,0,0)
GList *iconlist;
int n;
#else
GdkPixmap *iconpm;
GdkBitmap *iconmask;
#endif
if (!n_icon)
return;
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]));
#else
iconpm = gdk_pixmap_create_from_xpm_d(gtk_widget_get_window(window),
&iconmask, NULL, (gchar **)icon[0]);
gdk_window_set_icon(gtk_widget_get_window(window), NULL, iconpm, iconmask);
#endif
#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]));
}
gtk_window_set_icon_list(GTK_WINDOW(window), iconlist);
#endif
}
static void free_special_cmd(gpointer data) { sfree(data); }
New abstraction 'Seat', to pass to backends. This is a new vtable-based abstraction which is passed to a backend in place of Frontend, and it implements only the subset of the Frontend functions needed by a backend. (Many other Frontend functions still exist, notably the wide range of things called by terminal.c providing platform-independent operations on the GUI terminal window.) The purpose of making it a vtable is that this opens up the possibility of creating a backend as an internal implementation detail of some other activity, by providing just that one backend with a custom Seat that implements the methods differently. For example, this refactoring should make it feasible to directly implement an SSH proxy type, aka the 'jump host' feature supported by OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP mode, and then expose the main channel of that as the Socket for the primary connection'. (Which of course you can already do by spawning 'plink -nc' as a separate proxy process, but this would permit it in the _same_ process without anything getting confused.) I've centralised a full set of stub methods in misc.c for the new abstraction, which allows me to get rid of several annoying stubs in the previous code. Also, while I'm here, I've moved a lot of duplicated modalfatalbox() type functions from application main program files into wincons.c / uxcons.c, which I think saves duplication overall. (A minor visible effect is that the prefixes on those console-based fatal error messages will now be more consistent between applications.)
2018-10-11 21:58:42 +03:00
static void gtk_seat_update_specials_menu(Seat *seat)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst = container_of(seat, GtkFrontend, seat);
const SessionSpecial *specials;
if (inst->backend)
specials = backend_get_specials(inst->backend);
else
specials = NULL;
/* I believe this disposes of submenus too. */
gtk_container_foreach(GTK_CONTAINER(inst->specialsmenu),
(GtkCallback)gtk_widget_destroy, NULL);
if (specials) {
int i;
GtkWidget *menu = inst->specialsmenu;
/* A lame "stack" for submenus that will do for now. */
GtkWidget *saved_menu = NULL;
int nesting = 1;
for (i = 0; nesting > 0; i++) {
GtkWidget *menuitem = NULL;
switch (specials[i].code) {
case SS_SUBMENU:
assert (nesting < 2);
saved_menu = menu; /* XXX lame stacking */
menu = gtk_menu_new();
menuitem = gtk_menu_item_new_with_label(specials[i].name);
gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), menu);
gtk_container_add(GTK_CONTAINER(saved_menu), menuitem);
gtk_widget_show(menuitem);
menuitem = NULL;
nesting++;
break;
case SS_EXITMENU:
nesting--;
if (nesting) {
menu = saved_menu; /* XXX lame stacking */
saved_menu = NULL;
}
break;
case SS_SEP:
menuitem = gtk_menu_item_new();
break;
default:
menuitem = gtk_menu_item_new_with_label(specials[i].name);
{
SessionSpecial *sc = snew(SessionSpecial);
*sc = specials[i]; /* structure copy */
g_object_set_data_full(G_OBJECT(menuitem), "user-data",
sc, free_special_cmd);
}
g_signal_connect(G_OBJECT(menuitem), "activate",
G_CALLBACK(special_menuitem), inst);
break;
}
if (menuitem) {
gtk_container_add(GTK_CONTAINER(menu), menuitem);
gtk_widget_show(menuitem);
}
}
gtk_widget_show(inst->specialsitem1);
gtk_widget_show(inst->specialsitem2);
} else {
gtk_widget_hide(inst->specialsitem1);
gtk_widget_hide(inst->specialsitem2);
}
}
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
static void start_backend(GtkFrontend *inst)
{
const struct BackendVtable *vt;
char *realhost;
const char *error;
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
char *s;
vt = select_backend(inst->conf);
New abstraction 'Seat', to pass to backends. This is a new vtable-based abstraction which is passed to a backend in place of Frontend, and it implements only the subset of the Frontend functions needed by a backend. (Many other Frontend functions still exist, notably the wide range of things called by terminal.c providing platform-independent operations on the GUI terminal window.) The purpose of making it a vtable is that this opens up the possibility of creating a backend as an internal implementation detail of some other activity, by providing just that one backend with a custom Seat that implements the methods differently. For example, this refactoring should make it feasible to directly implement an SSH proxy type, aka the 'jump host' feature supported by OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP mode, and then expose the main channel of that as the Socket for the primary connection'. (Which of course you can already do by spawning 'plink -nc' as a separate proxy process, but this would permit it in the _same_ process without anything getting confused.) I've centralised a full set of stub methods in misc.c for the new abstraction, which allows me to get rid of several annoying stubs in the previous code. Also, while I'm here, I've moved a lot of duplicated modalfatalbox() type functions from application main program files into wincons.c / uxcons.c, which I think saves duplication overall. (A minor visible effect is that the prefixes on those console-based fatal error messages will now be more consistent between applications.)
2018-10-11 21:58:42 +03:00
error = backend_init(vt, &inst->seat, &inst->backend,
Refactor the LogContext type. LogContext is now the owner of the logevent() function that back ends and so forth are constantly calling. Previously, logevent was owned by the Frontend, which would store the message into its list for the GUI Event Log dialog (or print it to standard error, or whatever) and then pass it _back_ to LogContext to write to the currently open log file. Now it's the other way round: LogContext gets the message from the back end first, writes it to its log file if it feels so inclined, and communicates it back to the front end. This means that lots of parts of the back end system no longer need to have a pointer to a full-on Frontend; the only thing they needed it for was logging, so now they just have a LogContext (which many of them had to have anyway, e.g. for logging SSH packets or session traffic). LogContext itself also doesn't get a full Frontend pointer any more: it now talks back to the front end via a little vtable of its own called LogPolicy, which contains the method that passes Event Log entries through, the old askappend() function that decides whether to truncate a pre-existing log file, and an emergency function for printing an especially prominent message if the log file can't be created. One minor nice effect of this is that console and GUI apps can implement that last function subtly differently, so that Unix console apps can write it with a plain \n instead of the \r\n (harmless but inelegant) that the old centralised implementation generated. One other consequence of this is that the LogContext has to be provided to backend_init() so that it's available to backends from the instant of creation, rather than being provided via a separate API call a couple of function calls later, because backends have typically started doing things that need logging (like making network connections) before the call to backend_provide_logctx. Fortunately, there's no case in the whole code base where we don't already have logctx by the time we make a backend (so I don't actually remember why I ever delayed providing one). So that shortens the backend API by one function, which is always nice. While I'm tidying up, I've also moved the printf-style logeventf() and the handy logevent_and_free() into logging.c, instead of having copies of them scattered around other places. This has also let me remove some stub functions from a couple of outlying applications like Pageant. Finally, I've removed the pointless "_tag" at the end of LogContext's official struct name.
2018-10-10 21:26:18 +03:00
inst->logctx, inst->conf,
conf_get_str(inst->conf, CONF_host),
conf_get_int(inst->conf, CONF_port),
&realhost,
conf_get_bool(inst->conf, CONF_tcp_nodelay),
conf_get_bool(inst->conf, CONF_tcp_keepalives));
if (error) {
char *msg = dupprintf("Unable to open connection to %s:\n%s",
conf_dest(inst->conf), error);
inst->exited = true;
New abstraction 'Seat', to pass to backends. This is a new vtable-based abstraction which is passed to a backend in place of Frontend, and it implements only the subset of the Frontend functions needed by a backend. (Many other Frontend functions still exist, notably the wide range of things called by terminal.c providing platform-independent operations on the GUI terminal window.) The purpose of making it a vtable is that this opens up the possibility of creating a backend as an internal implementation detail of some other activity, by providing just that one backend with a custom Seat that implements the methods differently. For example, this refactoring should make it feasible to directly implement an SSH proxy type, aka the 'jump host' feature supported by OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP mode, and then expose the main channel of that as the Socket for the primary connection'. (Which of course you can already do by spawning 'plink -nc' as a separate proxy process, but this would permit it in the _same_ process without anything getting confused.) I've centralised a full set of stub methods in misc.c for the new abstraction, which allows me to get rid of several annoying stubs in the previous code. Also, while I'm here, I've moved a lot of duplicated modalfatalbox() type functions from application main program files into wincons.c / uxcons.c, which I think saves duplication overall. (A minor visible effect is that the prefixes on those console-based fatal error messages will now be more consistent between applications.)
2018-10-11 21:58:42 +03:00
seat_connection_fatal(&inst->seat, msg);
sfree(msg);
return;
}
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
s = conf_get_str(inst->conf, CONF_wintitle);
if (s[0]) {
set_title_and_icon(inst, s, s);
} else {
char *title = make_default_wintitle(realhost);
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
set_title_and_icon(inst, title, title);
sfree(title);
}
sfree(realhost);
term_provide_backend(inst->term, inst->backend);
New abstraction 'Seat', to pass to backends. This is a new vtable-based abstraction which is passed to a backend in place of Frontend, and it implements only the subset of the Frontend functions needed by a backend. (Many other Frontend functions still exist, notably the wide range of things called by terminal.c providing platform-independent operations on the GUI terminal window.) The purpose of making it a vtable is that this opens up the possibility of creating a backend as an internal implementation detail of some other activity, by providing just that one backend with a custom Seat that implements the methods differently. For example, this refactoring should make it feasible to directly implement an SSH proxy type, aka the 'jump host' feature supported by OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP mode, and then expose the main channel of that as the Socket for the primary connection'. (Which of course you can already do by spawning 'plink -nc' as a separate proxy process, but this would permit it in the _same_ process without anything getting confused.) I've centralised a full set of stub methods in misc.c for the new abstraction, which allows me to get rid of several annoying stubs in the previous code. Also, while I'm here, I've moved a lot of duplicated modalfatalbox() type functions from application main program files into wincons.c / uxcons.c, which I think saves duplication overall. (A minor visible effect is that the prefixes on those console-based fatal error messages will now be more consistent between applications.)
2018-10-11 21:58:42 +03:00
inst->ldisc = ldisc_create(inst->conf, inst->term, inst->backend,
&inst->seat);
gtk_widget_set_sensitive(inst->restartitem, false);
}
#if GTK_CHECK_VERSION(2,0,0)
static void get_monitor_geometry(GtkWidget *widget, GdkRectangle *geometry)
{
#if GTK_CHECK_VERSION(3,4,0)
GdkDisplay *display = gtk_widget_get_display(widget);
GdkWindow *gdkwindow = gtk_widget_get_window(widget);
# if GTK_CHECK_VERSION(3,22,0)
GdkMonitor *monitor;
if (gdkwindow)
monitor = gdk_display_get_monitor_at_window(display, gdkwindow);
else
monitor = gdk_display_get_monitor(display, 0);
gdk_monitor_get_geometry(monitor, geometry);
# else
GdkScreen *screen = gdk_display_get_default_screen(display);
gint monitor_num = gdk_screen_get_monitor_at_window(screen, gdkwindow);
gdk_screen_get_monitor_geometry(screen, monitor_num, geometry);
# endif
#else
geometry->x = geometry->y = 0;
geometry->width = gdk_screen_width();
geometry->height = gdk_screen_height();
#endif
}
#endif
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
static const TermWinVtable gtk_termwin_vt = {
gtkwin_setup_draw_ctx,
gtkwin_draw_text,
gtkwin_draw_cursor,
gtkwin_char_width,
gtkwin_free_draw_ctx,
gtkwin_set_cursor_pos,
gtkwin_set_raw_mouse_mode,
gtkwin_set_scrollbar,
gtkwin_bell,
gtkwin_clip_write,
gtkwin_clip_request_paste,
gtkwin_refresh,
gtkwin_request_resize,
gtkwin_set_title,
gtkwin_set_icon_title,
gtkwin_set_minimised,
gtkwin_is_minimised,
gtkwin_set_maximised,
gtkwin_move,
gtkwin_set_zorder,
gtkwin_palette_get,
gtkwin_palette_set,
gtkwin_palette_reset,
gtkwin_get_pos,
gtkwin_get_pixels,
gtkwin_get_title,
gtkwin_is_utf8,
};
void new_session_window(Conf *conf, const char *geometry_string)
{
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
GtkFrontend *inst;
prepare_session(conf);
/*
* Create an instance structure and initialise to zeroes
*/
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
inst = snew(GtkFrontend);
memset(inst, 0, sizeof(*inst));
#ifdef JUST_USE_GTK_CLIPBOARD_UTF8
inst->cdi_headtail.next = inst->cdi_headtail.prev = &inst->cdi_headtail;
#endif
inst->alt_keycode = -1; /* this one needs _not_ to be zero */
inst->busy_status = BUSY_NOT;
Divide the whole of gtkwin.c into three parts. This lays further groundwork for the OS X GTK3 port, which is going to have to deal with multiple sessions sharing the same process. gtkwin.c was a bit too monolithic for this, since it included some process-global runtime state (timers, toplevel callbacks), some process startup stuff (gtk_init, gtk_main, argv processing) and some per-session-window stuff. The per-session stuff remains in gtkwin.c, with the top-level function now being new_session_window() taking a Conf. The new gtkmain.c contains the outer skeleton of pt_main(), handling argv processing and one-off startup stuff like setlocale; and the new gtkcomm.c contains the pieces of PuTTY infrastructure like timers and uxsel that are shared between multiple sessions rather than reinstantiated per session, which have been rewritten to use global variables rather than fields in 'inst' (since it's now clear to me that they'll have to apply to all the insts in existence at once). There are still some lurking assumptions of one-session-per-process, e.g. the use of gtk_main_quit when a session finishes, and the fact that the config box insists on running as a separate invocation of gtk_main so that one session's preliminary config box can't coexist with another session already active. But this should make it possible to at least write an OS X app good enough to start testing with, even if it doesn't get everything quite right yet. This change is almost entirely rearranging existing code, so it shouldn't be seriously destabilising. But two noticeable actual changes have happened, both pleasantly simplifying: Firstly, the global-variables rewrite of gtkcomm.c has allowed the post_main edifice to become a great deal simpler. Most of its complexity was about remembering what 'inst' it had to call back to, and in fact the right answer is that it shouldn't be calling back to one at all. So now the post_main() called by gtkdlg.c has become the same function as the old inst_post_main() that actually did the work, instead of the two having to be connected by a piece of ugly plumbing. Secondly, a piece of code that's vanished completely in this refactoring is the temporary blocking of SIGCHLD around most of the session setup code. This turns out to have been introduced in 2002, _before_ I switched to using the intra-process signal pipe strategy for SIGCHLD handling in 2003. So I now expect that we should be robust in any case against receiving SIGCHLD at an inconvenient moment, and hence there's no need to block it.
2016-03-23 00:24:30 +03:00
inst->conf = conf;
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
inst->wintitle = inst->icontitle = NULL;
Refactor the GTK drawing system to do both GDK and Cairo. We're going to have to use Cairo in the GTK3 port, because that's all GTK3 supports; but we still need old-style GDK for GTK1 support, and also for performance reasons in GTK2 (see below). Hence, this change completely restructures GTK PuTTY's drawing code so that there's a central 'drawing context' structure which contains a type code indicating GDK or Cairo, and then either some GDK gubbins or some Cairo gubbins as appropriate; all actual drawing is abstracted through a set of routines which test the type code in that structure and do one thing or another. And because the type code is tested at run time, both sets of drawing primitives can be compiled in at once, and where possible, they will be. X server-side bitmap fonts are still supported in the Cairo world, but because Cairo drawing is entirely client-side, they have to work by cheekily downloading each glyph bitmap from the server when it's first needed, and building up a client-side cache of 'cairo_surface_t's containing the bitmaps with which we then draw on the window. This technique works, but it's rather slow; hence, even in GTK2, we keep the GDK drawing back end compiled in, and switch over to it when the main selected font is a bitmap one. One visible effect of the new Cairo routines is in the double-width and double-height text you can get by sending ESC # 3, ESC # 4 and ESC # 6 escape sequences. In GDK, that's always been done by a really horrible process of manually scaling the bitmap, server-side, column by column and row by row, causing each pixel to be exactly doubled or quadrupled. But in Cairo, we can just set a transformation matrix, and then that takes effect _before_ the scalable fonts are rendered - so the results are visibly nicer, and use all the available resolution. (Sadly, if you're using a server-side bitmap font as your primary one, then the GDK backend will be selected for all drawing in the terminal as a whole - so in that situation, even fallback characters absent from the primary font and rendered by Pango will get the old GDK scaling treatment. It's only if your main font is scalable, so that the Cairo backend is selected, that DW/DH characters will come out looking nice.)
2015-08-15 23:05:56 +03:00
inst->drawtype = DRAWTYPE_DEFAULT;
#if GTK_CHECK_VERSION(3,4,0)
inst->cumulative_scroll = 0.0;
#endif
inst->drawing_area_setup_needed = true;
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
inst->termwin.vt = &gtk_termwin_vt;
New abstraction 'Seat', to pass to backends. This is a new vtable-based abstraction which is passed to a backend in place of Frontend, and it implements only the subset of the Frontend functions needed by a backend. (Many other Frontend functions still exist, notably the wide range of things called by terminal.c providing platform-independent operations on the GUI terminal window.) The purpose of making it a vtable is that this opens up the possibility of creating a backend as an internal implementation detail of some other activity, by providing just that one backend with a custom Seat that implements the methods differently. For example, this refactoring should make it feasible to directly implement an SSH proxy type, aka the 'jump host' feature supported by OpenSSH, aka 'open a secondary SSH session in MAINCHAN_DIRECT_TCP mode, and then expose the main channel of that as the Socket for the primary connection'. (Which of course you can already do by spawning 'plink -nc' as a separate proxy process, but this would permit it in the _same_ process without anything getting confused.) I've centralised a full set of stub methods in misc.c for the new abstraction, which allows me to get rid of several annoying stubs in the previous code. Also, while I'm here, I've moved a lot of duplicated modalfatalbox() type functions from application main program files into wincons.c / uxcons.c, which I think saves duplication overall. (A minor visible effect is that the prefixes on those console-based fatal error messages will now be more consistent between applications.)
2018-10-11 21:58:42 +03:00
inst->seat.vt = &gtk_seat_vt;
Refactor the LogContext type. LogContext is now the owner of the logevent() function that back ends and so forth are constantly calling. Previously, logevent was owned by the Frontend, which would store the message into its list for the GUI Event Log dialog (or print it to standard error, or whatever) and then pass it _back_ to LogContext to write to the currently open log file. Now it's the other way round: LogContext gets the message from the back end first, writes it to its log file if it feels so inclined, and communicates it back to the front end. This means that lots of parts of the back end system no longer need to have a pointer to a full-on Frontend; the only thing they needed it for was logging, so now they just have a LogContext (which many of them had to have anyway, e.g. for logging SSH packets or session traffic). LogContext itself also doesn't get a full Frontend pointer any more: it now talks back to the front end via a little vtable of its own called LogPolicy, which contains the method that passes Event Log entries through, the old askappend() function that decides whether to truncate a pre-existing log file, and an emergency function for printing an especially prominent message if the log file can't be created. One minor nice effect of this is that console and GUI apps can implement that last function subtly differently, so that Unix console apps can write it with a plain \n instead of the \r\n (harmless but inelegant) that the old centralised implementation generated. One other consequence of this is that the LogContext has to be provided to backend_init() so that it's available to backends from the instant of creation, rather than being provided via a separate API call a couple of function calls later, because backends have typically started doing things that need logging (like making network connections) before the call to backend_provide_logctx. Fortunately, there's no case in the whole code base where we don't already have logctx by the time we make a backend (so I don't actually remember why I ever delayed providing one). So that shortens the backend API by one function, which is always nice. While I'm tidying up, I've also moved the printf-style logeventf() and the handy logevent_and_free() into logging.c, instead of having copies of them scattered around other places. This has also let me remove some stub functions from a couple of outlying applications like Pageant. Finally, I've removed the pointless "_tag" at the end of LogContext's official struct name.
2018-10-10 21:26:18 +03:00
inst->logpolicy.vt = &gtk_logpolicy_vt;
#ifndef NOT_X_WINDOWS
Basic support for running under GDK Wayland back end. GTK 3 PuTTY/pterm has always assumed that if it was compiled with _support_ for talking to the raw X11 layer underneath GTK and GDK, then it was entitled to expect that raw X11 layer to exist at all times, i.e. that GDK_DISPLAY_XDISPLAY would return a meaningful X display that it could do useful things with. So if you ran it over the GDK Wayland backend, it would immediately segfault. Modern GTK applications need to cope with multiple GDK backends at run time. It's fine for GTK PuTTY to _contain_ the code to find and use underlying X11 primitives like the display and the X window id, but it should be prepared to find that it's running on Wayland (or something else again!) so those functions don't return anything useful - in which case it should degrade gracefully to the subset of functionality that can be accessed through backend-independent GTK calls. Accordingly, I've centralised the use of GDK_DISPLAY_XDISPLAY into a support function get_x_display() in gtkmisc.c, which starts by checking that there actually is one first. All previous direct uses of GDK_*_XDISPLAY now go via that function, and check the result for NULL afterwards. (To save faffing about calling that function too many times, I'm also caching the display pointer in more places, and passing it as an extra argument to various subfunctions, mostly in gtkfont.c.) Similarly, the get_windowid() function that retrieves the window id to put in the environment of pterm's child process has to be prepared for there not to be a window id. This isn't a complete fix for all Wayland-related problems. The other one I'm currently aware of is that the default font is "server:fixed", which is a bad default now that it won't be available on all backends. And I expect that further problems will show up with more testing. But it's a start.
2018-05-09 11:18:20 +03:00
inst->disp = get_x11_display();
Divide the whole of gtkwin.c into three parts. This lays further groundwork for the OS X GTK3 port, which is going to have to deal with multiple sessions sharing the same process. gtkwin.c was a bit too monolithic for this, since it included some process-global runtime state (timers, toplevel callbacks), some process startup stuff (gtk_init, gtk_main, argv processing) and some per-session-window stuff. The per-session stuff remains in gtkwin.c, with the top-level function now being new_session_window() taking a Conf. The new gtkmain.c contains the outer skeleton of pt_main(), handling argv processing and one-off startup stuff like setlocale; and the new gtkcomm.c contains the pieces of PuTTY infrastructure like timers and uxsel that are shared between multiple sessions rather than reinstantiated per session, which have been rewritten to use global variables rather than fields in 'inst' (since it's now clear to me that they'll have to apply to all the insts in existence at once). There are still some lurking assumptions of one-session-per-process, e.g. the use of gtk_main_quit when a session finishes, and the fact that the config box insists on running as a separate invocation of gtk_main so that one session's preliminary config box can't coexist with another session already active. But this should make it possible to at least write an OS X app good enough to start testing with, even if it doesn't get everything quite right yet. This change is almost entirely rearranging existing code, so it shouldn't be seriously destabilising. But two noticeable actual changes have happened, both pleasantly simplifying: Firstly, the global-variables rewrite of gtkcomm.c has allowed the post_main edifice to become a great deal simpler. Most of its complexity was about remembering what 'inst' it had to call back to, and in fact the right answer is that it shouldn't be calling back to one at all. So now the post_main() called by gtkdlg.c has become the same function as the old inst_post_main() that actually did the work, instead of the two having to be connected by a piece of ugly plumbing. Secondly, a piece of code that's vanished completely in this refactoring is the temporary blocking of SIGCHLD around most of the session setup code. This turns out to have been introduced in 2002, _before_ I switched to using the intra-process signal pipe strategy for SIGCHLD handling in 2003. So I now expect that we should be robust in any case against receiving SIGCHLD at an inconvenient moment, and hence there's no need to block it.
2016-03-23 00:24:30 +03:00
if (geometry_string) {
int flags, x, y;
unsigned int w, h;
flags = XParseGeometry(geometry_string, &x, &y, &w, &h);
if (flags & WidthValue)
conf_set_int(conf, CONF_width, w);
if (flags & HeightValue)
conf_set_int(conf, CONF_height, h);
if (flags & (XValue | YValue)) {
inst->xpos = x;
inst->ypos = y;
inst->gotpos = true;
Divide the whole of gtkwin.c into three parts. This lays further groundwork for the OS X GTK3 port, which is going to have to deal with multiple sessions sharing the same process. gtkwin.c was a bit too monolithic for this, since it included some process-global runtime state (timers, toplevel callbacks), some process startup stuff (gtk_init, gtk_main, argv processing) and some per-session-window stuff. The per-session stuff remains in gtkwin.c, with the top-level function now being new_session_window() taking a Conf. The new gtkmain.c contains the outer skeleton of pt_main(), handling argv processing and one-off startup stuff like setlocale; and the new gtkcomm.c contains the pieces of PuTTY infrastructure like timers and uxsel that are shared between multiple sessions rather than reinstantiated per session, which have been rewritten to use global variables rather than fields in 'inst' (since it's now clear to me that they'll have to apply to all the insts in existence at once). There are still some lurking assumptions of one-session-per-process, e.g. the use of gtk_main_quit when a session finishes, and the fact that the config box insists on running as a separate invocation of gtk_main so that one session's preliminary config box can't coexist with another session already active. But this should make it possible to at least write an OS X app good enough to start testing with, even if it doesn't get everything quite right yet. This change is almost entirely rearranging existing code, so it shouldn't be seriously destabilising. But two noticeable actual changes have happened, both pleasantly simplifying: Firstly, the global-variables rewrite of gtkcomm.c has allowed the post_main edifice to become a great deal simpler. Most of its complexity was about remembering what 'inst' it had to call back to, and in fact the right answer is that it shouldn't be calling back to one at all. So now the post_main() called by gtkdlg.c has become the same function as the old inst_post_main() that actually did the work, instead of the two having to be connected by a piece of ugly plumbing. Secondly, a piece of code that's vanished completely in this refactoring is the temporary blocking of SIGCHLD around most of the session setup code. This turns out to have been introduced in 2002, _before_ I switched to using the intra-process signal pipe strategy for SIGCHLD handling in 2003. So I now expect that we should be robust in any case against receiving SIGCHLD at an inconvenient moment, and hence there's no need to block it.
2016-03-23 00:24:30 +03:00
inst->gravity = ((flags & XNegative ? 1 : 0) |
(flags & YNegative ? 2 : 0));
}
}
#endif
if (!compound_text_atom)
compound_text_atom = gdk_atom_intern("COMPOUND_TEXT", false);
if (!utf8_string_atom)
utf8_string_atom = gdk_atom_intern("UTF8_STRING", false);
if (!clipboard_atom)
clipboard_atom = gdk_atom_intern("CLIPBOARD", false);
inst->area = gtk_drawing_area_new();
gtk_widget_set_name(GTK_WIDGET(inst->area), "drawing-area");
{
char *errmsg = setup_fonts_ucs(inst);
if (errmsg) {
window_setup_error(errmsg);
sfree(errmsg);
gtk_widget_destroy(inst->area);
sfree(inst);
return;
}
}
#if GTK_CHECK_VERSION(2,0,0)
inst->imc = gtk_im_multicontext_new();
#endif
inst->window = make_gtk_toplevel_window(inst);
gtk_widget_set_name(GTK_WIDGET(inst->window), "top-level");
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
{
const char *winclass = conf_get_str(inst->conf, CONF_winclass);
if (*winclass) {
#if GTK_CHECK_VERSION(3,22,0)
#ifndef NOT_X_WINDOWS
GdkWindow *gdkwin;
gtk_widget_realize(GTK_WIDGET(inst->window));
gdkwin = gtk_widget_get_window(GTK_WIDGET(inst->window));
Basic support for running under GDK Wayland back end. GTK 3 PuTTY/pterm has always assumed that if it was compiled with _support_ for talking to the raw X11 layer underneath GTK and GDK, then it was entitled to expect that raw X11 layer to exist at all times, i.e. that GDK_DISPLAY_XDISPLAY would return a meaningful X display that it could do useful things with. So if you ran it over the GDK Wayland backend, it would immediately segfault. Modern GTK applications need to cope with multiple GDK backends at run time. It's fine for GTK PuTTY to _contain_ the code to find and use underlying X11 primitives like the display and the X window id, but it should be prepared to find that it's running on Wayland (or something else again!) so those functions don't return anything useful - in which case it should degrade gracefully to the subset of functionality that can be accessed through backend-independent GTK calls. Accordingly, I've centralised the use of GDK_DISPLAY_XDISPLAY into a support function get_x_display() in gtkmisc.c, which starts by checking that there actually is one first. All previous direct uses of GDK_*_XDISPLAY now go via that function, and check the result for NULL afterwards. (To save faffing about calling that function too many times, I'm also caching the display pointer in more places, and passing it as an extra argument to various subfunctions, mostly in gtkfont.c.) Similarly, the get_windowid() function that retrieves the window id to put in the environment of pterm's child process has to be prepared for there not to be a window id. This isn't a complete fix for all Wayland-related problems. The other one I'm currently aware of is that the default font is "server:fixed", which is a bad default now that it won't be available on all backends. And I expect that further problems will show up with more testing. But it's a start.
2018-05-09 11:18:20 +03:00
if (inst->disp && gdk_window_ensure_native(gdkwin)) {
XClassHint *xch = XAllocClassHint();
xch->res_name = (char *)winclass;
xch->res_class = (char *)winclass;
Basic support for running under GDK Wayland back end. GTK 3 PuTTY/pterm has always assumed that if it was compiled with _support_ for talking to the raw X11 layer underneath GTK and GDK, then it was entitled to expect that raw X11 layer to exist at all times, i.e. that GDK_DISPLAY_XDISPLAY would return a meaningful X display that it could do useful things with. So if you ran it over the GDK Wayland backend, it would immediately segfault. Modern GTK applications need to cope with multiple GDK backends at run time. It's fine for GTK PuTTY to _contain_ the code to find and use underlying X11 primitives like the display and the X window id, but it should be prepared to find that it's running on Wayland (or something else again!) so those functions don't return anything useful - in which case it should degrade gracefully to the subset of functionality that can be accessed through backend-independent GTK calls. Accordingly, I've centralised the use of GDK_DISPLAY_XDISPLAY into a support function get_x_display() in gtkmisc.c, which starts by checking that there actually is one first. All previous direct uses of GDK_*_XDISPLAY now go via that function, and check the result for NULL afterwards. (To save faffing about calling that function too many times, I'm also caching the display pointer in more places, and passing it as an extra argument to various subfunctions, mostly in gtkfont.c.) Similarly, the get_windowid() function that retrieves the window id to put in the environment of pterm's child process has to be prepared for there not to be a window id. This isn't a complete fix for all Wayland-related problems. The other one I'm currently aware of is that the default font is "server:fixed", which is a bad default now that it won't be available on all backends. And I expect that further problems will show up with more testing. But it's a start.
2018-05-09 11:18:20 +03:00
XSetClassHint(inst->disp, GDK_WINDOW_XID(gdkwin), xch);
XFree(xch);
}
#endif
/*
* If we do have NOT_X_WINDOWS set, then we don't have any
* function in GTK 3.22 equivalent to the above. But then,
* surely in that situation the deprecated
* gtk_window_set_wmclass wouldn't have done anything
* meaningful in previous GTKs either.
*/
#else
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
gtk_window_set_wmclass(GTK_WINDOW(inst->window),
winclass, winclass);
#endif
}
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
}
/*
* Set up the colour map.
*/
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
win_palette_reset(&inst->termwin);
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
inst->width = conf_get_int(inst->conf, CONF_width);
inst->height = conf_get_int(inst->conf, CONF_height);
cache_conf_values(inst);
Initial support for clipboard on OS X. Rather than trying to get my existing hugely complicated X-style clipboard code to somehow work with the Quartz GTK back end, I've written an entirely new and much simpler alternative clipboard handler usnig the higher-leve GtkClipboard interface. It assumes all clipboard text can be converted to and from UTF-8 sensibly (which isn't a good assumption on all front ends, but on OS X I think it's reasonable), and it talks to GDK_SELECTION_CLIPBOARD rather than PRIMARY, which is the only clipboard OS X has. I had to do a fiddly thing to cope with the fact that each call to gtk_clipboard_set_with_data caused a call to the clipboard clear function left over from the previous set of data, so I had to avoid mistaking that for a clipboard-clear for the _new_ data and immediately deselecting it. I did that by allocating a distinct placeholder object in memory for each instance of the copy operation, so that I can tell whether a clipboard-clear is for the current copy or a previous one. This is only very basic support which demonstrates successful copying and pasting is at least possible. For a sensible OS X implementation we'll need a more believable means of generating a paste UI action (it's quite easy to find a Mac on which neither Shift-Ins nor the third mouse button even exists!). Also, after the trouble I had with the clipboard-clear event, it's a bit annoying to find that it _doesn't_ seem to get called when another application becomes the clipboard owner. That may just be something we have to put up with, if I can't find any reason why it's failing.
2015-09-02 23:37:33 +03:00
init_clipboard(inst);
inst->sbar_adjust = GTK_ADJUSTMENT(gtk_adjustment_new(0,0,0,0,0,0));
inst->sbar = gtk_vscrollbar_new(inst->sbar_adjust);
inst->hbox = GTK_BOX(gtk_hbox_new(false, 0));
/*
* We always create the scrollbar; it remains invisible if
* unwanted, so we can pop it up quickly if it suddenly becomes
* desirable.
*/
if (conf_get_bool(inst->conf, CONF_scrollbar_on_left))
gtk_box_pack_start(inst->hbox, inst->sbar, false, false, 0);
gtk_box_pack_start(inst->hbox, inst->area, true, true, 0);
if (!conf_get_bool(inst->conf, CONF_scrollbar_on_left))
gtk_box_pack_start(inst->hbox, inst->sbar, false, false, 0);
gtk_container_add(GTK_CONTAINER(inst->window), GTK_WIDGET(inst->hbox));
gtk_widget_show(inst->area);
show_scrollbar(inst, conf_get_bool(inst->conf, CONF_scrollbar));
gtk_widget_show(GTK_WIDGET(inst->hbox));
/*
* We must call gtk_widget_realize before setting up the geometry
* hints, so that GtkApplicationWindow will have actually created
* its menu bar (if it's going to) and hence compute_geom_hints
* can find it to take its size into account.
*/
gtk_widget_realize(inst->window);
set_geom_hints(inst);
#if GTK_CHECK_VERSION(3,0,0)
{
int wp, hp;
compute_whole_window_size(inst, inst->width, inst->height, &wp, &hp);
gtk_window_set_default_size(GTK_WINDOW(inst->window), wp, hp);
}
#else
{
int w = inst->font_width * inst->width + 2*inst->window_border;
int h = inst->font_height * inst->height + 2*inst->window_border;
#if GTK_CHECK_VERSION(2,0,0)
gtk_widget_set_size_request(inst->area, w, h);
#else
gtk_drawing_area_size(GTK_DRAWING_AREA(inst->area), w, h);
#endif
}
#endif
#if GTK_CHECK_VERSION(2,0,0)
if (inst->gotpos) {
static const GdkGravity gravities[] = {
GDK_GRAVITY_NORTH_WEST,
GDK_GRAVITY_NORTH_EAST,
GDK_GRAVITY_SOUTH_WEST,
GDK_GRAVITY_SOUTH_EAST,
};
int x = inst->xpos, y = inst->ypos;
int wp, hp;
GdkRectangle monitor_geometry;
compute_whole_window_size(inst, inst->width, inst->height, &wp, &hp);
get_monitor_geometry(GTK_WIDGET(inst->window), &monitor_geometry);
if (inst->gravity & 1) x += (monitor_geometry.width - wp);
if (inst->gravity & 2) y += (monitor_geometry.height - hp);
gtk_window_set_gravity(GTK_WINDOW(inst->window),
gravities[inst->gravity & 3]);
gtk_window_move(GTK_WINDOW(inst->window), x, y);
}
#else
if (inst->gotpos) {
int x = inst->xpos, y = inst->ypos;
GtkRequisition req;
gtk_widget_size_request(GTK_WIDGET(inst->window), &req);
if (inst->gravity & 1) x += gdk_screen_width() - req.width;
if (inst->gravity & 2) y += gdk_screen_height() - req.height;
gtk_window_set_position(GTK_WINDOW(inst->window), GTK_WIN_POS_NONE);
gtk_widget_set_uposition(GTK_WIDGET(inst->window), x, y);
}
#endif
g_signal_connect(G_OBJECT(inst->window), "destroy",
G_CALLBACK(destroy), inst);
g_signal_connect(G_OBJECT(inst->window), "delete_event",
G_CALLBACK(delete_window), inst);
g_signal_connect(G_OBJECT(inst->window), "key_press_event",
G_CALLBACK(key_event), inst);
g_signal_connect(G_OBJECT(inst->window), "key_release_event",
G_CALLBACK(key_event), inst);
g_signal_connect(G_OBJECT(inst->window), "focus_in_event",
G_CALLBACK(focus_event), inst);
g_signal_connect(G_OBJECT(inst->window), "focus_out_event",
G_CALLBACK(focus_event), inst);
Stop using the GTK "configure-event" signal. I've been using that signal since the very first commit of this source file, as a combined way to be notified when the size of the drawing area changes (typically due to user window resizing actions) and also when the drawing area is first created and available to be drawn on. Unfortunately, testing on Ubuntu 18.04, I ran into an oddity, in which the call to gtk_widget_show(inst->window) in new_session_window() has the side effect of delivering a spurious configure_event on the drawing area with size 1x46 pixels. This causes the terminal to resize itself to 1 column wide, and the mistake isn't rectified until a followup configure-event arrives after new_session_window returns to the GTK main loop. But that means terminal output can occur between those two configure events (the connection-sharing "Reusing a shared connection to host.name" is a good example), and when it does, it gets embarrassingly wrapped at one character per line down the left column. I briefly tried to bodge around this by trying to heuristically guess which configure events were real and which were spurious, but I have no faith in that strategy continuing to work. I think a better approach is to abandon configure-event completely, and move to a system in which the two purposes I was using it for are handled by two _different_ GTK signals, namely "size-allocate" (for knowing when we get resized) and "realize" (for knowing when the drawing area physically exists for us to start setting up Cairo or GDK machinery). The result seems to have fixed the silly one-column wrapping bug, and retained the ability to handle window resizes, on every GTK version I have conveniently available to test on, including GTK 3 both before and after these spurious configures started to happen.
2018-05-10 22:22:02 +03:00
g_signal_connect(G_OBJECT(inst->area), "realize",
G_CALLBACK(area_realised), inst);
g_signal_connect(G_OBJECT(inst->area), "size_allocate",
G_CALLBACK(area_size_allocate), inst);
GTK 3: be aware of the window's scale factor. In GTK 3.10 and above, high-DPI support is arranged by each window having a property called a 'scale factor', which translates logical pixels as seen by most of the GTK API (widget and window sizes and positions, coordinates in the "draw" event, etc) into the physical pixels on the screen. This is handled more or less transparently, except that one side effect is that your Cairo-based drawing code had better be able to cope with that scaling without getting confused. PuTTY's isn't, because we do all our serious drawing on a separate Cairo surface we made ourselves, and then blit subrectangles of that to the window during updates. This has two bad consequences. Firstly, our surface has a size derived from what GTK told us the drawing area size is, i.e. corresponding to GTK's _logical_ pixels, so when the scale factor is (say) 2, our drawing takes place at half size and then gets scaled up by the final blit in the draw event, making it look blurry and unpleasant. Secondly, those final blits seem to end up offset by half a pixel, so that a second blit over the same subrectangle doesn't _quite_ completely wipe out the previously blitted data - so there's a ghostly rectangle left behind everywhere the cursor has been. It's not that GTK doesn't _let_ you find out the scale factor; it's just that it's in an out-of-the-way piece of API that you have to call specially. So now we do: our backing surface is now created at a pixel resolution matching the screen's real pixels, and we translate GTK's scale factor into an ordinary cairo_scale() before we commence drawing. So we still end up drawing the same text at the same size - and this strategy also means that non-text elements like cursor outlines and underlining will be scaled up with the screen DPI rather than stubbornly staying one physical pixel thick - but now it's nice and sharp at full screen resolution, and the subrectangle blits in the draw event are back to affecting the exact set of pixels we expect them to. One silly consequence is that, immediately after removing the last one, I've installed a handler for the GTK "configure-event" signal! That's because the GTK 3 docs claim that that's how you get notified that your scale factor has changed at run time (e.g. if you reconfigure the scale factor of a whole monitor in the GNOME settings dialog). Actually in practice I seem to find out via the "draw" event before "configure" bothers to tell me, but now I've got a usefully idempotent function for 'check whether the scale factor has changed and sort it out if so', I don't see any harm in calling it from anywhere it _might_ be useful.
2018-05-11 09:53:05 +03:00
#if GTK_CHECK_VERSION(3,10,0)
g_signal_connect(G_OBJECT(inst->area), "configure_event",
G_CALLBACK(area_configured), inst);
#endif
#if GTK_CHECK_VERSION(3,0,0)
g_signal_connect(G_OBJECT(inst->area), "draw",
G_CALLBACK(draw_area), inst);
#else
g_signal_connect(G_OBJECT(inst->area), "expose_event",
G_CALLBACK(expose_area), inst);
#endif
g_signal_connect(G_OBJECT(inst->area), "button_press_event",
G_CALLBACK(button_event), inst);
g_signal_connect(G_OBJECT(inst->area), "button_release_event",
G_CALLBACK(button_event), inst);
#if GTK_CHECK_VERSION(2,0,0)
g_signal_connect(G_OBJECT(inst->area), "scroll_event",
G_CALLBACK(scroll_event), inst);
#endif
g_signal_connect(G_OBJECT(inst->area), "motion_notify_event",
G_CALLBACK(motion_event), inst);
#if GTK_CHECK_VERSION(2,0,0)
g_signal_connect(G_OBJECT(inst->imc), "commit",
G_CALLBACK(input_method_commit_event), inst);
#endif
if (conf_get_bool(inst->conf, CONF_scrollbar))
g_signal_connect(G_OBJECT(inst->sbar_adjust), "value_changed",
G_CALLBACK(scrollbar_moved), inst);
gtk_widget_add_events(GTK_WIDGET(inst->area),
GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK |
GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
GDK_POINTER_MOTION_MASK | GDK_BUTTON_MOTION_MASK
#if GTK_CHECK_VERSION(3,4,0)
| GDK_SMOOTH_SCROLL_MASK
#endif
);
set_window_icon(inst->window, main_icon, n_main_icon);
gtk_widget_show(inst->window);
set_window_background(inst);
/*
* Set up the Ctrl+rightclick context menu.
*/
{
GtkWidget *menuitem;
char *s;
inst->menu = gtk_menu_new();
#define MKMENUITEM(title, func) do \
{ \
menuitem = gtk_menu_item_new_with_label(title); \
gtk_container_add(GTK_CONTAINER(inst->menu), menuitem); \
gtk_widget_show(menuitem); \
g_signal_connect(G_OBJECT(menuitem), "activate", \
G_CALLBACK(func), inst); \
} while (0)
#define MKSUBMENU(title) do \
{ \
menuitem = gtk_menu_item_new_with_label(title); \
gtk_container_add(GTK_CONTAINER(inst->menu), menuitem); \
gtk_widget_show(menuitem); \
} while (0)
#define MKSEP() do \
{ \
menuitem = gtk_menu_item_new(); \
gtk_container_add(GTK_CONTAINER(inst->menu), menuitem); \
gtk_widget_show(menuitem); \
} while (0)
if (new_session)
MKMENUITEM("New Session...", new_session_menuitem);
MKMENUITEM("Restart Session", restart_session_menuitem);
inst->restartitem = menuitem;
gtk_widget_set_sensitive(inst->restartitem, false);
MKMENUITEM("Duplicate Session", dup_session_menuitem);
if (saved_sessions) {
inst->sessionsmenu = gtk_menu_new();
/* sessionsmenu will be updated when it's invoked */
/* XXX is this the right way to do dynamic menus in Gtk? */
MKMENUITEM("Saved Sessions", update_savedsess_menu);
gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem),
inst->sessionsmenu);
}
MKSEP();
MKMENUITEM("Change Settings...", change_settings_menuitem);
MKSEP();
if (use_event_log)
MKMENUITEM("Event Log", event_log_menuitem);
MKSUBMENU("Special Commands");
inst->specialsmenu = gtk_menu_new();
gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), inst->specialsmenu);
inst->specialsitem1 = menuitem;
MKSEP();
inst->specialsitem2 = menuitem;
gtk_widget_hide(inst->specialsitem1);
gtk_widget_hide(inst->specialsitem2);
MKMENUITEM("Clear Scrollback", clear_scrollback_menuitem);
MKMENUITEM("Reset Terminal", reset_terminal_menuitem);
MKSEP();
MKMENUITEM("Copy to " CLIPNAME_EXPLICIT_OBJECT,
copy_clipboard_menuitem);
MKMENUITEM("Paste from " CLIPNAME_EXPLICIT_OBJECT,
paste_clipboard_menuitem);
MKMENUITEM("Copy All", copy_all_menuitem);
MKSEP();
s = dupcat("About ", appname, NULL);
MKMENUITEM(s, about_menuitem);
sfree(s);
#undef MKMENUITEM
#undef MKSUBMENU
#undef MKSEP
}
inst->textcursor = make_mouse_ptr(inst, GDK_XTERM);
inst->rawcursor = make_mouse_ptr(inst, GDK_LEFT_PTR);
inst->waitcursor = make_mouse_ptr(inst, GDK_WATCH);
inst->blankcursor = make_mouse_ptr(inst, -1);
inst->currcursor = inst->textcursor;
Convert a lot of 'int' variables to 'bool'. My normal habit these days, in new code, is to treat int and bool as _almost_ completely separate types. I'm still willing to use C's implicit test for zero on an integer (e.g. 'if (!blob.len)' is fine, no need to spell it out as blob.len != 0), but generally, if a variable is going to be conceptually a boolean, I like to declare it bool and assign to it using 'true' or 'false' rather than 0 or 1. PuTTY is an exception, because it predates the C99 bool, and I've stuck to its existing coding style even when adding new code to it. But it's been annoying me more and more, so now that I've decided C99 bool is an acceptable thing to require from our toolchain in the first place, here's a quite thorough trawl through the source doing 'boolification'. Many variables and function parameters are now typed as bool rather than int; many assignments of 0 or 1 to those variables are now spelled 'true' or 'false'. I managed this thorough conversion with the help of a custom clang plugin that I wrote to trawl the AST and apply heuristics to point out where things might want changing. So I've even managed to do a decent job on parts of the code I haven't looked at in years! To make the plugin's work easier, I pushed platform front ends generally in the direction of using standard 'bool' in preference to platform-specific boolean types like Windows BOOL or GTK's gboolean; I've left the platform booleans in places they _have_ to be for the platform APIs to work right, but variables only used by my own code have been converted wherever I found them. In a few places there are int values that look very like booleans in _most_ of the places they're used, but have a rarely-used third value, or a distinction between different nonzero values that most users don't care about. In these cases, I've _removed_ uses of 'true' and 'false' for the return values, to emphasise that there's something more subtle going on than a simple boolean answer: - the 'multisel' field in dialog.h's list box structure, for which the GTK front end in particular recognises a difference between 1 and 2 but nearly everything else treats as boolean - the 'urgent' parameter to plug_receive, where 1 vs 2 tells you something about the specific location of the urgent pointer, but most clients only care about 0 vs 'something nonzero' - the return value of wc_match, where -1 indicates a syntax error in the wildcard. - the return values from SSH-1 RSA-key loading functions, which use -1 for 'wrong passphrase' and 0 for all other failures (so any caller which already knows it's not loading an _encrypted private_ key can treat them as boolean) - term->esc_query, and the 'query' parameter in toggle_mode in terminal.c, which _usually_ hold 0 for ESC[123h or 1 for ESC[?123h, but can also hold -1 for some other intervening character that we don't support. In a few places there's an integer that I haven't turned into a bool even though it really _can_ only take values 0 or 1 (and, as above, tried to make the call sites consistent in not calling those values true and false), on the grounds that I thought it would make it more confusing to imply that the 0 value was in some sense 'negative' or bad and the 1 positive or good: - the return value of plug_accepting uses the POSIXish convention of 0=success and nonzero=error; I think if I made it bool then I'd also want to reverse its sense, and that's a job for a separate piece of work. - the 'screen' parameter to lineptr() in terminal.c, where 0 and 1 represent the default and alternate screens. There's no obvious reason why one of those should be considered 'true' or 'positive' or 'success' - they're just indices - so I've left it as int. ssh_scp_recv had particularly confusing semantics for its previous int return value: its call sites used '<= 0' to check for error, but it never actually returned a negative number, just 0 or 1. Now the function and its call sites agree that it's a bool. In a couple of places I've renamed variables called 'ret', because I don't like that name any more - it's unclear whether it means the return value (in preparation) for the _containing_ function or the return value received from a subroutine call, and occasionally I've accidentally used the same variable for both and introduced a bug. So where one of those got in my way, I've renamed it to 'toret' or 'retd' (the latter short for 'returned') in line with my usual modern practice, but I haven't done a thorough job of finding all of them. Finally, one amusing side effect of doing this is that I've had to separate quite a few chained assignments. It used to be perfectly fine to write 'a = b = c = TRUE' when a,b,c were int and TRUE was just a the 'true' defined by stdbool.h, that idiom provokes a warning from gcc: 'suggest parentheses around assignment used as truth value'!
2018-11-02 22:23:19 +03:00
show_mouseptr(inst, true);
inst->eventlogstuff = eventlogstuff_new();
Remove the 'Frontend' type and replace it with a vtable. After the recent Seat and LogContext revamps, _nearly_ all the remaining uses of the type 'Frontend' were in terminal.c, which needs all sorts of interactions with the GUI window the terminal lives in, from the obvious (actually drawing text on the window, reading and writing the clipboard) to the obscure (minimising, maximising and moving the window in response to particular escape sequences). All of those functions are now provided by an abstraction called TermWin. The few remaining uses of Frontend after _that_ are internal to a particular platform directory, so as to spread the implementation of that particular kind of Frontend between multiple source files; so I've renamed all of those so that they take a more specifically named type that refers to the particular implementation rather than the general abstraction. So now the name 'Frontend' no longer exists in the code base at all, and everywhere one used to be used, it's completely clear whether it was operating in one of Frontend's three abstract roles (and if so, which), or whether it was specific to a particular implementation. Another type that's disappeared is 'Context', which used to be a typedef defined to something different on each platform, describing whatever short-lived resources were necessary to draw on the terminal window: the front end would provide a ready-made one when calling term_paint, and the terminal could request one with get_ctx/free_ctx if it wanted to do proactive window updates. Now that drawing context lives inside the TermWin itself, because there was never any need to have two of those contexts live at the same time. (Another minor API change is that the window-title functions - both reading and writing - have had a missing 'const' added to their char * parameters / return values.) I don't expect this change to enable any particularly interesting new functionality (in particular, I have no plans that need more than one implementation of TermWin in the same application). But it completes the tidying-up that began with the Seat and LogContext rework.
2018-10-25 20:44:04 +03:00
inst->term = term_init(inst->conf, &inst->ucsdata, &inst->termwin);
setup_clipboards(inst, inst->term, inst->conf);
Refactor the LogContext type. LogContext is now the owner of the logevent() function that back ends and so forth are constantly calling. Previously, logevent was owned by the Frontend, which would store the message into its list for the GUI Event Log dialog (or print it to standard error, or whatever) and then pass it _back_ to LogContext to write to the currently open log file. Now it's the other way round: LogContext gets the message from the back end first, writes it to its log file if it feels so inclined, and communicates it back to the front end. This means that lots of parts of the back end system no longer need to have a pointer to a full-on Frontend; the only thing they needed it for was logging, so now they just have a LogContext (which many of them had to have anyway, e.g. for logging SSH packets or session traffic). LogContext itself also doesn't get a full Frontend pointer any more: it now talks back to the front end via a little vtable of its own called LogPolicy, which contains the method that passes Event Log entries through, the old askappend() function that decides whether to truncate a pre-existing log file, and an emergency function for printing an especially prominent message if the log file can't be created. One minor nice effect of this is that console and GUI apps can implement that last function subtly differently, so that Unix console apps can write it with a plain \n instead of the \r\n (harmless but inelegant) that the old centralised implementation generated. One other consequence of this is that the LogContext has to be provided to backend_init() so that it's available to backends from the instant of creation, rather than being provided via a separate API call a couple of function calls later, because backends have typically started doing things that need logging (like making network connections) before the call to backend_provide_logctx. Fortunately, there's no case in the whole code base where we don't already have logctx by the time we make a backend (so I don't actually remember why I ever delayed providing one). So that shortens the backend API by one function, which is always nice. While I'm tidying up, I've also moved the printf-style logeventf() and the handy logevent_and_free() into logging.c, instead of having copies of them scattered around other places. This has also let me remove some stub functions from a couple of outlying applications like Pageant. Finally, I've removed the pointless "_tag" at the end of LogContext's official struct name.
2018-10-10 21:26:18 +03:00
inst->logctx = log_init(&inst->logpolicy, inst->conf);
term_provide_logctx(inst->term, inst->logctx);
Post-release destabilisation! Completely remove the struct type 'Config' in putty.h, which stores all PuTTY's settings and includes an arbitrary length limit on every single one of those settings which is stored in string form. In place of it is 'Conf', an opaque data type everywhere outside the new file conf.c, which stores a list of (key, value) pairs in which every key contains an integer identifying a configuration setting, and for some of those integers the key also contains extra parts (so that, for instance, CONF_environmt is a string-to-string mapping). Everywhere that a Config was previously used, a Conf is now; everywhere there was a Config structure copy, conf_copy() is called; every lookup, adjustment, load and save operation on a Config has been rewritten; and there's a mechanism for serialising a Conf into a binary blob and back for use with Duplicate Session. User-visible effects of this change _should_ be minimal, though I don't doubt I've introduced one or two bugs here and there which will eventually be found. The _intended_ visible effects of this change are that all arbitrary limits on configuration strings and lists (e.g. limit on number of port forwardings) should now disappear; that list boxes in the configuration will now be displayed in a sorted order rather than the arbitrary order in which they were added to the list (since the underlying data structure is now a sorted tree234 rather than an ad-hoc comma-separated string); and one more specific change, which is that local and dynamic port forwardings on the same port number are now mutually exclusive in the configuration (putting 'D' in the key rather than the value was a mistake in the first place). One other reorganisation as a result of this is that I've moved all the dialog.c standard handlers (dlg_stdeditbox_handler and friends) out into config.c, because I can't really justify calling them generic any more. When they took a pointer to an arbitrary structure type and the offset of a field within that structure, they were independent of whether that structure was a Config or something completely different, but now they really do expect to talk to a Conf, which can _only_ be used for PuTTY configuration, so I've renamed them all things like conf_editbox_handler and moved them out of the nominally independent dialog-box management module into the PuTTY-specific config.c. [originally from svn r9214]
2011-07-14 22:52:21 +04:00
term_size(inst->term, inst->height, inst->width,
conf_get_int(inst->conf, CONF_savelines));
inst->exited = false;
start_backend(inst);
if (inst->ldisc) /* early backend failure might make this NULL already */
ldisc_echoedit_update(inst->ldisc); /* cause ldisc to notice changes */
}