1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-05-28 23:34:49 -05:00

Implement true-colour in write_clip for Windows

This allows text copied from PuTTY to a rich-text program to retain the
true-colour attribute.
This commit is contained in:
Jeff Smith 2017-06-12 23:55:57 -05:00 committed by Simon Tatham
parent 7bdfdabb5e
commit 891d909b3d

View File

@ -24,6 +24,7 @@
#include "storage.h"
#include "win_res.h"
#include "winsecur.h"
#include "tree234.h"
#ifndef NO_MULTIMON
#include <multimon.h>
@ -4986,6 +4987,18 @@ void write_aclip(void *frontend, char *data, int len, int must_deselect)
SendMessage(hwnd, WM_IGNORE_CLIP, FALSE, 0);
}
typedef struct _rgbindex {
int index;
COLORREF ref;
} rgbindex;
int cmpCOLORREF(void *va, void *vb)
{
COLORREF a = ((rgbindex *)va)->ref;
COLORREF b = ((rgbindex *)vb)->ref;
return (a < b) ? -1 : (a > b) ? +1 : 0;
}
/*
* Note: unlike write_aclip() this will not append a nul.
*/
@ -5033,12 +5046,15 @@ void write_clip(void *frontend, wchar_t *data, int *attr, truecolour *truecolour
int rtfsize = 0;
int multilen, blen, alen, totallen, i;
char before[16], after[4];
int fgcolour, lastfgcolour = 0;
int bgcolour, lastbgcolour = 0;
int fgcolour, lastfgcolour = -1;
int bgcolour, lastbgcolour = -1;
COLORREF fg, lastfg = -1;
COLORREF bg, lastbg = -1;
int attrBold, lastAttrBold = 0;
int attrUnder, lastAttrUnder = 0;
int palette[NALLCOLOURS];
int numcolours;
tree234 *rgbtree = NULL;
FontSpec *font = conf_get_fontspec(conf, CONF_font);
get_unitab(CP_ACP, unitab, 0);
@ -5076,7 +5092,7 @@ void write_clip(void *frontend, wchar_t *data, int *attr, truecolour *truecolour
fgcolour ++;
}
if (attr[i] & ATTR_BLINK) {
if ((attr[i] & ATTR_BLINK)) {
if (bgcolour < 8) /* ANSI colours */
bgcolour += 8;
else if (bgcolour >= 256) /* Default colours */
@ -5087,6 +5103,28 @@ void write_clip(void *frontend, wchar_t *data, int *attr, truecolour *truecolour
palette[bgcolour]++;
}
if (truecolour) {
rgbtree = newtree234(cmpCOLORREF);
for (i = 0; i < (len-1); i++) {
if (truecolour[i].fg.enabled) {
rgbindex *rgbp = snew(rgbindex);
rgbp->ref = RGB(truecolour[i].fg.r,
truecolour[i].fg.g,
truecolour[i].fg.b);
if (add234(rgbtree, rgbp) != rgbp)
sfree(rgbp);
}
if (truecolour[i].bg.enabled) {
rgbindex *rgbp = snew(rgbindex);
rgbp->ref = RGB(truecolour[i].bg.r,
truecolour[i].bg.g,
truecolour[i].bg.b);
if (add234(rgbtree, rgbp) != rgbp)
sfree(rgbp);
}
}
}
/*
* Next - Create a reduced palette
*/
@ -5096,6 +5134,12 @@ void write_clip(void *frontend, wchar_t *data, int *attr, truecolour *truecolour
palette[i] = ++numcolours;
}
if (rgbtree) {
rgbindex *rgbp;
for (i = 0; (rgbp = index234(rgbtree, i)) != NULL; i++)
rgbp->index = ++numcolours;
}
/*
* Finally - Write the colour table
*/
@ -5108,6 +5152,12 @@ void write_clip(void *frontend, wchar_t *data, int *attr, truecolour *truecolour
rtflen += sprintf(&rtf[rtflen], "\\red%d\\green%d\\blue%d;", defpal[i].rgbtRed, defpal[i].rgbtGreen, defpal[i].rgbtBlue);
}
}
if (rgbtree) {
rgbindex *rgbp;
for (i = 0; (rgbp = index234(rgbtree, i)) != NULL; i++)
rtflen += sprintf(&rtf[rtflen], "\\red%d\\green%d\\blue%d;",
GetRValue(rgbp->ref), GetGValue(rgbp->ref), GetBValue(rgbp->ref));
}
strcpy(&rtf[rtflen], "}");
rtflen ++;
}
@ -5151,23 +5201,44 @@ void write_clip(void *frontend, wchar_t *data, int *attr, truecolour *truecolour
/*
* Determine foreground and background colours
*/
fgcolour = ((attr[tindex] & ATTR_FGMASK) >> ATTR_FGSHIFT);
bgcolour = ((attr[tindex] & ATTR_BGMASK) >> ATTR_BGSHIFT);
if (truecolour && truecolour[tindex].fg.enabled) {
fgcolour = -1;
fg = RGB(truecolour[tindex].fg.r,
truecolour[tindex].fg.g,
truecolour[tindex].fg.b);
} else {
fgcolour = ((attr[tindex] & ATTR_FGMASK) >> ATTR_FGSHIFT);
fg = -1;
}
if (truecolour && truecolour[tindex].bg.enabled) {
bgcolour = -1;
bg = RGB(truecolour[tindex].bg.r,
truecolour[tindex].bg.g,
truecolour[tindex].bg.b);
} else {
bgcolour = ((attr[tindex] & ATTR_BGMASK) >> ATTR_BGSHIFT);
bg = -1;
}
if (attr[tindex] & ATTR_REVERSE) {
int tmpcolour = fgcolour; /* Swap foreground and background */
fgcolour = bgcolour;
bgcolour = tmpcolour;
COLORREF tmpref = fg;
fg = bg;
bg = tmpref;
}
if (bold_colours && (attr[tindex] & ATTR_BOLD)) {
if (bold_colours && (attr[tindex] & ATTR_BOLD) && (fgcolour >= 0)) {
if (fgcolour < 8) /* ANSI colours */
fgcolour += 8;
else if (fgcolour >= 256) /* Default colours */
fgcolour ++;
}
if (attr[tindex] & ATTR_BLINK) {
if ((attr[tindex] & ATTR_BLINK) && (bgcolour >= 0)) {
if (bgcolour < 8) /* ANSI colours */
bgcolour += 8;
else if (bgcolour >= 256) /* Default colours */
@ -5206,15 +5277,33 @@ void write_clip(void *frontend, wchar_t *data, int *attr, truecolour *truecolour
/*
* Write RTF text attributes
*/
if (lastfgcolour != fgcolour) {
lastfgcolour = fgcolour;
rtflen += sprintf(&rtf[rtflen], "\\cf%d ", (fgcolour >= 0) ? palette[fgcolour] : 0);
}
if ((lastfgcolour != fgcolour) || (lastfg != fg)) {
lastfgcolour = fgcolour;
lastfg = fg;
if (fg == -1)
rtflen += sprintf(&rtf[rtflen], "\\cf%d ",
(fgcolour >= 0) ? palette[fgcolour] : 0);
else {
rgbindex rgb, *rgbp;
rgb.ref = fg;
if ((rgbp = find234(rgbtree, &rgb, NULL)) != NULL)
rtflen += sprintf(&rtf[rtflen], "\\cf%d ", rgbp->index);
}
}
if (lastbgcolour != bgcolour) {
lastbgcolour = bgcolour;
rtflen += sprintf(&rtf[rtflen], "\\highlight%d ", (bgcolour >= 0) ? palette[bgcolour] : 0);
}
if ((lastbgcolour != bgcolour) || (lastbg != bg)) {
lastbgcolour = bgcolour;
lastbg = bg;
if (bg == -1)
rtflen += sprintf(&rtf[rtflen], "\\highlight%d ",
(bgcolour >= 0) ? palette[bgcolour] : 0);
else {
rgbindex rgb, *rgbp;
rgb.ref = bg;
if ((rgbp = find234(rgbtree, &rgb, NULL)) != NULL)
rtflen += sprintf(&rtf[rtflen], "\\highlight%d ", rgbp->index);
}
}
if (lastAttrBold != attrBold) {
lastAttrBold = attrBold;
@ -5295,6 +5384,13 @@ void write_clip(void *frontend, wchar_t *data, int *attr, truecolour *truecolour
GlobalUnlock(clipdata3);
}
sfree(rtf);
if (rgbtree) {
rgbindex *rgbp;
while ((rgbp = delpos234(rgbtree, 0)) != NULL)
sfree(rgbp);
freetree234(rgbtree);
}
} else
clipdata3 = NULL;