Make parent_class static.

Sun Nov  5 04:24:53 2000  Owen Taylor  <otaylor@redhat.com>

	* gtk/gtkcellrenderertextpixbuf.c: Make parent_class
	static.

Tue Sep 19 10:54:22 2000  Owen Taylor  <otaylor@redhat.com>

	* gtk/gtkimcontext*.[ch] gtk/gtkimmulticontext.[ch]
	gtk/gtktextlayout.[ch] gtk/gtktextview.c gtk/gtkentry.c:
	Add support for positioning the cursor within the preedit string.

Mon Sep 18 23:56:32 2000  Owen Taylor  <otaylor@redhat.com>

	* gtk/gtktextview.c: Check for bindings after passing
	events to im context filter.

Mon Sep 18 11:50:51 2000  Owen Taylor  <otaylor@redhat.com>

	* gtk/gtktextlayout.c (add_preedit_attrs): Handle
	empty attribute lists properly.

Sun Sep 17 10:08:16 2000  Owen Taylor  <otaylor@redhat.com>

	* gtk/queryimmodules.c (main): Return non-zero exit
	status if errors were encountered querying any
	modules.

Sat Sep 16 14:01:52 2000  Owen Taylor  <otaylor@redhat.com>

	* gtk/gtk.h: include gtkmodule.h gtkoldeditable.h,
	don't include gtkthemes.h.

	* gtk/testgtk.c gtk/testtext.c: Set environment variables
	to point

	* gtk/Makefile.am: Add new .c and .h files, build
	gtk-query-immodules and use it to create a gtk.immodules
	file for use of test programs.

	* gtk/gtkpreview.c: remove extra blank line.

Sat Sep 16 13:21:04 2000  Owen Taylor  <otaylor@redhat.com>

	* gtk/gtkimcontextsimple.c (gtk_im_context_simple_add_table):
	Add the ability to add extra tables beyond the default
	one, and also the ability to have compose sequences
	that are prefixes of other compose sequences.

	* gtk/gtkimcontextsimple.c: Export a preedit string which
	consists of possible candidates for keystrokes that have
	been entered but not yet committed.

	* gtk/gtkimcontext.[ch] gtk/immulticontext.[ch]
	gtk/gtkimcontextsimple.[ch]: add gtk_im_context_reset()

	* gtk/gtkmulticontext.[ch] (gtk_im_multicontext_append_menuitems):
	Add a function to add input-method switching menu items
	to a menu.

	* gtk/gtkimmulticontext.[ch]: Properly handly set_client_window
	when switching input methods.

	* gtk/gtkimcontextsimple.[ch]: Change the format of
	the compose table to allow compose tables of different
	lengths / sequence.

Sat Sep 16 13:05:48 2000  Owen Taylor  <otaylor@redhat.com>

	* gtk/gtkimmodule.[ch]: Support routines for loading
	GtkIMContext implementations dynamically at runtime.

	* gtk/queryimmodules.c: Program to query the available
	input modules and write the results into a file.

	* gtk/gtkrc.[ch] (gtk_rc_get_im_module_file): Add
	extra config options "im_module_file" (cache file for
	input method modules), and "im_module_path" - path
	to look for modules when generating cache file.

	This doesn't scale.

Sat Sep 16 13:09:06 2000  Owen Taylor  <otaylor@redhat.com>

	* gtk/gtkthemes.[ch] gtk/gtkmodule.[ch]: Move most of the
	generic	code from gtkthemes into a new abstraction
	GtkModule which has the logic for implementing
	a loadable module which implements a number of
	GObject types.

Sat Sep 16 13:07:13 2000  Owen Taylor  <otaylor@redhat.com>

        * gtk/gtkeditable.[ch]: Convert GtkEditable from
	a class into an interface

	* gtk/gtkoldeditable.[ch]: Move the old editable
	implementation into here, so legacy widgets can
	still rely on the implemenation. GtkOldEditable
	exports GtkEditable. Make selection handling
	code use new text conversion functions (and
	handle UTF-8 as a side-effect). Use GtkClipboard
	for CLIPBOARD.

	* gtk/gtktext.[ch] gtk/gtkcombo.c gtk/gtkspinbutton.c:
	Adopt to match above changes.

	* gtk/gtkentry.[ch]: Implement GtkEditable directly,
	avoid GtkOldEditable implementation. Restructure
        to reduce number of places that modify state directly.
	Move to GtkBindingSet. Display the preedit string.
	Queue recomputation of PangoLayout and scroll position
	to improve effiency of doing complex changes naively.
	Add a menu with cut/copy/paste and input method selection.

Thu Sep 14 22:11:05 2000  Owen Taylor  <otaylor@redhat.com>

	* gtk/gtktextlayout.[ch]: Add gtk_text_layout_set_preedit_string()
	to set preedit string and attributes; display preedit string by
	inserting string and attributes at cursor when creating the
	GtkTextLineDisplay.

	* gtk/gtktextlayout.c: Move all conversions between byte
	positions in PangoLayout and GtkTextIter into new functions
	line_display_iter_to_index/index_to_iter that properly
	handle the preedit string.

	* gtk/gtktextmark.[ch]: Restore gtk_text_mark_get_name, modify
	it to return const char * (eventually will end up
	as GCONST char *, most likely.)

	* gtk/gtktextview.[ch]: Handle the preedit string, call
	gtk_im_context_reset() as necessary, add a menu to switch
	input methods.

	* gtk/gtktextlayout.[ch]: Remove useless
	gtk_text_layout_get_log_attrs() function.
This commit is contained in:
Owen Taylor 2000-11-12 03:43:24 +00:00 committed by Owen Taylor
parent b9d3287313
commit dfba226908
36 changed files with 5628 additions and 3659 deletions

View File

@ -19,6 +19,7 @@ testtree
gtkcompat.h
testthreads
libgtk.la
gtkfeatures.h
gtkmarshal.h
gtktypebuiltins.h
gtkmarshal.c
@ -30,3 +31,5 @@ testdnd
stamp-gtktypebuiltins.h
stamp-gtkmarshal.h
stamp-gtk.defs
gtk-query-immodules-2.0
gtk.immodules

View File

