1
0
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:
Owen Dunn 2006-02-13 22:18:17 +00:00
parent 4475ed6ed9
commit d526e3bb33
6 changed files with 181 additions and 12 deletions

View File

@ -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;

View File

@ -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 */

View File

@ -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);

View File

@ -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);
} }

View File

@ -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)

View File

@ -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);