mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-10 01:48:00 +00:00
Real COMPOUND_TEXT support! I was expecting to have to read the spec
and implement the required subset of ISO-2022 in libcharset, but it turns out that Xlib provides conversion functions between UTF-8 and compound text, which are just about ideal for us. So now we can paste multilingual stuff both to and from emacs21. Rock on. [originally from svn r3193]
This commit is contained in:
parent
ef2ccb56cf
commit
d49e6e1476
88
unix/pterm.c
88
unix/pterm.c
@ -58,8 +58,8 @@ struct gui_data {
|
||||
wchar_t *pastein_data;
|
||||
int direct_to_font;
|
||||
int pastein_data_len;
|
||||
char *pasteout_data, *pasteout_data_utf8;
|
||||
int pasteout_data_len, pasteout_data_utf8_len;
|
||||
char *pasteout_data, *pasteout_data_ctext, *pasteout_data_utf8;
|
||||
int pasteout_data_len, pasteout_data_ctext_len, pasteout_data_utf8_len;
|
||||
int font_width, font_height;
|
||||
int width, height;
|
||||
int ignore_sbar;
|
||||
@ -1327,16 +1327,20 @@ void write_clip(void *frontend, wchar_t * data, int len, int must_deselect)
|
||||
struct gui_data *inst = (struct gui_data *)frontend;
|
||||
if (inst->pasteout_data)
|
||||
sfree(inst->pasteout_data);
|
||||
if (inst->pasteout_data_ctext)
|
||||
sfree(inst->pasteout_data_ctext);
|
||||
if (inst->pasteout_data_utf8)
|
||||
sfree(inst->pasteout_data_utf8);
|
||||
|
||||
/*
|
||||
* Set up UTF-8 paste data. This only happens if we aren't in
|
||||
* direct-to-font mode using the D800 hack.
|
||||
* Set up UTF-8 and compound text paste data. This only happens
|
||||
* if we aren't in direct-to-font mode using the D800 hack.
|
||||
*/
|
||||
if (!inst->direct_to_font) {
|
||||
wchar_t *tmp = data;
|
||||
int tmplen = len;
|
||||
XTextProperty tp;
|
||||
char *list[1];
|
||||
|
||||
inst->pasteout_data_utf8 = snewn(len*6, char);
|
||||
inst->pasteout_data_utf8_len = len*6;
|
||||
@ -1350,11 +1354,26 @@ void write_clip(void *frontend, wchar_t * data, int len, int must_deselect)
|
||||
} else {
|
||||
inst->pasteout_data_utf8 =
|
||||
sresize(inst->pasteout_data_utf8,
|
||||
inst->pasteout_data_utf8_len, char);
|
||||
inst->pasteout_data_utf8_len + 1, char);
|
||||
inst->pasteout_data_utf8[inst->pasteout_data_utf8_len] = '\0';
|
||||
}
|
||||
|
||||
/*
|
||||
* Now let Xlib convert our UTF-8 data into compound text.
|
||||
*/
|
||||
list[0] = inst->pasteout_data_utf8;
|
||||
if (Xutf8TextListToTextProperty(GDK_DISPLAY(), list, 1,
|
||||
XCompoundTextStyle, &tp) == 0) {
|
||||
inst->pasteout_data_ctext = snewn(tp.nitems+1, char);
|
||||
memcpy(inst->pasteout_data_ctext, tp.value, tp.nitems);
|
||||
inst->pasteout_data_ctext_len = tp.nitems;
|
||||
XFree(tp.value);
|
||||
}
|
||||
} else {
|
||||
inst->pasteout_data_utf8 = NULL;
|
||||
inst->pasteout_data_utf8_len = 0;
|
||||
inst->pasteout_data_ctext = NULL;
|
||||
inst->pasteout_data_ctext_len = 0;
|
||||
}
|
||||
|
||||
inst->pasteout_data = snewn(len*6, char);
|
||||
@ -1375,8 +1394,9 @@ void write_clip(void *frontend, wchar_t * data, int len, int must_deselect)
|
||||
GDK_CURRENT_TIME)) {
|
||||
gtk_selection_add_target(inst->area, GDK_SELECTION_PRIMARY,
|
||||
GDK_SELECTION_TYPE_STRING, 1);
|
||||
gtk_selection_add_target(inst->area, GDK_SELECTION_PRIMARY,
|
||||
compound_text_atom, 1);
|
||||
if (inst->pasteout_data_ctext)
|
||||
gtk_selection_add_target(inst->area, GDK_SELECTION_PRIMARY,
|
||||
compound_text_atom, 1);
|
||||
if (inst->pasteout_data_utf8)
|
||||
gtk_selection_add_target(inst->area, GDK_SELECTION_PRIMARY,
|
||||
utf8_string_atom, 1);
|
||||
@ -1394,6 +1414,10 @@ void selection_get(GtkWidget *widget, GtkSelectionData *seldata,
|
||||
gtk_selection_data_set(seldata, seldata->target, 8,
|
||||
inst->pasteout_data_utf8,
|
||||
inst->pasteout_data_utf8_len);
|
||||
else if (seldata->target == compound_text_atom)
|
||||
gtk_selection_data_set(seldata, seldata->target, 8,
|
||||
inst->pasteout_data_ctext,
|
||||
inst->pasteout_data_ctext_len);
|
||||
else
|
||||
gtk_selection_data_set(seldata, seldata->target, 8,
|
||||
inst->pasteout_data, inst->pasteout_data_len);
|
||||
@ -1406,10 +1430,14 @@ gint selection_clear(GtkWidget *widget, GdkEventSelection *seldata,
|
||||
term_deselect(inst->term);
|
||||
if (inst->pasteout_data)
|
||||
sfree(inst->pasteout_data);
|
||||
if (inst->pasteout_data_ctext)
|
||||
sfree(inst->pasteout_data_ctext);
|
||||
if (inst->pasteout_data_utf8)
|
||||
sfree(inst->pasteout_data_utf8);
|
||||
inst->pasteout_data = NULL;
|
||||
inst->pasteout_data_len = 0;
|
||||
inst->pasteout_data_ctext = NULL;
|
||||
inst->pasteout_data_ctext_len = 0;
|
||||
inst->pasteout_data_utf8 = NULL;
|
||||
inst->pasteout_data_utf8_len = 0;
|
||||
return TRUE;
|
||||
@ -1450,6 +1478,12 @@ void selection_received(GtkWidget *widget, GtkSelectionData *seldata,
|
||||
guint time, gpointer data)
|
||||
{
|
||||
struct gui_data *inst = (struct gui_data *)data;
|
||||
XTextProperty tp;
|
||||
char **list;
|
||||
char *text;
|
||||
int length, count, ret;
|
||||
int free_list_required = 0;
|
||||
int charset;
|
||||
|
||||
if (seldata->target == utf8_string_atom && seldata->length <= 0) {
|
||||
/*
|
||||
@ -1480,21 +1514,51 @@ void selection_received(GtkWidget *widget, GtkSelectionData *seldata,
|
||||
seldata->type != utf8_string_atom))
|
||||
return; /* Nothing happens. */
|
||||
|
||||
|
||||
/*
|
||||
* Convert COMPOUND_TEXT into UTF-8.
|
||||
*/
|
||||
if (seldata->type == compound_text_atom) {
|
||||
tp.value = seldata->data;
|
||||
tp.encoding = (Atom) seldata->type;
|
||||
tp.format = seldata->format;
|
||||
tp.nitems = seldata->length;
|
||||
ret = Xutf8TextPropertyToTextList(GDK_DISPLAY(), &tp, &list, &count);
|
||||
if (ret != 0 || count != 1) {
|
||||
/*
|
||||
* Compound text failed; fall back to STRING.
|
||||
*/
|
||||
gtk_selection_convert(inst->area, GDK_SELECTION_PRIMARY,
|
||||
GDK_SELECTION_TYPE_STRING, GDK_CURRENT_TIME);
|
||||
return;
|
||||
}
|
||||
text = list[0];
|
||||
length = strlen(list[0]);
|
||||
charset = CS_UTF8;
|
||||
free_list_required = 1;
|
||||
} else {
|
||||
text = (char *)seldata->data;
|
||||
length = seldata->length;
|
||||
charset = (seldata->type == utf8_string_atom ?
|
||||
CS_UTF8 : inst->ucsdata.line_codepage);
|
||||
}
|
||||
|
||||
if (inst->pastein_data)
|
||||
sfree(inst->pastein_data);
|
||||
|
||||
inst->pastein_data = snewn(seldata->length, wchar_t);
|
||||
inst->pastein_data_len = seldata->length;
|
||||
inst->pastein_data = snewn(length, wchar_t);
|
||||
inst->pastein_data_len = length;
|
||||
inst->pastein_data_len =
|
||||
mb_to_wc((seldata->type == utf8_string_atom ?
|
||||
CS_UTF8 : inst->ucsdata.line_codepage),
|
||||
0, seldata->data, seldata->length,
|
||||
mb_to_wc(charset, 0, text, length,
|
||||
inst->pastein_data, inst->pastein_data_len);
|
||||
|
||||
term_do_paste(inst->term);
|
||||
|
||||
if (term_paste_pending(inst->term))
|
||||
inst->term_paste_idle_id = gtk_idle_add(idle_paste_func, inst);
|
||||
|
||||
if (free_list_required)
|
||||
XFreeStringList(list);
|
||||
}
|
||||
|
||||
gint idle_paste_func(gpointer data)
|
||||
|
Loading…
Reference in New Issue
Block a user