(3)

NAME
XfwfLabel

DESCRIPTION
The Label class has the capability to display one or more lines of text in a single font. Otherwise it is the same as the Board class. The text can be left, right or center justified and it can be centered vertically or put against the top or the bottom of the widget. There is also a resource to set tab stops. The text is `grayed out' when the widget becomes insensitive (resource: sensitive), even though a Label widget has no actions of its own. There are two ways of highlighting portions of the label: reversing the colors or changing the foreground. Both methods can be combined, though the result when both highlighting methods are applied to the same part of the text is undefined.

  Public variables
XfwfLabel
Name | Class | Type | Default
XtNlabel | XtCLabel | String | NULL
XtNtablist | XtCTablist | String | NULL
XtNfont | XtCFont | FontStruct | XtDefaultFont
XtNforeground | XtCForeground | Pixel | XtDefaultForeground
XtNhlForeground | XtCHlForeground | Pixel | XtDefaultForeground
XtNalignment | XtCAlignment | Alignment | 0
XtNtopMargin | XtCTopMargin | Dimension | 2
XtNbottomMargin | XtCBottomMargin | Dimension | 2
XtNleftMargin | XtCLeftMargin | Dimension | 2
XtNrightMargin | XtCRightMargin | Dimension | 2
XtNshrinkToFit | XtCShrinkToFit | Boolean | False
XtNrvStart | XtCRvStart | int | 0
XtNrvLength | XtCRvLength | int | 0
XtNhlStart | XtCHlStart | int | 0
XtNhlLength | XtCHlLength | int | 0

XtNlabel
    The text is a single string, which may contain embedded newlines. There is no provision for changing fonts in the middle of a text.

    String label = NULL

XtNtablist
    A tablist can be provided for tabbing to particular columns within the label.

    String tablist = NULL

XtNfont
    The text is drawn in the font which is given as the font resource.

    <FontStruct> XFontStruct * font = <String>XtDefaultFont

XtNforeground
    The foreground color is the color used to draw the text. hlForeground is the foreground for highlighted text.

    Pixel foreground = <String>XtDefaultForeground

XtNhlForeground
    Pixel hlForeground = <String>XtDefaultForeground

XtNalignment
    The text can be aligned in the widget in nine ways: left, right or center, combined with top, center or bottom. Symbolic constants XfwfTop, XfwfBottom, XfwfLeft and XfwfRight can be added together to get the desired alignment. The alignment is actually a four-bit number made up of two parts of 2 bits added together: 1 is left, 2 is right, 0 is center, 4 is top, 8 is bottom, 0 is vertical center. Thus 5 (= 1 + 4) means top left and 2 (= 2 + 0) means center right. For easier specification, there is also a converter from strings, that accepts string like `top left' or `center right'.

    Alignment alignment = 0

XtNtopMargin
    The topmargin is only used when the text is not centered. It gives the number of pixels between the frame and the top of the text.

    Dimension topMargin = 2

XtNbottomMargin
    The bottomMargin is only used to compute the preferred size of the button in case shrinkToFit = True.

    Dimension bottomMargin = 2

XtNleftMargin
    The leftMargin is only used when the text is not centered. It gives the number of pixels between the frame and the left edge of the text, and if possible also between the frame and the right edge of the text.

    Dimension leftMargin = 2

XtNrightMargin
    The rightMargin is only used to compute the preferred size of the button in case shrinkToFit = True.

    Dimension rightMargin = 2

XtNshrinkToFit
    Buttons will normally not occupy the full area of their parents. Most likely they will be a fixed size or a size depending on the label. By setting the shrinkToFit resource to True, the width and height are recomputed with every new label.

    Boolean shrinkToFit = False

XtNrvStart
    It is possible to set a part of the label apart by drawing it in reverse. The rvStart resource gives the index of the first character to draw in reverse video.

    int rvStart = 0

XtNrvLength
    The rvLength resource contains the number of characters to draw in reverse video.

    int rvLength = 0

XtNtraversalOn
    A label normally needs no keyboard interface, therefore traversal is turned off.

     traversalOn = False

XtNhlStart
    The start and length of the highlighted portion are set with the resources hlStart and hlLength.

    int hlStart = 0

