1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-09 17:38:00 +00:00

Implement writing RTF to the clipboard (off by default), so that if

you enable it text will paste into Word et al in the same font as
PuTTY itself is displaying in. In particular, this will be a fixed-
pitch font, so tables and `ls' and the like will naturally line up.

[originally from svn r1373]
This commit is contained in:
Simon Tatham 2001-11-07 22:22:53 +00:00
parent 4e77787527
commit 7f1e73904a
5 changed files with 136 additions and 8 deletions

View File

@ -328,6 +328,7 @@ typedef struct {
int mouse_is_xterm;
int rect_select;
int rawcnp;
int rtf_paste;
int mouse_override;
short wordness[256];
/* translations */
@ -539,6 +540,7 @@ int check_compose(int first, int second);
int decode_codepage(char *cp_name);
char *cp_enumerate (int index);
char *cp_name(int codepage);
void get_unitab(int codepage, wchar_t * unitab, int ftype);
/*
* Exports from mscrypto.c

View File

@ -234,6 +234,7 @@ void save_settings(char *section, int do_host, Config * cfg)
write_setting_s(sesskey, buf, buf2);
}
write_setting_i(sesskey, "RawCNP", cfg->rawcnp);
write_setting_i(sesskey, "PasteRTF", cfg->rtf_paste);
write_setting_i(sesskey, "MouseIsXterm", cfg->mouse_is_xterm);
write_setting_i(sesskey, "RectSelect", cfg->rect_select);
write_setting_i(sesskey, "MouseOverride", cfg->mouse_override);
@ -440,6 +441,7 @@ void load_settings(char *section, int do_host, Config * cfg)
}
}
gppi(sesskey, "RawCNP", 0, &cfg->rawcnp);
gppi(sesskey, "PasteRTF", 0, &cfg->rtf_paste);
gppi(sesskey, "MouseIsXterm", 0, &cfg->mouse_is_xterm);
gppi(sesskey, "RectSelect", 0, &cfg->rect_select);
gppi(sesskey, "MouseOverride", 1, &cfg->mouse_override);

View File

@ -8,8 +8,6 @@
#include "putty.h"
#include "misc.h"
static void get_unitab(int codepage, wchar_t * unitab, int ftype);
/* Character conversion arrays; they are usually taken from windows,
* the xterm one has the four scanlines that have no unicode 2.0
* equivalents mapped to their unicode 3.0 locations.
@ -1218,7 +1216,7 @@ char *cp_enumerate(int index)
return cp_list[index].name;
}
static void get_unitab(int codepage, wchar_t * unitab, int ftype)
void get_unitab(int codepage, wchar_t * unitab, int ftype)
{
char tbuf[4];
int i, max = 256, flg = MB_ERR_INVALID_CHARS;

View File

@ -488,6 +488,7 @@ enum { IDCX_ABOUT =
IDC_CCSTATIC2,
IDC_CCEDIT,
IDC_RAWCNP,
IDC_RTFPASTE,
selectionpanelend,
colourspanelstart,
@ -772,6 +773,7 @@ static void init_dlg_ctrls(HWND hwnd, int keepsess)
cfg.rect_select == 0 ? IDC_SELTYPELEX : IDC_SELTYPERECT);
CheckDlgButton(hwnd, IDC_MOUSEOVERRIDE, cfg.mouse_override);
CheckDlgButton(hwnd, IDC_RAWCNP, cfg.rawcnp);
CheckDlgButton(hwnd, IDC_RTFPASTE, cfg.rtf_paste);
{
static int tabs[4] = { 25, 61, 96, 128 };
SendDlgItemMessage(hwnd, IDC_CCLIST, LB_SETTABSTOPS, 4,
@ -1145,7 +1147,7 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
}
if (panel == selectionpanelstart) {
/* The Selection panel. Accelerators used: [acgo] d wxp hst nr */
/* The Selection panel. Accelerators used: [acgo] df wxp hst nr */
struct ctlpos cp;
ctlposinit(&cp, hwnd, 80, 3, 13);
bartitle(&cp, "Options controlling copy and paste",
@ -1155,6 +1157,9 @@ static void create_controls(HWND hwnd, int dlgtype, int panel)
checkbox(&cp,
"&Don't translate line drawing chars into +, - and |",
IDC_RAWCNP);
checkbox(&cp,
"Paste to clipboard in RT&F as well as plain text",
IDC_RTFPASTE);
endbox(&cp);
beginbox(&cp, "Control which mouse button does which thing",
IDC_BOX_SELECTION2);
@ -2412,6 +2417,9 @@ static int GenericMainDlgProc(HWND hwnd, UINT msg,
case IDC_RAWCNP:
cfg.rawcnp = IsDlgButtonChecked(hwnd, IDC_RAWCNP);
break;
case IDC_RTFPASTE:
cfg.rtf_paste = IsDlgButtonChecked(hwnd, IDC_RTFPASTE);
break;
case IDC_MBWINDOWS:
case IDC_MBXTERM:
cfg.mouse_is_xterm = IsDlgButtonChecked(hwnd, IDC_MBXTERM);

126
window.c
View File

@ -1,6 +1,7 @@
#include <windows.h>
#include <imm.h>
#include <commctrl.h>
#include <richedit.h>
#include <mmsystem.h>
#ifndef AUTO_WINSOCK
#ifdef WINSOCK_TWO
@ -14,6 +15,7 @@
#include <stdlib.h>
#include <ctype.h>
#include <time.h>
#include <assert.h>
#define PUTTY_DO_GLOBALS /* actually _define_ globals */
#include "putty.h"
@ -3642,10 +3644,9 @@ void write_aclip(char *data, int len, int must_deselect)
*/
void write_clip(wchar_t * data, int len, int must_deselect)
{
HGLOBAL clipdata;
HGLOBAL clipdata2;
HGLOBAL clipdata, clipdata2, clipdata3;
int len2;
void *lock, *lock2;
void *lock, *lock2, *lock3;
len2 = WideCharToMultiByte(CP_ACP, 0, data, len, 0, 0, NULL, NULL);
@ -3653,11 +3654,13 @@ void write_clip(wchar_t * data, int len, int must_deselect)
len * sizeof(wchar_t));
clipdata2 = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, len2);
if (!clipdata || !clipdata2) {
if (!clipdata || !clipdata2 || !clipdata3) {
if (clipdata)
GlobalFree(clipdata);
if (clipdata2)
GlobalFree(clipdata2);
if (clipdata3)
GlobalFree(clipdata3);
return;
}
if (!(lock = GlobalLock(clipdata)))
@ -3668,6 +3671,119 @@ void write_clip(wchar_t * data, int len, int must_deselect)
memcpy(lock, data, len * sizeof(wchar_t));
WideCharToMultiByte(CP_ACP, 0, data, len, lock2, len2, NULL, NULL);
if (cfg.rtf_paste) {
wchar_t unitab[256];
char *rtf = NULL;
unsigned char *tdata = (unsigned char *)lock2;
wchar_t *udata = (wchar_t *)lock;
int rtflen = 0, uindex = 0, tindex = 0;
int rtfsize = 0;
int multilen, blen, alen, totallen, i;
char before[16], after[4];
get_unitab(CP_ACP, unitab, 0);
rtfsize = 100 + strlen(cfg.font);
rtf = smalloc(rtfsize);
sprintf(rtf, "{\\rtf1\\ansi%d{\\fonttbl\\f0\\fmodern %s;}\\f0",
GetACP(), cfg.font);
rtflen = strlen(rtf);
/*
* We want to construct a piece of RTF that specifies the
* same Unicode text. To do this we will read back in
* parallel from the Unicode data in `udata' and the
* non-Unicode data in `tdata'. For each character in
* `tdata' which becomes the right thing in `udata' when
* looked up in `unitab', we just copy straight over from
* tdata. For each one that doesn't, we must WCToMB it
* individually and produce a \u escape sequence.
*
* It would probably be more robust to just bite the bullet
* and WCToMB each individual Unicode character one by one,
* then MBToWC each one back to see if it was an accurate
* translation; but that strikes me as a horrifying number
* of Windows API calls so I want to see if this faster way
* will work. If it screws up badly we can always revert to
* the simple and slow way.
*/
while (tindex < len2 && uindex < len &&
tdata[tindex] && udata[uindex]) {
if (tindex + 1 < len2 &&
tdata[tindex] == '\r' &&
tdata[tindex+1] == '\n') {
tindex++;
uindex++;
}
if (unitab[tdata[tindex]] == udata[uindex]) {
multilen = 1;
before[0] = '\0';
after[0] = '\0';
blen = alen = 0;
} else {
multilen = WideCharToMultiByte(CP_ACP, 0, unitab+uindex, 1,
NULL, 0, NULL, NULL);
if (multilen != 1) {
blen = sprintf(before, "{\\u%d", udata[uindex]);
alen = 1; strcpy(after, "}");
} else {
blen = sprintf(before, "\\u%d", udata[uindex]);
alen = 0; after[0] = '\0';
}
}
assert(tindex + multilen <= len2);
totallen = blen + alen;
for (i = 0; i < multilen; i++) {
if (tdata[tindex+i] == '\\' ||
tdata[tindex+i] == '{' ||
tdata[tindex+i] == '}')
totallen += 2;
else if (tdata[tindex+i] == 0x0D || tdata[tindex+i] == 0x0A)
totallen += 6; /* \par\r\n */
else if (tdata[tindex+i] > 0x7E || tdata[tindex+i] < 0x20)
totallen += 4;
else
totallen++;
}
if (rtfsize < rtflen + totallen + 3) {
rtfsize = rtflen + totallen + 512;
rtf = srealloc(rtf, rtfsize);
}
strcpy(rtf + rtflen, before); rtflen += blen;
for (i = 0; i < multilen; i++) {
if (tdata[tindex+i] == '\\' ||
tdata[tindex+i] == '{' ||
tdata[tindex+i] == '}') {
rtf[rtflen++] = '\\';
rtf[rtflen++] = tdata[tindex+i];
} else if (tdata[tindex+i] == 0x0D || tdata[tindex+i] == 0x0A) {
rtflen += sprintf(rtf+rtflen, "\\par\r\n");
} else if (tdata[tindex+i] > 0x7E || tdata[tindex+i] < 0x20) {
rtflen += sprintf(rtf+rtflen, "\\'%02x", tdata[tindex+i]);
} else {
rtf[rtflen++] = tdata[tindex+i];
}
}
strcpy(rtf + rtflen, after); rtflen += alen;
tindex += multilen;
uindex++;
}
strcpy(rtf + rtflen, "}");
rtflen += 2;
clipdata3 = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, rtflen);
if (clipdata3 && (lock3 = GlobalLock(clipdata3)) != NULL) {
strcpy(lock3, rtf);
GlobalUnlock(clipdata3);
}
sfree(rtf);
} else
clipdata3 = NULL;
GlobalUnlock(clipdata);
GlobalUnlock(clipdata2);
@ -3678,6 +3794,8 @@ void write_clip(wchar_t * data, int len, int must_deselect)
EmptyClipboard();
SetClipboardData(CF_UNICODETEXT, clipdata);
SetClipboardData(CF_TEXT, clipdata2);
if (clipdata3)
SetClipboardData(RegisterClipboardFormat(CF_RTF), clipdata3);
CloseClipboard();
} else {
GlobalFree(clipdata);