Mercurial > hg > xemacs-beta
comparison src/input-method-xlib.c @ 428:3ecd8885ac67 r21-2-22
Import from CVS: tag r21-2-22
author | cvs |
---|---|
date | Mon, 13 Aug 2007 11:28:15 +0200 |
parents | |
children | 3a7e78e1142d |
comparison
equal
deleted
inserted
replaced
427:0a0253eac470 | 428:3ecd8885ac67 |
---|---|
1 /* Various functions for X11R5+ input methods, using the Xlib interface. | |
2 Copyright (C) 1996 Sun Microsystems. | |
3 | |
4 This file is part of XEmacs. | |
5 | |
6 XEmacs is free software; you can redistribute it and/or modify it | |
7 under the terms of the GNU General Public License as published by the | |
8 Free Software Foundation; either version 2, or (at your option) any | |
9 later version. | |
10 | |
11 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
14 for more details. | |
15 | |
16 You should have received a copy of the GNU General Public License | |
17 along with XEmacs; see the file COPYING. If not, write to | |
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
19 Boston, MA 02111-1307, USA. */ | |
20 | |
21 /* Synched up with: Not in FSF. */ | |
22 | |
23 /* Written by Martin Buchholz. */ | |
24 | |
25 /* This file implements an interface to X input methods, available | |
26 with X11R5 and above. See O'Reilly, Xlib programmer's guide, | |
27 and X11 R6 release guide chapters on internationalized input, | |
28 for further details */ | |
29 | |
30 /* | |
31 Policy: | |
32 | |
33 The XIM is of the device, by the device, for the device. | |
34 The XIC is of each frame, by each frame, for each frame. | |
35 The exceptions are: | |
36 1. Activate XICs on poor frames when the XIM is back. | |
37 2. Deactivate all the XICs when the XIM go down. | |
38 | |
39 Methods: | |
40 | |
41 - Register a callback for an XIM when the X device is being initialized. | |
42 XIM_init_device (d) { XRegisterIMInstantiateCallback (); } | |
43 The "XRegisterIMInstantiateCallback" is called when an XIM become | |
44 available on the X display. | |
45 | |
46 - Catch the XIC when the frame is being initialized if XIM was available. | |
47 XIM_init_frame (f) { ... XCreateIC (); ... } | |
48 | |
49 - Release the XIC when the frame is being closed. | |
50 XIM_delete_frame (f) { ... FRAME_X_XIC (f) = NULL; ... } | |
51 "XIM_delete_frame" is a "DestroyCallback" function declared in | |
52 XIM_init_frame (); | |
53 | |
54 - Release all the XICs when the XIM was down accidentally. | |
55 In IMDestroyCallback: | |
56 DEVICE_FRAME_LOOP (...) { FRAME_X_XIC (f) = NULL; } | |
57 | |
58 - Re-enable XIC for all the frames which doesn't have XIC when the XIM | |
59 is back. | |
60 In IMInstantiateCallback: | |
61 DEVICE_FRAME_LOOP (...) { XIM_init_frame (f); } | |
62 | |
63 | |
64 Note: | |
65 | |
66 - Currently, we don't use XDestroyIC because of _XimProtoCloseIM | |
67 (internally registered as im->methods->close) does "Xfree (ic)". | |
68 | |
69 */ | |
70 | |
71 #include <config.h> | |
72 #include "lisp.h" | |
73 #include <X11/Xlocale.h> /* More portable than <locale.h> ? */ | |
74 #include "frame.h" | |
75 #include "device.h" | |
76 #include "window.h" | |
77 #include "buffer.h" | |
78 #include "console-x.h" | |
79 #include "EmacsFrame.h" | |
80 #include "events.h" | |
81 | |
82 #ifdef THIS_IS_X11R6 | |
83 #include <X11/IntrinsicP.h> | |
84 #include <X11/Xaw/XawImP.h> | |
85 #endif | |
86 | |
87 #ifndef XIM_XLIB | |
88 #error XIM_XLIB is not defined?? | |
89 #endif | |
90 | |
91 Lisp_Object Qxim_xlib; | |
92 #define xim_warn(str) warn_when_safe (Qxim_xlib, Qwarning, str); | |
93 #define xim_warn1(fmt, str) warn_when_safe (Qxim_xlib, Qwarning, fmt, str); | |
94 #define xim_info(str) warn_when_safe (Qxim_xlib, Qinfo, str); | |
95 | |
96 /* Get/Set IC values for just one attribute */ | |
97 #ifdef DEBUG_XEMACS | |
98 #define XIC_Value(Get_Set, xic, name, attr, value) \ | |
99 do { \ | |
100 char *bad_arg; \ | |
101 XVaNestedList list = XVaCreateNestedList (0, attr, value, NULL); \ | |
102 if ((bad_arg = X##Get_Set##ICValues (xic, name, list, NULL)) != NULL) \ | |
103 stderr_out ("X" #Get_Set "ICValues " "bad Arg: %s\n", bad_arg); \ | |
104 XFree (list); \ | |
105 } while (0) | |
106 #else /* ! DEBUG_XEMACS */ | |
107 #define XIC_Value(Get_Set, xic, name, attr, value) \ | |
108 do { \ | |
109 XVaNestedList list = XVaCreateNestedList (0, attr, value, NULL); \ | |
110 X##Get_Set##ICValues (xic, name, list, NULL); \ | |
111 XFree (list); \ | |
112 } while (0) | |
113 #endif /* DEBUG_XEMACS */ | |
114 | |
115 static char DefaultXIMStyles[] = | |
116 "XIMPreeditPosition|XIMStatusArea\n" | |
117 "XIMPreeditPosition|XIMStatusNone\n" | |
118 "XIMPreeditPosition|XIMStatusNothing\n" | |
119 "XIMPreeditNothing|XIMStatusArea\n" | |
120 "XIMPreeditNothing|XIMStatusNothing\n" | |
121 "XIMPreeditNothing|XIMStatusNone\n" | |
122 "XIMPreeditNone|XIMStatusArea\n" | |
123 "XIMPreeditNone|XIMStatusNothing\n" | |
124 "XIMPreeditNone|XIMStatusNone"; | |
125 | |
126 static Boolean xim_initted = False; | |
127 | |
128 static XIMStyle best_style (XIMStyles *user, XIMStyles *xim); | |
129 | |
130 void | |
131 Initialize_Locale (void) | |
132 { | |
133 char *locale; | |
134 | |
135 /* dverna - Nov. 98: ### DON'T DO THIS !!! The default XtLanguageProc | |
136 routine calls setlocale(LC_ALL, lang) which fucks up our lower-level | |
137 locale management, and especially the value of LC_NUMERIC. Anyway, since | |
138 at this point, we don't know yet whether we're gonna need an X11 frame, | |
139 we should really do it manually and not use Xlib's dumb default routine */ | |
140 /*XtSetLanguageProc (NULL, (XtLanguageProc) NULL, NULL);*/ | |
141 if ((locale = setlocale (LC_ALL, "")) == NULL) | |
142 { | |
143 xim_warn ("Can't set locale.\n" | |
144 "Using C locale instead.\n"); | |
145 putenv ("LANG=C"); | |
146 putenv ("LC_ALL=C"); | |
147 if ((locale = setlocale (LC_ALL, "C")) == NULL) | |
148 { | |
149 xim_warn ("Can't even set locale to `C'!\n"); | |
150 return; | |
151 } | |
152 } | |
153 | |
154 if (!XSupportsLocale ()) | |
155 { | |
156 xim_warn1 ("X Windows does not support locale `%s'\n" | |
157 "Using C Locale instead\n", locale); | |
158 putenv ("LANG=C"); | |
159 putenv ("LC_ALL=C"); | |
160 if ((locale = setlocale (LC_ALL, "C")) == NULL) | |
161 { | |
162 xim_warn ("Can't even set locale to `C'!\n"); | |
163 return; | |
164 } | |
165 if (!XSupportsLocale ()) | |
166 { | |
167 xim_warn ("X Windows does not even support locale `C'!\n"); | |
168 return; | |
169 } | |
170 } | |
171 | |
172 setlocale(LC_NUMERIC, "C"); | |
173 | |
174 if (XSetLocaleModifiers ("") == NULL) | |
175 { | |
176 xim_warn ("XSetLocaleModifiers(\"\") failed\n" | |
177 "Check the value of the XMODIFIERS environment variable.\n"); | |
178 } | |
179 } | |
180 | |
181 #ifdef THIS_IS_X11R6 /* Callbacks for IM are supported from X11R6 or later. */ | |
182 /* Called from when XIM is destroying. | |
183 Clear all the XIC when the XIM was destroying... */ | |
184 static void | |
185 IMDestroyCallback (XIM im, XPointer client_data, XPointer call_data) | |
186 { | |
187 struct device *d = (struct device *)client_data; | |
188 Lisp_Object tail; | |
189 | |
190 DEVICE_FRAME_LOOP (tail, d) | |
191 { | |
192 struct frame *target_frame = XFRAME (XCAR (tail)); | |
193 if (FRAME_X_P (target_frame) && FRAME_X_XIC (target_frame)) | |
194 { | |
195 /* XDestroyIC (FRAME_X_XIC (target_frame)); */ | |
196 FRAME_X_XIC (target_frame) = NULL; | |
197 } | |
198 } | |
199 | |
200 DEVICE_X_XIM (d) = NULL; | |
201 xim_initted = False; | |
202 return; | |
203 } | |
204 | |
205 /* This is registered in XIM_init_device (when DEVICE is initializing). | |
206 This activates XIM when XIM becomes available. */ | |
207 static void | |
208 IMInstantiateCallback (Display *dpy, XPointer client_data, XPointer call_data) | |
209 { | |
210 struct device *d = (struct device *)client_data; | |
211 XIM xim; | |
212 char *name, *class; | |
213 XIMCallback ximcallback; | |
214 Lisp_Object tail; | |
215 | |
216 /* if no xim is presented, initialize xim ... */ | |
217 if ( xim_initted == False ) | |
218 { | |
219 xim_initted = True; | |
220 XtGetApplicationNameAndClass (dpy, &name, &class); | |
221 DEVICE_X_XIM (d) = xim = XOpenIM (dpy, XtDatabase (dpy), name, class); | |
222 | |
223 /* destroy callback for im */ | |
224 ximcallback.callback = IMDestroyCallback; | |
225 ximcallback.client_data = (XPointer) d; | |
226 XSetIMValues (xim, XNDestroyCallback, &ximcallback, NULL); | |
227 } | |
228 | |
229 /* activate XIC on all the X frames... */ | |
230 DEVICE_FRAME_LOOP (tail, d) | |
231 { | |
232 struct frame *target_frame = XFRAME (XCAR (tail)); | |
233 if (FRAME_X_P (target_frame) && !FRAME_X_XIC (target_frame)) | |
234 { | |
235 XIM_init_frame (target_frame); | |
236 } | |
237 } | |
238 return; | |
239 } | |
240 #endif /* if THIS_IS_X11R6 */ | |
241 | |
242 /* Initialize XIM for X device. | |
243 Register the use of XIM using XRegisterIMInstantiateCallback. */ | |
244 void | |
245 XIM_init_device (struct device *d) | |
246 { | |
247 #ifdef THIS_IS_X11R6 | |
248 DEVICE_X_XIM (d) = NULL; | |
249 XRegisterIMInstantiateCallback (DEVICE_X_DISPLAY (d), NULL, NULL, NULL, | |
250 IMInstantiateCallback, (XPointer) d); | |
251 return; | |
252 #else | |
253 Display *dpy = DEVICE_X_DISPLAY (d); | |
254 char *name, *class; | |
255 XIM xim; | |
256 | |
257 XtGetApplicationNameAndClass (dpy, &name, &class); | |
258 DEVICE_X_XIM (d) = xim = XOpenIM (dpy, XtDatabase (dpy), name, class); | |
259 if (xim == NULL) | |
260 { | |
261 xim_warn ("XOpenIM() failed...no input server available\n"); | |
262 return; | |
263 } | |
264 else | |
265 { | |
266 XGetIMValues (xim, XNQueryInputStyle, &DEVICE_X_XIM_STYLES (d), NULL); | |
267 return; | |
268 } | |
269 #endif | |
270 } | |
271 | |
272 | |
273 /* | |
274 * For the frames | |
275 */ | |
276 | |
277 /* Callback for the deleting frame. */ | |
278 static void | |
279 XIM_delete_frame (Widget w, XtPointer client_data, XtPointer call_data) | |
280 { | |
281 struct frame *f = (struct frame *) client_data; | |
282 struct device *d = XDEVICE (FRAME_DEVICE (f)); | |
283 | |
284 if (DEVICE_X_XIM (d)) | |
285 { | |
286 if (FRAME_X_XIC (f)) | |
287 { | |
288 XDestroyIC (FRAME_X_XIC (f)); | |
289 FRAME_X_XIC (f) = NULL; | |
290 } | |
291 } | |
292 return; | |
293 } | |
294 | |
295 /* Initialize XIC for new frame. | |
296 Create an X input context (XIC) for this frame. */ | |
297 void | |
298 XIM_init_frame (struct frame *f) | |
299 { | |
300 struct device *d = XDEVICE (FRAME_DEVICE (f)); | |
301 XIM xim; | |
302 Widget w = FRAME_X_TEXT_WIDGET (f); | |
303 Window win = XtWindow (w); | |
304 XRectangle p_area = {0,0,1,1}, s_area = {0,0,1,1}; | |
305 XPoint spot = {0,0}; | |
306 XIMStyle style; | |
307 XVaNestedList p_list, s_list; | |
308 typedef struct | |
309 { | |
310 XIMStyles styles; | |
311 XFontSet fontset; | |
312 Pixel fg; | |
313 Pixel bg; | |
314 char *inputmethod; | |
315 } xic_vars_t; | |
316 xic_vars_t xic_vars; | |
317 XIC xic; | |
318 | |
319 #define res(name, class, representation, field, default_value) \ | |
320 { name, class, representation, sizeof(xic_vars.field), \ | |
321 XtOffsetOf(xic_vars_t, field), XtRString, default_value } | |
322 | |
323 static XtResource resources[] = | |
324 { | |
325 /* name class represent'n field default value */ | |
326 #ifdef THIS_IS_X11R6 | |
327 res(XtNinputMethod, XtCInputMethod, XtRString, inputmethod, (XtPointer) NULL), | |
328 #endif | |
329 res(XtNximStyles, XtCXimStyles, XtRXimStyles, styles, (XtPointer) DefaultXIMStyles), | |
330 res(XtNfontSet, XtCFontSet, XtRFontSet, fontset, (XtPointer) XtDefaultFontSet), | |
331 res(XtNximForeground, XtCForeground, XtRPixel, fg, (XtPointer) XtDefaultForeground), | |
332 res(XtNximBackground, XtCBackground, XtRPixel, bg, (XtPointer) XtDefaultBackground) | |
333 }; | |
334 | |
335 | |
336 xim = DEVICE_X_XIM (d); | |
337 | |
338 if (!xim) | |
339 { | |
340 xim_info ("X Input Method open failed. Waiting for an XIM to be enabled.\n"); | |
341 return; | |
342 } | |
343 | |
344 w = FRAME_X_TEXT_WIDGET (f); | |
345 | |
346 /* | |
347 * initialize XIC | |
348 */ | |
349 if (FRAME_X_XIC (f)) return; | |
350 XtGetApplicationResources (w, &xic_vars, | |
351 resources, XtNumber (resources), | |
352 NULL, 0); | |
353 if (!xic_vars.fontset) | |
354 { | |
355 xim_warn ("Can't get fontset resource for Input Method\n"); | |
356 FRAME_X_XIC (f) = NULL; | |
357 return; | |
358 } | |
359 | |
360 /* construct xic */ | |
361 XGetIMValues (xim, XNQueryInputStyle, &DEVICE_X_XIM_STYLES(d), NULL); | |
362 FRAME_X_XIC_STYLE (f) = style = | |
363 best_style (&xic_vars.styles, (XIMStyles *)DEVICE_X_XIM_STYLES(d)); | |
364 | |
365 p_list = XVaCreateNestedList (0, | |
366 XNArea, &p_area, | |
367 XNSpotLocation, &spot, | |
368 XNForeground, xic_vars.fg, | |
369 XNBackground, xic_vars.bg, | |
370 XNFontSet, xic_vars.fontset, | |
371 NULL); | |
372 | |
373 s_list = XVaCreateNestedList (0, | |
374 XNArea, &s_area, | |
375 XNForeground, xic_vars.fg, | |
376 XNBackground, xic_vars.bg, | |
377 XNFontSet, xic_vars.fontset, | |
378 NULL); | |
379 | |
380 FRAME_X_XIC (f) = xic = | |
381 XCreateIC (xim, | |
382 XNInputStyle, style, | |
383 XNClientWindow, win, | |
384 XNFocusWindow, win, | |
385 XNPreeditAttributes, p_list, | |
386 XNStatusAttributes, s_list, | |
387 NULL); | |
388 XFree (p_list); | |
389 XFree (s_list); | |
390 | |
391 if (!xic) | |
392 { | |
393 xim_warn ("Warning: XCreateIC failed.\n"); | |
394 return; | |
395 } | |
396 | |
397 if (style & XIMPreeditPosition) | |
398 { | |
399 XPoint *frame_spot = &(FRAME_X_XIC_SPOT(f)); | |
400 frame_spot->x = frame_spot->y = -1; | |
401 } | |
402 | |
403 XIM_SetGeometry (f); | |
404 | |
405 XSetICFocus (xic); | |
406 | |
407 #ifdef THIS_IS_X11R6 | |
408 /* when frame is going to be destroyed (closed) */ | |
409 XtAddCallback (FRAME_X_TEXT_WIDGET(f), XNDestroyCallback, | |
410 XIM_delete_frame, (XtPointer)f); | |
411 #endif | |
412 } | |
413 | |
414 | |
415 void | |
416 XIM_SetGeometry (struct frame *f) | |
417 { | |
418 XIC xic = FRAME_X_XIC (f); | |
419 XIMStyle style = FRAME_X_XIC_STYLE (f); | |
420 XRectangle area; | |
421 | |
422 if (!xic || !f) | |
423 return; | |
424 | |
425 if (style & XIMStatusArea) | |
426 { | |
427 /* Place Status Area in bottom right corner */ | |
428 /* Negotiate geometry of status area */ | |
429 /* See O'Reilly Xlib XIM chapter (but beware, it's buggy) */ | |
430 XRectangle *needed; | |
431 | |
432 /* If input method has existing status area, use its current size */ | |
433 /* The following at least works for Sun's htt */ | |
434 area.x = area.y = area.width = area.height = 0; | |
435 XIC_Value (Set, xic, XNStatusAttributes, XNAreaNeeded, &area); | |
436 XIC_Value (Get, xic, XNStatusAttributes, XNAreaNeeded, &needed); | |
437 if (needed->width == 0) /* Use XNArea instead of XNAreaNeeded */ | |
438 XIC_Value (Get, xic, XNStatusAttributes, XNArea, &needed); | |
439 | |
440 area.width = needed->width; | |
441 area.height = needed->height; | |
442 area.x = FRAME_RIGHT_BORDER_START (f) - area.width; | |
443 area.y = FRAME_BOTTOM_BORDER_START (f) - area.height; | |
444 | |
445 #ifdef DEBUG_XIM | |
446 stderr_out ("Putting StatusArea in x=%d y=%d w=%d h=%d\n", | |
447 area.x, area.y, area.width, area.height); | |
448 #endif /* DEBUG_XIM */ | |
449 | |
450 XIC_Value (Set, xic, XNStatusAttributes, XNArea, &area); | |
451 } | |
452 | |
453 if (style & XIMPreeditPosition) | |
454 { | |
455 /* Set Preedit Area to whole frame size (sans border) */ | |
456 /* We include the border because Preedit window might be larger | |
457 than display line at edge. #### FIX: we should adjust to make | |
458 sure that there is always room for the spot sub-window */ | |
459 area.x = FRAME_LEFT_BORDER_START (f); | |
460 area.y = FRAME_TOP_BORDER_START (f); | |
461 area.width = FRAME_RIGHT_BORDER_END (f) - area.x; | |
462 area.height = FRAME_BOTTOM_BORDER_END (f) - area.y; | |
463 XIC_Value(Set, xic, XNPreeditAttributes, XNArea, &area); | |
464 } | |
465 | |
466 #ifdef DEBUG_XIM | |
467 describe_XIC (xic); | |
468 #endif | |
469 } | |
470 | |
471 void | |
472 XIM_SetSpotLocation (struct frame *f, int x, int y) | |
473 { | |
474 XIC xic = FRAME_X_XIC (f); | |
475 XPoint *spot = &(FRAME_X_XIC_SPOT (f)); | |
476 | |
477 /* Only care if we have a valid XIC using Over the Spot in | |
478 * a different location */ | |
479 if (!xic || | |
480 !(FRAME_X_XIC_STYLE (f) & XIMPreeditPosition) || | |
481 (spot->x == (short) x && | |
482 spot->y == (short) y)) | |
483 return; | |
484 | |
485 spot->x = (short) x; | |
486 spot->y = (short) y; | |
487 | |
488 /* ### FIX: Must make sure spot fits within Preedit Area */ | |
489 XIC_Value (Set, xic, XNPreeditAttributes, XNSpotLocation, spot); | |
490 #ifdef DEBUG_XIM | |
491 stderr_out ("Spot: %d %d\n", spot->x, spot->y); | |
492 #endif | |
493 } | |
494 | |
495 void | |
496 XIM_focus_event (struct frame *f, int in_p) | |
497 { | |
498 if (FRAME_X_XIC (f) /* && FRAME_X_XIM_REGISTERED(f) */) | |
499 (in_p ? XSetICFocus : XUnsetICFocus) (FRAME_X_XIC (f)); | |
500 } | |
501 | |
502 #if 0 | |
503 #define XIM_Composed_Text_BUFSIZE 64 | |
504 typedef struct XIM_Composed_Text | |
505 { | |
506 int size; | |
507 wchar_t data [XIM_Composed_Text_BUFSIZE]; | |
508 } XIM_Composed_Text; | |
509 | |
510 static XIM_Composed_Text composed_input_buf = {XIM_Composed_Text_BUFSIZE, {0}}; | |
511 Window main_window; | |
512 | |
513 /* get_XIM_input -- Process results of input method composition. | |
514 | |
515 This function copies the results of the input method composition to | |
516 composed_input_buf. Then for each character, a custom event of type | |
517 wc_atom is sent with the character as its data. | |
518 | |
519 It is probably more efficient to copy the composition results to some | |
520 allocated memory and send a single event pointing to that memory. | |
521 That would cut down on the event processing as well as allow quick | |
522 insertion into the buffer of the whole string. It might require some | |
523 care, though, to avoid fragmenting memory through the allocation and | |
524 freeing of many small chunks. Maybe the existing system for | |
525 (single-byte) string allocation can be used, multiplying the length by | |
526 sizeof (wchar_t) to get the right size. | |
527 */ | |
528 void | |
529 get_XIM_input (XKeyPressedEvent *x_key_event, XIC ic, Display *dpy) | |
530 { | |
531 KeySym keysym; | |
532 Status status; | |
533 int len; | |
534 int i; | |
535 XClientMessageEvent new_event; | |
536 | |
537 retry: | |
538 len = XwcLookupString (ic, x_key_event, composed_input_buf.data, | |
539 composed_input_buf.size, &keysym, &status); | |
540 switch (status) | |
541 { | |
542 case XBufferOverflow: | |
543 /* GROW_WC_STRING (&composed_input_buf, 32); mrb */ | |
544 goto retry; | |
545 case XLookupChars: | |
546 break; | |
547 default: | |
548 abort (); | |
549 } | |
550 | |
551 new_event.type = ClientMessage; | |
552 new_event.display = x_key_event->display; | |
553 new_event.window = x_key_event->window; | |
554 new_event.message_type = wc_atom; | |
555 new_event.format = 32; /* 32-bit wide data */ | |
556 new_event.data.l[2] = new_event.data.l[3] = new_event.data.l[4] = 0L; | |
557 new_event.data.l[0] = x_key_event->time; | |
558 for (i = 0; i < len; i++) | |
559 { | |
560 new_event.data.l[1] = ((wchar_t *) composed_input_buf.data)[i]; | |
561 XSendEvent (display, main_window, False, 0L, (XEvent *) &new_event); | |
562 } | |
563 } | |
564 #endif /* 0 */ | |
565 | |
566 /* ============================================================== */ | |
567 /* X input method style determination */ | |
568 /* ============================================================== */ | |
569 | |
570 #if 0 | |
571 #define done(type, value) \ | |
572 if (toVal->addr != NULL) { \ | |
573 if (toVal->size < sizeof(type)) { \ | |
574 toVal->size = sizeof(type); \ | |
575 return False; \ | |
576 } \ | |
577 *(type*)toVal->addr = (value); \ | |
578 } else { \ | |
579 static type static_val; \ | |
580 static_val = (value); \ | |
581 toVal->addr = (XPointer)&static_val; \ | |
582 } \ | |
583 toVal->size = sizeof(type); \ | |
584 return True /* Caller supplies `;' */ | |
585 #endif /* 0 */ | |
586 | |
587 /* | |
588 * This is a standard Xt type converter, except that the caller MUST | |
589 * supply a proper non-NULL toVal XIMStyles structure that we will | |
590 * fill in. | |
591 * | |
592 * fromVal points to a string like | |
593 * | |
594 "XIMPreeditPosition|XIMStatusArea, | |
595 XIMPreeditPosition|XIMStatusNothing | |
596 XIMPreeditNothing|XIMStatusNothing" | |
597 * | |
598 * This is converted in the obvious way to a XIMStyles structure. | |
599 * | |
600 * mrb: #### Fix this to handle Motif-style specifications for | |
601 * XIMStyles as well: overTheSpot, rootWindow, none */ | |
602 | |
603 /* XtTypeConverter */ | |
604 Boolean | |
605 EmacsXtCvtStringToXIMStyles ( | |
606 Display *dpy, | |
607 XrmValuePtr args, | |
608 Cardinal *num_args, | |
609 XrmValuePtr fromVal, | |
610 XrmValuePtr toVal, | |
611 XtPointer *converter_data) | |
612 { | |
613 #define STYLE_INFO(style) { style, #style, sizeof(#style) } | |
614 static struct XIMStyleInfo | |
615 { | |
616 CONST XIMStyle style; | |
617 CONST char * CONST name; | |
618 CONST int namelen; | |
619 } emacs_XIMStyleInfo[] = { | |
620 STYLE_INFO (XIMPreeditPosition|XIMStatusArea), | |
621 STYLE_INFO (XIMPreeditPosition|XIMStatusNothing), | |
622 STYLE_INFO (XIMPreeditPosition|XIMStatusNone), | |
623 STYLE_INFO (XIMPreeditNothing|XIMStatusArea), | |
624 STYLE_INFO (XIMPreeditNothing|XIMStatusNothing), | |
625 STYLE_INFO (XIMPreeditNothing|XIMStatusNone), | |
626 STYLE_INFO (XIMPreeditNone|XIMStatusArea), | |
627 STYLE_INFO (XIMPreeditNone|XIMStatusNothing), | |
628 STYLE_INFO (XIMPreeditNone|XIMStatusNone) | |
629 }; | |
630 #undef STYLE_INFO | |
631 | |
632 char *s = (char *) fromVal->addr; | |
633 char *end = s + fromVal->size; | |
634 XIMStyles * CONST p = (XIMStyles *) toVal->addr; | |
635 CONST char * CONST delimiter = " \t\n\r:;," ; | |
636 CONST int max_styles = XtNumber(emacs_XIMStyleInfo); | |
637 int i; | |
638 char *c; | |
639 | |
640 #ifdef DEBUG_XIM | |
641 stderr_out ("EmacsCvtStringToXIMStyles called with size=%d, string=\"%s\"\n", | |
642 fromVal->size, (char *) fromVal->addr); | |
643 #endif /* DEBUG_XIM */ | |
644 | |
645 if (*num_args != 0) | |
646 { | |
647 XtAppContext the_app_con = XtDisplayToApplicationContext (dpy); | |
648 XtAppWarningMsg(the_app_con, "wrongParameters", "cvtStringToXIMStyle", | |
649 "XtToolkitError", | |
650 "String to XIMStyle conversion requires exactly 0 parameters", | |
651 (String *)NULL, (Cardinal *)NULL); | |
652 return False; | |
653 } | |
654 | |
655 #ifdef DEBUG_XEMACS | |
656 /* Make sure caller is giving us good data */ | |
657 assert (fromVal->addr != NULL); | |
658 assert (fromVal->size == strlen(fromVal->addr)+1); | |
659 assert (toVal->addr != NULL); | |
660 assert (toVal->size == sizeof(XIMStyles)); | |
661 #endif /* DEBUG_XEMACS */ | |
662 | |
663 p->count_styles = 0; | |
664 p->supported_styles = xnew_array (XIMStyle, max_styles); | |
665 | |
666 /* | |
667 * The following routine assumes that the style name resource is | |
668 * identical with the programmatic name of style. For example, | |
669 * "XIMPreeditPosition|XIMStatusArea" means the | |
670 * XIMPreeditPosition|XIMStatusArea value is specified. If the | |
671 * style name is changed, such as "OverTheSpot|imDisplaysInClient", | |
672 * the parsing logic below should be modified as well. */ | |
673 | |
674 if ((c = strtok(s, delimiter)) == NULL) | |
675 c = end; | |
676 | |
677 while (c < end) | |
678 { | |
679 for(i=0 ; i<max_styles ; i++) | |
680 { | |
681 struct XIMStyleInfo *rec = emacs_XIMStyleInfo + i; | |
682 if(!strncmp(c, rec->name, rec->namelen - 1)) { | |
683 p->supported_styles[p->count_styles] = rec->style; | |
684 p->count_styles++; | |
685 break; | |
686 } | |
687 } | |
688 if((c = strtok(NULL, delimiter)) == NULL) { | |
689 break ; | |
690 } | |
691 } | |
692 | |
693 if (p->count_styles == 0) | |
694 { /* No valid styles? */ | |
695 char *buf = (char *)alloca (strlen (fromVal->addr) | |
696 + strlen (DefaultXIMStyles) | |
697 + 100); | |
698 XrmValue new_from; | |
699 XtAppContext the_app_con = XtDisplayToApplicationContext (dpy); | |
700 | |
701 sprintf(buf, "Cannot convert string \"%s\" to type XIMStyles.\n" | |
702 "Using default string \"%s\" instead.\n", | |
703 fromVal->addr, DefaultXIMStyles); | |
704 XtAppWarningMsg(the_app_con, "wrongParameters", "cvtStringToXIMStyle", | |
705 "XtToolkitError", | |
706 buf, (String *)NULL, (Cardinal *)NULL); | |
707 new_from.addr = DefaultXIMStyles; | |
708 new_from.size = sizeof(DefaultXIMStyles); | |
709 return EmacsXtCvtStringToXIMStyles (dpy, args, num_args, | |
710 &new_from, toVal, converter_data); | |
711 } | |
712 XREALLOC_ARRAY (p->supported_styles, XIMStyle, p->count_styles); | |
713 *converter_data = (char *) True; | |
714 return True; | |
715 } | |
716 | |
717 /* XtDestructor */ | |
718 void | |
719 EmacsFreeXIMStyles ( | |
720 XtAppContext app, | |
721 XrmValuePtr toVal, | |
722 XtPointer converter_data, | |
723 XrmValuePtr args, | |
724 Cardinal *num_args) | |
725 { | |
726 #ifdef DEBUG_XIM | |
727 stderr_out ("Converter data: %x\n", converter_data); | |
728 stderr_out ("EmacsFreeXIMStyles called\n"); | |
729 #endif /* DEBUG_XIM */ | |
730 | |
731 if (*num_args != 0) | |
732 { | |
733 XtAppWarningMsg(app, "wrongParameters","freeXIMStyles","XtToolkitError", | |
734 "Freeing an XIMStyles requires that zero arguments be passwd", | |
735 (String *)NULL, (Cardinal *)NULL); | |
736 return; | |
737 } | |
738 | |
739 if (converter_data) | |
740 { | |
741 Boolean free_p = (Boolean) (int) converter_data; | |
742 XIMStyles *styles = (XIMStyles *) toVal->addr; | |
743 if (free_p) | |
744 XFree ( styles->supported_styles ); | |
745 } | |
746 } | |
747 | |
748 #if 0 | |
749 /* O'Reilly XLib Programming Manual, pg. 371 */ | |
750 /* Much nicer implementation than O'Reilly */ | |
751 /* Choose the more `complicated', hence nicer, XIM input style */ | |
752 static XIMStyle | |
753 BetterStyle (XIMStyle s, XIMStyle t) | |
754 { | |
755 #define CHECK_XIMStyle_BIT(bit) \ | |
756 if ((s ^ t) & bit) { return (s & bit) ? s : t; } | |
757 | |
758 CHECK_XIMStyle_BIT (XIMPreeditCallbacks); | |
759 CHECK_XIMStyle_BIT (XIMPreeditPosition); | |
760 CHECK_XIMStyle_BIT (XIMPreeditArea); | |
761 CHECK_XIMStyle_BIT (XIMPreeditNothing); | |
762 CHECK_XIMStyle_BIT (XIMStatusCallbacks); | |
763 CHECK_XIMStyle_BIT (XIMStatusArea); | |
764 CHECK_XIMStyle_BIT (XIMStatusNothing); | |
765 #undef CHECK_XIMStyle_BIT | |
766 return s ? s : t ; | |
767 } | |
768 #endif /* 0 */ | |
769 | |
770 /* Choose the best style, given: | |
771 * - user preferences (already checked to be supported by XEmacs) | |
772 * - styles supported by the input method */ | |
773 #define DEFAULTStyle (XIMPreeditNothing|XIMStatusNothing) | |
774 static XIMStyle | |
775 best_style (XIMStyles *user, XIMStyles *xim) | |
776 { | |
777 REGISTER int i, j; | |
778 for (i=0 ; i<user->count_styles ; i++) | |
779 { | |
780 for (j=0 ; j<xim->count_styles ; j++) | |
781 { | |
782 if (user->supported_styles[i] == xim->supported_styles[j]) | |
783 return user->supported_styles[i]; | |
784 } | |
785 } | |
786 return DEFAULTStyle; /* Default Style */ | |
787 } | |
788 | |
789 /* These lisp-callable functions will be sealed until xim-leim is needed. | |
790 Oct 22 1999 - kazz */ | |
791 #if 0 | |
792 /* | |
793 * External callable function for XIM | |
794 */ | |
795 DEFUN ("x-open-xim", Fx_open_xim, 1, 1, 0, /* | |
796 Open the XIC on the frame if XIM is available. | |
797 Commonly, use this as \(x-open-xim \(selected-frame)). | |
798 If the frame is not on X device, return signal. | |
799 If XIC is created successfully return t. If not return nil. | |
800 */ | |
801 (frame)) | |
802 { | |
803 struct frame *f; | |
804 | |
805 CHECK_LIVE_FRAME (frame); | |
806 f = XFRAME (frame); | |
807 if (!FRAME_X_P (f)) | |
808 return signal_simple_error ("This frame is not on X device", frame); | |
809 | |
810 XIM_init_frame (f); | |
811 return FRAME_X_XIC (f) ? Qt : Qnil; | |
812 } | |
813 | |
814 DEFUN ("x-close-xim", Fx_close_xim, 1, 1, 0, /* | |
815 Close the XIC on the frame if it exists. | |
816 Commonly, use this as \(x-close-xim \(selected-frame)). | |
817 If the frame is not on X device, return signal. | |
818 Otherwise, it destroys the XIC if it exists, then returns t anyway. | |
819 */ | |
820 (frame)) | |
821 { | |
822 struct frame *f; | |
823 struct device *d; | |
824 | |
825 CHECK_LIVE_FRAME (frame); | |
826 f = XFRAME (frame); | |
827 if (!FRAME_X_P (f)) | |
828 return signal_simple_error ("This frame is not on X device", frame); | |
829 | |
830 d = XDEVICE (FRAME_DEVICE (f)); | |
831 if (DEVICE_X_XIM (d)) { | |
832 /* XDestroyIC (FRAME_X_XIC (XFRAME (f))); */ | |
833 FRAME_X_XIC (XFRAME (f)) = NULL; | |
834 } | |
835 return Qt; | |
836 } | |
837 #endif /* if 0 */ | |
838 | |
839 void | |
840 syms_of_input_method_xlib (void) | |
841 { | |
842 defsymbol (&Qxim_xlib, "xim-xlib"); | |
843 #if 0 /* see above */ | |
844 DEFSUBR (Fx_open_xim); | |
845 DEFSUBR (Fx_close_xim); | |
846 #endif | |
847 } | |
848 | |
849 void | |
850 vars_of_input_method_xlib (void) | |
851 { | |
852 Fprovide (intern ("xim")); | |
853 } | |
854 | |
855 | |
856 /* ====================================================================== */ | |
857 /* Internal Debugging Routines */ | |
858 /* ====================================================================== */ | |
859 #ifdef DEBUG_XEMACS | |
860 | |
861 void | |
862 describe_XIM (XIM xim) | |
863 { | |
864 XIMStyles *styles; | |
865 | |
866 /* Print locale of XIM */ | |
867 stderr_out ("\nXIM Locale of IM: %s\n", XLocaleOfIM(xim)); | |
868 | |
869 /* List supported input method styles */ | |
870 XGetIMValues(xim, XNQueryInputStyle, &styles, NULL); | |
871 | |
872 stderr_out ("\n%d input style(s) supported by input method.\n", | |
873 styles->count_styles); | |
874 | |
875 #ifdef DEBUG_XIM | |
876 { | |
877 int i; | |
878 for (i=0; i < styles->count_styles; i++) | |
879 describe_XIMStyle (styles->supported_styles[i]); | |
880 } | |
881 #endif /* DEBUG_XIM */ | |
882 XFree(styles); | |
883 } | |
884 | |
885 void | |
886 describe_XFontSet (XFontSet fontset) | |
887 { | |
888 XFontStruct **font_struct_list; | |
889 char **font_name_list; | |
890 int count, i; | |
891 | |
892 if (fontset == NULL) | |
893 { | |
894 stderr_out ("NULL\n"); | |
895 return; | |
896 } | |
897 | |
898 count = XFontsOfFontSet (fontset, &font_struct_list, &font_name_list); | |
899 stderr_out ( "%d font(s) available:\n", count); | |
900 for (i=0 ; i < count ; i++) | |
901 stderr_out ("Font: %s\n", *(font_name_list+i)); | |
902 } | |
903 | |
904 void | |
905 describe_Status (Status status) | |
906 { | |
907 #define DESCRIBE_STATUS(value) \ | |
908 if (status == value) stderr_out ("Status: " #value "\n") | |
909 | |
910 DESCRIBE_STATUS (XBufferOverflow); | |
911 DESCRIBE_STATUS (XLookupNone); | |
912 DESCRIBE_STATUS (XLookupKeySym); | |
913 DESCRIBE_STATUS (XLookupBoth); | |
914 DESCRIBE_STATUS (XLookupChars); | |
915 #undef DESCRIBE_STATUS | |
916 } | |
917 | |
918 void | |
919 describe_Window (Window win) | |
920 { | |
921 char xwincmd[128]; | |
922 sprintf (xwincmd, "xwininfo -id 0x%x >&2; xwininfo -events -id 0x%x >&2", | |
923 (int) win, (int) win); | |
924 system (xwincmd); | |
925 } | |
926 | |
927 void | |
928 describe_XIC (XIC xic) | |
929 { | |
930 XIMStyle style; | |
931 Window client_win=0, focus_win=0; | |
932 char *resourceName = NULL; | |
933 char *resourceClass = NULL; | |
934 char *bad_arg = NULL; | |
935 unsigned long filter_mask = NoEventMask; | |
936 XVaNestedList p_list, s_list; | |
937 XFontSet p_fontset = NULL, s_fontset = NULL; | |
938 Pixel p_fg=0, p_bg = 0, s_fg=0, s_bg = 0; | |
939 XRectangle *p_area = NULL, *s_area = NULL; | |
940 XRectangle *p_needed = NULL, *s_needed = NULL; | |
941 XPoint *p_spot = NULL; | |
942 | |
943 /* Check for valid input context and method */ | |
944 if (!xic) | |
945 stderr_out ("Input method is NULL\n"); | |
946 | |
947 if (!XIMOfIC(xic)) | |
948 stderr_out ("XIMOfIC() returns NULL\n"); | |
949 | |
950 /* Print out Input Context Attributes */ | |
951 p_list = XVaCreateNestedList (0, | |
952 XNFontSet, &p_fontset, | |
953 XNArea, &p_area, | |
954 XNAreaNeeded, &p_needed, | |
955 XNSpotLocation, &p_spot, | |
956 XNForeground, &p_fg, | |
957 XNBackground, &p_bg, | |
958 NULL); | |
959 | |
960 s_list = XVaCreateNestedList (0, | |
961 XNFontSet, &s_fontset, | |
962 XNArea, &s_area, | |
963 XNAreaNeeded, &s_needed, | |
964 XNForeground, &s_fg, | |
965 XNBackground, &s_bg, | |
966 NULL); | |
967 | |
968 bad_arg = XGetICValues(xic, | |
969 XNInputStyle, &style, | |
970 XNFilterEvents, &filter_mask, | |
971 XNClientWindow, &client_win, | |
972 XNFocusWindow, &focus_win, | |
973 XNResourceName, &resourceName, | |
974 XNResourceClass, &resourceClass, | |
975 XNPreeditAttributes, p_list, | |
976 XNStatusAttributes, s_list, | |
977 NULL); | |
978 XFree(p_list); | |
979 XFree(s_list); | |
980 | |
981 if (bad_arg != NULL) | |
982 stderr_out ("Couldn't get IC value: %s\n", bad_arg); | |
983 | |
984 stderr_out ("\nInput method context attributes:\n"); | |
985 stderr_out ("Style: "); describe_XIMStyle (style); | |
986 stderr_out ("Client window: %lx\n", (unsigned long int)client_win); | |
987 stderr_out ("Focus window: %lx\n", (unsigned long int)focus_win); | |
988 stderr_out ("Preedit:\n"); | |
989 describe_XRectangle (" Area", p_area); | |
990 describe_XRectangle (" Area needed", p_needed); | |
991 stderr_out (" foreground: %lx\n", (unsigned long int)p_fg); | |
992 stderr_out (" background: %lx\n", (unsigned long int)p_bg); | |
993 stderr_out (" fontset: "); describe_XFontSet (p_fontset); | |
994 stderr_out ("Status:\n"); | |
995 describe_XRectangle (" Area", s_area); | |
996 describe_XRectangle (" Area needed", s_needed); | |
997 stderr_out (" foreground: %lx\n", (unsigned long int)s_fg); | |
998 stderr_out (" background: %lx\n", (unsigned long int)s_bg); | |
999 stderr_out (" fontset: \n"); describe_XFontSet (s_fontset); | |
1000 stderr_out ("XNResourceName: %s\n", resourceName ? resourceName : "NULL"); | |
1001 stderr_out ("XNResourceClass: %s\n", resourceClass ? resourceClass : "NULL"); | |
1002 stderr_out ("XNFilterEvents: "); describe_event_mask (filter_mask); | |
1003 } | |
1004 | |
1005 void | |
1006 describe_XRectangle (char *name, XRectangle *r) | |
1007 { | |
1008 if (r == NULL) | |
1009 stderr_out ("%s: NULL\n", name); | |
1010 else | |
1011 stderr_out ("%s: x=%d y=%d w=%d h=%d\n", | |
1012 name, r->x, r->y, r->width, r->height); | |
1013 } | |
1014 | |
1015 /* Print out elements of Event mask */ | |
1016 /* Defines from X11/X.h */ | |
1017 void | |
1018 describe_event_mask (unsigned long mask) | |
1019 { | |
1020 #define DESCRIBE_EVENT_MASK(bit) if ((bit) & mask) stderr_out (#bit " ") | |
1021 DESCRIBE_EVENT_MASK (NoEventMask); | |
1022 DESCRIBE_EVENT_MASK (KeyPressMask); | |
1023 DESCRIBE_EVENT_MASK (KeyReleaseMask); | |
1024 DESCRIBE_EVENT_MASK (ButtonPressMask); | |
1025 DESCRIBE_EVENT_MASK (ButtonReleaseMask); | |
1026 DESCRIBE_EVENT_MASK (EnterWindowMask); | |
1027 DESCRIBE_EVENT_MASK (LeaveWindowMask); | |
1028 DESCRIBE_EVENT_MASK (PointerMotionMask); | |
1029 DESCRIBE_EVENT_MASK (PointerMotionHintMask); | |
1030 DESCRIBE_EVENT_MASK (Button1MotionMask); | |
1031 DESCRIBE_EVENT_MASK (Button2MotionMask); | |
1032 DESCRIBE_EVENT_MASK (Button3MotionMask); | |
1033 DESCRIBE_EVENT_MASK (Button4MotionMask); | |
1034 DESCRIBE_EVENT_MASK (Button5MotionMask); | |
1035 DESCRIBE_EVENT_MASK (ButtonMotionMask); | |
1036 DESCRIBE_EVENT_MASK (KeymapStateMask); | |
1037 DESCRIBE_EVENT_MASK (ExposureMask); | |
1038 DESCRIBE_EVENT_MASK (VisibilityChangeMask); | |
1039 DESCRIBE_EVENT_MASK (StructureNotifyMask); | |
1040 DESCRIBE_EVENT_MASK (ResizeRedirectMask); | |
1041 DESCRIBE_EVENT_MASK (SubstructureNotifyMask); | |
1042 DESCRIBE_EVENT_MASK (SubstructureRedirectMask); | |
1043 DESCRIBE_EVENT_MASK (FocusChangeMask); | |
1044 DESCRIBE_EVENT_MASK (PropertyChangeMask); | |
1045 DESCRIBE_EVENT_MASK (ColormapChangeMask); | |
1046 DESCRIBE_EVENT_MASK (OwnerGrabButtonMask); | |
1047 #undef DESCRIBE_EVENT_MASK | |
1048 stderr_out("\n"); | |
1049 } | |
1050 | |
1051 void | |
1052 describe_XIMStyle (XIMStyle style) | |
1053 { | |
1054 #define DESCRIBE_STYLE(bit) \ | |
1055 if (bit & style) \ | |
1056 stderr_out (#bit " "); | |
1057 | |
1058 DESCRIBE_STYLE (XIMPreeditArea); | |
1059 DESCRIBE_STYLE (XIMPreeditCallbacks); | |
1060 DESCRIBE_STYLE (XIMPreeditPosition); | |
1061 DESCRIBE_STYLE (XIMPreeditNothing); | |
1062 DESCRIBE_STYLE (XIMPreeditNone); | |
1063 DESCRIBE_STYLE (XIMStatusArea); | |
1064 DESCRIBE_STYLE (XIMStatusCallbacks); | |
1065 DESCRIBE_STYLE (XIMStatusNothing); | |
1066 DESCRIBE_STYLE (XIMStatusNone); | |
1067 #undef DESCRIBE_STYLE | |
1068 stderr_out("\n"); | |
1069 } | |
1070 | |
1071 void | |
1072 describe_XIMStyles (XIMStyles *p) | |
1073 { | |
1074 int i; | |
1075 stderr_out ("%d Style(s):\n", p->count_styles); | |
1076 for (i=0; i<p->count_styles ; i++) | |
1077 { | |
1078 describe_XIMStyle (p->supported_styles[i]); | |
1079 } | |
1080 } | |
1081 | |
1082 #endif /* DEBUG_XEMACS */ | |
1083 | |
1084 /* Random cruft follows */ | |
1085 | |
1086 #if 0 | |
1087 static void | |
1088 Unit_Test (struct frame *f, char * s) | |
1089 /* mrb unit testing */ | |
1090 { | |
1091 XrmValue fromVal, toVal; | |
1092 | |
1093 fromVal.addr = s; | |
1094 fromVal.size = strlen (s); | |
1095 toVal.addr = (XtPointer) &user_preferred_XIMStyles; | |
1096 toVal.size = sizeof (XIMStyles); | |
1097 | |
1098 if (XtConvertAndStore (FRAME_X_TEXT_WIDGET (f), XtRString, &fromVal, | |
1099 XtRXimStyles, &toVal) != False) | |
1100 { | |
1101 stderr_out ("Unit_Test: fromVal.addr=0x%x\n",fromVal.addr); | |
1102 stderr_out ("Unit_Test: fromVal.size=%d\n", fromVal.size); | |
1103 stderr_out ("Unit_Test: toVal.addr=0x%x\n", toVal.addr); | |
1104 stderr_out ("Unit_Test: toVal.size=%d\n", toVal.size); | |
1105 describe_XIMStyles ((XIMStyles *) toVal.addr); | |
1106 } | |
1107 } | |
1108 #endif | |
1109 | |
1110 #if 0 | |
1111 /* Get a fontset for IM to use */ | |
1112 void | |
1113 x_init_fontset (struct device *d) | |
1114 { | |
1115 Display *dpy = DEVICE_X_DISPLAY (d); | |
1116 XFontSet fontset; | |
1117 char ** missing_charsets; | |
1118 int num_missing_charsets; | |
1119 char * default_string; | |
1120 /* char * font_set_string = "-dt-interface user-medium-r-normal-s*-*-*-*-*-*-*-*-*";*/ | |
1121 char * font_set_string = "-dt-interface user-medium-r-normal-s*-*-*-*-*-*-*-*-*, -misc-fixed-medium-r-normal--14-130-75-75-c-70-jisx0201.1976-0,-misc-fixed-medium-r-normal--14-130-75-75-c-140-jisx0208.1983-0, -misc-fixed-medium-r-normal--14-130-75-75-c-70-jisx0201.1976-0" ; | |
1122 | |
1123 DEVICE_X_FONTSET (d) = fontset = | |
1124 XCreateFontSet (dpy, | |
1125 font_set_string, | |
1126 &missing_charsets, | |
1127 &num_missing_charsets, | |
1128 &default_string); | |
1129 | |
1130 if (fontset == NULL) | |
1131 { | |
1132 stderr_out ("Unable to create fontset from string:\n%s\n", font_set_string); | |
1133 return; | |
1134 } | |
1135 if (num_missing_charsets > 0) | |
1136 { | |
1137 int i; | |
1138 stderr_out ("\nMissing charsets for fontset %s:\n", font_set_string); | |
1139 for (i=0; i < num_missing_charsets; i++) | |
1140 { | |
1141 stderr_out ("%s\n", missing_charsets[i]); | |
1142 } | |
1143 XFreeStringList (missing_charsets); | |
1144 stderr_out ("Default string: %s\n", default_string); | |
1145 } | |
1146 | |
1147 #ifdef DEBUG_XIM | |
1148 describe_XFontSet (fontset); | |
1149 #endif | |
1150 } | |
1151 #endif /* 0 */ |