@ -104,6 +104,7 @@ gtk_public_h_sources = @STRIP_BEGIN@ \
gtkiconfactory.h \
gtkimage.h \
gtkimcontext.h \
gtkimmodule.h \
gtkimmulticontext.h \
gtkinputdialog.h \
gtkinvisible.h \
@ -124,6 +125,7 @@ gtk_public_h_sources = @STRIP_BEGIN@ \
gtkmisc.h \
gtkmodelsimple.h \
gtknotebook.h \
gtkoldeditable.h \
gtkobject.h \
gtkoptionmenu.h \
gtkpacker.h \
@ -163,7 +165,6 @@ gtk_public_h_sources = @STRIP_BEGIN@ \
gtktexttagtable.h \
gtktextview.h \
gtktext.h \
gtkthemes.h \
gtktipsquery.h \
gtktogglebutton.h \
gtktoolbar.h \
@ -198,6 +199,7 @@ gtk_private_h_sources = @STRIP_BEGIN@ \
gtktextiterprivate.h \
gtktextmarkprivate.h \
gtktexttagprivate.h \
gtkthemes.h \
gtktreeprivate.h \
@STRIP_END@
# GTK+ C sources to build the library from
@ -257,6 +259,7 @@ gtk_c_sources = @STRIP_BEGIN@ \
gtkimcontext.c \
gtkimcontextsimple.c \
gtkimcontextsimple.h \
gtkimmodule.c \
gtkimmulticontext.c \
gtkinputdialog.c \
gtkintl.h \
@ -279,6 +282,7 @@ gtk_c_sources = @STRIP_BEGIN@ \
gtkmodelsimple.c \
gtknotebook.c \
gtkobject.c \
gtkoldeditable.c \
gtkoptionmenu.c \
gtkpacker.c \
gtkpaned.c \
@ -543,11 +547,9 @@ install-data-local:
uninstall-local:
rm -f $(DESTDIR)$(datadir)/themes/Default/gtk-2.0/gtkrc
#
# test programs, not to be installed
#
noinst_PROGRAMS = testgtk testcalendar testinput testselection testrgb testdnd testtext simple treestoretest testtextbuffer # testthreads
DEPS = @gtktargetlib@ $(top_builddir)/gdk-pixbuf/libgdk_pixbuf-1.3.la $(top_builddir)/gdk/@gdktargetlib@
DEPS = @gtktargetlib@ $(top_builddir)/gdk-pixbuf/libgdk_pixbuf-1.3.la $(top_builddir)/gdk/@gdktargetlib@
TEST_DEPS = $(DEPS) gtk.immodules
LDADDS = @STRIP_BEGIN@ \
@gtktargetlib@ \
$(top_builddir)/gdk-pixbuf/libgdk_pixbuf-1.3.la \
@ -561,25 +563,44 @@ LDADDS = @STRIP_BEGIN@ \
-lm \
@STRIP_END@
testgtk_DEPENDENCIES = $(DEPS)
testcalendar_DEPENDENCIES = $(DEPS)
testinput_DEPENDENCIES = $(DEPS)
testselection_DEPENDENCIES = $(DEPS)
testrgb_DEPENDENCIES = $(DEPS)
testtext_DEPENDENCIES = $(DEPS)
testtextbuffer_DEPENDENCIES = $(DEPS)
treestoretest_DEPENDENCIES = $(DEPS)
testdnd_DEPENDENCIES = $(DEPS)
simple_DEPENDENCIES = $(DEPS)
#testthreads_DEPENDENCIES = $(DEPS)
#
# Installed tools
#
bin_PROGRAMS = gtk-query-immodules-2.0
gtk_query_immodules_2_0_DEPENDENCIES = $(DEPS)
gtk_query_immodules_2_0_LDADD = $(LDADDS)
gtk_query_immodules_2_0_SOURCES = queryimmodules.c
gtk.immodules: gtk-query-immodules-2.0
./gtk-query-immodules-2.0 ../modules/input/.libs/*.so > gtk.immodules
#
# test programs, not to be installed
#
noinst_PROGRAMS = testgtk testcalendar testinput testselection testrgb testdnd testtext simple treestoretest testtextbuffer # testthreads
testcalendar_DEPENDENCIES = $(TEST_DEPS)
testgtk_DEPENDENCIES = $(TEST_DEPS)
testinput_DEPENDENCIES = $(TEST_DEPS)
testrgb_DEPENDENCIES = $(TEST_DEPS)
testselection_DEPENDENCIES = $(TEST_DEPS)
testtext_DEPENDENCIES = $(TEST_DEPS)
testtextbuffer_DEPENDENCIES = $(TEST_DEPS)
treestoretest_DEPENDENCIES = $(TEST_DEPS)
testdnd_DEPENDENCIES = $(TEST_DEPS)
simple_DEPENDENCIES = $(TEST_DEPS)
#testthreads_DEPENDENCIES = $(TEST_DEPS)
testcalendar_LDADD = $(LDADDS)
testgtk_LDADD = $(LDADDS)
testinput_LDADD = $(LDADDS)
testrgb_LDADD = $(LDADDS)
testselection_LDADD = $(LDADDS)
testtext_LDADD = $(LDADDS)
treestoretest_LDADD = $(LDADDS)
testtextbuffer_LDADD = $(LDADDS)
testrgb_LDADD = $(LDADDS)
treestoretest_LDADD = $(LDADDS)
testdnd_LDADD = $(LDADDS)
simple_LDADD = $(LDADDS)
#testthreads_LDADD = $(LDADDS)

View File

@ -104,6 +104,7 @@
#include <gtk/gtkmodelsimple.h>
#include <gtk/gtknotebook.h>
#include <gtk/gtkobject.h>
#include <gtk/gtkoldeditable.h>
#include <gtk/gtkoptionmenu.h>
#include <gtk/gtkpacker.h>
#include <gtk/gtkpaned.h>
@ -133,7 +134,6 @@
#include <gtk/gtktext.h>
#include <gtk/gtktextbuffer.h>
#include <gtk/gtktextview.h>
#include <gtk/gtkthemes.h>
#include <gtk/gtktipsquery.h>
#include <gtk/gtktogglebutton.h>
#include <gtk/gtktoolbar.h>

View File

@ -60,7 +60,7 @@ static void gtk_cell_renderer_text_pixbuf_render (GtkCellRenderer
guint flags);
GtkCellRendererTextClass *parent_class = NULL;
static GtkCellRendererTextClass *parent_class = NULL;
GtkType

View File

@ -132,6 +132,7 @@ gtk_combo_entry_key_press (GtkEntry * entry, GdkEventKey * event, GtkCombo * com
/* completion */
if ((event->keyval == GDK_Tab) && (event->state & GDK_MOD1_MASK))
{
GtkEditable *editable = GTK_EDITABLE (entry);
GCompletion * cmpl;
gchar* prefix;
gchar* nprefix = NULL;
@ -145,16 +146,16 @@ gtk_combo_entry_key_press (GtkEntry * entry, GdkEventKey * event, GtkCombo * com
cmpl = g_completion_new ((GCompletionFunc)gtk_combo_func);
g_completion_add_items (cmpl, GTK_LIST (combo->list)->children);
pos = GTK_EDITABLE (entry)->current_pos;
prefix = gtk_editable_get_chars (GTK_EDITABLE (entry), 0, pos);
pos = gtk_editable_get_position (editable);
prefix = gtk_editable_get_chars (editable, 0, pos);
g_completion_complete(cmpl, prefix, &nprefix);
if (nprefix && strlen (nprefix) > strlen (prefix))
{
gtk_editable_insert_text (GTK_EDITABLE (entry), nprefix + pos,
strlen (nprefix) - strlen (prefix), &pos);
GTK_EDITABLE (entry)->current_pos = pos;
gtk_editable_insert_text (editable, nprefix + pos,
strlen (nprefix) - strlen (prefix), &pos);
gtk_editable_set_position (editable, pos);
}
if (nprefix)

View File

@ -24,91 +24,11 @@
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
#include <ctype.h>
#include <string.h>
#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 {
CHANGED,
INSERT_TEXT,
DELETE_TEXT,
/* Binding actions */
ACTIVATE,
SET_EDITABLE,
MOVE_CURSOR,
MOVE_WORD,
MOVE_PAGE,
MOVE_TO_ROW,
MOVE_TO_COLUMN,
KILL_CHAR,
KILL_WORD,
KILL_LINE,
CUT_CLIPBOARD,
COPY_CLIPBOARD,
PASTE_CLIPBOARD,
LAST_SIGNAL
};
enum {
ARG_0,
ARG_TEXT_POSITION,
ARG_EDITABLE
};
/* values for selection info */
enum {
TARGET_STRING,
TARGET_TEXT,
TARGET_COMPOUND_TEXT
};
static void gtk_editable_class_init (GtkEditableClass *klass);
static void gtk_editable_init (GtkEditable *editable);
static void gtk_editable_set_arg (GtkObject *object,
GtkArg *arg,
guint arg_id);
static void gtk_editable_get_arg (GtkObject *object,
GtkArg *arg,
guint arg_id);
static void *gtk_editable_get_public_chars (GtkEditable *editable,
gint start,
gint end);
static gint gtk_editable_selection_clear (GtkWidget *widget,
GdkEventSelection *event);
static void gtk_editable_selection_get (GtkWidget *widget,
GtkSelectionData *selection_data,
guint info,
guint time);
static void gtk_editable_selection_received (GtkWidget *widget,
GtkSelectionData *selection_data,
guint time);
static void gtk_editable_set_selection (GtkEditable *editable,
gint start,
gint end);
static guint32 gtk_editable_get_event_time (GtkEditable *editable);
static void gtk_editable_real_cut_clipboard (GtkEditable *editable);
static void gtk_editable_real_copy_clipboard (GtkEditable *editable);
static void gtk_editable_real_paste_clipboard (GtkEditable *editable);
static void gtk_editable_real_set_editable (GtkEditable *editable,
gboolean is_editable);
static GtkWidgetClass *parent_class = NULL;
static guint editable_signals[LAST_SIGNAL] = { 0 };
static GdkAtom clipboard_atom = GDK_NONE;
GtkType
gtk_editable_get_type (void)
{
@ -116,331 +36,32 @@ gtk_editable_get_type (void)
if (!editable_type)
{
static const GtkTypeInfo editable_info =
static const GTypeInfo editable_info =
{
"GtkEditable",
sizeof (GtkEditable),
sizeof (GtkEditableClass),
(GtkClassInitFunc) gtk_editable_class_init,
(GtkObjectInitFunc) gtk_editable_init,
/* reserved_1 */ NULL,
/* reserved_2 */ NULL,
(GtkClassInitFunc) NULL,
sizeof (GtkEditableClass), /* class_size */
NULL, /* base_init */
NULL, /* base_finalize */
};
editable_type = gtk_type_unique (GTK_TYPE_WIDGET, &editable_info);
editable_type = g_type_register_static (G_TYPE_INTERFACE, "GtkEditable", &editable_info, 0);
}
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_TYPE_WIDGET);
editable_signals[CHANGED] =
gtk_signal_new ("changed",
GTK_RUN_LAST,
GTK_CLASS_TYPE (object_class),
GTK_SIGNAL_OFFSET (GtkEditableClass, changed),
gtk_marshal_VOID__VOID,
GTK_TYPE_NONE, 0);
editable_signals[INSERT_TEXT] =
gtk_signal_new ("insert_text",
GTK_RUN_LAST,
GTK_CLASS_TYPE (object_class),
GTK_SIGNAL_OFFSET (GtkEditableClass, insert_text),
gtk_marshal_VOID__POINTER_INT_POINTER,
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,
GTK_CLASS_TYPE (object_class),
GTK_SIGNAL_OFFSET (GtkEditableClass, delete_text),
gtk_marshal_VOID__INT_INT,
GTK_TYPE_NONE,
2,
GTK_TYPE_INT,
GTK_TYPE_INT);
editable_signals[ACTIVATE] =
gtk_signal_new ("activate",
GTK_RUN_LAST | GTK_RUN_ACTION,
GTK_CLASS_TYPE (object_class),
GTK_SIGNAL_OFFSET (GtkEditableClass, activate),
gtk_marshal_VOID__VOID,
GTK_TYPE_NONE, 0);
widget_class->activate_signal = editable_signals[ACTIVATE];
editable_signals[SET_EDITABLE] =
gtk_signal_new ("set-editable",
GTK_RUN_LAST | GTK_RUN_ACTION,
GTK_CLASS_TYPE (object_class),
GTK_SIGNAL_OFFSET (GtkEditableClass, set_editable),
gtk_marshal_VOID__BOOLEAN,
GTK_TYPE_NONE, 1,
GTK_TYPE_BOOL);
editable_signals[MOVE_CURSOR] =
gtk_signal_new ("move_cursor",
GTK_RUN_LAST | GTK_RUN_ACTION,
GTK_CLASS_TYPE (object_class),
GTK_SIGNAL_OFFSET (GtkEditableClass, move_cursor),
gtk_marshal_VOID__INT_INT,
GTK_TYPE_NONE, 2,
GTK_TYPE_INT,
GTK_TYPE_INT);
editable_signals[MOVE_WORD] =
gtk_signal_new ("move_word",
GTK_RUN_LAST | GTK_RUN_ACTION,
GTK_CLASS_TYPE (object_class),
GTK_SIGNAL_OFFSET (GtkEditableClass, move_word),
gtk_marshal_VOID__INT,
GTK_TYPE_NONE, 1,
GTK_TYPE_INT);
editable_signals[MOVE_PAGE] =
gtk_signal_new ("move_page",
GTK_RUN_LAST | GTK_RUN_ACTION,
GTK_CLASS_TYPE (object_class),
GTK_SIGNAL_OFFSET (GtkEditableClass, move_page),
gtk_marshal_VOID__INT_INT,
GTK_TYPE_NONE, 2,
GTK_TYPE_INT,
GTK_TYPE_INT);
editable_signals[MOVE_TO_ROW] =
gtk_signal_new ("move_to_row",
GTK_RUN_LAST | GTK_RUN_ACTION,
GTK_CLASS_TYPE (object_class),
GTK_SIGNAL_OFFSET (GtkEditableClass, move_to_row),
gtk_marshal_VOID__INT,
GTK_TYPE_NONE, 1,
GTK_TYPE_INT);
editable_signals[MOVE_TO_COLUMN] =
gtk_signal_new ("move_to_column",
GTK_RUN_LAST | GTK_RUN_ACTION,
GTK_CLASS_TYPE (object_class),
GTK_SIGNAL_OFFSET (GtkEditableClass, move_to_column),
gtk_marshal_VOID__INT,
GTK_TYPE_NONE, 1,
GTK_TYPE_INT);
editable_signals[KILL_CHAR] =
gtk_signal_new ("kill_char",
GTK_RUN_LAST | GTK_RUN_ACTION,
GTK_CLASS_TYPE (object_class),
GTK_SIGNAL_OFFSET (GtkEditableClass, kill_char),
gtk_marshal_VOID__INT,
GTK_TYPE_NONE, 1,
GTK_TYPE_INT);
editable_signals[KILL_WORD] =
gtk_signal_new ("kill_word",
GTK_RUN_LAST | GTK_RUN_ACTION,
GTK_CLASS_TYPE (object_class),
GTK_SIGNAL_OFFSET (GtkEditableClass, kill_word),
gtk_marshal_VOID__INT,
GTK_TYPE_NONE, 1,
GTK_TYPE_INT);
editable_signals[KILL_LINE] =
gtk_signal_new ("kill_line",
GTK_RUN_LAST | GTK_RUN_ACTION,
GTK_CLASS_TYPE (object_class),
GTK_SIGNAL_OFFSET (GtkEditableClass, kill_line),
gtk_marshal_VOID__INT,
GTK_TYPE_NONE, 1,
GTK_TYPE_INT);
editable_signals[CUT_CLIPBOARD] =
gtk_signal_new ("cut_clipboard",
GTK_RUN_LAST | GTK_RUN_ACTION,
GTK_CLASS_TYPE (object_class),
GTK_SIGNAL_OFFSET (GtkEditableClass, cut_clipboard),
gtk_marshal_VOID__VOID,
GTK_TYPE_NONE, 0);
editable_signals[COPY_CLIPBOARD] =
gtk_signal_new ("copy_clipboard",
GTK_RUN_LAST | GTK_RUN_ACTION,
GTK_CLASS_TYPE (object_class),
GTK_SIGNAL_OFFSET (GtkEditableClass, copy_clipboard),
gtk_marshal_VOID__VOID,
GTK_TYPE_NONE, 0);
editable_signals[PASTE_CLIPBOARD] =
gtk_signal_new ("paste_clipboard",
GTK_RUN_LAST | GTK_RUN_ACTION,
GTK_CLASS_TYPE (object_class),
GTK_SIGNAL_OFFSET (GtkEditableClass, paste_clipboard),
gtk_marshal_VOID__VOID,
GTK_TYPE_NONE, 0);
gtk_object_class_add_signals (object_class, editable_signals, LAST_SIGNAL);
gtk_object_add_arg_type ("GtkEditable::text_position", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_TEXT_POSITION);
gtk_object_add_arg_type ("GtkEditable::editable", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_EDITABLE);
object_class->set_arg = gtk_editable_set_arg;
object_class->get_arg = gtk_editable_get_arg;
widget_class->selection_clear_event = gtk_editable_selection_clear;
widget_class->selection_received = gtk_editable_selection_received;
widget_class->selection_get = gtk_editable_selection_get;
class->insert_text = NULL;
class->delete_text = NULL;
class->activate = NULL;
class->set_editable = gtk_editable_real_set_editable;
class->move_cursor = NULL;
class->move_word = NULL;
class->move_page = NULL;
class->move_to_row = NULL;
class->move_to_column = NULL;
class->kill_char = NULL;
class->kill_word = NULL;
class->kill_line = NULL;
class->cut_clipboard = gtk_editable_real_cut_clipboard;
class->copy_clipboard = gtk_editable_real_copy_clipboard;
class->paste_clipboard = gtk_editable_real_paste_clipboard;
class->update_text = NULL;
class->get_chars = NULL;
class->set_selection = NULL;
class->set_position = NULL;
}
static void
gtk_editable_set_arg (GtkObject *object,
GtkArg *arg,
guint arg_id)
{
GtkEditable *editable;
editable = GTK_EDITABLE (object);
switch (arg_id)
{
case ARG_TEXT_POSITION:
gtk_editable_set_position (editable, GTK_VALUE_INT (*arg));
break;
case ARG_EDITABLE:
gtk_editable_set_editable (editable, GTK_VALUE_BOOL (*arg));
break;
default:
break;
}
}
static void
gtk_editable_get_arg (GtkObject *object,
GtkArg *arg,
guint arg_id)
{
GtkEditable *editable;
editable = GTK_EDITABLE (object);
switch (arg_id)
{
case ARG_TEXT_POSITION:
GTK_VALUE_INT (*arg) = editable->current_pos;
break;
case ARG_EDITABLE:
GTK_VALUE_BOOL (*arg) = editable->editable;
break;
default:
arg->type = GTK_TYPE_INVALID;
break;
}
}
static void
gtk_editable_init (GtkEditable *editable)
{
static const GtkTargetEntry targets[] = {
{ "STRING", 0, TARGET_STRING },
{ "TEXT", 0, TARGET_TEXT },
{ "COMPOUND_TEXT", 0, TARGET_COMPOUND_TEXT }
};
static const gint n_targets = sizeof(targets) / sizeof(targets[0]);
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->visible = 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_targets (GTK_WIDGET (editable), GDK_SELECTION_PRIMARY,
targets, n_targets);
gtk_selection_add_targets (GTK_WIDGET (editable), clipboard_atom,
targets, n_targets);
}
void
gtk_editable_insert_text (GtkEditable *editable,
const gchar *new_text,
gint new_text_length,
gint *position)
{
GtkEditableClass *klass;
gchar buf[64];
gchar *text;
g_return_if_fail (editable != NULL);
g_return_if_fail (GTK_IS_EDITABLE (editable));
gtk_widget_ref (GTK_WIDGET (editable));
klass = GTK_EDITABLE_GET_CLASS (editable);
g_return_if_fail (position != NULL);
if (new_text_length < 0)
new_text_length = strlen (new_text);
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);
gtk_widget_unref (GTK_WIDGET (editable));
GTK_EDITABLE_GET_CLASS (editable)->insert_text (editable, new_text, new_text_length, position);
}
void
@ -448,360 +69,67 @@ gtk_editable_delete_text (GtkEditable *editable,
gint start_pos,
gint end_pos)
{
GtkEditableClass *klass;
g_return_if_fail (editable != NULL);
g_return_if_fail (GTK_IS_EDITABLE (editable));
gtk_widget_ref (GTK_WIDGET (editable));
klass = GTK_EDITABLE_GET_CLASS (editable);
gtk_signal_emit (GTK_OBJECT (editable), editable_signals[DELETE_TEXT], start_pos, end_pos);
gtk_signal_emit (GTK_OBJECT (editable), editable_signals[CHANGED]);
gtk_widget_unref (GTK_WIDGET (editable));
}
static void
gtk_editable_update_text (GtkEditable *editable,
gint start_pos,
gint end_pos)
{
GtkEditableClass *klass;
g_return_if_fail (editable != NULL);
g_return_if_fail (GTK_IS_EDITABLE (editable));
klass = GTK_EDITABLE_GET_CLASS (editable);
klass->update_text (editable, start_pos, end_pos);
GTK_EDITABLE_GET_CLASS (editable)->delete_text (editable, start_pos, end_pos);
}
gchar *
gtk_editable_get_chars (GtkEditable *editable,
gint start,
gint end)
gtk_editable_get_chars (GtkEditable *editable,
gint start,
gint end)
{
GtkEditableClass *klass;
g_return_val_if_fail (GTK_IS_EDITABLE (editable), FALSE);
g_return_val_if_fail (editable != NULL, NULL);
g_return_val_if_fail (GTK_IS_EDITABLE (editable), NULL);
klass = GTK_EDITABLE_GET_CLASS (editable);
return klass->get_chars (editable, start, end);
}
/*
* Like gtk_editable_get_chars, but if the editable is not
* visible, return asterisks
*/
static void *
gtk_editable_get_public_chars (GtkEditable *editable,
gint start,
gint end)
{
if (editable->visible)
return gtk_editable_get_chars (editable, start, end);
else
{
gint i;
gint nchars = end - start;
gchar *str;
if (nchars < 0)
nchars = -nchars;
str = g_new (gchar, nchars + 1);
for (i = 0; i<nchars; i++)
str[i] = '*';
str[i] = '\0';
return str;
}
}
static void
gtk_editable_set_selection (GtkEditable *editable,
gint start_pos,
gint end_pos)
{
GtkEditableClass *klass;
g_return_if_fail (editable != NULL);
g_return_if_fail (GTK_IS_EDITABLE (editable));
klass = GTK_EDITABLE_GET_CLASS (editable);
klass->set_selection (editable, start_pos, end_pos);
return GTK_EDITABLE_GET_CLASS (editable)->get_chars (editable, start, end);
}
void
gtk_editable_set_position (GtkEditable *editable,
gint position)
{
GtkEditableClass *klass;
g_return_if_fail (editable != NULL);
g_return_if_fail (GTK_IS_EDITABLE (editable));
klass = GTK_EDITABLE_GET_CLASS (editable);
klass->set_position (editable, position);
GTK_EDITABLE_GET_CLASS (editable)->set_position (editable, position);
}
gint
gtk_editable_get_position (GtkEditable *editable)
{
g_return_val_if_fail (editable != NULL, -1);
g_return_val_if_fail (GTK_IS_EDITABLE (editable), -1);
g_return_val_if_fail (GTK_IS_EDITABLE (editable), 0);
return editable->current_pos;
return GTK_EDITABLE_GET_CLASS (editable)->get_position (editable);
}
static gint
gtk_editable_selection_clear (GtkWidget *widget,
GdkEventSelection *event)
gboolean
gtk_editable_get_selection_bounds (GtkEditable *editable,
gint *start_pos,
gint *end_pos)
{
GtkEditable *editable;
gint tmp_start, tmp_end;
gboolean result;
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 */
if (!gtk_selection_clear (widget, event))
return FALSE;
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 TRUE;
}
g_return_val_if_fail (GTK_IS_EDITABLE (editable), FALSE);
static void
gtk_editable_selection_get (GtkWidget *widget,
GtkSelectionData *selection_data,
guint info,
guint time)
{
GtkEditable *editable;
gint selection_start_pos;
gint selection_end_pos;
result = GTK_EDITABLE_GET_CLASS (editable)->get_selection_bounds (editable, &tmp_start, &tmp_end);
gchar *str;
gint length;
if (start_pos)
*start_pos = MIN (tmp_start, tmp_end);
if (end_pos)
*end_pos = MAX (tmp_start, tmp_end);
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_public_chars(editable,
selection_start_pos,
selection_end_pos);
if (!str)
return; /* Refuse */
length = strlen (str);
}
else /* CLIPBOARD */
{
if (!editable->clipboard_text)
return; /* Refuse */
str = editable->clipboard_text;
length = strlen (editable->clipboard_text);
}
if (info == TARGET_STRING)
{
gtk_selection_data_set (selection_data,
GDK_SELECTION_TYPE_STRING,
8*sizeof(gchar), (guchar *)str, length);
}
else if ((info == TARGET_TEXT) || (info == TARGET_COMPOUND_TEXT))
{
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,
guint time)
{
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 == gdk_atom_intern ("COMPOUND_TEXT", FALSE)) ||
(selection_data->type == gdk_atom_intern ("TEXT", FALSE)))
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, 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, (gchar *)selection_data->data,
strlen ((gchar *)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);
return result;
}
void
gtk_editable_delete_selection (GtkEditable *editable)
{
guint start;
guint end;
gint start, end;
g_return_if_fail (editable != NULL);
g_return_if_fail (GTK_IS_EDITABLE (editable));
if (!editable->editable)
return;
start = editable->selection_start_pos;
end = editable->selection_end_pos;
editable->selection_start_pos = 0;
editable->selection_end_pos = 0;
if (start != end)
gtk_editable_delete_text (editable, MIN (start, end), MAX (start,end));
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 (editable != NULL);
g_return_if_fail (GTK_IS_EDITABLE (editable));
g_return_if_fail (GTK_WIDGET_REALIZED (editable));
editable->has_selection = FALSE;
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);
}
if (gtk_editable_get_selection_bounds (editable, &start, &end))
gtk_editable_delete_text (editable, start, end);
}
void
@ -809,57 +137,9 @@ gtk_editable_select_region (GtkEditable *editable,
gint start,
gint end)
{
g_return_if_fail (editable != NULL);
g_return_if_fail (GTK_IS_EDITABLE (editable));
if (GTK_WIDGET_REALIZED (editable))
gtk_editable_claim_selection (editable, start != end, GDK_CURRENT_TIME);
gtk_editable_set_selection (editable, start, end);
}
/* Get the timestamp of the current event. Actually, the only thing
* we really care about below is the key event
*/
static guint32
gtk_editable_get_event_time (GtkEditable *editable)
{
GdkEvent *event;
guint32 tm = GDK_CURRENT_TIME;
event = gtk_get_current_event();
if (event)
switch (event->type)
{
case GDK_MOTION_NOTIFY:
tm = event->motion.time; break;
case GDK_BUTTON_PRESS:
case GDK_2BUTTON_PRESS:
case GDK_3BUTTON_PRESS:
case GDK_BUTTON_RELEASE:
tm = event->button.time; break;
case GDK_KEY_PRESS:
case GDK_KEY_RELEASE:
tm = event->key.time; break;
case GDK_ENTER_NOTIFY:
case GDK_LEAVE_NOTIFY:
tm = event->crossing.time; break;
case GDK_PROPERTY_NOTIFY:
tm = event->property.time; break;
case GDK_SELECTION_CLEAR:
case GDK_SELECTION_REQUEST:
case GDK_SELECTION_NOTIFY:
tm = event->selection.time; break;
case GDK_PROXIMITY_IN:
case GDK_PROXIMITY_OUT:
tm = event->proximity.time; break;
default: /* use current time */
break;
}
gdk_event_free(event);
return tm;
GTK_EDITABLE_GET_CLASS (editable)->set_selection_bounds (editable, start, end);
}
void
@ -868,7 +148,7 @@ gtk_editable_cut_clipboard (GtkEditable *editable)
g_return_if_fail (editable != NULL);
g_return_if_fail (GTK_IS_EDITABLE (editable));
gtk_signal_emit (GTK_OBJECT (editable), editable_signals[CUT_CLIPBOARD]);
gtk_signal_emit_by_name (GTK_OBJECT (editable), "cut_clipboard");
}
void
@ -877,7 +157,7 @@ gtk_editable_copy_clipboard (GtkEditable *editable)
g_return_if_fail (editable != NULL);
g_return_if_fail (GTK_IS_EDITABLE (editable));
gtk_signal_emit (GTK_OBJECT (editable), editable_signals[COPY_CLIPBOARD]);
gtk_signal_emit_by_name (GTK_OBJECT (editable), "copy_clipboard");
}
void
@ -886,85 +166,16 @@ gtk_editable_paste_clipboard (GtkEditable *editable)
g_return_if_fail (editable != NULL);
g_return_if_fail (GTK_IS_EDITABLE (editable));
gtk_signal_emit (GTK_OBJECT (editable), editable_signals[PASTE_CLIPBOARD]);
gtk_signal_emit_by_name (GTK_OBJECT (editable), "paste_clipboard");
}
void
gtk_editable_set_editable (GtkEditable *editable,
gboolean is_editable)
{
g_return_if_fail (editable != NULL);
g_return_if_fail (GTK_IS_EDITABLE (editable));
gtk_signal_emit (GTK_OBJECT (editable), editable_signals[SET_EDITABLE], is_editable != FALSE);
}
static void
gtk_editable_real_set_editable (GtkEditable *editable,
gboolean is_editable)
{
g_return_if_fail (editable != NULL);
g_return_if_fail (GTK_IS_EDITABLE (editable));
editable->editable = is_editable != FALSE;
gtk_widget_queue_draw (GTK_WIDGET (editable));
}
static void
gtk_editable_real_cut_clipboard (GtkEditable *editable)
{
g_return_if_fail (editable != NULL);
g_return_if_fail (GTK_IS_EDITABLE (editable));
gtk_editable_real_copy_clipboard (editable);
gtk_editable_delete_selection (editable);
}
static void
gtk_editable_real_copy_clipboard (GtkEditable *editable)
{
guint32 time;
gint selection_start_pos;
gint selection_end_pos;
g_return_if_fail (editable != NULL);
g_return_if_fail (GTK_IS_EDITABLE (editable));
time = gtk_editable_get_event_time (editable);
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,
time))
editable->clipboard_text = gtk_editable_get_public_chars (editable,
selection_start_pos,
selection_end_pos);
}
}
static void
gtk_editable_real_paste_clipboard (GtkEditable *editable)
{
guint32 time;
g_return_if_fail (editable != NULL);
g_return_if_fail (GTK_IS_EDITABLE (editable));
time = gtk_editable_get_event_time (editable);
if (editable->editable)
gtk_selection_convert (GTK_WIDGET(editable),
clipboard_atom,
gdk_atom_intern ("COMPOUND_TEXT", FALSE), time);
}
void
gtk_editable_changed (GtkEditable *editable)
{
g_return_if_fail (editable != NULL);
g_return_if_fail (GTK_IS_EDITABLE (editable));
gtk_signal_emit (GTK_OBJECT (editable), editable_signals[CHANGED]);
gtk_object_set (GTK_OBJECT (editable),
"editable", is_editable != FALSE,
NULL);
}

View File

@ -31,132 +31,73 @@
#include <gdk/gdk.h>
#include <gtk/gtkwidget.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#define GTK_TYPE_EDITABLE (gtk_editable_get_type ())
#define GTK_EDITABLE(obj) (GTK_CHECK_CAST ((obj), GTK_TYPE_EDITABLE, GtkEditable))
#define GTK_EDITABLE_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_EDITABLE, GtkEditableClass))
#define GTK_IS_EDITABLE(obj) (GTK_CHECK_TYPE ((obj), GTK_TYPE_EDITABLE))
#define GTK_IS_EDITABLE_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_EDITABLE))
#define GTK_EDITABLE_GET_CLASS(obj) (GTK_CHECK_GET_CLASS ((obj), GTK_TYPE_EDITABLE, GtkEditableClass))
#define GTK_TYPE_EDITABLE (gtk_editable_get_type ())
#define GTK_EDITABLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_EDITABLE, GtkEditable))
#define GTK_EDITABLE_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST ((vtable), GTK_TYPE_EDITABLE, GtkEditableClass))
#define GTK_IS_EDITABLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_EDITABLE))
#define GTK_IS_EDITABLE_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE ((vtable), GTK_TYPE_EDITABLE))
#define GTK_EDITABLE_GET_CLASS(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), GTK_TYPE_EDITABLE, GtkEditableClass))
typedef struct _GtkEditable GtkEditable;
typedef struct _GtkEditable GtkEditable; /* Dummy typedef */
typedef struct _GtkEditableClass GtkEditableClass;
typedef void (*GtkTextFunction) (GtkEditable *editable, guint32 time);
struct _GtkEditable
{
GtkWidget widget;
/*< public >*/
guint current_pos;
guint selection_start_pos;
guint selection_end_pos;
guint has_selection : 1;
/*< private >*/
guint editable : 1;
guint visible : 1;
GdkIC *ic;
GdkICAttr *ic_attr;
gchar *clipboard_text;
};
struct _GtkEditableClass
{
GtkWidgetClass parent_class;
GTypeInterface base_iface;
/* Signals for notification/filtering of changes */
void (* changed) (GtkEditable *editable);
void (* insert_text) (GtkEditable *editable,
const gchar *text,
gint length,
gint *position);
void (* delete_text) (GtkEditable *editable,
gint start_pos,
gint end_pos);
/* Bindings actions */
void (* activate) (GtkEditable *editable);
void (* set_editable) (GtkEditable *editable,
gboolean is_editable);
void (* move_cursor) (GtkEditable *editable,
gint x,
gint y);
void (* move_word) (GtkEditable *editable,
gint n);
void (* move_page) (GtkEditable *editable,
gint x,
gint y);
void (* move_to_row) (GtkEditable *editable,
gint row);
void (* move_to_column) (GtkEditable *editable,
gint row);
void (* kill_char) (GtkEditable *editable,
gint direction);
void (* kill_word) (GtkEditable *editable,
gint direction);
void (* kill_line) (GtkEditable *editable,
gint direction);
void (* cut_clipboard) (GtkEditable *editable);
void (* copy_clipboard) (GtkEditable *editable);
void (* paste_clipboard) (GtkEditable *editable);
/* Virtual functions. get_chars is in paricular not a signal because
* it returns malloced memory. The others are not signals because
* they would not be particularly useful as such. (All changes to
* selection and position do not go through these functions)
*/
void (* update_text) (GtkEditable *editable,
gint start_pos,
gint end_pos);
gchar* (* get_chars) (GtkEditable *editable,
gint start_pos,
gint end_pos);
void (* set_selection)(GtkEditable *editable,
gint start_pos,
gint end_pos);
void (* set_position) (GtkEditable *editable,
gint position);
void (* insert_text) (GtkEditable *editable,
const gchar *text,
gint length,
gint *position);
void (* delete_text) (GtkEditable *editable,
gint start_pos,
gint end_pos);
gchar* (* get_chars) (GtkEditable *editable,
gint start_pos,
gint end_pos);
void (* set_selection_bounds) (GtkEditable *editable,
gint start_pos,
gint end_pos);
gboolean (* get_selection_bounds) (GtkEditable *editable,
gint *start_pos,
gint *end_pos);
void (* set_position) (GtkEditable *editable,
gint position);
gint (* get_position) (GtkEditable *editable);
};
GtkType gtk_editable_get_type (void) G_GNUC_CONST;
void gtk_editable_select_region (GtkEditable *editable,
gint start,
gint end);
void gtk_editable_insert_text (GtkEditable *editable,
const gchar *new_text,
gint new_text_length,
gint *position);
void gtk_editable_delete_text (GtkEditable *editable,
gint start_pos,
gint end_pos);
gchar* gtk_editable_get_chars (GtkEditable *editable,
gint start_pos,
gint end_pos);
void gtk_editable_cut_clipboard (GtkEditable *editable);
void gtk_editable_copy_clipboard (GtkEditable *editable);
void gtk_editable_paste_clipboard (GtkEditable *editable);
void gtk_editable_claim_selection (GtkEditable *editable,
gboolean claim,
guint32 time);
void gtk_editable_delete_selection (GtkEditable *editable);
void gtk_editable_changed (GtkEditable *editable);
void gtk_editable_set_position (GtkEditable *editable,
gint position);
gint gtk_editable_get_position (GtkEditable *editable);
void gtk_editable_set_editable (GtkEditable *editable,
gboolean is_editable);
GtkType gtk_editable_get_type (void) G_GNUC_CONST;
void gtk_editable_select_region (GtkEditable *editable,
gint start,
gint end);
gboolean gtk_editable_get_selection_bounds (GtkEditable *editable,
gint *start,
gint *end);
void gtk_editable_insert_text (GtkEditable *editable,
const gchar *new_text,
gint new_text_length,
gint *position);
void gtk_editable_delete_text (GtkEditable *editable,
gint start_pos,
gint end_pos);
gchar* gtk_editable_get_chars (GtkEditable *editable,
gint start_pos,
gint end_pos);
void gtk_editable_cut_clipboard (GtkEditable *editable);
void gtk_editable_copy_clipboard (GtkEditable *editable);
void gtk_editable_paste_clipboard (GtkEditable *editable);
void gtk_editable_delete_selection (GtkEditable *editable);
void gtk_editable_set_position (GtkEditable *editable,
gint position);
gint gtk_editable_get_position (GtkEditable *editable);
void gtk_editable_set_editable (GtkEditable *editable,
gboolean is_editable);
#ifdef __cplusplus
}

