comparison lib/CandPanel.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
comparison
equal deleted inserted replaced
-1:000000000000 0:92745d501b9a
1 #ifndef lint
2 static char *rcsid = "$Id: CandPanel.c,v 1.11 1994/04/22 04:26:22 ishisone Rel $";
3 #endif
4 /*
5 * Copyright (c) 1990 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 <X11/IntrinsicP.h>
22 #include <X11/StringDefs.h>
23 #include "CandPanelP.h"
24 #include "ConvDisp.h"
25
26 static XtResource resources[] = {
27 #define offset(field) XtOffset(CandidatePanelWidget, cpanel.field)
28 { XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
29 offset(foreground), XtRString, XtDefaultForeground },
30 { XtNhorizontalSpacing, XtCSpacing, XtRDimension, sizeof(Dimension),
31 offset(hspace), XtRString, "6" },
32 { XtNverticalSpacing, XtCSpacing, XtRDimension, sizeof(Dimension),
33 offset(vspace), XtRString, "4" },
34 { XtNlist, XtCList, XtRPointer, sizeof(ICString*),
35 offset(list), XtRImmediate, NULL },
36 { XtNnumStrings, XtCNumStrings, XtRInt, sizeof(int),
37 offset(nstrings), XtRImmediate, 0 },
38 { XtNdefaultWidth, XtCDefaultWidth, XtRDimension, sizeof(Dimension),
39 offset(defaultwidth), XtRString, "400" },
40 { XtNcurrentItem, XtCCurrentItem, XtRInt, sizeof(int),
41 offset(current), XtRImmediate, 0 },
42 { XtNcursor, XtCCursor, XtRCursor, sizeof(Cursor),
43 offset(cursor), XtRImmediate, (XtPointer)None },
44 { XtNcallback, XtCCallback, XtRCallback, sizeof(XtPointer),
45 offset(callback), XtRCallback, NULL },
46 #undef offset
47 };
48
49 static void Move(/* Widget, XEvent*, String*, Cardinal* */);
50 static void Set(/* Widget, XEvent*, String*, Cardinal* */);
51 static void Notify(/* Widget, XEvent*, String*, Cardinal* */);
52
53 static XtActionsRec actions[] = {
54 { "move", Move },
55 { "set", Set },
56 { "select", Notify },
57 };
58
59 static char translations[] =
60 "<Btn1Down>: set() select()\n\
61 <Key>Up: move(up)\n\
62 <Key>Down: move(down)\n\
63 <Key>Left: move(left)\n\
64 <Key>Right: move(right)";
65
66 static void Initialize(), Destroy();
67 static void Realize();
68 static void Redisplay();
69 static void Resize();
70 static Boolean SetValues();
71 static XtGeometryResult QueryGeometry();
72 static void InsertChild();
73
74 static void GetInvGC();
75 static int MaxWidth();
76 static void ComputeSize();
77 static void Layout();
78 static void ToggleHighlight();
79
80 static CompositeClassExtensionRec CompositeExtension = {
81 /* next_extension */ NULL,
82 /* record_type */ NULLQUARK,
83 /* version */ XtCompositeExtensionVersion,
84 /* record_size */ sizeof(CompositeClassExtensionRec),
85 /* accept_objects */ True,
86 };
87
88 CandidatePanelClassRec candidatePanelClassRec = {
89 { /* core fields */
90 /* superclass */ (WidgetClass) &compositeClassRec,
91 /* class_name */ "CandidatePanel",
92 /* widget_size */ sizeof(CandidatePanelRec),
93 /* class_initialize */ NULL,
94 /* class_part_initialize */ NULL,
95 /* class_inited */ FALSE,
96 /* initialize */ Initialize,
97 /* initialize_hook */ NULL,
98 /* realize */ Realize,
99 /* actions */ actions,
100 /* num_actions */ XtNumber(actions),
101 /* resources */ resources,
102 /* num_resources */ XtNumber(resources),
103 /* xrm_class */ NULLQUARK,
104 /* compress_motion */ TRUE,
105 /* compress_exposure */ TRUE,
106 /* compress_enterleave */ TRUE,
107 /* visible_interest */ FALSE,
108 /* destroy */ Destroy,
109 /* resize */ Resize,
110 /* expose */ Redisplay,
111 /* set_values */ SetValues,
112 /* set_values_hook */ NULL,
113 /* set_values_almost */ XtInheritSetValuesAlmost,
114 /* get_values_hook */ NULL,
115 /* accept_focus */ NULL,
116 /* version */ XtVersion,
117 /* callback_private */ NULL,
118 /* tm_table */ translations,
119 /* query_geometry */ QueryGeometry,
120 /* display_accelerator */ XtInheritDisplayAccelerator,
121 /* extension */ NULL
122 },
123 { /* composite fields */
124 /* geometry_manager */ NULL,
125 /* change_managed */ NULL,
126 /* insert_child */ InsertChild,
127 /* delete_child */ XtInheritDeleteChild,
128 /* extension */ (XtPointer)&CompositeExtension,
129 },
130 { /* candidatepanel fields */
131 /* empty */ 0
132 }
133 };
134
135 WidgetClass candidatePanelWidgetClass = (WidgetClass)&candidatePanelClassRec;
136
137 /* ARGSUSED */
138 static void
139 Initialize(req, new, args, num_args)
140 Widget req;
141 Widget new;
142 ArgList args;
143 Cardinal *num_args;
144 {
145 CandidatePanelWidget cpw = (CandidatePanelWidget)new;
146
147 cpw->cpanel.displayobj = NULL;
148 GetInvGC(cpw);
149 }
150
151 static void
152 Destroy(w)
153 Widget w;
154 {
155 CandidatePanelWidget cpw = (CandidatePanelWidget)w;
156
157 if (cpw->cpanel.invgc != NULL) XtReleaseGC(w, cpw->cpanel.invgc);
158 }
159
160 static void
161 Realize(w, mask, value)
162 Widget w;
163 XtValueMask *mask;
164 XSetWindowAttributes *value;
165 {
166 CandidatePanelWidget cpw = (CandidatePanelWidget)w;
167 CompositeWidgetClass super = (CompositeWidgetClass)XtClass(w)->core_class.superclass;
168 String params[1];
169 Cardinal num_params;
170
171 if (cpw->cpanel.displayobj == NULL) {
172 params[0] = XtClass(w)->core_class.class_name;
173 num_params = 1;
174 XtAppErrorMsg(XtWidgetToApplicationContext(w),
175 "childError", "number", "WidgetError",
176 "%s: has no child (ConvDisplayObject)",
177 params, &num_params);
178 }
179
180 if (cpw->cpanel.cursor != None) {
181 *mask |= CWCursor;
182 value->cursor = cpw->cpanel.cursor;
183 }
184
185 (*super->core_class.realize)(w, mask, value);
186 }
187
188 /* ARGSUSED */
189 static void
190 Redisplay(w, ev, region)
191 Widget w;
192 XEvent *ev;
193 Region region;
194 {
195 CandidatePanelWidget cpw = (CandidatePanelWidget)w;
196 Widget dispobj = cpw->cpanel.displayobj;
197 XExposeEvent *event = (XExposeEvent *)ev;
198 ICString *list = cpw->cpanel.list;
199 int cwidth, cheight, hspace, vspace;
200 int c0, c1, r0, r1;
201 int row, col;
202 int idx;
203 int x, y;
204
205 if (list == NULL || dispobj == NULL) return;
206
207 cwidth = cpw->cpanel.maxwidth;
208 cheight = cpw->cpanel.fontheight;
209 hspace = cpw->cpanel.hspace;
210 vspace = cpw->cpanel.vspace;
211
212 c0 = (event->x + hspace - hspace / 2) / (cwidth + hspace);
213 c1 = (event->x + event->width - 1 - hspace / 2) / (cwidth + hspace) + 1;
214 if (c1 > cpw->cpanel.ncolumns) c1 = cpw->cpanel.ncolumns;
215
216 r0 = (event->y + vspace - vspace / 2) / (cheight + vspace);
217 r1 = (event->y + event->height - 1 - vspace / 2) / (cheight + vspace) + 1;
218 if (r1 > cpw->cpanel.nrows) r1 = cpw->cpanel.nrows;
219
220 for (row = r0; row < r1; row++) {
221 y = (cheight + vspace) * row + vspace / 2;
222 for (col = c0; col < c1; col++) {
223 x = (cwidth + hspace) * col + hspace / 2;
224 idx = row * cpw->cpanel.ncolumns + col;
225 if (idx >= cpw->cpanel.nstrings) return;
226 if (idx == cpw->cpanel.current) {
227 XClearArea(XtDisplay(w), XtWindow(w), x, y,
228 (unsigned int)cwidth, (unsigned int)cheight,
229 False);
230 }
231 CDDrawString(dispobj, w, list + idx, 0, -1, x, y);
232 if (idx == cpw->cpanel.current) {
233 ToggleHighlight(cpw, idx);
234 }
235 }
236 }
237 }
238
239 static void
240 Resize(w)
241 Widget w;
242 {
243 CandidatePanelWidget cpw = (CandidatePanelWidget)w;
244
245 Layout(cpw, False, False);
246 }
247
248 /* ARGSUSED */
249 static Boolean
250 SetValues(cur, req, wid, args, num_args)
251 Widget cur;
252 Widget req;
253 Widget wid;
254 ArgList args;
255 Cardinal *num_args;
256 {
257 CandidatePanelWidget old = (CandidatePanelWidget)cur;
258 CandidatePanelWidget new = (CandidatePanelWidget)wid;
259 Boolean redisplay = False;
260 Boolean listspecified = False;
261 int i;
262
263 if (new->cpanel.displayobj == NULL) return False;
264
265 for (i = 0; i < *num_args; i++) {
266 if (!strcmp(args[i].name, XtNlist)) {
267 listspecified = True;
268 break;
269 }
270 }
271
272 if (new->cpanel.foreground != old->cpanel.foreground ||
273 new->core.background_pixel != old->core.background_pixel) {
274 XtVaSetValues(new->cpanel.displayobj,
275 XtNforeground, new->cpanel.foreground,
276 XtNbackground, new->core.background_pixel,
277 NULL);
278 redisplay = True;
279 }
280
281 if (listspecified ||
282 new->cpanel.list != old->cpanel.list ||
283 new->cpanel.nstrings != old->cpanel.nstrings) {
284 /* compute maximum pixel width of the list items */
285 new->cpanel.maxwidth = MaxWidth(new);
286 }
287
288 if (listspecified ||
289 new->cpanel.list != old->cpanel.list ||
290 new->cpanel.nstrings != old->cpanel.nstrings ||
291 new->cpanel.hspace != old->cpanel.hspace ||
292 new->cpanel.vspace != old->cpanel.vspace ||
293 new->cpanel.defaultwidth != old->cpanel.defaultwidth) {
294 Layout(new, True, True);
295 redisplay = True;
296 }
297
298 if (new->cpanel.current != old->cpanel.current &&
299 !redisplay && XtIsRealized(wid)) {
300 ToggleHighlight(new, old->cpanel.current);
301 ToggleHighlight(new, new->cpanel.current);
302 }
303
304 if (new->cpanel.cursor != old->cpanel.cursor && XtIsRealized(wid)) {
305 XDefineCursor(XtDisplay(wid), XtWindow(wid), new->cpanel.cursor);
306 }
307
308 return redisplay;
309 }
310
311 static XtGeometryResult
312 QueryGeometry(w, req, ret)
313 Widget w;
314 XtWidgetGeometry *req;
315 XtWidgetGeometry *ret;
316 {
317 Dimension width, height;
318 Dimension owidth, oheight;
319
320 ret->request_mode = 0;
321
322 if ((req->request_mode & (CWWidth | CWHeight)) == 0) return XtGeometryYes;
323
324 width = (req->request_mode & CWWidth) ? req->width : w->core.width;
325 height = (req->request_mode & CWHeight) ? req->height : w->core.height;
326
327 owidth = width;
328 oheight = height;
329 ComputeSize((CandidatePanelWidget)w,
330 (req->request_mode & CWWidth) != 0,
331 (req->request_mode & CWHeight) != 0,
332 &width, &height);
333 ret->request_mode = CWWidth | CWHeight;
334 ret->width = width;
335 ret->height = height;
336
337 if (width != owidth || height != oheight) return XtGeometryAlmost;
338
339 return XtGeometryYes;
340 }
341
342 static void
343 InsertChild(w)
344 Widget w;
345 {
346 CandidatePanelWidget cpw = (CandidatePanelWidget)XtParent(w);
347 CompositeWidgetClass super = (CompositeWidgetClass)XtClass(cpw)->core_class.superclass;
348 String params[1];
349 Cardinal num_params;
350
351 if (!XtIsSubclass(w, convDisplayObjectClass)) {
352 params[0] = XtClass(cpw)->core_class.class_name;
353 num_params = 1;
354 XtAppErrorMsg(XtWidgetToApplicationContext(w),
355 "childError", "class", "WidgetError",
356 "%s: child must be subclass of ConvDisplayObject",
357 params, &num_params);
358 }
359 if (cpw->composite.num_children != 0) {
360 params[0] = XtClass(cpw)->core_class.class_name;
361 num_params = 1;
362 XtAppErrorMsg(XtWidgetToApplicationContext(w),
363 "childError", "number", "WidgetError",
364 "%s: can only take one child",
365 params, &num_params);
366 }
367
368 (*super->composite_class.insert_child)(w);
369
370 cpw->cpanel.displayobj = w;
371 cpw->cpanel.fontheight = CDLineHeight(w, (Position *)NULL);
372
373 #ifdef notdef
374 {
375 Pixel fg, bg;
376 XtVaGetValues(w, XtNforeground, &fg, XtNbackground, &bg, NULL);
377 GetInvGC(cpw, fg, bg);
378 }
379 #endif
380
381 if (cpw->cpanel.list != NULL) {
382 cpw->cpanel.maxwidth = MaxWidth(cpw);
383 Layout(cpw, cpw->core.width == 0, cpw->core.height == 0);
384 }
385 }
386
387 static void
388 GetInvGC(cpw)
389 CandidatePanelWidget cpw;
390 {
391 XGCValues values;
392
393 values.function = GXinvert;
394 values.plane_mask = cpw->cpanel.foreground ^ cpw->core.background_pixel;
395 cpw->cpanel.invgc = XtGetGC((Widget)cpw, GCFunction|GCPlaneMask, &values);
396 }
397
398 /* ARGSUSED */
399 static void
400 Move(w, ev, args, num_args)
401 Widget w;
402 XEvent *ev;
403 String *args;
404 Cardinal *num_args;
405 {
406 int dir;
407
408 if (*num_args < 1) return;
409
410 if (!strcmp(*args, "left") || !strcmp(*args, "Left")) {
411 dir = ICMoveLeft;
412 } else if (!strcmp(*args, "right") || !strcmp(*args, "Right")) {
413 dir = ICMoveRight;
414 } else if (!strcmp(*args, "up") || !strcmp(*args, "Up")) {
415 dir = ICMoveUp;
416 } else if (!strcmp(*args, "down") || !strcmp(*args, "Down")) {
417 dir = ICMoveDown;
418 } else {
419 XtAppWarning(XtWidgetToApplicationContext(w),
420 "CandidatePanel: unknown direction");
421 return;
422 }
423
424 CPanelMoveCurrent(w, dir);
425 }
426
427 /* ARGSUSED */
428 static void
429 Set(w, ev, args, num_args)
430 Widget w;
431 XEvent *ev;
432 String *args;
433 Cardinal *num_args;
434 {
435 CandidatePanelWidget cpw = (CandidatePanelWidget)w;
436 XButtonEvent *event = (XButtonEvent *)ev;
437 int cwidth, cheight, hspace, vspace;
438 int x, y;
439 int row, col;
440 int newidx;
441
442 cwidth = cpw->cpanel.maxwidth;
443 cheight = cpw->cpanel.fontheight;
444 hspace = cpw->cpanel.hspace;
445 vspace = cpw->cpanel.vspace;
446
447 x = event->x - hspace / 2;
448 col = x / (cwidth + hspace);
449 if (col >= cpw->cpanel.ncolumns || (x % (cwidth + hspace)) > cwidth) return;
450
451 y = event->y - vspace / 2;
452 row = y / (cheight + vspace);
453 if (row >= cpw->cpanel.nrows || (y % (cheight + vspace)) > cheight) return;
454
455 newidx = col + cpw->cpanel.ncolumns * row;
456 if (newidx >= cpw->cpanel.nstrings) return;
457
458 CPanelSetCurrent(w, newidx);
459 }
460
461 /* ARGSUSED */
462 static void
463 Notify(w, ev, args, num_args)
464 Widget w;
465 XEvent *ev;
466 String *args;
467 Cardinal *num_args;
468 {
469 CandidatePanelWidget cpw = (CandidatePanelWidget)w;
470
471 XtCallCallbackList(w, cpw->cpanel.callback,
472 (XtPointer)cpw->cpanel.current);
473 }
474
475 static int
476 MaxWidth(cpw)
477 CandidatePanelWidget cpw;
478 {
479 Widget dispobj = cpw->cpanel.displayobj;
480 ICString *list = cpw->cpanel.list;
481 int maxwidth;
482 int i;
483
484 maxwidth = 0;
485 for (i = 0; i < cpw->cpanel.nstrings; i++) {
486 int w = CDStringWidth(dispobj, list + i, 0, -1);
487 if (w > maxwidth) maxwidth = w;
488 }
489
490 return maxwidth;
491 }
492
493 static void
494 ComputeSize(cpw, resizex, resizey, width_inout, height_inout)
495 CandidatePanelWidget cpw;
496 int resizex;
497 int resizey;
498 Dimension *width_inout;
499 Dimension *height_inout;
500 {
501 int nrows, ncolumns;
502 int width, height;
503
504 if (cpw->cpanel.displayobj == NULL || cpw->cpanel.nstrings == 0) return;
505
506 width = *width_inout;
507 height = *height_inout;
508
509 if (resizex) {
510 if (resizey) {
511 int maxheight = HeightOfScreen(XtScreen((Widget)cpw));
512
513 /* use defaultwidth */
514 ncolumns = cpw->cpanel.defaultwidth /
515 (cpw->cpanel.maxwidth + cpw->cpanel.hspace);
516 if (ncolumns > cpw->cpanel.nstrings) ncolumns = cpw->cpanel.nstrings;
517 if (ncolumns <= 0) ncolumns = 1;
518 nrows = (cpw->cpanel.nstrings + ncolumns - 1) / ncolumns;
519 width = (cpw->cpanel.maxwidth + cpw->cpanel.hspace) * ncolumns;
520 height = (cpw->cpanel.fontheight + cpw->cpanel.vspace) * nrows;
521 /*
522 * If the computed height exceeds display height,
523 * expand width so that the entire window fits into the display.
524 */
525 if (height > maxheight) {
526 /* compute maximum number of rows */
527 nrows = maxheight / (cpw->cpanel.fontheight + cpw->cpanel.vspace);
528 if (nrows <= 0) nrows = 1;
529 ncolumns = (cpw->cpanel.nstrings + nrows - 1) / nrows;
530 if (ncolumns > cpw->cpanel.nstrings) {
531 ncolumns = cpw->cpanel.nstrings;
532 }
533 /* re-compute correct number of rows */
534 nrows = (cpw->cpanel.nstrings + ncolumns - 1) / ncolumns;
535 width = (cpw->cpanel.maxwidth + cpw->cpanel.hspace) * ncolumns;
536 height = (cpw->cpanel.fontheight + cpw->cpanel.vspace) * nrows;
537 }
538 } else {
539 /* use specified height */
540 nrows = height / (cpw->cpanel.fontheight + cpw->cpanel.vspace);
541 if (nrows <= 0) nrows = 1;
542 ncolumns = (cpw->cpanel.nstrings + nrows - 1) / nrows;
543 if (ncolumns > cpw->cpanel.nstrings) ncolumns = cpw->cpanel.nstrings;
544 width = (cpw->cpanel.maxwidth + cpw->cpanel.hspace) * ncolumns;
545 }
546 } else {
547 ncolumns = width / (cpw->cpanel.maxwidth + cpw->cpanel.hspace);
548 if (ncolumns <= 0) ncolumns = 1;
549 nrows = (cpw->cpanel.nstrings + ncolumns - 1) / ncolumns;
550 if (resizey) {
551 height = (cpw->cpanel.fontheight + cpw->cpanel.vspace) * nrows;
552 }
553 }
554 cpw->cpanel.ncolumns = ncolumns;
555 cpw->cpanel.nrows = nrows;
556 *width_inout = width;
557 *height_inout = height;
558 }
559
560 static void
561 Layout(cpw, resizex, resizey)
562 CandidatePanelWidget cpw;
563 int resizex;
564 int resizey;
565 {
566 Dimension width, height;
567 Dimension owidth, oheight;
568 XtGeometryResult re;
569
570 if (cpw->cpanel.displayobj == NULL) return;
571
572 width = cpw->core.width;
573 height = cpw->core.height;
574 ComputeSize(cpw, resizex, resizey, &width, &height);
575
576 if (width != cpw->core.width || height != cpw->core.height) {
577 owidth = width;
578 oheight = height;
579 re = XtMakeResizeRequest((Widget)cpw, owidth, oheight, &width, &height);
580 switch (re) {
581 case XtGeometryYes:
582 /* no problem */
583 break;
584 case XtGeometryNo:
585 width = cpw->core.width;
586 height = cpw->core.height;
587 ComputeSize(cpw, False, False, &width, &height);
588 break;
589 case XtGeometryAlmost:
590 ComputeSize(cpw,
591 width != owidth,
592 height != oheight,
593 &width, &height);
594 re = XtMakeResizeRequest((Widget)cpw, width, height, &width, &height);
595 switch (re) {
596 case XtGeometryYes:
597 break;
598 case XtGeometryNo:
599 width = cpw->core.width;
600 height = cpw->core.height;
601 ComputeSize(cpw, False, False, &width, &height);
602 break;
603 case XtGeometryAlmost:
604 ComputeSize(cpw, False, False, &width, &height);
605 (void)XtMakeResizeRequest((Widget)cpw, width, height, &width, &height);
606 }
607 }
608 }
609 }
610
611 static void
612 ToggleHighlight(cpw, idx)
613 CandidatePanelWidget cpw;
614 int idx;
615 {
616 int row, col;
617 int x, y;
618 int width;
619
620 if (idx < 0 || cpw->cpanel.nstrings <= idx) return;
621
622 col = idx % cpw->cpanel.ncolumns;
623 row = idx / cpw->cpanel.ncolumns;
624 x = (cpw->cpanel.maxwidth + cpw->cpanel.hspace) * col +
625 cpw->cpanel.hspace / 2;
626 y = (cpw->cpanel.fontheight + cpw->cpanel.vspace) * row +
627 cpw->cpanel.vspace / 2;
628 width = CDStringWidth(cpw->cpanel.displayobj, cpw->cpanel.list + idx,
629 0, -1);
630
631 XFillRectangle(XtDisplay(cpw), XtWindow(cpw), cpw->cpanel.invgc, x, y,
632 (unsigned int)width, (unsigned int)cpw->cpanel.fontheight);
633 }
634
635
636 /*
637 * Public Functions
638 */
639
640 void
641 CPanelSetList(w, list, nstrings, current, resize)
642 Widget w;
643 ICString *list;
644 int nstrings;
645 int current;
646 int resize;
647 {
648 CandidatePanelWidget cpw = (CandidatePanelWidget)w;
649
650 if (list != NULL) {
651 cpw->cpanel.list = list;
652 cpw->cpanel.nstrings = nstrings;
653 if (current < 0) current = 0;
654 if (current >= nstrings) current = nstrings - 1;
655 cpw->cpanel.current = current;
656 }
657
658 if (cpw->cpanel.displayobj == NULL) return;
659
660 cpw->cpanel.fontheight = CDLineHeight(cpw->cpanel.displayobj,
661 (Position *)NULL);
662 /* compute maximum pixel width of the list items */
663 cpw->cpanel.maxwidth = MaxWidth(cpw);
664 Layout(cpw, resize, resize);
665
666 if (XtIsRealized(w)) XClearWindow(XtDisplay(w), XtWindow(w));
667 }
668
669 void
670 CPanelSetCurrent(w, idx)
671 Widget w;
672 int idx;
673 {
674 CandidatePanelWidget cpw = (CandidatePanelWidget)w;
675
676 if (idx < 0 || cpw->cpanel.nstrings <= idx) return;
677
678 if (idx == cpw->cpanel.current) return;
679
680 if (cpw->cpanel.displayobj != NULL && XtIsRealized(w)) {
681 ToggleHighlight(cpw, cpw->cpanel.current);
682 ToggleHighlight(cpw, idx);
683 }
684 cpw->cpanel.current = idx;
685 }
686
687 void
688 CPanelMoveCurrent(w, dir)
689 Widget w;
690 int dir;
691 {
692 CandidatePanelWidget cpw = (CandidatePanelWidget)w;
693 int newidx;
694 int row, col;
695 int nstrings = cpw->cpanel.nstrings;
696
697 if (nstrings <= 0) return;
698
699 col = cpw->cpanel.current % cpw->cpanel.ncolumns;
700 row = cpw->cpanel.current / cpw->cpanel.ncolumns;
701
702 switch (dir) {
703 case ICMoveLeft:
704 if ((newidx = cpw->cpanel.current - 1) < 0) newidx = nstrings - 1;
705 break;
706 case ICMoveRight:
707 if ((newidx = cpw->cpanel.current + 1) >= nstrings) newidx = 0;
708 break;
709 case ICMoveUp:
710 case ICMovePrevPage:
711 if (--row < 0) row = cpw->cpanel.nrows - 1;
712 newidx = row * cpw->cpanel.ncolumns + col;
713 if (newidx >= nstrings) newidx -= cpw->cpanel.ncolumns;
714 break;
715 case ICMoveDown:
716 case ICMoveNextPage:
717 if (++row >= cpw->cpanel.nrows) row = 0;
718 newidx = row * cpw->cpanel.ncolumns + col;
719 if (newidx >= nstrings) newidx = col;
720 break;
721 case ICMoveLeftMost:
722 newidx = row * cpw->cpanel.ncolumns;
723 break;
724 case ICMoveRightMost:
725 newidx = (row + 1) * cpw->cpanel.ncolumns - 1;
726 if (newidx >= cpw->cpanel.nstrings) newidx = cpw->cpanel.nstrings - 1;
727 break;
728 case ICMoveFirst:
729 newidx = 0;
730 break;
731 case ICMoveLast:
732 newidx = cpw->cpanel.nstrings - 1;
733 break;
734 }
735
736 CPanelSetCurrent(w, newidx);
737 }