mirror of
https://github.com/Gnucash/gnucash.git
synced 2025-02-25 18:55:30 -06:00
Bug 605802: Can't input Japanese characters at an account register window on windows with SCIM, IIIMF and XIM
Latest patch by Yasuaki Taniguchi to fix two problems 1) Can't use account separator char when entering account name in a split, and 2) Can't use <SHIFT>+ and <SHIFT>- to go forward/backward a week. git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@18742 57a11ea4-9604-0410-9ed3-97b8803252fd
This commit is contained in:
@@ -184,8 +184,10 @@ gnc_item_edit_draw_info (GncItemEdit *item_edit, int x, int y, TextDrawInfo *inf
|
||||
const gchar *text;
|
||||
PangoRectangle strong_pos;
|
||||
PangoAttribute *attr;
|
||||
PangoAttrList *attr_list;
|
||||
PangoAttrList *attr_list;
|
||||
GnucashSheet *sheet;
|
||||
|
||||
sheet = GNUCASH_SHEET (item_edit->sheet);
|
||||
style = item_edit->style;
|
||||
table = item_edit->sheet->table;
|
||||
|
||||
@@ -233,6 +235,17 @@ gnc_item_edit_draw_info (GncItemEdit *item_edit, int x, int y, TextDrawInfo *inf
|
||||
|
||||
info->layout = gtk_widget_create_pango_layout (GTK_WIDGET (item_edit->sheet), text);
|
||||
|
||||
/* IMContext attributes*/
|
||||
if (sheet->preedit_length && sheet->preedit_attrs != NULL) {
|
||||
PangoAttrList *tmp_attrs = pango_attr_list_new ();
|
||||
pango_attr_list_splice (tmp_attrs, sheet->preedit_attrs,
|
||||
g_utf8_offset_to_pointer (text, sheet->preedit_start_position) - text ,
|
||||
g_utf8_offset_to_pointer (text, sheet->preedit_start_position + sheet->preedit_char_length) - text);
|
||||
pango_layout_set_attributes (info->layout, tmp_attrs);
|
||||
pango_attr_list_unref (tmp_attrs);
|
||||
}
|
||||
|
||||
|
||||
/* Selection */
|
||||
if (start_pos != end_pos)
|
||||
{
|
||||
@@ -298,6 +311,18 @@ gnc_item_edit_draw_info (GncItemEdit *item_edit, int x, int y, TextDrawInfo *inf
|
||||
}
|
||||
|
||||
gnc_item_edit_update_offset (item_edit, info);
|
||||
|
||||
/* Calcurate IMContext aux window position */
|
||||
{
|
||||
gint xoff, yoff;
|
||||
GdkRectangle rect;
|
||||
rect = info->cursor_rect;
|
||||
gnome_canvas_get_scroll_offsets(GNOME_CANVAS(sheet), &xoff, &yoff);
|
||||
rect.x += (x - xoff + item_edit->x_offset);
|
||||
rect.y += (y - yoff);
|
||||
gtk_im_context_set_cursor_location (sheet->im_context, &rect);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -40,18 +40,13 @@
|
||||
#include "gnucash-style.h"
|
||||
#include "gnucash-header.h"
|
||||
#include "gnucash-item-edit.h"
|
||||
#include "split-register.h"
|
||||
#include "gnc-engine.h" // For debugging, e.g. ENTER(), LEAVE()
|
||||
|
||||
#define DEFAULT_REGISTER_HEIGHT 400
|
||||
#define DEFAULT_REGISTER_WIDTH 400
|
||||
|
||||
|
||||
/* FIXME: at least broken on gtk 2.4.14 */
|
||||
/* jsled: and 2.6.8 */
|
||||
/* jsled: and 2.8.8 */
|
||||
/* jsled: and 2.9.{0,1}, as per http://bugzilla.gnome.org/show_bug.cgi?id=342182 */
|
||||
#define GTK_ALLOWED_SELECTION_WITHIN_INSERT_SIGNAL (GTK_MINOR_VERSION < 4)
|
||||
|
||||
/* Register signals */
|
||||
enum
|
||||
{
|
||||
@@ -83,7 +78,19 @@ static void gnucash_sheet_deactivate_cursor_cell (GnucashSheet *sheet);
|
||||
static void gnucash_sheet_activate_cursor_cell (GnucashSheet *sheet,
|
||||
gboolean changed_cells);
|
||||
static void gnucash_sheet_stop_editing (GnucashSheet *sheet);
|
||||
|
||||
static void gnucash_sheet_im_context_reset (GnucashSheet *sheet);
|
||||
static void gnucash_sheet_commit_cb (GtkIMContext *context, const gchar *str,
|
||||
GnucashSheet *sheet);
|
||||
static void gnucash_sheet_preedit_changed_cb (GtkIMContext *context,
|
||||
GnucashSheet *sheet);
|
||||
static gboolean gnucash_sheet_retrieve_surrounding_cb (GtkIMContext *context,
|
||||
GnucashSheet *sheet);
|
||||
static gboolean gnucash_sheet_delete_surrounding_cb (GtkIMContext *context,
|
||||
gint offset,
|
||||
gint n_chars,
|
||||
GnucashSheet *sheet);
|
||||
static gboolean gnucash_sheet_check_direct_update_cell(GnucashSheet *sheet,
|
||||
const VirtualLocation virt_loc);
|
||||
|
||||
/** Implementation *****************************************************/
|
||||
|
||||
@@ -191,15 +198,35 @@ gnucash_sheet_hide_editing_cursor (GnucashSheet *sheet)
|
||||
static void
|
||||
gnucash_sheet_stop_editing (GnucashSheet *sheet)
|
||||
{
|
||||
/* Rollback an uncommitted string if it exists *
|
||||
* *before* disconnecting signal handlers. */
|
||||
gnucash_sheet_im_context_reset(sheet);
|
||||
|
||||
if (sheet->insert_signal != 0)
|
||||
g_signal_handler_disconnect (G_OBJECT(sheet->entry),
|
||||
sheet->insert_signal);
|
||||
if (sheet->delete_signal != 0)
|
||||
g_signal_handler_disconnect (G_OBJECT(sheet->entry),
|
||||
sheet->delete_signal);
|
||||
|
||||
if (sheet->commit_signal != 0)
|
||||
g_signal_handler_disconnect (G_OBJECT(sheet->im_context),
|
||||
sheet->commit_signal);
|
||||
if (sheet->preedit_changed_signal != 0)
|
||||
g_signal_handler_disconnect (G_OBJECT(sheet->im_context),
|
||||
sheet->preedit_changed_signal);
|
||||
if (sheet->retrieve_surrounding_signal != 0)
|
||||
g_signal_handler_disconnect (G_OBJECT(sheet->im_context),
|
||||
sheet->retrieve_surrounding_signal);
|
||||
if (sheet->delete_surrounding_signal != 0)
|
||||
g_signal_handler_disconnect (G_OBJECT(sheet->im_context),
|
||||
sheet->delete_surrounding_signal);
|
||||
sheet->insert_signal = 0;
|
||||
sheet->delete_signal = 0;
|
||||
sheet->commit_signal = 0;
|
||||
sheet->preedit_changed_signal = 0;
|
||||
sheet->retrieve_surrounding_signal = 0;
|
||||
sheet->delete_surrounding_signal = 0;
|
||||
sheet->direct_update_cell = FALSE;
|
||||
|
||||
gnucash_sheet_hide_editing_cursor (sheet);
|
||||
|
||||
@@ -270,11 +297,12 @@ gnucash_sheet_activate_cursor_cell (GnucashSheet *sheet,
|
||||
gnucash_sheet_redraw_block (sheet, virt_loc.vcell_loc);
|
||||
else
|
||||
{
|
||||
gnucash_sheet_im_context_reset(sheet);
|
||||
gnucash_sheet_start_editing_at_cursor (sheet);
|
||||
|
||||
gtk_editable_set_position (editable, cursor_pos);
|
||||
|
||||
gtk_editable_select_region (editable, start_sel, end_sel);
|
||||
sheet->direct_update_cell =
|
||||
gnucash_sheet_check_direct_update_cell (sheet, virt_loc);
|
||||
}
|
||||
|
||||
gtk_widget_grab_focus (GTK_WIDGET(sheet));
|
||||
@@ -657,6 +685,10 @@ gnucash_sheet_finalize (GObject *object)
|
||||
if (G_OBJECT_CLASS (sheet_parent_class)->finalize)
|
||||
(*G_OBJECT_CLASS (sheet_parent_class)->finalize)(object);
|
||||
|
||||
/* Clean up IMContext and unref */
|
||||
gnucash_sheet_im_context_reset(sheet);
|
||||
g_object_unref (sheet->im_context);
|
||||
|
||||
/* This has to come after the parent destroy, so the item edit
|
||||
destruction can do its disconnects. */
|
||||
g_object_unref (sheet->entry);
|
||||
@@ -674,6 +706,8 @@ gnucash_sheet_realize (GtkWidget *widget)
|
||||
window = widget->window;
|
||||
gdk_window_set_back_pixmap (GTK_LAYOUT (widget)->bin_window,
|
||||
NULL, FALSE);
|
||||
gtk_im_context_set_client_window( GNUCASH_SHEET (widget)->im_context,
|
||||
window);
|
||||
}
|
||||
|
||||
|
||||
@@ -801,7 +835,6 @@ gnucash_sheet_modify_current_cell (GnucashSheet *sheet, const gchar *new_text)
|
||||
return retval;
|
||||
}
|
||||
|
||||
#if !GTK_ALLOWED_SELECTION_WITHIN_INSERT_SIGNAL
|
||||
typedef struct {
|
||||
GtkEditable *editable;
|
||||
int start_sel;
|
||||
@@ -824,7 +857,6 @@ gnucash_sheet_select_data_cb (select_info *info)
|
||||
g_free(info);
|
||||
return FALSE; /* This is a one shot function */
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
gnucash_sheet_insert_cb (GtkWidget *widget,
|
||||
@@ -947,29 +979,34 @@ gnucash_sheet_insert_cb (GtkWidget *widget,
|
||||
{
|
||||
retval = old_text;
|
||||
|
||||
/* reset IMContext if disallowed chars and clear preedit*/
|
||||
gnucash_sheet_im_context_reset(sheet);
|
||||
/* the entry was disallowed, so we stop the insert signal */
|
||||
g_signal_stop_emission_by_name (G_OBJECT (sheet->entry),
|
||||
"insert_text");
|
||||
}
|
||||
if (*position < 0)
|
||||
*position = g_utf8_strlen(retval, -1);
|
||||
|
||||
#if GTK_ALLOWED_SELECTION_WITHIN_INSERT_SIGNAL
|
||||
gtk_editable_select_region (editable, start_sel, end_sel);
|
||||
#else
|
||||
{
|
||||
select_info *info;
|
||||
if (start_sel != end_sel) {
|
||||
info = g_malloc(sizeof(*info));
|
||||
info->editable = editable;
|
||||
info->start_sel = start_sel;
|
||||
info->end_sel = end_sel;
|
||||
g_timeout_add(/*ASAP*/ 1,
|
||||
(GSourceFunc)gnucash_sheet_select_data_cb,
|
||||
info);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* sync cursor position and selection to preedit if it exists */
|
||||
if (sheet->preedit_length) {
|
||||
gtk_editable_set_position (editable,
|
||||
sheet->preedit_start_position
|
||||
+ sheet->preedit_cursor_position);
|
||||
}
|
||||
else if (*position < 0)
|
||||
*position = g_utf8_strlen(retval, -1);
|
||||
|
||||
if (start_sel != end_sel) {
|
||||
select_info *info;
|
||||
|
||||
info = g_malloc(sizeof(*info));
|
||||
info->editable = editable;
|
||||
info->start_sel = start_sel;
|
||||
info->end_sel = end_sel;
|
||||
g_timeout_add(/*ASAP*/ 1,
|
||||
(GSourceFunc)gnucash_sheet_select_data_cb,
|
||||
info);
|
||||
}
|
||||
|
||||
g_string_free (new_text_gs, TRUE);
|
||||
g_string_free (change_text_gs, TRUE);
|
||||
}
|
||||
@@ -1071,8 +1108,9 @@ gnucash_sheet_delete_cb (GtkWidget *widget,
|
||||
}
|
||||
|
||||
gtk_editable_set_position (editable, cursor_position);
|
||||
|
||||
if (start_sel != end_sel)
|
||||
gtk_editable_select_region(editable, start_sel, end_sel);
|
||||
gtk_editable_select_region (editable, start_sel, end_sel);
|
||||
|
||||
g_string_free (new_text_gs, TRUE);
|
||||
}
|
||||
@@ -1136,7 +1174,12 @@ gnucash_sheet_focus_in_event (GtkWidget *widget, GdkEventFocus *event)
|
||||
(widget, event);
|
||||
|
||||
gnc_item_edit_focus_in (GNC_ITEM_EDIT(sheet->item_editor));
|
||||
gtk_im_context_focus_in(sheet->im_context);
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
gnucash_sheet_im_context_reset(sheet);
|
||||
#endif /* G_OS_WIN32 */
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@@ -1149,11 +1192,42 @@ gnucash_sheet_focus_out_event (GtkWidget *widget, GdkEventFocus *event)
|
||||
(*GTK_WIDGET_CLASS (sheet_parent_class)->focus_out_event)
|
||||
(widget, event);
|
||||
|
||||
gnc_item_edit_focus_out (GNC_ITEM_EDIT(sheet->item_editor));
|
||||
#ifdef G_OS_WIN32
|
||||
gnucash_sheet_im_context_reset(sheet);
|
||||
#endif /* G_OS_WIN32 */
|
||||
|
||||
gtk_im_context_focus_out (sheet->im_context);
|
||||
gnc_item_edit_focus_out (GNC_ITEM_EDIT(sheet->item_editor));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gnucash_sheet_check_direct_update_cell(GnucashSheet *sheet,
|
||||
const VirtualLocation virt_loc)
|
||||
{
|
||||
const gchar *dupdate_list[] =
|
||||
{ /* From src/register/ledger-core/split-register-layout.c */
|
||||
/* DATE_CELL_TYPE_NAME */
|
||||
DATE_CELL,
|
||||
DDUE_CELL,
|
||||
/* COMBO_CELL_TYPE_NAME */
|
||||
XFRM_CELL,
|
||||
MXFRM_CELL,
|
||||
ACTN_CELL,
|
||||
NULL,
|
||||
};
|
||||
const gchar *cell_name;
|
||||
int i;
|
||||
|
||||
cell_name = gnc_table_get_cell_name (sheet->table, virt_loc);
|
||||
for (i=0; dupdate_list[i]; i++){
|
||||
if (gnc_cell_name_equal (cell_name,
|
||||
dupdate_list[i]))
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gnucash_sheet_start_editing_at_cursor (GnucashSheet *sheet)
|
||||
{
|
||||
@@ -1184,8 +1258,26 @@ gnucash_sheet_start_editing_at_cursor (GnucashSheet *sheet)
|
||||
sheet->delete_signal =
|
||||
g_signal_connect(G_OBJECT(sheet->entry), "delete_text",
|
||||
G_CALLBACK(gnucash_sheet_delete_cb), sheet);
|
||||
|
||||
sheet->commit_signal =
|
||||
g_signal_connect (G_OBJECT (sheet->im_context), "commit",
|
||||
G_CALLBACK (gnucash_sheet_commit_cb), sheet);
|
||||
sheet->preedit_changed_signal =
|
||||
g_signal_connect (G_OBJECT (sheet->im_context), "preedit_changed",
|
||||
G_CALLBACK (gnucash_sheet_preedit_changed_cb),
|
||||
sheet);
|
||||
sheet->retrieve_surrounding_signal =
|
||||
g_signal_connect (G_OBJECT (sheet->im_context),
|
||||
"retrieve_surrounding",
|
||||
G_CALLBACK (gnucash_sheet_retrieve_surrounding_cb),
|
||||
sheet);
|
||||
sheet->delete_surrounding_signal =
|
||||
g_signal_connect (G_OBJECT (sheet->im_context), "delete_surrounding",
|
||||
G_CALLBACK (gnucash_sheet_delete_surrounding_cb),
|
||||
sheet);
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
gnucash_motion_event (GtkWidget *widget, GdkEventMotion *event)
|
||||
{
|
||||
@@ -1645,7 +1737,7 @@ gnucash_sheet_direct_event(GnucashSheet *sheet, GdkEvent *event)
|
||||
}
|
||||
|
||||
static gint
|
||||
gnucash_sheet_key_press_event (GtkWidget *widget, GdkEventKey *event)
|
||||
gnucash_sheet_key_press_event_internal (GtkWidget *widget, GdkEventKey *event)
|
||||
{
|
||||
Table *table;
|
||||
GnucashSheet *sheet;
|
||||
@@ -1673,7 +1765,7 @@ gnucash_sheet_key_press_event (GtkWidget *widget, GdkEventKey *event)
|
||||
|
||||
/* Don't process any keystrokes where a modifier key (Alt,
|
||||
* Meta, etc.) is being held down. This should't include
|
||||
* MOD2, aka NUM LOCK. */
|
||||
* MOD2, aka NUM LOCK. */
|
||||
if (event->state & (GDK_MOD1_MASK | GDK_MOD3_MASK |
|
||||
GDK_MOD4_MASK | GDK_MOD5_MASK))
|
||||
pass_on = TRUE;
|
||||
@@ -1771,8 +1863,17 @@ gnucash_sheet_key_press_event (GtkWidget *widget, GdkEventKey *event)
|
||||
}
|
||||
|
||||
/* Forward the keystroke to the input line */
|
||||
if (pass_on)
|
||||
return gtk_widget_event (sheet->entry, (GdkEvent *) event);
|
||||
if (pass_on) {
|
||||
GValue gval = {0,};
|
||||
gboolean result;
|
||||
g_value_init (&gval, G_TYPE_BOOLEAN);
|
||||
g_value_set_boolean (&gval, TRUE);
|
||||
g_object_set_property (G_OBJECT (sheet->entry), "editable", &gval);
|
||||
result = gtk_widget_event (sheet->entry, (GdkEvent *) event);
|
||||
g_value_set_boolean (&gval, FALSE);
|
||||
g_object_set_property (G_OBJECT (sheet->entry), "editable", &gval);
|
||||
return result;
|
||||
}
|
||||
|
||||
abort_move = gnc_table_traverse_update (table, cur_virt_loc,
|
||||
direction, &new_virt_loc);
|
||||
@@ -1787,6 +1888,245 @@ gnucash_sheet_key_press_event (GtkWidget *widget, GdkEventKey *event)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gint
|
||||
gnucash_sheet_key_press_event (GtkWidget *widget, GdkEventKey *event)
|
||||
{
|
||||
GnucashSheet *sheet;
|
||||
gint result;
|
||||
|
||||
g_return_val_if_fail(widget != NULL, TRUE);
|
||||
g_return_val_if_fail(GNUCASH_IS_SHEET(widget), TRUE);
|
||||
g_return_val_if_fail(event != NULL, TRUE);
|
||||
|
||||
sheet = GNUCASH_SHEET (widget);
|
||||
|
||||
/* save shift state to enable <shift minus> and <shift equal>.
|
||||
see bug#60582 comment#27 2)
|
||||
*/
|
||||
if(sheet->preedit_length)
|
||||
sheet->shift_state = 0;
|
||||
else
|
||||
sheet->shift_state = event->state & GDK_SHIFT_MASK;
|
||||
|
||||
if (gtk_im_context_filter_keypress (sheet->im_context, event)) {
|
||||
sheet->need_im_reset = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return gnucash_sheet_key_press_event_internal (widget, event);
|
||||
}
|
||||
|
||||
static gint
|
||||
gnucash_sheet_key_release_event(GtkWidget *widget, GdkEventKey *event)
|
||||
{
|
||||
GnucashSheet *sheet;
|
||||
|
||||
g_return_val_if_fail(widget != NULL, TRUE);
|
||||
g_return_val_if_fail(GNUCASH_IS_SHEET(widget), TRUE);
|
||||
g_return_val_if_fail(event != NULL, TRUE);
|
||||
|
||||
sheet = GNUCASH_SHEET (widget);
|
||||
|
||||
if(gtk_im_context_filter_keypress (sheet->im_context, event)){
|
||||
sheet->need_im_reset = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gnucash_sheet_im_context_reset_flags(GnucashSheet *sheet)
|
||||
{
|
||||
sheet->preedit_length = 0;
|
||||
sheet->preedit_char_length = 0;
|
||||
sheet->preedit_start_position = -1;
|
||||
sheet->preedit_cursor_position = 0;
|
||||
sheet->preedit_selection_length = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
gnucash_sheet_im_context_reset(GnucashSheet *sheet)
|
||||
{
|
||||
if (sheet->need_im_reset) {
|
||||
if (sheet->preedit_attrs) {
|
||||
pango_attr_list_unref (sheet->preedit_attrs);
|
||||
sheet->preedit_attrs = NULL;
|
||||
}
|
||||
gtk_im_context_reset (sheet->im_context);
|
||||
sheet->need_im_reset = FALSE;
|
||||
}
|
||||
gnucash_sheet_im_context_reset_flags(sheet);
|
||||
}
|
||||
|
||||
static void
|
||||
gnucash_sheet_commit_cb (GtkIMContext *context, const gchar *str,
|
||||
GnucashSheet *sheet)
|
||||
{
|
||||
GtkEditable *editable;
|
||||
gint tmp_pos, length, sel_start, sel_end;
|
||||
|
||||
g_return_if_fail(strlen(str) > 0);
|
||||
g_return_if_fail(sheet->editing == TRUE);
|
||||
|
||||
editable = GTK_EDITABLE (sheet->entry);
|
||||
|
||||
if(strlen(str) == 1 && sheet->direct_update_cell) {
|
||||
/* Reconstruct keyevent and direct update */
|
||||
GdkEvent *event;
|
||||
GdkEventKey *keyevent;
|
||||
gboolean result;
|
||||
|
||||
event = gdk_event_new (GDK_KEY_PRESS);
|
||||
keyevent = (GdkEventKey *) event;
|
||||
keyevent->keyval = gdk_unicode_to_keyval(str[0]);
|
||||
keyevent->state |= sheet->shift_state;
|
||||
result = gnucash_sheet_direct_event(sheet, event);
|
||||
gdk_event_free(event);
|
||||
|
||||
if (result) {
|
||||
gnucash_sheet_im_context_reset_flags(sheet);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* delete preedit string from editable*/
|
||||
if (sheet->preedit_length){
|
||||
g_signal_handler_block (G_OBJECT (sheet->entry),
|
||||
sheet->delete_signal);
|
||||
gtk_editable_delete_text (editable, sheet->preedit_start_position,
|
||||
sheet->preedit_start_position
|
||||
+ sheet->preedit_char_length);
|
||||
g_signal_handler_unblock (G_OBJECT (sheet->entry),
|
||||
sheet->delete_signal);
|
||||
}
|
||||
|
||||
if (gtk_editable_get_selection_bounds (editable, &sel_start, &sel_end)){
|
||||
if (sel_start != sel_end) {
|
||||
sheet->preedit_selection_length = 0;
|
||||
gtk_editable_delete_selection (editable);
|
||||
}
|
||||
}
|
||||
|
||||
tmp_pos = (sheet->preedit_start_position == -1)?
|
||||
gtk_editable_get_position (editable)
|
||||
:sheet->preedit_start_position;
|
||||
gtk_editable_insert_text (editable, str, strlen (str), &tmp_pos);
|
||||
gtk_editable_set_position (editable, tmp_pos);
|
||||
gnucash_sheet_im_context_reset_flags(sheet);
|
||||
}
|
||||
|
||||
static void
|
||||
gnucash_sheet_preedit_changed_cb (GtkIMContext *context, GnucashSheet *sheet)
|
||||
{
|
||||
gchar *preedit_string;
|
||||
GtkEditable *editable;
|
||||
|
||||
g_return_if_fail(context != NULL);
|
||||
g_return_if_fail(sheet->editing == TRUE);
|
||||
|
||||
editable = GTK_EDITABLE (sheet->entry);
|
||||
|
||||
/* save preedit start position and selection */
|
||||
if(sheet->preedit_length == 0) {
|
||||
int start_pos, end_pos;
|
||||
if ( gtk_editable_get_selection_bounds (editable, &start_pos, &end_pos)) {
|
||||
sheet->preedit_start_position = start_pos;
|
||||
sheet->preedit_selection_length = end_pos - start_pos;
|
||||
} else {
|
||||
sheet->preedit_start_position =
|
||||
gtk_editable_get_position (editable);
|
||||
}
|
||||
}
|
||||
#ifdef G_OS_WIN32
|
||||
else {/* sheet->preedit_length != 0 */
|
||||
/* On Windows, gtk_im_context_reset() in gnucash_sheet_key_press_event()
|
||||
* always returns FALSE because Windows IME handles key press at the
|
||||
* top level window. So sheet->need_im_reset = TRUE here. */
|
||||
sheet->need_im_reset = TRUE;
|
||||
}
|
||||
#endif /* G_OS_WIN32 */
|
||||
|
||||
if (sheet->preedit_attrs)
|
||||
pango_attr_list_unref (sheet->preedit_attrs);
|
||||
|
||||
gtk_im_context_get_preedit_string (sheet->im_context, &preedit_string,
|
||||
&sheet->preedit_attrs, &(sheet->preedit_cursor_position));
|
||||
|
||||
if (sheet->preedit_length){
|
||||
g_signal_handler_block (G_OBJECT (sheet->entry),
|
||||
sheet->delete_signal);
|
||||
gtk_editable_delete_text (editable, sheet->preedit_start_position,
|
||||
sheet->preedit_start_position
|
||||
+ sheet->preedit_char_length);
|
||||
g_signal_handler_unblock (G_OBJECT (sheet->entry),
|
||||
sheet->delete_signal);
|
||||
}
|
||||
|
||||
sheet->preedit_length = strlen (preedit_string);
|
||||
sheet->preedit_char_length = g_utf8_strlen(preedit_string, -1);
|
||||
|
||||
if (sheet->preedit_length) {
|
||||
int tmp_pos = sheet->preedit_start_position;
|
||||
g_signal_handler_block (G_OBJECT (sheet->entry),
|
||||
sheet->insert_signal);
|
||||
gtk_editable_insert_text (editable, preedit_string, sheet->preedit_length,
|
||||
&tmp_pos);
|
||||
g_signal_handler_unblock (G_OBJECT (sheet->entry),
|
||||
sheet->insert_signal);
|
||||
|
||||
gtk_editable_set_position (editable, sheet->preedit_start_position
|
||||
+ sheet->preedit_cursor_position);
|
||||
|
||||
if( sheet->preedit_selection_length != 0) {
|
||||
gtk_editable_select_region (editable,
|
||||
sheet->preedit_start_position
|
||||
+ sheet->preedit_char_length,
|
||||
sheet->preedit_start_position
|
||||
+ sheet->preedit_char_length
|
||||
+ sheet->preedit_selection_length);
|
||||
}
|
||||
} else {
|
||||
gnucash_sheet_im_context_reset_flags(sheet);
|
||||
}
|
||||
|
||||
g_free (preedit_string);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gnucash_sheet_retrieve_surrounding_cb (GtkIMContext *context, GnucashSheet *sheet)
|
||||
{
|
||||
GtkEditable *editable;
|
||||
gchar *surrounding;
|
||||
gint cur_pos;
|
||||
|
||||
editable = GTK_EDITABLE (sheet->entry);
|
||||
surrounding = gtk_editable_get_chars (editable, 0, -1);
|
||||
cur_pos = gtk_editable_get_position (editable);
|
||||
|
||||
gtk_im_context_set_surrounding (context,
|
||||
surrounding, strlen (surrounding),
|
||||
g_utf8_offset_to_pointer (surrounding, cur_pos) - surrounding);
|
||||
g_free (surrounding);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gnucash_sheet_delete_surrounding_cb (GtkIMContext *context, gint offset,
|
||||
gint n_chars, GnucashSheet *sheet)
|
||||
{
|
||||
GtkEditable *editable;
|
||||
gint cur_pos;
|
||||
|
||||
editable = GTK_EDITABLE (sheet->entry);
|
||||
cur_pos = gtk_editable_get_position (editable);
|
||||
|
||||
gtk_editable_delete_text (editable,
|
||||
cur_pos + offset,
|
||||
cur_pos + offset + n_chars);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gnucash_sheet_goto_virt_loc (GnucashSheet *sheet, VirtualLocation virt_loc)
|
||||
@@ -2237,6 +2577,11 @@ gnucash_sheet_selection_received (GtkWidget *widget,
|
||||
static void
|
||||
gnucash_sheet_realize_entry (GnucashSheet *sheet, GtkWidget *entry)
|
||||
{
|
||||
GValue gval = {0,};
|
||||
g_value_init (&gval, G_TYPE_BOOLEAN);
|
||||
g_value_set_boolean (&gval, FALSE);
|
||||
g_object_set_property (G_OBJECT (entry), "editable", &gval);
|
||||
|
||||
gtk_widget_realize (entry);
|
||||
}
|
||||
|
||||
@@ -2368,6 +2713,7 @@ gnucash_sheet_class_init (GnucashSheetClass *class)
|
||||
widget_class->focus_out_event = gnucash_sheet_focus_out_event;
|
||||
|
||||
widget_class->key_press_event = gnucash_sheet_key_press_event;
|
||||
widget_class->key_release_event = gnucash_sheet_key_release_event;
|
||||
widget_class->button_press_event = gnucash_button_press_event;
|
||||
widget_class->button_release_event = gnucash_button_release_event;
|
||||
widget_class->motion_notify_event = gnucash_motion_event;
|
||||
@@ -2412,6 +2758,22 @@ gnucash_sheet_init (GnucashSheet *sheet)
|
||||
sheet->blocks = g_table_new (sizeof (SheetBlock),
|
||||
gnucash_sheet_block_construct,
|
||||
gnucash_sheet_block_destroy, NULL);
|
||||
|
||||
/* setup IMContext */
|
||||
sheet->im_context = gtk_im_multicontext_new ();
|
||||
sheet->preedit_length = 0;
|
||||
sheet->preedit_char_length = 0;
|
||||
sheet->preedit_start_position = -1;
|
||||
sheet->preedit_cursor_position = 0;
|
||||
sheet->preedit_selection_length = 0;
|
||||
sheet->preedit_attrs = NULL;
|
||||
sheet->direct_update_cell = FALSE;
|
||||
sheet->need_im_reset = FALSE;
|
||||
sheet->commit_signal = 0;
|
||||
sheet->preedit_changed_signal = 0;
|
||||
sheet->retrieve_surrounding_signal = 0;
|
||||
sheet->delete_surrounding_signal = 0;
|
||||
sheet->shift_state = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -126,6 +126,25 @@ typedef struct
|
||||
|
||||
GFunc moved_cb;
|
||||
gpointer moved_cb_data;
|
||||
|
||||
/* IMContext */
|
||||
GtkIMContext *im_context;
|
||||
gint preedit_length; /* num of bytes */
|
||||
gint preedit_char_length; /* num of chars in UTF-8 */
|
||||
gint preedit_start_position; /* save preedit start position *
|
||||
* combined with selection start */
|
||||
gint preedit_cursor_position; /* save preedit cursor position */
|
||||
gint preedit_selection_length;
|
||||
PangoAttrList *preedit_attrs;
|
||||
gboolean need_im_reset;
|
||||
gboolean direct_update_cell;
|
||||
guint commit_signal;
|
||||
guint preedit_changed_signal;
|
||||
guint retrieve_surrounding_signal;
|
||||
guint delete_surrounding_signal;
|
||||
|
||||
guint shift_state;
|
||||
|
||||
} GnucashSheet;
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user