comparison src/input-method-xlib.c @ 70:131b0175ea99 r20-0b30

Import from CVS: tag r20-0b30
author cvs
date Mon, 13 Aug 2007 09:02:59 +0200
parents
children 9ad43877534d
comparison
equal deleted inserted replaced
69:804d1389bcd6 70:131b0175ea99
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 #include <X11/Xlocale.h> /* More portable than <locale.h> ? */
31 #include <config.h>
32 #include "lisp.h"
33 #include "frame.h"
34 #include "device.h"
35 #include "window.h"
36 #include "buffer.h"
37 #include "console-x.h"
38 #include "EmacsFrame.h"
39 #include "events.h"
40
41 #ifndef XIM_XLIB
42 #error XIM_XLIB is not defined??
43 #endif
44
45 /* Get/Set IC values for just one attribute */
46 #ifdef DEBUG_XEMACS
47 #define XIC_Value(Get_Set, xic, name, attr, value) \
48 do { \
49 char *bad_arg; \
50 XVaNestedList list = XVaCreateNestedList (0, attr, value, NULL); \
51 if ((bad_arg = X##Get_Set##ICValues (xic, name, list, NULL)) != NULL) \
52 stderr_out ("X" #Get_Set "ICValues " "bad Arg: %s\n", bad_arg); \
53 XFree (list); \
54 } while (0)
55 #else /* ! DEBUG_XEMACS */
56 #define XIC_Value(Get_Set, xic, name, attr, value) \
57 do { \
58 XVaNestedList list = XVaCreateNestedList (0, attr, value, NULL); \
59 X##Get_Set##ICValues (xic, name, list, NULL); \
60 XFree (list); \
61 } while (0)
62 #endif /* DEBUG_XEMACS */
63
64 static char DefaultXIMStyles[] =
65 "XIMPreeditPosition|XIMStatusArea\n"
66 "XIMPreeditPosition|XIMStatusNone\n"
67 "XIMPreeditPosition|XIMStatusNothing\n"
68 "XIMPreeditNothing|XIMStatusArea\n"
69 "XIMPreeditNothing|XIMStatusNothing\n"
70 "XIMPreeditNothing|XIMStatusNone\n"
71 "XIMPreeditNone|XIMStatusArea\n"
72 "XIMPreeditNone|XIMStatusNothing\n"
73 "XIMPreeditNone|XIMStatusNone";
74
75 static XIMStyle best_style (XIMStyles *user, XIMStyles *xim);
76
77 void
78 Initialize_Locale (void)
79 {
80 char *locale;
81
82 XtSetLanguageProc (NULL, (XtLanguageProc) NULL, NULL);
83 if ((locale = setlocale (LC_ALL, "")) == NULL)
84 {
85 stderr_out ("Can't set locale.\n");
86 stderr_out ("Using C locale instead.\n");
87 putenv ("LANG=C");
88 putenv ("LC_ALL=C");
89 if ((locale = setlocale (LC_ALL, "C")) == NULL)
90 {
91 stderr_out ("Can't even set locale to `C'!\n");
92 return;
93 }
94 }
95
96 if (!XSupportsLocale ())
97 {
98 stderr_out ("X Windows does not support locale `%s'\n", locale);
99 stderr_out ("Using C Locale instead\n");
100 putenv ("LANG=C");
101 putenv ("LC_ALL=C");
102 if ((locale = setlocale (LC_ALL, "C")) == NULL)
103 {
104 stderr_out ("Can't even set locale to `C'!\n");
105 return;
106 }
107 if (!XSupportsLocale ())
108 {
109 stderr_out ("X Windows does not even support locale `C'!\n");
110 return;
111 }
112 }
113
114 if (XSetLocaleModifiers ("") == NULL)
115 {
116 stderr_out ("XSetLocaleModifiers(\"\") failed\n");
117 stderr_out ("Check the value of the XMODIFIERS environment variable.\n");
118 }
119 }
120
121 /* Create X input method for device */
122 void
123 XIM_init_device (struct device *d)
124 {
125 Display *dpy = DEVICE_X_DISPLAY (d);
126 char *name, *class;
127 XIM xim;
128
129 XtGetApplicationNameAndClass (dpy, &name, &class);
130
131 DEVICE_X_XIM (d) = xim = XOpenIM (dpy, XtDatabase (dpy), name, class);
132
133 if (xim == NULL)
134 {
135 stderr_out ("Warning: XOpenIM() failed...no input server available\n");
136 return;
137 }
138 else
139 {
140 /* Get supported styles */
141 XGetIMValues (xim, XNQueryInputStyle, &DEVICE_X_XIM_STYLES (d), NULL);
142 #ifdef DEBUG_XIM
143 describe_XIM (xim);
144 #endif
145 }
146 }
147
148 /* Create an X input context for this frame. */
149 void
150 XIM_init_frame (struct frame *f)
151 {
152 struct device *d = XDEVICE (FRAME_DEVICE (f));
153 XIM xim = DEVICE_X_XIM (d);
154 XIC xic;
155 Widget w = FRAME_X_TEXT_WIDGET (f);
156 Window win = XtWindow (w);
157 XRectangle p_area = {0,0,0,0}, s_area={0,0,0,0};
158 XPoint spot = {0,0};
159 XIMStyle style;
160 XVaNestedList p_list, s_list;
161
162 typedef struct
163 {
164 XIMStyles styles;
165 XFontSet fontset;
166 Pixel fg;
167 Pixel bg;
168 } xic_vars_t;
169
170 xic_vars_t xic_vars;
171
172 /* mrb: #### Fix so that background and foreground is set from
173 default face, rather than foreground and background resources, or
174 that the user can use set-frame-parameters to set xic attributes */
175
176 #define res(name, class, representation, field, default_value) \
177 { name, class, representation, sizeof(xic_vars.field), \
178 XtOffsetOf(xic_vars_t, field), XtRString, default_value }
179
180 static XtResource resources[] =
181 {
182 /* name class represent'n field default value */
183 res(XtNximStyles, XtCXimStyles, XtRXimStyles, styles, DefaultXIMStyles),
184 res(XtNfontSet, XtCFontSet, XtRFontSet, fontset, XtDefaultFontSet),
185 res(XtNximForeground, XtCForeground, XtRPixel, fg, XtDefaultForeground),
186 res(XtNximBackground, XtCBackground, XtRPixel, bg, XtDefaultBackground)
187 };
188
189 assert (win != 0 && w != NULL && d != NULL);
190
191 if (!xim)
192 { /* No input method? */
193 FRAME_X_XIC (f) = NULL;
194 return;
195 }
196
197 XtGetApplicationResources (w, &xic_vars,
198 resources, XtNumber (resources),
199 NULL, 0);
200
201 if (!xic_vars.fontset)
202 {
203 stderr_out ("Can't get fontset resource for Input Method\n");
204 FRAME_X_XIC (f) = NULL;
205 return;
206 }
207
208 FRAME_X_XIC_STYLE (f) = style =
209 best_style (&xic_vars.styles, DEVICE_X_XIM_STYLES (d));
210
211 /* Hopefully we don't have to conditionalize the following based on
212 style; the IM should ignore values it doesn't use */
213 p_list = XVaCreateNestedList (0,
214 XNArea, &p_area,
215 XNSpotLocation, &spot,
216 XNForeground, xic_vars.fg,
217 XNBackground, xic_vars.bg,
218 XNFontSet, xic_vars.fontset,
219 NULL);
220
221 s_list = XVaCreateNestedList (0,
222 XNArea, &s_area,
223 XNForeground, xic_vars.fg,
224 XNBackground, xic_vars.bg,
225 XNFontSet, xic_vars.fontset,
226 NULL);
227
228 FRAME_X_XIC (f) = xic =
229 XCreateIC (xim,
230 XNInputStyle, style,
231 XNClientWindow, win,
232 XNFocusWindow, win,
233 XNPreeditAttributes, p_list,
234 XNStatusAttributes, s_list,
235 NULL);
236 XFree (p_list);
237 XFree (s_list);
238
239 if (!xic)
240 {
241 stderr_out ("Warning: XCreateIC failed\n");
242 return;
243 }
244
245 if (style & XIMPreeditPosition)
246 { /* Init spot to invalid values */
247 XPoint *spot = &(FRAME_X_XIC_SPOT (f));
248 spot->x = spot->y = -1;
249 }
250
251 XIM_SetGeometry (f);
252
253 XSetICFocus (xic);
254
255 #ifdef DEBUG_XIM
256 describe_XIC (xic);
257 #endif
258 }
259
260 void
261 XIM_SetGeometry (struct frame *f)
262 {
263 XIC xic = FRAME_X_XIC (f);
264 XIMStyle style = FRAME_X_XIC_STYLE (f);
265 XRectangle area;
266
267 if (!xic || !f)
268 return;
269
270 if (style & XIMStatusArea)
271 {
272 /* Place Status Area in bottom right corner */
273 /* Negotiate geometry of status area */
274 /* See O'Reilly Xlib XIM chapter (but beware, it's buggy) */
275 XRectangle *needed;
276
277 /* If input method has existing status area, use its current size */
278 /* The following at least works for Sun's htt */
279 area.x = area.y = area.width = area.height = 0;
280 XIC_Value (Set, xic, XNStatusAttributes, XNAreaNeeded, &area);
281 XIC_Value (Get, xic, XNStatusAttributes, XNAreaNeeded, &needed);
282 if (needed->width == 0) /* Use XNArea instead of XNAreaNeeded */
283 XIC_Value (Get, xic, XNStatusAttributes, XNArea, &needed);
284
285 area.width = needed->width;
286 area.height = needed->height;
287 area.x = FRAME_RIGHT_BORDER_START (f) - area.width;
288 area.y = FRAME_BOTTOM_BORDER_START (f) - area.height;
289
290 #ifdef DEBUG_XIM
291 stderr_out ("Putting StatusArea in x=%d y=%d w=%d h=%d\n",
292 area.x, area.y, area.width, area.height);
293 #endif /* DEBUG_XIM */
294
295 XIC_Value (Set, xic, XNStatusAttributes, XNArea, &area);
296 }
297
298 if (style & XIMPreeditPosition)
299 {
300 /* Set Preedit Area to whole frame size (sans border) */
301 /* We include the border because Preedit window might be larger
302 than display line at edge. #### FIX: we should adjust to make
303 sure that there is always room for the spot sub-window */
304 area.x = FRAME_LEFT_BORDER_START (f);
305 area.y = FRAME_TOP_BORDER_START (f);
306 area.width = FRAME_RIGHT_BORDER_END (f) - area.x;
307 area.height = FRAME_BOTTOM_BORDER_END (f) - area.y;
308 XIC_Value(Set, xic, XNPreeditAttributes, XNArea, &area);
309 }
310
311 #ifdef DEBUG_XIM
312 describe_XIC (xic);
313 #endif
314 }
315
316 void
317 XIM_SetSpotLocation (struct frame *f, int x, int y)
318 {
319 XIC xic = FRAME_X_XIC (f);
320 XPoint *spot = &(FRAME_X_XIC_SPOT (f));
321
322 /* Only care if we have a valid XIC using Over the Spot in
323 * a different location */
324 if (!xic ||
325 !(FRAME_X_XIC_STYLE (f) & XIMPreeditPosition) ||
326 (spot->x == (short) x &&
327 spot->y == (short) y))
328 return;
329
330 spot->x = (short) x;
331 spot->y = (short) y;
332
333 /* ### FIX: Must make sure spot fits within Preedit Area */
334 XIC_Value (Set, xic, XNPreeditAttributes, XNSpotLocation, spot);
335 #ifdef DEBUG_XIM
336 stderr_out ("Spot: %d %d\n", spot->x, spot->y);
337 #endif
338 }
339
340 void
341 XIM_focus_event (struct frame *f, int in_p)
342 {
343 if (FRAME_X_XIC (f))
344 (in_p ? XSetICFocus : XUnsetICFocus) (FRAME_X_XIC (f));
345 }
346
347 #if 0
348 #define XIM_Composed_Text_BUFSIZE 64
349 typedef struct XIM_Composed_Text
350 {
351 int size;
352 wchar_t data [XIM_Composed_Text_BUFSIZE];
353 } XIM_Composed_Text;
354
355 static XIM_Composed_Text composed_input_buf = {XIM_Composed_Text_BUFSIZE, {0}};
356 Window main_window;
357
358 /* get_XIM_input -- Process results of input method composition.
359
360 This function copies the results of the input method composition to
361 composed_input_buf. Then for each character, a custom event of type
362 wc_atom is sent with the character as its data.
363
364 It is probably more efficient to copy the composition results to some
365 allocated memory and send a single event pointing to that memory.
366 That would cut down on the event processing as well as allow quick
367 insertion into the buffer of the whole string. It might require some
368 care, though, to avoid fragmenting memory through the allocation and
369 freeing of many small chunks. Maybe the existing system for
370 (single-byte) string allocation can be used, multiplying the length by
371 sizeof (wchar_t) to get the right size.
372 */
373 void
374 get_XIM_input (XKeyPressedEvent *x_key_event, XIC ic, Display *dpy)
375 {
376 KeySym keysym;
377 Status status;
378 int len;
379 int i;
380 XClientMessageEvent new_event;
381
382 try_again:
383 len = XwcLookupString (ic, x_key_event, composed_input_buf.data,
384 composed_input_buf.size, &keysym, &status);
385 switch (status)
386 {
387 case XBufferOverflow:
388 /* GROW_WC_STRING (&composed_input_buf, 32); mrb */
389 goto try_again;
390 case XLookupChars:
391 break;
392 default:
393 abort ();
394 }
395
396 new_event.type = ClientMessage;
397 new_event.display = x_key_event->display;
398 new_event.window = x_key_event->window;
399 new_event.message_type = wc_atom;
400 new_event.format = 32; /* 32-bit wide data */
401 new_event.data.l[2] = new_event.data.l[3] = new_event.data.l[4] = 0L;
402 new_event.data.l[0] = x_key_event->time;
403 for (i = 0; i < len; i++)
404 {
405 new_event.data.l[1] = ((wchar_t *) composed_input_buf.data)[i];
406 XSendEvent (display, main_window, False, 0L, (XEvent *) &new_event);
407 }
408 }
409 #endif /* 0 */
410
411 /* ============================================================== */
412 /* X input method style determination */
413 /* ============================================================== */
414
415 #if 0
416 #define done(type, value) \
417 if (toVal->addr != NULL) { \
418 if (toVal->size < sizeof(type)) { \
419 toVal->size = sizeof(type); \
420 return False; \
421 } \
422 *(type*)toVal->addr = (value); \
423 } else { \
424 static type static_val; \
425 static_val = (value); \
426 toVal->addr = (XPointer)&static_val; \
427 } \
428 toVal->size = sizeof(type); \
429 return True /* Caller supplies `;' */
430 #endif /* 0 */
431
432 /*
433 * This is a standard Xt type converter, except that the caller MUST
434 * supply a proper non-NULL toVal XIMStyles structure that we will
435 * fill in.
436 *
437 * fromVal points to a string like
438 *
439 "XIMPreeditPosition|XIMStatusArea,
440 XIMPreeditPosition|XIMStatusNothing
441 XIMPreeditNothing|XIMStatusNothing"
442 *
443 * This is converted in the obvious way to a XIMStyles structure.
444 *
445 * mrb: #### Fix this to handle Motif-style specifications for
446 * XIMStyles as well: overTheSpot, rootWindow, none */
447
448 /* XtTypeConverter */
449 Boolean
450 EmacsXtCvtStringToXIMStyles (
451 Display *dpy,
452 XrmValuePtr args,
453 Cardinal *num_args,
454 XrmValuePtr fromVal,
455 XrmValuePtr toVal,
456 XtPointer *converter_data)
457 {
458 #define STYLE_INFO(style) { style, #style, sizeof(#style) }
459 static struct XIMStyleInfo
460 {
461 CONST XIMStyle style;
462 CONST char * CONST name;
463 CONST int namelen;
464 } emacs_XIMStyleInfo[] = {
465 STYLE_INFO (XIMPreeditPosition|XIMStatusArea),
466 STYLE_INFO (XIMPreeditPosition|XIMStatusNothing),
467 STYLE_INFO (XIMPreeditPosition|XIMStatusNone),
468 STYLE_INFO (XIMPreeditNothing|XIMStatusArea),
469 STYLE_INFO (XIMPreeditNothing|XIMStatusNothing),
470 STYLE_INFO (XIMPreeditNothing|XIMStatusNone),
471 STYLE_INFO (XIMPreeditNone|XIMStatusArea),
472 STYLE_INFO (XIMPreeditNone|XIMStatusNothing),
473 STYLE_INFO (XIMPreeditNone|XIMStatusNone)
474 };
475 #undef STYLE_INFO
476
477 CONST char *s = (char *) fromVal->addr;
478 CONST char *end = s + fromVal->size;
479 XIMStyles * CONST p = (XIMStyles *) toVal->addr;
480 CONST char * CONST delimiter = " \t\n\r:;," ;
481 CONST int max_styles = XtNumber(emacs_XIMStyleInfo);
482 int i;
483 char *c;
484
485 #ifdef DEBUG_XIM
486 stderr_out ("EmacsCvtStringToXIMStyles called with size=%d, string=\"%s\"\n",
487 fromVal->size, (char *) fromVal->addr);
488 #endif /* DEBUG_XIM */
489
490 if (*num_args != 0)
491 {
492 XtAppContext the_app_con = XtDisplayToApplicationContext (dpy);
493 XtAppWarningMsg(the_app_con, "wrongParameters", "cvtStringToXIMStyle",
494 "XtToolkitError",
495 "String to XIMStyle conversion requires exactly 0 parameters",
496 (String *)NULL, (Cardinal *)NULL);
497 return False;
498 }
499
500 #ifdef DEBUG_XEMACS
501 /* Make sure caller is giving us good data */
502 assert (fromVal->addr != NULL);
503 assert (fromVal->size == strlen(fromVal->addr)+1);
504 assert (toVal->addr != NULL);
505 assert (toVal->size == sizeof(XIMStyles));
506 #endif /* DEBUG_XEMACS */
507
508 p->count_styles = 0;
509 p->supported_styles = xmalloc (max_styles * sizeof (XIMStyle));
510
511 /*
512 * The following routine assumes that the style name resource is
513 * identical with the programmatic name of style. For example,
514 * "XIMPreeditPosition|XIMStatusArea" means the
515 * XIMPreeditPosition|XIMStatusArea value is specified. If the
516 * style name is changed, such as "OverTheSpot|imDisplaysInClient",
517 * the parsing logic below should be modified as well. */
518
519 if ((c = strtok(s, delimiter)) == NULL)
520 c = end;
521
522 while (c < end)
523 {
524 for(i=0 ; i<max_styles ; i++)
525 {
526 struct XIMStyleInfo *rec = emacs_XIMStyleInfo + i;
527 if(!strncmp(c, rec->name, rec->namelen - 1)) {
528 p->supported_styles[p->count_styles] = rec->style;
529 p->count_styles++;
530 break;
531 }
532 }
533 if((c = strtok(NULL, delimiter)) == NULL) {
534 break ;
535 }
536 }
537
538 if (p->count_styles == 0)
539 { /* No valid styles? */
540 char buf[1024];
541 XrmValue new_from;
542 XtAppContext the_app_con = XtDisplayToApplicationContext (dpy);
543
544 sprintf(buf, "Cannot convert string \"%s\" to type XIMStyles.\n"
545 "Using default string \"%s\" instead.\n",
546 fromVal->addr, DefaultXIMStyles);
547 XtAppWarningMsg(the_app_con, "wrongParameters", "cvtStringToXIMStyle",
548 "XtToolkitError",
549 buf, (String *)NULL, (Cardinal *)NULL);
550 new_from.addr = DefaultXIMStyles;
551 new_from.size = sizeof(DefaultXIMStyles);
552 return EmacsXtCvtStringToXIMStyles (dpy, args, num_args,
553 &new_from, toVal, converter_data);
554 }
555 p->supported_styles = xrealloc (p->supported_styles,
556 p->count_styles * sizeof(XIMStyle));
557 *converter_data = (char *) True;
558 return True;
559 }
560
561 /* XtDestructor */
562 void
563 EmacsFreeXIMStyles (
564 XtAppContext app,
565 XrmValuePtr toVal,
566 XtPointer converter_data,
567 XrmValuePtr args,
568 Cardinal *num_args)
569 {
570 #ifdef DEBUG_XIM
571 stderr_out ("Converter data: %x\n", converter_data);
572 stderr_out ("EmacsFreeXIMStyles called\n");
573 #endif /* DEBUG_XIM */
574
575 if (*num_args != 0)
576 {
577 XtAppWarningMsg(app, "wrongParameters","freeXIMStyles","XtToolkitError",
578 "Freeing an XIMStyles requires that zero arguments be passwd",
579 (String *)NULL, (Cardinal *)NULL);
580 return;
581 }
582
583 if (converter_data)
584 {
585 Boolean free_p = (Boolean) (int) converter_data;
586 XIMStyles *styles = (XIMStyles *) toVal->addr;
587 if (free_p)
588 XFree ( styles->supported_styles );
589 }
590 }
591
592 #if 0
593 /* O'Reilly XLib Programming Manual, pg. 371 */
594 /* Much nicer implementation than O'Reilly */
595 /* Choose the more `complicated', hence nicer, XIM input style */
596 static XIMStyle
597 BetterStyle (XIMStyle s, XIMStyle t)
598 {
599 #define CHECK_XIMStyle_BIT(bit) \
600 if ((s ^ t) & bit) { return (s & bit) ? s : t; }
601
602 CHECK_XIMStyle_BIT (XIMPreeditCallbacks);
603 CHECK_XIMStyle_BIT (XIMPreeditPosition);
604 CHECK_XIMStyle_BIT (XIMPreeditArea);
605 CHECK_XIMStyle_BIT (XIMPreeditNothing);
606 CHECK_XIMStyle_BIT (XIMStatusCallbacks);
607 CHECK_XIMStyle_BIT (XIMStatusArea);
608 CHECK_XIMStyle_BIT (XIMStatusNothing);
609 #undef CHECK_XIMStyle_BIT
610 return s ? s : t ;
611 }
612 #endif /* 0 */
613
614 /* Choose the best style, given:
615 * - user preferences (already checked to be supported by XEmacs)
616 * - styles supported by the input method */
617 #define DEFAULTStyle (XIMPreeditNothing|XIMStatusNothing)
618 static XIMStyle
619 best_style (XIMStyles *user, XIMStyles *xim)
620 {
621 register int i, j;
622 for (i=0 ; i<user->count_styles ; i++)
623 {
624 for (j=0 ; j<xim->count_styles ; j++)
625 {
626 if (user->supported_styles[i] == xim->supported_styles[j])
627 return user->supported_styles[i];
628 }
629 }
630 return DEFAULTStyle; /* Default Style */
631 }
632
633
634 void
635 vars_of_input_method_xlib (void)
636 {
637 Fprovide (intern ("xim"));
638 }
639
640
641 /* ====================================================================== */
642 /* Internal Debugging Routines */
643 /* ====================================================================== */
644 #ifdef DEBUG_XEMACS
645
646 void
647 describe_XIM (XIM xim)
648 {
649 XIMStyles *styles;
650
651 /* Print locale of XIM */
652 stderr_out ("\nXIM Locale of IM: %s\n", XLocaleOfIM(xim));
653
654 /* List supported input method styles */
655 XGetIMValues(xim, XNQueryInputStyle, &styles, NULL);
656
657 stderr_out ("\n%d input style(s) supported by input method.\n",
658 styles->count_styles);
659
660 #ifdef DEBUG_XIM
661 {
662 int i;
663 for (i=0; i < styles->count_styles; i++)
664 describe_XIMStyle (styles->supported_styles[i]);
665 }
666 #endif /* DEBUG_XIM */
667 XFree(styles);
668 }
669
670 void
671 describe_XFontSet (XFontSet fontset)
672 {
673 XFontStruct **font_struct_list;
674 char **font_name_list;
675 int count, i;
676
677 if (fontset == NULL)
678 {
679 stderr_out ("NULL\n");
680 return;
681 }
682
683 count = XFontsOfFontSet (fontset, &font_struct_list, &font_name_list);
684 stderr_out ( "%d font(s) available:\n", count);
685 for (i=0 ; i < count ; i++)
686 stderr_out ("Font: %s\n", *(font_name_list+i));
687 }
688
689 void
690 describe_Status (Status status)
691 {
692 #define DESCRIBE_STATUS(value) \
693 if (status == value) stderr_out ("Status: " #value "\n")
694
695 DESCRIBE_STATUS (XBufferOverflow);
696 DESCRIBE_STATUS (XLookupNone);
697 DESCRIBE_STATUS (XLookupKeySym);
698 DESCRIBE_STATUS (XLookupBoth);
699 DESCRIBE_STATUS (XLookupChars);
700 #undef DESCRIBE_STATUS
701 }
702
703 void
704 describe_Window (Window win)
705 {
706 char xwincmd[64];
707 sprintf (xwincmd, "xwininfo -id 0x%x >&2; xwininfo -events -id 0x%x >&2",
708 (int) win, (int) win);
709 system (xwincmd);
710 }
711
712 void
713 describe_XIC (XIC xic)
714 {
715 XIMStyle style;
716 Window client_win=0, focus_win=0;
717 char *resourceName = NULL;
718 char *resourceClass = NULL;
719 char *bad_arg = NULL;
720 unsigned long filter_mask = NoEventMask;
721 XVaNestedList p_list, s_list;
722 XFontSet p_fontset = NULL, s_fontset = NULL;
723 Pixel p_fg=0, p_bg = 0, s_fg=0, s_bg = 0;
724 XRectangle *p_area = NULL, *s_area = NULL;
725 XRectangle *p_needed = NULL, *s_needed = NULL;
726 XPoint *p_spot = NULL;
727
728 /* Check for valid input context and method */
729 if (!xic)
730 stderr_out ("Input method is NULL\n");
731
732 if (!XIMOfIC(xic))
733 stderr_out ("XIMOfIC() returns NULL\n");
734
735 /* Print out Input Context Attributes */
736 p_list = XVaCreateNestedList (0,
737 XNFontSet, &p_fontset,
738 XNArea, &p_area,
739 XNAreaNeeded, &p_needed,
740 XNSpotLocation, &p_spot,
741 XNForeground, &p_fg,
742 XNBackground, &p_bg,
743 NULL);
744
745 s_list = XVaCreateNestedList (0,
746 XNFontSet, &s_fontset,
747 XNArea, &s_area,
748 XNAreaNeeded, &s_needed,
749 XNForeground, &s_fg,
750 XNBackground, &s_bg,
751 NULL);
752
753 bad_arg = XGetICValues(xic,
754 XNInputStyle, &style,
755 XNFilterEvents, &filter_mask,
756 XNClientWindow, &client_win,
757 XNFocusWindow, &focus_win,
758 XNResourceName, &resourceName,
759 XNResourceClass, &resourceClass,
760 XNPreeditAttributes, p_list,
761 XNStatusAttributes, s_list,
762 NULL);
763 XFree(p_list);
764 XFree(s_list);
765
766 if (bad_arg != NULL)
767 stderr_out ("Couldn't get IC value: %s\n", bad_arg);
768
769 stderr_out ("\nInput method context attributes:\n");
770 stderr_out ("Style: "); describe_XIMStyle (style);
771 stderr_out ("Client window: %x\n", client_win);
772 stderr_out ("Focus window: %x\n", focus_win);
773 stderr_out ("Preedit:\n");
774 describe_XRectangle (" Area", p_area);
775 describe_XRectangle (" Area needed", p_needed);
776 stderr_out (" foreground: %x\n", p_fg);
777 stderr_out (" background: %x\n", p_bg);
778 stderr_out (" fontset: "); describe_XFontSet (p_fontset);
779 stderr_out ("Status:\n");
780 describe_XRectangle (" Area", s_area);
781 describe_XRectangle (" Area needed", s_needed);
782 stderr_out (" foreground: %x\n", s_fg);
783 stderr_out (" background: %x\n", s_bg);
784 stderr_out (" fontset: \n"); describe_XFontSet (s_fontset);
785 stderr_out ("XNResourceName: %s\n", resourceName ? resourceName : "NULL");
786 stderr_out ("XNResourceClass: %s\n", resourceClass ? resourceClass : "NULL");
787 stderr_out ("XNFilterEvents: "); describe_event_mask (filter_mask);
788 }
789
790 void
791 describe_XRectangle (char *name, XRectangle *r)
792 {
793 if (r == NULL)
794 stderr_out ("%s: NULL\n", name);
795 else
796 stderr_out ("%s: x=%d y=%d w=%d h=%d\n",
797 name, r->x, r->y, r->width, r->height);
798 }
799
800 /* Print out elements of Event mask */
801 /* Defines from X11/X.h */
802 void
803 describe_event_mask (unsigned long mask)
804 {
805 #define DESCRIBE_EVENT_MASK(bit) if ((bit) & mask) stderr_out (#bit " ")
806 DESCRIBE_EVENT_MASK (NoEventMask);
807 DESCRIBE_EVENT_MASK (KeyPressMask);
808 DESCRIBE_EVENT_MASK (KeyReleaseMask);
809 DESCRIBE_EVENT_MASK (ButtonPressMask);
810 DESCRIBE_EVENT_MASK (ButtonReleaseMask);
811 DESCRIBE_EVENT_MASK (EnterWindowMask);
812 DESCRIBE_EVENT_MASK (LeaveWindowMask);
813 DESCRIBE_EVENT_MASK (PointerMotionMask);
814 DESCRIBE_EVENT_MASK (PointerMotionHintMask);
815 DESCRIBE_EVENT_MASK (Button1MotionMask);
816 DESCRIBE_EVENT_MASK (Button2MotionMask);
817 DESCRIBE_EVENT_MASK (Button3MotionMask);
818 DESCRIBE_EVENT_MASK (Button4MotionMask);
819 DESCRIBE_EVENT_MASK (Button5MotionMask);
820 DESCRIBE_EVENT_MASK (ButtonMotionMask);
821 DESCRIBE_EVENT_MASK (KeymapStateMask);
822 DESCRIBE_EVENT_MASK (ExposureMask);
823 DESCRIBE_EVENT_MASK (VisibilityChangeMask);
824 DESCRIBE_EVENT_MASK (StructureNotifyMask);
825 DESCRIBE_EVENT_MASK (ResizeRedirectMask);
826 DESCRIBE_EVENT_MASK (SubstructureNotifyMask);
827 DESCRIBE_EVENT_MASK (SubstructureRedirectMask);
828 DESCRIBE_EVENT_MASK (FocusChangeMask);
829 DESCRIBE_EVENT_MASK (PropertyChangeMask);
830 DESCRIBE_EVENT_MASK (ColormapChangeMask);
831 DESCRIBE_EVENT_MASK (OwnerGrabButtonMask);
832 #undef DESCRIBE_EVENT_MASK
833 stderr_out("\n");
834 }
835
836 void
837 describe_XIMStyle (XIMStyle style)
838 {
839 #define DESCRIBE_STYLE(bit) \
840 if (bit & style) \
841 stderr_out (#bit " ");
842
843 DESCRIBE_STYLE (XIMPreeditArea);
844 DESCRIBE_STYLE (XIMPreeditCallbacks);
845 DESCRIBE_STYLE (XIMPreeditPosition);
846 DESCRIBE_STYLE (XIMPreeditNothing);
847 DESCRIBE_STYLE (XIMPreeditNone);
848 DESCRIBE_STYLE (XIMStatusArea);
849 DESCRIBE_STYLE (XIMStatusCallbacks);
850 DESCRIBE_STYLE (XIMStatusNothing);
851 DESCRIBE_STYLE (XIMStatusNone);
852 #undef DESCRIBE_STYLE
853 stderr_out("\n");
854 }
855
856 void
857 describe_XIMStyles (XIMStyles *p)
858 {
859 int i;
860 stderr_out ("%d Style(s):\n", p->count_styles);
861 for (i=0; i<p->count_styles ; i++)
862 {
863 describe_XIMStyle (p->supported_styles[i]);
864 }
865 }
866
867 #endif /* DEBUG_XEMACS */
868
869 /* Random cruft follows */
870
871 #if 0
872 static void
873 Unit_Test (struct frame *f, char * s)
874 /* mrb unit testing */
875 {
876 XrmValue fromVal, toVal;
877
878 fromVal.addr = s;
879 fromVal.size = strlen (s);
880 toVal.addr = (XtPointer) &user_preferred_XIMStyles;
881 toVal.size = sizeof (XIMStyles);
882
883 if (XtConvertAndStore (FRAME_X_TEXT_WIDGET (f), XtRString, &fromVal,
884 XtRXimStyles, &toVal) != False)
885 {
886 stderr_out ("Unit_Test: fromVal.addr=0x%x\n",fromVal.addr);
887 stderr_out ("Unit_Test: fromVal.size=%d\n", fromVal.size);
888 stderr_out ("Unit_Test: toVal.addr=0x%x\n", toVal.addr);
889 stderr_out ("Unit_Test: toVal.size=%d\n", toVal.size);
890 describe_XIMStyles ((XIMStyles *) toVal.addr);
891 }
892 }
893 #endif
894
895 #if 0
896 /* Get a fontset for IM to use */
897 void
898 x_init_fontset (struct device *d)
899 {
900 Display *dpy = DEVICE_X_DISPLAY (d);
901 XFontSet fontset;
902 char ** missing_charsets;
903 int num_missing_charsets;
904 char * default_string;
905 /* char * font_set_string = "-dt-interface user-medium-r-normal-s*-*-*-*-*-*-*-*-*";*/
906 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" ;
907
908 DEVICE_X_FONTSET (d) = fontset =
909 XCreateFontSet (dpy,
910 font_set_string,
911 &missing_charsets,
912 &num_missing_charsets,
913 &default_string);
914
915 if (fontset == NULL)
916 {
917 stderr_out ("Unable to create fontset from string:\n%s\n", font_set_string);
918 return;
919 }
920 if (num_missing_charsets > 0)
921 {
922 int i;
923 stderr_out ("\nMissing charsets for fontset %s:\n", font_set_string);
924 for (i=0; i < num_missing_charsets; i++)
925 {
926 stderr_out ("%s\n", missing_charsets[i]);
927 }
928 XFreeStringList (missing_charsets);
929 stderr_out ("Default string: %s\n", default_string);
930 }
931
932 #ifdef DEBUG_XIM
933 describe_XFontSet (fontset);
934 #endif
935 }
936 #endif /* 0 */