home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
x
/
volume10
/
xt-examples
/
part05
/
LabelGadge.c
next >
Wrap
C/C++ Source or Header
|
1990-11-04
|
13KB
|
423 lines
/***********************************************************
Copyright 1990 by Digital Equipment Corporation, Maynard, Massachusetts.
All Rights Reserved
Permission to use, copy, modify, and distribute these examples for any
purpose and without fee is hereby granted, provided that the above
copyright notice appear in all copies and that both that copyright
notice and this permission notice appear in supporting documentation,
and that the name of Digital not be used in advertising or publicity
pertaining to distribution of the software without specific, written
prior permission.
DIGITAL AND THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT
OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
OR PERFORMANCE OF THIS SOFTWARE.
******************************************************************/
#include <string.h> /* Needed for string manipulation */
#include <X11/IntrinsicP.h> /* Intrinsics header file */
#include <X11/StringDefs.h> /* Resource string definitions */
#include "LabelGadgP.h" /* LabelGadget private header file */
#define Offset(field) XtOffsetOf(LabelGadgetRec, label.field)
static XtResource resources[] = {
{XtNlabel, XtCLabel, XtRString, sizeof(String),
Offset(label), XtRString, (XtPointer) NULL},
{XtNfont, XtCFont, XtRFontStruct, sizeof(XFontStruct *),
Offset(font), XtRString, (XtPointer) XtDefaultFont},
{XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
Offset(foreground), XtRString,
(XtPointer) XtDefaultForeground},
{XtNjustify, XtCJustify, XtRJustify, sizeof(Justify),
Offset(justify), XtRImmediate, (XtPointer) Left},
{XtNspace, XtCSpace, XtRDimension, sizeof(Dimension),
Offset(space), XtRImmediate, (XtPointer) 2},
{XtNborderWidth, XtCBorderWidth, XtRDimension, sizeof(Dimension),
XtOffsetOf(LabelGadgetRec, rectObj.border_width),
XtRImmediate, (XtPointer) 0},
{XtNbackground, XtCBackground, XtRPixel, sizeof(Pixel),
Offset(background), XtRString,
(XtPointer) XtDefaultBackground},
{XtNborderColor, XtCBorderColor, XtRPixel, sizeof(Pixel),
Offset(border), XtRString, (XtPointer) XtDefaultForeground},
};
#undef Offset
/* Forward declarations */
static void ClassInitialize(), Initialize(),
Redisplay(), Destroy(), Resize();
static Boolean SetValues();
static XtGeometryResult QueryGeometry();
/* Class record declaration */
LabelGadgetClassRec labelGadgetClassRec = {
/* RectObj class part */
{
/* superclass */ (WidgetClass) &rectObjClassRec,
/* class_name */ "LabelGadget",
/* widget_size */ sizeof(LabelGadgetRec),
/* class_initialize */ ClassInitialize,
/* class_part_initialize */ NULL,
/* class_inited */ FALSE,
/* initialize */ Initialize,
/* initialize_hook */ NULL,
/* rect1 */ NULL,
/* rect2 */ NULL,
/* rect3 */ 0,
/* resources */ resources,
/* num_resources */ XtNumber(resources),
/* xrm_class */ NULLQUARK,
/* rect4 */ 0,
/* rect5 */ 0,
/* rect6 */ 0,
/* rect7 */ 0,
/* destroy */ Destroy,
/* resize */ Resize,
/* expose */ Redisplay,
/* set_values */ SetValues,
/* set_values_hook */ NULL,
/* set_values_almost */ XtInheritSetValuesAlmost,
/* get_values_hook */ NULL,
/* rect9 */ NULL,
/* version */ XtVersion,
/* callback offsets */ NULL,
/* rect10 */ NULL,
/* query_geometry */ QueryGeometry,
/* rect11 */ NULL,
/* extension */ NULL
},
/* LabelGadget class part */
{
/* extension */ NULL
}
};
/* Class record pointer */
WidgetClass labelGadgetClass = (WidgetClass) &labelGadgetClassRec;
static void ClassInitialize()
{
extern void CvtStringToJustify(); /* Defined in Label.c */
/* Register a converter for string to justification */
XtSetTypeConverter(XtRString, XtRJustify, CvtStringToJustify,
(XtConvertArgList) NULL, 0,
XtCacheAll, (XtDestructor) NULL);
}
static void SetTextWidthAndHeight(lw)
LabelGadget lw;
{
register XFontStruct *fs = lw->label.font;
/* Compute the text dimensions based on the string and the font */
lw->label.label_len = strlen(lw->label.label);
lw->label.label_width =
XTextWidth(fs, lw->label.label, lw->label.label_len);
lw->label.label_height =
fs->max_bounds.ascent + fs->max_bounds.descent;
}
static GC GetNormalGC(lw)
LabelGadget lw;
{
XGCValues values;
/* Allocate a graphics context with the foreground and font */
values.foreground = lw->label.foreground;
values.font = lw->label.font->fid;
return XtGetGC((Widget) lw, GCForeground | GCFont, &values);
}
static GC GetBackgroundGC(lw)
LabelGadget lw;
{
XGCValues values;
/* Allocate a graphics context with the background */
values.foreground = lw->label.background;
return XtGetGC((Widget) lw, GCForeground, &values);
}
static GC GetBorderGC(lw)
LabelGadget lw;
{
XGCValues values;
if (lw->rectObj.border_width == 0) return NULL;
/* Allocate a graphics context with the border values */
values.foreground = lw->label.border;
values.line_width = lw->rectObj.border_width;
return XtGetGC((Widget) lw, GCForeground | GCLineWidth, &values);
}
static void Initialize(request, new, args, num_args)
Widget request, new;
ArgList args;
Cardinal *num_args;
{
LabelGadget lw = (LabelGadget) new;
/* If no label is specified, use the name */
if (lw->label.label == NULL) lw->label.label = XtName(lw);
/* Copy the label */
lw->label.label = XtNewString(lw->label.label);
/* Compute the text dimensions and get graphics contexts. */
SetTextWidthAndHeight(lw);
lw->label.gc = lw->label.current_gc = GetNormalGC(lw);
lw->label.background_gc =
lw->label.current_bg_gc = GetBackgroundGC(lw);
lw->label.border_gc = GetBorderGC(lw);
/* If no size specified, compute one */
lw->label.size_computed =
(lw->rectObj.width == 0) && (lw->rectObj.height == 0);
if (lw->rectObj.width == 0) {
lw->rectObj.width = lw->label.label_width +
2 * lw->label.space;
}
if (lw->rectObj.height == 0) {
lw->rectObj.height = lw->label.label_height +
2 * lw->label.space;
}
lw->label.old_border = lw->rectObj.border_width;
lw->label.desired_width = lw->rectObj.width;
lw->label.desired_height = lw->rectObj.height;
}
static Boolean SetValues(old, request, new, args, num_args)
Widget old, request, new;
ArgList args;
Cardinal *num_args;
{
LabelGadget oldlw = (LabelGadget) old;
LabelGadget newlw = (LabelGadget) new;
Boolean redisplay = FALSE;
#define NE(field) (oldlw->field != newlw->field)
/* If the label has been reset to NULL, change to the name */
if (newlw->label.label == NULL) {
newlw->label.label = XtName(newlw);
}
/* Decide whether to compute the size */
if (newlw->rectObj.width == 0 && newlw->rectObj.height == 0) {
newlw->label.size_computed = TRUE;
} else if (NE(rectObj.width) || NE(rectObj.height)) {
newlw->label.size_computed = FALSE;
if (NE(rectObj.width)) {
newlw->label.desired_width = newlw->rectObj.width;
}
if (NE(rectObj.height)) {
newlw->label.desired_height = newlw->rectObj.height;
}
} /* else leave the same */
/* If label, or font has changed, recopy and compute size */
if (NE(label.label) || NE(label.font)) {
if (NE(label.label)) {
XtFree((char *) oldlw->label.label);
newlw->label.label = XtNewString(newlw->label.label);
}
SetTextWidthAndHeight(newlw);
redisplay = TRUE;
}
/* Compute the size if necessary */
if (newlw->label.size_computed || newlw->rectObj.width == 0) {
newlw->label.desired_width = newlw->rectObj.width =
newlw->label.label_width + 2 * newlw->label.space;
}
if (newlw->label.size_computed || newlw->rectObj.height == 0) {
newlw->label.desired_height = newlw->rectObj.height =
newlw->label.label_height + 2 * newlw->label.space;
}
/* If foreground or font has changed, update GC */
if (NE(label.foreground) || NE(label.font->fid)) {
XtReleaseGC(newlw, oldlw->label.gc);
newlw->label.gc = GetNormalGC(newlw);
if (newlw->label.current_gc == oldlw->label.gc) {
newlw->label.current_gc = newlw->label.gc;
redisplay = TRUE;
}
}
/* If background has changed, update background GC */
if (NE(label.background)) {
XtReleaseGC(newlw, oldlw->label.background_gc);
newlw->label.background_gc = GetBackgroundGC(newlw);
if (newlw->label.current_bg_gc == oldlw->label.background_gc) {
newlw->label.current_bg_gc = newlw->label.background_gc;
redisplay = TRUE;
}
}
/* If border has changed, update border GC */
if (NE(label.border) || NE(rectObj.border_width)) {
if (oldlw->label.border_gc != NULL) {
XtReleaseGC(newlw, oldlw->label.border_gc);
}
newlw->label.border_gc = GetBorderGC(newlw);
redisplay = TRUE;
}
return redisplay || NE(label.space) || NE(label.justify);
#undef NE
}
static void Destroy(w)
Widget w;
{
LabelGadget lw = (LabelGadget) w;
XtFree((char *) lw->label.label);
XtReleaseGC(w, lw->label.gc);
XtReleaseGC(w, lw->label.background_gc);
if (lw->label.border_gc != NULL) {
XtReleaseGC(w, lw->label.border_gc);
}
}
static void Redisplay(w, event, region)
Widget w;
XEvent *event;
Region region;
{
LabelGadget lw = (LabelGadget) w;
int offset, x;
XRectangle rect;
Region r1, r2;
/* Draw the background */
XFillRectangle(XtDisplayOfObject(w), XtWindowOfObject(w),
lw->label.current_bg_gc,
lw->rectObj.x + lw->rectObj.border_width,
lw->rectObj.y + lw->rectObj.border_width,
lw->rectObj.width, lw->rectObj.height);
/* Draw the border */
if (lw->rectObj.border_width != 0) {
offset = lw->rectObj.border_width / 2;
XDrawRectangle(XtDisplayOfObject(w), XtWindowOfObject(w),
lw->label.border_gc,
lw->rectObj.x + offset, lw->rectObj.y + offset,
lw->rectObj.width + lw->rectObj.border_width,
lw->rectObj.height + lw->rectObj.border_width);
}
switch (lw->label.justify) {
case Left:
x = lw->label.space;
break;
case Right:
x = (int) lw->rectObj.width - (int) lw->label.space -
(int) lw->label.label_width;
break;
case Center:
x = ((int) lw->rectObj.width -
(int) lw->label.label_width) / 2;
break;
}
/* Temporarily change the clip mask in the gc */
rect.x = lw->rectObj.x + lw->rectObj.border_width;
rect.y = lw->rectObj.y + lw->rectObj.border_width;
rect.width = lw->rectObj.width;
rect.height = lw->rectObj.height;
r1 = XCreateRegion();
r2 = XCreateRegion();
if (region != NULL) {
XUnionRectWithRegion(&rect, r1, r2); /* r2 = rectangle */
XIntersectRegion(region, r2, r1); /* r1 = intersection */
} else XUnionRectWithRegion(&rect, r2, r1); /* r1 = rectangle */
XSetRegion(XtDisplayOfObject(w), lw->label.current_gc, r1);
XDestroyRegion(r1);
XDestroyRegion(r2);
XDrawString(XtDisplayOfObject(w), XtWindowOfObject(w),
lw->label.current_gc,
lw->rectObj.x + lw->rectObj.border_width + x,
lw->rectObj.y + lw->rectObj.border_width +
lw->label.space + lw->label.font->max_bounds.ascent,
lw->label.label, lw->label.label_len);
/* Restore the GC */
XSetClipMask(XtDisplayOfObject(w), lw->label.current_gc, None);
}
static void Resize(w)
Widget w;
{
LabelGadget lw = (LabelGadget) w;
/* If border width changed, update border GC */
if (lw->label.old_border != lw->rectObj.border_width) {
if (lw->label.border_gc != NULL) {
XtReleaseGC(w, lw->label.border_gc);
}
lw->label.border_gc = GetBorderGC(lw);
lw->label.old_border = lw->rectObj.border_width;
}
}
static XtGeometryResult QueryGeometry(w, proposed, desired)
Widget w;
XtWidgetGeometry *proposed, *desired;
{
LabelGadget lw = (LabelGadget) w;
#define Set(bit) (proposed->request_mode & bit)
desired->width = lw->label.desired_width;
desired->height = lw->label.desired_height;
desired->request_mode = CWWidth | CWHeight;
if (Set(CWWidth) && proposed->width == desired->width &&
Set(CWHeight) && proposed->height == desired->height) {
return XtGeometryYes;
}
if (desired->width == lw->rectObj.width &&
desired->height == lw->rectObj.height) {
return XtGeometryNo;
}
return XtGeometryAlmost;
#undef Set
}