summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOwen Taylor <owt1@cornell.edu>1998-03-01 05:11:05 +0000
committerOwen Taylor <otaylor@src.gnome.org>1998-03-01 05:11:05 +0000
commit9205edae41b7fdcdda29e8a47739c56f34834f0f (patch)
tree8f2a329df7aaa39bc746eadf55b45c42fe4bf3d2
parentd491547e869c5b918e998e1c68449d2d0e742ada (diff)
downloadgdk-pixbuf-9205edae41b7fdcdda29e8a47739c56f34834f0f.tar.gz
gtk/gtkentry.[ch] gtktext.c gtkeditable.[ch]
Sat Feb 28 23:58:54 1998 Owen Taylor <owt1@cornell.edu> * gtk/gtkentry.[ch] gtktext.c gtkeditable.[ch] Created a new base widget type Editable for the entry and text widgets, which encapsulates most of the selection and clipboard handling stuff, plus some common signals. Changed the Entry widget extensively to support this, but the interface and appearance should be the same. Changed the Text widget moderately to support this. It now supports: - Selection style cut and paste - Clipboard style cut and paste - Emacs style key bindings (~same as Entry) - Word motion - "changed" signal There are definitely still some bugs in the new stuff. * gtkfilesel.c gtkspinbutton.c testgtk.c: small changes to fit the new interface more exactly.
-rw-r--r--ChangeLog22
-rw-r--r--ChangeLog.pre-2-022
-rw-r--r--ChangeLog.pre-2-1022
-rw-r--r--ChangeLog.pre-2-222
-rw-r--r--ChangeLog.pre-2-422
-rw-r--r--ChangeLog.pre-2-622
-rw-r--r--ChangeLog.pre-2-822
-rw-r--r--TODO31
-rw-r--r--gtk/Makefile.am5
-rw-r--r--gtk/gtk.h1
-rw-r--r--gtk/gtkeditable.c664
-rw-r--r--gtk/gtkeditable.h112
-rw-r--r--gtk/gtkentry.c904
-rw-r--r--gtk/gtkentry.h29
-rw-r--r--gtk/gtkfilesel.c4
-rw-r--r--gtk/gtkspinbutton.c24
-rw-r--r--gtk/gtktext.c920
-rw-r--r--gtk/gtktext.h34
18 files changed, 1971 insertions, 911 deletions
diff --git a/ChangeLog b/ChangeLog
index 45c6e743a..a750a31ca 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,25 @@
+Sat Feb 28 23:58:54 1998 Owen Taylor <owt1@cornell.edu>
+
+ * gtk/gtkentry.[ch] gtktext.c gtkeditable.[ch]
+
+ Created a new base widget type Editable for the entry and
+ text widgets, which encapsulates most of the selection and
+ clipboard handling stuff, plus some common signals.
+
+ Changed the Entry widget extensively to support this,
+ but the interface and appearance should be the same.
+
+ Changed the Text widget moderately to support this.
+
+ It now supports:
+
+ - Selection style cut and paste
+ - Clipboard style cut and paste
+ - Emacs style key bindings (~same as Entry)
+ - Word motion
+
+ There are definitely still some bugs in the new stuff.
+
Sat Feb 28 19:29:09 1998 Tim Janik <timj@gimp.org>
* gtk/gtkclist.c (gtk_clist_new_with_titles): retrive the clist widget
diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0
index 45c6e743a..a750a31ca 100644
--- a/ChangeLog.pre-2-0
+++ b/ChangeLog.pre-2-0
@@ -1,3 +1,25 @@
+Sat Feb 28 23:58:54 1998 Owen Taylor <owt1@cornell.edu>
+
+ * gtk/gtkentry.[ch] gtktext.c gtkeditable.[ch]
+
+ Created a new base widget type Editable for the entry and
+ text widgets, which encapsulates most of the selection and
+ clipboard handling stuff, plus some common signals.
+
+ Changed the Entry widget extensively to support this,
+ but the interface and appearance should be the same.
+
+ Changed the Text widget moderately to support this.
+
+ It now supports:
+
+ - Selection style cut and paste
+ - Clipboard style cut and paste
+ - Emacs style key bindings (~same as Entry)
+ - Word motion
+
+ There are definitely still some bugs in the new stuff.
+
Sat Feb 28 19:29:09 1998 Tim Janik <timj@gimp.org>
* gtk/gtkclist.c (gtk_clist_new_with_titles): retrive the clist widget
diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10
index 45c6e743a..a750a31ca 100644
--- a/ChangeLog.pre-2-10
+++ b/ChangeLog.pre-2-10
@@ -1,3 +1,25 @@
+Sat Feb 28 23:58:54 1998 Owen Taylor <owt1@cornell.edu>
+
+ * gtk/gtkentry.[ch] gtktext.c gtkeditable.[ch]
+
+ Created a new base widget type Editable for the entry and
+ text widgets, which encapsulates most of the selection and
+ clipboard handling stuff, plus some common signals.
+
+ Changed the Entry widget extensively to support this,
+ but the interface and appearance should be the same.
+
+ Changed the Text widget moderately to support this.
+
+ It now supports:
+
+ - Selection style cut and paste
+ - Clipboard style cut and paste
+ - Emacs style key bindings (~same as Entry)
+ - Word motion
+
+ There are definitely still some bugs in the new stuff.
+
Sat Feb 28 19:29:09 1998 Tim Janik <timj@gimp.org>
* gtk/gtkclist.c (gtk_clist_new_with_titles): retrive the clist widget
diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2
index 45c6e743a..a750a31ca 100644
--- a/ChangeLog.pre-2-2
+++ b/ChangeLog.pre-2-2
@@ -1,3 +1,25 @@
+Sat Feb 28 23:58:54 1998 Owen Taylor <owt1@cornell.edu>
+
+ * gtk/gtkentry.[ch] gtktext.c gtkeditable.[ch]
+
+ Created a new base widget type Editable for the entry and
+ text widgets, which encapsulates most of the selection and
+ clipboard handling stuff, plus some common signals.
+
+ Changed the Entry widget extensively to support this,
+ but the interface and appearance should be the same.
+
+ Changed the Text widget moderately to support this.
+
+ It now supports:
+
+ - Selection style cut and paste
+ - Clipboard style cut and paste
+ - Emacs style key bindings (~same as Entry)
+ - Word motion
+
+ There are definitely still some bugs in the new stuff.
+
Sat Feb 28 19:29:09 1998 Tim Janik <timj@gimp.org>
* gtk/gtkclist.c (gtk_clist_new_with_titles): retrive the clist widget
diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4
index 45c6e743a..a750a31ca 100644
--- a/ChangeLog.pre-2-4
+++ b/ChangeLog.pre-2-4
@@ -1,3 +1,25 @@
+Sat Feb 28 23:58:54 1998 Owen Taylor <owt1@cornell.edu>
+
+ * gtk/gtkentry.[ch] gtktext.c gtkeditable.[ch]
+
+ Created a new base widget type Editable for the entry and
+ text widgets, which encapsulates most of the selection and
+ clipboard handling stuff, plus some common signals.
+
+ Changed the Entry widget extensively to support this,
+ but the interface and appearance should be the same.
+
+ Changed the Text widget moderately to support this.
+
+ It now supports:
+
+ - Selection style cut and paste
+ - Clipboard style cut and paste
+ - Emacs style key bindings (~same as Entry)
+ - Word motion
+
+ There are definitely still some bugs in the new stuff.
+
Sat Feb 28 19:29:09 1998 Tim Janik <timj@gimp.org>
* gtk/gtkclist.c (gtk_clist_new_with_titles): retrive the clist widget
diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6
index 45c6e743a..a750a31ca 100644
--- a/ChangeLog.pre-2-6
+++ b/ChangeLog.pre-2-6
@@ -1,3 +1,25 @@
+Sat Feb 28 23:58:54 1998 Owen Taylor <owt1@cornell.edu>
+
+ * gtk/gtkentry.[ch] gtktext.c gtkeditable.[ch]
+
+ Created a new base widget type Editable for the entry and
+ text widgets, which encapsulates most of the selection and
+ clipboard handling stuff, plus some common signals.
+
+ Changed the Entry widget extensively to support this,
+ but the interface and appearance should be the same.
+
+ Changed the Text widget moderately to support this.
+
+ It now supports:
+
+ - Selection style cut and paste
+ - Clipboard style cut and paste
+ - Emacs style key bindings (~same as Entry)
+ - Word motion
+
+ There are definitely still some bugs in the new stuff.
+
Sat Feb 28 19:29:09 1998 Tim Janik <timj@gimp.org>
* gtk/gtkclist.c (gtk_clist_new_with_titles): retrive the clist widget
diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8
index 45c6e743a..a750a31ca 100644
--- a/ChangeLog.pre-2-8
+++ b/ChangeLog.pre-2-8
@@ -1,3 +1,25 @@
+Sat Feb 28 23:58:54 1998 Owen Taylor <owt1@cornell.edu>
+
+ * gtk/gtkentry.[ch] gtktext.c gtkeditable.[ch]
+
+ Created a new base widget type Editable for the entry and
+ text widgets, which encapsulates most of the selection and
+ clipboard handling stuff, plus some common signals.
+
+ Changed the Entry widget extensively to support this,
+ but the interface and appearance should be the same.
+
+ Changed the Text widget moderately to support this.
+
+ It now supports:
+
+ - Selection style cut and paste
+ - Clipboard style cut and paste
+ - Emacs style key bindings (~same as Entry)
+ - Word motion
+
+ There are definitely still some bugs in the new stuff.
+
Sat Feb 28 19:29:09 1998 Tim Janik <timj@gimp.org>
* gtk/gtkclist.c (gtk_clist_new_with_titles): retrive the clist widget
diff --git a/TODO b/TODO
index f834e5610..141410c77 100644
--- a/TODO
+++ b/TODO
@@ -57,6 +57,8 @@ Bugs:
segfault in malloc
-timj
+ * Change bitfields to guints from enums for C++ ?
+
Additions:
* it might be good to ues stdio and getch() instead of 1-character reads.
so one can take advantage of buffering. Currently each read() takes a separate
@@ -111,3 +113,32 @@ TODO AFTER GTK 1.0
This will be covered by upcoming themability, raster is working on it.
* More work on Documentation
+
+ * Check return values on all calls to XIC[Get/Set]Values
+
+ * Rewrite the interface to the i18n stuff so GTK widgets don't need to
+ retrieve X values, and so they don't have to know the value of the
+ XNxxx character constants.
+
+ * The "-geometry" option should be supported
+
+ - Having gdk_init() parse the geometry option. (putting it into
+ GDK means you can use XParseGeometry() without wrapping it)
+
+ - Add a call gdk_get_geometry() that retrieves the results
+ in a form like that returned by XParseGeometry()
+
+ - The application then can modify the results (as would gemvt)
+ then call a routine gtk_window_set_geometry() on whatever
+ it considers to be its main window.
+
+ - Then in some manner GtkWindow takes that into account when
+ setting its hints. (Probably it uses the size and position
+ as the current uposition and usize, and modulates that
+ be the equivalents of the X flags
+
+ XValue, YValue, WidthValue, HeightValue, XNegative, or YNegative
+
+ ( You'd have to extend gdk_window_set_hints to accept the
+ window gravity option to get it right. )
+
diff --git a/gtk/Makefile.am b/gtk/Makefile.am
index 6e26be2a7..c311c0240 100644
--- a/gtk/Makefile.am
+++ b/gtk/Makefile.am
@@ -24,6 +24,7 @@ libgtk_la_SOURCES = \
gtkdata.c \
gtkdialog.c \
gtkdrawingarea.c \
+ gtkeditable.c \
gtkentry.c \
gtkeventbox.c \
gtkfilesel.c \
@@ -117,6 +118,7 @@ gtkinclude_HEADERS = \
gtkdebug.h \
gtkdialog.h \
gtkdrawingarea.h \
+ gtkeditable.h \
gtkentry.h \
gtkenums.h \
gtkeventbox.h \
@@ -213,7 +215,8 @@ EXTRA_DIST = \
tree_plus.xpm \
tree_minus.xpm \
tree_plus.xbm \
- tree_minus.xbm
+ tree_minus.xbm \
+ circles.xbm
INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/glib @x_cflags@
diff --git a/gtk/gtk.h b/gtk/gtk.h
index cabecd211..fc7f3bff9 100644
--- a/gtk/gtk.h
+++ b/gtk/gtk.h
@@ -39,6 +39,7 @@
#include <gtk/gtkdata.h>
#include <gtk/gtkdialog.h>
#include <gtk/gtkdrawingarea.h>
+#include <gtk/gtkeditable.h>
#include <gtk/gtkentry.h>
#include <gtk/gtkenums.h>
#include <gtk/gtkeventbox.h>
diff --git a/gtk/gtkeditable.c b/gtk/gtkeditable.c
new file mode 100644
index 000000000..93ec740ad
--- /dev/null
+++ b/gtk/gtkeditable.c
@@ -0,0 +1,664 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <ctype.h>
+#include <string.h>
+#ifdef USE_XIM
+#include "gdk/gdkx.h"
+#endif
+#include "gdk/gdkkeysyms.h"
+#include "gdk/gdki18n.h"
+#include "gtkeditable.h"
+#include "gtkmain.h"
+#include "gtkselection.h"
+#include "gtksignal.h"
+
+#define MIN_EDITABLE_WIDTH 150
+#define DRAW_TIMEOUT 20
+#define INNER_BORDER 2
+
+enum {
+ INSERT_TEXT,
+ DELETE_TEXT,
+ UPDATE_TEXT,
+ GET_CHARS,
+ SET_SELECTION,
+ CHANGED,
+ LAST_SIGNAL
+};
+
+
+typedef void (*GtkEditableSignal1) (GtkObject *object,
+ gpointer arg1,
+ gint arg2,
+ gpointer arg3,
+ gpointer data);
+typedef void (*GtkEditableSignal2) (GtkObject *object,
+ gint arg1,
+ gint arg2,
+ gpointer data);
+
+typedef gpointer (*GtkEditableSignal3) (GtkObject *object,
+ gint arg1,
+ gint arg2,
+ gpointer data);
+
+
+static void gtk_editable_marshal_signal_1 (GtkObject *object,
+ GtkSignalFunc func,
+ gpointer func_data,
+ GtkArg *args);
+static void gtk_editable_marshal_signal_2 (GtkObject *object,
+ GtkSignalFunc func,
+ gpointer func_data,
+ GtkArg *args);
+static void gtk_editable_marshal_signal_3 (GtkObject *object,
+ GtkSignalFunc func,
+ gpointer func_data,
+ GtkArg *args);
+
+static void gtk_editable_class_init (GtkEditableClass *klass);
+static void gtk_editable_init (GtkEditable *editable);
+static void gtk_editable_finalize (GtkObject *object);
+static gint gtk_editable_selection_clear (GtkWidget *widget,
+ GdkEventSelection *event);
+static void gtk_editable_selection_handler (GtkWidget *widget,
+ GtkSelectionData *selection_data,
+ gpointer data);
+static void gtk_editable_selection_received (GtkWidget *widget,
+ GtkSelectionData *selection_data);
+
+static void gtk_editable_set_selection (GtkEditable *editable,
+ gint start,
+ gint end);
+
+static GtkWidgetClass *parent_class = NULL;
+static gint editable_signals[LAST_SIGNAL] = { 0 };
+static GdkAtom ctext_atom = GDK_NONE;
+static GdkAtom text_atom = GDK_NONE;
+static GdkAtom clipboard_atom = GDK_NONE;
+
+guint
+gtk_editable_get_type ()
+{
+ static guint editable_type = 0;
+
+ if (!editable_type)
+ {
+ GtkTypeInfo editable_info =
+ {
+ "GtkEditable",
+ sizeof (GtkEditable),
+ sizeof (GtkEditableClass),
+ (GtkClassInitFunc) gtk_editable_class_init,
+ (GtkObjectInitFunc) gtk_editable_init,
+ (GtkArgSetFunc) NULL,
+ (GtkArgGetFunc) NULL,
+ };
+
+ editable_type = gtk_type_unique (gtk_widget_get_type (), &editable_info);
+ }
+
+ return editable_type;
+}
+
+static void
+gtk_editable_class_init (GtkEditableClass *class)
+{
+ GtkObjectClass *object_class;
+ GtkWidgetClass *widget_class;
+
+ object_class = (GtkObjectClass*) class;
+ widget_class = (GtkWidgetClass*) class;
+
+ parent_class = gtk_type_class (gtk_widget_get_type ());
+
+ editable_signals[INSERT_TEXT] =
+ gtk_signal_new ("insert_text",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkEditableClass, insert_text),
+ gtk_editable_marshal_signal_1,
+ GTK_TYPE_NONE, 3,
+ GTK_TYPE_STRING, GTK_TYPE_INT,
+ GTK_TYPE_POINTER);
+ editable_signals[DELETE_TEXT] =
+ gtk_signal_new ("delete_text",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkEditableClass, delete_text),
+ gtk_editable_marshal_signal_2,
+ GTK_TYPE_NONE, 2,
+ GTK_TYPE_INT, GTK_TYPE_INT);
+ editable_signals[UPDATE_TEXT] =
+ gtk_signal_new ("update_text",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkEditableClass, update_text),
+ gtk_editable_marshal_signal_2,
+ GTK_TYPE_NONE, 2,
+ GTK_TYPE_INT, GTK_TYPE_INT);
+ editable_signals[GET_CHARS] =
+ gtk_signal_new ("get_chars",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkEditableClass, get_chars),
+ gtk_editable_marshal_signal_3,
+ GTK_TYPE_POINTER, 2,
+ GTK_TYPE_INT, GTK_TYPE_INT);
+ editable_signals[SET_SELECTION] =
+ gtk_signal_new ("set_selection",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkEditableClass, set_selection),
+ gtk_editable_marshal_signal_2,
+ GTK_TYPE_NONE, 2,
+ GTK_TYPE_INT, GTK_TYPE_INT);
+ editable_signals[CHANGED] =
+ gtk_signal_new ("changed",
+ GTK_RUN_LAST,
+ object_class->type,
+ GTK_SIGNAL_OFFSET (GtkEditableClass, changed),
+ gtk_signal_default_marshaller,
+ GTK_TYPE_NONE, 0);
+
+ gtk_object_class_add_signals (object_class, editable_signals, LAST_SIGNAL);
+
+ object_class->finalize = gtk_editable_finalize;
+
+ widget_class->selection_clear_event = gtk_editable_selection_clear;
+ widget_class->selection_received = gtk_editable_selection_received;
+
+ class->insert_text = NULL;
+ class->delete_text = NULL;
+ class->update_text = NULL;
+ class->get_chars = NULL;
+ class->set_selection = NULL;
+ class->changed = NULL;
+}
+
+static void
+gtk_editable_init (GtkEditable *editable)
+{
+ GTK_WIDGET_SET_FLAGS (editable, GTK_CAN_FOCUS);
+
+ editable->selection_start_pos = 0;
+ editable->selection_end_pos = 0;
+ editable->has_selection = FALSE;
+ editable->editable = 1;
+ editable->clipboard_text = NULL;
+
+#ifdef USE_XIM
+ editable->ic = NULL;
+#endif
+
+ if (!clipboard_atom)
+ clipboard_atom = gdk_atom_intern ("CLIPBOARD", FALSE);
+
+ gtk_selection_add_handler (GTK_WIDGET(editable), GDK_SELECTION_PRIMARY,
+ GDK_TARGET_STRING, gtk_editable_selection_handler,
+ NULL);
+ gtk_selection_add_handler (GTK_WIDGET(editable), clipboard_atom,
+ GDK_TARGET_STRING, gtk_editable_selection_handler,
+ NULL);
+
+ if (!text_atom)
+ text_atom = gdk_atom_intern ("TEXT", FALSE);
+
+ gtk_selection_add_handler (GTK_WIDGET(editable), GDK_SELECTION_PRIMARY,
+ text_atom,
+ gtk_editable_selection_handler,
+ NULL);
+ gtk_selection_add_handler (GTK_WIDGET(editable), clipboard_atom,
+ text_atom,
+ gtk_editable_selection_handler,
+ NULL);
+
+ if (!ctext_atom)
+ ctext_atom = gdk_atom_intern ("COMPOUND_TEXT", FALSE);
+
+ gtk_selection_add_handler (GTK_WIDGET(editable), GDK_SELECTION_PRIMARY,
+ ctext_atom,
+ gtk_editable_selection_handler,
+ NULL);
+ gtk_selection_add_handler (GTK_WIDGET(editable), clipboard_atom,
+ ctext_atom,
+ gtk_editable_selection_handler,
+ NULL);
+}
+
+static void
+gtk_editable_marshal_signal_1 (GtkObject *object,
+ GtkSignalFunc func,
+ gpointer func_data,
+ GtkArg *args)
+{
+ GtkEditableSignal1 rfunc;
+
+ rfunc = (GtkEditableSignal1) func;
+
+ (* rfunc) (object, GTK_VALUE_STRING (args[0]), GTK_VALUE_INT (args[1]),
+ GTK_VALUE_POINTER (args[2]), func_data);
+}
+
+static void
+gtk_editable_marshal_signal_2 (GtkObject *object,
+ GtkSignalFunc func,
+ gpointer func_data,
+ GtkArg *args)
+{
+ GtkEditableSignal2 rfunc;
+
+ rfunc = (GtkEditableSignal2) func;
+
+ (* rfunc) (object, GTK_VALUE_INT (args[0]), GTK_VALUE_INT (args[1]),
+ func_data);
+}
+
+static void
+gtk_editable_marshal_signal_3 (GtkObject *object,
+ GtkSignalFunc func,
+ gpointer func_data,
+ GtkArg *args)
+{
+ GtkEditableSignal3 rfunc;
+ gpointer *return_val;
+
+ rfunc = (GtkEditableSignal3) func;
+
+ return_val = GTK_RETLOC_POINTER (args[2]);
+
+ *return_val = (* rfunc) (object,
+ GTK_VALUE_INT (args[0]),
+ GTK_VALUE_INT (args[1]),
+ func_data);
+}
+
+static void
+gtk_editable_finalize (GtkObject *object)
+{
+ GtkEditable *editable;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (GTK_IS_EDITABLE (object));
+
+ editable = GTK_EDITABLE (object);
+
+#ifdef USE_XIM
+ if (editable->ic)
+ {
+ gdk_ic_destroy (editable->ic);
+ editable->ic = NULL;
+ }
+#endif
+
+ (* GTK_OBJECT_CLASS (parent_class)->finalize) (object);
+}
+
+void
+gtk_editable_insert_text (GtkEditable *editable,
+ const gchar *new_text,
+ guint new_text_length,
+ guint *position)
+{
+ gchar buf[64];
+ gchar *text;
+
+ g_return_if_fail (editable != NULL);
+ g_return_if_fail (GTK_IS_EDITABLE (editable));
+
+ if (new_text_length <= 64)
+ text = buf;
+ else
+ text = g_new (gchar, new_text_length);
+
+ strncpy (text, new_text, new_text_length);
+
+ gtk_signal_emit (GTK_OBJECT (editable), editable_signals[INSERT_TEXT],
+ text, new_text_length, position);
+ gtk_signal_emit (GTK_OBJECT (editable), editable_signals[CHANGED]);
+
+ if (new_text_length > 64)
+ g_free (text);
+}
+
+void
+gtk_editable_delete_text (GtkEditable *editable,
+ guint start_pos,
+ guint end_pos)
+{
+ g_return_if_fail (editable != NULL);
+ g_return_if_fail (GTK_IS_EDITABLE (editable));
+
+ gtk_signal_emit (GTK_OBJECT (editable), editable_signals[DELETE_TEXT],
+ start_pos, end_pos);
+ gtk_signal_emit (GTK_OBJECT (editable), editable_signals[CHANGED]);
+}
+
+static void
+gtk_editable_update_text (GtkEditable *editable,
+ gint start_pos,
+ gint end_pos)
+{
+ g_return_if_fail (editable != NULL);
+ g_return_if_fail (GTK_IS_EDITABLE (editable));
+
+ gtk_signal_emit (GTK_OBJECT (editable), editable_signals[UPDATE_TEXT],
+ start_pos, end_pos);
+}
+
+gchar *
+gtk_editable_get_chars (GtkEditable *editable,
+ guint start,
+ guint end)
+{
+ gchar *retval = NULL;
+
+ g_return_val_if_fail (editable != NULL, NULL);
+ g_return_val_if_fail (GTK_IS_EDITABLE (editable), NULL);
+
+ gtk_signal_emit (GTK_OBJECT (editable), editable_signals[GET_CHARS],
+ start, end, &retval);
+
+ return retval;
+}
+
+static void
+gtk_editable_set_selection (GtkEditable *editable,
+ gint start_pos,
+ gint end_pos)
+{
+ g_return_if_fail (editable != NULL);
+ g_return_if_fail (GTK_IS_EDITABLE (editable));
+
+ gtk_signal_emit (GTK_OBJECT (editable), editable_signals[SET_SELECTION],
+ start_pos, end_pos);
+}
+
+static gint
+gtk_editable_selection_clear (GtkWidget *widget,
+ GdkEventSelection *event)
+{
+ GtkEditable *editable;
+
+ g_return_val_if_fail (widget != NULL, FALSE);
+ g_return_val_if_fail (GTK_IS_EDITABLE (widget), FALSE);
+ g_return_val_if_fail (event != NULL, FALSE);
+
+ /* Let the selection handling code know that the selection
+ * has been changed, since we've overriden the default handler */
+ gtk_selection_clear (widget, event);
+
+ editable = GTK_EDITABLE (widget);
+
+ if (event->selection == GDK_SELECTION_PRIMARY)
+ {
+ if (editable->has_selection)
+ {
+ editable->has_selection = FALSE;
+ gtk_editable_update_text (editable, editable->selection_start_pos,
+ editable->selection_end_pos);
+ }
+ }
+ else if (event->selection == clipboard_atom)
+ {
+ g_free (editable->clipboard_text);
+ editable->clipboard_text = NULL;
+ }
+
+ return FALSE;
+}
+
+static void
+gtk_editable_selection_handler (GtkWidget *widget,
+ GtkSelectionData *selection_data,
+ gpointer data)
+{
+ GtkEditable *editable;
+ gint selection_start_pos;
+ gint selection_end_pos;
+
+ gchar *str;
+ gint length;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_EDITABLE (widget));
+
+ editable = GTK_EDITABLE (widget);
+
+ if (selection_data->selection == GDK_SELECTION_PRIMARY)
+ {
+ selection_start_pos = MIN (editable->selection_start_pos, editable->selection_end_pos);
+ selection_end_pos = MAX (editable->selection_start_pos, editable->selection_end_pos);
+ str = gtk_editable_get_chars(editable, selection_start_pos,
+ selection_end_pos);
+ length = selection_end_pos - selection_start_pos;
+ }
+ else /* CLIPBOARD */
+ {
+ if (!editable->clipboard_text)
+ return; /* Refuse */
+
+ str = editable->clipboard_text;
+ length = strlen (editable->clipboard_text);
+ }
+
+ if (selection_data->target == GDK_SELECTION_TYPE_STRING)
+ {
+ gtk_selection_data_set (selection_data,
+ GDK_SELECTION_TYPE_STRING,
+ 8*sizeof(gchar), str, length);
+ }
+ else if (selection_data->target == text_atom ||
+ selection_data->target == ctext_atom)
+ {
+ guchar *text;
+ gchar c;
+ GdkAtom encoding;
+ gint format;
+ gint new_length;
+
+ c = str[length];
+ str[length] = '\0';
+ gdk_string_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);
+ str[length] = c;
+ }
+
+ if (str != editable->clipboard_text)
+ g_free (str);
+}
+
+static void
+gtk_editable_selection_received (GtkWidget *widget,
+ GtkSelectionData *selection_data)
+{
+ GtkEditable *editable;
+ gint reselect;
+ gint old_pos;
+ gint tmp_pos;
+ enum {INVALID, STRING, CTEXT} type;
+
+ g_return_if_fail (widget != NULL);
+ g_return_if_fail (GTK_IS_EDITABLE (widget));
+
+ editable = GTK_EDITABLE (widget);
+
+ if (selection_data->type == GDK_TARGET_STRING)
+ type = STRING;
+ else if (selection_data->type == ctext_atom)
+ type = CTEXT;
+ else
+ type = INVALID;
+
+ if (type == INVALID || selection_data->length < 0)
+ {
+ /* avoid infinite loop */
+ if (selection_data->target != GDK_TARGET_STRING)
+ gtk_selection_convert (widget, selection_data->selection,
+ GDK_TARGET_STRING, GDK_CURRENT_TIME);
+ return;
+ }
+
+ reselect = FALSE;
+
+ if ((editable->selection_start_pos != editable->selection_end_pos) &&
+ (!editable->has_selection ||
+ (selection_data->selection == clipboard_atom)))
+ {
+ reselect = TRUE;
+
+ /* Don't want to call gtk_editable_delete_selection here if we are going
+ * to reclaim the selection to avoid extra server traffic */
+ if (editable->has_selection)
+ {
+ gtk_editable_delete_text (editable,
+ MIN (editable->selection_start_pos, editable->selection_end_pos),
+ MAX (editable->selection_start_pos, editable->selection_end_pos));
+ }
+ else
+ gtk_editable_delete_selection (editable);
+ }
+
+ tmp_pos = old_pos = editable->current_pos;
+
+ switch (type)
+ {
+ case STRING:
+ selection_data->data[selection_data->length] = 0;
+ gtk_editable_insert_text (editable, selection_data->data,
+ strlen (selection_data->data), &tmp_pos);
+ editable->current_pos = tmp_pos;
+ 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++)
+ {
+ gtk_editable_insert_text (editable, list[i], strlen (list[i]), &tmp_pos);
+ editable->current_pos = tmp_pos;
+ }
+ if (count > 0)
+ gdk_free_text_list (list);
+ }
+ break;
+ case INVALID: /* quiet compiler */
+ break;
+ }
+
+ if (reselect)
+ gtk_editable_set_selection (editable, old_pos, editable->current_pos);
+}
+
+void
+gtk_editable_delete_selection (GtkEditable *editable)
+{
+ if (editable->selection_start_pos != editable->selection_end_pos)
+ gtk_editable_delete_text (editable,
+ MIN (editable->selection_start_pos, editable->selection_end_pos),
+ MAX (editable->selection_start_pos, editable->selection_end_pos));
+
+ editable->selection_start_pos = 0;
+ editable->selection_end_pos = 0;
+
+ if (editable->has_selection)
+ {
+ editable->has_selection = FALSE;
+ if (gdk_selection_owner_get (GDK_SELECTION_PRIMARY) == GTK_WIDGET (editable)->window)
+ gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY, GDK_CURRENT_TIME);
+ }
+}
+
+void
+gtk_editable_claim_selection (GtkEditable *editable,
+ gboolean claim,
+ guint32 time)
+{
+ g_return_if_fail (GTK_WIDGET_REALIZED (editable));
+
+ if (claim)
+ {
+ if (gtk_selection_owner_set (GTK_WIDGET(editable), GDK_SELECTION_PRIMARY, time))
+ editable->has_selection = TRUE;
+ }
+ else
+ {
+ if (gdk_selection_owner_get (GDK_SELECTION_PRIMARY) ==
+ GTK_WIDGET(editable)->window)
+ gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY, time);
+ }
+}
+
+void
+gtk_editable_select_region (GtkEditable *editable,
+ guint start,
+ guint end)
+{
+ if (GTK_WIDGET_REALIZED (editable))
+ gtk_editable_claim_selection (editable, start != end, GDK_CURRENT_TIME);
+
+ gtk_editable_set_selection (editable, start, end);
+}
+
+void
+gtk_editable_cut_clipboard (GtkEditable *editable, GdkEventKey *event)
+{
+ gtk_editable_copy_clipboard (editable, event);
+ gtk_editable_delete_selection (editable);
+}
+
+void
+gtk_editable_copy_clipboard (GtkEditable *editable, GdkEventKey *event)
+{
+ gint selection_start_pos;
+ gint selection_end_pos;
+
+ selection_start_pos = MIN (editable->selection_start_pos, editable->selection_end_pos);
+ selection_end_pos = MAX (editable->selection_start_pos, editable->selection_end_pos);
+
+ if (selection_start_pos != selection_end_pos)
+ {
+ if (gtk_selection_owner_set (GTK_WIDGET (editable),
+ clipboard_atom,
+ event->time))
+ editable->clipboard_text = gtk_editable_get_chars (editable,
+ editable->selection_start_pos,
+ editable->selection_end_pos);
+ }
+}
+
+void
+gtk_editable_paste_clipboard (GtkEditable *editable, GdkEventKey *event)
+{
+ gtk_selection_convert (GTK_WIDGET(editable),
+ clipboard_atom, ctext_atom, event->time);
+}
+
+void
+gtk_editable_changed (GtkEditable *editable)
+{
+ gtk_signal_emit (GTK_OBJECT (editable), editable_signals[CHANGED]);
+}
diff --git a/gtk/gtkeditable.h b/gtk/gtkeditable.h
new file mode 100644
index 000000000..253206338
--- /dev/null
+++ b/gtk/gtkeditable.h
@@ -0,0 +1,112 @@
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#ifndef __GTK_EDITABLE_H__
+#define __GTK_EDITABLE_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkwidget.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_EDITABLE(obj) GTK_CHECK_CAST (obj, gtk_editable_get_type (), GtkEditable)
+#define GTK_EDITABLE_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, gtk_editable_get_type (), GtkEditableClass)
+#define GTK_IS_EDITABLE(obj) GTK_CHECK_TYPE (obj, gtk_editable_get_type ())
+
+
+typedef struct _GtkEditable GtkEditable;
+typedef struct _GtkEditableClass GtkEditableClass;
+
+typedef void (*GtkTextFunction) (GtkEditable *editable, GdkEventKey *event);
+
+struct _GtkEditable
+{
+ GtkWidget widget;
+
+ guint current_pos;
+
+ guint selection_start_pos;
+ guint selection_end_pos;
+ guint has_selection : 1;
+ guint editable : 1;
+ GdkIC ic;
+
+ gchar *clipboard_text;
+};
+
+struct _GtkEditableClass
+{
+ GtkWidgetClass parent_class;
+
+ void (* insert_text) (GtkEditable *editable,
+ const gchar *text,
+ guint length,
+ guint *position);
+ void (* delete_text) (GtkEditable *editable,
+ guint start_pos,
+ guint end_pos);
+ void (* update_text) (GtkEditable *editable,
+ guint start_pos,
+ guint end_pos);
+ gchar* (* get_chars) (GtkEditable *editable,
+ guint start_pos,
+ guint end_pos);
+ void (* set_selection)(GtkEditable *editable,
+ guint start_pos,
+ guint end_pos);
+ void (* changed) (GtkEditable *editable);
+};
+
+guint gtk_editable_get_type (void);
+void gtk_editable_select_region (GtkEditable *editable,
+ guint start,
+ guint end);
+void gtk_editable_insert_text (GtkEditable *editable,
+ const gchar *new_text,
+ guint new_text_length,
+ guint *position);
+void gtk_editable_delete_text (GtkEditable *editable,
+ guint start_pos,
+ guint end_pos);
+gchar * gtk_editable_get_chars (GtkEditable *editable,
+ guint start,
+ guint end);
+void gtk_editable_cut_clipboard (GtkEditable *editable,
+ GdkEventKey *event);
+void gtk_editable_copy_clipboard (GtkEditable *editable,
+ GdkEventKey *event);
+void gtk_editable_paste_clipboard (GtkEditable *editable,
+ GdkEventKey *event);
+void gtk_editable_claim_selection (GtkEditable *editable,
+ gboolean claim,
+ guint32 time);
+void gtk_editable_delete_selection (GtkEditable *editable);
+
+void gtk_editable_changed (GtkEditable *editable);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_EDITABLE_H__ */
diff --git a/gtk/gtkentry.c b/gtk/gtkentry.c
index a4fdd9731..738410b95 100644
--- a/gtk/gtkentry.c
+++ b/gtk/gtkentry.c
@@ -32,36 +32,10 @@
#define INNER_BORDER 2
enum {
- INSERT_TEXT,
- DELETE_TEXT,
- CHANGED,
- SET_TEXT,
ACTIVATE,
LAST_SIGNAL
};
-
-typedef void (*GtkTextFunction) (GtkEntry *entry, GdkEventKey *event);
-typedef void (*GtkEntrySignal1) (GtkObject *object,
- gpointer arg1,
- gint arg2,
- gpointer arg3,
- gpointer data);
-typedef void (*GtkEntrySignal2) (GtkObject *object,
- gint arg1,
- gint arg2,
- gpointer data);
-
-
-static void gtk_entry_marshal_signal_1 (GtkObject *object,
- GtkSignalFunc func,
- gpointer func_data,
- GtkArg *args);
-static void gtk_entry_marshal_signal_2 (GtkObject *object,
- GtkSignalFunc func,
- gpointer func_data,
- GtkArg *args);
-
static void gtk_entry_class_init (GtkEntryClass *klass);
static void gtk_entry_init (GtkEntry *entry);
static void gtk_entry_finalize (GtkObject *object);
@@ -90,13 +64,6 @@ static gint gtk_entry_focus_in (GtkWidget *widget,
GdkEventFocus *event);
static gint gtk_entry_focus_out (GtkWidget *widget,
GdkEventFocus *event);
-static gint gtk_entry_selection_clear (GtkWidget *widget,
- GdkEventSelection *event);
-static void gtk_entry_selection_handler (GtkWidget *widget,
- GtkSelectionData *selection_data,
- gpointer data);
-static void gtk_entry_selection_received (GtkWidget *widget,
- GtkSelectionData *selection_data);
static void gtk_entry_draw_text (GtkEntry *entry);
static void gtk_entry_draw_cursor (GtkEntry *entry);
static void gtk_entry_draw_cursor_on_drawable
@@ -108,20 +75,19 @@ static gint gtk_entry_position (GtkEntry *entry,
gint x);
void gtk_entry_adjust_scroll (GtkEntry *entry);
static void gtk_entry_grow_text (GtkEntry *entry);
-static void gtk_entry_insert_text (GtkEntry *entry,
+static void gtk_entry_insert_text (GtkEditable *editable,
const gchar *new_text,
- gint new_text_length,
- gint *position);
-static void gtk_entry_delete_text (GtkEntry *entry,
- gint start_pos,
- gint end_pos);
-static void gtk_real_entry_insert_text (GtkEntry *entry,
- const gchar *new_text,
- gint new_text_length,
- gint *position);
-static void gtk_real_entry_delete_text (GtkEntry *entry,
- gint start_pos,
- gint end_pos);
+ guint new_text_length,
+ guint *position);
+static void gtk_entry_delete_text (GtkEditable *editable,
+ guint start_pos,
+ guint end_pos);
+static void gtk_entry_update_text (GtkEditable *editable,
+ guint start_pos,
+ guint end_pos);
+static gchar *gtk_entry_get_chars (GtkEditable *editable,
+ guint start,
+ guint end);
static gint move_backward_character (gchar *str, gint index);
static void gtk_move_forward_character (GtkEntry *entry);
@@ -136,27 +102,23 @@ static void gtk_delete_forward_word (GtkEntry *entry);
static void gtk_delete_backward_word (GtkEntry *entry);
static void gtk_delete_line (GtkEntry *entry);
static void gtk_delete_to_line_end (GtkEntry *entry);
-static void gtk_delete_selection (GtkEntry *entry);
static void gtk_select_word (GtkEntry *entry);
static void gtk_select_line (GtkEntry *entry);
-static void gtk_entry_cut_clipboard (GtkEntry *entry,
- GdkEventKey *event);
-static void gtk_entry_copy_clipboard (GtkEntry *entry,
- GdkEventKey *event);
-static void gtk_entry_paste_clipboard (GtkEntry *entry,
- GdkEventKey *event);
+
+
+static void gtk_entry_set_selection (GtkEditable *editable,
+ guint start,
+ guint end);
static GtkWidgetClass *parent_class = NULL;
static gint entry_signals[LAST_SIGNAL] = { 0 };
static GdkAtom ctext_atom = GDK_NONE;
-static GdkAtom text_atom = GDK_NONE;
-static GdkAtom clipboard_atom = GDK_NONE;
static GtkTextFunction control_keys[26] =
{
(GtkTextFunction)gtk_move_beginning_of_line, /* a */
(GtkTextFunction)gtk_move_backward_character, /* b */
- gtk_entry_copy_clipboard, /* c */
+ gtk_editable_copy_clipboard, /* c */
(GtkTextFunction)gtk_delete_forward_character, /* d */
(GtkTextFunction)gtk_move_end_of_line, /* e */
(GtkTextFunction)gtk_move_forward_character, /* f */
@@ -175,9 +137,9 @@ static GtkTextFunction control_keys[26] =
NULL, /* s */
NULL, /* t */
(GtkTextFunction)gtk_delete_line, /* u */
- gtk_entry_paste_clipboard, /* v */
+ gtk_editable_paste_clipboard, /* v */
(GtkTextFunction)gtk_delete_backward_word, /* w */
- gtk_entry_cut_clipboard, /* x */
+ gtk_editable_cut_clipboard, /* x */
NULL, /* y */
NULL, /* z */
};
@@ -231,7 +193,7 @@ gtk_entry_get_type ()
(GtkArgGetFunc) NULL,
};
- entry_type = gtk_type_unique (gtk_widget_get_type (), &entry_info);
+ entry_type = gtk_type_unique (gtk_editable_get_type (), &entry_info);
}
return entry_type;
@@ -242,43 +204,14 @@ gtk_entry_class_init (GtkEntryClass *class)
{
GtkObjectClass *object_class;
GtkWidgetClass *widget_class;
+ GtkEditableClass *editable_class;
object_class = (GtkObjectClass*) class;
widget_class = (GtkWidgetClass*) class;
+ editable_class = (GtkEditableClass*) class;
parent_class = gtk_type_class (gtk_widget_get_type ());
- entry_signals[INSERT_TEXT] =
- gtk_signal_new ("insert_text",
- GTK_RUN_LAST,
- object_class->type,
- GTK_SIGNAL_OFFSET (GtkEntryClass, insert_text),
- gtk_entry_marshal_signal_1,
- GTK_TYPE_NONE, 3,
- GTK_TYPE_STRING, GTK_TYPE_INT,
- GTK_TYPE_POINTER);
- entry_signals[DELETE_TEXT] =
- gtk_signal_new ("delete_text",
- GTK_RUN_LAST,
- object_class->type,
- GTK_SIGNAL_OFFSET (GtkEntryClass, delete_text),
- gtk_entry_marshal_signal_2,
- GTK_TYPE_NONE, 2,
- GTK_TYPE_INT, GTK_TYPE_INT);
- entry_signals[CHANGED] =
- gtk_signal_new ("changed",
- GTK_RUN_LAST,
- object_class->type,
- GTK_SIGNAL_OFFSET (GtkEntryClass, changed),
- gtk_signal_default_marshaller,
- GTK_TYPE_NONE, 0);
- entry_signals[SET_TEXT] =
- gtk_signal_new ("set_text",
- GTK_RUN_LAST,
- object_class->type,
- GTK_SIGNAL_OFFSET (GtkEntryClass, set_text),
- gtk_signal_default_marshaller,
- GTK_TYPE_NONE, 0);
entry_signals[ACTIVATE] =
gtk_signal_new ("activate",
GTK_RUN_LAST,
@@ -304,14 +237,14 @@ gtk_entry_class_init (GtkEntryClass *class)
widget_class->key_press_event = gtk_entry_key_press;
widget_class->focus_in_event = gtk_entry_focus_in;
widget_class->focus_out_event = gtk_entry_focus_out;
- widget_class->selection_clear_event = gtk_entry_selection_clear;
- widget_class->selection_received = gtk_entry_selection_received;
-
- class->insert_text = gtk_real_entry_insert_text;
- class->delete_text = gtk_real_entry_delete_text;
- class->changed = gtk_entry_adjust_scroll;
- class->set_text = NULL; /* user defined handling */
- class->activate = NULL; /* user defined handling */
+
+ editable_class->insert_text = gtk_entry_insert_text;
+ editable_class->delete_text = gtk_entry_delete_text;
+ editable_class->update_text = gtk_entry_update_text;
+ editable_class->get_chars = gtk_entry_get_chars;
+ editable_class->set_selection = gtk_entry_set_selection;
+ editable_class->changed = (void (*)(GtkEditable *)) gtk_entry_adjust_scroll;
+ class->activate = NULL;
}
static void
@@ -325,53 +258,9 @@ gtk_entry_init (GtkEntry *entry)
entry->text_size = 0;
entry->text_length = 0;
entry->text_max_length = 0;
- entry->current_pos = 0;
- entry->selection_start_pos = 0;
- entry->selection_end_pos = 0;
entry->scroll_offset = 0;
- entry->have_selection = FALSE;
entry->timer = 0;
entry->visible = 1;
- entry->editable = 1;
- entry->clipboard_text = NULL;
-
-#ifdef USE_XIM
- entry->ic = NULL;
-#endif
-
- if (!clipboard_atom)
- clipboard_atom = gdk_atom_intern ("CLIPBOARD", FALSE);
-
- gtk_selection_add_handler (GTK_WIDGET(entry), GDK_SELECTION_PRIMARY,
- GDK_TARGET_STRING, gtk_entry_selection_handler,
- NULL);
- gtk_selection_add_handler (GTK_WIDGET(entry), clipboard_atom,
- GDK_TARGET_STRING, gtk_entry_selection_handler,
- NULL);
-
- if (!text_atom)
- text_atom = gdk_atom_intern ("TEXT", FALSE);
-
- gtk_selection_add_handler (GTK_WIDGET(entry), GDK_SELECTION_PRIMARY,
- text_atom,
- gtk_entry_selection_handler,
- NULL);
- gtk_selection_add_handler (GTK_WIDGET(entry), clipboard_atom,
- text_atom,
- gtk_entry_selection_handler,
- NULL);
-
- if (!ctext_atom)
- ctext_atom = gdk_atom_intern ("COMPOUND_TEXT", FALSE);
-
- gtk_selection_add_handler (GTK_WIDGET(entry), GDK_SELECTION_PRIMARY,
- ctext_atom,
- gtk_entry_selection_handler,
- NULL);
- gtk_selection_add_handler (GTK_WIDGET(entry), clipboard_atom,
- ctext_atom,
- gtk_entry_selection_handler,
- NULL);
gtk_entry_grow_text (entry);
}
@@ -397,23 +286,25 @@ gtk_entry_set_text (GtkEntry *entry,
{
gint tmp_pos;
+ GtkEditable *editable;
+
g_return_if_fail (entry != NULL);
g_return_if_fail (GTK_IS_ENTRY (entry));
g_return_if_fail (text != NULL);
- gtk_real_entry_delete_text (entry, 0, entry->text_length);
+ editable = GTK_EDITABLE (entry);
+
+ gtk_entry_delete_text (GTK_EDITABLE(entry), 0, entry->text_length);
tmp_pos = 0;
- gtk_entry_insert_text (entry, text, strlen (text), &tmp_pos);
- entry->current_pos = tmp_pos;
+ gtk_editable_insert_text (editable, text, strlen (text), &tmp_pos);
+ editable->current_pos = tmp_pos;
- entry->selection_start_pos = 0;
- entry->selection_end_pos = 0;
+ editable->selection_start_pos = 0;
+ editable->selection_end_pos = 0;
if (GTK_WIDGET_DRAWABLE (entry))
gtk_entry_draw_text (entry);
-
- gtk_signal_emit (GTK_OBJECT (entry), entry_signals[SET_TEXT]);
}
void
@@ -426,10 +317,8 @@ gtk_entry_append_text (GtkEntry *entry,
g_return_if_fail (GTK_IS_ENTRY (entry));
tmp_pos = entry->text_length;
- gtk_entry_insert_text (entry, text, strlen (text), &tmp_pos);
- entry->current_pos = tmp_pos;
-
- gtk_signal_emit (GTK_OBJECT (entry), entry_signals[SET_TEXT]);
+ gtk_editable_insert_text (GTK_EDITABLE(entry), text, strlen (text), &tmp_pos);
+ GTK_EDITABLE(entry)->current_pos = tmp_pos;
}
void
@@ -442,10 +331,8 @@ gtk_entry_prepend_text (GtkEntry *entry,
g_return_if_fail (GTK_IS_ENTRY (entry));
tmp_pos = 0;
- gtk_entry_insert_text (entry, text, strlen (text), &tmp_pos);
- entry->current_pos = tmp_pos;
-
- gtk_signal_emit (GTK_OBJECT (entry), entry_signals[SET_TEXT]);
+ gtk_editable_insert_text (GTK_EDITABLE(entry), text, strlen (text), &tmp_pos);
+ GTK_EDITABLE(entry)->current_pos = tmp_pos;
}
void
@@ -456,9 +343,9 @@ gtk_entry_set_position (GtkEntry *entry,
g_return_if_fail (GTK_IS_ENTRY (entry));
if ((position == -1) || (position > entry->text_length))
- entry->current_pos = entry->text_length;
+ GTK_EDITABLE(entry)->current_pos = entry->text_length;
else
- entry->current_pos = position;
+ GTK_EDITABLE(entry)->current_pos = position;
}
void
@@ -477,7 +364,7 @@ gtk_entry_set_editable(GtkEntry *entry,
{
g_return_if_fail (entry != NULL);
g_return_if_fail (GTK_IS_ENTRY (entry));
- entry->editable = editable;
+ GTK_EDITABLE(entry)->editable = editable;
gtk_entry_queue_draw(entry);
}
@@ -494,35 +381,6 @@ gtk_entry_get_text (GtkEntry *entry)
return entry->text;
}
-
-static void
-gtk_entry_marshal_signal_1 (GtkObject *object,
- GtkSignalFunc func,
- gpointer func_data,
- GtkArg *args)
-{
- GtkEntrySignal1 rfunc;
-
- rfunc = (GtkEntrySignal1) func;
-
- (* rfunc) (object, GTK_VALUE_STRING (args[0]), GTK_VALUE_INT (args[1]),
- GTK_VALUE_POINTER (args[2]), func_data);
-}
-
-static void
-gtk_entry_marshal_signal_2 (GtkObject *object,
- GtkSignalFunc func,
- gpointer func_data,
- GtkArg *args)
-{
- GtkEntrySignal2 rfunc;
-
- rfunc = (GtkEntrySignal2) func;
-
- (* rfunc) (object, GTK_VALUE_INT (args[0]), GTK_VALUE_INT (args[1]),
- func_data);
-}
-
static void
gtk_entry_finalize (GtkObject *object)
{
@@ -534,10 +392,10 @@ gtk_entry_finalize (GtkObject *object)
entry = GTK_ENTRY (object);
#ifdef USE_XIM
- if (entry->ic)
+ if (GTK_EDITABLE(entry)->ic)
{
- gdk_ic_destroy (entry->ic);
- entry->ic = NULL;
+ gdk_ic_destroy (GTK_EDITABLE(entry)->ic);
+ GTK_EDITABLE(entry)->ic = NULL;
}
#endif
@@ -559,6 +417,7 @@ static void
gtk_entry_realize (GtkWidget *widget)
{
GtkEntry *entry;
+ GtkEditable *editable;
GdkWindowAttr attributes;
gint attributes_mask;
@@ -567,6 +426,7 @@ gtk_entry_realize (GtkWidget *widget)
GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
entry = GTK_ENTRY (widget);
+ editable = GTK_EDITABLE (widget);
attributes.window_type = GDK_WINDOW_CHILD;
attributes.x = widget->allocation.x;
@@ -637,7 +497,7 @@ gtk_entry_realize (GtkWidget *widget)
rect.height = height;
spot.x = 0;
spot.y = height;
- entry->ic = gdk_ic_new (entry->text_area, entry->text_area,
+ editable->ic = gdk_ic_new (entry->text_area, entry->text_area,
style,
"spotLocation", &spot,
"area", &rect,
@@ -645,28 +505,28 @@ gtk_entry_realize (GtkWidget *widget)
NULL);
break;
default:
- entry->ic = gdk_ic_new (entry->text_area, entry->text_area,
+ editable->ic = gdk_ic_new (entry->text_area, entry->text_area,
style, NULL);
}
- if (entry->ic == NULL)
+ if (editable->ic == NULL)
g_warning ("Can't create input context.");
else
{
GdkColormap *colormap;
mask = gdk_window_get_events (entry->text_area);
- mask |= gdk_ic_get_events (entry->ic);
+ mask |= gdk_ic_get_events (editable->ic);
gdk_window_set_events (entry->text_area, mask);
if ((colormap = gtk_widget_get_colormap (widget)) !=
gtk_widget_get_default_colormap ())
{
- gdk_ic_set_attr (entry->ic, "preeditAttributes",
+ gdk_ic_set_attr (editable->ic, "preeditAttributes",
"colorMap", GDK_COLORMAP_XCOLORMAP (colormap),
NULL);
}
- gdk_ic_set_attr (entry->ic,"preeditAttributes",
+ gdk_ic_set_attr (editable->ic,"preeditAttributes",
"foreground", widget->style->fg[GTK_STATE_NORMAL].pixel,
"background", widget->style->base[GTK_STATE_NORMAL].pixel,
NULL);
@@ -675,6 +535,9 @@ gtk_entry_realize (GtkWidget *widget)
#endif
gdk_window_show (entry->text_area);
+
+ if (editable->selection_start_pos != editable->selection_end_pos)
+ gtk_editable_claim_selection (editable, TRUE, GDK_CURRENT_TIME);
}
static void
@@ -763,6 +626,7 @@ gtk_entry_size_allocate (GtkWidget *widget,
GtkAllocation *allocation)
{
GtkEntry *entry;
+ GtkEditable *editable;
g_return_if_fail (widget != NULL);
g_return_if_fail (GTK_IS_ENTRY (widget));
@@ -770,6 +634,7 @@ gtk_entry_size_allocate (GtkWidget *widget,
widget->allocation = *allocation;
entry = GTK_ENTRY (widget);
+ editable = GTK_EDITABLE (widget);
if (GTK_WIDGET_REALIZED (widget))
{
@@ -786,7 +651,7 @@ gtk_entry_size_allocate (GtkWidget *widget,
entry->scroll_offset = 0;
gtk_entry_adjust_scroll (entry);
#ifdef USE_XIM
- if (entry->ic && (gdk_ic_get_style (entry->ic) & GdkIMPreeditPosition))
+ if (editable->ic && (gdk_ic_get_style (editable->ic) & GdkIMPreeditPosition))
{
gint width, height;
GdkRectangle rect;
@@ -796,7 +661,7 @@ gtk_entry_size_allocate (GtkWidget *widget,
rect.y = 0;
rect.width = width;
rect.height = height;
- gdk_ic_set_attr (entry->ic, "preeditAttributes", "area", &rect, NULL);
+ gdk_ic_set_attr (editable->ic, "preeditAttributes", "area", &rect, NULL);
}
#endif
}
@@ -842,6 +707,7 @@ gtk_entry_button_press (GtkWidget *widget,
GdkEventButton *event)
{
GtkEntry *entry;
+ GtkEditable *editable;
gint tmp_pos;
g_return_val_if_fail (widget != NULL, FALSE);
@@ -852,6 +718,8 @@ gtk_entry_button_press (GtkWidget *widget,
ctext_atom = gdk_atom_intern ("COMPOUND_TEXT", FALSE);
entry = GTK_ENTRY (widget);
+ editable = GTK_EDITABLE (widget);
+
if (!GTK_WIDGET_HAS_FOCUS (widget))
gtk_widget_grab_focus (widget);
@@ -863,8 +731,8 @@ gtk_entry_button_press (GtkWidget *widget,
gtk_grab_add (widget);
tmp_pos = gtk_entry_position (entry, event->x + entry->scroll_offset);
- gtk_entry_select_region (entry, tmp_pos, tmp_pos);
- entry->current_pos = entry->selection_start_pos;
+ gtk_entry_set_selection (editable, tmp_pos, tmp_pos);
+ editable->current_pos = editable->selection_start_pos;
break;
case GDK_2BUTTON_PRESS:
@@ -883,9 +751,9 @@ gtk_entry_button_press (GtkWidget *widget,
{
if (event->button == 2)
{
- if (entry->selection_start_pos == entry->selection_end_pos ||
- entry->have_selection)
- entry->current_pos = gtk_entry_position (entry, event->x + entry->scroll_offset);
+ if (editable->selection_start_pos == editable->selection_end_pos ||
+ editable->has_selection)
+ editable->current_pos = gtk_entry_position (entry, event->x + entry->scroll_offset);
gtk_selection_convert (widget, GDK_SELECTION_PRIMARY,
ctext_atom, event->time);
}
@@ -894,9 +762,9 @@ gtk_entry_button_press (GtkWidget *widget,
gtk_grab_add (widget);
tmp_pos = gtk_entry_position (entry, event->x + entry->scroll_offset);
- gtk_entry_select_region (entry, tmp_pos, tmp_pos);
- entry->have_selection = FALSE;
- entry->current_pos = entry->selection_start_pos;
+ gtk_entry_set_selection (editable, tmp_pos, tmp_pos);
+ editable->has_selection = FALSE;
+ editable->current_pos = editable->selection_start_pos;
}
}
@@ -908,6 +776,7 @@ gtk_entry_button_release (GtkWidget *widget,
GdkEventButton *event)
{
GtkEntry *entry;
+ GtkEditable *editable;
g_return_val_if_fail (widget != NULL, FALSE);
g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE);
@@ -916,16 +785,18 @@ gtk_entry_button_release (GtkWidget *widget,
if (event->button == 1)
{
entry = GTK_ENTRY (widget);
+ editable = GTK_EDITABLE (widget);
+
gtk_grab_remove (widget);
- entry->have_selection = FALSE;
- if (entry->selection_start_pos != entry->selection_end_pos)
+ editable->has_selection = FALSE;
+ if (editable->selection_start_pos != editable->selection_end_pos)
{
if (gtk_selection_owner_set (widget,
GDK_SELECTION_PRIMARY,
event->time))
{
- entry->have_selection = TRUE;
+ editable->has_selection = TRUE;
gtk_entry_queue_draw (entry);
}
}
@@ -962,8 +833,8 @@ gtk_entry_motion_notify (GtkWidget *widget,
if (event->is_hint || (entry->text_area != event->window))
gdk_window_get_pointer (entry->text_area, &x, NULL, NULL);
- entry->selection_end_pos = gtk_entry_position (entry, event->x + entry->scroll_offset);
- entry->current_pos = entry->selection_end_pos;
+ GTK_EDITABLE(entry)->selection_end_pos = gtk_entry_position (entry, event->x + entry->scroll_offset);
+ GTK_EDITABLE(entry)->current_pos = GTK_EDITABLE(entry)->selection_end_pos;
gtk_entry_adjust_scroll (entry);
gtk_entry_queue_draw (entry);
@@ -975,6 +846,8 @@ gtk_entry_key_press (GtkWidget *widget,
GdkEventKey *event)
{
GtkEntry *entry;
+ GtkEditable *editable;
+
gint return_val;
gint key;
gint tmp_pos;
@@ -986,9 +859,10 @@ gtk_entry_key_press (GtkWidget *widget,
g_return_val_if_fail (event != NULL, FALSE);
entry = GTK_ENTRY (widget);
+ editable = GTK_EDITABLE (widget);
return_val = FALSE;
- if(entry->editable == FALSE)
+ if(editable->editable == FALSE)
return FALSE;
extend_selection = event->state & GDK_SHIFT_MASK;
@@ -996,21 +870,21 @@ gtk_entry_key_press (GtkWidget *widget,
if (extend_selection)
{
- if (entry->selection_start_pos == entry->selection_end_pos)
+ if (editable->selection_start_pos == editable->selection_end_pos)
{
- entry->selection_start_pos = entry->current_pos;
- entry->selection_end_pos = entry->current_pos;
+ editable->selection_start_pos = editable->current_pos;
+ editable->selection_end_pos = editable->current_pos;
}
- extend_start = (entry->current_pos == entry->selection_start_pos);
+ extend_start = (editable->current_pos == editable->selection_start_pos);
}
switch (event->keyval)
{
case GDK_BackSpace:
return_val = TRUE;
- if (entry->selection_start_pos != entry->selection_end_pos)
- gtk_delete_selection (entry);
+ if (editable->selection_start_pos != editable->selection_end_pos)
+ gtk_editable_delete_selection (editable);
else if (event->state & GDK_CONTROL_MASK)
gtk_delete_backward_word (entry);
else
@@ -1025,11 +899,11 @@ gtk_entry_key_press (GtkWidget *widget,
if (event->state & GDK_SHIFT_MASK)
{
extend_selection = FALSE;
- gtk_entry_paste_clipboard (entry, event);
+ gtk_editable_paste_clipboard (editable, event);
}
else if (event->state & GDK_CONTROL_MASK)
{
- gtk_entry_copy_clipboard (entry, event);
+ gtk_editable_copy_clipboard (editable, event);
}
else
{
@@ -1041,7 +915,7 @@ gtk_entry_key_press (GtkWidget *widget,
if (event->state & GDK_CONTROL_MASK)
gtk_delete_line (entry);
else if (event->state & GDK_SHIFT_MASK)
- gtk_entry_cut_clipboard (entry, event);
+ gtk_editable_cut_clipboard (editable, event);
else
gtk_delete_forward_character (entry);
break;
@@ -1081,7 +955,7 @@ gtk_entry_key_press (GtkWidget *widget,
if ((key >= 'a') && (key <= 'z') && control_keys[key - 'a'])
{
- (* control_keys[key - 'a']) (entry, event);
+ (* control_keys[key - 'a']) (editable, event);
return_val = TRUE;
}
break;
@@ -1093,7 +967,7 @@ gtk_entry_key_press (GtkWidget *widget,
if ((key >= 'a') && (key <= 'z') && alt_keys[key - 'a'])
{
- (* alt_keys[key - 'a']) (entry, event);
+ (* alt_keys[key - 'a']) (editable, event);
return_val = TRUE;
}
break;
@@ -1102,11 +976,11 @@ gtk_entry_key_press (GtkWidget *widget,
if (event->length > 0)
{
extend_selection = FALSE;
- gtk_delete_selection (entry);
+ gtk_editable_delete_selection (editable);
- tmp_pos = entry->current_pos;
- gtk_entry_insert_text (entry, event->string, event->length, &tmp_pos);
- entry->current_pos = tmp_pos;
+ tmp_pos = editable->current_pos;
+ gtk_editable_insert_text (editable, event->string, event->length, &tmp_pos);
+ editable->current_pos = tmp_pos;
return_val = TRUE;
}
@@ -1117,39 +991,27 @@ gtk_entry_key_press (GtkWidget *widget,
{
if (extend_selection)
{
- if (entry->current_pos < entry->selection_start_pos)
- entry->selection_start_pos = entry->current_pos;
- else if (entry->current_pos > entry->selection_end_pos)
- entry->selection_end_pos = entry->current_pos;
+ if (editable->current_pos < editable->selection_start_pos)
+ editable->selection_start_pos = editable->current_pos;
+ else if (editable->current_pos > editable->selection_end_pos)
+ editable->selection_end_pos = editable->current_pos;
else
{
if (extend_start)
- entry->selection_start_pos = entry->current_pos;
+ editable->selection_start_pos = editable->current_pos;
else
- entry->selection_end_pos = entry->current_pos;
+ editable->selection_end_pos = editable->current_pos;
}
}
else
{
- entry->selection_start_pos = 0;
- entry->selection_end_pos = 0;
+ editable->selection_start_pos = 0;
+ editable->selection_end_pos = 0;
}
- /* alex stuff */
- if (entry->selection_start_pos != entry->selection_end_pos)
- {
- if (gtk_selection_owner_set (widget, GDK_SELECTION_PRIMARY, event->time))
- {
- entry->have_selection = TRUE;
- gtk_entry_queue_draw (entry);
- }
- }
- else
- {
- if (gdk_selection_owner_get (GDK_SELECTION_PRIMARY) == widget->window)
- gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY, event->time);
- }
- /* end of alex stuff */
+ gtk_editable_claim_selection (editable,
+ editable->selection_start_pos != editable->selection_end_pos,
+ event->time);
gtk_entry_adjust_scroll (entry);
gtk_entry_queue_draw (entry);
@@ -1170,8 +1032,8 @@ gtk_entry_focus_in (GtkWidget *widget,
gtk_widget_draw_focus (widget);
#ifdef USE_XIM
- if (GTK_ENTRY(widget)->ic)
- gdk_im_begin (GTK_ENTRY(widget)->ic, GTK_ENTRY(widget)->text_area);
+ if (GTK_EDITABLE(widget)->ic)
+ gdk_im_begin (GTK_EDITABLE(widget)->ic, GTK_ENTRY(widget)->text_area);
#endif
return FALSE;
@@ -1195,187 +1057,6 @@ gtk_entry_focus_out (GtkWidget *widget,
return FALSE;
}
-static gint
-gtk_entry_selection_clear (GtkWidget *widget,
- GdkEventSelection *event)
-{
- GtkEntry *entry;
-
- g_return_val_if_fail (widget != NULL, FALSE);
- g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE);
- g_return_val_if_fail (event != NULL, FALSE);
-
- /* Let the selection handling code know that the selection
- * has been changed, since we've overriden the default handler */
- gtk_selection_clear (widget, event);
-
- entry = GTK_ENTRY (widget);
-
- if (event->selection == GDK_SELECTION_PRIMARY)
- {
- if (entry->have_selection)
- {
- entry->have_selection = FALSE;
- gtk_entry_queue_draw (entry);
- }
- }
- else if (event->selection == clipboard_atom)
- {
- g_free (entry->clipboard_text);
- entry->clipboard_text = NULL;
- }
-
- return FALSE;
-}
-
-static void
-gtk_entry_selection_handler (GtkWidget *widget,
- GtkSelectionData *selection_data,
- gpointer data)
-{
- GtkEntry *entry;
- gint selection_start_pos;
- gint selection_end_pos;
-
- guchar *str;
- gint length;
-
- g_return_if_fail (widget != NULL);
- g_return_if_fail (GTK_IS_ENTRY (widget));
-
- entry = GTK_ENTRY (widget);
-
- if (selection_data->selection == GDK_SELECTION_PRIMARY)
- {
- selection_start_pos = MIN (entry->selection_start_pos, entry->selection_end_pos);
- selection_end_pos = MAX (entry->selection_start_pos, entry->selection_end_pos);
- str = &entry->text[selection_start_pos];
- length = selection_end_pos - selection_start_pos;
- }
- else /* CLIPBOARD */
- {
- if (!entry->clipboard_text)
- return; /* Refuse */
-
- str = entry->clipboard_text;
- length = strlen (entry->clipboard_text);
- }
-
- if (selection_data->target == GDK_SELECTION_TYPE_STRING)
- {
- gtk_selection_data_set (selection_data,
- GDK_SELECTION_TYPE_STRING,
- 8*sizeof(gchar), str, length);
- }
- else if (selection_data->target == text_atom ||
- selection_data->target == ctext_atom)
- {
- guchar *text;
- gchar c;
- GdkAtom encoding;
- gint format;
- gint new_length;
-
- c = str[length];
- str[length] = '\0';
- gdk_string_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);
- str[length] = c;
- }
-}
-
-static void
-gtk_entry_selection_received (GtkWidget *widget,
- GtkSelectionData *selection_data)
-{
- GtkEntry *entry;
- gint reselect;
- gint old_pos;
- gint tmp_pos;
- enum {INVALID, STRING, CTEXT} type;
-
- g_return_if_fail (widget != NULL);
- g_return_if_fail (GTK_IS_ENTRY (widget));
-
- entry = GTK_ENTRY (widget);
-
- if (selection_data->type == GDK_TARGET_STRING)
- type = STRING;
- else if (selection_data->type == ctext_atom)
- type = CTEXT;
- else
- type = INVALID;
-
- if (type == INVALID || selection_data->length < 0)
- {
- /* avoid infinite loop */
- if (selection_data->target != GDK_TARGET_STRING)
- gtk_selection_convert (widget, selection_data->selection,
- GDK_TARGET_STRING, GDK_CURRENT_TIME);
- return;
- }
-
- reselect = FALSE;
-
- if ((entry->selection_start_pos != entry->selection_end_pos) &&
- (!entry->have_selection ||
- (selection_data->selection == clipboard_atom)))
- {
- reselect = TRUE;
-
- /* Don't want to call gtk_delete_selection here if we are going
- * to reclaim the selection to avoid extra server traffic */
- if (entry->have_selection)
- {
- gtk_entry_delete_text (entry,
- MIN (entry->selection_start_pos, entry->selection_end_pos),
- MAX (entry->selection_start_pos, entry->selection_end_pos));
- }
- else
- gtk_delete_selection (entry);
- }
-
- tmp_pos = old_pos = entry->current_pos;
-
- switch (type)
- {
- case STRING:
- selection_data->data[selection_data->length] = 0;
- gtk_entry_insert_text (entry, selection_data->data,
- strlen (selection_data->data), &tmp_pos);
- entry->current_pos = tmp_pos;
- 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++)
- {
- gtk_entry_insert_text (entry, list[i], strlen (list[i]), &tmp_pos);
- entry->current_pos = tmp_pos;
- }
- if (count > 0)
- gdk_free_text_list (list);
- }
- break;
- case INVALID: /* quiet compiler */
- break;
- }
-
- if (reselect)
- gtk_entry_select_region (entry, old_pos, entry->current_pos);
-
- gtk_entry_queue_draw (entry);
-}
-
static void
gtk_entry_make_backing_pixmap (GtkEntry *entry, gint width, gint height)
{
@@ -1407,6 +1088,7 @@ static void
gtk_entry_draw_text (GtkEntry *entry)
{
GtkWidget *widget;
+ GtkEditable *editable;
GtkStateType selected_state;
gint selection_start_pos;
gint selection_end_pos;
@@ -1435,11 +1117,12 @@ gtk_entry_draw_text (GtkEntry *entry)
if (GTK_WIDGET_DRAWABLE (entry))
{
widget = GTK_WIDGET (entry);
+ editable = GTK_EDITABLE (entry);
if (!entry->text)
{
gdk_window_clear (entry->text_area);
- if (entry->editable)
+ if (editable->editable)
gtk_entry_draw_cursor (entry);
return;
}
@@ -1472,14 +1155,14 @@ gtk_entry_draw_text (GtkEntry *entry)
y = (height - (widget->style->font->ascent + widget->style->font->descent)) / 2;
y += widget->style->font->ascent;
- if (entry->selection_start_pos != entry->selection_end_pos)
+ if (editable->selection_start_pos != editable->selection_end_pos)
{
selected_state = GTK_STATE_SELECTED;
- if (!entry->have_selection)
+ if (!editable->has_selection)
selected_state = GTK_STATE_ACTIVE;
- selection_start_pos = MIN (entry->selection_start_pos, entry->selection_end_pos);
- selection_end_pos = MAX (entry->selection_start_pos, entry->selection_end_pos);
+ selection_start_pos = MIN (editable->selection_start_pos, editable->selection_end_pos);
+ selection_end_pos = MAX (editable->selection_start_pos, editable->selection_end_pos);
selection_start_xoffset = gdk_text_width (widget->style->font,
entry->text,
@@ -1525,7 +1208,7 @@ gtk_entry_draw_text (GtkEntry *entry)
entry->text);
}
- if (entry->editable)
+ if (editable->editable)
gtk_entry_draw_cursor_on_drawable (entry, drawable);
if (use_backing_pixmap)
@@ -1549,6 +1232,7 @@ static void
gtk_entry_draw_cursor_on_drawable (GtkEntry *entry, GdkDrawable *drawable)
{
GtkWidget *widget;
+ GtkEditable *editable;
GdkGC *gc;
gint xoffset;
gint text_area_height;
@@ -1559,15 +1243,16 @@ gtk_entry_draw_cursor_on_drawable (GtkEntry *entry, GdkDrawable *drawable)
if (GTK_WIDGET_DRAWABLE (entry))
{
widget = GTK_WIDGET (entry);
+ editable = GTK_EDITABLE (entry);
- if (entry->current_pos > 0 && entry->visible)
- xoffset = gdk_text_width (widget->style->font, entry->text, entry->current_pos);
+ if (editable->current_pos > 0 && entry->visible)
+ xoffset = gdk_text_width (widget->style->font, entry->text, editable->current_pos);
else
xoffset = 0;
xoffset -= entry->scroll_offset;
if (GTK_WIDGET_HAS_FOCUS (widget) &&
- (entry->selection_start_pos == entry->selection_end_pos))
+ (editable->selection_start_pos == editable->selection_end_pos))
gc = widget->style->fg_gc[GTK_STATE_NORMAL];
else
gc = widget->style->base_gc[GTK_WIDGET_STATE(widget)];
@@ -1575,14 +1260,14 @@ gtk_entry_draw_cursor_on_drawable (GtkEntry *entry, GdkDrawable *drawable)
gdk_window_get_size (entry->text_area, NULL, &text_area_height);
gdk_draw_line (drawable, gc, xoffset, 0, xoffset, text_area_height);
#ifdef USE_XIM
- if (gdk_im_ready() && entry->ic &&
- gdk_ic_get_style (entry->ic) & GdkIMPreeditPosition)
+ if (gdk_im_ready() && editable->ic &&
+ gdk_ic_get_style (editable->ic) & GdkIMPreeditPosition)
{
GdkPoint spot;
spot.x = xoffset;
spot.y = (text_area_height + (widget->style->font->ascent - widget->style->font->descent) + 1) / 2;
- gdk_ic_set_attr (entry->ic, "preeditAttributes", "spotLocation", &spot, NULL);
+ gdk_ic_set_attr (editable->ic, "preeditAttributes", "spotLocation", &spot, NULL);
}
#endif
}
@@ -1664,8 +1349,8 @@ gtk_entry_adjust_scroll (GtkEntry *entry)
gdk_window_get_size (entry->text_area, &text_area_width, NULL);
- if (entry->current_pos > 0)
- xoffset = gdk_text_width (GTK_WIDGET (entry)->style->font, entry->text, entry->current_pos);
+ if (GTK_EDITABLE(entry)->current_pos > 0)
+ xoffset = gdk_text_width (GTK_WIDGET (entry)->style->font, entry->text, GTK_EDITABLE(entry)->current_pos);
else
xoffset = 0;
xoffset -= entry->scroll_offset;
@@ -1697,50 +1382,10 @@ gtk_entry_grow_text (GtkEntry *entry)
}
static void
-gtk_entry_insert_text (GtkEntry *entry,
- const gchar *new_text,
- gint new_text_length,
- gint *position)
-{
- gchar buf[64];
- gchar *text;
-
- g_return_if_fail (entry != NULL);
- g_return_if_fail (GTK_IS_ENTRY (entry));
-
- if (new_text_length <= 64)
- text = buf;
- else
- text = g_new (gchar, new_text_length);
-
- strncpy (text, new_text, new_text_length);
-
- gtk_signal_emit (GTK_OBJECT (entry), entry_signals[INSERT_TEXT],
- text, new_text_length, position);
- gtk_signal_emit (GTK_OBJECT (entry), entry_signals[CHANGED]);
-
- if (new_text_length > 64)
- g_free (text);
-}
-
-static void
-gtk_entry_delete_text (GtkEntry *entry,
- gint start_pos,
- gint end_pos)
-{
- g_return_if_fail (entry != NULL);
- g_return_if_fail (GTK_IS_ENTRY (entry));
-
- gtk_signal_emit (GTK_OBJECT (entry), entry_signals[DELETE_TEXT],
- start_pos, end_pos);
- gtk_signal_emit (GTK_OBJECT (entry), entry_signals[CHANGED]);
-}
-
-static void
-gtk_real_entry_insert_text (GtkEntry *entry,
+gtk_entry_insert_text (GtkEditable *editable,
const gchar *new_text,
- gint new_text_length,
- gint *position)
+ guint new_text_length,
+ guint *position)
{
gchar *text;
gint start_pos;
@@ -1748,8 +1393,12 @@ gtk_real_entry_insert_text (GtkEntry *entry,
gint last_pos;
gint i;
+ GtkEntry *entry;
+
g_return_if_fail (entry != NULL);
- g_return_if_fail (GTK_IS_ENTRY (entry));
+ g_return_if_fail (GTK_IS_ENTRY (editable));
+
+ entry = GTK_ENTRY (editable);
/* Make sure we do not exceed the maximum size of the entry. */
if (entry->text_max_length != 0 &&
@@ -1764,10 +1413,10 @@ gtk_real_entry_insert_text (GtkEntry *entry,
end_pos = start_pos + new_text_length;
last_pos = new_text_length + entry->text_length;
- if (entry->selection_start_pos >= *position)
- entry->selection_start_pos += new_text_length;
- if (entry->selection_end_pos >= *position)
- entry->selection_end_pos += new_text_length;
+ if (editable->selection_start_pos >= *position)
+ editable->selection_start_pos += new_text_length;
+ if (editable->selection_end_pos >= *position)
+ editable->selection_end_pos += new_text_length;
while (last_pos >= entry->text_size)
gtk_entry_grow_text (entry);
@@ -1780,24 +1429,30 @@ gtk_real_entry_insert_text (GtkEntry *entry,
entry->text_length += new_text_length;
*position = end_pos;
+
+ gtk_entry_queue_draw (entry);
}
static void
-gtk_real_entry_delete_text (GtkEntry *entry,
- gint start_pos,
- gint end_pos)
+gtk_entry_delete_text (GtkEditable *editable,
+ guint start_pos,
+ guint end_pos)
{
gchar *text;
gint deletion_length;
gint i;
+ GtkEntry *entry;
+
g_return_if_fail (entry != NULL);
- g_return_if_fail (GTK_IS_ENTRY (entry));
+ g_return_if_fail (GTK_IS_ENTRY (editable));
+
+ entry = GTK_ENTRY (editable);
- if (entry->selection_start_pos > start_pos)
- entry->selection_start_pos -= MIN(end_pos, entry->selection_start_pos) - start_pos;
- if (entry->selection_end_pos > start_pos)
- entry->selection_end_pos -= MIN(end_pos, entry->selection_end_pos) - start_pos;
+ if (editable->selection_start_pos > start_pos)
+ editable->selection_start_pos -= MIN(end_pos, editable->selection_start_pos) - start_pos;
+ if (editable->selection_end_pos > start_pos)
+ editable->selection_end_pos -= MIN(end_pos, editable->selection_end_pos) - start_pos;
if ((start_pos < end_pos) &&
(start_pos >= 0) &&
@@ -1813,23 +1468,62 @@ gtk_real_entry_delete_text (GtkEntry *entry,
text[i] = '\0';
entry->text_length -= deletion_length;
- entry->current_pos = start_pos;
+ editable->current_pos = start_pos;
}
+
+ gtk_entry_queue_draw (entry);
}
+static void
+gtk_entry_update_text (GtkEditable *editable,
+ guint start_pos,
+ guint end_pos)
+{
+ gtk_entry_queue_draw (GTK_ENTRY(editable));
+}
+
+gchar *
+gtk_entry_get_chars (GtkEditable *editable,
+ guint start,
+ guint end)
+{
+ gchar *retval;
+ GtkEntry *entry;
+ gchar c;
+
+ g_return_val_if_fail (entry != NULL, NULL);
+ g_return_val_if_fail (GTK_IS_ENTRY (editable), NULL);
+
+ entry = GTK_ENTRY (editable);
+
+ start = MIN(entry->text_length, start);
+ end = MIN(entry->text_length, end);
+
+ c = entry->text[end];
+ entry->text[end] = '\0';
+
+ retval = g_strdup (&entry->text[start]);
+
+ entry->text[end] = c;
+
+ return retval;
+}
static void
gtk_move_forward_character (GtkEntry *entry)
{
gint len;
- if (entry->current_pos < entry->text_length)
+ GtkEditable *editable;
+ editable = GTK_EDITABLE (entry);
+
+ if (editable->current_pos < entry->text_length)
{
- len = mblen (entry->text+entry->current_pos, MB_CUR_MAX);
- entry->current_pos += (len>0)? len:1;
+ len = mblen (entry->text+editable->current_pos, MB_CUR_MAX);
+ editable->current_pos += (len>0)? len:1;
}
- if (entry->current_pos > entry->text_length)
- entry->current_pos = entry->text_length;
+ if (editable->current_pos > entry->text_length)
+ editable->current_pos = entry->text_length;
}
static gint
@@ -1852,14 +1546,17 @@ move_backward_character (gchar *str, gint index)
static void
gtk_move_backward_character (GtkEntry *entry)
{
+ GtkEditable *editable;
+ editable = GTK_EDITABLE (entry);
+
/* this routine is correct only if string is state-independent-encoded */
- if (0 < entry->current_pos)
+ if (0 < editable->current_pos)
{
- entry->current_pos = move_backward_character (entry->text,
- entry->current_pos);
- if (entry->current_pos < 0)
- entry->current_pos = 0;
+ editable->current_pos = move_backward_character (entry->text,
+ editable->current_pos);
+ if (editable->current_pos < 0)
+ editable->current_pos = 0;
}
}
@@ -1871,10 +1568,13 @@ gtk_move_forward_word (GtkEntry *entry)
wchar_t c;
gint len;
+ GtkEditable *editable;
+ editable = GTK_EDITABLE (entry);
+
if (entry->text)
{
text = entry->text;
- i = entry->current_pos;
+ i = editable->current_pos;
len = mbtowc (&c, text+i, MB_CUR_MAX);
if (!iswalnum(c))
@@ -1892,9 +1592,9 @@ gtk_move_forward_word (GtkEntry *entry)
break;
}
- entry->current_pos = i;
- if (entry->current_pos > entry->text_length)
- entry->current_pos = entry->text_length;
+ editable->current_pos = i;
+ if (editable->current_pos > entry->text_length)
+ editable->current_pos = entry->text_length;
}
}
@@ -1906,14 +1606,17 @@ gtk_move_backward_word (GtkEntry *entry)
wchar_t c;
gint len;
+ GtkEditable *editable;
+ editable = GTK_EDITABLE (entry);
+
if (entry->text)
{
text = entry->text;
- i=move_backward_character(text, entry->current_pos);
+ i=move_backward_character(text, editable->current_pos);
if (i < 0) /* Per */
{
- entry->selection_start_pos = 0;
- entry->selection_end_pos = 0;
+ editable->selection_start_pos = 0;
+ editable->selection_end_pos = 0;
return;
}
@@ -1939,20 +1642,20 @@ gtk_move_backward_word (GtkEntry *entry)
if (i < 0)
i = 0;
- entry->current_pos = i;
+ editable->current_pos = i;
}
}
static void
gtk_move_beginning_of_line (GtkEntry *entry)
{
- entry->current_pos = 0;
+ GTK_EDITABLE(entry)->current_pos = 0;
}
static void
gtk_move_end_of_line (GtkEntry *entry)
{
- entry->current_pos = entry->text_length;
+ GTK_EDITABLE(entry)->current_pos = entry->text_length;
}
static void
@@ -1960,13 +1663,16 @@ gtk_delete_forward_character (GtkEntry *entry)
{
gint old_pos;
- if (entry->selection_start_pos != entry->selection_end_pos)
- gtk_delete_selection (entry);
+ GtkEditable *editable;
+ editable = GTK_EDITABLE (entry);
+
+ if (editable->selection_start_pos != editable->selection_end_pos)
+ gtk_editable_delete_selection (editable);
else
{
- old_pos = entry->current_pos;
+ old_pos = editable->current_pos;
gtk_move_forward_character (entry);
- gtk_entry_delete_text (entry, old_pos, entry->current_pos);
+ gtk_editable_delete_text (editable, old_pos, editable->current_pos);
}
}
@@ -1975,13 +1681,16 @@ gtk_delete_backward_character (GtkEntry *entry)
{
gint old_pos;
- if (entry->selection_start_pos != entry->selection_end_pos)
- gtk_delete_selection (entry);
+ GtkEditable *editable;
+ editable = GTK_EDITABLE (entry);
+
+ if (editable->selection_start_pos != editable->selection_end_pos)
+ gtk_editable_delete_selection (editable);
else
{
- old_pos = entry->current_pos;
+ old_pos = editable->current_pos;
gtk_move_backward_character (entry);
- gtk_entry_delete_text (entry, entry->current_pos, old_pos);
+ gtk_editable_delete_text (editable, editable->current_pos, old_pos);
}
}
@@ -1990,13 +1699,16 @@ gtk_delete_forward_word (GtkEntry *entry)
{
gint old_pos;
- if (entry->selection_start_pos != entry->selection_end_pos)
- gtk_delete_selection (entry);
+ GtkEditable *editable;
+ editable = GTK_EDITABLE (entry);
+
+ if (editable->selection_start_pos != editable->selection_end_pos)
+ gtk_editable_delete_selection (editable);
else
{
- old_pos = entry->current_pos;
+ old_pos = editable->current_pos;
gtk_move_forward_word (entry);
- gtk_entry_delete_text (entry, old_pos, entry->current_pos);
+ gtk_editable_delete_text (editable, old_pos, editable->current_pos);
}
}
@@ -2005,45 +1717,29 @@ gtk_delete_backward_word (GtkEntry *entry)
{
gint old_pos;
- if (entry->selection_start_pos != entry->selection_end_pos)
- gtk_delete_selection (entry);
+ GtkEditable *editable;
+ editable = GTK_EDITABLE (entry);
+
+ if (editable->selection_start_pos != editable->selection_end_pos)
+ gtk_editable_delete_selection (editable);
else
{
- old_pos = entry->current_pos;
+ old_pos = editable->current_pos;
gtk_move_backward_word (entry);
- gtk_entry_delete_text (entry, entry->current_pos, old_pos);
+ gtk_editable_delete_text (editable, editable->current_pos, old_pos);
}
}
static void
gtk_delete_line (GtkEntry *entry)
{
- gtk_entry_delete_text (entry, 0, entry->text_length);
+ gtk_editable_delete_text (GTK_EDITABLE(entry), 0, entry->text_length);
}
static void
gtk_delete_to_line_end (GtkEntry *entry)
{
- gtk_entry_delete_text (entry, entry->current_pos, entry->text_length);
-}
-
-static void
-gtk_delete_selection (GtkEntry *entry)
-{
- if (entry->selection_start_pos != entry->selection_end_pos)
- gtk_entry_delete_text (entry,
- MIN (entry->selection_start_pos, entry->selection_end_pos),
- MAX (entry->selection_start_pos, entry->selection_end_pos));
-
- entry->selection_start_pos = 0;
- entry->selection_end_pos = 0;
-
- if (entry->have_selection)
- {
- entry->have_selection = FALSE;
- if (gdk_selection_owner_get (GDK_SELECTION_PRIMARY) == GTK_WIDGET (entry)->window)
- gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY, GDK_CURRENT_TIME);
- }
+ gtk_editable_delete_text (GTK_EDITABLE(entry), GTK_EDITABLE(entry)->current_pos, entry->text_length);
}
static void
@@ -2052,82 +1748,46 @@ gtk_select_word (GtkEntry *entry)
gint start_pos;
gint end_pos;
+ GtkEditable *editable;
+ editable = GTK_EDITABLE (entry);
+
gtk_move_backward_word (entry);
- start_pos = entry->current_pos;
- end_pos = entry->current_pos;
+ start_pos = editable->current_pos;
gtk_move_forward_word (entry);
- end_pos = entry->current_pos;
+ end_pos = editable->current_pos;
- gtk_entry_select_region (entry, start_pos, end_pos);
+ gtk_entry_set_selection (editable, start_pos, end_pos);
}
static void
gtk_select_line (GtkEntry *entry)
{
- gtk_entry_select_region (entry, 0, entry->text_length);
- entry->current_pos = entry->selection_end_pos;
-}
-
-void
-gtk_entry_select_region (GtkEntry *entry,
- gint start,
- gint end)
-{
- entry->have_selection = TRUE;
-
- entry->selection_start_pos = start;
- entry->selection_end_pos = end;
-
- gtk_widget_queue_draw (GTK_WIDGET (entry));
-}
-
-static void
-gtk_entry_cut_clipboard (GtkEntry *entry, GdkEventKey *event)
-{
- gtk_entry_copy_clipboard (entry, event);
- gtk_delete_selection (entry);
+ GtkEditable *editable;
+ editable = GTK_EDITABLE (entry);
- gtk_entry_queue_draw (entry);
+ gtk_entry_set_selection (editable, 0, entry->text_length);
+ editable->current_pos = editable->selection_end_pos;
}
-static void
-gtk_entry_copy_clipboard (GtkEntry *entry, GdkEventKey *event)
+static void
+gtk_entry_set_selection (GtkEditable *editable,
+ guint start,
+ guint end)
{
- gint selection_start_pos;
- gint selection_end_pos;
+ g_return_if_fail (GTK_IS_ENTRY (editable));
- selection_start_pos = MIN (entry->selection_start_pos, entry->selection_end_pos);
- selection_end_pos = MAX (entry->selection_start_pos, entry->selection_end_pos);
-
- if (selection_start_pos != selection_end_pos)
- {
- if (gtk_selection_owner_set (GTK_WIDGET (entry),
- clipboard_atom,
- event->time))
- {
- char c;
+ editable->selection_start_pos = start;
+ editable->selection_end_pos = end;
- c = entry->text[selection_end_pos];
- entry->text[selection_end_pos] = 0;
- entry->clipboard_text = g_strdup (entry->text + selection_start_pos);
- entry->text[selection_end_pos] = c;
- }
- }
+ gtk_entry_queue_draw (GTK_ENTRY (editable));
}
-static void
-gtk_entry_paste_clipboard (GtkEntry *entry, GdkEventKey *event)
+void
+gtk_entry_select_region (GtkEntry *entry,
+ guint start,
+ guint end)
{
- gtk_selection_convert (GTK_WIDGET(entry),
- clipboard_atom, ctext_atom, event->time);
+ gtk_editable_select_region (GTK_EDITABLE(entry), start, end);
}
-void
-gtk_entry_set_max_length (GtkEntry *entry, guint16 max)
-{
- g_return_if_fail (entry != NULL);
- g_return_if_fail (GTK_IS_ENTRY (entry));
-
- entry->text_max_length = max;
-}
diff --git a/gtk/gtkentry.h b/gtk/gtkentry.h
index e977e5761..137818136 100644
--- a/gtk/gtkentry.h
+++ b/gtk/gtkentry.h
@@ -20,7 +20,7 @@
#include <gdk/gdk.h>
-#include <gtk/gtkwidget.h>
+#include <gtk/gtkeditable.h>
#ifdef __cplusplus
@@ -38,7 +38,7 @@ typedef struct _GtkEntryClass GtkEntryClass;
struct _GtkEntry
{
- GtkWidget widget;
+ GtkEditable editable;
GdkWindow *text_area;
GdkPixmap *backing_pixmap;
@@ -48,32 +48,15 @@ struct _GtkEntry
guint16 text_size;
guint16 text_length;
guint16 text_max_length;
- gint16 current_pos;
- gint16 selection_start_pos;
- gint16 selection_end_pos;
gint16 scroll_offset;
- guint have_selection : 1;
guint visible : 1;
- guint editable : 1;
guint32 timer;
- GdkIC ic;
-
- gchar *clipboard_text;
};
struct _GtkEntryClass
{
- GtkWidgetClass parent_class;
-
- void (* insert_text) (GtkEntry *entry,
- const gchar *text,
- gint length,
- gint *position);
- void (* delete_text) (GtkEntry *entry,
- gint start_pos,
- gint end_pos);
- void (* changed) (GtkEntry *entry);
- void (* set_text) (GtkEntry *entry);
+ GtkEditableClass parent_class;
+
void (* activate) (GtkEntry *entry);
};
@@ -90,8 +73,8 @@ void gtk_entry_set_position (GtkEntry *entry,
gint position);
gchar* gtk_entry_get_text (GtkEntry *entry);
void gtk_entry_select_region (GtkEntry *entry,
- gint start,
- gint end);
+ guint start,
+ guint end);
void gtk_entry_set_visibility (GtkEntry *entry,
gboolean visible);
void gtk_entry_set_editable (GtkEntry *entry,
diff --git a/gtk/gtkfilesel.c b/gtk/gtkfilesel.c
index 6ac032659..56013eec1 100644
--- a/gtk/gtkfilesel.c
+++ b/gtk/gtkfilesel.c
@@ -936,8 +936,8 @@ gtk_file_selection_rename_file (GtkWidget *widget, gpointer data)
gtk_widget_show (fs->fileop_entry);
gtk_entry_set_text (GTK_ENTRY (fs->fileop_entry), fs->fileop_file);
- gtk_entry_select_region (GTK_ENTRY (fs->fileop_entry),
- 0, strlen (fs->fileop_file));
+ gtk_editable_select_region (GTK_EDITABLE (fs->fileop_entry),
+ 0, strlen (fs->fileop_file));
/* buttons */
button = gtk_button_new_with_label ("Rename");
diff --git a/gtk/gtkspinbutton.c b/gtk/gtkspinbutton.c
index 8de901e5a..552e20ef3 100644
--- a/gtk/gtkspinbutton.c
+++ b/gtk/gtkspinbutton.c
@@ -73,7 +73,7 @@ static void gtk_spin_button_value_changed (GtkWidget *widget,
static gint gtk_spin_button_key_press (GtkWidget *widget,
GdkEventKey *event);
static void gtk_spin_button_update (GtkSpinButton *spin_button);
-static void gtk_spin_button_changed (GtkEntry *entry);
+static void gtk_spin_button_changed (GtkEditable *editable);
static void gtk_spin_button_activate (GtkEntry *entry);
@@ -109,11 +109,13 @@ gtk_spin_button_class_init (GtkSpinButtonClass *class)
{
GtkObjectClass *object_class;
GtkWidgetClass *widget_class;
+ GtkEditableClass *editable_class;
GtkEntryClass *entry_class;
object_class = (GtkObjectClass*) class;
widget_class = (GtkWidgetClass*) class;
entry_class = (GtkEntryClass*) class;
+ editable_class = (GtkEditableClass*) class;
parent_class = gtk_type_class (gtk_entry_get_type ());
@@ -135,7 +137,7 @@ gtk_spin_button_class_init (GtkSpinButtonClass *class)
widget_class->leave_notify_event = gtk_spin_button_leave_notify;
widget_class->focus_out_event = gtk_spin_button_focus_out;
- entry_class->changed = gtk_spin_button_changed;
+ editable_class->changed = gtk_spin_button_changed;
entry_class->activate = gtk_spin_button_activate;
}
@@ -900,22 +902,22 @@ gtk_spin_button_update (GtkSpinButton *spin_button)
}
static void
-gtk_spin_button_changed (GtkEntry *entry)
+gtk_spin_button_changed (GtkEditable *editable)
{
- g_return_if_fail (entry != NULL);
- g_return_if_fail (GTK_IS_ENTRY (entry));
+ g_return_if_fail (editable != NULL);
+ g_return_if_fail (GTK_IS_SPIN_BUTTON (editable));
- GTK_ENTRY_CLASS (parent_class)->changed (entry);
- if (GTK_WIDGET_VISIBLE (GTK_WIDGET (entry)))
+ GTK_EDITABLE_CLASS (parent_class)->changed (editable);
+ if (GTK_WIDGET_VISIBLE (GTK_WIDGET (editable)))
{
GtkSpinButton *spin;
gfloat val;
gchar *error = NULL;
- spin = GTK_SPIN_BUTTON (entry);
+ spin = GTK_SPIN_BUTTON (editable);
spin->snapped = 0;
- val = strtod (entry->text, &error);
+ val = strtod (GTK_ENTRY (editable)->text, &error);
if (val < spin->adjustment->lower)
val = spin->adjustment->lower;
else if (val > spin->adjustment->upper)
@@ -928,9 +930,9 @@ static void
gtk_spin_button_activate (GtkEntry *entry)
{
g_return_if_fail (entry != NULL);
- g_return_if_fail (GTK_IS_ENTRY (entry));
+ g_return_if_fail (GTK_IS_SPIN_BUTTON (entry));
- if (entry->editable)
+ if (GTK_EDITABLE(entry)->editable)
gtk_spin_button_update (GTK_SPIN_BUTTON (entry));
}
diff --git a/gtk/gtktext.c b/gtk/gtktext.c
index bf803ea86..a8c8df434 100644
--- a/gtk/gtktext.c
+++ b/gtk/gtktext.c
@@ -22,6 +22,7 @@
#include "gdk/gdkx.h"
#endif
#include "gtkmain.h"
+#include "gtkselection.h"
#include "gtksignal.h"
#include "gtktext.h"
#include "line-wrap.xbm"
@@ -57,6 +58,7 @@
#define MARK_CURRENT_FONT(mark) (((TextProperty*)(mark)->property->data)->font->gdk_font)
#define MARK_CURRENT_FORE(mark) (&((TextProperty*)(mark)->property->data)->fore_color)
#define MARK_CURRENT_BACK(mark) (&((TextProperty*)(mark)->property->data)->back_color)
+
#define MARK_CURRENT_TEXT_FONT(m) (((TextProperty*)(m)->property->data)->font)
#define TEXT_LENGTH(t) ((t)->text_end - (t)->gap_size)
#define FONT_HEIGHT(f) ((f)->ascent + (f)->descent)
@@ -165,6 +167,23 @@ static void gtk_text_adjustment (GtkAdjustment *adjustment,
static void gtk_text_disconnect (GtkAdjustment *adjustment,
GtkText *text);
+static void gtk_text_insert_text (GtkEditable *editable,
+ const gchar *new_text,
+ guint new_text_length,
+ guint *position);
+static void gtk_text_delete_text (GtkEditable *editable,
+ guint start_pos,
+ guint end_pos);
+static void gtk_text_update_text (GtkEditable *editable,
+ guint start_pos,
+ guint end_pos);
+static gchar *gtk_text_get_chars (GtkEditable *editable,
+ guint start,
+ guint end);
+static void gtk_text_set_selection (GtkEditable *editable,
+ guint start,
+ guint end);
+
/* Event handlers */
static void gtk_text_draw (GtkWidget *widget,
GdkRectangle *area);
@@ -182,12 +201,6 @@ static gint gtk_text_focus_in (GtkWidget *widget,
GdkEventFocus *event);
static gint gtk_text_focus_out (GtkWidget *widget,
GdkEventFocus *event);
-static gint gtk_text_selection_clear (GtkWidget *widget,
- GdkEventSelection *event);
-static gint gtk_text_selection_request (GtkWidget *widget,
- GdkEventSelection *event);
-static gint gtk_text_selection_notify (GtkWidget *widget,
- GdkEventSelection *event);
static void move_gap_to_point (GtkText* text);
static void make_forward_space (GtkText* text, guint len);
@@ -242,7 +255,7 @@ static void find_cursor (GtkText* text);
static void find_cursor_at_line (GtkText* text,
const LineParams* start_line,
gint pixel_height);
-static void mouse_click_1 (GtkText* text, GdkEventButton *event);
+static void find_mouse_cursor (GtkText* text, gint x, gint y);
/* Scrolling. */
static void adjust_adj (GtkText* text, GtkAdjustment* adj);
@@ -261,6 +274,21 @@ static void move_cursor_page_ver (GtkText *text, int dir);
static void move_cursor_ver (GtkText *text, int count);
static void move_cursor_hor (GtkText *text, int count);
+static void gtk_text_move_forward_character (GtkText *text);
+static void gtk_text_move_backward_character (GtkText *text);
+static void gtk_text_move_forward_word (GtkText *text);
+static void gtk_text_move_backward_word (GtkText *text);
+static void gtk_text_move_beginning_of_line (GtkText *text);
+static void gtk_text_move_end_of_line (GtkText *text);
+static void gtk_text_delete_forward_character (GtkText *text);
+static void gtk_text_delete_backward_character (GtkText *text);
+static void gtk_text_delete_forward_word (GtkText *text);
+static void gtk_text_delete_backward_word (GtkText *text);
+static void gtk_text_delete_line (GtkText *text);
+static void gtk_text_delete_to_line_end (GtkText *text);
+static void gtk_text_select_word (GtkText *text);
+static void gtk_text_select_line (GtkText *text);
+
#define DEBUG_GTK_TEXT
#if defined(DEBUG_GTK_TEXT) && defined(__GNUC__)
@@ -313,6 +341,67 @@ static GMemChunk *text_property_chunk = NULL;
static GtkWidgetClass *parent_class = NULL;
+static GtkTextFunction control_keys[26] =
+{
+ (GtkTextFunction)gtk_text_move_beginning_of_line, /* a */
+ (GtkTextFunction)gtk_text_move_backward_character, /* b */
+ gtk_editable_copy_clipboard, /* c */
+ (GtkTextFunction)gtk_text_delete_forward_character, /* d */
+ (GtkTextFunction)gtk_text_move_end_of_line, /* e */
+ (GtkTextFunction)gtk_text_move_forward_character, /* f */
+ NULL, /* g */
+ (GtkTextFunction)gtk_text_delete_backward_character, /* h */
+ NULL, /* i */
+ NULL, /* j */
+ (GtkTextFunction)gtk_text_delete_to_line_end, /* k */
+ NULL, /* l */
+ NULL, /* m */
+ NULL, /* n */
+ NULL, /* o */
+ NULL, /* p */
+ NULL, /* q */
+ NULL, /* r */
+ NULL, /* s */
+ NULL, /* t */
+ (GtkTextFunction)gtk_text_delete_line, /* u */
+ gtk_editable_paste_clipboard, /* v */
+ (GtkTextFunction)gtk_text_delete_backward_word, /* w */
+ gtk_editable_cut_clipboard, /* x */
+ NULL, /* y */
+ NULL, /* z */
+};
+
+static GtkTextFunction alt_keys[26] =
+{
+ NULL, /* a */
+ (GtkTextFunction)gtk_text_move_backward_word, /* b */
+ NULL, /* c */
+ (GtkTextFunction)gtk_text_delete_forward_word, /* d */
+ NULL, /* e */
+ (GtkTextFunction)gtk_text_move_forward_word, /* f */
+ NULL, /* g */
+ NULL, /* h */
+ NULL, /* i */
+ NULL, /* j */
+ NULL, /* k */
+ NULL, /* l */
+ NULL, /* m */
+ NULL, /* n */
+ NULL, /* o */
+ NULL, /* p */
+ NULL, /* q */
+ NULL, /* r */
+ NULL, /* s */
+ NULL, /* t */
+ NULL, /* u */
+ NULL, /* v */
+ NULL, /* w */
+ NULL, /* x */
+ NULL, /* y */
+ NULL, /* z */
+};
+
+
/**********************************************************************/
/* Widget Crap */
/**********************************************************************/
@@ -335,7 +424,7 @@ gtk_text_get_type ()
(GtkArgGetFunc) NULL,
};
- text_type = gtk_type_unique (gtk_widget_get_type (), &text_info);
+ text_type = gtk_type_unique (gtk_editable_get_type (), &text_info);
}
return text_type;
@@ -346,9 +435,11 @@ gtk_text_class_init (GtkTextClass *class)
{
GtkObjectClass *object_class;
GtkWidgetClass *widget_class;
+ GtkEditableClass *editable_class;
object_class = (GtkObjectClass*) class;
widget_class = (GtkWidgetClass*) class;
+ editable_class = (GtkEditableClass*) class;
parent_class = gtk_type_class (gtk_widget_get_type ());
@@ -367,9 +458,12 @@ gtk_text_class_init (GtkTextClass *class)
widget_class->key_press_event = gtk_text_key_press;
widget_class->focus_in_event = gtk_text_focus_in;
widget_class->focus_out_event = gtk_text_focus_out;
- widget_class->selection_clear_event = gtk_text_selection_clear;
- widget_class->selection_request_event = gtk_text_selection_request;
- widget_class->selection_notify_event = gtk_text_selection_notify;
+
+ editable_class->insert_text = gtk_text_insert_text;
+ editable_class->delete_text = gtk_text_delete_text;
+ editable_class->update_text = gtk_text_update_text;
+ editable_class->get_chars = gtk_text_get_chars;
+ editable_class->set_selection = gtk_text_set_selection;
}
static void
@@ -393,7 +487,7 @@ gtk_text_init (GtkText *text)
text->tab_stops = g_list_prepend (text->tab_stops, (void*)8);
text->line_wrap = TRUE;
- text->is_editable = FALSE;
+ GTK_EDITABLE(text)->editable = FALSE;
}
GtkWidget*
@@ -416,7 +510,7 @@ gtk_text_set_editable (GtkText *text,
g_return_if_fail (text != NULL);
g_return_if_fail (GTK_IS_TEXT (text));
- text->is_editable = (editable != FALSE);
+ GTK_EDITABLE(text)->editable = (editable != FALSE);
}
void
@@ -552,9 +646,9 @@ gtk_text_insert (GtkText *text,
g_assert (GTK_WIDGET_REALIZED (text));
if (fore == NULL)
- fore = &text->widget.style->fg[GTK_STATE_NORMAL];
+ fore = &GTK_WIDGET (text)->style->text[GTK_STATE_NORMAL];
if (back == NULL)
- back = &text->widget.style->bg[GTK_STATE_NORMAL];
+ back = &GTK_WIDGET (text)->style->base[GTK_STATE_NORMAL];
/* This must be because we need to have the style set up. */
g_assert (GTK_WIDGET_REALIZED(text));
@@ -631,9 +725,18 @@ gtk_text_forward_delete (GtkText *text,
}
if (text->point.index < text->first_line_start_index)
- text->first_line_start_index -= MIN(nchars,
- text->first_line_start_index -
- text->point.index);
+ {
+ if (text->point.index >= text->first_line_start_index - nchars)
+ {
+ text->first_line_start_index = text->point.index;
+ while ((text->first_line_start_index > 0) &&
+ (GTK_TEXT_INDEX (text, text->first_line_start_index - 1) != LINE_DELIM))
+ text->first_line_start_index -= 1;
+
+ }
+ else
+ text->first_line_start_index -= nchars;
+ }
move_gap_to_point (text);
@@ -647,14 +750,20 @@ gtk_text_forward_delete (GtkText *text,
return TRUE;
}
-gchar *
-gtk_text_get_chars (GtkText *text,
+static gchar *
+gtk_text_get_chars (GtkEditable *editable,
guint index,
guint nchars)
{
+ GtkText *text;
+
gchar *retval;
gchar *p;
guint n;
+
+ g_return_val_if_fail (editable != NULL, NULL);
+ g_return_val_if_fail (GTK_IS_TEXT (editable), NULL);
+ text = GTK_TEXT (editable);
if (index+nchars > TEXT_LENGTH (text))
return NULL;
@@ -668,7 +777,7 @@ gtk_text_get_chars (GtkText *text,
if (index < text->gap_position)
{
n = MIN (text->gap_position - index, nchars);
- memcpy (p, text->text + GTK_TEXT_INDEX(text, index), n);
+ memcpy (p, &text->text[index], n);
p += n;
index += n;
nchars -= n;
@@ -680,9 +789,10 @@ gtk_text_get_chars (GtkText *text,
text->text + MAX (text->gap_position + text->gap_size,
index + text->gap_size),
nchars);
+ p += nchars;
}
- retval[nchars+1] = 0;
+ *p = 0;
return retval;
}
@@ -703,10 +813,10 @@ gtk_text_finalize (GtkObject *object)
gtk_object_unref (GTK_OBJECT (text->vadj));
#ifdef USE_XIM
- if (text->ic)
+ if (GTK_EDITABLE(text)->ic)
{
- gdk_ic_destroy (text->ic);
- text->ic = NULL;
+ gdk_ic_destroy (GTK_EDITABLE(text)->ic);
+ GTK_EDITABLE(text)->ic = NULL;
}
#endif
@@ -717,13 +827,15 @@ static void
gtk_text_realize (GtkWidget *widget)
{
GtkText *text;
+ GtkEditable *editable;
GdkWindowAttr attributes;
gint attributes_mask;
g_return_if_fail (widget != NULL);
g_return_if_fail (GTK_IS_TEXT (widget));
- text = (GtkText*) widget;
+ text = GTK_TEXT (widget);
+ editable = GTK_EDITABLE (widget);
GTK_WIDGET_SET_FLAGS (text, GTK_REALIZED);
attributes.window_type = GDK_WINDOW_CHILD;
@@ -758,11 +870,11 @@ gtk_text_realize (GtkWidget *widget)
widget->style = gtk_style_attach (widget->style, widget->window);
/* Can't call gtk_style_set_background here because its handled specially */
- if (!text->widget.style->bg_pixmap[GTK_STATE_NORMAL])
- gdk_window_set_background (text->widget.window, &text->widget.style->bg[GTK_STATE_NORMAL]);
+ if (!widget->style->bg_pixmap[GTK_STATE_NORMAL])
+ gdk_window_set_background (widget->window, &widget->style->base[GTK_STATE_NORMAL]);
- if (!text->widget.style->bg_pixmap[GTK_STATE_NORMAL])
- gdk_window_set_background (text->text_area, &text->widget.style->bg[GTK_STATE_NORMAL]);
+ if (!widget->style->bg_pixmap[GTK_STATE_NORMAL])
+ gdk_window_set_background (text->text_area, &widget->style->base[GTK_STATE_NORMAL]);
text->line_wrap_bitmap = gdk_bitmap_create_from_data (text->text_area,
(gchar*) line_wrap_bits,
@@ -776,7 +888,7 @@ gtk_text_realize (GtkWidget *widget)
text->gc = gdk_gc_new (text->text_area);
gdk_gc_set_exposures (text->gc, TRUE);
- gdk_gc_set_foreground (text->gc, &widget->style->fg[GTK_STATE_NORMAL]);
+ gdk_gc_set_foreground (text->gc, &widget->style->text[GTK_STATE_NORMAL]);
#ifdef USE_XIM
if (gdk_im_ready ())
@@ -810,7 +922,7 @@ gtk_text_realize (GtkWidget *widget)
spot.x = 0;
spot.y = height;
- text->ic = gdk_ic_new (text->text_area, text->text_area,
+ editable->ic = gdk_ic_new (text->text_area, text->text_area,
style,
"spotLocation", &spot,
"area", &rect,
@@ -818,24 +930,24 @@ gtk_text_realize (GtkWidget *widget)
NULL);
break;
default:
- text->ic = gdk_ic_new (text->text_area, text->text_area,
+ editable->ic = gdk_ic_new (text->text_area, text->text_area,
style, NULL);
}
- if (text->ic == NULL)
+ if (editable->ic == NULL)
g_warning ("Can't create input context.");
else
{
GdkColormap *colormap;
mask = gdk_window_get_events (text->text_area);
- mask |= gdk_ic_get_events (text->ic);
+ mask |= gdk_ic_get_events (editable->ic);
gdk_window_set_events (text->text_area, mask);
if ((colormap = gtk_widget_get_colormap (widget)) !=
gtk_widget_get_default_colormap ())
{
- gdk_ic_set_attr (text->ic, "preeditAttributes",
+ gdk_ic_set_attr (editable->ic, "preeditAttributes",
"colorMap", GDK_COLORMAP_XCOLORMAP (colormap),
NULL);
}
@@ -846,6 +958,9 @@ gtk_text_realize (GtkWidget *widget)
init_properties (text);
gdk_window_show (text->text_area);
+
+ if (editable->selection_start_pos != editable->selection_end_pos)
+ gtk_editable_claim_selection (editable, TRUE, GDK_CURRENT_TIME);
}
static void
@@ -872,14 +987,16 @@ gtk_text_unrealize (GtkWidget *widget)
static void
clear_focus_area (GtkText *text, gint area_x, gint area_y, gint area_width, gint area_height)
{
- gint ythick = TEXT_BORDER_ROOM + text->widget.style->klass->ythickness;
- gint xthick = TEXT_BORDER_ROOM + text->widget.style->klass->xthickness;
+ GtkWidget *widget = GTK_WIDGET (text);
+
+ gint ythick = TEXT_BORDER_ROOM + widget->style->klass->ythickness;
+ gint xthick = TEXT_BORDER_ROOM + widget->style->klass->xthickness;
gint width, height;
gint xorig, yorig;
gint x, y;
- gdk_window_get_size (text->widget.style->bg_pixmap[GTK_STATE_NORMAL], &width, &height);
+ gdk_window_get_size (widget->style->bg_pixmap[GTK_STATE_NORMAL], &width, &height);
yorig = - text->first_onscreen_ver_pixel + ythick;
xorig = - text->first_onscreen_hor_pixel + xthick;
@@ -900,9 +1017,9 @@ clear_focus_area (GtkText *text, gint area_x, gint area_y, gint area_width, gint
gint xoff = (x - xorig) % width;
gint xw = MIN(width - xoff, (area_x + area_width) - x);
- gdk_draw_pixmap (text->widget.window,
+ gdk_draw_pixmap (widget->window,
text->gc,
- text->widget.style->bg_pixmap[GTK_STATE_NORMAL],
+ widget->style->bg_pixmap[GTK_STATE_NORMAL],
xoff,
yoff,
x,
@@ -1018,12 +1135,14 @@ gtk_text_size_allocate (GtkWidget *widget,
GtkAllocation *allocation)
{
GtkText *text;
+ GtkEditable *editable;
g_return_if_fail (widget != NULL);
g_return_if_fail (GTK_IS_TEXT (widget));
g_return_if_fail (allocation != NULL);
text = GTK_TEXT (widget);
+ editable = GTK_EDITABLE (widget);
widget->allocation = *allocation;
if (GTK_WIDGET_REALIZED (widget))
@@ -1041,7 +1160,7 @@ gtk_text_size_allocate (GtkWidget *widget,
TEXT_BORDER_ROOM) * 2);
#ifdef USE_XIM
- if (text->ic && (gdk_ic_get_style (text->ic) & GdkIMPreeditPosition))
+ if (editable->ic && (gdk_ic_get_style (editable->ic) & GdkIMPreeditPosition))
{
gint width, height;
GdkRectangle rect;
@@ -1051,7 +1170,7 @@ gtk_text_size_allocate (GtkWidget *widget,
rect.y = 0;
rect.width = width;
rect.height = height;
- gdk_ic_set_attr (text->ic, "preeditAttributes", "area", &rect, NULL);
+ gdk_ic_set_attr (editable->ic, "preeditAttributes", "area", &rect, NULL);
}
#endif
@@ -1101,12 +1220,19 @@ gtk_text_button_press (GtkWidget *widget,
GdkEventButton *event)
{
GtkText *text;
+ GtkEditable *editable;
+ static GdkAtom ctext_atom = GDK_NONE;
g_return_val_if_fail (widget != NULL, FALSE);
g_return_val_if_fail (GTK_IS_TEXT (widget), FALSE);
g_return_val_if_fail (event != NULL, FALSE);
- text = GTK_TEXT(widget);
+ if (ctext_atom == GDK_NONE)
+ ctext_atom = gdk_atom_intern ("COMPOUND_TEXT", FALSE);
+
+ text = GTK_TEXT (widget);
+ editable = GTK_EDITABLE (widget);
+
if (!GTK_WIDGET_HAS_FOCUS (widget))
gtk_widget_grab_focus (widget);
@@ -1118,18 +1244,21 @@ gtk_text_button_press (GtkWidget *widget,
switch (event->type)
{
case GDK_BUTTON_PRESS:
- undraw_cursor (GTK_TEXT (widget), FALSE);
- mouse_click_1 (GTK_TEXT (widget), event);
- draw_cursor (GTK_TEXT (widget), FALSE);
- /* start selection */
+ undraw_cursor (text, FALSE);
+ find_mouse_cursor (text, event->x, event->y);
+ draw_cursor (text, FALSE);
+
+ gtk_text_set_selection (GTK_EDITABLE(text),
+ text->cursor_mark.index,
+ text->cursor_mark.index);
break;
case GDK_2BUTTON_PRESS:
- /* select word */
+ gtk_text_select_word (text);
break;
case GDK_3BUTTON_PRESS:
- /* select line */
+ gtk_text_select_line (text);
break;
default:
@@ -1140,11 +1269,28 @@ gtk_text_button_press (GtkWidget *widget,
{
if (event->button == 2)
{
- /* insert selection. */
+ if (editable->selection_start_pos == editable->selection_end_pos ||
+ editable->has_selection)
+ {
+ undraw_cursor (text, FALSE);
+ find_mouse_cursor (text, event->x, event->y);
+ draw_cursor (text, FALSE);
+
+ editable->current_pos = text->cursor_mark.index;
+ }
+
+ gtk_selection_convert (widget, GDK_SELECTION_PRIMARY,
+ ctext_atom, event->time);
}
else
{
- /* start selection */
+ undraw_cursor (text, FALSE);
+ find_mouse_cursor (text, event->x, event->y);
+ draw_cursor (text, FALSE);
+
+ gtk_text_set_selection (GTK_EDITABLE(text),
+ text->cursor_mark.index,
+ text->cursor_mark.index);
}
}
@@ -1156,17 +1302,43 @@ gtk_text_button_release (GtkWidget *widget,
GdkEventButton *event)
{
GtkText *text;
+ GtkEditable *editable;
g_return_val_if_fail (widget != NULL, FALSE);
g_return_val_if_fail (GTK_IS_TEXT (widget), FALSE);
g_return_val_if_fail (event != NULL, FALSE);
- if (event->button != 2)
+ text = GTK_TEXT (widget);
+
+ if (event->button == 1)
{
- gtk_grab_remove (widget);
-
text = GTK_TEXT (widget);
+ editable = GTK_EDITABLE (widget);
- /* stop selecting. */
+ gtk_grab_remove (widget);
+
+ editable->has_selection = FALSE;
+ if (editable->selection_start_pos != editable->selection_end_pos)
+ {
+ if (gtk_selection_owner_set (widget,
+ GDK_SELECTION_PRIMARY,
+ event->time))
+ {
+ editable->has_selection = TRUE;
+ gtk_text_update_text (editable, editable->selection_start_pos,
+ editable->selection_end_pos);
+ }
+ }
+ else
+ {
+ if (gdk_selection_owner_get (GDK_SELECTION_PRIMARY) == widget->window)
+ gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY, event->time);
+ }
+ }
+ else if (event->button == 3)
+ {
+ gtk_grab_remove (widget);
+ if (gdk_selection_owner_get (GDK_SELECTION_PRIMARY) == widget->window)
+ gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY, event->time);
}
return FALSE;
@@ -1189,7 +1361,13 @@ gtk_text_motion_notify (GtkWidget *widget,
if (event->is_hint || (text->text_area != event->window))
gdk_window_get_pointer (text->text_area, &x, NULL, NULL);
- /* update selection */
+ undraw_cursor (GTK_TEXT (widget), FALSE);
+ find_mouse_cursor (GTK_TEXT (widget), event->x, event->y);
+ draw_cursor (GTK_TEXT (widget), FALSE);
+
+ gtk_text_set_selection (GTK_EDITABLE(text),
+ GTK_EDITABLE(text)->selection_start_pos,
+ text->cursor_mark.index);
return FALSE;
}
@@ -1204,16 +1382,29 @@ gtk_text_insert_1_at_point (GtkText* text, gchar key)
&key, 1);
}
-static void
-gtk_text_backward_delete_1_at_point (GtkText* text)
+static void
+gtk_text_insert_text (GtkEditable *editable,
+ const gchar *new_text,
+ guint new_text_length,
+ guint *position)
{
- gtk_text_backward_delete (text, 1);
+ GtkText *text = GTK_TEXT (editable);
+
+ gtk_text_set_point (text, *position);
+ gtk_text_insert (text, NULL, NULL, NULL, new_text, new_text_length);
+
+ *position = text->point.index;
}
-static void
-gtk_text_forward_delete_1_at_point (GtkText* text)
+static void
+gtk_text_delete_text (GtkEditable *editable,
+ guint start_pos,
+ guint end_pos)
{
- gtk_text_forward_delete (text, 1);
+ GtkText *text = GTK_TEXT (editable);
+
+ gtk_text_set_point (text, start_pos);
+ gtk_text_forward_delete (text, end_pos - start_pos);
}
static gint
@@ -1221,6 +1412,7 @@ gtk_text_key_press (GtkWidget *widget,
GdkEventKey *event)
{
GtkText *text;
+ GtkEditable *editable;
gchar key;
gint return_val;
@@ -1231,11 +1423,12 @@ gtk_text_key_press (GtkWidget *widget,
return_val = FALSE;
text = GTK_TEXT (widget);
+ editable = GTK_EDITABLE (widget);
key = event->keyval;
return_val = TRUE;
- if (text->is_editable == FALSE)
+ if (GTK_EDITABLE(text)->editable == FALSE)
{
switch (event->keyval)
{
@@ -1252,8 +1445,25 @@ gtk_text_key_press (GtkWidget *widget,
}
else
{
+ gint extend_selection;
+ gint extend_start;
+
text->point = find_mark (text, text->cursor_mark.index);
+ extend_selection = event->state & GDK_SHIFT_MASK;
+ extend_start = FALSE;
+
+ if (extend_selection)
+ {
+ if (editable->selection_start_pos == editable->selection_end_pos)
+ {
+ editable->selection_start_pos = text->point.index;
+ editable->selection_end_pos = text->point.index;
+ }
+
+ extend_start = (text->point.index == editable->selection_start_pos);
+ }
+
switch (event->keyval)
{
case GDK_Home: move_cursor_buffer_ver (text, -1); break;
@@ -1266,16 +1476,32 @@ gtk_text_key_press (GtkWidget *widget,
case GDK_Right: move_cursor_hor (text, +1); break;
case GDK_BackSpace:
- if (!text->has_cursor || text->cursor_mark.index == 0)
- break;
-
- gtk_text_backward_delete_1_at_point (text);
+ if (editable->selection_start_pos != editable->selection_end_pos)
+ {
+ gtk_editable_delete_selection (editable);
+ break;
+ }
+ if (text->has_cursor && text->cursor_mark.index != 0)
+ {
+ if (event->state & GDK_CONTROL_MASK)
+ gtk_text_delete_backward_word (text);
+ else
+ gtk_text_backward_delete (text, 1);
+ }
break;
case GDK_Delete:
- if (!text->has_cursor || LAST_INDEX (text, text->cursor_mark))
- break;
-
- gtk_text_forward_delete_1_at_point (text);
+ if (editable->selection_start_pos != editable->selection_end_pos)
+ {
+ gtk_editable_delete_selection (editable);
+ break;
+ }
+ if (text->has_cursor && !LAST_INDEX(text, text->cursor_mark))
+ {
+ if (event->state & GDK_CONTROL_MASK)
+ gtk_text_delete_forward_word (text);
+ else
+ gtk_text_forward_delete (text, 1);
+ }
break;
case GDK_Tab:
if (!text->has_cursor)
@@ -1305,9 +1531,9 @@ gtk_text_key_press (GtkWidget *widget,
if ((key >= 'A') && (key <= 'Z'))
key -= 'A' - 'a';
- if ((key >= 'a') && (key <= 'z') && text->control_keys[(int) (key - 'a')])
+ if ((key >= 'a') && (key <= 'z') && control_keys[(int) (key - 'a')])
{
- (* text->control_keys[(int) (key - 'a')]) (text);
+ (* control_keys[(int) (key - 'a')]) (editable, event);
return_val = TRUE;
}
@@ -1318,9 +1544,9 @@ gtk_text_key_press (GtkWidget *widget,
if ((key >= 'A') && (key <= 'Z'))
key -= 'A' - 'a';
- if ((key >= 'a') && (key <= 'z') && text->alt_keys[(int) (key - 'a')])
+ if ((key >= 'a') && (key <= 'z') && alt_keys[(int) (key - 'a')])
{
- (* text->alt_keys[(int) (key - 'a')]) (text);
+ (* alt_keys[(int) (key - 'a')]) (editable, event);
return_val = TRUE;
}
@@ -1335,6 +1561,35 @@ gtk_text_key_press (GtkWidget *widget,
else
return_val = FALSE;
}
+ editable->current_pos = text->cursor_mark.index;
+
+ if (return_val)
+ {
+ if (extend_selection)
+ {
+ if (editable->current_pos < editable->selection_start_pos)
+ gtk_text_set_selection (editable, editable->current_pos,
+ editable->selection_end_pos);
+ else if (editable->current_pos > editable->selection_end_pos)
+ gtk_text_set_selection (editable, editable->selection_start_pos,
+ editable->current_pos);
+ else
+ {
+ if (extend_start)
+ gtk_text_set_selection (editable, editable->current_pos,
+ editable->selection_end_pos);
+ else
+ gtk_text_set_selection (editable, editable->selection_start_pos,
+ editable->current_pos);
+ }
+ }
+ else
+ gtk_text_set_selection (editable, 0, 0);
+
+ gtk_editable_claim_selection (editable,
+ editable->selection_start_pos != editable->selection_end_pos,
+ event->time);
+ }
}
return return_val;
@@ -1354,8 +1609,8 @@ gtk_text_focus_in (GtkWidget *widget,
gtk_widget_draw_focus (widget);
#ifdef USE_XIM
- if (GTK_TEXT(widget)->ic)
- gdk_im_begin (GTK_TEXT(widget)->ic, GTK_TEXT(widget)->text_area);
+ if (GTK_EDITABLE(widget)->ic)
+ gdk_im_begin (GTK_EDITABLE(widget)->ic, GTK_TEXT(widget)->text_area);
#endif
draw_cursor (GTK_TEXT(widget), TRUE);
@@ -2175,14 +2430,16 @@ delete_text_property (GtkText* text, guint nchars)
static void
init_properties (GtkText *text)
{
+ GtkWidget *widget = (GtkWidget *)text;
+
if (!text->text_properties)
{
text->text_properties = g_list_alloc();
text->text_properties->next = NULL;
text->text_properties->prev = NULL;
- text->text_properties->data = new_text_property (text->widget.style->font,
- &text->widget.style->fg[GTK_STATE_NORMAL],
- &text->widget.style->bg[GTK_STATE_NORMAL],
+ text->text_properties->data = new_text_property (widget->style->font,
+ &widget->style->text[GTK_STATE_NORMAL],
+ &widget->style->base[GTK_STATE_NORMAL],
1);
text->text_properties_end = text->text_properties;
@@ -2440,6 +2697,7 @@ static void
find_cursor_at_line (GtkText* text, const LineParams* start_line, gint pixel_height)
{
gchar ch;
+ GtkEditable *editable = (GtkEditable *)text;
GtkPropertyMark mark = start_line->start;
TabStopMark tab_mark = start_line->tab_cont.tab_start;
@@ -2466,19 +2724,19 @@ find_cursor_at_line (GtkText* text, const LineParams* start_line, gint pixel_hei
text->cursor_char = 0;
#ifdef USE_XIM
- if (gdk_im_ready() && text->ic &&
- gdk_ic_get_style (text->ic) & GdkIMPreeditPosition)
+ if (gdk_im_ready() && editable->ic &&
+ gdk_ic_get_style (editable->ic) & GdkIMPreeditPosition)
{
GdkPoint spot;
spot.x = text->cursor_pos_x;
spot.y = text->cursor_pos_y - text->cursor_char_offset;
if (MARK_CURRENT_FONT (&mark)->type == GDK_FONT_FONTSET)
- gdk_ic_set_attr (text->ic, "preeditAttributes",
+ gdk_ic_set_attr (editable->ic, "preeditAttributes",
"fontSet", GDK_FONT_XFONT (MARK_CURRENT_FONT (&mark)),
NULL);
- gdk_ic_set_attr (text->ic, "preeditAttributes",
+ gdk_ic_set_attr (editable->ic, "preeditAttributes",
"spotLocation", &spot,
"lineSpace", LINE_HEIGHT (*start_line),
"foreground", MARK_CURRENT_FORE (&mark)->pixel,
@@ -2506,7 +2764,7 @@ find_cursor (GtkText* text)
}
static void
-mouse_click_1_at_line (GtkText *text, const LineParams* lp,
+find_mouse_cursor_at_line (GtkText *text, const LineParams* lp,
guint line_pixel_height,
gint button_x)
{
@@ -2548,9 +2806,9 @@ mouse_click_1_at_line (GtkText *text, const LineParams* lp,
}
static void
-mouse_click_1 (GtkText* text, GdkEventButton *event)
+find_mouse_cursor (GtkText* text, gint x, gint y)
{
- if (text->is_editable)
+ if (GTK_EDITABLE(text)->editable)
{
gint pixel_height;
GList* cache = text->line_start_cache;
@@ -2565,9 +2823,9 @@ mouse_click_1 (GtkText* text, GdkEventButton *event)
{
pixel_height += LINE_HEIGHT(CACHE_DATA(cache));
- if (event->y < pixel_height || !cache->next)
+ if (y < pixel_height || !cache->next)
{
- mouse_click_1_at_line (text, &CACHE_DATA(cache), pixel_height, event->x);
+ find_mouse_cursor_at_line (text, &CACHE_DATA(cache), pixel_height, x);
find_cursor (text);
@@ -2714,6 +2972,185 @@ move_cursor_hor (GtkText *text, int count)
draw_cursor (text, FALSE);
}
+static void
+gtk_text_move_forward_character (GtkText *text)
+{
+ move_cursor_hor (text, 1);
+}
+
+static void
+gtk_text_move_backward_character (GtkText *text)
+{
+ move_cursor_hor (text, -1);
+}
+
+static void
+gtk_text_move_forward_word (GtkText *text)
+{
+ undraw_cursor (text, FALSE);
+
+ while (!LAST_INDEX (text, text->cursor_mark) &&
+ !isalnum (GTK_TEXT_INDEX(text, text->cursor_mark.index)))
+ advance_mark (&text->cursor_mark);
+
+ while (!LAST_INDEX (text, text->cursor_mark) &&
+ isalnum (GTK_TEXT_INDEX(text, text->cursor_mark.index)))
+ advance_mark (&text->cursor_mark);
+
+ find_cursor (text);
+ draw_cursor (text, FALSE);
+}
+
+static void
+gtk_text_move_backward_word (GtkText *text)
+{
+ undraw_cursor (text, FALSE);
+
+ while ((text->cursor_mark.index > 0) &&
+ !isalnum (GTK_TEXT_INDEX(text, text->cursor_mark.index)))
+ decrement_mark (&text->cursor_mark);
+
+ while ((text->cursor_mark.index > 0) &&
+ isalnum (GTK_TEXT_INDEX(text, text->cursor_mark.index)))
+ decrement_mark (&text->cursor_mark);
+
+ find_cursor (text);
+ draw_cursor (text, FALSE);
+}
+
+static void
+gtk_text_move_beginning_of_line (GtkText *text)
+{
+ undraw_cursor (text, FALSE);
+ text->cursor_mark = CACHE_DATA(text->current_line).start;
+ find_cursor (text);
+ draw_cursor (text, FALSE);
+}
+
+static void
+gtk_text_move_end_of_line (GtkText *text)
+{
+ undraw_cursor (text, FALSE);
+ text->cursor_mark = CACHE_DATA(text->current_line).end;
+ find_cursor (text);
+ draw_cursor (text, FALSE);
+}
+
+static void
+gtk_text_delete_forward_character (GtkText *text)
+{
+ GtkEditable *editable;
+ editable = GTK_EDITABLE (text);
+
+ if (editable->selection_start_pos != editable->selection_end_pos)
+ gtk_editable_delete_selection (editable);
+ else
+ {
+ gtk_text_forward_delete (text, 1);
+ gtk_editable_changed (editable);
+ }
+}
+
+static void
+gtk_text_delete_backward_character (GtkText *text)
+{
+ GtkEditable *editable;
+ editable = GTK_EDITABLE (text);
+
+ if (editable->selection_start_pos != editable->selection_end_pos)
+ gtk_editable_delete_selection (editable);
+ else
+ {
+ gtk_text_backward_delete (text, 1);
+ gtk_editable_changed (editable);
+ }
+}
+
+static void
+gtk_text_delete_forward_word (GtkText *text)
+{
+ guint old_pos;
+
+ GtkEditable *editable;
+ editable = GTK_EDITABLE (text);
+
+ if (editable->selection_start_pos != editable->selection_end_pos)
+ gtk_editable_delete_selection (editable);
+ else
+ {
+ old_pos = text->cursor_mark.index;
+ gtk_text_move_forward_word (text);
+ gtk_text_backward_delete (text, old_pos - text->cursor_mark.index);
+ gtk_editable_changed (editable);
+ }
+}
+
+static void
+gtk_text_delete_backward_word (GtkText *text)
+{
+ gint old_pos;
+
+ GtkEditable *editable;
+ editable = GTK_EDITABLE (text);
+
+ if (editable->selection_start_pos != editable->selection_end_pos)
+ gtk_editable_delete_selection (editable);
+ else
+ {
+ old_pos = text->point.index;
+ gtk_text_move_backward_word (text);
+ gtk_text_forward_delete (text, text->point.index - old_pos);
+ gtk_editable_changed (editable);
+ }
+}
+
+static void
+gtk_text_delete_line (GtkText *text)
+{
+ gtk_text_set_point (text, CACHE_DATA(text->current_line).start.index);
+ gtk_text_forward_delete (text,
+ CACHE_DATA(text->current_line).end.index -
+ CACHE_DATA(text->current_line).start.index + 1);
+
+ gtk_editable_changed (GTK_EDITABLE (text));
+}
+
+static void
+gtk_text_delete_to_line_end (GtkText *text)
+{
+ gtk_text_forward_delete (text,
+ MAX(CACHE_DATA(text->current_line).end.index -
+ text->point.index, 1));
+
+ gtk_editable_changed (GTK_EDITABLE (text));
+}
+
+static void
+gtk_text_select_word (GtkText *text)
+{
+ gint start_pos;
+ gint end_pos;
+
+ GtkEditable *editable;
+ editable = GTK_EDITABLE (text);
+
+ gtk_text_move_backward_word (text);
+ start_pos = text->cursor_mark.index;
+
+ gtk_text_move_forward_word (text);
+ end_pos = text->cursor_mark.index;
+
+ gtk_text_set_selection (editable, start_pos, end_pos);
+}
+
+static void
+gtk_text_select_line (GtkText *text)
+{
+ gtk_text_set_selection (GTK_EDITABLE (text),
+ CACHE_DATA(text->current_line).end.index,
+ CACHE_DATA(text->current_line).start.index);
+}
+
/**********************************************************************/
/* Scrolling */
/**********************************************************************/
@@ -2948,14 +3385,8 @@ scroll_down (GtkText* text, gint diff0)
cursor_min = drawn_cursor_min(text);
if (cursor_min < 0)
- {
- GdkEventButton button;
-
- button.x = text->cursor_pos_x;
- button.y = first_visible_line_height (text);
-
- mouse_click_1 (text, &button);
- }
+ find_mouse_cursor (text, text->cursor_pos_x,
+ first_visible_line_height (text));
}
if (height > real_diff)
@@ -3025,14 +3456,8 @@ scroll_up (GtkText* text, gint diff0)
gdk_window_get_size (text->text_area, NULL, &height);
if (cursor_max >= height)
- {
- GdkEventButton button;
-
- button.x = text->cursor_pos_x;
- button.y = last_visible_line_height(text);
-
- mouse_click_1 (text, &button);
- }
+ find_mouse_cursor (text, text->cursor_pos_x,
+ last_visible_line_height (text));
}
if (height > real_diff)
@@ -3184,6 +3609,32 @@ expand_scratch_buffer (GtkText* text, guint len)
}
}
+/* Returns a GC to draw a background for the text at a mark,
+ * or NULL, if the mark's background is NULL
+ *
+ * Side effect: modifies text->gc
+ */
+static GdkGC *
+mark_bg_gc (GtkText* text, const GtkPropertyMark *mark)
+{
+ GtkEditable *editable = GTK_EDITABLE(text);
+
+ if ((mark->index >= MIN(editable->selection_start_pos, editable->selection_end_pos) &&
+ mark->index < MAX(editable->selection_start_pos, editable->selection_end_pos)))
+ {
+ if (editable->has_selection)
+ return GTK_WIDGET(text)->style->bg_gc[GTK_STATE_SELECTED];
+ else
+ return GTK_WIDGET(text)->style->bg_gc[GTK_STATE_ACTIVE];
+ }
+ else if (MARK_CURRENT_BACK (mark))
+ {
+ gdk_gc_set_foreground (text->gc, MARK_CURRENT_BACK (mark));
+ return text->gc;
+ }
+ return NULL;
+}
+
static void
draw_line (GtkText* text,
gint pixel_start_height,
@@ -3194,6 +3645,12 @@ draw_line (GtkText* text,
gint len = 0;
guint running_offset = lp->tab_cont.pixel_offset;
guchar* buffer;
+ GdkGC *fg_gc, *bg_gc;
+
+ GtkEditable *editable = GTK_EDITABLE(text);
+
+ guint selection_start_pos = MIN (editable->selection_start_pos, editable->selection_end_pos);
+ guint selection_end_pos = MAX (editable->selection_start_pos, editable->selection_end_pos);
GtkPropertyMark mark = lp->start;
TabStopMark tab_mark = lp->tab_cont.tab_start;
@@ -3221,17 +3678,19 @@ draw_line (GtkText* text,
buffer = text->text + mark.index;
}
- if (running_offset > 0 && MARK_CURRENT_BACK (&mark))
+
+ if (running_offset > 0)
{
- gdk_gc_set_foreground (text->gc, MARK_CURRENT_BACK (&mark));
-
- gdk_draw_rectangle (text->text_area,
- text->gc,
- TRUE,
- 0,
- pixel_start_height,
- running_offset,
- LINE_HEIGHT (*lp));
+ bg_gc = mark_bg_gc (text, &mark);
+
+ if (bg_gc)
+ gdk_draw_rectangle (text->text_area,
+ bg_gc,
+ TRUE,
+ 0,
+ pixel_start_height,
+ running_offset,
+ LINE_HEIGHT (*lp));
}
for (; chars > 0; chars -= len, buffer += len, len = 0)
@@ -3247,6 +3706,11 @@ draw_line (GtkText* text,
if (next_tab)
len = MIN (len, next_tab - buffer);
+ if (mark.index < selection_start_pos)
+ len = MIN (len, selection_start_pos - mark.index);
+ else if (mark.index < selection_end_pos)
+ len = MIN (len, selection_end_pos - mark.index);
+
font = MARK_CURRENT_PROPERTY (&mark)->font->gdk_font;
if (font->type == GDK_FONT_FONT)
{
@@ -3257,24 +3721,33 @@ draw_line (GtkText* text,
}
else
pixel_width = gdk_text_width (font, (gchar*) buffer, len);
-
- if (MARK_CURRENT_BACK (&mark))
+
+ bg_gc = mark_bg_gc (text, &mark);
+ if (bg_gc)
+ gdk_draw_rectangle (text->text_area,
+ bg_gc,
+ TRUE,
+ running_offset,
+ pixel_start_height,
+ pixel_width,
+ LINE_HEIGHT(*lp));
+
+ if ((mark.index >= selection_start_pos) &&
+ (mark.index < selection_end_pos))
{
- gdk_gc_set_foreground (text->gc, MARK_CURRENT_BACK (&mark));
-
- gdk_draw_rectangle (text->text_area,
- text->gc,
- TRUE,
- running_offset,
- pixel_start_height,
- pixel_width,
- LINE_HEIGHT(*lp));
+ if (editable->has_selection)
+ fg_gc = GTK_WIDGET(text)->style->fg_gc[GTK_STATE_SELECTED];
+ else
+ fg_gc = GTK_WIDGET(text)->style->fg_gc[GTK_STATE_ACTIVE];
+ }
+ else
+ {
+ gdk_gc_set_foreground (text->gc, MARK_CURRENT_FORE (&mark));
+ fg_gc = text->gc;
}
-
- gdk_gc_set_foreground (text->gc, MARK_CURRENT_FORE (&mark));
gdk_draw_text (text->text_area, MARK_CURRENT_FONT (&mark),
- text->gc,
+ fg_gc,
running_offset,
pixel_height,
(gchar*) buffer,
@@ -3288,7 +3761,8 @@ draw_line (GtkText* text,
{
len = 1;
- if (MARK_CURRENT_BACK (&mark))
+ bg_gc = mark_bg_gc (text, &mark);
+ if (bg_gc)
{
gint pixels_remaining;
gint space_width;
@@ -3302,10 +3776,8 @@ draw_line (GtkText* text,
spaces_avail = pixels_remaining / space_width;
spaces_avail = MIN (spaces_avail, tab_mark.to_next_tab);
- gdk_gc_set_foreground (text->gc, MARK_CURRENT_BACK (&mark));
-
gdk_draw_rectangle (text->text_area,
- text->gc,
+ bg_gc,
TRUE,
running_offset,
pixel_start_height,
@@ -3352,7 +3824,7 @@ draw_line_wrap (GtkText* text, guint height /* baseline height */)
gdk_gc_set_fill (text->gc, GDK_STIPPLED);
- gdk_gc_set_foreground (text->gc, &text->widget.style->fg[GTK_STATE_NORMAL]);
+ gdk_gc_set_foreground (text->gc, &GTK_WIDGET (text)->style->text[GTK_STATE_NORMAL]);
gdk_gc_set_ts_origin (text->gc,
width + 1,
@@ -3379,7 +3851,8 @@ undraw_cursor (GtkText* text, gint absolute)
if (absolute)
text->cursor_drawn_level = 0;
- if (text->has_cursor && (text->cursor_drawn_level ++ == 0))
+ if (text->has_cursor && (text->cursor_drawn_level ++ == 0) &&
+ (GTK_EDITABLE(text)->selection_start_pos == GTK_EDITABLE(text)->selection_end_pos))
{
GdkFont* font;
@@ -3387,7 +3860,7 @@ undraw_cursor (GtkText* text, gint absolute)
font = MARK_CURRENT_FONT(&text->cursor_mark);
- if (text->widget.style->bg_pixmap[GTK_STATE_NORMAL])
+ if (GTK_WIDGET (text)->style->bg_pixmap[GTK_STATE_NORMAL])
{
GdkRectangle rect;
@@ -3403,7 +3876,7 @@ undraw_cursor (GtkText* text, gint absolute)
if (MARK_CURRENT_BACK (&text->cursor_mark))
gdk_gc_set_foreground (text->gc, MARK_CURRENT_BACK (&text->cursor_mark));
else
- gdk_gc_set_foreground (text->gc, &text->widget.style->bg[GTK_STATE_NORMAL]);
+ gdk_gc_set_foreground (text->gc, &GTK_WIDGET (text)->style->base[GTK_STATE_NORMAL]);
gdk_draw_line (text->text_area, text->gc, text->cursor_pos_x,
text->cursor_pos_y - text->cursor_char_offset, text->cursor_pos_x,
@@ -3469,7 +3942,8 @@ draw_cursor (GtkText* text, gint absolute)
if (absolute)
text->cursor_drawn_level = 1;
- if (text->has_cursor && (--text->cursor_drawn_level == 0))
+ if (text->has_cursor && (--text->cursor_drawn_level == 0) &&
+ (GTK_EDITABLE(text)->selection_start_pos == GTK_EDITABLE(text)->selection_end_pos))
{
GdkFont* font;
@@ -3477,7 +3951,7 @@ draw_cursor (GtkText* text, gint absolute)
font = MARK_CURRENT_FONT (&text->cursor_mark);
- gdk_gc_set_foreground (text->gc, &text->widget.style->fg[GTK_STATE_NORMAL]);
+ gdk_gc_set_foreground (text->gc, &GTK_WIDGET (text)->style->text[GTK_STATE_NORMAL]);
gdk_draw_line (text->text_area, text->gc, text->cursor_pos_x,
text->cursor_pos_y - text->cursor_char_offset,
@@ -3489,13 +3963,15 @@ draw_cursor (GtkText* text, gint absolute)
static void
clear_area (GtkText *text, GdkRectangle *area)
{
- if (text->widget.style->bg_pixmap[GTK_STATE_NORMAL])
+ GtkWidget *widget = GTK_WIDGET (text);
+
+ if (widget->style->bg_pixmap[GTK_STATE_NORMAL])
{
gint width, height;
gint x = area->x, y = area->y;
gint xorig, yorig;
- gdk_window_get_size (text->widget.style->bg_pixmap[GTK_STATE_NORMAL], &width, &height);
+ gdk_window_get_size (widget->style->bg_pixmap[GTK_STATE_NORMAL], &width, &height);
yorig = - text->first_onscreen_ver_pixel;
xorig = - text->first_onscreen_hor_pixel;
@@ -3512,7 +3988,7 @@ clear_area (GtkText *text, GdkRectangle *area)
gdk_draw_pixmap (text->text_area,
text->gc,
- text->widget.style->bg_pixmap[GTK_STATE_NORMAL],
+ widget->style->bg_pixmap[GTK_STATE_NORMAL],
xoff,
yoff,
x,
@@ -3555,7 +4031,7 @@ expose_text (GtkText* text, GdkRectangle *area, gboolean cursor)
draw_line_wrap (text, pixels + CACHE_DATA(cache).font_ascent);
}
- if (cursor && text->has_cursor && GTK_WIDGET_HAS_FOCUS (&text->widget))
+ if (cursor && text->has_cursor && GTK_WIDGET_HAS_FOCUS (text))
{
if (CACHE_DATA(cache).start.index <= text->cursor_mark.index &&
CACHE_DATA(cache).end.index >= text->cursor_mark.index)
@@ -3574,6 +4050,56 @@ expose_text (GtkText* text, GdkRectangle *area, gboolean cursor)
}
}
+static void
+gtk_text_update_text (GtkEditable *editable,
+ guint start_pos,
+ guint end_pos)
+{
+ GtkText *text = GTK_TEXT (editable);
+
+ GList *cache = text->line_start_cache;
+ gint pixels = - text->first_cut_pixels;
+ GdkRectangle area;
+ gint width;
+ gint height;
+
+ gdk_window_get_size (text->text_area, &width, &height);
+ area.x = 0;
+ area.y = -1;
+ area.width = width;
+ area.height = 0;
+
+ TDEBUG (("in expose span start=%d stop=%d\n", start_pos, end_pos));
+
+ for (; pixels < height; cache = cache->next)
+ {
+ if (CACHE_DATA(cache).start.index < end_pos)
+ {
+ if (CACHE_DATA(cache).end.index >= start_pos)
+ {
+ if (area.y < 0)
+ area.y = pixels;
+ area.height = pixels + LINE_HEIGHT(CACHE_DATA(cache)) - area.y;
+ }
+ }
+ else
+ break;
+
+ pixels += LINE_HEIGHT(CACHE_DATA(cache));
+
+ if (!cache->next)
+ {
+ fetch_lines_forward (text, 1);
+
+ if (!cache->next)
+ break;
+ }
+ }
+
+ if (area.y >= 0)
+ expose_text (text, &area, TRUE);
+}
+
static void
recompute_geometry (GtkText* text)
{
@@ -3600,99 +4126,43 @@ recompute_geometry (GtkText* text)
/* Selection */
/**********************************************************************/
-static gint
-gtk_text_selection_clear (GtkWidget *widget,
- GdkEventSelection *event)
+void
+gtk_text_set_selection (GtkEditable *editable,
+ guint start,
+ guint end)
{
-#if 0
- GtkEntry *entry;
+ GtkText *text = GTK_TEXT (editable);
- g_return_val_if_fail (widget != NULL, FALSE);
- g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE);
- g_return_val_if_fail (event != NULL, FALSE);
+ guint start1 = MIN(start,end);
+ guint end1 = MAX(start,end);
+ guint start2 = MIN(editable->selection_start_pos, editable->selection_end_pos);
+ guint end2 = MAX(editable->selection_start_pos, editable->selection_end_pos);
- entry = GTK_ENTRY (widget);
-
- if (entry->have_selection)
+ if (start2 < start1)
{
- entry->have_selection = FALSE;
- gtk_entry_queue_draw (entry);
- }
-#endif
- return FALSE;
-}
-
-static gint
-gtk_text_selection_request (GtkWidget *widget,
- GdkEventSelection *event)
-{
-#if 0
-
- GtkEntry *entry;
- gint selection_start_pos;
- gint selection_end_pos;
-
- g_return_val_if_fail (widget != NULL, FALSE);
- g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE);
- g_return_val_if_fail (event != NULL, FALSE);
-
- entry = GTK_ENTRY (widget);
- if (entry->selection_start_pos != entry->selection_end_pos)
- {
- selection_start_pos = MIN (entry->selection_start_pos, entry->selection_end_pos);
- selection_end_pos = MAX (entry->selection_start_pos, entry->selection_end_pos);
-
- gdk_selection_set (event->requestor, event->selection,
- event->property, event->time,
- (guchar*) &entry->text[selection_start_pos],
- selection_end_pos - selection_start_pos);
- }
-#endif
- return FALSE;
-}
-
-static gint
-gtk_text_selection_notify (GtkWidget *widget,
- GdkEventSelection *event)
-{
-#if 0
- GtkEntry *entry;
- gchar *data;
- gint tmp_pos;
- gint reselect;
-
- g_return_val_if_fail (widget != NULL, FALSE);
- g_return_val_if_fail (GTK_IS_ENTRY (widget), FALSE);
- g_return_val_if_fail (event != NULL, FALSE);
-
- entry = GTK_ENTRY (widget);
+ guint tmp;
- gdk_selection_get (widget->window, (guchar**) &data);
-
- reselect = FALSE;
- if (entry->selection_start_pos != entry->selection_end_pos)
- {
- reselect = TRUE;
- gtk_delete_selection (entry);
+ tmp = start1; start1 = start2; start2 = tmp;
+ tmp = end1; end1 = end2; end2 = tmp;
}
- tmp_pos = entry->current_pos;
- gtk_entry_insert_text (entry, data, strlen (data), &tmp_pos);
+ undraw_cursor (text, FALSE);
+ editable->selection_start_pos = start;
+ editable->selection_end_pos = end;
+ draw_cursor (text, FALSE);
- if (reselect)
- {
- reselect = entry->have_selection;
- gtk_select_region (entry, entry->current_pos, tmp_pos);
- entry->have_selection = reselect;
- }
+ /* Expose only what changed */
- entry->current_pos = tmp_pos;
+ if (start1 < start2)
+ gtk_text_update_text (editable, start1, MIN(end1, start2));
- gtk_entry_queue_draw (entry);
-#endif
- return FALSE;
+ if (end2 > end1)
+ gtk_text_update_text (editable, MAX(end1, start2), end2);
+ else if (end2 < end1)
+ gtk_text_update_text (editable, end2, end1);
}
+
/**********************************************************************/
/* Debug */
/**********************************************************************/
diff --git a/gtk/gtktext.h b/gtk/gtktext.h
index 7ae0cd12f..d10c63a20 100644
--- a/gtk/gtktext.h
+++ b/gtk/gtktext.h
@@ -21,7 +21,7 @@
#include <gdk/gdk.h>
#include <gtk/gtkadjustment.h>
-#include <gtk/gtkwidget.h>
+#include <gtk/gtkeditable.h>
#ifdef __cplusplus
@@ -38,8 +38,6 @@ typedef struct _GtkPropertyMark GtkPropertyMark;
typedef struct _GtkText GtkText;
typedef struct _GtkTextClass GtkTextClass;
-typedef void (*GtkTextFunction) (GtkText *text);
-
struct _GtkPropertyMark
{
/* Position in list. */
@@ -54,7 +52,7 @@ struct _GtkPropertyMark
struct _GtkText
{
- GtkWidget widget;
+ GtkEditable editable;
GdkWindow *text_area;
@@ -66,8 +64,6 @@ struct _GtkText
GdkPixmap* line_wrap_bitmap;
GdkPixmap* line_arrow_bitmap;
- GdkIC ic;
-
/* GAPPED TEXT SEGMENT */
/* The text, a single segment of text a'la emacs, with a gap
@@ -96,24 +92,17 @@ struct _GtkText
/* First visible horizontal pixel. */
guint first_onscreen_hor_pixel;
/* First visible vertical pixel. */
- guint first_onscreen_ver_pixel;
+ guint first_onscreen_ver_pixel;
/* FLAGS */
/* True iff the cursor has been placed yet. */
guint has_cursor : 1;
- /* True iff this buffer is editable. (Allowing a cursor to be placed). */
- guint is_editable : 1;
/* True iff this buffer is wrapping lines, otherwise it is using a
* horizontal scrollbar. */
guint line_wrap : 1;
/* Frozen, don't do updates. @@@ fixme */
guint freeze : 1;
- /* Whether a selection. */
- guint has_selection : 1;
- /* Whether the selection is in the clipboard. */
- guint own_selection : 1;
- /* Whether it has been realized yet. */
/* TEXT PROPERTIES */
@@ -155,20 +144,11 @@ struct _GtkText
GList *tab_stops;
gint default_tab_width;
- /* Key bindings */
-
- GtkTextFunction control_keys[26];
- GtkTextFunction alt_keys[26];
-
- /* Selection nonsense. */
-
- guint selection_start;
- guint selection_stop;
};
struct _GtkTextClass
{
- GtkWidgetClass parent_class;
+ GtkEditableClass parent_class;
};
@@ -197,9 +177,9 @@ gint gtk_text_backward_delete (GtkText *text,
gint gtk_text_forward_delete (GtkText *text,
guint nchars);
-gchar * gtk_text_get_chars (GtkText *text,
- guint index,
- guint nchars);
+void gtk_text_select_region (GtkText *entry,
+ guint start,
+ guint end);
#define GTK_TEXT_INDEX(t, index) \
((index) < (t)->gap_position ? (t)->text[index] : \