mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-09 01:18:00 +00:00
Centralise palette setup into terminal.c.
Now terminal.c makes nearly all the decisions about what the colour palette should actually contain: it does the job of reading the GUI-configurable colours out of Conf, and also the job of making up the rest of the xterm-256 palette. The only exception is that TermWin can provide a method to override some of the default colours, which on Windows is used to implement the 'Use system colours' config option. This saves code overall, partly because the front ends don't have to be able to send palette data back to the Terminal any more (the Terminal keeps the master copy and can answer palette-query escape sequences from its own knowledge), and also because now there's only one copy of the xterm-256 palette setup code (previously gtkwin.c and window.c each had their own version of it). In this rewrite, I've also introduced a multi-layered storage system for the palette data in Terminal. One layer contains the palette information derived from Conf; the next contains platform overrides (currently just Windows's 'Use system colours'); the last one contains overrides set by escape sequences in the middle of the session. The topmost two layers can each _conditionally_ override the ones below. As a result, if a server-side application manually resets (say) the default fg and bg colours in mid-session to something that works well in a particular application, those changes won't be wiped out by a change in the Windows system colours or the Conf, which they would have been before. Instead, changes in Conf or the system colours alter the lower layers of the structure, but then when palette_rebuild is called, the upper layer continues to override them, until a palette reset (ESC]R) or terminal reset (e.g. ESC c) removes those upper-layer changes. This seems like a more consistent strategy, in that the same set of configuration settings will produce the same end result regardless of what order they were applied in. The palette-related methods in TermWin have had a total rework. palette_get and palette_reset are both gone; palette_set can now set a contiguous range of colours in one go; and the new palette_get_overrides replaces window.c's old systopalette().
This commit is contained in:
parent
cd32ef8733
commit
ca9cd983e1
10
fuzzterm.c
10
fuzzterm.c
@ -91,10 +91,9 @@ static void fuzz_set_minimised(TermWin *tw, bool minimised) {}
|
||||
static void fuzz_set_maximised(TermWin *tw, bool maximised) {}
|
||||
static void fuzz_move(TermWin *tw, int x, int y) {}
|
||||
static void fuzz_set_zorder(TermWin *tw, bool top) {}
|
||||
static bool fuzz_palette_get(TermWin *tw, unsigned n, int *r, int *g, int *b)
|
||||
{ return false; }
|
||||
static void fuzz_palette_set(TermWin *tw, unsigned n, int r, int g, int b) {}
|
||||
static void fuzz_palette_reset(TermWin *tw) {}
|
||||
static void fuzz_palette_set(TermWin *tw, unsigned start, unsigned ncolours,
|
||||
const rgb *colours) {}
|
||||
static void fuzz_palette_get_overrides(TermWin *tw) {}
|
||||
static void fuzz_get_pos(TermWin *tw, int *x, int *y) { *x = *y = 0; }
|
||||
static void fuzz_get_pixels(TermWin *tw, int *x, int *y) { *x = *y = 0; }
|
||||
|
||||
@ -119,9 +118,8 @@ static const TermWinVtable fuzz_termwin_vt = {
|
||||
.set_maximised = fuzz_set_maximised,
|
||||
.move = fuzz_move,
|
||||
.set_zorder = fuzz_set_zorder,
|
||||
.palette_get = fuzz_palette_get,
|
||||
.palette_set = fuzz_palette_set,
|
||||
.palette_reset = fuzz_palette_reset,
|
||||
.palette_get_overrides = fuzz_palette_get_overrides,
|
||||
.get_pos = fuzz_get_pos,
|
||||
.get_pixels = fuzz_get_pixels,
|
||||
};
|
||||
|
37
putty.h
37
putty.h
@ -63,9 +63,9 @@
|
||||
* Since the OSC 4 encoding contains the full set of colours used in
|
||||
* the terminal display, that's the encoding used by front ends to
|
||||
* store any actual data associated with their palette entries. So the
|
||||
* TermWin palette_{set,get} methods use that encoding, and so does
|
||||
* the bitwise encoding of attribute words used in terminal redraw
|
||||
* operations.
|
||||
* TermWin palette_set and palette_get_overrides methods use that
|
||||
* encoding, and so does the bitwise encoding of attribute words used
|
||||
* in terminal redraw operations.
|
||||
*
|
||||
* The Conf encoding, of course, is used by config.c and settings.c.
|
||||
*
|
||||
@ -1204,6 +1204,10 @@ bool console_set_trust_status(Seat *seat, bool trusted);
|
||||
int filexfer_get_userpass_input(Seat *seat, prompts_t *p, bufchain *input);
|
||||
bool cmdline_seat_verbose(Seat *seat);
|
||||
|
||||
typedef struct rgb {
|
||||
uint8_t r, g, b;
|
||||
} rgb;
|
||||
|
||||
/*
|
||||
* Data type 'TermWin', which is a vtable encapsulating all the
|
||||
* functionality that Terminal expects from its containing terminal
|
||||
@ -1268,10 +1272,16 @@ struct TermWinVtable {
|
||||
void (*move)(TermWin *, int x, int y);
|
||||
void (*set_zorder)(TermWin *, bool top);
|
||||
|
||||
/* Palette-handling functions. Palette indices are in OSC 4 encoding. */
|
||||
bool (*palette_get)(TermWin *, unsigned n, int *r, int *g, int *b);
|
||||
void (*palette_set)(TermWin *, unsigned n, int r, int g, int b);
|
||||
void (*palette_reset)(TermWin *);
|
||||
/* Set the colour palette that the TermWin will use to display
|
||||
* text. One call to this function sets 'ncolours' consecutive
|
||||
* colours in the OSC 4 sequence, starting at 'start'. */
|
||||
void (*palette_set)(TermWin *, unsigned start, unsigned ncolours,
|
||||
const rgb *colours);
|
||||
|
||||
/* Query the front end for any OS-local overrides to the default
|
||||
* colours stored in Conf. The front end should set any it cares
|
||||
* about by calling term_palette_override. */
|
||||
void (*palette_get_overrides)(TermWin *);
|
||||
|
||||
void (*get_pos)(TermWin *, int *x, int *y);
|
||||
void (*get_pixels)(TermWin *, int *x, int *y);
|
||||
@ -1325,12 +1335,11 @@ static inline void win_move(TermWin *win, int x, int y)
|
||||
{ win->vt->move(win, x, y); }
|
||||
static inline void win_set_zorder(TermWin *win, bool top)
|
||||
{ win->vt->set_zorder(win, top); }
|
||||
static inline bool win_palette_get(TermWin *win, unsigned n,
|
||||
int *r, int *g, int *b) { return win->vt->palette_get(win, n, r, g, b); }
|
||||
static inline void win_palette_set(TermWin *win, unsigned n,
|
||||
int r, int g, int b) { win->vt->palette_set(win, n, r, g, b); }
|
||||
static inline void win_palette_reset(TermWin *win)
|
||||
{ win->vt->palette_reset(win); }
|
||||
static inline void win_palette_set(
|
||||
TermWin *win, unsigned start, unsigned ncolours, const rgb *colours)
|
||||
{ win->vt->palette_set(win, start, ncolours, colours); }
|
||||
static inline void win_palette_get_overrides(TermWin *win)
|
||||
{ win->vt->palette_get_overrides(win); }
|
||||
static inline void win_get_pos(TermWin *win, int *x, int *y)
|
||||
{ win->vt->get_pos(win, x, y); }
|
||||
static inline void win_get_pixels(TermWin *win, int *x, int *y)
|
||||
@ -1763,6 +1772,8 @@ void term_keyinputw(Terminal *, const wchar_t * widebuf, int len);
|
||||
void term_get_cursor_position(Terminal *term, int *x, int *y);
|
||||
void term_setup_window_titles(Terminal *term, const char *title_hostname);
|
||||
void term_notify_minimised(Terminal *term, bool minimised);
|
||||
void term_notify_palette_overrides_changed(Terminal *term);
|
||||
void term_palette_override(Terminal *term, unsigned osc4_index, rgb rgb);
|
||||
|
||||
typedef enum SmallKeypadKey {
|
||||
SKK_HOME, SKK_END, SKK_INSERT, SKK_DELETE, SKK_PGUP, SKK_PGDN,
|
||||
|
147
terminal.c
147
terminal.c
@ -1716,6 +1716,113 @@ void term_setup_window_titles(Terminal *term, const char *title_hostname)
|
||||
win_set_icon_title(term->win, term->icon_title);
|
||||
}
|
||||
|
||||
static void palette_rebuild(Terminal *term)
|
||||
{
|
||||
unsigned min_changed = OSC4_NCOLOURS, max_changed = 0;
|
||||
|
||||
for (unsigned i = 0; i < OSC4_NCOLOURS; i++) {
|
||||
rgb new_value;
|
||||
bool found = false;
|
||||
|
||||
for (unsigned j = lenof(term->subpalettes); j-- > 0 ;) {
|
||||
if (term->subpalettes[j].present[i]) {
|
||||
new_value = term->subpalettes[j].values[i];
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assert(found); /* we expect SUBPAL_CONF to always be set */
|
||||
|
||||
if (new_value.r != term->palette[i].r ||
|
||||
new_value.g != term->palette[i].g ||
|
||||
new_value.b != term->palette[i].b) {
|
||||
term->palette[i] = new_value;
|
||||
if (min_changed > i)
|
||||
min_changed = i;
|
||||
if (max_changed < i)
|
||||
max_changed = i;
|
||||
}
|
||||
}
|
||||
|
||||
if (min_changed <= max_changed) {
|
||||
/*
|
||||
* At least one colour changed, so pass the result back to the
|
||||
* TermWin. This also requires invalidating the rest of the
|
||||
* window, because usually all the text will need redrawing in
|
||||
* the new colours.
|
||||
*/
|
||||
win_palette_set(term->win, min_changed, max_changed - min_changed + 1,
|
||||
term->palette + min_changed);
|
||||
term_invalidate(term);
|
||||
term_schedule_update(term);
|
||||
}
|
||||
}
|
||||
|
||||
static void palette_reset(Terminal *term, bool overrides_only)
|
||||
{
|
||||
if (!overrides_only) {
|
||||
for (unsigned i = 0; i < OSC4_NCOLOURS; i++)
|
||||
term->subpalettes[SUBPAL_CONF].present[i] = true;
|
||||
|
||||
/*
|
||||
* Copy all the palette information out of the Conf.
|
||||
*/
|
||||
for (unsigned i = 0; i < CONF_NCOLOURS; i++) {
|
||||
rgb *col = &term->subpalettes[SUBPAL_CONF].values[
|
||||
colour_indices_conf_to_osc4[i]];
|
||||
col->r = conf_get_int_int(term->conf, CONF_colours, i*3+0);
|
||||
col->g = conf_get_int_int(term->conf, CONF_colours, i*3+1);
|
||||
col->b = conf_get_int_int(term->conf, CONF_colours, i*3+2);
|
||||
}
|
||||
|
||||
/*
|
||||
* Directly invent the rest of the xterm-256 colours.
|
||||
*/
|
||||
for (unsigned i = 0; i < 216; i++) {
|
||||
rgb *col = &term->subpalettes[SUBPAL_CONF].values[i + 16];
|
||||
int r = i / 36, g = (i / 6) % 6, b = i % 6;
|
||||
col->r = r ? r * 40 + 55 : 0;
|
||||
col->g = g ? g * 40 + 55 : 0;
|
||||
col->b = b ? b * 40 + 55 : 0;
|
||||
}
|
||||
for (unsigned i = 0; i < 24; i++) {
|
||||
rgb *col = &term->subpalettes[SUBPAL_CONF].values[i + 232];
|
||||
int shade = i * 10 + 8;
|
||||
col->r = col->g = col->b = shade;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get rid of all escape-sequence configuration.
|
||||
*/
|
||||
for (unsigned i = 0; i < OSC4_NCOLOURS; i++)
|
||||
term->subpalettes[SUBPAL_SESSION].present[i] = false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Re-fetch any OS-local overrides.
|
||||
*/
|
||||
for (unsigned i = 0; i < OSC4_NCOLOURS; i++)
|
||||
term->subpalettes[SUBPAL_PLATFORM].present[i] = false;
|
||||
win_palette_get_overrides(term->win);
|
||||
|
||||
/*
|
||||
* Rebuild the composite palette.
|
||||
*/
|
||||
palette_rebuild(term);
|
||||
}
|
||||
|
||||
void term_palette_override(Terminal *term, unsigned osc4_index, rgb rgb)
|
||||
{
|
||||
/*
|
||||
* We never expect to be called except as re-entry from our own
|
||||
* call to win_palette_get_overrides above, so we need not mess
|
||||
* about calling palette_rebuild.
|
||||
*/
|
||||
term->subpalettes[SUBPAL_PLATFORM].present[osc4_index] = true;
|
||||
term->subpalettes[SUBPAL_PLATFORM].values[osc4_index] = rgb;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialise the terminal.
|
||||
*/
|
||||
@ -1812,6 +1919,8 @@ Terminal *term_init(Conf *myconf, struct unicode_data *ucsdata, TermWin *win)
|
||||
term->icon_title = dupstr("");
|
||||
term->minimised = false;
|
||||
|
||||
palette_reset(term, false);
|
||||
|
||||
return term;
|
||||
}
|
||||
|
||||
@ -2877,15 +2986,14 @@ static void do_osc(Terminal *term)
|
||||
break;
|
||||
case 4:
|
||||
if (term->ldisc && !strcmp(term->osc_string, "?")) {
|
||||
int r, g, b;
|
||||
if (win_palette_get(term->win, toint(term->esc_args[1]),
|
||||
&r, &g, &b)) {
|
||||
unsigned index = term->esc_args[1];
|
||||
if (index < OSC4_NCOLOURS) {
|
||||
rgb colour = term->palette[index];
|
||||
char *reply_buf = dupprintf(
|
||||
"\033]4;%u;rgb:%04x/%04x/%04x\007",
|
||||
term->esc_args[1],
|
||||
(unsigned)r * 0x0101,
|
||||
(unsigned)g * 0x0101,
|
||||
(unsigned)b * 0x0101);
|
||||
"\033]4;%u;rgb:%04x/%04x/%04x\007", index,
|
||||
(unsigned)colour.r * 0x0101,
|
||||
(unsigned)colour.g * 0x0101,
|
||||
(unsigned)colour.b * 0x0101);
|
||||
ldisc_send(term->ldisc, reply_buf, strlen(reply_buf),
|
||||
false);
|
||||
sfree(reply_buf);
|
||||
@ -4788,7 +4896,7 @@ static void term_out(Terminal *term)
|
||||
term->osc_strlen = 0;
|
||||
break;
|
||||
case 'R': /* Linux palette reset */
|
||||
win_palette_reset(term->win);
|
||||
palette_reset(term, false);
|
||||
term_invalidate(term);
|
||||
term->termstate = TOPLEVEL;
|
||||
break;
|
||||
@ -4890,12 +4998,16 @@ static void term_out(Terminal *term)
|
||||
unsigned osc4_index =
|
||||
colour_indices_oscp_to_osc4[oscp_index];
|
||||
|
||||
win_palette_set(
|
||||
term->win, osc4_index,
|
||||
term->osc_string[1] * 16 + term->osc_string[2],
|
||||
term->osc_string[3] * 16 + term->osc_string[4],
|
||||
term->osc_string[5] * 16 + term->osc_string[6]);
|
||||
term_invalidate(term);
|
||||
rgb *value = &term->subpalettes[SUBPAL_SESSION].values[
|
||||
osc4_index];
|
||||
value->r = term->osc_string[1] * 16 + term->osc_string[2];
|
||||
value->g = term->osc_string[3] * 16 + term->osc_string[4];
|
||||
value->b = term->osc_string[5] * 16 + term->osc_string[6];
|
||||
term->subpalettes[SUBPAL_SESSION].present[
|
||||
osc4_index] = true;
|
||||
|
||||
palette_rebuild(term);
|
||||
|
||||
term->termstate = TOPLEVEL;
|
||||
}
|
||||
break;
|
||||
@ -7349,3 +7461,8 @@ void term_notify_minimised(Terminal *term, bool minimised)
|
||||
{
|
||||
term->minimised = minimised;
|
||||
}
|
||||
|
||||
void term_notify_palette_overrides_changed(Terminal *term)
|
||||
{
|
||||
palette_reset(term, true);
|
||||
}
|
||||
|
15
terminal.h
15
terminal.h
@ -345,6 +345,21 @@ struct terminal_tag {
|
||||
|
||||
char *window_title, *icon_title;
|
||||
bool minimised;
|
||||
|
||||
/* Multi-layered colour palette. The colours from Conf (plus the
|
||||
* default xterm-256 ones that don't have Conf ids at all) have
|
||||
* lowest priority, followed by platform overrides if any,
|
||||
* followed by escape-sequence overrides during the session. */
|
||||
struct term_subpalette {
|
||||
rgb values[OSC4_NCOLOURS];
|
||||
bool present[OSC4_NCOLOURS];
|
||||
} subpalettes[3];
|
||||
#define SUBPAL_CONF 0
|
||||
#define SUBPAL_PLATFORM 1
|
||||
#define SUBPAL_SESSION 2
|
||||
|
||||
/* The composite palette that we make out of the above */
|
||||
rgb palette[OSC4_NCOLOURS];
|
||||
};
|
||||
|
||||
static inline bool in_utf(Terminal *term)
|
||||
|
145
unix/gtkwin.c
145
unix/gtkwin.c
@ -2518,26 +2518,6 @@ static void gtkwin_request_resize(TermWin *tw, int w, int h)
|
||||
|
||||
}
|
||||
|
||||
static void real_palette_set(GtkFrontend *inst, unsigned n,
|
||||
int r, int g, int b)
|
||||
{
|
||||
inst->cols[n].red = r * 0x0101;
|
||||
inst->cols[n].green = g * 0x0101;
|
||||
inst->cols[n].blue = b * 0x0101;
|
||||
|
||||
#if !GTK_CHECK_VERSION(3,0,0)
|
||||
{
|
||||
gboolean success[1];
|
||||
gdk_colormap_free_colors(inst->colmap, inst->cols + n, 1);
|
||||
gdk_colormap_alloc_colors(inst->colmap, inst->cols + n, 1,
|
||||
false, true, success);
|
||||
if (!success[0])
|
||||
g_error("%s: couldn't allocate colour %d (#%02x%02x%02x)\n",
|
||||
appname, n, r, g, b);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if GTK_CHECK_VERSION(3,0,0)
|
||||
char *colour_to_css(const GdkColor *col)
|
||||
{
|
||||
@ -2581,36 +2561,13 @@ void set_window_background(GtkFrontend *inst)
|
||||
set_gtk_widget_background(GTK_WIDGET(inst->window), &inst->cols[258]);
|
||||
}
|
||||
|
||||
static void gtkwin_palette_set(TermWin *tw, unsigned n, int r, int g, int b)
|
||||
static void gtkwin_palette_set(TermWin *tw, unsigned start, unsigned ncolours,
|
||||
const rgb *colours)
|
||||
{
|
||||
GtkFrontend *inst = container_of(tw, GtkFrontend, termwin);
|
||||
if (n >= OSC4_NCOLOURS)
|
||||
return;
|
||||
real_palette_set(inst, n, r, g, b);
|
||||
if (n == OSC4_COLOUR_bg) {
|
||||
/* Default Background changed. Ensure space between text area and
|
||||
* window border is redrawn */
|
||||
set_window_background(inst);
|
||||
draw_backing_rect(inst);
|
||||
gtk_widget_queue_draw(inst->area);
|
||||
}
|
||||
}
|
||||
|
||||
static bool gtkwin_palette_get(TermWin *tw, unsigned n, int *r, int *g, int *b)
|
||||
{
|
||||
GtkFrontend *inst = container_of(tw, GtkFrontend, termwin);
|
||||
if (n >= OSC4_NCOLOURS)
|
||||
return false;
|
||||
*r = inst->cols[n].red >> 8;
|
||||
*g = inst->cols[n].green >> 8;
|
||||
*b = inst->cols[n].blue >> 8;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void gtkwin_palette_reset(TermWin *tw)
|
||||
{
|
||||
GtkFrontend *inst = container_of(tw, GtkFrontend, termwin);
|
||||
int i;
|
||||
assert(start <= OSC4_NCOLOURS);
|
||||
assert(ncolours <= OSC4_NCOLOURS - start);
|
||||
|
||||
#if !GTK_CHECK_VERSION(3,0,0)
|
||||
if (!inst->colmap) {
|
||||
@ -2620,37 +2577,24 @@ static void gtkwin_palette_reset(TermWin *tw)
|
||||
}
|
||||
#endif
|
||||
|
||||
for (i = 0; i < CONF_NCOLOURS; i++) {
|
||||
int w = colour_indices_conf_to_osc4[i];
|
||||
inst->cols[w].red =
|
||||
conf_get_int_int(inst->conf, CONF_colours, i*3+0) * 0x0101;
|
||||
inst->cols[w].green =
|
||||
conf_get_int_int(inst->conf, CONF_colours, i*3+1) * 0x0101;
|
||||
inst->cols[w].blue =
|
||||
conf_get_int_int(inst->conf, CONF_colours, i*3+2) * 0x0101;
|
||||
}
|
||||
for (unsigned i = 0; i < ncolours; i++) {
|
||||
const rgb *in = &colours[i];
|
||||
GdkColor *out = &inst->cols[start + i];
|
||||
|
||||
for (i = 0; i < 216; i++) {
|
||||
int r = i / 36, g = (i / 6) % 6, b = i % 6;
|
||||
inst->cols[i+16].red = r ? r * 0x2828 + 0x3737 : 0;
|
||||
inst->cols[i+16].green = g ? g * 0x2828 + 0x3737 : 0;
|
||||
inst->cols[i+16].blue = b ? b * 0x2828 + 0x3737 : 0;
|
||||
}
|
||||
for (i = 0; i < 24; i++) {
|
||||
int shade = i * 0x0a0a + 0x0808;
|
||||
inst->cols[i+232].red = inst->cols[i+232].green =
|
||||
inst->cols[i+232].blue = shade;
|
||||
out->red = in->r * 0x0101;
|
||||
out->green = in->g * 0x0101;
|
||||
out->blue = in->b * 0x0101;
|
||||
}
|
||||
|
||||
#if !GTK_CHECK_VERSION(3,0,0)
|
||||
{
|
||||
gboolean success[OSC4_NCOLOURS];
|
||||
gdk_colormap_alloc_colors(inst->colmap, inst->cols, OSC4_NCOLOURS,
|
||||
false, true, success);
|
||||
for (i = 0; i < OSC4_NCOLOURS; i++) {
|
||||
gdk_colormap_alloc_colors(inst->colmap + start, inst->cols + start,
|
||||
ncolours, false, true, success);
|
||||
for (unsigned i = 0; i < ncolours; i++) {
|
||||
if (!success[i])
|
||||
g_error("%s: couldn't allocate colour %d (#%02x%02x%02x)\n",
|
||||
appname, i,
|
||||
appname, start + 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));
|
||||
@ -2658,15 +2602,24 @@ static void gtkwin_palette_reset(TermWin *tw)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Since Default Background may have changed, ensure that space
|
||||
* between text area and window border is refreshed. */
|
||||
set_window_background(inst);
|
||||
if (inst->area && gtk_widget_get_window(inst->area)) {
|
||||
draw_backing_rect(inst);
|
||||
gtk_widget_queue_draw(inst->area);
|
||||
if (start <= OSC4_COLOUR_bg && OSC4_COLOUR_bg < start + ncolours) {
|
||||
/* Default Background has changed, so ensure that space between text
|
||||
* area and window border is refreshed. */
|
||||
set_window_background(inst);
|
||||
if (inst->area && gtk_widget_get_window(inst->area)) {
|
||||
draw_backing_rect(inst);
|
||||
gtk_widget_queue_draw(inst->area);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void gtkwin_palette_get_overrides(TermWin *tw)
|
||||
{
|
||||
/* GTK has no analogue of Windows's 'standard system colours', so GTK PuTTY
|
||||
* has no config option to override the normally configured colours from
|
||||
* it */
|
||||
}
|
||||
|
||||
static struct clipboard_state *clipboard_from_atom(
|
||||
GtkFrontend *inst, GdkAtom atom)
|
||||
{
|
||||
@ -4616,7 +4569,6 @@ static void after_change_settings_dialog(void *vctx, int retval)
|
||||
*(struct after_change_settings_dialog_ctx *)vctx;
|
||||
GtkFrontend *inst = ctx.inst;
|
||||
Conf *oldconf = inst->conf, *newconf = ctx.newconf;
|
||||
int i, j;
|
||||
bool need_size;
|
||||
|
||||
sfree(vctx); /* we've copied this already */
|
||||
@ -4645,37 +4597,6 @@ static void after_change_settings_dialog(void *vctx, int retval)
|
||||
|
||||
cache_conf_values(inst);
|
||||
|
||||
/*
|
||||
* Just setting inst->conf is sufficient to cause colour
|
||||
* setting changes to appear on the next ESC]R palette
|
||||
* reset. But we should also check whether any colour
|
||||
* settings have been changed, and revert the ones that have
|
||||
* to the new default, on the assumption that the user is
|
||||
* most likely to want an immediate update.
|
||||
*/
|
||||
for (i = 0; i < CONF_NCOLOURS; i++) {
|
||||
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, colour_indices_conf_to_osc4[i],
|
||||
conf_get_int_int(newconf,CONF_colours,i*3+0),
|
||||
conf_get_int_int(newconf,CONF_colours,i*3+1),
|
||||
conf_get_int_int(newconf,CONF_colours,i*3+2));
|
||||
|
||||
/*
|
||||
* If the default background has changed, we must
|
||||
* repaint the space in between the window border
|
||||
* and the text area.
|
||||
*/
|
||||
if (i == CONF_COLOUR_bg) {
|
||||
set_window_background(inst);
|
||||
draw_backing_rect(inst);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
need_size = false;
|
||||
|
||||
/*
|
||||
@ -5130,9 +5051,8 @@ static const TermWinVtable gtk_termwin_vt = {
|
||||
.set_maximised = gtkwin_set_maximised,
|
||||
.move = gtkwin_move,
|
||||
.set_zorder = gtkwin_set_zorder,
|
||||
.palette_get = gtkwin_palette_get,
|
||||
.palette_set = gtkwin_palette_set,
|
||||
.palette_reset = gtkwin_palette_reset,
|
||||
.palette_get_overrides = gtkwin_palette_get_overrides,
|
||||
.get_pos = gtkwin_get_pos,
|
||||
.get_pixels = gtkwin_get_pixels,
|
||||
};
|
||||
@ -5243,11 +5163,6 @@ void new_session_window(Conf *conf, const char *geometry_string)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up the colour map.
|
||||
*/
|
||||
win_palette_reset(&inst->termwin);
|
||||
|
||||
inst->width = conf_get_int(inst->conf, CONF_width);
|
||||
inst->height = conf_get_int(inst->conf, CONF_height);
|
||||
cache_conf_values(inst);
|
||||
|
289
windows/window.c
289
windows/window.c
@ -92,8 +92,6 @@ static void show_mouseptr(bool show);
|
||||
static LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
|
||||
static int TranslateKey(UINT message, WPARAM wParam, LPARAM lParam,
|
||||
unsigned char *output);
|
||||
static void conftopalette(void);
|
||||
static void systopalette(void);
|
||||
static void init_palette(void);
|
||||
static void init_fonts(int, int);
|
||||
static void another_font(int);
|
||||
@ -190,12 +188,10 @@ static enum {
|
||||
static int descent, font_strikethrough_y;
|
||||
|
||||
static COLORREF colours[OSC4_NCOLOURS];
|
||||
static struct rgb {
|
||||
int r, g, b;
|
||||
} colours_rgb[OSC4_NCOLOURS];
|
||||
static HPALETTE pal;
|
||||
static LPLOGPALETTE logpal;
|
||||
static RGBTRIPLE defpal[OSC4_NCOLOURS];
|
||||
bool tried_pal = false;
|
||||
COLORREF colorref_modifier = 0;
|
||||
|
||||
static HBITMAP caretbm;
|
||||
|
||||
@ -244,9 +240,8 @@ static void wintw_set_minimised(TermWin *, bool minimised);
|
||||
static void wintw_set_maximised(TermWin *, bool maximised);
|
||||
static void wintw_move(TermWin *, int x, int y);
|
||||
static void wintw_set_zorder(TermWin *, bool top);
|
||||
static bool wintw_palette_get(TermWin *, unsigned n, int *r, int *g, int *b);
|
||||
static void wintw_palette_set(TermWin *, unsigned n, int r, int g, int b);
|
||||
static void wintw_palette_reset(TermWin *);
|
||||
static void wintw_palette_set(TermWin *, unsigned, unsigned, const rgb *);
|
||||
static void wintw_palette_get_overrides(TermWin *);
|
||||
static void wintw_get_pos(TermWin *, int *x, int *y);
|
||||
static void wintw_get_pixels(TermWin *, int *x, int *y);
|
||||
|
||||
@ -271,9 +266,8 @@ static const TermWinVtable windows_termwin_vt = {
|
||||
.set_maximised = wintw_set_maximised,
|
||||
.move = wintw_move,
|
||||
.set_zorder = wintw_set_zorder,
|
||||
.palette_get = wintw_palette_get,
|
||||
.palette_set = wintw_palette_set,
|
||||
.palette_reset = wintw_palette_reset,
|
||||
.palette_get_overrides = wintw_palette_get_overrides,
|
||||
.get_pos = wintw_get_pos,
|
||||
.get_pixels = wintw_get_pixels,
|
||||
};
|
||||
@ -681,8 +675,6 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
|
||||
|
||||
conf_cache_data();
|
||||
|
||||
conftopalette();
|
||||
|
||||
/*
|
||||
* Guess some defaults for the window size. This all gets
|
||||
* updated later, so we don't really care too much. However, we
|
||||
@ -735,6 +727,11 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
|
||||
*/
|
||||
init_fonts(0,0);
|
||||
|
||||
/*
|
||||
* Prepare a logical palette.
|
||||
*/
|
||||
init_palette();
|
||||
|
||||
/*
|
||||
* Initialise the terminal. (We have to do this _after_
|
||||
* creating the window, since the terminal is the first thing
|
||||
@ -869,13 +866,6 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show)
|
||||
ShowWindow(wgs.term_hwnd, show);
|
||||
SetForegroundWindow(wgs.term_hwnd);
|
||||
|
||||
/*
|
||||
* Set the palette up.
|
||||
*/
|
||||
pal = NULL;
|
||||
logpal = NULL;
|
||||
init_palette();
|
||||
|
||||
term_set_focus(term, GetForegroundWindow() == wgs.term_hwnd);
|
||||
UpdateWindow(wgs.term_hwnd);
|
||||
|
||||
@ -1198,115 +1188,36 @@ static void wm_netevent_callback(void *vctx)
|
||||
sfree(vctx);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy the colour palette from the configuration data into defpal.
|
||||
*/
|
||||
static void conftopalette(void)
|
||||
static inline rgb rgb_from_colorref(COLORREF cr)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 22; i++) {
|
||||
int w = colour_indices_conf_to_osc4[i];
|
||||
defpal[w].rgbtRed = conf_get_int_int(conf, CONF_colours, i*3+0);
|
||||
defpal[w].rgbtGreen = conf_get_int_int(conf, CONF_colours, i*3+1);
|
||||
defpal[w].rgbtBlue = conf_get_int_int(conf, CONF_colours, i*3+2);
|
||||
}
|
||||
for (i = 0; i < 216; i++) {
|
||||
int r = i / 36, g = (i / 6) % 6, b = i % 6;
|
||||
defpal[i+16].rgbtRed = r ? r * 40 + 55 : 0;
|
||||
defpal[i+16].rgbtGreen = g ? g * 40 + 55 : 0;
|
||||
defpal[i+16].rgbtBlue = b ? b * 40 + 55 : 0;
|
||||
}
|
||||
for (i = 0; i < 24; i++) {
|
||||
int shade = i * 10 + 8;
|
||||
defpal[i+232].rgbtRed = defpal[i+232].rgbtGreen =
|
||||
defpal[i+232].rgbtBlue = shade;
|
||||
}
|
||||
|
||||
/* Override with system colours if appropriate */
|
||||
if (conf_get_bool(conf, CONF_system_colour))
|
||||
systopalette();
|
||||
rgb toret;
|
||||
toret.r = GetRValue(cr);
|
||||
toret.g = GetGValue(cr);
|
||||
toret.b = GetBValue(cr);
|
||||
return toret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Override bit of defpal with colours from the system.
|
||||
* (NB that this takes a copy the system colours at the time this is called,
|
||||
* so subsequent colour scheme changes don't take effect. To fix that we'd
|
||||
* probably want to be using GetSysColorBrush() and the like.)
|
||||
*/
|
||||
static void systopalette(void)
|
||||
static void wintw_palette_get_overrides(TermWin *tw)
|
||||
{
|
||||
int i;
|
||||
static const struct { int nIndex; int norm; int bold; } or[] =
|
||||
{
|
||||
{ COLOR_WINDOWTEXT, OSC4_COLOUR_fg, OSC4_COLOUR_fg_bold },
|
||||
{ COLOR_WINDOW, OSC4_COLOUR_bg, OSC4_COLOUR_bg_bold },
|
||||
{ COLOR_HIGHLIGHTTEXT, OSC4_COLOUR_cursor_fg, OSC4_COLOUR_cursor_fg },
|
||||
{ COLOR_HIGHLIGHT, OSC4_COLOUR_cursor_bg, OSC4_COLOUR_cursor_bg },
|
||||
};
|
||||
if (conf_get_bool(conf, CONF_system_colour)) {
|
||||
rgb rgb;
|
||||
|
||||
for (i = 0; i < (sizeof(or)/sizeof(or[0])); i++) {
|
||||
COLORREF colour = GetSysColor(or[i].nIndex);
|
||||
defpal[or[i].norm].rgbtRed =
|
||||
defpal[or[i].bold].rgbtRed = GetRValue(colour);
|
||||
defpal[or[i].norm].rgbtGreen =
|
||||
defpal[or[i].bold].rgbtGreen = GetGValue(colour);
|
||||
defpal[or[i].norm].rgbtBlue =
|
||||
defpal[or[i].bold].rgbtBlue = GetBValue(colour);
|
||||
rgb = rgb_from_colorref(GetSysColor(COLOR_WINDOWTEXT));
|
||||
term_palette_override(term, OSC4_COLOUR_fg, rgb);
|
||||
term_palette_override(term, OSC4_COLOUR_fg_bold, rgb);
|
||||
|
||||
rgb = rgb_from_colorref(GetSysColor(COLOR_WINDOW));
|
||||
term_palette_override(term, OSC4_COLOUR_bg, rgb);
|
||||
term_palette_override(term, OSC4_COLOUR_bg_bold, rgb);
|
||||
|
||||
rgb = rgb_from_colorref(GetSysColor(COLOR_HIGHLIGHTTEXT));
|
||||
term_palette_override(term, OSC4_COLOUR_cursor_fg, rgb);
|
||||
|
||||
rgb = rgb_from_colorref(GetSysColor(COLOR_HIGHLIGHT));
|
||||
term_palette_override(term, OSC4_COLOUR_cursor_bg, rgb);
|
||||
}
|
||||
}
|
||||
|
||||
static void internal_set_colour(unsigned i, int r, int g, int b)
|
||||
{
|
||||
assert(i < OSC4_NCOLOURS);
|
||||
if (pal)
|
||||
colours[i] = PALETTERGB(r, g, b);
|
||||
else
|
||||
colours[i] = RGB(r, g, b);
|
||||
colours_rgb[i].r = r;
|
||||
colours_rgb[i].g = g;
|
||||
colours_rgb[i].b = b;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up the colour palette.
|
||||
*/
|
||||
static void init_palette(void)
|
||||
{
|
||||
int i;
|
||||
HDC hdc = GetDC(wgs.term_hwnd);
|
||||
if (hdc) {
|
||||
if (conf_get_bool(conf, CONF_try_palette) &&
|
||||
GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) {
|
||||
/*
|
||||
* This is a genuine case where we must use smalloc
|
||||
* because the snew macros can't cope.
|
||||
*/
|
||||
logpal = smalloc(sizeof(*logpal)
|
||||
- sizeof(logpal->palPalEntry)
|
||||
+ OSC4_NCOLOURS * sizeof(PALETTEENTRY));
|
||||
logpal->palVersion = 0x300;
|
||||
logpal->palNumEntries = OSC4_NCOLOURS;
|
||||
for (i = 0; i < OSC4_NCOLOURS; i++) {
|
||||
logpal->palPalEntry[i].peRed = defpal[i].rgbtRed;
|
||||
logpal->palPalEntry[i].peGreen = defpal[i].rgbtGreen;
|
||||
logpal->palPalEntry[i].peBlue = defpal[i].rgbtBlue;
|
||||
logpal->palPalEntry[i].peFlags = PC_NOCOLLAPSE;
|
||||
}
|
||||
pal = CreatePalette(logpal);
|
||||
if (pal) {
|
||||
SelectPalette(hdc, pal, false);
|
||||
RealizePalette(hdc);
|
||||
SelectPalette(hdc, GetStockObject(DEFAULT_PALETTE), false);
|
||||
}
|
||||
}
|
||||
ReleaseDC(wgs.term_hwnd, hdc);
|
||||
}
|
||||
for (i = 0; i < OSC4_NCOLOURS; i++)
|
||||
internal_set_colour(i, defpal[i].rgbtRed,
|
||||
defpal[i].rgbtGreen, defpal[i].rgbtBlue);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is a wrapper to ExtTextOut() to force Windows to display
|
||||
* the precise glyphs we give it. Otherwise it would do its own
|
||||
@ -2340,17 +2251,23 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
|
||||
ldisc_configure(ldisc, conf);
|
||||
ldisc_echoedit_update(ldisc);
|
||||
}
|
||||
if (pal)
|
||||
DeleteObject(pal);
|
||||
logpal = NULL;
|
||||
pal = NULL;
|
||||
conftopalette();
|
||||
init_palette();
|
||||
|
||||
if (conf_get_bool(conf, CONF_system_colour) !=
|
||||
conf_get_bool(prev_conf, CONF_system_colour))
|
||||
term_notify_palette_overrides_changed(term);
|
||||
|
||||
/* Pass new config data to the terminal */
|
||||
term_reconfig(term, conf);
|
||||
setup_clipboards(term, conf);
|
||||
|
||||
/* Reinitialise the colour palette, in case the terminal
|
||||
* just read new settings out of Conf */
|
||||
if (pal)
|
||||
DeleteObject(pal);
|
||||
logpal = NULL;
|
||||
pal = NULL;
|
||||
init_palette();
|
||||
|
||||
/* Pass new config data to the back end */
|
||||
if (backend)
|
||||
backend_reconfig(backend, conf);
|
||||
@ -3292,8 +3209,7 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
|
||||
case WM_SYSCOLORCHANGE:
|
||||
if (conf_get_bool(conf, CONF_system_colour)) {
|
||||
/* Refresh palette from system colours. */
|
||||
/* XXX actually this zaps the entire palette. */
|
||||
systopalette();
|
||||
term_notify_palette_overrides_changed(term);
|
||||
init_palette();
|
||||
/* Force a repaint of the terminal window. */
|
||||
term_invalidate(term);
|
||||
@ -4746,70 +4662,73 @@ static void wintw_free_draw_ctx(TermWin *tw)
|
||||
wintw_hdc = NULL;
|
||||
}
|
||||
|
||||
static void real_palette_set(unsigned n, int r, int g, int b)
|
||||
/*
|
||||
* Set up the colour palette.
|
||||
*/
|
||||
static void init_palette(void)
|
||||
{
|
||||
internal_set_colour(n, r, g, b);
|
||||
if (pal) {
|
||||
logpal->palPalEntry[n].peRed = r;
|
||||
logpal->palPalEntry[n].peGreen = g;
|
||||
logpal->palPalEntry[n].peBlue = b;
|
||||
logpal->palPalEntry[n].peFlags = PC_NOCOLLAPSE;
|
||||
SetPaletteEntries(pal, 0, OSC4_NCOLOURS, logpal->palPalEntry);
|
||||
pal = NULL;
|
||||
logpal = snew_plus(LOGPALETTE, (OSC4_NCOLOURS - 1) * sizeof(PALETTEENTRY));
|
||||
logpal->palVersion = 0x300;
|
||||
logpal->palNumEntries = OSC4_NCOLOURS;
|
||||
for (unsigned i = 0; i < OSC4_NCOLOURS; i++)
|
||||
logpal->palPalEntry[i].peFlags = PC_NOCOLLAPSE;
|
||||
}
|
||||
|
||||
static void wintw_palette_set(TermWin *win, unsigned start,
|
||||
unsigned ncolours, const rgb *colours_in)
|
||||
{
|
||||
assert(start <= OSC4_NCOLOURS);
|
||||
assert(ncolours <= OSC4_NCOLOURS - start);
|
||||
|
||||
for (unsigned i = 0; i < ncolours; i++) {
|
||||
const rgb *in = &colours_in[i];
|
||||
PALETTEENTRY *out = &logpal->palPalEntry[i + start];
|
||||
out->peRed = in->r;
|
||||
out->peGreen = in->g;
|
||||
out->peBlue = in->b;
|
||||
colours[i + start] = RGB(in->r, in->g, in->b) ^ colorref_modifier;
|
||||
}
|
||||
}
|
||||
|
||||
static bool wintw_palette_get(TermWin *tw, unsigned n, int *r, int *g, int *b)
|
||||
{
|
||||
if (n >= OSC4_NCOLOURS)
|
||||
return false;
|
||||
*r = colours_rgb[n].r;
|
||||
*g = colours_rgb[n].g;
|
||||
*b = colours_rgb[n].b;
|
||||
return true;
|
||||
}
|
||||
bool got_new_palette = false;
|
||||
|
||||
if (!tried_pal && conf_get_bool(conf, CONF_try_palette)) {
|
||||
HDC hdc = GetDC(wgs.term_hwnd);
|
||||
if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) {
|
||||
pal = CreatePalette(logpal);
|
||||
if (pal) {
|
||||
SelectPalette(hdc, pal, false);
|
||||
RealizePalette(hdc);
|
||||
SelectPalette(hdc, GetStockObject(DEFAULT_PALETTE), false);
|
||||
|
||||
/* Convert all RGB() values in colours[] into PALETTERGB(),
|
||||
* and ensure we stick to that later */
|
||||
colorref_modifier = PALETTERGB(0, 0, 0) ^ RGB(0, 0, 0);
|
||||
for (unsigned i = 0; i < OSC4_NCOLOURS; i++)
|
||||
colours[i] ^= colorref_modifier;
|
||||
|
||||
/* Inhibit the SetPaletteEntries call below */
|
||||
got_new_palette = true;
|
||||
}
|
||||
}
|
||||
ReleaseDC(wgs.term_hwnd, hdc);
|
||||
tried_pal = true;
|
||||
}
|
||||
|
||||
if (pal && !got_new_palette) {
|
||||
/* We already had a palette, so replace the changed colours in the
|
||||
* existing one. */
|
||||
SetPaletteEntries(pal, start, ncolours, logpal->palPalEntry + start);
|
||||
|
||||
static void wintw_palette_set(TermWin *tw, unsigned n, int r, int g, int b)
|
||||
{
|
||||
if (n >= OSC4_NCOLOURS)
|
||||
return;
|
||||
real_palette_set(n, r, g, b);
|
||||
if (pal) {
|
||||
HDC hdc = make_hdc();
|
||||
UnrealizeObject(pal);
|
||||
RealizePalette(hdc);
|
||||
free_hdc(hdc);
|
||||
} else {
|
||||
if (n == OSC4_COLOUR_bg)
|
||||
/* If Default Background changes, we need to ensure any
|
||||
* space between the text area and the window border is
|
||||
* redrawn. */
|
||||
InvalidateRect(wgs.term_hwnd, NULL, true);
|
||||
}
|
||||
}
|
||||
|
||||
static void wintw_palette_reset(TermWin *tw)
|
||||
{
|
||||
/* And this */
|
||||
for (unsigned i = 0; i < OSC4_NCOLOURS; i++) {
|
||||
internal_set_colour(i, defpal[i].rgbtRed,
|
||||
defpal[i].rgbtGreen, defpal[i].rgbtBlue);
|
||||
if (pal) {
|
||||
logpal->palPalEntry[i].peRed = defpal[i].rgbtRed;
|
||||
logpal->palPalEntry[i].peGreen = defpal[i].rgbtGreen;
|
||||
logpal->palPalEntry[i].peBlue = defpal[i].rgbtBlue;
|
||||
logpal->palPalEntry[i].peFlags = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (pal) {
|
||||
HDC hdc;
|
||||
SetPaletteEntries(pal, 0, OSC4_NCOLOURS, logpal->palPalEntry);
|
||||
hdc = make_hdc();
|
||||
RealizePalette(hdc);
|
||||
free_hdc(hdc);
|
||||
} else {
|
||||
/* Default Background may have changed. Ensure any space between
|
||||
* text area and window border is redrawn. */
|
||||
if (start <= OSC4_COLOUR_bg && OSC4_COLOUR_bg < start + ncolours) {
|
||||
/* If Default Background changes, we need to ensure any space between
|
||||
* the text area and the window border is redrawn. */
|
||||
InvalidateRect(wgs.term_hwnd, NULL, true);
|
||||
}
|
||||
}
|
||||
@ -5008,9 +4927,9 @@ static void wintw_clip_write(
|
||||
|
||||
for (i = 0; i < OSC4_NCOLOURS; i++) {
|
||||
if (palette[i] != 0) {
|
||||
const PALETTEENTRY *pe = &logpal->palPalEntry[i];
|
||||
strbuf_catf(rtf, "\\red%d\\green%d\\blue%d;",
|
||||
defpal[i].rgbtRed, defpal[i].rgbtGreen,
|
||||
defpal[i].rgbtBlue);
|
||||
pe->peRed, pe->peGreen, pe->peBlue);
|
||||
}
|
||||
}
|
||||
if (rgbtree) {
|
||||
|
Loading…
Reference in New Issue
Block a user