1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49 #include "XmL.h"
50 #include <Xm/XmP.h>
51 #include <Xm/LabelP.h>
52 #include <Xm/DrawnBP.h>
53 #include <Xm/MessageB.h>
54 #include <Xm/Protocols.h>
55 #include <Xm/AtomMgr.h>
56 #ifdef MOTIF11
57 #include <Xm/VendorE.h>
58 #else
59 #include <Xm/VendorS.h>
60 #endif
61 #include <Xm/BulletinB.h>
62 #include <Xm/MenuShell.h>
63
64 #include <X11/Xft/Xft.h>
65
66
67 #include <stdlib.h>
68 #include <stdio.h>
69
70 #ifdef SUNOS4
71 int fprintf(
FILE *,
char *, ...);
72 #endif
73
74 static void XmLDrawnBDestroyCB(Widget w, XtPointer clientData, XtPointer);
75 static void XmLDrawnBDrawCB(Widget, XtPointer, XtPointer);
76 static void XmLDrawnBDrawStringCB(Widget, XtPointer, XtPointer);
77 static int XmLDrawCalc(Widget w, Dimension width, Dimension height,
78 unsigned char alignment, XRectangle *rect, XRectangle *clipRect,
79 int *x,
int *y);
80 static void XmLFontGetAverageWidth(XFontStruct *fs,
short *width);
81 static void XmLMessageBoxResponse(Widget, XtPointer, XtPointer);
82 static void XmLMessageBoxWMDelete(Widget, XtPointer, XtPointer);
83 static void XmLSortFunc(
char *lvec,
char *rvec);
84
85 struct _XmLArrayRec
86 {
87 char _autonumber, _growFast;
88 int _count, _size;
89 void **_items;
90 };
91
92 XmLArray
93 XmLArrayNew(
char autonumber,
94 char growFast)
95 {
96 XmLArray array;
97
98 array = (XmLArray)malloc(
sizeof(
struct _XmLArrayRec));
99 array->_count =
0;
100 array->_size =
0;
101 array->_items =
0;
102 array->_autonumber = autonumber;
103 array->_growFast = growFast;
104 return array;
105 }
106
107 void
108 XmLArrayFree(XmLArray array)
109 {
110 if (array->_items)
111 free((
char *)array->_items);
112 free((
char *)array);
113 }
114
115 void
116 XmLArrayAdd(XmLArray array,
117 int pos,
118 int count)
119 {
120 int i;
121 void **items;
122
123 if (count <
1)
124 return;
125 if (pos <
0 || pos > array->_count)
126 pos = array->_count;
127 if (array->_count + count >= array->_size)
128 {
129 if (array->_growFast)
130 {
131 if (!array->_size)
132 array->_size = count +
256;
133 else
134 array->_size = (array->_count + count) *
2;
135 }
136 else
137 array->_size = array->_count + count;
138 items = (
void **)malloc(
sizeof(
void *) * array->_size);
139 if (array->_items)
140 {
141 for (i =
0; i < array->_count; i++)
142 items[i] = array->_items[i];
143 free((
char *)array->_items);
144 }
145 array->_items = items;
146 }
147 for (i = array->_count + count -
1; i >= pos + count; i--)
148 {
149 array->_items[i] = array->_items[i - count];
150 if (array->_autonumber)
151 ((XmLArrayItem *)array->_items[i])->pos = i;
152 }
153 for (i = pos; i < pos + count; i++)
154 array->_items[i] =
0;
155 array->_count += count;
156 }
157
158 int
159 XmLArrayDel(XmLArray array,
160 int pos,
161 int count)
162 {
163 int i;
164
165 if (pos <
0 || pos + count > array->_count)
166 return -
1;
167 for (i = pos; i < array->_count - count; i++)
168 {
169 array->_items[i] = array->_items[i + count];
170 if (array->_autonumber)
171 ((XmLArrayItem *)array->_items[i])->pos = i;
172 }
173 array->_count -= count;
174 if (!array->_count)
175 {
176 if (array->_items)
177 free((
char *)array->_items);
178 array->_items =
0;
179 array->_size =
0;
180 }
181 return 0;
182 }
183
184 int
185 XmLArraySet(XmLArray array,
186 int pos,
187 void *item)
188 {
189 if (pos <
0 || pos >= array->_count)
190 return -
1;
191 if (array->_items[pos])
192 fprintf(stderr,
"XmLArraySet: warning: overwriting pointer\n");
193 array->_items[pos] = item;
194 if (array->_autonumber)
195 ((XmLArrayItem *)array->_items[pos])->pos = pos;
196 return 0;
197 }
198
199 void *
200 XmLArrayGet(XmLArray array,
201 int pos)
202 {
203 if (pos <
0 || pos >= array->_count)
204 return 0;
205 return array->_items[pos];
206 }
207
208 int
209 XmLArrayGetCount(XmLArray array)
210 {
211 return array->_count;
212 }
213
214 int
215 XmLArrayMove(XmLArray array,
216 int newPos,
217 int pos,
218 int count)
219 {
220 void **items;
221 int i;
222
223 if (count <=
0)
224 return -
1;
225 if (newPos <
0 || newPos + count > array->_count)
226 return -
1;
227 if (pos <
0 || pos + count > array->_count)
228 return -
1;
229 if (pos == newPos)
230 return 0;
231
232 items = (
void **)malloc(
sizeof(
void *) * count);
233 for (i =
0; i < count; i++)
234 items[i] = array->_items[pos + i];
235
236 if (newPos < pos)
237 for (i = pos + count -
1; i >= newPos + count; i--)
238 {
239 array->_items[i] = array->_items[i - count];
240 if (array->_autonumber)
241 ((XmLArrayItem *)array->_items[i])->pos = i;
242 }
243 else
244 for (i = pos; i < newPos; i++)
245 {
246 array->_items[i] = array->_items[i + count];
247 if (array->_autonumber)
248 ((XmLArrayItem *)array->_items[i])->pos = i;
249 }
250
251 for (i =
0; i < count; i++)
252 {
253 array->_items[newPos + i] = items[i];
254 if (array->_autonumber)
255 ((XmLArrayItem *)array->_items[newPos + i])->pos = newPos + i;
256 }
257 free((
char *)items);
258 return 0;
259 }
260
261 int
262 XmLArrayReorder(XmLArray array,
263 int *newPositions,
264 int pos,
265 int count)
266 {
267 int i;
268 void **items;
269
270 if (count <=
0)
271 return -
1;
272 if (pos <
0 || pos + count > array->_count)
273 return -
1;
274 for (i =
0; i < count; i++)
275 {
276 if (newPositions[i] < pos || newPositions[i] >= pos + count)
277 return -
1;
278 }
279 items = (
void **)malloc(
sizeof(
void *) * count);
280 for (i =
0; i < count; i++)
281 items[i] = array->_items[newPositions[i]];
282 for (i =
0; i < count; i++)
283 {
284 array->_items[pos + i] = items[i];
285 if (array->_autonumber)
286 ((XmLArrayItem *)array->_items[pos + i])->pos = pos + i;
287 }
288 free((
char *)items);
289 return 0;
290 }
291
292 int
293 XmLArraySort(XmLArray array,
294 XmLArrayCompareFunc compare,
295 void *userData,
296 int pos,
297 int count)
298 {
299 int i;
300
301 if (pos <
0 || pos + count > array->_count)
302 return -
1;
303 XmLSort(&array->_items[pos], count,
sizeof(
void *),
304 (XmLSortCompareFunc)compare, userData);
305 if (array->_autonumber)
306 for (i = pos; i < pos + count; i++)
307 ((XmLArrayItem *)array->_items[i])->pos = i;
308 return 0;
309 }
310
311
312 Boolean
313 XmLCvtStringToUChar(Display *dpy,
314 char *resname,
315 XmLStringToUCharMap *map,
316 XrmValuePtr fromVal,
317 XrmValuePtr toVal)
318 {
319 char *from;
320 int i, valid;
321
322 from = (
char *)fromVal->addr;
323 valid =
0;
324 i =
0;
325 while (map[i].name)
326 {
327 if (!strcmp(from, map[i].name))
328 {
329 valid =
1;
330 break;
331 }
332 i++;
333 }
334 if (!valid)
335 {
336 XtDisplayStringConversionWarning(dpy, from, resname);
337 toVal->size =
0;
338 toVal->addr =
0;
339 return False;
340 }
341 if (toVal->addr)
342 {
343 if (toVal->size <
sizeof(
unsigned char))
344 {
345 toVal->size =
sizeof(
unsigned char);
346 return False;
347 }
348 *(
unsigned char *)(toVal->addr) = map[i].value;
349 }
350 else
351 toVal->addr = (
caddr_t)&map[i].value;
352 toVal->size =
sizeof(
unsigned char);
353 return True;
354 }
355
356 int
357 XmLDateDaysInMonth(
int m,
358 int y)
359 {
360 static int d[
12] = {
31,
28,
31,
30,
31,
30,
31,
31,
30,
31,
30,
31};
361
362 if (m <
1 || m >
12 || y <
1753 || y >
9999)
363 return -
1;
364 if (m ==
2 && (!((y %
4) && (y %
100)) || !(y %
400)))
365 return 29;
366 return d[m -
1];
367 }
368
369
370
371 int
372 XmLDateWeekDay(
int m,
373 int d,
374 int y)
375 {
376 long jd, j1, j2;
377
378 if (m <
1 || m >
12 || d <
1 || d > XmLDateDaysInMonth(m, y) ||
379 y <
1753 || y >
9999)
380 return -
1;
381 if (m >
2)
382 m -=
3;
383 else
384 {
385 m +=
9;
386 y--;
387 }
388 j1 = y /
100;
389 j2 = y -
100 * j1;
390 jd = (
146097 * j1) /
4 + (
1461 * j2) /
4 + (
153 * m +
2) /
5 +
391 1721119 + d;
392 return (jd +
1) %
7;
393 }
394
395 typedef struct
396 {
397 GC gc;
398 int type;
399 int dir;
400 XFontStruct *fontStruct;
401 } XmLDrawnBData;
402
403 void
404 XmLDrawnButtonSetType(Widget w,
405 int drawnType,
406 int drawnDir)
407 {
408 XmLDrawnBData *dd;
409 XmDrawnButtonWidget b;
410 XmString str;
411 XmRenderTable rendertable;
412 XGCValues values;
413 XtGCMask mask;
414 Dimension width, height, dim;
415 Dimension highlightThickness, shadowThickness;
416 Dimension marginWidth, marginHeight;
417 Dimension marginTop, marginBottom, marginLeft, marginRight;
418
419 if (!XtIsSubclass(w, xmDrawnButtonWidgetClass))
420 {
421 XmLWarning(w,
"DrawnButtonSetType() - not an XmDrawnButton");
422 return;
423 }
424 XtVaSetValues(w,
425 XmNpushButtonEnabled, True,
426 NULL);
427 XtRemoveAllCallbacks(w, XmNexposeCallback);
428 XtRemoveAllCallbacks(w, XmNresizeCallback);
429 if (drawnType == XmDRAWNB_STRING && drawnDir == XmDRAWNB_RIGHT)
430 {
431 XtVaSetValues(w,
432 XmNlabelType, XmSTRING,
433 NULL);
434 return;
435 }
436 b = (XmDrawnButtonWidget)w;
437 dd = (XmLDrawnBData *)malloc(
sizeof(XmLDrawnBData));
438 dd->type = drawnType;
439 dd->dir = drawnDir;
440 dd->gc =
0;
441 if (dd->type == XmDRAWNB_STRING)
442 {
443 XtVaGetValues(w,
444 XmNlabelString, &str,
445 XmNrenderTable, &rendertable,
446 XmNhighlightThickness, &highlightThickness,
447 XmNshadowThickness, &shadowThickness,
448 XmNmarginHeight, &marginHeight,
449 XmNmarginWidth, &marginWidth,
450 XmNmarginTop, &marginTop,
451 XmNmarginBottom, &marginBottom,
452 XmNmarginLeft, &marginLeft,
453 XmNmarginRight, &marginRight,
454 NULL);
455 if (!str && XtName(w))
456 str = XmStringCreateSimple(XtName(w));
457 if (!str)
458 str = XmStringCreateSimple(
"");
459 XmStringExtent(rendertable, str, &width, &height);
460 XmStringFree(str);
461 if (drawnDir == XmDRAWNB_UP || drawnDir == XmDRAWNB_DOWN)
462 {
463 dim = width;
464 width = height;
465 height = dim;
466 }
467 height += (highlightThickness + shadowThickness +
468 marginHeight) *
2 + marginTop + marginBottom;
469 width += (highlightThickness + shadowThickness +
470 marginWidth) *
2 + marginLeft + marginRight;
471
472 XtVaSetValues(w,
473 XmNlabelType, XmPIXMAP,
474 NULL);
475 XtVaSetValues(w,
476 XmNwidth, width,
477 XmNheight, height,
478 NULL);
479 XtAddCallback(w, XmNexposeCallback, XmLDrawnBDrawStringCB,
480 (XtPointer)dd);
481 XtAddCallback(w, XmNresizeCallback, XmLDrawnBDrawStringCB,
482 (XtPointer)dd);
483 }
484 else
485 {
486 mask = GCForeground;
487 values.foreground = b->primitive.foreground;
488 dd->gc = XtGetGC(w, mask, &values);
489 XtAddCallback(w, XmNexposeCallback, XmLDrawnBDrawCB, (XtPointer)dd);
490 XtAddCallback(w, XmNresizeCallback, XmLDrawnBDrawCB, (XtPointer)dd);
491 }
492 XtAddCallback(w, XmNdestroyCallback, XmLDrawnBDestroyCB, (XtPointer)dd);
493 }
494
495 static void
496 XmLDrawnBDestroyCB(Widget w,
497 XtPointer clientData,
498 XtPointer callData)
499 {
500 XmLDrawnBData *dd;
501
502 dd = (XmLDrawnBData *)clientData;
503 if (dd->type == XmDRAWNB_STRING)
504 {
505 if (dd->gc)
506 {
507 XFreeGC(XtDisplay(w), dd->gc);
508 XFreeFont(XtDisplay(w), dd->fontStruct);
509 }
510 }
511 else
512 XtReleaseGC(w, dd->gc);
513 free((
char *)dd);
514 }
515
516 static void
517 XmLDrawnBDrawStringCB(Widget w,
518 XtPointer clientData,
519 XtPointer callData)
520 {
521 XmLDrawnBData *dd;
522 XmRenderTable rendertable;
523 XmString str;
524 XmStringDirection stringDir;
525 unsigned char drawDir, alignment;
526 int width, height, xoff, yoff, drawWidth;
527 Pixel fg;
528 Dimension highlightThickness;
529 Dimension shadowThickness, marginWidth, marginHeight;
530 Dimension marginLeft, marginRight, marginTop, marginBottom;
531
532 if (!XtIsRealized(w))
533 return;
534 dd = (XmLDrawnBData *)clientData;
535 XtVaGetValues(w,
536 XmNlabelString, &str,
537 NULL);
538 if (!str && XtName(w))
539 str = XmStringCreateSimple(XtName(w));
540 if (!str)
541 return;
542 XtVaGetValues(w,
543 XmNforeground, &fg,
544 XmNrenderTable, &rendertable,
545 XmNalignment, &alignment,
546 XmNhighlightThickness, &highlightThickness,
547 XmNshadowThickness, &shadowThickness,
548 XmNmarginWidth, &marginWidth,
549 XmNmarginHeight, &marginHeight,
550 XmNmarginLeft, &marginLeft,
551 XmNmarginRight, &marginRight,
552 XmNmarginTop, &marginTop,
553 XmNmarginBottom, &marginBottom,
554 NULL);
555 xoff = highlightThickness + shadowThickness + marginLeft + marginWidth;
556 yoff = highlightThickness + shadowThickness + marginTop + marginHeight;
557 width = XtWidth(w) - xoff - xoff + marginLeft - marginRight;
558 height = XtHeight(w) - yoff - yoff + marginTop - marginBottom;
559 if (XmIsManager(XtParent(w)))
560 XtVaGetValues(XtParent(w),
561 XmNstringDirection, &stringDir,
562 NULL);
563 else
564 stringDir = XmSTRING_DIRECTION_L_TO_R;
565 switch (dd->dir)
566 {
567 case XmDRAWNB_LEFT:
568 drawDir = XmSTRING_LEFT;
569 break;
570 case XmDRAWNB_UP:
571 drawDir = XmSTRING_UP;
572 break;
573 case XmDRAWNB_DOWN:
574 drawDir = XmSTRING_DOWN;
575 break;
576 default:
577 drawDir = XmSTRING_RIGHT;
578 break;
579 }
580 if (drawDir == XmSTRING_LEFT || drawDir == XmSTRING_RIGHT)
581 drawWidth = width;
582 else
583 drawWidth = height;
584 if (!dd->gc)
585 {
586 dd->gc = XCreateGC(XtDisplay(w), XtWindow(w),
0,
NULL);
587 dd->fontStruct = XLoadQueryFont(XtDisplay(w),
"fixed");
588 if (!dd->fontStruct)
589 {
590 XmLWarning(w,
"DrawnBDrawString() - FATAL can''t load fixed font");
591 return;
592 }
593 XSetFont(XtDisplay(w), dd->gc, dd->fontStruct->fid);
594 }
595 XSetForeground(XtDisplay(w), dd->gc, fg);
596 XmLStringDrawDirection(XtDisplay(w), XtWindow(w), rendertable,
597 str, dd->gc, xoff, yoff, drawWidth, alignment, stringDir, drawDir);
598 XmStringFree(str);
599 }
600
601 static void
602 XmLDrawnBDrawCB(Widget w,
603 XtPointer clientData,
604 XtPointer callData)
605 {
606 XmLDrawnBData *dd;
607 XmDrawnButtonWidget b;
608
609
610 Display *dpy;
611 Window win;
612 GC gc;
613 XPoint p[
2][
5];
614 XSegment seg;
615 int np[
2];
616 int i, j, temp;
617 int md, type, dir;
618 int avgx, avgy, xoff, yoff, st;
619
620 if (!XtIsRealized(w))
621 return;
622 dd = (XmLDrawnBData *)clientData;
623 type = dd->type;
624 dir = dd->dir;
625 gc = dd->gc;
626 b = (XmDrawnButtonWidget)w;
627 win = XtWindow(w);
628 dpy = XtDisplay(w);
629 st = b->primitive.shadow_thickness;
630 i = st *
2 + b->primitive.highlight_thickness *
2;
631
632 md = XtWidth(w) - i;
633 if (md > ((
int)XtHeight(w) - i))
634 md = XtHeight(w) - i;
635 if (md <
4)
636 return;
637 xoff = ((
int)XtWidth(w) - md) /
2;
638 yoff = ((
int)XtHeight(w) - md) /
2;
639 np[
0] =
0;
640 np[
1] =
0;
641 switch (type)
642 {
643 case XmDRAWNB_SMALLARROW:
644 p[
0][
0].x = md /
4;
645 p[
0][
0].y = md /
4;
646 p[
0][
1].x = md /
4;
647 p[
0][
1].y = md - md /
4;
648 p[
0][
2].x = md - md /
4;
649 p[
0][
2].y = md /
2;
650 np[
0] =
3;
651 break;
652 case XmDRAWNB_ARROW:
653 p[
0][
0].x = md /
6;
654 p[
0][
0].y = md /
6;
655 p[
0][
1].x = md /
6;
656 p[
0][
1].y = md - md /
6;
657 p[
0][
2].x = md - md /
6;
658 p[
0][
2].y = md /
2;
659 np[
0] =
3;
660 break;
661 case XmDRAWNB_ARROWLINE:
662 p[
0][
0].x = md /
5;
663 p[
0][
0].y = md /
5;
664 p[
0][
1].x = md /
5;
665 p[
0][
1].y = md - md /
5;
666 p[
0][
2].x = md - md /
5;
667 p[
0][
2].y = md /
2;
668 np[
0] =
3;
669 p[
1][
0].x = md - md /
5 +
1;
670 p[
1][
0].y = md /
5;
671 p[
1][
1].x = md - md /
5 +
1;
672 p[
1][
1].y = md - md /
5;
673 p[
1][
2].x = md - md /
10;
674 p[
1][
2].y = md - md /
5;
675 p[
1][
3].x = md - md /
10;
676 p[
1][
3].y = md /
5;
677 np[
1] =
4;
678 break;
679 case XmDRAWNB_DOUBLEARROW:
680
681 if (md %
2)
682 md -=
1;
683 p[
0][
0].x = md /
10;
684 p[
0][
0].y = md /
10;
685 p[
0][
1].x = md /
10;
686 p[
0][
1].y = md - md /
10;
687 p[
0][
2].x = md /
2;
688 p[
0][
2].y = md /
2;
689 np[
0] =
3;
690 p[
1][
0].x = md - md /
2;
691 p[
1][
0].y = md /
10;
692 p[
1][
1].x = md - md /
2;
693 p[
1][
1].y = md - md /
10;
694 p[
1][
2].x = md - md /
10;
695 p[
1][
2].y = md /
2;
696 np[
1] =
3;
697 break;
698 case XmDRAWNB_SQUARE:
699 p[
0][
0].x = md /
3;
700 p[
0][
0].y = md /
3;
701 p[
0][
1].x = md /
3;
702 p[
0][
1].y = md - md /
3;
703 p[
0][
2].x = md - md /
3;
704 p[
0][
2].y = md - md /
3;
705 p[
0][
3].x = md - md /
3;
706 p[
0][
3].y = md /
3;
707 np[
0] =
4;
708 break;
709 case XmDRAWNB_DOUBLEBAR:
710 p[
0][
0].x = md /
3;
711 p[
0][
0].y = md /
4;
712 p[
0][
1].x = md /
3;
713 p[
0][
1].y = md - md /
4;
714 p[
0][
2].x = md /
2 - md /
10;
715 p[
0][
2].y = md - md /
4;
716 p[
0][
3].x = md /
2 - md /
10;
717 p[
0][
3].y = md /
4;
718 np[
0] =
4;
719 p[
1][
0].x = md - md /
3;
720 p[
1][
0].y = md /
4;
721 p[
1][
1].x = md - md /
3;
722 p[
1][
1].y = md - md /
4;
723 p[
1][
2].x = md - md /
2 + md /
10;
724 p[
1][
2].y = md - md /
4;
725 p[
1][
3].x = md - md /
2 + md /
10;
726 p[
1][
3].y = md /
4;
727 np[
1] =
4;
728 break;
729 }
730 for (i =
0; i <
2; i++)
731 {
732 avgx =
0;
733 avgy =
0;
734 for (j =
0; j < np[i]; j++)
735 {
736 switch (dir)
737 {
738 case XmDRAWNB_RIGHT:
739
740 break;
741 case XmDRAWNB_LEFT:
742 p[i][j].x = md - p[i][j].x -
1;
743 break;
744 case XmDRAWNB_UP:
745 temp = p[i][j].x;
746 p[i][j].x = p[i][j].y;
747 p[i][j].y = md - temp;
748 break;
749 case XmDRAWNB_DOWN:
750 temp = p[i][j].x;
751 p[i][j].x = p[i][j].y;
752 p[i][j].y = temp;
753 break;
754 }
755 p[i][j].x += xoff;
756 p[i][j].y += yoff;
757 avgx += p[i][j].x;
758 avgy += p[i][j].y;
759 }
760 if (!np[i])
761 continue;
762 avgx /= np[i];
763 avgy /= np[i];
764 XFillPolygon(dpy, win, gc, p[i], np[i], Nonconvex, CoordModeOrigin);
765 p[i][np[i]].x = p[i][
0].x;
766 p[i][np[i]].y = p[i][
0].y;
767 for (j =
0; j < np[i]; j++)
768 {
769 seg.x1 = p[i][j].x;
770 seg.y1 = p[i][j].y;
771 seg.x2 = p[i][j +
1].x;
772 seg.y2 = p[i][j +
1].y;
773 if ((seg.x1 <= avgx && seg.x2 <= avgx) ||
774 (seg.y1 <= avgy && seg.y2 <= avgy))
775 XDrawSegments(dpy, win,
776 b->primitive.bottom_shadow_GC, &seg,
1);
777 else
778 XDrawSegments(dpy, win,
779 b->primitive.top_shadow_GC, &seg,
1);
780 }
781 }
782 }
783
784 #define XmLDrawNODRAW
0
785 #define XmLDrawNOCLIP
1
786 #define XmLDrawCLIPPED
2
787
788 static int
789 XmLDrawCalc(Widget w,
790 Dimension width,
791 Dimension height,
792 unsigned char alignment,
793 XRectangle *rect,
794 XRectangle *clipRect,
795 int *x,
796 int *y)
797 {
798 if (rect->width <=
4 || rect->height <=
4 ||
799 clipRect->width <
3 || clipRect->height <
3 ||
800 !width || !height ||
801 !XtIsRealized(w) ||
802 XmLRectIntersect(rect, clipRect) == XmLRectOutside)
803 return XmLDrawNODRAW;
804 if (alignment == XmALIGNMENT_TOP_LEFT ||
805 alignment == XmALIGNMENT_LEFT ||
806 alignment == XmALIGNMENT_BOTTOM_LEFT)
807 *x = rect->x +
2;
808 else if (alignment == XmALIGNMENT_TOP ||
809 alignment == XmALIGNMENT_CENTER ||
810 alignment == XmALIGNMENT_BOTTOM)
811 *x = rect->x + ((
int)rect->width - (
int)width) /
2;
812 else
813 *x = rect->x + rect->width - width -
2;
814 if (alignment == XmALIGNMENT_TOP ||
815 alignment == XmALIGNMENT_TOP_LEFT ||
816 alignment == XmALIGNMENT_TOP_RIGHT)
817 *y = rect->y +
2;
818 else if (alignment == XmALIGNMENT_LEFT ||
819 alignment == XmALIGNMENT_CENTER ||
820 alignment == XmALIGNMENT_RIGHT)
821 *y = rect->y + ((
int)rect->height - (
int)height) /
2;
822 else
823 *y = rect->y + rect->height - height -
2;
824 if (clipRect->x == rect->x &&
825 clipRect->y == rect->y &&
826 clipRect->width == rect->width &&
827 clipRect->height == rect->height &&
828 (
int)width +
4 <= (
int)clipRect->width &&
829 (
int)height +
4 <= (
int)clipRect->height)
830 return XmLDrawNOCLIP;
831 return XmLDrawCLIPPED;
832 }
833
834 void
835 XmLDrawToggle(Widget w,
836 Boolean state,
837 Dimension size,
838 unsigned char alignment,
839 GC gc,
840 Pixel backgroundColor,
841 Pixel topColor,
842 Pixel bottomColor,
843 Pixel checkColor,
844 XRectangle *rect,
845 XRectangle *clipRect)
846 {
847 Display *dpy;
848 Window win;
849 XPoint point[
5];
850 int x, y, cx[
3], cy[
4], drawType;
851
852 drawType = XmLDrawCalc(w, size, size, alignment, rect, clipRect, &x, &y);
853 if (size <
3 || drawType == XmLDrawNODRAW)
854 return;
855 dpy = XtDisplay(w);
856 win = XtWindow(w);
857 if (drawType == XmLDrawCLIPPED)
858 XSetClipRectangles(dpy, gc,
0,
0, clipRect,
1, Unsorted);
859
860 XSetForeground(dpy, gc, backgroundColor);
861 XFillRectangle(dpy, win, gc, x, y, size, size);
862
863 XSetForeground(dpy, gc, topColor);
864 point[
0].x = x;
865 point[
0].y = y + size -
1;
866 point[
1].x = x;
867 point[
1].y = y;
868 point[
2].x = x + size -
1;
869 point[
2].y = y;
870 XDrawLines(dpy, win, gc, point,
3, CoordModeOrigin);
871 point[
1].x = x + size -
1;
872 point[
1].y = y + size -
1;
873 XSetForeground(dpy, gc, bottomColor);
874 XDrawLines(dpy, win, gc, point,
3, CoordModeOrigin);
875 if (state == True)
876 {
877
878 cx[
0] = x +
1;
879 cx[
1] = x + (((
int)size -
3) /
3) +
1;
880 cx[
2] = x + size -
2;
881 cy[
0] = y +
1;
882 cy[
1] = y + (((
int)size -
3) /
2) +
1;
883 cy[
2] = y + ((((
int)size -
3) *
2) /
3) +
1;
884 cy[
3] = y + size -
2;
885 point[
0].x = cx[
0];
886 point[
0].y = cy[
1];
887 point[
1].x = cx[
1];
888 point[
1].y = cy[
3];
889 point[
2].x = cx[
2];
890 point[
2].y = cy[
0];
891 point[
3].x = cx[
1];
892 point[
3].y = cy[
2];
893 point[
4].x = point[
0].x;
894 point[
4].y = point[
0].y;
895 XSetForeground(dpy, gc, checkColor);
896 XFillPolygon(dpy, win, gc, point,
4, Nonconvex, CoordModeOrigin);
897 XDrawLines(dpy, win, gc, point,
5, CoordModeOrigin);
898 }
899 if (drawType == XmLDrawCLIPPED)
900 XSetClipMask(dpy, gc, None);
901 }
902
903 int
904 XmLRectIntersect(XRectangle *r1,
905 XRectangle *r2)
906 {
907 if (!r1->width || !r1->height || !r2->width || !r2->height)
908 return XmLRectOutside;
909 if (r1->x + (
int)r1->width -
1 < r2->x ||
910 r1->x > r2->x + (
int)r2->width -
1 ||
911 r1->y + (
int)r1->height -
1 < r2->y ||
912 r1->y > r2->y + (
int)r2->height -
1)
913 return XmLRectOutside;
914 if (r1->x >= r2->x &&
915 r1->x + (
int)r1->width <= r2->x + (
int)r2->width &&
916 r1->y >= r2->y &&
917 r1->y + (
int)r1->height <= r2->y + (
int)r2->height)
918 return XmLRectInside;
919 return XmLRectPartial;
920 }
921
922
923 XmFontList
924 XmLFontListCopyDefault(Widget widget)
925 {
926 return XmLRenderTableCopyDefault(widget);
927 }
928
929 XmRenderTable
930 XmLRenderTableCopyDefault(Widget widget)
931 {
932 Widget parent;
933 XmRenderTable renderTable, fl;
934
935 renderTable =
0;
936 parent = XtParent(widget);
937 while (parent)
938 {
939 fl =
0;
940 if (XmIsVendorShell(parent) || XmIsMenuShell(parent))
941 XtVaGetValues(parent, XmNdefaultFontList, &fl,
NULL);
942 else if (XmIsBulletinBoard(parent))
943 XtVaGetValues(parent, XmNbuttonFontList, &fl,
NULL);
944 if (fl)
945 {
946 renderTable = XmRenderTableCopy(fl,
NULL,
0);
947 parent =
0;
948 }
949 if (parent)
950 parent = XtParent(parent);
951 }
952 if (!renderTable)
953 {
954 XmRendition rendition = XmRenditionCreate( widget,
NULL,
NULL,
0 );
955 renderTable = XmRenderTableAddRenditions(
NULL, &rendition,
1, XmMERGE_REPLACE );
956 }
957 return renderTable;
958 }
959
960
961
962 void
963 XmLFontListGetDimensions(
964 Widget w,
965 XmFontList fontList,
966 short *width,
967 short *height,
968 Boolean useAverageWidth)
969 {
970 XmLRenderTableGetDimensions(
971 w,
972 fontList,
973 width,
974 height,
975 useAverageWidth
976 );
977 }
978
979
980 static void XmLGetDimensionsOfFontstruct(
981 XFontStruct *fs,
982 short *width,
983 short *height,
984 Boolean useAverageWidth)
985 {
986 if (useAverageWidth == True) {
987 XmLFontGetAverageWidth(fs, width);
988 }
else {
989 *width = fs->max_bounds.width;
990 }
991 *height = fs->max_bounds.ascent + fs->max_bounds.descent;
992 }
993
994 void
995 XmLRenderTableGetDimensions(
996 Widget w,
997 XmRenderTable renderTable,
998 short *width,
999 short *height,
1000 Boolean useAverageWidth)
1001 {
1002 #if 0
1003 XmStringCharSet charset;
1004 XmFontContext context;
1005 XFontStruct *fs;
1006 #if XmVersion <
2000
1007
1008 typedef struct {
1009 XmFontList nextFontList;
1010 Boolean unused;
1011 } XmFontListContextRec;
1012 typedef struct {
1013 XFontStruct *font;
1014 XmStringCharSet unused;
1015 } XmFontListRec;
1016 XmFontList nextFontList;
1017 #endif
1018 #endif
1019
1020 Display *dpy = XtDisplay(w);
1021 *width =
0;
1022 *height =
0;
1023 XmStringTag* tag_list =
NULL;
1024 int tag_count = XmRenderTableGetTags( renderTable, &tag_list );
1025 int renditionIdx;
1026 XmRendition* renditions = XmRenderTableGetRenditions( renderTable, tag_list, tag_count );
1027 for ( renditionIdx =
0; renditionIdx < tag_count; renditionIdx++ ) {
1028 short w =
0, h =
0;
1029 XmRendition rendition = renditions[renditionIdx];
1030
1031 XmFontType fontType = XmFONT_IS_FONT;
1032 XtPointer font =
NULL;
1033 XftFont* xftFont =
NULL;
1034 Arg arglist[
3];
1035 int argCount =
0;
1036 XtSetArg(arglist[argCount], XmNfontType, &fontType); argCount++;
1037 XtSetArg(arglist[argCount], XmNfont, &font); argCount++;
1038 #ifdef XmNxftFont
1039 XtSetArg(arglist[argCount], XmNxftFont, &xftFont); argCount++;
1040 #endif
1041 XmRenditionRetrieve( rendition, arglist, argCount );
1042 switch(fontType)
1043 {
1044 case XmFONT_IS_FONT:
1045 {
1046 XFontStruct *fs = (XFontStruct*)(font);
1047 if ( ( fs !=
NULL ) && ( fs != (XFontStruct*)XmAS_IS ) ) {
1048 XmLGetDimensionsOfFontstruct(
1049 fs, &w, &h, useAverageWidth
1050 );
1051 }
1052 }
break;
1053 case XmFONT_IS_FONTSET:
1054 {
1055 XFontSet fontSet = (XFontSet)(font);
1056 if ( ( fontSet !=
NULL ) && ( fontSet != (XFontSet)XmAS_IS ) ) {
1057
1058 XFontSetExtents* fontsetExtents =
1059 XExtentsOfFontSet(fontSet);
1060
1061 w = fontsetExtents->max_logical_extent.width;
1062 h = fontsetExtents->max_logical_extent.height;
1063 }
1064 }
break;
1065 #if defined(XmFONT_IS_XFT) || defined(
USE_XFT)
1066 case XmFONT_IS_XFT:
1067 {
1068 if ( ( xftFont !=
NULL ) && ( xftFont != (XftFont*)XmAS_IS ) ) {
1069 w = xftFont->max_advance_width;
1070 h = xftFont->ascent + xftFont->descent;
1071
1072 if ( useAverageWidth ) {
1073
1074
1075 const char* testString =
"abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
1076 const size_t testStringLen = strlen(testString);
1077 XGlyphInfo extents;
1078 XftTextExtentsUtf8 (
1079 dpy,
1080 xftFont,
1081 (
const FcChar8*)testString,
1082 testStringLen,
1083 &extents
1084 );
1085 w = extents.xOff / testStringLen;
1086 }
1087 }
1088 }
break;
1089 #endif
1090 }
1091
1092 if (*height < h) {
1093 *height = h;
1094 }
1095 if (*width < w) {
1096 *width = w;
1097 }
1098 }
1099
1100 for ( renditionIdx =
0; renditionIdx < tag_count; renditionIdx++ ) {
1101 XtFree(tag_list[renditionIdx]);
1102 }
1103 XtFree( (XtPointer)tag_list );
1104 for ( renditionIdx =
0; renditionIdx < tag_count; renditionIdx++ ) {
1105 XmRenditionFree( renditions[renditionIdx] );
1106 }
1107 XtFree( (XtPointer)renditions );
1108 #if 0
1109 if (XmFontListInitFontContext(&context, renderTable))
1110 {
1111 while (
1)
1112 {
1113 #if XmVersion <
2000
1114
1115
1116 nextFontList = ((XmFontListContextRec *)context)->nextFontList;
1117 if (!nextFontList)
1118 break;
1119 if (!((XmFontListRec *)nextFontList)->font)
1120 break;
1121
1122 #endif
1123 if (XmFontListGetNextFont(context, &charset, &fs) == False)
1124 break;
1125 XtFree(charset);
1126 if (useAverageWidth == True)
1127 XmLFontGetAverageWidth(fs, &w);
1128 else
1129 w = fs->max_bounds.width;
1130 h = fs->max_bounds.ascent + fs->max_bounds.descent;
1131 if (*height < h)
1132 *height = h;
1133 if (*width < w)
1134 *width = w;
1135 }
1136 XmFontListFreeFontContext(context);
1137 }
1138 #endif
1139 }
1140
1141 static void
1142 XmLFontGetAverageWidth(XFontStruct *fs,
1143 short *width)
1144 {
1145 long aw, n;
1146 int r, c, mm, i;
1147 XCharStruct *cs;
1148
1149 n =
0;
1150 aw =
0;
1151 mm = fs->max_char_or_byte2 - fs->min_char_or_byte2 +
1;
1152 for (r = fs->min_byte1; r <= fs->max_byte1; r++)
1153 for (c = fs->min_char_or_byte2; c <= fs->max_char_or_byte2; c++)
1154 {
1155 if (!fs->per_char)
1156 continue;
1157 i = ((r - fs->min_byte1) * mm) + (c - fs->min_char_or_byte2);
1158 cs = &fs->per_char[i];
1159 if (!cs->width)
1160 continue;
1161 aw += cs->width;
1162 n++;
1163 }
1164 if (n)
1165 aw = aw / n;
1166 else
1167 aw = fs->min_bounds.width;
1168 *width = (
short)aw;
1169 }
1170
1171 int _XmLKey;
1172
1173 void XmLInitialize(
void)
1174 {
1175 static int first =
1;
1176
1177 if (!first)
1178 return;
1179 first =
0;
1180
1181 #ifdef XmLEVAL
1182 fprintf(stderr,
"XmL: This is an evalation version of the Microline\n");
1183 fprintf(stderr,
"XmL: Widget Library. Some features are disabled.\n");
1184 #endif
1185
1186 #ifdef XmLJAVA
1187 if (_XmLKey !=
444)
1188 {
1189 fprintf(stderr,
"XmL: Error: This version of the library will only");
1190 fprintf(stderr,
"XmL: work with JAVA.\n");
1191 exit(
0);
1192 }
1193 #endif
1194 }
1195
1196 int
1197 XmLMessageBox(Widget w,
1198 char *string,
1199 Boolean okOnly)
1200 {
1201 int status =
0;
1202 Widget dialog, shell;
1203 Arg args[
3];
1204 XtAppContext context;
1205 XmString str, titleStr;
1206 String shellTitle;
1207 Atom
WM_DELETE_WINDOW;
1208
1209 str = XmStringCreateLtoR(string, XmSTRING_DEFAULT_CHARSET);
1210 XtSetArg(args[
0], XmNmessageString, str);
1211 XtSetArg(args[
1], XmNdialogStyle, XmDIALOG_APPLICATION_MODAL);
1212 shell = XmLShellOfWidget(w);
1213 if (shell)
1214 XtVaGetValues(shell, XmNtitle, &shellTitle,
NULL);
1215 if (shell && shellTitle)
1216 titleStr = XmStringCreateLtoR(shellTitle,
1217 XmSTRING_DEFAULT_CHARSET);
1218 else
1219 titleStr = XmStringCreateSimple(
"Notice");
1220 XtSetArg(args[
2], XmNdialogTitle, titleStr);
1221 if (okOnly == True)
1222 dialog = XmCreateMessageDialog(XtParent(w),
"popup", args,
3);
1223 else
1224 dialog = XmCreateQuestionDialog(XtParent(w),
"popup", args,
3);
1225 WM_DELETE_WINDOW = XmInternAtom(XtDisplay(w),
"WM_DELETE_WINDOW",
1226 False);
1227 XmAddWMProtocolCallback(shell,
WM_DELETE_WINDOW, XmLMessageBoxWMDelete,
1228 (
caddr_t)&status);
1229 XmStringFree(str);
1230 XmStringFree(titleStr);
1231 XtAddCallback(dialog, XmNokCallback, XmLMessageBoxResponse,
1232 (XtPointer)&status);
1233 if (okOnly == True)
1234 {
1235 XtUnmanageChild(XmMessageBoxGetChild(dialog,
1236 XmDIALOG_CANCEL_BUTTON));
1237 XtUnmanageChild(XmMessageBoxGetChild(dialog,
1238 XmDIALOG_HELP_BUTTON));
1239 }
1240 else
1241 {
1242 XtAddCallback(dialog, XmNcancelCallback, XmLMessageBoxResponse,
1243 (XtPointer)&status);
1244 XtAddCallback(dialog, XmNhelpCallback, XmLMessageBoxResponse,
1245 (XtPointer)&status);
1246 }
1247 XtManageChild(dialog);
1248
1249 context = XtWidgetToApplicationContext(w);
1250 while (!status || XtAppPending(context))
1251 XtAppProcessEvent(context, XtIMAll);
1252 XtDestroyWidget(dialog);
1253 return status;
1254 }
1255
1256 static void
1257 XmLMessageBoxWMDelete(Widget w,
1258 XtPointer clientData,
1259 XtPointer callData)
1260 {
1261 int *status = (
int *)clientData;
1262 *status =
1;
1263 }
1264
1265 static void
1266 XmLMessageBoxResponse(Widget w,
1267 XtPointer clientData,
1268 XtPointer callData)
1269 {
1270 int *status = (
int *)clientData;
1271 XmAnyCallbackStruct *reason;
1272
1273 reason = (XmAnyCallbackStruct *)callData;
1274 switch (reason->reason)
1275 {
1276 case XmCR_OK:
1277 *status =
1;
1278 break;
1279 case XmCR_CANCEL:
1280 *status =
2;
1281 break;
1282 case XmCR_HELP:
1283 *status =
3;
1284 break;
1285 }
1286 }
1287
1288 void
1289 XmLPixmapDraw(Widget w,
1290 Pixmap pixmap,
1291 Pixmap pixmask,
1292 int pixmapWidth,
1293 int pixmapHeight,
1294 unsigned char alignment,
1295 GC gc,
1296 XRectangle *rect,
1297 XRectangle *clipRect)
1298 {
1299 Display *dpy;
1300 Window win;
1301 int px, py, x, y, width, height, drawType;
1302
1303 if (pixmap == XmUNSPECIFIED_PIXMAP)
1304 return;
1305 dpy = XtDisplay(w);
1306 win = XtWindow(w);
1307 width = pixmapWidth;
1308 height = pixmapHeight;
1309 if (!width || !height)
1310 {
1311 alignment = XmALIGNMENT_TOP_LEFT;
1312 width = clipRect->width -
4;
1313 height = clipRect->height -
4;
1314 }
1315 drawType = XmLDrawCalc(w, width, height, alignment,
1316 rect, clipRect, &x, &y);
1317 if (drawType == XmLDrawNODRAW)
1318 return;
1319 px =
0;
1320 py =
0;
1321
1322 if (clipRect->y > y && clipRect->y < y + height -
1)
1323 {
1324 py = clipRect->y - y;
1325 y += py;
1326 height -= py;
1327 }
1328
1329 if (clipRect->y + (
int)clipRect->height -
1 >= y &&
1330 clipRect->y + (
int)clipRect->height -
1 <= y + height -
1)
1331 height = clipRect->y + clipRect->height - y;
1332
1333 if (clipRect->x > x && clipRect->x < x + width -
1)
1334 {
1335 px = clipRect->x - x;
1336 x += px;
1337 width -= px;
1338 }
1339
1340 if (clipRect->x + (
int)clipRect->width -
1 >= x &&
1341 clipRect->x + (
int)clipRect->width -
1 <= x + width -
1)
1342 width = clipRect->x + clipRect->width - x;
1343
1344 if (pixmask != XmUNSPECIFIED_PIXMAP)
1345 {
1346 XSetClipMask(dpy, gc, pixmask);
1347 XSetClipOrigin(dpy, gc, x - px, y - py);
1348 }
1349 XSetGraphicsExposures(dpy, gc, False);
1350 XCopyArea(dpy, pixmap, win, gc, px, py, width, height, x, y);
1351 XSetGraphicsExposures(dpy, gc, True);
1352 if (pixmask != XmUNSPECIFIED_PIXMAP)
1353 {
1354 XSetClipMask(dpy, gc, None);
1355 XSetClipOrigin(dpy, gc,
0,
0);
1356 }
1357 }
1358
1359 Widget
1360 XmLShellOfWidget(Widget w)
1361 {
1362 while(
1)
1363 {
1364 if (!w)
1365 return 0;
1366 if (XtIsSubclass(w, shellWidgetClass))
1367 return w;
1368 w = XtParent(w);
1369 }
1370 }
1371
1372 static XmLSortCompareFunc XmLSortCompare;
1373 static int XmLSortEleSize;
1374 static void *XmLSortUserData;
1375
1376 void
1377 XmLSort(
void *base,
1378 int numItems,
1379 unsigned int itemSize,
1380 XmLSortCompareFunc compare,
1381 void *userData)
1382 {
1383 XmLSortCompareFunc oldCompare;
1384 int oldEleSize;
1385 void *oldUserData;
1386 char *lvec, *rvec;
1387
1388 if (numItems <
2)
1389 return;
1390
1391
1392
1393
1394 oldCompare = XmLSortCompare;
1395 oldEleSize = XmLSortEleSize;
1396 oldUserData = XmLSortUserData;
1397 XmLSortCompare = compare;
1398 XmLSortEleSize = itemSize;
1399 XmLSortUserData = userData;
1400
1401 lvec = (
char *)base;
1402 rvec = lvec + (numItems -
1) * itemSize;
1403 XmLSortFunc(lvec, rvec);
1404
1405 XmLSortCompare = oldCompare;
1406 XmLSortEleSize = oldEleSize;
1407 XmLSortUserData = oldUserData;
1408 }
1409
1410 #define SWAP(p1, p2) \
1411 { \
1412 if (p1 != p2) \
1413 { \
1414 int zi; \
1415 char zc; \
1416 for (zi =
0; zi < XmLSortEleSize; zi++) \
1417 { \
1418 zc = (p1)[zi]; \
1419 (p1)[zi] = (p2)[zi]; \
1420 (p2)[zi] = zc; \
1421 } \
1422 }\
1423 }
1424
1425 static void
1426 XmLSortFunc(
char *lvec,
1427 char *rvec)
1428 {
1429 int i;
1430 char *nlvec, *nrvec, *pvec;
1431
1432 start:
1433 i = (*XmLSortCompare)(XmLSortUserData, lvec, rvec);
1434
1435
1436 if (rvec == lvec + XmLSortEleSize)
1437 {
1438 if (i >
0)
1439 SWAP(lvec, rvec)
1440 return;
1441 }
1442
1443
1444 pvec = lvec + ((rvec - lvec) / (XmLSortEleSize *
2)) * XmLSortEleSize;
1445 if (i <
0)
1446 {
1447 i = (*XmLSortCompare)(XmLSortUserData, lvec, pvec);
1448 if (i >
0)
1449 pvec = lvec;
1450 else if (i ==
0)
1451 pvec = rvec;
1452 }
1453 else if (i >
0)
1454 {
1455 i = (*XmLSortCompare)(XmLSortUserData, rvec, pvec);
1456 if (i >
0)
1457 pvec = rvec;
1458 else if (i ==
0)
1459 pvec = lvec;
1460 }
1461 else
1462 {
1463 pvec = lvec + XmLSortEleSize;
1464 while (
1)
1465 {
1466 i = (*XmLSortCompare)(XmLSortUserData, lvec, pvec);
1467 if (i <
0)
1468 break;
1469 else if (i >
0)
1470 {
1471 pvec = lvec;
1472 break;
1473 }
1474 if (pvec == rvec)
1475 return;
1476 pvec += XmLSortEleSize;
1477 }
1478 }
1479
1480
1481 nlvec = lvec;
1482 nrvec = rvec;
1483 while (
1)
1484 {
1485 if (pvec == nrvec)
1486 pvec = nlvec;
1487 else if (pvec == nlvec)
1488 pvec = nrvec;
1489 SWAP(nrvec, nlvec)
1490 while ((*XmLSortCompare)(XmLSortUserData, nlvec, pvec) <
0)
1491 nlvec += XmLSortEleSize;
1492 while ((*XmLSortCompare)(XmLSortUserData, nrvec, pvec) >=
0)
1493 nrvec -= XmLSortEleSize;
1494 if (nlvec > nrvec)
1495 break;
1496 }
1497
1498
1499 if (lvec < nlvec - XmLSortEleSize)
1500 XmLSortFunc(lvec, nlvec - XmLSortEleSize);
1501 if (nlvec < rvec)
1502 {
1503 lvec = nlvec;
1504 goto start;
1505 }
1506 }
1507
1508 void
1509 XmLStringDraw(Widget w,
1510 XmString string,
1511 XmStringDirection stringDir,
1512 XmRenderTable renderTable,
1513 unsigned char alignment,
1514 GC gc,
1515 XRectangle *rect,
1516 XRectangle *clipRect)
1517 {
1518 Display *dpy;
1519 Window win;
1520 Dimension width, height;
1521 int x, y, drawType;
1522 unsigned char strAlignment;
1523
1524 if (!string)
1525 return;
1526 dpy = XtDisplay(w);
1527 win = XtWindow(w);
1528 XmStringExtent(renderTable, string, &width, &height);
1529 drawType = XmLDrawCalc(w, width, height, alignment,
1530 rect, clipRect, &x, &y);
1531 if (drawType == XmLDrawNODRAW)
1532 return;
1533 x = rect->x +
2;
1534 if (alignment == XmALIGNMENT_LEFT ||
1535 alignment == XmALIGNMENT_TOP_LEFT ||
1536 alignment == XmALIGNMENT_BOTTOM_LEFT)
1537 strAlignment = XmALIGNMENT_BEGINNING;
1538 else if (alignment == XmALIGNMENT_CENTER ||
1539 alignment == XmALIGNMENT_TOP ||
1540 alignment == XmALIGNMENT_BOTTOM)
1541 if (width <= rect->width -
4)
1542 strAlignment = XmALIGNMENT_CENTER;
1543 else
1544 strAlignment = XmALIGNMENT_BEGINNING;
1545 else
1546 strAlignment = XmALIGNMENT_END;
1547
1548
1549 if (drawType == XmLDrawCLIPPED)
1550 XSetClipRectangles(dpy, gc,
0,
0, clipRect,
1, Unsorted);
1551 XmStringDraw(dpy, win, renderTable, string, gc,
1552 x, y, rect->width -
4, strAlignment, stringDir, clipRect);
1553 if (drawType == XmLDrawCLIPPED)
1554 XSetClipMask(dpy, gc, None);
1555 }
1556
1557 void
1558 XmLStringDrawDirection(Display *dpy,
1559 Window win,
1560 XmRenderTable rendertable,
1561 XmString string,
1562 GC gc,
1563 int x,
1564 int y,
1565 Dimension width,
1566 unsigned char alignment,
1567 unsigned char layout_direction,
1568 unsigned char drawing_direction)
1569 {
1570 Screen *screen;
1571 XFontStruct *fontStruct;
1572 XImage *sourceImage, *destImage;
1573 Pixmap pixmap;
1574 GC pixmapGC;
1575
1576 int destWidth, destHeight;
1577 int stringWidth, stringHeight;
1578 int i, j, bytesPerLine;
1579 Dimension dW, dH;
1580 char *data;
1581
1582 screen = DefaultScreenOfDisplay(dpy);
1583 XmStringExtent(rendertable, string, &dW, &dH);
1584 stringWidth = (
int)dW;
1585 stringHeight = (
int)dH;
1586 if (!stringWidth || !stringHeight)
1587 return;
1588
1589
1590 pixmap = XCreatePixmap(dpy, win, stringWidth, stringHeight,
1);
1591 pixmapGC = XCreateGC(dpy, pixmap,
0,
NULL);
1592 fontStruct = XLoadQueryFont(dpy,
"fixed");
1593 if (!fontStruct)
1594 {
1595 fprintf(stderr,
"XmLStringDrawDirection: error - ");
1596 fprintf(stderr,
"can''t load fixed font\n");
1597 return;
1598 }
1599 XSetFont(dpy, pixmapGC, fontStruct->fid);
1600 XSetBackground(dpy, pixmapGC,
0L);
1601 XSetForeground(dpy, pixmapGC,
0L);
1602 XFillRectangle(dpy, pixmap, pixmapGC,
0,
0, stringWidth, stringHeight);
1603 XSetForeground(dpy, pixmapGC,
1L);
1604 XmStringDraw(dpy, pixmap, rendertable, string, pixmapGC,
0,
0, stringWidth,
1605 XmALIGNMENT_BEGINNING, layout_direction,
0);
1606 XFreeFont(dpy, fontStruct);
1607
1608
1609 sourceImage = XGetImage(dpy, pixmap,
0,
0, stringWidth, stringHeight,
1610 1, XYPixmap);
1611 XFreePixmap(dpy, pixmap);
1612
1613
1614 if (drawing_direction == XmSTRING_UP || drawing_direction == XmSTRING_DOWN)
1615 {
1616 destWidth = stringHeight;
1617 destHeight = stringWidth;
1618 }
1619 else
1620 {
1621 destWidth = stringWidth;
1622 destHeight = stringHeight;
1623 }
1624 bytesPerLine = (destWidth -
1) /
8 +
1;
1625 data = (
char *)malloc(bytesPerLine * destHeight);
1626 destImage = XCreateImage(dpy, DefaultVisualOfScreen(screen),
1627 1, XYBitmap,
0, data, destWidth, destHeight,
8,
0);
1628 for (i =
0; i < stringWidth; i++)
1629 for (j =
0; j < stringHeight; j++)
1630 {
1631 if (drawing_direction == XmSTRING_UP)
1632 XPutPixel(destImage, j, i,
1633 XGetPixel(sourceImage, stringWidth - i -
1, j));
1634 else if (drawing_direction == XmSTRING_DOWN)
1635 XPutPixel(destImage, stringHeight - j -
1, stringWidth - i -
1,
1636 XGetPixel(sourceImage, stringWidth - i -
1, j));
1637 else if (drawing_direction == XmSTRING_LEFT)
1638 XPutPixel(destImage, i, stringHeight - j -
1,
1639 XGetPixel(sourceImage, stringWidth - i -
1, j));
1640 else
1641 XPutPixel(destImage, i, j,
1642 XGetPixel(sourceImage, i, j));
1643 }
1644 XDestroyImage(sourceImage);
1645
1646
1647 pixmap = XCreatePixmap(dpy, win, destWidth, destHeight,
1);
1648 XPutImage(dpy, pixmap, pixmapGC, destImage,
0,
0,
0,
0,
1649 destWidth, destHeight);
1650 XDestroyImage(destImage);
1651 XFreeGC(dpy, pixmapGC);
1652
1653
1654 if (drawing_direction == XmSTRING_UP || drawing_direction == XmSTRING_DOWN)
1655 {
1656 if (alignment == XmALIGNMENT_BEGINNING)
1657 ;
1658 else if (alignment == XmALIGNMENT_CENTER)
1659 y += width /
2 - stringWidth /
2;
1660 else if (alignment == XmALIGNMENT_END)
1661 y += (
int)width - stringWidth;
1662 }
1663 else
1664 {
1665 if (alignment == XmALIGNMENT_BEGINNING)
1666 ;
1667 else if (alignment == XmALIGNMENT_CENTER)
1668 x += width /
2 - stringWidth /
2;
1669 else if (alignment == XmALIGNMENT_END)
1670 x += (
int)width - stringWidth;
1671 }
1672
1673
1674 XSetStipple(dpy, gc, pixmap);
1675 XSetFillStyle(dpy, gc, FillStippled);
1676 XSetTSOrigin(dpy, gc, x % destWidth, y % destHeight);
1677 XFillRectangle(dpy, win, gc, x, y, destWidth, destHeight);
1678 XFreePixmap(dpy, pixmap);
1679 XSetFillStyle(dpy, gc, FillSolid);
1680 }
1681
1682 void
1683 XmLWarning(Widget w,
1684 char *msg)
1685 {
1686 XtAppContext app;
1687 char s[
512], *cname, *name;
1688 WidgetClass c;
1689
1690 app = XtWidgetToApplicationContext(w);
1691 name = XtName(w);
1692 if (!name)
1693 name =
"[No Name]";
1694 c = XtClass(w);
1695 cname = c->core_class.class_name;
1696 if (!cname)
1697 cname =
"[No Class]";
1698 sprintf(s,
"%s: %s: %s\n", cname, name, msg);
1699 XtAppWarning(app, s);
1700 }
1701