XtNhlLength
    int hlLength = 0
    XfwfBoard
    Name | Class | Type | Default
    XtNabs_x | XtCAbs_x | Position | 0
    XtNrel_x | XtCRel_x | Float | "0.0"
    XtNabs_y | XtCAbs_y | Position | 0
    XtNrel_y | XtCRel_y | Float | "0.0"
    XtNabs_width | XtCAbs_width | Position | 0
    XtNrel_width | XtCRel_width | Float | "1.0"
    XtNabs_height | XtCAbs_height | Position | 0
    XtNrel_height | XtCRel_height | Float | "1.0"
    XtNhunit | XtCHunit | Float | "1.0"
    XtNvunit | XtCVunit | Float | "1.0"
    XtNlocation | XtCLocation | String | NULL
    XfwfFrame
    Name | Class | Type | Default
    XtNcursor | XtCCursor | Cursor | None
    XtNframeType | XtCFrameType | FrameType | XfwfRaised
    XtNframeWidth | XtCFrameWidth | Dimension | 0
    XtNouterOffset | XtCOuterOffset | Dimension | 0
    XtNinnerOffset | XtCInnerOffset | Dimension | 0
    XtNshadowScheme | XtCShadowScheme | ShadowScheme | XfwfAuto
    XtNtopShadowColor | XtCTopShadowColor | Pixel | compute_topcolor
    XtNbottomShadowColor | XtCBottomShadowColor | Pixel | compute_bottomcolor
    XtNtopShadowStipple | XtCTopShadowStipple | Bitmap | NULL
    XtNbottomShadowStipple | XtCBottomShadowStipple | Bitmap | NULL
    XfwfCommon
    Name | Class | Type | Default
    XtNtraversalOn | XtCTraversalOn | Boolean | True
    XtNhighlightThickness | XtCHighlightThickness | Dimension | 2
    XtNhighlightColor | XtCHighlightColor | Pixel | XtDefaultForeground
    XtNhighlightPixmap | XtCHighlightPixmap | Pixmap | None
    XtNnextTop | XtCNextTop | Callback | NULL
    XtNuserData | XtCUserData | Pointer | NULL
    Composite
    Name | Class | Type | Default
    XtNchildren | XtCChildren | WidgetList | NULL
    insertPosition | XtCInsertPosition | XTOrderProc | NULL
    numChildren | XtCNumChildren | Cardinal | 0
    Core
    Name | Class | Type | Default
    XtNx | XtCX | Position | 0
    XtNy | XtCY | Position | 0
    XtNwidth | XtCWidth | Dimension | 0
    XtNheight | XtCHeight | Dimension | 0
    borderWidth | XtCBorderWidth | Dimension | 0
    XtNcolormap | XtCColormap | Colormap | NULL
    XtNdepth | XtCDepth | Int | 0
    destroyCallback | XtCDestroyCallback | XTCallbackList | NULL
    XtNsensitive | XtCSensitive | Boolean | True
    XtNtm | XtCTm | XTTMRec | NULL
    ancestorSensitive | XtCAncestorSensitive | Boolean | False
    accelerators | XtCAccelerators | XTTranslations | NULL
    borderColor | XtCBorderColor | Pixel | 0
    borderPixmap | XtCBorderPixmap | Pixmap | NULL
    background | XtCBackground | Pixel | 0
    backgroundPixmap | XtCBackgroundPixmap | Pixmap | NULL
    mappedWhenManaged | XtCMappedWhenManaged | Boolean | True
    XtNscreen | XtCScreen | Screen * | NULL

Importss
incl
 "stip4.bm"
incl
 <stdio.h>
incl
 <Xfwf/TabString.h>

  Private variables
For faster drawing, the number of lines in the text is stored in a private variable by the set_values and initialize methods.

int  nlines
The tablist is converted from string format to a list of int's for speed.

int * tabs
For drawing the text, this GC is used.

GC  gc
This GC is for the text that is drawn in reverse video.

GC  rv_gc
The GC for the highlighted portion of the text

GC  hl_gc
For graying out the text, another GC is used.

GC  graygc
When the shrinkToFit resource is set, we need the minimum area necessary for the complete label to be visible. label_width and label_height include the size of margin.

Dimension  label_width
Dimension  label_height

  Methods