File diff suppressed because it is too large Load Diff

View File

@ -51,50 +51,79 @@ typedef struct _GtkEntryClass GtkEntryClass;
struct _GtkEntry
{
GtkEditable editable;
GtkWidget widget;
GdkWindow *text_area;
GdkPixmap *backing_pixmap;
GdkCursor *cursor;
gchar *text;
guint16 text_size; /* allocated size, in bytes */
guint editable : 1;
guint visible : 1;
guint overwrite_mode : 1;
guint16 text_length; /* length in use, in chars */
guint16 text_max_length;
/*< private >*/
GdkWindow *text_area;
GtkIMContext *im_context;
GtkWidget *popup_menu;
gint current_pos;
gint selection_bound;
PangoLayout *cached_layout;
guint cache_includes_preedit : 1;
guint need_im_reset : 1;
guint button;
guint32 timer;
guint16 n_bytes; /* length in use, in bytes */
PangoLayout *layout;
guint timer;
guint recompute_idle;
gint scroll_offset;
gint ascent; /* font ascent, in pango units */
gint descent; /* font descent, in pango units */
GtkIMContext *im_context;
guint16 text_size; /* allocated size, in bytes */
guint16 n_bytes; /* length in use, in bytes */
guint16 preedit_length; /* length of preedit string, in bytes */
guint16 preedit_cursor; /* offset of cursor within preedit string, in bytes */
};
struct _GtkEntryClass
{
GtkEditableClass parent_class;
GtkWidgetClass parent_class;
/* Notification of changes
*/
void (* changed) (GtkEntry *entry);
void (* insert_text) (GtkEntry *entry,
const gchar *text,
gint length,
gint *position);
void (* delete_text) (GtkEntry *entry,
gint start_pos,
gint end_pos);
/* Action signals
*/
void (* activate) (GtkEntry *entry);
void (* move) (GtkEntry *entry,
GtkMovementStep step,
gint count,
gboolean extend_selection);
void (* insert) (GtkEntry *entry,
const gchar *str);
void (* delete) (GtkEntry *entry,
GtkDeleteType type,
gint count);
void (* cut_clipboard) (GtkEntry *entry);
void (* copy_clipboard) (GtkEntry *entry);
void (* paste_clipboard) (GtkEntry *entry);
void (* toggle_overwrite) (GtkEntry *entry);
};
GtkType gtk_entry_get_type (void) G_GNUC_CONST;
GtkWidget* gtk_entry_new (void);
GtkWidget* gtk_entry_new_with_max_length (guint16 max);
void gtk_entry_set_text (GtkEntry *entry,
const gchar *text);
void gtk_entry_append_text (GtkEntry *entry,
const gchar *text);
void gtk_entry_prepend_text (GtkEntry *entry,
const gchar *text);
void gtk_entry_set_position (GtkEntry *entry,
gint position);
/* returns a reference to the text */
gchar* gtk_entry_get_text (GtkEntry *entry);
void gtk_entry_select_region (GtkEntry *entry,
gint start,
gint end);
void gtk_entry_set_visibility (GtkEntry *entry,
gboolean visible);
void gtk_entry_set_editable (GtkEntry *entry,
@ -103,6 +132,26 @@ void gtk_entry_set_editable (GtkEntry *entry,
void gtk_entry_set_max_length (GtkEntry *entry,
guint16 max);
/* Somewhat more convenient than the GtkEditable generic functions
*/
void gtk_entry_set_text (GtkEntry *entry,
const gchar *text);
/* returns a reference to the text */
gchar* gtk_entry_get_text (GtkEntry *entry);
/* Deprecated compatibility functions
*/
GtkWidget* gtk_entry_new_with_max_length (guint16 max);
void gtk_entry_append_text (GtkEntry *entry,
const gchar *text);
void gtk_entry_prepend_text (GtkEntry *entry,
const gchar *text);
void gtk_entry_set_position (GtkEntry *entry,
gint position);
void gtk_entry_select_region (GtkEntry *entry,
gint start,
gint end);
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@ -35,7 +35,8 @@ static void gtk_im_context_init (GtkIMContext *im_context);
static void gtk_im_context_real_get_preedit_string (GtkIMContext *context,
gchar **str,
PangoAttrList **attrs);
PangoAttrList **attrs,
gint *cursor_pos);
static gboolean gtk_im_context_real_filter_keypress (GtkIMContext *context,
GdkEventKey *event);
@ -118,12 +119,15 @@ gtk_im_context_init (GtkIMContext *im_context)
static void
gtk_im_context_real_get_preedit_string (GtkIMContext *context,
gchar **str,
PangoAttrList **attrs)
PangoAttrList **attrs,
gint *cursor_pos)
{
if (str)
*str = g_strdup ("");
if (attrs)
*attrs = pango_attr_list_new ();
if (cursor_pos)
*cursor_pos = 0;
}
static gboolean
@ -175,7 +179,8 @@ gtk_im_context_set_client_window (GtkIMContext *context,
void
gtk_im_context_get_preedit_string (GtkIMContext *context,
gchar **str,
PangoAttrList **attrs)
PangoAttrList **attrs,
gint *cursor_pos)
{
GtkIMContextClass *klass;
@ -183,7 +188,7 @@ gtk_im_context_get_preedit_string (GtkIMContext *context,
g_return_if_fail (GTK_IS_IM_CONTEXT (context));
klass = GTK_IM_CONTEXT_GET_CLASS (context);
klass->get_preedit_string (context, str, attrs);
klass->get_preedit_string (context, str, attrs, cursor_pos);
}
/**
@ -235,7 +240,7 @@ gtk_im_context_focus_in (GtkIMContext *context)
}
/**
* gtk_im_context_focus_in:
* gtk_im_context_focus_out:
* @context: a #GtkIMContext
*
* Notify the input method that the widget to which this
@ -256,4 +261,25 @@ gtk_im_context_focus_out (GtkIMContext *context)
klass->focus_out (context);
}
/**
* gtk_im_context_reset:
* @context: a #GtkIMContext
*
* Notify the input method that a change such as a change in cursor
* position has been made. This will typically cause the input
* method to clear the preedit state.
**/
void
gtk_im_context_reset (GtkIMContext *context)
{
GtkIMContextClass *klass;
g_return_if_fail (context != NULL);
g_return_if_fail (GTK_IS_IM_CONTEXT (context));
klass = GTK_IM_CONTEXT_GET_CLASS (context);
if (klass->reset)
klass->reset (context);
}

View File

@ -60,11 +60,13 @@ struct _GtkIMContextClass
GdkWindow *window);
void (*get_preedit_string) (GtkIMContext *context,
gchar **str,
PangoAttrList **attrs);
PangoAttrList **attrs,
gint *cursor_pos);
gboolean (*filter_keypress) (GtkIMContext *context,
GdkEventKey *event);
void (*focus_in) (GtkIMContext *context);
void (*focus_out) (GtkIMContext *context);
void (*reset) (GtkIMContext *context);
};
GtkType gtk_im_context_get_type (void) G_GNUC_CONST;
@ -72,12 +74,14 @@ GtkType gtk_im_context_get_type (void) G_GNUC_CONST;
void gtk_im_context_set_client_window (GtkIMContext *context,
GdkWindow *window);
void gtk_im_context_get_preedit_string (GtkIMContext *context,
char **str,
PangoAttrList **attrs);
gchar **str,
PangoAttrList **attrs,
gint *cursor_pos);
gboolean gtk_im_context_filter_keypress (GtkIMContext *context,
GdkEventKey *event);
void gtk_im_context_focus_in (GtkIMContext *context);
void gtk_im_context_focus_out (GtkIMContext *context);
void gtk_im_context_reset (GtkIMContext *context);
#ifdef __cplusplus
}

File diff suppressed because it is too large Load Diff

View File

@ -38,13 +38,17 @@ extern "C" {
typedef struct _GtkIMContextSimple GtkIMContextSimple;
typedef struct _GtkIMContextSimpleClass GtkIMContextSimpleClass;
#define GTK_MAX_COMPOSE_LEN 4
#define GTK_MAX_COMPOSE_LEN 7
struct _GtkIMContextSimple
{
GtkIMContext object;
GSList *tables;
guint compose_buffer[GTK_MAX_COMPOSE_LEN + 1];
gunichar tentative_match;
gint tentative_match_len;
};
struct _GtkIMContextSimpleClass
@ -53,8 +57,12 @@ struct _GtkIMContextSimpleClass
};
GtkType gtk_im_context_simple_get_type (void) G_GNUC_CONST;
GtkIMContext *gtk_im_context_simple_new (void);
GtkIMContext *gtk_im_context_simple_new (void);
void gtk_im_context_simple_add_table (GtkIMContextSimple *context_simple,
guint16 *data,
gint max_seq_len,
gint n_seqs);
#ifdef __cplusplus
}
#endif /* __cplusplus */

527
gtk/gtkimmodule.c Normal file
View File

@ -0,0 +1,527 @@
/* GTK - The GIMP Toolkit
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
*
* Themes added by The Rasterman <raster@redhat.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GTK+ Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gmodule.h>
#include <pango/pango-utils.h>
#include "gtkimmodule.h"
#include "gtkimcontextsimple.h"
#include "gtkrc.h"
#include "config.h"
#include "gtkintl.h"
#define SIMPLE_ID "gtk-im-context-simple"
typedef struct _GtkIMModule GtkIMModule;
typedef struct _GtkIMModuleClass GtkIMModuleClass;
#define GTK_TYPE_IM_MODULE (gtk_im_module_get_type ())
#define GTK_IM_MODULE(im_module) (G_TYPE_CHECK_INSTANCE_CAST ((im_module), GTK_TYPE_IM_MODULE, GtkIMModule))
#define GTK_IS_IM_MODULE(im_module) (G_TYPE_CHECK_INSTANCE_TYPE ((im_module), GTK_TYPE_IM_MODULE))
struct _GtkIMModule
{
GTypeModule parent_instance;
GModule *library;
void (*list) (const GtkIMContextInfo ***contexts,
guint *n_contexts);
void (*init) (GTypeModule *module);
void (*exit) (void);
GtkIMContext *(*create) (const gchar *context_id);
GtkIMContextInfo **contexts;
guint n_contexts;
gchar *path;
};
struct _GtkIMModuleClass
{
GTypeModuleClass parent_class;
};
GType gtk_im_module_get_type (void);
gint n_loaded_contexts = 0;
static GHashTable *contexts_hash = NULL;
static GSList *modules_list = NULL;
static GObjectClass *parent_class = NULL;
static gboolean
gtk_im_module_load (GTypeModule *module)
{
GtkIMModule *im_module = GTK_IM_MODULE (module);
im_module->library = g_module_open (im_module->path, 0);
if (!im_module->library)
{
g_warning (g_module_error());
return FALSE;
}
/* extract symbols from the lib */
if (!g_module_symbol (im_module->library, "im_module_init",
(gpointer *)&im_module->init) ||
!g_module_symbol (im_module->library, "im_module_exit",
(gpointer *)&im_module->exit) ||
!g_module_symbol (im_module->library, "im_module_list",
(gpointer *)&im_module->list) ||
!g_module_symbol (im_module->library, "im_module_create",
(gpointer *)&im_module->create))
{
g_warning (g_module_error());
g_module_close (im_module->library);
return FALSE;
}
/* call the theme's init (theme_init) function to let it */
/* setup anything it needs to set up. */
im_module->init (module);
return TRUE;
}
static void
gtk_im_module_unload (GTypeModule *module)
{
GtkIMModule *im_module = GTK_IM_MODULE (module);
im_module->exit();
g_module_close (im_module->library);
im_module->library = NULL;
im_module->init = NULL;
im_module->exit = NULL;
im_module->list = NULL;
im_module->create = NULL;
}
/* This only will ever be called if an error occurs during
* initialization
*/
static void
gtk_im_module_finalize (GObject *object)
{
GtkIMModule *module = GTK_IM_MODULE (object);
g_free (module->path);
parent_class->finalize (object);
}
static void
gtk_im_module_class_init (GtkIMModuleClass *class)
{
GTypeModuleClass *module_class = G_TYPE_MODULE_CLASS (class);
GObjectClass *gobject_class = G_OBJECT_CLASS (class);
parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (class));
module_class->load = gtk_im_module_load;
module_class->unload = gtk_im_module_unload;
gobject_class->finalize = gtk_im_module_finalize;
}
GType
gtk_im_module_get_type (void)
{
static GType im_module_type = 0;
if (!im_module_type)
{
static const GTypeInfo im_module_info = {
sizeof (GtkIMModuleClass),
NULL, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc) gtk_im_module_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (GtkIMModule),
0, /* n_preallocs */
NULL, /* instance_init */
};
im_module_type = g_type_register_static (G_TYPE_TYPE_MODULE, "GtkIMModule", &im_module_info, 0);
}
return im_module_type;
}
static void
free_info (GtkIMContextInfo *info)
{
g_free ((char *)info->context_id);
g_free ((char *)info->context_name);
g_free ((char *)info->domain);
g_free ((char *)info->domain_dirname);
g_free ((char *)info->default_locales);
g_free (info);
}
static void
add_module (GtkIMModule *module, GSList *infos)
{
GSList *tmp_list = infos;
gint i = 0;
gint n = g_slist_length (infos);
module->contexts = g_new (GtkIMContextInfo *, n);
while (tmp_list)
{
GtkIMContextInfo *info = tmp_list->data;
if (g_hash_table_lookup (contexts_hash, info->context_id))
{
free_info (info); /* Duplicate */
}
else
{
g_hash_table_insert (contexts_hash, (char *)info->context_id, module);
module->contexts[i++] = tmp_list->data;
n_loaded_contexts++;
}
tmp_list = tmp_list->next;
}
g_slist_free (infos);
module->n_contexts = i;
modules_list = g_slist_prepend (modules_list, module);
}
static void
gtk_im_module_init ()
{
GString *line_buf = g_string_new (NULL);
GString *tmp_buf = g_string_new (NULL);
const gchar *filename = gtk_rc_get_im_module_file();
FILE *file;
gboolean have_error = FALSE;
GtkIMModule *module = NULL;
GSList *infos = NULL;
contexts_hash = g_hash_table_new (g_str_hash, g_str_equal);
file = fopen (filename, "r");
if (!file)
{
g_warning ("Can not open Input Method module file '%s': %s",
filename, g_strerror (errno));
return;
}
while (!have_error && pango_read_line (file, line_buf))
{
const char *p;
p = line_buf->str;
if (!pango_skip_space (&p))
{
/* Blank line marking the end of a module
*/
if (module && *p != '#')
{
add_module (module, infos);
module = NULL;
infos = NULL;
}
continue;
}
if (!module)
{
/* Read a module location
*/
module = g_object_new (GTK_TYPE_IM_MODULE, NULL);
if (!pango_scan_string (&p, tmp_buf) ||
pango_skip_space (&p))
{
g_warning ("Error parsing context info in '%s'\n %s",
filename, line_buf->str);
have_error = TRUE;
}
module->path = g_strdup (tmp_buf->str);
g_type_module_set_name (G_TYPE_MODULE (module), module->path);
}
else
{
GtkIMContextInfo *info = g_new0 (GtkIMContextInfo, 1);
/* Read information about a context type
*/
if (!pango_scan_string (&p, tmp_buf))
goto context_error;
info->context_id = g_strdup (tmp_buf->str);
if (!pango_scan_string (&p, tmp_buf))
goto context_error;
info->context_name = g_strdup (tmp_buf->str);
if (!pango_scan_string (&p, tmp_buf))
goto context_error;
info->domain = g_strdup (tmp_buf->str);
if (!pango_scan_string (&p, tmp_buf))
goto context_error;
info->domain_dirname = g_strdup (tmp_buf->str);
if (!pango_scan_string (&p, tmp_buf))
goto context_error;
info->default_locales = g_strdup (tmp_buf->str);
if (pango_skip_space (&p))
goto context_error;
infos = g_slist_prepend (infos, info);
continue;
context_error:
g_warning ("Error parsing context info in '%s'\n %s",
filename, line_buf->str);
have_error = TRUE;
}
}
if (have_error)
{
GSList *tmp_list = infos;
while (tmp_list)
{
free_info (tmp_list->data);
tmp_list = tmp_list->next;
}
g_slist_free (infos);
g_object_unref (G_OBJECT (module));
}
else if (module)
add_module (module, infos);
fclose (file);
g_string_free (line_buf, TRUE);
g_string_free (tmp_buf, TRUE);
}
/**
* _gtk_im_module_list:
* @contexts: location to store an array of pointers to #GtkIMContextInfo
* this array should be freed with g_free() when you are finished.
* The structures it points are statically allocated and should
* not be modified or freed.
* @n_contexts: the length of the array stored in @contexts
*
* List all available types of input method context
**/
void
_gtk_im_module_list (const GtkIMContextInfo ***contexts,
guint *n_contexts)
{
int n = 0;
static const GtkIMContextInfo simple_context_info = {
SIMPLE_ID,
"Default",
"gtk+",
NULL,
""
};
if (!contexts_hash)
gtk_im_module_init ();
if (n_contexts)
*n_contexts = (n_loaded_contexts + 1);
if (contexts)
{
GSList *tmp_list;
int i;
*contexts = g_new (const GtkIMContextInfo *, n_loaded_contexts + 1);
(*contexts)[n++] = &simple_context_info;
tmp_list = modules_list;
while (tmp_list)
{
GtkIMModule *module = tmp_list->data;
for (i=0; i<module->n_contexts; i++)
(*contexts)[n++] = module->contexts[i];
tmp_list = tmp_list->next;
}
}
}
/**
* _gtk_im_module_create:
* @context_id: the context ID for the context type to create
*
* Create an IM context of a type specified by the string
* ID @context_id.
*
* Return value: a newly created input context of or @context_id, or
* if that could not be created, a newly created GtkIMContextSimple.
**/
GtkIMContext *
_gtk_im_module_create (const gchar *context_id)
{
GtkIMModule *im_module;
GtkIMContext *context = NULL;
if (!contexts_hash)
gtk_im_module_init ();
if (strcmp (context_id, SIMPLE_ID) != 0)
{
im_module = g_hash_table_lookup (contexts_hash, context_id);
if (!im_module)
{
g_warning ("Attempt to load unknown IM context type '%s'", context_id);
}
else
{
if (g_type_module_use (G_TYPE_MODULE (im_module)))
{
context = im_module->create (context_id);
g_type_module_unuse (G_TYPE_MODULE (im_module));
}
if (!context)
g_warning ("Loading IM context type '%s' failed", context_id);
}
}
if (!context)
return gtk_im_context_simple_new ();
else
return context;
}
/* Match @locale against @against.
*
* 'en_US' against 'en_US' => 3
* 'en_US' against 'en' => 2
* 'en', 'en_UK' against 'en_US' => 1
*/
static gint
match_locale (const gchar *locale,
const gchar *against,
gint against_len)
{
if (strcmp (locale, against) == 0)
return 3;
if (strncmp (locale, against, 2) == 0)
return (against_len == 2) ? 2 : 1;
return 0;
}
/**
* _gtk_im_module_get_default_context_id:
* @locale: a locale id in the form 'en_US'
*
* Return the context_id of the best IM context type
* for the given locale ID.
*
* Return value: the context ID (will never be %NULL)
* the value is newly allocated and must be freed
* with g_free().
**/
const gchar *
_gtk_im_module_get_default_context_id (const gchar *locale)
{
GSList *tmp_list;
const gchar *context_id = NULL;
gint best_goodness = 0;
gint i;
gchar *tmp_locale, *tmp;
gchar *envvar;
if (!contexts_hash)
gtk_im_module_init ();
envvar = g_getenv ("GTK_IM_MODULE");
if (envvar && g_hash_table_lookup (contexts_hash, envvar))
return g_strdup (envvar);
/* Strip the locale code down to the essentials
*/
tmp_locale = g_strdup (locale);
tmp = strchr (tmp_locale, '.');
if (tmp)
*tmp = '\0';
tmp = strchr (tmp_locale, '@');
if (tmp)
*tmp = '\0';
tmp_list = modules_list;
while (tmp_list)
{
GtkIMModule *module = tmp_list->data;
for (i=0; i<module->n_contexts; i++)
{
const gchar *p = module->contexts[i]->default_locales;
while (p)
{
const gchar *q = strchr (p, ':');
gint goodness = match_locale (tmp_locale, p, q ? q - p : strlen (p));
if (goodness > best_goodness)
{
context_id = module->contexts[i]->context_id;
best_goodness = goodness;
}
p = q ? q + 1 : NULL;
}
}
tmp_list = tmp_list->next;
}
g_free (tmp_locale);
return g_strdup (context_id ? context_id : SIMPLE_ID);
}

62
gtk/gtkimmodule.h Normal file
View File

