home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
x
/
volume13
/
xcal
/
part04
/
xcal_strip.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-05-12
|
17KB
|
729 lines
#ifndef lint
static char *sccsid = "@(#)xcal_strip.c 3.10 (Hillside Systems) 1/16/91";
static char *copyright = "@(#)Copyright 1989,1990 Peter Collinson, Hillside Systems";
#endif /* lint */
/***
* module name:
xcal_strip.c
* function:
Deal with the popup strip calendars obtained either by
selection and the middle button, or by the < and > buttons
on each strip.
* history:
Written November 1989
Peter Collinson
Hillside Systems
* (C) Copyright: 1989 Hillside Systems/Peter Collinson
For full permissions and copyright notice - see xcal.c
***/
#include <stdio.h>
#include <ctype.h>
#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/Shell.h>
#include <X11/Xaw/Paned.h>
#include <X11/Xaw/Command.h>
#include <X11/Xaw/Label.h>
#include <X11/Xaw/Dialog.h>
#include <X11/Xaw/AsciiText.h>
#include "xcal.h"
static XtCallbackRec callbacks[] = {
{NULL,NULL},
{NULL,NULL},
{NULL,NULL},
{NULL,NULL}
};
#define ClearCallbacks() bzero((caddr_t)callbacks, sizeof (callbacks))
Date callb; /* contains date when calendar day button pressed */
/*
* Forward routines local to this file
*/
void MakeMonth();
void DayBack();
#ifndef LONG_IS_32_BITS
void YmBack();
#endif
void StripQuit();
void StripHelp();
void WeeklyHelp();
void MakeNewMonth();
Cardinal DateSum();
Cardinal NumberOfDays();
Cardinal FirstDay();
Cardinal JanuaryOne();
/*
* Local routines
*/
static void CreateActionBar();
static void CreateWeeklyActionBar();
/*
* Start a strip calendar happening
* a callback of left button
*/
/* ARGSUSED */
void
DoCalendar(w, closure, call_data)
Widget w;
caddr_t closure;
caddr_t call_data;
{
NewMonthStrip(&today); /* today is global */
}
/* ARGSUSED */
void
DoWeekly(w, closure, call_data)
Widget w;
caddr_t closure;
caddr_t call_data;
{
Date thisday;
thisday.day = 0;
thisday.month = 0;
thisday.year = 0;
thisday.wday = 0;
NewMonthStrip(&thisday); /* today is global */
}
/*
* Start a strip calendar happening
* a callback of the > or < buttons in another strip
*/
/* ARGSUSED */
static void
MakeNewMonth(w, closure, call_data)
Widget w;
caddr_t closure;
caddr_t call_data;
{
Date thisday;
thisday.year = YrUnpack((Cardinal)closure);
thisday.month = MoUnpack((Cardinal)closure);
thisday.day = today.day;
NewMonthStrip(&thisday);
}
/*
* Do all the X stuff to popup a Strip calendar
* A calendar strip is:
*
* Popup ("<month year>") // Name is the month and the year
* Paned ("<month>") // Name is the month
* Label ("header") // optional contains Month Year
* Form ("action") // < Quit >
* Command ("back") // contains <
* Label ("quit") // contains Quit
* Command ("next") // contains >
* (Then many of..)
* Form ("<dd DDD>") // where dd is the day number, DDD is the
* // day of the week
* Label ("label") // contains the string above
* Command ("info") // contains the text from the file
*
*/
void
NewMonthStrip(td)
Date *td;
{
Widget shell, mon, dw, lw, lwi, form;
Arg args[15];
char nbuf[256];
char iconName[80];
int type;
MonthEntry *me;
Instance *ins;
register int i;
register Cardinal nargs;
Cardinal thisDay;
Cardinal startLoop;
String dayStr;
Cardinal numberOfDays;
Boolean defaultsAreSet = False;
Boolean markThisMonth = False;
Cardinal adjustLabelY;
Cardinal adjustInfoY;
Dimension labelH, infoH;
Dimension width;
Dimension totalWidth;
type = (td->day == 0) ? ME_WEEKLY : ME_MONTHLY;
/*
* There are lots of differences between
* Months and weekly strips here.
* Later tests are done using a switch structure
*/
switch (type)
{
case ME_MONTHLY:
(void) sprintf(iconName, "%s %d", appResources.smon[td->month], td->year);
XtSetArg(args[0], XtNiconName, iconName);
shell = XtCreatePopupShell(XtNewString(iconName), topLevelShellWidgetClass, toplevel, args, 1);
ins = RegisterMonth(td->year, td->month, shell);
mon = XtCreateManagedWidget(appResources.mon[td->month], panedWidgetClass, shell, NULL, 0);
thisDay = FirstDay(td->month, td->year);
numberOfDays = NumberOfDays(td->month, td->year);
startLoop = 1;
/*
* Get the map for this year
*/
me = GetMonthEntry(td->year, td->month);
me->me_type = type;
/*
* Title bar is month and date
*/
(void) sprintf(nbuf, "%s %d", appResources.mon[td->month], td->year);
/*
* see if we will need to worry about marking today's entry
*/
if (appResources.markToday && td->year == today.year && td->month == today.month)
markThisMonth = True;
break;
case ME_WEEKLY:
(void) strcpy(iconName, appResources.weekly);
XtSetArg(args[0], XtNiconName, iconName);
shell = XtCreatePopupShell(XtNewString(iconName), topLevelShellWidgetClass, toplevel, args, 1);
ins = RegisterMonth(0, 0, shell);
mon = XtCreateManagedWidget(iconName, panedWidgetClass, shell, NULL, 0);
thisDay = 0;
numberOfDays = 6; /* test is <= */
startLoop = 0;
/*
* Get the map for this year
*/
me = GetWeeklyEntry();
me->me_type = type;
/*
* Title bar is from the resources
*/
strcpy(nbuf, iconName);
/*
* see if we will need to worry about marking today's entry
*/
if (appResources.markToday)
markThisMonth = True;
break;
}
/*
* Find size of title bar
* by creating the widget and then throwing it away
*/
XtSetArg(args[0], XtNlabel, "mmmmmmmmm NNNN");
lw = XtCreateManagedWidget("sizer", labelWidgetClass, shell, args, 1);
XtSetArg(args[0], XtNwidth, &totalWidth);
XtGetValues(lw, args, 1);
XtDestroyWidget(lw);
/*
* Width is affected by a resource value
*/
if (appResources.minstripwidth && appResources.minstripwidth > totalWidth)
totalWidth = appResources.minstripwidth;
/*
* Now set the title bar should we need it
*/
if (appResources.useWmTitle)
{ XtSetArg(args[0], XtNlabel, XtNewString(nbuf));
(void) XtCreateManagedWidget("header", labelWidgetClass, mon, args, 1);
}
/*
* Action bar
*/
nargs = 0;
XtSetArg(args[nargs], XtNshowGrip, False); nargs++;
XtSetArg(args[nargs], XtNdefaultDistance, 2); nargs++;
dw = XtCreateManagedWidget("action", formWidgetClass, mon, args, nargs);
switch (type)
{
case ME_MONTHLY:
CreateActionBar(shell, dw, mon, td);
break;
case ME_WEEKLY:
CreateWeeklyActionBar(shell, dw);
break;
}
#ifdef LONG_IS_32_BITS
callbacks[0].callback = DayBack;
#else
callbacks[0].callback = YmBack;
callbacks[1].callback = DayBack;
#endif
for (i = startLoop; i <= numberOfDays; i++)
{
dayStr = appResources.sday[thisDay];
switch(type)
{
case ME_MONTHLY:
(void) sprintf(nbuf, "%2d %s", i, dayStr);
break;
case ME_WEEKLY:
(void) strcpy(nbuf, dayStr);
break;
}
#ifdef LONG_IS_32_BITS
callbacks[0].closure = (caddr_t)DatePack(thisDay, i, td->month, td->year);
#else
callbacks[0].closure = (caddr_t)DatePack(td->month, td->year);
callbacks[1].closure = (caddr_t)DayPack(thisDay, i);
#endif
thisDay = (thisDay+1)%7;
/*
* Each line in the strip is
* form containing
* label - command
*/
nargs = 0;
XtSetArg(args[nargs], XtNshowGrip, False); nargs++;
XtSetArg(args[nargs], XtNdefaultDistance, 0); nargs++;
form = XtCreateManagedWidget(dayStr, formWidgetClass, mon, args, nargs);
nargs = 0;
XtSetArg(args[nargs], XtNlabel, XtNewString(nbuf)); nargs++;
/* a little naughty here */
/* this string memory is lost */
/* on quit */
XtSetArg(args[nargs], XtNborderWidth, 0); nargs++;
XtSetArg(args[nargs], XtNjustify, XtJustifyLeft); nargs++;
XtSetArg(args[nargs], XtNfromHoriz, NULL); nargs++;
XtSetArg(args[nargs], XtNleft, XtChainLeft); nargs++;
XtSetArg(args[nargs], XtNright, XtChainLeft); nargs++;
ins->i_day_label[i] = lw = XtCreateManagedWidget("label", labelWidgetClass, form, args, nargs);
/*
* To get a handle on the old values which are lost by
* highlighting we get them after we have created the
* widget. Then we highlight today.
*/
if (markThisMonth &&
((type == ME_MONTHLY && today.day == i) ||
(type == ME_WEEKLY && today.wday == i)))
{
nargs = 0;
XtSetArg(args[nargs], XtNforeground, &ins->i_col.fg); nargs++;
XtSetArg(args[nargs], XtNbackground, &ins->i_col.bg); nargs++;
XtSetArg(args[nargs], XtNfont, &ins->i_font); nargs++;
XtGetValues(lw, args, nargs);
nargs = 0;
XtSetArg(args[nargs], XtNforeground, appResources.today.fg); nargs++;
XtSetArg(args[nargs], XtNbackground, appResources.today.bg); nargs++;
XtSetArg(args[nargs], XtNfont, appResources.fontToday); nargs++;
XtSetValues(lw, args, nargs);
}
/*
* Done the first time through
* Gets the width of the line we have just made
*/
if (defaultsAreSet == False)
{ /* compute text width */
nargs = 0;
XtSetArg(args[nargs], XtNwidth, &width); nargs++;
XtSetArg(args[nargs], XtNheight, &labelH); nargs++;
XtGetValues(lw, args, nargs);
defaultsAreSet = True;
}
/*
* Start processing the RHS of the line
* This contains text from the file
* should any exist
*/
nargs = 0;
XtSetArg(args[nargs], XtNborderWidth, 0); nargs++;
XtSetArg(args[nargs], XtNcallback, callbacks); nargs++;
XtSetArg(args[nargs], XtNfromHoriz, lw); nargs++;
XtSetArg(args[nargs], XtNleft, XtChainLeft); nargs++;
XtSetArg(args[nargs], XtNright, XtChainRight); nargs++;
XtSetArg(args[nargs], XtNjustify, XtJustifyLeft); nargs++;
XtSetArg(args[nargs], XtNwidth, totalWidth - width); nargs++;
if (me->me_have[i])
{ XtSetArg(args[nargs], XtNforeground, appResources.marked.fg); nargs++;
XtSetArg(args[nargs], XtNbackground, appResources.marked.bg); nargs++;
XtSetArg(args[nargs], XtNlabel, me->me_have[i]); nargs++;
}
else
{ XtSetArg(args[nargs], XtNlabel, " "); nargs++; }
ins->i_day_info[i] = lwi = XtCreateManagedWidget("info", commandWidgetClass, form, args, nargs);
/* deal with height */
XtSetArg(args[0], XtNheight, &infoH);
XtGetValues(lwi, args, 1);
if (labelH < infoH)
{ adjustLabelY = ((infoH-labelH)/2);
/* fix up widget */
nargs = 0;
XtSetArg(args[nargs], XtNvertDistance, adjustLabelY); nargs++;
XtSetArg(args[nargs], XtNfromVert, NULL); nargs++;
XtSetValues(lw, args, nargs);
}
else
if (labelH > infoH)
{ adjustInfoY = ((labelH - infoH)/2);
/* fix up widget 1 */
nargs = 0;
XtSetArg(args[nargs], XtNvertDistance, adjustInfoY); nargs++;
XtSetArg(args[nargs], XtNfromVert, NULL); nargs++;
XtSetValues(lwi, args, nargs);
}
/*
* cope with 1752
*/
if (td->year == 1752 && td->month == 8 && i == 2)
{ i = 13;
numberOfDays += 11; /* giving back the 11 days */
}
}
ClearCallbacks();
XtPopup(shell, XtGrabNone);
}
/*
* Create action bar for normal monthly strip
*/
static void
CreateActionBar(shell, dw, mon, td)
Widget shell;
Widget dw;
Widget mon;
Date *td;
{
Widget lw;
register Cardinal nargs;
Arg args[8];
/*
* back one month
* label "<" from resources
*/
callbacks[0].callback = MakeNewMonth;
callbacks[0].closure = (caddr_t)DateSum(td, -1);
nargs = 0;
XtSetArg(args[nargs], XtNcallback, callbacks); nargs++;
XtSetArg(args[nargs], XtNfromHoriz, NULL); nargs++;
XtSetArg(args[nargs], XtNleft, XtChainLeft); nargs++;
XtSetArg(args[nargs], XtNright, XtChainLeft); nargs++;
lw = XtCreateManagedWidget("back", commandWidgetClass, dw, args, nargs);
ClearCallbacks();
/*
* Quit button
* label "quit" from resources
*/
callbacks[0].callback = StripQuit;
callbacks[0].closure = (caddr_t)shell;
nargs = 0;
XtSetArg(args[nargs], XtNcallback, callbacks); nargs++;
XtSetArg(args[nargs], XtNfromHoriz, lw); nargs++;
XtSetArg(args[nargs], XtNleft, XtChainLeft); nargs++;
XtSetArg(args[nargs], XtNright, XtChainRight); nargs++;
lw = XtCreateManagedWidget("quit", commandWidgetClass, dw, args, nargs);
ClearCallbacks();
/*
* On one month
* label ">" from reources
*/
callbacks[0].callback = MakeNewMonth;
callbacks[0].closure = (caddr_t)DateSum(td, 1);
nargs = 0;
XtSetArg(args[nargs], XtNcallback, callbacks); nargs++;
XtSetArg(args[nargs], XtNfromHoriz, lw); nargs++;
XtSetArg(args[nargs], XtNleft, XtChainRight); nargs++;
XtSetArg(args[nargs], XtNright, XtChainRight); nargs++;
lw = XtCreateManagedWidget("next", commandWidgetClass, dw, args, nargs);
ClearCallbacks();
/*
* Help button
* label help from resources
*/
if (appResources.giveHelp)
{
callbacks[0].callback = StripHelp;
callbacks[0].closure = (caddr_t)0;
nargs = 0;
XtSetArg(args[nargs], XtNcallback, callbacks); nargs++;
XtSetArg(args[nargs], XtNshowGrip, False); nargs++;
lw = XtCreateManagedWidget("help", commandWidgetClass, mon, args, nargs);
ClearCallbacks();
}
}
/*
* Create action bar for normal monthly strip
*/
static void
CreateWeeklyActionBar(shell, dw)
Widget shell;
Widget dw;
{
Widget lw;
register Cardinal nargs;
Arg args[8];
/*
* Quit button
* label "quit" from resources
*/
callbacks[0].callback = StripQuit;
callbacks[0].closure = (caddr_t)shell;
nargs = 0;
XtSetArg(args[nargs], XtNcallback, callbacks); nargs++;
XtSetArg(args[nargs], XtNfromHoriz, NULL); nargs++;
XtSetArg(args[nargs], XtNleft, XtChainLeft); nargs++;
XtSetArg(args[nargs], XtNright, appResources.giveHelp ? XtChainLeft: XtChainRight); nargs++;
lw = XtCreateManagedWidget("quit", commandWidgetClass, dw, args, nargs);
ClearCallbacks();
/*
* Help button
* label help from resources
*/
if (appResources.giveHelp)
{
callbacks[0].callback = WeeklyHelp;
callbacks[0].closure = (caddr_t)0;
nargs = 0;
XtSetArg(args[nargs], XtNcallback, callbacks); nargs++;
XtSetArg(args[nargs], XtNfromHoriz, lw); nargs++;
XtSetArg(args[nargs], XtNleft, XtChainLeft); nargs++;
XtSetArg(args[nargs], XtNright, XtChainRight); nargs++;
lw = XtCreateManagedWidget("help", commandWidgetClass, dw, args, nargs);
ClearCallbacks();
}
}
/*
* Called when the date changes to ensure that
* the correct day has the appropriate highlights
*/
void
ChangeHighlight(old, new)
Date *old;
Date *new;
{
register Instance *ins;
Arg args[5];
Cardinal nargs;
for (ins = FindInstanceList(old); ins; ins = ins->i_next)
{ nargs = 0;
XtSetArg(args[nargs], XtNforeground, ins->i_col.fg); nargs++;
XtSetArg(args[nargs], XtNbackground, ins->i_col.bg); nargs++;
XtSetArg(args[nargs], XtNfont, ins->i_font); nargs++;
XtSetValues(ins->i_day_label[old->day], args, nargs);
}
for (ins = FindInstanceList(new); ins; ins = ins->i_next)
{ nargs = 0;
XtSetArg(args[nargs], XtNforeground, &ins->i_col.fg); nargs++;
XtSetArg(args[nargs], XtNbackground, &ins->i_col.bg); nargs++;
XtSetArg(args[nargs], XtNfont, &ins->i_font); nargs++;
XtGetValues(ins->i_day_label[new->day], args, nargs);
nargs = 0;
XtSetArg(args[nargs], XtNforeground, appResources.today.fg); nargs++;
XtSetArg(args[nargs], XtNbackground, appResources.today.bg); nargs++;
XtSetArg(args[nargs], XtNfont, appResources.fontToday); nargs++;
XtSetValues(ins->i_day_label[new->day], args, nargs);
}
}
/*
* Call back from a quit button to lose a month strip
*/
/* ARGSUSED */
static void
StripQuit(w, closure, call_data)
Widget w;
caddr_t closure;
caddr_t call_data;
{
XtPopdown((Widget)closure);
XtDestroyWidget((Widget)closure);
}
/*
* Month arithmetic and packing
*/
static Cardinal
DateSum(td, inx)
Date *td;
int inx;
{
int m, y;
m = td->month;
y = td->year;
m += inx;
if (m < 0)
{ m = 11;
y--;
}
else
if (m > 11)
{ m = 0;
y++;
}
#ifdef LONG_IS_32_BITS
return(DatePack(0, 0, m, y));
#else
return(DatePack(m, y));
#endif
}
/*
* Call back from day selection button press
* This is done in two stages if cannot fold dates into a closure
*/
/* ARGSUSED */
static void
DayBack(w, closure, call_data)
Widget w;
caddr_t closure;
caddr_t call_data;
{
#ifdef LONG_IS_32_BITS
callb.month = MoUnpack((Cardinal)closure);
callb.year = YrUnpack((Cardinal)closure);
#endif
callb.day = DyUnpack((Cardinal)closure);
callb.wday = WdUnpack((Cardinal)closure);
StartEditing(w, &callb);
}
#ifndef LONG_IS_32_BITS
/* ARGSUSED */
static void
YmBack(w, closure, call_data)
Widget w;
caddr_t closure;
caddr_t call_data;
{
callb.month = MoUnpack((Cardinal)closure);
callb.year = YrUnpack((Cardinal)closure);
}
#endif
/*
* Stolen from xcalendar.c
*/
/* taken from cal.c */
char mon[] = {
31, 29, 31, 30,
31, 30, 31, 31,
30, 31, 30, 31,
};
static Cardinal calInit = 0;
static Cardinal
NumberOfDays(m, y)
Cardinal m, y;
{
if(calInit != y)
(void) FirstDay(m, y); /* set side effect */
return mon[m];
}
/* should be called first */
static Cardinal
FirstDay(m, y)
Cardinal m, y;
{
register d, i;
calInit = y;
d = JanuaryOne(y);
mon[1] = 29;
mon[8] = 30;
switch((JanuaryOne(y+1)+7-d)%7)
{
/*
* non-leap year
*/
case 1:
mon[1] = 28;
break;
/*
* 1752
*/
default:
mon[8] = 19;
break;
/*
* leap year
*/
case 2:
;
}
for(i=0; i<m; i++)
d += mon[i];
return(d%7);
}
/*
* return day of the week
* of jan 1 of given year
*/
static Cardinal
JanuaryOne(yr)
Cardinal yr;
{
register Cardinal y, d;
/*
* normal gregorian calendar
* one extra day per four years
*/
y = yr;
d = 4+y+(y+3)/4;
/*
* julian calendar
* regular gregorian
* less three days per 400
*/
if(y > 1800) {
d -= (y-1701)/100;
d += (y-1601)/400;
}
/*
* great calendar changeover instant
*/
if(y > 1752)
d += 3;
return(d%7);
}