Commit 9205edae authored by Owen Taylor's avatar Owen Taylor Committed by Owen Taylor

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.
parent d491547e
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
......
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
......
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
......
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
......
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
......
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
......
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
......
......@@ -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. )
......@@ -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@
......
......@@ -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>
......
/* 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)