summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdk/gdkproperty.h13
-rw-r--r--gdk/x11/gdkevents-x11.c70
-rw-r--r--gdk/x11/gdkprivate-x11.h6
-rw-r--r--gdk/x11/gdkselection-x11.c390
-rw-r--r--gdk/x11/gdkwindow-x11.c2
-rw-r--r--gdk/x11/gdkx.h2
-rw-r--r--gtk/gtkclipboard.c806
-rw-r--r--gtk/gtkclipboard.h87
-rw-r--r--gtk/gtkenums.h25
-rw-r--r--gtk/gtkinvisible.c5
-rw-r--r--gtk/gtkmain.c29
-rw-r--r--gtk/gtkmain.h4
-rw-r--r--gtk/gtkselection.c233
-rw-r--r--gtk/gtkselection.h47
-rw-r--r--gtk/gtktextbuffer.c619
-rw-r--r--gtk/gtktextbuffer.h35
-rw-r--r--gtk/gtktextlayout.c54
-rw-r--r--gtk/gtktextlayout.h4
-rw-r--r--gtk/gtktextview.c570
-rw-r--r--gtk/gtktextview.h44
20 files changed, 2072 insertions, 973 deletions
diff --git a/gdk/gdkproperty.h b/gdk/gdkproperty.h
index 2bb9770229..2255d30d3c 100644
--- a/gdk/gdkproperty.h
+++ b/gdk/gdkproperty.h
@@ -43,6 +43,19 @@ gint gdk_text_property_to_text_list (GdkAtom encoding,
const guchar *text,
gint length,
gchar ***list);
+gint gdk_text_property_to_utf8_list (GdkAtom encoding,
+ gint format,
+ const guchar *text,
+ gint length,
+ gchar ***list);
+
+gchar *gdk_utf8_to_string_target (const gchar *str);
+gboolean gdk_utf8_to_compound_text (const gchar *str,
+ GdkAtom *encoding,
+ gint *format,
+ guchar **ctext,
+ gint *length);
+
void gdk_free_text_list (gchar **list);
gint gdk_string_to_compound_text (const gchar *str,
GdkAtom *encoding,
diff --git a/gdk/x11/gdkevents-x11.c b/gdk/x11/gdkevents-x11.c
index a389dc4afa..cb1e107112 100644
--- a/gdk/x11/gdkevents-x11.c
+++ b/gdk/x11/gdkevents-x11.c
@@ -1059,12 +1059,17 @@ gdk_event_translate (GdkEvent *event,
GDK_NOTE (EVENTS,
g_message ("selection clear:\twindow: %ld",
xevent->xproperty.window));
-
- event->selection.type = GDK_SELECTION_CLEAR;
- event->selection.window = window;
- event->selection.selection = xevent->xselectionclear.selection;
- event->selection.time = xevent->xselectionclear.time;
-
+
+ if (_gdk_selection_filter_clear_event (&xevent->xselectionclear))
+ {
+ event->selection.type = GDK_SELECTION_CLEAR;
+ event->selection.window = window;
+ event->selection.selection = xevent->xselectionclear.selection;
+ event->selection.time = xevent->xselectionclear.time;
+ }
+ else
+ return_val = FALSE;
+
break;
case SelectionRequest:
@@ -1494,4 +1499,57 @@ gdk_flush (void)
XSync (gdk_display, False);
}
+static GdkAtom timestamp_prop_atom = 0;
+
+static Bool
+timestamp_predicate (Display *display,
+ XEvent *xevent,
+ XPointer arg)
+{
+ Window xwindow = GPOINTER_TO_UINT (arg);
+
+ if (xevent->type == PropertyNotify &&
+ xevent->xproperty.window == xwindow &&
+ xevent->xproperty.atom == timestamp_prop_atom)
+ return True;
+
+ return False;
+}
+
+/**
+ * gdk_x11_get_server_time:
+ * @window: a #GdkWindow, used for communication with the server.
+ * The window must have GDK_PROPERTY_CHANGE_MASK in its
+ * events mask or a hang will result.
+ *
+ * Routine to get the current X server time stamp.
+ *
+ * Return value: the time stamp.
+ **/
+guint32
+gdk_x11_get_server_time (GdkWindow *window)
+{
+ Display *xdisplay;
+ Window xwindow;
+ guchar c = 'a';
+ XEvent xevent;
+
+ g_return_val_if_fail (GDK_IS_WINDOW (window), 0);
+ g_return_val_if_fail (!GDK_WINDOW_DESTROYED (window), 0);
+
+ if (!timestamp_prop_atom)
+ timestamp_prop_atom = gdk_atom_intern ("GDK_TIMESTAMP_PROP", FALSE);
+
+ xdisplay = GDK_WINDOW_XDISPLAY (window);
+ xwindow = GDK_WINDOW_XWINDOW (window);
+
+ XChangeProperty (xdisplay, xwindow,
+ timestamp_prop_atom, timestamp_prop_atom,
+ 8, PropModeReplace, &c, 1);
+
+ XIfEvent (xdisplay, &xevent,
+ timestamp_predicate, GUINT_TO_POINTER(xwindow));
+
+ return xevent.xproperty.time;
+}
diff --git a/gdk/x11/gdkprivate-x11.h b/gdk/x11/gdkprivate-x11.h
index a521412622..8a600ee694 100644
--- a/gdk/x11/gdkprivate-x11.h
+++ b/gdk/x11/gdkprivate-x11.h
@@ -73,13 +73,15 @@ void _gdk_window_process_expose (GdkWindow *window,
gulong serial,
GdkRectangle *area);
+void _gdk_selection_window_destroyed (GdkWindow *window);
+gboolean _gdk_selection_filter_clear_event (XSelectionClearEvent *event);
+
extern GdkDrawableClass _gdk_x11_drawable_class;
extern gboolean gdk_use_xshm;
extern Atom gdk_wm_delete_window;
extern Atom gdk_wm_take_focus;
extern Atom gdk_wm_protocols;
extern Atom gdk_wm_window_protocols[];
-extern GdkWindow *selection_owner[];
extern gboolean gdk_null_window_warnings;
extern const int gdk_nevent_masks;
extern const int gdk_event_mask_table[];
@@ -95,5 +97,3 @@ extern GdkWindow *gdk_xim_window; /* currently using Window */
#endif /* __GDK_PRIVATE_X11_H__ */
-
-
diff --git a/gdk/x11/gdkselection-x11.c b/gdk/x11/gdkselection-x11.c
index 232dcf6394..1879226788 100644
--- a/gdk/x11/gdkselection-x11.c
+++ b/gdk/x11/gdkselection-x11.c
@@ -33,6 +33,66 @@
#include "gdkprivate.h"
#include "gdkprivate-x11.h"
+typedef struct _OwnerInfo OwnerInfo;
+
+struct _OwnerInfo
+{
+ GdkAtom selection;
+ GdkWindow *owner;
+ gulong serial;
+};
+
+GSList *owner_list;
+
+/* When a window is destroyed we check if it is the owner
+ * of any selections. This is somewhat inefficient, but
+ * owner_list is typically short, and it is a low memory,
+ * low code solution
+ */
+void
+_gdk_selection_window_destroyed (GdkWindow *window)
+{
+ GSList *tmp_list = owner_list;
+ while (tmp_list)
+ {
+ OwnerInfo *info = tmp_list->data;
+ if (info->owner == window)
+ {
+ owner_list = g_slist_remove (owner_list, info);
+ g_free (info);
+ }
+ tmp_list = tmp_list->next;
+ }
+}
+
+/* We only pass through those SelectionClear events that actually
+ * reflect changes to the selection owner that we didn't make ourself.
+ */
+gboolean
+_gdk_selection_filter_clear_event (XSelectionClearEvent *event)
+{
+ GSList *tmp_list = owner_list;
+
+ while (tmp_list)
+ {
+ OwnerInfo *info = tmp_list->data;
+ if (info->selection == event->selection)
+ {
+ if ((GDK_DRAWABLE_XID (info->owner) == event->window &&
+ event->serial >= info->serial))
+ {
+ owner_list = g_slist_remove (owner_list, info);
+ g_free (info);
+ return TRUE;
+ }
+ else
+ return FALSE;
+ }
+ tmp_list = tmp_list->next;
+ }
+
+ return FALSE;
+}
gboolean
gdk_selection_owner_set (GdkWindow *owner,
@@ -42,6 +102,8 @@ gdk_selection_owner_set (GdkWindow *owner,
{
Display *xdisplay;
Window xwindow;
+ GSList *tmp_list;
+ OwnerInfo *info;
if (owner)
{
@@ -56,6 +118,29 @@ gdk_selection_owner_set (GdkWindow *owner,
xdisplay = gdk_display;
xwindow = None;
}
+
+ tmp_list = owner_list;
+ while (tmp_list)
+ {
+ info = tmp_list->data;
+ if (info->selection == selection)
+ {
+ owner_list = g_slist_remove (owner_list, info);
+ g_free (info);
+ break;
+ }
+ tmp_list = tmp_list->next;
+ }
+
+ if (owner)
+ {
+ info = g_new (OwnerInfo, 1);
+ info->owner = owner;
+ info->serial = NextRequest (GDK_WINDOW_XDISPLAY (owner));
+ info->selection = selection;
+
+ owner_list = g_slist_prepend (owner_list, info);
+ }
XSetSelectionOwner (xdisplay, selection, xwindow, time);
@@ -221,6 +306,166 @@ gdk_free_text_list (gchar **list)
XFreeStringList (list);
}
+static gint
+make_list (const gchar *text,
+ gint length,
+ gboolean latin1,
+ gchar ***list)
+{
+ GSList *strings = NULL;
+ gint n_strings = 0;
+ gint i;
+ const gchar *p = text;
+ const gchar *q;
+ GSList *tmp_list;
+ GError *error = NULL;
+
+ while (p < text + length)
+ {
+ gchar *str;
+
+ q = p;
+ while (*q && q < text + length)
+ q++;
+
+ if (latin1)
+ {
+ str = g_convert (p, q - p,
+ "UTF-8", "ISO-8859-1",
+ NULL, NULL, &error);
+
+ if (!str)
+ {
+ g_warning ("Error converting selection from STRING: %s",
+ error->message);
+ g_error_free (error);
+ }
+ }
+ else
+ str = g_strndup (p, q - p);
+
+ if (str)
+ {
+ strings = g_slist_prepend (strings, str);
+ n_strings++;
+ }
+
+ p = q + 1;
+ }
+
+ if (list)
+ *list = g_new (gchar *, n_strings + 1);
+
+ (*list)[n_strings] = NULL;
+
+ i = n_strings;
+ tmp_list = strings;
+ while (tmp_list)
+ {
+ if (list)
+ (*list)[--i] = tmp_list->data;
+ else
+ g_free (tmp_list->data);
+
+ tmp_list = tmp_list->next;
+ }
+
+ g_slist_free (strings);
+
+ return n_strings;
+}
+
+/**
+ * gdk_text_property_to_utf8_list:
+ * @encoding: an atom representing the encoding of the text
+ * @format: the format of the property
+ * @text: the text to convert
+ * @length: the length of @text, in bytes
+ * @list: location to store the list of strings or %NULL. The
+ * list should be freed with g_strfreev().
+ *
+ * Convert a text property in the giving encoding to
+ * a list of UTF-8 strings.
+ *
+ * Return value: the number of strings in the resulting
+ * list.
+ **/
+gint
+gdk_text_property_to_utf8_list (GdkAtom encoding,
+ gint format,
+ const guchar *text,
+ gint length,
+ gchar ***list)
+{
+ g_return_val_if_fail (text != NULL, 0);
+ g_return_val_if_fail (length >= 0, 0);
+
+ if (encoding == GDK_TARGET_STRING)
+ {
+ return make_list ((gchar *)text, length, TRUE, list);
+ }
+ else if (encoding == gdk_atom_intern ("UTF8_STRING", FALSE))
+ {
+ return make_list ((gchar *)text, length, FALSE, list);
+ }
+ else
+ {
+ gchar **local_list;
+ gint local_count;
+ gint i;
+ gchar *charset = NULL;
+ gboolean need_conversion= g_get_charset (&charset);
+ gint count = 0;
+ GError *error = NULL;
+
+ /* Probably COMPOUND text, we fall back to Xlib routines
+ */
+ local_count = gdk_text_property_to_text_list (encoding,
+ format,
+ text,
+ length,
+ &local_list);
+ if (list)
+ *list = g_new (gchar *, local_count + 1);
+
+ for (i=0; i<local_count; i++)
+ {
+ /* list contains stuff in our default encoding
+ */
+ if (need_conversion)
+ {
+ gchar *utf = g_convert (local_list[i], -1,
+ "UTF-8", charset,
+ NULL, NULL, &error);
+ if (utf)
+ {
+ if (list)
+ (*list)[count++] = utf;
+ else
+ g_free (utf);
+ }
+ else
+ {
+ g_warning ("Error converting to UTF-8 from '%s': %s",
+ charset, error->message);
+ g_error_free (error);
+ error = NULL;
+ }
+ }
+ else
+ {
+ if (list)
+ (*list)[count++] = g_strdup (local_list[i]);
+ }
+ }
+
+ gdk_free_text_list (local_list);
+ (*list)[count] = NULL;
+
+ return count;
+ }
+}
+
gint
gdk_string_to_compound_text (const gchar *str,
GdkAtom *encoding,
@@ -254,6 +499,151 @@ gdk_string_to_compound_text (const gchar *str,
return res;
}
+/* The specifications for COMPOUND_TEXT and STRING specify that C0 and
+ * C1 are not allowed except for \n and \t, however the X conversions
+ * routines for COMPOUND_TEXT only enforce this in one direction,
+ * causing cut-and-paste of \r and \r\n separated text to fail.
+ * This routine strips out all non-allowed C0 and C1 characters
+ * from the input string and also canonicalizes \r, \r\n, and \n\r to \n
+ */
+static gchar *
+sanitize_utf8 (const gchar *src)
+{
+ gint len = strlen (src);
+ GString *result = g_string_sized_new (len);
+ const gchar *p = src;
+
+ while (*p)
+ {
+ if (*p == '\r' || *p == '\n')
+ {
+ p++;
+ if (*p == '\r' || *p == '\n')
+ p++;
+
+ g_string_append_c (result, '\n');
+ }
+ else
+ {
+ gunichar ch = g_utf8_get_char (p);
+ char buf[7];
+ gint buflen;
+
+ if (!((ch < 0x20 && ch != '\t') || (ch >= 0x7f && ch < 0xa0)))
+ {
+ buflen = g_unichar_to_utf8 (ch, buf);
+ g_string_append_len (result, buf, buflen);
+ }
+
+ p = g_utf8_next_char (p);
+ }
+ }
+
+ return g_string_free (result, FALSE);
+}
+
+/**
+ * gdk_utf8_to_string_target:
+ * @str: a UTF-8 string
+ *
+ * Convert an UTF-8 string into the best possible representation
+ * as a STRING. The representation of characters not in STRING
+ * is not specified; it may be as pseudo-escape sequences
+ * \x{ABCD}, or it may be in some other form of approximation.
+ *
+ * Return value: the newly allocated string, or %NULL if the
+ * conversion failed. (It should not fail for
+ * any properly formed UTF-8 string.)
+ **/
+gchar *
+gdk_utf8_to_string_target (const gchar *str)
+{
+ GError *error = NULL;
+
+ gchar *tmp_str = sanitize_utf8 (str);
+ gchar *result = g_convert_with_fallback (tmp_str, -1,
+ "ISO-8859-1", "UTF-8",
+ NULL, NULL, NULL, &error);
+ if (!result)
+ {
+ g_warning ("Error converting from UTF-8 to STRING: %s",
+ error->message);
+ g_error_free (error);
+ }
+
+ g_free (tmp_str);
+ return result;
+}
+
+/**
+ * gdk_utf8_to_compound_text:
+ * @str: a UTF-8 string
+ * @encoding: location to store resulting encoding
+ * @format: location to store format of the result
+ * @ctext: location to store the data of the result
+ * @length: location to store the length of the data
+ * stored in @ctext
+ *
+ * Convert from UTF-8 to compound text.
+ *
+ * Return value: %TRUE if the conversion succeeded, otherwise
+ * false.
+ **/
+gboolean
+gdk_utf8_to_compound_text (const gchar *str,
+ GdkAtom *encoding,
+ gint *format,
+ guchar **ctext,
+ gint *length)
+{
+ gboolean need_conversion;
+ gchar *charset;
+ gchar *locale_str, *tmp_str;
+ GError *error = NULL;
+ gboolean result;
+
+ g_return_val_if_fail (str != NULL, FALSE);
+
+ need_conversion = g_get_charset (&charset);
+
+ tmp_str = sanitize_utf8 (str);
+
+ if (need_conversion)
+ {
+ locale_str = g_convert_with_fallback (tmp_str, -1,
+ charset, "UTF-8",
+ NULL, NULL, NULL, &error);
+ g_free (tmp_str);
+
+ if (!locale_str)
+ {
+ g_warning ("Error converting from UTF-8 to '%s': %s",
+ charset, error->message);
+ g_error_free (error);
+
+ if (encoding)
+ *encoding = None;
+ if (format)
+ *format = None;
+ if (ctext)
+ *ctext = NULL;
+ if (length)
+ *length = 0;
+
+ return FALSE;
+ }
+ }
+ else
+ locale_str = tmp_str;
+
+ result = gdk_string_to_compound_text (locale_str,
+ encoding, format, ctext, length);
+
+ g_free (locale_str);
+
+ return result;
+}
+
void gdk_free_compound_text (guchar *ctext)
{
if (ctext)
diff --git a/gdk/x11/gdkwindow-x11.c b/gdk/x11/gdkwindow-x11.c
index d4741a4f72..761782d9f0 100644
--- a/gdk/x11/gdkwindow-x11.c
+++ b/gdk/x11/gdkwindow-x11.c
@@ -630,6 +630,8 @@ _gdk_windowing_window_destroy (GdkWindow *window,
GdkWindowObject *private = (GdkWindowObject *)window;
g_return_if_fail (GDK_IS_WINDOW (window));
+
+ _gdk_selection_window_destroyed (window);
if (private->extension_events != 0)
gdk_input_window_destroy (window);
diff --git a/gdk/x11/gdkx.h b/gdk/x11/gdkx.h
index 72c7d72bd2..697afea9ad 100644
--- a/gdk/x11/gdkx.h
+++ b/gdk/x11/gdkx.h
@@ -178,6 +178,8 @@ GdkWindow *gdk_window_foreign_new (GdkNativeWindow anid);
/* Return the Gdk* for a particular XID */
gpointer gdk_xid_table_lookup (XID xid);
+guint32 gdk_x11_get_server_time (GdkWindow *window);
+
#define gdk_window_lookup(xid) ((GdkWindow*) gdk_xid_table_lookup (xid))
#define gdk_pixmap_lookup(xid) ((GdkPixmap*) gdk_xid_table_lookup (xid))
#define gdk_font_lookup(xid) ((GdkFont*) gdk_xid_table_lookup (xid))
diff --git a/gtk/gtkclipboard.c b/gtk/gtkclipboard.c
new file mode 100644
index 0000000000..6df1843cfb
--- /dev/null
+++ b/gtk/gtkclipboard.c
@@ -0,0 +1,806 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2000 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Global clipboard abstraction.
+ */
+
+#include <string.h>
+
+#include "gtkclipboard.h"
+#include "gtkinvisible.h"
+#include "gtkmain.h"
+#include "gtksignal.h"
+
+#ifdef GDK_WINDOWING_X11
+#include "x11/gdkx.h"
+#endif
+
+typedef struct _RequestContentsInfo RequestContentsInfo;
+typedef struct _RequestTextInfo RequestTextInfo;
+
+struct _GtkClipboard
+{
+ GdkAtom selection;
+
+ GtkClipboardGetFunc get_func;
+ GtkClipboardClearFunc clear_func;
+ gpointer user_data;
+ gboolean have_owner;
+
+ guint32 timestamp;
+
+ gboolean have_selection;
+};
+
+struct _RequestContentsInfo
+{
+ GtkClipboardReceivedFunc callback;
+ gpointer user_data;
+};
+
+struct _RequestTextInfo
+{
+ GtkClipboardTextReceivedFunc callback;
+ gpointer user_data;
+};
+
+static void clipboard_unset (GtkClipboard *clipboard);
+static void selection_received (GtkWidget *widget,
+ GtkSelectionData *selection_data,
+ guint time);
+
+static GSList *clipboards;
+static GtkWidget *clipboard_widget;
+
+enum {
+ TARGET_STRING,
+ TARGET_TEXT,
+ TARGET_COMPOUND_TEXT,
+ TARGET_UTF8_STRING
+};
+
+static const gchar *request_contents_key = "gtk-request-contents";
+static GQuark request_contents_key_id = 0;
+
+static const gchar *clipboards_owned_key = "gtk-clipboards-owned";
+static GQuark clipboards_owned_key_id = 0;
+
+
+/**
+ * gtk_clipboard_get:
+ * @selection: a #GdkAtom which identifies the clipboard
+ * to use. A value of GDK_NONE here is the
+ * same as gdk_atom_intern ("CLIPBOARD", FALSE),
+ * and provides the default clipboard. Another
+ * common value is GDK_SELECTION_PRIMARY, which
+ * identifies the primary X selection.
+ *
+ * Returns the clipboard object for the given selection.
+ *
+ * Return value: the appropriate clipboard object. If no
+ * clipboard already exists, a new one will
+ * be created. Once a clipboard object has
+ * been created, it is persistant for all time.
+ **/
+GtkClipboard *
+gtk_clipboard_get (GdkAtom selection)
+{
+ GtkClipboard *clipboard = NULL;
+ GSList *tmp_list;
+
+ if (selection == GDK_NONE)
+ selection = gdk_atom_intern ("CLIPBOARD", FALSE);
+
+ tmp_list = clipboards;
+ while (tmp_list)
+ {
+ clipboard = tmp_list->data;
+ if (clipboard->selection == selection)
+ break;
+
+ tmp_list = tmp_list->next;
+ }
+
+ if (!tmp_list)
+ {
+ clipboard = g_new0 (GtkClipboard, 1);
+ clipboard->selection = selection;
+ clipboards = g_slist_prepend (clipboards, clipboard);
+ }
+
+ return clipboard;
+}
+
+static void
+selection_get_cb (GtkWidget *widget,
+ GtkSelectionData *selection_data,
+ guint time,
+ guint info)
+{
+ GtkClipboard *clipboard = gtk_clipboard_get (selection_data->selection);
+
+ if (clipboard && clipboard->get_func)
+ clipboard->get_func (clipboard, selection_data, info, clipboard->user_data);
+}
+
+static gboolean
+selection_clear_event_cb (GtkWidget *widget,
+ GdkEventSelection *event)
+{
+ GtkClipboard *clipboard = gtk_clipboard_get (event->selection);
+
+ if (clipboard)
+ {
+ clipboard_unset (clipboard);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+GtkWidget *
+make_clipboard_widget (gboolean provider)
+{
+ GtkWidget *widget = gtk_invisible_new ();
+
+ gtk_signal_connect (GTK_OBJECT (widget), "selection_received",
+ GTK_SIGNAL_FUNC (selection_received), NULL);
+
+ if (provider)
+ {
+ /* We need this for gdk_x11_get_server_time() */
+ gtk_widget_add_events (widget, GDK_PROPERTY_CHANGE_MASK);
+
+ gtk_signal_connect (GTK_OBJECT (widget), "selection_get",
+ GTK_SIGNAL_FUNC (selection_get_cb), NULL);
+ gtk_signal_connect (GTK_OBJECT (widget), "selection_clear_event",
+ GTK_SIGNAL_FUNC (selection_clear_event_cb), NULL);
+ }
+
+ return widget;
+}
+
+
+void
+ensure_clipboard_widget ()
+{
+ if (!clipboard_widget)
+ clipboard_widget = make_clipboard_widget (TRUE);
+}
+
+/* This function makes a very good guess at what the correct
+ * timestamp for a selection request should be. If there is
+ * a currently processed event, it uses the timestamp for that
+ * event, otherwise it uses the current server time. However,
+ * if the time resulting from that is older than the time used
+ * last time, it uses the time used last time instead.
+ *
+ * In order implement this correctly, we never use CurrentTime,
+ * but actually retrieve the actual timestamp from the server.
+ * This is a little slower but allows us to make the guarantee
+ * that the times used by this application will always ascend
+ * and we won't get selections being rejected just because
+ * we are using a correct timestamp from an event, but used
+ * CurrentTime previously.
+ */
+static guint32
+clipboard_get_timestamp (GtkClipboard *clipboard)
+{
+ guint32 timestamp = gtk_get_current_event_time ();
+
+ ensure_clipboard_widget ();
+
+ if (timestamp == GDK_CURRENT_TIME)
+ {
+ timestamp = gdk_x11_get_server_time (clipboard_widget->window);
+ }
+ else
+ {
+ if (clipboard->timestamp != GDK_CURRENT_TIME)
+ {
+ /* Check to see if clipboard->timestamp is newer than
+ * timestamp, accounting for wraparound.
+ */
+
+ guint32 max = timestamp + 0x80000000;
+
+ if ((max > timestamp &&
+ (clipboard->timestamp > timestamp &&
+ clipboard->timestamp <= max)) ||
+ (max <= timestamp &&
+ (clipboard->timestamp > timestamp ||
+ clipboard->timestamp <= max)))
+ {
+ timestamp = clipboard->timestamp;
+ }
+ }
+ }
+
+ clipboard->timestamp = timestamp;
+
+ return timestamp;
+}
+
+static void
+clipboard_owner_destroyed (gpointer data)
+{
+ GSList *clipboards = data;
+ GSList *tmp_list;
+
+ tmp_list = clipboards;
+ while (tmp_list)
+ {
+ GtkClipboard *clipboard = tmp_list->data;
+
+ clipboard->get_func = NULL;
+ clipboard->clear_func = NULL;
+ clipboard->user_data = NULL;
+ clipboard->have_owner = FALSE;
+
+ gtk_clipboard_clear (clipboard);
+
+ tmp_list = tmp_list->next;
+ }
+
+ g_slist_free (clipboards);
+}
+
+static void
+clipboard_add_owner_notify (GtkClipboard *clipboard)
+{
+ if (!clipboards_owned_key_id)
+ clipboards_owned_key_id = g_quark_from_static_string (clipboards_owned_key);
+
+ if (clipboard->have_owner)
+ g_object_set_qdata_full (clipboard->user_data, clipboards_owned_key_id,
+ g_slist_prepend (g_object_steal_qdata (clipboard->user_data,
+ clipboards_owned_key_id),
+ clipboard),
+ clipboard_owner_destroyed);
+}
+
+static void
+clipboard_remove_owner_notify (GtkClipboard *clipboard)
+{
+ if (clipboard->have_owner)
+ g_object_set_qdata_full (clipboard->user_data, clipboards_owned_key_id,
+ g_slist_remove (g_object_steal_qdata (clipboard->user_data,
+ clipboards_owned_key_id),
+ clipboard),
+ clipboard_owner_destroyed);
+}
+
+static gboolean
+gtk_clipboard_set_contents (GtkClipboard *clipboard,
+ const GtkTargetEntry *targets,
+ guint n_targets,
+ GtkClipboardGetFunc get_func,
+ GtkClipboardClearFunc clear_func,
+ gpointer user_data,
+ gboolean have_owner)
+{
+ ensure_clipboard_widget ();
+
+ if (gtk_selection_owner_set (clipboard_widget, clipboard->selection,
+ clipboard_get_timestamp (clipboard)))
+ {
+ clipboard->have_selection = TRUE;
+
+ if (!(clipboard->have_owner && have_owner) ||
+ clipboard->user_data != user_data)
+ {
+ clipboard_unset (clipboard);
+
+ if (clipboard->get_func)
+ {
+ /* Calling unset() caused the clipboard contents to be reset!
+ * Avoid leaking and return
+ */
+ if (!(clipboard->have_owner && have_owner) ||
+ clipboard->user_data != user_data)
+ {
+ (*clear_func) (clipboard, user_data);
+ return FALSE;
+ }
+ else
+ return TRUE;
+ }
+ else
+ {
+ clipboard->user_data = user_data;
+ clipboard->have_owner = have_owner;
+ if (have_owner)
+ clipboard_add_owner_notify (clipboard);
+ }
+
+ }
+
+ clipboard->get_func = get_func;
+ clipboard->clear_func = clear_func;
+
+ gtk_selection_clear_targets (clipboard_widget, clipboard->selection);
+ gtk_selection_add_targets (clipboard_widget, clipboard->selection,
+ targets, n_targets);
+
+ return TRUE;
+ }
+ else
+ return FALSE;
+}
+
+/**
+ * gtk_clipboard_set_with_data:
+ * @clipboard: a #GtkClipboard
+ * @targets: array containing information about the available forms for the
+ * clipboard data
+ * @n_targets: number of elements in @targets
+ * @get_func: function to call to get the actual clipboard data
+ * @clear_func: when the clipboard contents are set again, this function will
+ * be called, and get_func will not be subsequently called.
+ * @user_data: user data to pass to @get_func and @clear_func.
+ *
+ * Virtually set the contents of the specified clipboard by providing
+ * a list of supported formats for the clipboard data and a function
+ * to call to get the actual data when it is requested.
+ *
+ * Return value: %TRUE if setting the clipboard data succeeded. If setting
+ * the clipboard data failed the provided callback functions
+ * will be ignored.
+ **/
+gboolean
+gtk_clipboard_set_with_data (GtkClipboard *clipboard,
+ const GtkTargetEntry *targets,
+ guint n_targets,
+ GtkClipboardGetFunc get_func,
+ GtkClipboardClearFunc clear_func,
+ gpointer user_data)
+{
+ g_return_val_if_fail (clipboard != NULL, FALSE);
+ g_return_val_if_fail (targets != NULL, FALSE);
+ g_return_val_if_fail (get_func != NULL, FALSE);
+
+ return gtk_clipboard_set_contents (clipboard, targets, n_targets,
+ get_func, clear_func, user_data,
+ FALSE);
+}
+
+/**
+ * gtk_clipboard_set_with_owner:
+ * @clipboard: a #GtkClipboard
+ * @targets: array containing information about the available forms for the
+ * clipboard data
+ * @n_targets: number of elements in @targets
+ * @get_func: function to call to get the actual clipboard data
+ * @clear_func: when the clipboard contents are set again, this function will
+ * be called, and get_func will not be subsequently called.
+ * @owner: an object that "owns" the data. This object will be passed
+ * to the callbacks when called.
+ *
+ * Virtually set the contents of the specified clipboard by providing
+ * a list of supported formats for the clipboard data and a function
+ * to call to get the actual data when it is requested.
+ *
+ * The difference between this function and gtk_clipboard_set_with_data
+ * is that instead of an generic @user_data pointer, a #GObject is passed
+ * in. Because of this,
+ *
+ * Return value: %TRUE if setting the clipboard data succeeded. If setting
+ * the clipboard data failed the provided callback functions
+ * will be ignored.
+ **/
+gboolean
+gtk_clipboard_set_with_owner (GtkClipboard *clipboard,
+ const GtkTargetEntry *targets,
+ guint n_targets,
+ GtkClipboardGetFunc get_func,
+ GtkClipboardClearFunc clear_func,
+ GObject *owner)
+{
+ g_return_val_if_fail (clipboard != NULL, FALSE);
+ g_return_val_if_fail (targets != NULL, FALSE);
+ g_return_val_if_fail (get_func != NULL, FALSE);
+ g_return_val_if_fail (G_IS_OBJECT (owner), FALSE);
+
+ return gtk_clipboard_set_contents (clipboard, targets, n_targets,
+ get_func, clear_func, owner,
+ TRUE);
+}
+
+/**
+ * gtk_clipboard_get_owner:
+ * @clipboard: a #GtkClipboard
+ *
+ * If the clipboard contents callbacks were set with gtk_clipboard_set_owner(),
+ * and the gtk_clipboard_set_with_data() or gtk_clipboard_clear() has not
+ * subsequently called, returns the @owner set by gtk_clipboard_set_owner().
+ *
+ * Return value: the owner of the clipboard, if any; otherwise %NULL.
+ **/
+GObject *
+gtk_clipboard_get_owner (GtkClipboard *clipboard)
+{
+ g_return_val_if_fail (clipboard != NULL, NULL);
+
+ if (clipboard->have_owner)
+ return clipboard->user_data;
+ else
+ return NULL;
+}
+
+static void
+clipboard_unset (GtkClipboard *clipboard)
+{
+ GtkClipboardClearFunc old_clear_func;
+ gpointer old_data;
+
+ old_clear_func = clipboard->clear_func;
+ old_data = clipboard->user_data;
+
+ if (clipboard->have_owner)
+ {
+ clipboard_remove_owner_notify (clipboard);
+ clipboard->have_owner = FALSE;
+ }
+
+ clipboard->get_func = NULL;
+ clipboard->clear_func = NULL;
+ clipboard->user_data = NULL;
+
+ if (old_clear_func)
+ old_clear_func (clipboard, old_data);
+}
+
+/**
+ * gtk_clipboard_clear:
+ * @clipboard: a #GtkClipboard
+ *
+ * Clear the contents of the clipboard. Generally this should only
+ * be called between the time you call gtk_clipboard_set_contents(),
+ * and when the @clear_func you supplied is called. Otherwise, the
+ * clipboard may be owned by someone else.
+ **/
+void
+gtk_clipboard_clear (GtkClipboard *clipboard)
+{
+ g_return_if_fail (clipboard != NULL);
+
+ if (clipboard->have_selection)
+ gtk_selection_owner_set (NULL, clipboard->selection,
+ clipboard_get_timestamp (clipboard));
+}
+
+void
+text_get_func (GtkClipboard *clipboard,
+ GtkSelectionData *selection_data,
+ guint info,
+ gpointer data)
+{
+ gtk_selection_data_set_text (selection_data, data);
+}
+
+void
+text_clear_func (GtkClipboard *clipboard,
+ gpointer data)
+{
+ g_free (data);
+}
+
+/**
+ * gtk_clipboard_set_text:
+ * @clipboard: a #GtkClipboard object
+ * @text: a UTF-8 string.
+ * @len: length of @text, in bytes, or -1, in which case
+ * the length will be determined with strlen().
+ *
+ * Set the contents of the clipboard to the given UTF-8 string. GTK+ will
+ * make a copy of the text and take responsibility for responding
+ * for requests for the text, and for converting the text into
+ * the requested format.
+ **/
+void
+gtk_clipboard_set_text (GtkClipboard *clipboard,
+ const gchar *text,
+ gint len)
+{
+ static const GtkTargetEntry targets[] = {
+ { "STRING", 0, TARGET_STRING },
+ { "TEXT", 0, TARGET_TEXT },
+ { "COMPOUND_TEXT", 0, TARGET_COMPOUND_TEXT },
+ { "UTF8_STRING", 0, TARGET_UTF8_STRING }
+ };
+
+ g_return_if_fail (clipboard != NULL);
+ g_return_if_fail (text != NULL);
+
+ if (len < 0)
+ len = strlen (text);
+
+ gtk_clipboard_set_with_data (clipboard,
+ targets, G_N_ELEMENTS (targets),
+ text_get_func, text_clear_func,
+ g_strndup (text, len));
+}
+
+static void
+set_request_contents_info (GtkWidget *widget,
+ RequestContentsInfo *info)
+{
+ if (!request_contents_key_id)
+ request_contents_key_id = g_quark_from_static_string (request_contents_key);
+
+ gtk_object_set_data_by_id (GTK_OBJECT (widget),
+ request_contents_key_id,
+ info);
+}
+
+static RequestContentsInfo *
+get_request_contents_info (GtkWidget *widget)
+{
+ if (!request_contents_key_id)
+ return NULL;
+ else
+ return gtk_object_get_data_by_id (GTK_OBJECT (widget),
+ request_contents_key_id);
+}
+
+static void
+selection_received (GtkWidget *widget,
+ GtkSelectionData *selection_data,
+ guint time)
+{
+ RequestContentsInfo *request_info = get_request_contents_info (widget);
+ set_request_contents_info (widget, NULL);
+
+ request_info->callback (gtk_clipboard_get (selection_data->selection),
+ selection_data,
+ request_info->user_data);
+
+ g_free (request_info);
+
+ if (widget != clipboard_widget)
+ gtk_widget_destroy (widget);
+}
+
+/**
+ * gtk_clipboard_request_contents:
+ * @clipboard: a #GtkClipboard
+ * @target: an atom representing the form into which the clipboard
+ * owner should convert the selection.
+ * @callback: A function to call when the results are received
+ * (or the retrieval fails.) If the retrieval fails
+ * the length field of @selection_data will be
+ * negative.
+ * @user_data: user data to pass to @callback
+ *
+ * Requests the contents of clipboard as the given target.
+ * When the results of the result are later received the supplied callback
+ * will be called.
+ **/
+void
+gtk_clipboard_request_contents (GtkClipboard *clipboard,
+ GdkAtom target,
+ GtkClipboardReceivedFunc callback,
+ gpointer user_data)
+{
+ RequestContentsInfo *info;
+ GtkWidget *widget;
+
+ g_return_if_fail (clipboard != NULL);
+ g_return_if_fail (target != GDK_NONE);
+ g_return_if_fail (callback != NULL);
+
+ ensure_clipboard_widget ();
+
+ if (get_request_contents_info (clipboard_widget))
+ widget = make_clipboard_widget (FALSE);
+ else
+ widget = clipboard_widget;
+
+ info = g_new (RequestContentsInfo, 1);
+ info->callback = callback;
+ info->user_data = user_data;
+
+ set_request_contents_info (widget, info);
+
+ gtk_selection_convert (widget, clipboard->selection, target,
+ clipboard_get_timestamp (clipboard));
+}
+
+static void
+request_text_received_func (GtkClipboard *clipboard,
+ GtkSelectionData *selection_data,
+ gpointer data)
+{
+ RequestTextInfo *info = data;
+ gchar *result = NULL;
+
+ result = gtk_selection_data_get_text (selection_data);
+
+ if (!result)
+ {
+ /* If we asked for UTF8 and didn't get it, try text; if we asked
+ * for text and didn't get it, try string. If we asked for
+ * anything else and didn't get it, give up.
+ */
+ if (selection_data->target == gdk_atom_intern ("UTF8_STRING", FALSE))
+ {
+ gtk_clipboard_request_contents (clipboard,
+ gdk_atom_intern ("TEXT", FALSE),
+ request_text_received_func, info);
+ return;
+ }
+ else if (selection_data->target == gdk_atom_intern ("TEXT", FALSE))
+ {
+ gtk_clipboard_request_contents (clipboard,
+ GDK_TARGET_STRING,
+ request_text_received_func, info);
+ return;
+ }
+ }
+
+ info->callback (clipboard, result, info->user_data);
+ g_free (info);
+ g_free (result);
+}
+
+/**
+ * gtk_clipboard_request_text:
+ * @clipboard: a #GtkClipboard
+ * @callback: a function to call when the text is received,
+ * or the retrieval fails. (It will always be called
+ * one way or the other.)
+ * @user_data: user data to pass to @callback.
+ *
+ * Requests the contents of the clipboard as text. When the text is
+ * later received, it will be converted to UTF-8 if necessary, and
+ * @callback will be called.
+ *
+ * The @text parameter to @callback will contain the resulting text if
+ * the request succeeded, or %NULL if it failed. This could happen for
+ * various reasons, in particular if the clipboard was empty or if the
+ * contents of the clipboard could not be converted into text form.
+ **/
+void
+gtk_clipboard_request_text (GtkClipboard *clipboard,
+ GtkClipboardTextReceivedFunc callback,
+ gpointer user_data)
+{
+ RequestTextInfo *info;
+
+ g_return_if_fail (clipboard != NULL);
+ g_return_if_fail (callback != NULL);
+
+ info = g_new (RequestTextInfo, 1);
+ info->callback = callback;
+ info->user_data = user_data;
+
+ gtk_clipboard_request_contents (clipboard, gdk_atom_intern ("UTF8_STRING", FALSE),
+ request_text_received_func,
+ info);
+}
+
+
+typedef struct
+{
+ GMainLoop *loop;
+ gpointer data;
+} WaitResults;
+
+static void
+clipboard_received_func (GtkClipboard *clipboard,
+ GtkSelectionData *selection_data,
+ gpointer data)
+{
+ WaitResults *results = data;
+
+ if (selection_data->length >= 0)
+ results->data = gtk_selection_data_copy (selection_data);
+
+ g_main_quit (results->loop);
+}
+
+/**
+ * gtk_clipboard_wait_for_contents:
+ * @clipboard: a #GtkClipboard
+ * @target: an atom representing the form into which the clipboard
+ * owner should convert the selection.
+ *
+ * Requests the contents of the clipboard using the given target.
+ * This function waits for the data to be received using the main
+ * loop, so events, timeouts, etc, may be dispatched during the wait.
+ *
+ * Return value: a newly allocated #GtkSelectionData object or %NULL
+ * if retrieving the given target failed. If non-%NULL,
+ * this value freed with gtk_selection_data_free() when
+ * you are finished with it.
+ **/
+GtkSelectionData *
+gtk_clipboard_wait_for_contents (GtkClipboard *clipboard,
+ GdkAtom target)
+{
+ WaitResults results;
+
+ g_return_val_if_fail (clipboard != NULL, NULL);
+ g_return_val_if_fail (target != GDK_NONE, NULL);
+
+ results.data = NULL;
+ results.loop = g_main_new (TRUE);
+
+ gtk_clipboard_request_contents (clipboard, target,
+ clipboard_received_func,
+ &results);
+
+ if (g_main_is_running (results.loop))
+ g_main_run (results.loop);
+
+ g_main_destroy (results.loop);
+
+ return results.data;
+}
+
+static void
+clipboard_text_received_func (GtkClipboard *clipboard,
+ const gchar *text,
+ gpointer data)
+{
+ WaitResults *results = data;
+
+ results->data = g_strdup (text);
+ g_main_quit (results->loop);
+}
+
+
+/**
+ * gtk_clipboard_wait_for_text:
+ * @clipboard: a #GtkClipboard
+ *
+ * Requests the contents of the clipboard as text and converts
+ * the result to UTF-8 if necessary. This function waits for
+ * the data to be received using the main loop, so events,
+ * timeouts, etc, may be dispatched during the wait.
+ *
+ * Return value: a newly allocated UTF-8 string which must
+ * be freed with g_free(), or %NULL if retrieving
+ * the selection data failed. (This could happen
+ * for various reasons, in particular if the
+ * clipboard was empty or if the contents of the
+ * clipboard could not be converted into text form.)
+ **/
+gchar *
+gtk_clipboard_wait_for_text (GtkClipboard *clipboard)
+{
+ WaitResults results;
+
+ g_return_val_if_fail (clipboard != NULL, NULL);
+ g_return_val_if_fail (clipboard != NULL, NULL);
+
+ results.data = NULL;
+ results.loop = g_main_new (TRUE);
+
+ gtk_clipboard_request_text (clipboard,
+ clipboard_text_received_func,
+ &results);
+
+ if (g_main_is_running (results.loop))
+ g_main_run (results.loop);
+
+ g_main_destroy (results.loop);
+
+ return results.data;
+}
+
diff --git a/gtk/gtkclipboard.h b/gtk/gtkclipboard.h
new file mode 100644
index 0000000000..f35630e9d8
--- /dev/null
+++ b/gtk/gtkclipboard.h
@@ -0,0 +1,87 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 2000 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Global clipboard abstraction.
+ */
+
+#ifndef __GTK_CLIPBOARD_H__
+#define __GTK_CLIPBOARD_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#include <gtk/gtkselection.h>
+
+typedef struct _GtkClipboard GtkClipboard;
+
+typedef void (* GtkClipboardReceivedFunc) (GtkClipboard *clipboard,
+ GtkSelectionData *selection_data,
+ gpointer data);
+typedef void (* GtkClipboardTextReceivedFunc) (GtkClipboard *clipboard,
+ const gchar *text,
+ gpointer data);
+
+/* Should these functions have GtkClipboard *clipboard as the first argument?
+ * right now for ClearFunc, you may have trouble determining _which_ clipboard
+ * was cleared, if you reuse your ClearFunc for multiple clipboards.
+ */
+typedef void (* GtkClipboardGetFunc) (GtkClipboard *clipboard,
+ GtkSelectionData *selection_data,
+ guint info,
+ gpointer user_data_or_owner);
+typedef void (* GtkClipboardClearFunc) (GtkClipboard *clipboard,
+ gpointer user_data_or_owner);
+
+GtkClipboard *gtk_clipboard_get (GdkAtom selection);
+
+gboolean gtk_clipboard_set_with_data (GtkClipboard *clipboard,
+ const GtkTargetEntry *targets,
+ guint n_targets,
+ GtkClipboardGetFunc get_func,
+ GtkClipboardClearFunc clear_func,
+ gpointer user_data);
+gboolean gtk_clipboard_set_with_owner (GtkClipboard *clipboard,
+ const GtkTargetEntry *targets,
+ guint n_targets,
+ GtkClipboardGetFunc get_func,
+ GtkClipboardClearFunc clear_func,
+ GObject *owner);
+GObject *gtk_clipboard_get_owner (GtkClipboard *clipboard);
+void gtk_clipboard_clear (GtkClipboard *clipboard);
+void gtk_clipboard_set_text (GtkClipboard *clipboard,
+ const gchar *text,
+ gint len);
+
+void gtk_clipboard_request_contents (GtkClipboard *clipboard,
+ GdkAtom target,
+ GtkClipboardReceivedFunc callback,
+ gpointer user_data);
+void gtk_clipboard_request_text (GtkClipboard *clipboard,
+ GtkClipboardTextReceivedFunc callback,
+ gpointer user_data);
+
+GtkSelectionData *gtk_clipboard_wait_for_contents (GtkClipboard *clipboard,
+ GdkAtom target);
+gchar * gtk_clipboard_wait_for_text (GtkClipboard *clipboard);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif __GTK_CLIPBOARD_H__
diff --git a/gtk/gtkenums.h b/gtk/gtkenums.h
index 1971b7e2ee..dd8fe45fc0 100644
--- a/gtk/gtkenums.h
+++ b/gtk/gtkenums.h
@@ -66,6 +66,19 @@ typedef enum
GTK_CURVE_TYPE_FREE /* free form curve */
} GtkCurveType;
+typedef enum {
+ GTK_DELETE_CHARS,
+ GTK_DELETE_WORD_ENDS, /* delete only the portion of the word to the
+ * left/right of cursor if we're in the middle
+ * of a word */
+ GTK_DELETE_WORDS,
+ GTK_DELETE_DISPLAY_LINES,
+ GTK_DELETE_DISPLAY_LINE_ENDS,
+ GTK_DELETE_PARAGRAPH_ENDS, /* like C-k in Emacs (or its reverse) */
+ GTK_DELETE_PARAGRAPHS, /* C-k in pico, kill whole line */
+ GTK_DELETE_WHITESPACE, /* M-\ in Emacs */
+} GtkDeleteType;
+
/* Focus movement types */
typedef enum
{
@@ -128,6 +141,18 @@ typedef enum
GTK_CENTIMETERS
} GtkMetricType;
+typedef enum {
+ GTK_MOVEMENT_CHARS, /* move by forw/back chars */
+ GTK_MOVEMENT_POSITIONS, /* move by left/right chars */
+ GTK_MOVEMENT_WORDS, /* move by forward/back words */
+ GTK_MOVEMENT_DISPLAY_LINES, /* move up/down lines (wrapped lines) */
+ GTK_MOVEMENT_DISPLAY_LINE_ENDS, /* move up/down lines (wrapped lines) */
+ GTK_MOVEMENT_PARAGRAPHS, /* move up/down paragraphs (newline-ended lines) */
+ GTK_MOVEMENT_PARAGRAPH_ENDS, /* move to either end of a paragraph */
+ GTK_MOVEMENT_PAGES, /* move by pages */
+ GTK_MOVEMENT_BUFFER_ENDS /* move to ends of the buffer */
+} GtkMovementStep;
+
/* Orientation for toolbars, etc. */
typedef enum
{
diff --git a/gtk/gtkinvisible.c b/gtk/gtkinvisible.c
index c18c789348..e7d8cc4088 100644
--- a/gtk/gtkinvisible.c
+++ b/gtk/gtkinvisible.c
@@ -102,7 +102,10 @@ gtk_invisible_destroy (GtkObject *object)
GtkWidget*
gtk_invisible_new (void)
{
- return GTK_WIDGET (gtk_type_new (GTK_TYPE_INVISIBLE));
+ GtkWidget *result = GTK_WIDGET (gtk_type_new (GTK_TYPE_INVISIBLE));
+ gtk_widget_realize (result);
+
+ return result;
}
static void
diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c
index 121beb0985..7a690d2acd 100644
--- a/gtk/gtkmain.c
+++ b/gtk/gtkmain.c
@@ -33,21 +33,12 @@
#include <stdlib.h>
#include <string.h>
#include <gmodule.h>
-#include "gtkbutton.h"
#include "gtkdnd.h"
#include "gtkcompat.h"
-#include "gtkhscrollbar.h"
-#include "gtkhseparator.h"
#include "gtkmain.h"
-#include "gtkpreview.h"
#include "gtkrc.h"
-#include "gtkscrolledwindow.h"
#include "gtkselection.h"
#include "gtksignal.h"
-#include "gtktable.h"
-#include "gtktext.h"
-#include "gtkvbox.h"
-#include "gtkvscrollbar.h"
#include "gtkwidget.h"
#include "gtkwindow.h"
#include "gtkprivate.h"
@@ -1292,11 +1283,28 @@ GdkEvent*
gtk_get_current_event (void)
{
if (current_events)
- return gdk_event_copy ((GdkEvent *) current_events->data);
+ return gdk_event_copy (current_events->data);
else
return NULL;
}
+/**
+ * gtk_get_current_event_time:
+ *
+ * If there is a current event and it has a timestamp, return that
+ * timestamp, otherwise return %GDK_CURRENT_TIME.
+ *
+ * Return value: the timestamp from the current event, or %GDK_CURRENT_TIME.
+ **/
+guint32
+gtk_get_current_event_time (void)
+{
+ if (current_events)
+ return gdk_event_get_time (current_events->data);
+ else
+ return GDK_CURRENT_TIME;
+}
+
GtkWidget*
gtk_get_event_widget (GdkEvent *event)
{
@@ -1315,7 +1323,6 @@ gtk_exit_func (void)
if (gtk_initialized)
{
gtk_initialized = FALSE;
- gtk_preview_uninit ();
}
}
diff --git a/gtk/gtkmain.h b/gtk/gtkmain.h
index ea9829b6b6..7383788564 100644
--- a/gtk/gtkmain.h
+++ b/gtk/gtkmain.h
@@ -179,7 +179,9 @@ guint gtk_key_snooper_install (GtkKeySnoopFunc snooper,
gpointer func_data);
void gtk_key_snooper_remove (guint snooper_handler_id);
-GdkEvent* gtk_get_current_event (void);
+GdkEvent* gtk_get_current_event (void);
+guint32 gtk_get_current_event_time (void);
+
GtkWidget* gtk_get_event_widget (GdkEvent *event);
diff --git a/gtk/gtkselection.c b/gtk/gtkselection.c
index f2e07c3e32..e09da3d65e 100644
--- a/gtk/gtkselection.c
+++ b/gtk/gtkselection.c
@@ -313,7 +313,7 @@ gtk_target_list_find (GtkTargetList *list,
* results:
*************************************************************/
-gint
+gboolean
gtk_selection_owner_set (GtkWidget *widget,
GdkAtom selection,
guint32 time)
@@ -322,34 +322,26 @@ gtk_selection_owner_set (GtkWidget *widget,
GtkWidget *old_owner;
GtkSelectionInfo *selection_info = NULL;
GdkWindow *window;
+
+ g_return_val_if_fail (widget == NULL || GTK_WIDGET_REALIZED (widget), FALSE);
if (widget == NULL)
window = NULL;
else
- {
- if (!GTK_WIDGET_REALIZED (widget))
- gtk_widget_realize (widget);
-
- window = widget->window;
- }
-
+ window = widget->window;
+
tmp_list = current_selections;
while (tmp_list)
{
- selection_info = (GtkSelectionInfo *)tmp_list->data;
-
- if (selection_info->selection == selection)
- break;
+ if (((GtkSelectionInfo *)tmp_list->data)->selection == selection)
+ {
+ selection_info = tmp_list->data;
+ break;
+ }
tmp_list = tmp_list->next;
}
- if (tmp_list == NULL)
- selection_info = NULL;
- else
- if (selection_info->widget == widget)
- return TRUE;
-
if (gdk_selection_owner_set (window, selection, time, TRUE))
{
old_owner = NULL;
@@ -373,8 +365,8 @@ gtk_selection_owner_set (GtkWidget *widget,
selection_info->selection = selection;
selection_info->widget = widget;
selection_info->time = time;
- current_selections = g_list_append (current_selections,
- selection_info);
+ current_selections = g_list_prepend (current_selections,
+ selection_info);
}
else
{
@@ -384,9 +376,9 @@ gtk_selection_owner_set (GtkWidget *widget,
}
}
/* If another widget in the application lost the selection,
- * send it a GDK_SELECTION_CLEAR event, unless we're setting
- * the owner to None, in which case an event will be sent */
- if (old_owner && (widget != NULL))
+ * send it a GDK_SELECTION_CLEAR event.
+ */
+ if (old_owner && old_owner != widget)
{
GdkEventSelection event;
@@ -476,6 +468,43 @@ gtk_selection_target_list_remove (GtkWidget *widget)
gtk_object_set_data (GTK_OBJECT (widget), gtk_selection_handler_key, NULL);
}
+/**
+ * gtk_selection_clear_targets:
+ * @widget: a #GtkWidget
+ * @selection: an atom representing a selection
+ *
+ * Remove all targets registered for the given selection for the
+ * widget.
+ **/
+void
+gtk_selection_clear_targets (GtkWidget *widget,
+ GdkAtom selection)
+{
+ GtkSelectionTargetList *sellist;
+ GList *tmp_list;
+ GList *lists;
+
+ lists = gtk_object_get_data (GTK_OBJECT (widget), gtk_selection_handler_key);
+
+ tmp_list = lists;
+ while (tmp_list)
+ {
+ sellist = tmp_list->data;
+ if (sellist->selection == selection)
+ {
+ lists = g_list_delete_link (lists, tmp_list);
+ gtk_target_list_unref (sellist->list);
+ g_free (sellist);
+
+ break;
+ }
+
+ tmp_list = tmp_list->next;
+ }
+
+ gtk_object_set_data (GTK_OBJECT (widget), gtk_selection_handler_key, lists);
+}
+
void
gtk_selection_add_target (GtkWidget *widget,
GdkAtom selection,
@@ -505,6 +534,7 @@ gtk_selection_add_targets (GtkWidget *widget,
gtk_target_list_add_table (list, targets, ntargets);
}
+
/*************************************************************
* gtk_selection_remove_all:
* Removes all handlers and unsets ownership of all
@@ -728,6 +758,122 @@ gtk_selection_data_set (GtkSelectionData *selection_data,
selection_data->length = length;
}
+static GdkAtom utf8_atom;
+static GdkAtom text_atom;
+static GdkAtom ctext_atom;
+
+static void
+init_atoms (void)
+{
+ if (!utf8_atom)
+ {
+ utf8_atom = gdk_atom_intern ("UTF8_STRING", FALSE);
+ text_atom = gdk_atom_intern ("TEXT", FALSE);
+ ctext_atom = gdk_atom_intern ("COMPOUND_TEXT", FALSE);
+ }
+}
+
+/**
+ * gtk_selection_data_set_text:
+ * @selection_data: a #GtkSelectionData
+ * @str: a UTF-8 string
+ *
+ * Sets the contents of the selection from a UTF-8 encoded string.
+ * The string is converted to the form determined by
+ * @selection_data->target.
+ *
+ * Return value: %TRUE if the selection was succesfully set,
+ * otherwise %FALSE.
+ **/
+gboolean
+gtk_selection_data_set_text (GtkSelectionData *selection_data,
+ const guchar *str)
+{
+ init_atoms ();
+
+ if (selection_data->target == utf8_atom)
+ {
+ gtk_selection_data_set (selection_data,
+ utf8_atom,
+ 8, (guchar *)str, strlen (str));
+ return TRUE;
+ }
+ else if (selection_data->target == GDK_TARGET_STRING)
+ {
+ gchar *latin1 = gdk_utf8_to_string_target (str);
+
+ if (latin1)
+ {
+ gtk_selection_data_set (selection_data,
+ GDK_SELECTION_TYPE_STRING,
+ 8, latin1, strlen (latin1));
+ g_free(latin1);
+
+ return TRUE;
+ }
+
+ }
+ else if (selection_data->target == ctext_atom ||
+ selection_data->target == text_atom)
+ {
+ guchar *text;
+ GdkAtom encoding;
+ gint format;
+ gint new_length;
+
+ if (gdk_utf8_to_compound_text (str, &encoding, &format, &text, &new_length))
+ {
+ gtk_selection_data_set (selection_data, encoding, format, text, new_length);
+ gdk_free_compound_text (text);
+
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+/**
+ * gtk_selection_data_get_text:
+ * @selection_data: a #GtkSelectionData
+ *
+ * Gets the contents of the selection data as a UTF-8 string.
+ *
+ * Return value: if the selection data contained a recognized
+ * text type and it could be converted to UTF-8, a newly allocated
+ * string containing the converted text, otherwise %NULL.
+ * If the result is non-%NULL it must be freed with g_free().
+ **/
+guchar *
+gtk_selection_data_get_text (GtkSelectionData *selection_data)
+{
+ guchar *result = NULL;
+
+ init_atoms ();
+
+ if (selection_data->length >= 0 &&
+ (selection_data->type == GDK_TARGET_STRING ||
+ selection_data->type == ctext_atom ||
+ selection_data->type == utf8_atom))
+ {
+ gchar **list;
+ gint i;
+ gint count = gdk_text_property_to_utf8_list (selection_data->type,
+ selection_data->format,
+ selection_data->data,
+ selection_data->length,
+ &list);
+ if (count > 0)
+ result = list[0];
+
+ for (i = 1; i < count; i++)
+ g_free (list[i]);
+ g_free (list);
+ }
+
+ return result;
+}
+
/*************************************************************
* gtk_selection_init:
* Initialize local variables
@@ -755,16 +901,13 @@ gtk_selection_init (void)
*************************************************************/
gint
-gtk_selection_clear (GtkWidget *widget,
+gtk_selection_clear (GtkWidget *widget,
GdkEventSelection *event)
{
- /* FIXME: there can be a problem if we change the selection
- via gtk_selection_owner_set after another client claims
- the selection, but before we get the notification event.
- Tk filters based on serial #'s, which aren't retained by
- GTK. Filtering based on time's will be inherently
- somewhat unreliable. */
-
+ /* Note that we filter clear events in gdkselection-x11.c, so
+ * that we only will get here if the clear event actually
+ * represents a change that we didn't do ourself.
+ */
GList *tmp_list;
GtkSelectionInfo *selection_info = NULL;
@@ -782,16 +925,9 @@ gtk_selection_clear (GtkWidget *widget,
if (tmp_list)
{
- if (selection_info->time > event->time)
- return FALSE; /* return FALSE to indicate that
- * the selection was out of date,
- * and this clear should be ignored */
- else
- {
- current_selections = g_list_remove_link (current_selections, tmp_list);
- g_list_free (tmp_list);
- g_free (selection_info);
- }
+ current_selections = g_list_remove_link (current_selections, tmp_list);
+ g_list_free (tmp_list);
+ g_free (selection_info);
}
return TRUE;
@@ -1585,14 +1721,20 @@ gtk_selection_default_handler (GtkWidget *widget,
GtkSelectioData*
-gtk_selection_data_copy (GtkSelectionData *data)
+gtk_selection_data_copy (GtkSelectionData *selection_data)
{
GtkSelectionData *new_data;
- g_return_val_if_fail (data != NULL, NULL);
+ g_return_val_if_fail (selection_data != NULL, NULL);
new_data = g_new (GtkSelectionData, 1);
- *new_data = *data;
+ *new_data = *selection_data;
+
+ if (selection_data->data)
+ {
+ new_data->data = g_malloc (selection_data->length + 1);
+ memcpy (new_data->data, selection_data->data, selection_data->length + 1);
+ }
return new_data;
}
@@ -1602,6 +1744,9 @@ gtk_selection_data_free (GtkSelectionData *data)
{
g_return_if_fail (data != NULL);
+ if (data->data)
+ g_free (data->data);
+
g_free (data);
}
diff --git a/gtk/gtkselection.h b/gtk/gtkselection.h
index 157896f197..668fec4b3a 100644
--- a/gtk/gtkselection.h
+++ b/gtk/gtkselection.h
@@ -83,28 +83,31 @@ gboolean gtk_target_list_find (GtkTargetList *list,
/* Public interface */
-gint gtk_selection_owner_set (GtkWidget *widget,
- GdkAtom selection,
- guint32 time);
-void gtk_selection_add_target (GtkWidget *widget,
- GdkAtom selection,
- GdkAtom target,
- guint info);
-void gtk_selection_add_targets (GtkWidget *widget,
- GdkAtom selection,
- const GtkTargetEntry *targets,
- guint ntargets);
-gint gtk_selection_convert (GtkWidget *widget,
- GdkAtom selection,
- GdkAtom target,
- guint32 time);
-
-
-void gtk_selection_data_set (GtkSelectionData *selection_data,
- GdkAtom type,
- gint format,
- const guchar *data,
- gint length);
+gboolean gtk_selection_owner_set (GtkWidget *widget,
+ GdkAtom selection,
+ guint32 time);
+void gtk_selection_add_target (GtkWidget *widget,
+ GdkAtom selection,
+ GdkAtom target,
+ guint info);
+void gtk_selection_add_targets (GtkWidget *widget,
+ GdkAtom selection,
+ const GtkTargetEntry *targets,
+ guint ntargets);
+void gtk_selection_clear_targets (GtkWidget *widget,
+ GdkAtom selection);
+gint gtk_selection_convert (GtkWidget *widget,
+ GdkAtom selection,
+ GdkAtom target,
+ guint32 time);
+void gtk_selection_data_set (GtkSelectionData *selection_data,
+ GdkAtom type,
+ gint format,
+ const guchar *data,
+ gint length);
+gboolean gtk_selection_data_set_text (GtkSelectionData *selection_data,
+ const guchar *str);
+guchar * gtk_selection_data_get_text (GtkSelectionData *selection_data);
/* Called when a widget is destroyed */
diff --git a/gtk/gtktextbuffer.c b/gtk/gtktextbuffer.c
index 52f7e664d3..19549efdf9 100644
--- a/gtk/gtktextbuffer.c
+++ b/gtk/gtktextbuffer.c
@@ -5,14 +5,24 @@
#include <string.h>
+#include "gtkclipboard.h"
#include "gtkinvisible.h"
-#include "gtkselection.h"
#include "gtksignal.h"
#include "gtktextbuffer.h"
#include "gtktextbtree.h"
#include "gtktextiterprivate.h"
#include <string.h>
+typedef struct _ClipboardRequest ClipboardRequest;
+
+struct _ClipboardRequest
+{
+ GtkTextBuffer *buffer;
+ gboolean interactive;
+ gboolean default_editable;
+ gboolean is_clipboard;
+};
+
enum {
INSERT_TEXT,
DELETE_TEXT,
@@ -44,7 +54,6 @@ static void gtk_text_buffer_finalize (GObject *object);
static void gtk_text_buffer_update_primary_selection (GtkTextBuffer *buffer);
-static void gtk_text_buffer_update_clipboard_selection (GtkTextBuffer *buffer);
static void gtk_text_buffer_real_insert_text (GtkTextBuffer *buffer,
GtkTextIter *iter,
const gchar *text,
@@ -70,11 +79,6 @@ void gtk_marshal_NONE__INT_POINTER_INT (GtkObject *object,
gpointer func_data,
GtkArg *args);
-static GdkAtom clipboard_atom = GDK_NONE;
-static GdkAtom text_atom = GDK_NONE;
-static GdkAtom ctext_atom = GDK_NONE;
-static GdkAtom utf8_atom = GDK_NONE;
-
static GtkObjectClass *parent_class = NULL;
static guint signals[LAST_SIGNAL] = { 0 };
@@ -238,34 +242,6 @@ gtk_marshal_NONE__INT_POINTER_INT (GtkObject *object,
void
gtk_text_buffer_init (GtkTextBuffer *buffer)
{
- static const GtkTargetEntry targets[] = {
- { "STRING", 0, TARGET_STRING },
- { "TEXT", 0, TARGET_TEXT },
- { "COMPOUND_TEXT", 0, TARGET_COMPOUND_TEXT },
- { "UTF8_STRING", 0, TARGET_UTF8_STRING }
- };
- static const gint n_targets = sizeof(targets) / sizeof(targets[0]);
-
- if (!clipboard_atom)
- clipboard_atom = gdk_atom_intern ("CLIPBOARD", FALSE);
-
- if (!text_atom)
- text_atom = gdk_atom_intern ("TEXT", FALSE);
-
- if (!ctext_atom)
- ctext_atom = gdk_atom_intern ("COMPOUND_TEXT", FALSE);
-
- if (!utf8_atom)
- utf8_atom = gdk_atom_intern ("UTF8_STRING", FALSE);
-
- buffer->selection_widget = gtk_invisible_new();
-
- gtk_selection_add_targets (buffer->selection_widget,
- GDK_SELECTION_PRIMARY,
- targets, n_targets);
- gtk_selection_add_targets (buffer->selection_widget,
- clipboard_atom,
- targets, n_targets);
}
/**
@@ -301,9 +277,6 @@ gtk_text_buffer_destroy (GtkObject *object)
buffer = GTK_TEXT_BUFFER (object);
- gtk_widget_destroy(buffer->selection_widget);
- buffer->selection_widget = NULL;
-
if (buffer->tag_table)
{
gtk_object_unref(GTK_OBJECT(buffer->tag_table));
@@ -1284,41 +1257,6 @@ gtk_text_buffer_set_modified (GtkTextBuffer *buffer,
/*
- * Clipboard
- */
-
-static void
-set_clipboard_contents_nocopy(GtkTextBuffer *buffer,
- gchar *text)
-{
- if (text && *text == '\0')
- {
- g_free(text);
- text = NULL;
- }
-
- if (buffer->clipboard_text != NULL)
- g_free(buffer->clipboard_text);
-
- buffer->clipboard_text = text;
-
- gtk_text_buffer_update_clipboard_selection(buffer);
-}
-
-void
-gtk_text_buffer_set_clipboard_contents (GtkTextBuffer *buffer,
- const gchar *text)
-{
- set_clipboard_contents_nocopy(buffer, text ? g_strdup(text) : NULL);
-}
-
-const gchar*
-gtk_text_buffer_get_clipboard_contents (GtkTextBuffer *buffer)
-{
- return buffer->clipboard_text;
-}
-
-/*
* Assorted other stuff
*/
@@ -1370,449 +1308,198 @@ gtk_text_buffer_get_tags (GtkTextBuffer *buffer,
return retval;
}
-/*
- * Selection
+/* Called when we lose the primary selection.
*/
-
-static gboolean
-have_primary_x_selection(GtkWidget *widget)
-{
- return (gdk_selection_owner_get (GDK_SELECTION_PRIMARY) ==
- widget->window);
-}
-
-static gboolean
-request_primary_x_selection(GtkWidget *widget, guint32 time)
-{
- return gtk_selection_owner_set (widget, GDK_SELECTION_PRIMARY, time);
-}
-
-static gboolean
-release_primary_x_selection(GtkWidget *widget, guint32 time)
-{
- if (gdk_selection_owner_get (GDK_SELECTION_PRIMARY) ==
- widget->window)
- {
- gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY, time);
- return TRUE;
- }
- else
- return FALSE;
-}
-
-
-static gboolean
-have_clipboard_x_selection(GtkWidget *widget)
-{
- return (gdk_selection_owner_get (clipboard_atom) ==
- widget->window);
-}
-
-static gboolean
-request_clipboard_x_selection(GtkWidget *widget, guint32 time)
-{
- return gtk_selection_owner_set (widget, clipboard_atom, time);
-}
-
-static gboolean
-release_clipboard_x_selection(GtkWidget *widget, guint32 time)
-{
- if (gdk_selection_owner_get (clipboard_atom) ==
- widget->window)
- {
- gtk_selection_owner_set (NULL, clipboard_atom, time);
- return TRUE;
- }
- else
- return FALSE;
-}
-
-/* Called when we lose the selection */
-static gint
-selection_clear_event(GtkWidget *widget, GdkEventSelection *event,
- gpointer data)
+static void
+clipboard_clear_cb (GtkClipboard *clipboard,
+ gpointer data)
{
- GtkTextBuffer *buffer;
+ /* Move selection_bound to the insertion point */
+ GtkTextIter insert;
+ GtkTextIter selection_bound;
+ GtkTextBuffer *buffer = GTK_TEXT_BUFFER (data);
- buffer = GTK_TEXT_BUFFER(data);
-
- /* Let the selection handling code know that the selection
- * has been changed, since we've overriden the default handler */
- if (!gtk_selection_clear (widget, event))
- return FALSE;
-
- buffer->have_selection = FALSE;
+ gtk_text_buffer_get_iter_at_mark(buffer, &insert,
+ gtk_text_buffer_get_mark (buffer, "insert"));
+ gtk_text_buffer_get_iter_at_mark(buffer, &selection_bound,
+ gtk_text_buffer_get_mark (buffer, "selection_bound"));
- if (event->selection == GDK_SELECTION_PRIMARY)
- {
- /* Move selection_bound to the insertion point */
- GtkTextIter insert;
- GtkTextIter selection_bound;
-
- gtk_text_buffer_get_iter_at_mark(buffer, &insert,
- gtk_text_buffer_get_mark (buffer, "insert"));
- gtk_text_buffer_get_iter_at_mark(buffer, &selection_bound,
- gtk_text_buffer_get_mark (buffer, "selection_bound"));
-
- if (!gtk_text_iter_equal(&insert, &selection_bound))
- gtk_text_buffer_move_mark(buffer,
- gtk_text_buffer_get_mark (buffer, "selection_bound"),
- &insert);
- }
- else if (event->selection == clipboard_atom)
- {
- gtk_text_buffer_set_clipboard_contents(buffer, NULL);
- }
-
- return TRUE;
+ if (!gtk_text_iter_equal(&insert, &selection_bound))
+ gtk_text_buffer_move_mark(buffer,
+ gtk_text_buffer_get_mark (buffer, "selection_bound"),
+ &insert);
}
-/* Called when we have the selection and someone else wants our
- data in order to paste it */
+/* Called when we have the primary selection and someone else wants our
+ * data in order to paste it.
+ */
static void
-selection_get (GtkWidget *widget,
- GtkSelectionData *selection_data,
- guint info,
- guint time,
- gpointer data)
+clipboard_get_cb (GtkClipboard *clipboard,
+ GtkSelectionData *selection_data,
+ guint info,
+ gpointer data)
{
- GtkTextBuffer *buffer;
+ GtkTextBuffer *buffer = GTK_TEXT_BUFFER(data);
gchar *str;
- guint length;
-
- buffer = GTK_TEXT_BUFFER(data);
+ GtkTextIter start, end;
- if (selection_data->selection == GDK_SELECTION_PRIMARY)
- {
- GtkTextIter start;
- GtkTextIter end;
-
- if (gtk_text_buffer_get_selection_bounds(buffer, &start, &end))
- {
- /* Extract the selected text */
- str = gtk_text_iter_get_visible_text(&start, &end);
-
- length = strlen(str);
- }
- else
- return;
- }
- else
- {
- const gchar *cstr;
-
- cstr = gtk_text_buffer_get_clipboard_contents(buffer);
-
- if (cstr == NULL)
- return;
-
- str = g_strdup(cstr);
-
- length = strlen (str);
- }
-
- if (str)
+ if (gtk_text_buffer_get_selection_bounds(buffer, &start, &end))
{
- if (info == TARGET_UTF8_STRING)
- {
- /* Pass raw UTF8 */
- gtk_selection_data_set (selection_data,
- utf8_atom,
- 8*sizeof(gchar), (guchar *)str, length);
-
- }
- else if (info == TARGET_STRING ||
- info == TARGET_TEXT)
- {
- gchar *latin1;
-
- latin1 = gtk_text_utf_to_latin1(str, length);
-
- gtk_selection_data_set (selection_data,
- GDK_SELECTION_TYPE_STRING,
- 8*sizeof(gchar), latin1, strlen(latin1));
- g_free(latin1);
- }
- else if (info == TARGET_COMPOUND_TEXT)
- {
- /* FIXME convert UTF8 directly to current locale, not via
- latin1 */
-
- guchar *text;
- GdkAtom encoding;
- gint format;
- gint new_length;
- gchar *latin1;
-
- latin1 = gtk_text_utf_to_latin1(str, length);
-
- gdk_string_to_compound_text (latin1, &encoding, &format, &text, &new_length);
- gtk_selection_data_set (selection_data, encoding, format, text, new_length);
- gdk_free_compound_text (text);
-
- g_free(latin1);
- }
-
+ /* Extract the selected text */
+ str = gtk_text_iter_get_visible_text(&start, &end);
+ gtk_selection_data_set_text (selection_data, str);
g_free (str);
}
}
-/* Called when we request a paste and receive the data */
+/* Called when we request a paste and receive the data
+ */
static void
-selection_received (GtkWidget *widget,
- GtkSelectionData *selection_data,
- guint time,
- gpointer data)
+clipboard_received (GtkClipboard *clipboard,
+ const gchar *str,
+ gpointer data)
{
- GtkTextBuffer *buffer;
- gboolean reselect;
- GtkTextIter insert_point;
- GtkTextMark *paste_point_override;
- enum {INVALID, STRING, CTEXT, UTF8} type;
-
- g_return_if_fail (widget != NULL);
-
- buffer = GTK_TEXT_BUFFER(data);
-
- if (selection_data->type == GDK_TARGET_STRING)
- type = STRING;
- else if (selection_data->type == ctext_atom)
- type = CTEXT;
- else if (selection_data->type == utf8_atom)
- type = UTF8;
- else
- type = INVALID;
-
- if (type == INVALID || selection_data->length < 0)
- {
- /* If we asked for UTF8 and didn't get it, try text; if we asked
- for text and didn't get it, try string. If we asked for
- anything else and didn't get it, give up. */
- if (selection_data->target == utf8_atom)
- gtk_selection_convert (widget, selection_data->selection,
- GDK_TARGET_STRING, time);
- return;
- }
-
- paste_point_override = gtk_text_buffer_get_mark (buffer,
- "__paste_point_override");
-
- if (paste_point_override != NULL)
- {
- gtk_text_buffer_get_iter_at_mark(buffer, &insert_point,
- paste_point_override);
- gtk_text_buffer_delete_mark(buffer,
- gtk_text_buffer_get_mark (buffer,
- "__paste_point_override"));
- }
- else
- {
- gtk_text_buffer_get_iter_at_mark(buffer, &insert_point,
- gtk_text_buffer_get_mark (buffer,
- "insert"));
- }
-
- reselect = FALSE;
+ ClipboardRequest *request_data = data;
+ GtkTextBuffer *buffer = request_data->buffer;
- if ((TRUE/* Text is selected FIXME */) &&
- (!buffer->have_selection ||
- (selection_data->selection == clipboard_atom)))
+ if (str)
{
- reselect = TRUE;
-
- if (buffer->have_selection)
- {
- /* FIXME Delete currently-selected chars but don't give up X
- selection since we'll use the newly-pasted stuff as
- a new X selection */
+ gboolean reselect;
+ GtkTextIter insert_point;
+ GtkTextMark *paste_point_override;
- }
+ paste_point_override = gtk_text_buffer_get_mark (buffer,
+ "__paste_point_override");
+
+ if (paste_point_override != NULL)
+ {
+ gtk_text_buffer_get_iter_at_mark(buffer, &insert_point,
+ paste_point_override);
+ gtk_text_buffer_delete_mark(buffer,
+ gtk_text_buffer_get_mark (buffer,
+ "__paste_point_override"));
+ }
else
- ; /* FIXME Delete selected chars and give up X selection */
- }
-
- switch (type)
- {
- case STRING:
- {
- gchar *utf;
-
- utf = gtk_text_latin1_to_utf((const gchar*)selection_data->data,
- selection_data->length);
- if (buffer->paste_interactive)
- gtk_text_buffer_insert_interactive (buffer, &insert_point,
- utf, -1, buffer->paste_default_editable);
- else
- gtk_text_buffer_insert (buffer, &insert_point,
- utf, -1);
- g_free(utf);
- }
- break;
+ {
+ gtk_text_buffer_get_iter_at_mark(buffer, &insert_point,
+ gtk_text_buffer_get_mark (buffer,
+ "insert"));
+ }
- case UTF8:
- gtk_text_buffer_insert (buffer, &insert_point,
- (const gchar *)selection_data->data,
- selection_data->length);
- break;
+ reselect = FALSE;
+
+ /* FIXME ALL OF THIS - I think that the "best method" is that when pasting
+ * with the cursor inside the selection area, you replace the selection
+ * with the new text, otherwise, you simply insert the new text at
+ * the point where the click occured, unselecting any selected text.
+ *
+ * This probably is best implemented as a "replace_selection" flag in
+ * ClipboardRequest.
+ */
+#if 0
+ if ((TRUE/* Text is selected FIXME */) &&
+ (!buffer->have_selection || request_data->is_clipboard))
+ {
+ reselect = TRUE;
+
+ if (buffer->have_selection)
+ {
+ /* FIXME Delete currently-selected chars but don't give up X
+ selection since we'll use the newly-pasted stuff as
+ a new X selection */
+
+ }
+ else
+ ; /* FIXME Delete selected chars and give up X selection */
+ }
+#endif
- case CTEXT:
- {
- gchar **list;
- gint count;
- gint i;
-
- count = gdk_text_property_to_text_list (selection_data->type,
- selection_data->format,
- selection_data->data,
- selection_data->length,
- &list);
- for (i=0; i<count; i++)
- {
- /* list contains stuff in our default encoding */
- gboolean free_utf = FALSE;
- gchar *utf = NULL;
- gchar *charset = NULL;
-
- if (g_get_charset (&charset))
- {
- utf = g_convert (list[i], -1,
- "UTF8", charset,
- NULL);
- free_utf = TRUE;
- }
- else
- utf = list[i];
-
- if (buffer->paste_interactive)
- gtk_text_buffer_insert_interactive (buffer, &insert_point,
- utf, -1, buffer->paste_default_editable);
- else
- gtk_text_buffer_insert (buffer, &insert_point,
- utf, -1);
-
- if (free_utf)
- g_free(utf);
- }
-
- if (count > 0)
- gdk_free_text_list (list);
- }
- break;
- case INVALID: /* quiet compiler */
- break;
+ if (request_data->interactive)
+ gtk_text_buffer_insert_interactive (buffer, &insert_point,
+ str, -1, request_data->default_editable);
+ else
+ gtk_text_buffer_insert (buffer, &insert_point,
+ str, -1);
+
+ if (reselect)
+ ; /* FIXME Select the region of text we just inserted */
}
- if (reselect)
- ; /* FIXME Select the region of text we just inserted */
-
+ g_object_unref (G_OBJECT (buffer));
+ g_free (request_data);
}
static void
-ensure_handlers(GtkTextBuffer *buffer)
+gtk_text_buffer_update_primary_selection (GtkTextBuffer *buffer)
{
- if (!buffer->selection_handlers_installed)
- {
- buffer->selection_handlers_installed = TRUE;
-
- gtk_signal_connect(GTK_OBJECT(buffer->selection_widget),
- "selection_clear_event",
- GTK_SIGNAL_FUNC(selection_clear_event),
- buffer);
-
- gtk_signal_connect(GTK_OBJECT(buffer->selection_widget),
- "selection_received",
- GTK_SIGNAL_FUNC(selection_received),
- buffer);
-
- gtk_signal_connect(GTK_OBJECT(buffer->selection_widget),
- "selection_get",
- GTK_SIGNAL_FUNC(selection_get),
- buffer);
- }
-}
+ static const GtkTargetEntry targets[] = {
+ { "STRING", 0, TARGET_STRING },
+ { "TEXT", 0, TARGET_TEXT },
+ { "COMPOUND_TEXT", 0, TARGET_COMPOUND_TEXT },
+ { "UTF8_STRING", 0, TARGET_UTF8_STRING }
+ };
-/* FIXME GDK_CURRENT_TIME should probably go away and we should
- figure out how to get the events in here */
-static void
-gtk_text_buffer_update_primary_selection(GtkTextBuffer *buffer)
-{
GtkTextIter start;
GtkTextIter end;
- ensure_handlers(buffer);
-
+ GtkClipboard *clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
+
/* Determine whether we have a selection and adjust X selection
- accordingly. */
+ * accordingly.
+ */
- if (!gtk_text_buffer_get_selection_bounds(buffer, &start, &end))
- {
- release_primary_x_selection(buffer->selection_widget, GDK_CURRENT_TIME);
- buffer->have_selection = FALSE;
- }
- else
- {
- /* Even if we already have the selection, we need to update our
- timestamp. */
- buffer->have_selection = FALSE;
- request_primary_x_selection(buffer->selection_widget, GDK_CURRENT_TIME);
- if (have_primary_x_selection(buffer->selection_widget))
- buffer->have_selection = TRUE;
- }
-}
-
-static void
-gtk_text_buffer_update_clipboard_selection(GtkTextBuffer *buffer)
-{
- if (buffer->clipboard_text == NULL ||
- buffer->clipboard_text[0] == '\0')
+ if (!gtk_text_buffer_get_selection_bounds (buffer, &start, &end))
{
- release_clipboard_x_selection(buffer->selection_widget, GDK_CURRENT_TIME);
+ if (gtk_clipboard_get_owner (clipboard) == G_OBJECT (buffer))
+ gtk_clipboard_clear (clipboard);
}
else
{
/* Even if we already have the selection, we need to update our
- timestamp. */
- request_clipboard_x_selection(buffer->selection_widget, GDK_CURRENT_TIME);
+ * timestamp.
+ */
+ if (!gtk_clipboard_set_with_owner (clipboard, targets, G_N_ELEMENTS (targets),
+ clipboard_get_cb, clipboard_clear_cb, G_OBJECT (buffer)))
+ clipboard_clear_cb (clipboard, buffer);
}
}
static void
-paste (GtkTextBuffer *buffer, GdkAtom selection, guint32 time,
+paste (GtkTextBuffer *buffer,
+ gboolean is_clipboard,
gboolean interactive,
gboolean default_editable)
{
- ensure_handlers(buffer);
+ ClipboardRequest *data = g_new (ClipboardRequest, 1);
- buffer->paste_interactive = interactive;
- buffer->paste_default_editable = default_editable;
-
- gtk_selection_convert (buffer->selection_widget, selection,
- utf8_atom, time);
+ data->buffer = buffer;
+ g_object_ref (G_OBJECT (buffer));
+ data->interactive = interactive;
+ data->default_editable = default_editable;
+
+ gtk_clipboard_request_text (gtk_clipboard_get (is_clipboard ? GDK_NONE : GDK_SELECTION_PRIMARY),
+ clipboard_received, data);
}
void
-gtk_text_buffer_paste_primary_selection(GtkTextBuffer *buffer,
- GtkTextIter *override_location,
- guint32 time,
- gboolean interactive,
- gboolean default_editable)
+gtk_text_buffer_paste_primary (GtkTextBuffer *buffer,
+ GtkTextIter *override_location,
+ gboolean default_editable)
{
if (override_location != NULL)
gtk_text_buffer_create_mark(buffer,
"__paste_point_override",
override_location, FALSE);
- paste(buffer, GDK_SELECTION_PRIMARY, time, interactive, default_editable);
+ paste (buffer, FALSE, TRUE, default_editable);
}
void
-gtk_text_buffer_paste_clipboard (GtkTextBuffer *buffer,
- guint32 time,
- gboolean interactive,
- gboolean default_editable)
+gtk_text_buffer_paste_clipboard (GtkTextBuffer *buffer,
+ gboolean default_editable)
{
- paste(buffer, clipboard_atom, time, interactive, default_editable);
+ paste (buffer, TRUE, TRUE, default_editable);
}
gboolean
@@ -1833,15 +1520,13 @@ gtk_text_buffer_delete_selection (GtkTextBuffer *buffer,
gtk_text_buffer_delete_interactive (buffer, &start, &end, default_editable);
else
gtk_text_buffer_delete (buffer, &start, &end);
-
- gtk_text_buffer_update_primary_selection(buffer);
+
return TRUE; /* We deleted stuff */
}
}
static void
cut_or_copy(GtkTextBuffer *buffer,
- guint32 time,
gboolean delete_region_after,
gboolean interactive,
gboolean default_editable)
@@ -1871,11 +1556,12 @@ cut_or_copy(GtkTextBuffer *buffer,
if (!gtk_text_iter_equal(&start, &end))
{
+ GtkClipboard *clipboard = gtk_clipboard_get (GDK_NONE);
gchar *text;
- text = gtk_text_iter_get_visible_text(&start, &end);
-
- set_clipboard_contents_nocopy(buffer, text);
+ text = gtk_text_iter_get_visible_text (&start, &end);
+ gtk_clipboard_set_text (clipboard, text, -1);
+ g_free (text);
if (delete_region_after)
{
@@ -1888,19 +1574,16 @@ cut_or_copy(GtkTextBuffer *buffer,
}
void
-gtk_text_buffer_cut (GtkTextBuffer *buffer,
- guint32 time,
- gboolean interactive,
- gboolean default_editable)
+gtk_text_buffer_cut_clipboard (GtkTextBuffer *buffer,
+ gboolean default_editable)
{
- cut_or_copy(buffer, time, TRUE, interactive, default_editable);
+ cut_or_copy (buffer, TRUE, TRUE, default_editable);
}
void
-gtk_text_buffer_copy (GtkTextBuffer *buffer,
- guint32 time)
+gtk_text_buffer_copy_clipboard (GtkTextBuffer *buffer)
{
- cut_or_copy(buffer, time, FALSE, FALSE, TRUE);
+ cut_or_copy (buffer, FALSE, TRUE, TRUE);
}
diff --git a/gtk/gtktextbuffer.h b/gtk/gtktextbuffer.h
index 7680294b71..b58feb62c4 100644
--- a/gtk/gtktextbuffer.h
+++ b/gtk/gtktextbuffer.h
@@ -32,18 +32,8 @@ struct _GtkTextBuffer {
GtkTextTagTable *tag_table;
GtkTextBTree *btree;
- /* Text currently pasted to the clipboard */
- gchar *clipboard_text;
-
/* Whether the buffer has been modified since last save */
gboolean modified;
-
- /* We use this for selections */
- GtkWidget *selection_widget;
- gboolean have_selection;
- gboolean selection_handlers_installed;
- gboolean paste_interactive;
- gboolean paste_default_editable;
};
struct _GtkTextBufferClass {
@@ -233,33 +223,22 @@ GSList *gtk_text_buffer_get_tags (GtkTextBuffer *buffer,
gboolean gtk_text_buffer_modified (GtkTextBuffer *buffer);
void gtk_text_buffer_set_modified (GtkTextBuffer *buffer,
gboolean setting);
-void gtk_text_buffer_set_clipboard_contents (GtkTextBuffer *buffer,
- const gchar *text);
-const gchar *gtk_text_buffer_get_clipboard_contents (GtkTextBuffer *buffer);
-
-void gtk_text_buffer_paste_primary_selection (GtkTextBuffer *buffer,
+void gtk_text_buffer_paste_primary (GtkTextBuffer *buffer,
GtkTextIter *override_location,
- guint32 time,
- gboolean interactive,
- gboolean default_editable);
-gboolean gtk_text_buffer_delete_selection (GtkTextBuffer *buffer,
- gboolean interactive,
gboolean default_editable);
-void gtk_text_buffer_cut (GtkTextBuffer *buffer,
- guint32 time,
- gboolean interactive,
+void gtk_text_buffer_cut_clipboard (GtkTextBuffer *buffer,
gboolean default_editable);
-void gtk_text_buffer_copy (GtkTextBuffer *buffer,
- guint32 time);
+void gtk_text_buffer_copy_clipboard (GtkTextBuffer *buffer);
void gtk_text_buffer_paste_clipboard (GtkTextBuffer *buffer,
- guint32 time,
- gboolean interactive,
gboolean default_editable);
+
gboolean gtk_text_buffer_get_selection_bounds (GtkTextBuffer *buffer,
GtkTextIter *start,
GtkTextIter *end);
-
+gboolean gtk_text_buffer_delete_selection (GtkTextBuffer *buffer,
+ gboolean interactive,
+ gboolean default_editable);
/* This function is not implemented. */
gboolean gtk_text_buffer_find_string(GtkTextBuffer *buffer,
diff --git a/gtk/gtktextlayout.c b/gtk/gtktextlayout.c
index af2b76edb2..901aa92666 100644
--- a/gtk/gtktextlayout.c
+++ b/gtk/gtktextlayout.c
@@ -2062,6 +2062,60 @@ gtk_text_layout_move_iter_to_next_line (GtkTextLayout *layout,
}
/**
+ * gtk_text_layout_move_iter_to_line_end:
+ * @layout: a #GtkTextLayout
+ * @direction: if negative, move to beginning of line, otherwise
+ move to end of line.
+ *
+ * Move to the beginning or end of a display line.
+ **/
+void
+gtk_text_layout_move_iter_to_line_end (GtkTextLayout *layout,
+ GtkTextIter *iter,
+ gint direction)
+{
+ GtkTextLine *line;
+ GtkTextLineDisplay *display;
+ gint line_byte;
+ gint byte_offset = 0;
+ GSList *tmp_list;
+
+ g_return_if_fail (layout != NULL);
+ g_return_if_fail (GTK_IS_TEXT_LAYOUT (layout));
+ g_return_if_fail (iter != NULL);
+
+ line = gtk_text_iter_get_text_line (iter);
+ line_byte = gtk_text_iter_get_line_index (iter);
+
+ display = gtk_text_layout_get_line_display (layout, line, FALSE);
+
+ tmp_list = pango_layout_get_lines (display->layout);
+ while (tmp_list)
+ {
+ PangoLayoutLine *layout_line = tmp_list->data;
+
+ if (line_byte < byte_offset + layout_line->length || !tmp_list->next)
+ {
+ gtk_text_btree_get_iter_at_line (_gtk_text_buffer_get_btree (layout->buffer),
+ iter, line,
+ direction < 0 ? byte_offset : layout_line->length);
+
+ /* FIXME: Move back one position to avoid going to next line
+ */
+ if (direction < 0 && layout_line->length > 0)
+ gtk_text_iter_prev_char (iter);
+
+ break;
+ }
+
+ byte_offset += layout_line->length;
+ tmp_list = tmp_list->next;
+ }
+
+ gtk_text_layout_free_line_display (layout, display);
+}
+
+/**
* gtk_text_layout_move_iter_to_x:
* @layout: a #GtkTextLayout
* @iter: a #GtkTextIter
diff --git a/gtk/gtktextlayout.h b/gtk/gtktextlayout.h
index 048b55d771..e06ed4fd3f 100644
--- a/gtk/gtktextlayout.h
+++ b/gtk/gtktextlayout.h
@@ -245,6 +245,9 @@ gboolean gtk_text_layout_clamp_iter_to_vrange (GtkTextLayout *layout,
gint top,
gint bottom);
+void gtk_text_layout_move_iter_to_line_end (GtkTextLayout *layout,
+ GtkTextIter *iter,
+ gint direction);
void gtk_text_layout_move_iter_to_previous_line (GtkTextLayout *layout,
GtkTextIter *iter);
void gtk_text_layout_move_iter_to_next_line (GtkTextLayout *layout,
@@ -256,7 +259,6 @@ void gtk_text_layout_move_iter_visually (GtkTextLayout *layout,
GtkTextIter *iter,
gint count);
-
void gtk_text_layout_spew (GtkTextLayout *layout);
#ifdef __cplusplus
diff --git a/gtk/gtktextview.c b/gtk/gtktextview.c
index e97df15f72..55b378c6e9 100644
--- a/gtk/gtktextview.c
+++ b/gtk/gtktextview.c
@@ -63,13 +63,13 @@
#include <string.h>
enum {
- MOVE_INSERT,
+ MOVE,
SET_ANCHOR,
- SCROLL_TEXT,
- DELETE_TEXT,
- CUT_TEXT,
- COPY_TEXT,
- PASTE_TEXT,
+ INSERT,
+ DELETE,
+ CUT_CLIPBOARD,
+ COPY_CLIPBOARD,
+ PASTE_CLIPBOARD,
TOGGLE_OVERWRITE,
SET_SCROLL_ADJUSTMENTS,
LAST_SIGNAL
@@ -168,21 +168,22 @@ static void gtk_text_view_set_scroll_adjustments (GtkTextView *text_view,
GtkAdjustment *hadj,
GtkAdjustment *vadj);
-static void gtk_text_view_move_insert (GtkTextView *text_view,
- GtkTextViewMovementStep step,
- gint count,
- gboolean extend_selection);
-static void gtk_text_view_set_anchor (GtkTextView *text_view);
-static void gtk_text_view_scroll_text (GtkTextView *text_view,
- GtkTextViewScrollType type);
-static void gtk_text_view_delete_text (GtkTextView *text_view,
- GtkTextViewDeleteType type,
- gint count);
-static void gtk_text_view_cut_text (GtkTextView *text_view);
-static void gtk_text_view_copy_text (GtkTextView *text_view);
-static void gtk_text_view_paste_text (GtkTextView *text_view);
-static void gtk_text_view_toggle_overwrite (GtkTextView *text_view);
-
+static void gtk_text_view_move (GtkTextView *text_view,
+ GtkMovementStep step,
+ gint count,
+ gboolean extend_selection);
+static void gtk_text_view_set_anchor (GtkTextView *text_view);
+static void gtk_text_view_scroll_pages (GtkTextView *text_view,
+ gint count);
+static void gtk_text_view_insert (GtkTextView *text_view,
+ const gchar *str);
+static void gtk_text_view_delete (GtkTextView *text_view,
+ GtkDeleteType type,
+ gint count);
+static void gtk_text_view_cut_clipboard (GtkTextView *text_view);
+static void gtk_text_view_copy_clipboard (GtkTextView *text_view);
+static void gtk_text_view_paste_clipboard (GtkTextView *text_view);
+static void gtk_text_view_toggle_overwrite (GtkTextView *text_view);
static void gtk_text_view_validate_onscreen (GtkTextView *text_view);
static void gtk_text_view_get_first_para_iter (GtkTextView *text_view,
@@ -231,12 +232,6 @@ enum {
TARGET_UTF8_STRING
};
-static GdkAtom clipboard_atom = GDK_NONE;
-static GdkAtom text_atom = GDK_NONE;
-static GdkAtom ctext_atom = GDK_NONE;
-static GdkAtom utf8_atom = GDK_NONE;
-
-
static GtkTargetEntry target_table[] = {
{ "UTF8_STRING", 0, TARGET_UTF8_STRING },
{ "COMPOUND_TEXT", 0, TARGET_COMPOUND_TEXT },
@@ -245,8 +240,6 @@ static GtkTargetEntry target_table[] = {
{ "STRING", 0, TARGET_STRING }
};
-static guint n_targets = sizeof (target_table) / sizeof (target_table[0]);
-
static GtkContainerClass *parent_class = NULL;
static guint signals[LAST_SIGNAL] = { 0 };
@@ -276,23 +269,23 @@ gtk_text_view_get_type (void)
}
static void
-add_move_insert_binding (GtkBindingSet *binding_set,
- guint keyval,
- guint modmask,
- GtkTextViewMovementStep step,
- gint count)
+add_move_binding (GtkBindingSet *binding_set,
+ guint keyval,
+ guint modmask,
+ GtkMovementStep step,
+ gint count)
{
g_return_if_fail ((modmask & GDK_SHIFT_MASK) == 0);
gtk_binding_entry_add_signal (binding_set, keyval, modmask,
- "move_insert", 3,
+ "move", 3,
GTK_TYPE_ENUM, step,
GTK_TYPE_INT, count,
GTK_TYPE_BOOL, FALSE);
/* Selection-extending version */
gtk_binding_entry_add_signal (binding_set, keyval, modmask | GDK_SHIFT_MASK,
- "move_insert", 3,
+ "move", 3,
GTK_TYPE_ENUM, step,
GTK_TYPE_INT, count,
GTK_TYPE_BOOL, TRUE);
@@ -331,13 +324,13 @@ gtk_text_view_class_init (GtkTextViewClass *klass)
* Signals
*/
- signals[MOVE_INSERT] =
- gtk_signal_new ("move_insert",
+ signals[MOVE] =
+ gtk_signal_new ("move",
GTK_RUN_LAST | GTK_RUN_ACTION,
GTK_CLASS_TYPE (object_class),
- GTK_SIGNAL_OFFSET (GtkTextViewClass, move_insert),
+ GTK_SIGNAL_OFFSET (GtkTextViewClass, move),
gtk_marshal_NONE__INT_INT_INT,
- GTK_TYPE_NONE, 3, GTK_TYPE_ENUM, GTK_TYPE_INT, GTK_TYPE_BOOL);
+ GTK_TYPE_NONE, 3, GTK_TYPE_MOVEMENT_STEP, GTK_TYPE_INT, GTK_TYPE_BOOL);
signals[SET_ANCHOR] =
gtk_signal_new ("set_anchor",
@@ -347,43 +340,43 @@ gtk_text_view_class_init (GtkTextViewClass *klass)
gtk_marshal_NONE__NONE,
GTK_TYPE_NONE, 0);
- signals[SCROLL_TEXT] =
- gtk_signal_new ("scroll_text",
+ signals[INSERT] =
+ gtk_signal_new ("insert",
GTK_RUN_LAST | GTK_RUN_ACTION,
GTK_CLASS_TYPE (object_class),
- GTK_SIGNAL_OFFSET (GtkTextViewClass, scroll_text),
- gtk_marshal_NONE__INT,
- GTK_TYPE_NONE, 1, GTK_TYPE_ENUM);
+ GTK_SIGNAL_OFFSET (GtkTextViewClass, insert),
+ gtk_marshal_NONE__STRING,
+ GTK_TYPE_NONE, 1, GTK_TYPE_STRING);
- signals[DELETE_TEXT] =
- gtk_signal_new ("delete_text",
+ signals[DELETE] =
+ gtk_signal_new ("delete",
GTK_RUN_LAST | GTK_RUN_ACTION,
GTK_CLASS_TYPE (object_class),
- GTK_SIGNAL_OFFSET (GtkTextViewClass, delete_text),
+ GTK_SIGNAL_OFFSET (GtkTextViewClass, delete),
gtk_marshal_NONE__INT_INT,
- GTK_TYPE_NONE, 2, GTK_TYPE_ENUM, GTK_TYPE_INT);
+ GTK_TYPE_NONE, 2, GTK_TYPE_DELETE_TYPE, GTK_TYPE_INT);
- signals[CUT_TEXT] =
- gtk_signal_new ("cut_text",
+ signals[CUT_CLIPBOARD] =
+ gtk_signal_new ("cut_clipboard",
GTK_RUN_LAST | GTK_RUN_ACTION,
GTK_CLASS_TYPE (object_class),
- GTK_SIGNAL_OFFSET (GtkTextViewClass, cut_text),
+ GTK_SIGNAL_OFFSET (GtkTextViewClass, cut_clipboard),
gtk_marshal_NONE__NONE,
GTK_TYPE_NONE, 0);
- signals[COPY_TEXT] =
- gtk_signal_new ("copy_text",
+ signals[COPY_CLIPBOARD] =
+ gtk_signal_new ("copy_clipboard",
GTK_RUN_LAST | GTK_RUN_ACTION,
GTK_CLASS_TYPE (object_class),
- GTK_SIGNAL_OFFSET (GtkTextViewClass, copy_text),
+ GTK_SIGNAL_OFFSET (GtkTextViewClass, copy_clipboard),
gtk_marshal_NONE__NONE,
GTK_TYPE_NONE, 0);
- signals[PASTE_TEXT] =
- gtk_signal_new ("paste_text",
+ signals[PASTE_CLIPBOARD] =
+ gtk_signal_new ("paste_clipboard",
GTK_RUN_LAST | GTK_RUN_ACTION,
GTK_CLASS_TYPE (object_class),
- GTK_SIGNAL_OFFSET (GtkTextViewClass, paste_text),
+ GTK_SIGNAL_OFFSET (GtkTextViewClass, paste_clipboard),
gtk_marshal_NONE__NONE,
GTK_TYPE_NONE, 0);
@@ -412,123 +405,142 @@ gtk_text_view_class_init (GtkTextViewClass *klass)
binding_set = gtk_binding_set_by_class (klass);
/* Moving the insertion point */
- add_move_insert_binding (binding_set, GDK_Right, 0,
- GTK_TEXT_MOVEMENT_POSITIONS, 1);
+ add_move_binding (binding_set, GDK_Right, 0,
+ GTK_MOVEMENT_POSITIONS, 1);
- add_move_insert_binding (binding_set, GDK_Left, 0,
- GTK_TEXT_MOVEMENT_POSITIONS, -1);
+ add_move_binding (binding_set, GDK_Left, 0,
+ GTK_MOVEMENT_POSITIONS, -1);
- add_move_insert_binding (binding_set, GDK_f, GDK_CONTROL_MASK,
- GTK_TEXT_MOVEMENT_CHAR, 1);
+ add_move_binding (binding_set, GDK_f, GDK_CONTROL_MASK,
+ GTK_MOVEMENT_CHARS, 1);
- add_move_insert_binding (binding_set, GDK_b, GDK_CONTROL_MASK,
- GTK_TEXT_MOVEMENT_CHAR, -1);
+ add_move_binding (binding_set, GDK_b, GDK_CONTROL_MASK,
+ GTK_MOVEMENT_CHARS, -1);
- add_move_insert_binding (binding_set, GDK_Right, GDK_CONTROL_MASK,
- GTK_TEXT_MOVEMENT_WORD, 1);
+ add_move_binding (binding_set, GDK_Right, GDK_CONTROL_MASK,
+ GTK_MOVEMENT_WORDS, 1);
- add_move_insert_binding (binding_set, GDK_Left, GDK_CONTROL_MASK,
- GTK_TEXT_MOVEMENT_WORD, -1);
+ add_move_binding (binding_set, GDK_Left, GDK_CONTROL_MASK,
+ GTK_MOVEMENT_WORDS, -1);
/* Eventually we want to move by display lines, not paragraphs */
- add_move_insert_binding (binding_set, GDK_Up, 0,
- GTK_TEXT_MOVEMENT_WRAPPED_LINE, -1);
+ add_move_binding (binding_set, GDK_Up, 0,
+ GTK_MOVEMENT_DISPLAY_LINES, -1);
- add_move_insert_binding (binding_set, GDK_Down, 0,
- GTK_TEXT_MOVEMENT_WRAPPED_LINE, 1);
+ add_move_binding (binding_set, GDK_Down, 0,
+ GTK_MOVEMENT_DISPLAY_LINES, 1);
- add_move_insert_binding (binding_set, GDK_p, GDK_CONTROL_MASK,
- GTK_TEXT_MOVEMENT_WRAPPED_LINE, -1);
+ add_move_binding (binding_set, GDK_p, GDK_CONTROL_MASK,
+ GTK_MOVEMENT_DISPLAY_LINES, -1);
- add_move_insert_binding (binding_set, GDK_n, GDK_CONTROL_MASK,
- GTK_TEXT_MOVEMENT_WRAPPED_LINE, 1);
+ add_move_binding (binding_set, GDK_n, GDK_CONTROL_MASK,
+ GTK_MOVEMENT_DISPLAY_LINES, 1);
- add_move_insert_binding (binding_set, GDK_a, GDK_CONTROL_MASK,
- GTK_TEXT_MOVEMENT_LINE_ENDS, -1);
+ add_move_binding (binding_set, GDK_a, GDK_CONTROL_MASK,
+ GTK_MOVEMENT_PARAGRAPH_ENDS, -1);
- add_move_insert_binding (binding_set, GDK_e, GDK_CONTROL_MASK,
- GTK_TEXT_MOVEMENT_LINE_ENDS, 1);
+ add_move_binding (binding_set, GDK_e, GDK_CONTROL_MASK,
+ GTK_MOVEMENT_PARAGRAPH_ENDS, 1);
- add_move_insert_binding (binding_set, GDK_f, GDK_MOD1_MASK,
- GTK_TEXT_MOVEMENT_WORD, 1);
+ add_move_binding (binding_set, GDK_f, GDK_MOD1_MASK,
+ GTK_MOVEMENT_WORDS, 1);
- add_move_insert_binding (binding_set, GDK_b, GDK_MOD1_MASK,
- GTK_TEXT_MOVEMENT_WORD, -1);
+ add_move_binding (binding_set, GDK_b, GDK_MOD1_MASK,
+ GTK_MOVEMENT_WORDS, -1);
- add_move_insert_binding (binding_set, GDK_Home, 0,
- GTK_TEXT_MOVEMENT_BUFFER_ENDS, -1);
+ add_move_binding (binding_set, GDK_Home, 0,
+ GTK_MOVEMENT_DISPLAY_LINE_ENDS, -1);
- add_move_insert_binding (binding_set, GDK_End, 0,
- GTK_TEXT_MOVEMENT_BUFFER_ENDS, 1);
+ add_move_binding (binding_set, GDK_End, 0,
+ GTK_MOVEMENT_DISPLAY_LINE_ENDS, 1);
+
+ add_move_binding (binding_set, GDK_Home, GDK_CONTROL_MASK,
+ GTK_MOVEMENT_BUFFER_ENDS, -1);
+
+ add_move_binding (binding_set, GDK_End, GDK_CONTROL_MASK,
+ GTK_MOVEMENT_BUFFER_ENDS, 1);
+
+ add_move_binding (binding_set, GDK_Page_Up, 0,
+ GTK_MOVEMENT_PAGES, -1);
+
+ add_move_binding (binding_set, GDK_Page_Down, 0,
+ GTK_MOVEMENT_PAGES, 1);
+
/* Setting the cut/paste/copy anchor */
gtk_binding_entry_add_signal (binding_set, GDK_space, GDK_CONTROL_MASK,
"set_anchor", 0);
-
- /* Scrolling around */
- gtk_binding_entry_add_signal (binding_set, GDK_Page_Up, 0,
- "scroll_text", 1,
- GTK_TYPE_ENUM, GTK_TEXT_SCROLL_PAGE_UP);
-
- gtk_binding_entry_add_signal (binding_set, GDK_Page_Down, 0,
- "scroll_text", 1,
- GTK_TYPE_ENUM, GTK_TEXT_SCROLL_PAGE_DOWN);
-
/* Deleting text */
gtk_binding_entry_add_signal (binding_set, GDK_Delete, 0,
- "delete_text", 2,
- GTK_TYPE_ENUM, GTK_TEXT_DELETE_CHAR,
+ "delete", 2,
+ GTK_TYPE_ENUM, GTK_DELETE_CHARS,
+ GTK_TYPE_INT, 1);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_d, GDK_CONTROL_MASK,
+ "delete", 2,
+ GTK_TYPE_ENUM, GTK_DELETE_CHARS,
GTK_TYPE_INT, 1);
gtk_binding_entry_add_signal (binding_set, GDK_BackSpace, 0,
- "delete_text", 2,
- GTK_TYPE_ENUM, GTK_TEXT_DELETE_CHAR,
+ "delete", 2,
+ GTK_TYPE_ENUM, GTK_DELETE_CHARS,
GTK_TYPE_INT, -1);
gtk_binding_entry_add_signal (binding_set, GDK_Delete, GDK_CONTROL_MASK,
- "delete_text", 2,
- GTK_TYPE_ENUM, GTK_TEXT_DELETE_HALF_WORD,
+ "delete", 2,
+ GTK_TYPE_ENUM, GTK_DELETE_WORD_ENDS,
+ GTK_TYPE_INT, 1);
+
+ gtk_binding_entry_add_signal (binding_set, GDK_d, GDK_MOD1_MASK,
+ "delete", 2,
+ GTK_TYPE_ENUM, GTK_DELETE_WORD_ENDS,
GTK_TYPE_INT, 1);
gtk_binding_entry_add_signal (binding_set, GDK_BackSpace, GDK_CONTROL_MASK,
- "delete_text", 2,
- GTK_TYPE_ENUM, GTK_TEXT_DELETE_HALF_WORD,
+ "delete", 2,
+ GTK_TYPE_ENUM, GTK_DELETE_WORD_ENDS,
GTK_TYPE_INT, -1);
gtk_binding_entry_add_signal (binding_set, GDK_k, GDK_CONTROL_MASK,
- "delete_text", 2,
- GTK_TYPE_ENUM, GTK_TEXT_DELETE_HALF_LINE,
+ "delete", 2,
+ GTK_TYPE_ENUM, GTK_DELETE_PARAGRAPH_ENDS,
GTK_TYPE_INT, 1);
gtk_binding_entry_add_signal (binding_set, GDK_u, GDK_CONTROL_MASK,
- "delete_text", 2,
- GTK_TYPE_ENUM, GTK_TEXT_DELETE_WHOLE_LINE,
+ "delete", 2,
+ GTK_TYPE_ENUM, GTK_DELETE_PARAGRAPHS,
GTK_TYPE_INT, 1);
gtk_binding_entry_add_signal (binding_set, GDK_space, GDK_MOD1_MASK,
- "delete_text", 2,
- GTK_TYPE_ENUM, GTK_TEXT_DELETE_WHITESPACE_LEAVE_ONE,
+ "delete", 2,
+ GTK_TYPE_ENUM, GTK_DELETE_WHITESPACE,
GTK_TYPE_INT, 1);
+ gtk_binding_entry_add_signal (binding_set, GDK_space, GDK_MOD1_MASK,
+ "insert", 1,
+ GTK_TYPE_STRING, " ");
gtk_binding_entry_add_signal (binding_set, GDK_backslash, GDK_MOD1_MASK,
- "delete_text", 2,
- GTK_TYPE_ENUM, GTK_TEXT_DELETE_WHITESPACE,
+ "delete", 2,
+ GTK_TYPE_ENUM, GTK_DELETE_WHITESPACE,
GTK_TYPE_INT, 1);
/* Cut/copy/paste */
gtk_binding_entry_add_signal (binding_set, GDK_x, GDK_CONTROL_MASK,
- "cut_text", 0);
+ "cut_clipboard", 0);
gtk_binding_entry_add_signal (binding_set, GDK_w, GDK_CONTROL_MASK,
- "cut_text", 0);
+ "cut_clipboard", 0);
gtk_binding_entry_add_signal (binding_set, GDK_c, GDK_CONTROL_MASK,
- "copy_text", 0);
+ "copy_clipboard", 0);
+ gtk_binding_entry_add_signal (binding_set, GDK_v, GDK_CONTROL_MASK,
+ "paste_clipboard", 0);
+
gtk_binding_entry_add_signal (binding_set, GDK_y, GDK_CONTROL_MASK,
- "paste_text", 0);
+ "paste_clipboard", 0);
/* Overwrite */
gtk_binding_entry_add_signal (binding_set, GDK_Insert, 0,
@@ -570,13 +582,13 @@ gtk_text_view_class_init (GtkTextViewClass *klass)
widget_class->drag_drop = gtk_text_view_drag_drop;
widget_class->drag_data_received = gtk_text_view_drag_data_received;
- klass->move_insert = gtk_text_view_move_insert;
+ klass->move = gtk_text_view_move;
klass->set_anchor = gtk_text_view_set_anchor;
- klass->scroll_text = gtk_text_view_scroll_text;
- klass->delete_text = gtk_text_view_delete_text;
- klass->cut_text = gtk_text_view_cut_text;
- klass->copy_text = gtk_text_view_copy_text;
- klass->paste_text = gtk_text_view_paste_text;
+ klass->insert = gtk_text_view_insert;
+ klass->delete = gtk_text_view_delete;
+ klass->cut_clipboard = gtk_text_view_cut_clipboard;
+ klass->copy_clipboard = gtk_text_view_copy_clipboard;
+ klass->paste_clipboard = gtk_text_view_paste_clipboard;
klass->toggle_overwrite = gtk_text_view_toggle_overwrite;
klass->set_scroll_adjustments = gtk_text_view_set_scroll_adjustments;
}
@@ -592,21 +604,9 @@ gtk_text_view_init (GtkTextView *text_view)
text_view->wrap_mode = GTK_WRAPMODE_NONE;
- if (!clipboard_atom)
- clipboard_atom = gdk_atom_intern ("CLIPBOARD", FALSE);
-
- if (!text_atom)
- text_atom = gdk_atom_intern ("TEXT", FALSE);
-
- if (!ctext_atom)
- ctext_atom = gdk_atom_intern ("COMPOUND_TEXT", FALSE);
-
- if (!utf8_atom)
- utf8_atom = gdk_atom_intern ("UTF8_STRING", FALSE);
-
gtk_drag_dest_set (widget,
GTK_DEST_DEFAULT_DROP | GTK_DEST_DEFAULT_MOTION,
- target_table, n_targets,
+ target_table, G_N_ELEMENTS (target_table),
GDK_ACTION_COPY | GDK_ACTION_MOVE);
text_view->virtual_cursor_x = -1;
@@ -1667,11 +1667,9 @@ gtk_text_view_button_press_event (GtkWidget *widget, GdkEventButton *event)
event->x + text_view->xoffset,
event->y + text_view->yoffset);
- gtk_text_buffer_paste_primary_selection (text_view->buffer,
- &iter,
- event->time,
- TRUE,
- text_view->editable);
+ gtk_text_buffer_paste_primary (text_view->buffer,
+ &iter,
+ text_view->editable);
return TRUE;
}
else if (event->button == 3)
@@ -1843,61 +1841,77 @@ gtk_text_view_move_iter_by_lines (GtkTextView *text_view,
}
static void
-gtk_text_view_move_insert (GtkTextView *text_view,
- GtkTextViewMovementStep step,
- gint count,
- gboolean extend_selection)
+gtk_text_view_move (GtkTextView *text_view,
+ GtkMovementStep step,
+ gint count,
+ gboolean extend_selection)
{
GtkTextIter insert;
GtkTextIter newplace;
gint cursor_x_pos = 0;
+ if (step == GTK_MOVEMENT_PAGES)
+ {
+ gtk_text_view_scroll_pages (text_view, count);
+ return;
+ }
+
gtk_text_buffer_get_iter_at_mark (text_view->buffer, &insert,
gtk_text_buffer_get_mark (text_view->buffer,
"insert"));
newplace = insert;
- if (step == GTK_TEXT_MOVEMENT_WRAPPED_LINE)
+ if (step == GTK_MOVEMENT_DISPLAY_LINES)
gtk_text_view_get_virtual_cursor_pos (text_view, &cursor_x_pos, NULL);
switch (step)
{
- case GTK_TEXT_MOVEMENT_CHAR:
+ case GTK_MOVEMENT_CHARS:
gtk_text_iter_forward_chars (&newplace, count);
break;
- case GTK_TEXT_MOVEMENT_POSITIONS:
+ case GTK_MOVEMENT_POSITIONS:
gtk_text_layout_move_iter_visually (text_view->layout,
&newplace, count);
break;
- case GTK_TEXT_MOVEMENT_WORD:
+ case GTK_MOVEMENT_WORDS:
if (count < 0)
gtk_text_iter_backward_word_starts (&newplace, -count);
else if (count > 0)
gtk_text_iter_forward_word_ends (&newplace, count);
break;
- case GTK_TEXT_MOVEMENT_WRAPPED_LINE:
+ case GTK_MOVEMENT_DISPLAY_LINES:
gtk_text_view_move_iter_by_lines (text_view, &newplace, count);
gtk_text_layout_move_iter_to_x (text_view->layout, &newplace, cursor_x_pos);
break;
- case GTK_TEXT_MOVEMENT_LINE:
+ case GTK_MOVEMENT_DISPLAY_LINE_ENDS:
+ if (count > 1)
+ gtk_text_view_move_iter_by_lines (text_view, &newplace, --count);
+ else if (count < -1)
+ gtk_text_view_move_iter_by_lines (text_view, &newplace, ++count);
+
+ if (count != 0)
+ gtk_text_layout_move_iter_to_line_end (text_view->layout, &newplace, count);
+ break;
+
+ case GTK_MOVEMENT_PARAGRAPHS:
/* This should almost certainly instead be doing the parallel thing to WORD */
/* gtk_text_iter_down_lines (&newplace, count); */
/* FIXME */
break;
- case GTK_TEXT_MOVEMENT_LINE_ENDS:
+ case GTK_MOVEMENT_PARAGRAPH_ENDS:
if (count > 0)
gtk_text_iter_forward_to_newline (&newplace);
else if (count < 0)
gtk_text_iter_set_line_offset (&newplace, 0);
break;
- case GTK_TEXT_MOVEMENT_BUFFER_ENDS:
+ case GTK_MOVEMENT_BUFFER_ENDS:
if (count > 0)
gtk_text_buffer_get_last_iter (text_view->buffer, &newplace);
else if (count < 0)
@@ -1922,7 +1936,7 @@ gtk_text_view_move_insert (GtkTextView *text_view,
gtk_text_buffer_get_mark (text_view->buffer,
"insert"), 0);
- if (step == GTK_TEXT_MOVEMENT_WRAPPED_LINE)
+ if (step == GTK_MOVEMENT_DISPLAY_LINES)
{
gtk_text_view_set_virtual_cursor_pos (text_view, cursor_x_pos, -1);
}
@@ -1942,8 +1956,8 @@ gtk_text_view_set_anchor (GtkTextView *text_view)
}
static void
-gtk_text_view_scroll_text (GtkTextView *text_view,
- GtkTextViewScrollType type)
+gtk_text_view_scroll_pages (GtkTextView *text_view,
+ gint count)
{
gfloat newval;
GtkAdjustment *adj;
@@ -1958,60 +1972,26 @@ gtk_text_view_scroll_text (GtkTextView *text_view,
/* Validate the region that will be brought into view by the cursor motion
*/
- switch (type)
+ if (count < 0)
{
- default:
- case GTK_TEXT_SCROLL_TO_TOP:
- gtk_text_buffer_get_iter_at_offset (text_view->buffer, &anchor, 0);
- y0 = 0;
- y1 = adj->page_size;
- break;
-
- case GTK_TEXT_SCROLL_TO_BOTTOM:
- gtk_text_buffer_get_last_iter (text_view->buffer, &anchor);
- y0 = -adj->page_size;
- y1 = adj->page_size;
- break;
-
- case GTK_TEXT_SCROLL_PAGE_DOWN:
gtk_text_view_get_first_para_iter (text_view, &anchor);
y0 = adj->page_size;
- y1 = adj->page_size + adj->page_increment;
- break;
-
- case GTK_TEXT_SCROLL_PAGE_UP:
+ y1 = adj->page_size + count * adj->page_increment;
+ }
+ else
+ {
gtk_text_view_get_first_para_iter (text_view, &anchor);
- y0 = - adj->page_increment + adj->page_size;
+ y0 = count * adj->page_increment + adj->page_size;
y1 = 0;
- break;
}
+
gtk_text_layout_validate_yrange (text_view->layout, &anchor, y0, y1);
gtk_text_view_get_virtual_cursor_pos (text_view, &cursor_x_pos, &cursor_y_pos);
newval = adj->value;
- switch (type)
- {
- case GTK_TEXT_SCROLL_TO_TOP:
- newval = adj->lower;
- break;
-
- case GTK_TEXT_SCROLL_TO_BOTTOM:
- newval = adj->upper;
- break;
-
- case GTK_TEXT_SCROLL_PAGE_DOWN:
- newval += adj->page_increment;
- break;
-
- case GTK_TEXT_SCROLL_PAGE_UP:
- newval -= adj->page_increment;
- break;
-
- default:
- break;
- }
+ newval += count * adj->page_increment;
cursor_y_pos += newval - adj->value;
set_adjustment_clamped (adj, newval);
@@ -2059,16 +2039,24 @@ find_whitepace_region (const GtkTextIter *center,
}
static void
-gtk_text_view_delete_text (GtkTextView *text_view,
- GtkTextViewDeleteType type,
- gint count)
+gtk_text_view_insert (GtkTextView *text_view,
+ const gchar *str)
+{
+ gtk_text_buffer_insert_interactive_at_cursor (text_view->buffer, str, -1,
+ text_view->editable);
+}
+
+static void
+gtk_text_view_delete (GtkTextView *text_view,
+ GtkDeleteType type,
+ gint count)
{
GtkTextIter insert;
GtkTextIter start;
GtkTextIter end;
gboolean leave_one = FALSE;
- if (type == GTK_TEXT_DELETE_CHAR)
+ if (type == GTK_DELETE_CHARS)
{
/* Char delete deletes the selection, if one exists */
if (gtk_text_buffer_delete_selection (text_view->buffer, TRUE,
@@ -2086,27 +2074,27 @@ gtk_text_view_delete_text (GtkTextView *text_view,
switch (type)
{
- case GTK_TEXT_DELETE_CHAR:
+ case GTK_DELETE_CHARS:
gtk_text_iter_forward_chars (&end, count);
break;
- case GTK_TEXT_DELETE_HALF_WORD:
+ case GTK_DELETE_WORD_ENDS:
if (count > 0)
gtk_text_iter_forward_word_ends (&end, count);
else if (count < 0)
gtk_text_iter_backward_word_starts (&start, 0 - count);
break;
- case GTK_TEXT_DELETE_WHOLE_WORD:
+ case GTK_DELETE_WORDS:
break;
- case GTK_TEXT_DELETE_HALF_WRAPPED_LINE:
+ case GTK_DELETE_DISPLAY_LINE_ENDS:
break;
- case GTK_TEXT_DELETE_WHOLE_WRAPPED_LINE:
+ case GTK_DELETE_DISPLAY_LINES:
break;
- case GTK_TEXT_DELETE_HALF_LINE:
+ case GTK_DELETE_PARAGRAPH_ENDS:
while (count > 0)
{
if (!gtk_text_iter_forward_to_newline (&end))
@@ -2119,7 +2107,7 @@ gtk_text_view_delete_text (GtkTextView *text_view,
and support that */
break;
- case GTK_TEXT_DELETE_WHOLE_LINE:
+ case GTK_DELETE_PARAGRAPHS:
if (count > 0)
{
gtk_text_iter_set_line_offset (&start, 0);
@@ -2138,9 +2126,7 @@ gtk_text_view_delete_text (GtkTextView *text_view,
break;
- case GTK_TEXT_DELETE_WHITESPACE_LEAVE_ONE:
- leave_one = TRUE; /* FALL THRU */
- case GTK_TEXT_DELETE_WHITESPACE:
+ case GTK_DELETE_WHITESPACE:
{
find_whitepace_region (&insert, &start, &end);
}
@@ -2168,9 +2154,9 @@ gtk_text_view_delete_text (GtkTextView *text_view,
}
static void
-gtk_text_view_cut_text (GtkTextView *text_view)
+gtk_text_view_cut_clipboard (GtkTextView *text_view)
{
- gtk_text_buffer_cut (text_view->buffer, GDK_CURRENT_TIME, TRUE, text_view->editable);
+ gtk_text_buffer_cut_clipboard (text_view->buffer, text_view->editable);
gtk_text_view_scroll_to_mark (text_view,
gtk_text_buffer_get_mark (text_view->buffer,
"insert"),
@@ -2178,9 +2164,9 @@ gtk_text_view_cut_text (GtkTextView *text_view)
}
static void
-gtk_text_view_copy_text (GtkTextView *text_view)
+gtk_text_view_copy_clipboard (GtkTextView *text_view)
{
- gtk_text_buffer_copy (text_view->buffer, GDK_CURRENT_TIME);
+ gtk_text_buffer_copy_clipboard (text_view->buffer);
gtk_text_view_scroll_to_mark (text_view,
gtk_text_buffer_get_mark (text_view->buffer,
"insert"),
@@ -2188,9 +2174,9 @@ gtk_text_view_copy_text (GtkTextView *text_view)
}
static void
-gtk_text_view_paste_text (GtkTextView *text_view)
+gtk_text_view_paste_clipboard (GtkTextView *text_view)
{
- gtk_text_buffer_paste_clipboard (text_view->buffer, GDK_CURRENT_TIME, TRUE, text_view->editable);
+ gtk_text_buffer_paste_clipboard (text_view->buffer, text_view->editable);
gtk_text_view_scroll_to_mark (text_view,
gtk_text_buffer_get_mark (text_view->buffer,
"insert"),
@@ -2567,16 +2553,14 @@ gtk_text_view_start_selection_dnd (GtkTextView *text_view,
GdkDragContext *context;
GtkTargetList *target_list;
- /* FIXME we have to handle more formats for the selection,
- and do the conversions to/from UTF8 */
-
- /* FIXME not sure how this is memory-managed. */
- target_list = gtk_target_list_new (target_table, n_targets);
-
+ target_list = gtk_target_list_new (target_table, G_N_ELEMENTS (target_table));
+
context = gtk_drag_begin (GTK_WIDGET (text_view), target_list,
GDK_ACTION_COPY | GDK_ACTION_MOVE,
1, (GdkEvent*)event);
+ gtk_target_list_unref (target_list);
+
gtk_drag_set_icon_default (context);
/* We're inside the selection, so start without being able
@@ -2631,46 +2615,7 @@ gtk_text_view_drag_data_get (GtkWidget *widget,
if (str)
{
- if (info == TARGET_UTF8_STRING)
- {
- /* Pass raw UTF8 */
- gtk_selection_data_set (selection_data,
- utf8_atom,
- 8*sizeof (gchar), (guchar *)str, length);
-
- }
- else if (info == TARGET_STRING ||
- info == TARGET_TEXT)
- {
- gchar *latin1;
-
- latin1 = gtk_text_utf_to_latin1(str, length);
-
- gtk_selection_data_set (selection_data,
- GDK_SELECTION_TYPE_STRING,
- 8*sizeof (gchar), latin1, strlen (latin1));
- g_free (latin1);
- }
- else if (info == TARGET_COMPOUND_TEXT)
- {
- /* FIXME convert UTF8 directly to current locale, not via
- latin1 */
-
- guchar *text;
- GdkAtom encoding;
- gint format;
- gint new_length;
- gchar *latin1;
-
- latin1 = gtk_text_utf_to_latin1(str, length);
-
- gdk_string_to_compound_text (latin1, &encoding, &format, &text, &new_length);
- gtk_selection_data_set (selection_data, encoding, format, text, new_length);
- gdk_free_compound_text (text);
-
- g_free (latin1);
- }
-
+ gtk_selection_data_set_text (selection_data, str);
g_free (str);
}
}
@@ -2792,27 +2737,10 @@ gtk_text_view_drag_data_received (GtkWidget *widget,
GtkTextIter drop_point;
GtkTextView *text_view;
GtkTextMark *drag_target_mark;
+ gchar *str;
- enum {INVALID, STRING, CTEXT, UTF8} type;
-
text_view = GTK_TEXT_VIEW (widget);
- if (selection_data->type == GDK_TARGET_STRING)
- type = STRING;
- else if (selection_data->type == ctext_atom)
- type = CTEXT;
- else if (selection_data->type == utf8_atom)
- type = UTF8;
- else
- type = INVALID;
-
- if (type == INVALID || selection_data->length < 0)
- {
- /* I think the DND code automatically tries asking
- for the various formats. */
- return;
- }
-
drag_target_mark = gtk_text_buffer_get_mark (text_view->buffer,
"__drag_target");
@@ -2823,71 +2751,13 @@ gtk_text_view_drag_data_received (GtkWidget *widget,
&drop_point,
drag_target_mark);
-
- switch (type)
+ str = gtk_selection_data_get_text (selection_data);
+ if (str)
{
- case STRING:
- {
- gchar *utf;
-
- utf = gtk_text_latin1_to_utf ((const gchar*)selection_data->data,
- selection_data->length);
- gtk_text_buffer_insert_interactive (text_view->buffer, &drop_point,
- utf, -1,
- text_view->editable);
- g_free (utf);
- }
- break;
-
- case UTF8:
- gtk_text_buffer_insert_interactive (text_view->buffer, &drop_point,
- (const gchar *)selection_data->data,
- selection_data->length,
- text_view->editable);
- break;
-
- case CTEXT:
- {
- gchar **list;
- gint count;
- gint i;
-
- count = gdk_text_property_to_text_list (selection_data->type,
- selection_data->format,
- selection_data->data,
- selection_data->length,
- &list);
- for (i=0; i<count; i++)
- {
- /* list contains stuff in our default encoding */
- gboolean free_utf = FALSE;
- gchar *utf = NULL;
- gchar *charset = NULL;
-
- if (g_get_charset (&charset))
- {
- utf = g_convert (list[i], -1,
- "UTF8", charset, NULL);
- free_utf = TRUE;
- }
- else
- utf = list[i];
-
- gtk_text_buffer_insert_interactive (text_view->buffer,
- &drop_point, utf, -1,
- text_view->editable);
-
- if (free_utf)
- g_free(utf);
- }
-
- if (count > 0)
- gdk_free_text_list (list);
- }
- break;
-
- case INVALID: /* quiet compiler */
- break;
+ gtk_text_buffer_insert_interactive (text_view->buffer,
+ &drop_point, str, -1,
+ text_view->editable);
+ g_free (str);
}
}
@@ -3029,7 +2899,7 @@ gtk_text_view_commit_handler (GtkIMContext *context,
else
{
if (text_view->overwrite_mode)
- gtk_text_view_delete_text (text_view, GTK_TEXT_DELETE_CHAR, 1);
+ gtk_text_view_delete (text_view, GTK_DELETE_CHARS, 1);
gtk_text_buffer_insert_interactive_at_cursor (text_view->buffer, str, -1,
text_view->editable);
}
diff --git a/gtk/gtktextview.h b/gtk/gtktextview.h
index f20c2f0620..1b32c0386d 100644
--- a/gtk/gtktextview.h
+++ b/gtk/gtktextview.h
@@ -9,37 +9,6 @@
extern "C" {
#endif /* __cplusplus */
-typedef enum {
- GTK_TEXT_MOVEMENT_CHAR, /* move by forw/back chars */
- GTK_TEXT_MOVEMENT_POSITIONS, /* move by left/right chars */
- GTK_TEXT_MOVEMENT_WORD, /* move by forward/back words */
- GTK_TEXT_MOVEMENT_WRAPPED_LINE, /* move up/down lines (wrapped lines) */
- GTK_TEXT_MOVEMENT_LINE, /* move up/down paragraphs (newline-ended lines) */
- GTK_TEXT_MOVEMENT_LINE_ENDS, /* move to either end of a paragraph */
- GTK_TEXT_MOVEMENT_BUFFER_ENDS /* move to ends of the buffer */
-} GtkTextViewMovementStep;
-
-typedef enum {
- GTK_TEXT_SCROLL_TO_TOP,
- GTK_TEXT_SCROLL_TO_BOTTOM,
- GTK_TEXT_SCROLL_PAGE_DOWN,
- GTK_TEXT_SCROLL_PAGE_UP
-} GtkTextViewScrollType;
-
-typedef enum {
- GTK_TEXT_DELETE_CHAR,
- GTK_TEXT_DELETE_HALF_WORD, /* delete only the portion of the word to the
- left/right of cursor if we're in the middle
- of a word */
- GTK_TEXT_DELETE_WHOLE_WORD,
- GTK_TEXT_DELETE_HALF_WRAPPED_LINE,
- GTK_TEXT_DELETE_WHOLE_WRAPPED_LINE,
- GTK_TEXT_DELETE_HALF_LINE, /* like C-k in Emacs (or its reverse) */
- GTK_TEXT_DELETE_WHOLE_LINE, /* C-k in pico, kill whole line */
- GTK_TEXT_DELETE_WHITESPACE, /* M-\ in Emacs */
- GTK_TEXT_DELETE_WHITESPACE_LEAVE_ONE /* M-space in Emacs */
-} GtkTextViewDeleteType;
-
#define GTK_TYPE_TEXT_VIEW (gtk_text_view_get_type())
#define GTK_TEXT_VIEW(obj) (GTK_CHECK_CAST ((obj), GTK_TYPE_TEXT_VIEW, GtkTextView))
#define GTK_TEXT_VIEW_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_TEXT_VIEW, GtkTextViewClass))
@@ -107,17 +76,16 @@ struct _GtkTextViewClass {
/* These are all RUN_ACTION signals for keybindings */
/* move insertion point */
- void (* move_insert) (GtkTextView *text_view, GtkTextViewMovementStep step, gint count, gboolean extend_selection);
+ void (* move) (GtkTextView *text_view, GtkMovementStep step, gint count, gboolean extend_selection);
/* move the "anchor" (what Emacs calls the mark) to the cursor position */
void (* set_anchor) (GtkTextView *text_view);
- /* Scroll */
- void (* scroll_text) (GtkTextView *text_view, GtkTextViewScrollType type);
/* Deletions */
- void (* delete_text) (GtkTextView *text_view, GtkTextViewDeleteType type, gint count);
+ void (* insert) (GtkTextView *text_view, const gchar *str);
+ void (* delete) (GtkTextView *text_view, GtkDeleteType type, gint count);
/* cut copy paste */
- void (* cut_text) (GtkTextView *text_view);
- void (* copy_text) (GtkTextView *text_view);
- void (* paste_text) (GtkTextView *text_view);
+ void (* cut_clipboard) (GtkTextView *text_view);
+ void (* copy_clipboard) (GtkTextView *text_view);
+ void (* paste_clipboard) (GtkTextView *text_view);
/* overwrite */
void (* toggle_overwrite) (GtkTextView *text_view);
void (*set_scroll_adjustments) (GtkTextView *text_view,