Don't use -import argument as fprintf format
[nedit.git] / Microline / XmL / XmL.c
blob6ee72380617719b5b1d992fcfdac58793e3fb054
1 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
3 * ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
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/
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.
16 * The Original Code is the Microline Widget Library, originally made available under the NPL by Neuron Data <http://www.neurondata.com>.
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.
23 * Contributor(s):
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.
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.
47 * ***** END LICENSE BLOCK ***** */
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>
64 #include <stdlib.h>
65 #include <stdio.h>
67 #ifdef SUNOS4
68 int fprintf(FILE *, char *, ...);
69 #endif
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);
82 struct _XmLArrayRec
84 char _autonumber, _growFast;
85 int _count, _size;
86 void **_items;
89 XmLArray
90 XmLArrayNew(char autonumber,
91 char growFast)
93 XmLArray array;
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;
104 void
105 XmLArrayFree(XmLArray array)
107 if (array->_items)
108 free((char *)array->_items);
109 free((char *)array);
112 void
113 XmLArrayAdd(XmLArray array,
114 int pos,
115 int count)
117 int i;
118 void **items;
120 if (count < 1)
121 return;
122 if (pos < 0 || pos > array->_count)
123 pos = array->_count;
124 if (array->_count + count >= array->_size)
126 if (array->_growFast)
128 if (!array->_size)
129 array->_size = count + 256;
130 else
131 array->_size = (array->_count + count) * 2;
133 else
134 array->_size = array->_count + count;
135 items = (void **)malloc(sizeof(void *) * array->_size);
136 if (array->_items)
138 for (i = 0; i < array->_count; i++)
139 items[i] = array->_items[i];
140 free((char *)array->_items);
142 array->_items = items;
144 for (i = array->_count + count - 1; i >= pos + count; i--)
146 array->_items[i] = array->_items[i - count];
147 if (array->_autonumber)
148 ((XmLArrayItem *)array->_items[i])->pos = i;
150 for (i = pos; i < pos + count; i++)
151 array->_items[i] = 0;
152 array->_count += count;
156 XmLArrayDel(XmLArray array,
157 int pos,
158 int count)
160 int i;
162 if (pos < 0 || pos + count > array->_count)
163 return -1;
164 for (i = pos; i < array->_count - count; i++)
166 array->_items[i] = array->_items[i + count];
167 if (array->_autonumber)
168 ((XmLArrayItem *)array->_items[i])->pos = i;
170 array->_count -= count;
171 if (!array->_count)
173 if (array->_items)
174 free((char *)array->_items);
175 array->_items = 0;
176 array->_size = 0;
178 return 0;
182 XmLArraySet(XmLArray array,
183 int pos,
184 void *item)
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;
196 void *
197 XmLArrayGet(XmLArray array,
198 int pos)
200 if (pos < 0 || pos >= array->_count)
201 return 0;
202 return array->_items[pos];
206 XmLArrayGetCount(XmLArray array)
208 return array->_count;
212 XmLArrayMove(XmLArray array,
213 int newPos,
214 int pos,
215 int count)
217 void **items;
218 int i;
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--)
236 array->_items[i] = array->_items[i - count];
237 if (array->_autonumber)
238 ((XmLArrayItem *)array->_items[i])->pos = i;
240 else
241 for (i = pos; i < newPos; i++)
243 array->_items[i] = array->_items[i + count];
244 if (array->_autonumber)
245 ((XmLArrayItem *)array->_items[i])->pos = i;
247 /* move items copy back */
248 for (i = 0; i < count; i++)
250 array->_items[newPos + i] = items[i];
251 if (array->_autonumber)
252 ((XmLArrayItem *)array->_items[newPos + i])->pos = newPos + i;
254 free((char *)items);
255 return 0;
259 XmLArrayReorder(XmLArray array,
260 int *newPositions,
261 int pos,
262 int count)
264 int i;
265 void **items;
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++)
273 if (newPositions[i] < pos || newPositions[i] >= pos + count)
274 return -1;
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++)
281 array->_items[pos + i] = items[i];
282 if (array->_autonumber)
283 ((XmLArrayItem *)array->_items[pos + i])->pos = pos + i;
285 free((char *)items);
286 return 0;
290 XmLArraySort(XmLArray array,
291 XmLArrayCompareFunc compare,
292 void *userData,
293 int pos,
294 int count)
296 int i;
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;
309 Boolean
310 XmLCvtStringToUChar(Display *dpy,
311 char *resname,
312 XmLStringToUCharMap *map,
313 XrmValuePtr fromVal,
314 XrmValuePtr toVal)
316 char *from;
317 int i, /*num,*/ valid;
319 from = (char *)fromVal->addr;
320 valid = 0;
321 i = 0;
322 while (map[i].name)
324 if (!strcmp(from, map[i].name))
326 valid = 1;
327 break;
329 i++;
331 if (!valid)
333 XtDisplayStringConversionWarning(dpy, from, resname);
334 toVal->size = 0;
335 toVal->addr = 0;
336 return False;
338 if (toVal->addr)
340 if (toVal->size < sizeof(unsigned char))
342 toVal->size = sizeof(unsigned char);
343 return False;
345 *(unsigned char *)(toVal->addr) = map[i].value;
347 else
348 toVal->addr = (caddr_t)&map[i].value;
349 toVal->size = sizeof(unsigned char);
350 return True;
354 XmLDateDaysInMonth(int m,
355 int y)
357 static int d[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
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];
366 /* Calculation from Communications Of The ACM, Vol 6, No 8, p 444 */
367 /* sun is 0, sat is 6 */
369 XmLDateWeekDay(int m,
370 int d,
371 int y)
373 long jd, j1, j2;
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
382 m += 9;
383 y--;
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;
392 typedef struct
394 GC gc;
395 int type;
396 int dir;
397 XFontStruct *fontStruct;
398 } XmLDrawnBData;
400 void
401 XmLDrawnButtonSetType(Widget w,
402 int drawnType,
403 int drawnDir)
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;
416 if (!XtIsSubclass(w, xmDrawnButtonWidgetClass))
418 XmLWarning(w, "DrawnButtonSetType() - not an XmDrawnButton");
419 return;
421 XtVaSetValues(w,
422 XmNpushButtonEnabled, True,
423 NULL);
424 XtRemoveAllCallbacks(w, XmNexposeCallback);
425 XtRemoveAllCallbacks(w, XmNresizeCallback);
426 if (drawnType == XmDRAWNB_STRING && drawnDir == XmDRAWNB_RIGHT)
428 XtVaSetValues(w,
429 XmNlabelType, XmSTRING,
430 NULL);
431 return;
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)
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)
460 dim = width;
461 width = height;
462 height = dim;
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);
481 else
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);
489 XtAddCallback(w, XmNdestroyCallback, XmLDrawnBDestroyCB, (XtPointer)dd);
492 static void
493 XmLDrawnBDestroyCB(Widget w,
494 XtPointer clientData,
495 XtPointer callData)
497 XmLDrawnBData *dd;
499 dd = (XmLDrawnBData *)clientData;
500 if (dd->type == XmDRAWNB_STRING)
502 if (dd->gc)
504 XFreeGC(XtDisplay(w), dd->gc);
505 XFreeFont(XtDisplay(w), dd->fontStruct);
508 else
509 XtReleaseGC(w, dd->gc);
510 free((char *)dd);
513 static void
514 XmLDrawnBDrawStringCB(Widget w,
515 XtPointer clientData,
516 XtPointer callData)
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;
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)
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;
577 if (drawDir == XmSTRING_LEFT || drawDir == XmSTRING_RIGHT)
578 drawWidth = width;
579 else
580 drawWidth = height;
581 if (!dd->gc)
583 dd->gc = XCreateGC(XtDisplay(w), XtWindow(w), 0, NULL);
584 dd->fontStruct = XLoadQueryFont(XtDisplay(w), "fixed");
585 if (!dd->fontStruct)
587 XmLWarning(w, "DrawnBDrawString() - FATAL can't load fixed font");
588 return;
590 XSetFont(XtDisplay(w), dd->gc, dd->fontStruct->fid);
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);
598 static void
599 XmLDrawnBDrawCB(Widget w,
600 XtPointer clientData,
601 XtPointer callData)
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;
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)
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;
727 for (i = 0; i < 2; i++)
729 avgx = 0;
730 avgy = 0;
731 for (j = 0; j < np[i]; j++)
733 switch (dir)
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;
752 p[i][j].x += xoff;
753 p[i][j].y += yoff;
754 avgx += p[i][j].x;
755 avgy += p[i][j].y;
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++)
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);
781 #define XmLDrawNODRAW 0
782 #define XmLDrawNOCLIP 1
783 #define XmLDrawCLIPPED 2
785 static int
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)
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;
831 void
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)
844 Display *dpy;
845 Window win;
846 XPoint point[5];
847 int x, y, cx[3], cy[4], drawType;
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)
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);
896 if (drawType == XmLDrawCLIPPED)
897 XSetClipMask(dpy, gc, None);
901 XmLRectIntersect(XRectangle *r1,
902 XRectangle *r2)
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;
920 XmFontList
921 XmLFontListCopyDefault(Widget widget)
923 Widget parent;
924 XFontStruct *font;
925 XmFontList fontList, fl;
927 fontList = 0;
928 parent = XtParent(widget);
929 while (parent)
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)
938 fontList = XmFontListCopy(fl);
939 parent = 0;
941 if (parent)
942 parent = XtParent(parent);
944 if (!fontList)
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);
952 return fontList;
955 void
956 XmLFontListGetDimensions(XmFontList fontList,
957 short *width,
958 short *height,
959 Boolean useAverageWidth)
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
978 *width = 0;
979 *height = 0;
980 if (XmFontListInitFontContext(&context, fontList))
982 while (1)
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;
1007 XmFontListFreeFontContext(context);
1011 static void
1012 XmLFontGetAverageWidth(XFontStruct *fs,
1013 short *width)
1015 long aw, n;
1016 int r, c, mm, i;
1017 XCharStruct *cs;
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++)
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++;
1034 if (n)
1035 aw = aw / n;
1036 else
1037 aw = fs->min_bounds.width;
1038 *width = (short)aw;
1041 int _XmLKey;
1043 void XmLInitialize(void)
1045 static int first = 1;
1047 if (!first)
1048 return;
1049 first = 0;
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
1056 #ifdef XmLJAVA
1057 if (_XmLKey != 444)
1059 fprintf(stderr, "XmL: Error: This version of the library will only");
1060 fprintf(stderr, "XmL: work with JAVA.\n");
1061 exit(0);
1063 #endif
1067 XmLMessageBox(Widget w,
1068 char *string,
1069 Boolean okOnly)
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;
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)
1105 XtUnmanageChild(XmMessageBoxGetChild(dialog,
1106 XmDIALOG_CANCEL_BUTTON));
1107 XtUnmanageChild(XmMessageBoxGetChild(dialog,
1108 XmDIALOG_HELP_BUTTON));
1110 else
1112 XtAddCallback(dialog, XmNcancelCallback, XmLMessageBoxResponse,
1113 (XtPointer)&status);
1114 XtAddCallback(dialog, XmNhelpCallback, XmLMessageBoxResponse,
1115 (XtPointer)&status);
1117 XtManageChild(dialog);
1119 context = XtWidgetToApplicationContext(w);
1120 while (!status || XtAppPending(context))
1121 XtAppProcessEvent(context, XtIMAll);
1122 XtDestroyWidget(dialog);
1123 return status;
1126 static void
1127 XmLMessageBoxWMDelete(Widget w,
1128 XtPointer clientData,
1129 XtPointer callData)
1131 int *status = (int *)clientData;
1132 *status = 1;
1135 static void
1136 XmLMessageBoxResponse(Widget w,
1137 XtPointer clientData,
1138 XtPointer callData)
1140 int *status = (int *)clientData;
1141 XmAnyCallbackStruct *reason;
1143 reason = (XmAnyCallbackStruct *)callData;
1144 switch (reason->reason)
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;
1158 void
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)
1169 Display *dpy;
1170 Window win;
1171 int px, py, x, y, width, height, drawType;
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)
1181 alignment = XmALIGNMENT_TOP_LEFT;
1182 width = clipRect->width - 4;
1183 height = clipRect->height - 4;
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)
1194 py = clipRect->y - y;
1195 y += py;
1196 height -= py;
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)
1205 px = clipRect->x - x;
1206 x += px;
1207 width -= px;
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;
1214 if (pixmask != XmUNSPECIFIED_PIXMAP)
1216 XSetClipMask(dpy, gc, pixmask);
1217 XSetClipOrigin(dpy, gc, x - px, y - py);
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)
1224 XSetClipMask(dpy, gc, None);
1225 XSetClipOrigin(dpy, gc, 0, 0);
1229 Widget
1230 XmLShellOfWidget(Widget w)
1232 while(1)
1234 if (!w)
1235 return 0;
1236 if (XtIsSubclass(w, shellWidgetClass))
1237 return w;
1238 w = XtParent(w);
1242 static XmLSortCompareFunc XmLSortCompare;
1243 static int XmLSortEleSize;
1244 static void *XmLSortUserData;
1246 void
1247 XmLSort(void *base,
1248 int numItems,
1249 unsigned int itemSize,
1250 XmLSortCompareFunc compare,
1251 void *userData)
1253 XmLSortCompareFunc oldCompare;
1254 int oldEleSize;
1255 void *oldUserData;
1256 char *lvec, *rvec;
1258 if (numItems < 2)
1259 return;
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;
1271 lvec = (char *)base;
1272 rvec = lvec + (numItems - 1) * itemSize;
1273 XmLSortFunc(lvec, rvec);
1275 XmLSortCompare = oldCompare;
1276 XmLSortEleSize = oldEleSize;
1277 XmLSortUserData = oldUserData;
1280 #define SWAP(p1, p2) \
1282 if (p1 != p2) \
1284 int zi; \
1285 char zc; \
1286 for (zi = 0; zi < XmLSortEleSize; zi++) \
1288 zc = (p1)[zi]; \
1289 (p1)[zi] = (p2)[zi]; \
1290 (p2)[zi] = zc; \
1295 static void
1296 XmLSortFunc(char *lvec,
1297 char *rvec)
1299 int i;
1300 char *nlvec, *nrvec, *pvec;
1302 start:
1303 i = (*XmLSortCompare)(XmLSortUserData, lvec, rvec);
1305 /* two item sort */
1306 if (rvec == lvec + XmLSortEleSize)
1308 if (i > 0)
1309 SWAP(lvec, rvec)
1310 return;
1313 /* find mid of three items */
1314 pvec = lvec + ((rvec - lvec) / (XmLSortEleSize * 2)) * XmLSortEleSize;
1315 if (i < 0)
1317 i = (*XmLSortCompare)(XmLSortUserData, lvec, pvec);
1318 if (i > 0)
1319 pvec = lvec;
1320 else if (i == 0)
1321 pvec = rvec;
1323 else if (i > 0)
1325 i = (*XmLSortCompare)(XmLSortUserData, rvec, pvec);
1326 if (i > 0)
1327 pvec = rvec;
1328 else if (i == 0)
1329 pvec = lvec;
1331 else
1333 pvec = lvec + XmLSortEleSize;
1334 while (1)
1336 i = (*XmLSortCompare)(XmLSortUserData, lvec, pvec);
1337 if (i < 0)
1338 break;
1339 else if (i > 0)
1341 pvec = lvec;
1342 break;
1344 if (pvec == rvec)
1345 return;
1346 pvec += XmLSortEleSize;
1350 /* partition the set */
1351 nlvec = lvec;
1352 nrvec = rvec;
1353 while (1)
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;
1368 /* sort partitioned sets */
1369 if (lvec < nlvec - XmLSortEleSize)
1370 XmLSortFunc(lvec, nlvec - XmLSortEleSize);
1371 if (nlvec < rvec)
1373 lvec = nlvec;
1374 goto start;
1378 void
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)
1388 Display *dpy;
1389 Window win;
1390 Dimension width, height;
1391 int x, y, drawType;
1392 unsigned char strAlignment;
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);
1427 void
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)
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;
1452 screen = DefaultScreenOfDisplay(dpy);
1453 XmStringExtent(fontlist, string, &dW, &dH);
1454 stringWidth = (int)dW;
1455 stringHeight = (int)dH;
1456 if (!stringWidth || !stringHeight)
1457 return;
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)
1465 fprintf(stderr, "XmLStringDrawDirection: error - ");
1466 fprintf(stderr, "can't load fixed font\n");
1467 return;
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);
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);
1483 /* draw rotated text into destination image */
1484 if (drawing_direction == XmSTRING_UP || drawing_direction == XmSTRING_DOWN)
1486 destWidth = stringHeight;
1487 destHeight = stringWidth;
1489 else
1491 destWidth = stringWidth;
1492 destHeight = stringHeight;
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++)
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));
1514 XDestroyImage(sourceImage);
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);
1523 /* adjust position for alignment */
1524 if (drawing_direction == XmSTRING_UP || drawing_direction == XmSTRING_DOWN)
1526 if (alignment == XmALIGNMENT_BEGINNING)
1528 else if (alignment == XmALIGNMENT_CENTER)
1529 y += width / 2 - stringWidth / 2;
1530 else if (alignment == XmALIGNMENT_END)
1531 y += (int)width - stringWidth;
1533 else
1535 if (alignment == XmALIGNMENT_BEGINNING)
1537 else if (alignment == XmALIGNMENT_CENTER)
1538 x += width / 2 - stringWidth / 2;
1539 else if (alignment == XmALIGNMENT_END)
1540 x += (int)width - stringWidth;
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);
1552 void
1553 XmLWarning(Widget w,
1554 char *msg)
1556 XtAppContext app;
1557 char s[512], *cname, *name;
1558 WidgetClass c;
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);