home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The World of Computer Software
/
World_Of_Computer_Software-02-385-Vol-1of3.iso
/
x
/
xtici.zip
/
xtici
/
widgets
/
RepeatB.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-08-28
|
17KB
|
580 lines
/*
* Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc.
* All Rights Reserved
*
* This file is a component of an X Window System client which uses the Xcms
* Color Management System. TekColor is a trademark of Tektronix, Inc. The
* TekColor Editor is the subject of U.S. and foreign patents pending. The
* term "TekHVC" designates a particular color space that is the subject of
* U.S. Patent No. 4,985,853 (equivalent foreign patents pending).
* Permission is hereby granted to use, copy, modify, sell, and otherwise
* distribute this software and its documentation for the X Window System
* environment, for any purpose and without fee, provided that:
*
* 1. The code and documentation are only used to implement a
* TekColor Editor in an X Window System environment; and
* 2. This copyright and permission notice is reproduced in all copies
* of the code and in supporting documentation.
*
* Permission is granted to modify this code as required to allow it to
* be compiled on any host computer, provided that the functionality of
* the TekColor Editor is not modified in any way. A description of any
* modifications must be sent to Tektronix, Inc. Contact
* Tektronix Inc., P.O. Box 1000, Mail Station 60-850,
* Network Displays Division Engineering, Wilsonville, OR 97070.
*
* Tektronix makes no representation about the suitability of this software
* for any purpose. It is provided "as is" and with all faults.
*
* TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE,
* INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE. IN NO EVENT SHALL TEKTRONIX 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 THE PERFORMANCE OF THIS SOFTWARE.
*
*
* NAME
* RepeatB.c -- The RepeaterButton Widget
*
* DESCRIPTION
* This is an arrow button with a repeat value.
*
* HISTORY
*
* HISTORY END
*
*/
#ifndef LINT
static char *copy_notice = "Copyright 1991 Tektronix, Inc.";
#ifdef RCS_ID
static char *rcsid= "$Header: RepeatB.c,v 1.2 91/08/22 11:36:33 adamsc Exp $";
#endif /* RCS_ID */
#endif /* LINT */
#include <stdio.h>
#include <X11/IntrinsicP.h>
#include <X11/StringDefs.h>
#include <X11/Xaw/XawInit.h>
#include <X11/Xaw/SimpleP.h>
#include "RepeatBP.h"
/*
* Translations to give user interface of press-notify...-release_or_leave
*/
static char defaultTranslations[] =
"<Btn1Down>: arm() armActivate() \n\
<Btn1Up>: disarm()";
static XtResource resources[] = {
#define offset(field) XtOffset(RepeaterButtonWidget, repeater.field)
/* {name, class, type, size, offset, default_type, default_addr}, */
{ XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
offset(fg_pixel), XtRImmediate, (XtPointer) XtDefaultForeground },
{ XtNinitialDelay, XtCDelay, XtRInt, sizeof(int),
offset(initial), XtRImmediate, (XtPointer) (REP_DEF_INITIAL_DELAY * 4)},
{ XtNminimumDelay, XtCMinimumDelay, XtRInt, sizeof (int),
offset(minimum), XtRImmediate, (XtPointer) REP_DEF_MINIMUM_DELAY },
{ XtNrepeatDelay, XtCDelay, XtRInt, sizeof(int),
offset(repeat), XtRImmediate, (XtPointer)REP_DEF_REPEAT_DELAY },
{ XtNarrowDirection, XtCArrowDirection, XtRInt, sizeof(int),
offset(direction), XtRImmediate, (XtPointer)XtorientationUp },
{ XtNarmCallback, XtCArmCallback, XtRCallback, sizeof(XtPointer),
offset(arm_callbacks), XtRImmediate, (XtPointer) NULL },
{ XtNactivateCallback, XtCActivateCallback, XtRCallback, sizeof(XtPointer),
offset(activate_callbacks), XtRImmediate, (XtPointer) NULL },
{ XtNdisarmCallback, XtCDisarmCallback, XtRCallback, sizeof(XtPointer),
offset(disarm_callbacks), XtRImmediate, (XtPointer) NULL },
#undef offset
};
#define MIN_WIDTH 15
/* forward declarations for the class struct */
static void Initialize();
static void Destroy();
static void Exposed();
static void Resize();
static Boolean SetValues();
static XtGeometryResult QueryGeometry();
/*
* Actions added by this widget
*/
static void Arm(), ArmActivate(), Disarm();
static XtActionsRec actionsList[] = {
{ "arm", Arm }, /* add the timer */
{ "armActivate", ArmActivate }, /* trigger the timer */
{ "disarm", Disarm }, /* clear the timer */
};
RepeaterButtonClassRec repeaterButtonClassRec = {
{ /* core fields */
/* superclass */ (WidgetClass) &simpleClassRec,
/* class_name */ "RepeaterButton",
/* widget_size */ sizeof(RepeaterButtonRec),
/* class_initialize */ XawInitializeWidgetSet,
/* class_part_initialize */ NULL,
/* class_inited */ FALSE,
/* initialize */ Initialize,
/* initialize_hook */ NULL,
/* realize */ XtInheritRealize,
/* actions */ actionsList,
/* num_actions */ XtNumber(actionsList),
/* resources */ resources,
/* num_resources */ XtNumber(resources),
/* xrm_class */ NULLQUARK,
/* compress_motion */ TRUE,
/* compress_exposure */ TRUE,
/* compress_enterleave */ TRUE,
/* visible_interest */ FALSE,
/* destroy */ Destroy,
/* resize */ Resize,
/* expose */ Exposed,
/* set_values */ SetValues,
/* set_values_hook */ NULL,
/* set_values_almost */ XtInheritSetValuesAlmost,
/* get_values_hook */ NULL,
/* accept_focus */ NULL,
/* version */ XtVersion,
/* callback_private */ NULL,
/* tm_table */ defaultTranslations,
/* query_geometry */ QueryGeometry,
/* display_accelerator */ XtInheritDisplayAccelerator,
/* extension */ NULL
},
{ /* simple fields */
/* change_sensitive */ XtInheritChangeSensitive,
},
{ /* repeater fields */
/* extension */ NULL
}
};
WidgetClass repeaterButtonClass = (WidgetClass)&repeaterButtonClassRec;
/* forward declarations for utility functions */
static void TimeoutContinue();
static void TimeoutStop();
static void Draw();
static char *warning1 = "Delay must be positive";
static char *warning2 = "Foreground color must be different than background";
static char *warning3 = "Arrow direction must be up, down, left or right";
static void ArmActivate(rpt)
RepeaterButtonWidget rpt;
{
/* if already armed (a timeout set), just activate */
if (rpt->repeater.timer) {
ScaleCallbackStruct data;
data.reason = CR_ACTIVATE;
data.event = NULL;
XtCallCallbacks((Widget)rpt, XtNactivateCallback, &data);
return;
}
/* replace the timeout with ours that will activate AND disarm */
if (rpt->repeater.timer) /* should always be true */
XtRemoveTimeOut(rpt->repeater.timer);
rpt->repeater.timer = XtAppAddTimeOut(
XtWidgetToApplicationContext((Widget)rpt),
rpt->repeater.repeat, TimeoutStop, rpt);
}
static void Warning (widget, message)
Widget widget;
char *message;
{
/* R4 says use XtAppWarningMsg but no information on how to set
* the parameters.
*/
if (!widget)
XtWarning(message);
else
XtAppWarning(XtWidgetToApplicationContext(widget), message);
}
static void Initialize(req, new)
RepeaterButtonWidget req, new;
{
if (new->repeater.minimum < 0) {
Warning(new, warning1);
new->repeater.minimum = 0;
}
if (new->repeater.initial < new->repeater.minimum) {
Warning(new, warning1);
new->repeater.initial = new->repeater.minimum;
}
if (new->repeater.repeat < new->repeater.minimum) {
Warning(new, warning1);
new->repeater.repeat = new->repeater.minimum;
}
new->repeater.timer = (XtIntervalId) 0;
if (req->core.width == 0)
new->core.width = MIN_WIDTH;
if (req->core.height == 0)
new->core.height = MIN_WIDTH;
if (new->core.width > new->core.height) {
new->repeater.prefer_width = new->core.height;
new->repeater.prefer_height = new->core.height;
} else {
new->repeater.prefer_width = new->core.width;
new->repeater.prefer_height = new->core.width;
}
if (new->repeater.prefer_width < MIN_WIDTH) {
new->repeater.prefer_width = MIN_WIDTH;
new->repeater.prefer_height = MIN_WIDTH;
}
/* Building the GC is deferred until we know we have a window, */
/* ie, when the widget is first expose */
new->repeater.localGC = 0;
if (new->core.background_pixel == new->repeater.fg_pixel) {
Warning(new, warning2);
if (new->core.background_pixel > 0)
new->repeater.fg_pixel = new->core.background_pixel - 1;
else
new->repeater.fg_pixel = new->core.background_pixel + 1;
}
switch (new->repeater.direction) {
case XtorientationUp:
case XtorientationLeft:
case XtorientationDown:
case XtorientationRight:
break;
default:
Warning(new, warning3);
new->repeater.direction = XtorientationUp;
break;
}
}
static void Destroy (w)
RepeaterButtonWidget w;
{
Disarm (w);
if (w->repeater.localGC)
XFreeGC(XtDisplay(w), w->repeater.localGC);
}
/*ARGSUSED*/
static void Exposed (rpt, evnt, region)
RepeaterButtonWidget rpt;
XEvent *evnt;
Region region;
{
Draw (rpt);
}
static void Resize (rpt)
RepeaterButtonWidget rpt;
{
/* defer the drawing until we have a window to work in */
if (!rpt->repeater.localGC)
return;
Draw (rpt);
if (rpt->core.width > rpt->core.height) {
rpt->repeater.prefer_width = rpt->core.height;
rpt->repeater.prefer_height = rpt->core.height;
} else {
rpt->repeater.prefer_width = rpt->core.width;
rpt->repeater.prefer_height = rpt->core.width;
}
if (rpt->repeater.prefer_width < MIN_WIDTH) {
rpt->repeater.prefer_width = MIN_WIDTH;
rpt->repeater.prefer_height = MIN_WIDTH;
}
}
static XtGeometryResult QueryGeometry(rpt, request, result)
RepeaterButtonWidget rpt;
XtWidgetGeometry *request, *result;
{
result->request_mode = CWWidth | CWHeight;
result->width = rpt->repeater.prefer_width;
result->height = rpt->repeater.prefer_height;
if (((request->request_mode & (CWWidth | CWHeight)) ==
(CWWidth | CWHeight)) &&
request->width == result->width &&
request->height == result->height)
return (XtGeometryYes);
else if (result->width == rpt->core.width &&
result->height == rpt->core.height)
return (XtGeometryNo);
return (XtGeometryAlmost);
}
/*ARGSUSED*/
static Boolean SetValues(cur, req, new)
RepeaterButtonWidget cur, req, new;
{
if (cur->repeater.minimum < 0) {
new->repeater.minimum = 0;
}
if (new->repeater.initial < new->repeater.minimum) {
Warning(new, warning1);
new->repeater.initial = new->repeater.minimum;
}
if (new->repeater.repeat < 0) {
Warning(new, warning1);
new->repeater.repeat = cur->repeater.repeat;
}
if (cur->repeater.minimum != new->repeater.minimum) {
if (new->repeater.next_delay < new->repeater.minimum)
new->repeater.next_delay = new->repeater.minimum;
}
if (cur->repeater.fg_pixel != new->repeater.fg_pixel) {
if (cur->core.background_pixel == new->repeater.fg_pixel) {
Warning(new, warning2);
new->repeater.fg_pixel = cur->core.background_pixel;
}
}
if (cur->core.background_pixel != new->core.background_pixel) {
if (new->core.background_pixel == new->repeater.fg_pixel) {
Warning(new, warning2);
if (new->core.background_pixel > 0)
new->repeater.fg_pixel = new->core.background_pixel - 1;
else
new->repeater.fg_pixel = new->core.background_pixel + 1;
}
}
return(False);
}
static void Arm(rpt)
RepeaterButtonWidget rpt;
{
/* If a timer is there, it was set by arrow button. override */
if (rpt->repeater.timer)
XtRemoveTimeOut(rpt->repeater.timer);
rpt->repeater.timer = XtAppAddTimeOut(
XtWidgetToApplicationContext((Widget)rpt),
rpt->repeater.initial, TimeoutContinue, rpt);
Draw (rpt);
}
static void Disarm(rpt)
RepeaterButtonWidget rpt;
{
if (rpt->repeater.timer)
XtRemoveTimeOut(rpt->repeater.timer);
rpt->repeater.timer = 0;
Draw(rpt);
}
/*ARGSUSED*/
static void TimeoutContinue(prpt, id)
XtPointer prpt;
XtIntervalId *id;
{
RepeaterButtonWidget rpt = (RepeaterButtonWidget)prpt;
ScaleCallbackStruct data;
if (rpt->repeater.timer <= 0) {
rpt->repeater.timer = 0;
return;
}
rpt->repeater.timer = 0;
data.reason = CR_ACTIVATE;
data.event = NULL;
XtCallCallbacks((Widget)rpt, XtNactivateCallback, &data);
rpt->repeater.timer = XtAppAddTimeOut(
XtWidgetToApplicationContext((Widget)rpt),
rpt->repeater.repeat, TimeoutContinue, rpt);
}
/*ARGSUSED*/
static void TimeoutStop(rpt, id)
RepeaterButtonWidget rpt;
XtIntervalId *id;
{
ScaleCallbackStruct data;
rpt->repeater.timer = 0;
data.reason = CR_ACTIVATE;
data.event = NULL;
XtCallCallbacks((Widget)rpt, XtNactivateCallback, &data);
data.reason = CR_DISARM;
data.event = NULL;
XtCallCallbacks((Widget)rpt, XtNdisarmCallback, &data);
/* redraw using inherited routine */
}
static GC GetGC(rpt)
RepeaterButtonWidget rpt;
{
XtGCMask mask = GCForeground | GCBackground | GCFillStyle;
XGCValues gcv;
gcv.foreground = rpt->repeater.fg_pixel;
gcv.background = rpt->core.background_pixel;
gcv.fill_style = FillSolid;
return (XCreateGC(XtDisplay(rpt), XtWindow(rpt), mask, &gcv));
}
static void Draw(rpt)
RepeaterButtonWidget rpt;
{
Display *pDpy;
Window win;
Position nx, ny;
Dimension width;
XPoint points[4];
if (!XtIsRealized((Widget)rpt))
return;
if (!rpt->repeater.localGC)
rpt->repeater.localGC = GetGC(rpt);
if (!rpt->repeater.localGC)
return;
pDpy = XtDisplay (rpt);
win = XtWindow(rpt);
XClearWindow (pDpy, win);
switch (rpt->repeater.direction) {
case XtorientationUp:
/* when pointing up put the arrow head in lower right */
if (rpt->core.width > rpt->core.height) {
nx = rpt->core.width - rpt->core.height;
ny = 0;
width = rpt->core.height;
} else {
nx = 0;
ny = rpt->core.height - rpt->core.width;
width = rpt->core.width;
}
points[0].x = nx + (width / 2);
if (width > 20) {
points[0].y = ny + 4;
points[1].x = rpt->core.width - 4;
points[1].y = rpt->core.height - 4;
points[2].x = nx + 4;
} else {
points[0].y = ny + 1;
points[1].x = rpt->core.width - 1;
points[1].y = rpt->core.height - 1;
points[2].x = nx + 1;
}
points[2].y = points[1].y;
break;
case XtorientationLeft:
/* when pointing left put the arrow head in upper right */
ny = 0;
if (rpt->core.width > rpt->core.height) {
nx = rpt->core.width - rpt->core.height;
width = rpt->core.height;
} else {
nx = 0;
width = rpt->core.width;
}
points[0].y = width / 2;
if (width > 20) {
points[0].x = nx + 4;
points[1].x = rpt->core.width - 4;
points[1].y = 4;
points[2].y = width - 4;
} else {
points[0].x = nx + 1;
points[1].x = rpt->core.width - 1;
points[1].y = 1;
points[2].y = width - 1;
}
points[2].x = points[1].x;
break;
case XtorientationDown:
/* when pointing down put the arrow head in upper right */
ny = 0;
if (rpt->core.width > rpt->core.height) {
nx = rpt->core.width - rpt->core.height;
width = rpt->core.height;
} else {
nx = 0;
width = rpt->core.width;
}
points[0].x = nx + (width / 2);
if (width > 20) {
points[0].y = width - 4;
points[1].x = nx + 4;
points[1].y = 4;
points[2].x = rpt->core.width - 4;
} else {
points[0].y = width - 1;
points[1].x = nx + 1;
points[1].y = 1;
points[2].x = rpt->core.width - 1;
}
points[2].y = points[1].y;
break;
case XtorientationRight:
/* when pointing right put the arrow head in upper right */
nx = 0;
ny = 0;
if (rpt->core.width > rpt->core.height) {
width = rpt->core.height;
} else {
width = rpt->core.width;
}
points[0].y = width / 2;
if (width > 20) {
points[0].x = width - 4;
points[1].x = 4;
points[1].y = width - 4;
points[2].y = 4;
} else {
points[0].x = rpt->core.width - 1;
points[1].x = 1;
points[1].y = width - 1;
points[2].y = 1;
}
points[2].x = points[1].x;
break;
}
if (rpt->repeater.timer) {
/* With the timer on draw the button in the down position */
XFillPolygon(pDpy, win, rpt->repeater.localGC, points, 3,
Convex, CoordModeOrigin);
} else {
/* With the timer off draw the button in the up position */
points[3].x = points[0].x;
points[3].y = points[0].y;
XDrawLines(pDpy, win, rpt->repeater.localGC, points, 4,
CoordModeOrigin);
}
}