1 /***********************************************************
3 Copyright 1987, 1988, 1994, 1998 The Open Group
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 Except as contained in this notice, the name of The Open Group shall not be
22 used in advertising or otherwise to promote the sale, use or other dealings
23 in this Software without prior written authorization from The Open Group.
26 Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
30 Permission to use, copy, modify, and distribute this software and its
31 documentation for any purpose and without fee is hereby granted,
32 provided that the above copyright notice appear in all copies and that
33 both that copyright notice and this permission notice appear in
34 supporting documentation, and that the name of Digital not be
35 used in advertising or publicity pertaining to distribution of the
36 software without specific, written prior permission.
38 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
39 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
40 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
41 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
42 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
43 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
46 ******************************************************************/
53 #include <X11/IntrinsicP.h>
54 #include <X11/StringDefs.h>
56 #include <X11/Xmu/Converters.h>
57 #include <X11/Xmu/Drawing.h>
58 #include <X11/Xaw/LabelP.h>
59 #include <X11/Xaw/XawInit.h>
62 #define streq(a, b) (strcmp((a), (b)) == 0)
64 #define MULTI_LINE_LABEL 32767
73 static void XawLabelClassInitialize(void);
74 static void XawLabelDestroy(Widget);
75 static void XawLabelInitialize(Widget, Widget, ArgList, Cardinal*);
76 static XtGeometryResult XawLabelQueryGeometry(Widget, XtWidgetGeometry*,
78 static void XawLabelRedisplay(Widget, XEvent*, Region);
79 static void XawLabelResize(Widget);
80 static Boolean XawLabelSetValues(Widget, Widget, Widget,
87 static int _XawLabelWidth16(XFontStruct*, char*, int);
88 static void _XawLabelDraw16(Display*, Drawable, GC, int, int, char*, int);
90 static void compute_bitmap_offsets(LabelWidget);
91 static void GetGrayGC(LabelWidget);
92 static void GetNormalGC(LabelWidget);
93 static void _Reposition(LabelWidget, unsigned int, unsigned int,
94 Position*, Position*);
95 static void set_bitmap_info(LabelWidget);
96 static void SetTextWidthAndHeight(LabelWidget);
101 #define offset(field) XtOffsetOf(LabelRec, field)
102 static XtResource resources[] = {
108 offset(label.foreground),
116 sizeof(XFontStruct*),
126 offset(label.fontset),
143 sizeof(unsigned char),
144 offset(label.encoding),
146 (XtPointer)XawTextEncoding8bit
153 offset(label.justify),
155 (XtPointer)XtJustifyCenter
162 offset(label.internal_width),
171 offset(label.internal_height),
180 offset(label.left_bitmap),
189 offset(label.pixmap),
198 offset(label.resize),
207 offset(label.label_x),
216 offset(label.label_y),
223 #define Superclass (&simpleClassRec)
224 LabelClassRec labelClassRec = {
227 (WidgetClass)&simpleClassRec, /* superclass */
228 "Label", /* class_name */
229 sizeof(LabelRec), /* widget_size */
230 XawLabelClassInitialize, /* class_initialize */
231 NULL, /* class_part_initialize */
232 False, /* class_inited */
233 XawLabelInitialize, /* initialize */
234 NULL, /* initialize_hook */
235 XtInheritRealize, /* realize */
238 resources, /* resources */
239 XtNumber(resources), /* num_resources */
240 NULLQUARK, /* xrm_class */
241 True, /* compress_motion */
242 True, /* compress_exposure */
243 True, /* compress_enterleave */
244 False, /* visible_interest */
245 XawLabelDestroy, /* destroy */
246 XawLabelResize, /* resize */
247 XawLabelRedisplay, /* expose */
248 XawLabelSetValues, /* set_values */
249 NULL, /* set_values_hook */
250 XtInheritSetValuesAlmost, /* set_values_almost */
251 NULL, /* get_values_hook */
252 NULL, /* accept_focus */
253 XtVersion, /* version */
254 NULL, /* callback_private */
256 XawLabelQueryGeometry, /* query_geometry */
257 XtInheritDisplayAccelerator, /* display_accelerator */
258 NULL, /* extension */
262 XtInheritChangeSensitive, /* change_sensitive */
266 NULL, /* extension */
270 WidgetClass labelWidgetClass = (WidgetClass)&labelClassRec;
276 XawLabelClassInitialize(void)
278 XawInitializeWidgetSet();
279 XtAddConverter(XtRString, XtRJustify, XmuCvtStringToJustify, NULL, 0);
280 XtSetTypeConverter(XtRJustify, XtRString, XmuCvtJustifyToString,
281 NULL, 0, XtCacheNone, NULL);
285 #define TXT16 XChar2b
289 static XChar2b *buf2b;
290 static int buf2blen = 0;
293 _XawLabelWidth16(XFontStruct *fs, char *str, int n)
299 buf2b = (XChar2b *)XtRealloc((char *)buf2b, n * sizeof(XChar2b));
302 for (ptr = buf2b, i = n; --i >= 0; ptr++) {
307 return (XTextWidth16(fs, buf2b, n));
311 _XawLabelDraw16(Display *dpy, Drawable d, GC gc, int x, int y,
318 buf2b = (XChar2b *)XtRealloc((char *)buf2b, n * sizeof(XChar2b));
321 for (ptr = buf2b, i = n; --i >= 0; ptr++) {
325 XDrawString16(dpy, d, gc, x, y, buf2b, n);
328 #define XTextWidth16 _XawLabelWidth16
329 #define XDrawString16 _XawLabelDraw16
333 * Calculate width and height of displayed text in pixels
336 SetTextWidthAndHeight(LabelWidget lw)
338 XFontStruct *fs = lw->label.font;
341 if (lw->label.pixmap != None) {
344 unsigned int width, height, bw, depth;
346 if (XGetGeometry(XtDisplay(lw), lw->label.pixmap, &root, &x, &y,
347 &width, &height, &bw, &depth)) {
348 lw->label.label_height = height;
349 lw->label.label_width = width;
350 lw->label.label_len = depth;
354 if (lw->simple.international == True) {
355 XFontSet fset = lw->label.fontset;
356 XFontSetExtents *ext = XExtentsOfFontSet(fset);
358 lw->label.label_height = ext->max_ink_extent.height;
359 if (lw->label.label == NULL) {
360 lw->label.label_len = 0;
361 lw->label.label_width = 0;
363 else if ((nl = index(lw->label.label, '\n')) != NULL) {
366 lw->label.label_len = MULTI_LINE_LABEL;
367 lw->label.label_width = 0;
368 for (label = lw->label.label; nl != NULL; nl = index(label, '\n')) {
369 int width = XmbTextEscapement(fset, label, (int)(nl - label));
371 if (width > (int)lw->label.label_width)
372 lw->label.label_width = width;
375 lw->label.label_height += ext->max_ink_extent.height;
378 int width = XmbTextEscapement(fset, label, strlen(label));
380 if (width > (int)lw->label.label_width)
381 lw->label.label_width = width;
385 lw->label.label_len = strlen(lw->label.label);
386 lw->label.label_width =
387 XmbTextEscapement(fset, lw->label.label, lw->label.label_len);
391 lw->label.label_height = fs->max_bounds.ascent + fs->max_bounds.descent;
392 if (lw->label.label == NULL) {
393 lw->label.label_len = 0;
394 lw->label.label_width = 0;
396 else if ((nl = index(lw->label.label, '\n')) != NULL) {
399 lw->label.label_len = MULTI_LINE_LABEL;
400 lw->label.label_width = 0;
401 for (label = lw->label.label; nl != NULL; nl = index(label, '\n')) {
404 if (lw->label.encoding)
405 width = XTextWidth16(fs, (TXT16*)label, (int)(nl - label) / 2);
407 width = XTextWidth(fs, label, (int)(nl - label));
408 if (width > (int)lw->label.label_width)
409 lw->label.label_width = width;
412 lw->label.label_height +=
413 fs->max_bounds.ascent + fs->max_bounds.descent;
416 int width = XTextWidth(fs, label, strlen(label));
418 if (lw->label.encoding)
419 width = XTextWidth16(fs, (TXT16*)label, strlen(label) / 2);
421 width = XTextWidth(fs, label, strlen(label));
422 if (width > (int) lw->label.label_width)
423 lw->label.label_width = width;
427 lw->label.label_len = strlen(lw->label.label);
428 if (lw->label.encoding)
429 lw->label.label_width =
430 XTextWidth16(fs, (TXT16*)lw->label.label,
431 (int)lw->label.label_len / 2);
433 lw->label.label_width =
434 XTextWidth(fs, lw->label.label, (int)lw->label.label_len);
440 GetNormalGC(LabelWidget lw)
444 values.foreground = lw->label.foreground;
445 values.background = lw->core.background_pixel;
446 values.font = lw->label.font->fid;
447 values.graphics_exposures = False;
449 if (lw->simple.international == True)
450 /* Since Xmb/wcDrawString eats the font, I must use XtAllocateGC */
451 lw->label.normal_GC = XtAllocateGC((Widget)lw, 0,
452 GCForeground | GCBackground |
456 lw->label.normal_GC = XtGetGC((Widget)lw,
457 GCForeground | GCBackground | GCFont |
458 GCGraphicsExposures, &values);
462 GetGrayGC(LabelWidget lw)
466 values.foreground = lw->label.foreground;
467 values.background = lw->core.background_pixel;
468 values.font = lw->label.font->fid;
469 values.fill_style = FillTiled;
470 values.tile = XmuCreateStippledPixmap(XtScreen((Widget)lw),
471 lw->label.foreground,
472 lw->core.background_pixel,
474 values.graphics_exposures = False;
476 lw->label.stipple = values.tile;
477 if (lw->simple.international == True)
478 /* Since Xmb/wcDrawString eats the font, I must use XtAllocateGC */
479 lw->label.gray_GC = XtAllocateGC((Widget)lw, 0,
480 GCForeground | GCBackground |
481 GCTile | GCFillStyle |
485 lw->label.gray_GC = XtGetGC((Widget)lw,
486 GCForeground | GCBackground |
487 GCFont | GCTile | GCFillStyle |
493 compute_bitmap_offsets(LabelWidget lw)
496 * bitmap will be eventually be displayed at
497 * (internal_width, internal_height + lbm_y)
499 if (lw->label.lbm_height != 0)
500 lw->label.lbm_y = (XtHeight(lw) - (lw->label.internal_height * 2 +
501 lw->label.lbm_height)) / 2;
507 set_bitmap_info(LabelWidget lw)
511 unsigned int bw, depth;
513 if (!(lw->label.left_bitmap
514 && XGetGeometry(XtDisplay(lw), lw->label.left_bitmap, &root, &x, &y,
515 &lw->label.lbm_width, &lw->label.lbm_height,
517 lw->label.lbm_width = lw->label.lbm_height = 0;
519 compute_bitmap_offsets(lw);
524 XawLabelInitialize(Widget request, Widget cnew,
525 ArgList args, Cardinal *num_args)
527 LabelWidget lw = (LabelWidget)cnew;
529 if (!lw->label.font) XtError("Aborting: no font found\n");
530 if (lw->simple.international && !lw->label.fontset)
531 XtError("Aborting: no fontset found\n");
533 if (lw->label.label == NULL)
534 lw->label.label = XtNewString(lw->core.name);
536 lw->label.label = XtNewString(lw->label.label);
541 SetTextWidthAndHeight(lw);
543 if (XtHeight(lw) == 0)
544 XtHeight(lw) = lw->label.label_height + 2 * lw->label.internal_height;
546 set_bitmap_info(lw); /* need core.height */
548 if (XtWidth(lw) == 0) /* need label.lbm_width */
549 XtWidth(lw) = lw->label.label_width + 2 * lw->label.internal_width +
552 lw->label.label_x = lw->label.label_y = 0;
553 (*XtClass(cnew)->core_class.resize)((Widget)lw);
558 XawLabelRedisplay(Widget gw, XEvent *event, Region region)
560 LabelWidget w = (LabelWidget)gw;
563 if (*Superclass->core_class.expose != NULL)
564 (*Superclass->core_class.expose)(gw, event, region);
566 gc = XtIsSensitive(gw) ? w->label.normal_GC : w->label.gray_GC;
569 XSetRegion(XtDisplay(gw), gc, region);
572 if (w->label.pixmap == None) {
573 int len = w->label.label_len;
574 char *label = w->label.label;
575 Position y = w->label.label_y + w->label.font->max_bounds.ascent;
576 Position ksy = w->label.label_y;
578 /* display left bitmap */
579 if (w->label.left_bitmap && w->label.lbm_width != 0)
580 XCopyPlane (XtDisplay(gw), w->label.left_bitmap, XtWindow(gw), gc,
581 0, 0, w->label.lbm_width, w->label.lbm_height,
582 w->label.internal_width,
583 w->label.internal_height + w->label.lbm_y, 1L);
585 if (w->simple.international == True) {
586 XFontSetExtents *ext = XExtentsOfFontSet(w->label.fontset);
588 ksy += XawAbs(ext->max_ink_extent.y);
590 if (len == MULTI_LINE_LABEL) {
593 while ((nl = index(label, '\n')) != NULL) {
594 XmbDrawString(XtDisplay(w), XtWindow(w), w->label.fontset,
595 gc, w->label.label_x, ksy, label,
597 ksy += ext->max_ink_extent.height;
603 XmbDrawString(XtDisplay(w), XtWindow(w), w->label.fontset, gc,
604 w->label.label_x, ksy, label, len);
607 if (len == MULTI_LINE_LABEL) {
610 while ((nl = index(label, '\n')) != NULL) {
611 if (w->label.encoding)
612 XDrawString16(XtDisplay(gw), XtWindow(gw), gc,
614 (TXT16*)label, (int)(nl - label) / 2);
616 XDrawString(XtDisplay(gw), XtWindow(gw), gc,
617 w->label.label_x, y, label, (int)(nl - label));
618 y += w->label.font->max_bounds.ascent +
619 w->label.font->max_bounds.descent;
625 if (w->label.encoding)
626 XDrawString16(XtDisplay(gw), XtWindow(gw), gc,
627 w->label.label_x, y, (TXT16*)label, len / 2);
629 XDrawString(XtDisplay(gw), XtWindow(gw), gc,
630 w->label.label_x, y, label, len);
634 else if (w->label.label_len == 1)
635 XCopyPlane(XtDisplay(gw), w->label.pixmap, XtWindow(gw), gc,
636 0, 0, w->label.label_width, w->label.label_height,
637 w->label.label_x, w->label.label_y, 1L);
639 XCopyArea(XtDisplay(gw), w->label.pixmap, XtWindow(gw), gc,
640 0, 0, w->label.label_width, w->label.label_height,
641 w->label.label_x, w->label.label_y);
645 XSetClipMask(XtDisplay(gw), gc, (Pixmap)None);
650 _Reposition(LabelWidget lw, unsigned int width, unsigned int height,
651 Position *dx, Position *dy)
654 Position leftedge = lw->label.internal_width + LEFT_OFFSET(lw);
656 switch (lw->label.justify) {
661 newPos = width - (lw->label.label_width + lw->label.internal_width);
663 case XtJustifyCenter:
666 newPos = (int)(width - lw->label.label_width) >> 1;
669 if (newPos < (Position)leftedge)
671 *dx = newPos - lw->label.label_x;
672 lw->label.label_x = newPos;
674 newPos = (height - lw->label.label_height) >> 1;
675 *dy = newPos - lw->label.label_y;
676 lw->label.label_y = newPos;
680 XawLabelResize(Widget w)
682 LabelWidget lw = (LabelWidget)w;
685 _Reposition(lw, XtWidth(w), XtHeight(w), &dx, &dy);
686 compute_bitmap_offsets(lw);
694 XawLabelSetValues(Widget current, Widget request, Widget cnew,
695 ArgList args, Cardinal *num_args)
697 LabelWidget curlw = (LabelWidget)current;
698 LabelWidget reqlw = (LabelWidget)request;
699 LabelWidget newlw = (LabelWidget)cnew;
701 Boolean was_resized = False, redisplay = False, checks[NUM_CHECKS];
703 for (i = 0; i < NUM_CHECKS; i++)
706 for (i = 0; i < *num_args; i++) {
707 if (streq(XtNbitmap, args[i].name))
708 checks[PIXMAP] = True;
709 else if (streq(XtNwidth, args[i].name))
710 checks[WIDTH] = True;
711 else if (streq(XtNheight, args[i].name))
712 checks[HEIGHT] = True;
715 if (newlw->label.label == NULL)
716 newlw->label.label = newlw->core.name;
719 * resize on bitmap change
721 if (curlw->label.left_bitmap != newlw->label.left_bitmap)
724 if (curlw->label.encoding != newlw->label.encoding)
727 if (curlw->simple.international
728 && curlw->label.fontset != newlw->label.fontset)
731 if (curlw->label.label != newlw->label.label) {
732 if (curlw->label.label != curlw->core.name)
733 XtFree((char *)curlw->label.label);
735 if (newlw->label.label != newlw->core.name)
736 newlw->label.label = XtNewString(newlw->label.label);
741 if (was_resized || (curlw->label.font != newlw->label.font) ||
742 curlw->label.justify != newlw->label.justify || checks[PIXMAP]) {
743 SetTextWidthAndHeight(newlw);
747 /* recalculate the window size if something has changed */
748 if (newlw->label.resize && was_resized) {
749 if (XtHeight(curlw) == XtHeight(reqlw) && !checks[HEIGHT])
750 XtHeight(newlw) = newlw->label.label_height +
751 (newlw->label.internal_height << 1);
753 set_bitmap_info(newlw);
755 if (XtWidth(curlw) == XtWidth(reqlw) && !checks[WIDTH])
756 XtWidth(newlw) = newlw->label.label_width + LEFT_OFFSET(newlw) +
757 (newlw->label.internal_width << 1);
760 if (curlw->label.foreground != newlw->label.foreground
761 || curlw->core.background_pixel != newlw->core.background_pixel
762 || curlw->label.font->fid != newlw->label.font->fid) {
763 /* The Fontset is not in the GC - don't make a new GC if FS changes! */
764 XtReleaseGC(cnew, curlw->label.normal_GC);
765 XtReleaseGC(cnew, curlw->label.gray_GC);
766 XmuReleaseStippledPixmap(XtScreen(current), curlw->label.stipple);
772 if (curlw->label.label_x != newlw->label.label_x ||
773 curlw->label.label_y != newlw->label.label_y)
776 if (curlw->label.internal_width != newlw->label.internal_width
777 || curlw->label.internal_height != newlw->label.internal_height
779 /* Resize() will be called if geometry changes succeed */
782 _Reposition(newlw, XtWidth(curlw), XtHeight(curlw), &dx, &dy);
785 return (was_resized || redisplay ||
786 XtIsSensitive(current) != XtIsSensitive(cnew));
790 XawLabelDestroy(Widget w)
792 LabelWidget lw = (LabelWidget)w;
794 if (lw->label.label != lw->core.name)
795 XtFree(lw->label.label);
796 XtReleaseGC(w, lw->label.normal_GC);
797 XtReleaseGC(w, lw->label.gray_GC);
798 XmuReleaseStippledPixmap(XtScreen(w), lw->label.stipple);
801 static XtGeometryResult
802 XawLabelQueryGeometry(Widget w, XtWidgetGeometry *intended,
803 XtWidgetGeometry *preferred)
805 LabelWidget lw = (LabelWidget)w;
807 preferred->request_mode = CWWidth | CWHeight;
808 preferred->width = lw->label.label_width +
809 (lw->label.internal_width << 1) + LEFT_OFFSET(lw);
810 preferred->height = lw->label.label_height +
811 (lw->label.internal_height << 1);
813 if (((intended->request_mode & (CWWidth | CWHeight)) == (CWWidth | CWHeight))
814 && intended->width == preferred->width
815 && intended->height == preferred->height)
816 return (XtGeometryYes);
817 else if (preferred->width == XtWidth(w) && preferred->height == XtHeight(w))
818 return (XtGeometryNo);
820 return (XtGeometryAlmost);