comparison lib/imlib/imattr.c @ 0:92745d501b9a

initial import from kinput2-v3.1
author Yoshiki Yazawa <yaz@honeyplanet.jp>
date Mon, 08 Mar 2010 04:44:30 +0900
parents
children 1f9e9cb00c6c
comparison
equal deleted inserted replaced
-1:000000000000 0:92745d501b9a
1 #ifndef lint
2 static char *rcsid = "$Id: imattr.c,v 1.18 2002/01/10 15:04:05 ishisone Exp $";
3 #endif
4 /*
5 * Copyright (c) 1994 Software Research Associates, Inc.
6 *
7 * Permission to use, copy, modify, and distribute this software and its
8 * documentation for any purpose and without fee is hereby granted, provided
9 * that the above copyright notice appear in all copies and that both that
10 * copyright notice and this permission notice appear in supporting
11 * documentation, and that the name of Software Research Associates not be
12 * used in advertising or publicity pertaining to distribution of the
13 * software without specific, written prior permission. Software Research
14 * Associates makes no representations about the suitability of this software
15 * for any purpose. It is provided "as is" without express or implied
16 * warranty.
17 *
18 * Author: Makoto Ishisone, Software Research Associates, Inc., Japan
19 */
20
21 #include "im.h"
22
23 #ifndef XNSeparatorofNestedList
24 #define XNSeparatorofNestedList "separatorofNesttedList"
25 #endif
26 #ifndef XNPreeditState
27 #define XNPreeditState "preeditState"
28 #endif
29 #ifndef XIMPreeditEnable
30 #define XIMPreeditEnable 1L
31 #define XIMPreeditDisable 2L
32 #endif
33 #ifndef XNResetState
34 #define XNResetState "resetState"
35 #endif
36 #ifndef XIMInitialState
37 #define XIMInitialState 1L
38 #define XIMPreserveState 2L
39 #endif
40
41 #define PAD4(n) ((((n) + 3) / 4) * 4)
42
43 /*
44 * List of supported input styles.
45 */
46
47 typedef struct {
48 XIMStyle xim_style; /* X11R5 spec. */
49 int conversion_style; /* kinput2 spec. */
50 } InputStyle;
51
52 static InputStyle styles[] = {
53 { XIMPreeditPosition|XIMStatusArea, IMSTYLE_OVER_THE_SPOT },
54 { XIMPreeditPosition|XIMStatusNothing, IMSTYLE_OVER_THE_SPOT },
55 { XIMPreeditArea|XIMStatusArea, IMSTYLE_OFF_THE_SPOT },
56 { XIMPreeditCallbacks|XIMStatusCallbacks, IMSTYLE_ON_THE_SPOT },
57 { XIMPreeditCallbacks|XIMStatusNothing, IMSTYLE_ON_THE_SPOT },
58 { XIMPreeditNothing|XIMStatusNothing, IMSTYLE_SEPARATE },
59 { 0 },
60 };
61
62 #define NEST_NONE 0
63 #define NEST_PREEDIT 1
64 #define NEST_STATUS 2
65
66 #define CHECK_ICATTR_SIZE(validsize, code) \
67 if (len != validsize) { badSizeError(icp, code); return -1; }
68
69 #undef OP_C
70 #undef OP_S
71 #undef OP_G
72
73 #define OP_C 1 /* Create */
74 #define OP_S 2 /* SetValues */
75 #define OP_G 4 /* GetValues */
76
77 typedef struct {
78 char *name; /* attribute name */
79 int type; /* type of attribute value */
80 int valid_ops; /* valid operations for this attribute */
81 int (*set_proc) _Pt_((IMIM *, char *, int));
82 int (*get_proc) _Pt_((IMIM *, unsigned int, int));
83 } IMAttribute;
84
85 typedef struct {
86 char *name; /* attribute name */
87 int type; /* type of attribute value */
88 int valid_ops; /* valid operations for this attribute */
89 int (*set_proc) _Pt_((IMIC *, char *, int, int, int, int));
90 int (*get_proc) _Pt_((IMIC *, unsigned int, int, int, char *, int));
91 } ICAttribute;
92
93
94 /*
95 * IM attributes
96 */
97
98 static int getQueryInputStyle _Pt_((IMIM *imp, unsigned int id, int offset));
99
100 static IMAttribute imAttributes[] = {
101 { XNQueryInputStyle, TYPE_XIM_STYLES, OP_G,
102 NULL, getQueryInputStyle },
103 };
104
105 static int numImAttributes = XtNumber(imAttributes);
106
107
108 /*
109 * IC attributes
110 */
111
112 static int setInputStyle _Pt_((IMIC *, char *, int, int, int, int));
113 static int setClientWindow _Pt_((IMIC *, char *, int, int, int, int));
114 static int setFocusWindow _Pt_((IMIC *, char *, int, int, int, int));
115 static int setPreeditAttributes _Pt_((IMIC *, char *, int, int, int, int));
116 static int setStatusAttributes _Pt_((IMIC *, char *, int, int, int, int));
117 static int setArea _Pt_((IMIC *, char *, int, int, int, int));
118 static int setAreaNeeded _Pt_((IMIC *, char *, int, int, int, int));
119 static int setForeground _Pt_((IMIC *, char *, int, int, int, int));
120 static int setBackground _Pt_((IMIC *, char *, int, int, int, int));
121 static int setColormap _Pt_((IMIC *, char *, int, int, int, int));
122 static int setBgPixmap _Pt_((IMIC *, char *, int, int, int, int));
123 static int setLineSpace _Pt_((IMIC *, char *, int, int, int, int));
124 static int setCursor _Pt_((IMIC *, char *, int, int, int, int));
125 static int setSpotLocation _Pt_((IMIC *, char *, int, int, int, int));
126 static int setStdColormap _Pt_((IMIC *, char *, int, int, int, int));
127 static int setFontSet _Pt_((IMIC *, char *, int, int, int, int));
128 static int setPreeditState _Pt_((IMIC *, char *, int, int, int, int));
129 static int setResetState _Pt_((IMIC *, char *, int, int, int, int));
130
131 static int getPreeditAttributes _Pt_((IMIC *, unsigned int, int, int, char *, int));
132 static int getStatusAttributes _Pt_((IMIC *, unsigned int, int, int, char *, int));
133 static int getInputStyle _Pt_((IMIC *, unsigned int, int, int, char *, int));
134 static int getClientWindow _Pt_((IMIC *, unsigned int, int, int, char *, int));
135 static int getFocusWindow _Pt_((IMIC *, unsigned int, int, int, char *, int));
136 static int getFilterEvents _Pt_((IMIC *, unsigned int, int, int, char *, int));
137 static int getArea _Pt_((IMIC *, unsigned int, int, int, char *, int));
138 static int getAreaNeeded _Pt_((IMIC *, unsigned int, int, int, char *, int));
139 static int getSpotLocation _Pt_((IMIC *, unsigned int, int, int, char *, int));
140 static int getColormap _Pt_((IMIC *, unsigned int, int, int, char *, int));
141 static int getStdColormap _Pt_((IMIC *, unsigned int, int, int, char *, int));
142 static int getForeground _Pt_((IMIC *, unsigned int, int, int, char *, int));
143 static int getBackground _Pt_((IMIC *, unsigned int, int, int, char *, int));
144 static int getBgPixmap _Pt_((IMIC *, unsigned int, int, int, char *, int));
145 static int getFontSet _Pt_((IMIC *, unsigned int, int, int, char *, int));
146 static int getLineSpace _Pt_((IMIC *, unsigned int, int, int, char *, int));
147 static int getCursor _Pt_((IMIC *, unsigned int, int, int, char *, int));
148 static int getPreeditState _Pt_((IMIC *, unsigned int, int, int, char *, int));
149 static int getResetState _Pt_((IMIC *, unsigned int, int, int, char *, int));
150
151 static ICAttribute icAttributes[] = {
152 { XNInputStyle, TYPE_CARD32, OP_C|OP_G,
153 setInputStyle, getInputStyle },
154 { XNClientWindow, TYPE_WINDOW, OP_C|OP_S|OP_G,
155 setClientWindow, getClientWindow },
156 { XNFocusWindow, TYPE_WINDOW, OP_C|OP_S|OP_G,
157 setFocusWindow, getFocusWindow },
158 { XNFilterEvents, TYPE_CARD32, OP_G,
159 NULL, getFilterEvents },
160 { XNPreeditAttributes, TYPE_NESTED_LIST, OP_C|OP_S|OP_G,
161 setPreeditAttributes, getPreeditAttributes },
162 { XNStatusAttributes, TYPE_NESTED_LIST, OP_C|OP_S|OP_G,
163 setStatusAttributes, getStatusAttributes },
164 { XNArea, TYPE_XRECTANGLE, OP_C|OP_S|OP_G,
165 setArea, getArea },
166 { XNAreaNeeded, TYPE_XRECTANGLE, OP_C|OP_S|OP_G,
167 setAreaNeeded, getAreaNeeded },
168 { XNSpotLocation, TYPE_XPOINT, OP_C|OP_S|OP_G,
169 setSpotLocation, getSpotLocation },
170 { XNColormap, TYPE_CARD32, OP_C|OP_S|OP_G,
171 setColormap, getColormap },
172 { XNStdColormap, TYPE_CARD32, OP_C|OP_S|OP_G,
173 setStdColormap, getStdColormap },
174 { XNForeground, TYPE_CARD32, OP_C|OP_S|OP_G,
175 setForeground, getForeground },
176 { XNBackground, TYPE_CARD32, OP_C|OP_S|OP_G,
177 setBackground, getBackground },
178 { XNBackgroundPixmap, TYPE_CARD32, OP_C|OP_S|OP_G,
179 setBgPixmap, getBgPixmap },
180 { XNFontSet, TYPE_XFONTSET, OP_C|OP_S|OP_G,
181 setFontSet, getFontSet },
182 { XNLineSpace, TYPE_CARD16, OP_C|OP_S|OP_G, /* should be TYPE_INT16 */
183 setLineSpace, getLineSpace },
184 { XNCursor, TYPE_CARD32, OP_C|OP_S|OP_G,
185 setCursor, getCursor },
186 { XNSeparatorofNestedList, TYPE_SEPARATOR, OP_G,
187 NULL, NULL },
188 { XNPreeditState, TYPE_CARD32, OP_C|OP_S|OP_G,
189 setPreeditState, getPreeditState },
190 { XNResetState, TYPE_CARD32, OP_C|OP_S|OP_G,
191 setResetState, getResetState },
192 };
193
194 static int numIcAttributes = XtNumber(icAttributes);
195
196
197 static unsigned int getC16 _Pt_((char *data, int order));
198 static int getI16 _Pt_((char *data, int order));
199 static unsigned long getC32 _Pt_((char *data, int order));
200 static int validateClientWindow _Pt_((IMIC *icp));
201 static int validateFocusWindow _Pt_((IMIC *icp));
202 static void badSizeError _Pt_((IMIC *icp, int code));
203 static void unnestedError _Pt_((IMIC *icp));
204 static IMPSAttributes *getPSPtr _Pt_((IMIC *icp, int type));
205 static int getIMValues _Pt_((IMIM *imp, char *data, int len, int offset));
206 static int getICValues _Pt_((IMIC *icp, char *data, int len, int nest,
207 int offset, int *sepp));
208 static int setICValues _Pt_((IMIC *icp, char *data, int len,
209 int major, int op));
210 static int getPSAttributes _Pt_((IMIC *icp, unsigned int id, int nest,
211 int offset, char *data, int len));
212 static void changeFonts _Pt_((IMIC *icp, int preedit));
213 static void fillCommonDefault _Pt_((IMIC *icp, unsigned long mask));
214 static int getNaturalLineSpace _Pt_((IMIC *icp, int preedit));
215 static void fillPSDefault _Pt_((IMIC *icp, int type, unsigned long mask));
216 static int validateCommonAttr _Pt_((IMIC *icp, int checkonly));
217 static int validatePSAttr _Pt_((IMIC *icp, int type, int checkonly));
218 static void changeConversionAttributes _Pt_((IMIC *icp));
219 static void computeAreaNeeded _Pt_((IMIC *icp));
220 static void computeAreaForQuery _Pt_((IMIC *icp));
221
222
223 /*
224 * Functions reading out numbers from byte buffer
225 */
226
227 static unsigned int
228 getC16(data, order)
229 char *data;
230 int order;
231 {
232 unsigned char *p = (unsigned char *)data;
233 unsigned int x;
234
235 x = (order == ORDER_BIG) ? ((p[0] << 8) | p[1]) : (p[0] | p[1] << 8);
236 return x;
237 }
238
239 static int
240 getI16(data, order)
241 char *data;
242 int order;
243 {
244 unsigned char *p = (unsigned char *)data;
245 long l;
246
247 l = (order == ORDER_BIG) ? ((p[0] << 8) | p[1]) : (p[0] | p[1] << 8);
248 return (l < 32768) ? (int)l : (int)(l - 65536L);
249 }
250
251 static unsigned long
252 getC32(data, order)
253 char *data;
254 int order;
255 {
256 unsigned char *p = (unsigned char *)data;
257 unsigned long x;
258
259 if (order == ORDER_BIG) {
260 x = (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
261 } else {
262 x = p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24);
263 }
264 return x;
265 }
266
267
268 /*
269 * Functions that check the validity of resources.
270 */
271
272 static int
273 validateClientWindow(icp)
274 IMIC *icp;
275 {
276 return IMValidateWindow(XtDisplay(icp->im->connection->proto_widget),
277 icp->common_attr.client, &icp->client_profile);
278 }
279
280 static int
281 validateFocusWindow(icp)
282 IMIC *icp;
283 {
284 IMCommonAttributes *ap = &icp->common_attr;
285
286 /*
287 * This function assumes that the client window has already
288 * been validated.
289 */
290 if ((ap->set_mask & ATTR_MASK_CLIENT) && ap->focus == ap->client) {
291 icp->focus_profile = icp->client_profile;
292 return 1;
293 } else {
294 return IMValidateWindow(XtDisplay(icp->im->connection->proto_widget),
295 icp->common_attr.focus, &icp->focus_profile);
296 }
297 }
298
299
300 /*
301 * Functions submit errors
302 */
303
304 static void
305 badSizeError(icp, code)
306 IMIC *icp;
307 int code;
308 {
309 DPRINT(("bad size error for IC #%d\n", icp->id));
310 IMSendError(icp->im->connection, code, icp->im->id, icp->id,
311 "invalid size of attribute value");
312 }
313
314 static void
315 unnestedError(icp)
316 IMIC *icp;
317 {
318 DPRINT(("unnested error for IC #%d\n", icp->id));
319 IMSendError(icp->im->connection, IMBadSomething, icp->im->id, icp->id,
320 "either preedit or status specification required");
321 }
322
323
324 /*
325 * Functions getting IM attributes
326 */
327
328 static IMPSAttributes *
329 getPSPtr(icp, type)
330 IMIC *icp;
331 int type;
332 {
333 switch (type) {
334 case NEST_PREEDIT: return &icp->preedit_attr;
335 case NEST_STATUS: return &icp->status_attr;
336 default: return NULL;
337 }
338 }
339
340 static int
341 getIMValues(imp, data, len, offset)
342 IMIM *imp;
343 char *data;
344 int len;
345 int offset; /* request offset */
346 {
347 unsigned int id; /* attribute ID */
348 IMAttribute *attrp;
349 IMConnection *conn = imp->connection;
350 int byte_order = conn->byte_order;
351
352 while (len >= 2) {
353 id = getC16(data, byte_order);
354 data += 2;
355 len -= 2;
356
357 if (id > numImAttributes) {
358 /* invalid attribute ID */
359 IMCancelRequest(conn, offset);
360 IMSendError(conn, IMBadSomething, imp->id, 0,
361 "invalid IM attribute ID");
362 return -1;
363 }
364
365 attrp = &imAttributes[id];
366 if (!(attrp->valid_ops & OP_G)) {
367 IMCancelRequest(conn, offset);
368 IMSendError(conn, IMBadSomething, imp->id, 0,
369 "invalid operation (IMGetValues) for this attribute");
370 return -1;
371 }
372
373 if ((*attrp->get_proc)(imp, id, offset) < 0) return -1;
374 }
375 return 0;
376 }
377
378 /* ARGSUSED */
379 static int
380 getQueryInputStyle(imp, id, offset)
381 IMIM *imp;
382 unsigned int id;
383 int offset;
384 {
385 IMConnection *conn = imp->connection;
386 unsigned int num_styles, num_bytes;
387 InputStyle *stp;
388
389 TRACE(("imlib:getQueryInputStyle()\n"));
390
391 for (num_styles = 0, stp = styles; stp->xim_style != 0; stp++) {
392 num_styles++;
393 }
394 num_bytes = num_styles * 4 + 4;
395 IMPutC16(conn, id);
396 IMPutC16(conn, num_bytes);
397 IMPutC16(conn, num_styles);
398 IMPutC16(conn, 0);
399 for (stp = styles; stp->xim_style != 0; stp++) {
400 IMPutC32(conn, stp->xim_style);
401 }
402 return 0;
403 }
404
405
406 /*
407 * Functions setting IC attributes
408 */
409
410 static int
411 setICValues(icp, data, len, nest, op)
412 IMIC *icp;
413 char *data;
414 int len;
415 int nest;
416 int op;
417 {
418 IMConnection *conn = icp->im->connection;
419 unsigned int imid = icp->im->id;
420 unsigned int icid = icp->id;
421 unsigned int id;
422 unsigned int value_len;
423 unsigned int attr_len;
424 char *value;
425 ICAttribute *attrp;
426 int byte_order = icp->im->connection->byte_order;
427
428 TRACE(("imlib:setICValues()\n"));
429
430 while (len > 0) {
431 if (len < 4) {
432 DPRINT(("attribute data length < 4\n"));
433 IMSendError(conn, IMBadSomething, imid, icid, "Bad attribute data");
434 return -1;
435 }
436 id = getC16(data, byte_order);
437 value_len = getC16(data + 2, byte_order);
438 attr_len = PAD4(4 + value_len);
439
440 if (attr_len > len) {
441 DPRINT(("attribute data length > request length\n"));
442 IMSendError(conn, IMBadSomething, imid, icid,
443 "Bad attribute length");
444 return -1;
445 }
446 value = data + 4;
447
448 if (id > numIcAttributes) {
449 DPRINT(("invalid IC attribute ID %d\n", id));
450 IMSendError(conn, IMBadSomething, imid, icid,
451 "invalid IC attribute ID");
452 return -1;
453 }
454 attrp = &icAttributes[id];
455 if (!(attrp->valid_ops & op)) {
456 DPRINT(("invalid operation (%s) for IC attr %d\n",
457 op == OP_C ? "create" : "set", id));
458 IMSendError(conn, IMBadSomething, imid, icid,
459 "invalid operation for this attribute");
460 return -1;
461 }
462
463 /*
464 * Call attribute set procedure.
465 */
466 if ((*attrp->set_proc)(icp, value, (int)value_len, byte_order, nest, op) < 0) {
467 /*
468 * Error has occured. The set procedure has already sent
469 * appropriate error message, so just return here.
470 */
471 return -1;
472 }
473
474 data += attr_len;
475 len -= attr_len;
476 }
477 return 0;
478 }
479
480 /* ARGSUSED */
481 static int
482 setInputStyle(icp, value, len, order, nest, op)
483 IMIC *icp;
484 char *value;
485 int len;
486 int order;
487 int nest;
488 int op;
489 {
490 TRACE(("imlib:setInputStyle()\n"));
491
492 CHECK_ICATTR_SIZE(4, IMBadStyle);
493
494 /*
495 * InputStyle must be set with CreateIC.
496 */
497 if (op != OP_C) {
498 DPRINT(("trying to change input style through SetICValues\n"));
499 IMSendError(icp->im->connection, IMBadStyle,
500 icp->im->id, icp->id,
501 "InputStyle cannot be changed by SetICValues");
502 return -1;
503 }
504
505 icp->common_attr.input_style = (XIMStyle)getC32(value, order);
506 icp->common_attr.set_mask |= ATTR_MASK_INPUT_STYLE;
507 icp->common_attr.change_mask |= ATTR_MASK_INPUT_STYLE;
508 TRACE(("\tinput style: %ld\n", icp->common_attr.input_style));
509 return 0;
510 }
511
512 /* ARGSUSED */
513 static int
514 setClientWindow(icp, value, len, order, nest, op)
515 IMIC *icp;
516 char *value;
517 int len;
518 int order;
519 int nest;
520 int op;
521 {
522 TRACE(("imlib:setClientWindow()\n"));
523
524 CHECK_ICATTR_SIZE(4, IMBadClientWindow);
525
526 /*
527 * ClientWindow cannot be changed.
528 */
529 if (icp->common_attr.set_mask & ATTR_MASK_CLIENT) {
530 DPRINT(("client window already specified\n"));
531 IMSendError(icp->im->connection, IMBadClientWindow,
532 icp->im->id, icp->id, "ClientWindow already set");
533 return -1;
534 }
535
536 icp->common_attr.client = (Window)getC32(value, order);
537 TRACE(("\tclient window: %08lx\n", icp->common_attr.client));
538
539 icp->common_attr.set_mask |= ATTR_MASK_CLIENT;
540 icp->common_attr.change_mask |= ATTR_MASK_CLIENT;
541
542 return 0;
543 }
544
545 /* ARGSUSED */
546 static int
547 setFocusWindow(icp, value, len, order, nest, op)
548 IMIC *icp;
549 char *value;
550 int len;
551 int order;
552 int nest;
553 int op;
554 {
555 Window focus;
556
557 TRACE(("imlib:setFocusWindow()\n"));
558
559 CHECK_ICATTR_SIZE(4, IMBadFocusWindow);
560
561 focus = (Window)getC32(value, order);
562 TRACE(("\tfocus window: %08lx\n", focus));
563
564 if (!(icp->common_attr.set_mask & ATTR_MASK_FOCUS) ||
565 focus != icp->common_attr.focus) {
566 icp->common_attr.change_mask |= ATTR_MASK_FOCUS;
567 }
568 icp->common_attr.focus = focus;
569 icp->common_attr.set_mask |= ATTR_MASK_FOCUS;
570 return 0;
571 }
572
573 /* ARGSUSED */
574 static int
575 setPreeditAttributes(icp, value, len, order, nest, op)
576 IMIC *icp;
577 char *value;
578 int len;
579 int order;
580 int nest;
581 int op;
582 {
583 TRACE(("imlib:setPreeditAttributes()\n"));
584 return setICValues(icp, value, len, NEST_PREEDIT, op);
585 }
586
587 /* ARGSUSED */
588 static int
589 setStatusAttributes(icp, value, len, order, nest, op)
590 IMIC *icp;
591 char *value;
592 int len;
593 int order;
594 int nest;
595 int op;
596 {
597 TRACE(("imlib:setStatusAttributes()\n"));
598 return setICValues(icp, value, len, NEST_STATUS, op);
599 }
600
601 /* ARGSUSED */
602 static int
603 setArea(icp, value, len, order, nest, op)
604 IMIC *icp;
605 char *value;
606 int len;
607 int order;
608 int nest;
609 int op;
610 {
611 IMPSAttributes *ap;
612 XRectangle area;
613
614 TRACE(("imlib:setArea()\n"));
615
616 CHECK_ICATTR_SIZE(8, IMBadArea);
617
618 if ((ap = getPSPtr(icp, nest)) == NULL) {
619 unnestedError(icp);
620 return -1;
621 }
622
623 area.x = getI16(value, order);
624 area.y = getI16(value + 2, order);
625 area.width = getC16(value + 4, order);
626 area.height = getC16(value + 6, order);
627 TRACE(("\tarea: %d, %d, %d, %d\n",
628 area.x, area.y, area.width, area.height));
629
630 if (!(ap->set_mask & ATTR_MASK_AREA) ||
631 area.x != ap->area.x ||
632 area.y != ap->area.y ||
633 area.width != ap->area.width ||
634 area.height != ap->area.height) {
635 ap->change_mask |= ATTR_MASK_AREA;
636 }
637
638 ap->area.x = area.x;
639 ap->area.y = area.y;
640 ap->area.width = area.width;
641 ap->area.height = area.height;
642 ap->set_mask |= ATTR_MASK_AREA;
643
644 return 0;
645 }
646
647 /* ARGSUSED */
648 static int
649 setAreaNeeded(icp, value, len, order, nest, op)
650 IMIC *icp;
651 char *value;
652 int len;
653 int order;
654 int nest;
655 int op;
656 {
657 IMPSAttributes *ap;
658 XRectangle area;
659
660 TRACE(("imlib:setAreaNeeded()\n"));
661
662 CHECK_ICATTR_SIZE(8, IMBadArea);
663
664 if ((ap = getPSPtr(icp, nest)) == NULL) {
665 unnestedError(icp);
666 return -1;
667 }
668
669 area.width = getC16(value + 4, order);
670 area.height = getC16(value + 6, order);
671 TRACE(("\tarea needed: %d, %d\n", area.width, area.height));
672
673 if (!(ap->set_mask & ATTR_MASK_AREA_NEEDED) ||
674 area.width != ap->area_needed.width ||
675 area.height != ap->area_needed.height) {
676 ap->change_mask |= ATTR_MASK_AREA_NEEDED;
677 }
678
679 ap->area_needed.width = area.width;
680 ap->area_needed.height = area.height;
681 ap->set_mask |= ATTR_MASK_AREA_NEEDED;
682
683 return 0;
684 }
685
686 /* ARGSUSED */
687 static int
688 setForeground(icp, value, len, order, nest, op)
689 IMIC *icp;
690 char *value;
691 int len;
692 int order;
693 int nest;
694 int op;
695 {
696 IMPSAttributes *ap;
697 Pixel fore;
698
699 TRACE(("imlib:setForeground()\n"));
700
701 CHECK_ICATTR_SIZE(4, IMBadForeground);
702
703 if ((ap = getPSPtr(icp, nest)) == NULL) {
704 unnestedError(icp);
705 return -1;
706 }
707
708 fore = getC32(value, order);
709 TRACE(("\tforeground: %ld\n", fore));
710
711 if (!(ap->set_mask & ATTR_MASK_FOREGROUND) || fore != ap->foreground) {
712 ap->change_mask |= ATTR_MASK_FOREGROUND;
713 }
714 ap->foreground = fore;
715 ap->set_mask |= ATTR_MASK_FOREGROUND;
716 return 0;
717 }
718
719 /* ARGSUSED */
720 static int
721 setBackground(icp, value, len, order, nest, op)
722 IMIC *icp;
723 char *value;
724 int len;
725 int order;
726 int nest;
727 int op;
728 {
729 IMPSAttributes *ap;
730 Pixel back;
731
732 TRACE(("imlib:setBackground()\n"));
733
734 CHECK_ICATTR_SIZE(4, IMBadBackground);
735
736 if ((ap = getPSPtr(icp, nest)) == NULL) {
737 unnestedError(icp);
738 return -1;
739 }
740
741 back = getC32(value, order);
742 TRACE(("\tbackground: %ld\n", back));
743
744 if (!(ap->set_mask & ATTR_MASK_BACKGROUND) || back != ap->background) {
745 ap->change_mask |= ATTR_MASK_BACKGROUND;
746 }
747 ap->background = back;
748 ap->set_mask |= ATTR_MASK_BACKGROUND;
749 return 0;
750 }
751
752 /* ARGSUSED */
753 static int
754 setColormap(icp, value, len, order, nest, op)
755 IMIC *icp;
756 char *value;
757 int len;
758 int order;
759 int nest;
760 int op;
761 {
762 IMPSAttributes *ap;
763 Colormap cmap;
764
765 TRACE(("imlib:setColormap()\n"));
766
767 CHECK_ICATTR_SIZE(4, IMBadColormap);
768
769 if ((ap = getPSPtr(icp, nest)) == NULL) {
770 unnestedError(icp);
771 return -1;
772 }
773
774 cmap = getC32(value, order);
775 TRACE(("\tcolormap: %08lx\n", cmap));
776
777 if (!(ap->set_mask & ATTR_MASK_COLORMAP) || cmap != ap->colormap) {
778 ap->change_mask |= ATTR_MASK_COLORMAP;
779 }
780 ap->colormap = cmap;
781 ap->set_mask |= ATTR_MASK_COLORMAP;
782 return 0;
783 }
784
785 /* ARGSUSED */
786 static int
787 setBgPixmap(icp, value, len, order, nest, op)
788 IMIC *icp;
789 char *value;
790 int len;
791 int order;
792 int nest;
793 int op;
794 {
795 IMPSAttributes *ap;
796 Pixmap pixmap;
797
798 TRACE(("imlib:setBgPixmap()\n"));
799
800 CHECK_ICATTR_SIZE(4, IMBadPixmap);
801
802 if ((ap = getPSPtr(icp, nest)) == NULL) {
803 unnestedError(icp);
804 return -1;
805 }
806
807 pixmap = getC32(value, order);
808 TRACE(("\tbackground pixmap: %08lx\n", pixmap));
809
810 if (!(ap->set_mask & ATTR_MASK_BG_PIXMAP) || pixmap != ap->bg_pixmap) {
811 ap->change_mask |= ATTR_MASK_BG_PIXMAP;
812 }
813
814 ap->bg_pixmap = pixmap;
815 ap->set_mask |= ATTR_MASK_BG_PIXMAP;
816
817 return 0;
818 }
819
820 /* ARGSUSED */
821 static int
822 setLineSpace(icp, value, len, order, nest, op)
823 IMIC *icp;
824 char *value;
825 int len;
826 int order;
827 int nest;
828 int op;
829 {
830 IMPSAttributes *ap;
831 int line_space;
832
833 TRACE(("imlib:setLineSpace()\n"));
834
835 CHECK_ICATTR_SIZE(2, IMBadSomething);
836
837 if ((ap = getPSPtr(icp, nest)) == NULL) {
838 unnestedError(icp);
839 return -1;
840 }
841
842 line_space = getI16(value, order); /* ??? linespacing is 'int' */
843 TRACE(("\tline space: %d\n", line_space));
844
845 if (!(ap->set_mask & ATTR_MASK_LINESPACE) ||
846 line_space != ap->line_space) {
847 ap->change_mask |= ATTR_MASK_LINESPACE;
848 }
849 ap->line_space = line_space;
850 ap->set_mask |= ATTR_MASK_LINESPACE;
851 return 0;
852 }
853
854 /* ARGSUSED */
855 static int
856 setCursor(icp, value, len, order, nest, op)
857 IMIC *icp;
858 char *value;
859 int len;
860 int order;
861 int nest;
862 int op;
863 {
864 IMPSAttributes *ap;
865 Cursor cursor;
866
867 TRACE(("imlib:setCursor()\n"));
868
869 CHECK_ICATTR_SIZE(4, IMBadCursor);
870
871 if ((ap = getPSPtr(icp, nest)) == NULL) {
872 unnestedError(icp);
873 return -1;
874 }
875
876 cursor = getC32(value, order);
877 TRACE(("\tcursor: %08lx\n", cursor));
878
879 if (!(ap->set_mask & ATTR_MASK_CURSOR) || cursor != ap->cursor) {
880 ap->change_mask |= ATTR_MASK_CURSOR;
881 }
882 ap->cursor = cursor;
883 ap->set_mask |= ATTR_MASK_CURSOR;
884 return 0;
885 }
886
887 /* ARGSUSED */
888 static int
889 setSpotLocation(icp, value, len, order, nest, op)
890 IMIC *icp;
891 char *value;
892 int len;
893 int order;
894 int nest;
895 int op;
896 {
897 IMPSAttributes *ap;
898 XPoint spot;
899
900 TRACE(("imlib:setSpotLocation()\n"));
901
902 CHECK_ICATTR_SIZE(4, IMBadSpotLocation);
903
904 if (nest == NEST_STATUS) {
905 DPRINT(("spot location specified in a status attribute list\n"));
906 IMSendError(icp->im->connection, IMBadSpotLocation,
907 icp->im->id, icp->id,
908 "spot location isn't a status attribute");
909 return -1;
910 }
911
912 ap = &icp->preedit_attr;
913
914 spot.x = getI16(value, order);
915 spot.y = getI16(value + 2, order);
916 TRACE(("\tspot location: %d, %d\n", spot.x, spot.y));
917
918 if (!(ap->set_mask & ATTR_MASK_SPOT_LOCATION) ||
919 spot.x != ap->spot_location.x || spot.y != ap->spot_location.y) {
920 ap->change_mask |= ATTR_MASK_SPOT_LOCATION;
921 }
922 ap->spot_location.x = spot.x;
923 ap->spot_location.y = spot.y;
924 ap->set_mask |= ATTR_MASK_SPOT_LOCATION;
925 return 0;
926 }
927
928 /* ARGSUSED */
929 static int
930 setStdColormap(icp, value, len, order, nest, op)
931 IMIC *icp;
932 char *value;
933 int len;
934 int order;
935 int nest;
936 int op;
937 {
938 IMPSAttributes *ap;
939 Atom colormap_name;
940 XStandardColormap *stdcolormaps;
941 Widget w = icp->im->connection->proto_widget;
942 Display *dpy = XtDisplay(w);
943 int ncolormaps;
944 Window root;
945 XAEHandle h;
946 int status;
947
948 TRACE(("imlib:setStdColormap()\n"));
949
950 CHECK_ICATTR_SIZE(4, IMBadAtom);
951
952 if ((ap = getPSPtr(icp, nest)) == NULL) {
953 unnestedError(icp);
954 return -1;
955 }
956
957 colormap_name = getC32(value, order);
958 if (icp->common_attr.set_mask & ATTR_MASK_CLIENT) {
959 root = icp->client_profile.root;
960 } else if (icp->common_attr.set_mask & ATTR_MASK_FOCUS) {
961 root = icp->focus_profile.root;
962 } else {
963 /*
964 * Client has not specified client window yet.
965 * Reading standard colormap property should been deffered
966 * until the window is set, but for now...
967 */
968 DDPRINT(2, ("std colormap specified, leaving client window unspecified\n"));
969 root = RootWindowOfScreen(XtScreen(w));
970 }
971
972 h = XAESetIgnoreErrors(dpy);
973 status = XGetRGBColormaps(dpy, root,
974 &stdcolormaps, &ncolormaps, colormap_name);
975 XAEUnset(h);
976 if (!status || ncolormaps < 0) {
977 DPRINT(("can't get standard colormap (%ld)\n", colormap_name));
978 IMSendError(icp->im->connection, IMBadName, icp->im->id, icp->id,
979 "invalid standard colormap name");
980 return -1;
981 }
982
983 if (!(ap->set_mask & ATTR_MASK_STD_COLORMAP) ||
984 colormap_name != ap->std_colormap) {
985 ap->change_mask |= ATTR_MASK_STD_COLORMAP;
986 }
987 ap->std_colormap = colormap_name;
988 ap->colormap = stdcolormaps[0].colormap;
989 TRACE(("\tstandard colormap: %ld (colormap=%08lx)\n",
990 colormap_name, ap->colormap));
991
992 ap->set_mask |= ATTR_MASK_STD_COLORMAP | ATTR_MASK_COLORMAP;
993 XFree((char *)stdcolormaps);
994 return 0;
995 }
996
997 /* ARGSUSED */
998 static int
999 setFontSet(icp, value, len, order, nest, op)
1000 IMIC *icp;
1001 char *value;
1002 int len;
1003 int order;
1004 int nest;
1005 int op;
1006 {
1007 IMPSAttributes *ap;
1008 unsigned int name_list_len;
1009 char *name_list;
1010
1011 TRACE(("imlib:setFontSet()\n"));
1012
1013 if (len < 2) {
1014 badSizeError(icp, IMBadName);
1015 return -1;
1016 }
1017 name_list_len = getC16(value, order);
1018 if (2 + name_list_len > len) {
1019 badSizeError(icp, IMBadName);
1020 return -1;
1021 }
1022
1023 if ((ap = getPSPtr(icp, nest)) == NULL) {
1024 unnestedError(icp);
1025 return -1;
1026 }
1027
1028 name_list = XtMalloc(name_list_len + 1);
1029 bcopy(value + 2, name_list, name_list_len);
1030 name_list[name_list_len] = '\0';
1031 TRACE(("\tfontset: %s\n", name_list));
1032
1033 if (ap->set_mask & ATTR_MASK_FONT_SET) {
1034 if (!strcmp(name_list, ap->font_set)) {
1035 XtFree(name_list);
1036 } else {
1037 ap->change_mask |= ATTR_MASK_FONT_SET;
1038 if (ap->font_set != IMDefaultFontSet(icp->im)) {
1039 XtFree(ap->font_set);
1040 }
1041 ap->font_set = name_list;
1042 }
1043 } else {
1044 ap->font_set = name_list;
1045 ap->set_mask |= ATTR_MASK_FONT_SET;
1046 ap->change_mask |= ATTR_MASK_FONT_SET;
1047 }
1048 return 0;
1049 }
1050
1051 /* ARGSUSED */
1052 static int
1053 setPreeditState(icp, value, len, order, nest, op)
1054 IMIC *icp;
1055 char *value;
1056 int len;
1057 int order;
1058 int nest;
1059 int op;
1060 {
1061 IMCommonAttributes *ap = &icp->common_attr;
1062 unsigned long preedit_state;
1063
1064 TRACE(("imlib:setPreeditState()\n"));
1065
1066 CHECK_ICATTR_SIZE(4, IMBadSomething);
1067
1068 if (nest == NEST_STATUS) {
1069 DPRINT(("preedit state specified in a status attribute list\n"));
1070 IMSendError(icp->im->connection, IMBadSomething,
1071 icp->im->id, icp->id,
1072 "preedit state isn't a status attribute");
1073 return -1;
1074 }
1075
1076 preedit_state = getC32(value, order);
1077
1078 ap->set_mask |= ATTR_MASK_PREEDIT_STATE;
1079 ap->change_mask |= ATTR_MASK_PREEDIT_STATE;
1080 ap->preedit_state = preedit_state;
1081 return 0;
1082 }
1083
1084 /* ARGSUSED */
1085 static int
1086 setResetState(icp, value, len, order, nest, op)
1087 IMIC *icp;
1088 char *value;
1089 int len;
1090 int order;
1091 int nest;
1092 int op;
1093 {
1094 IMCommonAttributes *ap = &icp->common_attr;
1095 unsigned long reset_state;
1096
1097 TRACE(("imlib:setResetState()\n"));
1098
1099 CHECK_ICATTR_SIZE(4, IMBadSomething);
1100
1101 reset_state = getC32(value, order);
1102
1103 ap->set_mask |= ATTR_MASK_RESET_STATE;
1104 ap->change_mask |= ATTR_MASK_RESET_STATE;
1105 ap->reset_state = reset_state;
1106 return 0;
1107 }
1108
1109
1110 /*
1111 * Functions getting IC attributes
1112 */
1113
1114 static int
1115 getICValues(icp, data, len, nest, offset, sepp)
1116 IMIC *icp;
1117 char *data;
1118 int len;
1119 int nest; /* NEST_NONE, NEST_PREEDIT or NEST_STATUS */
1120 int offset; /* request offset */
1121 int *sepp; /* Out: true if ended with a nested list separator */
1122 {
1123 unsigned int id; /* attribute ID */
1124 ICAttribute *attrp;
1125 IMConnection *conn = icp->im->connection;
1126 int byte_order = conn->byte_order;
1127 char *org_data = data;
1128 int r;
1129
1130 TRACE(("imlib:getICValues()\n"));
1131
1132 while (len >= 2) {
1133 id = getC16(data, byte_order);
1134 data += 2;
1135 len -= 2;
1136
1137 if (id > numIcAttributes) {
1138 /* invalid attribute ID */
1139 DPRINT(("invalid IC attribute ID (%d) specified\n", id));
1140 IMCancelRequest(conn, offset);
1141 IMSendError(conn, IMBadSomething, icp->im->id, icp->id,
1142 "invalid IC attribute ID");
1143 return -1;
1144 }
1145
1146 attrp = &icAttributes[id];
1147 if (attrp->type == TYPE_SEPARATOR) {
1148 /* nested list separator */
1149 *sepp = 1;
1150 return data - org_data;
1151 }
1152
1153 if (!(attrp->valid_ops & OP_G)) {
1154 DPRINT(("invalid operation (get) for IC attr %d\n", id));
1155 IMCancelRequest(conn, offset);
1156 IMSendError(conn, IMBadSomething, icp->im->id, icp->id,
1157 "invalid operation (ICGetValues) for this attribute");
1158 return -1;
1159 }
1160
1161 r = (*attrp->get_proc)(icp, id, nest, offset, data, len);
1162 /*
1163 * The return value of get_proc is usually 0, indicating success.
1164 * If it is less than 0, there are some errors.
1165 * If it is greater than 0,
1166 */
1167 if (r < 0) return -1;
1168
1169 data += r; /* r is extra offset */
1170 len -= r;
1171 }
1172 *sepp = 0;
1173 return data - org_data;
1174 }
1175
1176 /* ARGSUSED */
1177 static int
1178 getPSAttributes(icp, id, nest, offset, data, len)
1179 IMIC *icp;
1180 unsigned int id;
1181 int nest;
1182 int offset;
1183 char *data;
1184 int len;
1185 {
1186 IMConnection *conn = icp->im->connection;
1187 unsigned int length;
1188 int length_offset;
1189 int attr_offset;
1190 int nested_separator;
1191 int r;
1192
1193 IMPutC16(conn, id);
1194
1195 length_offset = IMWritePos(conn);
1196 IMPutC16(conn, 0); /* dummy -- overwritten afterwards */
1197
1198 attr_offset = IMWritePos(conn);
1199
1200 r = getICValues(icp, data, len, nest, offset, &nested_separator);
1201 if (r < 0) return -1;
1202 if (!nested_separator) {
1203 /* there's no nested list separator */
1204 DPRINT(("nested list doesn't end with separator\n"));
1205 /*
1206 * X11R6 Xlib sends nested attribute list which has no
1207 * separator at its end. In order to accommodate to it,
1208 * don't send error for that.
1209 */
1210 #ifdef notdef
1211 IMCancelRequest(conn, offset);
1212 IMSendError(conn, IMBadSomething, icp->im->id, icp->id,
1213 "corrupted nested list");
1214 return -1;
1215 #endif
1216 }
1217
1218 /*
1219 * Nested list is written on the output buffer.
1220 * Calculate the length of the list.
1221 */
1222 length = IMWritePos(conn) - attr_offset;
1223
1224 /* rewrite attribute length field */
1225 IMRewriteC16(conn, length_offset, length);
1226 IMPutPad(conn);
1227
1228 return r;
1229 }
1230
1231 /* ARGSUSED */
1232 static int
1233 getPreeditAttributes(icp, id, nest, offset, data, len)
1234 IMIC *icp;
1235 unsigned int id;
1236 int nest; /* unused */
1237 int offset;
1238 char *data;
1239 int len;
1240 {
1241 TRACE(("imlib:getPreeditAttributes()\n"));
1242 return getPSAttributes(icp, id, NEST_PREEDIT, offset, data, len);
1243 }
1244
1245 /* ARGSUSED */
1246 static int
1247 getStatusAttributes(icp, id, nest, offset, data, len)
1248 IMIC *icp;
1249 unsigned int id;
1250 int nest; /* unused */
1251 int offset;
1252 char *data;
1253 int len;
1254 {
1255 TRACE(("imlib:getStatusAttributes()\n"));
1256 return getPSAttributes(icp, id, NEST_STATUS, offset, data, len);
1257 }
1258
1259 /* ARGSUSED */
1260 static int
1261 getInputStyle(icp, id, nest, offset, data, len)
1262 IMIC *icp;
1263 unsigned int id;
1264 int nest;
1265 int offset;
1266 char *data;
1267 int len;
1268 {
1269 IMConnection *conn = icp->im->connection;
1270
1271 TRACE(("imlib:getInputStyle()\n"));
1272
1273 /*
1274 * Input style must have been specified, (and validated)
1275 * at IC creation. No need for checking.
1276 */
1277 IMPutC16(conn, id); /* attribute ID */
1278 IMPutC16(conn, 4); /* value length */
1279 IMPutC32(conn, icp->common_attr.input_style);
1280 return 0;
1281 }
1282
1283 /* ARGSUSED */
1284 static int
1285 getClientWindow(icp, id, nest, offset, data, len)
1286 IMIC *icp;
1287 unsigned int id;
1288 int nest;
1289 int offset;
1290 char *data;
1291 int len;
1292 {
1293 IMConnection *conn = icp->im->connection;
1294
1295 TRACE(("imlib:getClientWindow()\n"));
1296
1297 if (icp->common_attr.set_mask & ATTR_MASK_CLIENT) {
1298 IMPutC16(conn, id); /* attribute ID */
1299 IMPutC16(conn, 4); /* value length */
1300 IMPutC32(conn, icp->common_attr.client);
1301 return 0;
1302 } else {
1303 /* no default is available */
1304 DPRINT(("getClientWindow without setting client window previously\n"));
1305 IMCancelRequest(conn, offset);
1306 IMSendError(conn, IMBadClientWindow, icp->im->id, icp->id,
1307 "client window not specified yet");
1308 return -1;
1309 }
1310 }
1311
1312 /* ARGSUSED */
1313 static int
1314 getFocusWindow(icp, id, nest, offset, data, len)
1315 IMIC *icp;
1316 unsigned int id;
1317 int nest;
1318 int offset;
1319 char *data;
1320 int len;
1321 {
1322 IMConnection *conn = icp->im->connection;
1323
1324 TRACE(("imlib:getFocusWindow()\n"));
1325
1326 if (!(icp->common_attr.set_mask & ATTR_MASK_FOCUS)) {
1327 /* fill default value */
1328 fillCommonDefault(icp, (unsigned long)ATTR_MASK_FOCUS);
1329 }
1330
1331 if (icp->common_attr.set_mask & ATTR_MASK_FOCUS) {
1332 IMPutC16(conn, id); /* attribute ID */
1333 IMPutC16(conn, 4); /* value length */
1334 IMPutC32(conn, icp->common_attr.focus);
1335 return 0;
1336 } else {
1337 /*
1338 * Couldn't get the default value. That is, neither
1339 * focus window nor client window is specified yet.
1340 */
1341 DPRINT(("getFocusWindow without setting focus/client window previously\n"));
1342 IMCancelRequest(conn, offset);
1343 IMSendError(conn, IMBadFocusWindow, icp->im->id, icp->id,
1344 "neither of client/focus window not specified yet");
1345 return -1;
1346 }
1347 }
1348
1349 /* ARGSUSED */
1350 static int
1351 getFilterEvents(icp, id, nest, offset, data, len)
1352 IMIC *icp;
1353 unsigned int id;
1354 int nest;
1355 int offset;
1356 char *data;
1357 int len;
1358 {
1359 IMConnection *conn = icp->im->connection;
1360
1361 TRACE(("imlib:getFilterEvents()\n"));
1362
1363 /* We need only Key events */
1364 IMPutC16(conn, id); /* attribute ID */
1365 IMPutC16(conn, 4); /* value length */
1366 IMPutC32(conn, KeyPressMask | KeyReleaseMask);
1367 return 0;
1368 }
1369
1370 /* ARGSUSED */
1371 static int
1372 getArea(icp, id, nest, offset, data, len)
1373 IMIC *icp;
1374 unsigned int id;
1375 int nest;
1376 int offset;
1377 char *data;
1378 int len;
1379 {
1380 IMConnection *conn = icp->im->connection;
1381 IMPSAttributes *ap;
1382
1383 TRACE(("imlib:getArea()\n"));
1384
1385 if ((ap = getPSPtr(icp, nest)) == NULL) {
1386 IMCancelRequest(conn, offset);
1387 unnestedError(icp);
1388 return -1;
1389 }
1390
1391 if (!(ap->set_mask & ATTR_MASK_AREA)) {
1392 fillPSDefault(icp, nest, (unsigned long)ATTR_MASK_AREA);
1393 }
1394
1395 IMPutC16(conn, id); /* attribute ID */
1396 IMPutC16(conn, 8); /* value length */
1397 IMPutI16(conn, ap->area.x);
1398 IMPutI16(conn, ap->area.y);
1399 IMPutC16(conn, ap->area.width);
1400 IMPutC16(conn, ap->area.height);
1401 return 0;
1402 }
1403
1404 /* ARGSUSED */
1405 static int
1406 getAreaNeeded(icp, id, nest, offset, data, len)
1407 IMIC *icp;
1408 unsigned int id;
1409 int nest;
1410 int offset;
1411 char *data;
1412 int len;
1413 {
1414 IMConnection *conn = icp->im->connection;
1415 IMPSAttributes *ap;
1416
1417 TRACE(("imlib:getAreaNeeded()\n"));
1418
1419 if ((ap = getPSPtr(icp, nest)) == NULL) {
1420 IMCancelRequest(conn, offset);
1421 unnestedError(icp);
1422 return -1;
1423 }
1424
1425 /*
1426 * Always call fillPSDefault to get appropriate AreaNeeded value.
1427 */
1428 fillPSDefault(icp, nest, (unsigned long)ATTR_MASK_AREA_NEEDED);
1429
1430 TRACE(("\tarea needed: %d, %d, %d, %d\n",
1431 ap->area_needed.x, ap->area_needed.y,
1432 ap->area_needed.width, ap->area_needed.height));
1433
1434 IMPutC16(conn, id); /* attribute ID */
1435 IMPutC16(conn, 8); /* value length */
1436 IMPutI16(conn, ap->area_needed.x);
1437 IMPutI16(conn, ap->area_needed.y);
1438 IMPutC16(conn, ap->area_needed.width);
1439 IMPutC16(conn, ap->area_needed.height);
1440 return 0;
1441 }
1442
1443 /* ARGSUSED */
1444 static int
1445 getSpotLocation(icp, id, nest, offset, data, len)
1446 IMIC *icp;
1447 unsigned int id;
1448 int nest;
1449 int offset;
1450 char *data;
1451 int len;
1452 {
1453 IMConnection *conn = icp->im->connection;
1454 IMPSAttributes *ap = &icp->preedit_attr;
1455
1456 TRACE(("imlib:getSpotLocation()\n"));
1457
1458 if (nest == NEST_STATUS) {
1459 IMCancelRequest(conn, offset);
1460 IMSendError(conn, IMBadSomething, icp->im->id, icp->id,
1461 "spot location isn't a status attribute");
1462 return -1;
1463 }
1464
1465 if (!(ap->set_mask & ATTR_MASK_SPOT_LOCATION)) {
1466 fillPSDefault(icp, NEST_PREEDIT,
1467 (unsigned long)ATTR_MASK_SPOT_LOCATION);
1468 }
1469
1470 IMPutC16(conn, id); /* attribute ID */
1471 IMPutC16(conn, 4); /* value length */
1472 IMPutI16(conn, ap->spot_location.x);
1473 IMPutI16(conn, ap->spot_location.y);
1474 return 0;
1475 }
1476
1477 /* ARGSUSED */
1478 static int
1479 getColormap(icp, id, nest, offset, data, len)
1480 IMIC *icp;
1481 unsigned int id;
1482 int nest;
1483 int offset;
1484 char *data;
1485 int len;
1486 {
1487 IMConnection *conn = icp->im->connection;
1488 IMPSAttributes *ap;
1489
1490 TRACE(("imlib:getColormap()\n"));
1491
1492 if ((ap = getPSPtr(icp, nest)) == NULL) {
1493 IMCancelRequest(conn, offset);
1494 unnestedError(icp);
1495 return -1;
1496 }
1497
1498 if (!(ap->set_mask & ATTR_MASK_COLORMAP)) {
1499 fillPSDefault(icp, nest, (unsigned long)ATTR_MASK_COLORMAP);
1500 }
1501
1502 IMPutC16(conn, id); /* attribute ID */
1503 IMPutC16(conn, 4); /* value length */
1504 IMPutC32(conn, ap->colormap);
1505 return 0;
1506 }
1507
1508 /* ARGSUSED */
1509 static int
1510 getStdColormap(icp, id, nest, offset, data, len)
1511 IMIC *icp;
1512 unsigned int id;
1513 int nest;
1514 int offset;
1515 char *data;
1516 int len;
1517 {
1518 IMConnection *conn = icp->im->connection;
1519 IMPSAttributes *ap;
1520 Atom colormap_name;
1521
1522 TRACE(("imlib:getStdColormap()\n"));
1523
1524 if ((ap = getPSPtr(icp, nest)) == NULL) {
1525 IMCancelRequest(conn, offset);
1526 unnestedError(icp);
1527 return -1;
1528 }
1529
1530 if (ap->set_mask & ATTR_MASK_STD_COLORMAP) {
1531 colormap_name = ap->std_colormap;
1532 } else {
1533 /* what to do? */
1534 colormap_name = None;
1535 DPRINT(("client asks standard colormap, but not specified\n"));
1536 }
1537
1538 IMPutC16(conn, id); /* attribute ID */
1539 IMPutC16(conn, 4); /* value length */
1540 IMPutC32(conn, colormap_name);
1541 return 0;
1542 }
1543
1544 /* ARGSUSED */
1545 static int
1546 getForeground(icp, id, nest, offset, data, len)
1547 IMIC *icp;
1548 unsigned int id;
1549 int nest;
1550 int offset;
1551 char *data;
1552 int len;
1553 {
1554 IMConnection *conn = icp->im->connection;
1555 IMPSAttributes *ap;
1556
1557 TRACE(("imlib:getForeground()\n"));
1558
1559 if ((ap = getPSPtr(icp, nest)) == NULL) {
1560 IMCancelRequest(conn, offset);
1561 unnestedError(icp);
1562 return -1;
1563 }
1564
1565 if (!(ap->set_mask & ATTR_MASK_FOREGROUND)) {
1566 fillPSDefault(icp, nest, (unsigned long)ATTR_MASK_FOREGROUND);
1567 }
1568
1569 IMPutC16(conn, id); /* attribute ID */
1570 IMPutC16(conn, 4); /* value length */
1571 IMPutC32(conn, ap->foreground);
1572 return 0;
1573 }
1574
1575 /* ARGSUSED */
1576 static int
1577 getBackground(icp, id, nest, offset, data, len)
1578 IMIC *icp;
1579 unsigned int id;
1580 int nest;
1581 int offset;
1582 char *data;
1583 int len;
1584 {
1585 IMConnection *conn = icp->im->connection;
1586 IMPSAttributes *ap;
1587
1588 TRACE(("imlib:getBackground()\n"));
1589
1590 if ((ap = getPSPtr(icp, nest)) == NULL) {
1591 IMCancelRequest(conn, offset);
1592 unnestedError(icp);
1593 return -1;
1594 }
1595
1596 if (!(ap->set_mask & ATTR_MASK_BACKGROUND)) {
1597 fillPSDefault(icp, nest, (unsigned long)ATTR_MASK_BACKGROUND);
1598 }
1599
1600 IMPutC16(conn, id); /* attribute ID */
1601 IMPutC16(conn, 4); /* value length */
1602 IMPutC32(conn, ap->background);
1603 return 0;
1604 }
1605
1606 /* ARGSUSED */
1607 static int
1608 getBgPixmap(icp, id, nest, offset, data, len)
1609 IMIC *icp;
1610 unsigned int id;
1611 int nest;
1612 int offset;
1613 char *data;
1614 int len;
1615 {
1616 IMConnection *conn = icp->im->connection;
1617 IMPSAttributes *ap;
1618
1619 TRACE(("imlib:getBgPixmap()\n"));
1620
1621 if ((ap = getPSPtr(icp, nest)) == NULL) {
1622 IMCancelRequest(conn, offset);
1623 unnestedError(icp);
1624 return -1;
1625 }
1626
1627 if (!(ap->set_mask & ATTR_MASK_BG_PIXMAP)) {
1628 fillPSDefault(icp, nest, (unsigned long)ATTR_MASK_BG_PIXMAP);
1629 }
1630
1631 IMPutC16(conn, id); /* attribute ID */
1632 IMPutC16(conn, 4); /* value length */
1633 IMPutC32(conn, ap->bg_pixmap);
1634 return 0;
1635 }
1636
1637 /* ARGSUSED */
1638 static int
1639 getFontSet(icp, id, nest, offset, data, len)
1640 IMIC *icp;
1641 unsigned int id;
1642 int nest;
1643 int offset;
1644 char *data;
1645 int len;
1646 {
1647 IMConnection *conn = icp->im->connection;
1648 IMPSAttributes *ap;
1649 int name_len;
1650
1651 TRACE(("imlib:getFontSet()\n"));
1652
1653 if ((ap = getPSPtr(icp, nest)) == NULL) {
1654 IMCancelRequest(conn, offset);
1655 unnestedError(icp);
1656 return -1;
1657 }
1658
1659 if (!(ap->set_mask & ATTR_MASK_FONT_SET)) {
1660 fillPSDefault(icp, nest, (unsigned long)ATTR_MASK_FONT_SET);
1661 }
1662
1663 name_len = strlen(ap->font_set);
1664
1665 IMPutC16(conn, id); /* attribute ID */
1666
1667 IMPutC16(conn, (unsigned int)name_len); /* value length */
1668 IMPutString(conn, ap->font_set, name_len);
1669 IMPutPad(conn);
1670 return 0;
1671 }
1672
1673 /* ARGSUSED */
1674 static int
1675 getLineSpace(icp, id, nest, offset, data, len)
1676 IMIC *icp;
1677 unsigned int id;
1678 int nest;
1679 int offset;
1680 char *data;
1681 int len;
1682 {
1683 IMConnection *conn = icp->im->connection;
1684 IMPSAttributes *ap;
1685
1686 TRACE(("imlib:getLineSpace()\n"));
1687
1688 if ((ap = getPSPtr(icp, nest)) == NULL) {
1689 IMCancelRequest(conn, offset);
1690 unnestedError(icp);
1691 return -1;
1692 }
1693
1694 if (!(ap->set_mask & ATTR_MASK_LINESPACE)) {
1695 fillPSDefault(icp, nest, (unsigned long)ATTR_MASK_LINESPACE);
1696 }
1697
1698 IMPutC16(conn, id); /* attribute ID */
1699 IMPutC16(conn, 4); /* value length */
1700 IMPutC32(conn, (unsigned long)ap->line_space);
1701 return 0;
1702 }
1703
1704 /* ARGSUSED */
1705 static int
1706 getCursor(icp, id, nest, offset, data, len)
1707 IMIC *icp;
1708 unsigned int id;
1709 int nest;
1710 int offset;
1711 char *data;
1712 int len;
1713 {
1714 IMConnection *conn = icp->im->connection;
1715 IMPSAttributes *ap;
1716
1717 TRACE(("imlib:getCursor()\n"));
1718
1719 if ((ap = getPSPtr(icp, nest)) == NULL) {
1720 IMCancelRequest(conn, offset);
1721 unnestedError(icp);
1722 return -1;
1723 }
1724
1725 if (!(ap->set_mask & ATTR_MASK_CURSOR)) {
1726 fillPSDefault(icp, nest, (unsigned long)ATTR_MASK_CURSOR);
1727 }
1728
1729 IMPutC16(conn, id); /* attribute ID */
1730 IMPutC16(conn, 4); /* value length */
1731 IMPutC32(conn, ap->cursor);
1732 return 0;
1733 }
1734
1735 /* ARGSUSED */
1736 static int
1737 getPreeditState(icp, id, nest, offset, data, len)
1738 IMIC *icp;
1739 unsigned int id;
1740 int nest;
1741 int offset;
1742 char *data;
1743 int len;
1744 {
1745 IMConnection *conn = icp->im->connection;
1746
1747 TRACE(("imlib:getPreeditState()\n"));
1748
1749 if (nest == NEST_STATUS) {
1750 IMCancelRequest(conn, offset);
1751 IMSendError(conn, IMBadSomething, icp->im->id, icp->id,
1752 "preedit state isn't a status attribute");
1753 return -1;
1754 }
1755
1756 IMPutC16(conn, id); /* attribute ID */
1757 IMPutC16(conn, 4); /* value length */
1758 IMPutC32(conn,
1759 (icp->state & IC_CONVERTING) ?
1760 XIMPreeditEnable : XIMPreeditDisable);
1761 return 0;
1762 }
1763
1764 /* ARGSUSED */
1765 static int
1766 getResetState(icp, id, nest, offset, data, len)
1767 IMIC *icp;
1768 unsigned int id;
1769 int nest;
1770 int offset;
1771 char *data;
1772 int len;
1773 {
1774 IMConnection *conn = icp->im->connection;
1775
1776 TRACE(("imlib:getResetState()\n"));
1777
1778 IMPutC16(conn, id); /* attribute ID */
1779 IMPutC16(conn, 4); /* value length */
1780 IMPutC32(conn, icp->common_attr.reset_state);
1781 return 0;
1782 }
1783
1784 static void
1785 changeFonts(icp, preedit)
1786 IMIC *icp;
1787 int preedit;
1788 {
1789 FontBank bank = IMFontBank(icp->im);
1790 String font_set;
1791 XFontStruct ***fontsp;
1792 int *num_fontsp;
1793
1794 TRACE(("imlib:changeFonts()\n"));
1795
1796 if (preedit) {
1797 font_set = icp->preedit_attr.font_set;
1798 fontsp = &icp->fonts;
1799 num_fontsp = &icp->num_fonts;
1800 } else {
1801 font_set = icp->status_attr.font_set;
1802 fontsp = &icp->status_fonts;
1803 num_fontsp = &icp->num_status_fonts;
1804 }
1805
1806 /*
1807 * Unload previous fonts.
1808 */
1809 if (*num_fontsp > 0) {
1810 FontBankFreeFonts(bank, *fontsp, *num_fontsp);
1811 }
1812
1813 /*
1814 * Load new fonts and store them in the IC structure.
1815 */
1816 *fontsp = FontBankGet(bank, font_set, num_fontsp);
1817 }
1818
1819
1820 /*
1821 * Functions computing default attribute values
1822 */
1823
1824 static void
1825 fillCommonDefault(icp, mask)
1826 IMIC *icp;
1827 unsigned long mask;
1828 {
1829 IMCommonAttributes *ap = &icp->common_attr;
1830
1831 TRACE(("imlib:fillCommonDefault()\n"));
1832
1833 /*
1834 * Don't bother with the attributes which have been set.
1835 */
1836 mask &= ~ap->set_mask;
1837
1838 /*
1839 * The attributes that have default value are FocusWindow,
1840 * PreeditState and ResetState.
1841 */
1842 if (mask & ATTR_MASK_FOCUS) {
1843 /* if ClientWindow is not set... no way */
1844 if (mask & ATTR_MASK_CLIENT) {
1845 ap->focus = ap->client;
1846 ap->set_mask |= ATTR_MASK_FOCUS;
1847 icp->focus_profile = icp->client_profile;
1848 TRACE(("\tdefault focus window: %08lx\n", ap->focus));
1849 }
1850 }
1851 if (mask & ATTR_MASK_PREEDIT_STATE) {
1852 /* unless the client specified, we should start with disabled state. */
1853 ap->set_mask |= ATTR_MASK_PREEDIT_STATE;
1854 ap->reset_state = XIMPreeditDisable;
1855 }
1856 if (mask & ATTR_MASK_RESET_STATE) {
1857 /* the default reset state must be the initial state. */
1858 ap->set_mask |= ATTR_MASK_RESET_STATE;
1859 ap->reset_state = XIMInitialState;
1860 }
1861 }
1862
1863 static int
1864 getNaturalLineSpace(icp, preedit)
1865 IMIC *icp;
1866 int preedit;
1867 {
1868 XFontStruct **fonts;
1869 int num_fonts;
1870 int max_ascent = 0, max_descent = 0;
1871 int i;
1872
1873 changeFonts(icp, preedit);
1874 if (preedit) {
1875 fonts = icp->fonts;
1876 num_fonts = icp->num_fonts;
1877 } else {
1878 fonts = icp->status_fonts;
1879 num_fonts = icp->num_status_fonts;
1880 }
1881
1882 for (i = 0; i < num_fonts; i++) {
1883 XFontStruct *font = fonts[i];
1884 if (max_ascent < font->ascent) max_ascent = font->ascent;
1885 if (max_descent < font->descent) max_descent = font->descent;
1886 }
1887
1888 if (max_ascent + max_descent < MIN_LINE_SPACING) {
1889 return MIN_LINE_SPACING;
1890 } else {
1891 return max_ascent + max_descent;
1892 }
1893 }
1894
1895 static void
1896 fillPSDefault(icp, type, mask)
1897 IMIC *icp;
1898 int type; /* NEST_PREEDIT or NEST_STATUS */
1899 unsigned long mask;
1900 {
1901 IMPSAttributes *ap;
1902 IMConnection *conn = icp->im->connection;
1903 Widget pw = conn->proto_widget;
1904 int preedit;
1905 #ifdef DEBUG
1906 char *typename = (type == NEST_PREEDIT) ? "preedit" : "status";
1907 #endif
1908
1909 TRACE(("imlib:fillPSDefault(%s)\n", typename));
1910
1911 preedit = (type == NEST_PREEDIT);
1912 ap = preedit ? &icp->preedit_attr : &icp->status_attr;
1913
1914 /*
1915 * Don't bother with the attributes which have been set.
1916 * But area_needed needs to be computed each time (to get
1917 * correct X and Y coordinates).
1918 */
1919 mask &= ~ap->set_mask | ATTR_MASK_AREA_NEEDED;
1920
1921 if (mask & ATTR_MASK_AREA) {
1922 computeAreaForQuery(icp);
1923 ap->set_mask |= ATTR_MASK_AREA;
1924 DDPRINT(5, ("\tdefault %s area: %d,%d,%d,%d\n", typename,
1925 ap->area.x, ap->area.y, ap->area.width, ap->area.height));
1926 }
1927 if (mask & ATTR_MASK_FOREGROUND) {
1928 ap->foreground = IMDefaultForeground(pw);
1929 ap->set_mask |= ATTR_MASK_FOREGROUND;
1930 DDPRINT(5, ("\tdefault %s foreground: %ld\n",
1931 typename, ap->foreground));
1932 }
1933 if (mask & ATTR_MASK_BACKGROUND) {
1934 ap->background = IMDefaultBackground(pw);
1935 ap->set_mask |= ATTR_MASK_BACKGROUND;
1936 DDPRINT(5, ("\tdefault %s background: %ld\n",
1937 typename, ap->background));
1938 }
1939 if (mask & ATTR_MASK_COLORMAP) {
1940 ap->colormap = pw->core.colormap;
1941 ap->set_mask |= ATTR_MASK_COLORMAP;
1942 DDPRINT(5, ("\tdefault %s colormap: %08lx\n",
1943 typename, ap->colormap));
1944 }
1945 if (mask & ATTR_MASK_STD_COLORMAP) {
1946 /* you can't fill default. what to do? */
1947 DDPRINT(5, ("\tdefault %s std colormap: N/A\n", typename));
1948 }
1949 if (mask & ATTR_MASK_BG_PIXMAP) {
1950 ap->bg_pixmap = None;
1951 ap->set_mask |= ATTR_MASK_BG_PIXMAP;
1952 DDPRINT(5, ("\tdefault %s background pixmap: None\n", typename));
1953 }
1954 if (mask & ATTR_MASK_LINESPACE) {
1955 if (!(ap->set_mask & ATTR_MASK_FONT_SET)) {
1956 fillPSDefault(icp, type, (unsigned long)ATTR_MASK_FONT_SET);
1957 }
1958 ap->line_space = getNaturalLineSpace(icp, type == NEST_PREEDIT);
1959 ap->set_mask |= ATTR_MASK_LINESPACE;
1960 DDPRINT(5, ("\tdefault line space: %d\n", ap->line_space));
1961 }
1962 if (mask & ATTR_MASK_CURSOR) {
1963 ap->cursor = None;
1964 ap->set_mask |= ATTR_MASK_CURSOR;
1965 DDPRINT(5, ("\tdefault %s cursor: None\n", typename));
1966 }
1967 if (mask & ATTR_MASK_AREA_NEEDED) {
1968 computeAreaNeeded(icp);
1969 DDPRINT(5, ("\t%s area_needed: %d,%d,%d,%d\n", typename,
1970 ap->area_needed.x, ap->area_needed.y,
1971 ap->area_needed.width, ap->area_needed.height));
1972 }
1973 if (mask & ATTR_MASK_FONT_SET) {
1974 ap->font_set = IMDefaultFontSet(icp->im);
1975 ap->set_mask |= ATTR_MASK_FONT_SET;
1976 DDPRINT(5, ("\tdefault %s fontset: %s\n", typename, ap->font_set));
1977 }
1978 if (mask & ATTR_MASK_SPOT_LOCATION) {
1979 ap->spot_location.x = ap->spot_location.y = 0;
1980 ap->set_mask |= ATTR_MASK_SPOT_LOCATION;
1981 DDPRINT(5, ("\tdefault spot location: %d, %d\n",
1982 ap->spot_location.x, ap->spot_location.y));
1983 }
1984 }
1985
1986 /*
1987 * Function validating attribute values
1988 */
1989
1990 static int
1991 validateCommonAttr(icp, checkonly)
1992 IMIC *icp;
1993 int checkonly;
1994 {
1995 IMCommonAttributes *ap = &icp->common_attr;
1996 IMConnection *conn = icp->im->connection;
1997 unsigned long mask = ap->change_mask;
1998 int ret = 0;
1999
2000 TRACE(("imlib:validateCommonAttr()\n"));
2001
2002 mask &= ap->set_mask;
2003
2004 #define SENDERROR(code, msg) \
2005 if (!checkonly && ret == 0) { \
2006 IMSendError(conn, code, icp->im->id, icp->id, msg); ret = -1; \
2007 }
2008
2009 if (mask & ATTR_MASK_INPUT_STYLE) {
2010 XIMStyle xstyle = icp->common_attr.input_style;
2011 InputStyle *isp = styles;
2012
2013 while (isp->xim_style != 0) {
2014 if (isp->xim_style == xstyle) break;
2015 isp++;
2016 }
2017 if (isp->xim_style == 0) {
2018 DPRINT(("unsupported input style\n"));
2019 ap->set_mask &= ~ATTR_MASK_INPUT_STYLE;
2020 SENDERROR(IMBadStyle, "unsupported input style");
2021 } else {
2022 icp->style = isp->conversion_style;
2023 }
2024 }
2025 if (mask & ATTR_MASK_CLIENT) {
2026 if (!validateClientWindow(icp)) {
2027 DPRINT(("invalid client window ID\n"));
2028 ap->set_mask &= ~ATTR_MASK_CLIENT;
2029 SENDERROR(IMBadClientWindow, "invalid client window ID");
2030 }
2031 }
2032 if (mask & ATTR_MASK_FOCUS) {
2033 if (!validateFocusWindow(icp)) {
2034 DPRINT(("invalid focus window ID\n"));
2035 ap->set_mask &= ~ATTR_MASK_FOCUS;
2036 SENDERROR(IMBadFocusWindow, "invalid focus window ID");
2037 }
2038 }
2039 if (mask & ATTR_MASK_PREEDIT_STATE) {
2040 unsigned long preedit_state = ap->preedit_state;
2041
2042 if (preedit_state != XIMPreeditEnable &&
2043 preedit_state != XIMPreeditDisable) {
2044 DPRINT(("invalid preedit state\n"));
2045 ap->set_mask &= ~ATTR_MASK_PREEDIT_STATE;
2046 SENDERROR(IMBadSomething, "invalid preedit state");
2047 }
2048 }
2049 if (mask & ATTR_MASK_RESET_STATE) {
2050 unsigned long reset_state = ap->reset_state;
2051
2052 if (reset_state != XIMInitialState &&
2053 reset_state != XIMPreserveState) {
2054 /*
2055 * Xlib document says invalid values should be interpreted as
2056 * XIMInitialState.
2057 */
2058 DPRINT(("invalid reset state -- forcing initial state\n"));
2059 ap->reset_state = XIMInitialState;
2060 }
2061 }
2062
2063 return ret;
2064 #undef SENDERROR
2065 }
2066
2067 static int
2068 validatePSAttr(icp, type, checkonly)
2069 IMIC *icp;
2070 int type;
2071 int checkonly;
2072 {
2073 /*
2074 * Check validity of preedit/status attribute values.
2075 * 'type' is either NEST_PREEDIT or NEST_STATUS, indicating
2076 * whether preedit or status attributes are to be checked.
2077 * 'mask' is the attribute mask to be checked.
2078 * If all the attributes are valid, this function return 0.
2079 * Otherwise it issues an error message for the first invalid
2080 * value detected, and returns -1.
2081 */
2082 IMPSAttributes *ap;
2083 IMConnection *conn = icp->im->connection;
2084 unsigned long mask;
2085 int preedit;
2086 int ret = 0;
2087
2088 TRACE(("imlib:validatePSAttr()\n"));
2089
2090 preedit = (type == NEST_PREEDIT);
2091 ap = preedit ? &icp->preedit_attr : &icp->status_attr;
2092
2093 /* do not check unset attributes */
2094 mask = ap->change_mask & ap->set_mask;
2095
2096 #define SENDERROR(code, msg) \
2097 if (!checkonly && ret == 0) { \
2098 IMSendError(conn, code, icp->im->id, icp->id, msg); ret = -1; \
2099 }
2100
2101 if (mask & ATTR_MASK_AREA) {
2102 if (ap->area.width == 0 || ap->area.height == 0) {
2103 ap->set_mask &= ~ATTR_MASK_AREA;
2104 DPRINT(("zero area width/height\n"));
2105 SENDERROR(IMBadArea, "invalid area width/height");
2106 }
2107 }
2108
2109 #ifdef notdef
2110 if (mask & ATTR_MASK_COLORMAP) {
2111 }
2112
2113 if (mask & ATTR_MASK_BG_PIXMAP) {
2114 }
2115 #endif
2116
2117 if (mask & ATTR_MASK_LINESPACE) {
2118 if (ap->line_space < MIN_LINE_SPACING) {
2119 ap->set_mask &= ~ATTR_MASK_LINESPACE;
2120 /*
2121 * we don't send error message in this case, because
2122 * there exist some applications which send invalid line
2123 * spacing and we don't want to break them.
2124 */
2125 DPRINT(("line space too small %d\n", ap->line_space));
2126 }
2127 }
2128
2129 #ifdef notdef
2130 if (mask & ATTR_MASK_CURSOR) {
2131 /* How should we check it? */
2132 }
2133 #endif
2134
2135 if (mask & ATTR_MASK_AREA_NEEDED) {
2136 }
2137 #ifdef notdef
2138 if (mask & ATTR_MASK_FONT_SET) {
2139 }
2140 if (mask & ATTR_MASK_SPOT_LOCATION) {
2141 }
2142 #endif
2143
2144 return ret;
2145 #undef SENDERROR
2146 }
2147
2148
2149 /*
2150 * Functions to extract necessary attributes and make conversion argument
2151 */
2152
2153 static void
2154 changeConversionAttributes(icp)
2155 IMIC *icp;
2156 {
2157 unsigned long mask;
2158 ConversionAttributes attr;
2159
2160 TRACE(("imlib:changeConversionAttributes()\n"));
2161 mask = IMMakeConvAttributes(icp, &attr);
2162 CControlChangeAttributes(icp->conversion, mask, &attr);
2163 }
2164
2165 static void
2166 computeAreaNeeded(icp)
2167 IMIC *icp;
2168 {
2169 IMPSAttributes *pattr = &icp->preedit_attr;
2170 IMPSAttributes *sattr = &icp->status_attr;
2171 IMWindowProfile *cpr = &icp->client_profile;
2172 int width, height;
2173 int min_width, min_height;
2174 int default_status_width;
2175 int font_height;
2176
2177 TRACE(("computeAreaNeeded()\n"));
2178
2179 if (icp->style == IMSTYLE_SEPARATE) return;
2180
2181 /*
2182 * Get the current dimension of the client window.
2183 */
2184 (void)validateClientWindow(icp);
2185
2186 /*
2187 * Compute the dimensions of the status region.
2188 */
2189 fillPSDefault(icp, NEST_STATUS, (unsigned long)ATTR_MASK_LINESPACE);
2190 font_height = sattr->line_space + 2;
2191 width = height = 0;
2192 if (sattr->set_mask & ATTR_MASK_AREA_NEEDED) {
2193 width = sattr->area_needed.width;
2194 height = sattr->area_needed.height;
2195 TRACE(("\tstatus areaNeeded was: (%d,%d)\n", width, height));
2196 }
2197
2198 min_width = font_height * 3;
2199 min_height = font_height;
2200 if (min_width < MIN_AREA_WIDTH) min_width = MIN_AREA_WIDTH;
2201 if (min_height < MIN_AREA_HEIGHT) min_height = MIN_AREA_HEIGHT;
2202
2203 if (width == 0) {
2204 default_status_width =
2205 IMStatusWidth(icp->im->connection->proto_widget);
2206 if (default_status_width > 0) {
2207 width = default_status_width;
2208 } else {
2209 width = cpr->width / 5; /* wild guess */
2210 }
2211 }
2212
2213 if (width < min_width) width = min_width;
2214 if (height < min_height) height = min_height;
2215
2216 sattr->area_needed.x = 0;
2217 sattr->area_needed.y = cpr->height - height;
2218 sattr->area_needed.width = width;
2219 sattr->area_needed.height = height;
2220 TRACE(("\tstatus areaNeeded is now: (%d, %d, %d, %d)\n",
2221 sattr->area_needed.x, sattr->area_needed.y, width, height));
2222
2223 /*
2224 * Compute the dimensions of the pre-edit region.
2225 */
2226 if (icp->style != IMSTYLE_OFF_THE_SPOT) return;
2227
2228 fillPSDefault(icp, NEST_PREEDIT, (unsigned long)ATTR_MASK_LINESPACE);
2229 font_height = pattr->line_space + 2;
2230 width = height = 0;
2231 if (pattr->set_mask & ATTR_MASK_AREA_NEEDED) {
2232 width = pattr->area_needed.width;
2233 height = pattr->area_needed.height;
2234 TRACE(("\tpreedit areaNeeded was: (%d,%d)\n",
2235 width, height));
2236 }
2237
2238 min_width = (cpr->width - sattr->area_needed.width) / 2;
2239 min_height = font_height;
2240 if (min_width < MIN_AREA_WIDTH) min_width = MIN_AREA_WIDTH;
2241 if (min_height < MIN_AREA_HEIGHT) min_height = MIN_AREA_HEIGHT;
2242
2243 if (width < min_width) width = min_width;
2244 if (height < min_height) height = min_height;
2245
2246 pattr->area_needed.x = sattr->area_needed.width;
2247 pattr->area_needed.y = cpr->height - height;
2248 pattr->area_needed.width = width;
2249 pattr->area_needed.height = height;
2250 TRACE(("\tpreedit areaNeeded is now: (%d, %d, %d, %d)\n",
2251 pattr->area_needed.x, pattr->area_needed.y, width, height));
2252 }
2253
2254 static void
2255 computeAreaForQuery(icp)
2256 IMIC *icp;
2257 {
2258 IMPSAttributes *pattr = &icp->preedit_attr;
2259 IMPSAttributes *sattr = &icp->status_attr;
2260
2261 TRACE(("computeAreaForQuery()\n"));
2262
2263 if (icp->style == IMSTYLE_SEPARATE) return;
2264
2265 computeAreaNeeded(icp);
2266
2267 if (!(pattr->set_mask & ATTR_MASK_AREA)) {
2268 if (icp->style == IMSTYLE_OVER_THE_SPOT) {
2269 IMWindowProfile *fpr = &icp->focus_profile;
2270
2271 pattr->area.x = 0;
2272 pattr->area.y = 0;
2273 pattr->area.width = fpr->width;
2274 pattr->area.height = fpr->height;
2275 } else { /* IMSTYLE_OFF_THE_SPOT */
2276 pattr->area = pattr->area_needed;
2277 }
2278 }
2279
2280 if (!(sattr->set_mask & ATTR_MASK_AREA)) {
2281 sattr->area = sattr->area_needed;
2282 }
2283 }
2284
2285
2286 /*
2287 * Public functions
2288 */
2289
2290 /*- IMPutIMAttrList: write list of supported IM attributes to output buffer -*/
2291 void
2292 IMPutIMAttrList(imp)
2293 IMIM *imp;
2294 {
2295 IMConnection *conn = imp->connection;
2296 IMAttribute *iap;
2297 int offset, list_start, list_end;
2298 int n;
2299
2300 TRACE(("IMPutIMAttrList()\n"));
2301
2302 offset = IMWritePos(conn);
2303 IMPutC16(conn, 0); /* dummy. overwritten afterwards */
2304
2305 list_start = IMWritePos(conn);
2306 for (n = 0, iap = imAttributes; n < numImAttributes; n++, iap++) {
2307 int length;
2308
2309 IMPutC16(conn, (unsigned int)n);
2310 IMPutC16(conn, (unsigned int)iap->type);
2311 length = strlen(iap->name);
2312 IMPutC16(conn, (unsigned int)length);
2313 IMPutString(conn, iap->name, length);
2314 IMPutPad(conn);
2315 }
2316 list_end = IMWritePos(conn);
2317 IMRewriteC16(conn, offset, (unsigned int)(list_end - list_start));
2318 }
2319
2320 /*- IMPutICAttrList: write list of supported IC attributes to output buffer -*/
2321 void
2322 IMPutICAttrList(imp)
2323 IMIM *imp;
2324 {
2325 IMConnection *conn = imp->connection;
2326 ICAttribute *iap;
2327 int offset, list_start, list_end;
2328 int n;
2329
2330 TRACE(("IMPutICAttrList()\n"));
2331
2332 offset = IMWritePos(conn);
2333 IMPutC16(conn, 0); /* dummy. overwritten afterwards */
2334 IMPutC16(conn, 0); /* unused */
2335
2336 list_start = IMWritePos(conn);
2337 for (n = 0, iap = icAttributes; n < numIcAttributes; n++, iap++) {
2338 int length;
2339
2340 IMPutC16(conn, (unsigned int)n);
2341 IMPutC16(conn, (unsigned int)iap->type);
2342 length = strlen(iap->name);
2343 IMPutC16(conn, (unsigned int)length);
2344 IMPutString(conn, iap->name, length);
2345 IMPutPad(conn);
2346 }
2347 list_end = IMWritePos(conn);
2348 IMRewriteC16(conn, offset, (unsigned int)(list_end - list_start));
2349 }
2350
2351 /* ARGSUSED */
2352 int
2353 IMSetIMValues(imp, data, len, major)
2354 IMIM *imp;
2355 char *data;
2356 int len;
2357 int major;
2358 {
2359 TRACE(("IMSetIMValues(): not supported yet\n"));
2360 /* not supported yet */
2361
2362 IMSendError(imp->connection, IMBadProtocol, imp->id, 0,
2363 "this protocol is not supported yet");
2364 return -1;
2365 }
2366
2367 int
2368 IMGetIMValues(imp, data, len, offset)
2369 IMIM *imp;
2370 char *data;
2371 int len;
2372 int offset; /* request offset */
2373 {
2374 IMConnection *conn = imp->connection;
2375 int pos, list_start, list_end;
2376
2377 TRACE(("IMGetIMValues()\n"));
2378
2379 pos = IMWritePos(conn);
2380 IMPutC16(conn, 0); /* length of the list. to be overwritten. */
2381
2382 list_start = IMWritePos(conn);
2383
2384 if (getIMValues(imp, data, len, offset) < 0) return -1;
2385
2386 list_end = IMWritePos(conn);
2387 IMRewriteC16(conn, pos, (unsigned int)(list_end - list_start));
2388 return 0;
2389 }
2390
2391 int
2392 IMSetICValues(icp, data, len, major)
2393 IMIC *icp;
2394 char *data;
2395 int len;
2396 int major;
2397 {
2398 int r1, r2, r3;
2399
2400 TRACE(("IMSetICValues()\n"));
2401
2402 /* clear change mask */
2403 icp->common_attr.change_mask = 0;
2404 icp->preedit_attr.change_mask = 0;
2405 icp->status_attr.change_mask = 0;
2406
2407 /* read the specified data and set attributes */
2408 r1 = setICValues(icp, data, len, 0,
2409 (major == XIM_CREATE_IC) ? OP_C : OP_S);
2410
2411 /* validate attributes */
2412 r2 = IMValidateICAttributes(icp, (r1 < 0));
2413
2414 /*
2415 * If the operation is CREATE_IC, input style attribute must be set.
2416 */
2417 if (major == XIM_CREATE_IC &&
2418 !(icp->common_attr.set_mask & ATTR_MASK_INPUT_STYLE) &&
2419 r1 == 0 && r2 == 0) {
2420 DPRINT(("input style not specified by CreateIC\n"));
2421 IMSendError(icp->im->connection, IMBadSomething, icp->im->id, icp->id,
2422 "inputStyle resource must be set");
2423 r3 = -1;
2424 } else {
2425 r3 = 0;
2426 }
2427
2428 if (r1 == 0 && r2 == 0) {
2429 /* if conversion is taking place... */
2430 if (icp->state & IC_CONVERTING) {
2431 changeConversionAttributes(icp);
2432 }
2433
2434 /* if preedit state is specified... */
2435 if (icp->common_attr.change_mask & ATTR_MASK_PREEDIT_STATE) {
2436 TRACE(("changing preedit state to %s\n",
2437 (icp->common_attr.preedit_state == XIMPreeditEnable) ?
2438 "enabled" : "disabled"));
2439 if (icp->common_attr.preedit_state == XIMPreeditEnable) {
2440 IMStartConversion(icp);
2441 } else {
2442 IMStopConversion(icp);
2443 }
2444 }
2445 }
2446
2447 return (r1 < 0 || r2 < 0 || r3 < 0) ? -1 : 0;
2448 }
2449
2450 int
2451 IMGetICValues(icp, data, len, offset)
2452 IMIC *icp;
2453 char *data;
2454 int len;
2455 int offset; /* request offset */
2456 {
2457 int nested_separator;
2458 int r;
2459 IMConnection *conn = icp->im->connection;
2460 int pos, list_start, list_end;
2461
2462 TRACE(("IMGetICValues()\n"));
2463
2464 pos = IMWritePos(conn);
2465 IMPutC16(conn, 0); /* dummy. overwritten afterwards */
2466 IMPutC16(conn, 0); /* unused */
2467
2468 list_start = IMWritePos(conn);
2469
2470 r = getICValues(icp, data, len, NEST_NONE, offset, &nested_separator);
2471 if (r < 0) return -1;
2472
2473 list_end = IMWritePos(conn);
2474 IMRewriteC16(conn, pos, (unsigned int)(list_end - list_start));
2475
2476 if (nested_separator) {
2477 /*
2478 * There must have been some unbalanced NestedListSeparator.
2479 */
2480 DPRINT(("getICvalues: unmatched separator\n"));
2481 IMCancelRequest(icp->im->connection, offset);
2482 IMSendError(icp->im->connection, IMBadSomething, icp->im->id, icp->id,
2483 "corrupted nested list");
2484 return -1;
2485 }
2486 return 0;
2487 }
2488
2489 void
2490 IMFillDefault(icp, common_mask, preedit_mask, status_mask)
2491 IMIC *icp;
2492 unsigned long common_mask;
2493 unsigned long preedit_mask;
2494 unsigned long status_mask;
2495 {
2496 TRACE(("IMFillDefault()\n"));
2497
2498 if (common_mask != 0) fillCommonDefault(icp, common_mask);
2499 if (preedit_mask != 0) fillPSDefault(icp, NEST_PREEDIT, preedit_mask);
2500 if (status_mask != 0) fillPSDefault(icp, NEST_STATUS, status_mask);
2501 }
2502
2503 int
2504 IMValidateWindow(dpy, win, profilep)
2505 Display *dpy;
2506 Window win;
2507 IMWindowProfile *profilep;
2508 {
2509 Window root;
2510 int x, y;
2511 unsigned int width, height, border, depth;
2512 XAEHandle h;
2513 int s;
2514
2515 TRACE(("IMValidateWindow(win: %08lx)\n", win));
2516
2517 h = XAESetIgnoreErrors(dpy);
2518 s = XGetGeometry(dpy, win, &root, &x, &y,
2519 &width, &height, &border, &depth);
2520 XAEUnset(h);
2521
2522 if (profilep != NULL && s) {
2523 profilep->width = width;
2524 profilep->height = width;
2525 profilep->root = root;
2526 }
2527 return s;
2528 }
2529
2530 int
2531 IMValidateICAttributes(icp, checkonly)
2532 IMIC *icp;
2533 int checkonly;
2534 {
2535 int error_occured;
2536 int r;
2537
2538 TRACE(("IMValidateICAttributes()\n"));
2539
2540 /*
2541 * Be careful not to send multiple error messages.
2542 */
2543
2544 error_occured = 0;
2545
2546 r = validateCommonAttr(icp, checkonly);
2547 if (r < 0) error_occured = 1;
2548
2549 r = validatePSAttr(icp, NEST_PREEDIT, (checkonly && error_occured));
2550 if (r < 0) error_occured = 1;
2551
2552 r = validatePSAttr(icp, NEST_STATUS, (checkonly && error_occured));
2553 if (r < 0) error_occured = 1;
2554
2555 return error_occured ? -1 : 0;
2556 }
2557
2558 void
2559 IMFreeICAttributes(icp)
2560 IMIC *icp;
2561 {
2562 IMPSAttributes *pattr = &icp->preedit_attr;
2563 IMPSAttributes *sattr = &icp->status_attr;
2564 FontBank bank = IMFontBank(icp->im);
2565
2566 TRACE(("IMFreeICAttributes()\n"));
2567
2568 if (pattr->set_mask & ATTR_MASK_FONT_SET) XtFree(pattr->font_set);
2569 if (sattr->set_mask & ATTR_MASK_FONT_SET) XtFree(sattr->font_set);
2570
2571 if (icp->num_fonts > 0) {
2572 FontBankFreeFonts(bank, icp->fonts, icp->num_fonts);
2573 }
2574 if (icp->num_status_fonts > 0) {
2575 FontBankFreeFonts(bank, icp->status_fonts, icp->num_status_fonts);
2576 }
2577 }
2578
2579 unsigned long
2580 IMMakeConvAttributes(icp, attr)
2581 IMIC *icp;
2582 ConversionAttributes *attr;
2583 {
2584 IMCommonAttributes *cattr;
2585 IMPSAttributes *pattr, *sattr;
2586 unsigned long cmask; /* changed attributes */
2587 unsigned long mask; /* attributes to be set */
2588
2589 TRACE(("IMMakeConvAttributes()\n"));
2590 mask = 0L;
2591
2592 cattr = &icp->common_attr;
2593 pattr = &icp->preedit_attr;
2594 sattr = &icp->status_attr;
2595
2596 /*
2597 * Check changes of common attributes.
2598 */
2599 cmask = cattr->change_mask;
2600
2601 /* focus window */
2602 if (cmask & ATTR_MASK_FOCUS) {
2603 attr->focuswindow = cattr->focus;
2604 mask |= CAFocusWindow;
2605 }
2606
2607 /*
2608 * Check changes of preedit attributes.
2609 */
2610 cmask = pattr->change_mask;
2611
2612 /* client area */
2613 if (cmask & ATTR_MASK_AREA) {
2614 attr->clientarea.x = pattr->area.x;
2615 attr->clientarea.y = pattr->area.y;
2616 attr->clientarea.width = pattr->area.width;
2617 attr->clientarea.height = pattr->area.height;
2618 mask |= CAClientArea;
2619 }
2620
2621 /* foreground/background */
2622 if (cmask & ATTR_MASK_FOREGROUND) {
2623 attr->foreground = pattr->foreground;
2624 mask |= CAColor;
2625 }
2626 if (cmask & ATTR_MASK_BACKGROUND) {
2627 attr->background = pattr->background;
2628 mask |= CAColor;
2629 }
2630
2631 /* colormap */
2632 if (cmask & ATTR_MASK_COLORMAP) {
2633 attr->colormap = pattr->colormap;
2634 mask |= CAColormap;
2635 }
2636
2637 /* background pixmap */
2638 if (cmask & ATTR_MASK_BG_PIXMAP) {
2639 attr->background_pixmap = pattr->bg_pixmap;
2640 mask |= CABackgroundPixmap;
2641 }
2642
2643 /* line spacing */
2644 if (cmask & ATTR_MASK_LINESPACE) {
2645 attr->linespacing = pattr->line_space;
2646 mask |= CALineSpacing;
2647 }
2648
2649 /* cursor */
2650 if (cmask & ATTR_MASK_CURSOR) {
2651 attr->cursor = pattr->cursor;
2652 mask |= CACursor;
2653 }
2654
2655 /* font */
2656 if (cmask & ATTR_MASK_FONT_SET) {
2657 changeFonts(icp, 1);
2658 attr->fonts = icp->fonts;
2659 attr->num_fonts = icp->num_fonts;
2660 mask |= CAFonts;
2661 }
2662
2663 /* spot location */
2664 if ((cmask & ATTR_MASK_SPOT_LOCATION) &&
2665 icp->style == IMSTYLE_OVER_THE_SPOT) {
2666 attr->spotx = pattr->spot_location.x;
2667 attr->spoty = pattr->spot_location.y;
2668 mask |= CASpotLocation;
2669 }
2670
2671 /*
2672 * Check changes of status attributes.
2673 */
2674 cmask = sattr->change_mask;
2675
2676 /* status area */
2677 if (cmask & ATTR_MASK_AREA) {
2678 attr->statusarea.x = sattr->area.x;
2679 attr->statusarea.y = sattr->area.y;
2680 attr->statusarea.width = sattr->area.width;
2681 attr->statusarea.height = sattr->area.height;
2682 mask |= CAStatusArea;
2683 }
2684
2685 /* font */
2686 if (cmask & ATTR_MASK_FONT_SET) {
2687 changeFonts(icp, 0);
2688 attr->status_fonts = icp->status_fonts;
2689 attr->num_status_fonts = icp->num_status_fonts;
2690 mask |= CAStatusFonts;
2691 }
2692
2693 return mask;
2694 }
2695
2696 void
2697 IMMoveLocation(icp, x, y)
2698 IMIC *icp;
2699 int x;
2700 int y;
2701 {
2702 TRACE(("IMMoveLocation()\n"));
2703
2704 icp->preedit_attr.spot_location.x = x;
2705 icp->preedit_attr.spot_location.y = y;
2706 icp->preedit_attr.set_mask |= ATTR_MASK_SPOT_LOCATION;
2707 icp->preedit_attr.change_mask = ATTR_MASK_SPOT_LOCATION;
2708 if (icp->state & IC_CONVERTING) {
2709 changeConversionAttributes(icp);
2710 }
2711 }