summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Persch <chpe@gnome.org>2014-04-11 11:38:53 +0200
committerChristian Persch <chpe@gnome.org>2014-04-11 19:43:59 +0200
commita71e0eb84d1b88f764d13b5bb38e3faaded672d2 (patch)
tree9283c7a657633af91d252db399dfbd72f1d4ff2c
parent7f765481c24765dfb3d02932666686103e2a4e07 (diff)
parent0beed99e3000e8b60d8f0ab0e47f0f0865268d0c (diff)
downloadvte-a71e0eb84d1b88f764d13b5bb38e3faaded672d2.tar.gz
Merge remote-tracking branch 'nomeata/master-html-copy-paste' into work-master
Works, but needs much cleanup before it can be merged. Conflicts: src/vte-private.h src/vte.c
-rw-r--r--src/vte-private.h24
-rw-r--r--src/vte.c356
-rw-r--r--src/vte.h3
3 files changed, 306 insertions, 77 deletions
diff --git a/src/vte-private.h b/src/vte-private.h
index 72bd2320..1ccc44b7 100644
--- a/src/vte-private.h
+++ b/src/vte-private.h
@@ -132,10 +132,20 @@ typedef enum {
MOUSE_TRACKING_ALL_MOTION_TRACKING
} MouseTrackingMode;
-struct _vte_regex_match {
- int rm_so;
- int rm_eo;
-};
+/* For unified handling of PRIMARY and CLIPBOARD selection */
+typedef enum {
+ VTE_SELECTION_PRIMARY,
+ VTE_SELECTION_CLIPBOARD,
+ LAST_VTE_SELECTION
+} VteSelection;
+
+/* Used in the GtkClipboard API, to distinguish requests for HTML and TEXT
+ * contents of a clipboard */
+typedef enum {
+ VTE_TARGET_TEXT,
+ VTE_TARGET_HTML,
+ LAST_VTE_TARGET
+} VteSelectionTarget;
/* A match regex, with a tag. */
struct vte_match_regex {
@@ -271,7 +281,6 @@ struct _VteTerminalPrivate {
gboolean selecting_restart;
gboolean selecting_had_delta;
gboolean selection_block_mode;
- char *selection;
enum vte_selection_type {
selection_type_char,
selection_type_word,
@@ -282,6 +291,11 @@ struct _VteTerminalPrivate {
} selection_origin, selection_last;
VteVisualPosition selection_start, selection_end;
+ /* Clipboard data information. */
+ char *selection_text[LAST_VTE_SELECTION];
+ char *selection_html[LAST_VTE_SELECTION];
+ GtkClipboard *clipboard[LAST_VTE_SELECTION];
+
/* Miscellaneous options. */
VteEraseBinding backspace_binding, delete_binding;
gboolean meta_sends_escape;
diff --git a/src/vte.c b/src/vte.c
index a1dc1bfe..cb15f939 100644
--- a/src/vte.c
+++ b/src/vte.c
@@ -133,6 +133,11 @@ static void _vte_check_cursor_blink(VteTerminal *terminal);
static gboolean process_timeout (gpointer data);
static gboolean update_timeout (gpointer data);
static cairo_region_t *vte_cairo_get_clip_region (cairo_t *cr);
+static void vte_terminal_determine_colors_internal(VteTerminal *terminal,
+ const VteCellAttr *attr,
+ gboolean selected,
+ gboolean cursor,
+ guint *pfore, guint *pback);
enum {
COPY_CLIPBOARD,
@@ -4009,8 +4014,9 @@ next_match:
vte_cell_is_selected,
NULL,
NULL);
- if ((selection == NULL) || (terminal->pvt->selection == NULL) ||
- (strcmp(selection, terminal->pvt->selection) != 0)) {
+ if ((selection == NULL) ||
+ (terminal->pvt->selection_text[VTE_SELECTION_PRIMARY] == NULL) ||
+ (strcmp(selection, terminal->pvt->selection_text[VTE_SELECTION_PRIMARY]) != 0)) {
vte_terminal_deselect_all(terminal);
}
g_free(selection);
@@ -5863,6 +5869,13 @@ vte_terminal_match_hilite(VteTerminal *terminal, long x, long y)
vte_terminal_match_hilite_update(terminal, x, y);
}
+static GtkClipboard *
+vte_terminal_clipboard_get(VteTerminal *terminal, GdkAtom board)
+{
+ GdkDisplay *display;
+ display = gtk_widget_get_display(&terminal->widget);
+ return gtk_clipboard_get_for_display(display, board);
+}
/* Note that the clipboard has cleared. */
static void
@@ -5870,9 +5883,11 @@ vte_terminal_clear_cb(GtkClipboard *clipboard, gpointer owner)
{
VteTerminal *terminal;
terminal = owner;
- if (terminal->pvt->has_selection) {
- _vte_debug_print(VTE_DEBUG_SELECTION, "Lost selection.\n");
- vte_terminal_deselect_all(terminal);
+ if (clipboard == vte_terminal_clipboard_get(terminal, GDK_SELECTION_PRIMARY)) {
+ if (terminal->pvt->has_selection) {
+ _vte_debug_print(VTE_DEBUG_SELECTION, "Lost selection.\n");
+ vte_terminal_deselect_all(terminal);
+ }
}
}
@@ -5881,20 +5896,42 @@ static void
vte_terminal_copy_cb(GtkClipboard *clipboard, GtkSelectionData *data,
guint info, gpointer owner)
{
+ VteSelection sel;
VteTerminal *terminal;
terminal = owner;
- if (terminal->pvt->selection != NULL) {
- _VTE_DEBUG_IF(VTE_DEBUG_SELECTION) {
- int i;
- g_printerr("Setting selection (%"G_GSIZE_FORMAT" UTF-8 bytes.)\n",
- strlen(terminal->pvt->selection));
- for (i = 0; terminal->pvt->selection[i] != '\0'; i++) {
- g_printerr("0x%04x\n",
- terminal->pvt->selection[i]);
+ for (sel = 0; sel < LAST_VTE_SELECTION; sel ++) {
+ if (clipboard == terminal->pvt->clipboard[sel] && terminal->pvt->selection_text[sel] != NULL) {
+ _VTE_DEBUG_IF(VTE_DEBUG_SELECTION) {
+ int i;
+ g_printerr("Setting selection %d (%"G_GSIZE_FORMAT" UTF-8 bytes.)\n",
+ sel,
+ strlen(terminal->pvt->selection_text[sel]));
+ for (i = 0; terminal->pvt->selection_text[sel][i] != '\0'; i++) {
+ g_printerr("0x%04x\n",
+ terminal->pvt->selection_text[sel][i]);
+ }
+ }
+ if (info == VTE_TARGET_TEXT) {
+ gtk_selection_data_set_text(data, terminal->pvt->selection_text[sel], -1);
+ } else {
+ gsize len;
+ gchar *selection;
+
+ g_assert(info == VTE_TARGET_HTML);
+
+ /* Mozilla asks that we start our text/html with the Unicode byte order mark */
+ /* (Comment found in gtkimhtml.c of pidgin fame) */
+ selection = g_convert(terminal->pvt->selection_html[sel],
+ -1, "UTF-16", "UTF-8", NULL, &len, NULL);
+ gtk_selection_data_set(data,
+ gdk_atom_intern("text/html", FALSE),
+ 16,
+ (const guchar *)selection,
+ len);
+ g_free(selection);
}
}
- gtk_selection_data_set_text(data, terminal->pvt->selection, -1);
- }
+ }
}
/* Convert the internal color code (either index or RGB, see vte-private.h) into RGB. */
@@ -6190,6 +6227,164 @@ vte_terminal_get_text_include_trailing_spaces(VteTerminal *terminal,
TRUE);
}
+/*
+ * Compares the visual attributes of a VteCellAttr for equality, but ignores
+ * attributes that tend to change from character to character or are otherwise
+ * strange (in particular: fragment, columns).
+ */
+static gboolean
+vte_terminal_cellattr_equal(const VteCellAttr *attr1, const VteCellAttr *attr2) {
+ return (attr1->bold == attr2->bold &&
+ attr1->fore == attr2->fore &&
+ attr1->back == attr2->back &&
+ attr1->standout == attr2->standout &&
+ attr1->underline == attr2->underline &&
+ attr1->strikethrough == attr2->strikethrough &&
+ attr1->reverse == attr2->reverse &&
+ attr1->blink == attr2->blink &&
+ attr1->half == attr2->half &&
+ attr1->invisible == attr2->invisible);
+}
+
+/*
+ * Wraps a given string according to the VteCellAttr in HTML tags. Used
+ * old-style HTML (and not CSS) for better compatibility with, for example,
+ * evolution's mail editor component.
+ */
+static gchar *
+vte_terminal_cellattr_to_html(VteTerminal *terminal, const VteCellAttr *attr, const gchar *text) {
+ GString *string;
+ guint fore, back;
+
+ g_assert (terminal->pvt->palette_initialized);
+
+ string = g_string_new(text);
+
+ vte_terminal_determine_colors_internal (terminal, attr,
+ FALSE, FALSE,
+ &fore, &back);
+
+ if (attr->bold || attr->standout) {
+ g_string_prepend(string, "<b>");
+ g_string_append(string, "</b>");
+ }
+ if (attr->fore != VTE_DEFAULT_FG || attr->reverse) {
+ PangoColor color;
+ char *tag;
+
+ vte_terminal_get_rgb_from_index(terminal, attr->fore, &color);
+ tag = g_strdup_printf("<font color=\"#%02X%02X%02X\">",
+ color.red >> 8,
+ color.green >> 8,
+ color.blue >> 8);
+ g_string_prepend(string, tag);
+ g_free(tag);
+ g_string_append(string, "</font>");
+ }
+ if (attr->back != VTE_DEFAULT_BG || attr->reverse) {
+ PangoColor color;
+ char *tag;
+
+ vte_terminal_get_rgb_from_index(terminal, attr->back, &color);
+ tag = g_strdup_printf("<span style=\"background-color:#%02X%02X%02X\">",
+ color.red >> 8,
+ color.green >> 8,
+ color.blue >> 8);
+ g_string_prepend(string, tag);
+ g_free(tag);
+ g_string_append(string, "</span>");
+ }
+ if (attr->underline) {
+ g_string_prepend(string, "<u>");
+ g_string_append(string, "</u>");
+ }
+ if (attr->strikethrough) {
+ g_string_prepend(string, "<strike>");
+ g_string_append(string, "</strike>");
+ }
+ if (attr->blink) {
+ g_string_prepend(string, "<blink>");
+ g_string_append(string, "</blink>");
+ }
+ // reverse and invisible are not supported
+
+ return g_string_free(string, FALSE);
+}
+
+/*
+ * Similar to vte_terminal_find_charcell, but takes a VteCharAttribute for
+ * indexing and returns the VteCellAttr.
+ */
+static const VteCellAttr *
+vte_terminal_char_to_cell_attr(VteTerminal *terminal, VteCharAttributes *attr)
+{
+ const VteCell *cell;
+
+ cell = vte_terminal_find_charcell(terminal, attr->column, attr->row);
+ if (cell)
+ return &cell->attr;
+ return NULL;
+}
+
+
+/**
+ * vte_terminal_attributes_to_html:
+ * @terminal: a #VteTerminal
+ * @text: A string as returned by the vte_terminal_get_* family of functions.
+ * @attrs: (array) (element-type Vte.CharAttributes): text attributes, as created by vte_terminal_get_*
+ *
+ * Marks the given text up according to the given attributes, using HTML <span>
+ * commands, and wraps the string in a <pre> element. The attributes have to be
+ * "fresh" in the sense that the terminal must not have changed since they were
+ * obtained using the vte_terminal_get* function.
+ *
+ * Returns: (transfer full): a newly allocated text string, or %NULL.
+ */
+char *
+vte_terminal_attributes_to_html(VteTerminal *terminal, const gchar *text, GArray *attrs) {
+ GString *string;
+ guint from,to;
+ const VteCellAttr *attr;
+ char *escaped, *marked;
+
+ g_assert(strlen(text) == attrs->len);
+
+ // Initial size fits perfectly if the text has no attributes and no
+ // characters that need to be escaped
+ string = g_string_sized_new (strlen(text) + 11);
+
+ g_string_append(string, "<pre>");
+ // Find streches with equal attributes. Newlines are treated specially,
+ // so that the <span> do not cover multiple lines.
+ from = to = 0;
+ while (text[from] != '\0') {
+ g_assert(from == to);
+ if (text[from] == '\n') {
+ g_string_append_c(string, '\n');
+ from = ++to;
+ } else {
+ attr = vte_terminal_char_to_cell_attr(terminal,
+ &g_array_index(attrs, VteCharAttributes, from));
+ while (text[to] != '\0' && text[to] != '\n' &&
+ vte_terminal_cellattr_equal(attr,
+ vte_terminal_char_to_cell_attr(terminal,
+ &g_array_index(attrs, VteCharAttributes, to))))
+ {
+ to++;
+ }
+ escaped = g_markup_escape_text(text + from, to - from);
+ marked = vte_terminal_cellattr_to_html(terminal, attr, escaped);
+ g_string_append(string, marked);
+ g_free(escaped);
+ g_free(marked);
+ from = to;
+ }
+ }
+ g_string_append(string, "</pre>");
+
+ return g_string_free(string, FALSE);
+}
+
/**
* vte_terminal_get_cursor_position:
* @terminal: a #VteTerminal
@@ -6212,28 +6407,24 @@ vte_terminal_get_cursor_position(VteTerminal *terminal,
}
}
-static GtkClipboard *
-vte_terminal_clipboard_get(VteTerminal *terminal, GdkAtom board)
-{
- GdkDisplay *display;
- display = gtk_widget_get_display(&terminal->widget);
- return gtk_clipboard_get_for_display(display, board);
-}
-
/* Place the selected text onto the clipboard. Do this asynchronously so that
* we get notified when the selection we placed on the clipboard is replaced. */
static void
-vte_terminal_copy(VteTerminal *terminal, GdkAtom board)
+vte_terminal_copy(VteTerminal *terminal, VteSelection sel)
{
GtkClipboard *clipboard;
static GtkTargetEntry *targets = NULL;
static gint n_targets = 0;
+ GArray *attributes;
- clipboard = vte_terminal_clipboard_get(terminal, board);
+ clipboard = terminal->pvt->clipboard[sel];
+
+ attributes = g_array_new(FALSE, TRUE, sizeof(struct _VteCharAttributes));
/* Chuck old selected text and retrieve the newly-selected text. */
- g_free(terminal->pvt->selection);
- terminal->pvt->selection =
+ g_free(terminal->pvt->selection_text[sel]);
+ g_free(terminal->pvt->selection_html[sel]);
+ terminal->pvt->selection_text[sel] =
vte_terminal_get_text_range(terminal,
terminal->pvt->selection_start.row,
0,
@@ -6241,18 +6432,29 @@ vte_terminal_copy(VteTerminal *terminal, GdkAtom board)
terminal->pvt->column_count,
vte_cell_is_selected,
NULL,
- NULL);
- terminal->pvt->has_selection = TRUE;
+ attributes);
+ terminal->pvt->selection_html[sel] =
+ vte_terminal_attributes_to_html(terminal,
+ terminal->pvt->selection_text[sel],
+ attributes);
+ g_array_free (attributes, TRUE);
+
+ if (sel == VTE_SELECTION_PRIMARY)
+ terminal->pvt->has_selection = TRUE;
/* Place the text on the clipboard. */
- if (terminal->pvt->selection != NULL) {
+ if (terminal->pvt->selection_text[sel] != NULL) {
_vte_debug_print(VTE_DEBUG_SELECTION,
"Assuming ownership of selection.\n");
if (!targets) {
GtkTargetList *list;
list = gtk_target_list_new (NULL, 0);
- gtk_target_list_add_text_targets (list, 0);
+ gtk_target_list_add_text_targets (list, VTE_TARGET_TEXT);
+ gtk_target_list_add (list,
+ gdk_atom_intern("text/html", FALSE),
+ 0,
+ VTE_TARGET_HTML);
targets = gtk_target_table_new_from_list (list, &n_targets);
gtk_target_list_unref (list);
}
@@ -8126,6 +8328,7 @@ vte_terminal_init(VteTerminal *terminal)
{
VteTerminalPrivate *pvt;
GtkStyleContext *context;
+ GdkDisplay *display;
_vte_debug_print(VTE_DEBUG_LIFECYCLE, "vte_terminal_init()\n");
@@ -8213,6 +8416,11 @@ vte_terminal_init(VteTerminal *terminal)
pvt->scrollback_lines = -1; /* force update in vte_terminal_set_scrollback_lines */
vte_terminal_set_scrollback_lines(terminal, VTE_SCROLLBACK_INIT);
+ /* Selection info. */
+ display = gtk_widget_get_display(&terminal->widget);
+ pvt->clipboard[VTE_SELECTION_PRIMARY] = gtk_clipboard_get_for_display(display, GDK_SELECTION_PRIMARY);
+ pvt->clipboard[VTE_SELECTION_CLIPBOARD] = gtk_clipboard_get_for_display(display, GDK_SELECTION_CLIPBOARD);
+
/* Miscellaneous options. */
vte_terminal_set_backspace_binding(terminal, VTE_ERASE_AUTO);
vte_terminal_set_delete_binding(terminal, VTE_ERASE_AUTO);
@@ -8565,6 +8773,7 @@ vte_terminal_finalize(GObject *object)
VteTerminalPrivate *pvt = terminal->pvt;
GtkClipboard *clipboard;
GtkSettings *settings;
+ VteSelection sel;
struct vte_match_regex *regex;
guint i;
@@ -8624,15 +8833,17 @@ vte_terminal_finalize(GObject *object)
/* Free any selected text, but if we currently own the selection,
* throw the text onto the clipboard without an owner so that it
* doesn't just disappear. */
- if (terminal->pvt->selection != NULL) {
- clipboard = vte_terminal_clipboard_get(terminal,
- GDK_SELECTION_PRIMARY);
- if (gtk_clipboard_get_owner(clipboard) == object) {
- gtk_clipboard_set_text(clipboard,
- terminal->pvt->selection,
- -1);
+ for (sel = VTE_SELECTION_PRIMARY; sel < LAST_VTE_SELECTION; sel++) {
+ if (terminal->pvt->selection_text[sel] != NULL) {
+ clipboard = terminal->pvt->clipboard[sel];
+ if (gtk_clipboard_get_owner(clipboard) == object) {
+ gtk_clipboard_set_text(clipboard,
+ terminal->pvt->selection_text[sel],
+ -1);
+ }
+ g_free(terminal->pvt->selection_text[sel]);
+ g_free(terminal->pvt->selection_html[sel]);
}
- g_free(terminal->pvt->selection);
}
/* Clear the output histories. */
@@ -8837,19 +9048,18 @@ swap (guint *a, guint *b)
static void
vte_terminal_determine_colors_internal(VteTerminal *terminal,
- const VteCell *cell,
+ const VteCellAttr *attr,
gboolean selected,
gboolean cursor,
guint *pfore, guint *pback)
{
guint fore, back;
- if (!cell)
- cell = &basic_cell.cell;
+ g_assert(attr);
/* Start with cell colors */
- fore = cell->attr.fore;
- back = cell->attr.back;
+ fore = attr->fore;
+ back = attr->back;
/* Reverse-mode switches default fore and back colors */
if (G_UNLIKELY (terminal->pvt->screen->reverse_mode)) {
@@ -8860,7 +9070,7 @@ vte_terminal_determine_colors_internal(VteTerminal *terminal,
}
/* Handle bold by using set bold color or brightening */
- if (cell->attr.bold) {
+ if (attr->bold) {
if (fore == VTE_DEFAULT_FG)
fore = VTE_BOLD_FG;
else if (fore >= VTE_LEGACY_COLORS_OFFSET && fore < VTE_LEGACY_COLORS_OFFSET + VTE_LEGACY_COLOR_SET_SIZE) {
@@ -8869,7 +9079,7 @@ vte_terminal_determine_colors_internal(VteTerminal *terminal,
}
/* Handle half similarly */
- if (cell->attr.half) {
+ if (attr->half) {
if (fore == VTE_DEFAULT_FG)
fore = VTE_DIM_FG;
else if (fore >= VTE_LEGACY_COLORS_OFFSET && fore < VTE_LEGACY_COLORS_OFFSET + VTE_LEGACY_COLOR_SET_SIZE)
@@ -8877,13 +9087,13 @@ vte_terminal_determine_colors_internal(VteTerminal *terminal,
}
/* And standout */
- if (cell->attr.standout) {
+ if (attr->standout) {
if (back >= VTE_LEGACY_COLORS_OFFSET && back < VTE_LEGACY_COLORS_OFFSET + VTE_LEGACY_COLOR_SET_SIZE)
back += VTE_COLOR_BRIGHT_OFFSET;
}
/* Reverse cell? */
- if (cell->attr.reverse) {
+ if (attr->reverse) {
swap (&fore, &back);
}
@@ -8913,7 +9123,7 @@ vte_terminal_determine_colors_internal(VteTerminal *terminal,
}
/* Invisible? */
- if (cell && cell->attr.invisible) {
+ if (attr->invisible) {
fore = back;
}
@@ -8927,7 +9137,7 @@ vte_terminal_determine_colors (VteTerminal *terminal,
gboolean highlight,
guint *fore, guint *back)
{
- vte_terminal_determine_colors_internal (terminal, cell,
+ vte_terminal_determine_colors_internal (terminal, cell ? &cell->attr : &basic_cell.cell.attr,
highlight, FALSE,
fore, back);
}
@@ -8938,7 +9148,7 @@ vte_terminal_determine_cursor_colors (VteTerminal *terminal,
gboolean highlight,
guint *fore, guint *back)
{
- vte_terminal_determine_colors_internal (terminal, cell,
+ vte_terminal_determine_colors_internal (terminal, cell ? &cell->attr : &basic_cell.cell.attr,
highlight, TRUE,
fore, back);
}
@@ -12121,16 +12331,12 @@ vte_terminal_get_rewrap_on_resize(VteTerminal *terminal)
return terminal->pvt->rewrap_on_resize;
}
+/* Place the selected text onto the CLIPBOARD clipboard. Do this
+ * asynchronously, so that we can support the html target as well */
static void
vte_terminal_real_copy_clipboard(VteTerminal *terminal)
{
- _vte_debug_print(VTE_DEBUG_SELECTION, "Copying to CLIPBOARD.\n");
- if (terminal->pvt->selection != NULL) {
- GtkClipboard *clipboard;
- clipboard = vte_terminal_clipboard_get(terminal,
- GDK_SELECTION_CLIPBOARD);
- gtk_clipboard_set_text(clipboard, terminal->pvt->selection, -1);
- }
+ vte_terminal_copy(terminal, VTE_SELECTION_CLIPBOARD);
}
/**
@@ -12182,7 +12388,7 @@ vte_terminal_copy_primary(VteTerminal *terminal)
{
g_return_if_fail(VTE_IS_TERMINAL(terminal));
_vte_debug_print(VTE_DEBUG_SELECTION, "Copying to PRIMARY.\n");
- vte_terminal_copy(terminal, GDK_SELECTION_PRIMARY);
+ vte_terminal_copy(terminal, VTE_SELECTION_PRIMARY);
}
/**
@@ -12576,6 +12782,7 @@ vte_terminal_reset(VteTerminal *terminal,
{
VteTerminalPrivate *pvt;
int i;
+ VteSelection sel;
g_return_if_fail(VTE_IS_TERMINAL(terminal));
@@ -12699,18 +12906,23 @@ vte_terminal_reset(VteTerminal *terminal,
pvt->selecting = FALSE;
pvt->selecting_restart = FALSE;
pvt->selecting_had_delta = FALSE;
- if (pvt->selection != NULL) {
- g_free(pvt->selection);
- pvt->selection = NULL;
- memset(&pvt->selection_origin, 0,
- sizeof(pvt->selection_origin));
- memset(&pvt->selection_last, 0,
- sizeof(pvt->selection_last));
- memset(&pvt->selection_start, 0,
- sizeof(pvt->selection_start));
- memset(&pvt->selection_end, 0,
- sizeof(pvt->selection_end));
- }
+ for (sel = VTE_SELECTION_PRIMARY; sel < LAST_VTE_SELECTION; sel++) {
+ if (pvt->selection_text[sel] != NULL) {
+ g_free(pvt->selection_text[sel]);
+ g_free(pvt->selection_html[sel]);
+ pvt->selection_text[sel] = NULL;
+ pvt->selection_html[sel] = NULL;
+ }
+ }
+ memset(&pvt->selection_origin, 0,
+ sizeof(pvt->selection_origin));
+ memset(&pvt->selection_last, 0,
+ sizeof(pvt->selection_last));
+ memset(&pvt->selection_start, 0,
+ sizeof(pvt->selection_start));
+ memset(&pvt->selection_end, 0,
+ sizeof(pvt->selection_end));
+
/* Reset mouse motion events. */
pvt->mouse_tracking_mode = MOUSE_TRACKING_NONE;
pvt->mouse_last_button = 0;
@@ -12986,7 +13198,7 @@ _vte_terminal_get_selection(VteTerminal *terminal)
{
g_return_val_if_fail(VTE_IS_TERMINAL(terminal), NULL);
- return g_strdup (terminal->pvt->selection);
+ return g_strdup (terminal->pvt->selection_text[VTE_SELECTION_PRIMARY]);
}
void
diff --git a/src/vte.h b/src/vte.h
index e1c60db0..abd7be94 100644
--- a/src/vte.h
+++ b/src/vte.h
@@ -318,6 +318,9 @@ char *vte_terminal_get_text_range(VteTerminal *terminal,
VteSelectionFunc is_selected,
gpointer user_data,
GArray *attributes);
+char *vte_terminal_attributes_to_html(VteTerminal *terminal,
+ const gchar *text,
+ GArray *attributes);
void vte_terminal_get_cursor_position(VteTerminal *terminal,
glong *column, glong *row);