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