1 /* ***********************************************************************
2 * This module implements a motif tabbed window widget.
3 * The source is copied from the Free Widget Foundation
4 * This file is divided into thse parts
5 * o - Conversion routines for the X resource manager
6 * o - Routines for drawing rotated text
7 * o - A motif widget for tabbed windows
8 * o - A driver for the above in the flavor of the xt utilities module
9 * ***********************************************************************
18 #include <Xm/RowColumn.h>
19 #include <X11/StringDefs.h>
20 #include <X11/IntrinsicP.h>
22 #include <DECW$INCLUDE/shape.h>
24 #include <X11/extensions/shape.h>
27 #include <X11/Xutil.h>
28 #include <X11/Xatom.h>
32 /* ***********************************************************************
34 * ***********************************************************************
37 /* ************************************************************************ */
40 /* Header file for the `xvertext 5.0' routines.
42 Copyright (c) 1993 Alan Richardson (mppa3@uk.ac.sussex.syma) */
45 /* ************************************************************************ */
47 #ifndef _XVERTEXT_INCLUDED_
48 #define _XVERTEXT_INCLUDED_
51 #define XV_VERSION 5.0
52 #define XV_COPYRIGHT \
53 "xvertext routines Copyright (c) 1993 Alan Richardson"
56 /* ---------------------------------------------------------------------- */
73 /* ---------------------------------------------------------------------- */
75 /* this shoulf be C++ compliant, thanks to
76 vlp@latina.inesc.pt (Vasco Lopes Paulo) */
78 #if defined(__cplusplus) || defined(c_plusplus)
81 static float XRotVersion(char*, int);
82 static void XRotSetMagnification(float);
83 static void XRotSetBoundingBoxPad(int);
84 static int XRotDrawString(Display
*, XFontStruct
*, float,
85 Drawable
, GC
, int, int, char*);
86 static int XRotDrawImageString(Display
*, XFontStruct
*, float,
87 Drawable
, GC
, int, int, char*);
88 static int XRotDrawAlignedString(Display
*, XFontStruct
*, float,
89 Drawable
, GC
, int, int, char*, int);
90 static int XRotDrawAlignedImageString(Display
*, XFontStruct
*, float,
91 Drawable
, GC
, int, int, char*, int);
92 static XPoint
*XRotTextExtents(Display
*, XFontStruct
*, float,
93 int, int, char*, int);
98 static float XRotVersion();
99 static void XRotSetMagnification();
100 static void XRotSetBoundingBoxPad();
101 static int XRotDrawString();
102 static int XRotDrawImageString();
103 static int XRotDrawAlignedString();
104 static int XRotDrawAlignedImageString();
105 static XPoint
*XRotTextExtents();
107 #endif /* __cplusplus */
109 /* ---------------------------------------------------------------------- */
112 #endif /* _XVERTEXT_INCLUDED_ */
117 /* ***********************************************************************
119 * ***********************************************************************
127 The type |StringArray| represents an array of |String|s, with the
128 proviso that by convention the last member of a |StringArray| is
129 always a |NULL| pointer. There is a converter that can construct a
130 |StringArray| from a single string.
133 cvtStringToStringArray
134 ======================
135 The converter from |String| to |StringArray| makes a copy of the
136 passed string and then replaces all occurences of the delimiter
137 with a nul byte. The |StringArray| is filled with pointers to the
140 The delimiter character is the first character in the string.
145 The function |newStringArray| makes a copy of a |StringArray|. It
146 allocates new space for the array itself and for the strings that
152 |freeStringArray| deallocates the array and all strings it
153 contains. Note that this works for StringArrays produced with
154 |newStringArray|, but not for those created by
155 |cvtStringToStringArray|!
160 typedef String
* StringArray
;
162 static Boolean
cvtStringToStringArray(
163 #if NeedFunctionPrototypes
169 XtPointer
*converter_data
174 StringArray
newStringArray(
175 #if NeedFunctionPrototypes
181 void freeStringArray(
182 #if NeedFunctionPrototypes
188 #endif /* _strarray_h_ */
191 /* ***********************************************************************
193 * ***********************************************************************
196 /* Generated by wbuild from "XmTabs.w"
197 ** (generator version $Revision: 8.4 $ of $Date: 1996/12/17 19:11:41 $)
202 XfwfUpTabs
, XfwfDownTabs
, XfwfLeftTabs
, XfwfRightTabs
,
205 #ifndef XtNorientation
206 #define XtNorientation "orientation"
208 #ifndef XtCOrientation
209 #define XtCOrientation "Orientation"
211 #ifndef XtRTabsOrientation
212 #define XtRTabsOrientation "TabsOrientation"
216 #define XtNlefttabs "lefttabs"
219 #define XtCLefttabs "Lefttabs"
226 #define XtNrighttabs "righttabs"
229 #define XtCRighttabs "Righttabs"
236 #define XtNlabels "labels"
239 #define XtCLabels "Labels"
241 #ifndef XtRStringArray
242 #define XtRStringArray "StringArray"
245 #ifndef XtNtabWidthPercentage
246 #define XtNtabWidthPercentage "tabWidthPercentage"
248 #ifndef XtCTabWidthPercentage
249 #define XtCTabWidthPercentage "TabWidthPercentage"
255 #ifndef XtNcornerwidth
256 #define XtNcornerwidth "cornerwidth"
258 #ifndef XtCCornerwidth
259 #define XtCCornerwidth "Cornerwidth"
262 #define XtRCardinal "Cardinal"
265 #ifndef XtNcornerheight
266 #define XtNcornerheight "cornerheight"
268 #ifndef XtCCornerheight
269 #define XtCCornerheight "Cornerheight"
272 #define XtRCardinal "Cardinal"
275 #ifndef XtNtextmargin
276 #define XtNtextmargin "textmargin"
278 #ifndef XtCTextmargin
279 #define XtCTextmargin "Textmargin"
286 #define XtNtabcolor "tabcolor"
289 #define XtCTabcolor "Tabcolor"
292 #define XtRPixel "Pixel"
296 #define XtNfont "font"
299 #define XtCFont "Font"
301 #ifndef XtRFontStruct
302 #define XtRFontStruct "FontStruct"
305 #ifndef XtNactivateCallback
306 #define XtNactivateCallback "activateCallback"
308 #ifndef XtCActivateCallback
309 #define XtCActivateCallback "ActivateCallback"
312 #define XtRCallback "Callback"
315 typedef struct _XmTabsClassRec
*XmTabsWidgetClass
;
316 typedef struct _XmTabsRec
*XmTabsWidget
;
317 #endif /*_XmTabs_H_*/
320 /* ***********************************************************************
322 * ***********************************************************************
325 /* Generated by wbuild from "XmTabs.w"
326 ** (generator version $Revision: 8.4 $ of $Date: 1996/12/17 19:11:41 $)
331 /* raz modified 22 Jul 96 for bluestone */
333 #if ! defined(MGR_ShadowThickness)
334 #include <Xm/ManagerP.h>
337 typedef void (*border_highlight_Proc
)(
338 #if NeedFunctionPrototypes
342 #define XtInherit_border_highlight ((border_highlight_Proc) _XtInherit)
343 typedef void (*border_unhighlight_Proc
)(
344 #if NeedFunctionPrototypes
348 #define XtInherit_border_unhighlight ((border_unhighlight_Proc) _XtInherit)
350 /* Constraint resources */
351 /* Private constraint variables */
353 } XmTabsConstraintPart
;
355 typedef struct _XmTabsConstraintRec
{
356 XmManagerConstraintPart xmManager
;
357 XmTabsConstraintPart xmTabs
;
358 } XmTabsConstraintRec
;
363 border_highlight_Proc border_highlight
;
364 border_unhighlight_Proc border_unhighlight
;
365 /* class variables */
368 typedef struct _XmTabsClassRec
{
369 CoreClassPart core_class
;
370 CompositeClassPart composite_class
;
371 ConstraintClassPart constraint_class
;
372 XmManagerClassPart xmManager_class
;
373 XmTabsClassPart xmTabs_class
;
378 TabsOrientation orientation
;
382 int tabWidthPercentage
;
383 Cardinal cornerwidth
;
384 Cardinal cornerheight
;
388 XtCallbackList activateCallback
;
399 typedef struct _XmTabsRec
{
401 CompositePart composite
;
402 ConstraintPart constraint
;
403 XmManagerPart xmManager
;
407 #endif /* _XmTabsP_H_ */
410 /* ***********************************************************************
411 * A motif widget for tabbed windows
412 * ***********************************************************************
415 static void activate(
416 #if NeedFunctionPrototypes
417 Widget
,XEvent
*,String
*,Cardinal
*
421 static XtActionsRec actionsList
[] = {
422 {"activate", activate
},
425 static char defaultTranslations
[] = "\
426 <Btn1Down>,<Btn1Up>: activate() \n\
428 static void _resolve_inheritance(
429 #if NeedFunctionPrototypes
433 static void class_initialize(
434 #if NeedFunctionPrototypes
438 static void initialize(
439 #if NeedFunctionPrototypes
440 Widget
,Widget
,ArgList
,Cardinal
*
443 static Boolean
set_values(
444 #if NeedFunctionPrototypes
445 Widget
,Widget
,Widget
,ArgList
,Cardinal
*
449 #if NeedFunctionPrototypes
450 Widget
,XtValueMask
*,XSetWindowAttributes
*
454 #if NeedFunctionPrototypes
459 #if NeedFunctionPrototypes
460 Widget
,XEvent
*,Region
463 static void border_highlight(
464 #if NeedFunctionPrototypes
468 static void border_unhighlight(
469 #if NeedFunctionPrototypes
474 #if NeedFunctionPrototypes
478 #define min(a, b) ((a )<(b )?(a ):(b ))
481 #define abs(x) ((x )<0 ?-(x ):(x ))
484 static void compute_tabsizes(
485 #if NeedFunctionPrototypes
489 static void comp_hor_tab_shape(
490 #if NeedFunctionPrototypes
491 Widget
,int ,XPoint p
[12],int *,int *,int *
494 static void comp_ver_tab_shape(
495 #if NeedFunctionPrototypes
496 Widget
,int ,XPoint p
[12],int *,int *,int *
499 static void draw_border(
500 #if NeedFunctionPrototypes
501 Widget
,XPoint poly
[12]
504 static void draw_hor_tab(
505 #if NeedFunctionPrototypes
509 static void draw_ver_tab(
510 #if NeedFunctionPrototypes
514 static void create_topgc(
515 #if NeedFunctionPrototypes
519 static void create_bottomgc(
520 #if NeedFunctionPrototypes
524 static void create_textgc(
525 #if NeedFunctionPrototypes
529 static void create_fillgc(
530 #if NeedFunctionPrototypes
534 static void create_backgc(
535 #if NeedFunctionPrototypes
540 #if NeedFunctionPrototypes
541 Widget
,int ,XrmValue
*
544 static void set_shape(
545 #if NeedFunctionPrototypes
549 #define done(type, value) do {\
550 if (to->addr != NULL) {\
551 if (to->size < sizeof(type)) {\
552 to->size = sizeof(type);\
555 *(type*)(to->addr) = (value);\
557 static type static_val;\
558 static_val = (value);\
559 to->addr = (XtPointer)&static_val;\
561 to->size = sizeof(type);\
566 static Boolean
cvtStringToTabsOrientation(
567 #if NeedFunctionPrototypes
568 Display
*,XrmValuePtr
,Cardinal
*,XrmValuePtr
,XrmValuePtr
,XtPointer
*
571 static Boolean
cvtTabsOrientationToString(
572 #if NeedFunctionPrototypes
573 Display
*,XrmValuePtr
,Cardinal
*,XrmValuePtr
,XrmValuePtr
,XtPointer
*
577 #if NeedFunctionPrototypes
578 static void compute_tabsizes(Widget self
)
580 static void compute_tabsizes(self
)Widget self
;
583 int maxwd
, basewidth
, delta
, i
, n
= ((XmTabsWidget
)self
)->xmTabs
.lefttabs
+ ((XmTabsWidget
)self
)->xmTabs
.righttabs
+ 1;
584 int sum
, len
, h
, length
, breadth
, shad
= ((XmTabsWidget
)self
)->xmManager
.shadow_thickness
;
586 if (((XmTabsWidget
)self
)->xmTabs
.offsets
) XtFree((XtPointer
) ((XmTabsWidget
)self
)->xmTabs
.offsets
);
587 if (((XmTabsWidget
)self
)->xmTabs
.tabwidths
) XtFree((XtPointer
) ((XmTabsWidget
)self
)->xmTabs
.tabwidths
);
588 ((XmTabsWidget
)self
)->xmTabs
.offsets
= (XtPointer
) XtMalloc(n
* sizeof(*((XmTabsWidget
)self
)->xmTabs
.offsets
));
589 ((XmTabsWidget
)self
)->xmTabs
.tabwidths
= (XtPointer
) XtMalloc(n
* sizeof(*((XmTabsWidget
)self
)->xmTabs
.tabwidths
));
591 if (((XmTabsWidget
)self
)->xmTabs
.orientation
== XfwfUpTabs
|| ((XmTabsWidget
)self
)->xmTabs
.orientation
== XfwfDownTabs
) {
592 length
= ((XmTabsWidget
)self
)->core
.width
;
593 breadth
= ((XmTabsWidget
)self
)->core
.height
;
595 length
= ((XmTabsWidget
)self
)->core
.height
;
596 breadth
= ((XmTabsWidget
)self
)->core
.width
;
598 if (((XmTabsWidget
)self
)->xmTabs
.tabWidthPercentage
!= 0) { /* Fixed width tabs */
599 basewidth
= ((XmTabsWidget
)self
)->xmTabs
.tabWidthPercentage
* length
/100;
600 if (n
> 1) delta
= (length
- basewidth
)/(((XmTabsWidget
)self
)->xmTabs
.lefttabs
+ ((XmTabsWidget
)self
)->xmTabs
.righttabs
);
601 for (i
= 0; i
< n
; i
++) {
602 ((XmTabsWidget
)self
)->xmTabs
.tabwidths
[i
] = basewidth
;
603 ((XmTabsWidget
)self
)->xmTabs
.offsets
[i
] = i
* delta
;
605 } else if (((XmTabsWidget
)self
)->xmTabs
.labels
== NULL
) { /* Empty tabs */
606 basewidth
= length
/n
;
607 delta
= (length
- basewidth
)/(((XmTabsWidget
)self
)->xmTabs
.lefttabs
+ ((XmTabsWidget
)self
)->xmTabs
.righttabs
);
608 for (i
= 0; i
< n
; i
++) {
609 ((XmTabsWidget
)self
)->xmTabs
.tabwidths
[i
] = basewidth
;
610 ((XmTabsWidget
)self
)->xmTabs
.offsets
[i
] = i
* delta
;
612 } else { /* Variable width tabs */
614 h
= 2 * (((XmTabsWidget
)self
)->xmTabs
.cornerwidth
+ shad
+ ((XmTabsWidget
)self
)->xmTabs
.textmargin
);
615 maxwd
= length
- n
* (shad
+ ((XmTabsWidget
)self
)->xmTabs
.textmargin
);
616 for (i
= 0; i
< n
; i
++) {
617 len
= strlen(((XmTabsWidget
)self
)->xmTabs
.labels
[i
]);
618 ((XmTabsWidget
)self
)->xmTabs
.tabwidths
[i
] = min(maxwd
, XTextWidth(((XmTabsWidget
)self
)->xmTabs
.font
,((XmTabsWidget
)self
)->xmTabs
.labels
[i
],len
) + h
);
619 sum
+= ((XmTabsWidget
)self
)->xmTabs
.tabwidths
[i
];
621 ((XmTabsWidget
)self
)->xmTabs
.offsets
[0] = 0;
623 delta
= (length
- sum
)/(n
- 1); /* Between tabs */
625 delta
= -((sum
- length
+ n
- 2)/(n
- 1)); /* Round down! */
626 for (i
= 1; i
< n
; i
++)
627 ((XmTabsWidget
)self
)->xmTabs
.offsets
[i
] = ((XmTabsWidget
)self
)->xmTabs
.offsets
[i
-1] + ((XmTabsWidget
)self
)->xmTabs
.tabwidths
[i
-1] + delta
;
631 #if NeedFunctionPrototypes
632 static void comp_hor_tab_shape(Widget self
,int i
,XPoint p
[12],int * x0
,int * x1
,int * midy
)
634 static void comp_hor_tab_shape(self
,i
,p
,x0
,x1
,midy
)Widget self
;int i
;XPoint p
[12];int * x0
;int * x1
;int * midy
;
637 int shad
= ((XmTabsWidget
)self
)->xmManager
.shadow_thickness
;
638 int k
= min(((XmTabsWidget
)self
)->xmTabs
.cornerheight
, (((XmTabsWidget
)self
)->core
.height
- shad
)/2);
640 * 4 o-------------o 5
646 * 0 o--------o o--------o 9
647 * 11 o---------------------------------------o 10
649 * 11 o---------------------------------------o 10
650 * 0 o--------o o--------o 9
656 * 4 o-------------o 5
659 p
[1].x
= ((XmTabsWidget
)self
)->xmTabs
.offsets
[i
];
660 p
[2].x
= ((XmTabsWidget
)self
)->xmTabs
.offsets
[i
] + ((XmTabsWidget
)self
)->xmTabs
.cornerwidth
;
661 p
[3].x
= ((XmTabsWidget
)self
)->xmTabs
.offsets
[i
] + ((XmTabsWidget
)self
)->xmTabs
.cornerwidth
;
662 p
[4].x
= ((XmTabsWidget
)self
)->xmTabs
.offsets
[i
] + 2 * ((XmTabsWidget
)self
)->xmTabs
.cornerwidth
;
663 p
[5].x
= ((XmTabsWidget
)self
)->xmTabs
.offsets
[i
] + ((XmTabsWidget
)self
)->xmTabs
.tabwidths
[i
] - 2 * ((XmTabsWidget
)self
)->xmTabs
.cornerwidth
;
664 p
[6].x
= ((XmTabsWidget
)self
)->xmTabs
.offsets
[i
] + ((XmTabsWidget
)self
)->xmTabs
.tabwidths
[i
] - ((XmTabsWidget
)self
)->xmTabs
.cornerwidth
;
665 p
[7].x
= ((XmTabsWidget
)self
)->xmTabs
.offsets
[i
] + ((XmTabsWidget
)self
)->xmTabs
.tabwidths
[i
] - ((XmTabsWidget
)self
)->xmTabs
.cornerwidth
;
666 p
[8].x
= ((XmTabsWidget
)self
)->xmTabs
.offsets
[i
] + ((XmTabsWidget
)self
)->xmTabs
.tabwidths
[i
];
667 p
[9].x
= ((XmTabsWidget
)self
)->core
.width
;
668 p
[10].x
= ((XmTabsWidget
)self
)->core
.width
;
671 if (((XmTabsWidget
)self
)->xmTabs
.orientation
== XfwfUpTabs
) {
672 p
[0].y
= ((XmTabsWidget
)self
)->core
.height
- shad
;
673 p
[1].y
= ((XmTabsWidget
)self
)->core
.height
- shad
;
674 p
[2].y
= ((XmTabsWidget
)self
)->core
.height
- shad
- k
;
679 p
[7].y
= ((XmTabsWidget
)self
)->core
.height
- shad
- k
;
680 p
[8].y
= ((XmTabsWidget
)self
)->core
.height
- shad
;
681 p
[9].y
= ((XmTabsWidget
)self
)->core
.height
- shad
;
682 p
[10].y
= ((XmTabsWidget
)self
)->core
.height
;
683 p
[11].y
= ((XmTabsWidget
)self
)->core
.height
;
688 p
[3].y
= ((XmTabsWidget
)self
)->core
.height
- k
;
689 p
[4].y
= ((XmTabsWidget
)self
)->core
.height
;
690 p
[5].y
= ((XmTabsWidget
)self
)->core
.height
;
691 p
[6].y
= ((XmTabsWidget
)self
)->core
.height
- k
;
700 *midy
= (p
[1].y
+ p
[4].y
)/2;
703 #if NeedFunctionPrototypes
704 static void comp_ver_tab_shape(Widget self
,int i
,XPoint p
[12],int * y0
,int * y1
,int * midx
)
706 static void comp_ver_tab_shape(self
,i
,p
,y0
,y1
,midx
)Widget self
;int i
;XPoint p
[12];int * y0
;int * y1
;int * midx
;
709 int shad
= ((XmTabsWidget
)self
)->xmManager
.shadow_thickness
;
710 int k
= min(((XmTabsWidget
)self
)->xmTabs
.cornerheight
, (((XmTabsWidget
)self
)->core
.width
- shad
)/2);
728 if (((XmTabsWidget
)self
)->xmTabs
.orientation
== XfwfLeftTabs
) {
729 p
[0].x
= ((XmTabsWidget
)self
)->core
.width
- shad
;
730 p
[1].x
= ((XmTabsWidget
)self
)->core
.width
- shad
;
731 p
[2].x
= ((XmTabsWidget
)self
)->core
.width
- shad
- k
;
736 p
[7].x
= ((XmTabsWidget
)self
)->core
.width
- shad
- k
;
737 p
[8].x
= ((XmTabsWidget
)self
)->core
.width
- shad
;
738 p
[9].x
= ((XmTabsWidget
)self
)->core
.width
- shad
;
739 p
[10].x
= ((XmTabsWidget
)self
)->core
.width
;
740 p
[11].x
= ((XmTabsWidget
)self
)->core
.width
;
745 p
[3].x
= ((XmTabsWidget
)self
)->core
.width
- k
;
746 p
[4].x
= ((XmTabsWidget
)self
)->core
.width
;
747 p
[5].x
= ((XmTabsWidget
)self
)->core
.width
;
748 p
[6].x
= ((XmTabsWidget
)self
)->core
.width
- k
;
756 p
[1].y
= ((XmTabsWidget
)self
)->xmTabs
.offsets
[i
];
757 p
[2].y
= ((XmTabsWidget
)self
)->xmTabs
.offsets
[i
] + ((XmTabsWidget
)self
)->xmTabs
.cornerwidth
;
758 p
[3].y
= ((XmTabsWidget
)self
)->xmTabs
.offsets
[i
] + ((XmTabsWidget
)self
)->xmTabs
.cornerwidth
;
759 p
[4].y
= ((XmTabsWidget
)self
)->xmTabs
.offsets
[i
] + 2 * ((XmTabsWidget
)self
)->xmTabs
.cornerwidth
;
760 p
[5].y
= ((XmTabsWidget
)self
)->xmTabs
.offsets
[i
] + ((XmTabsWidget
)self
)->xmTabs
.tabwidths
[i
] - 2 * ((XmTabsWidget
)self
)->xmTabs
.cornerwidth
;
761 p
[6].y
= ((XmTabsWidget
)self
)->xmTabs
.offsets
[i
] + ((XmTabsWidget
)self
)->xmTabs
.tabwidths
[i
] - ((XmTabsWidget
)self
)->xmTabs
.cornerwidth
;
762 p
[7].y
= ((XmTabsWidget
)self
)->xmTabs
.offsets
[i
] + ((XmTabsWidget
)self
)->xmTabs
.tabwidths
[i
] - ((XmTabsWidget
)self
)->xmTabs
.cornerwidth
;
763 p
[8].y
= ((XmTabsWidget
)self
)->xmTabs
.offsets
[i
] + ((XmTabsWidget
)self
)->xmTabs
.tabwidths
[i
];
764 p
[9].y
= ((XmTabsWidget
)self
)->core
.height
;
765 p
[10].y
= ((XmTabsWidget
)self
)->core
.height
;
769 *midx
= (p
[1].x
+ p
[4].x
)/2;
772 #if NeedFunctionPrototypes
773 static void draw_border(Widget self
,XPoint poly
[12])
775 static void draw_border(self
,poly
)Widget self
;XPoint poly
[12];
778 Display
*dpy
= XtDisplay(self
);
779 Window win
= XtWindow(self
);
781 if (((XmTabsWidget
)self
)->xmTabs
.orientation
== XfwfUpTabs
) {
782 XDrawLines(dpy
, win
, ((XmTabsWidget
)self
)->xmTabs
.topgc
, poly
, 6, CoordModeOrigin
);
783 XDrawLines(dpy
, win
, ((XmTabsWidget
)self
)->xmTabs
.bottomgc
, poly
+ 5, 4, CoordModeOrigin
);
784 XDrawLines(dpy
, win
, ((XmTabsWidget
)self
)->xmTabs
.topgc
, poly
+ 8, 2, CoordModeOrigin
);
786 XDrawLines(dpy
, win
, ((XmTabsWidget
)self
)->xmTabs
.bottomgc
, poly
, 2, CoordModeOrigin
);
787 XDrawLines(dpy
, win
, ((XmTabsWidget
)self
)->xmTabs
.topgc
, poly
+ 1, 4, CoordModeOrigin
);
788 XDrawLines(dpy
, win
, ((XmTabsWidget
)self
)->xmTabs
.bottomgc
, poly
+ 4, 6, CoordModeOrigin
);
792 #if NeedFunctionPrototypes
793 static void draw_hor_tab(Widget self
,Region region
,int i
)
795 static void draw_hor_tab(self
,region
,i
)Widget self
;Region region
;int i
;
799 Display
*dpy
= XtDisplay(self
);
800 Window win
= XtWindow(self
);
804 comp_hor_tab_shape(self
, i
, p
, &x0
, &x1
, &midy
);
805 clip
= XPolygonRegion(p
, XtNumber(p
), WindingRule
);
806 if (region
) XIntersectRegion(clip
, region
, clip
);
807 if (XEmptyRegion(clip
)) return;
809 XSetRegion(dpy
, ((XmTabsWidget
)self
)->xmTabs
.textgc
, clip
);
810 XSetRegion(dpy
, ((XmTabsWidget
)self
)->xmTabs
.topgc
, clip
);
811 XSetRegion(dpy
, ((XmTabsWidget
)self
)->xmTabs
.bottomgc
, clip
);
812 if (i
== ((XmTabsWidget
)self
)->xmTabs
.lefttabs
) {
813 XSetRegion(dpy
, ((XmTabsWidget
)self
)->xmTabs
.backgc
, clip
);
814 XFillPolygon(dpy
, win
, ((XmTabsWidget
)self
)->xmTabs
.backgc
,
815 p
, XtNumber(p
), Convex
, CoordModeOrigin
);
817 XSetRegion(dpy
, ((XmTabsWidget
)self
)->xmTabs
.fillgc
, clip
);
818 XFillPolygon(dpy
, win
, ((XmTabsWidget
)self
)->xmTabs
.fillgc
,
819 p
, XtNumber(p
), Convex
, CoordModeOrigin
);
821 if (((XmTabsWidget
)self
)->xmTabs
.labels
) {
822 int w
, y
, x
, len
= strlen(((XmTabsWidget
)self
)->xmTabs
.labels
[i
]);
823 y
= midy
- (((XmTabsWidget
)self
)->xmTabs
.font
->ascent
+ ((XmTabsWidget
)self
)->xmTabs
.font
->descent
)/2 + ((XmTabsWidget
)self
)->xmTabs
.font
->ascent
;
824 w
= XTextWidth(((XmTabsWidget
)self
)->xmTabs
.font
, ((XmTabsWidget
)self
)->xmTabs
.labels
[i
], len
);
825 if (i
== ((XmTabsWidget
)self
)->xmTabs
.lefttabs
826 || ((XmTabsWidget
)self
)->xmTabs
.tabWidthPercentage
<= 100/(((XmTabsWidget
)self
)->xmTabs
.lefttabs
+ ((XmTabsWidget
)self
)->xmTabs
.righttabs
+ 1))
827 x
= (x0
+ x1
- w
)/2; /* Centered text */
828 else if (i
< ((XmTabsWidget
)self
)->xmTabs
.lefttabs
)
829 x
= x0
+ ((XmTabsWidget
)self
)->xmTabs
.textmargin
; /* Left aligned text */
831 x
= x1
- ((XmTabsWidget
)self
)->xmTabs
.textmargin
- w
; /* Right aligned text */
832 XDrawString(dpy
, win
, ((XmTabsWidget
)self
)->xmTabs
.textgc
, x
, y
, ((XmTabsWidget
)self
)->xmTabs
.labels
[i
], len
);
834 draw_border(self
, p
);
835 XDestroyRegion(clip
);
838 #if NeedFunctionPrototypes
839 static void draw_ver_tab(Widget self
,Region region
,int i
)
841 static void draw_ver_tab(self
,region
,i
)Widget self
;Region region
;int i
;
844 Display
*dpy
= XtDisplay(self
);
845 Window win
= XtWindow(self
);
850 comp_ver_tab_shape(self
, i
, p
, &y0
, &y1
, &midx
);
851 clip
= XPolygonRegion(p
, XtNumber(p
), WindingRule
);
852 if (region
) XIntersectRegion(clip
, region
, clip
);
853 if (XEmptyRegion(clip
)) return;
855 XSetRegion(dpy
, ((XmTabsWidget
)self
)->xmTabs
.textgc
, clip
);
856 XSetRegion(dpy
, ((XmTabsWidget
)self
)->xmTabs
.topgc
, clip
);
857 XSetRegion(dpy
, ((XmTabsWidget
)self
)->xmTabs
.bottomgc
, clip
);
858 if (i
== ((XmTabsWidget
)self
)->xmTabs
.lefttabs
) {
859 XSetRegion(dpy
, ((XmTabsWidget
)self
)->xmTabs
.backgc
, clip
);
860 XFillPolygon(dpy
, win
, ((XmTabsWidget
)self
)->xmTabs
.backgc
,
861 p
, XtNumber(p
), Convex
, CoordModeOrigin
);
863 XSetRegion(dpy
, ((XmTabsWidget
)self
)->xmTabs
.fillgc
, clip
);
864 XFillPolygon(dpy
, win
, ((XmTabsWidget
)self
)->xmTabs
.fillgc
,
865 p
, XtNumber(p
), Convex
, CoordModeOrigin
);
867 if (((XmTabsWidget
)self
)->xmTabs
.labels
) {
869 float angle
= ((XmTabsWidget
)self
)->xmTabs
.orientation
== XfwfLeftTabs
? 90.0 : -90.0;
870 if (i
== ((XmTabsWidget
)self
)->xmTabs
.lefttabs
871 || ((XmTabsWidget
)self
)->xmTabs
.tabWidthPercentage
<= 100/(((XmTabsWidget
)self
)->xmTabs
.lefttabs
+ ((XmTabsWidget
)self
)->xmTabs
.righttabs
+ 1)) {
874 } else if (i
< ((XmTabsWidget
)self
)->xmTabs
.lefttabs
) {
875 y
= y0
+ ((XmTabsWidget
)self
)->xmTabs
.textmargin
;
876 align
= ((XmTabsWidget
)self
)->xmTabs
.orientation
== XfwfLeftTabs
? MRIGHT
: MLEFT
;
878 y
= y1
- ((XmTabsWidget
)self
)->xmTabs
.textmargin
;
879 align
= ((XmTabsWidget
)self
)->xmTabs
.orientation
== XfwfLeftTabs
? MLEFT
: MRIGHT
;
881 XRotDrawAlignedString
882 (dpy
, ((XmTabsWidget
)self
)->xmTabs
.font
, angle
, win
, ((XmTabsWidget
)self
)->xmTabs
.textgc
, midx
, y
, ((XmTabsWidget
)self
)->xmTabs
.labels
[i
], align
);
884 draw_border(self
, p
);
885 XDestroyRegion(clip
);
888 #if NeedFunctionPrototypes
889 static void create_topgc(Widget self
)
891 static void create_topgc(self
)Widget self
;
894 XtGCMask mask
= GCForeground
| GCLineWidth
;
897 if (((XmTabsWidget
)self
)->xmTabs
.topgc
!= NULL
) XFreeGC(XtDisplay(self
), ((XmTabsWidget
)self
)->xmTabs
.topgc
);
898 values
.foreground
= ((XmTabsWidget
)self
)->xmManager
.top_shadow_color
;
899 values
.line_width
= 2 * ((XmTabsWidget
)self
)->xmManager
.shadow_thickness
;
900 ((XmTabsWidget
)self
)->xmTabs
.topgc
= XCreateGC(XtDisplay(self
), RootWindowOfScreen(XtScreen(self
)),
904 #if NeedFunctionPrototypes
905 static void create_bottomgc(Widget self
)
907 static void create_bottomgc(self
)Widget self
;
910 XtGCMask mask
= GCForeground
| GCLineWidth
;
913 if (((XmTabsWidget
)self
)->xmTabs
.bottomgc
!= NULL
) XFreeGC(XtDisplay(self
), ((XmTabsWidget
)self
)->xmTabs
.bottomgc
);
914 values
.foreground
= ((XmTabsWidget
)self
)->xmManager
.bottom_shadow_color
;
915 values
.line_width
= 2 * ((XmTabsWidget
)self
)->xmManager
.shadow_thickness
;
916 ((XmTabsWidget
)self
)->xmTabs
.bottomgc
= XCreateGC(XtDisplay(self
), RootWindowOfScreen(XtScreen(self
)),
920 #if NeedFunctionPrototypes
921 static void create_textgc(Widget self
)
923 static void create_textgc(self
)Widget self
;
926 XtGCMask mask
= GCForeground
| GCFont
;
929 if (((XmTabsWidget
)self
)->xmTabs
.textgc
!= NULL
) XFreeGC(XtDisplay(self
), ((XmTabsWidget
)self
)->xmTabs
.textgc
);
930 values
.foreground
= ((XmTabsWidget
)self
)->xmManager
.foreground
;
931 values
.font
= ((XmTabsWidget
)self
)->xmTabs
.font
->fid
;
932 ((XmTabsWidget
)self
)->xmTabs
.textgc
= XCreateGC(XtDisplay(self
), RootWindowOfScreen(XtScreen(self
)),
936 #if NeedFunctionPrototypes
937 static void create_fillgc(Widget self
)
939 static void create_fillgc(self
)Widget self
;
942 XtGCMask mask
= GCForeground
;
945 if (((XmTabsWidget
)self
)->xmTabs
.fillgc
!= NULL
) XFreeGC(XtDisplay(self
), ((XmTabsWidget
)self
)->xmTabs
.fillgc
);
946 values
.foreground
= ((XmTabsWidget
)self
)->xmTabs
.tabcolor
;
947 ((XmTabsWidget
)self
)->xmTabs
.fillgc
= XCreateGC(XtDisplay(self
), RootWindowOfScreen(XtScreen(self
)),
951 #if NeedFunctionPrototypes
952 static void create_backgc(Widget self
)
954 static void create_backgc(self
)Widget self
;
957 XtGCMask mask
= GCForeground
;
960 if (((XmTabsWidget
)self
)->xmTabs
.backgc
!= NULL
) XFreeGC(XtDisplay(self
), ((XmTabsWidget
)self
)->xmTabs
.backgc
);
961 values
.foreground
= ((XmTabsWidget
)self
)->core
.background_pixel
;
962 ((XmTabsWidget
)self
)->xmTabs
.backgc
= XCreateGC(XtDisplay(self
), RootWindowOfScreen(XtScreen(self
)),
966 #if NeedFunctionPrototypes
967 static void copy_bg(Widget self
,int offset
,XrmValue
* value
)
969 static void copy_bg(self
,offset
,value
)Widget self
;int offset
;XrmValue
* value
;
972 value
->addr
= (XtPointer
) &((XmTabsWidget
)self
)->core
.background_pixel
;
975 #if NeedFunctionPrototypes
976 static void set_shape(Widget self
)
978 static void set_shape(self
)Widget self
;
981 int x0
, x1
, midy
, y0
, y1
, midx
, i
;
985 if (! XtIsRealized(self
)) return;
987 region
= XCreateRegion();
989 switch (((XmTabsWidget
)self
)->xmTabs
.orientation
) {
992 for (i
= 0; i
<= ((XmTabsWidget
)self
)->xmTabs
.lefttabs
+ ((XmTabsWidget
)self
)->xmTabs
.righttabs
; i
++) {
993 comp_hor_tab_shape(self
, i
, poly
, &x0
, &x1
, &midy
);
994 clip
= XPolygonRegion(poly
, XtNumber(poly
), WindingRule
);
995 XUnionRegion(region
, clip
, region
);
996 XDestroyRegion(clip
);
1001 for (i
= 0; i
<= ((XmTabsWidget
)self
)->xmTabs
.lefttabs
+ ((XmTabsWidget
)self
)->xmTabs
.righttabs
; i
++) {
1002 comp_ver_tab_shape(self
, i
, poly
, &y0
, &y1
, &midx
);
1003 clip
= XPolygonRegion(poly
, XtNumber(poly
), WindingRule
);
1004 XUnionRegion(region
, clip
, region
);
1005 XDestroyRegion(clip
);
1009 XShapeCombineRegion(XtDisplay(self
), XtWindow(self
), ShapeBounding
,
1010 0, 0, region
, ShapeSet
);
1011 XDestroyRegion(region
);
1015 #if NeedFunctionPrototypes
1016 static Boolean
cvtStringToTabsOrientation(Display
* display
,XrmValuePtr args
,Cardinal
* num_args
,XrmValuePtr from
,XrmValuePtr to
,XtPointer
* converter_data
)
1018 static Boolean
cvtStringToTabsOrientation(display
,args
,num_args
,from
,to
,converter_data
)Display
* display
;XrmValuePtr args
;Cardinal
* num_args
;XrmValuePtr from
;XrmValuePtr to
;XtPointer
* converter_data
;
1021 TabsOrientation a
= XfwfUpTabs
;
1022 char *s
= (char*) from
->addr
;
1025 TabsOrientation orient
;
1027 { "up", XfwfUpTabs
},
1028 { "uptabs", XfwfUpTabs
},
1029 { "down", XfwfDownTabs
},
1030 { "downtabs", XfwfDownTabs
},
1031 { "left", XfwfLeftTabs
},
1032 { "lefttabs", XfwfLeftTabs
},
1033 { "right", XfwfRightTabs
},
1034 { "righttabs", XfwfRightTabs
},
1040 (XtDisplayToApplicationContext(display
),
1041 "cvtStringToTabsOrientation", "wrongParameters", "XtToolkitError",
1042 "String to TabsOrientation conversion needs no arguments",
1043 (String
*) NULL
, (Cardinal
*) NULL
);
1045 for (i
=0; i
<XtNumber(strings
); i
++)
1046 if ( strcmp( s
, strings
[i
].name
) == 0 ) {
1047 a
|= strings
[i
].orient
;
1051 if ( i
>= XtNumber(strings
) )
1052 XtDisplayStringConversionWarning(display
, s
, "TabsOrientation");
1053 done(TabsOrientation
, a
);
1056 #if NeedFunctionPrototypes
1057 static Boolean
cvtTabsOrientationToString(Display
* display
,XrmValuePtr args
,Cardinal
* num_args
,XrmValuePtr from
,XrmValuePtr to
,XtPointer
* converter_data
)
1059 static Boolean
cvtTabsOrientationToString(display
,args
,num_args
,from
,to
,converter_data
)Display
* display
;XrmValuePtr args
;Cardinal
* num_args
;XrmValuePtr from
;XrmValuePtr to
;XtPointer
* converter_data
;
1062 TabsOrientation
*a
= (TabsOrientation
*) from
->addr
;
1066 (XtDisplayToApplicationContext(display
),
1067 "cvtTabsOrientationToString", "wrongParameters", "XtToolkitError",
1068 "TabsOrientation to String conversion needs no arguments",
1069 (String
*) NULL
, (Cardinal
*) NULL
);
1071 case XfwfUpTabs
: done(String
, "up");
1072 case XfwfDownTabs
: done(String
, "down");
1073 case XfwfLeftTabs
: done(String
, "left");
1074 case XfwfRightTabs
: done(String
, "right");
1077 (XtDisplayToApplicationContext(display
),
1078 "cvtTabsOrientationToString", "illParameters", "XtToolkitError",
1079 "TabsOrientation to String conversion got illegal argument",
1080 (String
*) NULL
, (Cardinal
*) NULL
);
1084 static XtResource resources
[] = {
1085 {XtNorientation
,XtCOrientation
,XtRTabsOrientation
,sizeof(((XmTabsRec
*)NULL
)->xmTabs
.orientation
),XtOffsetOf(XmTabsRec
,xmTabs
.orientation
),XtRImmediate
,(XtPointer
)XfwfUpTabs
},
1086 {XtNlefttabs
,XtCLefttabs
,XtRInt
,sizeof(((XmTabsRec
*)NULL
)->xmTabs
.lefttabs
),XtOffsetOf(XmTabsRec
,xmTabs
.lefttabs
),XtRImmediate
,(XtPointer
)0 },
1087 {XtNrighttabs
,XtCRighttabs
,XtRInt
,sizeof(((XmTabsRec
*)NULL
)->xmTabs
.righttabs
),XtOffsetOf(XmTabsRec
,xmTabs
.righttabs
),XtRImmediate
,(XtPointer
)0 },
1088 {XtNlabels
,XtCLabels
,XtRStringArray
,sizeof(((XmTabsRec
*)NULL
)->xmTabs
.labels
),XtOffsetOf(XmTabsRec
,xmTabs
.labels
),XtRImmediate
,(XtPointer
)NULL
},
1089 {XtNtabWidthPercentage
,XtCTabWidthPercentage
,XtRInt
,sizeof(((XmTabsRec
*)NULL
)->xmTabs
.tabWidthPercentage
),XtOffsetOf(XmTabsRec
,xmTabs
.tabWidthPercentage
),XtRImmediate
,(XtPointer
)50 },
1090 {XtNcornerwidth
,XtCCornerwidth
,XtRCardinal
,sizeof(((XmTabsRec
*)NULL
)->xmTabs
.cornerwidth
),XtOffsetOf(XmTabsRec
,xmTabs
.cornerwidth
),XtRImmediate
,(XtPointer
)3 },
1091 {XtNcornerheight
,XtCCornerheight
,XtRCardinal
,sizeof(((XmTabsRec
*)NULL
)->xmTabs
.cornerheight
),XtOffsetOf(XmTabsRec
,xmTabs
.cornerheight
),XtRImmediate
,(XtPointer
)3 },
1092 {XtNtextmargin
,XtCTextmargin
,XtRInt
,sizeof(((XmTabsRec
*)NULL
)->xmTabs
.textmargin
),XtOffsetOf(XmTabsRec
,xmTabs
.textmargin
),XtRImmediate
,(XtPointer
)3 },
1093 {XtNtabcolor
,XtCTabcolor
,XtRPixel
,sizeof(((XmTabsRec
*)NULL
)->xmTabs
.tabcolor
),XtOffsetOf(XmTabsRec
,xmTabs
.tabcolor
),XtRCallProc
,(XtPointer
)copy_bg
},
1094 {XtNfont
,XtCFont
,XtRFontStruct
,sizeof(((XmTabsRec
*)NULL
)->xmTabs
.font
),XtOffsetOf(XmTabsRec
,xmTabs
.font
),XtRString
,(XtPointer
)XtDefaultFont
},
1095 {XtNactivateCallback
,XtCActivateCallback
,XtRCallback
,sizeof(((XmTabsRec
*)NULL
)->xmTabs
.activateCallback
),XtOffsetOf(XmTabsRec
,xmTabs
.activateCallback
),XtRImmediate
,(XtPointer
)NULL
},
1098 XmTabsClassRec xmTabsClassRec
= {
1099 { /* core_class part */
1100 /* superclass */ (WidgetClass
) &xmManagerClassRec
,
1101 /* class_name */ "XmTabs",
1102 /* widget_size */ sizeof(XmTabsRec
),
1103 /* class_initialize */ class_initialize
,
1104 /* class_part_initialize*/ _resolve_inheritance
,
1105 /* class_inited */ FALSE
,
1106 /* initialize */ initialize
,
1107 /* initialize_hook */ NULL
,
1108 /* realize */ realize
,
1109 /* actions */ actionsList
,
1110 /* num_actions */ 1,
1111 /* resources */ resources
,
1112 /* num_resources */ 11,
1113 /* xrm_class */ NULLQUARK
,
1114 /* compres_motion */ True
,
1115 /* compress_exposure */ XtExposeCompressMultiple
,
1116 /* compress_enterleave */ True
,
1117 /* visible_interest */ False
,
1118 /* destroy */ destroy
,
1119 /* resize */ resize
,
1120 /* expose */ expose
,
1121 /* set_values */ set_values
,
1122 /* set_values_hook */ NULL
,
1123 /* set_values_almost */ XtInheritSetValuesAlmost
,
1124 /* get_values+hook */ NULL
,
1125 /* accept_focus */ XtInheritAcceptFocus
,
1126 /* version */ XtVersion
,
1127 /* callback_private */ NULL
,
1128 /* tm_table */ defaultTranslations
,
1129 /* query_geometry */ XtInheritQueryGeometry
,
1130 /* display_acceleator */ XtInheritDisplayAccelerator
,
1131 /* extension */ NULL
1133 { /* composite_class part */
1134 XtInheritGeometryManager
,
1135 XtInheritChangeManaged
,
1136 XtInheritInsertChild
,
1137 XtInheritDeleteChild
,
1140 { /* constraint_class part */
1141 /* constraint_resources */ NULL
,
1142 /* num_constraint_resources */ 0,
1143 /* constraint_size */ sizeof(XmTabsConstraintRec
),
1144 /* constraint_initialize */ NULL
,
1145 /* constraint_destroy */ NULL
,
1146 /* constraint_set_values */ NULL
,
1147 /* constraint_extension */ NULL
1149 { /* XmManager class part */
1150 #define manager_extension extension
1151 /* translations */ XtInheritTranslations
,
1152 /* syn_resources */ NULL
,
1153 /* num_syn_resources */ 0 ,
1154 /* syn_constraint_resources */ NULL
,
1155 /* num_syn_constraint_resources */ 0 ,
1156 /* parent_process */ XmInheritParentProcess
,
1157 /* manager_extension */ NULL
,
1159 { /* XmTabs_class part */
1164 WidgetClass xmTabsWidgetClass
= (WidgetClass
) &xmTabsClassRec
;
1166 static void activate(self
,event
,params
,num_params
)Widget self
;XEvent
*event
;String
*params
;Cardinal
*num_params
;
1168 int x0
, x1
, dummy
, i
, x
, y
;
1171 switch (((XmTabsWidget
)self
)->xmTabs
.orientation
) {
1174 x
= event
->xbutton
.x
;
1175 comp_hor_tab_shape(self
, ((XmTabsWidget
)self
)->xmTabs
.lefttabs
, poly
, &x0
, &x1
, &dummy
);
1176 if (x0
<= x
&& x
< x1
) {
1177 XtCallCallbackList(self
, ((XmTabsWidget
)self
)->xmTabs
.activateCallback
, (XtPointer
) 0);
1180 for (i
= -1; i
>= -((XmTabsWidget
)self
)->xmTabs
.lefttabs
; i
--) {
1181 comp_hor_tab_shape(self
, i
+ ((XmTabsWidget
)self
)->xmTabs
.lefttabs
, poly
, &x0
, &x1
, &dummy
);
1182 if (x0
<= x
&& x
< x1
) {
1183 XtCallCallbackList(self
, ((XmTabsWidget
)self
)->xmTabs
.activateCallback
, (XtPointer
) i
);
1187 for (i
= 1; i
<= ((XmTabsWidget
)self
)->xmTabs
.righttabs
; i
++) {
1188 comp_hor_tab_shape(self
, i
+ ((XmTabsWidget
)self
)->xmTabs
.lefttabs
, poly
, &x0
, &x1
, &dummy
);
1189 if (x0
<= x
&& x
< x1
) {
1190 XtCallCallbackList(self
, ((XmTabsWidget
)self
)->xmTabs
.activateCallback
, (XtPointer
) i
);
1197 y
= event
->xbutton
.y
;
1198 comp_ver_tab_shape(self
, ((XmTabsWidget
)self
)->xmTabs
.lefttabs
, poly
, &x0
, &x1
, &dummy
);
1199 if (x0
<= y
&& y
< x1
) {
1200 XtCallCallbackList(self
, ((XmTabsWidget
)self
)->xmTabs
.activateCallback
, (XtPointer
) 0);
1203 for (i
= -1; i
>= -((XmTabsWidget
)self
)->xmTabs
.lefttabs
; i
--) {
1204 comp_ver_tab_shape(self
, i
+ ((XmTabsWidget
)self
)->xmTabs
.lefttabs
, poly
, &x0
, &x1
, &dummy
);
1205 if (x0
<= y
&& y
< x1
) {
1206 XtCallCallbackList(self
, ((XmTabsWidget
)self
)->xmTabs
.activateCallback
, (XtPointer
) i
);
1210 for (i
= 1; i
<= ((XmTabsWidget
)self
)->xmTabs
.righttabs
; i
++) {
1211 comp_ver_tab_shape(self
, i
+ ((XmTabsWidget
)self
)->xmTabs
.lefttabs
, poly
, &x0
, &x1
, &dummy
);
1212 if (x0
<= y
&& y
< x1
) {
1213 XtCallCallbackList(self
, ((XmTabsWidget
)self
)->xmTabs
.activateCallback
, (XtPointer
) i
);
1221 static void _resolve_inheritance(class)
1224 XmTabsWidgetClass c
= (XmTabsWidgetClass
) class;
1225 XmTabsWidgetClass super
;
1226 static CompositeClassExtensionRec extension_rec
= {
1227 NULL
, NULLQUARK
, XtCompositeExtensionVersion
,
1228 sizeof(CompositeClassExtensionRec
), True
};
1229 CompositeClassExtensionRec
*ext
;
1230 ext
= (XtPointer
)XtMalloc(sizeof(*ext
));
1231 *ext
= extension_rec
;
1232 ext
->next_extension
= c
->composite_class
.extension
;
1233 c
->composite_class
.extension
= ext
;
1234 if (class == xmTabsWidgetClass
) return;
1235 super
= (XmTabsWidgetClass
)class->core_class
.superclass
;
1236 if (c
->xmTabs_class
.border_highlight
== XtInherit_border_highlight
)
1237 c
->xmTabs_class
.border_highlight
= super
->xmTabs_class
.border_highlight
;
1238 if (c
->xmTabs_class
.border_unhighlight
== XtInherit_border_unhighlight
)
1239 c
->xmTabs_class
.border_unhighlight
= super
->xmTabs_class
.border_unhighlight
;
1242 #if NeedFunctionPrototypes
1243 static void class_initialize(void)
1245 static void class_initialize()
1248 XtSetTypeConverter(XtRString
, "StringArray",
1249 cvtStringToStringArray
,
1250 NULL
, 0, XtCacheNone
, NULL
);
1251 XtSetTypeConverter(XtRString
, "TabsOrientation",
1252 cvtStringToTabsOrientation
,
1253 NULL
, 0, XtCacheNone
, NULL
);
1254 XtSetTypeConverter("TabsOrientation", XtRString
,
1255 cvtTabsOrientationToString
,
1256 NULL
, 0, XtCacheNone
, NULL
);
1259 #if NeedFunctionPrototypes
1260 static void initialize(Widget request
,Widget self
,ArgList args
,Cardinal
* num_args
)
1262 static void initialize(request
,self
,args
,num_args
)Widget request
;Widget self
;ArgList args
;Cardinal
* num_args
;
1268 ((XmTabsWidget
)self
)->xmManager
.traversal_on
= FALSE
;
1269 ((XmTabsWidget
)self
)->xmTabs
.topgc
= NULL
;
1271 ((XmTabsWidget
)self
)->xmTabs
.bottomgc
= NULL
;
1272 create_bottomgc(self
);
1273 ((XmTabsWidget
)self
)->xmTabs
.textgc
= NULL
;
1274 create_textgc(self
);
1275 ((XmTabsWidget
)self
)->xmTabs
.fillgc
= NULL
;
1276 create_fillgc(self
);
1277 ((XmTabsWidget
)self
)->xmTabs
.backgc
= NULL
;
1278 create_backgc(self
);
1279 if (((XmTabsWidget
)self
)->xmTabs
.labels
) {
1280 h
= (String
*) XtMalloc((((XmTabsWidget
)self
)->xmTabs
.lefttabs
+ ((XmTabsWidget
)self
)->xmTabs
.righttabs
+ 1) * sizeof(*h
));
1281 for (i
= ((XmTabsWidget
)self
)->xmTabs
.lefttabs
+ ((XmTabsWidget
)self
)->xmTabs
.righttabs
; i
>= 0; i
--)
1282 h
[i
] = XtNewString(((XmTabsWidget
)self
)->xmTabs
.labels
[i
]);
1283 ((XmTabsWidget
)self
)->xmTabs
.labels
= h
;
1285 if (((XmTabsWidget
)self
)->xmTabs
.tabWidthPercentage
< 0 || ((XmTabsWidget
)self
)->xmTabs
.tabWidthPercentage
> 100) {
1286 XtAppWarning(XtWidgetToApplicationContext(self
),
1287 "tabWidthPercentage out of range; reset to 50");
1288 ((XmTabsWidget
)self
)->xmTabs
.tabWidthPercentage
= 50;
1290 ((XmTabsWidget
)self
)->xmTabs
.offsets
= NULL
;
1291 ((XmTabsWidget
)self
)->xmTabs
.tabwidths
= NULL
;
1292 compute_tabsizes(self
);
1295 #if NeedFunctionPrototypes
1296 static Boolean
set_values(Widget old
,Widget request
,Widget self
,ArgList args
,Cardinal
* num_args
)
1298 static Boolean
set_values(old
,request
,self
,args
,num_args
)Widget old
;Widget request
;Widget self
;ArgList args
;Cardinal
* num_args
;
1301 Bool redraw
= FALSE
, resize_labels
= FALSE
;
1305 if (((XmTabsWidget
)self
)->core
.background_pixel
!= ((XmTabsWidget
)old
)->core
.background_pixel
1306 || ((XmTabsWidget
)self
)->core
.background_pixmap
!= ((XmTabsWidget
)old
)->core
.background_pixmap
1307 || ((XmTabsWidget
)self
)->xmManager
.shadow_thickness
!= ((XmTabsWidget
)old
)->xmManager
.shadow_thickness
) {
1309 create_bottomgc(self
);
1310 create_backgc(self
);
1312 if (((XmTabsWidget
)self
)->xmManager
.foreground
!= ((XmTabsWidget
)old
)->xmManager
.foreground
|| ((XmTabsWidget
)self
)->xmTabs
.font
!= ((XmTabsWidget
)old
)->xmTabs
.font
) {
1313 create_textgc(self
);
1316 if (((XmTabsWidget
)self
)->xmTabs
.tabcolor
!= ((XmTabsWidget
)old
)->xmTabs
.tabcolor
) {
1317 create_fillgc(self
);
1320 if ((((XmTabsWidget
)self
)->xmTabs
.textmargin
!= ((XmTabsWidget
)old
)->xmTabs
.textmargin
&& ((XmTabsWidget
)self
)->xmTabs
.tabWidthPercentage
== 0)
1321 || ((XmTabsWidget
)self
)->xmTabs
.cornerwidth
!= ((XmTabsWidget
)old
)->xmTabs
.cornerwidth
1322 || ((XmTabsWidget
)self
)->xmTabs
.cornerheight
!= ((XmTabsWidget
)old
)->xmTabs
.cornerheight
) {
1323 resize_labels
= TRUE
;
1325 if (((XmTabsWidget
)self
)->xmTabs
.labels
!= ((XmTabsWidget
)old
)->xmTabs
.labels
) {
1326 if (((XmTabsWidget
)self
)->xmTabs
.labels
) {
1327 h
= (String
*) XtMalloc((((XmTabsWidget
)self
)->xmTabs
.lefttabs
+ ((XmTabsWidget
)self
)->xmTabs
.righttabs
+ 1) * sizeof(*h
));
1328 for (i
= ((XmTabsWidget
)self
)->xmTabs
.lefttabs
+ ((XmTabsWidget
)self
)->xmTabs
.righttabs
; i
>= 0; i
--)
1329 h
[i
] = XtNewString(((XmTabsWidget
)self
)->xmTabs
.labels
[i
]);
1330 ((XmTabsWidget
)self
)->xmTabs
.labels
= h
;
1332 if (((XmTabsWidget
)old
)->xmTabs
.labels
) {
1333 for (i
= ((XmTabsWidget
)old
)->xmTabs
.lefttabs
+ ((XmTabsWidget
)old
)->xmTabs
.righttabs
; i
>= 0; i
--)
1334 XtFree(((XmTabsWidget
)old
)->xmTabs
.labels
[i
]);
1335 XtFree((XtPointer
) ((XmTabsWidget
)old
)->xmTabs
.labels
);
1337 resize_labels
= TRUE
;
1339 if (((XmTabsWidget
)self
)->xmTabs
.tabWidthPercentage
< 0 || ((XmTabsWidget
)self
)->xmTabs
.tabWidthPercentage
> 100) {
1340 XtAppWarning(XtWidgetToApplicationContext(self
),
1341 "tabWidthPercentage out of range; reset to 50");
1342 ((XmTabsWidget
)self
)->xmTabs
.tabWidthPercentage
= 50;
1344 if (((XmTabsWidget
)old
)->xmTabs
.tabWidthPercentage
!= ((XmTabsWidget
)self
)->xmTabs
.tabWidthPercentage
)
1345 resize_labels
= TRUE
;
1346 if (((XmTabsWidget
)self
)->xmTabs
.lefttabs
!= ((XmTabsWidget
)old
)->xmTabs
.lefttabs
|| ((XmTabsWidget
)self
)->xmTabs
.righttabs
!= ((XmTabsWidget
)old
)->xmTabs
.righttabs
)
1348 if (resize_labels
) {
1349 compute_tabsizes(self
);
1355 #if NeedFunctionPrototypes
1356 static void realize(Widget self
,XtValueMask
* mask
,XSetWindowAttributes
* attributes
)
1358 static void realize(self
,mask
,attributes
)Widget self
;XtValueMask
* mask
;XSetWindowAttributes
* attributes
;
1361 *mask
|= CWBitGravity
;
1362 attributes
->bit_gravity
= ForgetGravity
;
1363 xmManagerClassRec
.core_class
.realize(self
, mask
, attributes
);
1367 #if NeedFunctionPrototypes
1368 static void resize(Widget self
)
1370 static void resize(self
)Widget self
;
1373 if (XtIsRealized(self
))
1374 XClearArea(XtDisplay(self
), XtWindow(self
), 0, 0, 0, 0, True
);
1375 compute_tabsizes(self
);
1377 if ( xmManagerClassRec
.core_class
.resize
) xmManagerClassRec
.core_class
.resize(self
);
1380 #if NeedFunctionPrototypes
1381 static void expose(Widget self
,XEvent
* event
,Region region
)
1383 static void expose(self
,event
,region
)Widget self
;XEvent
* event
;Region region
;
1388 if (! XtIsRealized(self
)) return;
1390 switch (((XmTabsWidget
)self
)->xmTabs
.orientation
) {
1393 for (i
= 0; i
< ((XmTabsWidget
)self
)->xmTabs
.lefttabs
; i
++)
1394 draw_hor_tab(self
, region
, i
);
1395 for (i
= ((XmTabsWidget
)self
)->xmTabs
.lefttabs
+ ((XmTabsWidget
)self
)->xmTabs
.righttabs
; i
> ((XmTabsWidget
)self
)->xmTabs
.lefttabs
; i
--)
1396 draw_hor_tab(self
, region
, i
);
1397 draw_hor_tab(self
, region
, ((XmTabsWidget
)self
)->xmTabs
.lefttabs
);
1401 for (i
= 0; i
< ((XmTabsWidget
)self
)->xmTabs
.lefttabs
; i
++)
1402 draw_ver_tab(self
, region
, i
);
1403 for (i
= ((XmTabsWidget
)self
)->xmTabs
.lefttabs
+ ((XmTabsWidget
)self
)->xmTabs
.righttabs
; i
> ((XmTabsWidget
)self
)->xmTabs
.lefttabs
; i
--)
1404 draw_ver_tab(self
, region
, i
);
1405 draw_ver_tab(self
, region
, ((XmTabsWidget
)self
)->xmTabs
.lefttabs
);
1408 /* Focus highlight? */
1411 #if NeedFunctionPrototypes
1412 static void border_highlight(void)
1414 static void border_highlight()
1419 #if NeedFunctionPrototypes
1420 static void border_unhighlight(void)
1422 static void border_unhighlight()
1427 #if NeedFunctionPrototypes
1428 static void destroy(Widget self
)
1430 static void destroy(self
)Widget self
;
1435 if (((XmTabsWidget
)self
)->xmTabs
.labels
) {
1436 for (i
= ((XmTabsWidget
)self
)->xmTabs
.lefttabs
+ ((XmTabsWidget
)self
)->xmTabs
.righttabs
; i
>= 0; i
--)
1437 XtFree(((XmTabsWidget
)self
)->xmTabs
.labels
[i
]);
1438 XtFree((XtPointer
) ((XmTabsWidget
)self
)->xmTabs
.labels
);
1440 if (((XmTabsWidget
)self
)->xmTabs
.offsets
)
1441 XtFree((XtPointer
) ((XmTabsWidget
)self
)->xmTabs
.offsets
);
1442 if (((XmTabsWidget
)self
)->xmTabs
.tabwidths
)
1443 XtFree((XtPointer
) ((XmTabsWidget
)self
)->xmTabs
.tabwidths
);
1447 /* ***********************************************************************
1448 * Routines for drawing rotated text
1449 * ***********************************************************************
1452 /* xvertext 5.0, Copyright (c) 1993 Alan Richardson (mppa3@uk.ac.sussex.syma)
1454 * Permission to use, copy, modify, and distribute this software and its
1455 * documentation for any purpose and without fee is hereby granted, provided
1456 * that the above copyright notice appear in all copies and that both the
1457 * copyright notice and this permission notice appear in supporting
1458 * documentation. All work developed as a consequence of the use of
1459 * this program should duly acknowledge such use. No representations are
1460 * made about the suitability of this software for any purpose. It is
1461 * provided "as is" without express or implied warranty.
1463 * 8 Jun '95: [Bert Bos] added GCClipXOrigin|GCClipYOrigin|GCClipMask
1464 * when calling XCopyGC()
1467 /* ********************************************************************** */
1470 /* BETTER: xvertext now does rotation at any angle!!
1472 * BEWARE: function arguments have CHANGED since version 2.0!!
1475 /* ********************************************************************** */
1479 /* ---------------------------------------------------------------------- */
1482 /* Make sure cache size is set */
1484 #ifndef CACHE_SIZE_LIMIT
1485 #define CACHE_SIZE_LIMIT 0
1486 #endif /*CACHE_SIZE_LIMIT */
1488 /* Make sure a cache method is specified */
1490 #ifndef CACHE_XIMAGES
1491 #ifndef CACHE_BITMAPS
1492 #define CACHE_BITMAPS
1493 #endif /*CACHE_BITMAPS*/
1494 #endif /*CACHE_XIMAGES*/
1497 /* ---------------------------------------------------------------------- */
1500 /* Debugging macros */
1508 #define DEBUG_PRINT1(a) if (debug) printf (a)
1509 #define DEBUG_PRINT2(a, b) if (debug) printf (a, b)
1510 #define DEBUG_PRINT3(a, b, c) if (debug) printf (a, b, c)
1511 #define DEBUG_PRINT4(a, b, c, d) if (debug) printf (a, b, c, d)
1512 #define DEBUG_PRINT5(a, b, c, d, e) if (debug) printf (a, b, c, d, e)
1515 /* ---------------------------------------------------------------------- */
1519 #define M_PI 3.14159265358979323846
1523 /* ---------------------------------------------------------------------- */
1526 /* A structure holding everything needed for a rotated string */
1528 typedef struct rotated_text_item_template
{
1552 struct rotated_text_item_template
*next
;
1555 RotatedTextItem
*first_text_item
=NULL
;
1558 /* ---------------------------------------------------------------------- */
1561 /* A structure holding current magnification and bounding box padding */
1563 static struct style_template
{
1572 /* ---------------------------------------------------------------------- */
1575 static char *my_strdup();
1576 static char *my_strtok();
1578 static float XRotVersion();
1579 static void XRotSetMagnification();
1580 static void XRotSetBoundingBoxPad();
1581 static int XRotDrawString();
1582 static int XRotDrawImageString();
1583 static int XRotDrawAlignedString();
1584 static int XRotDrawAlignedImageString();
1585 static XPoint
*XRotTextExtents();
1587 static XImage
*MakeXImage();
1588 static int XRotPaintAlignedString();
1589 static int XRotDrawHorizontalString();
1590 static RotatedTextItem
*XRotRetrieveFromCache();
1591 static RotatedTextItem
*XRotCreateTextItem();
1592 static void XRotAddToLinkedList();
1593 static void XRotFreeTextItem();
1594 static XImage
*XRotMagnifyImage();
1597 /* ---------------------------------------------------------------------- */
1600 /**************************************************************************/
1601 /* Routine to mimic `strdup()' (some machines don't have it) */
1602 /**************************************************************************/
1604 static char *my_strdup(str
)
1612 s
=(char *)malloc((unsigned)(strlen(str
)+1));
1620 /* ---------------------------------------------------------------------- */
1623 /**************************************************************************/
1624 /* Routine to replace `strtok' : this one returns a zero length string if */
1625 /* it encounters two consecutive delimiters */
1626 /**************************************************************************/
1628 static char *my_strtok(str1
, str2
)
1633 static int start
, len
;
1639 /* initialise if str1 not NULL */
1646 /* run out of tokens ? */
1650 /* loop through characters */
1651 for(i
=start
; i
<len
; i
++) {
1652 /* loop through delimiters */
1654 for(j
=0; j
<strlen(str2
); j
++)
1655 if(stext
[i
]==str2
[j
])
1672 /* ---------------------------------------------------------------------- */
1675 /**************************************************************************/
1676 /* Return version/copyright information */
1677 /**************************************************************************/
1679 float XRotVersion(str
, n
)
1684 strncpy(str
, XV_COPYRIGHT
, n
);
1689 /* ---------------------------------------------------------------------- */
1692 /**************************************************************************/
1693 /* Set the font magnification factor for all subsequent operations */
1694 /**************************************************************************/
1696 void XRotSetMagnification(m
)
1704 /* ---------------------------------------------------------------------- */
1707 /**************************************************************************/
1708 /* Set the padding used when calculating bounding boxes */
1709 /**************************************************************************/
1711 void XRotSetBoundingBoxPad(p
)
1719 /* ---------------------------------------------------------------------- */
1722 /**************************************************************************/
1723 /* Create an XImage structure and allocate memory for it */
1724 /**************************************************************************/
1726 static XImage
*MakeXImage(dpy
, w
, h
)
1733 /* reserve memory for image */
1734 data
=(char *)calloc((unsigned)(((w
-1)/8+1)*h
), 1);
1738 /* create the XImage */
1739 I
=XCreateImage(dpy
, DefaultVisual(dpy
, DefaultScreen(dpy
)), 1, XYBitmap
,
1740 0, data
, w
, h
, 8, 0);
1744 I
->byte_order
=I
->bitmap_bit_order
=MSBFirst
;
1749 /* ---------------------------------------------------------------------- */
1752 /**************************************************************************/
1753 /* A front end to XRotPaintAlignedString: */
1754 /* -no alignment, no background */
1755 /**************************************************************************/
1757 int XRotDrawString(dpy
, font
, angle
, drawable
, gc
, x
, y
, str
)
1766 return (XRotPaintAlignedString(dpy
, font
, angle
, drawable
, gc
,
1767 x
, y
, str
, NONE
, 0));
1771 /* ---------------------------------------------------------------------- */
1774 /**************************************************************************/
1775 /* A front end to XRotPaintAlignedString: */
1776 /* -no alignment, paints background */
1777 /**************************************************************************/
1779 int XRotDrawImageString(dpy
, font
, angle
, drawable
, gc
, x
, y
, str
)
1788 return(XRotPaintAlignedString(dpy
, font
, angle
, drawable
, gc
,
1789 x
, y
, str
, NONE
, 1));
1793 /* ---------------------------------------------------------------------- */
1796 /**************************************************************************/
1797 /* A front end to XRotPaintAlignedString: */
1798 /* -does alignment, no background */
1799 /**************************************************************************/
1801 int XRotDrawAlignedString(dpy
, font
, angle
, drawable
, gc
, x
, y
, text
, align
)
1811 return(XRotPaintAlignedString(dpy
, font
, angle
, drawable
, gc
,
1812 x
, y
, text
, align
, 0));
1816 /* ---------------------------------------------------------------------- */
1819 /**************************************************************************/
1820 /* A front end to XRotPaintAlignedString: */
1821 /* -does alignment, paints background */
1822 /**************************************************************************/
1824 int XRotDrawAlignedImageString(dpy
, font
, angle
, drawable
, gc
, x
, y
, text
,
1835 return(XRotPaintAlignedString(dpy
, font
, angle
, drawable
, gc
,
1836 x
, y
, text
, align
, 1));
1840 /* ---------------------------------------------------------------------- */
1843 /**************************************************************************/
1844 /* Aligns and paints a rotated string */
1845 /**************************************************************************/
1847 static int XRotPaintAlignedString(dpy
, font
, angle
, drawable
, gc
, x
, y
, text
,
1863 float hot_xp
, hot_yp
;
1864 float sin_angle
, cos_angle
;
1865 RotatedTextItem
*item
;
1866 Pixmap bitmap_to_paint
;
1868 /* return early for NULL/empty strings */
1875 /* manipulate angle to 0<=angle<360 degrees */
1884 /* horizontal text made easy */
1885 if(angle
==0. && style
.magnify
==1.)
1886 return(XRotDrawHorizontalString(dpy
, font
, drawable
, gc
, x
, y
,
1889 /* get a rotated bitmap */
1890 item
=XRotRetrieveFromCache(dpy
, font
, angle
, text
, align
);
1894 /* this gc has similar properties to the user's gc */
1895 my_gc
=XCreateGC(dpy
, drawable
, NULL
, 0);
1896 XCopyGC(dpy
, gc
, GCForeground
|GCBackground
|GCFunction
|GCPlaneMask
1897 |GCClipXOrigin
|GCClipYOrigin
|GCClipMask
, my_gc
);
1899 /* alignment : which point (hot_x, hot_y) relative to bitmap centre
1900 coincides with user's specified point? */
1903 if(align
==TLEFT
|| align
==TCENTRE
|| align
==TRIGHT
)
1904 hot_y
=(float)item
->rows_in
/2*style
.magnify
;
1905 else if(align
==MLEFT
|| align
==MCENTRE
|| align
==MRIGHT
)
1907 else if(align
==BLEFT
|| align
==BCENTRE
|| align
==BRIGHT
)
1908 hot_y
= -(float)item
->rows_in
/2*style
.magnify
;
1910 hot_y
= -((float)item
->rows_in
/2-(float)font
->descent
)*style
.magnify
;
1913 if(align
==TLEFT
|| align
==MLEFT
|| align
==BLEFT
|| align
==NONE
)
1914 hot_x
= -(float)item
->max_width
/2*style
.magnify
;
1915 else if(align
==TCENTRE
|| align
==MCENTRE
|| align
==BCENTRE
)
1918 hot_x
=(float)item
->max_width
/2*style
.magnify
;
1920 /* pre-calculate sin and cos */
1921 sin_angle
=sin(angle
);
1922 cos_angle
=cos(angle
);
1924 /* rotate hot_x and hot_y around bitmap centre */
1925 hot_xp
= hot_x
*cos_angle
- hot_y
*sin_angle
;
1926 hot_yp
= hot_x
*sin_angle
+ hot_y
*cos_angle
;
1928 /* text background will be drawn using XFillPolygon */
1932 Pixmap empty_stipple
;
1934 /* reserve space for XPoints */
1935 xpoints
=(XPoint
*)malloc((unsigned)(4*item
->nl
*sizeof(XPoint
)));
1939 /* rotate corner positions */
1940 for(i
=0; i
<4*item
->nl
; i
++) {
1941 xpoints
[i
].x
=(float)x
+ ( (item
->corners_x
[i
]-hot_x
)*cos_angle
+
1942 (item
->corners_y
[i
]+hot_y
)*sin_angle
);
1943 xpoints
[i
].y
=(float)y
+ (-(item
->corners_x
[i
]-hot_x
)*sin_angle
+
1944 (item
->corners_y
[i
]+hot_y
)*cos_angle
);
1947 /* we want to swap foreground and background colors here;
1948 XGetGCValues() is only available in R4+ */
1950 empty_stipple
=XCreatePixmap(dpy
, drawable
, 1, 1, 1);
1952 depth_one_gc
=XCreateGC(dpy
, empty_stipple
, NULL
, 0);
1953 XSetForeground(dpy
, depth_one_gc
, 0);
1954 XFillRectangle(dpy
, empty_stipple
, depth_one_gc
, 0, 0, 2, 2);
1956 XSetStipple(dpy
, my_gc
, empty_stipple
);
1957 XSetFillStyle(dpy
, my_gc
, FillOpaqueStippled
);
1959 XFillPolygon(dpy
, drawable
, my_gc
, xpoints
, 4*item
->nl
, Nonconvex
,
1962 /* free our resources */
1963 free((char *)xpoints
);
1964 XFreeGC(dpy
, depth_one_gc
);
1965 XFreePixmap(dpy
, empty_stipple
);
1968 /* where should top left corner of bitmap go ? */
1969 xp
=(float)x
-((float)item
->cols_out
/2 +hot_xp
);
1970 yp
=(float)y
-((float)item
->rows_out
/2 -hot_yp
);
1972 /* by default we draw the rotated bitmap, solid */
1973 bitmap_to_paint
=item
->bitmap
;
1975 /* handle user stippling */
1980 Pixmap new_bitmap
, inverse
;
1982 /* try and get some GC properties */
1983 if(XGetGCValues(dpy
, gc
,
1984 GCStipple
|GCFillStyle
|GCForeground
|GCBackground
|
1985 GCTileStipXOrigin
|GCTileStipYOrigin
,
1988 /* only do this if stippling requested */
1989 if((values
.fill_style
==FillStippled
||
1990 values
.fill_style
==FillOpaqueStippled
) && !bg
) {
1992 /* opaque stipple: draw rotated text in background colour */
1993 if(values
.fill_style
==FillOpaqueStippled
) {
1994 XSetForeground(dpy
, my_gc
, values
.background
);
1995 XSetFillStyle(dpy
, my_gc
, FillStippled
);
1996 XSetStipple(dpy
, my_gc
, item
->bitmap
);
1997 XSetTSOrigin(dpy
, my_gc
, xp
, yp
);
1998 XFillRectangle(dpy
, drawable
, my_gc
, xp
, yp
,
1999 item
->cols_out
, item
->rows_out
);
2000 XSetForeground(dpy
, my_gc
, values
.foreground
);
2003 /* this will merge the rotated text and the user's stipple */
2004 new_bitmap
=XCreatePixmap(dpy
, drawable
,
2005 item
->cols_out
, item
->rows_out
, 1);
2008 depth_one_gc
=XCreateGC(dpy
, new_bitmap
, NULL
, 0);
2009 XSetForeground(dpy
, depth_one_gc
, 1);
2010 XSetBackground(dpy
, depth_one_gc
, 0);
2012 /* set the relative stipple origin */
2013 XSetTSOrigin(dpy
, depth_one_gc
,
2014 values
.ts_x_origin
-xp
, values
.ts_y_origin
-yp
);
2016 /* fill the whole bitmap with the user's stipple */
2017 XSetStipple(dpy
, depth_one_gc
, values
.stipple
);
2018 XSetFillStyle(dpy
, depth_one_gc
, FillOpaqueStippled
);
2019 XFillRectangle(dpy
, new_bitmap
, depth_one_gc
,
2020 0, 0, item
->cols_out
, item
->rows_out
);
2022 /* set stipple origin back to normal */
2023 XSetTSOrigin(dpy
, depth_one_gc
, 0, 0);
2025 /* this will contain an inverse copy of the rotated text */
2026 inverse
=XCreatePixmap(dpy
, drawable
,
2027 item
->cols_out
, item
->rows_out
, 1);
2030 XSetFillStyle(dpy
, depth_one_gc
, FillSolid
);
2031 XSetFunction(dpy
, depth_one_gc
, GXcopyInverted
);
2032 XCopyArea(dpy
, item
->bitmap
, inverse
, depth_one_gc
,
2033 0, 0, item
->cols_out
, item
->rows_out
, 0, 0);
2035 /* now delete user's stipple everywhere EXCEPT on text */
2036 XSetForeground(dpy
, depth_one_gc
, 0);
2037 XSetBackground(dpy
, depth_one_gc
, 1);
2038 XSetStipple(dpy
, depth_one_gc
, inverse
);
2039 XSetFillStyle(dpy
, depth_one_gc
, FillStippled
);
2040 XSetFunction(dpy
, depth_one_gc
, GXcopy
);
2041 XFillRectangle(dpy
, new_bitmap
, depth_one_gc
,
2042 0, 0, item
->cols_out
, item
->rows_out
);
2044 /* free resources */
2045 XFreePixmap(dpy
, inverse
);
2046 XFreeGC(dpy
, depth_one_gc
);
2048 /* this is the new bitmap */
2049 bitmap_to_paint
=new_bitmap
;
2055 /* paint text using stipple technique */
2056 XSetFillStyle(dpy
, my_gc
, FillStippled
);
2057 XSetStipple(dpy
, my_gc
, bitmap_to_paint
);
2058 XSetTSOrigin(dpy
, my_gc
, xp
, yp
);
2059 XFillRectangle(dpy
, drawable
, my_gc
, xp
, yp
,
2060 item
->cols_out
, item
->rows_out
);
2062 /* free our resources */
2063 XFreeGC(dpy
, my_gc
);
2065 /* stippled bitmap no longer needed */
2066 if(bitmap_to_paint
!=item
->bitmap
)
2067 XFreePixmap(dpy
, bitmap_to_paint
);
2069 #ifdef CACHE_XIMAGES
2070 XFreePixmap(dpy
, item
->bitmap
);
2071 #endif /*CACHE_XIMAGES*/
2073 /* if item isn't cached, destroy it completely */
2075 XRotFreeTextItem(dpy
,item
);
2077 /* we got to the end OK! */
2082 /* ---------------------------------------------------------------------- */
2085 /**************************************************************************/
2086 /* Draw a horizontal string in a quick fashion */
2087 /**************************************************************************/
2089 static int XRotDrawHorizontalString(dpy
, font
, drawable
, gc
, x
, y
, text
,
2104 char *str1
, *str2
, *str3
;
2105 char *str2_a
="\0", *str2_b
="\n\0";
2107 XCharStruct overall
;
2109 DEBUG_PRINT1("**\nHorizontal text.\n");
2111 /* this gc has similar properties to the user's gc (including stipple) */
2112 my_gc
=XCreateGC(dpy
, drawable
, NULL
, 0);
2114 GCForeground
|GCBackground
|GCFunction
|GCStipple
|GCFillStyle
|
2115 GCTileStipXOrigin
|GCTileStipYOrigin
|GCPlaneMask
|
2116 GCClipXOrigin
|GCClipYOrigin
|GCClipMask
, my_gc
);
2117 XSetFont(dpy
, my_gc
, font
->fid
);
2119 /* count number of sections in string */
2121 for(i
=0; i
<strlen(text
)-1; i
++)
2125 /* ignore newline characters if not doing alignment */
2131 /* overall font height */
2132 height
=font
->ascent
+font
->descent
;
2135 if(align
==TLEFT
|| align
==TCENTRE
|| align
==TRIGHT
)
2137 else if(align
==MLEFT
|| align
==MCENTRE
|| align
==MRIGHT
)
2138 yp
=y
-nl
*height
/2+font
->ascent
;
2139 else if(align
==BLEFT
|| align
==BCENTRE
|| align
==BRIGHT
)
2140 yp
=y
-nl
*height
+font
->ascent
;
2144 str1
=my_strdup(text
);
2148 str3
=my_strtok(str1
, str2
);
2150 /* loop through each section in the string */
2152 XTextExtents(font
, str3
, strlen(str3
), &dir
, &asc
, &desc
,
2155 /* where to draw section in x ? */
2156 if(align
==TLEFT
|| align
==MLEFT
|| align
==BLEFT
|| align
==NONE
)
2158 else if(align
==TCENTRE
|| align
==MCENTRE
|| align
==BCENTRE
)
2159 xp
=x
-overall
.rbearing
/2;
2161 xp
=x
-overall
.rbearing
;
2163 /* draw string onto bitmap */
2165 XDrawString(dpy
, drawable
, my_gc
, xp
, yp
, str3
, strlen(str3
));
2167 XDrawImageString(dpy
, drawable
, my_gc
, xp
, yp
, str3
, strlen(str3
));
2169 /* move to next line */
2172 str3
=my_strtok((char *)NULL
, str2
);
2177 XFreeGC(dpy
, my_gc
);
2183 /* ---------------------------------------------------------------------- */
2186 /**************************************************************************/
2187 /* Query cache for a match with this font/text/angle/alignment */
2188 /* request, otherwise arrange for its creation */
2189 /**************************************************************************/
2191 static RotatedTextItem
*XRotRetrieveFromCache(dpy
, font
, angle
, text
, align
)
2199 char *font_name
=NULL
;
2200 unsigned long name_value
;
2201 RotatedTextItem
*item
=NULL
;
2202 RotatedTextItem
*i1
=first_text_item
;
2204 /* get font name, if it exists */
2205 if(XGetFontProperty(font
, XA_FONT
, &name_value
)) {
2206 DEBUG_PRINT1("got font name OK\n");
2207 font_name
=XGetAtomName(dpy
, name_value
);
2211 /* otherwise rely (unreliably?) on font ID */
2213 DEBUG_PRINT1("can't get fontname, caching FID\n");
2218 /* not allowed to cache font ID's */
2220 DEBUG_PRINT1("can't get fontname, can't cache\n");
2224 #endif /*CACHE_FID*/
2226 /* look for a match in cache */
2228 /* matching formula:
2230 identical fontname (if defined, font ID's if not);
2231 angles close enough (<0.00001 here, could be smaller);
2232 HORIZONTAL alignment matches, OR it's a one line string;
2233 magnifications the same */
2235 while(i1
&& !item
) {
2236 /* match everything EXCEPT fontname/ID */
2237 if(strcmp(text
, i1
->text
)==0 &&
2238 fabs(angle
-i1
->angle
)<0.00001 &&
2239 style
.magnify
==i1
->magnify
&&
2241 ((align
==0)?9:(align
-1))%3==
2242 ((i1
->align
==0)?9:(i1
->align
-1))%3)) {
2244 /* now match fontname/ID */
2245 if(font_name
!=NULL
&& i1
->font_name
!=NULL
) {
2246 if(strcmp(font_name
, i1
->font_name
)==0) {
2248 DEBUG_PRINT1("Matched against font names\n");
2254 else if(font_name
==NULL
&& i1
->font_name
==NULL
) {
2257 DEBUG_PRINT1("Matched against FID's\n");
2262 #endif /*CACHE_FID*/
2271 DEBUG_PRINT1("**\nFound target in cache.\n");
2273 DEBUG_PRINT1("**\nNo match in cache.\n");
2277 /* create new item */
2278 item
=XRotCreateTextItem(dpy
, font
, angle
, text
, align
);
2282 /* record what it shows */
2283 item
->text
=my_strdup(text
);
2285 /* fontname or ID */
2286 if(font_name
!=NULL
) {
2287 item
->font_name
=my_strdup(font_name
);
2291 item
->font_name
=NULL
;
2297 item
->magnify
=style
.magnify
;
2300 XRotAddToLinkedList(dpy
, item
);
2306 /* if XImage is cached, need to recreate the bitmap */
2308 #ifdef CACHE_XIMAGES
2312 /* create bitmap to hold rotated text */
2313 item
->bitmap
=XCreatePixmap(dpy
, DefaultRootWindow(dpy
),
2314 item
->cols_out
, item
->rows_out
, 1);
2317 depth_one_gc
=XCreateGC(dpy
, item
->bitmap
, NULL
, 0);
2318 XSetBackground(dpy
, depth_one_gc
, 0);
2319 XSetForeground(dpy
, depth_one_gc
, 1);
2321 /* make the text bitmap from XImage */
2322 XPutImage(dpy
, item
->bitmap
, depth_one_gc
, item
->ximage
, 0, 0, 0, 0,
2323 item
->cols_out
, item
->rows_out
);
2325 XFreeGC(dpy
, depth_one_gc
);
2327 #endif /*CACHE_XIMAGES*/
2333 /* ---------------------------------------------------------------------- */
2336 /**************************************************************************/
2337 /* Create a rotated text item */
2338 /**************************************************************************/
2340 static RotatedTextItem
*XRotCreateTextItem(dpy
, font
, angle
, text
, align
)
2347 RotatedTextItem
*item
=NULL
;
2352 char *str1
, *str2
, *str3
;
2353 char *str2_a
="\0", *str2_b
="\n\0";
2355 int byte_w_in
, byte_w_out
;
2357 float sin_angle
, cos_angle
;
2364 XCharStruct overall
;
2365 int old_cols_in
=0, old_rows_in
=0;
2367 /* allocate memory */
2368 item
=(RotatedTextItem
*)malloc((unsigned)sizeof(RotatedTextItem
));
2372 /* count number of sections in string */
2375 for(i
=0; i
<strlen(text
)-1; i
++)
2379 /* ignore newline characters if not doing alignment */
2385 /* find width of longest section */
2386 str1
=my_strdup(text
);
2390 str3
=my_strtok(str1
, str2
);
2392 XTextExtents(font
, str3
, strlen(str3
), &dir
, &asc
, &desc
,
2395 item
->max_width
=overall
.rbearing
;
2397 /* loop through each section */
2399 str3
=my_strtok((char *)NULL
, str2
);
2402 XTextExtents(font
, str3
, strlen(str3
), &dir
, &asc
, &desc
,
2405 if(overall
.rbearing
>item
->max_width
)
2406 item
->max_width
=overall
.rbearing
;
2413 /* overall font height */
2414 height
=font
->ascent
+font
->descent
;
2416 /* dimensions horizontal text will have */
2417 item
->cols_in
=item
->max_width
;
2418 item
->rows_in
=item
->nl
*height
;
2420 /* bitmap for drawing on */
2421 canvas
=XCreatePixmap(dpy
, DefaultRootWindow(dpy
),
2422 item
->cols_in
, item
->rows_in
, 1);
2424 /* create a GC for the bitmap */
2425 font_gc
=XCreateGC(dpy
, canvas
, NULL
, 0);
2426 XSetBackground(dpy
, font_gc
, 0);
2427 XSetFont(dpy
, font_gc
, font
->fid
);
2429 /* make sure the bitmap is blank */
2430 XSetForeground(dpy
, font_gc
, 0);
2431 XFillRectangle(dpy
, canvas
, font_gc
, 0, 0,
2432 item
->cols_in
+1, item
->rows_in
+1);
2433 XSetForeground(dpy
, font_gc
, 1);
2435 /* pre-calculate sin and cos */
2436 sin_angle
=sin(angle
);
2437 cos_angle
=cos(angle
);
2439 /* text background will be drawn using XFillPolygon */
2441 (float *)malloc((unsigned)(4*item
->nl
*sizeof(float)));
2442 if(!item
->corners_x
)
2446 (float *)malloc((unsigned)(4*item
->nl
*sizeof(float)));
2447 if(!item
->corners_y
)
2450 /* draw text horizontally */
2452 /* start at top of bitmap */
2455 str1
=my_strdup(text
);
2459 str3
=my_strtok(str1
, str2
);
2461 /* loop through each section in the string */
2463 XTextExtents(font
, str3
, strlen(str3
), &dir
, &asc
, &desc
,
2466 /* where to draw section in x ? */
2467 if(align
==TLEFT
|| align
==MLEFT
|| align
==BLEFT
|| align
==NONE
)
2469 else if(align
==TCENTRE
|| align
==MCENTRE
|| align
==BCENTRE
)
2470 xp
=(item
->max_width
-overall
.rbearing
)/2;
2472 xp
=item
->max_width
-overall
.rbearing
;
2474 /* draw string onto bitmap */
2475 XDrawString(dpy
, canvas
, font_gc
, xp
, yp
, str3
, strlen(str3
));
2477 /* keep a note of corner positions of this string */
2478 item
->corners_x
[ic
]=((float)xp
-(float)item
->cols_in
/2)*style
.magnify
;
2479 item
->corners_y
[ic
]=((float)(yp
-font
->ascent
)-(float)item
->rows_in
/2)
2481 item
->corners_x
[ic
+1]=item
->corners_x
[ic
];
2482 item
->corners_y
[ic
+1]=item
->corners_y
[ic
]+(float)height
*style
.magnify
;
2483 item
->corners_x
[item
->nl
*4-1-ic
]=item
->corners_x
[ic
]+
2484 (float)overall
.rbearing
*style
.magnify
;
2485 item
->corners_y
[item
->nl
*4-1-ic
]=item
->corners_y
[ic
];
2486 item
->corners_x
[item
->nl
*4-2-ic
]=
2487 item
->corners_x
[item
->nl
*4-1-ic
];
2488 item
->corners_y
[item
->nl
*4-2-ic
]=item
->corners_y
[ic
+1];
2492 /* move to next line */
2495 str3
=my_strtok((char *)NULL
, str2
);
2501 /* create image to hold horizontal text */
2502 I_in
=MakeXImage(dpy
, item
->cols_in
, item
->rows_in
);
2506 /* extract horizontal text */
2507 XGetSubImage(dpy
, canvas
, 0, 0, item
->cols_in
, item
->rows_in
,
2508 1, XYPixmap
, I_in
, 0, 0);
2509 I_in
->format
=XYBitmap
;
2511 /* magnify horizontal text */
2512 if(style
.magnify
!=1.) {
2513 I_in
=XRotMagnifyImage(dpy
, I_in
);
2515 old_cols_in
=item
->cols_in
;
2516 old_rows_in
=item
->rows_in
;
2517 item
->cols_in
=(float)item
->cols_in
*style
.magnify
;
2518 item
->rows_in
=(float)item
->rows_in
*style
.magnify
;
2521 /* how big will rotated text be ? */
2522 item
->cols_out
=fabs((float)item
->rows_in
*sin_angle
) +
2523 fabs((float)item
->cols_in
*cos_angle
) +0.99999 +2;
2525 item
->rows_out
=fabs((float)item
->rows_in
*cos_angle
) +
2526 fabs((float)item
->cols_in
*sin_angle
) +0.99999 +2;
2528 if(item
->cols_out
%2==0)
2531 if(item
->rows_out
%2==0)
2534 /* create image to hold rotated text */
2535 item
->ximage
=MakeXImage(dpy
, item
->cols_out
, item
->rows_out
);
2536 if(item
->ximage
==NULL
)
2539 byte_w_in
=(item
->cols_in
-1)/8+1;
2540 byte_w_out
=(item
->cols_out
-1)/8+1;
2542 /* we try to make this bit as fast as possible - which is why it looks
2543 a bit over-the-top */
2545 /* vertical distance from centre */
2546 dj
=0.5-(float)item
->rows_out
/2;
2548 /* where abouts does text actually lie in rotated image? */
2549 if(angle
==0 || angle
==M_PI
/2 ||
2550 angle
==M_PI
|| angle
==3*M_PI
/2) {
2552 xr
=(float)item
->cols_out
;
2555 else if(angle
<M_PI
) {
2556 xl
=(float)item
->cols_out
/2+
2557 (dj
-(float)item
->rows_in
/(2*cos_angle
))/
2559 xr
=(float)item
->cols_out
/2+
2560 (dj
+(float)item
->rows_in
/(2*cos_angle
))/
2565 xl
=(float)item
->cols_out
/2+
2566 (dj
+(float)item
->rows_in
/(2*cos_angle
))/
2568 xr
=(float)item
->cols_out
/2+
2569 (dj
-(float)item
->rows_in
/(2*cos_angle
))/
2575 /* loop through all relevent bits in rotated image */
2576 for(j
=0; j
<item
->rows_out
; j
++) {
2578 /* no point re-calculating these every pass */
2579 di
=(float)((xl
<0)?0:(int)xl
)+0.5-(float)item
->cols_out
/2;
2580 byte_out
=(item
->rows_out
-j
-1)*byte_w_out
;
2582 /* loop through meaningful columns */
2583 for(i
=((xl
<0)?0:(int)xl
);
2584 i
<((xr
>=item
->cols_out
)?item
->cols_out
:(int)xr
); i
++) {
2586 /* rotate coordinates */
2587 it
=(float)item
->cols_in
/2 + ( di
*cos_angle
+ dj
*sin_angle
);
2588 jt
=(float)item
->rows_in
/2 - (-di
*sin_angle
+ dj
*cos_angle
);
2590 /* set pixel if required */
2591 if(it
>=0 && it
<item
->cols_in
&& jt
>=0 && jt
<item
->rows_in
)
2592 if((I_in
->data
[jt
*byte_w_in
+it
/8] & 128>>(it
%8))>0)
2593 item
->ximage
->data
[byte_out
+i
/8]|=128>>i
%8;
2601 XDestroyImage(I_in
);
2603 if(style
.magnify
!=1.) {
2604 item
->cols_in
=old_cols_in
;
2605 item
->rows_in
=old_rows_in
;
2609 #ifdef CACHE_BITMAPS
2611 /* create a bitmap to hold rotated text */
2612 item
->bitmap
=XCreatePixmap(dpy
, DefaultRootWindow(dpy
),
2613 item
->cols_out
, item
->rows_out
, 1);
2615 /* make the text bitmap from XImage */
2616 XPutImage(dpy
, item
->bitmap
, font_gc
, item
->ximage
, 0, 0, 0, 0,
2617 item
->cols_out
, item
->rows_out
);
2619 XDestroyImage(item
->ximage
);
2621 #endif /*CACHE_BITMAPS*/
2623 XFreeGC(dpy
, font_gc
);
2624 XFreePixmap(dpy
, canvas
);
2630 /* ---------------------------------------------------------------------- */
2633 /**************************************************************************/
2634 /* Adds a text item to the end of the cache, removing as many items */
2635 /* from the front as required to keep cache size below limit */
2636 /**************************************************************************/
2638 static void XRotAddToLinkedList(dpy
, item
)
2640 RotatedTextItem
*item
;
2643 static long int current_size
=0;
2644 static RotatedTextItem
*last
=NULL
;
2645 RotatedTextItem
*i1
=first_text_item
, *i2
=NULL
;
2647 #ifdef CACHE_BITMAPS
2649 /* I don't know how much memory a pixmap takes in the server -
2650 probably this + a bit more we can't account for */
2652 item
->size
=((item
->cols_out
-1)/8+1)*item
->rows_out
;
2656 /* this is pretty much the size of a RotatedTextItem */
2658 item
->size
=((item
->cols_out
-1)/8+1)*item
->rows_out
+
2659 sizeof(XImage
) + strlen(item
->text
) +
2660 item
->nl
*8*sizeof(float) + sizeof(RotatedTextItem
);
2662 if(item
->font_name
!=NULL
)
2663 item
->size
+=strlen(item
->font_name
);
2665 item
->size
+=sizeof(Font
);
2667 #endif /*CACHE_BITMAPS */
2670 /* count number of items in cache, for debugging */
2678 DEBUG_PRINT2("Cache has %d items.\n", i
);
2683 DEBUG_PRINT4("current cache size=%ld, new item=%ld, limit=%ld\n",
2684 current_size
, item
->size
, CACHE_SIZE_LIMIT
*1024);
2686 /* if this item is bigger than whole cache, forget it */
2687 if(item
->size
>CACHE_SIZE_LIMIT
*1024) {
2688 DEBUG_PRINT1("Too big to cache\n\n");
2693 /* remove elements from cache as needed */
2694 while(i1
&& current_size
+item
->size
>CACHE_SIZE_LIMIT
*1024) {
2696 DEBUG_PRINT2("Removed %d bytes\n", i1
->size
);
2698 if(i1
->font_name
!=NULL
)
2699 DEBUG_PRINT5(" (`%s'\n %s\n angle=%f align=%d)\n",
2700 i1
->text
, i1
->font_name
, i1
->angle
, i1
->align
);
2703 if(i1
->font_name
==NULL
)
2704 DEBUG_PRINT5(" (`%s'\n FID=%ld\n angle=%f align=%d)\n",
2705 i1
->text
, i1
->fid
, i1
->angle
, i1
->align
);
2706 #endif /*CACHE_FID*/
2708 current_size
-=i1
->size
;
2712 /* free resources used by the unlucky item */
2713 XRotFreeTextItem(dpy
, i1
);
2715 /* remove it from linked list */
2720 /* add new item to end of linked list */
2721 if(first_text_item
==NULL
) {
2723 first_text_item
=item
;
2732 /* new cache size */
2733 current_size
+=item
->size
;
2737 DEBUG_PRINT1("Added item to cache.\n");
2741 /* ---------------------------------------------------------------------- */
2744 /**************************************************************************/
2745 /* Free the resources used by a text item */
2746 /**************************************************************************/
2748 static void XRotFreeTextItem(dpy
, item
)
2750 RotatedTextItem
*item
;
2754 if(item
->font_name
!=NULL
)
2755 free(item
->font_name
);
2757 free((char *)item
->corners_x
);
2758 free((char *)item
->corners_y
);
2760 #ifdef CACHE_BITMAPS
2761 XFreePixmap(dpy
, item
->bitmap
);
2763 XDestroyImage(item
->ximage
);
2764 #endif /* CACHE_BITMAPS */
2770 /* ---------------------------------------------------------------------- */
2773 /**************************************************************************/
2774 /* Magnify an XImage using bilinear interpolation */
2775 /**************************************************************************/
2777 static XImage
*XRotMagnifyImage(dpy
, ximage
)
2785 int cols_in
, rows_in
;
2786 int cols_out
, rows_out
;
2787 register int i2
, j2
;
2788 float z1
, z2
, z3
, z4
;
2789 int byte_width_in
, byte_width_out
;
2792 /* size of input image */
2793 cols_in
=ximage
->width
;
2794 rows_in
=ximage
->height
;
2796 /* size of final image */
2797 cols_out
=(float)cols_in
*style
.magnify
;
2798 rows_out
=(float)rows_in
*style
.magnify
;
2800 /* this will hold final image */
2801 I_out
=MakeXImage(dpy
, cols_out
, rows_out
);
2805 /* width in bytes of input, output images */
2806 byte_width_in
=(cols_in
-1)/8+1;
2807 byte_width_out
=(cols_out
-1)/8+1;
2810 mag_inv
=1./style
.magnify
;
2814 /* loop over magnified image */
2815 for(j2
=0; j2
<rows_out
; j2
++) {
2819 for(i2
=0; i2
<cols_out
; i2
++) {
2822 /* bilinear interpolation - where are we on bitmap ? */
2824 if(i
==cols_in
-1 && j
!=rows_in
-1) {
2828 z1
=(ximage
->data
[j
*byte_width_in
+i
/8] & 128>>(i
%8))>0;
2830 z3
=(ximage
->data
[(j
+1)*byte_width_in
+i
/8] & 128>>(i
%8))>0;
2834 else if(i
!=cols_in
-1 && j
==rows_in
-1) {
2838 z1
=(ximage
->data
[j
*byte_width_in
+i
/8] & 128>>(i
%8))>0;
2839 z2
=(ximage
->data
[j
*byte_width_in
+(i
+1)/8] & 128>>((i
+1)%8))>0;
2843 /* top right corner */
2844 else if(i
==cols_in
-1 && j
==rows_in
-1) {
2848 z1
=(ximage
->data
[j
*byte_width_in
+i
/8] & 128>>(i
%8))>0;
2853 /* somewhere `safe' */
2858 z1
=(ximage
->data
[j
*byte_width_in
+i
/8] & 128>>(i
%8))>0;
2859 z2
=(ximage
->data
[j
*byte_width_in
+(i
+1)/8] & 128>>((i
+1)%8))>0;
2860 z3
=(ximage
->data
[(j
+1)*byte_width_in
+(i
+1)/8] &
2862 z4
=(ximage
->data
[(j
+1)*byte_width_in
+i
/8] & 128>>(i
%8))>0;
2865 /* if interpolated value is greater than 0.5, set bit */
2866 if(((1-t
)*(1-u
)*z1
+ t
*(1-u
)*z2
+ t
*u
*z3
+ (1-t
)*u
*z4
)>0.5)
2867 I_out
->data
[j2
*byte_width_out
+i2
/8]|=128>>i2
%8;
2874 /* destroy original */
2875 XDestroyImage(ximage
);
2877 /* return big image */
2883 /* ---------------------------------------------------------------------- */
2886 /**************************************************************************/
2887 /* Calculate the bounding box some text will have when painted */
2888 /**************************************************************************/
2890 XPoint
*XRotTextExtents(dpy
, font
, angle
, x
, y
, text
, align
)
2899 char *str1
, *str2
, *str3
;
2900 char *str2_a
="\0", *str2_b
="\n\0";
2902 float sin_angle
, cos_angle
;
2904 int cols_in
, rows_in
;
2906 XPoint
*xp_in
, *xp_out
;
2908 XCharStruct overall
;
2910 /* manipulate angle to 0<=angle<360 degrees */
2919 /* count number of sections in string */
2922 for(i
=0; i
<strlen(text
)-1; i
++)
2926 /* ignore newline characters if not doing alignment */
2932 /* find width of longest section */
2933 str1
=my_strdup(text
);
2937 str3
=my_strtok(str1
, str2
);
2939 XTextExtents(font
, str3
, strlen(str3
), &dir
, &asc
, &desc
,
2942 max_width
=overall
.rbearing
;
2944 /* loop through each section */
2946 str3
=my_strtok((char *)NULL
, str2
);
2949 XTextExtents(font
, str3
, strlen(str3
), &dir
, &asc
, &desc
,
2952 if(overall
.rbearing
>max_width
)
2953 max_width
=overall
.rbearing
;
2960 /* overall font height */
2961 height
=font
->ascent
+font
->descent
;
2963 /* dimensions horizontal text will have */
2967 /* pre-calculate sin and cos */
2968 sin_angle
=sin(angle
);
2969 cos_angle
=cos(angle
);
2972 if(align
==TLEFT
|| align
==TCENTRE
|| align
==TRIGHT
)
2973 hot_y
=(float)rows_in
/2*style
.magnify
;
2974 else if(align
==MLEFT
|| align
==MCENTRE
|| align
==MRIGHT
)
2976 else if(align
==BLEFT
|| align
==BCENTRE
|| align
==BRIGHT
)
2977 hot_y
= -(float)rows_in
/2*style
.magnify
;
2979 hot_y
= -((float)rows_in
/2-(float)font
->descent
)*style
.magnify
;
2982 if(align
==TLEFT
|| align
==MLEFT
|| align
==BLEFT
|| align
==NONE
)
2983 hot_x
= -(float)max_width
/2*style
.magnify
;
2984 else if(align
==TCENTRE
|| align
==MCENTRE
|| align
==BCENTRE
)
2987 hot_x
=(float)max_width
/2*style
.magnify
;
2989 /* reserve space for XPoints */
2990 xp_in
=(XPoint
*)malloc((unsigned)(5*sizeof(XPoint
)));
2994 xp_out
=(XPoint
*)malloc((unsigned)(5*sizeof(XPoint
)));
2998 /* bounding box when horizontal, relative to bitmap centre */
2999 xp_in
[0].x
= -(float)cols_in
*style
.magnify
/2-style
.bbx_pad
;
3000 xp_in
[0].y
= (float)rows_in
*style
.magnify
/2+style
.bbx_pad
;
3001 xp_in
[1].x
= (float)cols_in
*style
.magnify
/2+style
.bbx_pad
;
3002 xp_in
[1].y
= (float)rows_in
*style
.magnify
/2+style
.bbx_pad
;
3003 xp_in
[2].x
= (float)cols_in
*style
.magnify
/2+style
.bbx_pad
;
3004 xp_in
[2].y
= -(float)rows_in
*style
.magnify
/2-style
.bbx_pad
;
3005 xp_in
[3].x
= -(float)cols_in
*style
.magnify
/2-style
.bbx_pad
;
3006 xp_in
[3].y
= -(float)rows_in
*style
.magnify
/2-style
.bbx_pad
;
3007 xp_in
[4].x
=xp_in
[0].x
;
3008 xp_in
[4].y
=xp_in
[0].y
;
3010 /* rotate and translate bounding box */
3011 for(i
=0; i
<5; i
++) {
3012 xp_out
[i
].x
=(float)x
+ ( ((float)xp_in
[i
].x
-hot_x
)*cos_angle
+
3013 ((float)xp_in
[i
].y
+hot_y
)*sin_angle
);
3014 xp_out
[i
].y
=(float)y
+ (-((float)xp_in
[i
].x
-hot_x
)*sin_angle
+
3015 ((float)xp_in
[i
].y
+hot_y
)*cos_angle
);
3018 free((char *)xp_in
);
3025 /* ***********************************************************************
3026 * Conversion routines for the X resource manager
3027 * ***********************************************************************
3030 #if defined(__STDC__)
3032 Boolean
strtocard( Display
*dsp
,
3041 Boolean
strtocard( dsp
, args
, num_args
, from
, to
, unused
)
3050 static Cardinal temp
;
3052 if ( to
->addr
== NULL
) {
3053 to
->addr
= (XtPointer
) &temp
;
3054 to
->size
= sizeof(Cardinal
);
3057 *((Cardinal
*) to
->addr
) = atoi( from
->addr
);
3062 #define done_bert(type, value) \
3064 if (to->addr != NULL) {\
3065 if (to->size < sizeof(type)) {\
3066 to->size = sizeof(type);\
3069 *(type*)(to->addr) = (value);\
3071 static type static_val;\
3072 static_val = (value);\
3073 to->addr = (XtPointer)&static_val;\
3075 to->size = sizeof(type);\
3079 Boolean
cvtStringToStringArray(display
, args
, num_args
, from
, to
,
3086 XtPointer
*converter_data
;
3089 StringArray a
= NULL
;
3094 XtAppErrorMsg(XtDisplayToApplicationContext(display
),
3095 "cvtStringToStringArray", "wrongParameters",
3097 "String to StringArray conversion needs no arguments",
3098 (String
*) NULL
, (Cardinal
*) NULL
);
3100 delim
= ((String
) from
->addr
)[0];
3101 s
= XtNewString((String
) from
->addr
+ 1);
3104 t
= strchr(s
, delim
);
3106 a
= (StringArray
) XtRealloc((String
) a
, (i
+ 1) * sizeof(*a
));
3109 s
= t
? t
+ 1 : NULL
;
3111 a
= (StringArray
) XtRealloc((String
) a
, (i
+ 1) * sizeof(*a
));
3113 done_bert(StringArray
, a
);
3117 /* ***********************************************************************
3118 * A driver for the above in the flavor of the xt utilities module
3119 * ***********************************************************************
3124 typedef struct tab_data
{
3128 void (*activate_func
)();
3132 #if defined(__STDC__)
3133 static void handle_click( Widget w
, TabData td
, XtPointer call_data
)
3135 static void handle_click(w
, td
, call_data
)
3138 XtPointer call_data
;
3141 int tab
= (int) call_data
;
3143 /* note that the tab is relative to the current tab.
3144 * if tab is 0, the user clicked on the current one.
3145 * there is nothing to do
3147 if (tab
== 0) return;
3150 /* Change tabs. We must manually inform the UI which tab is current */
3152 XtNlefttabs
, td
->cur
,
3153 XtNrighttabs
, td
->num_tabs
- td
->cur
- 1,
3157 (*td
->activate_func
)( td
->form
, td
->cur
);
3162 * PUBLIC: Widget __vi_CreateTabbedFolder
3163 * PUBLIC: __P((String, Widget, String, int, void (*)(Widget, int)));
3165 #if defined(__STDC__)
3166 Widget
__vi_CreateTabbedFolder( String name
,
3170 void (*activate_func
)()
3173 Widget
__vi_CreateTabbedFolder( name
, parent
, tab_labels
, num_tabs
, activate_func
)
3178 void (*activate_func
)();
3182 TabData td
= (TabData
) malloc( sizeof(struct tab_data
) );
3185 XtAppSetTypeConverter( XtDisplayToApplicationContext(XtDisplay(parent
)),
3195 /* init our internal structure */
3197 td
->num_tabs
= num_tabs
;
3198 td
->activate_func
= activate_func
;
3200 /* tabs go on the top */
3201 tabs
= XtVaCreateManagedWidget( "tabs",
3205 XtNrighttabs
, num_tabs
-1,
3206 XtNorientation
, XfwfUpTabs
,
3207 XmNtopAttachment
, XmATTACH_FORM
,
3208 XmNleftAttachment
, XmATTACH_FORM
,
3209 XmNleftOffset
, TABHT
/4,
3210 XmNrightAttachment
,XmATTACH_FORM
,
3211 XmNrightOffset
, TABHT
/4,
3212 XmNbottomAttachment
,XmATTACH_OPPOSITE_FORM
,
3213 XmNbottomOffset
, -TABHT
,
3214 XtNlabels
, tab_labels
,
3215 XtVaTypedArg
, XtNlabels
,
3218 strlen(tab_labels
) + 1,
3222 /* add the callback */
3223 XtAddCallback( tabs
,
3224 XtNactivateCallback
,
3225 (XtCallbackProc
) handle_click
,
3229 /* another form to hold the controls */
3230 td
->form
= XtVaCreateWidget( "form",
3233 XmNtopAttachment
, XmATTACH_WIDGET
,
3235 XmNleftAttachment
, XmATTACH_FORM
,
3236 XmNbottomAttachment
, XmATTACH_FORM
,
3237 XmNrightAttachment
, XmATTACH_FORM
,