The new method set_label makes a copy of the string that is passed in, counts the number of lines and also draws the new label. This could have been done in set_values, but it is expected that subclasses will redraw the label frequently, so a more efficient way is provided. Note that this method does not resize the widget in case shrinkToFit is set.
set_label($, String  newlabel)
{
    Position x, y;
    Dimension w, h;
    XtFree($label);
    $label = XtNewString(newlabel);
    count_lines($);
    if (XtIsRealized($)) {
	$compute_inside($, x, y, w, h);
	XClearArea(XtDisplay($), XtWindow($), x, y, w, h, True);
	/* $expose($, NULL, NULL); */
    }
}
The set_values method checks the background resource, because is is used in the GC graygc. When the text or the font change, the private variables nlines, label_height and label_width are updated. need_count is set to True if the size of the label changes. need_count implies need_redisplay.
Boolean  set_values(Widget  old, Widget  request, $, ArgList  args, Cardinal * num_args)
{
    Boolean need_redisplay = False, need_count = False;
    Position x, y;
    Dimension w, h, wd, ht;
    if ($background_pixel != $old$background_pixel)
	make_graygc($);
    if ($tablist != $old$tablist) {
	XtFree((String) $old$tabs);
	$tabs = XfwfTablist2Tabs($tablist);
	if ($label != NULL) need_count = True;
    }
    if ($font != $old$font) {
	make_gc($);
	if ($label != NULL) need_count = True;
    }
    if ($foreground != $old$foreground
 	|| $hlForeground != $hlForeground
	|| $background_pixel != $old$background_pixel) {
	make_gc($);
	if ($label != NULL) need_redisplay = True;
    }
    if ($topMargin != $old$topMargin
	|| $bottomMargin != $old$bottomMargin
	|| $leftMargin != $old$leftMargin
	|| $rightMargin != $old$rightMargin)
	need_count = True;
    if ($sensitive != $old$sensitive)
	if ($label != NULL) need_redisplay = True;
    if ($rvStart != $old$rvStart || $rvLength != $old$rvLength
 	|| $hlStart != $old$hlStart || $hlLength != $old$hlLength)
	if ($label != NULL) need_redisplay = True;
    if ($label != $old$label) {
	XtFree($old$label);
	$label = XtNewString($label);
	need_count = True;
    }
    if (need_count) {
	count_lines($);
	need_redisplay = True;
    }
    if (need_count  $shrinkToFit) {
	$compute_inside($, x, y, w, h);
	wd = $label_width + $width - w;
	ht = $label_height + $height - h;
	if (wd != $width || ht != $height) {
	    $set_abs_location($, CWWidth | CWHeight, 0, 0, wd, ht);
	    need_redisplay = False;
	}
    }
    return need_redisplay;
}
The initialize methods creates the first GC's and initializes the private variables. It sets the GC's to NULL and calls two utility routines to actually create them.
initialize(Widget  request, $, ArgList  args, Cardinal * num_args)
{
    char *s;
    Position x, y;
    Dimension w, h, wd, ht;
    if ($label) $label = XtNewString($label);
    count_lines($);
    $gc = NULL;
    $rv_gc = NULL;
    $graygc = NULL;
    $hl_gc = NULL;
    make_gc($);
    make_graygc($);
    $tabs = XfwfTablist2Tabs($tablist);
    if ($shrinkToFit) {
	$compute_inside($, x, y, w, h);
	wd = $label_width + $width - w;
	ht = $label_height + $height - h;
	$set_abs_location($, CWWidth | CWHeight, 0, 0, wd, ht);
    }
}
The expose method is responsible for drawing the text. The text is put in the position given in alignment. The text is always kept within the frame. If necessary, the text is clipped. The routine ends by calling the expose method from the superclass, which is responsible for drawing the frame. The part of the text that is to appear in reverse video is drawn with the rv_gc GC. def draw_line(dpy, win, from, to) = do {
    if ($hlStart >= to) hstart = to;
     else hstart = max($hlStart, from);
    if ($hlStart + $hlLength <= from) hend = hstart;
     else hend = min($hlStart + $hlLength, to);
        if ($rvStart >= to) rstart = to;
    else rstart = max($rvStart, from);
    if ($rvStart + $rvLength <= from) rend = rstart;
    else rend = min($rvStart + $rvLength, to);
    w1 = XfwfTextWidth($font, $label + from, rstart - from, $tabs);
    w2 = XfwfTextWidth($font, $label + rstart, rend - rstart, $tabs);
    w3 = XfwfTextWidth($font, $label + rend, to - rend, $tabs);
     w4 = XfwfTextWidth($font, $label + hstart, hend - hstart, $tabs);
     w5 = XfwfTextWidth($font, $label + from, hstart - from, $tabs);
    if ($alignment XfwfLeft)
        x = rect.x;
    else if ($alignment XfwfRight)
        x = rect.x + rect.width - w1 - w2 - w3;
    else
        x = rect.x + (rect.width - w1 - w2 - w3)/2;
    if (w1)
        XfwfDrawImageString(dpy, win, $gc, x, y, $label + from,
                 rstart - from, $tabs);
    if (w2)
        XfwfDrawImageString(dpy, win, $rv_gc, x + w1, y, $label
                 + rstart, rend - rstart, $tabs);
    if (w3)
        XfwfDrawImageString(dpy, win, $gc, x + w1 + w2, y, $label +
                 rend, to - rend, $tabs);
     if (w4)
         XfwfDrawString(dpy, win, $hl_gc, x + w5, y, $label
                  + hstart, hend - hstart, $tabs);
    }while (0 )
