2 static char Xrcsid
[] = "$XConsortium: Label.c,v 1.77 89/12/08 12:35:36 swick Exp $";
6 /***********************************************************
7 Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts,
8 and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
12 Permission to use, copy, modify, and distribute this software and its
13 documentation for any purpose and without fee is hereby granted,
14 provided that the above copyright notice appear in all copies and that
15 both that copyright notice and this permission notice appear in
16 supporting documentation, and that the names of Digital or MIT not be
17 used in advertising or publicity pertaining to distribution of the
18 software without specific, written prior permission.
20 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
21 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
22 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
23 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
24 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
25 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
28 ******************************************************************/
31 * Label.c - Label widget
35 #define XtStrlen(s) ((s) ? strlen(s) : 0)
39 #include <X11/IntrinsicP.h>
40 #include <X11/StringDefs.h>
41 #include <./Xaw3_1XawInit.h>
42 #include <./Xaw3_1LabelP.h>
46 #define index(a,b) strchr(a,b)
50 #define streq(a,b) (strcmp( (a), (b) ) == 0)
52 #define MULTI_LINE_LABEL 32767
54 /****************************************************************
56 * Full class record constant
58 ****************************************************************/
62 #define offset(field) XtOffset(LabelWidget, field)
63 static XtResource resources
[] = {
64 {XtNforeground
, XtCForeground
, XtRPixel
, sizeof(Pixel
),
65 offset(label
.foreground
), XtRString
, "XtDefaultForeground"},
66 {XtNfont
, XtCFont
, XtRFontStruct
, sizeof(XFontStruct
*),
67 offset(label
.font
),XtRString
, "XtDefaultFont"},
68 {XtNlabel
, XtCLabel
, XtRString
, sizeof(String
),
69 offset(label
.label
), XtRString
, NULL
},
70 {XtNjustify
, XtCJustify
, XtRJustify
, sizeof(XtJustify
),
71 offset(label
.justify
), XtRImmediate
, (caddr_t
)XtJustifyCenter
},
72 {XtNinternalWidth
, XtCWidth
, XtRDimension
, sizeof(Dimension
),
73 offset(label
.internal_width
), XtRImmediate
, (caddr_t
)4},
74 {XtNinternalHeight
, XtCHeight
, XtRDimension
, sizeof(Dimension
),
75 offset(label
.internal_height
), XtRImmediate
, (caddr_t
)2},
76 {XtNbitmap
, XtCPixmap
, XtRBitmap
, sizeof(Pixmap
),
77 offset(label
.pixmap
), XtRImmediate
, (caddr_t
)None
},
78 {XtNresize
, XtCResize
, XtRBoolean
, sizeof(Boolean
),
79 offset(label
.resize
), XtRImmediate
, (caddr_t
)True
},
82 static void Initialize();
84 static void Redisplay();
85 static Boolean
SetValues();
86 static void ClassInitialize();
87 static void Destroy();
88 static XtGeometryResult
QueryGeometry();
90 LabelClassRec labelClassRec
= {
92 /* core_class fields */
93 #define superclass (&simpleClassRec)
94 /* superclass */ (WidgetClass
) superclass
,
95 /* class_name */ "Label",
96 /* widget_size */ sizeof(LabelRec
),
97 /* class_initialize */ ClassInitialize
,
98 /* class_part_initialize */ NULL
,
99 /* class_inited */ FALSE
,
100 /* initialize */ Initialize
,
101 /* initialize_hook */ NULL
,
102 /* realize */ XtInheritRealize
,
105 /* resources */ resources
,
106 /* num_resources */ XtNumber(resources
),
107 /* xrm_class */ NULLQUARK
,
108 /* compress_motion */ TRUE
,
109 /* compress_exposure */ TRUE
,
110 /* compress_enterleave */ TRUE
,
111 /* visible_interest */ FALSE
,
112 /* destroy */ Destroy
,
114 /* expose */ Redisplay
,
115 /* set_values */ SetValues
,
116 /* set_values_hook */ NULL
,
117 /* set_values_almost */ XtInheritSetValuesAlmost
,
118 /* get_values_hook */ NULL
,
119 /* accept_focus */ NULL
,
120 /* version */ XtVersion
,
121 /* callback_private */ NULL
,
123 /* query_geometry */ QueryGeometry
,
124 /* display_accelerator */ XtInheritDisplayAccelerator
,
127 /* Simple class fields initialization */
129 /* change_sensitive */ XtInheritChangeSensitive
132 WidgetClass labelWidgetClass
= (WidgetClass
)&labelClassRec
;
133 /****************************************************************
137 ****************************************************************/
139 static void ClassInitialize()
141 extern void XmuCvtStringToJustify();
142 extern void XmuCvtStringToBitmap();
143 static XtConvertArgRec screenConvertArg
[] = {
144 {XtWidgetBaseOffset
, (caddr_t
) XtOffset(Widget
, core
.screen
),
147 XawInitializeWidgetSet();
148 XtAddConverter( XtRString
, XtRJustify
, XmuCvtStringToJustify
, NULL
, 0 );
149 XtAddConverter("String", "Bitmap", XmuCvtStringToBitmap
,
150 screenConvertArg
, XtNumber(screenConvertArg
));
151 } /* ClassInitialize */
154 * Calculate width and height of displayed text in pixels
157 static void SetTextWidthAndHeight(lw
)
160 register XFontStruct
*fs
= lw
->label
.font
;
163 if (lw
->label
.pixmap
!= None
) {
166 unsigned int width
, height
, bw
, depth
;
167 if (XGetGeometry(XtDisplay(lw
), lw
->label
.pixmap
, &root
, &x
, &y
,
168 &width
, &height
, &bw
, &depth
)) {
169 lw
->label
.label_height
= height
;
170 lw
->label
.label_width
= width
;
171 lw
->label
.label_len
= depth
;
176 lw
->label
.label_height
= fs
->max_bounds
.ascent
+ fs
->max_bounds
.descent
;
177 if (lw
->label
.label
== NULL
) {
178 lw
->label
.label_len
= 0;
179 lw
->label
.label_width
= 0;
181 else if ((nl
= index(lw
->label
.label
, '\n')) != NULL
) {
183 lw
->label
.label_len
= MULTI_LINE_LABEL
;
184 lw
->label
.label_width
= 0;
185 for (label
= lw
->label
.label
; nl
!= NULL
; nl
= index(label
, '\n')) {
186 int width
= XTextWidth(fs
, label
, (int)(nl
- label
));
187 if (width
> lw
->label
.label_width
) lw
->label
.label_width
= width
;
190 lw
->label
.label_height
+=
191 fs
->max_bounds
.ascent
+ fs
->max_bounds
.descent
;
194 int width
= XTextWidth(fs
, label
, strlen(label
));
195 if (width
> lw
->label
.label_width
) lw
->label
.label_width
= width
;
198 lw
->label
.label_len
= strlen(lw
->label
.label
);
199 lw
->label
.label_width
=
200 XTextWidth(fs
, lw
->label
.label
, (int) lw
->label
.label_len
);
204 static void GetnormalGC(lw
)
209 values
.foreground
= lw
->label
.foreground
;
210 values
.background
= lw
->core
.background_pixel
;
211 values
.font
= lw
->label
.font
->fid
;
213 lw
->label
.normal_GC
= XtGetGC(
215 (unsigned) GCForeground
| GCBackground
| GCFont
,
219 static void GetgrayGC(lw
)
224 values
.foreground
= lw
->label
.foreground
;
225 values
.background
= lw
->core
.background_pixel
;
226 values
.font
= lw
->label
.font
->fid
;
227 values
.fill_style
= FillTiled
;
228 values
.tile
= XmuCreateStippledPixmap(XtScreen((Widget
)lw
),
229 lw
->label
.foreground
,
230 lw
->core
.background_pixel
,
233 lw
->label
.stipple
= values
.tile
;
234 lw
->label
.gray_GC
= XtGetGC((Widget
)lw
,
235 (unsigned) GCForeground
| GCBackground
|
236 GCFont
| GCTile
| GCFillStyle
,
241 static void Initialize(request
, new)
244 LabelWidget lw
= (LabelWidget
) new;
246 if (lw
->label
.label
== NULL
)
247 lw
->label
.label
= XtNewString(lw
->core
.name
);
249 lw
->label
.label
= XtNewString(lw
->label
.label
);
255 SetTextWidthAndHeight(lw
);
257 if (lw
->core
.width
== 0)
258 lw
->core
.width
= lw
->label
.label_width
+ 2 * lw
->label
.internal_width
;
259 if (lw
->core
.height
== 0)
260 lw
->core
.height
= lw
->label
.label_height
+ 2*lw
->label
.internal_height
;
262 lw
->label
.label_x
= lw
->label
.label_y
= 0;
263 (*XtClass(new)->core_class
.resize
) ((Widget
)lw
);
268 * Repaint the widget window
272 static void Redisplay(w
, event
, region
)
277 LabelWidget lw
= (LabelWidget
) w
;
280 if (region
!= NULL
&&
281 XRectInRegion(region
, lw
->label
.label_x
, lw
->label
.label_y
,
282 lw
->label
.label_width
, lw
->label
.label_height
)
286 gc
= XtIsSensitive((Widget
)lw
) ? lw
->label
.normal_GC
: lw
->label
.gray_GC
;
288 if (region
!= NULL
) XSetRegion(XtDisplay(w
), gc
, region
);
290 if (lw
->label
.pixmap
== None
) {
291 int len
= lw
->label
.label_len
;
292 char *label
= lw
->label
.label
;
293 Position y
= lw
->label
.label_y
+ lw
->label
.font
->max_bounds
.ascent
;
294 if (len
== MULTI_LINE_LABEL
) {
296 while ((nl
= index(label
, '\n')) != NULL
) {
298 XtDisplay(w
), XtWindow(w
), gc
, lw
->label
.label_x
,
299 y
, label
, (int)(nl
- label
));
300 y
+= lw
->label
.font
->max_bounds
.ascent
+ lw
->label
.font
->max_bounds
.descent
;
307 XtDisplay(w
), XtWindow(w
), gc
, lw
->label
.label_x
,
309 } else if (lw
->label
.label_len
== 1) { /* depth */
311 XtDisplay(w
), lw
->label
.pixmap
, XtWindow(w
), gc
,
312 0, 0, lw
->label
.label_width
, lw
->label
.label_height
,
313 lw
->label
.label_x
, lw
->label
.label_y
, 1L);
316 XtDisplay(w
), lw
->label
.pixmap
, XtWindow(w
), gc
,
317 0, 0, lw
->label
.label_width
, lw
->label
.label_height
,
318 lw
->label
.label_x
, lw
->label
.label_y
);
321 if (region
!= NULL
) XSetClipMask(XtDisplay(w
), gc
, (Pixmap
)None
);
325 static void _Reposition(lw
, width
, height
, dx
, dy
)
326 register LabelWidget lw
;
327 Dimension width
, height
;
331 switch (lw
->label
.justify
) {
334 newPos
= lw
->label
.internal_width
;
337 case XtJustifyRight
:
339 (lw
->label
.label_width
+ lw
->label
.internal_width
);
342 case XtJustifyCenter
:
343 newPos
= (width
- lw
->label
.label_width
) / 2;
346 if (newPos
< (Position
)lw
->label
.internal_width
)
347 newPos
= lw
->label
.internal_width
;
348 *dx
= newPos
- lw
->label
.label_x
;
349 lw
->label
.label_x
= newPos
;
350 *dy
= (newPos
= (height
- lw
->label
.label_height
) / 2) - lw
->label
.label_y
;
351 lw
->label
.label_y
= newPos
;
355 static void Resize(w
)
358 LabelWidget lw
= (LabelWidget
)w
;
360 _Reposition(lw
, w
->core
.width
, w
->core
.height
, &dx
, &dy
);
364 * Set specified arguments into widget
372 static Boolean
SetValues(current
, request
, new, args
, num_args
)
373 Widget current
, request
, new;
377 LabelWidget curlw
= (LabelWidget
) current
;
378 LabelWidget reqlw
= (LabelWidget
) request
;
379 LabelWidget newlw
= (LabelWidget
) new;
381 Boolean was_resized
= False
, redisplay
= False
, checks
[NUM_CHECKS
];
383 for (i
= 0; i
< NUM_CHECKS
; i
++)
386 for (i
= 0; i
< *num_args
; i
++) {
387 if (streq(XtNbitmap
, args
[i
].name
))
388 checks
[PIXMAP
] = TRUE
;
389 if (streq(XtNwidth
, args
[i
].name
))
390 checks
[WIDTH
] = TRUE
;
391 if (streq(XtNheight
, args
[i
].name
))
392 checks
[HEIGHT
] = TRUE
;
395 if (newlw
->label
.label
== NULL
) {
396 newlw
->label
.label
= newlw
->core
.name
;
399 if (curlw
->label
.label
!= newlw
->label
.label
) {
400 if (curlw
->label
.label
!= curlw
->core
.name
)
401 XtFree( (char *)curlw
->label
.label
);
403 if (newlw
->label
.label
!= newlw
->core
.name
) {
404 newlw
->label
.label
= XtNewString( newlw
->label
.label
);
409 if (was_resized
|| (curlw
->label
.font
!= newlw
->label
.font
) ||
410 (curlw
->label
.justify
!= newlw
->label
.justify
) || checks
[PIXMAP
]) {
412 SetTextWidthAndHeight(newlw
);
416 /* recalculate the window size if something has changed. */
417 if (newlw
->label
.resize
&& was_resized
) {
418 if ((curlw
->core
.width
== reqlw
->core
.width
) && !checks
[WIDTH
])
419 newlw
->core
.width
= (newlw
->label
.label_width
+
420 2 * newlw
->label
.internal_width
);
422 if ((curlw
->core
.height
== reqlw
->core
.height
) && !checks
[HEIGHT
])
423 newlw
->core
.height
= (newlw
->label
.label_height
+
424 2 * newlw
->label
.internal_height
);
427 if (curlw
->label
.foreground
!= newlw
->label
.foreground
428 || curlw
->label
.font
->fid
!= newlw
->label
.font
->fid
) {
430 XtReleaseGC(new, curlw
->label
.normal_GC
);
431 XtReleaseGC(new, curlw
->label
.gray_GC
);
432 XmuReleaseStippledPixmap( XtScreen(current
), curlw
->label
.stipple
);
438 if ((curlw
->label
.internal_width
!= newlw
->label
.internal_width
)
439 || (curlw
->label
.internal_height
!= newlw
->label
.internal_height
)
441 /* Resize() will be called if geometry changes succeed */
443 _Reposition(newlw
, curlw
->core
.width
, curlw
->core
.height
, &dx
, &dy
);
446 return was_resized
|| redisplay
||
447 XtIsSensitive(current
) != XtIsSensitive(new);
450 static void Destroy(w
)
453 LabelWidget lw
= (LabelWidget
)w
;
455 XtFree( lw
->label
.label
);
456 XtReleaseGC( w
, lw
->label
.normal_GC
);
457 XtReleaseGC( w
, lw
->label
.gray_GC
);
458 XmuReleaseStippledPixmap( XtScreen(w
), lw
->label
.stipple
);
462 static XtGeometryResult
QueryGeometry(w
, intended
, preferred
)
464 XtWidgetGeometry
*intended
, *preferred
;
466 register LabelWidget lw
= (LabelWidget
)w
;
468 preferred
->request_mode
= CWWidth
| CWHeight
;
469 preferred
->width
= lw
->label
.label_width
+ 2 * lw
->label
.internal_width
;
470 preferred
->height
= lw
->label
.label_height
+ 2*lw
->label
.internal_height
;
471 if ( ((intended
->request_mode
& (CWWidth
| CWHeight
))
472 == (CWWidth
| CWHeight
)) &&
473 intended
->width
== preferred
->width
&&
474 intended
->height
== preferred
->height
)
475 return XtGeometryYes
;
476 else if (preferred
->width
== w
->core
.width
&&
477 preferred
->height
== w
->core
.height
)
480 return XtGeometryAlmost
;