forked from AuroraMiddleware/gtk
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:
parent
b9d3287313
commit
dfba226908
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
2684
gtk/gtkentry.c
2684
gtk/gtkentry.c
File diff suppressed because it is too large
Load Diff
@ -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 */
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
@ -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
527
gtk/gtkimmodule.c
Normal 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
62
gtk/gtkimmodule.h
Normal 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__
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
859
gtk/gtkoldeditable.c
Normal 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
142
gtk/gtkoldeditable.h
Normal 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__ */
|
@ -184,7 +184,6 @@ gtk_preview_init (GtkPreview *preview)
|
||||
void
|
||||
gtk_preview_uninit (void)
|
||||
{
|
||||
|
||||
/* unimplemented */
|
||||
}
|
||||
|
||||
|
127
gtk/gtkrc.c
127
gtk/gtkrc.c
@ -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)
|
||||
{
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
542
gtk/gtktext.c
542
gtk/gtktext.c
File diff suppressed because it is too large
Load Diff
@ -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,
|
||||
|
@ -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 == >k_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 == >k_text_right_mark_type ||
|
||||
seg->type == >k_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 != >k_text_right_mark_type &&
|
||||
seg->next->type != >k_text_left_mark_type &&
|
||||
seg->next->type != >k_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 == >k_text_right_mark_type ||
|
||||
seg->type == >k_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
|
||||
}
|
||||
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
456
gtk/gtkthemes.c
456
gtk/gtkthemes.c
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
170
gtk/queryimmodules.c
Normal 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;
|
||||
}
|
@ -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
|
||||
|
@ -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 ();
|
||||
|
@ -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
|
||||
|
@ -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 ();
|
||||
|
Loading…
Reference in New Issue
Block a user