expose($, XEvent * event, Region  region)
{
    Region reg;
    XRectangle rect;
    int baseline;
    int w1, w2, w3, w4, w5;
    char *s, *t;
    int x, y, i, j, rstart, rend, hstart, hend;
    if (! XtIsRealized($)) return;
    #expose($, event, region);
    if ($label != NULL) {
	baseline = $font->ascent + $font->descent;
	$compute_inside($, rect.x, rect.y, rect.width, rect.height);
	rect.x += $leftMargin;  rect.width -= $leftMargin + $rightMargin;
	rect.y += $topMargin;  rect.height -= $topMargin + $bottomMargin;
	reg = XCreateRegion();
	XUnionRectWithRegion(rect, reg, reg);
	if (region != NULL) XIntersectRegion(region, reg, reg);
	XSetRegion(XtDisplay($), $gc, reg);
	XSetRegion(XtDisplay($), $rv_gc, reg);
 	XSetRegion(XtDisplay($), $hl_gc, reg);
	if ($alignment  XfwfTop)
	    y = rect.y + $font->ascent;
	else if ($alignment  XfwfBottom)
	    y = rect.y + rect.height - $nlines * baseline + $font->ascent;
	else
	    y = rect.y + (rect.height - $nlines * baseline)/2 + $font->ascent;
	for (i = 0, j = 0; $label[i]; i++) {
	    if ($label[i] == '\n') {
		draw_line(XtDisplay($), XtWindow($), j, i);
		j = i + 1;
		y += baseline;
	    }
	}
	draw_line(XtDisplay($), XtWindow($), j, i);
	/* Gray out if not sensitive */
	if (! $sensitive) {
	    XSetRegion(XtDisplay($), $graygc, reg);
	    XFillRectangle(XtDisplay($), XtWindow($), $graygc, rect.x,
			   rect.y, rect.width, rect.height);
	    XSetClipMask(XtDisplay($), $graygc, None);
	}
	XSetClipMask(XtDisplay($), $gc, None);
	XSetClipMask(XtDisplay($), $rv_gc, None);
 	XSetClipMask(XtDisplay($), $hl_gc, None);
    }
}

Utilities
The make_gc routine creates the GCs for the normal and highlighted text.
make_gc($)
{
    XtGCMask mask;
    XGCValues values;
    if ($gc != NULL) XtReleaseGC($, $gc);
    values.background = $background_pixel;
    values.foreground = $foreground;
    values.font = $font->fid;
    mask = GCFont | GCBackground | GCForeground;
    $gc = XtGetGC($, mask, values);
    if ($rv_gc != NULL) XtReleaseGC($, $rv_gc);
    values.foreground = $background_pixel;
    values.background = $foreground;
    values.font = $font->fid;
    mask = GCFont | GCBackground | GCForeground;
    $rv_gc = XtGetGC($, mask, values);
    if ($hl_gc != NULL) XtReleaseGC($, $hl_gc);
    values.background = $background_pixel;
    values.foreground = $hlForeground;
    values.font = $font->fid;
    values.function = GXcopy;
    $hl_gc = XtGetGC($, mask, values);
}
The make_graygc routine creates a GC for graying out the text. It contains a stipple in the background color, that will be applied over the text.
make_graygc($)
{
    XtGCMask mask;
    XGCValues values;
    if ($graygc != NULL) XtReleaseGC($, $graygc);
    values.foreground = $background_pixel;
    values.stipple =
	XCreateBitmapFromData(XtDisplay($),
			      RootWindowOfScreen(XtScreen($)),
			      stip4_bits, stip4_width, stip4_height);
    values.fill_style = FillStippled;
    mask = GCForeground | GCStipple | GCFillStyle;
    $graygc = XtGetGC($, mask, values);
}
The funtion count_lines computes the correct values for the private variables nlines, label_width and label_height.
count_lines($)
{
    String p, s;
    int w;
    $nlines = 0;
    $label_width = 0;
    if ($label) {
	for (p = $label, $nlines = 1, s = $label; *s; s++) {
	    if (*s == '\n') {
		$nlines++;
		w = XfwfTextWidth($font, p, s - p, $tabs);
		p = s + 1;
		if (w > $label_width) $label_width = w;
	    }
	}
	w = XfwfTextWidth($font, p, s - p, $tabs);
	if (w > $label_width) $label_width = w;
    }
    $label_height = $nlines * ($font->ascent + $font->descent);
    $label_width += $leftMargin + $rightMargin;
    $label_height += $topMargin + $bottomMargin;
}