📄 gtkimcontextxim.c
字号:
{ PangoAttribute *attr; gint start_index = g_utf8_offset_to_pointer (str, start_pos) - str; gint end_index = g_utf8_offset_to_pointer (str, end_pos) - str; if (feedback & XIMUnderline) { attr = pango_attr_underline_new (PANGO_UNDERLINE_SINGLE); attr->start_index = start_index; attr->end_index = end_index; pango_attr_list_change (attrs, attr); } if (feedback & XIMReverse) { attr = pango_attr_foreground_new (0xffff, 0xffff, 0xffff); attr->start_index = start_index; attr->end_index = end_index; pango_attr_list_change (attrs, attr); attr = pango_attr_background_new (0, 0, 0); attr->start_index = start_index; attr->end_index = end_index; pango_attr_list_change (attrs, attr); } if (feedback & ~FEEDBACK_MASK) g_warning ("Unrendered feedback style: %#lx", feedback & ~FEEDBACK_MASK);}static void gtk_im_context_xim_get_preedit_string (GtkIMContext *context, gchar **str, PangoAttrList **attrs, gint *cursor_pos){ GtkIMContextXIM *context_xim = GTK_IM_CONTEXT_XIM (context); gchar *utf8 = g_ucs4_to_utf8 (context_xim->preedit_chars, context_xim->preedit_length, NULL, NULL, NULL); if (attrs) { int i; XIMFeedback last_feedback = 0; gint start = -1; *attrs = pango_attr_list_new (); for (i = 0; i < context_xim->preedit_length; i++) { XIMFeedback new_feedback = context_xim->feedbacks[i] & FEEDBACK_MASK; if (new_feedback != last_feedback) { if (start >= 0) add_feedback_attr (*attrs, utf8, last_feedback, start, i); last_feedback = new_feedback; start = i; } } if (start >= 0) add_feedback_attr (*attrs, utf8, last_feedback, start, i); } if (str) *str = utf8; else g_free (utf8); if (cursor_pos) *cursor_pos = context_xim->preedit_cursor;}static intpreedit_start_callback (XIC xic, XPointer client_data, XPointer call_data){ GtkIMContext *context = GTK_IM_CONTEXT (client_data); GtkIMContextXIM *context_xim = GTK_IM_CONTEXT_XIM (context); if (!context_xim->finalizing) g_signal_emit_by_name (context, "preedit_start"); return -1; /* No length limit */} static voidpreedit_done_callback (XIC xic, XPointer client_data, XPointer call_data){ GtkIMContext *context = GTK_IM_CONTEXT (client_data); GtkIMContextXIM *context_xim = GTK_IM_CONTEXT_XIM (context); if (context_xim->preedit_length) { context_xim->preedit_length = 0; if (!context_xim->finalizing) g_signal_emit_by_name (context_xim, "preedit_changed"); } if (!context_xim->finalizing) g_signal_emit_by_name (context, "preedit_end"); } static gintxim_text_to_utf8 (GtkIMContextXIM *context, XIMText *xim_text, gchar **text){ gint text_length = 0; GError *error = NULL; gchar *result = NULL; if (xim_text && xim_text->string.multi_byte) { if (xim_text->encoding_is_wchar) { g_warning ("Wide character return from Xlib not currently supported"); *text = NULL; return 0; } if (strcmp (context->mb_charset, "UTF-8") == 0) result = g_strdup (xim_text->string.multi_byte); else result = g_convert (xim_text->string.multi_byte, -1, "UTF-8", context->mb_charset, NULL, NULL, &error); if (result) { text_length = g_utf8_strlen (result, -1); if (text_length != xim_text->length) { g_warning ("Size mismatch when converting text from input method: supplied length = %d\n, result length = %d", xim_text->length, text_length); } } else { g_warning ("Error converting text from IM to UCS-4: %s", error->message); g_error_free (error); *text = NULL; return 0; } *text = result; return text_length; } else { *text = NULL; return 0; }}static voidpreedit_draw_callback (XIC xic, XPointer client_data, XIMPreeditDrawCallbackStruct *call_data){ GtkIMContextXIM *context = GTK_IM_CONTEXT_XIM (client_data); XIMText *new_xim_text = call_data->text; gint new_text_length; gunichar *new_text = NULL; gint i; gint diff; gint new_length; gchar *tmp; gint chg_first = CLAMP (call_data->chg_first, 0, context->preedit_length); gint chg_length = CLAMP (call_data->chg_length, 0, context->preedit_length - chg_first); context->preedit_cursor = call_data->caret; if (chg_first != call_data->chg_first || chg_length != call_data->chg_length) g_warning ("Invalid change to preedit string, first=%d length=%d (orig length == %d)", call_data->chg_first, call_data->chg_length, context->preedit_length); new_text_length = xim_text_to_utf8 (context, new_xim_text, &tmp); if (tmp) { new_text = g_utf8_to_ucs4_fast (tmp, -1, NULL); g_free (tmp); } diff = new_text_length - chg_length; new_length = context->preedit_length + diff; if (new_length > context->preedit_size) { context->preedit_size = new_length; context->preedit_chars = g_renew (gunichar, context->preedit_chars, new_length); context->feedbacks = g_renew (XIMFeedback, context->feedbacks, new_length); } if (diff < 0) { for (i = chg_first + chg_length ; i < context->preedit_length; i++) { context->preedit_chars[i + diff] = context->preedit_chars[i]; context->feedbacks[i + diff] = context->feedbacks[i]; } } else { for (i = context->preedit_length - 1; i >= chg_first + chg_length ; i--) { context->preedit_chars[i + diff] = context->preedit_chars[i]; context->feedbacks[i + diff] = context->feedbacks[i]; } } for (i = 0; i < new_text_length; i++) { context->preedit_chars[chg_first + i] = new_text[i]; context->feedbacks[chg_first + i] = new_xim_text->feedback[i]; } context->preedit_length += diff; if (new_text) g_free (new_text); if (!context->finalizing) g_signal_emit_by_name (context, "preedit_changed");} static voidpreedit_caret_callback (XIC xic, XPointer client_data, XIMPreeditCaretCallbackStruct *call_data){ GtkIMContextXIM *context = GTK_IM_CONTEXT_XIM (client_data); if (call_data->direction == XIMAbsolutePosition) { context->preedit_cursor = call_data->position; if (!context->finalizing) g_signal_emit_by_name (context, "preedit_changed"); } else { g_warning ("Caret movement command: %d %d %d not supported", call_data->position, call_data->direction, call_data->style); }} static voidstatus_start_callback (XIC xic, XPointer client_data, XPointer call_data){ return;} static voidstatus_done_callback (XIC xic, XPointer client_data, XPointer call_data){ return;}static voidstatus_draw_callback (XIC xic, XPointer client_data, XIMStatusDrawCallbackStruct *call_data){ GtkIMContextXIM *context = GTK_IM_CONTEXT_XIM (client_data); if (call_data->type == XIMTextType) { gchar *text; xim_text_to_utf8 (context, call_data->data.text, &text); if (context->status_window) status_window_set_text (context->status_window, text ? text : ""); } else /* bitmap */ { g_print ("Status drawn with bitmap - id = %#lx\n", call_data->data.bitmap); }}static voidstring_conversion_callback (XIC xic, XPointer client_data, XPointer call_data){ GtkIMContextXIM *context_xim; XIMStringConversionCallbackStruct *conv_data; gchar *surrounding; gint cursor_index; context_xim = (GtkIMContextXIM *)client_data; conv_data = (XIMStringConversionCallbackStruct *)call_data; if (gtk_im_context_get_surrounding ((GtkIMContext *)context_xim, &surrounding, &cursor_index)) { gchar *text = NULL; gsize text_len = 0; gint subst_offset = 0, subst_nchars = 0; gint i; gchar *p = surrounding + cursor_index, *q; gshort position = (gshort)conv_data->position; if (position > 0) { for (i = position; i > 0 && *p; --i) p = g_utf8_next_char (p); if (i > 0) return; } /* According to X11R6.4 Xlib - C Library Reference Manual * section 13.5.7.3 String Conversion Callback, * XIMStringConversionPosition is starting position _relative_ * to current client's cursor position. So it should be able * to be negative, or referring to a position before the cursor * would be impossible. But current X protocol defines this as * unsigned short. So, compiler may warn about the value range * here. We hope the X protocol is fixed soon. */ else if (position < 0) { for (i = position; i < 0 && p > surrounding; ++i) p = g_utf8_prev_char (p); if (i < 0) return; } switch (conv_data->direction) { case XIMForwardChar: for (i = conv_data->factor, q = p; i > 0 && *q; --i) q = g_utf8_next_char (q); if (i > 0) break; text = g_locale_from_utf8 (p, q - p, NULL, &text_len, NULL); subst_offset = position; subst_nchars = conv_data->factor; break; case XIMBackwardChar: for (i = conv_data->factor, q = p; i > 0 && q > surrounding; --i) q = g_utf8_prev_char (q); if (i > 0) break; text = g_locale_from_utf8 (q, p - q, NULL, &text_len, NULL); subst_offset = position - conv_data->factor; subst_nchars = conv_data->factor; break; case XIMForwardWord: case XIMBackwardWord: case XIMCaretUp: case XIMCaretDown: case XIMNextLine: case XIMPreviousLine: case XIMLineStart: case XIMLineEnd: case XIMAbsolutePosition: case XIMDontChange: default: break; } /* block out any failure happenning to "text", including conversion */ if (text) { conv_data->text = (XIMStringConversionText *) malloc (sizeof (XIMStringConversionText)); if (conv_data->text) { conv_data->text->length = text_len; conv_data->text->feedback = NULL; conv_data->text->encoding_is_wchar = False; conv_data->text->string.mbs = (char *)malloc (text_len); if (conv_data->text->string.mbs) memcpy (conv_data->text->string.mbs, text, text_len); else { free (conv_data->text); conv_data->text = NULL; } } g_free (text); } if (conv_data->operation == XIMStringConversionSubstitution && subst_nchars > 0) { gtk_im_context_delete_surrounding ((GtkIMContext *)context_xim, subst_offset, subst_nchars); } g_free (surrounding); }}static XVaNestedListset_preedit_callback (GtkIMContextXIM *context_xim){ context_xim->preedit_start_callback.client_data = (XPointer)context_xim; context_xim->preedit_start_callback.callback = (XIMProc)preedit_start_callback; context_xim->preedit_done_callback.client_data = (XPointer)context_xim; context_xim->preedit_done_callback.callback = (XIMProc)preedit_done_callback; context_xim->preedit_draw_callback.client_data = (XPointer)context_xim; context_xim->preedit_draw_callback.callback = (XIMProc)preedit_draw_callback; context_xim->preedit_caret_callback.client_data = (XPointer)context_xim; context_xim->preedit_caret_callback.callback = (XIMProc)preedit_caret_callback; return XVaCreateNestedList (0, XNPreeditStartCallback, &context_xim->preedit_start_callback, XNPreeditDoneCallback, &context_xim->preedit_done_callback, XNPreeditDrawCallback, &context_xim->preedit_draw_callback, XNPreeditCaretCallback, &context_xim->preedit_caret_callback, NULL);}static XVaNestedListset_status_callback (GtkIMContextXIM *context_xim){ context_xim->status_start_callback.client_data = (XPointer)context_xim; context_xim->status_start_callback.callback = (XIMProc)status_start_callback; context_xim->status_done_callback.client_data = (XPointer)context_xim; context_xim->status_done_callback.callback = (XIMProc)status_done_callback; context_xim->status_draw_callback.client_data = (XPointer)context_xim; context_xim->status_draw_callback.callback = (XIMProc)status_draw_callback; return XVaCreateNestedList (0, XNStatusStartCallback, &context_xim->status_start_callback, XNStatusDoneCallback, &context_xim->status_done_callback, XNStatusDrawCallback, &context_xim->status_draw_callback, NULL);}static voidset_string_conversion_callback (GtkIMContextXIM *context_xim, XIC xic){ if (!context_xim->im_info->supports_string_conversion) return; context_xim->string_conversion_callback.client_data = (XPointer)context_xim; context_xim->string_conversion_callback.callback = (XIMProc)string_conversion_callback; XSetICValues (xic, XNStringConversionCallback, (XPointer)&context_xim->string_conversion_callback, NULL);}static XICgtk_im_context_xim_get_ic (GtkIMContextXIM *context_xim){ if (context_xim->im_info == NULL || context_xim->im_info->im == NULL) return NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -