mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-03-23 15:09:24 -05:00
Support OSC 4 terminal colour-palette queries.
Markus Gans points out that some applications which (not at all unreasonably) don't trust $TERM to tell them the full capabilities of their terminal will use the sequence "OSC 4 ; nn ; ? BEL" to ask for the colour-palette value in position nn, and they may not particularly care _what_ the results are but they will use them to decide whether the right number of colour palette entries even exist.
This commit is contained in:
parent
262376a054
commit
4743798400
@ -81,6 +81,7 @@ Context get_ctx(void *frontend) {
|
|||||||
void free_ctx(Context ctx) { }
|
void free_ctx(Context ctx) { }
|
||||||
void palette_set(void *frontend, int a, int b, int c, int d) { }
|
void palette_set(void *frontend, int a, int b, int c, int d) { }
|
||||||
void palette_reset(void *frontend) { }
|
void palette_reset(void *frontend) { }
|
||||||
|
int palette_get(void *frontend, int n, int *r, int *g, int *b) {return FALSE;}
|
||||||
void write_clip(void *frontend, wchar_t *a, int *b, int c, int d) { }
|
void write_clip(void *frontend, wchar_t *a, int *b, int c, int d) { }
|
||||||
void get_clip(void *frontend, wchar_t **w, int *i) { }
|
void get_clip(void *frontend, wchar_t **w, int *i) { }
|
||||||
void set_raw_mouse_mode(void *frontend, int m) { }
|
void set_raw_mouse_mode(void *frontend, int m) { }
|
||||||
|
1
putty.h
1
putty.h
@ -633,6 +633,7 @@ Context get_ctx(void *frontend);
|
|||||||
void free_ctx(Context);
|
void free_ctx(Context);
|
||||||
void palette_set(void *frontend, int, int, int, int);
|
void palette_set(void *frontend, int, int, int, int);
|
||||||
void palette_reset(void *frontend);
|
void palette_reset(void *frontend);
|
||||||
|
int palette_get(void *frontend, int n, int *r, int *g, int *b);
|
||||||
void write_aclip(void *frontend, char *, int, int);
|
void write_aclip(void *frontend, char *, int, int);
|
||||||
void write_clip(void *frontend, wchar_t *, int *, int, int);
|
void write_clip(void *frontend, wchar_t *, int *, int, int);
|
||||||
void get_clip(void *frontend, wchar_t **, int *);
|
void get_clip(void *frontend, wchar_t **, int *);
|
||||||
|
66
terminal.c
66
terminal.c
@ -2727,6 +2727,22 @@ static void do_osc(Terminal *term)
|
|||||||
if (!term->no_remote_wintitle)
|
if (!term->no_remote_wintitle)
|
||||||
set_title(term->frontend, term->osc_string);
|
set_title(term->frontend, term->osc_string);
|
||||||
break;
|
break;
|
||||||
|
case 4:
|
||||||
|
if (term->ldisc && !strcmp(term->osc_string, "?")) {
|
||||||
|
int r, g, b;
|
||||||
|
if (palette_get(term->frontend, toint(term->esc_args[1]),
|
||||||
|
&r, &g, &b)) {
|
||||||
|
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);
|
||||||
|
ldisc_send(term->ldisc, reply_buf, strlen(reply_buf), 0);
|
||||||
|
sfree(reply_buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3365,6 +3381,7 @@ static void term_out(Terminal *term)
|
|||||||
compatibility(OTHER);
|
compatibility(OTHER);
|
||||||
term->termstate = SEEN_OSC;
|
term->termstate = SEEN_OSC;
|
||||||
term->esc_args[0] = 0;
|
term->esc_args[0] = 0;
|
||||||
|
term->esc_nargs = 1;
|
||||||
break;
|
break;
|
||||||
case '7': /* DECSC: save cursor */
|
case '7': /* DECSC: save cursor */
|
||||||
compatibility(VT100);
|
compatibility(VT100);
|
||||||
@ -4470,25 +4487,40 @@ static void term_out(Terminal *term)
|
|||||||
case '7':
|
case '7':
|
||||||
case '8':
|
case '8':
|
||||||
case '9':
|
case '9':
|
||||||
if (term->esc_args[0] <= UINT_MAX / 10 &&
|
if (term->esc_args[term->esc_nargs-1] <= UINT_MAX / 10 &&
|
||||||
term->esc_args[0] * 10 <= UINT_MAX - c - '0')
|
term->esc_args[term->esc_nargs-1] * 10 <= UINT_MAX - c - '0')
|
||||||
term->esc_args[0] = 10 * term->esc_args[0] + c - '0';
|
term->esc_args[term->esc_nargs-1] =
|
||||||
|
10 * term->esc_args[term->esc_nargs-1] + c - '0';
|
||||||
else
|
else
|
||||||
term->esc_args[0] = UINT_MAX;
|
term->esc_args[term->esc_nargs-1] = UINT_MAX;
|
||||||
break;
|
break;
|
||||||
case 'L':
|
default:
|
||||||
/*
|
/*
|
||||||
* Grotty hack to support xterm and DECterm title
|
* _Most_ other characters here terminate the
|
||||||
* sequences concurrently.
|
* immediate parsing of the OSC sequence and go
|
||||||
*/
|
* into OSC_STRING state, but we deal with a
|
||||||
if (term->esc_args[0] == 2) {
|
* couple of exceptions first.
|
||||||
term->esc_args[0] = 1;
|
*/
|
||||||
break;
|
if (c == 'L' && term->esc_args[0] == 2) {
|
||||||
}
|
/*
|
||||||
/* else fall through */
|
* Grotty hack to support xterm and DECterm title
|
||||||
default:
|
* sequences concurrently.
|
||||||
term->termstate = OSC_STRING;
|
*/
|
||||||
term->osc_strlen = 0;
|
term->esc_args[0] = 1;
|
||||||
|
} else if (c == ';' && term->esc_nargs == 1 &&
|
||||||
|
term->esc_args[0] == 4) {
|
||||||
|
/*
|
||||||
|
* xterm's OSC 4 sequence to query the current
|
||||||
|
* RGB value of a colour takes a second
|
||||||
|
* numeric argument which is easiest to parse
|
||||||
|
* using the existing system rather than in
|
||||||
|
* do_osc.
|
||||||
|
*/
|
||||||
|
term->esc_args[term->esc_nargs++] = 0;
|
||||||
|
} else {
|
||||||
|
term->termstate = OSC_STRING;
|
||||||
|
term->osc_strlen = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OSC_STRING:
|
case OSC_STRING:
|
||||||
|
@ -2222,6 +2222,17 @@ void palette_set(void *frontend, int n, int r, int g, int b)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
void palette_reset(void *frontend)
|
void palette_reset(void *frontend)
|
||||||
{
|
{
|
||||||
struct gui_data *inst = (struct gui_data *)frontend;
|
struct gui_data *inst = (struct gui_data *)frontend;
|
||||||
|
@ -198,6 +198,9 @@ static int descent;
|
|||||||
#define NEXTCOLOURS 240
|
#define NEXTCOLOURS 240
|
||||||
#define NALLCOLOURS (NCFGCOLOURS + NEXTCOLOURS)
|
#define NALLCOLOURS (NCFGCOLOURS + NEXTCOLOURS)
|
||||||
static COLORREF colours[NALLCOLOURS];
|
static COLORREF colours[NALLCOLOURS];
|
||||||
|
struct rgb {
|
||||||
|
int r, g, b;
|
||||||
|
} colours_rgb[NALLCOLOURS];
|
||||||
static HPALETTE pal;
|
static HPALETTE pal;
|
||||||
static LPLOGPALETTE logpal;
|
static LPLOGPALETTE logpal;
|
||||||
static RGBTRIPLE defpal[NALLCOLOURS];
|
static RGBTRIPLE defpal[NALLCOLOURS];
|
||||||
@ -1264,6 +1267,19 @@ static void systopalette(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void internal_set_colour(int i, int r, int g, int b)
|
||||||
|
{
|
||||||
|
assert(i >= 0);
|
||||||
|
assert(i < NALLCOLOURS);
|
||||||
|
if (pal)
|
||||||
|
colours[i] = PALETTERGB(r, g, b);
|
||||||
|
else
|
||||||
|
colours[i] = RGB(r, g, b);
|
||||||
|
colours_rgb[i].r = r;
|
||||||
|
colours_rgb[i].g = g;
|
||||||
|
colours_rgb[i].b = b;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set up the colour palette.
|
* Set up the colour palette.
|
||||||
*/
|
*/
|
||||||
@ -1298,15 +1314,9 @@ static void init_palette(void)
|
|||||||
}
|
}
|
||||||
ReleaseDC(hwnd, hdc);
|
ReleaseDC(hwnd, hdc);
|
||||||
}
|
}
|
||||||
if (pal)
|
for (i = 0; i < NALLCOLOURS; i++)
|
||||||
for (i = 0; i < NALLCOLOURS; i++)
|
internal_set_colour(i, defpal[i].rgbtRed,
|
||||||
colours[i] = PALETTERGB(defpal[i].rgbtRed,
|
defpal[i].rgbtGreen, defpal[i].rgbtBlue);
|
||||||
defpal[i].rgbtGreen,
|
|
||||||
defpal[i].rgbtBlue);
|
|
||||||
else
|
|
||||||
for (i = 0; i < NALLCOLOURS; i++)
|
|
||||||
colours[i] = RGB(defpal[i].rgbtRed,
|
|
||||||
defpal[i].rgbtGreen, defpal[i].rgbtBlue);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -4865,15 +4875,24 @@ void free_ctx(Context ctx)
|
|||||||
|
|
||||||
static void real_palette_set(int n, int r, int g, int b)
|
static void real_palette_set(int n, int r, int g, int b)
|
||||||
{
|
{
|
||||||
|
internal_set_colour(n, r, g, b);
|
||||||
if (pal) {
|
if (pal) {
|
||||||
logpal->palPalEntry[n].peRed = r;
|
logpal->palPalEntry[n].peRed = r;
|
||||||
logpal->palPalEntry[n].peGreen = g;
|
logpal->palPalEntry[n].peGreen = g;
|
||||||
logpal->palPalEntry[n].peBlue = b;
|
logpal->palPalEntry[n].peBlue = b;
|
||||||
logpal->palPalEntry[n].peFlags = PC_NOCOLLAPSE;
|
logpal->palPalEntry[n].peFlags = PC_NOCOLLAPSE;
|
||||||
colours[n] = PALETTERGB(r, g, b);
|
|
||||||
SetPaletteEntries(pal, 0, NALLCOLOURS, logpal->palPalEntry);
|
SetPaletteEntries(pal, 0, NALLCOLOURS, logpal->palPalEntry);
|
||||||
} else
|
}
|
||||||
colours[n] = RGB(r, g, b);
|
}
|
||||||
|
|
||||||
|
int palette_get(void *frontend, int n, int *r, int *g, int *b)
|
||||||
|
{
|
||||||
|
if (n < 0 || n >= NALLCOLOURS)
|
||||||
|
return FALSE;
|
||||||
|
*r = colours_rgb[n].r;
|
||||||
|
*g = colours_rgb[n].g;
|
||||||
|
*b = colours_rgb[n].b;
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void palette_set(void *frontend, int n, int r, int g, int b)
|
void palette_set(void *frontend, int n, int r, int g, int b)
|
||||||
@ -4903,17 +4922,14 @@ void palette_reset(void *frontend)
|
|||||||
|
|
||||||
/* And this */
|
/* And this */
|
||||||
for (i = 0; i < NALLCOLOURS; i++) {
|
for (i = 0; i < NALLCOLOURS; i++) {
|
||||||
|
internal_set_colour(i, defpal[i].rgbtRed,
|
||||||
|
defpal[i].rgbtGreen, defpal[i].rgbtBlue);
|
||||||
if (pal) {
|
if (pal) {
|
||||||
logpal->palPalEntry[i].peRed = defpal[i].rgbtRed;
|
logpal->palPalEntry[i].peRed = defpal[i].rgbtRed;
|
||||||
logpal->palPalEntry[i].peGreen = defpal[i].rgbtGreen;
|
logpal->palPalEntry[i].peGreen = defpal[i].rgbtGreen;
|
||||||
logpal->palPalEntry[i].peBlue = defpal[i].rgbtBlue;
|
logpal->palPalEntry[i].peBlue = defpal[i].rgbtBlue;
|
||||||
logpal->palPalEntry[i].peFlags = 0;
|
logpal->palPalEntry[i].peFlags = 0;
|
||||||
colours[i] = PALETTERGB(defpal[i].rgbtRed,
|
}
|
||||||
defpal[i].rgbtGreen,
|
|
||||||
defpal[i].rgbtBlue);
|
|
||||||
} else
|
|
||||||
colours[i] = RGB(defpal[i].rgbtRed,
|
|
||||||
defpal[i].rgbtGreen, defpal[i].rgbtBlue);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pal) {
|
if (pal) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user