749N/A#ifndef lint
749N/Astatic char Xrcsid[] = "$XConsortium: Label.c,v 1.77 89/12/08 12:35:36 swick Exp $";
749N/A#endif /* lint */
749N/A
749N/A
749N/A/***********************************************************
749N/ACopyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts,
749N/Aand the Massachusetts Institute of Technology, Cambridge, Massachusetts.
749N/A
749N/A All Rights Reserved
749N/A
749N/APermission to use, copy, modify, and distribute this software and its
749N/Adocumentation for any purpose and without fee is hereby granted,
749N/Aprovided that the above copyright notice appear in all copies and that
749N/Aboth that copyright notice and this permission notice appear in
749N/Asupporting documentation, and that the names of Digital or MIT not be
749N/Aused in advertising or publicity pertaining to distribution of the
749N/Asoftware without specific, written prior permission.
749N/A
749N/ADIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
749N/AALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
749N/ADIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
749N/AANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
749N/AWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
749N/AARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
749N/ASOFTWARE.
749N/A
749N/A******************************************************************/
749N/A
749N/A/*
749N/A * Label.c - Label widget
749N/A *
749N/A */
749N/A
749N/A#define XtStrlen(s) ((s) ? strlen(s) : 0)
749N/A
749N/A#include <stdio.h>
749N/A#include <ctype.h>
749N/A#include <X11/IntrinsicP.h>
749N/A#include <X11/StringDefs.h>
749N/A#include <./Xaw3_1XawInit.h>
749N/A#include <./Xaw3_1LabelP.h>
749N/A
749N/A#ifdef SYSV
749N/A#ifndef index
749N/A#define index(a,b) strchr(a,b)
749N/A#endif
749N/A#endif
749N/A
749N/A#define streq(a,b) (strcmp( (a), (b) ) == 0)
749N/A
749N/A#define MULTI_LINE_LABEL 32767
749N/A
749N/A/****************************************************************
749N/A *
749N/A * Full class record constant
749N/A *
749N/A ****************************************************************/
749N/A
749N/A/* Private Data */
749N/A
749N/A#define offset(field) XtOffset(LabelWidget, field)
749N/Astatic XtResource resources[] = {
749N/A {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
749N/A offset(label.foreground), XtRString, "XtDefaultForeground"},
749N/A {XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct *),
749N/A offset(label.font),XtRString, "XtDefaultFont"},
749N/A {XtNlabel, XtCLabel, XtRString, sizeof(String),
749N/A offset(label.label), XtRString, NULL},
749N/A {XtNjustify, XtCJustify, XtRJustify, sizeof(XtJustify),
749N/A offset(label.justify), XtRImmediate, (caddr_t)XtJustifyCenter},
749N/A {XtNinternalWidth, XtCWidth, XtRDimension, sizeof(Dimension),
749N/A offset(label.internal_width), XtRImmediate, (caddr_t)4},
749N/A {XtNinternalHeight, XtCHeight, XtRDimension, sizeof(Dimension),
749N/A offset(label.internal_height), XtRImmediate, (caddr_t)2},
749N/A {XtNbitmap, XtCPixmap, XtRBitmap, sizeof(Pixmap),
749N/A offset(label.pixmap), XtRImmediate, (caddr_t)None},
749N/A {XtNresize, XtCResize, XtRBoolean, sizeof(Boolean),
749N/A offset(label.resize), XtRImmediate, (caddr_t)True},
749N/A};
749N/A
749N/Astatic void Initialize();
749N/Astatic void Resize();
749N/Astatic void Redisplay();
749N/Astatic Boolean SetValues();
749N/Astatic void ClassInitialize();
749N/Astatic void Destroy();
749N/Astatic XtGeometryResult QueryGeometry();
749N/A
749N/ALabelClassRec labelClassRec = {
749N/A {
749N/A/* core_class fields */
749N/A#define superclass (&simpleClassRec)
749N/A /* superclass */ (WidgetClass) superclass,
749N/A /* class_name */ "Label",
749N/A /* widget_size */ sizeof(LabelRec),
749N/A /* class_initialize */ ClassInitialize,
749N/A /* class_part_initialize */ NULL,
749N/A /* class_inited */ FALSE,
749N/A /* initialize */ Initialize,
749N/A /* initialize_hook */ NULL,
749N/A /* realize */ XtInheritRealize,
749N/A /* actions */ NULL,
749N/A /* num_actions */ 0,
749N/A /* resources */ resources,
749N/A /* num_resources */ XtNumber(resources),
749N/A /* xrm_class */ NULLQUARK,
749N/A /* compress_motion */ TRUE,
749N/A /* compress_exposure */ TRUE,
749N/A /* compress_enterleave */ TRUE,
749N/A /* visible_interest */ FALSE,
749N/A /* destroy */ Destroy,
749N/A /* resize */ Resize,
749N/A /* expose */ Redisplay,
749N/A /* set_values */ SetValues,
749N/A /* set_values_hook */ NULL,
749N/A /* set_values_almost */ XtInheritSetValuesAlmost,
749N/A /* get_values_hook */ NULL,
749N/A /* accept_focus */ NULL,
749N/A /* version */ XtVersion,
749N/A /* callback_private */ NULL,
749N/A /* tm_table */ NULL,
749N/A /* query_geometry */ QueryGeometry,
749N/A /* display_accelerator */ XtInheritDisplayAccelerator,
749N/A /* extension */ NULL
749N/A },
749N/A/* Simple class fields initialization */
749N/A {
749N/A /* change_sensitive */ XtInheritChangeSensitive
749N/A }
749N/A};
749N/AWidgetClass labelWidgetClass = (WidgetClass)&labelClassRec;
749N/A/****************************************************************
749N/A *
749N/A * Private Procedures
749N/A *
749N/A ****************************************************************/
749N/A
749N/Astatic void ClassInitialize()
749N/A{
749N/A extern void XmuCvtStringToJustify();
749N/A extern void XmuCvtStringToBitmap();
749N/A static XtConvertArgRec screenConvertArg[] = {
749N/A {XtWidgetBaseOffset, (caddr_t) XtOffset(Widget, core.screen),
749N/A sizeof(Screen *)}
749N/A };
749N/A XawInitializeWidgetSet();
749N/A XtAddConverter( XtRString, XtRJustify, XmuCvtStringToJustify, NULL, 0 );
749N/A XtAddConverter("String", "Bitmap", XmuCvtStringToBitmap,
749N/A screenConvertArg, XtNumber(screenConvertArg));
749N/A} /* ClassInitialize */
749N/A
749N/A/*
749N/A * Calculate width and height of displayed text in pixels
749N/A */
749N/A
749N/Astatic void SetTextWidthAndHeight(lw)
749N/A LabelWidget lw;
749N/A{
749N/A register XFontStruct *fs = lw->label.font;
749N/A char *nl;
749N/A
749N/A if (lw->label.pixmap != None) {
749N/A Window root;
749N/A int x, y;
749N/A unsigned int width, height, bw, depth;
749N/A if (XGetGeometry(XtDisplay(lw), lw->label.pixmap, &root, &x, &y,
749N/A &width, &height, &bw, &depth)) {
749N/A lw->label.label_height = height;
749N/A lw->label.label_width = width;
749N/A lw->label.label_len = depth;
749N/A return;
749N/A }
749N/A }
749N/A
749N/A lw->label.label_height = fs->max_bounds.ascent + fs->max_bounds.descent;
749N/A if (lw->label.label == NULL) {
749N/A lw->label.label_len = 0;
749N/A lw->label.label_width = 0;
749N/A }
749N/A else if ((nl = index(lw->label.label, '\n')) != NULL) {
749N/A char *label;
749N/A lw->label.label_len = MULTI_LINE_LABEL;
749N/A lw->label.label_width = 0;
749N/A for (label = lw->label.label; nl != NULL; nl = index(label, '\n')) {
749N/A int width = XTextWidth(fs, label, (int)(nl - label));
749N/A if (width > lw->label.label_width) lw->label.label_width = width;
749N/A label = nl + 1;
749N/A if (*label)
749N/A lw->label.label_height +=
749N/A fs->max_bounds.ascent + fs->max_bounds.descent;
749N/A }
749N/A if (*label) {
749N/A int width = XTextWidth(fs, label, strlen(label));
749N/A if (width > lw->label.label_width) lw->label.label_width = width;
749N/A }
749N/A } else {
749N/A lw->label.label_len = strlen(lw->label.label);
749N/A lw->label.label_width =
749N/A XTextWidth(fs, lw->label.label, (int) lw->label.label_len);
749N/A }
749N/A}
749N/A
749N/Astatic void GetnormalGC(lw)
749N/A LabelWidget lw;
749N/A{
749N/A XGCValues values;
749N/A
749N/A values.foreground = lw->label.foreground;
749N/A values.background = lw->core.background_pixel;
749N/A values.font = lw->label.font->fid;
749N/A
749N/A lw->label.normal_GC = XtGetGC(
749N/A (Widget)lw,
749N/A (unsigned) GCForeground | GCBackground | GCFont,
749N/A &values);
749N/A}
749N/A
749N/Astatic void GetgrayGC(lw)
749N/A LabelWidget lw;
749N/A{
749N/A XGCValues values;
749N/A
749N/A values.foreground = lw->label.foreground;
749N/A values.background = lw->core.background_pixel;
749N/A values.font = lw->label.font->fid;
749N/A values.fill_style = FillTiled;
749N/A values.tile = XmuCreateStippledPixmap(XtScreen((Widget)lw),
749N/A lw->label.foreground,
749N/A lw->core.background_pixel,
749N/A lw->core.depth);
749N/A
749N/A lw->label.stipple = values.tile;
749N/A lw->label.gray_GC = XtGetGC((Widget)lw,
749N/A (unsigned) GCForeground | GCBackground |
749N/A GCFont | GCTile | GCFillStyle,
749N/A &values);
749N/A}
749N/A
749N/A/* ARGSUSED */
749N/Astatic void Initialize(request, new)
749N/A Widget request, new;
749N/A{
749N/A LabelWidget lw = (LabelWidget) new;
749N/A
749N/A if (lw->label.label == NULL)
749N/A lw->label.label = XtNewString(lw->core.name);
749N/A else {
749N/A lw->label.label = XtNewString(lw->label.label);
749N/A }
749N/A
749N/A GetnormalGC(lw);
749N/A GetgrayGC(lw);
749N/A
749N/A SetTextWidthAndHeight(lw);
749N/A
749N/A if (lw->core.width == 0)
749N/A lw->core.width = lw->label.label_width + 2 * lw->label.internal_width;
749N/A if (lw->core.height == 0)
749N/A lw->core.height = lw->label.label_height + 2*lw->label.internal_height;
749N/A
749N/A lw->label.label_x = lw->label.label_y = 0;
749N/A (*XtClass(new)->core_class.resize) ((Widget)lw);
749N/A
749N/A} /* Initialize */
749N/A
749N/A/*
749N/A * Repaint the widget window
749N/A */
749N/A
749N/A/* ARGSUSED */
749N/Astatic void Redisplay(w, event, region)
749N/A Widget w;
749N/A XEvent *event;
749N/A Region region;
749N/A{
749N/A LabelWidget lw = (LabelWidget) w;
749N/A GC gc;
749N/A
749N/A if (region != NULL &&
749N/A XRectInRegion(region, lw->label.label_x, lw->label.label_y,
749N/A lw->label.label_width, lw->label.label_height)
749N/A == RectangleOut)
749N/A return;
749N/A
749N/A gc = XtIsSensitive((Widget)lw) ? lw->label.normal_GC : lw->label.gray_GC;
749N/A#ifdef notdef
749N/A if (region != NULL) XSetRegion(XtDisplay(w), gc, region);
749N/A#endif /*notdef*/
749N/A if (lw->label.pixmap == None) {
749N/A int len = lw->label.label_len;
749N/A char *label = lw->label.label;
749N/A Position y = lw->label.label_y + lw->label.font->max_bounds.ascent;
749N/A if (len == MULTI_LINE_LABEL) {
749N/A char *nl;
749N/A while ((nl = index(label, '\n')) != NULL) {
749N/A XDrawString(
749N/A XtDisplay(w), XtWindow(w), gc, lw->label.label_x,
749N/A y, label, (int)(nl - label));
749N/A y += lw->label.font->max_bounds.ascent + lw->label.font->max_bounds.descent;
749N/A label = nl + 1;
749N/A }
749N/A len = strlen(label);
749N/A }
749N/A if (len)
749N/A XDrawString(
749N/A XtDisplay(w), XtWindow(w), gc, lw->label.label_x,
749N/A y, label, len);
749N/A } else if (lw->label.label_len == 1) { /* depth */
749N/A XCopyPlane(
749N/A XtDisplay(w), lw->label.pixmap, XtWindow(w), gc,
749N/A 0, 0, lw->label.label_width, lw->label.label_height,
749N/A lw->label.label_x, lw->label.label_y, 1L);
749N/A } else {
749N/A XCopyArea(
749N/A XtDisplay(w), lw->label.pixmap, XtWindow(w), gc,
749N/A 0, 0, lw->label.label_width, lw->label.label_height,
749N/A lw->label.label_x, lw->label.label_y);
749N/A }
749N/A#ifdef notdef
749N/A if (region != NULL) XSetClipMask(XtDisplay(w), gc, (Pixmap)None);
749N/A#endif /* notdef */
749N/A}
749N/A
749N/Astatic void _Reposition(lw, width, height, dx, dy)
749N/A register LabelWidget lw;
749N/A Dimension width, height;
749N/A Position *dx, *dy;
749N/A{
749N/A Position newPos;
749N/A switch (lw->label.justify) {
749N/A
749N/A case XtJustifyLeft :
749N/A newPos = lw->label.internal_width;
749N/A break;
749N/A
749N/A case XtJustifyRight :
749N/A newPos = width -
749N/A (lw->label.label_width + lw->label.internal_width);
749N/A break;
749N/A
749N/A case XtJustifyCenter :
749N/A newPos = (width - lw->label.label_width) / 2;
749N/A break;
749N/A }
749N/A if (newPos < (Position)lw->label.internal_width)
749N/A newPos = lw->label.internal_width;
749N/A *dx = newPos - lw->label.label_x;
749N/A lw->label.label_x = newPos;
749N/A *dy = (newPos = (height - lw->label.label_height) / 2) - lw->label.label_y;
749N/A lw->label.label_y = newPos;
749N/A return;
749N/A}
749N/A
749N/Astatic void Resize(w)
749N/A Widget w;
749N/A{
749N/A LabelWidget lw = (LabelWidget)w;
749N/A Position dx, dy;
749N/A _Reposition(lw, w->core.width, w->core.height, &dx, &dy);
749N/A}
749N/A
749N/A/*
749N/A * Set specified arguments into widget
749N/A */
749N/A
749N/A#define PIXMAP 0
749N/A#define WIDTH 1
749N/A#define HEIGHT 2
749N/A#define NUM_CHECKS 3
749N/A
749N/Astatic Boolean SetValues(current, request, new, args, num_args)
749N/A Widget current, request, new;
749N/A ArgList args;
749N/A Cardinal *num_args;
749N/A{
749N/A LabelWidget curlw = (LabelWidget) current;
749N/A LabelWidget reqlw = (LabelWidget) request;
749N/A LabelWidget newlw = (LabelWidget) new;
749N/A int i;
749N/A Boolean was_resized = False, redisplay = False, checks[NUM_CHECKS];
749N/A
749N/A for (i = 0; i < NUM_CHECKS; i++)
749N/A checks[i] = FALSE;
749N/A
749N/A for (i = 0; i < *num_args; i++) {
749N/A if (streq(XtNbitmap, args[i].name))
749N/A checks[PIXMAP] = TRUE;
749N/A if (streq(XtNwidth, args[i].name))
749N/A checks[WIDTH] = TRUE;
749N/A if (streq(XtNheight, args[i].name))
749N/A checks[HEIGHT] = TRUE;
749N/A }
749N/A
749N/A if (newlw->label.label == NULL) {
749N/A newlw->label.label = newlw->core.name;
749N/A }
749N/A
749N/A if (curlw->label.label != newlw->label.label) {
749N/A if (curlw->label.label != curlw->core.name)
749N/A XtFree( (char *)curlw->label.label );
749N/A
749N/A if (newlw->label.label != newlw->core.name) {
749N/A newlw->label.label = XtNewString( newlw->label.label );
749N/A }
749N/A was_resized = True;
749N/A }
749N/A
749N/A if (was_resized || (curlw->label.font != newlw->label.font) ||
749N/A (curlw->label.justify != newlw->label.justify) || checks[PIXMAP]) {
749N/A
749N/A SetTextWidthAndHeight(newlw);
749N/A was_resized = True;
749N/A }
749N/A
749N/A /* recalculate the window size if something has changed. */
749N/A if (newlw->label.resize && was_resized) {
749N/A if ((curlw->core.width == reqlw->core.width) && !checks[WIDTH])
749N/A newlw->core.width = (newlw->label.label_width +
749N/A 2 * newlw->label.internal_width);
749N/A
749N/A if ((curlw->core.height == reqlw->core.height) && !checks[HEIGHT])
749N/A newlw->core.height = (newlw->label.label_height +
749N/A 2 * newlw->label.internal_height);
749N/A }
749N/A
749N/A if (curlw->label.foreground != newlw->label.foreground
749N/A || curlw->label.font->fid != newlw->label.font->fid) {
749N/A
749N/A XtReleaseGC(new, curlw->label.normal_GC);
749N/A XtReleaseGC(new, curlw->label.gray_GC);
749N/A XmuReleaseStippledPixmap( XtScreen(current), curlw->label.stipple );
749N/A GetnormalGC(newlw);
749N/A GetgrayGC(newlw);
749N/A redisplay = True;
749N/A }
749N/A
749N/A if ((curlw->label.internal_width != newlw->label.internal_width)
749N/A || (curlw->label.internal_height != newlw->label.internal_height)
749N/A || was_resized) {
749N/A /* Resize() will be called if geometry changes succeed */
749N/A Position dx, dy;
749N/A _Reposition(newlw, curlw->core.width, curlw->core.height, &dx, &dy);
749N/A }
749N/A
749N/A return was_resized || redisplay ||
749N/A XtIsSensitive(current) != XtIsSensitive(new);
749N/A}
749N/A
749N/Astatic void Destroy(w)
749N/A Widget w;
749N/A{
749N/A LabelWidget lw = (LabelWidget)w;
749N/A
749N/A XtFree( lw->label.label );
749N/A XtReleaseGC( w, lw->label.normal_GC );
749N/A XtReleaseGC( w, lw->label.gray_GC);
749N/A XmuReleaseStippledPixmap( XtScreen(w), lw->label.stipple );
749N/A}
749N/A
749N/A
749N/Astatic XtGeometryResult QueryGeometry(w, intended, preferred)
749N/A Widget w;
749N/A XtWidgetGeometry *intended, *preferred;
749N/A{
749N/A register LabelWidget lw = (LabelWidget)w;
749N/A
749N/A preferred->request_mode = CWWidth | CWHeight;
749N/A preferred->width = lw->label.label_width + 2 * lw->label.internal_width;
749N/A preferred->height = lw->label.label_height + 2*lw->label.internal_height;
749N/A if ( ((intended->request_mode & (CWWidth | CWHeight))
749N/A == (CWWidth | CWHeight)) &&
749N/A intended->width == preferred->width &&
749N/A intended->height == preferred->height)
749N/A return XtGeometryYes;
749N/A else if (preferred->width == w->core.width &&
749N/A preferred->height == w->core.height)
749N/A return XtGeometryNo;
749N/A else
749N/A return XtGeometryAlmost;
749N/A}