From: Jihoon Kim <imfine98@gmail.com>
authorraster <raster@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Tue, 20 Dec 2011 09:49:55 +0000 (09:49 +0000)
committerraster <raster@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Tue, 20 Dec 2011 09:49:55 +0000 (09:49 +0000)
Subject: [E-devel] [PATCH] support to get style attribute of XIM module

ATM, edje entry doesn't display the style of preedit string such as
underline, reverse, and Highlight.
It's because XIM module doesn't provide the style attribute.
This patch is made for providing the style attibute information to
entry or other editable widget.

git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/ecore@66381 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

ChangeLog
src/modules/immodules/xim/ecore_imf_xim.c

index d907eed..a8a0a1a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
 2011-12-20 Carsten Haitzler (The Rasterman)
 
         * Fix probable leak for g_static_mutex's on some architectures
+
+2011-12-20 Jihoon Kim
+
+       * Add XIM attribute support to Ecore_IMF
+
index 7c40606..f2fd6a4 100644 (file)
@@ -23,6 +23,8 @@
 static Eina_List *open_ims = NULL;
 #endif
 
+#define FEEDBACK_MASK (XIMReverse | XIMUnderline | XIMHighlight)
+
 typedef struct _XIM_Im_Info XIM_Im_Info;
 struct _XIM_Im_Info
 {
@@ -51,6 +53,7 @@ struct _Ecore_IMF_Context_Data
    Eina_Bool      finalizing;
    Eina_Bool      has_focus;
    Eina_Bool      in_toplevel;
+   XIMFeedback   *feedbacks;
 
    XIMCallback    preedit_start_cb;
    XIMCallback    preedit_done_cb;
@@ -63,6 +66,12 @@ Ecore_IMF_Context_Data *imf_context_data_new();
 void                    imf_context_data_destroy(Ecore_IMF_Context_Data *imf_context_data);
 
 #ifdef ENABLE_XIM
+static void add_feedback_attr (Eina_List **attrs,
+                               const char   *str,
+                               XIMFeedback   feedback,
+                               int           start_pos,
+                               int           end_pos);
+
 static void reinitialize_ic(Ecore_IMF_Context *ctx);
 static void reinitialize_all_ics(XIM_Im_Info *info);
 static void set_ic_client_window(Ecore_IMF_Context *ctx,
@@ -99,6 +108,19 @@ static void xim_destroy_callback(XIM      xim,
                                  XPointer call_data);
 #endif
 
+static unsigned int
+utf8_offset_to_index(const char *str, int offset)
+{
+   int index = 0;
+   int i;
+   for (i = 0; i < offset; i++)
+     {
+        eina_unicode_utf8_get_next(str, &index);
+     }
+
+   return index;
+}
+
 static void
 _ecore_imf_context_xim_add(Ecore_IMF_Context *ctx)
 {
@@ -204,6 +226,43 @@ _ecore_imf_context_xim_preedit_string_get(Ecore_IMF_Context *ctx,
 }
 
 static void
+_ecore_imf_context_xim_preedit_string_with_attributes_get(Ecore_IMF_Context *ctx,
+                                          char             **str,
+                                          Eina_List        **attrs,
+                                          int               *cursor_pos)
+{
+   EINA_LOG_DBG("in");
+
+   Ecore_IMF_Context_Data *imf_context_data = ecore_imf_context_data_get(ctx);
+
+   _ecore_imf_context_xim_preedit_string_get(ctx, str, cursor_pos);
+
+   if (!attrs) return;
+   if (!imf_context_data || !imf_context_data->feedbacks) return;
+
+   int i = 0;
+   XIMFeedback last_feedback = 0;
+   int start = -1;
+
+   for (i = 0; i < imf_context_data->preedit_length; i++)
+     {
+        XIMFeedback new_feedback = imf_context_data->feedbacks[i] & FEEDBACK_MASK;
+
+        if (new_feedback != last_feedback)
+          {
+             if (start >= 0)
+               add_feedback_attr (attrs, *str, last_feedback, start, i);
+
+             last_feedback = new_feedback;
+             start = i;
+          }
+     }
+
+   if (start >= 0)
+     add_feedback_attr (attrs, *str, last_feedback, start, i);
+}
+
+static void
 _ecore_imf_context_xim_focus_in(Ecore_IMF_Context *ctx)
 {
    EINA_LOG_DBG("in");
@@ -291,11 +350,18 @@ _ecore_imf_context_xim_reset(Ecore_IMF_Context *ctx)
 
    XFree(preedit_attr);
 
+   if (imf_context_data->feedbacks)
+     {
+        free(imf_context_data->feedbacks);
+        imf_context_data->feedbacks = NULL;
+     }
+
    if(imf_context_data->preedit_length)
      {
         imf_context_data->preedit_length = 0;
         free(imf_context_data->preedit_chars);
         imf_context_data->preedit_chars = NULL;
+
         ecore_imf_context_preedit_changed_event_add(ctx);
      }
 
@@ -333,6 +399,36 @@ _ecore_imf_context_xim_use_preedit_set(Ecore_IMF_Context *ctx,
 }
 
 static void
+add_feedback_attr (Eina_List **attrs,
+                   const char   *str,
+                   XIMFeedback   feedback,
+                   int           start_pos,
+                   int           end_pos)
+{
+   Ecore_IMF_Preedit_Attr *attr = NULL;
+
+   unsigned int start_index = utf8_offset_to_index (str, start_pos);
+   unsigned int end_index = utf8_offset_to_index (str, end_pos);
+
+   if (feedback & FEEDBACK_MASK)
+    {
+        attr = (Ecore_IMF_Preedit_Attr *)calloc(1, sizeof(Ecore_IMF_Preedit_Attr));
+        attr->start_index = start_index;
+        attr->end_index = end_index;
+        *attrs = eina_list_append(*attrs, (void *)attr);
+    }
+
+   if (feedback & XIMUnderline)
+     attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB1;
+
+   if (feedback & XIMReverse)
+     attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB2;
+
+   if (feedback & XIMHighlight)
+     attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB3;
+}
+
+static void
 _ecore_imf_context_xim_cursor_location_set (Ecore_IMF_Context   *ctx,
                                             int x, int y, int w, int h)
 {
@@ -608,7 +704,7 @@ static Ecore_IMF_Context_Class xim_class = {
    .use_preedit_set = _ecore_imf_context_xim_use_preedit_set,
    .input_mode_set = NULL,
    .filter_event = _ecore_imf_context_xim_filter_event,
-   .preedit_string_with_attributes_get = NULL,
+   .preedit_string_with_attributes_get = _ecore_imf_context_xim_preedit_string_with_attributes_get,
    .prediction_allow_set = NULL,
    .autocapital_type_set = NULL,
    .control_panel_show = NULL,
@@ -712,6 +808,13 @@ imf_context_data_destroy(Ecore_IMF_Context_Data *imf_context_data)
      XDestroyIC(imf_context_data->ic);
 
    free(imf_context_data->preedit_chars);
+
+   if (imf_context_data->feedbacks)
+     {
+        free(imf_context_data->feedbacks);
+        imf_context_data->feedbacks = NULL;
+     }
+
    free(imf_context_data->locale);
    free(imf_context_data);
 }
@@ -811,6 +914,7 @@ preedit_draw_callback(XIC                           xic __UNUSED__,
    Eina_Unicode *new_text = NULL;
    Eina_UStrbuf *preedit_bufs = NULL;
    int new_text_length;
+   int i = 0;
 
    preedit_bufs = eina_ustrbuf_new();
    if(imf_context_data->preedit_chars) {
@@ -854,6 +958,20 @@ preedit_draw_callback(XIC                           xic __UNUSED__,
       imf_context_data->preedit_length =
           eina_unicode_strlen(imf_context_data->preedit_chars);
 
+      if (imf_context_data->feedbacks)
+        {
+           free(imf_context_data->feedbacks);
+           imf_context_data->feedbacks = NULL;
+        }
+
+      if (imf_context_data->preedit_length > 0)
+        {
+           imf_context_data->feedbacks = calloc(imf_context_data->preedit_length, sizeof(XIMFeedback));
+
+           for (i = 0; i < imf_context_data->preedit_length; i++)
+             imf_context_data->feedbacks[i] = t->feedback[i];
+        }
+
       ecore_imf_context_preedit_changed_event_add(ctx);
    }