mirror of
git://git.code.sf.net/p/cdesktopenv/code
synced 2025-03-09 15:50:02 +00:00
Removed PORT_NOFORK define in favor of autotools vfork availablility checking. Use vfork if present. Got rid of getenv/putenv definitions in favor of including correct system headers. Use FD_CLOEXEC in fcntl() call rather than hardcoded '1'. Added -lm check to configure so dtwm will build. Renamed internal round() function to wmround() to fix warning about redefinition of builtin. Fixed missing backslash in Makefile.am that prevented half the sources from building.
1082 lines
29 KiB
C
1082 lines
29 KiB
C
/*
|
||
* CDE - Common Desktop Environment
|
||
*
|
||
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
||
*
|
||
* These libraries and programs are free software; you can
|
||
* redistribute them and/or modify them under the terms of the GNU
|
||
* Lesser General Public License as published by the Free Software
|
||
* Foundation; either version 2 of the License, or (at your option)
|
||
* any later version.
|
||
*
|
||
* These libraries and programs are distributed in the hope that
|
||
* they will be useful, but WITHOUT ANY WARRANTY; without even the
|
||
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||
* PURPOSE. See the GNU Lesser General Public License for more
|
||
* details.
|
||
*
|
||
* You should have received a copy of the GNU Lesser General Public
|
||
* License along with these libraries and programs; if not, write
|
||
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
||
* Floor, Boston, MA 02110-1301 USA
|
||
*/
|
||
/**---------------------------------------------------------------------
|
||
***
|
||
*** file: Clock.c
|
||
***
|
||
*** project: MotifPlus Widgets
|
||
***
|
||
*** description: Source code for DtClock class.
|
||
*** Portions adapted from the Xaw Clock widget.
|
||
***
|
||
***
|
||
*** (c) Copyright 1990 by Hewlett-Packard Company.
|
||
***
|
||
***
|
||
Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts,
|
||
and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
|
||
|
||
All Rights Reserved
|
||
|
||
Permission to use, copy, modify, and distribute this software and its
|
||
documentation 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 names of Digital or MIT not be
|
||
used in advertising or publicity pertaining to distribution of the
|
||
software without specific, written prior permission.
|
||
|
||
DIGITAL DISCLAIMS 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 Files
|
||
*/
|
||
|
||
#include <stdio.h>
|
||
#include <sys/stat.h>
|
||
#include <time.h>
|
||
#include <Xm/GadgetP.h>
|
||
#include <Xm/ManagerP.h>
|
||
#include "ClockP.h"
|
||
#include <Dt/Control.h>
|
||
|
||
|
||
/*-------------------------------------------------------------
|
||
** Public Interface
|
||
**-------------------------------------------------------------
|
||
*/
|
||
|
||
WidgetClass dtClockGadgetClass;
|
||
|
||
|
||
/*-------------------------------------------------------------
|
||
*/
|
||
|
||
#define SIZE_DEFAULT 32
|
||
#define DELAY_DEFAULT 250
|
||
#define VERTICES_IN_HANDS 6 /* to draw triangle */
|
||
#define PI 3.14159265358979
|
||
#define TWOPI (2. * PI)
|
||
|
||
#define SMALL_TICK_FRACT 100
|
||
#define SMALL_MINUTE_HAND_FRACT 95
|
||
#define SMALL_HOUR_HAND_FRACT 68
|
||
#define SMALL_HAND_WIDTH_FRACT 12
|
||
|
||
#define TICK_FRACT 90
|
||
#define MINUTE_HAND_FRACT 70
|
||
#define HOUR_HAND_FRACT 40
|
||
#define HAND_WIDTH_FRACT 7
|
||
|
||
#define max(a,b) ((a) > (b) ? (a) : (b))
|
||
#define min(a,b) ((a) < (b) ? (a) : (b))
|
||
#define abs(a) ((a) < 0 ? - (a) : (a))
|
||
|
||
#define G_Width(r) (r -> rectangle.width)
|
||
#define G_Height(r) (r -> rectangle.height)
|
||
#define M_BackgroundGC(m) (m -> manager.background_GC)
|
||
#define G_X(r) (r -> rectangle.x)
|
||
#define G_Y(r) (r -> rectangle.y)
|
||
|
||
|
||
/* Is this still needed, or does <time.h> always declare time()? */
|
||
extern time_t time ( time_t * );
|
||
|
||
|
||
/******** Public Function Declarations ********/
|
||
|
||
extern Widget DtCreateClock(
|
||
Widget parent,
|
||
String name,
|
||
ArgList arglist,
|
||
Cardinal argcount) ;
|
||
|
||
/******** End Public Function Declarations ********/
|
||
|
||
/******** Static Function Declarations ********/
|
||
|
||
static void ClockTick(
|
||
XtPointer client_data,
|
||
XtIntervalId *id) ;
|
||
static void DrawLine(
|
||
DtClockGadget w,
|
||
Dimension blank_length,
|
||
Dimension length,
|
||
double fraction_of_a_circle) ;
|
||
static void DrawHand(
|
||
DtClockGadget w,
|
||
Dimension length,
|
||
Dimension width,
|
||
double fraction_of_a_circle) ;
|
||
static void SetSegment(
|
||
DtClockGadget w,
|
||
int x1,
|
||
int y1,
|
||
int x2,
|
||
int y2) ;
|
||
static int wmround(
|
||
double x) ;
|
||
static void DrawClockFace(
|
||
DtClockGadget g) ;
|
||
static void Initialize(
|
||
Widget request_w,
|
||
Widget new_w) ;
|
||
static void Destroy(
|
||
Widget w) ;
|
||
static void Resize(
|
||
Widget widget) ;
|
||
static void Draw(
|
||
DtClockGadget g,
|
||
Drawable drawable,
|
||
Position x,
|
||
Position y,
|
||
Dimension w,
|
||
Dimension h,
|
||
Dimension h_t,
|
||
Dimension s_t,
|
||
unsigned char s_type,
|
||
unsigned char fill_mode) ;
|
||
static void UpdateGCs(
|
||
DtClockGadget g) ;
|
||
static void EraseHands ( DtClockGadget w, struct tm * tm );
|
||
|
||
/******** End Static Function Declarations ********/
|
||
|
||
|
||
/*-------------------------------------------------------------
|
||
** Resource List
|
||
*/
|
||
#define R_Offset(field) \
|
||
XtOffset (DtClockGadget, clock.field)
|
||
|
||
static XtResource resources[] =
|
||
{
|
||
{
|
||
XmNclockInterval,
|
||
XmCInterval, XmRInt, sizeof (int),
|
||
R_Offset (clock_interval), XmRImmediate, (XtPointer) 60
|
||
},
|
||
{
|
||
XmNchime,
|
||
XmCBoolean, XmRBoolean, sizeof (Boolean),
|
||
R_Offset (chime), XmRImmediate, (XtPointer) FALSE
|
||
},
|
||
{
|
||
XmNleftInset,
|
||
XmCSpacing, XmRHorizontalDimension, sizeof (Dimension),
|
||
R_Offset (left_inset), XmRImmediate, (caddr_t) 2
|
||
},
|
||
{
|
||
XmNrightInset,
|
||
XmCSpacing, XmRHorizontalDimension, sizeof (Dimension),
|
||
R_Offset (right_inset), XmRImmediate, (caddr_t) 2
|
||
},
|
||
{
|
||
XmNtopInset,
|
||
XmCSpacing, XmRVerticalDimension, sizeof (Dimension),
|
||
R_Offset (top_inset), XmRImmediate, (caddr_t) 2
|
||
},
|
||
{
|
||
XmNbottomInset,
|
||
XmCSpacing, XmRVerticalDimension, sizeof (Dimension),
|
||
R_Offset (bottom_inset), XmRImmediate, (caddr_t) 2
|
||
}
|
||
};
|
||
#undef R_Offset
|
||
|
||
|
||
|
||
/*-------------------------------------------------------------
|
||
** Class Record
|
||
*/
|
||
DtClockClassRec dtClockClassRec =
|
||
{
|
||
/* Core Part
|
||
*/
|
||
{
|
||
(WidgetClass) &dtControlClassRec, /* superclass */
|
||
"Clock", /* class_name */
|
||
sizeof (DtClockRec), /* widget_size */
|
||
NULL, /* class_initialize */
|
||
NULL, /* class_part_initialize*/
|
||
False, /* class_inited */
|
||
(XtInitProc) Initialize, /* initialize */
|
||
NULL, /* initialize_hook */
|
||
NULL, /* realize */
|
||
NULL, /* actions */
|
||
0, /* num_actions */
|
||
resources, /* resources */
|
||
XtNumber (resources), /* num_resources */
|
||
NULLQUARK, /* xrm_class */
|
||
True, /* compress_motion */
|
||
True, /* compress_exposure */
|
||
True, /* compress_enterleave */
|
||
False, /* visible_interest */
|
||
Destroy, /* destroy */
|
||
Resize, /* resize */
|
||
XtInheritExpose, /* expose */
|
||
NULL, /* set_values */
|
||
NULL, /* set_values_hook */
|
||
XtInheritSetValuesAlmost, /* set_values_almost */
|
||
NULL, /* get_values_hook */
|
||
NULL, /* accept_focus */
|
||
XtVersion, /* version */
|
||
NULL, /* callback private */
|
||
NULL, /* tm_table */
|
||
NULL, /* query_geometry */
|
||
NULL, /* display_accelerator */
|
||
NULL, /* extension */
|
||
},
|
||
|
||
/* XmGadget Part
|
||
*/
|
||
{
|
||
XmInheritBorderHighlight, /* border_highlight */
|
||
XmInheritBorderUnhighlight, /* border_unhighlight */
|
||
(XtActionProc) XmInheritArmAndActivate, /* arm_and_activate */
|
||
(XmWidgetDispatchProc) XmInheritInputDispatch, /* input_dispatch */
|
||
XmInheritVisualChange, /* visual_change */
|
||
NULL, /* get_resources */
|
||
0, /* num_get_resources */
|
||
XmInheritCachePart, /* class_cache_part */
|
||
NULL, /* extension */
|
||
},
|
||
|
||
/* DtIcon Part
|
||
*/
|
||
{
|
||
DtInheritGetSize, /* get_size */
|
||
DtInheritGetPositions, /* get_positions */
|
||
(DrawProc) Draw, /* draw */
|
||
DtInheritCallCallback, /* call_callback */
|
||
(UpdateGCsProc) UpdateGCs, /* update_gcs */
|
||
False, /* optimize_redraw */
|
||
NULL, /* class_cache_part */
|
||
NULL, /* extension */
|
||
},
|
||
|
||
/* DtClock Part
|
||
*/
|
||
{
|
||
NULL, /* class_cache_part */
|
||
NULL, /* extension */
|
||
},
|
||
|
||
/* DtControl Part
|
||
*/
|
||
{
|
||
NULL, /* class_cache_part */
|
||
NULL, /* extension */
|
||
}
|
||
};
|
||
|
||
|
||
WidgetClass dtClockGadgetClass = (WidgetClass) &dtClockClassRec;
|
||
|
||
|
||
|
||
/*-------------------------------------------------------------
|
||
** Private Functions
|
||
**-------------------------------------------------------------
|
||
*/
|
||
|
||
/*-------------------------------------------------------------
|
||
** ClockTick
|
||
** Clock timeout.
|
||
*/
|
||
static void
|
||
ClockTick(
|
||
XtPointer client_data,
|
||
XtIntervalId *id )
|
||
{
|
||
DtClockGadget w = (DtClockGadget)client_data;
|
||
struct tm * localtime ();
|
||
struct tm tm;
|
||
time_t time_value;
|
||
char * time_ptr;
|
||
Display * dpy = XtDisplay (w);
|
||
Window win = XtWindow (w);
|
||
|
||
if (id || !w->clock.interval_id)
|
||
w->clock.interval_id =
|
||
XtAppAddTimeOut (
|
||
XtWidgetToApplicationContext ((Widget) w),
|
||
G_ClockInterval (w)*1000, ClockTick,
|
||
(XtPointer)w );
|
||
(void) time (&time_value);
|
||
tm = *localtime (&time_value);
|
||
|
||
if (! XtIsManaged ((Widget)w))
|
||
{
|
||
w->clock.otm = tm;
|
||
return;
|
||
}
|
||
|
||
/* Beep on the half hour; double-beep on the hour.
|
||
*/
|
||
if (w->clock.chime == TRUE)
|
||
{
|
||
if (w->clock.beeped && (tm.tm_min != 30) &&
|
||
(tm.tm_min != 0))
|
||
w->clock.beeped = FALSE;
|
||
if (((tm.tm_min == 30) || (tm.tm_min == 0))
|
||
&& (!w->clock.beeped))
|
||
{
|
||
w->clock.beeped = TRUE;
|
||
XBell (dpy, 50);
|
||
if (tm.tm_min == 0)
|
||
XBell (dpy, 50);
|
||
}
|
||
}
|
||
|
||
/* remove this when clipping added to gcs */
|
||
if ((G_Width (w) <
|
||
(Dimension)((G_ClockWidth (w) / 2) + w->clock.centerX)) ||
|
||
(G_Height (w) <
|
||
(Dimension)((G_ClockHeight (w) / 2) + w->clock.centerY)))
|
||
return;
|
||
|
||
/* The second (or minute) hand is sec (or min) sixtieths around the
|
||
* clock face. The hour hand is (hour + min/60) twelfths of the way
|
||
* around the clock-face.
|
||
*/
|
||
if (tm.tm_hour > 12)
|
||
tm.tm_hour -= 12;
|
||
|
||
EraseHands (w, &tm);
|
||
|
||
w->clock.segbuffptr = w->clock.segbuff;
|
||
w->clock.numseg = 0;
|
||
|
||
/* Calculate the hour hand, fill it in with its color.
|
||
*/
|
||
DrawHand (w, w->clock.minute_hand_length, w->clock.hand_width,
|
||
((double) tm.tm_min)/60.0);
|
||
XDrawLines (dpy, win, G_ClockHandGC (w), w->clock.segbuff,
|
||
VERTICES_IN_HANDS, CoordModeOrigin);
|
||
XFillPolygon (dpy, win, G_ClockHandGC (w), w->clock.segbuff,
|
||
VERTICES_IN_HANDS, Convex, CoordModeOrigin);
|
||
|
||
w->clock.hour = w->clock.segbuffptr;
|
||
|
||
DrawHand (w, w->clock.hour_hand_length, w->clock.hand_width,
|
||
((((double)tm.tm_hour) +
|
||
(((double)tm.tm_min)/60.0)) / 12.0));
|
||
XFillPolygon (dpy, win, G_ClockHandGC (w), w->clock.hour,
|
||
VERTICES_IN_HANDS, Convex, CoordModeOrigin);
|
||
XDrawLines (dpy, win, G_ClockHandGC (w), w->clock.hour,
|
||
VERTICES_IN_HANDS, CoordModeOrigin);
|
||
|
||
w->clock.sec = w->clock.segbuffptr;
|
||
w->clock.otm = tm;
|
||
}
|
||
|
||
|
||
|
||
/*-------------------------------------------------------------
|
||
** EraseHands
|
||
** Erase clock hands.
|
||
*/
|
||
static void
|
||
EraseHands (
|
||
DtClockGadget w,
|
||
struct tm * tm )
|
||
{
|
||
XmManagerWidget mgr = (XmManagerWidget) XtParent (w);
|
||
Display * dpy = XtDisplay (w);
|
||
Window win = XtWindow (w);
|
||
unsigned char behavior = G_Behavior (w);
|
||
GC gc;
|
||
|
||
if (! XtIsManaged ((Widget)w) || w->clock.numseg <= 0)
|
||
return;
|
||
|
||
gc = G_ClockBackgroundGC (w);
|
||
|
||
/* Erase old hands.
|
||
*/
|
||
if (!tm || tm->tm_min != w->clock.otm.tm_min ||
|
||
tm->tm_hour != w->clock.otm.tm_hour)
|
||
{
|
||
XDrawLines (dpy, win, gc, w->clock.segbuff,
|
||
VERTICES_IN_HANDS, CoordModeOrigin);
|
||
XDrawLines (dpy, win, gc, w->clock.hour,
|
||
VERTICES_IN_HANDS, CoordModeOrigin);
|
||
XFillPolygon (dpy, win, gc, w->clock.segbuff,
|
||
VERTICES_IN_HANDS, Convex, CoordModeOrigin);
|
||
XFillPolygon (dpy, win, gc, w->clock.hour,
|
||
VERTICES_IN_HANDS, Convex, CoordModeOrigin);
|
||
}
|
||
}
|
||
|
||
|
||
|
||
/*-------------------------------------------------------------
|
||
** DrawLine
|
||
** Draw a line.
|
||
* blank_length is the distance from the center which the line begins.
|
||
* length is the maximum length of the hand.
|
||
* Fraction_of_a_circle is a fraction between 0 and 1 (inclusive) indicating
|
||
* how far around the circle (clockwise) from high noon.
|
||
*
|
||
* The blank_length feature is because I wanted to draw tick-marks around the
|
||
* circle (for seconds). The obvious means of drawing lines from the center
|
||
* to the perimeter, then erasing all but the outside most pixels doesn't
|
||
* work because of round-off error (sigh).
|
||
*/
|
||
static void
|
||
DrawLine (
|
||
DtClockGadget w,
|
||
Dimension blank_length,
|
||
Dimension length,
|
||
double fraction_of_a_circle )
|
||
{
|
||
double dblank_length = (double)blank_length, dlength = (double)length;
|
||
double angle, cosangle, sinangle;
|
||
double cos ();
|
||
double sin ();
|
||
int cx = w->clock.centerX, cy = w->clock.centerY, x1, y1, x2, y2;
|
||
|
||
/*
|
||
* A full circle is 2 PI radians.
|
||
* Angles are measured from 12 o'clock, clockwise increasing.
|
||
* Since in X, +x is to the right and +y is downward:
|
||
*
|
||
* x = x0 + r * sin (theta)
|
||
* y = y0 - r * cos (theta)
|
||
*
|
||
*/
|
||
angle = TWOPI * fraction_of_a_circle;
|
||
cosangle = cos (angle);
|
||
sinangle = sin (angle);
|
||
|
||
/* break this out so that stupid compilers can cope */
|
||
x1 = cx + (int) (dblank_length * sinangle);
|
||
y1 = cy - (int) (dblank_length * cosangle);
|
||
x2 = cx + (int) (dlength * sinangle);
|
||
y2 = cy - (int) (dlength * cosangle);
|
||
SetSegment (w, x1, y1, x2, y2);
|
||
}
|
||
|
||
|
||
|
||
/*-------------------------------------------------------------
|
||
** DrawHand
|
||
** Draw a hand.
|
||
*
|
||
* length is the maximum length of the hand.
|
||
* width is the half-width of the hand.
|
||
* Fraction_of_a_circle is a fraction between 0 and 1 (inclusive) indicating
|
||
* how far around the circle (clockwise) from high noon.
|
||
*
|
||
*/
|
||
static void
|
||
DrawHand(
|
||
DtClockGadget w,
|
||
Dimension length,
|
||
Dimension width,
|
||
double fraction_of_a_circle )
|
||
{
|
||
double angle, cosangle, sinangle;
|
||
double ws, wc;
|
||
Position x, y, x1, y1, x2, y2;
|
||
double cos ();
|
||
double sin ();
|
||
|
||
/* A full circle is 2 PI radians.
|
||
* Angles are measured from 12 o'clock, clockwise increasing.
|
||
* Since in X, +x is to the right and +y is downward:
|
||
*
|
||
* x = x0 + r * sin (theta)
|
||
* y = y0 - r * cos (theta)
|
||
*/
|
||
angle = TWOPI * fraction_of_a_circle;
|
||
cosangle = cos (angle);
|
||
sinangle = sin (angle);
|
||
|
||
/* Order of points when drawing the hand.
|
||
* 1,4
|
||
* / \
|
||
* / \
|
||
* / \
|
||
* 2 ------- 3
|
||
*/
|
||
wc = width * cosangle;
|
||
ws = width * sinangle;
|
||
SetSegment (w,
|
||
x = w->clock.centerX + wmround (length * sinangle),
|
||
y = w->clock.centerY - wmround (length * cosangle),
|
||
x1 = w->clock.centerX - wmround (ws + wc),
|
||
y1 = w->clock.centerY + wmround (wc - ws)); /* 1 ---- 2 */
|
||
SetSegment (w, x1, y1,
|
||
x2 = w->clock.centerX - wmround (ws - wc),
|
||
y2 = w->clock.centerY + wmround (wc + ws)); /* 2 ----- 3 */
|
||
SetSegment (w, x2, y2, x, y); /* 3 ----- 1 (4) */
|
||
}
|
||
|
||
|
||
|
||
/*-------------------------------------------------------------
|
||
** SetSegment
|
||
** Set segment values.
|
||
*/
|
||
static void
|
||
SetSegment(
|
||
DtClockGadget w,
|
||
int x1,
|
||
int y1,
|
||
int x2,
|
||
int y2 )
|
||
{
|
||
w->clock.segbuffptr->x = x1 + G_X (w);
|
||
w->clock.segbuffptr++->y = y1 + G_Y (w);
|
||
w->clock.segbuffptr->x = x2 + G_X (w);
|
||
w->clock.segbuffptr++->y = y2 + G_Y (w);
|
||
w->clock.numseg += 2;
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------------------
|
||
** round
|
||
** round integer.
|
||
*/
|
||
static int
|
||
wmround(
|
||
double x )
|
||
{
|
||
return (x >= 0.0 ? (int) (x + .5) : (int) (x - .5));
|
||
}
|
||
|
||
|
||
|
||
/*-------------------------------------------------------------
|
||
** DrawClockFace
|
||
*
|
||
* Draw the clock face (every fifth tick-mark is longer
|
||
* than the others).
|
||
*/
|
||
static void
|
||
DrawClockFace(
|
||
DtClockGadget g )
|
||
{
|
||
Boolean draw_minute_ticks =
|
||
((G_ClockWidth (g) > (Dimension) (2 * SIZE_DEFAULT)) &&
|
||
(G_ClockHeight (g) > (Dimension) (2 * SIZE_DEFAULT)));
|
||
int i;
|
||
int delta =
|
||
(int)(g->clock.radius - g->clock.tick_spacing) / 3;
|
||
|
||
if (! XtIsManaged ((Widget)g))
|
||
return;
|
||
|
||
g->clock.segbuffptr = g->clock.segbuff;
|
||
g->clock.numseg = 0;
|
||
|
||
/* Set segments.
|
||
*/
|
||
for (i = 0; i < 60; i++)
|
||
{
|
||
if (draw_minute_ticks)
|
||
{
|
||
if ((i % 5) == 0)
|
||
DrawLine (g, g->clock.tick_spacing,
|
||
g->clock.radius, ((double) i)/60.);
|
||
else
|
||
DrawLine (g, g->clock.radius - delta,
|
||
g->clock.radius, ((double) i)/60.);
|
||
}
|
||
else
|
||
if ((i % 15) == 0)
|
||
DrawLine (g, g->clock.radius - 1,
|
||
g->clock.radius, ((double) i)/60.);
|
||
}
|
||
|
||
/* Draw clock face.
|
||
*/
|
||
XDrawSegments (XtDisplay (g), XtWindow (g), G_ClockHandGC (g),
|
||
(XSegment *) & (g->clock.segbuff[0]),
|
||
g->clock.numseg/2);
|
||
|
||
g->clock.segbuffptr = g->clock.segbuff;
|
||
g->clock.numseg = 0;
|
||
}
|
||
|
||
|
||
|
||
/*-------------------------------------------------------------
|
||
** Action Procs
|
||
**-------------------------------------------------------------
|
||
*/
|
||
|
||
/*-------------------------------------------------------------
|
||
** Core Procs
|
||
**-------------------------------------------------------------
|
||
*/
|
||
|
||
|
||
/*-------------------------------------------------------------
|
||
** Initialize
|
||
** Initialize a new gadget instance.
|
||
*/
|
||
/* ARGSUSED */
|
||
static void
|
||
Initialize(
|
||
Widget request_w,
|
||
Widget new_w )
|
||
{
|
||
DtClockGadget request = (DtClockGadget) request_w,
|
||
new = (DtClockGadget) new_w;
|
||
Dimension w, h,
|
||
h_t = G_HighlightThickness (new),
|
||
s_t = G_ShadowThickness (new);
|
||
XmManagerWidget mw = (XmManagerWidget) XtParent (new);
|
||
EventMask mask;
|
||
String name = NULL;
|
||
|
||
/* Set width and height.
|
||
*/
|
||
if ((G_Width (request) == 0) ||
|
||
(G_Height (request) == 0))
|
||
{
|
||
G_ClockWidth (new) = SIZE_DEFAULT;
|
||
G_ClockHeight (new) = SIZE_DEFAULT;
|
||
G_GetSize ((DtIconGadget)new, &w, &h);
|
||
if (G_Width (request) == 0)
|
||
G_Width (new) = w;
|
||
if (G_Height (request) == 0)
|
||
G_Height (new) = h;
|
||
}
|
||
|
||
Resize ((Widget)new);
|
||
|
||
if (G_ClockInterval (new) <= 0)
|
||
G_ClockInterval (new) = 60; /* make invalid update's use a default */
|
||
new->clock.interval_id = 0;
|
||
new->clock.numseg = 0;
|
||
}
|
||
|
||
|
||
|
||
/*-------------------------------------------------------------
|
||
** Destroy
|
||
** Release resources allocated for gadget.
|
||
*/
|
||
static void
|
||
Destroy(
|
||
Widget w )
|
||
{
|
||
DtClockGadget g = (DtClockGadget) w;
|
||
XmManagerWidget mw = (XmManagerWidget) XtParent (g);
|
||
|
||
if (g->clock.interval_id) XtRemoveTimeOut (g->clock.interval_id);
|
||
|
||
XtReleaseGC ((Widget) mw, G_ClockHandGC (g));
|
||
}
|
||
|
||
|
||
|
||
/*-------------------------------------------------------------
|
||
** Resize
|
||
** Set positions of string and pixmap.
|
||
*/
|
||
static void
|
||
Resize(
|
||
Widget widget )
|
||
{
|
||
DtClockGadget g = (DtClockGadget) widget;
|
||
Position pix_x, pix_y, str_x, str_y;
|
||
Dimension s_t = G_ShadowThickness (g),
|
||
h_t = G_HighlightThickness (g),
|
||
p_w = G_PixmapWidth (g),
|
||
p_h = G_PixmapHeight (g),
|
||
m_w = G_MarginWidth (g),
|
||
m_h = G_MarginHeight (g),
|
||
s_w = G_StringWidth (g),
|
||
s_h = G_StringHeight (g),
|
||
v_pad = 2 * (s_t + h_t + m_h),
|
||
h_pad = 2 * (s_t + h_t + m_w),
|
||
spacing = G_Spacing (g),
|
||
w = G_Width (g),
|
||
h = G_Height (g);
|
||
int radius;
|
||
|
||
G_ClockWidth (g) = p_w - G_LeftInset (g) - G_RightInset (g);
|
||
G_ClockHeight (g) = p_h - G_TopInset (g) - G_BottomInset (g);
|
||
|
||
G_ClockWidth (g) = min (G_ClockWidth (g), G_ClockHeight (g));
|
||
G_ClockHeight (g) = G_ClockWidth (g);
|
||
|
||
G_GetPositions ((DtIconGadget)g, w, h, h_t, s_t,
|
||
&pix_x, &pix_y, &str_x, &str_y);
|
||
|
||
/* Compute clock size factors.
|
||
* (need signed radius value since Dimension is unsigned)
|
||
*/
|
||
radius = ((int) min (G_ClockWidth (g), G_ClockHeight (g))/2);
|
||
g->clock.radius = (Dimension) max (radius, 1);
|
||
|
||
if (G_ClockWidth (g) < (Dimension)(SIZE_DEFAULT / 2))
|
||
{
|
||
g->clock.tick_spacing =
|
||
((Dimension)(TICK_FRACT * g->clock.radius)/100);
|
||
g->clock.minute_hand_length =
|
||
((Dimension)(MINUTE_HAND_FRACT * g->clock.radius)/100);
|
||
g->clock.hour_hand_length =
|
||
((Dimension)(HOUR_HAND_FRACT * g->clock.radius)/100);
|
||
g->clock.hand_width =
|
||
((Dimension)(HAND_WIDTH_FRACT * g->clock.radius)/100);
|
||
}
|
||
else
|
||
{
|
||
g->clock.tick_spacing =
|
||
((Dimension)(SMALL_TICK_FRACT * g->clock.radius)/100);
|
||
g->clock.minute_hand_length =
|
||
((Dimension)(SMALL_MINUTE_HAND_FRACT * g->clock.radius)/100);
|
||
g->clock.hour_hand_length =
|
||
((Dimension)(SMALL_HOUR_HAND_FRACT * g->clock.radius)/100);
|
||
g->clock.hand_width =
|
||
((Dimension)(SMALL_HAND_WIDTH_FRACT * g->clock.radius)/100);
|
||
}
|
||
|
||
/* Compute clock position factors.
|
||
*/
|
||
g->clock.centerX = pix_x + (p_w / 2);
|
||
g->clock.centerY = pix_y + (p_h / 2);
|
||
}
|
||
|
||
|
||
|
||
/*-------------------------------------------------------------
|
||
** SetValues
|
||
**
|
||
*/
|
||
#if 0
|
||
/* ARGSUSED */
|
||
static Boolean
|
||
SetValues(
|
||
Widget current_w,
|
||
Widget request_w,
|
||
Widget new_w )
|
||
{
|
||
DtClockGadget request = (DtClockGadget) request_w,
|
||
current = (DtClockGadget) current_w,
|
||
new = (DtClockGadget) new_w;
|
||
Boolean redraw_flag = False;
|
||
|
||
if (G_ClockInterval (new) != current->clock.update)
|
||
{
|
||
if (current->clock.interval_id)
|
||
XtRemoveTimeOut (current->clock.interval_id);
|
||
if (XtIsRealized (new))
|
||
new->clock.interval_id =
|
||
XtAppAddTimeOut (
|
||
XtWidgetToApplicationContext (new_w),
|
||
G_ClockInterval (new)*1000,
|
||
(XtTimerCallbackProc) ClockTick,
|
||
(XtPointer)new_w);
|
||
}
|
||
|
||
/* Update clock face and hand color.
|
||
*/
|
||
if ((G_ClockBackground (new) != G_ClockBackground (current)) ||
|
||
(G_ClockHandPixel (new) != G_ClockHandPixel (current)))
|
||
{
|
||
G_UpdateGCs ((DtIconGadget)new);
|
||
redraw_flag = True;
|
||
}
|
||
|
||
/* Update size factors if no resize.
|
||
*/
|
||
if ((G_Width (new) == G_Width (current) &&
|
||
G_Height (new) == G_Height (current)) &&
|
||
(G_MarginWidth (new) != G_MarginWidth (current) ||
|
||
G_MarginHeight (new) != G_MarginHeight (current) ||
|
||
G_Spacing (new) != G_Spacing (current) ||
|
||
G_ShadowThickness (new) != G_ShadowThickness (current) ||
|
||
G_HighlightThickness (new) != G_HighlightThickness (current)))
|
||
Resize (new_w);
|
||
|
||
return (redraw_flag);
|
||
}
|
||
#endif /* 0 */
|
||
|
||
|
||
/*-------------------------------------------------------------
|
||
** Gadget Procs
|
||
**-------------------------------------------------------------
|
||
*/
|
||
|
||
|
||
/*-------------------------------------------------------------
|
||
** Icon Procs
|
||
**-------------------------------------------------------------
|
||
*/
|
||
|
||
/*-------------------------------------------------------------
|
||
** Draw
|
||
** Draw gadget to drawable.
|
||
*/
|
||
static void
|
||
Draw(
|
||
DtClockGadget g,
|
||
Drawable drawable,
|
||
Position x,
|
||
Position y,
|
||
Dimension w,
|
||
Dimension h,
|
||
Dimension h_t,
|
||
Dimension s_t,
|
||
unsigned char s_type,
|
||
unsigned char fill_mode )
|
||
{
|
||
XmManagerWidget mgr = (XmManagerWidget) XtParent (g);
|
||
Display * d = XtDisplay (g);
|
||
GC gc;
|
||
XRectangle clip;
|
||
Position p_x, p_y, s_x, s_y;
|
||
unsigned char behavior = G_Behavior (g);
|
||
Dimension m_w = G_MarginWidth (g);
|
||
Dimension m_h = G_MarginHeight (g);
|
||
Dimension h_pad = h_t + s_t + m_w;
|
||
Dimension v_pad = h_t + s_t + m_h;
|
||
Dimension width, height;
|
||
Pixmap pix;
|
||
Pixmap mask;
|
||
Boolean bMono;
|
||
|
||
bMono = ( ((G_Foreground (g) == BlackPixelOfScreen (XtScreen (g))) ||
|
||
(G_Foreground (g) == WhitePixelOfScreen (XtScreen (g)))) &&
|
||
((G_Background (g) == BlackPixelOfScreen (XtScreen (g))) ||
|
||
(G_Background (g) == WhitePixelOfScreen (XtScreen (g)))) );
|
||
|
||
if ((G_Armed (g)) && (fill_mode != XmFILL_PARENT))
|
||
gc = G_ArmedBackgroundGC (g);
|
||
else
|
||
gc = M_BackgroundGC (mgr);
|
||
|
||
if ((fill_mode != XmFILL_NONE) && (fill_mode != XmFILL_TRANSPARENT))
|
||
XFillRectangle (d, drawable, gc, x + h_t, y + h_t,
|
||
w - 2 * h_t, h - 2 * h_t);
|
||
|
||
G_GetPositions ((DtIconGadget)g, w, h, h_t, s_t, &p_x, &p_y, &s_x, &s_y);
|
||
|
||
if (G_Pixmap (g))
|
||
{
|
||
width = ((Dimension)(p_x + s_t + h_t) >= G_Width (g))
|
||
? 0 : min (G_PixmapWidth (g),
|
||
(Dimension)(G_Width (g) - p_x - s_t - h_t));
|
||
height = ((Dimension)(p_y + s_t + h_t) >= G_Height (g))
|
||
? 0 : min (G_PixmapHeight (g),
|
||
(Dimension)(G_Height (g) - p_y - s_t - h_t));
|
||
/* Use normal image.
|
||
*/
|
||
pix = G_Pixmap (g);
|
||
mask = G_Mask (g);
|
||
|
||
/* Update clip gc.
|
||
*/
|
||
if (mask != XmUNSPECIFIED_PIXMAP)
|
||
{
|
||
gc = G_ClipGC (g);
|
||
XSetClipMask (XtDisplay(g), gc, mask);
|
||
XSetClipOrigin (XtDisplay(g), gc, x + p_x, y + p_y);
|
||
}
|
||
else
|
||
gc = G_NormalGC (g);
|
||
|
||
/* Paint pixmap.
|
||
*/
|
||
if ((gc != NULL) && (pix != XmUNSPECIFIED_PIXMAP))
|
||
XCopyArea (d, pix, drawable, gc, 0, 0,
|
||
width, height, x + p_x, y + p_y);
|
||
}
|
||
|
||
/* Fill clock face region and draw clock.
|
||
*/
|
||
if (g->clock.numseg != 0)
|
||
EraseHands (g, (struct tm *) 0);
|
||
|
||
ClockTick ((XtPointer)g, (XtIntervalId*)NULL);
|
||
|
||
/* Draw shadow.
|
||
*/
|
||
if ((behavior == XmICON_BUTTON || behavior == XmICON_DRAG) &&
|
||
G_FillOnArm (g) && G_Armed (g))
|
||
gc = G_ArmedGC (g);
|
||
else if (behavior == XmICON_TOGGLE && G_FillOnArm (g) &&
|
||
((G_Armed (g) && !G_Set (g)) ||
|
||
(!G_Armed (g) && G_Set (g))))
|
||
gc = G_ArmedGC (g);
|
||
else
|
||
gc = G_NormalGC (g);
|
||
|
||
/* Draw string.
|
||
*/
|
||
if (G_String (g))
|
||
{
|
||
clip.x = x + h_t + s_x;
|
||
clip.y = y + h_t + s_y;
|
||
clip.width = G_Width (g) - (2 * (h_t + s_t));
|
||
clip.height = G_Height (g) - (2 * (h_t + s_t));
|
||
if (clip.width > 0 && clip.height > 0)
|
||
{
|
||
if (bMono)
|
||
{
|
||
if ((s_x - 2) >= (Position)(h_t + s_t))
|
||
XFillRectangle (d, drawable,
|
||
G_ArmedBackgroundGC (g),
|
||
x + s_x - 2, y + s_y,
|
||
2, G_StringHeight (g));
|
||
XmStringDrawImage (d, drawable, G_FontList (g),
|
||
G_String (g), G_NormalGC (g),
|
||
x + s_x, y + s_y,
|
||
clip.width, XmALIGNMENT_BEGINNING,
|
||
XmSTRING_DIRECTION_L_TO_R, &clip);
|
||
if ((s_x + (Position)(G_StringWidth (g) + 2))
|
||
<= (Position)(G_Width (g) - h_t - s_t))
|
||
XFillRectangle (d, drawable,
|
||
G_ArmedBackgroundGC (g),
|
||
x + s_x + G_StringWidth (g),
|
||
y + s_y, 2, G_StringHeight (g));
|
||
}
|
||
else
|
||
{
|
||
if (G_UseEmbossedText (g))
|
||
XmStringDraw (d, drawable, G_FontList (g),
|
||
G_String (g), G_BottomShadowGC (g),
|
||
x + s_x + 1, y + s_y + 1,
|
||
clip.width, XmALIGNMENT_BEGINNING,
|
||
XmSTRING_DIRECTION_L_TO_R, &clip);
|
||
XmStringDraw (d, drawable, G_FontList (g),
|
||
G_String (g), G_NormalGC (g),
|
||
x + s_x, y + s_y,
|
||
clip.width, XmALIGNMENT_BEGINNING,
|
||
XmSTRING_DIRECTION_L_TO_R, &clip);
|
||
|
||
}
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
|
||
|
||
/*-------------------------------------------------------------
|
||
** UpdateGCs
|
||
** Get normal and background graphics contexts.
|
||
** Use standard mask to maximize caching opportunities.
|
||
*/
|
||
static void
|
||
UpdateGCs(
|
||
DtClockGadget g )
|
||
{
|
||
XGCValues values;
|
||
XtGCMask value_mask;
|
||
XmManagerWidget mw = (XmManagerWidget) XtParent(g);
|
||
XFontStruct * font;
|
||
Boolean font_rtn;
|
||
DtIconGadgetClass
|
||
super = (DtIconGadgetClass) XtSuperclass (g);
|
||
static Boolean first = True;
|
||
|
||
/* Let superclass do most of the work.
|
||
*/
|
||
(* C_UpdateGCs (super)) ((DtIconGadget)g);
|
||
|
||
if (first)
|
||
first = False;
|
||
else if (G_ClockHandGC (g))
|
||
XtReleaseGC ((Widget)mw, G_ClockHandGC (g));
|
||
|
||
/* Get clock hand GC.
|
||
*/
|
||
|
||
value_mask = GCForeground | GCFillStyle;
|
||
|
||
if (XmeRenderTableGetDefaultFont (G_FontList (g), &font)) {
|
||
value_mask |= GCFont;
|
||
values.font = font->fid;
|
||
}
|
||
|
||
if (((G_PixmapForeground (g) == WhitePixelOfScreen (XtScreen (g))) &&
|
||
(G_PixmapBackground (g) == BlackPixelOfScreen (XtScreen (g)))) ||
|
||
((G_PixmapForeground (g) == BlackPixelOfScreen (XtScreen (g))) &&
|
||
(G_PixmapBackground (g) == WhitePixelOfScreen (XtScreen (g)))))
|
||
values.foreground = G_PixmapBackground (g);
|
||
else
|
||
values.foreground = mw->manager.top_shadow_color;
|
||
values.fill_style = FillSolid;
|
||
|
||
|
||
G_ClockHandGC (g) = XtGetGC ((Widget) mw, value_mask, &values);
|
||
|
||
/* Get clock background GC
|
||
*/
|
||
|
||
value_mask |= GCBackground;
|
||
|
||
if (((G_PixmapForeground (g) == WhitePixelOfScreen (XtScreen (g))) &&
|
||
(G_PixmapBackground (g) == BlackPixelOfScreen (XtScreen (g)))) ||
|
||
((G_PixmapForeground (g) == BlackPixelOfScreen (XtScreen (g))) &&
|
||
(G_PixmapBackground (g) == WhitePixelOfScreen (XtScreen (g)))))
|
||
values.foreground = G_PixmapForeground (g);
|
||
else
|
||
values.foreground = G_ArmColor (g);
|
||
values.background = G_PixmapBackground (g);
|
||
|
||
G_ClockBackgroundGC (g) = XtGetGC ((Widget) mw, value_mask, &values);
|
||
}
|
||
|
||
|
||
|
||
/*-------------------------------------------------------------
|
||
** Public Entry Points
|
||
**-------------------------------------------------------------
|
||
*/
|
||
|
||
/*-------------------------------------------------------------
|
||
** DtCreateClock
|
||
** Create a new gadget instance.
|
||
**-------------------------------------------------------------
|
||
*/
|
||
Widget
|
||
DtCreateClock(
|
||
Widget parent,
|
||
String name,
|
||
ArgList arglist,
|
||
Cardinal argcount )
|
||
{
|
||
return (XtCreateWidget (name, dtClockGadgetClass,
|
||
parent, arglist, argcount));
|
||
}
|