2002-10-07 20:45:23 +04:00
|
|
|
/*
|
2004-12-31 16:02:46 +03:00
|
|
|
* gtkwin.c: the main code that runs a PuTTY terminal emulator and
|
|
|
|
* backend in a GTK window.
|
2002-10-07 20:45:23 +04:00
|
|
|
*/
|
|
|
|
|
2002-10-23 18:21:12 +04:00
|
|
|
#define _GNU_SOURCE
|
|
|
|
|
2002-10-07 20:45:23 +04:00
|
|
|
#include <string.h>
|
2002-10-10 14:40:30 +04:00
|
|
|
#include <assert.h>
|
2002-10-07 20:45:23 +04:00
|
|
|
#include <stdlib.h>
|
2002-10-23 18:21:12 +04:00
|
|
|
#include <string.h>
|
2002-12-04 15:40:36 +03:00
|
|
|
#include <signal.h>
|
2002-10-09 22:09:42 +04:00
|
|
|
#include <stdio.h>
|
2002-10-07 20:45:23 +04:00
|
|
|
#include <time.h>
|
2002-10-10 16:40:05 +04:00
|
|
|
#include <errno.h>
|
2012-06-17 11:26:23 +04:00
|
|
|
#include <locale.h>
|
2002-10-10 16:40:05 +04:00
|
|
|
#include <fcntl.h>
|
|
|
|
#include <unistd.h>
|
2002-10-23 18:21:12 +04:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/wait.h>
|
2002-10-07 20:45:23 +04:00
|
|
|
#include <gtk/gtk.h>
|
2015-08-08 17:06:15 +03:00
|
|
|
#if !GTK_CHECK_VERSION(3,0,0)
|
2002-10-10 16:14:05 +04:00
|
|
|
#include <gdk/gdkkeysyms.h>
|
2015-08-08 17:06:15 +03:00
|
|
|
#endif
|
2002-10-07 20:45:23 +04:00
|
|
|
|
2012-06-17 11:26:23 +04:00
|
|
|
#if GTK_CHECK_VERSION(2,0,0)
|
|
|
|
#include <gtk/gtkimmodule.h>
|
|
|
|
#endif
|
|
|
|
|
2002-10-09 22:09:42 +04:00
|
|
|
#define PUTTY_DO_GLOBALS /* actually _define_ globals */
|
2002-12-31 15:20:34 +03:00
|
|
|
|
2013-01-14 01:59:10 +04:00
|
|
|
#define MAY_REFER_TO_GTK_IN_HEADERS
|
|
|
|
|
2002-10-09 22:09:42 +04:00
|
|
|
#include "putty.h"
|
2002-10-22 20:11:33 +04:00
|
|
|
#include "terminal.h"
|
2015-08-08 17:53:43 +03:00
|
|
|
#include "gtkcompat.h"
|
Refactor the font handling code: I've moved all the code that
explicitly deals with GdkFont out into a new module, behind a
polymorphic interface (done by ad-hoc explicit vtable management in
C). This should allow me to drop in a Pango font handling module in
parallel with the existing one, meaning that GTK2 PuTTY will be able
to seamlessly switch between X11 server-side fonts and Pango client-
side ones as the user chooses, or even use a mixture of the two
(e.g. an X11 font for narrow characters and a Pango one for wide
characters, or vice versa).
In the process, incidentally, I got to the bottom of the `weird bug'
mentioned in the old do_text_internal(). It's not a bug in
gdk_draw_text_wc() as I had thought: it's simply that GdkWChar is a
32-bit type rather than a 16-bit one, so no wonder you have to
specify twice the length to find all the characters in the string!
However, there _is_ a bug in GTK2's gdk_draw_text_wc(), which causes
it to strip off everything above the low byte of each GdkWChar,
sigh. Solution to both problems is to use an array of the underlying
Xlib type XChar2b instead, and pass it to gdk_draw_text() cast to
gchar *. Grotty, but it works. (And it'll become significantly less
grotty if and when we have to stop using the GDK font handling
wrappers in favour of going direct to Xlib.)
[originally from svn r7933]
2008-03-22 14:40:23 +03:00
|
|
|
#include "gtkfont.h"
|
2015-08-31 17:44:24 +03:00
|
|
|
#include "gtkmisc.h"
|
2002-10-09 22:09:42 +04:00
|
|
|
|
2015-08-31 15:05:51 +03:00
|
|
|
#ifndef NOT_X_WINDOWS
|
|
|
|
#include <gdk/gdkx.h>
|
|
|
|
#include <X11/Xlib.h>
|
|
|
|
#include <X11/Xutil.h>
|
|
|
|
#include <X11/Xatom.h>
|
|
|
|
#endif
|
|
|
|
|
2016-03-20 21:16:43 +03:00
|
|
|
#include "x11misc.h"
|
|
|
|
|
2004-11-28 18:13:34 +03:00
|
|
|
/* Colours come in two flavours: configurable, and xterm-extended. */
|
|
|
|
#define NEXTCOLOURS 240 /* 216 colour-cube plus 24 shades of grey */
|
|
|
|
#define NALLCOLOURS (NCFGCOLOURS + NEXTCOLOURS)
|
2002-10-10 14:40:30 +04:00
|
|
|
|
2003-04-11 21:40:52 +04:00
|
|
|
GdkAtom compound_text_atom, utf8_string_atom;
|
2018-03-03 21:18:54 +03:00
|
|
|
GdkAtom clipboard_atom
|
|
|
|
#if GTK_CHECK_VERSION(2,0,0) /* GTK1 will have to fill this in at startup */
|
|
|
|
= GDK_SELECTION_CLIPBOARD
|
|
|
|
#endif
|
|
|
|
;
|
2003-04-11 21:40:52 +04:00
|
|
|
|
2017-12-17 23:12:52 +03:00
|
|
|
#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
|
2015-09-02 23:37:33 +03:00
|
|
|
|
2017-12-10 13:23:39 +03:00
|
|
|
struct clipboard_state {
|
|
|
|
struct gui_data *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
|
|
|
|
};
|
|
|
|
|
2002-10-10 14:40:30 +04:00
|
|
|
struct gui_data {
|
2002-10-14 04:05:37 +04:00
|
|
|
GtkWidget *window, *area, *sbar;
|
2016-03-29 15:42:54 +03:00
|
|
|
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;
|
2018-05-17 13:20:01 +03:00
|
|
|
gboolean drawing_area_setup_needed;
|
2002-10-13 13:54:36 +04:00
|
|
|
GtkBox *hbox;
|
|
|
|
GtkAdjustment *sbar_adjust;
|
2004-08-14 17:04:18 +04:00
|
|
|
GtkWidget *menu, *specialsmenu, *specialsitem1, *specialsitem2,
|
|
|
|
*restartitem;
|
2003-04-12 21:37:15 +04:00
|
|
|
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
|
2015-08-16 11:02:31 +03:00
|
|
|
#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.
|
|
|
|
*/
|
2002-10-10 14:40:30 +04:00
|
|
|
GdkPixmap *pixmap;
|
2015-08-16 11:02:31 +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
|
|
|
#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
|
2012-06-17 11:26:23 +04:00
|
|
|
#if GTK_CHECK_VERSION(2,0,0)
|
|
|
|
GtkIMContext *imc;
|
|
|
|
#endif
|
Refactor the font handling code: I've moved all the code that
explicitly deals with GdkFont out into a new module, behind a
polymorphic interface (done by ad-hoc explicit vtable management in
C). This should allow me to drop in a Pango font handling module in
parallel with the existing one, meaning that GTK2 PuTTY will be able
to seamlessly switch between X11 server-side fonts and Pango client-
side ones as the user chooses, or even use a mixture of the two
(e.g. an X11 font for narrow characters and a Pango one for wide
characters, or vice versa).
In the process, incidentally, I got to the bottom of the `weird bug'
mentioned in the old do_text_internal(). It's not a bug in
gdk_draw_text_wc() as I had thought: it's simply that GdkWChar is a
32-bit type rather than a 16-bit one, so no wonder you have to
specify twice the length to find all the characters in the string!
However, there _is_ a bug in GTK2's gdk_draw_text_wc(), which causes
it to strip off everything above the low byte of each GdkWChar,
sigh. Solution to both problems is to use an array of the underlying
Xlib type XChar2b instead, and pass it to gdk_draw_text() cast to
gchar *. Grotty, but it works. (And it'll become significantly less
grotty if and when we have to stop using the GDK font handling
wrappers in favour of going direct to Xlib.)
[originally from svn r7933]
2008-03-22 14:40:23 +03:00
|
|
|
unifont *fonts[4]; /* normal, bold, wide, widebold */
|
2003-04-08 17:49:12 +04:00
|
|
|
int xpos, ypos, gotpos, gravity;
|
2005-02-15 20:05:58 +03:00
|
|
|
GdkCursor *rawcursor, *textcursor, *blankcursor, *waitcursor, *currcursor;
|
2004-11-28 18:13:34 +03:00
|
|
|
GdkColor cols[NALLCOLOURS];
|
2015-08-16 16:22:14 +03:00
|
|
|
#if !GTK_CHECK_VERSION(3,0,0)
|
2002-10-10 14:40:30 +04:00
|
|
|
GdkColormap *colmap;
|
2015-08-16 16:22:14 +03:00
|
|
|
#endif
|
2003-01-02 19:17:56 +03:00
|
|
|
int direct_to_font;
|
2017-12-10 13:23:39 +03:00
|
|
|
struct clipboard_state clipstates[N_CLIPBOARDS];
|
2017-12-17 23:12:52 +03:00
|
|
|
#ifdef JUST_USE_GTK_CLIPBOARD_UTF8
|
|
|
|
/* Remember all clipboard_data_instance structures currently
|
|
|
|
* associated with this gui_data, in case they're still around
|
|
|
|
* when it gets destroyed */
|
|
|
|
struct clipboard_data_instance cdi_headtail;
|
|
|
|
#endif
|
2017-12-17 21:44:27 +03:00
|
|
|
int clipboard_ctrlshiftins, clipboard_ctrlshiftcv;
|
2002-10-10 18:42:56 +04:00
|
|
|
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;
|
2002-10-13 16:44:01 +04:00
|
|
|
int ignore_sbar;
|
2002-10-15 03:39:07 +04:00
|
|
|
int mouseptr_visible;
|
2005-02-15 20:05:58 +03:00
|
|
|
int busy_status;
|
2002-10-15 21:18:24 +04:00
|
|
|
int alt_keycode;
|
2002-10-28 20:34:45 +03:00
|
|
|
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;
|
2003-03-29 21:30:14 +03:00
|
|
|
int master_fd, master_func_id;
|
2002-10-26 14:16:19 +04:00
|
|
|
void *ldisc;
|
2002-10-26 14:33:59 +04:00
|
|
|
Backend *back;
|
|
|
|
void *backhandle;
|
2002-10-26 15:08:59 +04:00
|
|
|
Terminal *term;
|
2002-10-26 16:58:13 +04:00
|
|
|
void *logctx;
|
2003-03-29 21:30:14 +03:00
|
|
|
int exited;
|
2003-01-14 21:28:23 +03:00
|
|
|
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;
|
2003-04-09 22:46:45 +04:00
|
|
|
void *eventlogstuff;
|
2003-08-21 22:03:06 +04:00
|
|
|
guint32 input_event_time; /* Timestamp of the most recent input event. */
|
2017-11-26 19:51:19 +03:00
|
|
|
GtkWidget *dialogs[DIALOG_SLOT_LIMIT];
|
2015-09-25 17:11:44 +03:00
|
|
|
#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 */
|
2012-06-09 19:09:22 +04:00
|
|
|
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;
|
2015-09-01 21:00:25 +03:00
|
|
|
int meta_mod_mask;
|
2017-12-18 13:43:13 +03:00
|
|
|
#ifdef OSX_META_KEY_CONFIG
|
|
|
|
int system_mod_mask;
|
|
|
|
#endif
|
2002-10-26 16:58:13 +04:00
|
|
|
};
|
|
|
|
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 22:52:21 +04:00
|
|
|
static void cache_conf_values(struct gui_data *inst)
|
|
|
|
{
|
2012-06-09 19:09:22 +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);
|
2015-09-01 21:00:25 +03:00
|
|
|
#ifdef OSX_META_KEY_CONFIG
|
|
|
|
inst->meta_mod_mask = 0;
|
|
|
|
if (conf_get_int(inst->conf, CONF_osx_option_meta))
|
|
|
|
inst->meta_mod_mask |= GDK_MOD1_MASK;
|
|
|
|
if (conf_get_int(inst->conf, CONF_osx_command_meta))
|
|
|
|
inst->meta_mod_mask |= GDK_MOD2_MASK;
|
2017-12-18 13:43:13 +03:00
|
|
|
inst->system_mod_mask = GDK_MOD2_MASK & ~inst->meta_mod_mask;
|
2015-09-01 21:00:25 +03:00
|
|
|
#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
|
|
|
}
|
|
|
|
|
2002-10-26 16:58:13 +04:00
|
|
|
struct draw_ctx {
|
|
|
|
struct gui_data *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
|
|
|
unifont_drawctx uctx;
|
2002-10-10 14:40:30 +04:00
|
|
|
};
|
|
|
|
|
|
|
|
static int send_raw_mouse;
|
|
|
|
|
2004-08-14 17:04:18 +04:00
|
|
|
static void start_backend(struct gui_data *inst);
|
2013-08-17 20:06:22 +04:00
|
|
|
static void exit_callback(void *vinst);
|
2017-11-26 22:59:24 +03:00
|
|
|
static void destroy_inst_connection(struct gui_data *inst);
|
|
|
|
static void delete_inst(struct gui_data *inst);
|
|
|
|
|
|
|
|
static void post_fatal_message_box_toplevel(void *vctx)
|
|
|
|
{
|
|
|
|
struct gui_data *inst = (struct gui_data *)vctx;
|
|
|
|
gtk_widget_destroy(inst->window);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void post_fatal_message_box(void *vctx, int result)
|
|
|
|
{
|
|
|
|
struct gui_data *inst = (struct gui_data *)vctx;
|
|
|
|
unregister_dialog(inst, DIALOG_SLOT_CONNECTION_FATAL);
|
|
|
|
queue_toplevel_callback(post_fatal_message_box_toplevel, inst);
|
|
|
|
}
|
|
|
|
|
|
|
|
void fatal_message_box(struct gui_data *inst, const char *msg)
|
|
|
|
{
|
|
|
|
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, post_fatal_message_box, inst);
|
|
|
|
register_dialog(inst, DIALOG_SLOT_CONNECTION_FATAL, dialog);
|
|
|
|
sfree(title);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void connection_fatal_callback(void *vinst)
|
|
|
|
{
|
|
|
|
struct gui_data *inst = (struct gui_data *)vinst;
|
|
|
|
destroy_inst_connection(inst);
|
|
|
|
}
|
2004-08-14 17:04:18 +04:00
|
|
|
|
2015-05-15 13:15:42 +03:00
|
|
|
void connection_fatal(void *frontend, const char *p, ...)
|
2003-04-01 22:10:25 +04:00
|
|
|
{
|
Rationalisation of the system of frontend handles. Most modular bits
of PuTTY (terminal, backend, logctx etc) take a `void *' handle
passed to them from the frontend, and used as a context for all
their callbacks. Most of these point at the frontend structure
itself (on platforms where this is meaningful), except that the
handle passed to the backend has always pointed at the terminal
because from_backend() was implemented in terminal.c. This has
finally bitten Unix PuTTY, because both backend and logctx have
been passing their respective and very different frontend handles to
logevent(), so I've fixed it.
from_backend() is now a function supplied by the _frontend_ itself,
in all cases, and the frontend handle passed to backends must be the
same as that passed to everything else. What was from_backend() in
terminal.c is now called term_data(), and the typical implementation
of from_backend() in a GUI frontend will just extract the terminal
handle from the frontend structure and delegate to that.
This appears to work on Unix and Windows, but has most likely broken
the Mac build.
[originally from svn r3100]
2003-04-11 22:36:27 +04:00
|
|
|
struct gui_data *inst = (struct gui_data *)frontend;
|
2003-04-01 22:10:25 +04:00
|
|
|
|
|
|
|
va_list ap;
|
|
|
|
char *msg;
|
|
|
|
va_start(ap, p);
|
|
|
|
msg = dupvprintf(p, ap);
|
|
|
|
va_end(ap);
|
2017-11-26 22:59:24 +03:00
|
|
|
fatal_message_box(inst, msg);
|
2003-04-01 22:10:25 +04:00
|
|
|
sfree(msg);
|
2013-08-17 20:06:22 +04:00
|
|
|
|
2017-11-26 22:59:24 +03:00
|
|
|
inst->exited = TRUE; /* suppress normal exit handling */
|
|
|
|
queue_toplevel_callback(connection_fatal_callback, frontend);
|
2003-04-01 22:10:25 +04:00
|
|
|
}
|
|
|
|
|
2003-01-09 21:06:29 +03:00
|
|
|
/*
|
|
|
|
* Default settings that are specific to pterm.
|
|
|
|
*/
|
2011-10-01 21:38:59 +04:00
|
|
|
FontSpec *platform_default_fontspec(const char *name)
|
2003-01-09 21:06:29 +03:00
|
|
|
{
|
|
|
|
if (!strcmp(name, "Font"))
|
2015-08-31 15:24:09 +03:00
|
|
|
return fontspec_new(DEFAULT_GTK_FONT);
|
2003-02-01 15:54:40 +03:00
|
|
|
else
|
2011-10-01 21:38:59 +04:00
|
|
|
return fontspec_new("");
|
2003-02-01 15:54:40 +03:00
|
|
|
}
|
|
|
|
|
2011-10-02 15:01:57 +04:00
|
|
|
Filename *platform_default_filename(const char *name)
|
2003-02-01 15:54:40 +03:00
|
|
|
{
|
|
|
|
if (!strcmp(name, "LogFileName"))
|
2011-10-02 15:01:57 +04:00
|
|
|
return filename_from_str("putty.log");
|
2003-02-01 15:54:40 +03:00
|
|
|
else
|
2011-10-02 15:01:57 +04:00
|
|
|
return filename_from_str("");
|
2003-02-01 15:54:40 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
char *platform_default_s(const char *name)
|
|
|
|
{
|
2006-08-28 18:29:02 +04:00
|
|
|
if (!strcmp(name, "SerialLine"))
|
|
|
|
return dupstr("/dev/ttyS0");
|
2003-01-09 21:06:29 +03:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2003-01-14 21:43:45 +03:00
|
|
|
int platform_default_i(const char *name, int def)
|
2003-01-09 21:06:29 +03:00
|
|
|
{
|
|
|
|
if (!strcmp(name, "CloseOnExit"))
|
2003-01-28 15:06:37 +03:00
|
|
|
return 2; /* maps to FORCE_ON after painful rearrangement :-( */
|
2003-04-26 17:55:47 +04:00
|
|
|
if (!strcmp(name, "WinNameAlways"))
|
|
|
|
return 0; /* X natively supports icon titles, so use 'em by default */
|
2003-01-09 21:06:29 +03:00
|
|
|
return def;
|
|
|
|
}
|
|
|
|
|
2009-08-22 03:25:48 +04:00
|
|
|
/* Dummy routine, only required in plink. */
|
Move echo/edit state change functionality out of ldisc_send.
I'm not actually sure why we've always had back ends notify ldisc of
changes to echo/edit settings by giving ldisc_send(ldisc,NULL,0,0) a
special meaning, instead of by having a separate dedicated notify
function with its own prototype and parameter set. Coverity's recent
observation that the two kinds of call don't even have the same
requirements on the ldisc (particularly, whether ldisc->term can be
NULL) makes me realise that it's really high time I separated the two
conceptually different operations into actually different functions.
While I'm here, I've renamed the confusing ldisc_update() function
which that special operation ends up feeding to, because it's not
actually a function applying to an ldisc - it applies to a front end.
So ldisc_send(ldisc,NULL,0,0) is now ldisc_echoedit_update(ldisc), and
that in turn figures out the current echo/edit settings before passing
them on to frontend_echoedit_update(). I think that should be clearer.
2014-11-22 19:12:47 +03:00
|
|
|
void frontend_echoedit_update(void *frontend, int echo, int edit)
|
2002-10-09 22:09:42 +04:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2005-04-21 17:57:08 +04:00
|
|
|
char *get_ttymode(void *frontend, const char *mode)
|
|
|
|
{
|
|
|
|
struct gui_data *inst = (struct gui_data *)frontend;
|
|
|
|
return term_get_ttymode(inst->term, mode);
|
|
|
|
}
|
|
|
|
|
2018-05-26 10:31:34 +03:00
|
|
|
int from_backend(void *frontend, int is_stderr, const void *data, int len)
|
Rationalisation of the system of frontend handles. Most modular bits
of PuTTY (terminal, backend, logctx etc) take a `void *' handle
passed to them from the frontend, and used as a context for all
their callbacks. Most of these point at the frontend structure
itself (on platforms where this is meaningful), except that the
handle passed to the backend has always pointed at the terminal
because from_backend() was implemented in terminal.c. This has
finally bitten Unix PuTTY, because both backend and logctx have
been passing their respective and very different frontend handles to
logevent(), so I've fixed it.
from_backend() is now a function supplied by the _frontend_ itself,
in all cases, and the frontend handle passed to backends must be the
same as that passed to everything else. What was from_backend() in
terminal.c is now called term_data(), and the typical implementation
of from_backend() in a GUI frontend will just extract the terminal
handle from the frontend structure and delegate to that.
This appears to work on Unix and Windows, but has most likely broken
the Mac build.
[originally from svn r3100]
2003-04-11 22:36:27 +04:00
|
|
|
{
|
|
|
|
struct gui_data *inst = (struct gui_data *)frontend;
|
|
|
|
return term_data(inst->term, is_stderr, data, len);
|
|
|
|
}
|
|
|
|
|
2018-05-26 10:31:34 +03:00
|
|
|
int from_backend_untrusted(void *frontend, const void *data, int len)
|
2005-10-30 23:24:09 +03:00
|
|
|
{
|
|
|
|
struct gui_data *inst = (struct gui_data *)frontend;
|
|
|
|
return term_data_untrusted(inst->term, data, len);
|
|
|
|
}
|
|
|
|
|
2011-09-13 15:44:03 +04:00
|
|
|
int from_backend_eof(void *frontend)
|
|
|
|
{
|
|
|
|
return TRUE; /* do respond to incoming EOF with outgoing */
|
|
|
|
}
|
|
|
|
|
2018-05-18 09:22:57 +03:00
|
|
|
int get_userpass_input(prompts_t *p, bufchain *input)
|
2005-10-30 23:24:09 +03:00
|
|
|
{
|
|
|
|
struct gui_data *inst = (struct gui_data *)p->frontend;
|
|
|
|
int ret;
|
2018-05-18 09:22:56 +03:00
|
|
|
ret = cmdline_get_passwd_input(p);
|
2005-10-30 23:24:09 +03:00
|
|
|
if (ret == -1)
|
2018-05-18 09:22:57 +03:00
|
|
|
ret = term_get_userpass_input(inst->term, p, input);
|
2005-10-30 23:24:09 +03:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2003-05-04 18:18:18 +04:00
|
|
|
void logevent(void *frontend, const char *string)
|
2002-10-09 22:09:42 +04:00
|
|
|
{
|
Rationalisation of the system of frontend handles. Most modular bits
of PuTTY (terminal, backend, logctx etc) take a `void *' handle
passed to them from the frontend, and used as a context for all
their callbacks. Most of these point at the frontend structure
itself (on platforms where this is meaningful), except that the
handle passed to the backend has always pointed at the terminal
because from_backend() was implemented in terminal.c. This has
finally bitten Unix PuTTY, because both backend and logctx have
been passing their respective and very different frontend handles to
logevent(), so I've fixed it.
from_backend() is now a function supplied by the _frontend_ itself,
in all cases, and the frontend handle passed to backends must be the
same as that passed to everything else. What was from_backend() in
terminal.c is now called term_data(), and the typical implementation
of from_backend() in a GUI frontend will just extract the terminal
handle from the frontend structure and delegate to that.
This appears to work on Unix and Windows, but has most likely broken
the Mac build.
[originally from svn r3100]
2003-04-11 22:36:27 +04:00
|
|
|
struct gui_data *inst = (struct gui_data *)frontend;
|
2003-04-09 22:46:45 +04:00
|
|
|
|
|
|
|
log_eventlog(inst->logctx, string);
|
|
|
|
|
|
|
|
logevent_dlg(inst->eventlogstuff, string);
|
2002-10-09 22:09:42 +04:00
|
|
|
}
|
|
|
|
|
2002-10-26 16:58:13 +04:00
|
|
|
int font_dimension(void *frontend, int which)/* 0 for width, 1 for height */
|
2002-10-15 19:16:21 +04:00
|
|
|
{
|
2002-10-26 16:58:13 +04:00
|
|
|
struct gui_data *inst = (struct gui_data *)frontend;
|
|
|
|
|
2002-10-15 19:16:21 +04:00
|
|
|
if (which)
|
|
|
|
return inst->font_height;
|
|
|
|
else
|
|
|
|
return inst->font_width;
|
|
|
|
}
|
|
|
|
|
2002-10-09 22:09:42 +04:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
2003-01-25 19:23:48 +03:00
|
|
|
static Mouse_Button translate_button(Mouse_Button button)
|
2002-10-09 22:09:42 +04:00
|
|
|
{
|
2002-10-26 16:58:13 +04:00
|
|
|
/* struct gui_data *inst = (struct gui_data *)frontend; */
|
|
|
|
|
2002-10-09 22:09:42 +04:00
|
|
|
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 */
|
|
|
|
}
|
|
|
|
|
2003-03-31 15:21:07 +04:00
|
|
|
/*
|
|
|
|
* Return the top-level GtkWindow associated with a particular
|
|
|
|
* front end instance.
|
|
|
|
*/
|
2017-11-26 17:55:15 +03:00
|
|
|
GtkWidget *get_window(void *frontend)
|
2003-03-31 15:21:07 +04:00
|
|
|
{
|
Rationalisation of the system of frontend handles. Most modular bits
of PuTTY (terminal, backend, logctx etc) take a `void *' handle
passed to them from the frontend, and used as a context for all
their callbacks. Most of these point at the frontend structure
itself (on platforms where this is meaningful), except that the
handle passed to the backend has always pointed at the terminal
because from_backend() was implemented in terminal.c. This has
finally bitten Unix PuTTY, because both backend and logctx have
been passing their respective and very different frontend handles to
logevent(), so I've fixed it.
from_backend() is now a function supplied by the _frontend_ itself,
in all cases, and the frontend handle passed to backends must be the
same as that passed to everything else. What was from_backend() in
terminal.c is now called term_data(), and the typical implementation
of from_backend() in a GUI frontend will just extract the terminal
handle from the frontend structure and delegate to that.
This appears to work on Unix and Windows, but has most likely broken
the Mac build.
[originally from svn r3100]
2003-04-11 22:36:27 +04:00
|
|
|
struct gui_data *inst = (struct gui_data *)frontend;
|
2003-03-31 15:21:07 +04:00
|
|
|
return inst->window;
|
|
|
|
}
|
|
|
|
|
2017-11-26 17:55:15 +03:00
|
|
|
/*
|
|
|
|
* 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?').
|
|
|
|
*/
|
2017-11-26 19:51:19 +03:00
|
|
|
void register_dialog(void *frontend, enum DialogSlot slot, GtkWidget *dialog)
|
2017-11-26 17:55:15 +03:00
|
|
|
{
|
|
|
|
struct gui_data *inst = (struct gui_data *)frontend;
|
2017-11-26 19:51:19 +03:00
|
|
|
assert(slot < DIALOG_SLOT_LIMIT);
|
|
|
|
assert(!inst->dialogs[slot]);
|
|
|
|
inst->dialogs[slot] = dialog;
|
2017-11-26 17:55:15 +03:00
|
|
|
}
|
2017-11-26 19:51:19 +03:00
|
|
|
void unregister_dialog(void *frontend, enum DialogSlot slot)
|
2017-11-26 17:55:15 +03:00
|
|
|
{
|
|
|
|
struct gui_data *inst = (struct gui_data *)frontend;
|
2017-11-26 19:51:19 +03:00
|
|
|
assert(slot < DIALOG_SLOT_LIMIT);
|
|
|
|
assert(inst->dialogs[slot]);
|
|
|
|
inst->dialogs[slot] = NULL;
|
2017-11-26 17:55:15 +03:00
|
|
|
}
|
|
|
|
|
2002-10-09 22:09:42 +04:00
|
|
|
/*
|
|
|
|
* Minimise or restore the window in response to a server-side
|
|
|
|
* request.
|
|
|
|
*/
|
2002-10-26 16:58:13 +04:00
|
|
|
void set_iconic(void *frontend, int iconic)
|
2002-10-09 22:09:42 +04:00
|
|
|
{
|
2002-10-15 18:31:06 +04:00
|
|
|
/*
|
|
|
|
* GTK 1.2 doesn't know how to do this.
|
|
|
|
*/
|
|
|
|
#if GTK_CHECK_VERSION(2,0,0)
|
2002-10-26 16:58:13 +04:00
|
|
|
struct gui_data *inst = (struct gui_data *)frontend;
|
2002-10-15 18:31:06 +04:00
|
|
|
if (iconic)
|
|
|
|
gtk_window_iconify(GTK_WINDOW(inst->window));
|
|
|
|
else
|
|
|
|
gtk_window_deiconify(GTK_WINDOW(inst->window));
|
|
|
|
#endif
|
2002-10-09 22:09:42 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Move the window in response to a server-side request.
|
|
|
|
*/
|
2002-10-26 16:58:13 +04:00
|
|
|
void move_window(void *frontend, int x, int y)
|
2002-10-09 22:09:42 +04:00
|
|
|
{
|
2002-10-26 16:58:13 +04:00
|
|
|
struct gui_data *inst = (struct gui_data *)frontend;
|
2002-10-15 18:31:06 +04:00
|
|
|
/*
|
|
|
|
* 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)
|
2016-04-04 13:27:01 +03:00
|
|
|
/* in case we reset this at startup due to a geometry string */
|
|
|
|
gtk_window_set_gravity(GTK_WINDOW(inst->window), GDK_GRAVITY_NORTH_EAST);
|
2002-10-15 18:31:06 +04:00
|
|
|
gtk_window_move(GTK_WINDOW(inst->window), x, y);
|
|
|
|
#else
|
2015-08-08 17:53:43 +03:00
|
|
|
gdk_window_move(gtk_widget_get_window(inst->window), x, y);
|
2002-10-15 18:31:06 +04:00
|
|
|
#endif
|
2002-10-09 22:09:42 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Move the window to the top or bottom of the z-order in response
|
|
|
|
* to a server-side request.
|
|
|
|
*/
|
2002-10-26 16:58:13 +04:00
|
|
|
void set_zorder(void *frontend, int top)
|
2002-10-09 22:09:42 +04:00
|
|
|
{
|
2002-10-26 16:58:13 +04:00
|
|
|
struct gui_data *inst = (struct gui_data *)frontend;
|
2002-10-15 18:31:06 +04:00
|
|
|
if (top)
|
2015-08-08 17:53:43 +03:00
|
|
|
gdk_window_raise(gtk_widget_get_window(inst->window));
|
2002-10-15 18:31:06 +04:00
|
|
|
else
|
2015-08-08 17:53:43 +03:00
|
|
|
gdk_window_lower(gtk_widget_get_window(inst->window));
|
2002-10-09 22:09:42 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Refresh the window in response to a server-side request.
|
|
|
|
*/
|
2002-10-26 16:58:13 +04:00
|
|
|
void refresh_window(void *frontend)
|
2002-10-09 22:09:42 +04:00
|
|
|
{
|
2002-10-26 16:58:13 +04:00
|
|
|
struct gui_data *inst = (struct gui_data *)frontend;
|
2002-10-26 15:08:59 +04:00
|
|
|
term_invalidate(inst->term);
|
2002-10-09 22:09:42 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Maximise or restore the window in response to a server-side
|
|
|
|
* request.
|
|
|
|
*/
|
2002-10-26 16:58:13 +04:00
|
|
|
void set_zoomed(void *frontend, int zoomed)
|
2002-10-09 22:09:42 +04:00
|
|
|
{
|
2002-10-15 18:31:06 +04:00
|
|
|
/*
|
|
|
|
* GTK 1.2 doesn't know how to do this.
|
|
|
|
*/
|
|
|
|
#if GTK_CHECK_VERSION(2,0,0)
|
2002-10-26 16:58:13 +04:00
|
|
|
struct gui_data *inst = (struct gui_data *)frontend;
|
2007-01-25 22:33:29 +03:00
|
|
|
if (zoomed)
|
2002-10-15 18:31:06 +04:00
|
|
|
gtk_window_maximize(GTK_WINDOW(inst->window));
|
|
|
|
else
|
|
|
|
gtk_window_unmaximize(GTK_WINDOW(inst->window));
|
|
|
|
#endif
|
2002-10-09 22:09:42 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Report whether the window is iconic, for terminal reports.
|
|
|
|
*/
|
2002-10-26 16:58:13 +04:00
|
|
|
int is_iconic(void *frontend)
|
2002-10-09 22:09:42 +04:00
|
|
|
{
|
2002-10-26 16:58:13 +04:00
|
|
|
struct gui_data *inst = (struct gui_data *)frontend;
|
2015-08-08 17:53:43 +03:00
|
|
|
return !gdk_window_is_viewable(gtk_widget_get_window(inst->window));
|
2002-10-09 22:09:42 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Report the window's position, for terminal reports.
|
|
|
|
*/
|
2002-10-26 16:58:13 +04:00
|
|
|
void get_window_pos(void *frontend, int *x, int *y)
|
2002-10-09 22:09:42 +04:00
|
|
|
{
|
2002-10-26 16:58:13 +04:00
|
|
|
struct gui_data *inst = (struct gui_data *)frontend;
|
2002-10-15 18:31:06 +04:00
|
|
|
/*
|
|
|
|
* 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
|
2015-08-08 17:53:43 +03:00
|
|
|
gdk_window_get_position(gtk_widget_get_window(inst->window), x, y);
|
2002-10-15 18:31:06 +04:00
|
|
|
#endif
|
2002-10-09 22:09:42 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Report the window's pixel size, for terminal reports.
|
|
|
|
*/
|
2002-10-26 16:58:13 +04:00
|
|
|
void get_window_pixels(void *frontend, int *x, int *y)
|
2002-10-09 22:09:42 +04:00
|
|
|
{
|
2002-10-26 16:58:13 +04:00
|
|
|
struct gui_data *inst = (struct gui_data *)frontend;
|
2002-10-15 18:31:06 +04:00
|
|
|
/*
|
|
|
|
* 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
|
2015-08-08 17:53:43 +03:00
|
|
|
gdk_window_get_size(gtk_widget_get_window(inst->window), x, y);
|
2002-10-15 18:31:06 +04:00
|
|
|
#endif
|
2002-10-09 22:09:42 +04:00
|
|
|
}
|
|
|
|
|
2017-11-26 20:21:32 +03:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
static int find_and_raise_dialog(struct gui_data *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;
|
|
|
|
}
|
|
|
|
|
2002-10-09 22:09:42 +04:00
|
|
|
/*
|
|
|
|
* Return the window or icon title.
|
|
|
|
*/
|
2002-10-26 16:58:13 +04:00
|
|
|
char *get_window_title(void *frontend, int icon)
|
2002-10-09 22:09:42 +04:00
|
|
|
{
|
2002-10-26 16:58:13 +04:00
|
|
|
struct gui_data *inst = (struct gui_data *)frontend;
|
2003-05-10 13:05:41 +04:00
|
|
|
return icon ? inst->icontitle : inst->wintitle;
|
2002-10-09 22:09:42 +04:00
|
|
|
}
|
2002-10-07 20:45:23 +04:00
|
|
|
|
2017-11-26 20:21:32 +03:00
|
|
|
static void warn_on_close_callback(void *vctx, int result)
|
|
|
|
{
|
|
|
|
struct gui_data *inst = (struct gui_data *)vctx;
|
|
|
|
unregister_dialog(inst, 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'.)
|
|
|
|
*/
|
2002-10-07 20:45:23 +04:00
|
|
|
gint delete_window(GtkWidget *widget, GdkEvent *event, gpointer data)
|
|
|
|
{
|
2003-04-11 22:15:47 +04:00
|
|
|
struct gui_data *inst = (struct gui_data *)data;
|
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->exited && conf_get_int(inst->conf, CONF_warn_on_close)) {
|
2017-11-26 20:21:32 +03:00
|
|
|
/*
|
|
|
|
* 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);
|
|
|
|
register_dialog(inst, DIALOG_SLOT_WARN_ON_CLOSE, dialog);
|
|
|
|
sfree(title);
|
|
|
|
}
|
|
|
|
return TRUE;
|
2003-04-11 22:15:47 +04:00
|
|
|
}
|
2002-10-07 20:45:23 +04:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2005-02-15 20:05:58 +03:00
|
|
|
static void update_mouseptr(struct gui_data *inst)
|
|
|
|
{
|
|
|
|
switch (inst->busy_status) {
|
|
|
|
case BUSY_NOT:
|
|
|
|
if (!inst->mouseptr_visible) {
|
2015-08-08 17:53:43 +03:00
|
|
|
gdk_window_set_cursor(gtk_widget_get_window(inst->area),
|
|
|
|
inst->blankcursor);
|
2005-02-15 20:05:58 +03:00
|
|
|
} else if (send_raw_mouse) {
|
2015-08-08 17:53:43 +03:00
|
|
|
gdk_window_set_cursor(gtk_widget_get_window(inst->area),
|
|
|
|
inst->rawcursor);
|
2005-02-15 20:05:58 +03:00
|
|
|
} else {
|
2015-08-08 17:53:43 +03:00
|
|
|
gdk_window_set_cursor(gtk_widget_get_window(inst->area),
|
|
|
|
inst->textcursor);
|
2005-02-15 20:05:58 +03:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case BUSY_WAITING: /* XXX can we do better? */
|
|
|
|
case BUSY_CPU:
|
|
|
|
/* We always display these cursors. */
|
2015-08-08 17:53:43 +03:00
|
|
|
gdk_window_set_cursor(gtk_widget_get_window(inst->area),
|
|
|
|
inst->waitcursor);
|
2005-02-15 20:05:58 +03:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
assert(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-10-26 16:58:13 +04:00
|
|
|
static void show_mouseptr(struct gui_data *inst, int show)
|
2002-10-14 13:58:27 +04:00
|
|
|
{
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 22:52:21 +04:00
|
|
|
if (!conf_get_int(inst->conf, CONF_hide_mouseptr))
|
2002-10-14 13:58:27 +04:00
|
|
|
show = 1;
|
2002-10-15 03:39:07 +04:00
|
|
|
inst->mouseptr_visible = show;
|
2005-02-15 20:05:58 +03:00
|
|
|
update_mouseptr(inst);
|
2002-10-14 13:58:27 +04:00
|
|
|
}
|
|
|
|
|
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
|
|
|
static void draw_backing_rect(struct gui_data *inst);
|
2003-05-13 22:14:14 +04: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
|
|
|
static void drawing_area_setup(struct gui_data *inst, int width, int height)
|
2002-10-07 20:45:23 +04:00
|
|
|
{
|
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 w, h, new_scale, need_size = 0;
|
2002-10-07 20:45:23 +04:00
|
|
|
|
2003-04-12 15:03:44 +04:00
|
|
|
/*
|
2018-05-19 09:38:22 +03:00
|
|
|
* See if the terminal size has changed.
|
2003-04-12 15:03:44 +04: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
|
|
|
w = (width - 2*inst->window_border) / inst->font_width;
|
|
|
|
h = (height - 2*inst->window_border) / inst->font_height;
|
2003-04-10 22:00:50 +04:00
|
|
|
if (w != inst->width || h != inst->height) {
|
2018-05-19 09:38:22 +03:00
|
|
|
/*
|
|
|
|
* 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);
|
2018-05-19 09:38:22 +03:00
|
|
|
/*
|
|
|
|
* We'll need to tell terminal.c about the resize below.
|
|
|
|
*/
|
|
|
|
need_size = TRUE;
|
|
|
|
/*
|
|
|
|
* And we must refresh the window's backing image.
|
|
|
|
*/
|
2018-05-17 13:20:01 +03:00
|
|
|
inst->drawing_area_setup_needed = TRUE;
|
2002-10-13 16:44:01 +04:00
|
|
|
}
|
2003-04-12 15:03:44 +04:00
|
|
|
|
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);
|
2018-05-17 13:20:01 +03:00
|
|
|
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
|
|
|
|
|
2018-04-03 20:57:00 +03:00
|
|
|
/*
|
2018-05-17 13:20:01 +03:00
|
|
|
* 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.
|
2018-04-03 20:57:00 +03:00
|
|
|
*/
|
2018-05-17 13:20:01 +03:00
|
|
|
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;
|
2018-05-17 13:20:01 +03:00
|
|
|
|
|
|
|
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;
|
2018-04-03 20:57:00 +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
|
|
|
{
|
|
|
|
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;
|
|
|
|
|
2015-08-16 11:02:31 +03:00
|
|
|
#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;
|
|
|
|
}
|
2002-10-07 20:45:23 +04: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
|
|
|
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);
|
2015-08-16 11:02:31 +03:00
|
|
|
#endif
|
2003-04-12 15:03:44 +04: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
|
|
|
#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
|
|
|
|
}
|
|
|
|
|
2003-05-13 22:14:14 +04:00
|
|
|
draw_backing_rect(inst);
|
2003-04-12 15:03:44 +04:00
|
|
|
|
|
|
|
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));
|
2002-10-13 16:44:01 +04:00
|
|
|
}
|
|
|
|
|
2003-04-12 15:03:44 +04:00
|
|
|
if (inst->term)
|
|
|
|
term_invalidate(inst->term);
|
|
|
|
|
2012-06-17 11:26:23 +04:00
|
|
|
#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));
|
2012-06-17 11:26:23 +04:00
|
|
|
#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
|
|
|
}
|
2012-06-17 11:26:23 +04:00
|
|
|
|
2018-05-11 11:00:46 +03:00
|
|
|
static void drawing_area_setup_simple(struct gui_data *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);
|
|
|
|
}
|
|
|
|
|
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_realised(GtkWidget *widget, gpointer data)
|
|
|
|
{
|
|
|
|
struct gui_data *inst = (struct gui_data *)data;
|
|
|
|
|
|
|
|
inst->drawing_area_realised = TRUE;
|
|
|
|
if (inst->drawing_area_realised && inst->drawing_area_got_size &&
|
2018-05-17 13:20:01 +03:00
|
|
|
inst->drawing_area_setup_needed)
|
2018-05-11 11:00:46 +03:00
|
|
|
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(
|
|
|
|
GtkWidget *widget, GdkRectangle *alloc, gpointer data)
|
|
|
|
{
|
|
|
|
struct gui_data *inst = (struct gui_data *)data;
|
|
|
|
|
|
|
|
inst->drawing_area_got_size = TRUE;
|
|
|
|
if (inst->drawing_area_realised && inst->drawing_area_got_size)
|
|
|
|
drawing_area_setup(inst, alloc->width, alloc->height);
|
2002-10-07 20:45:23 +04:00
|
|
|
}
|
|
|
|
|
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)
|
|
|
|
static void area_check_scale(struct gui_data *inst)
|
|
|
|
{
|
2018-05-17 13:20:01 +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)
|
|
|
|
{
|
|
|
|
struct gui_data *inst = (struct gui_data *)data;
|
|
|
|
area_check_scale(inst);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2015-08-16 16:34:19 +03:00
|
|
|
#ifdef DRAW_TEXT_CAIRO
|
|
|
|
static void cairo_setup_dctx(struct draw_ctx *dctx)
|
|
|
|
{
|
|
|
|
cairo_get_matrix(dctx->uctx.u.cairo.cr,
|
|
|
|
&dctx->uctx.u.cairo.origmatrix);
|
|
|
|
cairo_set_line_width(dctx->uctx.u.cairo.cr, 1.0);
|
|
|
|
cairo_set_line_cap(dctx->uctx.u.cairo.cr, CAIRO_LINE_CAP_SQUARE);
|
|
|
|
cairo_set_line_join(dctx->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 */
|
|
|
|
cairo_set_antialias(dctx->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)
|
|
|
|
{
|
|
|
|
struct gui_data *inst = (struct gui_data *)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) {
|
2015-08-16 16:34:19 +03:00
|
|
|
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));
|
2015-08-16 16:34:19 +03:00
|
|
|
|
|
|
|
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);
|
2015-08-16 16:34:19 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
#else
|
2002-10-07 20:45:23 +04:00
|
|
|
gint expose_area(GtkWidget *widget, GdkEventExpose *event, gpointer data)
|
|
|
|
{
|
2002-10-26 16:58:13 +04:00
|
|
|
struct gui_data *inst = (struct gui_data *)data;
|
2002-10-07 20:45:23 +04:00
|
|
|
|
2015-08-16 11:02:31 +03:00
|
|
|
#ifndef NO_BACKING_PIXMAPS
|
2002-10-07 20:45:23 +04: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
|
|
|
* Draw to the exposed part of the window from the server-side
|
|
|
|
* backing pixmap.
|
2002-10-07 20:45:23 +04:00
|
|
|
*/
|
2002-10-13 13:54:36 +04:00
|
|
|
if (inst->pixmap) {
|
2015-08-08 17:53:43 +03:00
|
|
|
gdk_draw_pixmap(gtk_widget_get_window(widget),
|
|
|
|
(gtk_widget_get_style(widget)->fg_gc
|
|
|
|
[gtk_widget_get_state(widget)]),
|
2002-10-13 13:54:36 +04:00
|
|
|
inst->pixmap,
|
|
|
|
event->area.x, event->area.y,
|
|
|
|
event->area.x, event->area.y,
|
|
|
|
event->area.width, event->area.height);
|
|
|
|
}
|
2015-08-16 11:02:31 +03:00
|
|
|
#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);
|
2015-08-16 11:02:31 +03:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2002-10-09 22:09:42 +04:00
|
|
|
return TRUE;
|
2002-10-07 20:45:23 +04:00
|
|
|
}
|
2015-08-16 16:34:19 +03:00
|
|
|
#endif
|
2002-10-07 20:45:23 +04:00
|
|
|
|
|
|
|
#define KEY_PRESSED(k) \
|
|
|
|
(inst->keystate[(k) / 32] & (1 << ((k) % 32)))
|
|
|
|
|
2015-09-06 11:13:48 +03:00
|
|
|
#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
|
|
|
|
|
2016-11-13 16:53:42 +03:00
|
|
|
static void change_font_size(struct gui_data *inst, int increment);
|
|
|
|
|
2002-10-07 20:45:23 +04:00
|
|
|
gint key_event(GtkWidget *widget, GdkEventKey *event, gpointer data)
|
|
|
|
{
|
2002-10-26 16:58:13 +04:00
|
|
|
struct gui_data *inst = (struct gui_data *)data;
|
2009-02-28 19:52:42 +03:00
|
|
|
char output[256];
|
2003-04-27 15:10:48 +04:00
|
|
|
wchar_t ucsoutput[2];
|
2009-02-28 19:52:42 +03:00
|
|
|
int ucsval, start, end, special, output_charset, use_ucsoutput;
|
2012-07-06 03:45:20 +04:00
|
|
|
int nethack_mode, app_keypad_mode;
|
2002-10-07 20:45:23 +04:00
|
|
|
|
2017-12-18 13:43:13 +03:00
|
|
|
#ifdef OSX_META_KEY_CONFIG
|
|
|
|
if (event->state & inst->system_mod_mask)
|
|
|
|
return FALSE; /* let GTK process OS X Command key */
|
|
|
|
#endif
|
|
|
|
|
2003-08-21 22:03:06 +04:00
|
|
|
/* Remember the timestamp. */
|
|
|
|
inst->input_event_time = event->time;
|
|
|
|
|
2002-10-15 21:18:24 +04:00
|
|
|
/* By default, nothing is generated. */
|
|
|
|
end = start = 0;
|
2003-04-27 15:10:48 +04:00
|
|
|
special = use_ucsoutput = FALSE;
|
2009-02-28 19:52:42 +03:00
|
|
|
output_charset = CS_ISO8859_1;
|
2002-10-15 21:18:24 +04:00
|
|
|
|
2015-08-27 20:35:17 +03:00
|
|
|
#ifdef KEY_EVENT_DIAGNOSTICS
|
|
|
|
{
|
2015-09-06 11:13:48 +03:00
|
|
|
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);
|
2015-08-27 20:35:17 +03:00
|
|
|
}
|
|
|
|
#endif /* KEY_EVENT_DIAGNOSTICS */
|
|
|
|
|
2002-10-15 21:18:24 +04:00
|
|
|
/*
|
|
|
|
* If Alt is being released after typing an Alt+numberpad
|
|
|
|
* sequence, we should generate the code that was typed.
|
2002-10-28 20:34:45 +03:00
|
|
|
*
|
|
|
|
* 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.
|
2002-10-15 21:18:24 +04:00
|
|
|
*/
|
2012-06-17 11:26:23 +04:00
|
|
|
if (event->type == GDK_KEY_RELEASE) {
|
2015-08-08 18:23:54 +03:00
|
|
|
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) &&
|
2012-06-17 11:26:23 +04:00
|
|
|
inst->alt_keycode >= 0 && inst->alt_digits > 1) {
|
2015-09-06 11:13:48 +03:00
|
|
|
#ifdef KEY_EVENT_DIAGNOSTICS
|
|
|
|
debug((" - modifier release terminates Alt+numberpad input, "
|
|
|
|
"keycode = %d\n", inst->alt_keycode));
|
2012-06-17 11:26:23 +04:00
|
|
|
#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)
|
2015-09-06 11:13:48 +03:00
|
|
|
#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
|
2012-06-17 11:26:23 +04:00
|
|
|
return TRUE;
|
2015-09-06 11:13:48 +03:00
|
|
|
} else {
|
|
|
|
#ifdef KEY_EVENT_DIAGNOSTICS
|
|
|
|
debug((" - key release not accepted by IM\n"));
|
|
|
|
#endif
|
|
|
|
}
|
2002-10-15 21:18:24 +04:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2002-10-09 22:09:42 +04:00
|
|
|
if (event->type == GDK_KEY_PRESS) {
|
2002-10-15 21:18:24 +04:00
|
|
|
/*
|
|
|
|
* 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).
|
|
|
|
*/
|
2015-08-08 18:23:54 +03:00
|
|
|
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)) {
|
2015-09-06 11:13:48 +03:00
|
|
|
#ifdef KEY_EVENT_DIAGNOSTICS
|
|
|
|
debug((" - modifier press potentially begins Alt+numberpad "
|
|
|
|
"input\n"));
|
|
|
|
#endif
|
2002-10-15 21:18:24 +04:00
|
|
|
inst->alt_keycode = -1;
|
2002-10-28 20:34:45 +03:00
|
|
|
inst->alt_digits = 0;
|
2002-10-15 21:18:24 +04:00
|
|
|
goto done; /* this generates nothing else */
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2015-09-01 21:00:25 +03:00
|
|
|
* If we're seeing a numberpad key press with Meta down,
|
2002-10-15 21:18:24 +04:00
|
|
|
* consider adding it to alt_keycode if that's sensible.
|
2015-09-01 21:00:25 +03:00
|
|
|
* Anything _else_ with Meta down cancels any possibility
|
2002-10-15 21:18:24 +04:00
|
|
|
* of an ALT keycode: we set alt_keycode to -2.
|
|
|
|
*/
|
2015-09-01 21:00:25 +03:00
|
|
|
if ((event->state & inst->meta_mod_mask) && inst->alt_keycode != -2) {
|
2002-10-15 21:18:24 +04:00
|
|
|
int digit = -1;
|
|
|
|
switch (event->keyval) {
|
2015-08-08 18:23:54 +03:00
|
|
|
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;
|
2002-10-15 21:18:24 +04:00
|
|
|
}
|
|
|
|
if (digit < 0)
|
|
|
|
inst->alt_keycode = -2; /* it's invalid */
|
|
|
|
else {
|
2015-09-06 11:13:48 +03:00
|
|
|
#ifdef KEY_EVENT_DIAGNOSTICS
|
|
|
|
int old_keycode = inst->alt_keycode;
|
2002-10-15 21:18:24 +04:00
|
|
|
#endif
|
|
|
|
if (inst->alt_keycode == -1)
|
|
|
|
inst->alt_keycode = digit; /* one-digit code */
|
|
|
|
else
|
|
|
|
inst->alt_keycode = inst->alt_keycode * 10 + digit;
|
2002-10-28 20:34:45 +03:00
|
|
|
inst->alt_digits++;
|
2015-09-06 11:13:48 +03:00
|
|
|
#ifdef KEY_EVENT_DIAGNOSTICS
|
|
|
|
debug((" - Alt+numberpad digit %d added to keycode %d"
|
|
|
|
" gives %d\n", digit, old_keycode, inst->alt_keycode));
|
2002-10-15 21:18:24 +04:00
|
|
|
#endif
|
|
|
|
/* Having used this digit, we now do nothing more with it. */
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-13 16:53:42 +03:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2002-10-13 13:54:36 +04:00
|
|
|
/*
|
|
|
|
* Shift-PgUp and Shift-PgDn don't even generate keystrokes
|
|
|
|
* at all.
|
|
|
|
*/
|
2017-11-03 17:31:10 +03:00
|
|
|
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;
|
|
|
|
}
|
2015-08-08 18:23:54 +03:00
|
|
|
if (event->keyval == GDK_KEY_Page_Up &&
|
|
|
|
(event->state & GDK_SHIFT_MASK)) {
|
2015-09-06 11:13:48 +03:00
|
|
|
#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);
|
2002-10-13 13:54:36 +04:00
|
|
|
return TRUE;
|
|
|
|
}
|
2015-08-08 18:23:54 +03:00
|
|
|
if (event->keyval == GDK_KEY_Page_Up &&
|
|
|
|
(event->state & GDK_CONTROL_MASK)) {
|
2015-09-06 11:13:48 +03:00
|
|
|
#ifdef KEY_EVENT_DIAGNOSTICS
|
|
|
|
debug((" - Ctrl-PgUp scroll\n"));
|
|
|
|
#endif
|
2003-01-14 14:24:26 +03:00
|
|
|
term_scroll(inst->term, 0, -1);
|
|
|
|
return TRUE;
|
|
|
|
}
|
2017-11-03 17:31:10 +03:00
|
|
|
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;
|
|
|
|
}
|
2015-08-08 18:23:54 +03:00
|
|
|
if (event->keyval == GDK_KEY_Page_Down &&
|
|
|
|
(event->state & GDK_SHIFT_MASK)) {
|
2015-09-06 11:13:48 +03:00
|
|
|
#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);
|
2002-10-13 13:54:36 +04:00
|
|
|
return TRUE;
|
|
|
|
}
|
2015-08-08 18:23:54 +03:00
|
|
|
if (event->keyval == GDK_KEY_Page_Down &&
|
|
|
|
(event->state & GDK_CONTROL_MASK)) {
|
2015-09-06 11:13:48 +03:00
|
|
|
#ifdef KEY_EVENT_DIAGNOSTICS
|
|
|
|
debug((" - Ctrl-PgDn scroll\n"));
|
|
|
|
#endif
|
2003-01-14 14:24:26 +03:00
|
|
|
term_scroll(inst->term, 0, +1);
|
|
|
|
return TRUE;
|
|
|
|
}
|
2002-10-13 13:54:36 +04:00
|
|
|
|
2002-10-13 15:27:39 +04:00
|
|
|
/*
|
2017-12-10 20:16:50 +03:00
|
|
|
* Neither do Shift-Ins or Ctrl-Ins (if enabled).
|
2002-10-13 15:27:39 +04:00
|
|
|
*/
|
2015-09-06 11:17:53 +03:00
|
|
|
if (event->keyval == GDK_KEY_Insert &&
|
2015-08-08 18:23:54 +03:00
|
|
|
(event->state & GDK_SHIFT_MASK)) {
|
2017-12-10 20:16:50 +03:00
|
|
|
int cfgval = conf_get_int(inst->conf, CONF_ctrlshiftins);
|
|
|
|
|
|
|
|
switch (cfgval) {
|
|
|
|
case CLIPUI_IMPLICIT:
|
2015-09-06 11:13:48 +03:00
|
|
|
#ifdef KEY_EVENT_DIAGNOSTICS
|
2017-12-10 20:16:50 +03:00
|
|
|
debug((" - Shift-Insert: paste from PRIMARY\n"));
|
2015-09-06 11:13:48 +03:00
|
|
|
#endif
|
2017-12-10 20:16:50 +03:00
|
|
|
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;
|
2017-12-17 21:44:27 +03:00
|
|
|
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;
|
2017-12-10 20:16:50 +03:00
|
|
|
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;
|
2017-12-17 21:44:27 +03:00
|
|
|
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;
|
2017-12-10 20:16:50 +03:00
|
|
|
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);
|
|
|
|
int 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;
|
2017-12-17 21:44:27 +03:00
|
|
|
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;
|
2017-12-10 20:16:50 +03:00
|
|
|
}
|
2002-10-13 15:27:39 +04:00
|
|
|
}
|
|
|
|
|
2003-04-12 13:27:56 +04:00
|
|
|
special = FALSE;
|
2003-04-27 15:10:48 +04:00
|
|
|
use_ucsoutput = FALSE;
|
2003-04-12 13:27:56 +04:00
|
|
|
|
2012-07-06 03:45:20 +04:00
|
|
|
nethack_mode = conf_get_int(inst->conf, CONF_nethack_keypad);
|
|
|
|
app_keypad_mode = (inst->term->app_keypad_keys &&
|
|
|
|
!conf_get_int(inst->conf, CONF_no_applic_k));
|
|
|
|
|
2002-10-10 16:14:05 +04:00
|
|
|
/* ALT+things gives leading Escape. */
|
|
|
|
output[0] = '\033';
|
2009-02-28 19:52:42 +03:00
|
|
|
#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);
|
2015-09-06 11:13:48 +03:00
|
|
|
#else /* !GTK_CHECK_VERSION(2,0,0) */
|
2012-07-06 03:45:20 +04:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
if (app_keypad_mode &&
|
2015-08-08 18:23:54 +03:00
|
|
|
(event->keyval == GDK_KEY_Num_Lock ||
|
|
|
|
event->keyval == GDK_KEY_KP_Divide ||
|
|
|
|
event->keyval == GDK_KEY_KP_Multiply ||
|
|
|
|
event->keyval == GDK_KEY_KP_Subtract ||
|
|
|
|
event->keyval == GDK_KEY_KP_Add ||
|
|
|
|
event->keyval == GDK_KEY_KP_Enter ||
|
|
|
|
event->keyval == GDK_KEY_KP_0 ||
|
|
|
|
event->keyval == GDK_KEY_KP_Insert ||
|
|
|
|
event->keyval == GDK_KEY_KP_1 ||
|
|
|
|
event->keyval == GDK_KEY_KP_End ||
|
|
|
|
event->keyval == GDK_KEY_KP_2 ||
|
|
|
|
event->keyval == GDK_KEY_KP_Down ||
|
|
|
|
event->keyval == GDK_KEY_KP_3 ||
|
|
|
|
event->keyval == GDK_KEY_KP_Page_Down ||
|
|
|
|
event->keyval == GDK_KEY_KP_4 ||
|
|
|
|
event->keyval == GDK_KEY_KP_Left ||
|
|
|
|
event->keyval == GDK_KEY_KP_5 ||
|
|
|
|
event->keyval == GDK_KEY_KP_Begin ||
|
|
|
|
event->keyval == GDK_KEY_KP_6 ||
|
|
|
|
event->keyval == GDK_KEY_KP_Right ||
|
|
|
|
event->keyval == GDK_KEY_KP_7 ||
|
|
|
|
event->keyval == GDK_KEY_KP_Home ||
|
|
|
|
event->keyval == GDK_KEY_KP_8 ||
|
|
|
|
event->keyval == GDK_KEY_KP_Up ||
|
|
|
|
event->keyval == GDK_KEY_KP_9 ||
|
|
|
|
event->keyval == GDK_KEY_KP_Page_Up ||
|
|
|
|
event->keyval == GDK_KEY_KP_Decimal ||
|
|
|
|
event->keyval == GDK_KEY_KP_Delete)) {
|
2012-07-06 03:45:20 +04:00
|
|
|
/* app keypad; do nothing */
|
|
|
|
} else if (nethack_mode &&
|
2015-08-08 18:23:54 +03:00
|
|
|
(event->keyval == GDK_KEY_KP_1 ||
|
|
|
|
event->keyval == GDK_KEY_KP_End ||
|
|
|
|
event->keyval == GDK_KEY_KP_2 ||
|
|
|
|
event->keyval == GDK_KEY_KP_Down ||
|
|
|
|
event->keyval == GDK_KEY_KP_3 ||
|
|
|
|
event->keyval == GDK_KEY_KP_Page_Down ||
|
|
|
|
event->keyval == GDK_KEY_KP_4 ||
|
|
|
|
event->keyval == GDK_KEY_KP_Left ||
|
|
|
|
event->keyval == GDK_KEY_KP_5 ||
|
|
|
|
event->keyval == GDK_KEY_KP_Begin ||
|
|
|
|
event->keyval == GDK_KEY_KP_6 ||
|
|
|
|
event->keyval == GDK_KEY_KP_Right ||
|
|
|
|
event->keyval == GDK_KEY_KP_7 ||
|
|
|
|
event->keyval == GDK_KEY_KP_Home ||
|
|
|
|
event->keyval == GDK_KEY_KP_8 ||
|
|
|
|
event->keyval == GDK_KEY_KP_Up ||
|
|
|
|
event->keyval == GDK_KEY_KP_9 ||
|
|
|
|
event->keyval == GDK_KEY_KP_Page_Up)) {
|
2012-07-06 03:45:20 +04:00
|
|
|
/* nethack mode; do nothing */
|
|
|
|
} else {
|
2015-09-06 11:13:48 +03:00
|
|
|
int try_filter = TRUE;
|
|
|
|
|
2015-09-01 21:10:29 +03:00
|
|
|
#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).
|
|
|
|
*/
|
2015-09-06 11:13:48 +03:00
|
|
|
#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"));
|
2015-09-01 21:10:29 +03:00
|
|
|
#endif
|
|
|
|
return TRUE;
|
2015-09-06 11:13:48 +03:00
|
|
|
} else {
|
|
|
|
#ifdef KEY_EVENT_DIAGNOSTICS
|
|
|
|
debug((" - key press not accepted by IM\n"));
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
2012-07-06 03:45:20 +04:00
|
|
|
}
|
2012-06-17 11:26:23 +04:00
|
|
|
|
2009-02-28 19:52:42 +03:00
|
|
|
/*
|
|
|
|
* 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;
|
|
|
|
{
|
2011-09-16 23:18:52 +04:00
|
|
|
wchar_t widedata[32];
|
|
|
|
const wchar_t *wp;
|
2009-02-28 19:52:42 +03:00
|
|
|
int wlen;
|
|
|
|
int ulen;
|
|
|
|
|
|
|
|
wlen = mb_to_wc(DEFAULT_CODEPAGE, 0,
|
|
|
|
event->string, strlen(event->string),
|
|
|
|
widedata, lenof(widedata)-1);
|
|
|
|
|
2015-09-06 11:13:48 +03:00
|
|
|
#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
|
|
|
|
|
2009-02-28 19:52:42 +03:00
|
|
|
wp = widedata;
|
|
|
|
ulen = charset_from_unicode(&wp, &wlen, output+1, lenof(output)-2,
|
|
|
|
CS_UTF8, NULL, NULL, 0);
|
2015-09-06 11:13:48 +03:00
|
|
|
|
|
|
|
#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
|
|
|
|
|
2009-02-28 19:52:42 +03:00
|
|
|
output[1+ulen] = '\0';
|
|
|
|
}
|
2015-09-06 11:13:48 +03:00
|
|
|
#endif /* !GTK_CHECK_VERSION(2,0,0) */
|
2009-02-28 19:52:42 +03:00
|
|
|
|
|
|
|
if (!output[1] &&
|
2003-04-27 15:10:48 +04:00
|
|
|
(ucsval = keysym_to_unicode(event->keyval)) >= 0) {
|
|
|
|
ucsoutput[0] = '\033';
|
|
|
|
ucsoutput[1] = ucsval;
|
2015-09-06 11:13:48 +03:00
|
|
|
#ifdef KEY_EVENT_DIAGNOSTICS
|
|
|
|
debug((" - keysym_to_unicode gave %04x\n",
|
|
|
|
(unsigned)ucsoutput[1]));
|
|
|
|
#endif
|
2003-04-27 15:10:48 +04:00
|
|
|
use_ucsoutput = TRUE;
|
|
|
|
end = 2;
|
|
|
|
} else {
|
2009-02-28 19:52:42 +03:00
|
|
|
output[lenof(output)-1] = '\0';
|
2003-04-27 15:10:48 +04:00
|
|
|
end = strlen(output);
|
|
|
|
}
|
2015-09-01 21:00:25 +03:00
|
|
|
if (event->state & inst->meta_mod_mask) {
|
2002-10-17 20:58:24 +04:00
|
|
|
start = 0;
|
|
|
|
if (end == 1) end = 0;
|
2015-09-01 21:10:29 +03:00
|
|
|
|
|
|
|
#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);
|
2015-09-06 11:13:48 +03:00
|
|
|
#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
|
2015-09-01 21:10:29 +03:00
|
|
|
use_ucsoutput = TRUE;
|
|
|
|
end = 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
2002-10-17 20:58:24 +04:00
|
|
|
} else
|
|
|
|
start = 1;
|
2002-10-10 16:14:05 +04:00
|
|
|
|
|
|
|
/* Control-` is the same as Control-\ (unless gtk has a better idea) */
|
2009-02-28 19:52:42 +03:00
|
|
|
if (!output[1] && event->keyval == '`' &&
|
2002-10-10 16:14:05 +04:00
|
|
|
(event->state & GDK_CONTROL_MASK)) {
|
2015-09-06 11:13:48 +03:00
|
|
|
#ifdef KEY_EVENT_DIAGNOSTICS
|
|
|
|
debug((" - Ctrl-` special case, translating as 1c\n"));
|
|
|
|
#endif
|
2002-10-10 16:14:05 +04:00
|
|
|
output[1] = '\x1C';
|
2003-04-27 15:10:48 +04:00
|
|
|
use_ucsoutput = FALSE;
|
2002-10-10 16:14:05 +04:00
|
|
|
end = 2;
|
|
|
|
}
|
|
|
|
|
2015-08-31 15:00:42 +03:00
|
|
|
/* 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) {
|
2015-09-06 11:13:48 +03:00
|
|
|
#ifdef KEY_EVENT_DIAGNOSTICS
|
|
|
|
int orig = output[1];
|
|
|
|
#endif
|
|
|
|
|
2015-08-31 15:00:42 +03:00
|
|
|
if (output[1] >= '3' && output[1] <= '7') {
|
|
|
|
/* ^3,...,^7 map to 0x1B,...,0x1F */
|
|
|
|
output[1] += '\x1B' - '3';
|
2015-09-01 21:18:26 +03:00
|
|
|
} else if (output[1] == '2' || output[1] == ' ') {
|
|
|
|
/* ^2 and ^Space are both ^@, i.e. \0 */
|
2015-08-31 15:00:42 +03:00
|
|
|
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. */
|
2015-09-06 11:13:48 +03:00
|
|
|
|
|
|
|
#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
|
2015-08-31 15:00:42 +03:00
|
|
|
}
|
|
|
|
|
2007-02-18 17:02:39 +03:00
|
|
|
/* Control-Break sends a Break special to the backend */
|
2015-08-08 18:23:54 +03:00
|
|
|
if (event->keyval == GDK_KEY_Break &&
|
2002-10-10 16:14:05 +04:00
|
|
|
(event->state & GDK_CONTROL_MASK)) {
|
2015-09-06 11:13:48 +03:00
|
|
|
#ifdef KEY_EVENT_DIAGNOSTICS
|
|
|
|
debug((" - Ctrl-Break special case, sending TS_BRK\n"));
|
|
|
|
#endif
|
2007-02-18 17:02:39 +03:00
|
|
|
if (inst->back)
|
|
|
|
inst->back->special(inst->backhandle, TS_BRK);
|
|
|
|
return TRUE;
|
2003-04-12 13:27:56 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* We handle Return ourselves, because it needs to be flagged as
|
|
|
|
* special to ldisc. */
|
2015-08-08 18:23:54 +03:00
|
|
|
if (event->keyval == GDK_KEY_Return) {
|
2015-09-06 11:13:48 +03:00
|
|
|
#ifdef KEY_EVENT_DIAGNOSTICS
|
|
|
|
debug((" - Return special case, translating as 0d + special\n"));
|
|
|
|
#endif
|
2003-04-12 13:27:56 +04:00
|
|
|
output[1] = '\015';
|
2003-04-27 15:10:48 +04:00
|
|
|
use_ucsoutput = FALSE;
|
2003-04-12 13:27:56 +04:00
|
|
|
end = 2;
|
|
|
|
special = TRUE;
|
2002-10-10 16:14:05 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Control-2, Control-Space and Control-@ are NUL */
|
2009-02-28 19:52:42 +03:00
|
|
|
if (!output[1] &&
|
2002-10-10 16:14:05 +04:00
|
|
|
(event->keyval == ' ' || event->keyval == '2' ||
|
|
|
|
event->keyval == '@') &&
|
|
|
|
(event->state & (GDK_SHIFT_MASK |
|
|
|
|
GDK_CONTROL_MASK)) == GDK_CONTROL_MASK) {
|
2015-09-06 11:13:48 +03:00
|
|
|
#ifdef KEY_EVENT_DIAGNOSTICS
|
|
|
|
debug((" - Ctrl-{space,2,@} special case, translating as 00\n"));
|
|
|
|
#endif
|
2002-10-10 16:14:05 +04:00
|
|
|
output[1] = '\0';
|
2003-04-27 15:10:48 +04:00
|
|
|
use_ucsoutput = FALSE;
|
2002-10-10 16:14:05 +04:00
|
|
|
end = 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Control-Shift-Space is 160 (ISO8859 nonbreaking space) */
|
2009-02-28 19:52:42 +03:00
|
|
|
if (!output[1] && event->keyval == ' ' &&
|
2002-10-10 16:14:05 +04:00
|
|
|
(event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK)) ==
|
|
|
|
(GDK_SHIFT_MASK | GDK_CONTROL_MASK)) {
|
2015-09-06 11:13:48 +03:00
|
|
|
#ifdef KEY_EVENT_DIAGNOSTICS
|
|
|
|
debug((" - Ctrl-Shift-space special case, translating as 00a0\n"));
|
|
|
|
#endif
|
2002-10-10 16:14:05 +04:00
|
|
|
output[1] = '\240';
|
2009-02-28 19:52:42 +03:00
|
|
|
output_charset = CS_ISO8859_1;
|
2003-04-27 15:10:48 +04:00
|
|
|
use_ucsoutput = FALSE;
|
2002-10-10 16:14:05 +04:00
|
|
|
end = 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We don't let GTK tell us what Backspace is! We know better. */
|
2015-08-08 18:23:54 +03:00
|
|
|
if (event->keyval == GDK_KEY_BackSpace &&
|
2002-10-10 16:14:05 +04:00
|
|
|
!(event->state & GDK_SHIFT_MASK)) {
|
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
|
|
|
output[1] = conf_get_int(inst->conf, CONF_bksp_is_delete) ?
|
|
|
|
'\x7F' : '\x08';
|
2015-09-06 11:13:48 +03:00
|
|
|
#ifdef KEY_EVENT_DIAGNOSTICS
|
|
|
|
debug((" - Backspace, translating as %02x\n",
|
|
|
|
(unsigned)output[1]));
|
|
|
|
#endif
|
2003-04-27 15:10:48 +04:00
|
|
|
use_ucsoutput = FALSE;
|
2002-10-10 16:14:05 +04:00
|
|
|
end = 2;
|
2003-04-12 13:27:56 +04:00
|
|
|
special = TRUE;
|
2002-10-10 16:14:05 +04:00
|
|
|
}
|
2002-10-16 13:40:36 +04:00
|
|
|
/* For Shift Backspace, do opposite of what is configured. */
|
2015-08-08 18:23:54 +03:00
|
|
|
if (event->keyval == GDK_KEY_BackSpace &&
|
2002-10-16 13:40:36 +04:00
|
|
|
(event->state & GDK_SHIFT_MASK)) {
|
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
|
|
|
output[1] = conf_get_int(inst->conf, CONF_bksp_is_delete) ?
|
|
|
|
'\x08' : '\x7F';
|
2015-09-06 11:13:48 +03:00
|
|
|
#ifdef KEY_EVENT_DIAGNOSTICS
|
|
|
|
debug((" - Shift-Backspace, translating as %02x\n",
|
|
|
|
(unsigned)output[1]));
|
|
|
|
#endif
|
2003-04-27 15:10:48 +04:00
|
|
|
use_ucsoutput = FALSE;
|
2002-10-16 13:40:36 +04:00
|
|
|
end = 2;
|
2003-04-12 13:27:56 +04:00
|
|
|
special = TRUE;
|
2002-10-16 13:40:36 +04:00
|
|
|
}
|
2002-10-10 16:14:05 +04:00
|
|
|
|
|
|
|
/* Shift-Tab is ESC [ Z */
|
2015-08-08 18:23:54 +03:00
|
|
|
if (event->keyval == GDK_KEY_ISO_Left_Tab ||
|
|
|
|
(event->keyval == GDK_KEY_Tab &&
|
|
|
|
(event->state & GDK_SHIFT_MASK))) {
|
2015-09-06 11:13:48 +03:00
|
|
|
#ifdef KEY_EVENT_DIAGNOSTICS
|
|
|
|
debug((" - Shift-Tab, translating as ESC [ Z\n"));
|
|
|
|
#endif
|
2002-10-10 16:14:05 +04:00
|
|
|
end = 1 + sprintf(output+1, "\033[Z");
|
2003-04-27 15:10:48 +04:00
|
|
|
use_ucsoutput = FALSE;
|
2002-10-10 16:14:05 +04:00
|
|
|
}
|
2008-03-09 18:32:20 +03:00
|
|
|
/* 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. */
|
2015-08-08 18:23:54 +03:00
|
|
|
if (event->keyval == GDK_KEY_Tab && end <= 1) {
|
2015-09-06 11:13:48 +03:00
|
|
|
#ifdef KEY_EVENT_DIAGNOSTICS
|
|
|
|
debug((" - Tab, translating as 09\n"));
|
|
|
|
#endif
|
2008-03-09 18:32:20 +03:00
|
|
|
output[1] = '\t';
|
|
|
|
end = 2;
|
|
|
|
}
|
2002-10-10 16:14:05 +04:00
|
|
|
|
2002-10-14 14:06:07 +04:00
|
|
|
/*
|
|
|
|
* NetHack keypad mode.
|
|
|
|
*/
|
2012-07-06 03:45:20 +04:00
|
|
|
if (nethack_mode) {
|
2015-05-15 13:15:42 +03:00
|
|
|
const char *keys = NULL;
|
2002-10-14 14:06:07 +04:00
|
|
|
switch (event->keyval) {
|
2015-08-08 18:23:54 +03:00
|
|
|
case GDK_KEY_KP_1: case GDK_KEY_KP_End:
|
|
|
|
keys = "bB\002"; break;
|
|
|
|
case GDK_KEY_KP_2: case GDK_KEY_KP_Down:
|
|
|
|
keys = "jJ\012"; break;
|
|
|
|
case GDK_KEY_KP_3: case GDK_KEY_KP_Page_Down:
|
|
|
|
keys = "nN\016"; break;
|
|
|
|
case GDK_KEY_KP_4: case GDK_KEY_KP_Left:
|
|
|
|
keys = "hH\010"; break;
|
|
|
|
case GDK_KEY_KP_5: case GDK_KEY_KP_Begin:
|
|
|
|
keys = "..."; break;
|
|
|
|
case GDK_KEY_KP_6: case GDK_KEY_KP_Right:
|
|
|
|
keys = "lL\014"; break;
|
|
|
|
case GDK_KEY_KP_7: case GDK_KEY_KP_Home:
|
|
|
|
keys = "yY\031"; break;
|
|
|
|
case GDK_KEY_KP_8: case GDK_KEY_KP_Up:
|
|
|
|
keys = "kK\013"; break;
|
|
|
|
case GDK_KEY_KP_9: case GDK_KEY_KP_Page_Up:
|
|
|
|
keys = "uU\025"; break;
|
2002-10-14 14:06:07 +04:00
|
|
|
}
|
|
|
|
if (keys) {
|
|
|
|
end = 2;
|
2006-03-08 21:10:12 +03:00
|
|
|
if (event->state & GDK_CONTROL_MASK)
|
|
|
|
output[1] = keys[2];
|
|
|
|
else if (event->state & GDK_SHIFT_MASK)
|
2002-10-14 14:06:07 +04:00
|
|
|
output[1] = keys[1];
|
|
|
|
else
|
|
|
|
output[1] = keys[0];
|
2015-09-06 11:13:48 +03:00
|
|
|
#ifdef KEY_EVENT_DIAGNOSTICS
|
|
|
|
debug((" - Nethack-mode key"));
|
|
|
|
#endif
|
2003-04-27 15:10:48 +04:00
|
|
|
use_ucsoutput = FALSE;
|
2002-10-14 14:06:07 +04:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-10-10 16:14:05 +04:00
|
|
|
/*
|
|
|
|
* Application keypad mode.
|
|
|
|
*/
|
2012-07-06 03:45:20 +04:00
|
|
|
if (app_keypad_mode) {
|
2002-10-10 16:14:05 +04:00
|
|
|
int xkey = 0;
|
|
|
|
switch (event->keyval) {
|
2015-08-08 18:23:54 +03:00
|
|
|
case GDK_KEY_Num_Lock: xkey = 'P'; break;
|
|
|
|
case GDK_KEY_KP_Divide: xkey = 'Q'; break;
|
|
|
|
case GDK_KEY_KP_Multiply: xkey = 'R'; break;
|
|
|
|
case GDK_KEY_KP_Subtract: xkey = 'S'; break;
|
2002-10-10 16:14:05 +04:00
|
|
|
/*
|
|
|
|
* Keypad + is tricky. It covers a space that would
|
|
|
|
* be taken up on the VT100 by _two_ keys; so we
|
|
|
|
* let Shift select between the two. Worse still,
|
|
|
|
* in xterm function key mode we change which two...
|
|
|
|
*/
|
2015-08-08 18:23:54 +03:00
|
|
|
case GDK_KEY_KP_Add:
|
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(inst->conf, CONF_funky_type) == FUNKY_XTERM) {
|
2002-10-10 16:14:05 +04:00
|
|
|
if (event->state & GDK_SHIFT_MASK)
|
|
|
|
xkey = 'l';
|
|
|
|
else
|
|
|
|
xkey = 'k';
|
|
|
|
} else if (event->state & GDK_SHIFT_MASK)
|
|
|
|
xkey = 'm';
|
|
|
|
else
|
|
|
|
xkey = 'l';
|
|
|
|
break;
|
2015-08-08 18:23:54 +03:00
|
|
|
case GDK_KEY_KP_Enter: xkey = 'M'; break;
|
|
|
|
case GDK_KEY_KP_0: case GDK_KEY_KP_Insert: xkey = 'p'; break;
|
|
|
|
case GDK_KEY_KP_1: case GDK_KEY_KP_End: xkey = 'q'; break;
|
|
|
|
case GDK_KEY_KP_2: case GDK_KEY_KP_Down: xkey = 'r'; break;
|
|
|
|
case GDK_KEY_KP_3: case GDK_KEY_KP_Page_Down: xkey = 's'; break;
|
|
|
|
case GDK_KEY_KP_4: case GDK_KEY_KP_Left: xkey = 't'; break;
|
|
|
|
case GDK_KEY_KP_5: case GDK_KEY_KP_Begin: xkey = 'u'; break;
|
|
|
|
case GDK_KEY_KP_6: case GDK_KEY_KP_Right: xkey = 'v'; break;
|
|
|
|
case GDK_KEY_KP_7: case GDK_KEY_KP_Home: xkey = 'w'; break;
|
|
|
|
case GDK_KEY_KP_8: case GDK_KEY_KP_Up: xkey = 'x'; break;
|
|
|
|
case GDK_KEY_KP_9: case GDK_KEY_KP_Page_Up: xkey = 'y'; break;
|
|
|
|
case GDK_KEY_KP_Decimal: case GDK_KEY_KP_Delete:
|
|
|
|
xkey = 'n'; break;
|
2002-10-10 16:14:05 +04:00
|
|
|
}
|
|
|
|
if (xkey) {
|
2002-10-26 15:08:59 +04:00
|
|
|
if (inst->term->vt52_mode) {
|
2002-10-10 16:14:05 +04:00
|
|
|
if (xkey >= 'P' && xkey <= 'S')
|
|
|
|
end = 1 + sprintf(output+1, "\033%c", xkey);
|
|
|
|
else
|
|
|
|
end = 1 + sprintf(output+1, "\033?%c", xkey);
|
|
|
|
} else
|
|
|
|
end = 1 + sprintf(output+1, "\033O%c", xkey);
|
2003-04-27 15:10:48 +04:00
|
|
|
use_ucsoutput = FALSE;
|
2015-09-06 11:13:48 +03:00
|
|
|
#ifdef KEY_EVENT_DIAGNOSTICS
|
|
|
|
debug((" - Application keypad mode key"));
|
|
|
|
#endif
|
2002-10-10 16:14:05 +04:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Next, all the keys that do tilde codes. (ESC '[' nn '~',
|
|
|
|
* for integer decimal nn.)
|
|
|
|
*
|
|
|
|
* We also deal with the weird ones here. Linux VCs replace F1
|
|
|
|
* to F5 by ESC [ [ A to ESC [ [ E. rxvt doesn't do _that_, but
|
|
|
|
* does replace Home and End (1~ and 4~) by ESC [ H and ESC O w
|
|
|
|
* respectively.
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
int code = 0;
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 22:52:21 +04:00
|
|
|
int funky_type = conf_get_int(inst->conf, CONF_funky_type);
|
2002-10-10 16:14:05 +04:00
|
|
|
switch (event->keyval) {
|
2015-08-08 18:23:54 +03:00
|
|
|
case GDK_KEY_F1:
|
2002-10-10 16:14:05 +04:00
|
|
|
code = (event->state & GDK_SHIFT_MASK ? 23 : 11);
|
|
|
|
break;
|
2015-08-08 18:23:54 +03:00
|
|
|
case GDK_KEY_F2:
|
2002-10-10 16:14:05 +04:00
|
|
|
code = (event->state & GDK_SHIFT_MASK ? 24 : 12);
|
|
|
|
break;
|
2015-08-08 18:23:54 +03:00
|
|
|
case GDK_KEY_F3:
|
2002-10-10 16:14:05 +04:00
|
|
|
code = (event->state & GDK_SHIFT_MASK ? 25 : 13);
|
|
|
|
break;
|
2015-08-08 18:23:54 +03:00
|
|
|
case GDK_KEY_F4:
|
2002-10-10 16:14:05 +04:00
|
|
|
code = (event->state & GDK_SHIFT_MASK ? 26 : 14);
|
|
|
|
break;
|
2015-08-08 18:23:54 +03:00
|
|
|
case GDK_KEY_F5:
|
2002-10-10 16:14:05 +04:00
|
|
|
code = (event->state & GDK_SHIFT_MASK ? 28 : 15);
|
|
|
|
break;
|
2015-08-08 18:23:54 +03:00
|
|
|
case GDK_KEY_F6:
|
2002-10-10 16:14:05 +04:00
|
|
|
code = (event->state & GDK_SHIFT_MASK ? 29 : 17);
|
|
|
|
break;
|
2015-08-08 18:23:54 +03:00
|
|
|
case GDK_KEY_F7:
|
2002-10-10 16:14:05 +04:00
|
|
|
code = (event->state & GDK_SHIFT_MASK ? 31 : 18);
|
|
|
|
break;
|
2015-08-08 18:23:54 +03:00
|
|
|
case GDK_KEY_F8:
|
2002-10-10 16:14:05 +04:00
|
|
|
code = (event->state & GDK_SHIFT_MASK ? 32 : 19);
|
|
|
|
break;
|
2015-08-08 18:23:54 +03:00
|
|
|
case GDK_KEY_F9:
|
2002-10-10 16:14:05 +04:00
|
|
|
code = (event->state & GDK_SHIFT_MASK ? 33 : 20);
|
|
|
|
break;
|
2015-08-08 18:23:54 +03:00
|
|
|
case GDK_KEY_F10:
|
2002-10-10 16:14:05 +04:00
|
|
|
code = (event->state & GDK_SHIFT_MASK ? 34 : 21);
|
|
|
|
break;
|
2015-08-08 18:23:54 +03:00
|
|
|
case GDK_KEY_F11:
|
2002-10-10 16:14:05 +04:00
|
|
|
code = 23;
|
|
|
|
break;
|
2015-08-08 18:23:54 +03:00
|
|
|
case GDK_KEY_F12:
|
2002-10-10 16:14:05 +04:00
|
|
|
code = 24;
|
|
|
|
break;
|
2015-08-08 18:23:54 +03:00
|
|
|
case GDK_KEY_F13:
|
2002-10-10 16:14:05 +04:00
|
|
|
code = 25;
|
|
|
|
break;
|
2015-08-08 18:23:54 +03:00
|
|
|
case GDK_KEY_F14:
|
2002-10-10 16:14:05 +04:00
|
|
|
code = 26;
|
|
|
|
break;
|
2015-08-08 18:23:54 +03:00
|
|
|
case GDK_KEY_F15:
|
2002-10-10 16:14:05 +04:00
|
|
|
code = 28;
|
|
|
|
break;
|
2015-08-08 18:23:54 +03:00
|
|
|
case GDK_KEY_F16:
|
2002-10-10 16:14:05 +04:00
|
|
|
code = 29;
|
|
|
|
break;
|
2015-08-08 18:23:54 +03:00
|
|
|
case GDK_KEY_F17:
|
2002-10-10 16:14:05 +04:00
|
|
|
code = 31;
|
|
|
|
break;
|
2015-08-08 18:23:54 +03:00
|
|
|
case GDK_KEY_F18:
|
2002-10-10 16:14:05 +04:00
|
|
|
code = 32;
|
|
|
|
break;
|
2015-08-08 18:23:54 +03:00
|
|
|
case GDK_KEY_F19:
|
2002-10-10 16:14:05 +04:00
|
|
|
code = 33;
|
|
|
|
break;
|
2015-08-08 18:23:54 +03:00
|
|
|
case GDK_KEY_F20:
|
2002-10-10 16:14:05 +04:00
|
|
|
code = 34;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (!(event->state & GDK_CONTROL_MASK)) switch (event->keyval) {
|
2015-08-08 18:23:54 +03:00
|
|
|
case GDK_KEY_Home: case GDK_KEY_KP_Home:
|
2002-10-10 16:14:05 +04:00
|
|
|
code = 1;
|
|
|
|
break;
|
2015-08-08 18:23:54 +03:00
|
|
|
case GDK_KEY_Insert: case GDK_KEY_KP_Insert:
|
2002-10-10 16:14:05 +04:00
|
|
|
code = 2;
|
|
|
|
break;
|
2015-08-08 18:23:54 +03:00
|
|
|
case GDK_KEY_Delete: case GDK_KEY_KP_Delete:
|
2002-10-10 16:14:05 +04:00
|
|
|
code = 3;
|
|
|
|
break;
|
2015-08-08 18:23:54 +03:00
|
|
|
case GDK_KEY_End: case GDK_KEY_KP_End:
|
2002-10-10 16:14:05 +04:00
|
|
|
code = 4;
|
|
|
|
break;
|
2015-08-08 18:23:54 +03:00
|
|
|
case GDK_KEY_Page_Up: case GDK_KEY_KP_Page_Up:
|
2002-10-10 16:14:05 +04:00
|
|
|
code = 5;
|
|
|
|
break;
|
2015-08-08 18:23:54 +03:00
|
|
|
case GDK_KEY_Page_Down: case GDK_KEY_KP_Page_Down:
|
2002-10-10 16:14:05 +04:00
|
|
|
code = 6;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
/* Reorder edit keys to physical order */
|
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 (funky_type == FUNKY_VT400 && code <= 6)
|
2002-10-10 16:14:05 +04:00
|
|
|
code = "\0\2\1\4\5\3\6"[code];
|
|
|
|
|
2002-10-26 15:08:59 +04:00
|
|
|
if (inst->term->vt52_mode && code > 0 && code <= 6) {
|
2002-10-10 16:14:05 +04:00
|
|
|
end = 1 + sprintf(output+1, "\x1B%c", " HLMEIG"[code]);
|
2015-09-06 11:13:48 +03:00
|
|
|
#ifdef KEY_EVENT_DIAGNOSTICS
|
|
|
|
debug((" - VT52 mode small keypad key"));
|
|
|
|
#endif
|
2003-04-27 15:10:48 +04:00
|
|
|
use_ucsoutput = FALSE;
|
2002-10-10 16:14:05 +04:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
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 (funky_type == FUNKY_SCO && /* SCO function keys */
|
2002-10-10 16:14:05 +04:00
|
|
|
code >= 11 && code <= 34) {
|
|
|
|
char codes[] = "MNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@[\\]^_`{";
|
|
|
|
int index = 0;
|
|
|
|
switch (event->keyval) {
|
2015-08-08 18:23:54 +03:00
|
|
|
case GDK_KEY_F1: index = 0; break;
|
|
|
|
case GDK_KEY_F2: index = 1; break;
|
|
|
|
case GDK_KEY_F3: index = 2; break;
|
|
|
|
case GDK_KEY_F4: index = 3; break;
|
|
|
|
case GDK_KEY_F5: index = 4; break;
|
|
|
|
case GDK_KEY_F6: index = 5; break;
|
|
|
|
case GDK_KEY_F7: index = 6; break;
|
|
|
|
case GDK_KEY_F8: index = 7; break;
|
|
|
|
case GDK_KEY_F9: index = 8; break;
|
|
|
|
case GDK_KEY_F10: index = 9; break;
|
|
|
|
case GDK_KEY_F11: index = 10; break;
|
|
|
|
case GDK_KEY_F12: index = 11; break;
|
2002-10-10 16:14:05 +04:00
|
|
|
}
|
|
|
|
if (event->state & GDK_SHIFT_MASK) index += 12;
|
|
|
|
if (event->state & GDK_CONTROL_MASK) index += 24;
|
|
|
|
end = 1 + sprintf(output+1, "\x1B[%c", codes[index]);
|
2015-09-06 11:13:48 +03:00
|
|
|
#ifdef KEY_EVENT_DIAGNOSTICS
|
|
|
|
debug((" - SCO mode function key"));
|
|
|
|
#endif
|
2003-04-27 15:10:48 +04:00
|
|
|
use_ucsoutput = FALSE;
|
2002-10-10 16:14:05 +04:00
|
|
|
goto done;
|
|
|
|
}
|
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 (funky_type == FUNKY_SCO && /* SCO small keypad */
|
2002-10-10 16:14:05 +04:00
|
|
|
code >= 1 && code <= 6) {
|
|
|
|
char codes[] = "HL.FIG";
|
|
|
|
if (code == 3) {
|
|
|
|
output[1] = '\x7F';
|
|
|
|
end = 2;
|
|
|
|
} else {
|
|
|
|
end = 1 + sprintf(output+1, "\x1B[%c", codes[code-1]);
|
|
|
|
}
|
2015-09-06 11:13:48 +03:00
|
|
|
#ifdef KEY_EVENT_DIAGNOSTICS
|
|
|
|
debug((" - SCO mode small keypad key"));
|
|
|
|
#endif
|
2003-04-27 15:10:48 +04:00
|
|
|
use_ucsoutput = FALSE;
|
2002-10-10 16:14:05 +04:00
|
|
|
goto done;
|
|
|
|
}
|
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->term->vt52_mode || funky_type == FUNKY_VT100P) &&
|
2002-10-22 20:11:33 +04:00
|
|
|
code >= 11 && code <= 24) {
|
2002-10-10 16:14:05 +04:00
|
|
|
int offt = 0;
|
|
|
|
if (code > 15)
|
|
|
|
offt++;
|
|
|
|
if (code > 21)
|
|
|
|
offt++;
|
2015-09-06 11:13:48 +03:00
|
|
|
if (inst->term->vt52_mode) {
|
|
|
|
#ifdef KEY_EVENT_DIAGNOSTICS
|
|
|
|
debug((" - VT52 mode function key"));
|
|
|
|
#endif
|
2002-10-10 16:14:05 +04:00
|
|
|
end = 1 + sprintf(output+1,
|
|
|
|
"\x1B%c", code + 'P' - 11 - offt);
|
2015-09-06 11:13:48 +03:00
|
|
|
} else {
|
|
|
|
#ifdef KEY_EVENT_DIAGNOSTICS
|
|
|
|
debug((" - VT100+ mode function key"));
|
|
|
|
#endif
|
2002-10-10 16:14:05 +04:00
|
|
|
end = 1 + sprintf(output+1,
|
|
|
|
"\x1BO%c", code + 'P' - 11 - offt);
|
2015-09-06 11:13:48 +03:00
|
|
|
}
|
2003-04-27 15:10:48 +04:00
|
|
|
use_ucsoutput = FALSE;
|
2002-10-10 16:14:05 +04:00
|
|
|
goto done;
|
|
|
|
}
|
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 (funky_type == FUNKY_LINUX && code >= 11 && code <= 15) {
|
2002-10-10 16:14:05 +04:00
|
|
|
end = 1 + sprintf(output+1, "\x1B[[%c", code + 'A' - 11);
|
2015-09-06 11:13:48 +03:00
|
|
|
#ifdef KEY_EVENT_DIAGNOSTICS
|
|
|
|
debug((" - Linux mode F1-F5 function key"));
|
|
|
|
#endif
|
2003-04-27 15:10:48 +04:00
|
|
|
use_ucsoutput = FALSE;
|
2002-10-10 16:14:05 +04:00
|
|
|
goto done;
|
|
|
|
}
|
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 (funky_type == FUNKY_XTERM && code >= 11 && code <= 14) {
|
2015-09-06 11:13:48 +03:00
|
|
|
if (inst->term->vt52_mode) {
|
|
|
|
#ifdef KEY_EVENT_DIAGNOSTICS
|
|
|
|
debug((" - VT52 mode (overriding xterm) F1-F4 function"
|
|
|
|
" key"));
|
|
|
|
#endif
|
2002-10-10 16:14:05 +04:00
|
|
|
end = 1 + sprintf(output+1, "\x1B%c", code + 'P' - 11);
|
2015-09-06 11:13:48 +03:00
|
|
|
} else {
|
|
|
|
#ifdef KEY_EVENT_DIAGNOSTICS
|
|
|
|
debug((" - xterm mode F1-F4 function key"));
|
|
|
|
#endif
|
2002-10-10 16:14:05 +04:00
|
|
|
end = 1 + sprintf(output+1, "\x1BO%c", code + 'P' - 11);
|
2015-09-06 11:13:48 +03:00
|
|
|
}
|
2003-04-27 15:10:48 +04:00
|
|
|
use_ucsoutput = FALSE;
|
2002-10-10 16:14:05 +04:00
|
|
|
goto done;
|
|
|
|
}
|
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 ((code == 1 || code == 4) &&
|
|
|
|
conf_get_int(inst->conf, CONF_rxvt_homeend)) {
|
2015-09-06 11:13:48 +03:00
|
|
|
#ifdef KEY_EVENT_DIAGNOSTICS
|
|
|
|
debug((" - rxvt style Home/End"));
|
|
|
|
#endif
|
2002-10-10 16:14:05 +04:00
|
|
|
end = 1 + sprintf(output+1, code == 1 ? "\x1B[H" : "\x1BOw");
|
2003-04-27 15:10:48 +04:00
|
|
|
use_ucsoutput = FALSE;
|
2002-10-10 16:14:05 +04:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
if (code) {
|
2015-09-06 11:13:48 +03:00
|
|
|
#ifdef KEY_EVENT_DIAGNOSTICS
|
|
|
|
debug((" - ordinary function key encoding"));
|
|
|
|
#endif
|
2002-10-10 16:14:05 +04:00
|
|
|
end = 1 + sprintf(output+1, "\x1B[%d~", code);
|
2003-04-27 15:10:48 +04:00
|
|
|
use_ucsoutput = FALSE;
|
2002-10-10 16:14:05 +04:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Cursor keys. (This includes the numberpad cursor keys,
|
|
|
|
* if we haven't already done them due to app keypad mode.)
|
|
|
|
*
|
|
|
|
* Here we also process un-numlocked un-appkeypadded KP5,
|
|
|
|
* which sends ESC [ G.
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
int xkey = 0;
|
|
|
|
switch (event->keyval) {
|
2015-08-08 18:23:54 +03:00
|
|
|
case GDK_KEY_Up: case GDK_KEY_KP_Up: xkey = 'A'; break;
|
|
|
|
case GDK_KEY_Down: case GDK_KEY_KP_Down: xkey = 'B'; break;
|
|
|
|
case GDK_KEY_Right: case GDK_KEY_KP_Right: xkey = 'C'; break;
|
|
|
|
case GDK_KEY_Left: case GDK_KEY_KP_Left: xkey = 'D'; break;
|
|
|
|
case GDK_KEY_Begin: case GDK_KEY_KP_Begin: xkey = 'G'; break;
|
2002-10-10 16:14:05 +04:00
|
|
|
}
|
|
|
|
if (xkey) {
|
2010-03-06 18:50:26 +03:00
|
|
|
end = 1 + format_arrow_key(output+1, inst->term, xkey,
|
|
|
|
event->state & GDK_CONTROL_MASK);
|
2015-09-06 11:13:48 +03:00
|
|
|
#ifdef KEY_EVENT_DIAGNOSTICS
|
|
|
|
debug((" - arrow key"));
|
|
|
|
#endif
|
2003-04-27 15:10:48 +04:00
|
|
|
use_ucsoutput = FALSE;
|
2002-10-10 16:14:05 +04:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
}
|
2002-10-15 21:18:24 +04:00
|
|
|
goto done;
|
|
|
|
}
|
2002-10-10 16:14:05 +04:00
|
|
|
|
2002-10-15 21:18:24 +04:00
|
|
|
done:
|
2002-10-10 16:14:05 +04:00
|
|
|
|
2002-10-15 21:18:24 +04:00
|
|
|
if (end-start > 0) {
|
2003-04-12 13:27:56 +04:00
|
|
|
if (special) {
|
2015-09-06 11:13:48 +03:00
|
|
|
#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
|
2003-04-12 13:27:56 +04:00
|
|
|
/*
|
|
|
|
* For special control characters, the character set
|
|
|
|
* should never matter.
|
|
|
|
*/
|
|
|
|
output[end] = '\0'; /* NUL-terminate */
|
2004-08-14 17:04:18 +04:00
|
|
|
if (inst->ldisc)
|
|
|
|
ldisc_send(inst->ldisc, output+start, -2, 1);
|
2003-04-12 13:27:56 +04:00
|
|
|
} else if (!inst->direct_to_font) {
|
2003-04-27 15:10:48 +04:00
|
|
|
if (!use_ucsoutput) {
|
2015-09-06 11:13:48 +03:00
|
|
|
#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
|
2004-08-14 17:04:18 +04:00
|
|
|
if (inst->ldisc)
|
2009-02-28 19:52:42 +03:00
|
|
|
lpage_send(inst->ldisc, output_charset, output+start,
|
2004-08-14 17:04:18 +04:00
|
|
|
end-start, 1);
|
2003-04-27 15:10:48 +04:00
|
|
|
} else {
|
2015-09-06 11:13:48 +03:00
|
|
|
#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
|
|
|
|
|
2003-04-27 15:10:48 +04:00
|
|
|
/*
|
|
|
|
* We generated our own Unicode key data from the
|
|
|
|
* keysym, so use that instead.
|
|
|
|
*/
|
2004-08-14 17:04:18 +04:00
|
|
|
if (inst->ldisc)
|
|
|
|
luni_send(inst->ldisc, ucsoutput+start, end-start, 1);
|
2003-04-27 15:10:48 +04:00
|
|
|
}
|
2003-01-02 01:25:25 +03:00
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* In direct-to-font mode, we just send the string
|
|
|
|
* exactly as we received it.
|
|
|
|
*/
|
2015-09-06 11:13:48 +03:00
|
|
|
#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
|
2004-08-14 17:04:18 +04:00
|
|
|
if (inst->ldisc)
|
|
|
|
ldisc_send(inst->ldisc, output+start, end-start, 1);
|
2003-01-02 01:25:25 +03:00
|
|
|
}
|
2002-12-31 15:20:34 +03:00
|
|
|
|
2002-10-26 16:58:13 +04:00
|
|
|
show_mouseptr(inst, 0);
|
2002-10-26 15:08:59 +04:00
|
|
|
term_seen_key_event(inst->term);
|
2002-10-09 22:09:42 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
2002-10-07 20:45:23 +04:00
|
|
|
}
|
|
|
|
|
2012-06-17 11:26:23 +04:00
|
|
|
#if GTK_CHECK_VERSION(2,0,0)
|
|
|
|
void input_method_commit_event(GtkIMContext *imc, gchar *str, gpointer data)
|
|
|
|
{
|
|
|
|
struct gui_data *inst = (struct gui_data *)data;
|
2015-09-06 11:13:48 +03:00
|
|
|
|
|
|
|
#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
|
|
|
|
|
2013-07-11 21:24:20 +04:00
|
|
|
if (inst->ldisc)
|
|
|
|
lpage_send(inst->ldisc, CS_UTF8, str, strlen(str), 1);
|
2012-06-18 22:10:59 +04:00
|
|
|
show_mouseptr(inst, 0);
|
|
|
|
term_seen_key_event(inst->term);
|
2012-06-17 11:26:23 +04:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2015-09-25 17:11:44 +03:00
|
|
|
#define SCROLL_INCREMENT_LINES 5
|
|
|
|
|
|
|
|
#if GTK_CHECK_VERSION(3,4,0)
|
|
|
|
gboolean scroll_internal(struct gui_data *inst, gdouble delta, guint state,
|
|
|
|
gdouble ex, gdouble ey)
|
|
|
|
{
|
|
|
|
int shift, ctrl, alt, x, y, raw_mouse_mode;
|
|
|
|
|
|
|
|
show_mouseptr(inst, 1);
|
|
|
|
|
|
|
|
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 =
|
|
|
|
send_raw_mouse && !(shift && conf_get_int(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
|
|
|
|
|
2017-03-06 00:41:21 +03:00
|
|
|
static gboolean button_internal(struct gui_data *inst, GdkEventButton *event)
|
2002-10-13 15:24:25 +04:00
|
|
|
{
|
2014-02-16 20:40:46 +04:00
|
|
|
int shift, ctrl, alt, x, y, button, act, raw_mouse_mode;
|
2002-10-13 15:24:25 +04:00
|
|
|
|
2003-08-21 22:03:06 +04:00
|
|
|
/* Remember the timestamp. */
|
2017-03-06 00:41:21 +03:00
|
|
|
inst->input_event_time = event->time;
|
2003-08-21 22:03:06 +04:00
|
|
|
|
2002-10-26 16:58:13 +04:00
|
|
|
show_mouseptr(inst, 1);
|
2002-10-14 13:58:27 +04:00
|
|
|
|
2017-03-06 00:41:21 +03:00
|
|
|
shift = event->state & GDK_SHIFT_MASK;
|
|
|
|
ctrl = event->state & GDK_CONTROL_MASK;
|
|
|
|
alt = event->state & inst->meta_mod_mask;
|
2003-04-05 20:05:00 +04:00
|
|
|
|
2014-02-16 20:40:46 +04:00
|
|
|
raw_mouse_mode =
|
|
|
|
send_raw_mouse && !(shift && conf_get_int(inst->conf,
|
|
|
|
CONF_mouse_override));
|
|
|
|
|
|
|
|
if (!raw_mouse_mode) {
|
2017-03-06 00:41:21 +03:00
|
|
|
if (event->button == 4 && event->type == GDK_BUTTON_PRESS) {
|
2015-09-25 17:11:44 +03:00
|
|
|
term_scroll(inst->term, 0, -SCROLL_INCREMENT_LINES);
|
2014-02-16 20:40:46 +04:00
|
|
|
return TRUE;
|
|
|
|
}
|
2017-03-06 00:41:21 +03:00
|
|
|
if (event->button == 5 && event->type == GDK_BUTTON_PRESS) {
|
2015-09-25 17:11:44 +03:00
|
|
|
term_scroll(inst->term, 0, +SCROLL_INCREMENT_LINES);
|
2014-02-16 20:40:46 +04:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-06 00:41:21 +03:00
|
|
|
if (event->button == 3 && ctrl) {
|
|
|
|
#if GTK_CHECK_VERSION(3,22,0)
|
|
|
|
gtk_menu_popup_at_pointer(GTK_MENU(inst->menu), (GdkEvent *)event);
|
|
|
|
#else
|
2003-04-05 20:05:00 +04:00
|
|
|
gtk_menu_popup(GTK_MENU(inst->menu), NULL, NULL, NULL, NULL,
|
2017-03-06 00:41:21 +03:00
|
|
|
event->button, event->time);
|
|
|
|
#endif
|
2003-04-05 20:05:00 +04:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2017-03-06 00:41:21 +03:00
|
|
|
if (event->button == 1)
|
2002-10-13 15:24:25 +04:00
|
|
|
button = MBT_LEFT;
|
2017-03-06 00:41:21 +03:00
|
|
|
else if (event->button == 2)
|
2002-10-13 15:24:25 +04:00
|
|
|
button = MBT_MIDDLE;
|
2017-03-06 00:41:21 +03:00
|
|
|
else if (event->button == 3)
|
2002-10-13 15:24:25 +04:00
|
|
|
button = MBT_RIGHT;
|
2017-03-06 00:41:21 +03:00
|
|
|
else if (event->button == 4)
|
2014-02-16 20:40:46 +04:00
|
|
|
button = MBT_WHEEL_UP;
|
2017-03-06 00:41:21 +03:00
|
|
|
else if (event->button == 5)
|
2014-02-16 20:40:46 +04:00
|
|
|
button = MBT_WHEEL_DOWN;
|
2002-10-13 15:24:25 +04:00
|
|
|
else
|
|
|
|
return FALSE; /* don't even know what button! */
|
|
|
|
|
2017-03-06 00:41:21 +03:00
|
|
|
switch (event->type) {
|
2002-10-13 15:24:25 +04:00
|
|
|
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 */
|
|
|
|
}
|
|
|
|
|
2014-02-16 20:40:46 +04:00
|
|
|
if (raw_mouse_mode && act != MA_CLICK && act != MA_RELEASE)
|
2002-10-13 15:24:25 +04:00
|
|
|
return TRUE; /* we ignore these in raw mouse mode */
|
|
|
|
|
2017-03-06 00:41:21 +03:00
|
|
|
x = (event->x - inst->window_border) / inst->font_width;
|
|
|
|
y = (event->y - inst->window_border) / inst->font_height;
|
2002-10-13 15:24:25 +04:00
|
|
|
|
2003-01-25 19:16:45 +03:00
|
|
|
term_mouse(inst->term, button, translate_button(button), act,
|
|
|
|
x, y, shift, ctrl, alt);
|
2002-10-13 15:24:25 +04:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2008-06-11 00:18:23 +04:00
|
|
|
gboolean button_event(GtkWidget *widget, GdkEventButton *event, gpointer data)
|
|
|
|
{
|
|
|
|
struct gui_data *inst = (struct gui_data *)data;
|
2017-03-06 00:41:21 +03:00
|
|
|
return button_internal(inst, event);
|
2008-06-11 00:18:23 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
#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)
|
|
|
|
{
|
|
|
|
struct gui_data *inst = (struct gui_data *)data;
|
|
|
|
|
2015-09-25 17:11:44 +03:00
|
|
|
#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;
|
2017-03-06 00:41:21 +03:00
|
|
|
GdkEventButton *event_button;
|
|
|
|
gboolean ret;
|
|
|
|
|
2008-06-11 00:18:23 +04:00
|
|
|
if (event->direction == GDK_SCROLL_UP)
|
|
|
|
button = 4;
|
|
|
|
else if (event->direction == GDK_SCROLL_DOWN)
|
|
|
|
button = 5;
|
|
|
|
else
|
|
|
|
return FALSE;
|
|
|
|
|
2017-03-06 00:41:21 +03:00
|
|
|
event_button = (GdkEventButton *)gdk_event_new(GDK_BUTTON_PRESS);
|
2017-05-20 14:44:56 +03:00
|
|
|
event_button->window = g_object_ref(event->window);
|
2017-03-06 00:41:21 +03:00
|
|
|
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;
|
2017-05-20 14:44:56 +03:00
|
|
|
event_button->device = g_object_ref(event->device);
|
2017-03-06 00:41:21 +03:00
|
|
|
event_button->x_root = event->x_root;
|
|
|
|
event_button->y_root = event->y_root;
|
|
|
|
ret = button_internal(inst, event_button);
|
2017-04-30 13:39:07 +03:00
|
|
|
gdk_event_free((GdkEvent *)event_button);
|
2017-03-06 00:41:21 +03:00
|
|
|
return ret;
|
2015-09-25 17:11:44 +03:00
|
|
|
#endif
|
2008-06-11 00:18:23 +04:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2002-10-13 15:24:25 +04:00
|
|
|
gint motion_event(GtkWidget *widget, GdkEventMotion *event, gpointer data)
|
|
|
|
{
|
|
|
|
struct gui_data *inst = (struct gui_data *)data;
|
|
|
|
int shift, ctrl, alt, x, y, button;
|
|
|
|
|
2003-08-21 22:03:06 +04:00
|
|
|
/* Remember the timestamp. */
|
|
|
|
inst->input_event_time = event->time;
|
|
|
|
|
2002-10-26 16:58:13 +04:00
|
|
|
show_mouseptr(inst, 1);
|
2002-10-14 13:58:27 +04:00
|
|
|
|
2002-10-13 15:24:25 +04:00
|
|
|
shift = event->state & GDK_SHIFT_MASK;
|
|
|
|
ctrl = event->state & GDK_CONTROL_MASK;
|
2015-09-01 21:00:25 +03:00
|
|
|
alt = event->state & inst->meta_mod_mask;
|
2002-10-13 15:24:25 +04:00
|
|
|
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;
|
2002-10-13 15:24:25 +04:00
|
|
|
|
2003-01-25 19:16:45 +03:00
|
|
|
term_mouse(inst->term, button, translate_button(button), MA_DRAG,
|
|
|
|
x, y, shift, ctrl, alt);
|
2002-10-13 15:24:25 +04:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2002-10-26 14:16:19 +04:00
|
|
|
void frontend_keypress(void *handle)
|
2002-10-23 18:21:12 +04:00
|
|
|
{
|
2002-10-26 14:16:19 +04:00
|
|
|
struct gui_data *inst = (struct gui_data *)handle;
|
|
|
|
|
2002-10-23 18:21:12 +04:00
|
|
|
/*
|
|
|
|
* If our child process has exited but not closed, terminate on
|
|
|
|
* any keypress.
|
|
|
|
*/
|
|
|
|
if (inst->exited)
|
2017-11-27 23:18:23 +03:00
|
|
|
gtk_widget_destroy(inst->window);
|
2002-10-23 18:21:12 +04:00
|
|
|
}
|
|
|
|
|
2013-08-17 20:06:22 +04:00
|
|
|
static void exit_callback(void *vinst)
|
2002-10-07 20:45:23 +04:00
|
|
|
{
|
2013-08-17 20:06:22 +04:00
|
|
|
struct gui_data *inst = (struct gui_data *)vinst;
|
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;
|
2002-10-14 13:18:34 +04:00
|
|
|
|
2003-04-01 22:10:25 +04:00
|
|
|
if (!inst->exited &&
|
|
|
|
(exitcode = inst->back->exitcode(inst->backhandle)) >= 0) {
|
2017-11-26 22:59:24 +03:00
|
|
|
destroy_inst_connection(inst);
|
2017-11-26 14:50:49 +03:00
|
|
|
|
2017-11-26 22:59:24 +03:00
|
|
|
close_on_exit = conf_get_int(inst->conf, CONF_close_on_exit);
|
2017-11-26 14:50:49 +03:00
|
|
|
if (close_on_exit == FORCE_ON ||
|
|
|
|
(close_on_exit == AUTO && exitcode == 0)) {
|
|
|
|
gtk_widget_destroy(inst->window);
|
|
|
|
}
|
2002-10-14 13:18:34 +04:00
|
|
|
}
|
2008-11-17 21:36:27 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void notify_remote_exit(void *frontend)
|
|
|
|
{
|
|
|
|
struct gui_data *inst = (struct gui_data *)frontend;
|
|
|
|
|
2013-08-17 20:06:22 +04:00
|
|
|
queue_toplevel_callback(exit_callback, inst);
|
2004-11-27 16:20:21 +03:00
|
|
|
}
|
2002-10-07 20:45:23 +04:00
|
|
|
|
2017-11-26 22:59:24 +03:00
|
|
|
static void destroy_inst_connection(struct gui_data *inst)
|
|
|
|
{
|
|
|
|
inst->exited = TRUE;
|
|
|
|
if (inst->ldisc) {
|
|
|
|
ldisc_free(inst->ldisc);
|
|
|
|
inst->ldisc = NULL;
|
|
|
|
}
|
|
|
|
if (inst->backhandle) {
|
|
|
|
inst->back->free(inst->backhandle);
|
|
|
|
inst->backhandle = NULL;
|
|
|
|
inst->back = NULL;
|
|
|
|
}
|
|
|
|
if (inst->term)
|
|
|
|
term_provide_resize_fn(inst->term, NULL, NULL);
|
|
|
|
if (inst->menu) {
|
|
|
|
update_specials_menu(inst);
|
|
|
|
gtk_widget_set_sensitive(inst->restartitem, TRUE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-26 14:50:49 +03:00
|
|
|
static void delete_inst(struct gui_data *inst)
|
|
|
|
{
|
2017-11-26 19:51:19 +03:00
|
|
|
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;
|
|
|
|
}
|
2017-11-26 17:55:15 +03:00
|
|
|
}
|
2017-11-26 14:50:49 +03:00
|
|
|
if (inst->window) {
|
|
|
|
gtk_widget_destroy(inst->window);
|
|
|
|
inst->window = NULL;
|
|
|
|
}
|
|
|
|
if (inst->menu) {
|
|
|
|
gtk_widget_destroy(inst->menu);
|
|
|
|
inst->menu = NULL;
|
|
|
|
}
|
2017-11-26 22:59:24 +03:00
|
|
|
destroy_inst_connection(inst);
|
2017-11-26 14:50:49 +03:00
|
|
|
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;
|
|
|
|
}
|
2017-11-26 18:35:25 +03:00
|
|
|
|
2017-12-17 23:12:52 +03:00
|
|
|
#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
|
|
|
|
|
2017-11-26 18:35:25 +03:00
|
|
|
/*
|
|
|
|
* 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);
|
|
|
|
|
2017-11-26 14:50:49 +03:00
|
|
|
sfree(inst);
|
|
|
|
}
|
|
|
|
|
2002-10-07 20:45:23 +04:00
|
|
|
void destroy(GtkWidget *widget, gpointer data)
|
|
|
|
{
|
2017-11-26 14:50:49 +03:00
|
|
|
struct gui_data *inst = (struct gui_data *)data;
|
|
|
|
inst->window = NULL;
|
|
|
|
delete_inst(inst);
|
Make the configuration dialog non-modal.
Now every call to do_config_box is replaced with a call to
create_config_box, which returns immediately having constructed the
new GTK window object, and is passed a callback function which it will
arrange to be called when the dialog terminates (whether by OK or by
Cancel). That callback is now what triggers the construction of a
session window after 'Open' is pressed in the initial config box, or
the actual mid-session reconfiguration action after 'Apply' is pressed
in a Change Settings box.
We were already prepared to ignore the re-selection of 'Change
Settings' from the context menu of a window that already had a Change
Settings box open (and not accidentally create a second config box for
the same window); but now we do slightly better, by finding the
existing config box and un-minimising and raising it, in case the user
had forgotten it was there.
That's a useful featurelet, but not the main purpose of this change.
The mani point, of course, is that now the multi-window GtkApplication
based front ends now don't do anything confusing to the nesting of
gtk_main() when config boxes are involved. Whether you're changing the
settings of one (or more than one) of your already-running sessions,
preparing to start up a new PuTTY connection, or both at once, we stay
in the same top-level instance of gtk_main() and all sessions' top-
level callbacks continue to run sensibly.
2017-11-26 14:58:02 +03:00
|
|
|
session_window_closed();
|
2002-10-07 20:45:23 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
gint focus_event(GtkWidget *widget, GdkEventFocus *event, gpointer data)
|
|
|
|
{
|
2002-10-26 16:58:13 +04:00
|
|
|
struct gui_data *inst = (struct gui_data *)data;
|
2004-11-27 22:34:45 +03:00
|
|
|
term_set_focus(inst->term, event->in);
|
2002-10-26 15:08:59 +04:00
|
|
|
term_update(inst->term);
|
2002-10-26 16:58:13 +04:00
|
|
|
show_mouseptr(inst, 1);
|
2002-10-09 22:09:42 +04:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2005-02-15 20:05:58 +03:00
|
|
|
void set_busy_status(void *frontend, int status)
|
|
|
|
{
|
|
|
|
struct gui_data *inst = (struct gui_data *)frontend;
|
|
|
|
inst->busy_status = status;
|
|
|
|
update_mouseptr(inst);
|
|
|
|
}
|
|
|
|
|
2002-10-09 22:09:42 +04:00
|
|
|
/*
|
|
|
|
* set or clear the "raw mouse message" mode
|
|
|
|
*/
|
2002-10-26 16:58:13 +04:00
|
|
|
void set_raw_mouse_mode(void *frontend, int activate)
|
2002-10-09 22:09:42 +04:00
|
|
|
{
|
2002-10-26 16:58:13 +04:00
|
|
|
struct gui_data *inst = (struct gui_data *)frontend;
|
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
|
|
|
activate = activate && !conf_get_int(inst->conf, CONF_no_mouse_rep);
|
2002-10-10 14:40:30 +04:00
|
|
|
send_raw_mouse = activate;
|
2005-02-15 20:05:58 +03:00
|
|
|
update_mouseptr(inst);
|
2002-10-09 22:09:42 +04:00
|
|
|
}
|
|
|
|
|
2016-04-04 13:24:24 +03:00
|
|
|
#if GTK_CHECK_VERSION(2,0,0)
|
|
|
|
static void compute_whole_window_size(struct gui_data *inst,
|
|
|
|
int wchars, int hchars,
|
|
|
|
int *wpix, int *hpix);
|
|
|
|
#endif
|
2016-04-04 13:23:25 +03:00
|
|
|
|
2002-10-26 16:58:13 +04:00
|
|
|
void request_resize(void *frontend, int w, int h)
|
2002-10-09 22:09:42 +04:00
|
|
|
{
|
2002-10-26 16:58:13 +04:00
|
|
|
struct gui_data *inst = (struct gui_data *)frontend;
|
2015-08-24 20:59:13 +03:00
|
|
|
|
|
|
|
#if !GTK_CHECK_VERSION(3,0,0)
|
|
|
|
|
2002-10-15 20:24:42 +04:00
|
|
|
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.
|
|
|
|
*/
|
2002-10-26 16:58:13 +04:00
|
|
|
get_window_pixels(inst, &large_x, &large_y);
|
2002-10-15 20:24:42 +04:00
|
|
|
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;
|
2002-10-15 20:24:42 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 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);
|
2015-08-09 11:59:25 +03:00
|
|
|
#if GTK_CHECK_VERSION(2,0,0)
|
2007-01-25 22:33:29 +03:00
|
|
|
gtk_window_resize(GTK_WINDOW(inst->window),
|
|
|
|
area_x + offset_x, area_y + offset_y);
|
2002-10-15 20:24:42 +04:00
|
|
|
#else
|
2003-04-10 22:00:50 +04:00
|
|
|
gtk_drawing_area_size(GTK_DRAWING_AREA(inst->area), area_x, area_y);
|
2008-03-29 23:02:12 +03:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
2003-04-10 22:00:50 +04:00
|
|
|
gtk_container_dequeue_resize_handler(GTK_CONTAINER(inst->window));
|
2015-08-08 17:53:43 +03:00
|
|
|
gdk_window_resize(gtk_widget_get_window(inst->window),
|
2002-10-15 20:24:42 +04:00
|
|
|
area_x + offset_x, area_y + offset_y);
|
|
|
|
#endif
|
2015-08-24 20:59:13 +03:00
|
|
|
|
|
|
|
#else /* GTK_CHECK_VERSION(3,0,0) */
|
|
|
|
|
2016-04-04 13:24:24 +03:00
|
|
|
int wp, hp;
|
|
|
|
compute_whole_window_size(inst, w, h, &wp, &hp);
|
|
|
|
gtk_window_resize(GTK_WINDOW(inst->window), wp, hp);
|
2015-08-24 20:59:13 +03:00
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2002-10-09 22:09:42 +04:00
|
|
|
}
|
|
|
|
|
2002-10-26 16:58:13 +04:00
|
|
|
static void real_palette_set(struct gui_data *inst, int n, int r, int g, int b)
|
2002-10-14 14:21:35 +04:00
|
|
|
{
|
|
|
|
inst->cols[n].red = r * 0x0101;
|
|
|
|
inst->cols[n].green = g * 0x0101;
|
|
|
|
inst->cols[n].blue = b * 0x0101;
|
|
|
|
|
2015-08-16 16:22:14 +03:00
|
|
|
#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
|
2002-10-14 14:21:35 +04:00
|
|
|
}
|
|
|
|
|
2015-08-22 16:11:45 +03:00
|
|
|
#if GTK_CHECK_VERSION(3,0,0)
|
2017-03-06 00:45:04 +03:00
|
|
|
char *colour_to_css(const GdkColor *col)
|
|
|
|
{
|
2015-08-22 16:11:45 +03:00
|
|
|
GdkRGBA rgba;
|
|
|
|
rgba.red = col->red / 65535.0;
|
|
|
|
rgba.green = col->green / 65535.0;
|
|
|
|
rgba.blue = col->blue / 65535.0;
|
|
|
|
rgba.alpha = 1.0;
|
2017-03-06 00:45:04 +03:00
|
|
|
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);
|
2015-08-22 16:11:45 +03:00
|
|
|
#else
|
2017-04-30 13:01:13 +03:00
|
|
|
if (gtk_widget_get_window(widget)) {
|
2015-08-25 21:50:23 +03:00
|
|
|
/* For GTK1, which doesn't have a 'const' on
|
|
|
|
* gdk_window_set_background's second parameter type. */
|
|
|
|
GdkColor col_mutable = *col;
|
2017-04-30 13:01:13 +03:00
|
|
|
gdk_window_set_background(gtk_widget_get_window(widget), &col_mutable);
|
2015-08-25 21:50:23 +03:00
|
|
|
}
|
2015-08-22 16:11:45 +03:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2002-10-26 16:58:13 +04:00
|
|
|
void set_window_background(struct gui_data *inst)
|
2002-10-25 15:58:59 +04:00
|
|
|
{
|
2017-03-06 00:45:04 +03:00
|
|
|
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]);
|
2002-10-25 15:58:59 +04:00
|
|
|
}
|
|
|
|
|
2002-10-26 16:58:13 +04:00
|
|
|
void palette_set(void *frontend, int n, int r, int g, int b)
|
2002-10-09 22:09:42 +04:00
|
|
|
{
|
2002-10-26 16:58:13 +04:00
|
|
|
struct gui_data *inst = (struct gui_data *)frontend;
|
2004-11-28 18:13:34 +03:00
|
|
|
if (n >= 16)
|
|
|
|
n += 256 - 16;
|
2013-07-01 21:56:33 +04:00
|
|
|
if (n >= NALLCOLOURS)
|
2004-11-28 18:13:34 +03:00
|
|
|
return;
|
|
|
|
real_palette_set(inst, n, r, g, b);
|
2006-03-13 01:17:46 +03:00
|
|
|
if (n == 258) {
|
|
|
|
/* Default Background changed. Ensure space between text area and
|
|
|
|
* window border is redrawn */
|
2002-10-26 16:58:13 +04:00
|
|
|
set_window_background(inst);
|
2006-03-13 01:17:46 +03:00
|
|
|
draw_backing_rect(inst);
|
|
|
|
gtk_widget_queue_draw(inst->area);
|
|
|
|
}
|
2002-10-09 22:09:42 +04:00
|
|
|
}
|
2002-10-14 14:21:35 +04:00
|
|
|
|
2017-10-05 22:43:02 +03:00
|
|
|
int palette_get(void *frontend, int n, int *r, int *g, int *b)
|
|
|
|
{
|
|
|
|
struct gui_data *inst = (struct gui_data *)frontend;
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2002-10-26 16:58:13 +04:00
|
|
|
void palette_reset(void *frontend)
|
2002-10-09 22:09:42 +04:00
|
|
|
{
|
2002-10-26 16:58:13 +04:00
|
|
|
struct gui_data *inst = (struct gui_data *)frontend;
|
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. */
|
2002-10-14 14:21:35 +04:00
|
|
|
static const int ww[] = {
|
2004-11-28 18:13:34 +03:00
|
|
|
256, 257, 258, 259, 260, 261,
|
|
|
|
0, 8, 1, 9, 2, 10, 3, 11,
|
|
|
|
4, 12, 5, 13, 6, 14, 7, 15
|
2002-10-14 14:21:35 +04:00
|
|
|
};
|
|
|
|
int i;
|
|
|
|
|
2004-11-28 18:13:34 +03:00
|
|
|
assert(lenof(ww) == NCFGCOLOURS);
|
2002-10-14 14:21:35 +04:00
|
|
|
|
2015-08-16 16:22:14 +03:00
|
|
|
#if !GTK_CHECK_VERSION(3,0,0)
|
2002-10-14 14:21:35 +04:00
|
|
|
if (!inst->colmap) {
|
|
|
|
inst->colmap = gdk_colormap_get_system();
|
|
|
|
} else {
|
2004-11-28 18:13:34 +03:00
|
|
|
gdk_colormap_free_colors(inst->colmap, inst->cols, NALLCOLOURS);
|
2002-10-14 14:21:35 +04:00
|
|
|
}
|
2015-08-16 16:22:14 +03:00
|
|
|
#endif
|
2002-10-14 14:21:35 +04:00
|
|
|
|
2004-11-28 18:13:34 +03:00
|
|
|
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;
|
2002-10-14 14:21:35 +04:00
|
|
|
}
|
|
|
|
|
2004-11-28 18:13:34 +03:00
|
|
|
for (i = 0; i < NEXTCOLOURS; i++) {
|
|
|
|
if (i < 216) {
|
|
|
|
int r = i / 36, g = (i / 6) % 6, b = i % 6;
|
2005-10-14 01:56:43 +04:00
|
|
|
inst->cols[i+16].red = r ? r * 0x2828 + 0x3737 : 0;
|
|
|
|
inst->cols[i+16].green = g ? g * 0x2828 + 0x3737 : 0;
|
2007-03-19 15:05:34 +03:00
|
|
|
inst->cols[i+16].blue = b ? b * 0x2828 + 0x3737 : 0;
|
2004-11-28 18:13:34 +03:00
|
|
|
} else {
|
|
|
|
int shade = i - 216;
|
2005-10-14 01:56:43 +04:00
|
|
|
shade = shade * 0x0a0a + 0x0808;
|
2004-11-28 18:13:34 +03:00
|
|
|
inst->cols[i+16].red = inst->cols[i+16].green =
|
|
|
|
inst->cols[i+16].blue = shade;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-08-16 16:22:14 +03:00
|
|
|
#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));
|
|
|
|
}
|
2002-10-14 14:21:35 +04:00
|
|
|
}
|
2015-08-16 16:22:14 +03:00
|
|
|
#endif
|
2002-10-25 15:58:59 +04:00
|
|
|
|
2006-03-13 01:17:46 +03:00
|
|
|
/* Since Default Background may have changed, ensure that space
|
|
|
|
* between text area and window border is refreshed. */
|
2002-10-26 16:58:13 +04:00
|
|
|
set_window_background(inst);
|
2015-08-08 17:53:43 +03:00
|
|
|
if (inst->area && gtk_widget_get_window(inst->area)) {
|
2006-03-13 01:17:46 +03:00
|
|
|
draw_backing_rect(inst);
|
|
|
|
gtk_widget_queue_draw(inst->area);
|
|
|
|
}
|
2002-10-09 22:09:42 +04:00
|
|
|
}
|
|
|
|
|
2017-12-17 21:44:27 +03:00
|
|
|
static struct clipboard_state *clipboard_from_atom(
|
|
|
|
struct gui_data *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;
|
|
|
|
}
|
|
|
|
|
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.
|
2003-08-21 22:07:27 +04:00
|
|
|
*/
|
2015-09-02 23:37:33 +03:00
|
|
|
|
2017-12-17 21:44:27 +03:00
|
|
|
void set_clipboard_atom(struct gui_data *inst, int clipboard, GdkAtom atom)
|
2017-12-10 13:23:39 +03:00
|
|
|
{
|
|
|
|
struct clipboard_state *state = &inst->clipstates[clipboard];
|
|
|
|
|
|
|
|
state->inst = inst;
|
|
|
|
state->clipboard = clipboard;
|
2017-12-17 21:44:27 +03:00
|
|
|
state->atom = atom;
|
2017-12-10 13:23:39 +03:00
|
|
|
|
2017-12-17 21:44:27 +03:00
|
|
|
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;
|
|
|
|
}
|
2017-12-10 13:23:39 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
int init_clipboard(struct gui_data *inst)
|
2003-08-21 22:07:27 +04:00
|
|
|
{
|
2017-12-17 21:44:27 +03:00
|
|
|
set_clipboard_atom(inst, CLIP_PRIMARY, GDK_SELECTION_PRIMARY);
|
2018-03-03 21:18:54 +03:00
|
|
|
set_clipboard_atom(inst, CLIP_CLIPBOARD, clipboard_atom);
|
2017-12-10 13:23:39 +03:00
|
|
|
return TRUE;
|
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;
|
|
|
|
|
2017-12-17 23:12:52 +03:00
|
|
|
if (cdi->state && cdi->state->current_cdi == cdi) {
|
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;
|
|
|
|
|
2017-12-17 23:12:52 +03:00
|
|
|
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;
|
2015-09-02 23:37:33 +03:00
|
|
|
}
|
|
|
|
sfree(cdi->pasteout_data_utf8);
|
2017-12-17 23:43:44 +03:00
|
|
|
cdi->next->prev = cdi->prev;
|
|
|
|
cdi->prev->next = cdi->next;
|
2015-09-02 23:37:33 +03:00
|
|
|
sfree(cdi);
|
|
|
|
}
|
|
|
|
|
2017-12-09 15:00:13 +03:00
|
|
|
void write_clip(void *frontend, int clipboard,
|
2017-12-10 13:23:39 +03:00
|
|
|
wchar_t *data, int *attr, truecolour *truecolour, int len,
|
2017-12-09 15:00:13 +03:00
|
|
|
int must_deselect)
|
2015-09-02 23:37:33 +03:00
|
|
|
{
|
|
|
|
struct gui_data *inst = (struct gui_data *)frontend;
|
2017-12-10 13:23:39 +03:00
|
|
|
struct clipboard_state *state = &inst->clipstates[clipboard];
|
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;
|
|
|
|
}
|
|
|
|
|
2017-12-17 21:44:27 +03:00
|
|
|
if (!state->gtkclipboard)
|
|
|
|
return;
|
|
|
|
|
2015-09-02 23:37:33 +03:00
|
|
|
cdi = snew(struct clipboard_data_instance);
|
2017-12-17 23:12:52 +03:00
|
|
|
cdi->state = state;
|
2017-12-10 13:23:39 +03:00
|
|
|
state->current_cdi = cdi;
|
2015-09-02 23:37:33 +03:00
|
|
|
cdi->pasteout_data_utf8 = snewn(len*6, char);
|
2017-12-17 23:12:52 +03:00
|
|
|
cdi->prev = inst->cdi_headtail.prev;
|
|
|
|
cdi->next = &inst->cdi_headtail;
|
|
|
|
cdi->next->prev = cdi;
|
|
|
|
cdi->prev->next = cdi;
|
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);
|
2017-12-10 13:23:39 +03:00
|
|
|
gtk_clipboard_set_with_data(state->gtkclipboard, targettable,
|
|
|
|
n_targets, clipboard_provide_data,
|
|
|
|
clipboard_clear, cdi);
|
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)
|
|
|
|
{
|
|
|
|
struct gui_data *inst = (struct gui_data *)data;
|
Stop front ends remembering the data of their last paste.
Previously, both the Unix and Windows front ends would respond to a
paste action by retrieving data from the system clipboard, converting
it appropriately, _storing_ it in a persistent dynamic data block
inside the front end, and then calling term_do_paste(term), which in
turn would call back to the front end via get_clip() to retrieve the
current contents of that stored data block.
But, as far as I can tell, this was a completely pointless mechanism,
because after a data block was written into this storage area, it
would be immediately used for exactly one paste, and then never
accessed again until the next paste action caused it to be freed and
replaced with a new chunk of pasted data.
So why on earth was it stored persistently at all, and why that
callback mechanism from frontend to terminal back to frontend to
retrieve it for the actual paste action? I have no idea. This change
removes the entire system and replaces it with the completely obvious
alternative: the character-set-converted version of paste data is
allocated in a _local_ variable in the frontend paste functions,
passed directly to term_do_paste which now takes (buffer,length)
parameters, and freed immediately afterwards. get_clip() is gone.
2017-12-09 11:41:03 +03:00
|
|
|
wchar_t *paste;
|
|
|
|
int paste_len;
|
2015-09-02 23:37:33 +03:00
|
|
|
int length;
|
|
|
|
|
|
|
|
if (!text)
|
|
|
|
return;
|
|
|
|
|
|
|
|
length = strlen(text);
|
|
|
|
|
Stop front ends remembering the data of their last paste.
Previously, both the Unix and Windows front ends would respond to a
paste action by retrieving data from the system clipboard, converting
it appropriately, _storing_ it in a persistent dynamic data block
inside the front end, and then calling term_do_paste(term), which in
turn would call back to the front end via get_clip() to retrieve the
current contents of that stored data block.
But, as far as I can tell, this was a completely pointless mechanism,
because after a data block was written into this storage area, it
would be immediately used for exactly one paste, and then never
accessed again until the next paste action caused it to be freed and
replaced with a new chunk of pasted data.
So why on earth was it stored persistently at all, and why that
callback mechanism from frontend to terminal back to frontend to
retrieve it for the actual paste action? I have no idea. This change
removes the entire system and replaces it with the completely obvious
alternative: the character-set-converted version of paste data is
allocated in a _local_ variable in the frontend paste functions,
passed directly to term_do_paste which now takes (buffer,length)
parameters, and freed immediately afterwards. get_clip() is gone.
2017-12-09 11:41:03 +03:00
|
|
|
paste = snewn(length, wchar_t);
|
|
|
|
paste_len = mb_to_wc(CS_UTF8, 0, text, length, paste, length);
|
2015-09-02 23:37:33 +03:00
|
|
|
|
Stop front ends remembering the data of their last paste.
Previously, both the Unix and Windows front ends would respond to a
paste action by retrieving data from the system clipboard, converting
it appropriately, _storing_ it in a persistent dynamic data block
inside the front end, and then calling term_do_paste(term), which in
turn would call back to the front end via get_clip() to retrieve the
current contents of that stored data block.
But, as far as I can tell, this was a completely pointless mechanism,
because after a data block was written into this storage area, it
would be immediately used for exactly one paste, and then never
accessed again until the next paste action caused it to be freed and
replaced with a new chunk of pasted data.
So why on earth was it stored persistently at all, and why that
callback mechanism from frontend to terminal back to frontend to
retrieve it for the actual paste action? I have no idea. This change
removes the entire system and replaces it with the completely obvious
alternative: the character-set-converted version of paste data is
allocated in a _local_ variable in the frontend paste functions,
passed directly to term_do_paste which now takes (buffer,length)
parameters, and freed immediately afterwards. get_clip() is gone.
2017-12-09 11:41:03 +03:00
|
|
|
term_do_paste(inst->term, paste, paste_len);
|
2015-09-02 23:37:33 +03:00
|
|
|
|
Stop front ends remembering the data of their last paste.
Previously, both the Unix and Windows front ends would respond to a
paste action by retrieving data from the system clipboard, converting
it appropriately, _storing_ it in a persistent dynamic data block
inside the front end, and then calling term_do_paste(term), which in
turn would call back to the front end via get_clip() to retrieve the
current contents of that stored data block.
But, as far as I can tell, this was a completely pointless mechanism,
because after a data block was written into this storage area, it
would be immediately used for exactly one paste, and then never
accessed again until the next paste action caused it to be freed and
replaced with a new chunk of pasted data.
So why on earth was it stored persistently at all, and why that
callback mechanism from frontend to terminal back to frontend to
retrieve it for the actual paste action? I have no idea. This change
removes the entire system and replaces it with the completely obvious
alternative: the character-set-converted version of paste data is
allocated in a _local_ variable in the frontend paste functions,
passed directly to term_do_paste which now takes (buffer,length)
parameters, and freed immediately afterwards. get_clip() is gone.
2017-12-09 11:41:03 +03:00
|
|
|
sfree(paste);
|
2003-08-21 22:07:27 +04:00
|
|
|
}
|
|
|
|
|
2017-12-09 15:00:13 +03:00
|
|
|
void frontend_request_paste(void *frontend, int clipboard)
|
2015-09-02 23:37:33 +03:00
|
|
|
{
|
|
|
|
struct gui_data *inst = (struct gui_data *)frontend;
|
2017-12-10 13:23:39 +03:00
|
|
|
struct clipboard_state *state = &inst->clipstates[clipboard];
|
2017-12-17 21:44:27 +03:00
|
|
|
|
|
|
|
if (!state->gtkclipboard)
|
|
|
|
return;
|
|
|
|
|
2017-12-10 13:23:39 +03:00
|
|
|
gtk_clipboard_request_text(state->gtkclipboard,
|
|
|
|
clipboard_text_received, inst);
|
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!
|
|
|
|
*/
|
|
|
|
|
2003-08-21 22:07:27 +04:00
|
|
|
/* Store the data in a cut-buffer. */
|
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
|
|
|
static void store_cutbuffer(struct gui_data *inst, char *ptr, int len)
|
2003-08-21 22:07:27 +04:00
|
|
|
{
|
2015-08-08 18:35:19 +03:00
|
|
|
#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);
|
|
|
|
}
|
2015-08-08 18:35:19 +03:00
|
|
|
#endif
|
2003-08-21 22:07:27 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Retrieve data from a cut-buffer.
|
|
|
|
* Returned data needs to be freed with XFree().
|
|
|
|
*/
|
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
|
|
|
static char *retrieve_cutbuffer(struct gui_data *inst, int *nbytes)
|
2003-08-21 22:07:27 +04:00
|
|
|
{
|
2015-08-08 18:35:19 +03:00
|
|
|
#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);
|
2004-05-24 15:30:15 +04:00
|
|
|
if (*nbytes <= 0 && ptr != 0) {
|
2003-08-21 22:07:27 +04:00
|
|
|
XFree(ptr);
|
|
|
|
ptr = 0;
|
|
|
|
}
|
|
|
|
return ptr;
|
2015-08-08 18:35:19 +03:00
|
|
|
#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;
|
2015-08-08 18:35:19 +03:00
|
|
|
return NULL;
|
|
|
|
#endif
|
2003-08-21 22:07:27 +04:00
|
|
|
}
|
|
|
|
|
2017-12-09 15:00:13 +03:00
|
|
|
void write_clip(void *frontend, int clipboard,
|
|
|
|
wchar_t *data, int *attr, truecolour *truecolour, int len,
|
|
|
|
int must_deselect)
|
2002-10-09 22:09:42 +04:00
|
|
|
{
|
2002-10-26 16:58:13 +04:00
|
|
|
struct gui_data *inst = (struct gui_data *)frontend;
|
2017-12-10 13:23:39 +03:00
|
|
|
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);
|
2002-12-31 15:20:34 +03:00
|
|
|
|
2003-01-02 01:25:25 +03:00
|
|
|
/*
|
2003-05-13 23:57:17 +04:00
|
|
|
* 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.
|
2003-01-02 01:25:25 +03:00
|
|
|
*/
|
2003-01-02 19:17:56 +03:00
|
|
|
if (!inst->direct_to_font) {
|
2011-09-16 23:18:52 +04:00
|
|
|
const wchar_t *tmp = data;
|
2002-12-31 15:20:34 +03:00
|
|
|
int tmplen = len;
|
2015-08-08 18:35:19 +03:00
|
|
|
#ifndef NOT_X_WINDOWS
|
2003-05-13 23:57:17 +04:00
|
|
|
XTextProperty tp;
|
|
|
|
char *list[1];
|
2015-08-08 18:35:19 +03:00
|
|
|
#endif
|
2003-01-02 01:25:25 +03:00
|
|
|
|
2017-12-10 13:23:39 +03:00
|
|
|
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,
|
2002-12-31 15:20:34 +03:00
|
|
|
CS_UTF8, NULL, NULL, 0);
|
2017-12-10 13:23:39 +03:00
|
|
|
if (state->pasteout_data_utf8_len == 0) {
|
|
|
|
sfree(state->pasteout_data_utf8);
|
|
|
|
state->pasteout_data_utf8 = NULL;
|
2003-01-02 19:17:56 +03:00
|
|
|
} else {
|
2017-12-10 13:23:39 +03:00
|
|
|
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';
|
2003-05-13 23:57:17 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Now let Xlib convert our UTF-8 data into compound text.
|
|
|
|
*/
|
2015-08-08 18:35:19 +03:00
|
|
|
#ifndef NOT_X_WINDOWS
|
2017-12-10 13:23:39 +03:00
|
|
|
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) {
|
2017-12-10 13:23:39 +03:00
|
|
|
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;
|
2003-05-13 23:57:17 +04:00
|
|
|
XFree(tp.value);
|
2015-08-08 18:35:19 +03:00
|
|
|
} else
|
|
|
|
#endif
|
|
|
|
{
|
2017-12-10 13:23:39 +03:00
|
|
|
state->pasteout_data_ctext = NULL;
|
|
|
|
state->pasteout_data_ctext_len = 0;
|
2004-07-27 19:20:37 +04:00
|
|
|
}
|
2003-01-02 01:25:25 +03:00
|
|
|
} else {
|
2017-12-10 13:23:39 +03:00
|
|
|
state->pasteout_data_utf8 = NULL;
|
|
|
|
state->pasteout_data_utf8_len = 0;
|
|
|
|
state->pasteout_data_ctext = NULL;
|
|
|
|
state->pasteout_data_ctext_len = 0;
|
2002-12-31 15:20:34 +03:00
|
|
|
}
|
|
|
|
|
2017-12-10 13:23:39 +03:00
|
|
|
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,
|
2003-01-14 21:28:23 +03:00
|
|
|
NULL, NULL, NULL);
|
2017-12-10 13:23:39 +03:00
|
|
|
if (state->pasteout_data_len == 0) {
|
|
|
|
sfree(state->pasteout_data);
|
|
|
|
state->pasteout_data = NULL;
|
2003-01-02 19:17:56 +03:00
|
|
|
} else {
|
2017-12-10 13:23:39 +03:00
|
|
|
state->pasteout_data =
|
|
|
|
sresize(state->pasteout_data, state->pasteout_data_len, char);
|
2003-01-02 19:17:56 +03:00
|
|
|
}
|
2002-10-13 15:24:25 +04:00
|
|
|
|
2017-12-10 13:23:39 +03:00
|
|
|
/* 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);
|
2003-08-21 22:07:27 +04:00
|
|
|
|
2017-12-10 13:23:39 +03:00
|
|
|
if (gtk_selection_owner_set(inst->area, state->atom,
|
2003-08-21 22:03:06 +04:00
|
|
|
inst->input_event_time)) {
|
2008-12-03 03:06:38 +03:00
|
|
|
#if GTK_CHECK_VERSION(2,0,0)
|
2017-12-10 13:23:39 +03:00
|
|
|
gtk_selection_clear_targets(inst->area, state->atom);
|
2008-12-03 03:06:38 +03:00
|
|
|
#endif
|
2017-12-10 13:23:39 +03:00
|
|
|
gtk_selection_add_target(inst->area, state->atom,
|
2002-10-13 15:24:25 +04:00
|
|
|
GDK_SELECTION_TYPE_STRING, 1);
|
2017-12-10 13:23:39 +03:00
|
|
|
if (state->pasteout_data_ctext)
|
|
|
|
gtk_selection_add_target(inst->area, state->atom,
|
2003-05-13 23:57:17 +04:00
|
|
|
compound_text_atom, 1);
|
2017-12-10 13:23:39 +03:00
|
|
|
if (state->pasteout_data_utf8)
|
|
|
|
gtk_selection_add_target(inst->area, state->atom,
|
2003-04-11 21:40:52 +04:00
|
|
|
utf8_string_atom, 1);
|
2002-10-13 15:24:25 +04:00
|
|
|
}
|
2003-04-11 22:10:13 +04:00
|
|
|
|
|
|
|
if (must_deselect)
|
2017-12-09 15:00:13 +03:00
|
|
|
term_lost_clipboard_ownership(inst->term, clipboard);
|
2002-10-13 15:24:25 +04:00
|
|
|
}
|
|
|
|
|
2015-09-02 23:37:33 +03:00
|
|
|
static void selection_get(GtkWidget *widget, GtkSelectionData *seldata,
|
|
|
|
guint info, guint time_stamp, gpointer data)
|
2002-10-13 15:24:25 +04:00
|
|
|
{
|
2002-10-26 16:58:13 +04:00
|
|
|
struct gui_data *inst = (struct gui_data *)data;
|
2015-08-08 17:53:43 +03:00
|
|
|
GdkAtom target = gtk_selection_data_get_target(seldata);
|
2017-12-10 13:23:39 +03:00
|
|
|
struct clipboard_state *state = clipboard_from_atom(
|
|
|
|
inst, gtk_selection_data_get_selection(seldata));
|
|
|
|
|
|
|
|
if (!state)
|
|
|
|
return;
|
|
|
|
|
2015-08-08 17:53:43 +03:00
|
|
|
if (target == utf8_string_atom)
|
|
|
|
gtk_selection_data_set(seldata, target, 8,
|
2017-12-10 13:23:39 +03:00
|
|
|
(unsigned char *)state->pasteout_data_utf8,
|
|
|
|
state->pasteout_data_utf8_len);
|
2015-08-08 17:53:43 +03:00
|
|
|
else if (target == compound_text_atom)
|
|
|
|
gtk_selection_data_set(seldata, target, 8,
|
2017-12-10 13:23:39 +03:00
|
|
|
(unsigned char *)state->pasteout_data_ctext,
|
|
|
|
state->pasteout_data_ctext_len);
|
2002-12-31 15:20:34 +03:00
|
|
|
else
|
2015-08-08 17:53:43 +03:00
|
|
|
gtk_selection_data_set(seldata, target, 8,
|
2017-12-10 13:23:39 +03:00
|
|
|
(unsigned char *)state->pasteout_data,
|
|
|
|
state->pasteout_data_len);
|
2002-10-13 15:24:25 +04:00
|
|
|
}
|
|
|
|
|
2015-09-02 23:37:33 +03:00
|
|
|
static gint selection_clear(GtkWidget *widget, GdkEventSelection *seldata,
|
|
|
|
gpointer data)
|
2002-10-13 15:24:25 +04:00
|
|
|
{
|
2002-10-26 16:58:13 +04:00
|
|
|
struct gui_data *inst = (struct gui_data *)data;
|
2017-12-10 13:23:39 +03:00
|
|
|
struct clipboard_state *state = clipboard_from_atom(
|
|
|
|
inst, seldata->selection);
|
2003-08-21 22:03:06 +04:00
|
|
|
|
2017-12-10 13:23:39 +03:00
|
|
|
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;
|
2002-10-13 15:24:25 +04:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2017-12-09 15:00:13 +03:00
|
|
|
void frontend_request_paste(void *frontend, int clipboard)
|
2002-10-13 15:24:25 +04:00
|
|
|
{
|
2002-10-26 16:58:13 +04:00
|
|
|
struct gui_data *inst = (struct gui_data *)frontend;
|
2017-12-10 13:23:39 +03:00
|
|
|
struct clipboard_state *state = &inst->clipstates[clipboard];
|
2017-12-09 15:00:13 +03:00
|
|
|
|
2002-10-13 15:24:25 +04:00
|
|
|
/*
|
|
|
|
* 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().
|
|
|
|
*/
|
2002-12-31 15:20:34 +03:00
|
|
|
|
2003-01-02 19:17:56 +03:00
|
|
|
if (!inst->direct_to_font) {
|
2003-01-02 01:25:25 +03:00
|
|
|
/*
|
|
|
|
* 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.
|
|
|
|
*/
|
2017-12-10 13:23:39 +03:00
|
|
|
gtk_selection_convert(inst->area, state->atom, utf8_string_atom,
|
2003-08-21 22:03:06 +04:00
|
|
|
inst->input_event_time);
|
2003-01-02 01:25:25 +03:00
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* If we're in direct-to-font mode, we disable UTF-8
|
|
|
|
* pasting, and go straight to ordinary string data.
|
|
|
|
*/
|
2017-12-10 13:23:39 +03:00
|
|
|
gtk_selection_convert(inst->area, state->atom,
|
|
|
|
GDK_SELECTION_TYPE_STRING,
|
|
|
|
inst->input_event_time);
|
2003-01-02 01:25:25 +03:00
|
|
|
}
|
2002-10-13 15:24:25 +04:00
|
|
|
}
|
|
|
|
|
2015-09-02 23:37:33 +03:00
|
|
|
static void selection_received(GtkWidget *widget, GtkSelectionData *seldata,
|
|
|
|
guint time, gpointer data)
|
2002-10-13 15:24:25 +04:00
|
|
|
{
|
2002-10-26 16:58:13 +04:00
|
|
|
struct gui_data *inst = (struct gui_data *)data;
|
2003-05-13 23:57:17 +04:00
|
|
|
char *text;
|
2015-08-08 18:35:19 +03:00
|
|
|
int length;
|
|
|
|
#ifndef NOT_X_WINDOWS
|
|
|
|
char **list;
|
2003-05-13 23:57:17 +04:00
|
|
|
int free_list_required = 0;
|
2003-08-21 22:07:27 +04:00
|
|
|
int free_required = 0;
|
2015-08-08 18:35:19 +03:00
|
|
|
#endif
|
2003-05-13 23:57:17 +04:00
|
|
|
int charset;
|
2015-08-08 17:53:43 +03:00
|
|
|
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);
|
Stop front ends remembering the data of their last paste.
Previously, both the Unix and Windows front ends would respond to a
paste action by retrieving data from the system clipboard, converting
it appropriately, _storing_ it in a persistent dynamic data block
inside the front end, and then calling term_do_paste(term), which in
turn would call back to the front end via get_clip() to retrieve the
current contents of that stored data block.
But, as far as I can tell, this was a completely pointless mechanism,
because after a data block was written into this storage area, it
would be immediately used for exactly one paste, and then never
accessed again until the next paste action caused it to be freed and
replaced with a new chunk of pasted data.
So why on earth was it stored persistently at all, and why that
callback mechanism from frontend to terminal back to frontend to
retrieve it for the actual paste action? I have no idea. This change
removes the entire system and replaces it with the completely obvious
alternative: the character-set-converted version of paste data is
allocated in a _local_ variable in the frontend paste functions,
passed directly to term_do_paste which now takes (buffer,length)
parameters, and freed immediately afterwards. get_clip() is gone.
2017-12-09 11:41:03 +03:00
|
|
|
wchar_t *paste;
|
|
|
|
int paste_len;
|
2017-12-10 13:23:39 +03:00
|
|
|
struct clipboard_state *state = clipboard_from_atom(
|
|
|
|
inst, gtk_selection_data_get_selection(seldata));
|
|
|
|
|
|
|
|
if (!state)
|
|
|
|
return;
|
2002-10-26 16:58:13 +04:00
|
|
|
|
2015-08-08 17:53:43 +03:00
|
|
|
if (seldata_target == utf8_string_atom && seldata_length <= 0) {
|
2002-12-31 15:20:34 +03:00
|
|
|
/*
|
2003-05-13 22:43:30 +04:00
|
|
|
* Failed to get a UTF-8 selection string. Try compound
|
|
|
|
* text next.
|
|
|
|
*/
|
2017-12-10 13:23:39 +03:00
|
|
|
gtk_selection_convert(inst->area, state->atom,
|
2003-08-21 22:03:06 +04:00
|
|
|
compound_text_atom,
|
|
|
|
inst->input_event_time);
|
2003-05-13 22:43:30 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-08-08 17:53:43 +03:00
|
|
|
if (seldata_target == compound_text_atom && seldata_length <= 0) {
|
2003-05-13 22:43:30 +04:00
|
|
|
/*
|
|
|
|
* Failed to get UTF-8 or compound text. Try an ordinary
|
2002-12-31 15:20:34 +03:00
|
|
|
* string.
|
|
|
|
*/
|
2017-12-10 13:23:39 +03:00
|
|
|
gtk_selection_convert(inst->area, state->atom,
|
2003-08-21 22:03:06 +04:00
|
|
|
GDK_SELECTION_TYPE_STRING,
|
|
|
|
inst->input_event_time);
|
2002-12-31 15:20:34 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2003-08-21 22:07:27 +04:00
|
|
|
* If we have data, but it's not of a type we can deal with,
|
|
|
|
* we have to ignore the data.
|
2002-12-31 15:20:34 +03:00
|
|
|
*/
|
2015-08-08 17:53:43 +03:00
|
|
|
if (seldata_length > 0 &&
|
|
|
|
seldata_type != GDK_SELECTION_TYPE_STRING &&
|
|
|
|
seldata_type != compound_text_atom &&
|
|
|
|
seldata_type != utf8_string_atom)
|
2003-08-21 22:07:27 +04:00
|
|
|
return;
|
2003-05-13 23:57:17 +04:00
|
|
|
|
2003-08-21 22:07:27 +04:00
|
|
|
/*
|
|
|
|
* If we have no data, try looking in a cut buffer.
|
|
|
|
*/
|
2015-08-08 17:53:43 +03:00
|
|
|
if (seldata_length <= 0) {
|
2015-08-08 18:35:19 +03:00
|
|
|
#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);
|
2003-08-21 22:07:27 +04:00
|
|
|
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;
|
|
|
|
free_required = 1;
|
2015-08-08 18:35:19 +03:00
|
|
|
#else
|
|
|
|
return;
|
|
|
|
#endif
|
2003-08-21 22:07:27 +04:00
|
|
|
} else {
|
2004-05-22 18:21:27 +04:00
|
|
|
/*
|
|
|
|
* Convert COMPOUND_TEXT into UTF-8.
|
|
|
|
*/
|
2015-08-08 17:53:43 +03:00
|
|
|
if (seldata_type == compound_text_atom) {
|
2015-08-08 18:35:19 +03:00
|
|
|
#ifndef NOT_X_WINDOWS
|
|
|
|
XTextProperty tp;
|
|
|
|
int ret, count;
|
|
|
|
|
2015-08-08 17:53:43 +03:00
|
|
|
tp.value = (unsigned char *)seldata_data;
|
|
|
|
tp.encoding = (Atom) seldata_type;
|
2015-08-08 18:35:19 +03:00
|
|
|
tp.format = gtk_selection_data_get_format(seldata);
|
2015-08-08 17:53:43 +03:00
|
|
|
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);
|
2015-08-08 18:35:19 +03:00
|
|
|
if (ret == 0 && count == 1) {
|
|
|
|
text = list[0];
|
|
|
|
length = strlen(list[0]);
|
|
|
|
charset = CS_UTF8;
|
|
|
|
free_list_required = 1;
|
|
|
|
} else
|
|
|
|
#endif
|
|
|
|
{
|
2004-05-22 18:21:27 +04:00
|
|
|
/*
|
|
|
|
* Compound text failed; fall back to STRING.
|
|
|
|
*/
|
2017-12-10 13:23:39 +03:00
|
|
|
gtk_selection_convert(inst->area, state->atom,
|
2004-05-22 18:21:27 +04:00
|
|
|
GDK_SELECTION_TYPE_STRING,
|
|
|
|
inst->input_event_time);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else {
|
2015-08-08 17:53:43 +03:00
|
|
|
text = (char *)seldata_data;
|
|
|
|
length = seldata_length;
|
|
|
|
charset = (seldata_type == utf8_string_atom ?
|
2004-05-22 18:21:27 +04:00
|
|
|
CS_UTF8 : inst->ucsdata.line_codepage);
|
2003-05-13 23:57:17 +04:00
|
|
|
}
|
2003-08-21 22:07:27 +04:00
|
|
|
}
|
2003-05-13 23:57:17 +04:00
|
|
|
|
Stop front ends remembering the data of their last paste.
Previously, both the Unix and Windows front ends would respond to a
paste action by retrieving data from the system clipboard, converting
it appropriately, _storing_ it in a persistent dynamic data block
inside the front end, and then calling term_do_paste(term), which in
turn would call back to the front end via get_clip() to retrieve the
current contents of that stored data block.
But, as far as I can tell, this was a completely pointless mechanism,
because after a data block was written into this storage area, it
would be immediately used for exactly one paste, and then never
accessed again until the next paste action caused it to be freed and
replaced with a new chunk of pasted data.
So why on earth was it stored persistently at all, and why that
callback mechanism from frontend to terminal back to frontend to
retrieve it for the actual paste action? I have no idea. This change
removes the entire system and replaces it with the completely obvious
alternative: the character-set-converted version of paste data is
allocated in a _local_ variable in the frontend paste functions,
passed directly to term_do_paste which now takes (buffer,length)
parameters, and freed immediately afterwards. get_clip() is gone.
2017-12-09 11:41:03 +03:00
|
|
|
paste = snewn(length, wchar_t);
|
|
|
|
paste_len = mb_to_wc(charset, 0, text, length, paste, length);
|
2002-10-13 15:24:25 +04:00
|
|
|
|
Stop front ends remembering the data of their last paste.
Previously, both the Unix and Windows front ends would respond to a
paste action by retrieving data from the system clipboard, converting
it appropriately, _storing_ it in a persistent dynamic data block
inside the front end, and then calling term_do_paste(term), which in
turn would call back to the front end via get_clip() to retrieve the
current contents of that stored data block.
But, as far as I can tell, this was a completely pointless mechanism,
because after a data block was written into this storage area, it
would be immediately used for exactly one paste, and then never
accessed again until the next paste action caused it to be freed and
replaced with a new chunk of pasted data.
So why on earth was it stored persistently at all, and why that
callback mechanism from frontend to terminal back to frontend to
retrieve it for the actual paste action? I have no idea. This change
removes the entire system and replaces it with the completely obvious
alternative: the character-set-converted version of paste data is
allocated in a _local_ variable in the frontend paste functions,
passed directly to term_do_paste which now takes (buffer,length)
parameters, and freed immediately afterwards. get_clip() is gone.
2017-12-09 11:41:03 +03:00
|
|
|
term_do_paste(inst->term, paste, paste_len);
|
2002-10-13 15:24:25 +04:00
|
|
|
|
Stop front ends remembering the data of their last paste.
Previously, both the Unix and Windows front ends would respond to a
paste action by retrieving data from the system clipboard, converting
it appropriately, _storing_ it in a persistent dynamic data block
inside the front end, and then calling term_do_paste(term), which in
turn would call back to the front end via get_clip() to retrieve the
current contents of that stored data block.
But, as far as I can tell, this was a completely pointless mechanism,
because after a data block was written into this storage area, it
would be immediately used for exactly one paste, and then never
accessed again until the next paste action caused it to be freed and
replaced with a new chunk of pasted data.
So why on earth was it stored persistently at all, and why that
callback mechanism from frontend to terminal back to frontend to
retrieve it for the actual paste action? I have no idea. This change
removes the entire system and replaces it with the completely obvious
alternative: the character-set-converted version of paste data is
allocated in a _local_ variable in the frontend paste functions,
passed directly to term_do_paste which now takes (buffer,length)
parameters, and freed immediately afterwards. get_clip() is gone.
2017-12-09 11:41:03 +03:00
|
|
|
sfree(paste);
|
2002-10-15 03:32:00 +04:00
|
|
|
|
2015-08-08 18:35:19 +03:00
|
|
|
#ifndef NOT_X_WINDOWS
|
2003-05-13 23:57:17 +04:00
|
|
|
if (free_list_required)
|
|
|
|
XFreeStringList(list);
|
2003-08-21 22:07:27 +04:00
|
|
|
if (free_required)
|
|
|
|
XFree(text);
|
2015-08-08 18:35:19 +03:00
|
|
|
#endif
|
2002-10-15 03:32:00 +04:00
|
|
|
}
|
|
|
|
|
2017-12-17 21:44:27 +03:00
|
|
|
static void init_one_clipboard(struct gui_data *inst, int clipboard)
|
|
|
|
{
|
|
|
|
struct clipboard_state *state = &inst->clipstates[clipboard];
|
|
|
|
|
|
|
|
state->inst = inst;
|
|
|
|
state->clipboard = clipboard;
|
|
|
|
}
|
|
|
|
|
|
|
|
void set_clipboard_atom(struct gui_data *inst, int clipboard, GdkAtom atom)
|
2017-12-10 13:23:39 +03:00
|
|
|
{
|
|
|
|
struct clipboard_state *state = &inst->clipstates[clipboard];
|
|
|
|
|
|
|
|
state->inst = inst;
|
|
|
|
state->clipboard = clipboard;
|
2017-12-17 21:44:27 +03:00
|
|
|
|
|
|
|
state->atom = atom;
|
2017-12-10 13:23:39 +03:00
|
|
|
}
|
|
|
|
|
2015-09-02 23:37:33 +03:00
|
|
|
void init_clipboard(struct gui_data *inst)
|
|
|
|
{
|
|
|
|
#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);
|
|
|
|
}
|
2015-09-02 23:37:33 +03:00
|
|
|
#endif
|
|
|
|
|
2017-12-17 21:44:27 +03:00
|
|
|
inst->clipstates[CLIP_PRIMARY].atom = GDK_SELECTION_PRIMARY;
|
2018-03-03 21:18:54 +03:00
|
|
|
inst->clipstates[CLIP_CLIPBOARD].atom = clipboard_atom;
|
2017-12-17 21:44:27 +03:00
|
|
|
init_one_clipboard(inst, CLIP_PRIMARY);
|
|
|
|
init_one_clipboard(inst, CLIP_CLIPBOARD);
|
2017-12-10 13:23:39 +03:00
|
|
|
|
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 */
|
|
|
|
|
2003-04-26 17:55:47 +04:00
|
|
|
static void set_window_titles(struct gui_data *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);
|
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(inst->conf, CONF_win_name_always))
|
2015-08-08 17:53:43 +03:00
|
|
|
gdk_window_set_icon_name(gtk_widget_get_window(inst->window),
|
|
|
|
inst->icontitle);
|
2003-04-26 17:55:47 +04:00
|
|
|
}
|
|
|
|
|
2002-10-26 16:58:13 +04:00
|
|
|
void set_title(void *frontend, char *title)
|
2002-10-09 22:09:42 +04:00
|
|
|
{
|
2002-10-26 16:58:13 +04:00
|
|
|
struct gui_data *inst = (struct gui_data *)frontend;
|
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);
|
2003-04-26 17:55:47 +04:00
|
|
|
set_window_titles(inst);
|
2002-10-09 22:09:42 +04:00
|
|
|
}
|
|
|
|
|
2002-10-26 16:58:13 +04:00
|
|
|
void set_icon(void *frontend, char *title)
|
2002-10-09 22:09:42 +04:00
|
|
|
{
|
2002-10-26 16:58:13 +04:00
|
|
|
struct gui_data *inst = (struct gui_data *)frontend;
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
void set_title_and_icon(void *frontend, char *title, char *icon)
|
|
|
|
{
|
|
|
|
struct gui_data *inst = (struct gui_data *)frontend;
|
|
|
|
sfree(inst->wintitle);
|
|
|
|
inst->wintitle = dupstr(title);
|
|
|
|
sfree(inst->icontitle);
|
|
|
|
inst->icontitle = dupstr(icon);
|
2003-04-26 17:55:47 +04:00
|
|
|
set_window_titles(inst);
|
2002-10-09 22:09:42 +04:00
|
|
|
}
|
|
|
|
|
2002-10-26 16:58:13 +04:00
|
|
|
void set_sbar(void *frontend, int total, int start, int page)
|
2002-10-09 22:09:42 +04:00
|
|
|
{
|
2002-10-26 16:58:13 +04:00
|
|
|
struct gui_data *inst = (struct gui_data *)frontend;
|
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(inst->conf, CONF_scrollbar))
|
2002-10-15 18:55:19 +04:00
|
|
|
return;
|
2017-11-26 12:16:22 +03:00
|
|
|
inst->ignore_sbar = TRUE;
|
2015-08-08 17:53:43 +03:00
|
|
|
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);
|
2016-04-03 12:10:40 +03:00
|
|
|
#if !GTK_CHECK_VERSION(3,18,0)
|
2002-10-13 13:54:36 +04:00
|
|
|
gtk_adjustment_changed(inst->sbar_adjust);
|
2016-04-03 12:10:40 +03:00
|
|
|
#endif
|
2002-10-13 16:44:01 +04:00
|
|
|
inst->ignore_sbar = FALSE;
|
2002-10-13 13:54:36 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void scrollbar_moved(GtkAdjustment *adj, gpointer data)
|
|
|
|
{
|
2002-10-26 16:58:13 +04:00
|
|
|
struct gui_data *inst = (struct gui_data *)data;
|
|
|
|
|
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(inst->conf, CONF_scrollbar))
|
2002-10-15 18:55:19 +04:00
|
|
|
return;
|
2002-10-13 16:44:01 +04:00
|
|
|
if (!inst->ignore_sbar)
|
2015-08-08 17:53:43 +03:00
|
|
|
term_scroll(inst->term, 1, (int)gtk_adjustment_get_value(adj));
|
2002-10-09 22:09:42 +04:00
|
|
|
}
|
|
|
|
|
2016-03-29 15:42:54 +03:00
|
|
|
static void show_scrollbar(struct gui_data *inst, gboolean visible)
|
|
|
|
{
|
|
|
|
inst->sbar_visible = visible;
|
|
|
|
if (visible)
|
|
|
|
gtk_widget_show(inst->sbar);
|
|
|
|
else
|
|
|
|
gtk_widget_hide(inst->sbar);
|
|
|
|
}
|
|
|
|
|
2002-10-26 16:58:13 +04:00
|
|
|
void sys_cursor(void *frontend, int x, int y)
|
2002-10-09 22:09:42 +04:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* This is meaningless under X.
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
2002-10-29 00:58:07 +03:00
|
|
|
/*
|
|
|
|
* 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).
|
|
|
|
*/
|
2005-12-09 23:04:19 +03:00
|
|
|
void do_beep(void *frontend, int mode)
|
2002-10-09 22:09:42 +04:00
|
|
|
{
|
2007-02-24 16:36:11 +03:00
|
|
|
if (mode == BELL_DEFAULT)
|
2018-03-03 21:20:04 +03:00
|
|
|
gdk_display_beep(gdk_display_get_default());
|
2002-10-09 22:09:42 +04:00
|
|
|
}
|
|
|
|
|
2002-11-10 00:46:21 +03:00
|
|
|
int char_width(Context ctx, int uc)
|
2002-10-09 22:09:42 +04:00
|
|
|
{
|
|
|
|
/*
|
2015-09-26 14:59:26 +03:00
|
|
|
* In this front end, double-width characters are handled using a
|
|
|
|
* separate font, so this can safely just return 1 always.
|
2002-10-09 22:09:42 +04:00
|
|
|
*/
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2002-10-26 16:58:13 +04:00
|
|
|
Context get_ctx(void *frontend)
|
2002-10-09 22:09:42 +04:00
|
|
|
{
|
2002-10-26 16:58:13 +04:00
|
|
|
struct gui_data *inst = (struct gui_data *)frontend;
|
|
|
|
struct draw_ctx *dctx;
|
|
|
|
|
2015-08-08 17:53:43 +03:00
|
|
|
if (!gtk_widget_get_window(inst->area))
|
2002-10-10 14:40:30 +04:00
|
|
|
return NULL;
|
2002-10-26 16:58:13 +04:00
|
|
|
|
2003-03-29 19:14:26 +03:00
|
|
|
dctx = snew(struct draw_ctx);
|
2002-10-26 16:58:13 +04:00
|
|
|
dctx->inst = 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
|
|
|
dctx->uctx.type = inst->drawtype;
|
|
|
|
#ifdef DRAW_TEXT_GDK
|
|
|
|
if (dctx->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. */
|
|
|
|
dctx->uctx.u.gdk.target = inst->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
|
|
|
dctx->uctx.u.gdk.gc = gdk_gc_new(gtk_widget_get_window(inst->area));
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef DRAW_TEXT_CAIRO
|
|
|
|
if (dctx->uctx.type == DRAWTYPE_CAIRO) {
|
|
|
|
dctx->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. */
|
|
|
|
dctx->uctx.u.cairo.cr = cairo_create(inst->surface);
|
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_scale(dctx->uctx.u.cairo.cr, inst->scale, inst->scale);
|
2015-08-16 16:34:19 +03:00
|
|
|
cairo_setup_dctx(dctx);
|
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
|
2002-10-26 16:58:13 +04:00
|
|
|
return dctx;
|
2002-10-09 22:09:42 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void free_ctx(Context ctx)
|
|
|
|
{
|
2002-10-26 16:58:13 +04:00
|
|
|
struct draw_ctx *dctx = (struct draw_ctx *)ctx;
|
|
|
|
/* struct gui_data *inst = dctx->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
|
|
|
#ifdef DRAW_TEXT_GDK
|
|
|
|
if (dctx->uctx.type == DRAWTYPE_GDK) {
|
|
|
|
gdk_gc_unref(dctx->uctx.u.gdk.gc);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef DRAW_TEXT_CAIRO
|
|
|
|
if (dctx->uctx.type == DRAWTYPE_CAIRO) {
|
|
|
|
cairo_destroy(dctx->uctx.u.cairo.cr);
|
|
|
|
}
|
|
|
|
#endif
|
2002-10-26 16:58:13 +04:00
|
|
|
sfree(dctx);
|
2002-10-09 22:09:42 +04:00
|
|
|
}
|
|
|
|
|
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
|
|
|
|
|
|
|
static void draw_update(struct draw_ctx *dctx, int x, int y, int w, int h)
|
|
|
|
{
|
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
|
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 (dctx->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.
|
|
|
|
*/
|
|
|
|
cairo_t *cr = gdk_cairo_create(dctx->inst->pixmap);
|
|
|
|
cairo_set_source_surface(cr, dctx->inst->surface, 0, 0);
|
|
|
|
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 :-)
|
|
|
|
*/
|
|
|
|
gtk_widget_queue_draw_area(dctx->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
|
|
|
}
|
|
|
|
|
2017-10-05 23:02:56 +03:00
|
|
|
#ifdef DRAW_TEXT_CAIRO
|
|
|
|
static void cairo_set_source_rgb_dim(cairo_t *cr, double r, double g, double b,
|
|
|
|
int 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
|
|
|
|
|
|
|
|
static void draw_set_colour(struct draw_ctx *dctx, int col, int 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
|
|
|
|
if (dctx->uctx.type == DRAWTYPE_GDK) {
|
2017-10-05 23:02:56 +03:00
|
|
|
if (dim) {
|
2017-11-26 11:56:16 +03:00
|
|
|
#if GTK_CHECK_VERSION(2,0,0)
|
2017-10-05 23:02:56 +03:00
|
|
|
GdkColor color;
|
|
|
|
color.red = dctx->inst->cols[col].red * 2 / 3;
|
|
|
|
color.green = dctx->inst->cols[col].green * 2 / 3;
|
|
|
|
color.blue = dctx->inst->cols[col].blue * 2 / 3;
|
|
|
|
gdk_gc_set_rgb_fg_color(dctx->uctx.u.gdk.gc, &color);
|
2017-11-26 11:56:16 +03:00
|
|
|
#else
|
|
|
|
/* Poor GTK1 fallback */
|
|
|
|
gdk_gc_set_foreground(dctx->uctx.u.gdk.gc, &dctx->inst->cols[col]);
|
|
|
|
#endif
|
2017-10-05 23:02:56 +03:00
|
|
|
} else {
|
|
|
|
gdk_gc_set_foreground(dctx->uctx.u.gdk.gc, &dctx->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
|
|
|
|
if (dctx->uctx.type == DRAWTYPE_CAIRO) {
|
2017-10-05 23:02:56 +03:00
|
|
|
cairo_set_source_rgb_dim(dctx->uctx.u.cairo.cr,
|
|
|
|
dctx->inst->cols[col].red / 65535.0,
|
|
|
|
dctx->inst->cols[col].green / 65535.0,
|
|
|
|
dctx->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
|
|
|
|
}
|
|
|
|
|
2017-10-05 23:02:56 +03:00
|
|
|
static void draw_set_colour_rgb(struct draw_ctx *dctx, optionalrgb orgb,
|
|
|
|
int dim)
|
2017-09-30 19:32:32 +03:00
|
|
|
{
|
|
|
|
#ifdef DRAW_TEXT_GDK
|
|
|
|
if (dctx->uctx.type == DRAWTYPE_GDK) {
|
2017-11-26 11:56:16 +03:00
|
|
|
#if GTK_CHECK_VERSION(2,0,0)
|
2017-09-30 19:32:32 +03:00
|
|
|
GdkColor color;
|
|
|
|
color.red = orgb.r * 256;
|
|
|
|
color.green = orgb.g * 256;
|
|
|
|
color.blue = orgb.b * 256;
|
2017-10-05 23:02:56 +03:00
|
|
|
if (dim) {
|
|
|
|
color.red = color.red * 2 / 3;
|
|
|
|
color.green = color.green * 2 / 3;
|
|
|
|
color.blue = color.blue * 2 / 3;
|
|
|
|
}
|
2017-09-30 19:32:32 +03:00
|
|
|
gdk_gc_set_rgb_fg_color(dctx->uctx.u.gdk.gc, &color);
|
2017-11-26 11:56:16 +03:00
|
|
|
#else
|
|
|
|
/* Poor GTK1 fallback */
|
|
|
|
gdk_gc_set_foreground(dctx->uctx.u.gdk.gc, &dctx->inst->cols[256]);
|
|
|
|
#endif
|
2017-09-30 19:32:32 +03:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef DRAW_TEXT_CAIRO
|
2017-10-05 23:02:56 +03:00
|
|
|
if (dctx->uctx.type == DRAWTYPE_CAIRO) {
|
|
|
|
cairo_set_source_rgb_dim(dctx->uctx.u.cairo.cr, orgb.r / 255.0,
|
|
|
|
orgb.g / 255.0, orgb.b / 255.0, dim);
|
|
|
|
}
|
2017-09-30 19:32:32 +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
|
|
|
static void draw_rectangle(struct draw_ctx *dctx, int filled,
|
|
|
|
int x, int y, int w, int h)
|
|
|
|
{
|
|
|
|
#ifdef DRAW_TEXT_GDK
|
|
|
|
if (dctx->uctx.type == DRAWTYPE_GDK) {
|
|
|
|
gdk_draw_rectangle(dctx->uctx.u.gdk.target, dctx->uctx.u.gdk.gc,
|
|
|
|
filled, x, y, w, h);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef DRAW_TEXT_CAIRO
|
|
|
|
if (dctx->uctx.type == DRAWTYPE_CAIRO) {
|
|
|
|
cairo_new_path(dctx->uctx.u.cairo.cr);
|
|
|
|
if (filled) {
|
|
|
|
cairo_rectangle(dctx->uctx.u.cairo.cr, x, y, w, h);
|
|
|
|
cairo_fill(dctx->uctx.u.cairo.cr);
|
|
|
|
} else {
|
|
|
|
cairo_rectangle(dctx->uctx.u.cairo.cr,
|
|
|
|
x + 0.5, y + 0.5, w, h);
|
|
|
|
cairo_close_path(dctx->uctx.u.cairo.cr);
|
|
|
|
cairo_stroke(dctx->uctx.u.cairo.cr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static void draw_clip(struct draw_ctx *dctx, int x, int y, int w, int h)
|
|
|
|
{
|
|
|
|
#ifdef DRAW_TEXT_GDK
|
|
|
|
if (dctx->uctx.type == DRAWTYPE_GDK) {
|
|
|
|
GdkRectangle r;
|
|
|
|
|
|
|
|
r.x = x;
|
|
|
|
r.y = y;
|
|
|
|
r.width = w;
|
|
|
|
r.height = h;
|
|
|
|
|
|
|
|
gdk_gc_set_clip_rectangle(dctx->uctx.u.gdk.gc, &r);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef DRAW_TEXT_CAIRO
|
|
|
|
if (dctx->uctx.type == DRAWTYPE_CAIRO) {
|
|
|
|
cairo_reset_clip(dctx->uctx.u.cairo.cr);
|
|
|
|
cairo_new_path(dctx->uctx.u.cairo.cr);
|
|
|
|
cairo_rectangle(dctx->uctx.u.cairo.cr, x, y, w, h);
|
|
|
|
cairo_clip(dctx->uctx.u.cairo.cr);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static void draw_point(struct draw_ctx *dctx, int x, int y)
|
|
|
|
{
|
|
|
|
#ifdef DRAW_TEXT_GDK
|
|
|
|
if (dctx->uctx.type == DRAWTYPE_GDK) {
|
|
|
|
gdk_draw_point(dctx->uctx.u.gdk.target, dctx->uctx.u.gdk.gc, x, y);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef DRAW_TEXT_CAIRO
|
|
|
|
if (dctx->uctx.type == DRAWTYPE_CAIRO) {
|
|
|
|
cairo_new_path(dctx->uctx.u.cairo.cr);
|
|
|
|
cairo_rectangle(dctx->uctx.u.cairo.cr, x, y, 1, 1);
|
|
|
|
cairo_fill(dctx->uctx.u.cairo.cr);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static void draw_line(struct draw_ctx *dctx, int x0, int y0, int x1, int y1)
|
|
|
|
{
|
|
|
|
#ifdef DRAW_TEXT_GDK
|
|
|
|
if (dctx->uctx.type == DRAWTYPE_GDK) {
|
|
|
|
gdk_draw_line(dctx->uctx.u.gdk.target, dctx->uctx.u.gdk.gc,
|
|
|
|
x0, y0, x1, y1);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef DRAW_TEXT_CAIRO
|
|
|
|
if (dctx->uctx.type == DRAWTYPE_CAIRO) {
|
|
|
|
cairo_new_path(dctx->uctx.u.cairo.cr);
|
|
|
|
cairo_move_to(dctx->uctx.u.cairo.cr, x0 + 0.5, y0 + 0.5);
|
|
|
|
cairo_line_to(dctx->uctx.u.cairo.cr, x1 + 0.5, y1 + 0.5);
|
|
|
|
cairo_stroke(dctx->uctx.u.cairo.cr);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static void draw_stretch_before(struct draw_ctx *dctx, int x, int y,
|
|
|
|
int w, int wdouble,
|
|
|
|
int h, int hdouble, int hbothalf)
|
|
|
|
{
|
|
|
|
#ifdef DRAW_TEXT_CAIRO
|
|
|
|
if (dctx->uctx.type == DRAWTYPE_CAIRO) {
|
|
|
|
cairo_matrix_t matrix;
|
|
|
|
|
|
|
|
matrix.xy = 0;
|
|
|
|
matrix.yx = 0;
|
|
|
|
|
|
|
|
if (wdouble) {
|
|
|
|
matrix.xx = 2;
|
|
|
|
matrix.x0 = -x;
|
|
|
|
} else {
|
|
|
|
matrix.xx = 1;
|
|
|
|
matrix.x0 = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hdouble) {
|
|
|
|
matrix.yy = 2;
|
|
|
|
if (hbothalf) {
|
|
|
|
matrix.y0 = -(y+h);
|
|
|
|
} else {
|
|
|
|
matrix.y0 = -y;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
matrix.yy = 1;
|
|
|
|
matrix.y0 = 0;
|
|
|
|
}
|
|
|
|
cairo_transform(dctx->uctx.u.cairo.cr, &matrix);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static void draw_stretch_after(struct draw_ctx *dctx, int x, int y,
|
|
|
|
int w, int wdouble,
|
|
|
|
int h, int hdouble, int hbothalf)
|
|
|
|
{
|
|
|
|
#ifdef DRAW_TEXT_GDK
|
2015-08-16 11:02:31 +03:00
|
|
|
#ifndef NO_BACKING_PIXMAPS
|
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 (dctx->uctx.type == DRAWTYPE_GDK) {
|
|
|
|
/*
|
|
|
|
* 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++) {
|
|
|
|
gdk_draw_pixmap(dctx->uctx.u.gdk.target,
|
|
|
|
dctx->uctx.u.gdk.gc,
|
|
|
|
dctx->uctx.u.gdk.target,
|
|
|
|
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) {
|
|
|
|
gdk_draw_pixmap(dctx->uctx.u.gdk.target,
|
|
|
|
dctx->uctx.u.gdk.gc,
|
|
|
|
dctx->uctx.u.gdk.target,
|
|
|
|
x, y + dt*i + db,
|
|
|
|
x, y + dt*(i+1),
|
|
|
|
w, h-i-1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2015-08-16 11:02:31 +03:00
|
|
|
#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
|
2015-08-16 11:02:31 +03:00
|
|
|
#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
|
|
|
|
if (dctx->uctx.type == DRAWTYPE_CAIRO) {
|
|
|
|
cairo_set_matrix(dctx->uctx.u.cairo.cr,
|
|
|
|
&dctx->uctx.u.cairo.origmatrix);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static void draw_backing_rect(struct gui_data *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
|
|
|
int 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
|
|
|
struct draw_ctx *dctx = get_ctx(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
|
|
|
|
|
|
|
if (!dctx)
|
|
|
|
return;
|
|
|
|
|
|
|
|
w = inst->width * inst->font_width + 2*inst->window_border;
|
|
|
|
h = inst->height * inst->font_height + 2*inst->window_border;
|
2017-10-05 23:02:56 +03:00
|
|
|
draw_set_colour(dctx, 258, FALSE);
|
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_rectangle(dctx, 1, 0, 0, w, h);
|
|
|
|
draw_update(dctx, 0, 0, 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
|
|
|
free_ctx(dctx);
|
|
|
|
}
|
|
|
|
|
2002-10-09 22:09:42 +04: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'.
|
|
|
|
*/
|
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
|
|
|
void do_text_internal(Context ctx, int x, int y, wchar_t *text, int len,
|
2017-09-30 19:32:32 +03:00
|
|
|
unsigned long attr, int lattr, truecolour truecolour)
|
2002-10-09 22:09:42 +04:00
|
|
|
{
|
2002-10-26 16:58:13 +04:00
|
|
|
struct draw_ctx *dctx = (struct draw_ctx *)ctx;
|
|
|
|
struct gui_data *inst = dctx->inst;
|
2015-09-26 12:18:53 +03:00
|
|
|
int ncombining;
|
Refactor the font handling code: I've moved all the code that
explicitly deals with GdkFont out into a new module, behind a
polymorphic interface (done by ad-hoc explicit vtable management in
C). This should allow me to drop in a Pango font handling module in
parallel with the existing one, meaning that GTK2 PuTTY will be able
to seamlessly switch between X11 server-side fonts and Pango client-
side ones as the user chooses, or even use a mixture of the two
(e.g. an X11 font for narrow characters and a Pango one for wide
characters, or vice versa).
In the process, incidentally, I got to the bottom of the `weird bug'
mentioned in the old do_text_internal(). It's not a bug in
gdk_draw_text_wc() as I had thought: it's simply that GdkWChar is a
32-bit type rather than a 16-bit one, so no wonder you have to
specify twice the length to find all the characters in the string!
However, there _is_ a bug in GTK2's gdk_draw_text_wc(), which causes
it to strip off everything above the low byte of each GdkWChar,
sigh. Solution to both problems is to use an array of the underlying
Xlib type XChar2b instead, and pass it to gdk_draw_text() cast to
gchar *. Grotty, but it works. (And it'll become significantly less
grotty if and when we have to stop using the GDK font handling
wrappers in favour of going direct to Xlib.)
[originally from svn r7933]
2008-03-22 14:40:23 +03:00
|
|
|
int nfg, nbg, t, fontid, shadow, rlen, widefactor, bold;
|
2015-08-08 17:53:43 +03:00
|
|
|
int monochrome =
|
|
|
|
gdk_visual_get_depth(gtk_widget_get_visual(inst->area)) == 1;
|
2002-10-10 14:40:30 +04:00
|
|
|
|
2004-10-14 20:42:43 +04:00
|
|
|
if (attr & TATTR_COMBINING) {
|
|
|
|
ncombining = len;
|
|
|
|
len = 1;
|
|
|
|
} else
|
|
|
|
ncombining = 1;
|
|
|
|
|
2017-10-05 22:30:09 +03:00
|
|
|
if (monochrome)
|
|
|
|
truecolour.fg = truecolour.bg = optionalrgb_none;
|
|
|
|
|
2005-04-28 01:09:45 +04:00
|
|
|
nfg = ((monochrome ? ATTR_DEFFG : (attr & ATTR_FGMASK)) >> ATTR_FGSHIFT);
|
|
|
|
nbg = ((monochrome ? ATTR_DEFBG : (attr & ATTR_BGMASK)) >> ATTR_BGSHIFT);
|
2005-04-28 01:42:51 +04:00
|
|
|
if (!!(attr & ATTR_REVERSE) ^ (monochrome && (attr & TATTR_ACTCURS))) {
|
2017-10-08 15:49:54 +03:00
|
|
|
struct optionalrgb trgb;
|
|
|
|
|
2002-10-10 14:40:30 +04:00
|
|
|
t = nfg;
|
|
|
|
nfg = nbg;
|
|
|
|
nbg = t;
|
2017-10-08 15:49:54 +03:00
|
|
|
|
|
|
|
trgb = truecolour.fg;
|
|
|
|
truecolour.fg = truecolour.bg;
|
|
|
|
truecolour.bg = trgb;
|
2002-10-10 14:40:30 +04:00
|
|
|
}
|
2012-06-09 19:09:22 +04:00
|
|
|
if ((inst->bold_style & 2) && (attr & ATTR_BOLD)) {
|
2004-11-28 18:13:34 +03:00
|
|
|
if (nfg < 16) nfg |= 8;
|
|
|
|
else if (nfg >= 256) nfg |= 1;
|
|
|
|
}
|
2012-06-09 19:09:22 +04:00
|
|
|
if ((inst->bold_style & 2) && (attr & ATTR_BLINK)) {
|
2004-11-28 18:13:34 +03:00
|
|
|
if (nbg < 16) nbg |= 8;
|
|
|
|
else if (nbg >= 256) nbg |= 1;
|
|
|
|
}
|
2005-04-28 01:42:51 +04:00
|
|
|
if ((attr & TATTR_ACTCURS) && !monochrome) {
|
2017-10-05 22:30:04 +03:00
|
|
|
truecolour.fg = truecolour.bg = optionalrgb_none;
|
2004-11-28 18:13:34 +03:00
|
|
|
nfg = 260;
|
|
|
|
nbg = 261;
|
2017-10-05 23:02:56 +03:00
|
|
|
attr &= ~ATTR_DIM; /* don't dim the cursor */
|
2002-10-10 14:40:30 +04:00
|
|
|
}
|
|
|
|
|
2002-10-15 22:42:48 +04:00
|
|
|
fontid = shadow = 0;
|
2003-01-02 00:53:22 +03:00
|
|
|
|
|
|
|
if (attr & ATTR_WIDE) {
|
|
|
|
widefactor = 2;
|
|
|
|
fontid |= 2;
|
|
|
|
} else {
|
|
|
|
widefactor = 1;
|
|
|
|
}
|
|
|
|
|
2012-06-09 19:09:22 +04:00
|
|
|
if ((attr & ATTR_BOLD) && (inst->bold_style & 1)) {
|
Refactor the font handling code: I've moved all the code that
explicitly deals with GdkFont out into a new module, behind a
polymorphic interface (done by ad-hoc explicit vtable management in
C). This should allow me to drop in a Pango font handling module in
parallel with the existing one, meaning that GTK2 PuTTY will be able
to seamlessly switch between X11 server-side fonts and Pango client-
side ones as the user chooses, or even use a mixture of the two
(e.g. an X11 font for narrow characters and a Pango one for wide
characters, or vice versa).
In the process, incidentally, I got to the bottom of the `weird bug'
mentioned in the old do_text_internal(). It's not a bug in
gdk_draw_text_wc() as I had thought: it's simply that GdkWChar is a
32-bit type rather than a 16-bit one, so no wonder you have to
specify twice the length to find all the characters in the string!
However, there _is_ a bug in GTK2's gdk_draw_text_wc(), which causes
it to strip off everything above the low byte of each GdkWChar,
sigh. Solution to both problems is to use an array of the underlying
Xlib type XChar2b instead, and pass it to gdk_draw_text() cast to
gchar *. Grotty, but it works. (And it'll become significantly less
grotty if and when we have to stop using the GDK font handling
wrappers in favour of going direct to Xlib.)
[originally from svn r7933]
2008-03-22 14:40:23 +03:00
|
|
|
bold = 1;
|
|
|
|
fontid |= 1;
|
|
|
|
} else {
|
|
|
|
bold = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
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 */
|
2002-10-15 22:42:48 +04:00
|
|
|
}
|
|
|
|
|
Re-engineering of terminal emulator, phase 1.
The active terminal screen is no longer an array of `unsigned long'
encoding 16-bit Unicode plus 16 attribute bits. Now it's an array of
`termchar' structures, which currently have 32-bit Unicode and 32
attribute bits but which will probably expand further in future.
To prevent bloat of the memory footprint, I've introduced a mostly
RLE-like compression scheme for storing scrollback: each line is
compressed into a compact (but hard to modify) form when it moves
into the term->scrollback tree, and is temporarily decompressed when
the user wants to scroll back over it. My initial tests suggest that
this compression averages about 1/4 of the previous (32 bits per
character cell) data size in typical output, which means this is an
improvement even without counting the new ability to extend the
information stored in each character cell.
Another beneficial side effect is that the insane format in which
Unicode was passed to front ends through do_text() has now been
rendered sane.
Testing is incomplete; this _may_ still have instabilities. Windows
and Unix front ends both seem to work as far as I've looked, but I
haven't yet looked very hard. The Mac front end I've edited (it
seemed obvious how to change it) but I can't compile or test it.
As an immediate functional effect, the terminal emulator now
supports full 32-bit Unicode to whatever extent the host platform
allows it to. For example, if you output a 4-or-more-byte UTF-8
character in Unix pterm, it will not display it properly, but it
will correctly paste it back out in a UTF8_STRING selection. Windows
is more restricted, sadly.
[originally from svn r4609]
2004-10-13 15:50:16 +04:00
|
|
|
if ((lattr & LATTR_MODE) != LATTR_NORM) {
|
2002-10-15 04:22:48 +04:00
|
|
|
x *= 2;
|
2002-10-26 15:08:59 +04:00
|
|
|
if (x >= inst->term->cols)
|
2002-10-15 13:30:16 +04:00
|
|
|
return;
|
2003-01-02 00:53:22 +03:00
|
|
|
if (x + len*2*widefactor > inst->term->cols)
|
|
|
|
len = (inst->term->cols-x)/2/widefactor;/* trim to LH half */
|
2002-11-02 19:16:35 +03:00
|
|
|
rlen = len * 2;
|
|
|
|
} else
|
|
|
|
rlen = len;
|
|
|
|
|
2015-08-16 10:55:04 +03:00
|
|
|
draw_clip(dctx,
|
|
|
|
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) {
|
|
|
|
draw_stretch_before(dctx,
|
|
|
|
x*inst->font_width+inst->window_border,
|
|
|
|
y*inst->font_height+inst->window_border,
|
|
|
|
rlen*widefactor*inst->font_width, TRUE,
|
|
|
|
inst->font_height,
|
|
|
|
((lattr & LATTR_MODE) != LATTR_WIDE),
|
|
|
|
((lattr & LATTR_MODE) == LATTR_BOT));
|
|
|
|
}
|
|
|
|
|
2017-09-30 19:32:32 +03:00
|
|
|
if (truecolour.bg.enabled)
|
2017-10-05 23:02:56 +03:00
|
|
|
draw_set_colour_rgb(dctx, truecolour.bg, attr & ATTR_DIM);
|
2017-09-30 19:32:32 +03:00
|
|
|
else
|
2017-10-05 23:02:56 +03:00
|
|
|
draw_set_colour(dctx, nbg, attr & ATTR_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
|
|
|
draw_rectangle(dctx, TRUE,
|
|
|
|
x*inst->font_width+inst->window_border,
|
|
|
|
y*inst->font_height+inst->window_border,
|
|
|
|
rlen*widefactor*inst->font_width, inst->font_height);
|
|
|
|
|
2017-09-30 19:32:32 +03:00
|
|
|
if (truecolour.fg.enabled)
|
2017-10-05 23:02:56 +03:00
|
|
|
draw_set_colour_rgb(dctx, truecolour.fg, attr & ATTR_DIM);
|
2017-09-30 19:32:32 +03:00
|
|
|
else
|
2017-10-05 23:02:56 +03:00
|
|
|
draw_set_colour(dctx, nfg, attr & ATTR_DIM);
|
2015-09-26 12:18:53 +03:00
|
|
|
if (ncombining > 1) {
|
|
|
|
assert(len == 1);
|
|
|
|
unifont_draw_combining(&dctx->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 {
|
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
|
|
|
unifont_draw_text(&dctx->uctx, inst->fonts[fontid],
|
2011-09-16 23:18:53 +04:00
|
|
|
x*inst->font_width+inst->window_border,
|
2015-09-26 12:18:53 +03:00
|
|
|
(y*inst->font_height+inst->window_border+
|
|
|
|
inst->fonts[0]->ascent),
|
|
|
|
text, len, widefactor > 1,
|
2011-09-16 23:18:53 +04:00
|
|
|
bold, inst->font_width);
|
2002-12-31 15:20:34 +03:00
|
|
|
}
|
2002-10-10 14:40:30 +04:00
|
|
|
|
|
|
|
if (attr & ATTR_UNDER) {
|
|
|
|
int uheight = inst->fonts[0]->ascent + 1;
|
2002-10-10 18:42:56 +04:00
|
|
|
if (uheight >= inst->font_height)
|
|
|
|
uheight = inst->font_height - 1;
|
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_line(dctx, x*inst->font_width+inst->window_border,
|
|
|
|
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);
|
2002-10-10 14:40:30 +04:00
|
|
|
}
|
|
|
|
|
Re-engineering of terminal emulator, phase 1.
The active terminal screen is no longer an array of `unsigned long'
encoding 16-bit Unicode plus 16 attribute bits. Now it's an array of
`termchar' structures, which currently have 32-bit Unicode and 32
attribute bits but which will probably expand further in future.
To prevent bloat of the memory footprint, I've introduced a mostly
RLE-like compression scheme for storing scrollback: each line is
compressed into a compact (but hard to modify) form when it moves
into the term->scrollback tree, and is temporarily decompressed when
the user wants to scroll back over it. My initial tests suggest that
this compression averages about 1/4 of the previous (32 bits per
character cell) data size in typical output, which means this is an
improvement even without counting the new ability to extend the
information stored in each character cell.
Another beneficial side effect is that the insane format in which
Unicode was passed to front ends through do_text() has now been
rendered sane.
Testing is incomplete; this _may_ still have instabilities. Windows
and Unix front ends both seem to work as far as I've looked, but I
haven't yet looked very hard. The Mac front end I've edited (it
seemed obvious how to change it) but I can't compile or test it.
As an immediate functional effect, the terminal emulator now
supports full 32-bit Unicode to whatever extent the host platform
allows it to. For example, if you output a 4-or-more-byte UTF-8
character in Unix pterm, it will not display it properly, but it
will correctly paste it back out in a UTF8_STRING selection. Windows
is more restricted, sadly.
[originally from svn r4609]
2004-10-13 15:50:16 +04:00
|
|
|
if ((lattr & LATTR_MODE) != LATTR_NORM) {
|
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_stretch_after(dctx,
|
|
|
|
x*inst->font_width+inst->window_border,
|
|
|
|
y*inst->font_height+inst->window_border,
|
|
|
|
rlen*widefactor*inst->font_width, TRUE,
|
|
|
|
inst->font_height,
|
|
|
|
((lattr & LATTR_MODE) != LATTR_WIDE),
|
|
|
|
((lattr & LATTR_MODE) == LATTR_BOT));
|
2002-10-15 22:18:25 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Re-engineering of terminal emulator, phase 1.
The active terminal screen is no longer an array of `unsigned long'
encoding 16-bit Unicode plus 16 attribute bits. Now it's an array of
`termchar' structures, which currently have 32-bit Unicode and 32
attribute bits but which will probably expand further in future.
To prevent bloat of the memory footprint, I've introduced a mostly
RLE-like compression scheme for storing scrollback: each line is
compressed into a compact (but hard to modify) form when it moves
into the term->scrollback tree, and is temporarily decompressed when
the user wants to scroll back over it. My initial tests suggest that
this compression averages about 1/4 of the previous (32 bits per
character cell) data size in typical output, which means this is an
improvement even without counting the new ability to extend the
information stored in each character cell.
Another beneficial side effect is that the insane format in which
Unicode was passed to front ends through do_text() has now been
rendered sane.
Testing is incomplete; this _may_ still have instabilities. Windows
and Unix front ends both seem to work as far as I've looked, but I
haven't yet looked very hard. The Mac front end I've edited (it
seemed obvious how to change it) but I can't compile or test it.
As an immediate functional effect, the terminal emulator now
supports full 32-bit Unicode to whatever extent the host platform
allows it to. For example, if you output a 4-or-more-byte UTF-8
character in Unix pterm, it will not display it properly, but it
will correctly paste it back out in a UTF8_STRING selection. Windows
is more restricted, sadly.
[originally from svn r4609]
2004-10-13 15:50:16 +04:00
|
|
|
void do_text(Context ctx, int x, int y, wchar_t *text, int len,
|
2017-09-30 19:32:32 +03:00
|
|
|
unsigned long attr, int lattr, truecolour truecolour)
|
2002-10-15 22:18:25 +04:00
|
|
|
{
|
2002-10-26 16:58:13 +04:00
|
|
|
struct draw_ctx *dctx = (struct draw_ctx *)ctx;
|
|
|
|
struct gui_data *inst = dctx->inst;
|
2003-01-02 00:53:22 +03:00
|
|
|
int widefactor;
|
2002-10-15 22:18:25 +04:00
|
|
|
|
2017-09-30 19:32:32 +03:00
|
|
|
do_text_internal(ctx, x, y, text, len, attr, lattr, truecolour);
|
2002-10-15 22:18:25 +04:00
|
|
|
|
2003-01-02 00:53:22 +03:00
|
|
|
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) {
|
2002-10-15 22:18:25 +04:00
|
|
|
x *= 2;
|
2002-10-26 15:08:59 +04:00
|
|
|
if (x >= inst->term->cols)
|
2002-10-15 22:18:25 +04:00
|
|
|
return;
|
2003-01-02 00:53:22 +03:00
|
|
|
if (x + len*2*widefactor > inst->term->cols)
|
|
|
|
len = (inst->term->cols-x)/2/widefactor;/* trim to LH half */
|
2002-10-15 04:22:48 +04:00
|
|
|
len *= 2;
|
|
|
|
}
|
|
|
|
|
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_update(dctx,
|
|
|
|
x*inst->font_width+inst->window_border,
|
|
|
|
y*inst->font_height+inst->window_border,
|
|
|
|
len*widefactor*inst->font_width, inst->font_height);
|
2002-10-09 22:09:42 +04:00
|
|
|
}
|
|
|
|
|
Re-engineering of terminal emulator, phase 1.
The active terminal screen is no longer an array of `unsigned long'
encoding 16-bit Unicode plus 16 attribute bits. Now it's an array of
`termchar' structures, which currently have 32-bit Unicode and 32
attribute bits but which will probably expand further in future.
To prevent bloat of the memory footprint, I've introduced a mostly
RLE-like compression scheme for storing scrollback: each line is
compressed into a compact (but hard to modify) form when it moves
into the term->scrollback tree, and is temporarily decompressed when
the user wants to scroll back over it. My initial tests suggest that
this compression averages about 1/4 of the previous (32 bits per
character cell) data size in typical output, which means this is an
improvement even without counting the new ability to extend the
information stored in each character cell.
Another beneficial side effect is that the insane format in which
Unicode was passed to front ends through do_text() has now been
rendered sane.
Testing is incomplete; this _may_ still have instabilities. Windows
and Unix front ends both seem to work as far as I've looked, but I
haven't yet looked very hard. The Mac front end I've edited (it
seemed obvious how to change it) but I can't compile or test it.
As an immediate functional effect, the terminal emulator now
supports full 32-bit Unicode to whatever extent the host platform
allows it to. For example, if you output a 4-or-more-byte UTF-8
character in Unix pterm, it will not display it properly, but it
will correctly paste it back out in a UTF8_STRING selection. Windows
is more restricted, sadly.
[originally from svn r4609]
2004-10-13 15:50:16 +04:00
|
|
|
void do_cursor(Context ctx, int x, int y, wchar_t *text, int len,
|
2017-09-30 19:32:32 +03:00
|
|
|
unsigned long attr, int lattr, truecolour truecolour)
|
2002-10-09 22:09:42 +04:00
|
|
|
{
|
2002-10-26 16:58:13 +04:00
|
|
|
struct draw_ctx *dctx = (struct draw_ctx *)ctx;
|
|
|
|
struct gui_data *inst = dctx->inst;
|
|
|
|
|
2004-09-29 00:42:39 +04:00
|
|
|
int active, passive, widefactor;
|
2002-10-10 14:40:30 +04:00
|
|
|
|
2002-10-09 22:09:42 +04:00
|
|
|
if (attr & TATTR_PASCURS) {
|
|
|
|
attr &= ~TATTR_PASCURS;
|
2002-10-10 14:40:30 +04:00
|
|
|
passive = 1;
|
|
|
|
} else
|
|
|
|
passive = 0;
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 22:52:21 +04:00
|
|
|
if ((attr & TATTR_ACTCURS) && inst->cursor_type != 0) {
|
2002-10-15 22:18:25 +04:00
|
|
|
attr &= ~TATTR_ACTCURS;
|
2004-09-29 00:42:39 +04:00
|
|
|
active = 1;
|
|
|
|
} else
|
|
|
|
active = 0;
|
2017-09-30 19:32:32 +03:00
|
|
|
do_text_internal(ctx, x, y, text, len, attr, lattr, truecolour);
|
2002-10-15 22:18:25 +04:00
|
|
|
|
2004-10-15 12:51:57 +04:00
|
|
|
if (attr & TATTR_COMBINING)
|
|
|
|
len = 1;
|
|
|
|
|
2003-01-02 00:53:22 +03:00
|
|
|
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) {
|
2002-10-15 22:18:25 +04:00
|
|
|
x *= 2;
|
2002-10-26 15:08:59 +04:00
|
|
|
if (x >= inst->term->cols)
|
2002-10-15 22:18:25 +04:00
|
|
|
return;
|
2003-01-02 00:53:22 +03:00
|
|
|
if (x + len*2*widefactor > inst->term->cols)
|
|
|
|
len = (inst->term->cols-x)/2/widefactor;/* trim to LH half */
|
2002-10-15 22:18:25 +04:00
|
|
|
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) {
|
2002-10-15 22:18:25 +04:00
|
|
|
/*
|
|
|
|
* 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) {
|
2017-10-05 23:02:56 +03:00
|
|
|
draw_set_colour(dctx, 261, 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
|
|
|
draw_rectangle(dctx, FALSE,
|
|
|
|
x*inst->font_width+inst->window_border,
|
|
|
|
y*inst->font_height+inst->window_border,
|
|
|
|
len*widefactor*inst->font_width-1,
|
|
|
|
inst->font_height-1);
|
2002-10-15 22:18:25 +04:00
|
|
|
}
|
|
|
|
} 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)
|
2002-10-15 22:18:25 +04:00
|
|
|
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) {
|
2002-10-15 22:18:25 +04:00
|
|
|
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;
|
2002-10-15 22:18:25 +04:00
|
|
|
dx = 1;
|
|
|
|
dy = 0;
|
2004-10-15 16:25:51 +04:00
|
|
|
length = len * widefactor * char_width;
|
2002-10-15 22:18:25 +04:00
|
|
|
} 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;
|
2002-10-15 22:18:25 +04:00
|
|
|
dx = 0;
|
|
|
|
dy = 1;
|
|
|
|
length = inst->font_height;
|
|
|
|
}
|
|
|
|
|
2017-10-05 23:02:56 +03:00
|
|
|
draw_set_colour(dctx, 261, FALSE);
|
2002-10-15 22:18:25 +04:00
|
|
|
if (passive) {
|
|
|
|
for (i = 0; i < length; i++) {
|
|
|
|
if (i % 2 == 0) {
|
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_point(dctx, startx, starty);
|
2002-10-15 22:18:25 +04:00
|
|
|
}
|
|
|
|
startx += dx;
|
|
|
|
starty += dy;
|
|
|
|
}
|
2004-09-29 00:42:39 +04:00
|
|
|
} else if (active) {
|
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_line(dctx, startx, starty,
|
|
|
|
startx + (length-1) * dx, starty + (length-1) * dy);
|
2004-09-29 00:42:39 +04:00
|
|
|
} /* else no cursor (e.g., blinked off) */
|
2002-10-10 14:40:30 +04:00
|
|
|
}
|
2002-10-15 22:18:25 +04:00
|
|
|
|
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_update(dctx,
|
|
|
|
x*inst->font_width+inst->window_border,
|
|
|
|
y*inst->font_height+inst->window_border,
|
|
|
|
len*widefactor*inst->font_width, inst->font_height);
|
2012-06-17 11:26:23 +04:00
|
|
|
|
|
|
|
#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
|
2002-10-09 22:09:42 +04:00
|
|
|
}
|
|
|
|
|
2002-10-26 16:58:13 +04:00
|
|
|
GdkCursor *make_mouse_ptr(struct gui_data *inst, int cursor_val)
|
2002-10-13 16:17:03 +04:00
|
|
|
{
|
Withdraw the horrible bodge in make_mouse_ptr().
We were previously building our own mouse pointers out of pixmaps,
having first drawn characters from the X server standard font 'cursor'
on to those pixmaps, giving an effect almost exactly the same as just
calling gdk_cursor_new(some constant) except that we got to choose the
foreground and background colours of the resulting pointers.
But it's not clear why we needed to do that! In both GTK1 and GTK2 as
of my current testing, the standard colours appear to be just what I
wanted anyway (white pointer with black outline). The previous
implementation (and commit comment) was written in 2002, so perhaps it
was working around a GTK1 bug of the time.
So I've removed it completely, and replaced it with simple calls to
gdk_cursor_new (plus a workaround for GTK1's lack of GDK_BLANK_CURSOR,
but that's still much simpler than the previous code). If anyone does
report a colour problem, I may have to go back to doing something
clever, but if I can possibly arrange it, I'll want to do it by some
other technique, probably (as suggested in a comment in the previous
implementation) getting the underlying X cursor id and calling
XRecolorCursor.
2015-08-15 23:07:35 +03:00
|
|
|
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
|
2002-10-14 13:58:27 +04:00
|
|
|
}
|
2002-10-13 16:17:03 +04:00
|
|
|
|
Withdraw the horrible bodge in make_mouse_ptr().
We were previously building our own mouse pointers out of pixmaps,
having first drawn characters from the X server standard font 'cursor'
on to those pixmaps, giving an effect almost exactly the same as just
calling gdk_cursor_new(some constant) except that we got to choose the
foreground and background colours of the resulting pointers.
But it's not clear why we needed to do that! In both GTK1 and GTK2 as
of my current testing, the standard colours appear to be just what I
wanted anyway (white pointer with black outline). The previous
implementation (and commit comment) was written in 2002, so perhaps it
was working around a GTK1 bug of the time.
So I've removed it completely, and replaced it with simple calls to
gdk_cursor_new (plus a workaround for GTK1's lack of GDK_BLANK_CURSOR,
but that's still much simpler than the previous code). If anyone does
report a colour problem, I may have to go back to doing something
clever, but if I can possibly arrange it, I'll want to do it by some
other technique, probably (as suggested in a comment in the previous
implementation) getting the underlying X cursor id and calling
XRecolorCursor.
2015-08-15 23:07:35 +03:00
|
|
|
return gdk_cursor_new(cursor_val);
|
2002-10-13 16:17:03 +04:00
|
|
|
}
|
|
|
|
|
2015-05-15 13:15:42 +03:00
|
|
|
void modalfatalbox(const char *p, ...)
|
2002-10-09 22:09:42 +04:00
|
|
|
{
|
|
|
|
va_list ap;
|
|
|
|
fprintf(stderr, "FATAL ERROR: ");
|
|
|
|
va_start(ap, p);
|
|
|
|
vfprintf(stderr, p, ap);
|
|
|
|
va_end(ap);
|
|
|
|
fputc('\n', stderr);
|
|
|
|
exit(1);
|
2002-10-07 20:45:23 +04:00
|
|
|
}
|
|
|
|
|
2015-08-22 16:07:02 +03:00
|
|
|
const char *get_x_display(void *frontend)
|
2002-10-15 16:29:52 +04:00
|
|
|
{
|
|
|
|
return gdk_get_display();
|
|
|
|
}
|
|
|
|
|
2015-08-08 18:35:19 +03:00
|
|
|
#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
|
|
|
int get_windowid(void *frontend, long *id)
|
2003-03-06 15:57:37 +03:00
|
|
|
{
|
Rationalisation of the system of frontend handles. Most modular bits
of PuTTY (terminal, backend, logctx etc) take a `void *' handle
passed to them from the frontend, and used as a context for all
their callbacks. Most of these point at the frontend structure
itself (on platforms where this is meaningful), except that the
handle passed to the backend has always pointed at the terminal
because from_backend() was implemented in terminal.c. This has
finally bitten Unix PuTTY, because both backend and logctx have
been passing their respective and very different frontend handles to
logevent(), so I've fixed it.
from_backend() is now a function supplied by the _frontend_ itself,
in all cases, and the frontend handle passed to backends must be the
same as that passed to everything else. What was from_backend() in
terminal.c is now called term_data(), and the typical implementation
of from_backend() in a GUI frontend will just extract the terminal
handle from the frontend structure and delegate to that.
This appears to work on Unix and Windows, but has most likely broken
the Mac build.
[originally from svn r3100]
2003-04-11 22:36:27 +04:00
|
|
|
struct gui_data *inst = (struct gui_data *)frontend;
|
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;
|
|
|
|
*id = GDK_WINDOW_XID(window);
|
|
|
|
return TRUE;
|
2003-03-06 15:57:37 +03:00
|
|
|
}
|
2015-08-08 18:35:19 +03:00
|
|
|
#endif
|
2003-03-06 15:57:37 +03:00
|
|
|
|
2015-09-01 20:35:38 +03:00
|
|
|
int frontend_is_utf8(void *frontend)
|
|
|
|
{
|
|
|
|
struct gui_data *inst = (struct gui_data *)frontend;
|
|
|
|
return inst->ucsdata.line_codepage == CS_UTF8;
|
|
|
|
}
|
|
|
|
|
2013-01-14 01:59:10 +04:00
|
|
|
char *setup_fonts_ucs(struct gui_data *inst)
|
2003-04-10 22:00:50 +04:00
|
|
|
{
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 22:52:21 +04:00
|
|
|
int shadowbold = conf_get_int(inst->conf, CONF_shadowbold);
|
|
|
|
int shadowboldoffset = conf_get_int(inst->conf, CONF_shadowboldoffset);
|
|
|
|
FontSpec *fs;
|
2013-01-14 01:59:10 +04:00
|
|
|
unifont *fonts[4];
|
|
|
|
int i;
|
2003-04-10 22:00:50 +04:00
|
|
|
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 22:52:21 +04:00
|
|
|
fs = conf_get_fontspec(inst->conf, CONF_font);
|
2013-01-14 01:59:10 +04:00
|
|
|
fonts[0] = multifont_create(inst->area, fs->name, FALSE, FALSE,
|
|
|
|
shadowboldoffset, shadowbold);
|
|
|
|
if (!fonts[0]) {
|
|
|
|
return dupprintf("unable to load font \"%s\"", fs->name);
|
2003-04-10 22:00:50 +04:00
|
|
|
}
|
2003-05-10 14:15:00 +04:00
|
|
|
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 22:52:21 +04:00
|
|
|
fs = conf_get_fontspec(inst->conf, CONF_boldfont);
|
|
|
|
if (shadowbold || !fs->name[0]) {
|
2013-01-14 01:59:10 +04:00
|
|
|
fonts[1] = NULL;
|
2003-05-10 14:15:00 +04:00
|
|
|
} else {
|
2013-01-14 01:59:10 +04:00
|
|
|
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);
|
2003-08-21 22:39:17 +04:00
|
|
|
}
|
2003-05-10 14:15:00 +04:00
|
|
|
}
|
|
|
|
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 22:52:21 +04:00
|
|
|
fs = conf_get_fontspec(inst->conf, CONF_widefont);
|
|
|
|
if (fs->name[0]) {
|
2013-01-14 01:59:10 +04:00
|
|
|
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]);
|
2013-11-17 18:05:44 +04:00
|
|
|
return dupprintf("unable to load wide font \"%s\"", fs->name);
|
Refactor the font handling code: I've moved all the code that
explicitly deals with GdkFont out into a new module, behind a
polymorphic interface (done by ad-hoc explicit vtable management in
C). This should allow me to drop in a Pango font handling module in
parallel with the existing one, meaning that GTK2 PuTTY will be able
to seamlessly switch between X11 server-side fonts and Pango client-
side ones as the user chooses, or even use a mixture of the two
(e.g. an X11 font for narrow characters and a Pango one for wide
characters, or vice versa).
In the process, incidentally, I got to the bottom of the `weird bug'
mentioned in the old do_text_internal(). It's not a bug in
gdk_draw_text_wc() as I had thought: it's simply that GdkWChar is a
32-bit type rather than a 16-bit one, so no wonder you have to
specify twice the length to find all the characters in the string!
However, there _is_ a bug in GTK2's gdk_draw_text_wc(), which causes
it to strip off everything above the low byte of each GdkWChar,
sigh. Solution to both problems is to use an array of the underlying
Xlib type XChar2b instead, and pass it to gdk_draw_text() cast to
gchar *. Grotty, but it works. (And it'll become significantly less
grotty if and when we have to stop using the GDK font handling
wrappers in favour of going direct to Xlib.)
[originally from svn r7933]
2008-03-22 14:40:23 +03:00
|
|
|
}
|
2003-05-10 14:15:00 +04:00
|
|
|
} else {
|
2013-01-14 01:59:10 +04:00
|
|
|
fonts[2] = NULL;
|
2003-05-10 14:15:00 +04:00
|
|
|
}
|
|
|
|
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 22:52:21 +04:00
|
|
|
fs = conf_get_fontspec(inst->conf, CONF_wideboldfont);
|
|
|
|
if (shadowbold || !fs->name[0]) {
|
2013-01-14 01:59:10 +04:00
|
|
|
fonts[3] = NULL;
|
2003-05-10 14:15:00 +04:00
|
|
|
} else {
|
2013-01-14 01:59:10 +04:00
|
|
|
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]);
|
2013-11-17 18:05:44 +04:00
|
|
|
return dupprintf("unable to load wide bold font \"%s\"", fs->name);
|
2003-08-21 22:39:17 +04:00
|
|
|
}
|
2003-05-10 14:15:00 +04:00
|
|
|
}
|
2003-04-10 22:00:50 +04:00
|
|
|
|
2013-01-14 01:59:10 +04:00
|
|
|
/*
|
|
|
|
* 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];
|
|
|
|
}
|
|
|
|
|
2018-05-17 13:20:01 +03:00
|
|
|
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;
|
|
|
|
}
|
2003-04-10 22:00:50 +04:00
|
|
|
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 22:52:21 +04:00
|
|
|
inst->direct_to_font = init_ucs(&inst->ucsdata,
|
|
|
|
conf_get_str(inst->conf, CONF_line_codepage),
|
|
|
|
conf_get_int(inst->conf, CONF_utf8_override),
|
Refactor the font handling code: I've moved all the code that
explicitly deals with GdkFont out into a new module, behind a
polymorphic interface (done by ad-hoc explicit vtable management in
C). This should allow me to drop in a Pango font handling module in
parallel with the existing one, meaning that GTK2 PuTTY will be able
to seamlessly switch between X11 server-side fonts and Pango client-
side ones as the user chooses, or even use a mixture of the two
(e.g. an X11 font for narrow characters and a Pango one for wide
characters, or vice versa).
In the process, incidentally, I got to the bottom of the `weird bug'
mentioned in the old do_text_internal(). It's not a bug in
gdk_draw_text_wc() as I had thought: it's simply that GdkWChar is a
32-bit type rather than a 16-bit one, so no wonder you have to
specify twice the length to find all the characters in the string!
However, there _is_ a bug in GTK2's gdk_draw_text_wc(), which causes
it to strip off everything above the low byte of each GdkWChar,
sigh. Solution to both problems is to use an array of the underlying
Xlib type XChar2b instead, and pass it to gdk_draw_text() cast to
gchar *. Grotty, but it works. (And it'll become significantly less
grotty if and when we have to stop using the GDK font handling
wrappers in favour of going direct to Xlib.)
[originally from svn r7933]
2008-03-22 14:40:23 +03:00
|
|
|
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));
|
2013-01-14 01:59:10 +04:00
|
|
|
|
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;
|
|
|
|
|
2013-01-14 01:59:10 +04:00
|
|
|
return NULL;
|
2003-04-10 22:00:50 +04:00
|
|
|
}
|
|
|
|
|
2016-04-04 13:28:34 +03:00
|
|
|
#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
|
|
|
|
|
2016-04-04 13:23:25 +03:00
|
|
|
static void compute_geom_hints(struct gui_data *inst, GdkGeometry *geom)
|
2003-04-10 22:00:50 +04:00
|
|
|
{
|
2016-03-29 15:42:54 +03:00
|
|
|
/*
|
|
|
|
* Unused fields in geom.
|
|
|
|
*/
|
2016-04-04 13:23:25 +03:00
|
|
|
geom->max_width = geom->max_height = -1;
|
|
|
|
geom->min_aspect = geom->max_aspect = 0;
|
2016-03-29 15:42:54 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Set up the geometry fields we care about, with reference to
|
2016-04-04 13:28:34 +03:00
|
|
|
* just the drawing area. We'll correct for other widgets in a
|
2016-03-29 15:42:54 +03:00
|
|
|
* moment.
|
|
|
|
*/
|
2016-04-04 13:23:25 +03:00
|
|
|
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;
|
2016-03-29 15:42:54 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 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
|
2016-04-04 13:23:25 +03:00
|
|
|
* (geom->min_height - geom->base_height) is an integer multiple of
|
|
|
|
* geom->height_inc, because if it's not, then some window managers
|
2016-03-29 15:42:54 +03:00
|
|
|
* (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;
|
2016-04-04 13:23:25 +03:00
|
|
|
min_sb_height += geom->height_inc - 1;
|
|
|
|
min_sb_height -= ((min_sb_height - geom->base_height%geom->height_inc)
|
|
|
|
% geom->height_inc);
|
2016-03-29 15:42:54 +03:00
|
|
|
|
2016-04-04 13:23:25 +03:00
|
|
|
geom->min_width += req.width;
|
|
|
|
geom->base_width += req.width;
|
|
|
|
if (geom->min_height < min_sb_height)
|
|
|
|
geom->min_height = min_sb_height;
|
2016-03-29 15:42:54 +03:00
|
|
|
}
|
2016-04-04 13:28:34 +03:00
|
|
|
|
|
|
|
#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
|
2016-04-04 13:23:25 +03:00
|
|
|
}
|
2016-03-29 15:42:54 +03:00
|
|
|
|
2016-04-04 13:23:25 +03:00
|
|
|
void set_geom_hints(struct gui_data *inst)
|
|
|
|
{
|
|
|
|
GdkGeometry geom;
|
2016-04-04 13:27:01 +03:00
|
|
|
gint flags = GDK_HINT_MIN_SIZE | GDK_HINT_BASE_SIZE | GDK_HINT_RESIZE_INC;
|
2016-04-04 13:23:25 +03:00
|
|
|
compute_geom_hints(inst, &geom);
|
2016-04-04 13:27:01 +03:00
|
|
|
#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);
|
2003-04-10 22:00:50 +04:00
|
|
|
}
|
|
|
|
|
2016-04-04 13:24:24 +03:00
|
|
|
#if GTK_CHECK_VERSION(2,0,0)
|
|
|
|
static void compute_whole_window_size(struct gui_data *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
|
|
|
|
|
2003-04-05 20:05:00 +04:00
|
|
|
void clear_scrollback_menuitem(GtkMenuItem *item, gpointer data)
|
|
|
|
{
|
|
|
|
struct gui_data *inst = (struct gui_data *)data;
|
|
|
|
term_clrsb(inst->term);
|
|
|
|
}
|
|
|
|
|
|
|
|
void reset_terminal_menuitem(GtkMenuItem *item, gpointer data)
|
|
|
|
{
|
|
|
|
struct gui_data *inst = (struct gui_data *)data;
|
2006-02-19 17:59:48 +03:00
|
|
|
term_pwron(inst->term, TRUE);
|
2004-08-14 17:04:18 +04:00
|
|
|
if (inst->ldisc)
|
Move echo/edit state change functionality out of ldisc_send.
I'm not actually sure why we've always had back ends notify ldisc of
changes to echo/edit settings by giving ldisc_send(ldisc,NULL,0,0) a
special meaning, instead of by having a separate dedicated notify
function with its own prototype and parameter set. Coverity's recent
observation that the two kinds of call don't even have the same
requirements on the ldisc (particularly, whether ldisc->term can be
NULL) makes me realise that it's really high time I separated the two
conceptually different operations into actually different functions.
While I'm here, I've renamed the confusing ldisc_update() function
which that special operation ends up feeding to, because it's not
actually a function applying to an ldisc - it applies to a front end.
So ldisc_send(ldisc,NULL,0,0) is now ldisc_echoedit_update(ldisc), and
that in turn figures out the current echo/edit settings before passing
them on to frontend_echoedit_update(). I think that should be clearer.
2014-11-22 19:12:47 +03:00
|
|
|
ldisc_echoedit_update(inst->ldisc);
|
2003-04-05 20:05:00 +04:00
|
|
|
}
|
|
|
|
|
2017-12-10 19:25:54 +03:00
|
|
|
void copy_clipboard_menuitem(GtkMenuItem *item, gpointer data)
|
|
|
|
{
|
|
|
|
struct gui_data *inst = (struct gui_data *)data;
|
2017-12-17 23:35:45 +03:00
|
|
|
static const int clips[] = { MENU_CLIPBOARD };
|
2017-12-10 19:25:54 +03:00
|
|
|
term_request_copy(inst->term, clips, lenof(clips));
|
|
|
|
}
|
|
|
|
|
|
|
|
void paste_clipboard_menuitem(GtkMenuItem *item, gpointer data)
|
|
|
|
{
|
|
|
|
struct gui_data *inst = (struct gui_data *)data;
|
2017-12-17 23:35:45 +03:00
|
|
|
term_request_paste(inst->term, MENU_CLIPBOARD);
|
2017-12-10 19:25:54 +03:00
|
|
|
}
|
|
|
|
|
2003-04-11 21:59:36 +04:00
|
|
|
void copy_all_menuitem(GtkMenuItem *item, gpointer data)
|
|
|
|
{
|
|
|
|
struct gui_data *inst = (struct gui_data *)data;
|
2017-12-17 23:35:45 +03:00
|
|
|
static const int clips[] = { COPYALL_CLIPBOARDS };
|
2017-12-10 18:45:45 +03:00
|
|
|
term_copyall(inst->term, clips, lenof(clips));
|
2003-04-11 21:59:36 +04:00
|
|
|
}
|
|
|
|
|
2003-04-05 20:05:00 +04:00
|
|
|
void special_menuitem(GtkMenuItem *item, gpointer data)
|
|
|
|
{
|
|
|
|
struct gui_data *inst = (struct gui_data *)data;
|
2015-08-08 19:29:02 +03:00
|
|
|
int code = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(item),
|
|
|
|
"user-data"));
|
2003-04-05 20:05:00 +04:00
|
|
|
|
2004-08-14 17:04:18 +04:00
|
|
|
if (inst->back)
|
|
|
|
inst->back->special(inst->backhandle, code);
|
2003-04-05 20:05:00 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void about_menuitem(GtkMenuItem *item, gpointer data)
|
|
|
|
{
|
2003-04-10 12:53:43 +04:00
|
|
|
struct gui_data *inst = (struct gui_data *)data;
|
|
|
|
about_box(inst->window);
|
2003-04-05 20:05:00 +04:00
|
|
|
}
|
|
|
|
|
2003-04-09 22:46:45 +04:00
|
|
|
void event_log_menuitem(GtkMenuItem *item, gpointer data)
|
|
|
|
{
|
|
|
|
struct gui_data *inst = (struct gui_data *)data;
|
|
|
|
showeventlog(inst->eventlogstuff, inst->window);
|
|
|
|
}
|
|
|
|
|
2017-12-17 21:44:27 +03:00
|
|
|
void setup_clipboards(struct gui_data *inst, Terminal *term, Conf *conf)
|
2017-12-10 20:16:50 +03:00
|
|
|
{
|
|
|
|
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_int(conf, CONF_mouseautocopy)) {
|
|
|
|
term->mouse_select_clipboards[
|
|
|
|
term->n_mouse_select_clipboards++] = CLIP_CLIPBOARD;
|
|
|
|
}
|
|
|
|
|
2017-12-17 21:44:27 +03:00
|
|
|
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);
|
|
|
|
|
2017-12-10 20:16:50 +03:00
|
|
|
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;
|
2017-12-17 21:44:27 +03:00
|
|
|
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;
|
2017-12-10 20:16:50 +03:00
|
|
|
default:
|
|
|
|
term->mouse_paste_clipboard = CLIP_NULL;
|
|
|
|
break;
|
|
|
|
}
|
2017-12-17 21:44:27 +03:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
2017-12-10 20:16:50 +03:00
|
|
|
}
|
|
|
|
|
Make the configuration dialog non-modal.
Now every call to do_config_box is replaced with a call to
create_config_box, which returns immediately having constructed the
new GTK window object, and is passed a callback function which it will
arrange to be called when the dialog terminates (whether by OK or by
Cancel). That callback is now what triggers the construction of a
session window after 'Open' is pressed in the initial config box, or
the actual mid-session reconfiguration action after 'Apply' is pressed
in a Change Settings box.
We were already prepared to ignore the re-selection of 'Change
Settings' from the context menu of a window that already had a Change
Settings box open (and not accidentally create a second config box for
the same window); but now we do slightly better, by finding the
existing config box and un-minimising and raising it, in case the user
had forgotten it was there.
That's a useful featurelet, but not the main purpose of this change.
The mani point, of course, is that now the multi-window GtkApplication
based front ends now don't do anything confusing to the nesting of
gtk_main() when config boxes are involved. Whether you're changing the
settings of one (or more than one) of your already-running sessions,
preparing to start up a new PuTTY connection, or both at once, we stay
in the same top-level instance of gtk_main() and all sessions' top-
level callbacks continue to run sensibly.
2017-11-26 14:58:02 +03:00
|
|
|
struct after_change_settings_dialog_ctx {
|
|
|
|
struct gui_data *inst;
|
|
|
|
Conf *newconf;
|
|
|
|
};
|
|
|
|
|
|
|
|
static void after_change_settings_dialog(void *vctx, int retval);
|
|
|
|
|
2003-04-10 22:00:50 +04:00
|
|
|
void change_settings_menuitem(GtkMenuItem *item, gpointer data)
|
Make the configuration dialog non-modal.
Now every call to do_config_box is replaced with a call to
create_config_box, which returns immediately having constructed the
new GTK window object, and is passed a callback function which it will
arrange to be called when the dialog terminates (whether by OK or by
Cancel). That callback is now what triggers the construction of a
session window after 'Open' is pressed in the initial config box, or
the actual mid-session reconfiguration action after 'Apply' is pressed
in a Change Settings box.
We were already prepared to ignore the re-selection of 'Change
Settings' from the context menu of a window that already had a Change
Settings box open (and not accidentally create a second config box for
the same window); but now we do slightly better, by finding the
existing config box and un-minimising and raising it, in case the user
had forgotten it was there.
That's a useful featurelet, but not the main purpose of this change.
The mani point, of course, is that now the multi-window GtkApplication
based front ends now don't do anything confusing to the nesting of
gtk_main() when config boxes are involved. Whether you're changing the
settings of one (or more than one) of your already-running sessions,
preparing to start up a new PuTTY connection, or both at once, we stay
in the same top-level instance of gtk_main() and all sessions' top-
level callbacks continue to run sensibly.
2017-11-26 14:58:02 +03:00
|
|
|
{
|
|
|
|
struct gui_data *inst = (struct gui_data *)data;
|
|
|
|
struct after_change_settings_dialog_ctx *ctx;
|
2017-11-26 19:51:19 +03:00
|
|
|
GtkWidget *dialog;
|
Make the configuration dialog non-modal.
Now every call to do_config_box is replaced with a call to
create_config_box, which returns immediately having constructed the
new GTK window object, and is passed a callback function which it will
arrange to be called when the dialog terminates (whether by OK or by
Cancel). That callback is now what triggers the construction of a
session window after 'Open' is pressed in the initial config box, or
the actual mid-session reconfiguration action after 'Apply' is pressed
in a Change Settings box.
We were already prepared to ignore the re-selection of 'Change
Settings' from the context menu of a window that already had a Change
Settings box open (and not accidentally create a second config box for
the same window); but now we do slightly better, by finding the
existing config box and un-minimising and raising it, in case the user
had forgotten it was there.
That's a useful featurelet, but not the main purpose of this change.
The mani point, of course, is that now the multi-window GtkApplication
based front ends now don't do anything confusing to the nesting of
gtk_main() when config boxes are involved. Whether you're changing the
settings of one (or more than one) of your already-running sessions,
preparing to start up a new PuTTY connection, or both at once, we stay
in the same top-level instance of gtk_main() and all sessions' top-
level callbacks continue to run sensibly.
2017-11-26 14:58:02 +03:00
|
|
|
char *title;
|
|
|
|
|
2017-11-26 20:21:32 +03:00
|
|
|
if (find_and_raise_dialog(inst, DIALOG_SLOT_RECONFIGURE))
|
Make the configuration dialog non-modal.
Now every call to do_config_box is replaced with a call to
create_config_box, which returns immediately having constructed the
new GTK window object, and is passed a callback function which it will
arrange to be called when the dialog terminates (whether by OK or by
Cancel). That callback is now what triggers the construction of a
session window after 'Open' is pressed in the initial config box, or
the actual mid-session reconfiguration action after 'Apply' is pressed
in a Change Settings box.
We were already prepared to ignore the re-selection of 'Change
Settings' from the context menu of a window that already had a Change
Settings box open (and not accidentally create a second config box for
the same window); but now we do slightly better, by finding the
existing config box and un-minimising and raising it, in case the user
had forgotten it was there.
That's a useful featurelet, but not the main purpose of this change.
The mani point, of course, is that now the multi-window GtkApplication
based front ends now don't do anything confusing to the nesting of
gtk_main() when config boxes are involved. Whether you're changing the
settings of one (or more than one) of your already-running sessions,
preparing to start up a new PuTTY connection, or both at once, we stay
in the same top-level instance of gtk_main() and all sessions' top-
level callbacks continue to run sensibly.
2017-11-26 14:58:02 +03:00
|
|
|
return;
|
|
|
|
|
|
|
|
title = dupcat(appname, " Reconfiguration", NULL);
|
|
|
|
|
|
|
|
ctx = snew(struct after_change_settings_dialog_ctx);
|
|
|
|
ctx->inst = inst;
|
|
|
|
ctx->newconf = conf_copy(inst->conf);
|
|
|
|
|
2017-11-26 19:51:19 +03:00
|
|
|
dialog = create_config_box(
|
Make the configuration dialog non-modal.
Now every call to do_config_box is replaced with a call to
create_config_box, which returns immediately having constructed the
new GTK window object, and is passed a callback function which it will
arrange to be called when the dialog terminates (whether by OK or by
Cancel). That callback is now what triggers the construction of a
session window after 'Open' is pressed in the initial config box, or
the actual mid-session reconfiguration action after 'Apply' is pressed
in a Change Settings box.
We were already prepared to ignore the re-selection of 'Change
Settings' from the context menu of a window that already had a Change
Settings box open (and not accidentally create a second config box for
the same window); but now we do slightly better, by finding the
existing config box and un-minimising and raising it, in case the user
had forgotten it was there.
That's a useful featurelet, but not the main purpose of this change.
The mani point, of course, is that now the multi-window GtkApplication
based front ends now don't do anything confusing to the nesting of
gtk_main() when config boxes are involved. Whether you're changing the
settings of one (or more than one) of your already-running sessions,
preparing to start up a new PuTTY connection, or both at once, we stay
in the same top-level instance of gtk_main() and all sessions' top-
level callbacks continue to run sensibly.
2017-11-26 14:58:02 +03:00
|
|
|
title, ctx->newconf, 1,
|
|
|
|
inst->back ? inst->back->cfg_info(inst->backhandle) : 0,
|
|
|
|
after_change_settings_dialog, ctx);
|
2017-11-26 19:51:19 +03:00
|
|
|
register_dialog(inst, DIALOG_SLOT_RECONFIGURE, dialog);
|
Make the configuration dialog non-modal.
Now every call to do_config_box is replaced with a call to
create_config_box, which returns immediately having constructed the
new GTK window object, and is passed a callback function which it will
arrange to be called when the dialog terminates (whether by OK or by
Cancel). That callback is now what triggers the construction of a
session window after 'Open' is pressed in the initial config box, or
the actual mid-session reconfiguration action after 'Apply' is pressed
in a Change Settings box.
We were already prepared to ignore the re-selection of 'Change
Settings' from the context menu of a window that already had a Change
Settings box open (and not accidentally create a second config box for
the same window); but now we do slightly better, by finding the
existing config box and un-minimising and raising it, in case the user
had forgotten it was there.
That's a useful featurelet, but not the main purpose of this change.
The mani point, of course, is that now the multi-window GtkApplication
based front ends now don't do anything confusing to the nesting of
gtk_main() when config boxes are involved. Whether you're changing the
settings of one (or more than one) of your already-running sessions,
preparing to start up a new PuTTY connection, or both at once, we stay
in the same top-level instance of gtk_main() and all sessions' top-
level callbacks continue to run sensibly.
2017-11-26 14:58:02 +03:00
|
|
|
|
|
|
|
sfree(title);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void after_change_settings_dialog(void *vctx, int retval)
|
2003-04-10 22:00:50 +04:00
|
|
|
{
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 22:52:21 +04:00
|
|
|
/* This maps colour indices in inst->conf to those used in inst->cols. */
|
2003-04-10 22:00:50 +04:00
|
|
|
static const int ww[] = {
|
2004-11-28 18:13:34 +03:00
|
|
|
256, 257, 258, 259, 260, 261,
|
|
|
|
0, 8, 1, 9, 2, 10, 3, 11,
|
|
|
|
4, 12, 5, 13, 6, 14, 7, 15
|
2003-04-10 22:00:50 +04:00
|
|
|
};
|
Make the configuration dialog non-modal.
Now every call to do_config_box is replaced with a call to
create_config_box, which returns immediately having constructed the
new GTK window object, and is passed a callback function which it will
arrange to be called when the dialog terminates (whether by OK or by
Cancel). That callback is now what triggers the construction of a
session window after 'Open' is pressed in the initial config box, or
the actual mid-session reconfiguration action after 'Apply' is pressed
in a Change Settings box.
We were already prepared to ignore the re-selection of 'Change
Settings' from the context menu of a window that already had a Change
Settings box open (and not accidentally create a second config box for
the same window); but now we do slightly better, by finding the
existing config box and un-minimising and raising it, in case the user
had forgotten it was there.
That's a useful featurelet, but not the main purpose of this change.
The mani point, of course, is that now the multi-window GtkApplication
based front ends now don't do anything confusing to the nesting of
gtk_main() when config boxes are involved. Whether you're changing the
settings of one (or more than one) of your already-running sessions,
preparing to start up a new PuTTY connection, or both at once, we stay
in the same top-level instance of gtk_main() and all sessions' top-
level callbacks continue to run sensibly.
2017-11-26 14:58:02 +03:00
|
|
|
struct after_change_settings_dialog_ctx ctx =
|
|
|
|
*(struct after_change_settings_dialog_ctx *)vctx;
|
|
|
|
struct gui_data *inst = ctx.inst;
|
|
|
|
Conf *oldconf = inst->conf, *newconf = ctx.newconf;
|
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 i, j, need_size;
|
2003-04-10 22:00:50 +04:00
|
|
|
|
Make the configuration dialog non-modal.
Now every call to do_config_box is replaced with a call to
create_config_box, which returns immediately having constructed the
new GTK window object, and is passed a callback function which it will
arrange to be called when the dialog terminates (whether by OK or by
Cancel). That callback is now what triggers the construction of a
session window after 'Open' is pressed in the initial config box, or
the actual mid-session reconfiguration action after 'Apply' is pressed
in a Change Settings box.
We were already prepared to ignore the re-selection of 'Change
Settings' from the context menu of a window that already had a Change
Settings box open (and not accidentally create a second config box for
the same window); but now we do slightly better, by finding the
existing config box and un-minimising and raising it, in case the user
had forgotten it was there.
That's a useful featurelet, but not the main purpose of this change.
The mani point, of course, is that now the multi-window GtkApplication
based front ends now don't do anything confusing to the nesting of
gtk_main() when config boxes are involved. Whether you're changing the
settings of one (or more than one) of your already-running sessions,
preparing to start up a new PuTTY connection, or both at once, we stay
in the same top-level instance of gtk_main() and all sessions' top-
level callbacks continue to run sensibly.
2017-11-26 14:58:02 +03:00
|
|
|
sfree(vctx); /* we've copied this already */
|
2005-03-10 13:07:27 +03:00
|
|
|
|
2017-11-26 17:37:38 +03:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
Make the configuration dialog non-modal.
Now every call to do_config_box is replaced with a call to
create_config_box, which returns immediately having constructed the
new GTK window object, and is passed a callback function which it will
arrange to be called when the dialog terminates (whether by OK or by
Cancel). That callback is now what triggers the construction of a
session window after 'Open' is pressed in the initial config box, or
the actual mid-session reconfiguration action after 'Apply' is pressed
in a Change Settings box.
We were already prepared to ignore the re-selection of 'Change
Settings' from the context menu of a window that already had a Change
Settings box open (and not accidentally create a second config box for
the same window); but now we do slightly better, by finding the
existing config box and un-minimising and raising it, in case the user
had forgotten it was there.
That's a useful featurelet, but not the main purpose of this change.
The mani point, of course, is that now the multi-window GtkApplication
based front ends now don't do anything confusing to the nesting of
gtk_main() when config boxes are involved. Whether you're changing the
settings of one (or more than one) of your already-running sessions,
preparing to start up a new PuTTY connection, or both at once, we stay
in the same top-level instance of gtk_main() and all sessions' top-
level callbacks continue to run sensibly.
2017-11-26 14:58:02 +03:00
|
|
|
assert(lenof(ww) == NCFGCOLOURS);
|
2013-07-14 14:46:07 +04:00
|
|
|
|
2017-11-26 19:51:19 +03:00
|
|
|
unregister_dialog(inst, DIALOG_SLOT_RECONFIGURE);
|
2003-04-10 22:00:50 +04:00
|
|
|
|
Make the configuration dialog non-modal.
Now every call to do_config_box is replaced with a call to
create_config_box, which returns immediately having constructed the
new GTK window object, and is passed a callback function which it will
arrange to be called when the dialog terminates (whether by OK or by
Cancel). That callback is now what triggers the construction of a
session window after 'Open' is pressed in the initial config box, or
the actual mid-session reconfiguration action after 'Apply' is pressed
in a Change Settings box.
We were already prepared to ignore the re-selection of 'Change
Settings' from the context menu of a window that already had a Change
Settings box open (and not accidentally create a second config box for
the same window); but now we do slightly better, by finding the
existing config box and un-minimising and raising it, in case the user
had forgotten it was there.
That's a useful featurelet, but not the main purpose of this change.
The mani point, of course, is that now the multi-window GtkApplication
based front ends now don't do anything confusing to the nesting of
gtk_main() when config boxes are involved. Whether you're changing the
settings of one (or more than one) of your already-running sessions,
preparing to start up a new PuTTY connection, or both at once, we stay
in the same top-level instance of gtk_main() and all sessions' top-
level callbacks continue to run sensibly.
2017-11-26 14:58:02 +03:00
|
|
|
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;
|
2003-04-10 22:00:50 +04:00
|
|
|
|
|
|
|
/* 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);
|
2003-04-10 22:00:50 +04:00
|
|
|
/*
|
|
|
|
* Flush the line discipline's edit buffer in the case
|
|
|
|
* where local editing has just been disabled.
|
|
|
|
*/
|
2013-07-11 21:24:20 +04:00
|
|
|
if (inst->ldisc) {
|
|
|
|
ldisc_configure(inst->ldisc, inst->conf);
|
Move echo/edit state change functionality out of ldisc_send.
I'm not actually sure why we've always had back ends notify ldisc of
changes to echo/edit settings by giving ldisc_send(ldisc,NULL,0,0) a
special meaning, instead of by having a separate dedicated notify
function with its own prototype and parameter set. Coverity's recent
observation that the two kinds of call don't even have the same
requirements on the ldisc (particularly, whether ldisc->term can be
NULL) makes me realise that it's really high time I separated the two
conceptually different operations into actually different functions.
While I'm here, I've renamed the confusing ldisc_update() function
which that special operation ends up feeding to, because it's not
actually a function applying to an ldisc - it applies to a front end.
So ldisc_send(ldisc,NULL,0,0) is now ldisc_echoedit_update(ldisc), and
that in turn figures out the current echo/edit settings before passing
them on to frontend_echoedit_update(). I think that should be clearer.
2014-11-22 19:12:47 +03:00
|
|
|
ldisc_echoedit_update(inst->ldisc);
|
2013-07-11 21:24:20 +04:00
|
|
|
}
|
2003-04-10 22:00:50 +04:00
|
|
|
/* 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);
|
2017-12-17 21:44:27 +03:00
|
|
|
setup_clipboards(inst, inst->term, inst->conf);
|
2003-04-10 22:00:50 +04:00
|
|
|
/* Pass new config data to the back end */
|
2004-08-14 17:04:18 +04:00
|
|
|
if (inst->back)
|
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->back->reconfig(inst->backhandle, inst->conf);
|
|
|
|
|
|
|
|
cache_conf_values(inst);
|
2003-04-10 22:00:50 +04:00
|
|
|
|
|
|
|
/*
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 22:52:21 +04:00
|
|
|
* Just setting inst->conf is sufficient to cause colour
|
2003-04-10 22:00:50 +04:00
|
|
|
* 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.
|
2003-04-10 22:00:50 +04:00
|
|
|
*/
|
2004-11-28 18:13:34 +03:00
|
|
|
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));
|
2003-05-13 22:14:14 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If the default background has changed, we must
|
|
|
|
* repaint the space in between the window border
|
|
|
|
* and the text area.
|
|
|
|
*/
|
2013-07-14 14:45:48 +04:00
|
|
|
if (ww[i] == 258) {
|
2003-05-13 22:14:14 +04:00
|
|
|
set_window_background(inst);
|
|
|
|
draw_backing_rect(inst);
|
|
|
|
}
|
|
|
|
}
|
2003-04-10 22:00:50 +04:00
|
|
|
}
|
|
|
|
|
2016-03-29 15:42:54 +03:00
|
|
|
need_size = FALSE;
|
|
|
|
|
2003-04-10 22:00:50 +04:00
|
|
|
/*
|
|
|
|
* If the scrollbar needs to be shown, hidden, or moved
|
|
|
|
* from one end to the other of the window, do so now.
|
|
|
|
*/
|
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_scrollbar) !=
|
|
|
|
conf_get_int(newconf, CONF_scrollbar)) {
|
2016-03-29 15:42:54 +03:00
|
|
|
show_scrollbar(inst, conf_get_int(newconf, CONF_scrollbar));
|
|
|
|
need_size = TRUE;
|
2003-04-10 22:00:50 +04:00
|
|
|
}
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 22:52:21 +04:00
|
|
|
if (conf_get_int(oldconf, CONF_scrollbar_on_left) !=
|
|
|
|
conf_get_int(newconf, CONF_scrollbar_on_left)) {
|
2003-04-10 22:00:50 +04:00
|
|
|
gtk_box_reorder_child(inst->hbox, inst->sbar,
|
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_scrollbar_on_left)
|
|
|
|
? 0 : 1);
|
2003-04-10 22:00:50 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* 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)))
|
2011-08-19 18:55:24 +04:00
|
|
|
set_title(inst, conf_get_str(newconf, CONF_wintitle));
|
2003-04-26 17:55:47 +04:00
|
|
|
set_window_titles(inst);
|
2003-04-10 22:00:50 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 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)) ||
|
2012-04-22 18:22:08 +04:00
|
|
|
conf_get_int(oldconf, CONF_utf8_override) !=
|
|
|
|
conf_get_int(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_int(oldconf, CONF_shadowbold) !=
|
|
|
|
conf_get_int(newconf, CONF_shadowbold) ||
|
|
|
|
conf_get_int(oldconf, CONF_shadowboldoffset) !=
|
|
|
|
conf_get_int(newconf, CONF_shadowboldoffset)) {
|
2013-01-14 01:59:10 +04:00
|
|
|
char *errmsg = setup_fonts_ucs(inst);
|
|
|
|
if (errmsg) {
|
|
|
|
char *msgboxtext =
|
|
|
|
dupprintf("Could not change fonts in terminal window: %s\n",
|
|
|
|
errmsg);
|
2017-11-26 20:07:47 +03:00
|
|
|
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);
|
2013-07-14 14:46:07 +04:00
|
|
|
sfree(msgboxtext);
|
2013-01-14 01:59:10 +04:00
|
|
|
sfree(errmsg);
|
|
|
|
} else {
|
|
|
|
need_size = TRUE;
|
|
|
|
}
|
|
|
|
}
|
2003-04-10 22:00:50 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 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) {
|
2003-04-10 22:00:50 +04:00
|
|
|
set_geom_hints(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
|
|
|
request_resize(inst, conf_get_int(newconf, CONF_width),
|
|
|
|
conf_get_int(newconf, CONF_height));
|
2003-04-12 14:44:14 +04:00
|
|
|
} 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))
|
2003-04-12 14:44:14 +04:00
|
|
|
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));
|
2003-04-12 14:44:14 +04:00
|
|
|
}
|
2003-04-10 22:00:50 +04:00
|
|
|
|
|
|
|
term_invalidate(inst->term);
|
2003-05-13 22:14:14 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* 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);
|
2003-04-10 22:00:50 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-13 16:53:42 +03:00
|
|
|
static void change_font_size(struct gui_data *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);
|
|
|
|
request_resize(inst, 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);
|
|
|
|
}
|
|
|
|
|
2003-04-12 21:37:15 +04:00
|
|
|
void dup_session_menuitem(GtkMenuItem *item, gpointer gdata)
|
|
|
|
{
|
|
|
|
struct gui_data *inst = (struct gui_data *)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);
|
2003-04-12 21:37:15 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
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();
|
2003-04-12 21:37:15 +04:00
|
|
|
}
|
|
|
|
|
2004-08-14 17:04:18 +04:00
|
|
|
void restart_session_menuitem(GtkMenuItem *item, gpointer data)
|
|
|
|
{
|
|
|
|
struct gui_data *inst = (struct gui_data *)data;
|
|
|
|
|
|
|
|
if (!inst->back) {
|
|
|
|
logevent(inst, "----- Session restarted -----");
|
2006-02-19 17:59:48 +03:00
|
|
|
term_pwron(inst->term, FALSE);
|
2004-08-14 17:04:18 +04:00
|
|
|
start_backend(inst);
|
|
|
|
inst->exited = FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-04-12 21:37:15 +04:00
|
|
|
void saved_session_menuitem(GtkMenuItem *item, gpointer data)
|
|
|
|
{
|
2015-08-08 19:29:02 +03:00
|
|
|
char *str = (char *)g_object_get_data(G_OBJECT(item), "user-data");
|
2003-04-12 21:37:15 +04:00
|
|
|
|
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);
|
2003-04-12 21:37:15 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void saved_session_freedata(GtkMenuItem *item, gpointer data)
|
|
|
|
{
|
2015-08-08 19:29:02 +03:00
|
|
|
char *str = (char *)g_object_get_data(G_OBJECT(item), "user-data");
|
2003-04-12 21:37:15 +04:00
|
|
|
|
|
|
|
sfree(str);
|
|
|
|
}
|
|
|
|
|
2017-12-18 14:46:48 +03:00
|
|
|
void app_menu_action(void *frontend, enum MenuAction action)
|
|
|
|
{
|
|
|
|
struct gui_data *inst = (struct gui_data *)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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-04-07 05:36:28 +04:00
|
|
|
static void update_savedsess_menu(GtkMenuItem *menuitem, gpointer data)
|
|
|
|
{
|
|
|
|
struct gui_data *inst = (struct gui_data *)data;
|
|
|
|
struct sesslist sesslist;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
gtk_container_foreach(GTK_CONTAINER(inst->sessionsmenu),
|
|
|
|
(GtkCallback)gtk_widget_destroy, NULL);
|
|
|
|
|
|
|
|
get_sesslist(&sesslist, TRUE);
|
2009-09-14 03:29:11 +04:00
|
|
|
/* skip sesslist.sessions[0] == Default Settings */
|
2005-04-07 05:36:28 +04:00
|
|
|
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);
|
2015-08-08 19:29:02 +03:00
|
|
|
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);
|
2005-04-07 05:36:28 +04:00
|
|
|
}
|
2009-09-14 03:29:11 +04:00
|
|
|
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);
|
|
|
|
}
|
2005-04-07 05:36:28 +04:00
|
|
|
get_sesslist(&sesslist, FALSE); /* free up */
|
|
|
|
}
|
|
|
|
|
2007-01-06 21:27:00 +03:00
|
|
|
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;
|
2015-08-16 11:41:10 +03:00
|
|
|
#else
|
|
|
|
GdkPixmap *iconpm;
|
|
|
|
GdkBitmap *iconmask;
|
2007-01-06 21:27:00 +03:00
|
|
|
#endif
|
|
|
|
|
|
|
|
if (!n_icon)
|
|
|
|
return;
|
|
|
|
|
|
|
|
gtk_widget_realize(window);
|
2015-08-16 11:41:10 +03:00
|
|
|
#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
|
2015-08-08 17:53:43 +03:00
|
|
|
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);
|
2015-08-16 11:41:10 +03:00
|
|
|
#endif
|
2007-01-06 21:27:00 +03:00
|
|
|
|
|
|
|
#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]));
|
|
|
|
}
|
2015-08-16 11:41:10 +03:00
|
|
|
gtk_window_set_icon_list(GTK_WINDOW(window), iconlist);
|
2007-01-06 21:27:00 +03:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2003-04-05 20:05:00 +04:00
|
|
|
void update_specials_menu(void *frontend)
|
|
|
|
{
|
Rationalisation of the system of frontend handles. Most modular bits
of PuTTY (terminal, backend, logctx etc) take a `void *' handle
passed to them from the frontend, and used as a context for all
their callbacks. Most of these point at the frontend structure
itself (on platforms where this is meaningful), except that the
handle passed to the backend has always pointed at the terminal
because from_backend() was implemented in terminal.c. This has
finally bitten Unix PuTTY, because both backend and logctx have
been passing their respective and very different frontend handles to
logevent(), so I've fixed it.
from_backend() is now a function supplied by the _frontend_ itself,
in all cases, and the frontend handle passed to backends must be the
same as that passed to everything else. What was from_backend() in
terminal.c is now called term_data(), and the typical implementation
of from_backend() in a GUI frontend will just extract the terminal
handle from the frontend structure and delegate to that.
This appears to work on Unix and Windows, but has most likely broken
the Mac build.
[originally from svn r3100]
2003-04-11 22:36:27 +04:00
|
|
|
struct gui_data *inst = (struct gui_data *)frontend;
|
2003-04-05 20:05:00 +04:00
|
|
|
|
|
|
|
const struct telnet_special *specials;
|
|
|
|
|
2004-08-14 17:04:18 +04:00
|
|
|
if (inst->back)
|
|
|
|
specials = inst->back->get_specials(inst->backhandle);
|
|
|
|
else
|
|
|
|
specials = NULL;
|
|
|
|
|
2004-10-18 01:22:22 +04:00
|
|
|
/* I believe this disposes of submenus too. */
|
2003-04-05 20:05:00 +04:00
|
|
|
gtk_container_foreach(GTK_CONTAINER(inst->specialsmenu),
|
|
|
|
(GtkCallback)gtk_widget_destroy, NULL);
|
|
|
|
if (specials) {
|
|
|
|
int i;
|
2004-10-18 01:22:22 +04:00
|
|
|
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 TS_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 TS_EXITMENU:
|
|
|
|
nesting--;
|
|
|
|
if (nesting) {
|
|
|
|
menu = saved_menu; /* XXX lame stacking */
|
|
|
|
saved_menu = NULL;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case TS_SEP:
|
|
|
|
menuitem = gtk_menu_item_new();
|
|
|
|
break;
|
|
|
|
default:
|
2003-04-05 20:05:00 +04:00
|
|
|
menuitem = gtk_menu_item_new_with_label(specials[i].name);
|
2015-08-08 19:29:02 +03:00
|
|
|
g_object_set_data(G_OBJECT(menuitem), "user-data",
|
|
|
|
GINT_TO_POINTER(specials[i].code));
|
|
|
|
g_signal_connect(G_OBJECT(menuitem), "activate",
|
|
|
|
G_CALLBACK(special_menuitem), inst);
|
2004-10-18 01:22:22 +04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (menuitem) {
|
|
|
|
gtk_container_add(GTK_CONTAINER(menu), menuitem);
|
|
|
|
gtk_widget_show(menuitem);
|
|
|
|
}
|
2003-04-05 20:05:00 +04:00
|
|
|
}
|
|
|
|
gtk_widget_show(inst->specialsitem1);
|
|
|
|
gtk_widget_show(inst->specialsitem2);
|
|
|
|
} else {
|
|
|
|
gtk_widget_hide(inst->specialsitem1);
|
|
|
|
gtk_widget_hide(inst->specialsitem2);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2004-08-14 17:04:18 +04:00
|
|
|
static void start_backend(struct gui_data *inst)
|
2002-10-16 18:32:06 +04:00
|
|
|
{
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 22:52:21 +04:00
|
|
|
extern Backend *select_backend(Conf *conf);
|
2004-08-14 17:04:18 +04:00
|
|
|
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;
|
2004-08-14 17:04:18 +04:00
|
|
|
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 22:52:21 +04:00
|
|
|
inst->back = select_backend(inst->conf);
|
2004-08-14 17:04:18 +04:00
|
|
|
|
|
|
|
error = inst->back->init((void *)inst, &inst->backhandle,
|
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,
|
|
|
|
conf_get_str(inst->conf, CONF_host),
|
|
|
|
conf_get_int(inst->conf, CONF_port),
|
|
|
|
&realhost,
|
|
|
|
conf_get_int(inst->conf, CONF_tcp_nodelay),
|
|
|
|
conf_get_int(inst->conf, CONF_tcp_keepalives));
|
2004-08-14 17:04:18 +04:00
|
|
|
|
|
|
|
if (error) {
|
|
|
|
char *msg = dupprintf("Unable to open connection to %s:\n%s",
|
2017-06-10 13:29:21 +03:00
|
|
|
conf_dest(inst->conf), error);
|
2004-08-14 17:04:18 +04:00
|
|
|
inst->exited = TRUE;
|
2017-11-27 22:32:39 +03:00
|
|
|
connection_fatal(inst, msg);
|
2004-08-14 17:04:18 +04:00
|
|
|
sfree(msg);
|
2017-11-27 22:32:39 +03:00
|
|
|
return;
|
2004-08-14 17:04:18 +04:00
|
|
|
}
|
|
|
|
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 22:52:21 +04:00
|
|
|
s = conf_get_str(inst->conf, CONF_wintitle);
|
|
|
|
if (s[0]) {
|
|
|
|
set_title_and_icon(inst, s, s);
|
2004-08-14 17:04:18 +04:00
|
|
|
} 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);
|
2004-08-14 17:04:18 +04:00
|
|
|
sfree(title);
|
|
|
|
}
|
2006-03-15 01:01:27 +03:00
|
|
|
sfree(realhost);
|
|
|
|
|
2004-08-14 17:04:18 +04:00
|
|
|
inst->back->provide_logctx(inst->backhandle, inst->logctx);
|
|
|
|
|
|
|
|
term_provide_resize_fn(inst->term, inst->back->size, inst->backhandle);
|
|
|
|
|
|
|
|
inst->ldisc =
|
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
|
|
|
ldisc_create(inst->conf, inst->term, inst->back, inst->backhandle,
|
2004-08-14 17:04:18 +04:00
|
|
|
inst);
|
|
|
|
|
2009-09-14 03:41:55 +04:00
|
|
|
gtk_widget_set_sensitive(inst->restartitem, FALSE);
|
2004-08-14 17:04:18 +04:00
|
|
|
}
|
|
|
|
|
2017-11-26 11:56:16 +03:00
|
|
|
#if GTK_CHECK_VERSION(2,0,0)
|
2017-03-06 00:46:53 +03:00
|
|
|
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
|
|
|
|
}
|
2017-11-26 11:56:16 +03:00
|
|
|
#endif
|
2017-03-06 00:46:53 +03:00
|
|
|
|
Make the configuration dialog non-modal.
Now every call to do_config_box is replaced with a call to
create_config_box, which returns immediately having constructed the
new GTK window object, and is passed a callback function which it will
arrange to be called when the dialog terminates (whether by OK or by
Cancel). That callback is now what triggers the construction of a
session window after 'Open' is pressed in the initial config box, or
the actual mid-session reconfiguration action after 'Apply' is pressed
in a Change Settings box.
We were already prepared to ignore the re-selection of 'Change
Settings' from the context menu of a window that already had a Change
Settings box open (and not accidentally create a second config box for
the same window); but now we do slightly better, by finding the
existing config box and un-minimising and raising it, in case the user
had forgotten it was there.
That's a useful featurelet, but not the main purpose of this change.
The mani point, of course, is that now the multi-window GtkApplication
based front ends now don't do anything confusing to the nesting of
gtk_main() when config boxes are involved. Whether you're changing the
settings of one (or more than one) of your already-running sessions,
preparing to start up a new PuTTY connection, or both at once, we stay
in the same top-level instance of gtk_main() and all sessions' top-
level callbacks continue to run sensibly.
2017-11-26 14:58:02 +03:00
|
|
|
void new_session_window(Conf *conf, const char *geometry_string)
|
2004-08-14 17:04:18 +04:00
|
|
|
{
|
2002-10-26 16:58:13 +04:00
|
|
|
struct gui_data *inst;
|
2002-10-16 18:32:06 +04:00
|
|
|
|
2017-12-03 17:38:55 +03:00
|
|
|
prepare_session(conf);
|
|
|
|
|
2003-04-12 21:37:15 +04:00
|
|
|
/*
|
|
|
|
* Create an instance structure and initialise to zeroes
|
|
|
|
*/
|
|
|
|
inst = snew(struct gui_data);
|
|
|
|
memset(inst, 0, sizeof(*inst));
|
2017-12-17 23:12:52 +03:00
|
|
|
#ifdef JUST_USE_GTK_CLIPBOARD_UTF8
|
|
|
|
inst->cdi_headtail.next = inst->cdi_headtail.prev = &inst->cdi_headtail;
|
|
|
|
#endif
|
2003-04-12 21:37:15 +04:00
|
|
|
inst->alt_keycode = -1; /* this one needs _not_ to be zero */
|
2005-02-15 20:05:58 +03:00
|
|
|
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;
|
2015-09-25 17:11:44 +03:00
|
|
|
#if GTK_CHECK_VERSION(3,4,0)
|
|
|
|
inst->cumulative_scroll = 0.0;
|
|
|
|
#endif
|
2018-05-17 13:20:01 +03:00
|
|
|
inst->drawing_area_setup_needed = TRUE;
|
2003-04-12 21:37:15 +04:00
|
|
|
|
2016-04-04 13:27:01 +03:00
|
|
|
#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;
|
|
|
|
inst->gravity = ((flags & XNegative ? 1 : 0) |
|
|
|
|
(flags & YNegative ? 2 : 0));
|
|
|
|
}
|
2003-04-12 21:37:15 +04:00
|
|
|
}
|
2016-04-04 13:27:01 +03:00
|
|
|
#endif
|
2003-03-29 22:52:50 +03:00
|
|
|
|
2003-04-11 21:40:52 +04:00
|
|
|
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);
|
2018-03-03 21:18:54 +03:00
|
|
|
if (!clipboard_atom)
|
|
|
|
clipboard_atom = gdk_atom_intern("CLIPBOARD", FALSE);
|
2002-10-14 03:48:31 +04:00
|
|
|
|
2008-03-22 21:11:17 +03:00
|
|
|
inst->area = gtk_drawing_area_new();
|
2017-03-06 00:45:04 +03:00
|
|
|
gtk_widget_set_name(GTK_WIDGET(inst->area), "drawing-area");
|
2008-03-22 21:11:17 +03:00
|
|
|
|
2013-01-14 01:59:10 +04:00
|
|
|
{
|
|
|
|
char *errmsg = setup_fonts_ucs(inst);
|
|
|
|
if (errmsg) {
|
2017-11-27 23:09:54 +03:00
|
|
|
window_setup_error(errmsg);
|
|
|
|
sfree(errmsg);
|
|
|
|
gtk_widget_destroy(inst->area);
|
|
|
|
sfree(inst);
|
|
|
|
return;
|
2013-01-14 01:59:10 +04:00
|
|
|
}
|
|
|
|
}
|
2017-11-27 23:09:54 +03:00
|
|
|
|
|
|
|
#if GTK_CHECK_VERSION(2,0,0)
|
|
|
|
inst->imc = gtk_im_multicontext_new();
|
|
|
|
#endif
|
|
|
|
|
2016-03-24 01:03:46 +03:00
|
|
|
inst->window = make_gtk_toplevel_window(inst);
|
2017-03-06 00:45:04 +03:00
|
|
|
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);
|
2017-03-08 01:57:42 +03:00
|
|
|
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)) {
|
2017-03-08 01:57:42 +03:00
|
|
|
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);
|
2017-03-08 01:57:42 +03:00
|
|
|
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);
|
2017-03-08 01:57:42 +03:00
|
|
|
#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
|
|
|
}
|
2002-10-14 04:05:37 +04:00
|
|
|
|
2002-10-15 18:31:06 +04:00
|
|
|
/*
|
|
|
|
* Set up the colour map.
|
|
|
|
*/
|
2002-10-26 16:58:13 +04:00
|
|
|
palette_reset(inst);
|
2002-10-15 18:31:06 +04:00
|
|
|
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 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);
|
2003-04-10 22:00:50 +04:00
|
|
|
|
2015-09-02 23:37:33 +03:00
|
|
|
init_clipboard(inst);
|
|
|
|
|
2003-04-10 22:00:50 +04:00
|
|
|
inst->sbar_adjust = GTK_ADJUSTMENT(gtk_adjustment_new(0,0,0,0,0,0));
|
|
|
|
inst->sbar = gtk_vscrollbar_new(inst->sbar_adjust);
|
2002-10-13 13:54:36 +04:00
|
|
|
inst->hbox = GTK_BOX(gtk_hbox_new(FALSE, 0));
|
2003-04-10 22:00:50 +04:00
|
|
|
/*
|
|
|
|
* We always create the scrollbar; it remains invisible if
|
|
|
|
* unwanted, so we can pop it up quickly if it suddenly becomes
|
|
|
|
* desirable.
|
|
|
|
*/
|
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(inst->conf, CONF_scrollbar_on_left))
|
2003-04-10 22:00:50 +04:00
|
|
|
gtk_box_pack_start(inst->hbox, inst->sbar, FALSE, FALSE, 0);
|
2002-10-13 16:44:01 +04:00
|
|
|
gtk_box_pack_start(inst->hbox, inst->area, TRUE, TRUE, 0);
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 22:52:21 +04:00
|
|
|
if (!conf_get_int(inst->conf, CONF_scrollbar_on_left))
|
2003-04-10 22:00:50 +04:00
|
|
|
gtk_box_pack_start(inst->hbox, inst->sbar, FALSE, FALSE, 0);
|
2002-10-13 13:54:36 +04:00
|
|
|
|
2002-10-14 04:05:37 +04:00
|
|
|
gtk_container_add(GTK_CONTAINER(inst->window), GTK_WIDGET(inst->hbox));
|
2002-10-07 20:45:23 +04:00
|
|
|
|
2003-04-08 17:49:12 +04:00
|
|
|
gtk_widget_show(inst->area);
|
2016-03-29 15:42:54 +03:00
|
|
|
show_scrollbar(inst, conf_get_int(inst->conf, CONF_scrollbar));
|
2003-04-08 17:49:12 +04:00
|
|
|
gtk_widget_show(GTK_WIDGET(inst->hbox));
|
|
|
|
|
2016-04-04 13:28:34 +03:00
|
|
|
/*
|
|
|
|
* 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);
|
2016-03-29 15:42:54 +03:00
|
|
|
set_geom_hints(inst);
|
|
|
|
|
|
|
|
#if GTK_CHECK_VERSION(3,0,0)
|
2016-04-04 13:24:24 +03:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
2016-03-29 15:42:54 +03:00
|
|
|
#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
|
|
|
|
|
2015-08-08 20:22:05 +03:00
|
|
|
#if GTK_CHECK_VERSION(2,0,0)
|
2016-04-04 13:27:01 +03:00
|
|
|
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;
|
2017-03-06 00:46:53 +03:00
|
|
|
GdkRectangle monitor_geometry;
|
2016-04-04 13:27:01 +03:00
|
|
|
compute_whole_window_size(inst, inst->width, inst->height, &wp, &hp);
|
2017-03-06 00:46:53 +03:00
|
|
|
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);
|
2016-04-04 13:27:01 +03:00
|
|
|
gtk_window_set_gravity(GTK_WINDOW(inst->window),
|
|
|
|
gravities[inst->gravity & 3]);
|
|
|
|
gtk_window_move(GTK_WINDOW(inst->window), x, y);
|
2015-08-08 20:22:05 +03:00
|
|
|
}
|
|
|
|
#else
|
2003-04-08 17:49:12 +04:00
|
|
|
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);
|
|
|
|
}
|
2015-08-08 20:22:05 +03:00
|
|
|
#endif
|
2003-04-08 17:49:12 +04:00
|
|
|
|
2015-08-08 19:29:02 +03:00
|
|
|
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
|
2015-08-16 16:34:19 +03:00
|
|
|
#if GTK_CHECK_VERSION(3,0,0)
|
|
|
|
g_signal_connect(G_OBJECT(inst->area), "draw",
|
|
|
|
G_CALLBACK(draw_area), inst);
|
|
|
|
#else
|
2015-08-08 19:29:02 +03:00
|
|
|
g_signal_connect(G_OBJECT(inst->area), "expose_event",
|
|
|
|
G_CALLBACK(expose_area), inst);
|
2015-08-16 16:34:19 +03:00
|
|
|
#endif
|
2015-08-08 19:29:02 +03:00
|
|
|
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);
|
2008-06-11 00:18:23 +04:00
|
|
|
#if GTK_CHECK_VERSION(2,0,0)
|
2015-08-08 19:29:02 +03:00
|
|
|
g_signal_connect(G_OBJECT(inst->area), "scroll_event",
|
|
|
|
G_CALLBACK(scroll_event), inst);
|
2008-06-11 00:18:23 +04:00
|
|
|
#endif
|
2015-08-08 19:29:02 +03:00
|
|
|
g_signal_connect(G_OBJECT(inst->area), "motion_notify_event",
|
|
|
|
G_CALLBACK(motion_event), inst);
|
2012-06-17 11:26:23 +04:00
|
|
|
#if GTK_CHECK_VERSION(2,0,0)
|
|
|
|
g_signal_connect(G_OBJECT(inst->imc), "commit",
|
|
|
|
G_CALLBACK(input_method_commit_event), inst);
|
|
|
|
#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
|
|
|
if (conf_get_int(inst->conf, CONF_scrollbar))
|
2015-08-08 19:29:02 +03:00
|
|
|
g_signal_connect(G_OBJECT(inst->sbar_adjust), "value_changed",
|
|
|
|
G_CALLBACK(scrollbar_moved), inst);
|
2002-10-07 20:45:23 +04:00
|
|
|
gtk_widget_add_events(GTK_WIDGET(inst->area),
|
2002-10-13 15:24:25 +04:00
|
|
|
GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK |
|
|
|
|
GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
|
2015-09-25 16:09:57 +03:00
|
|
|
GDK_POINTER_MOTION_MASK | GDK_BUTTON_MOTION_MASK
|
|
|
|
#if GTK_CHECK_VERSION(3,4,0)
|
|
|
|
| GDK_SMOOTH_SCROLL_MASK
|
|
|
|
#endif
|
|
|
|
);
|
2002-10-07 20:45:23 +04:00
|
|
|
|
2007-01-06 21:27:00 +03:00
|
|
|
{
|
|
|
|
extern const char *const *const main_icon[];
|
|
|
|
extern const int n_main_icon;
|
|
|
|
set_window_icon(inst->window, main_icon, n_main_icon);
|
|
|
|
}
|
|
|
|
|
2002-10-14 04:05:37 +04:00
|
|
|
gtk_widget_show(inst->window);
|
2002-10-07 20:45:23 +04:00
|
|
|
|
2002-10-26 16:58:13 +04:00
|
|
|
set_window_background(inst);
|
2002-10-25 15:58:59 +04:00
|
|
|
|
2003-04-05 20:05:00 +04:00
|
|
|
/*
|
|
|
|
* Set up the Ctrl+rightclick context menu.
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
GtkWidget *menuitem;
|
|
|
|
char *s;
|
2003-04-12 21:37:15 +04:00
|
|
|
extern const int use_event_log, new_session, saved_sessions;
|
2003-04-05 20:05:00 +04:00
|
|
|
|
|
|
|
inst->menu = gtk_menu_new();
|
|
|
|
|
2011-05-07 14:57:19 +04:00
|
|
|
#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); \
|
2015-08-08 19:29:02 +03:00
|
|
|
g_signal_connect(G_OBJECT(menuitem), "activate", \
|
|
|
|
G_CALLBACK(func), inst); \
|
2011-05-07 14:57:19 +04:00
|
|
|
} 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)
|
|
|
|
|
2003-04-12 21:37:15 +04:00
|
|
|
if (new_session)
|
2009-09-14 03:37:55 +04:00
|
|
|
MKMENUITEM("New Session...", new_session_menuitem);
|
2004-08-14 17:04:18 +04:00
|
|
|
MKMENUITEM("Restart Session", restart_session_menuitem);
|
|
|
|
inst->restartitem = menuitem;
|
2009-09-14 03:41:55 +04:00
|
|
|
gtk_widget_set_sensitive(inst->restartitem, FALSE);
|
2003-04-12 21:37:15 +04:00
|
|
|
MKMENUITEM("Duplicate Session", dup_session_menuitem);
|
|
|
|
if (saved_sessions) {
|
|
|
|
inst->sessionsmenu = gtk_menu_new();
|
2005-04-07 05:36:28 +04:00
|
|
|
/* 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);
|
2003-04-12 21:37:15 +04:00
|
|
|
gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem),
|
|
|
|
inst->sessionsmenu);
|
|
|
|
}
|
2011-05-07 14:57:19 +04:00
|
|
|
MKSEP();
|
2009-09-14 03:37:55 +04:00
|
|
|
MKMENUITEM("Change Settings...", change_settings_menuitem);
|
2011-05-07 14:57:19 +04:00
|
|
|
MKSEP();
|
2003-04-09 22:46:45 +04:00
|
|
|
if (use_event_log)
|
|
|
|
MKMENUITEM("Event Log", event_log_menuitem);
|
2011-05-07 14:57:19 +04:00
|
|
|
MKSUBMENU("Special Commands");
|
2003-04-05 20:05:00 +04:00
|
|
|
inst->specialsmenu = gtk_menu_new();
|
|
|
|
gtk_menu_item_set_submenu(GTK_MENU_ITEM(menuitem), inst->specialsmenu);
|
|
|
|
inst->specialsitem1 = menuitem;
|
2011-05-07 14:57:19 +04:00
|
|
|
MKSEP();
|
2003-04-05 20:05:00 +04:00
|
|
|
inst->specialsitem2 = menuitem;
|
2004-10-17 18:44:27 +04:00
|
|
|
gtk_widget_hide(inst->specialsitem1);
|
|
|
|
gtk_widget_hide(inst->specialsitem2);
|
2003-04-05 20:05:00 +04:00
|
|
|
MKMENUITEM("Clear Scrollback", clear_scrollback_menuitem);
|
|
|
|
MKMENUITEM("Reset Terminal", reset_terminal_menuitem);
|
2017-12-10 19:25:54 +03:00
|
|
|
MKSEP();
|
2017-12-17 23:35:45 +03:00
|
|
|
MKMENUITEM("Copy to " CLIPNAME_EXPLICIT_OBJECT,
|
|
|
|
copy_clipboard_menuitem);
|
|
|
|
MKMENUITEM("Paste from " CLIPNAME_EXPLICIT_OBJECT,
|
|
|
|
paste_clipboard_menuitem);
|
2003-04-11 21:59:36 +04:00
|
|
|
MKMENUITEM("Copy All", copy_all_menuitem);
|
2011-05-07 14:57:19 +04:00
|
|
|
MKSEP();
|
2003-04-05 20:05:00 +04:00
|
|
|
s = dupcat("About ", appname, NULL);
|
|
|
|
MKMENUITEM(s, about_menuitem);
|
|
|
|
sfree(s);
|
|
|
|
#undef MKMENUITEM
|
2011-05-07 14:57:19 +04:00
|
|
|
#undef MKSUBMENU
|
|
|
|
#undef MKSEP
|
2003-04-05 20:05:00 +04:00
|
|
|
}
|
|
|
|
|
2002-10-26 16:58:13 +04:00
|
|
|
inst->textcursor = make_mouse_ptr(inst, GDK_XTERM);
|
|
|
|
inst->rawcursor = make_mouse_ptr(inst, GDK_LEFT_PTR);
|
2005-02-15 20:05:58 +03:00
|
|
|
inst->waitcursor = make_mouse_ptr(inst, GDK_WATCH);
|
2002-10-26 16:58:13 +04:00
|
|
|
inst->blankcursor = make_mouse_ptr(inst, -1);
|
2002-10-14 13:58:27 +04:00
|
|
|
inst->currcursor = inst->textcursor;
|
2002-10-26 16:58:13 +04:00
|
|
|
show_mouseptr(inst, 1);
|
2002-10-10 14:40:30 +04:00
|
|
|
|
2003-04-09 22:46:45 +04:00
|
|
|
inst->eventlogstuff = eventlogstuff_new();
|
|
|
|
|
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->term = term_init(inst->conf, &inst->ucsdata, inst);
|
2017-12-17 21:44:27 +03:00
|
|
|
setup_clipboards(inst, inst->term, 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
|
|
|
inst->logctx = log_init(inst, inst->conf);
|
2002-10-26 16:58:13 +04:00
|
|
|
term_provide_logctx(inst->term, inst->logctx);
|
2002-10-22 20:11:33 +04:00
|
|
|
|
Post-release destabilisation! Completely remove the struct type
'Config' in putty.h, which stores all PuTTY's settings and includes an
arbitrary length limit on every single one of those settings which is
stored in string form. In place of it is 'Conf', an opaque data type
everywhere outside the new file conf.c, which stores a list of (key,
value) pairs in which every key contains an integer identifying a
configuration setting, and for some of those integers the key also
contains extra parts (so that, for instance, CONF_environmt is a
string-to-string mapping). Everywhere that a Config was previously
used, a Conf is now; everywhere there was a Config structure copy,
conf_copy() is called; every lookup, adjustment, load and save
operation on a Config has been rewritten; and there's a mechanism for
serialising a Conf into a binary blob and back for use with Duplicate
Session.
User-visible effects of this change _should_ be minimal, though I
don't doubt I've introduced one or two bugs here and there which will
eventually be found. The _intended_ visible effects of this change are
that all arbitrary limits on configuration strings and lists (e.g.
limit on number of port forwardings) should now disappear; that list
boxes in the configuration will now be displayed in a sorted order
rather than the arbitrary order in which they were added to the list
(since the underlying data structure is now a sorted tree234 rather
than an ad-hoc comma-separated string); and one more specific change,
which is that local and dynamic port forwardings on the same port
number are now mutually exclusive in the configuration (putting 'D' in
the key rather than the value was a mistake in the first place).
One other reorganisation as a result of this is that I've moved all
the dialog.c standard handlers (dlg_stdeditbox_handler and friends)
out into config.c, because I can't really justify calling them generic
any more. When they took a pointer to an arbitrary structure type and
the offset of a field within that structure, they were independent of
whether that structure was a Config or something completely different,
but now they really do expect to talk to a Conf, which can _only_ be
used for PuTTY configuration, so I've renamed them all things like
conf_editbox_handler and moved them out of the nominally independent
dialog-box management module into the PuTTY-specific config.c.
[originally from svn r9214]
2011-07-14 22:52:21 +04:00
|
|
|
term_size(inst->term, inst->height, inst->width,
|
|
|
|
conf_get_int(inst->conf, CONF_savelines));
|
2003-04-01 22:10:25 +04:00
|
|
|
|
2017-11-27 22:32:39 +03:00
|
|
|
inst->exited = FALSE;
|
2002-10-15 16:29:52 +04:00
|
|
|
|
2017-11-27 22:32:39 +03:00
|
|
|
start_backend(inst);
|
2002-10-15 16:29:52 +04:00
|
|
|
|
2017-11-27 22:32:39 +03:00
|
|
|
if (inst->ldisc) /* early backend failure might make this NULL already */
|
|
|
|
ldisc_echoedit_update(inst->ldisc); /* cause ldisc to notice changes */
|
2002-10-07 20:45:23 +04:00
|
|
|
}
|