Update Serbian translation from master branch
[wmaker-crm.git] / WINGs / winputmethod.c
blobeff25b4f735166f29be363655bb6e82b650e5530
2 #include <X11/Xlib.h>
4 #include "wconfig.h"
6 #include "WINGsP.h"
8 typedef struct W_IMContext {
9 XIM xim;
10 XIMStyle ximstyle;
11 } WMIMContext;
13 static void instantiateIM_cb(Display * display, XPointer client_data, XPointer call_data)
15 /* Parameter not used, but tell the compiler that it is ok */
16 (void) display;
17 (void) call_data;
19 W_InitIM((W_Screen *) client_data);
22 static void destroyIM_cb(XIM xim, XPointer client_data, XPointer call_data)
24 W_Screen *scr = (W_Screen *) client_data;
25 W_View *target;
27 /* Parameter not used, but tell the compiler that it is ok */
28 (void) call_data;
30 if (scr->imctx->xim != xim)
31 return;
33 target = scr->rootView->childrenList;
34 while (target != NULL) {
35 W_DestroyIC(target);
36 target = target->nextSister;
39 wfree(scr->imctx);
40 scr->imctx = NULL;
42 XRegisterIMInstantiateCallback(scr->display, NULL, NULL, NULL, instantiateIM_cb, (XPointer) scr);
45 void W_InitIM(W_Screen * scr)
47 XIM xim;
49 if (scr->imctx)
50 return;
52 xim = XOpenIM(scr->display, NULL, NULL, NULL);
54 if (xim) {
55 XIMStyles *im_styles;
56 XIMCallback cb;
57 int i;
59 scr->imctx = wmalloc(sizeof(WMIMContext));
60 scr->imctx->xim = xim;
62 cb.callback = destroyIM_cb;
63 cb.client_data = (XPointer) scr;
64 if (XSetIMValues(scr->imctx->xim, XNDestroyCallback, &cb, NULL))
65 wwarning(_("could not add destroy callback for XIM input method"));
66 XUnregisterIMInstantiateCallback(scr->display, NULL, NULL, NULL, instantiateIM_cb, (XPointer) scr);
67 /* Get available input style */
68 XGetIMValues(scr->imctx->xim, XNQueryInputStyle, &im_styles, NULL);
70 scr->imctx->ximstyle = 0;
72 for (i = 0; i < im_styles->count_styles && scr->imctx->ximstyle == 0; i++) {
73 if ((im_styles->supported_styles[i] & XIMPreeditPosition) &&
74 (im_styles->supported_styles[i] & XIMStatusNothing)) {
75 scr->imctx->ximstyle = XIMPreeditPosition | XIMStatusNothing;
76 } else if ((im_styles->supported_styles[i] & XIMPreeditNothing) &&
77 (im_styles->supported_styles[i] & XIMStatusNothing)) {
78 scr->imctx->ximstyle = XIMPreeditNothing | XIMStatusNothing;
81 XFree(im_styles);
82 } else {
83 XRegisterIMInstantiateCallback(scr->display, NULL, NULL, NULL, instantiateIM_cb, (XPointer) scr);
87 void W_CreateIC(WMView * view)
89 WMScreen *scr = W_VIEW_SCREEN(view);
90 XVaNestedList preedit_attr = NULL;
92 if (view->xic || !view->flags.realized || !scr->imctx)
93 return;
95 if (scr->imctx->ximstyle & XIMPreeditPosition) {
96 XPoint spot;
97 XRectangle rect;
98 int ofs;
100 ofs = (view->size.height - WMFontHeight(scr->normalFont)) / 2;
102 rect.x = ofs;
103 rect.y = ofs;
104 rect.height = WMFontHeight(scr->normalFont);
105 rect.width = view->size.width - ofs * 2;
106 spot.x = rect.x;
107 spot.y = rect.y + rect.height;
109 // this really needs to be changed, but I don't know how yet -Dan
110 // it used to be like this with fontsets, but no longer applies to xft
111 preedit_attr = XVaCreateNestedList(0, XNSpotLocation, &spot,
112 XNArea, &rect, XNFontInfo, scr->normalFont->font, NULL);
115 view->xic = XCreateIC(scr->imctx->xim, XNInputStyle, scr->imctx->ximstyle,
116 XNClientWindow, view->window,
117 preedit_attr ? XNPreeditAttributes : NULL, preedit_attr, NULL);
119 if (preedit_attr)
120 XFree(preedit_attr);
122 if (view->xic) {
123 unsigned long fevent = 0;
124 XGetICValues(view->xic, XNFilterEvents, &fevent, NULL);
125 XSelectInput(scr->display, view->window,
126 ButtonPressMask | ButtonReleaseMask | ExposureMask |
127 KeyPressMask | FocusChangeMask | ButtonMotionMask | fevent);
131 void W_DestroyIC(WMView * view)
133 if (view->xic) {
134 XDestroyIC(view->xic);
135 view->xic = 0;
139 static void setPreeditArea(W_View * view)
141 WMScreen *scr = W_VIEW_SCREEN(view);
142 XVaNestedList preedit_attr = NULL;
144 if (view->xic && (scr->imctx->ximstyle & XIMPreeditPosition)) {
145 XRectangle rect;
146 int ofs;
148 ofs = (view->size.height - WMFontHeight(scr->normalFont)) / 2;
149 rect.x = ofs;
150 rect.y = ofs;
151 rect.height = WMFontHeight(scr->normalFont);
152 rect.width = view->size.width - ofs * 2;
154 preedit_attr = XVaCreateNestedList(0, XNArea, &rect, NULL);
155 XSetICValues(view->xic, XNPreeditAttributes, preedit_attr, NULL);
157 if (preedit_attr) {
158 XFree(preedit_attr);
163 void W_FocusIC(WMView * view)
165 WMScreen *scr = W_VIEW_SCREEN(view);
167 if (view->xic) {
168 XSetICFocus(view->xic);
169 XSetICValues(view->xic, XNFocusWindow, view->window, NULL);
171 if (scr->imctx->ximstyle & XIMPreeditPosition) {
172 setPreeditArea(view);
177 void W_UnFocusIC(WMView * view)
179 if (view->xic) {
180 XUnsetICFocus(view->xic);
184 void W_SetPreeditPositon(W_View * view, int x, int y)
186 WMScreen *scr = W_VIEW_SCREEN(view);
187 XVaNestedList preedit_attr = NULL;
189 if (view->xic && (scr->imctx->ximstyle & XIMPreeditPosition)) {
190 XPoint spot;
191 int ofs;
193 ofs = (view->size.height - WMFontHeight(scr->normalFont)) / 2;
194 spot.x = x;
195 spot.y = y + view->size.height - ofs - 3;
196 preedit_attr = XVaCreateNestedList(0, XNSpotLocation, &spot, NULL);
197 XSetICValues(view->xic, XNPreeditAttributes, preedit_attr, NULL);
198 if (preedit_attr) {
199 XFree(preedit_attr);
204 int W_LookupString(W_View *view, XKeyPressedEvent *event, char *buffer, int buflen, KeySym *keysym, Status *status)
206 WMScreen *scr = W_VIEW_SCREEN(view);
208 XSetInputFocus(scr->display, view->window, RevertToParent, CurrentTime);
210 #ifdef X_HAVE_UTF8_STRING
211 if (view->xic)
212 return Xutf8LookupString(view->xic, event, buffer, buflen, keysym, status);
213 #endif
214 return XLookupString(event, buffer, buflen, keysym, (XComposeStatus *) status);
218 * Map a keycode to the corresponding keysym
219 * To replace the deprecated X11 function XKeycodeToKeysym
221 KeySym W_KeycodeToKeysym(Display *display, KeyCode keycode, int index)
223 static int min_kc = -1;
224 static int max_kc;
225 int num_syms;
226 KeySym *key_syms;
227 KeySym ks;
229 XDisplayKeycodes(display, &min_kc, &max_kc);
230 if (keycode < min_kc || keycode > max_kc || index < 0) {
231 return NoSymbol;
234 key_syms = XGetKeyboardMapping(display, keycode, 1, &num_syms);
235 if (index >= num_syms) {
236 XFree(key_syms);
237 return NoSymbol;
240 ks = key_syms[index];
241 XFree(key_syms);
243 return ks;