mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-10 01:48:00 +00:00
Preserve more attributes of text copied as RTF. Thanks to Stephen Balousek.
[originally from svn r6555]
This commit is contained in:
parent
4475ed6ed9
commit
d526e3bb33
@ -595,7 +595,7 @@ static void text_click(Session *s, EventRecord *event)
|
|||||||
lastwhen = TickCount();
|
lastwhen = TickCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_clip(void *cookie, wchar_t *data, int len, int must_deselect)
|
void write_clip(void *cookie, wchar_t *data, int *attr, int len, int must_deselect)
|
||||||
{
|
{
|
||||||
#if !TARGET_API_MAC_CARBON
|
#if !TARGET_API_MAC_CARBON
|
||||||
Session *s = cookie;
|
Session *s = cookie;
|
||||||
|
@ -1176,7 +1176,7 @@ void get_clip(void *frontend, wchar_t ** p, int *len)
|
|||||||
/* FIXME */
|
/* FIXME */
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_clip(void *frontend, wchar_t * data, int len, int must_deselect)
|
void write_clip(void *frontend, wchar_t *data, int *arttr, int len, int must_deselect)
|
||||||
{
|
{
|
||||||
//SessionWindow *win = (SessionWindow *)frontend;
|
//SessionWindow *win = (SessionWindow *)frontend;
|
||||||
/* FIXME */
|
/* FIXME */
|
||||||
|
2
putty.h
2
putty.h
@ -680,7 +680,7 @@ 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);
|
||||||
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);
|
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 *);
|
||||||
void optimised_move(void *frontend, int, int, int);
|
void optimised_move(void *frontend, int, int, int);
|
||||||
void set_raw_mouse_mode(void *frontend, int);
|
void set_raw_mouse_mode(void *frontend, int);
|
||||||
|
12
terminal.c
12
terminal.c
@ -5047,10 +5047,15 @@ static void clipme(Terminal *term, pos top, pos bottom, int rect, int desel)
|
|||||||
int old_top_x;
|
int old_top_x;
|
||||||
int wblen = 0; /* workbuf len */
|
int wblen = 0; /* workbuf len */
|
||||||
int buflen; /* amount of memory allocated to workbuf */
|
int buflen; /* amount of memory allocated to workbuf */
|
||||||
|
int *attrbuf; /* Attribute buffer */
|
||||||
|
int *attrptr;
|
||||||
|
int attr;
|
||||||
|
|
||||||
buflen = 5120; /* Default size */
|
buflen = 5120; /* Default size */
|
||||||
workbuf = snewn(buflen, wchar_t);
|
workbuf = snewn(buflen, wchar_t);
|
||||||
|
attrbuf = buflen ? snewn(buflen, int) : 0;
|
||||||
wbptr = workbuf; /* start filling here */
|
wbptr = workbuf; /* start filling here */
|
||||||
|
attrptr = attrbuf;
|
||||||
old_top_x = top.x; /* needed for rect==1 */
|
old_top_x = top.x; /* needed for rect==1 */
|
||||||
|
|
||||||
while (poslt(top, bottom)) {
|
while (poslt(top, bottom)) {
|
||||||
@ -5113,6 +5118,7 @@ static void clipme(Terminal *term, pos top, pos bottom, int rect, int desel)
|
|||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
int uc = ldata->chars[x].chr;
|
int uc = ldata->chars[x].chr;
|
||||||
|
attr = ldata->chars[x].attr;
|
||||||
|
|
||||||
switch (uc & CSET_MASK) {
|
switch (uc & CSET_MASK) {
|
||||||
case CSET_LINEDRW:
|
case CSET_LINEDRW:
|
||||||
@ -5170,9 +5176,12 @@ static void clipme(Terminal *term, pos top, pos bottom, int rect, int desel)
|
|||||||
buflen += 100;
|
buflen += 100;
|
||||||
workbuf = sresize(workbuf, buflen, wchar_t);
|
workbuf = sresize(workbuf, buflen, wchar_t);
|
||||||
wbptr = workbuf + wblen;
|
wbptr = workbuf + wblen;
|
||||||
|
attrbuf = sresize(attrbuf, buflen, int);
|
||||||
|
attrptr = attrbuf + wblen;
|
||||||
}
|
}
|
||||||
wblen++;
|
wblen++;
|
||||||
*wbptr++ = *p;
|
*wbptr++ = *p;
|
||||||
|
*attrptr++ = attr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ldata->chars[x].cc_next)
|
if (ldata->chars[x].cc_next)
|
||||||
@ -5187,6 +5196,7 @@ static void clipme(Terminal *term, pos top, pos bottom, int rect, int desel)
|
|||||||
for (i = 0; i < sel_nl_sz; i++) {
|
for (i = 0; i < sel_nl_sz; i++) {
|
||||||
wblen++;
|
wblen++;
|
||||||
*wbptr++ = sel_nl[i];
|
*wbptr++ = sel_nl[i];
|
||||||
|
*attrptr++ = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
top.y++;
|
top.y++;
|
||||||
@ -5198,7 +5208,7 @@ static void clipme(Terminal *term, pos top, pos bottom, int rect, int desel)
|
|||||||
wblen++;
|
wblen++;
|
||||||
*wbptr++ = 0;
|
*wbptr++ = 0;
|
||||||
#endif
|
#endif
|
||||||
write_clip(term->frontend, workbuf, wblen, desel); /* transfer to clipbd */
|
write_clip(term->frontend, workbuf, attrbuf, wblen, desel); /* transfer to clipbd */
|
||||||
if (buflen > 0) /* indicates we allocated this buffer */
|
if (buflen > 0) /* indicates we allocated this buffer */
|
||||||
sfree(workbuf);
|
sfree(workbuf);
|
||||||
}
|
}
|
||||||
|
@ -1491,7 +1491,7 @@ char * retrieve_cutbuffer(int * nbytes)
|
|||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_clip(void *frontend, wchar_t * data, int len, int must_deselect)
|
void write_clip(void *frontend, wchar_t * data, int *attr, int len, int must_deselect)
|
||||||
{
|
{
|
||||||
struct gui_data *inst = (struct gui_data *)frontend;
|
struct gui_data *inst = (struct gui_data *)frontend;
|
||||||
if (inst->pasteout_data)
|
if (inst->pasteout_data)
|
||||||
|
173
windows/window.c
173
windows/window.c
@ -4462,7 +4462,7 @@ void write_aclip(void *frontend, char *data, int len, int must_deselect)
|
|||||||
/*
|
/*
|
||||||
* Note: unlike write_aclip() this will not append a nul.
|
* Note: unlike write_aclip() this will not append a nul.
|
||||||
*/
|
*/
|
||||||
void write_clip(void *frontend, wchar_t * data, int len, int must_deselect)
|
void write_clip(void *frontend, wchar_t * data, int *attr, int len, int must_deselect)
|
||||||
{
|
{
|
||||||
HGLOBAL clipdata, clipdata2, clipdata3;
|
HGLOBAL clipdata, clipdata2, clipdata3;
|
||||||
int len2;
|
int len2;
|
||||||
@ -4498,14 +4498,83 @@ void write_clip(void *frontend, wchar_t * data, int len, int must_deselect)
|
|||||||
int rtfsize = 0;
|
int rtfsize = 0;
|
||||||
int multilen, blen, alen, totallen, i;
|
int multilen, blen, alen, totallen, i;
|
||||||
char before[16], after[4];
|
char before[16], after[4];
|
||||||
|
int fgcolour, lastfgcolour = 0;
|
||||||
|
int bgcolour, lastbgcolour = 0;
|
||||||
|
int attrBold, lastAttrBold = 0;
|
||||||
|
int attrUnder, lastAttrUnder = 0;
|
||||||
|
int palette[NALLCOLOURS];
|
||||||
|
int numcolours;
|
||||||
|
|
||||||
get_unitab(CP_ACP, unitab, 0);
|
get_unitab(CP_ACP, unitab, 0);
|
||||||
|
|
||||||
rtfsize = 100 + strlen(cfg.font.name);
|
rtfsize = 100 + strlen(cfg.font.name);
|
||||||
rtf = snewn(rtfsize, char);
|
rtf = snewn(rtfsize, char);
|
||||||
sprintf(rtf, "{\\rtf1\\ansi%d{\\fonttbl\\f0\\fmodern %s;}\\f0 ",
|
rtflen = sprintf(rtf, "{\\rtf1\\ansi\\deff0{\\fonttbl\\f0\\fmodern %s;}\\f0\\fs%d",
|
||||||
GetACP(), cfg.font.name);
|
cfg.font.name, cfg.font.height*2);
|
||||||
rtflen = strlen(rtf);
|
|
||||||
|
/*
|
||||||
|
* Add colour palette
|
||||||
|
* {\colortbl ;\red255\green0\blue0;\red0\green0\blue128;}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* First - Determine all colours in use
|
||||||
|
* o Foregound and background colours share the same palette
|
||||||
|
*/
|
||||||
|
if (attr) {
|
||||||
|
memset(palette, 0, sizeof(palette));
|
||||||
|
for (i = 0; i < (len-1); i++) {
|
||||||
|
fgcolour = ((attr[i] & ATTR_FGMASK) >> ATTR_FGSHIFT);
|
||||||
|
bgcolour = ((attr[i] & ATTR_BGMASK) >> ATTR_BGSHIFT);
|
||||||
|
|
||||||
|
if (attr[i] & ATTR_REVERSE) {
|
||||||
|
int tmpcolour = fgcolour; /* Swap foreground and background */
|
||||||
|
fgcolour = bgcolour;
|
||||||
|
bgcolour = tmpcolour;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bold_mode == BOLD_COLOURS && (attr[i] & ATTR_BOLD)) {
|
||||||
|
if (fgcolour < 8) /* ANSI colours */
|
||||||
|
fgcolour += 8;
|
||||||
|
else if (fgcolour >= 256) /* Default colours */
|
||||||
|
fgcolour ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attr[i] & ATTR_BLINK) {
|
||||||
|
if (bgcolour < 8) /* ANSI colours */
|
||||||
|
bgcolour += 8;
|
||||||
|
else if (bgcolour >= 256) /* Default colours */
|
||||||
|
bgcolour ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
palette[fgcolour]++;
|
||||||
|
palette[bgcolour]++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Next - Create a reduced palette
|
||||||
|
*/
|
||||||
|
numcolours = 0;
|
||||||
|
for (i = 0; i < NALLCOLOURS; i++) {
|
||||||
|
if (palette[i] != 0)
|
||||||
|
palette[i] = ++numcolours;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Finally - Write the colour table
|
||||||
|
*/
|
||||||
|
rtf = sresize(rtf, rtfsize + (numcolours * 25), char);
|
||||||
|
strcat(rtf, "{\\colortbl ;");
|
||||||
|
rtflen = strlen(rtf);
|
||||||
|
|
||||||
|
for (i = 0; i < NALLCOLOURS; i++) {
|
||||||
|
if (palette[i] != 0) {
|
||||||
|
rtflen += sprintf(&rtf[rtflen], "\\red%d\\green%d\\blue%d;", defpal[i].rgbtRed, defpal[i].rgbtGreen, defpal[i].rgbtBlue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
strcpy(&rtf[rtflen], "}");
|
||||||
|
rtflen ++;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We want to construct a piece of RTF that specifies the
|
* We want to construct a piece of RTF that specifies the
|
||||||
@ -4532,7 +4601,96 @@ void write_clip(void *frontend, wchar_t * data, int len, int must_deselect)
|
|||||||
tdata[tindex+1] == '\n') {
|
tdata[tindex+1] == '\n') {
|
||||||
tindex++;
|
tindex++;
|
||||||
uindex++;
|
uindex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set text attributes
|
||||||
|
*/
|
||||||
|
if (attr) {
|
||||||
|
if (rtfsize < rtflen + 64) {
|
||||||
|
rtfsize = rtflen + 512;
|
||||||
|
rtf = sresize(rtf, rtfsize, char);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Determine foreground and background colours
|
||||||
|
*/
|
||||||
|
fgcolour = ((attr[tindex] & ATTR_FGMASK) >> ATTR_FGSHIFT);
|
||||||
|
bgcolour = ((attr[tindex] & ATTR_BGMASK) >> ATTR_BGSHIFT);
|
||||||
|
|
||||||
|
if (attr[tindex] & ATTR_REVERSE) {
|
||||||
|
int tmpcolour = fgcolour; /* Swap foreground and background */
|
||||||
|
fgcolour = bgcolour;
|
||||||
|
bgcolour = tmpcolour;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bold_mode == BOLD_COLOURS && (attr[tindex] & ATTR_BOLD)) {
|
||||||
|
if (fgcolour < 8) /* ANSI colours */
|
||||||
|
fgcolour += 8;
|
||||||
|
else if (fgcolour >= 256) /* Default colours */
|
||||||
|
fgcolour ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attr[tindex] & ATTR_BLINK) {
|
||||||
|
if (bgcolour < 8) /* ANSI colours */
|
||||||
|
bgcolour += 8;
|
||||||
|
else if (bgcolour >= 256) /* Default colours */
|
||||||
|
bgcolour ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Collect other attributes
|
||||||
|
*/
|
||||||
|
if (bold_mode != BOLD_COLOURS)
|
||||||
|
attrBold = attr[tindex] & ATTR_BOLD;
|
||||||
|
else
|
||||||
|
attrBold = 0;
|
||||||
|
|
||||||
|
attrUnder = attr[tindex] & ATTR_UNDER;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Reverse video
|
||||||
|
* o If video isn't reversed, ignore colour attributes for default foregound
|
||||||
|
* or background.
|
||||||
|
* o Special case where bolded text is displayed using the default foregound
|
||||||
|
* and background colours - force to bolded RTF.
|
||||||
|
*/
|
||||||
|
if (!(attr[tindex] & ATTR_REVERSE)) {
|
||||||
|
if (bgcolour >= 256) /* Default color */
|
||||||
|
bgcolour = -1; /* No coloring */
|
||||||
|
|
||||||
|
if (fgcolour >= 256) { /* Default colour */
|
||||||
|
if (bold_mode == BOLD_COLOURS && (fgcolour & 1) && bgcolour == -1)
|
||||||
|
attrBold = ATTR_BOLD; /* Emphasize text with bold attribute */
|
||||||
|
|
||||||
|
fgcolour = -1; /* No coloring */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write RTF text attributes
|
||||||
|
*/
|
||||||
|
if (lastfgcolour != fgcolour) {
|
||||||
|
lastfgcolour = fgcolour;
|
||||||
|
rtflen += sprintf(&rtf[rtflen], "\\cf%d ", (fgcolour >= 0) ? palette[fgcolour] : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastbgcolour != bgcolour) {
|
||||||
|
lastbgcolour = bgcolour;
|
||||||
|
rtflen += sprintf(&rtf[rtflen], "\\highlight%d ", (bgcolour >= 0) ? palette[bgcolour] : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastAttrBold != attrBold) {
|
||||||
|
lastAttrBold = attrBold;
|
||||||
|
rtflen += sprintf(&rtf[rtflen], "%s", attrBold ? "\\b " : "\\b0 ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastAttrUnder != attrUnder) {
|
||||||
|
lastAttrUnder = attrUnder;
|
||||||
|
rtflen += sprintf(&rtf[rtflen], "%s", attrUnder ? "\\ul " : "\\ulnone ");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unitab[tdata[tindex]] == udata[uindex]) {
|
if (unitab[tdata[tindex]] == udata[uindex]) {
|
||||||
multilen = 1;
|
multilen = 1;
|
||||||
before[0] = '\0';
|
before[0] = '\0';
|
||||||
@ -4591,12 +4749,13 @@ void write_clip(void *frontend, wchar_t * data, int len, int must_deselect)
|
|||||||
uindex++;
|
uindex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
strcpy(rtf + rtflen, "}");
|
rtf[rtflen++] = '}'; /* Terminate RTF stream */
|
||||||
rtflen += 2;
|
rtf[rtflen++] = '\0';
|
||||||
|
rtf[rtflen++] = '\0';
|
||||||
|
|
||||||
clipdata3 = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, rtflen);
|
clipdata3 = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, rtflen);
|
||||||
if (clipdata3 && (lock3 = GlobalLock(clipdata3)) != NULL) {
|
if (clipdata3 && (lock3 = GlobalLock(clipdata3)) != NULL) {
|
||||||
strcpy(lock3, rtf);
|
memcpy(lock3, rtf, rtflen);
|
||||||
GlobalUnlock(clipdata3);
|
GlobalUnlock(clipdata3);
|
||||||
}
|
}
|
||||||
sfree(rtf);
|
sfree(rtf);
|
||||||
|
Loading…
Reference in New Issue
Block a user