@ -0,0 +1,62 @@
/* GTK - The GIMP Toolkit
* Copyright (C) 2000 Red Hat Software
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef __GTK_IM_MODULE_H__
#define __GTK_IM_MODULE_H__
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#include <gtk/gtkimcontext.h>
typedef struct _GtkIMContextInfo GtkIMContextInfo;
struct _GtkIMContextInfo
{
const gchar *context_id;
const gchar *context_name;
const gchar *domain;
const gchar *domain_dirname;
const gchar *default_locales;
};
/* Functions for use within GTK+
*/
void _gtk_im_module_list (const GtkIMContextInfo ***contexts,
guint *n_contexts);
GtkIMContext *_gtk_im_module_create (const gchar *context_id);
const gchar * _gtk_im_module_get_default_context_id (const gchar *lang);
/* The following entry points are exported by each input method module
*/
/*
void im_module_list (const GtkIMContextInfo ***contexts,
guint *n_contexts);
void im_module_init (GtkModule *module);
void im_module_exit (void);
GtkIMContext *im_module_create (const gchar *context_id);
*/
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif __GTK_IM_MODULE_H__

View File

@ -17,9 +17,18 @@
* Boston, MA 02111-1307, USA.
*/
#include <string.h>
#ifdef GDK_WINDOWING_X11
#include <X11/Xlocale.h> /* so we get the right setlocale */
#else
#include <locale.h>
#endif
#include "gtksignal.h"
#include "gtkimmulticontext.h"
#include "gtkimcontextsimple.h"
#include "gtkimmodule.h"
#include "gtkmenuitem.h"
static void gtk_im_multicontext_class_init (GtkIMMulticontextClass *class);
static void gtk_im_multicontext_init (GtkIMMulticontext *im_multicontext);
@ -32,11 +41,13 @@ static void gtk_im_multicontext_set_client_window (GtkIMContext
GdkWindow *window);
static void gtk_im_multicontext_get_preedit_string (GtkIMContext *context,
gchar **str,
PangoAttrList **attrs);
PangoAttrList **attrs,
gint *cursor_pos);
static gboolean gtk_im_multicontext_filter_keypress (GtkIMContext *context,
GdkEventKey *event);
static void gtk_im_multicontext_focus_in (GtkIMContext *context);
static void gtk_im_multicontext_focus_out (GtkIMContext *context);
static void gtk_im_multicontext_reset (GtkIMContext *context);
void gtk_im_multicontext_preedit_start_cb (GtkIMContext *slave,
GtkIMMulticontext *multicontext);
@ -50,6 +61,8 @@ void gtk_im_multicontext_commit_cb (GtkIMContext
static GtkIMContextClass *parent_class;
static const gchar *global_context_id = NULL;
GtkType
gtk_im_multicontext_get_type (void)
{
@ -88,6 +101,7 @@ gtk_im_multicontext_class_init (GtkIMMulticontextClass *class)
im_context_class->filter_keypress = gtk_im_multicontext_filter_keypress;
im_context_class->focus_in = gtk_im_multicontext_focus_in;
im_context_class->focus_out = gtk_im_multicontext_focus_out;
im_context_class->reset = gtk_im_multicontext_reset;
gobject_class->finalize = gtk_im_multicontext_finalize;
}
@ -141,6 +155,9 @@ gtk_im_multicontext_set_slave (GtkIMMulticontext *multicontext,
gtk_signal_connect (GTK_OBJECT (multicontext->slave), "commit",
GTK_SIGNAL_FUNC (gtk_im_multicontext_commit_cb),
multicontext);
if (multicontext->client_window)
gtk_im_context_set_client_window (slave, multicontext->client_window);
}
}
@ -148,7 +165,22 @@ static GtkIMContext *
gtk_im_multicontext_get_slave (GtkIMMulticontext *multicontext)
{
if (!multicontext->slave)
gtk_im_multicontext_set_slave (multicontext, gtk_im_context_simple_new ());
{
if (!global_context_id)
{
const char *locale;
#ifdef HAVE_LC_MESSAGES
locale = setlocale (LC_MESSAGES, NULL);
#else
locale = setlocale (LC_CTYPE, NULL);
#endif
global_context_id = _gtk_im_module_get_default_context_id (locale);
}
gtk_im_multicontext_set_slave (multicontext, _gtk_im_module_create (global_context_id));
multicontext->context_id = global_context_id;
}
return multicontext->slave;
}
@ -160,6 +192,8 @@ gtk_im_multicontext_set_client_window (GtkIMContext *context,
GtkIMMulticontext *multicontext = GTK_IM_MULTICONTEXT (context);
GtkIMContext *slave = gtk_im_multicontext_get_slave (multicontext);
multicontext->client_window = window;
if (slave)
gtk_im_context_set_client_window (slave, window);
}
@ -167,13 +201,14 @@ gtk_im_multicontext_set_client_window (GtkIMContext *context,
static void
gtk_im_multicontext_get_preedit_string (GtkIMContext *context,
gchar **str,
PangoAttrList **attrs)
PangoAttrList **attrs,
gint *cursor_pos)
{
GtkIMMulticontext *multicontext = GTK_IM_MULTICONTEXT (context);
GtkIMContext *slave = gtk_im_multicontext_get_slave (multicontext);
if (slave)
gtk_im_context_get_preedit_string (slave, str, attrs);
gtk_im_context_get_preedit_string (slave, str, attrs, cursor_pos);
else
{
if (str)
@ -200,7 +235,17 @@ static void
gtk_im_multicontext_focus_in (GtkIMContext *context)
{
GtkIMMulticontext *multicontext = GTK_IM_MULTICONTEXT (context);
GtkIMContext *slave = gtk_im_multicontext_get_slave (multicontext);
GtkIMContext *slave;
/* If the global context type is different from the context we were
* using before, get rid of the old slave and create a new one
* for the new global context type.
*/
if (!multicontext->context_id ||
strcmp (global_context_id, multicontext->context_id) != 0)
gtk_im_multicontext_set_slave (multicontext, NULL);
slave = gtk_im_multicontext_get_slave (multicontext);
if (slave)
gtk_im_context_focus_in (slave);
@ -216,6 +261,16 @@ gtk_im_multicontext_focus_out (GtkIMContext *context)
gtk_im_context_focus_out (slave);
}
static void
gtk_im_multicontext_reset (GtkIMContext *context)
{
GtkIMMulticontext *multicontext = GTK_IM_MULTICONTEXT (context);
GtkIMContext *slave = gtk_im_multicontext_get_slave (multicontext);
if (slave)
gtk_im_context_reset (slave);
}
void
gtk_im_multicontext_preedit_start_cb (GtkIMContext *slave,
GtkIMMulticontext *multicontext)
@ -245,3 +300,49 @@ gtk_im_multicontext_commit_cb (GtkIMContext *slave,
gtk_signal_emit_by_name (GTK_OBJECT (multicontext), "commit", str);;
}
static void
activate_cb (GtkWidget *menuitem,
GtkIMMulticontext *context)
{
const gchar *id = gtk_object_get_data (GTK_OBJECT (menuitem), "gtk-context-id");
gtk_im_context_reset (GTK_IM_CONTEXT (context));
global_context_id = id;
gtk_im_multicontext_set_slave (context, NULL);
}
/**
* gtk_im_multicontext_append_menuitems:
* @context: a #GtkIMMultiContext
* @menushell: a #GtkMenuShell
*
* Add menuitems for various available input methods to a menu;
* the menuitems, when selected, will switch the input method
* for the context and the global default input method.
**/
void
gtk_im_multicontext_append_menuitems (GtkIMMulticontext *context,
GtkMenuShell *menushell)
{
const GtkIMContextInfo **contexts;
gint n_contexts, i;
_gtk_im_module_list (&contexts, &n_contexts);
for (i=0; i < n_contexts; i++)
{
GtkWidget *menuitem;
menuitem = gtk_menu_item_new_with_label (contexts[i]->context_name);
gtk_object_set_data (GTK_OBJECT (menuitem), "gtk-context-id",
(char *)contexts[i]->context_id);
gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
activate_cb, context);
gtk_widget_show (menuitem);
gtk_menu_shell_append (menushell, menuitem);
}
}

View File

@ -21,6 +21,7 @@
#define __GTK_IM_MULTICONTEXT_H__
#include <gtk/gtkimcontext.h>
#include <gtk/gtkmenushell.h>
#ifdef __cplusplus
extern "C" {
@ -43,6 +44,10 @@ struct _GtkIMMulticontext
GtkIMContext object;
GtkIMContext *slave;
GdkWindow *client_window;
const gchar *context_id;
};
struct _GtkIMMulticontextClass
@ -53,6 +58,9 @@ struct _GtkIMMulticontextClass
GtkType gtk_im_multicontext_get_type (void) G_GNUC_CONST;
GtkIMContext *gtk_im_multicontext_new (void);
void gtk_im_multicontext_append_menuitems (GtkIMMulticontext *context,
GtkMenuShell *menushell);
#ifdef __cplusplus
}
#endif /* __cplusplus */

859
gtk/gtkoldeditable.c Normal file
View File

@ -0,0 +1,859 @@
/* 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 Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GTK+ Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
#include <ctype.h>
#include <string.h>
#include "gdk/gdkkeysyms.h"
#include "gdk/gdki18n.h"
#include "gtkclipboard.h"
#include "gtkoldeditable.h"
#include "gtkmain.h"
#include "gtkselection.h"
#include "gtksignal.h"
#define MIN_EDITABLE_WIDTH 150
#define DRAW_TIMEOUT 20
#define INNER_BORDER 2
enum {
CHANGED,
INSERT_TEXT,
DELETE_TEXT,
/* Binding actions */
ACTIVATE,
SET_EDITABLE,
MOVE_CURSOR,
MOVE_WORD,
MOVE_PAGE,
MOVE_TO_ROW,
MOVE_TO_COLUMN,
KILL_CHAR,
KILL_WORD,
KILL_LINE,
CUT_CLIPBOARD,
COPY_CLIPBOARD,
PASTE_CLIPBOARD,
LAST_SIGNAL
};
enum {
ARG_0,
ARG_TEXT_POSITION,
ARG_EDITABLE
};
/* values for selection info */
enum {
TARGET_STRING,
TARGET_TEXT,
TARGET_COMPOUND_TEXT
};
static void gtk_old_editable_class_init (GtkOldEditableClass *klass);
static void gtk_old_editable_editable_init (GtkEditableClass *iface);
static void gtk_old_editable_init (GtkOldEditable *editable);
static void gtk_old_editable_set_arg (GtkObject *object,
GtkArg *arg,
guint arg_id);
static void gtk_old_editable_get_arg (GtkObject *object,
GtkArg *arg,
guint arg_id);
static void *gtk_old_editable_get_public_chars (GtkOldEditable *old_editable,
gint start,
gint end);
static gint gtk_old_editable_selection_clear (GtkWidget *widget,
GdkEventSelection *event);
static void gtk_old_editable_selection_get (GtkWidget *widget,
GtkSelectionData *selection_data,
guint info,
guint time);
static void gtk_old_editable_selection_received (GtkWidget *widget,
GtkSelectionData *selection_data,
guint time);
static void gtk_old_editable_set_selection (GtkOldEditable *old_editable,
gint start,
gint end);
static void gtk_old_editable_real_set_editable (GtkOldEditable *old_editable,
gboolean is_editable);
static void gtk_old_editable_real_cut_clipboard (GtkOldEditable *old_editable);
static void gtk_old_editable_real_copy_clipboard (GtkOldEditable *old_editable);
static void gtk_old_editable_real_paste_clipboard (GtkOldEditable *old_editable);
static void gtk_old_editable_insert_text (GtkEditable *editable,
const gchar *new_text,
gint new_text_length,
gint *position);
static void gtk_old_editable_delete_text (GtkEditable *editable,
gint start_pos,
gint end_pos);
static gchar * gtk_old_editable_get_chars (GtkEditable *editable,
gint start,
gint end);
static void gtk_old_editable_set_selection_bounds (GtkEditable *editable,
gint start,
gint end);
static gboolean gtk_old_editable_get_selection_bounds (GtkEditable *editable,
gint *start,
gint *end);
static void gtk_old_editable_set_position (GtkEditable *editable,
gint position);
static gint gtk_old_editable_get_position (GtkEditable *editable);
static GtkWidgetClass *parent_class = NULL;
static guint editable_signals[LAST_SIGNAL] = { 0 };
GtkType
gtk_old_editable_get_type (void)
{
static GtkType old_editable_type = 0;
if (!old_editable_type)
{
static const GtkTypeInfo old_editable_info =
{
"GtkOldEditable",
sizeof (GtkOldEditable),
sizeof (GtkOldEditableClass),
(GtkClassInitFunc) gtk_old_editable_class_init,
(GtkObjectInitFunc) gtk_old_editable_init,
/* reserved_1 */ NULL,
/* reserved_2 */ NULL,
(GtkClassInitFunc) NULL,
};
static const GInterfaceInfo editable_info =
{
(GInterfaceInitFunc) gtk_old_editable_editable_init, /* interface_init */
NULL, /* interface_finalize */
NULL /* interface_data */
};
old_editable_type = gtk_type_unique (GTK_TYPE_WIDGET, &old_editable_info);
g_type_add_interface_static (old_editable_type,
GTK_TYPE_EDITABLE,
&editable_info);
}
return old_editable_type;
}
static void
gtk_old_editable_class_init (GtkOldEditableClass *class)
{
GtkObjectClass *object_class;
GtkWidgetClass *widget_class;
object_class = (GtkObjectClass*) class;
widget_class = (GtkWidgetClass*) class;
parent_class = gtk_type_class (GTK_TYPE_WIDGET);
editable_signals[CHANGED] =
gtk_signal_new ("changed",
GTK_RUN_LAST,
GTK_CLASS_TYPE (object_class),
GTK_SIGNAL_OFFSET (GtkOldEditableClass, changed),
gtk_marshal_NONE__NONE,
GTK_TYPE_NONE, 0);
editable_signals[INSERT_TEXT] =
gtk_signal_new ("insert_text",
GTK_RUN_LAST,
GTK_CLASS_TYPE (object_class),
GTK_SIGNAL_OFFSET (GtkOldEditableClass, insert_text),
gtk_marshal_NONE__POINTER_INT_POINTER,
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,
GTK_CLASS_TYPE (object_class),
GTK_SIGNAL_OFFSET (GtkOldEditableClass, delete_text),
gtk_marshal_NONE__INT_INT,
GTK_TYPE_NONE,
2,
GTK_TYPE_INT,
GTK_TYPE_INT);
editable_signals[ACTIVATE] =
gtk_signal_new ("activate",
GTK_RUN_LAST | GTK_RUN_ACTION,
GTK_CLASS_TYPE (object_class),
GTK_SIGNAL_OFFSET (GtkOldEditableClass, activate),
gtk_marshal_NONE__NONE,
GTK_TYPE_NONE, 0);
widget_class->activate_signal = editable_signals[ACTIVATE];
editable_signals[SET_EDITABLE] =
gtk_signal_new ("set-editable",
GTK_RUN_LAST | GTK_RUN_ACTION,
GTK_CLASS_TYPE (object_class),
GTK_SIGNAL_OFFSET (GtkOldEditableClass, set_editable),
gtk_marshal_NONE__BOOL,
GTK_TYPE_NONE, 1,
GTK_TYPE_BOOL);
editable_signals[MOVE_CURSOR] =
gtk_signal_new ("move_cursor",
GTK_RUN_LAST | GTK_RUN_ACTION,
GTK_CLASS_TYPE (object_class),
GTK_SIGNAL_OFFSET (GtkOldEditableClass, move_cursor),
gtk_marshal_NONE__INT_INT,
GTK_TYPE_NONE, 2,
GTK_TYPE_INT,
GTK_TYPE_INT);
editable_signals[MOVE_WORD] =
gtk_signal_new ("move_word",
GTK_RUN_LAST | GTK_RUN_ACTION,
GTK_CLASS_TYPE (object_class),
GTK_SIGNAL_OFFSET (GtkOldEditableClass, move_word),
gtk_marshal_NONE__INT,
GTK_TYPE_NONE, 1,
GTK_TYPE_INT);
editable_signals[MOVE_PAGE] =
gtk_signal_new ("move_page",
GTK_RUN_LAST | GTK_RUN_ACTION,
GTK_CLASS_TYPE (object_class),
GTK_SIGNAL_OFFSET (GtkOldEditableClass, move_page),
gtk_marshal_NONE__INT_INT,
GTK_TYPE_NONE, 2,
GTK_TYPE_INT,
GTK_TYPE_INT);
editable_signals[MOVE_TO_ROW] =
gtk_signal_new ("move_to_row",
GTK_RUN_LAST | GTK_RUN_ACTION,
GTK_CLASS_TYPE (object_class),
GTK_SIGNAL_OFFSET (GtkOldEditableClass, move_to_row),
gtk_marshal_NONE__INT,
GTK_TYPE_NONE, 1,
GTK_TYPE_INT);
editable_signals[MOVE_TO_COLUMN] =
gtk_signal_new ("move_to_column",
GTK_RUN_LAST | GTK_RUN_ACTION,
GTK_CLASS_TYPE (object_class),
GTK_SIGNAL_OFFSET (GtkOldEditableClass, move_to_column),
gtk_marshal_NONE__INT,
GTK_TYPE_NONE, 1,
GTK_TYPE_INT);
editable_signals[KILL_CHAR] =
gtk_signal_new ("kill_char",
GTK_RUN_LAST | GTK_RUN_ACTION,
GTK_CLASS_TYPE (object_class),
GTK_SIGNAL_OFFSET (GtkOldEditableClass, kill_char),
gtk_marshal_NONE__INT,
GTK_TYPE_NONE, 1,
GTK_TYPE_INT);
editable_signals[KILL_WORD] =
gtk_signal_new ("kill_word",
GTK_RUN_LAST | GTK_RUN_ACTION,
GTK_CLASS_TYPE (object_class),
GTK_SIGNAL_OFFSET (GtkOldEditableClass, kill_word),
gtk_marshal_NONE__INT,
GTK_TYPE_NONE, 1,
GTK_TYPE_INT);
editable_signals[KILL_LINE] =
gtk_signal_new ("kill_line",
GTK_RUN_LAST | GTK_RUN_ACTION,
GTK_CLASS_TYPE (object_class),
GTK_SIGNAL_OFFSET (GtkOldEditableClass, kill_line),
gtk_marshal_NONE__INT,
GTK_TYPE_NONE, 1,
GTK_TYPE_INT);
editable_signals[CUT_CLIPBOARD] =
gtk_signal_new ("cut_clipboard",
GTK_RUN_LAST | GTK_RUN_ACTION,
GTK_CLASS_TYPE (object_class),
GTK_SIGNAL_OFFSET (GtkOldEditableClass, cut_clipboard),
gtk_marshal_NONE__NONE,
GTK_TYPE_NONE, 0);
editable_signals[COPY_CLIPBOARD] =
gtk_signal_new ("copy_clipboard",
GTK_RUN_LAST | GTK_RUN_ACTION,
GTK_CLASS_TYPE (object_class),
GTK_SIGNAL_OFFSET (GtkOldEditableClass, copy_clipboard),
gtk_marshal_NONE__NONE,
GTK_TYPE_NONE, 0);
editable_signals[PASTE_CLIPBOARD] =
gtk_signal_new ("paste_clipboard",
GTK_RUN_LAST | GTK_RUN_ACTION,
GTK_CLASS_TYPE (object_class),
GTK_SIGNAL_OFFSET (GtkOldEditableClass, paste_clipboard),
gtk_marshal_NONE__NONE,
GTK_TYPE_NONE, 0);
gtk_object_class_add_signals (object_class, editable_signals, LAST_SIGNAL);
gtk_object_add_arg_type ("GtkOldEditable::text_position", GTK_TYPE_INT, GTK_ARG_READWRITE, ARG_TEXT_POSITION);
gtk_object_add_arg_type ("GtkOldEditable::editable", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_EDITABLE);
object_class->set_arg = gtk_old_editable_set_arg;
object_class->get_arg = gtk_old_editable_get_arg;
widget_class->selection_clear_event = gtk_old_editable_selection_clear;
widget_class->selection_received = gtk_old_editable_selection_received;
widget_class->selection_get = gtk_old_editable_selection_get;
class->insert_text = NULL;
class->delete_text = NULL;
class->activate = NULL;
class->set_editable = gtk_old_editable_real_set_editable;
class->move_cursor = NULL;
class->move_word = NULL;
class->move_page = NULL;
class->move_to_row = NULL;
class->move_to_column = NULL;
class->kill_char = NULL;
class->kill_word = NULL;
class->kill_line = NULL;
class->cut_clipboard = gtk_old_editable_real_cut_clipboard;
class->copy_clipboard = gtk_old_editable_real_copy_clipboard;
class->paste_clipboard = gtk_old_editable_real_paste_clipboard;
class->update_text = NULL;
class->get_chars = NULL;
class->set_selection = NULL;
class->set_position = NULL;
}
static void
gtk_old_editable_editable_init (GtkEditableClass *iface)
{
iface->insert_text = gtk_old_editable_insert_text;
iface->delete_text = gtk_old_editable_delete_text;
iface->get_chars = gtk_old_editable_get_chars;
iface->set_selection_bounds = gtk_old_editable_set_selection_bounds;
iface->get_selection_bounds = gtk_old_editable_get_selection_bounds;
iface->set_position = gtk_old_editable_set_position;
iface->get_position = gtk_old_editable_get_position;
}
static void
gtk_old_editable_set_arg (GtkObject *object,
GtkArg *arg,
guint arg_id)
{
GtkEditable *editable = GTK_EDITABLE (object);
switch (arg_id)
{
case ARG_TEXT_POSITION:
gtk_editable_set_position (editable, GTK_VALUE_INT (*arg));
break;
case ARG_EDITABLE:
gtk_signal_emit (object, editable_signals[SET_EDITABLE],
GTK_VALUE_BOOL (*arg) != FALSE);
break;
default:
break;
}
}
static void
gtk_old_editable_get_arg (GtkObject *object,
GtkArg *arg,
guint arg_id)
{
GtkOldEditable *old_editable;
old_editable = GTK_OLD_EDITABLE (object);
switch (arg_id)
{
case ARG_TEXT_POSITION:
GTK_VALUE_INT (*arg) = old_editable->current_pos;
break;
case ARG_EDITABLE:
GTK_VALUE_BOOL (*arg) = old_editable->editable;
break;
default:
arg->type = GTK_TYPE_INVALID;
break;
}
}
static void
gtk_old_editable_init (GtkOldEditable *old_editable)
{
static const GtkTargetEntry targets[] = {
{ "UTF8_STRING", 0, 0 },
{ "STRING", 0, 0 },
{ "TEXT", 0, 0 },
{ "COMPOUND_TEXT", 0, 0 }
};
GTK_WIDGET_SET_FLAGS (old_editable, GTK_CAN_FOCUS);
old_editable->selection_start_pos = 0;
old_editable->selection_end_pos = 0;
old_editable->has_selection = FALSE;
old_editable->editable = 1;
old_editable->visible = 1;
old_editable->clipboard_text = NULL;
#ifdef USE_XIM
old_editable->ic = NULL;
#endif
gtk_selection_add_targets (GTK_WIDGET (old_editable), GDK_SELECTION_PRIMARY,
targets, G_N_ELEMENTS (targets));
}
static void
gtk_old_editable_insert_text (GtkEditable *editable,
const gchar *new_text,
gint new_text_length,
gint *position)
{
gchar buf[64];
gchar *text;
gtk_widget_ref (GTK_WIDGET (editable));
if (new_text_length <= 63)
text = buf;
else
text = g_new (gchar, new_text_length + 1);
text[new_text_length] = '\0';
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 > 63)
g_free (text);
gtk_widget_unref (GTK_WIDGET (editable));
}
static void
gtk_old_editable_delete_text (GtkEditable *editable,
gint start_pos,
gint end_pos)
{
GtkOldEditable *old_editable = GTK_OLD_EDITABLE (editable);
gtk_widget_ref (GTK_WIDGET (old_editable));
gtk_signal_emit (GTK_OBJECT (old_editable), editable_signals[DELETE_TEXT], start_pos, end_pos);
gtk_signal_emit (GTK_OBJECT (old_editable), editable_signals[CHANGED]);
if (old_editable->selection_start_pos == old_editable->selection_end_pos &&
old_editable->has_selection)
gtk_old_editable_claim_selection (old_editable, FALSE, GDK_CURRENT_TIME);
gtk_widget_unref (GTK_WIDGET (old_editable));
}
static void
gtk_old_editable_update_text (GtkOldEditable *old_editable,
gint start_pos,
gint end_pos)
{
GtkOldEditableClass *klass = GTK_OLD_EDITABLE_GET_CLASS (old_editable);
klass->update_text (GTK_OLD_EDITABLE (old_editable), start_pos, end_pos);
}
static gchar *
gtk_old_editable_get_chars (GtkEditable *editable,
gint start,
gint end)
{
GtkOldEditableClass *klass = GTK_OLD_EDITABLE_GET_CLASS (editable);
return klass->get_chars (GTK_OLD_EDITABLE (editable), start, end);
}
/*
* Like gtk_editable_get_chars, but if the editable is not
* visible, return asterisks; also convert result to UTF-8.
*/
static void *
gtk_old_editable_get_public_chars (GtkOldEditable *old_editable,
gint start,
gint end)
{
gchar *str = NULL;
gchar *charset;
gboolean need_conversion = !g_get_charset (&charset);
if (old_editable->visible)
{
GError *error;
gchar *tmp = gtk_editable_get_chars (GTK_EDITABLE (old_editable), start, end);
if (need_conversion)
{
str = g_convert (tmp, -1,
"UTF-8", charset,
NULL, NULL, &error);
if (!str)
{
g_warning ("Cannot convert text from charset to UTF-8 %s: %s", charset, error->message);
g_error_free (error);
}
g_free (tmp);
}
else
str = tmp;
}
else
{
gint i;
gint nchars = end - start;
if (nchars < 0)
nchars = -nchars;
str = g_new (gchar, nchars + 1);
for (i = 0; i<nchars; i++)
str[i] = '*';
str[i] = '\0';
}
return str;
}
static void
gtk_old_editable_set_selection (GtkOldEditable *old_editable,
gint start_pos,
gint end_pos)
{
GtkOldEditableClass *klass = GTK_OLD_EDITABLE_GET_CLASS (old_editable);
klass->set_selection (old_editable, start_pos, end_pos);
}
static void
gtk_old_editable_set_position (GtkEditable *editable,
gint position)
{
GtkOldEditableClass *klass = GTK_OLD_EDITABLE_GET_CLASS (editable);
klass->set_position (GTK_OLD_EDITABLE (editable), position);
}
static gint
gtk_old_editable_get_position (GtkEditable *editable)
{
return GTK_OLD_EDITABLE (editable)->current_pos;
}
static gint
gtk_old_editable_selection_clear (GtkWidget *widget,
GdkEventSelection *event)
{
GtkOldEditable *old_editable = GTK_OLD_EDITABLE (widget);
/* Let the selection handling code know that the selection
* has been changed, since we've overriden the default handler */
if (!gtk_selection_clear (widget, event))
return FALSE;
if (old_editable->has_selection)
{
old_editable->has_selection = FALSE;
gtk_old_editable_update_text (old_editable, old_editable->selection_start_pos,
old_editable->selection_end_pos);
}
return TRUE;
}
static void
gtk_old_editable_selection_get (GtkWidget *widget,
GtkSelectionData *selection_data,
guint info,
guint time)
{
GtkOldEditable *old_editable = GTK_OLD_EDITABLE (widget);
gint selection_start_pos;
gint selection_end_pos;
gchar *str;
selection_start_pos = MIN (old_editable->selection_start_pos, old_editable->selection_end_pos);
selection_end_pos = MAX (old_editable->selection_start_pos, old_editable->selection_end_pos);
str = gtk_old_editable_get_public_chars (old_editable,
selection_start_pos,
selection_end_pos);
if (str)
{
gtk_selection_data_set_text (selection_data, str);
g_free (str);
}
}
static void
gtk_old_editable_paste_received (GtkOldEditable *old_editable,
const gchar *text,
gboolean is_clipboard)
{
const gchar *str = NULL;
gchar *charset;
gboolean need_conversion = FALSE;
if (text)
{
GError *error;
need_conversion = !g_get_charset (&charset);
if (need_conversion)
{
str = g_convert_with_fallback (text, -1,
charset, "UTF-8", NULL,
NULL, NULL, &error);
if (!str)
{
g_warning ("Cannot convert text from UTF-8 to %s: %s",
charset, error->message);
g_error_free (error);
return;
}
}
else
str = text;
}
if (str)
{
gboolean reselect;
gint old_pos;
gint tmp_pos;
reselect = FALSE;
if ((old_editable->selection_start_pos != old_editable->selection_end_pos) &&
(!old_editable->has_selection || is_clipboard))
{
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 (old_editable->has_selection)
{
gtk_editable_delete_text (GTK_EDITABLE (old_editable),
MIN (old_editable->selection_start_pos, old_editable->selection_end_pos),
MAX (old_editable->selection_start_pos, old_editable->selection_end_pos));
}
else
gtk_editable_delete_selection (GTK_EDITABLE (old_editable));
}
tmp_pos = old_pos = old_editable->current_pos;
gtk_editable_insert_text (GTK_EDITABLE (old_editable), str, -1, &tmp_pos);
if (reselect)
gtk_old_editable_set_selection (old_editable, old_pos, old_editable->current_pos);
if (str && str != text)
g_free ((gchar *) str);
}
}
static void
gtk_old_editable_selection_received (GtkWidget *widget,
GtkSelectionData *selection_data,
guint time)
{
GtkOldEditable *old_editable = GTK_OLD_EDITABLE (widget);
gchar *text = gtk_selection_data_get_text (selection_data);
if (!text)
{
/* If we asked for UTF8 and didn't get it, try text; if we asked
* for text and didn't get it, try string. If we asked for
* anything else and didn't get it, give up.
*/
if (selection_data->target == gdk_atom_intern ("UTF8_STRING", FALSE))
{
gtk_selection_convert (widget, GDK_SELECTION_PRIMARY,
gdk_atom_intern ("TEXT", FALSE),
time);
return;
}
else if (selection_data->target == gdk_atom_intern ("TEXT", FALSE))
{
gtk_selection_convert (widget, GDK_SELECTION_PRIMARY,
GDK_TARGET_STRING,
time);
return;
}
}
if (text)
{
gtk_old_editable_paste_received (old_editable, text, FALSE);
g_free (text);
}
}
static void
old_editable_text_received_cb (GtkClipboard *clipboard,
const gchar *text,
gpointer data)
{
GtkOldEditable *old_editable = GTK_OLD_EDITABLE (data);
gtk_old_editable_paste_received (old_editable, text, TRUE);
g_object_unref (G_OBJECT (old_editable));
}
void
gtk_old_editable_claim_selection (GtkOldEditable *old_editable,
gboolean claim,
guint32 time)
{
g_return_if_fail (old_editable != NULL);
g_return_if_fail (GTK_IS_OLD_EDITABLE (old_editable));
g_return_if_fail (GTK_WIDGET_REALIZED (old_editable));
old_editable->has_selection = FALSE;
if (claim)
{
if (gtk_selection_owner_set (GTK_WIDGET (old_editable), GDK_SELECTION_PRIMARY, time))
old_editable->has_selection = TRUE;
}
else
{
if (gdk_selection_owner_get (GDK_SELECTION_PRIMARY) == GTK_WIDGET (old_editable)->window)
gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY, time);
}
}
static void
gtk_old_editable_set_selection_bounds (GtkEditable *editable,
gint start,
gint end)
{
GtkOldEditable *old_editable = GTK_OLD_EDITABLE (editable);
if (GTK_WIDGET_REALIZED (editable))
gtk_old_editable_claim_selection (old_editable, start != end, GDK_CURRENT_TIME);
gtk_old_editable_set_selection (old_editable, start, end);
}
static gboolean
gtk_old_editable_get_selection_bounds (GtkEditable *editable,
gint *start,
gint *end)
{
GtkOldEditable *old_editable = GTK_OLD_EDITABLE (editable);
*start = old_editable->selection_start_pos;
*end = old_editable->selection_end_pos;
return (old_editable->selection_start_pos != old_editable->selection_end_pos);
}
static void
gtk_old_editable_real_set_editable (GtkOldEditable *old_editable,
gboolean is_editable)
{
is_editable = is_editable != FALSE;
if (old_editable->editable != is_editable)
{
old_editable->editable = is_editable;
gtk_widget_queue_draw (GTK_WIDGET (old_editable));
}
}
static void
gtk_old_editable_real_cut_clipboard (GtkOldEditable *old_editable)
{
gtk_old_editable_real_copy_clipboard (old_editable);
gtk_editable_delete_selection (GTK_EDITABLE (old_editable));
}
static void
gtk_old_editable_real_copy_clipboard (GtkOldEditable *old_editable)
{
gint selection_start_pos;
gint selection_end_pos;
selection_start_pos = MIN (old_editable->selection_start_pos, old_editable->selection_end_pos);
selection_end_pos = MAX (old_editable->selection_start_pos, old_editable->selection_end_pos);
if (selection_start_pos != selection_end_pos)
{
gchar *text = gtk_old_editable_get_public_chars (old_editable,
selection_start_pos,
selection_end_pos);
if (text)
{
gtk_clipboard_set_text (gtk_clipboard_get (GDK_NONE), text, -1);
g_free (text);
}
}
}
static void
gtk_old_editable_real_paste_clipboard (GtkOldEditable *old_editable)
{
g_object_ref (G_OBJECT (old_editable));
gtk_clipboard_request_text (gtk_clipboard_get (GDK_NONE),
old_editable_text_received_cb, old_editable);
}
void
gtk_old_editable_changed (GtkOldEditable *old_editable)
{
g_return_if_fail (old_editable != NULL);
g_return_if_fail (GTK_IS_OLD_EDITABLE (old_editable));
gtk_signal_emit (GTK_OBJECT (old_editable), editable_signals[CHANGED]);
}

