1 /******************************************************************
2 
3          Copyright 1994, 1995 by Sun Microsystems, Inc.
4          Copyright 1993, 1994 by Hewlett-Packard Company
5 
6 Permission to use, copy, modify, distribute, and sell this software
7 and its documentation for any purpose is hereby granted without fee,
8 provided that the above copyright notice appear in all copies and
9 that both that copyright notice and this permission notice appear
10 in supporting documentation, and that the name of Sun Microsystems, Inc.
11 and Hewlett-Packard not be used in advertising or publicity pertaining to
12 distribution of the software without specific, written prior permission.
13 Sun Microsystems, Inc. and Hewlett-Packard make no representations about
14 the suitability of this software for any purpose.  It is provided "as is"
15 without express or implied warranty.
16 
17 SUN MICROSYSTEMS INC. AND HEWLETT-PACKARD COMPANY DISCLAIMS ALL
18 WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
19 WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
20 SUN MICROSYSTEMS, INC. AND HEWLETT-PACKARD COMPANY BE LIABLE FOR ANY
21 SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
22 RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
23 CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
24 IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
25 
26   Author: Hidetoshi Tajima(tajima@Eng.Sun.COM) Sun Microsystems, Inc.
27 
28 ******************************************************************/
29 #include <X11/Xlib.h>
30 #include <X11/Xmd.h>
31 
32 #include "Xi18n.h"
33 #include "IC.h"
34 #include "fcitx-utils/log.h"
35 #include "xim.h"
36 #include "fcitx-utils/utils.h"
37 #include "ximhandler.h"
38 #include "fcitx/instance.h"
39 
40 /**
41  * @file IC.c
42  *
43  * Process XIM Input Context
44  */
45 
46 static int Is(char *attr, XICAttribute * attr_list);
47 static void StoreIC(FcitxXimIC * rec, IMChangeICStruct * call_data);
48 
Is(char * attr,XICAttribute * attr_list)49 static int Is(char *attr, XICAttribute * attr_list)
50 {
51     return !strcmp(attr, attr_list->name);
52 }
53 
XimCheckIC(void * arg,FcitxInputContext * context,void * priv)54 boolean  XimCheckIC(void* arg, FcitxInputContext* context, void* priv)
55 {
56     FCITX_UNUSED(arg);
57     CARD16* picid = (CARD16*) priv;
58     FcitxXimIC* rec = (FcitxXimIC*) context->privateic;
59     if (rec->id == *picid)
60         return true;
61     else
62         return false;
63 }
64 
StoreIC(FcitxXimIC * rec,IMChangeICStruct * call_data)65 static void StoreIC(FcitxXimIC * rec, IMChangeICStruct * call_data)
66 {
67     XICAttribute   *ic_attr = call_data->ic_attr;
68     XICAttribute   *pre_attr = call_data->preedit_attr;
69     XICAttribute   *sts_attr = call_data->status_attr;
70     register int    i;
71 
72     for (i = 0; i < (int) call_data->ic_attr_num; i++, ic_attr++) {
73         if (Is(XNInputStyle, ic_attr))
74             rec->input_style = *(INT32 *) ic_attr->value;
75 
76         else if (Is(XNClientWindow, ic_attr)) {
77             CARD32 value = *(CARD32*) ic_attr->value;
78             rec->client_win = (Window) value;
79         } else if (Is(XNFocusWindow, ic_attr)) {
80             CARD32 value = *(CARD32*) ic_attr->value;
81             rec->focus_win = (Window) value;
82         }
83     }
84 
85     for (i = 0; i < (int) call_data->preedit_attr_num; i++, pre_attr++) {
86         if (Is(XNArea, pre_attr)) {
87             rec->pre_attr.area = *(XRectangle *) pre_attr->value;
88         } else if (Is(XNAreaNeeded, pre_attr)) {
89             rec->pre_attr.area_needed = *(XRectangle *) pre_attr->value;
90         } else if (Is(XNSpotLocation, pre_attr)) {
91             rec->pre_attr.spot_location = *(XPoint *) pre_attr->value;
92         } else if (Is(XNColormap, pre_attr))
93             rec->pre_attr.cmap = *(Colormap *) pre_attr->value;
94 
95         else if (Is(XNStdColormap, pre_attr))
96             rec->pre_attr.cmap = *(Colormap *) pre_attr->value;
97 
98         else if (Is(XNForeground, pre_attr)) {
99             rec->pre_attr.foreground = *(CARD32 *) pre_attr->value;
100         } else if (Is(XNBackground, pre_attr)) {
101             rec->pre_attr.background = *(CARD32 *) pre_attr->value;
102         } else if (Is(XNBackgroundPixmap, pre_attr))
103             rec->pre_attr.bg_pixmap = *(Pixmap *) pre_attr->value;
104 
105         else if (Is(XNFontSet, pre_attr)) {
106             int size = strlen((char*)pre_attr->value);
107             if (rec->pre_attr.base_font != NULL) {
108                 if (Is(rec->pre_attr.base_font, pre_attr)) {
109                     continue;
110                 }
111                 rec->pre_attr.base_font = realloc(rec->pre_attr.base_font,
112                                                   size);
113             } else {
114                 rec->pre_attr.base_font = malloc(size);
115             }
116             memcpy(rec->pre_attr.base_font, pre_attr->value, size);
117         } else if (Is(XNLineSpace, pre_attr))
118             rec->pre_attr.line_space = *(CARD32 *) pre_attr->value;
119         else if (Is(XNCursor, pre_attr))
120             rec->pre_attr.cursor = *(Cursor *) pre_attr->value;
121     }
122 
123     for (i = 0; i < (int) call_data->status_attr_num; i++, sts_attr++) {
124         if (Is(XNArea, sts_attr)) {
125             rec->sts_attr.area = *(XRectangle *) sts_attr->value;
126         } else if (Is(XNAreaNeeded, sts_attr)) {
127             rec->sts_attr.area_needed = *(XRectangle *) sts_attr->value;
128         } else if (Is(XNColormap, sts_attr)) {
129             rec->sts_attr.cmap = *(Colormap *) sts_attr->value;
130         } else if (Is(XNStdColormap, sts_attr))
131             rec->sts_attr.cmap = *(Colormap *) sts_attr->value;
132 
133         else if (Is(XNForeground, sts_attr)) {
134             rec->sts_attr.foreground = *(CARD32 *) sts_attr->value;
135         } else if (Is(XNBackground, sts_attr)) {
136             rec->sts_attr.background = *(CARD32 *) sts_attr->value;
137         }
138 
139         else if (Is(XNBackgroundPixmap, sts_attr))
140             rec->sts_attr.bg_pixmap = *(Pixmap *) sts_attr->value;
141 
142         else if (Is(XNFontSet, sts_attr)) {
143             int size = strlen((char*)sts_attr->value) + 1;
144             if (rec->sts_attr.base_font != NULL) {
145                 if (Is(rec->sts_attr.base_font, sts_attr))
146                     continue;
147                 rec->sts_attr.base_font = realloc(rec->sts_attr.base_font,
148                                                   size);
149             } else {
150                 rec->sts_attr.base_font = malloc(size);
151             }
152             memcpy(rec->sts_attr.base_font, sts_attr->value, size);
153         } else if (Is(XNLineSpace, sts_attr)) {
154             rec->sts_attr.line_space = *(CARD32 *) sts_attr->value;
155         } else if (Is(XNCursor, sts_attr)) {
156             rec->sts_attr.cursor = *(Cursor *) sts_attr->value;
157         }
158     }
159 }
160 
161 /**
162  * Interface for XIM Create Input Context
163  *
164  * @param  context Input Context
165  * @param  priv private data passed by CreateIC
166  * @return void
167  **/
XimCreateIC(void * arg,FcitxInputContext * context,void * priv)168 void XimCreateIC(void* arg, FcitxInputContext* context, void *priv)
169 {
170     FcitxXimFrontend* xim = (FcitxXimFrontend*) arg;
171     IMChangeICStruct * call_data = (IMChangeICStruct *)priv;
172     context->privateic = fcitx_utils_malloc0(sizeof(FcitxXimIC));
173     FcitxXimIC* privic = (FcitxXimIC*) context->privateic;
174     FcitxGlobalConfig* config = FcitxInstanceGetGlobalConfig(xim->owner);
175 
176     privic->connect_id = call_data->connect_id;
177     privic->id = ++ xim->icid;
178     privic->offset_x = -1;
179     privic->offset_y = -1;
180     StoreIC(privic, call_data);
181     SetTrackPos(xim, context, call_data);
182     call_data->icid = privic->id;
183 
184     if (config->shareState == ShareState_PerProgram)
185         FcitxInstanceSetICStateFromSameApplication(xim->owner, xim->frontendid, context);
186 
187     if (privic->input_style & XIMPreeditCallbacks)
188         context->contextCaps |= CAPACITY_PREEDIT;
189     else
190         context->contextCaps &= ~CAPACITY_PREEDIT;
191 
192     return;
193 }
194 
195 /**
196  * Destroy Input Context for XIM
197  *
198  * @param context Input Context to Destroy
199  * @return void
200  **/
XimDestroyIC(void * arg,FcitxInputContext * context)201 void XimDestroyIC(void* arg, FcitxInputContext* context)
202 {
203     FCITX_UNUSED(arg);
204     //free resource
205     FcitxXimIC* privic = (FcitxXimIC*) context->privateic;
206     if (privic->resource_name)
207         free(privic->resource_name);
208     if (privic->resource_class)
209         free(privic->resource_class);
210 
211     context->privateic = NULL;
212     free(privic);
213     return;
214 }
215 
216 /**
217  * Set Input Context Data
218  *
219  * @param call_data
220  * @return void
221  **/
XimSetIC(FcitxXimFrontend * xim,IMChangeICStruct * call_data)222 void XimSetIC(FcitxXimFrontend* xim, IMChangeICStruct * call_data)
223 {
224     FcitxInputContext   *ic = FcitxInstanceFindIC(xim->owner, xim->frontendid, &call_data->icid);
225 
226     if (ic == NULL)
227         return;
228     FcitxXimIC* rec = (FcitxXimIC*) ic->privateic;
229     StoreIC(rec, call_data);
230 
231     if (rec->input_style & XIMPreeditCallbacks)
232         ic->contextCaps |= CAPACITY_PREEDIT;
233     else
234         ic->contextCaps &= ~CAPACITY_PREEDIT;
235 
236     return;
237 }
238 
239 /**
240  * Fetch Input Context Data
241  *
242  * @param call_data
243  * @return void
244  **/
XimGetIC(FcitxXimFrontend * xim,IMChangeICStruct * call_data)245 void XimGetIC(FcitxXimFrontend* xim, IMChangeICStruct * call_data)
246 {
247     XICAttribute   *ic_attr = call_data->ic_attr;
248     XICAttribute   *pre_attr = call_data->preedit_attr;
249     XICAttribute   *sts_attr = call_data->status_attr;
250     register int    i;
251     FcitxInputContext *ic = FcitxInstanceFindIC(xim->owner, xim->frontendid, &call_data->icid);
252     if (ic == NULL)
253         return;
254     FcitxXimIC* rec = (FcitxXimIC*) ic->privateic;
255 
256     if (rec == NULL)
257         return;
258     for (i = 0; i < (int) call_data->ic_attr_num; i++, ic_attr++) {
259         if (Is(XNFilterEvents, ic_attr)) {
260             ic_attr->value = (void *) malloc(sizeof(CARD32));
261             *(CARD32 *) ic_attr->value = KeyPressMask | KeyReleaseMask;
262             ic_attr->value_length = sizeof(CARD32);
263         }
264     }
265 
266     /* preedit attributes */
267     for (i = 0; i < (int) call_data->preedit_attr_num; i++, pre_attr++) {
268         if (Is(XNArea, pre_attr)) {
269             pre_attr->value = (void *) malloc(sizeof(XRectangle));
270             *(XRectangle *) pre_attr->value = rec->pre_attr.area;
271             pre_attr->value_length = sizeof(XRectangle);
272 
273         } else if (Is(XNAreaNeeded, pre_attr)) {
274             pre_attr->value = (void *) malloc(sizeof(XRectangle));
275             *(XRectangle *) pre_attr->value = rec->pre_attr.area_needed;
276             pre_attr->value_length = sizeof(XRectangle);
277 
278         } else if (Is(XNSpotLocation, pre_attr)) {
279             pre_attr->value = (void *) malloc(sizeof(XPoint));
280             *(XPoint *) pre_attr->value = rec->pre_attr.spot_location;
281             pre_attr->value_length = sizeof(XPoint);
282 
283         } else if (Is(XNFontSet, pre_attr)) {
284             CARD16          base_len = (CARD16) strlen(rec->pre_attr.base_font);
285             int             total_len = sizeof(CARD16) + (CARD16) base_len;
286             char           *p;
287 
288             pre_attr->value = (void *) malloc(total_len);
289             p = (char *) pre_attr->value;
290             memcpy(p, &base_len, sizeof(CARD16));
291             p += sizeof(CARD16);
292             strncpy(p, rec->pre_attr.base_font, base_len);
293             pre_attr->value_length = total_len;
294 
295         } else if (Is(XNForeground, pre_attr)) {
296             pre_attr->value = (void *) malloc(sizeof(long));
297             *(long *) pre_attr->value = rec->pre_attr.foreground;
298             pre_attr->value_length = sizeof(long);
299 
300         } else if (Is(XNBackground, pre_attr)) {
301             pre_attr->value = (void *) malloc(sizeof(long));
302             *(long *) pre_attr->value = rec->pre_attr.background;
303             pre_attr->value_length = sizeof(long);
304 
305         } else if (Is(XNLineSpace, pre_attr)) {
306             pre_attr->value = (void *) malloc(sizeof(long));
307             *(long *) pre_attr->value = 18;
308             pre_attr->value_length = sizeof(long);
309         }
310     }
311 
312     /* status attributes */
313     for (i = 0; i < (int) call_data->status_attr_num; i++, sts_attr++) {
314         if (Is(XNArea, sts_attr)) {
315             sts_attr->value = (void *) malloc(sizeof(XRectangle));
316             *(XRectangle *) sts_attr->value = rec->sts_attr.area;
317             sts_attr->value_length = sizeof(XRectangle);
318 
319         } else if (Is(XNAreaNeeded, sts_attr)) {
320             sts_attr->value = (void *) malloc(sizeof(XRectangle));
321             *(XRectangle *) sts_attr->value = rec->sts_attr.area_needed;
322             sts_attr->value_length = sizeof(XRectangle);
323 
324         } else if (Is(XNFontSet, sts_attr)) {
325             CARD16          base_len = (CARD16) strlen(rec->sts_attr.base_font);
326             int             total_len = sizeof(CARD16) + (CARD16) base_len;
327             char           *p;
328 
329             sts_attr->value = (void *) malloc(total_len);
330             p = (char *) sts_attr->value;
331             memcpy(p, &base_len, sizeof(CARD16));
332             p += sizeof(CARD16);
333             strncpy(p, rec->sts_attr.base_font, base_len);
334             sts_attr->value_length = total_len;
335 
336         } else if (Is(XNForeground, sts_attr)) {
337             sts_attr->value = (void *) malloc(sizeof(long));
338             *(long *) sts_attr->value = rec->sts_attr.foreground;
339             sts_attr->value_length = sizeof(long);
340 
341         } else if (Is(XNBackground, sts_attr)) {
342             sts_attr->value = (void *) malloc(sizeof(long));
343             *(long *) sts_attr->value = rec->sts_attr.background;
344             sts_attr->value_length = sizeof(long);
345 
346         } else if (Is(XNLineSpace, sts_attr)) {
347             sts_attr->value = (void *) malloc(sizeof(long));
348             *(long *) sts_attr->value = 18;
349             sts_attr->value_length = sizeof(long);
350         }
351     }
352 }
353 
XimCheckICFromSameApplication(void * arg,FcitxInputContext * icToCheck,FcitxInputContext * ic)354 boolean XimCheckICFromSameApplication(void* arg, FcitxInputContext* icToCheck, FcitxInputContext* ic)
355 {
356     FCITX_UNUSED(arg);
357     FcitxXimIC* ximictoCheck = GetXimIC(icToCheck);
358     FcitxXimIC* ximic = GetXimIC(ic);
359 
360     return ximictoCheck->connect_id == ximic->connect_id;
361 }
362 
363 // kate: indent-mode cstyle; space-indent on; indent-width 0;
364