142
gtk/gtkoldeditable.h Normal file
View File

@ -0,0 +1,142 @@
/* 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 Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
* file for a list of people on the GTK+ Team. See the ChangeLog
* files for a list of changes. These files are distributed with
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
*/
#ifndef __GTK_OLD_EDITABLE_H__
#define __GTK_OLD_EDITABLE_H__
#include <gdk/gdk.h>
#include <gtk/gtkeditable.h>
#include <gtk/gtkwidget.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#define GTK_TYPE_OLD_EDITABLE (gtk_old_editable_get_type ())
#define GTK_OLD_EDITABLE(obj) (GTK_CHECK_CAST ((obj), GTK_TYPE_OLD_EDITABLE, GtkOldEditable))
#define GTK_OLD_EDITABLE_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_OLD_EDITABLE, GtkOldEditableClass))
#define GTK_IS_OLD_EDITABLE(obj) (GTK_CHECK_TYPE ((obj), GTK_TYPE_OLD_EDITABLE))
#define GTK_IS_OLD_EDITABLE_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_OLD_EDITABLE))
#define GTK_OLD_EDITABLE_GET_CLASS(obj) (GTK_CHECK_GET_CLASS ((obj), GTK_TYPE_OLD_EDITABLE, GtkOldEditableClass))
typedef struct _GtkOldEditable GtkOldEditable;
typedef struct _GtkOldEditableClass GtkOldEditableClass;
typedef void (*GtkTextFunction) (GtkOldEditable *editable, guint32 time);
struct _GtkOldEditable
{
GtkWidget widget;
/*< public >*/
guint current_pos;
guint selection_start_pos;
guint selection_end_pos;
guint has_selection : 1;
/*< private >*/
guint editable : 1;
guint visible : 1;
GdkIC *ic;
GdkICAttr *ic_attr;
gchar *clipboard_text;
};
struct _GtkOldEditableClass
{
GtkWidgetClass parent_class;
/* Signals for notification/filtering of changes */
void (* changed) (GtkOldEditable *editable);
void (* insert_text) (GtkOldEditable *editable,
const gchar *text,
gint length,
gint *position);
void (* delete_text) (GtkOldEditable *editable,
gint start_pos,
gint end_pos);
/* Bindings actions */
void (* activate) (GtkOldEditable *editable);
void (* set_editable) (GtkOldEditable *editable,
gboolean is_editable);
void (* move_cursor) (GtkOldEditable *editable,
gint x,
gint y);
void (* move_word) (GtkOldEditable *editable,
gint n);
void (* move_page) (GtkOldEditable *editable,
gint x,
gint y);
void (* move_to_row) (GtkOldEditable *editable,
gint row);
void (* move_to_column) (GtkOldEditable *editable,
gint row);
void (* kill_char) (GtkOldEditable *editable,
gint direction);
void (* kill_word) (GtkOldEditable *editable,
gint direction);
void (* kill_line) (GtkOldEditable *editable,
gint direction);
void (* cut_clipboard) (GtkOldEditable *editable);
void (* copy_clipboard) (GtkOldEditable *editable);
void (* paste_clipboard) (GtkOldEditable *editable);
/* Virtual functions. get_chars is in paricular not a signal because
* it returns malloced memory. The others are not signals because
* they would not be particularly useful as such. (All changes to
* selection and position do not go through these functions)
*/
void (* update_text) (GtkOldEditable *editable,
gint start_pos,
gint end_pos);
gchar* (* get_chars) (GtkOldEditable *editable,
gint start_pos,
gint end_pos);
void (* set_selection)(GtkOldEditable *editable,
gint start_pos,
gint end_pos);
void (* set_position) (GtkOldEditable *editable,
gint position);
};
GtkType gtk_old_editable_get_type (void) G_GNUC_CONST;
void gtk_old_editable_claim_selection (GtkOldEditable *old_editable,
gboolean claim,
guint32 time);
void gtk_old_editable_changed (GtkOldEditable *old_editable);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __GTK_OLD_EDITABLE_H__ */

View File

@ -184,7 +184,6 @@ gtk_preview_init (GtkPreview *preview)
void
gtk_preview_uninit (void)
{
/* unimplemented */
}

View File

@ -26,9 +26,6 @@
#include "config.h"
#include "glib.h"
#include "gdkconfig.h"
#ifdef GDK_WINDOWING_X11
#include <X11/Xlocale.h> /* so we get the right setlocale */
#else
@ -56,6 +53,9 @@
#include <io.h>
#endif
#include <glib.h>
#include "gdkconfig.h"
#include "gtkrc.h"
#include "gtkbindings.h"
#include "gtkthemes.h"
@ -127,6 +127,8 @@ static guint gtk_rc_parse_pixmap_path (GScanner *scanner);
static void gtk_rc_parse_pixmap_path_string (gchar *pix_path);
static guint gtk_rc_parse_module_path (GScanner *scanner);
static void gtk_rc_parse_module_path_string (gchar *mod_path);
static guint gtk_rc_parse_im_module_path (GScanner *scanner);
static guint gtk_rc_parse_im_module_file (GScanner *scanner);
static guint gtk_rc_parse_path_pattern (GScanner *scanner);
static guint gtk_rc_parse_stock (GScanner *scanner,
GtkRcStyle *rc_style,
@ -225,12 +227,17 @@ static const struct
{ "engine", GTK_RC_TOKEN_ENGINE },
{ "module_path", GTK_RC_TOKEN_MODULE_PATH },
{ "stock", GTK_RC_TOKEN_STOCK },
{ "im_module_path", GTK_RC_TOKEN_IM_MODULE_PATH },
{ "im_module_file", GTK_RC_TOKEN_IM_MODULE_FILE },
{ "LTR", GTK_RC_TOKEN_LTR },
{ "RTL", GTK_RC_TOKEN_RTL }
};
static const guint n_symbols = sizeof (symbols) / sizeof (symbols[0]);
static gchar *im_module_path = NULL;
static gchar *im_module_file = NULL;
static GHashTable *rc_style_ht = NULL;
static GHashTable *realized_style_ht = NULL;
static GSList *gtk_rc_sets_widget = NULL;
@ -304,6 +311,56 @@ get_themes_directory (void)
#endif
static gchar *
gtk_rc_make_default_dir (const gchar *type)
{
gchar *var, *path;
#ifndef G_OS_WIN32
var = getenv("GTK_EXE_PREFIX");
if (var)
path = g_strdup_printf("%s%s%s", var, "/lib/gtk-2.0/" GTK_VERSION "/", type);
else
path = g_strdup_printf("%s%s%s", GTK_EXE_PREFIX, "/lib/gtk-2.0/" GTK_VERSION "/", type);
#else
path = g_strdup_printf ("%s\\%s", get_themes_directory (), type);
#endif
return path;
}
gchar *
gtk_rc_get_im_module_path (void)
{
gchar *result = g_getenv ("GTK_IM_MODULE_PATH");
if (!result)
{
if (im_module_path)
result = im_module_path;
else
return gtk_rc_make_default_dir ("immodules");
}
return g_strdup (result);
}
gchar *
gtk_rc_get_im_module_file (void)
{
gchar *result = g_getenv ("GTK_IM_MODULE_FILE");
if (!result)
{
if (im_module_file)
result = im_module_file;
else
result = GTK_SYSCONFDIR G_DIR_SEPARATOR_S "gtk-2.0" G_DIR_SEPARATOR_S "gtk.immodules";
}
return g_strdup (result);
}
gchar *
gtk_rc_get_theme_dir(void)
{
@ -325,19 +382,7 @@ gtk_rc_get_theme_dir(void)
gchar *
gtk_rc_get_module_dir(void)
{
gchar *var, *path;
#ifndef G_OS_WIN32
var = getenv("GTK_EXE_PREFIX");
if (var)
path = g_strdup_printf("%s%s", var, "/lib/gtk-2.0/" GTK_VERSION "/engines");
else
path = g_strdup_printf("%s%s", GTK_EXE_PREFIX, "/lib/gtk-2.0/" GTK_VERSION "/engines");
#else
path = g_strdup_printf ("%s%s", get_themes_directory (), "\\engines");
#endif
return path;
return gtk_rc_make_default_dir ("engines");
}
static void
@ -1544,6 +1589,12 @@ gtk_rc_parse_statement (GScanner *scanner)
case GTK_RC_TOKEN_MODULE_PATH:
return gtk_rc_parse_module_path (scanner);
case GTK_RC_TOKEN_IM_MODULE_PATH:
return gtk_rc_parse_im_module_path (scanner);
case GTK_RC_TOKEN_IM_MODULE_FILE:
return gtk_rc_parse_im_module_file (scanner);
default:
g_scanner_get_next_token (scanner);
return /* G_TOKEN_SYMBOL */ GTK_RC_TOKEN_STYLE;
@ -2120,7 +2171,7 @@ gtk_rc_parse_engine (GScanner *scanner,
GtkRcStyleClass *new_class;
new_style = gtk_theme_engine_create_rc_style (engine);
gtk_theme_engine_unref (engine);
g_type_module_unuse (G_TYPE_MODULE (engine));
new_class = GTK_RC_STYLE_GET_CLASS (new_style);
@ -2460,6 +2511,48 @@ gtk_rc_parse_module_path (GScanner *scanner)
return G_TOKEN_NONE;
}
static guint
gtk_rc_parse_im_module_path (GScanner *scanner)
{
guint token;
token = g_scanner_get_next_token (scanner);
if (token != GTK_RC_TOKEN_IM_MODULE_FILE)
return GTK_RC_TOKEN_IM_MODULE_FILE;
token = g_scanner_get_next_token (scanner);
if (token != G_TOKEN_STRING)
return G_TOKEN_STRING;
if (im_module_path)
g_free (im_module_path);
im_module_path = g_strdup (scanner->value.v_string);
return G_TOKEN_NONE;
}
static guint
gtk_rc_parse_im_module_file (GScanner *scanner)
{
guint token;
token = g_scanner_get_next_token (scanner);
if (token != GTK_RC_TOKEN_IM_MODULE_FILE)
return GTK_RC_TOKEN_IM_MODULE_FILE;
token = g_scanner_get_next_token (scanner);
if (token != G_TOKEN_STRING)
return G_TOKEN_STRING;
if (im_module_file)
g_free (im_module_file);
im_module_file = g_strdup (scanner->value.v_string);
return G_TOKEN_NONE;
}
static void
gtk_rc_parse_module_path_string (gchar *mod_path)
{

View File

@ -148,6 +148,8 @@ gchar* gtk_rc_find_pixmap_in_path (GScanner *scanner,
gchar* gtk_rc_find_module_in_path (const gchar *module_file);
gchar* gtk_rc_get_theme_dir (void);
gchar* gtk_rc_get_module_dir (void);
gchar* gtk_rc_get_im_module_path (void);
gchar* gtk_rc_get_im_module_file (void);
/* private functions/definitions */
typedef enum {
@ -182,6 +184,8 @@ typedef enum {
GTK_RC_TOKEN_HIGHEST,
GTK_RC_TOKEN_ENGINE,
GTK_RC_TOKEN_MODULE_PATH,
GTK_RC_TOKEN_IM_MODULE_PATH,
GTK_RC_TOKEN_IM_MODULE_FILE,
GTK_RC_TOKEN_STOCK,
GTK_RC_TOKEN_LTR,
GTK_RC_TOKEN_RTL,

View File

@ -113,10 +113,10 @@ static gint gtk_spin_button_key_release (GtkWidget *widget,
GdkEventKey *event);
static gint gtk_spin_button_scroll (GtkWidget *widget,
GdkEventScroll *event);
static void gtk_spin_button_activate (GtkEditable *editable);
static void gtk_spin_button_activate (GtkEntry *entry);
static void gtk_spin_button_snap (GtkSpinButton *spin_button,
gfloat val);
static void gtk_spin_button_insert_text (GtkEditable *editable,
static void gtk_spin_button_insert_text (GtkEntry *entry,
const gchar *new_text,
gint new_text_length,
gint *position);
@ -161,11 +161,11 @@ gtk_spin_button_class_init (GtkSpinButtonClass *class)
GObjectClass *gobject_class = G_OBJECT_CLASS (class);
GtkObjectClass *object_class;
GtkWidgetClass *widget_class;
GtkEditableClass *editable_class;
GtkEntryClass *entry_class;
object_class = (GtkObjectClass*) class;
widget_class = (GtkWidgetClass*) class;
editable_class = (GtkEditableClass*) class;
entry_class = (GtkEntryClass*) class;
parent_class = gtk_type_class (GTK_TYPE_ENTRY);
@ -192,8 +192,8 @@ 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;
editable_class->insert_text = gtk_spin_button_insert_text;
editable_class->activate = gtk_spin_button_activate;
entry_class->insert_text = gtk_spin_button_insert_text;
entry_class->activate = gtk_spin_button_activate;
class->input = NULL;
class->output = NULL;
@ -756,7 +756,7 @@ gtk_spin_button_focus_out (GtkWidget *widget,
g_return_val_if_fail (GTK_IS_SPIN_BUTTON (widget), FALSE);
g_return_val_if_fail (event != NULL, FALSE);
if (GTK_EDITABLE (widget)->editable)
if (GTK_ENTRY (widget)->editable)
gtk_spin_button_update (GTK_SPIN_BUTTON (widget));
return GTK_WIDGET_CLASS (parent_class)->focus_out_event (widget, event);
@ -813,7 +813,7 @@ gtk_spin_button_button_press (GtkWidget *widget,
gtk_grab_add (widget);
spin->button = event->button;
if (GTK_EDITABLE (widget)->editable)
if (GTK_ENTRY (widget)->editable)
gtk_spin_button_update (spin);
if (event->y <= widget->requisition.height / 2)
@ -1066,7 +1066,7 @@ gtk_spin_button_key_press (GtkWidget *widget,
key_repeat = (event->time == spin->ev_time);
if (GTK_EDITABLE (widget)->editable &&
if (GTK_ENTRY (widget)->editable &&
(key == GDK_Up || key == GDK_Down ||
key == GDK_Page_Up || key == GDK_Page_Down))
gtk_spin_button_update (spin);
@ -1204,30 +1204,21 @@ gtk_spin_button_snap (GtkSpinButton *spin_button,
}
static void
gtk_spin_button_activate (GtkEditable *editable)
gtk_spin_button_activate (GtkEntry *entry)
{
g_return_if_fail (editable != NULL);
g_return_if_fail (GTK_IS_SPIN_BUTTON (editable));
if (editable->editable)
gtk_spin_button_update (GTK_SPIN_BUTTON (editable));
if (entry->editable)
gtk_spin_button_update (GTK_SPIN_BUTTON (entry));
}
static void
gtk_spin_button_insert_text (GtkEditable *editable,
gtk_spin_button_insert_text (GtkEntry *entry,
const gchar *new_text,
gint new_text_length,
gint *position)
{
GtkEntry *entry;
GtkSpinButton *spin;
GtkEditable *editable = GTK_EDITABLE (entry);
GtkSpinButton *spin = GTK_SPIN_BUTTON (editable);
g_return_if_fail (editable != NULL);
g_return_if_fail (GTK_IS_SPIN_BUTTON (editable));
entry = GTK_ENTRY (editable);
spin = GTK_SPIN_BUTTON (editable);
if (spin->numeric)
{
struct lconv *lc;
@ -1296,8 +1287,8 @@ gtk_spin_button_insert_text (GtkEditable *editable,
}
}
GTK_EDITABLE_CLASS (parent_class)->insert_text (editable, new_text,
new_text_length, position);
GTK_ENTRY_CLASS (parent_class)->insert_text (entry, new_text,
new_text_length, position);
}
static void
@ -1565,7 +1556,7 @@ gtk_spin_button_set_snap_to_ticks (GtkSpinButton *spin_button,
if (new_val != spin_button->snap_to_ticks)
{
spin_button->snap_to_ticks = new_val;
if (new_val && GTK_EDITABLE (spin_button)->editable)
if (new_val && GTK_ENTRY (spin_button)->editable)
gtk_spin_button_update (spin_button);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -30,7 +30,7 @@
#include <gdk/gdk.h>
#include <gtk/gtkadjustment.h>
#include <gtk/gtkeditable.h>
#include <gtk/gtkoldeditable.h>
#ifdef __cplusplus
extern "C" {
@ -64,7 +64,7 @@ struct _GtkPropertyMark
struct _GtkText
{
GtkEditable editable;
GtkOldEditable old_editable;
GdkWindow *text_area;
@ -169,7 +169,7 @@ struct _GtkText
struct _GtkTextClass
{
GtkEditableClass parent_class;
GtkOldEditableClass parent_class;
void (*set_scroll_adjustments) (GtkText *text,
GtkAdjustment *hadjustment,

View File

@ -92,11 +92,6 @@ static GtkTextLineData *gtk_text_layout_real_wrap (GtkTextLayout *layout,
/* may be NULL */
GtkTextLineData *line_data);
static void gtk_text_layout_real_get_log_attrs (GtkTextLayout *layout,
GtkTextLine *line,
PangoLogAttr **attrs,
gint *n_attrs);
static void gtk_text_layout_invalidated (GtkTextLayout *layout);
static void gtk_text_layout_real_invalidate (GtkTextLayout *layout,
@ -207,7 +202,6 @@ gtk_text_layout_class_init (GtkTextLayoutClass *klass)
gobject_class->finalize = gtk_text_layout_finalize;
klass->wrap = gtk_text_layout_real_wrap;
klass->get_log_attrs = gtk_text_layout_real_get_log_attrs;
klass->invalidate = gtk_text_layout_real_invalidate;
klass->free_line_data = gtk_text_layout_real_free_line_data;
}
@ -418,6 +412,69 @@ gtk_text_layout_get_cursor_visible (GtkTextLayout *layout)
return layout->cursor_visible;
}
/**
* gtk_text_layout_set_preedit_string:
* @layout: a #PangoLayout
* @preedit_string: a string to display at the insertion point
* @preedit_attrs: a #PangoAttrList of attributes that apply to @preedit_string
* @cursor_pos: position of cursor within preedit string in chars
*
* Set the preedit string and attributes. The preedit string is a
* string showing text that is currently being edited and not
* yet committed into the buffer.
**/
void
gtk_text_layout_set_preedit_string (GtkTextLayout *layout,
const gchar *preedit_string,
PangoAttrList *preedit_attrs,
gint cursor_pos)
{
GtkTextIter iter;
GtkTextLine *line;
GtkTextLineData *line_data;
g_return_if_fail (GTK_IS_TEXT_LAYOUT (layout));
g_return_if_fail (preedit_attrs != NULL || preedit_string == NULL);
if (layout->preedit_string)
g_free (layout->preedit_string);
if (layout->preedit_attrs)
pango_attr_list_unref (layout->preedit_attrs);
if (preedit_string)
{
layout->preedit_string = g_strdup (preedit_string);
layout->preedit_len = strlen (layout->preedit_string);
pango_attr_list_ref (preedit_attrs);
layout->preedit_attrs = preedit_attrs;
cursor_pos = CLAMP (cursor_pos, 0, g_utf8_strlen (layout->preedit_string, -1));
layout->preedit_cursor = g_utf8_offset_to_pointer (layout->preedit_string, cursor_pos) - layout->preedit_string;
}
else
{
layout->preedit_string = NULL;
layout->preedit_len = 0;
layout->preedit_attrs = NULL;
layout->preedit_cursor = 0;
}
/* Now invalidate the paragraph containing the cursor
*/
gtk_text_buffer_get_iter_at_mark (layout->buffer, &iter,
gtk_text_buffer_get_mark (layout->buffer, "insert"));
line = gtk_text_iter_get_text_line (&iter);
line_data = gtk_text_line_get_data (line, layout);
if (line_data)
{
gtk_text_layout_invalidate_cache (layout, line);
gtk_text_line_invalidate_wrap (line, line_data);
gtk_text_layout_invalidated (layout);
}
}
void
gtk_text_layout_get_size (GtkTextLayout *layout,
gint *width,
@ -483,16 +540,6 @@ gtk_text_layout_wrap (GtkTextLayout *layout,
return (* GTK_TEXT_LAYOUT_GET_CLASS (layout)->wrap) (layout, line, line_data);
}
void
gtk_text_layout_get_log_attrs (GtkTextLayout *layout,
GtkTextLine *line,
PangoLogAttr **attrs,
gint *n_attrs)
{
(* GTK_TEXT_LAYOUT_GET_CLASS (layout)->get_log_attrs)
(layout, line, attrs, n_attrs);
}
GSList*
gtk_text_layout_get_lines (GtkTextLayout *layout,
/* [top_y, bottom_y) */
@ -856,21 +903,6 @@ gtk_text_layout_real_wrap (GtkTextLayout *layout,
return line_data;
}
static void
gtk_text_layout_real_get_log_attrs (GtkTextLayout *layout,
GtkTextLine *line,
PangoLogAttr **attrs,
gint *n_attrs)
{
GtkTextLineDisplay *display;
g_return_if_fail (GTK_IS_TEXT_LAYOUT (layout));
display = gtk_text_layout_get_line_display (layout, line, TRUE);
pango_layout_get_log_attrs (display->layout, attrs, n_attrs);
gtk_text_layout_free_line_display (layout, display);
}
/*
* Layout utility functions
*/
@ -1285,6 +1317,18 @@ add_child_attrs (GtkTextLayout *layout,
return;
}
if (layout->preedit_string)
{
g_free (layout->preedit_string);
layout->preedit_string = NULL;
}
if (layout->preedit_attrs)
{
pango_attr_list_unref (layout->preedit_attrs);
layout->preedit_attrs = NULL;
}
logical_rect.x = 0;
logical_rect.y = -height * PANGO_SCALE;
@ -1355,6 +1399,96 @@ allocate_child_widgets (GtkTextLayout *layout,
#endif
}
static void
convert_color (GdkColor *result,
PangoAttrColor *attr)
{
result->red = attr->red;
result->blue = attr->blue;
result->green = attr->green;
}
/* This function is used to convert the preedit string attributes, which are
* standard PangoAttributes, into the custom attributes used by the text
* widget and insert them into a attr list with a given offset.
*/
static void
add_preedit_attrs (GtkTextLayout *layout,
GtkTextAttributes *style,
PangoAttrList *attrs,
gint offset,
gboolean size_only)
{
PangoAttrIterator *iter = pango_attr_list_get_iterator (layout->preedit_attrs);
do
{
GtkTextAppearance appearance = style->appearance;
PangoFontDescription font_desc;
PangoAttribute *insert_attr;
GSList *extra_attrs = NULL;
GSList *tmp_list;
gint start, end;
pango_attr_iterator_range (iter, &start, &end);
if (end == G_MAXINT)
end = layout->preedit_len;
pango_attr_iterator_get_font (iter, style->font_desc,
&font_desc, size_only ? NULL : &extra_attrs);
tmp_list = extra_attrs;
while (tmp_list)
{
PangoAttribute *attr = tmp_list->data;
switch (attr->klass->type)
{
case PANGO_ATTR_FOREGROUND:
convert_color (&appearance.fg_color, (PangoAttrColor *)attr);
break;
case PANGO_ATTR_BACKGROUND:
convert_color (&appearance.bg_color, (PangoAttrColor *)attr);
appearance.draw_bg = TRUE;
break;
case PANGO_ATTR_UNDERLINE:
appearance.underline = ((PangoAttrInt *)attr)->value;
break;
case PANGO_ATTR_STRIKETHROUGH:
appearance.strikethrough = ((PangoAttrInt *)attr)->value;
break;
default:
break;
}
pango_attribute_destroy (attr);
tmp_list = tmp_list->next;
}
g_slist_free (extra_attrs);
insert_attr = pango_attr_font_desc_new (&font_desc);
insert_attr->start_index = start + offset;
insert_attr->end_index = end + offset;
pango_attr_list_insert (attrs, insert_attr);
if (!size_only)
{
insert_attr = gtk_text_attr_appearance_new (&appearance);
insert_attr->start_index = start + offset;
insert_attr->end_index = end + offset;
pango_attr_list_insert (attrs, insert_attr);
}
}
while (pango_attr_iterator_next (iter));
pango_attr_iterator_destroy (iter);
}
GtkTextLineDisplay *
gtk_text_layout_get_line_display (GtkTextLayout *layout,
GtkTextLine *line,
@ -1393,6 +1527,7 @@ gtk_text_layout_get_line_display (GtkTextLayout *layout,
display->size_only = size_only;
display->line = line;
display->insert_index = -1;
gtk_text_btree_get_iter_at_line (_gtk_text_buffer_get_btree (layout->buffer),
&iter, line, 0);
@ -1454,8 +1589,9 @@ gtk_text_layout_get_line_display (GtkTextLayout *layout,
*/
gint byte_count = 0;
while (TRUE)
GtkTextLineSegment *prev_seg = NULL;
while (seg)
{
if (seg->type == &gtk_text_char_type)
{
@ -1463,21 +1599,32 @@ gtk_text_layout_get_line_display (GtkTextLayout *layout,
byte_offset += seg->byte_count;
byte_count += seg->byte_count;
}
else if (seg->body.mark.visible)
else if (seg->type == &gtk_text_right_mark_type ||
seg->type == &gtk_text_left_mark_type)
{
cursor_byte_offsets = g_slist_prepend (cursor_byte_offsets, GINT_TO_POINTER (byte_offset));
cursor_segs = g_slist_prepend (cursor_segs, seg);
/* If we have preedit string, break out of this loop - we'll almost
* certainly have different attributes on the preedit string
*/
if (layout->preedit_len > 0 &&
gtk_text_btree_mark_is_insert (_gtk_text_buffer_get_btree (layout->buffer),
seg->body.mark.obj))
break;
if (seg->body.mark.visible)
{
cursor_byte_offsets = g_slist_prepend (cursor_byte_offsets, GINT_TO_POINTER (byte_offset));
cursor_segs = g_slist_prepend (cursor_segs, seg);
}
}
else
break;
if (!seg->next ||
(seg->next->type != &gtk_text_right_mark_type &&
seg->next->type != &gtk_text_left_mark_type &&
seg->next->type != &gtk_text_char_type))
break;
prev_seg = seg;
seg = seg->next;
}
seg = prev_seg; /* Back up one */
add_text_attrs (layout, style, byte_count, attrs,
byte_offset - byte_count, size_only);
}
@ -1519,12 +1666,38 @@ gtk_text_layout_get_line_display (GtkTextLayout *layout,
else if (seg->type == &gtk_text_right_mark_type ||
seg->type == &gtk_text_left_mark_type)
{
gint cursor_offset = 0;
/* At the insertion point, add the preedit string, if any */
if (gtk_text_btree_mark_is_insert (_gtk_text_buffer_get_btree (layout->buffer),
seg->body.mark.obj))
{
display->insert_index = byte_offset;
if (layout->preedit_len > 0)
{
byte_count += layout->preedit_len;
text = g_realloc (text, byte_count);
style = get_style (layout, &iter);
add_preedit_attrs (layout, style, attrs, byte_offset, size_only);
release_style (layout, style);
memcpy (text + byte_offset, layout->preedit_string, layout->preedit_len);
byte_offset += layout->preedit_len;
cursor_offset = layout->preedit_cursor - layout->preedit_len;
}
}
/* Display visible marks */
if (seg->body.mark.visible)
{
cursor_byte_offsets = g_slist_prepend (cursor_byte_offsets,
GINT_TO_POINTER (byte_offset));
GINT_TO_POINTER (byte_offset + cursor_offset));
cursor_segs = g_slist_prepend (cursor_segs, seg);
}
}
@ -1602,6 +1775,46 @@ gtk_text_layout_free_line_display (GtkTextLayout *layout,
}
}
/* Functions to convert iter <=> index for the line of a GtkTextLineDisplay
* taking into account the preedit string, if necessary.
*/
gint
line_display_iter_to_index (GtkTextLayout *layout,
GtkTextLineDisplay *display,
const GtkTextIter *iter)
{
gint index;
g_return_val_if_fail (gtk_text_iter_get_text_line (iter) == display->line, 0);
index = gtk_text_iter_get_line_index (iter);
if (index >= display->insert_index)
index += layout->preedit_len;
return index;
}
void
line_display_index_to_iter (GtkTextLayout *layout,
GtkTextLineDisplay *display,
GtkTextIter *iter,
gint index,
gint trailing)
{
if (index >= display->insert_index + layout->preedit_len)
index -= layout->preedit_len;
else if (index > display->insert_index)
{
index = display->insert_index;
trailing = 0;
}
gtk_text_btree_get_iter_at_line (_gtk_text_buffer_get_btree (layout->buffer),
iter, display->line, index);
gtk_text_iter_forward_chars (iter, trailing);
}
/* FIXME: This really doesn't belong in this file ... */
static GtkTextLineData*
gtk_text_line_data_new (GtkTextLayout *layout,
@ -1711,12 +1924,7 @@ gtk_text_layout_get_iter_at_pixel (GtkTextLayout *layout,
trailing = 0;
}
gtk_text_btree_get_iter_at_line (_gtk_text_buffer_get_btree (layout->buffer),
target_iter,
line, byte_index);
while (trailing--)
gtk_text_iter_next_char (target_iter);
line_display_index_to_iter (layout, display, target_iter, byte_index, trailing);
gtk_text_layout_free_line_display (layout, display);
}
@ -1746,6 +1954,7 @@ gtk_text_layout_get_cursor_locations (GtkTextLayout *layout,
GtkTextLine *line;
GtkTextLineDisplay *display;
gint line_top;
gint index;
PangoRectangle pango_strong_pos;
PangoRectangle pango_weak_pos;
@ -1754,12 +1963,13 @@ gtk_text_layout_get_cursor_locations (GtkTextLayout *layout,
g_return_if_fail (iter != NULL);
line = gtk_text_iter_get_text_line (iter);
display = gtk_text_layout_get_line_display (layout, line, FALSE);
index = line_display_iter_to_index (layout, display, iter);
line_top = gtk_text_btree_find_line_top (_gtk_text_buffer_get_btree (layout->buffer),
line, layout);
display = gtk_text_layout_get_line_display (layout, line, FALSE);
pango_layout_get_cursor_pos (display->layout, gtk_text_iter_get_line_index (iter),
pango_layout_get_cursor_pos (display->layout, index,
strong_pos ? &pango_strong_pos : NULL,
weak_pos ? &pango_weak_pos : NULL);
@ -1885,7 +2095,7 @@ gtk_text_layout_get_iter_location (GtkTextLayout *layout,
}
else
{
byte_index = gtk_text_iter_get_line_index (iter);
byte_index = line_display_iter_to_index (layout, display, iter);
pango_layout_index_to_pos (display->layout, byte_index, &pango_rect);
@ -1898,6 +2108,8 @@ gtk_text_layout_get_iter_location (GtkTextLayout *layout,
gtk_text_layout_free_line_display (layout, display);
}
/* FFIXX */
/* Find the iter for the logical beginning of the first display line whose
* top y is >= y. If none exists, move the iter to the logical beginning
* of the last line in the buffer.
@ -2104,9 +2316,8 @@ gtk_text_layout_move_iter_to_previous_line (GtkTextLayout *layout,
g_return_if_fail (iter != NULL);
line = gtk_text_iter_get_text_line (iter);
line_byte = gtk_text_iter_get_line_index (iter);
display = gtk_text_layout_get_line_display (layout, line, FALSE);
line_byte = line_display_iter_to_index (layout, display, iter);
tmp_list = pango_layout_get_lines (display->layout);
layout_line = tmp_list->data;
@ -2122,7 +2333,7 @@ gtk_text_layout_move_iter_to_previous_line (GtkTextLayout *layout,
gtk_text_layout_free_line_display (layout, display);
display = gtk_text_layout_get_line_display (layout, prev_line, FALSE);
tmp_list = pango_layout_get_lines (display->layout);
tmp_list = pango_layout_get_lines (display->layout);
while (tmp_list->next)
{
@ -2132,12 +2343,10 @@ gtk_text_layout_move_iter_to_previous_line (GtkTextLayout *layout,
byte_offset += layout_line->length;
}
gtk_text_btree_get_iter_at_line (_gtk_text_buffer_get_btree (layout->buffer),
iter, prev_line, byte_offset);
line_display_index_to_iter (layout, display, iter, byte_offset, 0);
}
else
gtk_text_btree_get_iter_at_line (_gtk_text_buffer_get_btree (layout->buffer),
iter, line, 0);
line_display_index_to_iter (layout, display, iter, 0, 0);
}
else
{
@ -2151,8 +2360,7 @@ gtk_text_layout_move_iter_to_previous_line (GtkTextLayout *layout,
if (line_byte < byte_offset + layout_line->length || !tmp_list->next)
{
gtk_text_btree_get_iter_at_line (_gtk_text_buffer_get_btree (layout->buffer),
iter, line, prev_offset);
line_display_index_to_iter (layout, display, iter, prev_offset, 0);
break;
}
@ -2190,7 +2398,6 @@ gtk_text_layout_move_iter_to_next_line (GtkTextLayout *layout,
g_return_if_fail (iter != NULL);
line = gtk_text_iter_get_text_line (iter);
line_byte = gtk_text_iter_get_line_index (iter);
while (line && !found_after)
{
@ -2198,6 +2405,7 @@ gtk_text_layout_move_iter_to_next_line (GtkTextLayout *layout,
GSList *tmp_list;
display = gtk_text_layout_get_line_display (layout, line, FALSE);
line_byte = line_display_iter_to_index (layout, display, iter);
tmp_list = pango_layout_get_lines (display->layout);
while (tmp_list && !found_after)
@ -2206,9 +2414,7 @@ gtk_text_layout_move_iter_to_next_line (GtkTextLayout *layout,
if (found)
{
gtk_text_btree_get_iter_at_line (_gtk_text_buffer_get_btree (layout->buffer),
iter, line,
byte_offset);
line_display_index_to_iter (layout, display, iter, byte_offset, 0);
found_after = TRUE;
}
else if (line_byte < byte_offset + layout_line->length || !tmp_list->next)
@ -2248,9 +2454,8 @@ gtk_text_layout_move_iter_to_line_end (GtkTextLayout *layout,
g_return_if_fail (iter != NULL);
line = gtk_text_iter_get_text_line (iter);
line_byte = gtk_text_iter_get_line_index (iter);
display = gtk_text_layout_get_line_display (layout, line, FALSE);
line_byte = line_display_iter_to_index (layout, display, iter);
tmp_list = pango_layout_get_lines (display->layout);
while (tmp_list)
@ -2259,11 +2464,13 @@ gtk_text_layout_move_iter_to_line_end (GtkTextLayout *layout,
if (line_byte < byte_offset + layout_line->length || !tmp_list->next)
{
gtk_text_btree_get_iter_at_line (_gtk_text_buffer_get_btree (layout->buffer),
iter, line,
direction < 0 ? byte_offset : byte_offset + layout_line->length);
line_display_index_to_iter (layout, display, iter,
direction < 0 ? byte_offset : byte_offset + layout_line->length,
0);
/* FIXME: Move back one position to avoid going to next line
/* FIXME: As a bad hack, we move back one position to avoid going
* to next line on a forced break not at whitespace. Real fix
* is to keep track of whether marks are at leading or trailing edge?
*/
if (direction < 0 && layout_line->length > 0)
gtk_text_iter_prev_char (iter);
@ -2304,9 +2511,9 @@ gtk_text_layout_move_iter_to_x (GtkTextLayout *layout,
g_return_if_fail (iter != NULL);
line = gtk_text_iter_get_text_line (iter);
line_byte = gtk_text_iter_get_line_index (iter);
display = gtk_text_layout_get_line_display (layout, line, FALSE);
line_byte = line_display_iter_to_index (layout, display, iter);
tmp_list = pango_layout_get_lines (display->layout);
while (tmp_list)
@ -2342,13 +2549,8 @@ gtk_text_layout_move_iter_to_x (GtkTextLayout *layout,
x * PANGO_SCALE - x_offset,
&byte_index, &trailing);
gtk_text_btree_get_iter_at_line (_gtk_text_buffer_get_btree (layout->buffer),
iter,
line, byte_index);
while (trailing--)
gtk_text_iter_next_char (iter);
line_display_index_to_iter (layout, display, iter, byte_index, trailing);
break;
}
@ -2383,20 +2585,27 @@ gtk_text_layout_move_iter_visually (GtkTextLayout *layout,
GtkTextIter *iter,
gint count)
{
GtkTextLineDisplay *display = NULL;
g_return_if_fail (layout != NULL);
g_return_if_fail (iter != NULL);
while (count != 0)
{
GtkTextLine *line = gtk_text_iter_get_text_line (iter);
gint line_byte = gtk_text_iter_get_line_index (iter);
GtkTextLineDisplay *display = gtk_text_layout_get_line_display (layout, line, FALSE);
gint line_byte;
gint extra_back = 0;
int byte_count = gtk_text_line_byte_count (line);
int new_index;
int new_trailing;
if (!display)
display = gtk_text_layout_get_line_display (layout, line, FALSE);
line_byte = line_display_iter_to_index (layout, display, iter);
if (count > 0)
{
pango_layout_move_cursor_visually (display->layout, line_byte, 0, 1, &new_index, &new_trailing);
@ -2408,16 +2617,32 @@ gtk_text_layout_move_iter_visually (GtkTextLayout *layout,
count++;
}
gtk_text_layout_free_line_display (layout, display);
if (new_index < 0)
/* We need to handle the preedit string specially. Well, we don't really need to
* handle it specially, since hopefully calling gtk_im_context_reset() will
* remove the preedit string; but if we start off in front of the preedit
* string (logically) and end up in or on the back edge of the preedit string,
* we should move the iter one place farther.
*/
if (layout->preedit_len > 0 && display->insert_index >= 0)
{
if (line_byte == display->insert_index + layout->preedit_len &&
new_index < display->insert_index + layout->preedit_len)
{
line_byte = display->insert_index;
extra_back = 1;
}
}
if (new_index < 0 || (new_index == 0 && extra_back))
{
line = gtk_text_line_previous (line);
if (!line)
return;
gtk_text_layout_free_line_display (layout, display);
display = gtk_text_layout_get_line_display (layout, line, FALSE);
new_index = gtk_text_line_byte_count (line);
}
else if (new_index > byte_count)
{
@ -2425,16 +2650,17 @@ gtk_text_layout_move_iter_visually (GtkTextLayout *layout,
if (!line)
return;
gtk_text_layout_free_line_display (layout, display);
display = gtk_text_layout_get_line_display (layout, line, FALSE);
new_index = 0;
}
gtk_text_btree_get_iter_at_line (_gtk_text_buffer_get_btree (layout->buffer),
iter,
line, new_index);
while (new_trailing--)
gtk_text_iter_next_char (iter);
line_display_index_to_iter (layout, display, iter, new_index, new_trailing);
if (extra_back)
gtk_text_iter_prev_char (iter);
}
gtk_text_layout_free_line_display (layout, display);
}
void
@ -2472,5 +2698,3 @@ gtk_text_layout_spew (GtkTextLayout *layout)
layout->height, layout->screen_width);
#endif
}

View File

@ -156,6 +156,13 @@ struct _GtkTextLayout
/* Whether to show the insertion cursor */
guint cursor_visible : 1;
/* The preedit string and attributes, if any */
gchar *preedit_string;
PangoAttrList *preedit_attrs;
gint preedit_len;
gint preedit_cursor;
};
struct _GtkTextLayoutClass
@ -221,6 +228,7 @@ struct _GtkTextLineDisplay
gint right_margin;
gint top_margin;
gint bottom_margin;
gint insert_index; /* Byte index of insert cursor within para or -1 */
gboolean size_only;
GtkTextLine *line;
@ -238,8 +246,14 @@ void gtk_text_layout_set_contexts (GtkTextLayout *layout,
PangoContext *ltr_context,
PangoContext *rtl_context);
void gtk_text_layout_default_style_changed (GtkTextLayout *layout);
void gtk_text_layout_set_screen_width (GtkTextLayout *layout,
gint width);
void gtk_text_layout_set_preedit_string (GtkTextLayout *layout,
const gchar *preedit_string,
PangoAttrList *preedit_attrs,
gint cursor_pos);
void gtk_text_layout_set_cursor_visible (GtkTextLayout *layout,
gboolean cursor_visible);
gboolean gtk_text_layout_get_cursor_visible (GtkTextLayout *layout);
@ -302,10 +316,6 @@ void gtk_text_layout_validate (GtkTextLayout *layout,
GtkTextLineData* gtk_text_layout_wrap (GtkTextLayout *layout,
GtkTextLine *line,
GtkTextLineData *line_data); /* may be NULL */
void gtk_text_layout_get_log_attrs (GtkTextLayout *layout,
GtkTextLine *line,
PangoLogAttr **attrs,
gint *n_attrs);
void gtk_text_layout_changed (GtkTextLayout *layout,
gint y,
gint old_height,

View File

@ -28,7 +28,10 @@
#include "gtkbindings.h"
#include "gtkdnd.h"
#include "gtkintl.h"
#include "gtkmain.h"
#include "gtkmenu.h"
#include "gtkmenuitem.h"
#include "gtksignal.h"
#include "gtktext.h"
#include "gtktextdisplay.h"
@ -176,6 +179,7 @@ static void gtk_text_view_set_attributes_from_style (GtkTextView *tex
GtkStyle *style);
static void gtk_text_view_ensure_layout (GtkTextView *text_view);
static void gtk_text_view_destroy_layout (GtkTextView *text_view);
static void gtk_text_view_reset_im_context (GtkTextView *text_view);
static void gtk_text_view_start_selection_drag (GtkTextView *text_view,
const GtkTextIter *iter,
GdkEventButton *event);
@ -187,11 +191,13 @@ static void gtk_text_view_start_selection_dnd (GtkTextView *text_vi
static void gtk_text_view_start_cursor_blink (GtkTextView *text_view);
static void gtk_text_view_stop_cursor_blink (GtkTextView *text_view);
static void gtk_text_view_value_changed (GtkAdjustment *adj,
GtkTextView *view);
static void gtk_text_view_commit_handler (GtkIMContext *context,
const gchar *str,
GtkTextView *text_view);
static void gtk_text_view_value_changed (GtkAdjustment *adj,
GtkTextView *view);
static void gtk_text_view_commit_handler (GtkIMContext *context,
const gchar *str,
GtkTextView *text_view);
static void gtk_text_view_preedit_changed_handler (GtkIMContext *context,
GtkTextView *text_view);
static void gtk_text_view_mark_set_handler (GtkTextBuffer *buffer,
const GtkTextIter *location,
@ -207,6 +213,9 @@ static void gtk_text_view_set_virtual_cursor_pos (GtkTextView *text_view,
static GtkAdjustment* get_hadjustment (GtkTextView *text_view);
static GtkAdjustment* get_vadjustment (GtkTextView *text_view);
static void gtk_text_view_popup_menu (GtkTextView *text_view,
GdkEventButton *event);
/* Container methods */
static void gtk_text_view_add (GtkContainer *container,
GtkWidget *child);
@ -682,6 +691,9 @@ gtk_text_view_init (GtkTextView *text_view)
gtk_signal_connect (GTK_OBJECT (text_view->im_context), "commit",
GTK_SIGNAL_FUNC (gtk_text_view_commit_handler), text_view);
gtk_signal_connect (GTK_OBJECT (text_view->im_context), "preedit_changed",
GTK_SIGNAL_FUNC (gtk_text_view_preedit_changed_handler), text_view);
text_view->editable = TRUE;
text_view->cursor_visible = TRUE;
@ -1578,7 +1590,6 @@ gtk_text_view_size_allocate (GtkWidget *widget,
GdkRectangle right_rect;
GdkRectangle top_rect;
GdkRectangle bottom_rect;
GSList *tmp_list;
text_view = GTK_TEXT_VIEW (widget);
@ -1914,6 +1925,12 @@ gtk_text_view_unrealize (GtkWidget *widget)
text_view->incremental_validate_idle = 0;
}
if (text_view->popup_menu)
{
gtk_widget_destroy (text_view->popup_menu);
text_view->popup_menu = NULL;
}
text_window_unrealize (text_view->text_window);
if (text_view->left_window)
@ -2123,14 +2140,13 @@ gtk_text_view_key_press_event (GtkWidget *widget, GdkEventKey *event)
get_buffer (text_view) == NULL)
return FALSE;
if (GTK_WIDGET_CLASS (parent_class)->key_press_event &&
GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event))
return TRUE;
if (event->window != text_view->text_window->bin_window)
return FALSE;
if (gtk_im_context_filter_keypress (text_view->im_context, event))
{
text_view->need_im_reset = TRUE;
return TRUE;
}
else if (GTK_WIDGET_CLASS (parent_class)->key_press_event &&
GTK_WIDGET_CLASS (parent_class)->key_press_event (widget, event))
return TRUE;
else if (event->keyval == GDK_Return)
{
@ -2179,14 +2195,18 @@ gtk_text_view_button_press_event (GtkWidget *widget, GdkEventButton *event)
return FALSE;
}
#if 0
/* debug hack */
if (event->button == 3 && (event->state & GDK_CONTROL_MASK) != 0)
_gtk_text_buffer_spew (GTK_TEXT_VIEW (widget)->buffer);
else if (event->button == 3)
gtk_text_layout_spew (GTK_TEXT_VIEW (widget)->layout);
#endif
if (event->type == GDK_BUTTON_PRESS)
{
gtk_text_view_reset_im_context (text_view);
if (event->button == 1)
{
/* If we're in the selection, start a drag copy/move of the
@ -2230,10 +2250,7 @@ gtk_text_view_button_press_event (GtkWidget *widget, GdkEventButton *event)
}
else if (event->button == 3)
{
if (gtk_text_view_end_selection_drag (text_view, event))
return TRUE;
else
return FALSE;
gtk_text_view_popup_menu (text_view, event);
}
}
@ -2287,6 +2304,7 @@ gtk_text_view_focus_in_event (GtkWidget *widget, GdkEventFocus *event)
gtk_text_view_start_cursor_blink (text_view);
}
text_view->need_im_reset = TRUE;
gtk_im_context_focus_in (GTK_TEXT_VIEW (widget)->im_context);
return FALSE;
@ -2306,6 +2324,7 @@ gtk_text_view_focus_out_event (GtkWidget *widget, GdkEventFocus *event)
gtk_text_view_stop_cursor_blink (text_view);
}
text_view->need_im_reset = TRUE;
gtk_im_context_focus_out (GTK_TEXT_VIEW (widget)->im_context);
return FALSE;
@ -2642,6 +2661,8 @@ gtk_text_view_move_cursor (GtkTextView *text_view,
gint cursor_x_pos = 0;
gtk_text_view_reset_im_context (text_view);
if (step == GTK_MOVEMENT_PAGES)
{
gtk_text_view_scroll_pages (text_view, count);
@ -2847,6 +2868,8 @@ gtk_text_view_delete_from_cursor (GtkTextView *text_view,
GtkTextIter end;
gboolean leave_one = FALSE;
gtk_text_view_reset_im_context (text_view);
if (type == GTK_DELETE_CHARS)
{
/* Char delete deletes the selection, if one exists */
@ -3358,6 +3381,14 @@ gtk_text_view_destroy_layout (GtkTextView *text_view)
}
}
static void
gtk_text_view_reset_im_context (GtkTextView *text_view)
{
if (text_view->need_im_reset)
text_view->need_im_reset = 0;
gtk_im_context_reset (text_view->im_context);
}
/*
* DND feature
@ -3836,6 +3867,21 @@ gtk_text_view_commit_handler (GtkIMContext *context,
0);
}
static void
gtk_text_view_preedit_changed_handler (GtkIMContext *context,
GtkTextView *text_view)
{
gchar *str;
PangoAttrList *attrs;
gint cursor_pos;
gtk_im_context_get_preedit_string (context, &str, &attrs, &cursor_pos);
gtk_text_layout_set_preedit_string (text_view->layout, str, attrs, cursor_pos);
pango_attr_list_unref (attrs);
g_free (str);
}
static void
gtk_text_view_mark_set_handler (GtkTextBuffer *buffer,
const GtkTextIter *location,
@ -3843,12 +3889,21 @@ gtk_text_view_mark_set_handler (GtkTextBuffer *buffer,
gpointer data)
{
GtkTextView *text_view = GTK_TEXT_VIEW (data);
gboolean need_reset = FALSE;
if (mark == gtk_text_buffer_get_insert (buffer))
{
text_view->virtual_cursor_x = -1;
text_view->virtual_cursor_y = -1;
need_reset = TRUE;
}
else if (mark == gtk_text_buffer_get_selection_bound (buffer))
{
need_reset = TRUE;
}
if (need_reset)
gtk_text_view_reset_im_context (text_view);
}
static void
@ -3903,6 +3958,70 @@ gtk_text_view_set_virtual_cursor_pos (GtkTextView *text_view,
text_view->virtual_cursor_y = (y == -1) ? strong_pos.y + strong_pos.height / 2 : y;
}
/* Quick hack of a popup menu
*/
static void
activate_cb (GtkWidget *menuitem,
GtkTextView *text_view)
{
const gchar *signal = gtk_object_get_data (GTK_OBJECT (menuitem), "gtk-signal");
gtk_signal_emit_by_name (GTK_OBJECT (text_view), signal);
}
static void
append_action_signal (GtkTextView *text_view,
GtkWidget *menu,
const gchar *label,
const gchar *signal)
{
GtkWidget *menuitem = gtk_menu_item_new_with_label (label);
gtk_object_set_data (GTK_OBJECT (menuitem), "gtk-signal", (char *)signal);
gtk_signal_connect (GTK_OBJECT (menuitem), "activate",
activate_cb, text_view);
gtk_widget_show (menuitem);
gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);
}
static void
popup_menu_detach (GtkWidget *attach_widget,
GtkMenu *menu)
{
GTK_TEXT_VIEW (attach_widget)->popup_menu = NULL;
}
static void
gtk_text_view_popup_menu (GtkTextView *text_view,
GdkEventButton *event)
{
if (!text_view->popup_menu)
{
GtkWidget *menuitem;
text_view->popup_menu = gtk_menu_new ();
gtk_menu_attach_to_widget (GTK_MENU (text_view->popup_menu),
GTK_WIDGET (text_view),
popup_menu_detach);
append_action_signal (text_view, text_view->popup_menu, _("Cut"), "cut_clipboard");
append_action_signal (text_view, text_view->popup_menu, _("Copy"), "copy_clipboard");
append_action_signal (text_view, text_view->popup_menu, _("Paste"), "paste_clipboard");
menuitem = gtk_menu_item_new (); /* Separator */
gtk_widget_show (menuitem);
gtk_menu_shell_append (GTK_MENU_SHELL (text_view->popup_menu), menuitem);
gtk_im_multicontext_append_menuitems (GTK_IM_MULTICONTEXT (text_view->im_context),
GTK_MENU_SHELL (text_view->popup_menu));
}
gtk_menu_popup (GTK_MENU (text_view->popup_menu), NULL, NULL,
NULL, NULL,
event->button, event->time);
}
/* Child GdkWindows */

View File

@ -70,13 +70,12 @@ struct _GtkTextView
guint selection_drag_scan_timeout;
gint scrolling_accel_factor;
gboolean overwrite_mode;
GtkWrapMode wrap_mode; /* Default wrap mode */
gboolean editable; /* default editability */
gboolean cursor_visible;
guint editable : 1; /* default editability */
guint overwrite_mode : 1;
guint cursor_visible : 1;
guint need_im_reset : 1; /* If we have reset the IM since the last character entered */
GtkTextWindow *text_window;
GtkTextWindow *left_window;
@ -114,6 +113,7 @@ struct _GtkTextView
guint incremental_validate_idle; /* Idle to revalidate offscreen portions, runs after redraw */
GtkIMContext *im_context;
GtkWidget *popup_menu;
gint drag_start_x;
gint drag_start_y;

View File

@ -29,131 +29,135 @@
#include <stdlib.h>
#include <gmodule.h>
#include "gtkthemes.h"
#include "gtkmain.h"
#include "gtkrc.h"
#include "gtkselection.h"
#include "gtksignal.h"
#include "gtkwidget.h"
#include "config.h"
#include "gtkintl.h"
/*****************************
*****************************
* temporary compat code, make GtkThemeEnginePlugin a GObject plus GTypePlugin interface
*/
typedef struct _GtkThemeEnginePlugin GtkThemeEnginePlugin;
typedef struct _GObjectClass GtkThemeEnginePluginClass;
static void gtk_theme_engine_plugin_use (GTypePlugin *plugin);
static void gtk_theme_engine_plugin_unuse (GTypePlugin *plugin);
static void gtk_theme_engine_plugin_complete_type_info (GTypePlugin *plugin,
GType g_type,
GTypeInfo *info,
GTypeValueTable *value_table);
GType gtk_theme_engine_plugin_get_type (void);
struct _GtkThemeEnginePlugin
{
GObject parent_instance;
GtkThemeEngine *engine;
gchar *engine_name;
GTypeInfo info;
GType type;
GType parent_type;
};
#define GTK_TYPE_THEME_ENGINE_PLUGIN (gtk_theme_engine_plugin_get_type ())
#define GTK_THEME_ENGINE_PLUGIN(plugin) (G_TYPE_CHECK_INSTANCE_CAST ((plugin), GTK_TYPE_THEME_ENGINE_PLUGIN, GtkThemeEnginePlugin))
#define GTK_THEME_ENGINE_PLUGIN_CLASS(class) (G_TYPE_CHECK_CLASS_CAST ((class), GTK_TYPE_THEME_ENGINE_PLUGIN, GtkThemeEnginePluginClass))
#define GTK_IS_THEME_ENGINE_PLUGIN(plugin) (G_TYPE_CHECK_INSTANCE_TYPE ((plugin), GTK_TYPE_THEME_ENGINE_PLUGIN))
#define GTK_IS_THEME_ENGINE_PLUGIN_CLASS(class) (G_TYPE_CHECK_CLASS_TYPE ((class), GTK_TYPE_THEME_ENGINE_PLUGIN))
#define GTK_THEME_ENGINE_PLUGIN_GET_CLASS(plugin) (G_TYPE_INSTANCE_GET_CLASS ((plugin), GTK_TYPE_THEME_ENGINE_PLUGIN, GtkThemeEnginePluginClass))
static void
gtk_theme_engine_plugin_shutdown (GObject *object)
{
GtkThemeEnginePlugin *plugin = GTK_THEME_ENGINE_PLUGIN (object);
g_warning (G_STRLOC ": shutdown should never happen for static type plugins");
g_object_ref (object);
/* chain parent class handler */
G_OBJECT_CLASS (g_type_class_peek_parent (GTK_THEME_ENGINE_PLUGIN_GET_CLASS (plugin)))->shutdown (object);
}
static void
gtk_theme_engine_plugin_class_init (GtkThemeEnginePluginClass *class)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (class);
gobject_class->shutdown = gtk_theme_engine_plugin_shutdown;
}
static void
theme_engine_plugin_iface_init (GTypePluginClass *iface)
{
iface->use_plugin = gtk_theme_engine_plugin_use;
iface->unuse_plugin = gtk_theme_engine_plugin_unuse;
iface->complete_type_info = gtk_theme_engine_plugin_complete_type_info;
}
GType
gtk_theme_engine_plugin_get_type (void)
{
static GType theme_engine_plugin_type = 0;
if (!theme_engine_plugin_type)
{
static const GTypeInfo theme_engine_plugin_info = {
sizeof (GtkThemeEnginePluginClass),
NULL, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc) gtk_theme_engine_plugin_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (GtkThemeEnginePlugin),
0, /* n_preallocs */
NULL, /* instance_init */
};
static const GInterfaceInfo iface_info = {
(GInterfaceInitFunc) theme_engine_plugin_iface_init,
NULL, /* interface_finalize */
NULL, /* interface_data */
};
theme_engine_plugin_type = g_type_register_static (G_TYPE_OBJECT, "GtkThemeEnginePlugin", &theme_engine_plugin_info, 0);
g_type_add_interface_static (theme_engine_plugin_type, G_TYPE_TYPE_PLUGIN, &iface_info);
}
return theme_engine_plugin_type;
}
/* end of GtkThemeEnginePlugin object implementation stuff
*****************************
*****************************/
typedef struct _GtkThemeEngineClass GtkThemeEngineClass;
struct _GtkThemeEngine
{
GTypeModule parent_instance;
GModule *library;
void (*init) (GtkThemeEngine *);
void (*init) (GTypeModule *);
void (*exit) (void);
GtkRcStyle *(*create_rc_style) ();
gchar *name;
};
GSList *plugins; /* TypePlugins for this engine */
guint refcount;
struct _GtkThemeEngineClass
{
GTypeModuleClass parent_class;
};
static GHashTable *engine_hash = NULL;
#ifdef __EMX__
static void gen_8_3_dll_name(gchar *name, gchar *fullname)
static gboolean
gtk_theme_engine_load (GTypeModule *module)
{
/* 8.3 dll filename restriction */
fullname[0] = '_';
strncpy (fullname + 1, name, 7);
fullname[8] = '\0';
strcat (fullname, ".dll");
}
#endif
GtkThemeEngine *engine = GTK_THEME_ENGINE (module);
gchar *fullname;
gchar *engine_path;
fullname = g_module_build_path (NULL, engine->name);
engine_path = gtk_rc_find_module_in_path (fullname);
if (!engine_path)
{
g_warning (_("Unable to locate loadable module in module_path: \"%s\","),
fullname);
g_free (fullname);
return FALSE;
}
g_free (fullname);
/* load the lib */
GTK_NOTE (MISC, g_message ("Loading Theme %s\n", engine_path));
engine->library = g_module_open (engine_path, 0);
g_free(engine_path);
if (!engine->library)
{
g_warning (g_module_error());
return FALSE;
}
/* extract symbols from the lib */
if (!g_module_symbol (engine->library, "theme_init",
(gpointer *)&engine->init) ||
!g_module_symbol (engine->library, "theme_exit",
(gpointer *)&engine->exit) ||
!g_module_symbol (engine->library, "theme_create_rc_style",
(gpointer *)&engine->create_rc_style))
{
g_warning (g_module_error());
g_module_close (engine->library);
return FALSE;
}
/* call the theme's init (theme_init) function to let it */
/* setup anything it needs to set up. */
engine->init (module);
return TRUE;
}
static void
gtk_theme_engine_unload (GTypeModule *module)
{
GtkThemeEngine *engine = GTK_THEME_ENGINE (module);
engine->exit();
g_module_close (engine->library);
engine->library = NULL;
engine->init = NULL;
engine->exit = NULL;
engine->create_rc_style = NULL;
}
static void
gtk_theme_engine_class_init (GtkThemeEngineClass *class)
{
GTypeModuleClass *module_class = G_TYPE_MODULE_CLASS (class);
module_class->load = gtk_theme_engine_load;
module_class->unload = gtk_theme_engine_unload;
}
GType
gtk_theme_engine_get_type (void)
{
static GType theme_engine_type = 0;
if (!theme_engine_type)
{
static const GTypeInfo theme_engine_info = {
sizeof (GtkThemeEngineClass),
NULL, /* base_init */
NULL, /* base_finalize */
(GClassInitFunc) gtk_theme_engine_class_init,
NULL, /* class_finalize */
NULL, /* class_data */
sizeof (GtkThemeEngine),
0, /* n_preallocs */
NULL, /* instance_init */
};
theme_engine_type = g_type_register_static (G_TYPE_TYPE_MODULE, "GtkThemeEngine", &theme_engine_info, 0);
}
return theme_engine_type;
}
GtkThemeEngine*
gtk_theme_engine_get (const gchar *name)
@ -163,250 +167,28 @@ gtk_theme_engine_get (const gchar *name)
if (!engine_hash)
engine_hash = g_hash_table_new (g_str_hash, g_str_equal);
/* get the library name for the theme */
/* get the library name for the theme
*/
result = g_hash_table_lookup (engine_hash, name);
if (!result)
{
gchar *fullname;
gchar *engine_path;
GModule *library;
#ifndef __EMX__
fullname = g_module_build_path (NULL, name);
#else
fullname = g_malloc (13);
gen_8_3_dll_name(name, fullname);
#endif
engine_path = gtk_rc_find_module_in_path (fullname);
#ifdef __EMX__
if (!engine_path)
{
/* try theme name without prefix '_' */
memmove(fullname, fullname + 1, strlen(fullname));
engine_path = gtk_rc_find_module_in_path (fullname);
}
#endif
result = GTK_THEME_ENGINE (g_object_new (GTK_TYPE_THEME_ENGINE, NULL));
g_type_module_set_name (G_TYPE_MODULE (result), name);
if (!engine_path)
{
g_warning (_("Unable to locate loadable module in module_path: \"%s\","),
fullname);
g_free (fullname);
return NULL;
}
g_free (fullname);
/* load the lib */
GTK_NOTE (MISC, g_message ("Loading Theme %s\n", engine_path));
library = g_module_open (engine_path, 0);
g_free(engine_path);
if (!library)
{
g_warning (g_module_error());
return NULL;
}
else
{
result = g_new (GtkThemeEngine, 1);
result->refcount = 1;
result->name = g_strdup (name);
result->library = library;
result->plugins = NULL;
/* extract symbols from the lib */
if (!g_module_symbol (library, "theme_init",
(gpointer *)&result->init) ||
!g_module_symbol (library, "theme_exit",
(gpointer *)&result->exit) ||
!g_module_symbol (library, "theme_create_rc_style",
(gpointer *)&result->create_rc_style))
{
g_warning (g_module_error());
g_free (result);
return NULL;
}
/* call the theme's init (theme_init) function to let it */
/* setup anything it needs to set up. */
result->init((GtkThemeEngine *)result);
g_hash_table_insert (engine_hash, result->name, result);
}
g_hash_table_insert (engine_hash, result->name, result);
}
else
result->refcount++;
return (GtkThemeEngine *)result;
}
if (!g_type_module_use (G_TYPE_MODULE (result)))
return NULL;
void
gtk_theme_engine_ref (GtkThemeEngine *engine)
{
g_return_if_fail (engine != NULL);
engine->refcount++;
}
void
gtk_theme_engine_unref (GtkThemeEngine *engine)
{
GSList *tmp_list;
g_return_if_fail (engine != NULL);
g_return_if_fail (engine->refcount > 0);
engine->refcount--;
if (engine->refcount == 0)
{
engine->exit();
g_hash_table_remove (engine_hash, engine->name);
tmp_list = engine->plugins;
while (tmp_list)
{
GtkThemeEnginePlugin *plugin = tmp_list->data;
plugin->engine = NULL;
tmp_list = tmp_list->next;
}
g_slist_free (engine->plugins);
g_module_close (engine->library);
g_free (engine->name);
g_free (engine);
}
return result;
}
GtkRcStyle *
gtk_theme_engine_create_rc_style (GtkThemeEngine *engine)
{
g_return_val_if_fail (engine != NULL, NULL);
return engine->create_rc_style ();
}
static void
gtk_theme_engine_plugin_use (GTypePlugin *plugin)
{
GtkThemeEnginePlugin *theme_plugin = GTK_THEME_ENGINE_PLUGIN (plugin);
if (theme_plugin->engine == NULL)
{
gtk_theme_engine_get (theme_plugin->engine_name);
if (!theme_plugin->engine)
{
g_warning ("An attempt to create an instance of a type from\n"
"a previously loaded theme engine was made after the engine\n"
"was unloaded, but the engine could not be reloaded or no longer\n"
"implements the type. Bad things will happen.\n");
}
}
else
gtk_theme_engine_ref (theme_plugin->engine);
}
static void
gtk_theme_engine_plugin_unuse (GTypePlugin *plugin)
{
GtkThemeEnginePlugin *theme_plugin = GTK_THEME_ENGINE_PLUGIN (plugin);
g_return_if_fail (theme_plugin->engine != NULL);
gtk_theme_engine_unref (theme_plugin->engine);
}
static void
gtk_theme_engine_plugin_complete_type_info (GTypePlugin *plugin,
GType g_type,
GTypeInfo *info,
GTypeValueTable *value_table)
{
GtkThemeEnginePlugin *theme_plugin = GTK_THEME_ENGINE_PLUGIN (plugin);
*info = theme_plugin->info;
}
/**
* gtk_theme_engine_register_type:
* @engine: a #GtkThemeEngine
* @parent_type: the type for the parent class
* @type_name: name for the type
* @type_info: type information structure
*
* Looks up or registers a type that is implemented with a particular
* theme engine. If a type with name @type_name is already registered,
* the #GType identifier for the type is returned, otherwise the type
* is newly registered, and the resulting #GType identifier returned.
*
* As long as any instances of the type exist, the a reference will be
* held to the theme engine and the theme engine will not be unloaded.
*
* Return value: the type identifier for the class.
**/
GType
gtk_theme_engine_register_type (GtkThemeEngine *engine,
GType parent_type,
const gchar *type_name,
const GTypeInfo *type_info)
{
GtkThemeEnginePlugin *plugin;
GType type;
g_return_val_if_fail (engine != NULL, 0);
g_return_val_if_fail (type_name != NULL, 0);
g_return_val_if_fail (type_info != NULL, 0);
type = g_type_from_name (type_name);
if (type)
plugin = GTK_THEME_ENGINE_PLUGIN (g_type_get_plugin (type));
else
{
plugin = g_object_new (GTK_TYPE_THEME_ENGINE_PLUGIN, NULL);
plugin->engine = NULL;
plugin->engine_name = NULL;
plugin->parent_type = parent_type;
plugin->type = g_type_register_dynamic (parent_type, type_name, G_TYPE_PLUGIN (plugin), 0);
}
if (plugin->engine)
{
if (plugin->engine != engine)
{
g_warning ("Two different theme engines tried to register '%s'.", type_name);
return 0;
}
if (plugin->parent_type != parent_type)
{
g_warning ("Type '%s' recreated with different parent type.\n"
"(was '%s', now '%s')", type_name,
g_type_name (plugin->parent_type),
g_type_name (parent_type));
return 0;
}
}
else
{
plugin->engine = engine;
if (plugin->engine_name)
g_free (plugin->engine_name);
plugin->engine_name = g_strdup (engine->name);
plugin->info = *type_info;
engine->plugins = g_slist_prepend (engine->plugins, plugin);
}
return plugin->type;
}

View File

@ -32,21 +32,17 @@
#include <gtk/gtkstyle.h>
#include <gtk/gtkwidget.h>
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
GtkThemeEngine * gtk_theme_engine_get (const gchar *name);
void gtk_theme_engine_ref (GtkThemeEngine *engine);
void gtk_theme_engine_unref (GtkThemeEngine *engine);
GtkRcStyle * gtk_theme_engine_create_rc_style (GtkThemeEngine *engine);
GType gtk_theme_engine_register_type (GtkThemeEngine *engine,
GType parent_type,
const gchar *type_name,
const GTypeInfo *type_info);
#define GTK_TYPE_THEME_ENGINE (gtk_theme_engine_get_type ())
#define GTK_THEME_ENGINE(theme_engine) (G_TYPE_CHECK_INSTANCE_CAST ((theme_engine), GTK_TYPE_THEME_ENGINE, GtkThemeEngine))
#define GTK_IS_THEME_ENGINE(theme_engine) (G_TYPE_CHECK_INSTANCE_TYPE ((theme_engine), GTK_TYPE_THEME_ENGINE))
GType gtk_theme_engine_get_type (void);
GtkThemeEngine *gtk_theme_engine_get (const gchar *name);
GtkRcStyle *gtk_theme_engine_create_rc_style (GtkThemeEngine *engine);
#ifdef __cplusplus
}

170
gtk/queryimmodules.c Normal file
View File

@ -0,0 +1,170 @@
/* GTK+
* querymodules.c:
*
* Copyright (C) 2000 Red Hat Software
*
* 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., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <glib.h>
#ifdef HAVE_DIRENT_H
#include <dirent.h>
#endif
#include <gmodule.h>
#include <errno.h>
#include <string.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <stdio.h>
#ifdef G_OS_WIN32
#define SOEXT ".dll"
#else
#define SOEXT ".so"
#endif
#include <pango/pango-utils.h>
#include "gtk/gtkrc.h"
#include "gtk/gtkimmodule.h"
void
print_escaped (const char *str)
{
char *tmp = g_strescape (str, NULL);
printf ("\"%s\" ", tmp);
g_free (tmp);
}
gboolean
query_module (const char *dir, const char *name)
{
void (*list) (const GtkIMContextInfo ***contexts,
guint *n_contexts);
void (*init) (GTypeModule *type_module);
void (*exit) (void);
GtkIMContext *(*create) (const gchar *context_id);
GModule *module;
gchar *path;
gboolean error = FALSE;
if (name[0] == G_DIR_SEPARATOR)
path = g_strdup (name);
else
path = g_strconcat (dir, G_DIR_SEPARATOR_S, name, NULL);
module = g_module_open (path, 0);
if (!module)
{
fprintf(stderr, "Cannot load module %s: %s\n", path, g_module_error());
error = TRUE;
}
if (module &&
g_module_symbol (module, "im_module_list", (gpointer)&list) &&
g_module_symbol (module, "im_module_init", (gpointer)&init) &&
g_module_symbol (module, "im_module_exit", (gpointer)&exit) &&
g_module_symbol (module, "im_module_create", (gpointer)&create))
{
const GtkIMContextInfo **contexts;
guint n_contexts;
int i;
print_escaped (path);
fputs ("\n", stdout);
(*list) (&contexts, &n_contexts);
for (i=0; i<n_contexts; i++)
{
print_escaped (contexts[i]->context_id);
print_escaped (contexts[i]->context_name);
print_escaped (contexts[i]->domain);
print_escaped (contexts[i]->domain_dirname);
print_escaped (contexts[i]->default_locales);
fputs ("\n", stdout);
}
fputs ("\n", stdout);
}
else
{
fprintf (stderr, "%s does not export GTK+ IM module API: %s\n", path,
g_module_error());
error = TRUE;
}
g_free (path);
if (module)
g_module_close (module);
return error;
}
int main (int argc, char **argv)
{
char cwd[PATH_MAX];
int i;
char *path;
gboolean error = FALSE;
printf ("# GTK+ Input Method Modules file\n"
"# Automatically generated file, do not edit\n"
"#\n");
if (argc == 1) /* No arguments given */
{
char **dirs;
int i;
path = gtk_rc_get_im_module_path ();
printf ("# ModulesPath = %s\n#\n", path);
dirs = pango_split_file_list (path);
for (i=0; dirs[i]; i++)
{
DIR *dir = opendir (dirs[i]);
if (dir)
{
struct dirent *dent;
while ((dent = readdir (dir)))
{
int len = strlen (dent->d_name);
if (len > 3 && strcmp (dent->d_name + len - strlen (SOEXT), SOEXT) == 0)
error |= query_module (dirs[i], dent->d_name);
}
closedir (dir);
}
}
}
else
{
getcwd (cwd, PATH_MAX);
for (i=1; i<argc; i++)
error |= query_module (cwd, argv[i]);
}
return error ? 1 : 0;
}

View File

@ -9229,11 +9229,14 @@ create_main_window (void)
gtk_widget_show_all (window);
}
void
pixbuf_init ()
static void
test_init ()
{
if (file_exists ("../gdk-pixbuf/.libs/libpixbufloader-pnm.so"))
putenv ("GDK_PIXBUF_MODULEDIR=../gdk-pixbuf/.libs");
{
putenv ("GDK_PIXBUF_MODULEDIR=../gdk-pixbuf/.libs");
putenv ("GTK_IM_MODULE_FILE=./gtk.immodules");
}
}
int
@ -9243,7 +9246,7 @@ main (int argc, char *argv[])
srand (time (NULL));
pixbuf_init ();
test_init ();
gtk_set_locale ();
/* Check to see if we are being run from the correct

View File

@ -1922,13 +1922,32 @@ create_view (Buffer *buffer)
return view;
}
static gboolean
file_exists (const char *filename)
{
struct stat statbuf;
return stat (filename, &statbuf) == 0;
}
void
test_init ()
{
if (file_exists ("../gdk-pixbuf/.libs/libpixbufloader-pnm.so"))
{
putenv ("GDK_PIXBUF_MODULEDIR=../gdk-pixbuf/.libs");
putenv ("GTK_IM_MODULE_FILE=./gtk.immodules");
}
}
int
main (int argc, char** argv)
{
Buffer *buffer;
View *view;
int i;
test_init ();
gtk_set_locale ();
gtk_init (&argc, &argv);
buffer = create_buffer ();

View File

@ -9229,11 +9229,14 @@ create_main_window (void)
gtk_widget_show_all (window);
}
void
pixbuf_init ()
static void
test_init ()
{
if (file_exists ("../gdk-pixbuf/.libs/libpixbufloader-pnm.so"))
putenv ("GDK_PIXBUF_MODULEDIR=../gdk-pixbuf/.libs");
{
putenv ("GDK_PIXBUF_MODULEDIR=../gdk-pixbuf/.libs");
putenv ("GTK_IM_MODULE_FILE=./gtk.immodules");
}
}
int
@ -9243,7 +9246,7 @@ main (int argc, char *argv[])
srand (time (NULL));
pixbuf_init ();
test_init ();
gtk_set_locale ();
/* Check to see if we are being run from the correct

View File

@ -1922,13 +1922,32 @@ create_view (Buffer *buffer)
return view;
}
static gboolean
file_exists (const char *filename)
{
struct stat statbuf;
return stat (filename, &statbuf) == 0;
}
void
test_init ()
{
if (file_exists ("../gdk-pixbuf/.libs/libpixbufloader-pnm.so"))
{
putenv ("GDK_PIXBUF_MODULEDIR=../gdk-pixbuf/.libs");
putenv ("GTK_IM_MODULE_FILE=./gtk.immodules");
}
}
int
main (int argc, char** argv)
{
Buffer *buffer;
View *view;
int i;
test_init ();
gtk_set_locale ();
gtk_init (&argc, &argv);
buffer = create_buffer ();