1 /*
2  *
3  * Copyright (C) 1988 Massachusetts Institute of Technology
4  *
5  */
6 
7 /*
8  * Permission to use, copy, modify, and distribute this software and its
9  * documentation for any purpose and without fee is hereby granted, provided
10  * that the above copyright notice appear in all copies and that both that
11  * copyright notice and this permission notice appear in supporting
12  * documentation, and that the name of M.I.T. not be used in advertising or
13  * publicity pertaining to distribution of the software without specific,
14  * written prior permission. M.I.T. makes no representations about the
15  * suitability of this software for any purpose.  It is provided "as is"
16  * without express or implied warranty.
17  *
18  */
19 
20 /***********************************************************************
21 * Copyright 1990-1994 by Richard Bingle and Purdue University.  All rights
22 * reserved.  Some individual files may be covered by other copyrights.
23 *
24 * Redistribution and use in source and binary forms are permitted
25 * provided that this entire copyright notice is duplicated in all such
26 * copies.  Neither the name of the University, nor the name of the author
27 * may be used to endorse or promote products derived from this material
28 * without specific prior written permission.
29 *
30 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
31 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
32 * MERCHANTIBILITY AND FITNESS FOR ANY PARTICULAR PURPOSE.
33 ************************************************************************/
34 
35 
36 /** Authors:  Roman J. Budzianowski - Project Athena, MIT **/
37 /**           Richard Bingle - Comp. Sci. Dept., Purdue University **/
38 /** Version 4.0  **/
39 
40 #include "xcalendar.h"
41 
42 Cardinal        displayedMonth, displayedYear;
43 Widget          toplevel;
44 Display        *dsp;
45 int             debug = 0;
46 List            daylist;
47 List            holilist;
48 void            FormGeometryHandler();
49 LList          *dayEntryList;
50 Cardinal        day, month, year;
51 Boolean         dayEntryState = False;
52 Arg             markedDayColors[2];
53 Arg             unmarkedDayColors[2];
54 void            ShowEntries();
55 Window          markedDaysKey;
56 Window          allDaysKey;
57 LList          *allDaysList;
58 Widget          date;
59 Widget          daynumbers;
60 Widget          help_button;
61 Widget          cdate;
62 char           *smonth[13];
63 Cardinal        defFirstDay = 1;
64 
65 XtActionsRec    appActions[] = {
66     {"ShowEntries", ShowEntries},
67 };
68 
69 String          defTranslations =
70 "<Btn1Down>:ShowEntries()";
71 
72 #define SetResOffset(n,field) \
73   appResourceList[n].resource_offset = ((char *)&appResources.field - (char *)&appResources)
74 #define offset(field) XtOffset(struct _appRes *, field)
75 
76 AppResourcesRec appResources;	/* application specific resources */
77 
78 XtResource      appResourceList[] = {
79     {"reverseVideoMark", "ReverseVideo", XtRBoolean, sizeof(Boolean),
80     offset(reverseVideo), XtRString, "False"},
81     {"setMarkForeground", "SetForeground", XtRBoolean, sizeof(Boolean),
82     offset(setForeground), XtRString, "False"},
83     {"markForeground", "MarkForeground", XtRPixel, sizeof(Pixel),
84     offset(markForeground), XtRString, XtDefaultForeground},
85     {"setMarkBackground", "SetBackground", XtRBoolean, sizeof(Boolean),
86     offset(setBackground), XtRString, "False"},
87     {"markBackground", "MarkBackground", XtRPixel, sizeof(Pixel),
88     offset(markBackground), XtRString, XtDefaultBackground},
89     {"monthnames", "Monthnames", XtRString, sizeof(String),
90     offset(monthnames), XtRString, "January/February/March/April/May/June/July/August/September/October/November/December"},
91     {"monthnms", "Monthnms", XtRString, sizeof(String),
92     offset(monthnms), XtRString, "Jan/Feb/Mar/Apr/May/Jun/Jul/Aug/Sep/Oct/Nov/Dec"},
93     {"daynames", "Daynames", XtRString, sizeof(String),
94     offset(daynames), XtRString, "Sunday/Monday/Tuesday/Wednesday/Thursday/Friday/Saturday"},
95     {"daynms", "Daynms", XtRString, sizeof(String),
96     offset(daynms), XtRString, "Sun/Mon/Tue/Wed/Thu/Fri/Sat"},
97     {"date", "Date", XtRString, sizeof(String),
98     offset(date), XtRString, "%W, %M %d"},
99     {"january", "January", XtRString, sizeof(String),
100     offset(months[0]), XtRString, "January"},
101     {"february", "February", XtRString, sizeof(String),
102     offset(months[1]), XtRString, "February"},
103     {"march", "March", XtRString, sizeof(String),
104     offset(months[2]), XtRString, "March"},
105     {"april", "April", XtRString, sizeof(String),
106     offset(months[3]), XtRString, "April"},
107     {"may", "May", XtRString, sizeof(String),
108     offset(months[4]), XtRString, "May"},
109     {"june", "June", XtRString, sizeof(String),
110     offset(months[5]), XtRString, "June"},
111     {"july", "July", XtRString, sizeof(String),
112     offset(months[6]), XtRString, "July"},
113     {"august", "August", XtRString, sizeof(String),
114     offset(months[7]), XtRString, "August"},
115     {"september", "September", XtRString, sizeof(String),
116     offset(months[8]), XtRString, "September"},
117     {"october", "October", XtRString, sizeof(String),
118     offset(months[9]), XtRString, "October"},
119     {"november", "November", XtRString, sizeof(String),
120     offset(months[10]), XtRString, "November"},
121     {"december", "December", XtRString, sizeof(String),
122     offset(months[11]), XtRString, "December"},
123     {"firstDay", "FirstDay", XtRInt, sizeof(int),
124     offset(firstDay), XtRInt, (XtPointer) & defFirstDay},
125     {"markOnStartup", "MarkOnStarup", XtRBoolean, sizeof(Boolean),
126     offset(markOnStartup), XtRString, "False"},
127     {"helpFile", "HelpFile", XtRString, sizeof(String),
128     offset(helpFile), XtRString, "/usr/lib/X11/xcalendar/xcalendar.hlp"},
129     {"textBufferSize", "TextBufferSize", XtRInt, sizeof(int),
130     offset(textBufferSize), XtRString, "2048"},
131     {"calendarDir", "CalendarDir", XtRString, sizeof(String),
132     offset(calendarDir), XtRImmediate, NULL},
133     {"holidayFile", "HolidayFile", XtRString, sizeof(String),
134     offset(holidayFile), XtRImmediate, "/usr/lib/X11/xcalendar/xcalendar.hol"},
135     {"oldStyle", "OldStyle", XtRBoolean, sizeof(Boolean),
136     offset(oldStyle), XtRString, "True"},
137     {"markCurrent", "MarkCurrent", XtRBoolean, sizeof(Boolean),
138     offset(markCurrent), XtRString, "False"},
139     {"updateCurrent", "UpdateCurrent", XtRInt, sizeof(int),
140     offset(updateCurrent), XtRString, "60"},
141     {"currentForeground", "CurrentForeground", XtRPixel, sizeof(Pixel),
142     offset(currentForeground), XtRString, XtDefaultForeground},
143     {"markHoliday", "MarkHoliday", XtRBoolean, sizeof(Boolean),
144     offset(markHoliday), XtRString, "False"},
145     {"holidayForeground", "HolidayForeground", XtRPixel, sizeof(Pixel),
146     offset(holidayForeground), XtRString, XtDefaultForeground},
147 };
148 
149 static int      marked_day;
150 
151 Arg             markColors[2];
152 Cardinal        nMark = 0;
153 
154 static XtCallbackRec callbacks[] = {
155     {NULL, NULL},
156     {NULL, NULL},
157 };
158 
159 /*
160  * quit() - Quit callback.
161  */
162 
163 void
quit(w,closure,call_data)164 quit(w, closure, call_data)
165     Widget          w;
166     XtPointer       closure;
167     XtPointer       call_data;
168 {
169     CloseEditors();
170     exit(0);
171 }
172 
173 char           *helpText =
174 "\n\
175 The full text of help is not available, because the help file\n\
176 couldn't be opened. Set the resource 'helpFile' to\n\
177 the full pathname of the xcalendar.hlp on your system.\n\
178 \n\
179 XCalendar is a simple interactive calendar program with a notebook\n\
180 capability. It is built on the X Toolkit and uses either the Athena\n\
181 or Motif Widgets.\n\
182 \n\
183 You can start the program as:  xcalendar [month [year]]\n\
184 \n\
185 CREDITS:\n\
186       Version 4.0 \n\
187       Authors: Roman J. Budzianowski - MIT Project Athena\n\
188                     Copyright 1988 Massachusetts Institute of Technology\n\
189                Richard Bingle - Comp. Sci. Dept., Purdue University\n\
190                     Copyright 1990 Purdue University\n\
191       Contributions:\n\
192                Beth Chaney - Comp. Sci. Dept., Purdue University\n\
193                Mike Urban - JPL, NASA\n\
194                Joel Neisen - Minnesota Supercomputer Center\n\
195                Hiroshi Kuribayashi - Omron Corp.\n\
196 \n\
197 ";
198 
199 String          on[1] = {"on"};
200 
201 /*
202  * help() - Help callback.
203  */
204 
205 void
help(w,closure,call_data)206 help(w, closure, call_data)
207     Widget          w;
208     XtPointer       closure;
209     XtPointer       call_data;
210 {
211     static DayEditor help = NULL;
212     char           *iconName = "xcalendar: help";
213     Arg             args[10];
214     int             n;
215 
216     if (!help) {
217 #ifdef ATHENA
218 	help = CreateDayEditor("helpWindow", XawtextWrapNever, NULL);
219 #else
220 	help = CreateMotifDayEditor("helpWindow", NULL, NULL);
221 #endif
222 
223 	help->button = w;
224 	help->used = True;
225 	help->saved = True;
226 	help->filename = appResources.helpFile;
227 
228 	if (ReadFile(help) == False || EmptyBuffer(help)) {
229 	    XtFree(help->buffer);
230 	    (void) ChangeTextSource(help, helpText);
231 	}
232 	XtUnmanageChild(help->saveButton);
233 	XtUnmanageChild(help->clearEntry);
234 
235 	XtUnmanageChild(help->prevday);
236 	XtUnmanageChild(help->succday);
237 
238 	XtUnmanageChild(help->holiday);
239 
240 	n = 0;
241 #ifdef ATHENA
242 	XtSetArg(args[n], XtNeditType, XawtextRead);
243 	n++;
244 #else
245 	XtSetArg(args[n], XmNeditable, False);
246 	n++;
247 #endif
248 	XtSetValues(help->editor, args, n);
249     }
250     n = 0;
251     XtSetArg(args[n], XtNiconName, iconName);
252     n++;
253     XtSetValues(help->shell, args, n);
254 
255 #ifndef ATHENA
256     n = 0;
257     XtSetArg(args[n], XmNleftPosition, 1);
258     n++;
259     XtSetArg(args[n], XmNrightPosition, 2);
260     n++;
261     XtSetValues(help->doneButton, args, n);
262 #endif
263 
264     StartEditor(help);
265 }
266 
267 /*
268  * ChangeMonth() - changes view to month and year specified by the global
269  * variable month and year.
270  */
271 
272 void
ChangeMonth()273 ChangeMonth()
274 {
275     Widget          CreateCalendarFrame();
276     void            prevmonth(), succmonth();
277     Cardinal        numberOfDays, firstDay;
278     Arg             args[10];
279     int             n;
280     char            title[80];
281     void            NewDayNumbers();
282 #ifndef ATHENA
283     XmString        xms;
284 #endif
285 
286     /**  in order to add the new buttons **/
287 
288     sprintf(title, "%s %d", smonth[month], year);
289 
290     firstDay = FirstDay(month, year);
291     numberOfDays = NumberOfDays(month, year);
292 
293 
294     /* date label */
295 
296     n = 0;
297 #ifdef ATHENA
298     XtSetArg(args[n], XtNlabel, title);
299     n++;
300     XtSetValues(date, args, n);
301 #else
302     xms = XMS(title);
303     XtSetArg(args[n], XmNlabelString, xms);
304     n++;
305     XtSetValues(date, args, n);
306     XmStringFree(xms);
307 #endif
308 
309     /* call NewDayNumbers */
310     NewDayNumbers(numberOfDays, firstDay);
311 }
312 
313 /*
314  * prevmonth() - Sets month (and if needed, year) to the prior month.
315  */
316 
317 void
prevmonth(w,closure,call_data)318 prevmonth(w, closure, call_data)
319     Widget          w;
320     XtPointer       closure;
321     XtPointer       call_data;
322 
323 {
324     if (displayedMonth == 1) {
325 	displayedMonth = month = 12;
326 	displayedYear = year = --displayedYear;
327     } else
328 	displayedMonth = month = --displayedMonth;
329 
330     ChangeMonth();
331 }
332 
333 /*
334  * succmonth() - Sets month (and if needed, year) to the next month.
335  */
336 
337 void
succmonth(w,closure,call_data)338 succmonth(w, closure, call_data)
339     Widget          w;
340     XtPointer       closure;
341     XtPointer       call_data;
342 
343 {
344     if (displayedMonth == 12) {
345 	displayedMonth = month = 1;
346 	displayedYear = year = ++displayedYear;
347     } else
348 	displayedMonth = month = ++displayedMonth;
349     ChangeMonth();
350 }
351 
352 /*
353  * main() - Main routine.
354  */
355 
356 void
main(argc,argv)357 main(argc, argv)
358     int             argc;
359     char          **argv;
360 {
361     Arg             args[10];
362     int             n;
363     char            title[80];
364     char            iconName[80];
365     int             i, resNo = 0;
366     Widget          frame;
367 
368 #ifdef XI18N
369     XtSetLanguageProc(NULL, NULL, NULL);
370 #endif
371     toplevel = XtInitialize(NULL, "XCalendar", NULL, 0, &argc, argv);
372 
373     dsp = XtDisplay(toplevel);
374 
375     /* get application specific resources */
376 
377     if (XtScreen(toplevel)->root_visual->class == StaticGray)
378 	appResourceList[0].default_addr = "True";
379 
380     XtGetApplicationResources(toplevel, (XtPointer) & appResources,
381 			      appResourceList, XtNumber(appResourceList),
382 			      NULL, 0);
383 
384     for (i = 0; i < 12; i++) {
385 	smonth[i + 1] = appResources.months[i];
386     }
387 
388     if (appResources.setBackground) {
389 
390 	XtSetArg(markColors[nMark], XtNbackground, appResources.markBackground);
391 	nMark++;
392     }
393     if (appResources.setForeground) {
394 
395 	XtSetArg(markColors[nMark], XtNforeground, appResources.markForeground);
396 	nMark++;
397     }
398 
399 #ifndef ATHENA
400     XtAddEventHandler(toplevel, (EventMask)0, True,
401                       _XEditResCheckMessages, NULL);
402 #endif
403 
404     LoadHolidays();
405 
406     day = current_day();
407     month = current_month();
408     year = current_year();
409 
410     if (argc >= 2)
411 	month = atoi(argv[1]);
412     if (!month)
413 	month = current_month();
414 
415     if (argc == 3)
416 	year = atoi(argv[2]);
417     if (!year)
418 	year = current_year();
419 
420     displayedMonth = month;
421     displayedYear = year;
422 
423     sprintf(iconName, "xcalendar: %s %d", smonth[displayedMonth],
424 	    displayedYear);
425 
426     n = 0;
427     XtSetArg(args[n], XtNiconName, iconName);
428     n++;
429     XtSetValues(toplevel, args, n);
430 
431     sprintf(title, "%s %d", smonth[month], year);
432 
433 #ifdef ATHENA
434     frame = CreateCalendar(toplevel);
435 #else
436     frame = CreateMotifCalendar(toplevel);
437 #endif
438 
439     /*
440      * Create the windows
441      */
442 
443     XtRealizeWidget(toplevel);
444 
445     allDaysKey = XtWindow(toplevel);
446     allDaysList = NULL;
447     markedDaysKey = XtWindow(frame);
448     MakeDayList();
449 
450     /** mark the entries **/
451 
452     if (appResources.markOnStartup == True) {
453 	n = 1;
454 	ShowEntries(toplevel, NULL, on, &n);
455     }
456     marked_day = -1;
457     if (appResources.updateCurrent <= 0)
458 	appResources.updateCurrent = 60;
459     CurrentTic(toplevel, NULL);
460 
461     /*
462      * Now process the events.
463      */
464     XtMainLoop();
465 }
466 
467 /*
468  * ShowEntries() - Toggles the marking of days with something in them.
469  */
470 
471 void
ShowEntries(w,event,params,numb)472 ShowEntries(w, event, params, numb)
473     Widget          w;
474     XEvent         *event;
475     String         *params;
476     Cardinal       *numb;
477 {
478     LList          *listp;
479     Arg             colors[2];
480     Arg            *args = colors;
481     Cardinal        n = 2;
482 
483     initialized = False;
484 
485     if (!(initialized || InitEditors()))
486 	return;
487 
488     if (numb && *numb) {
489 	if (!strcmp(params[0], "on"))
490 	    dayEntryState = True;
491 	else if (!strcmp(params[0], "off"))
492 	    dayEntryState = False;
493     } else {
494 	if (dayEntryState)
495 	    dayEntryState = False;
496 	else
497 	    dayEntryState = True;
498     }
499 
500 
501     listp = allDaysList;
502     if (allDaysList)
503 	do {
504 
505 	    XtSetArg(colors[0], XtNforeground, DayForeground(listp));
506 
507 	    if (is_holiday((Widget) listp->element) &&
508 		appResources.markHoliday) {
509 		XtSetArg(colors[0], XtNforeground,
510 			 appResources.holidayForeground);
511 	    }
512 	    if (is_today((Widget) listp->element) && appResources.markCurrent) {
513 		XtSetArg(colors[0], XtNforeground,
514 			 appResources.currentForeground);
515 	    }
516 	    XtSetValues((Widget) listp->element, colors, 1);
517 
518 	    listp = listp->next;
519 
520 	} while (listp != allDaysList);
521 
522 
523     listp = dayEntryList;
524 
525     if (dayEntryList)
526 	do {
527 	    if (!dayEntryState) {
528 		XtSetArg(colors[0], XtNbackground, DayBackground(listp));
529 		XtSetArg(colors[1], XtNforeground, DayForeground(listp));
530 	    } else {
531 		if (appResources.reverseVideo) {
532 		    XtSetArg(colors[0], XtNbackground, DayForeground(listp));
533 		    XtSetArg(colors[1], XtNforeground, DayBackground(listp));
534 		} else {
535 		    args = markColors;
536 		    n = nMark;
537 		}
538 	    }
539 	    XtSetValues((Widget) listp->element, args, n);
540 
541 	    if (is_holiday((Widget) listp->element) &&
542 		appResources.markHoliday) {
543 		XtSetArg(colors[0], XtNforeground,
544 			 appResources.holidayForeground);
545 		XtSetValues((Widget) listp->element, colors, 1);
546 	    }
547 	    if (is_today((Widget) listp->element) &&
548 		appResources.markCurrent) {
549 		XtSetArg(colors[0], XtNforeground,
550 			 appResources.currentForeground);
551 		XtSetValues((Widget) listp->element, colors, 1);
552 	    }
553 	    listp = listp->next;
554 
555 	} while (listp != dayEntryList);
556 }
557 
558 /*
559  * MarkDayEntry() - Adds or removes days (widgets) from the marked
560  * list.
561  */
562 
563 void
MarkDayEntry(w,doFlag)564 MarkDayEntry(w, doFlag)
565     Widget          w;
566     Boolean         doFlag;
567 {
568     Arg             colors[10];
569     int             n;
570     LList          *lp;
571     LList          *lp2;
572 
573     if (doFlag == True) {
574 	if (lookup(w, markedDaysKey, dayEntryList) != NULL)
575 	    return;		/* it's already on the list */
576 
577 	dayEntryList = (LList *) pput(w, markedDaysKey, dayEntryList);
578 	dayEntryList->data = XtMalloc(sizeof(MarkColors));
579 	lp2 = (LList *) lookup(w, allDaysKey, allDaysList);
580 	DayBackground(dayEntryList) =
581 	    DayBackground(lp2);
582 	DayForeground(dayEntryList) =
583 	    DayForeground(lp2);
584 
585 	if (dayEntryState == True) {
586 	    if (appResources.reverseVideo) {
587 		n = 0;
588 		XtSetArg(colors[n], XtNbackground, DayForeground(dayEntryList));
589 		n++;
590 		XtSetArg(colors[n], XtNforeground, DayBackground(dayEntryList));
591 		n++;
592 		XtSetValues(w, colors, n);
593 	    } else
594 		XtSetValues(w, markColors, nMark);
595 	}
596 	if (is_holiday(w) && appResources.markHoliday) {
597 	    n = 0;
598 	    XtSetArg(colors[n], XtNforeground, appResources.holidayForeground);
599 	    n++;
600 	    XtSetValues(w, colors, n);
601 	}
602 	if (is_today(w) && appResources.markCurrent) {
603 	    n = 0;
604 	    XtSetArg(colors[n], XtNforeground, appResources.currentForeground);
605 	    n++;
606 	    XtSetValues(w, colors, n);
607 	}
608     } else {
609 	if ((lp = (LList *) lookup(w, markedDaysKey, dayEntryList)) == NULL) {
610 	    return;		/* it's not on the list */
611 	}
612 	if (dayEntryState == True) {
613 	    dayEntryList = lp;
614 	    n = 0;
615 	    XtSetArg(colors[n], XtNbackground, DayBackground(dayEntryList));
616 	    n++;
617 	    XtSetArg(colors[n], XtNforeground, DayForeground(dayEntryList));
618 	    n;
619 	    if (is_holiday(w) && appResources.markHoliday)
620 		XtSetArg(colors[n], XtNforeground,
621 			 appResources.holidayForeground);
622 	    if (is_today(w) && appResources.markCurrent)
623 		XtSetArg(colors[n], XtNforeground,
624 			 appResources.currentForeground);
625 	    n++;
626 	    XtSetValues(w, colors, n);
627 	}
628 	XtFree(dayEntryList->data);
629 	dayEntryList = (LList *) premove(w, markedDaysKey, dayEntryList);
630     }
631 }
632 
633 /*
634  * CreateCalendarFrame() - Creates the calendar pane and calls
635  * other routines responsible for creating day labels and buttons.
636  */
637 
638 Widget
CreateCalendarFrame(parent,args,nargs,numDays,firstDay)639 CreateCalendarFrame(parent, args, nargs, numDays, firstDay)
640     Widget          parent;
641     Cardinal        nargs;
642     ArgList         args;
643     Cardinal        numDays, firstDay;
644 {
645     Widget          calendar, CreateDayLabels();
646     void            CreateDayNumbers();
647     Widget          widget;
648     Arg             bargs[2];
649 
650     /* callist = CreateList(2,sizeof(Widget)); */
651 
652 #ifdef ATHENA
653     calendar = XtCreateManagedWidget("calendar", panedWidgetClass,
654 #else
655     calendar = XtCreateManagedWidget("calendar", xmPanedWindowWidgetClass,
656 #endif
657 				     parent, args, nargs);
658 
659     widget = CreateDayLabels(calendar);
660 
661     CreateDayNumbers(calendar, numDays, firstDay);
662     widget = daynumbers;
663 
664 #ifndef ATHENA
665     HideSashes(calendar);
666 #endif
667 
668     return calendar;
669 
670 }
671 
672 #ifdef ATHENA
673 
674 /*
675  * CreateDayNumbers() - Creates the buttons for the days of the month.
676  */
677 
678 void
CreateDayNumbers(parent,numDays,firstDay)679 CreateDayNumbers(parent, numDays, firstDay)
680     Widget          parent;
681     Cardinal        numDays, firstDay;
682 {
683     Widget          prevButton = NULL;
684     Cardinal        numButtons = 42;
685     Arg             bargs[10];
686     int             n;
687     int             i;
688     char            buttonText[4];
689     char            buttonName[8];
690     void            EditDayEntry();
691 
692 #ifdef notdef
693     if (firstDay + numDays - 1 > 35)
694 	numButtons = 42;
695     else
696 	numButtons = 35;
697 #endif
698 
699     daylist = CreateList(numButtons, sizeof(Widget));
700 
701     n = 0;
702     daynumbers = XtCreateManagedWidget("daynumbers", formWidgetClass,
703 				       parent, bargs, n);
704 
705     callbacks[0].callback = EditDayEntry;
706 
707     XtSetArg(bargs[0], XtNcallback, callbacks);
708 
709     for (i = 1; i <= numButtons; i++) {
710 	n = 1;
711 
712 	if (i < firstDay || i > firstDay + numDays - 1) {
713 	    XtSetArg(bargs[n], XtNmappedWhenManaged, False);
714 	    n++;
715 	    callbacks[0].closure = NULL;
716 	} else {
717 	    XtSetArg(bargs[n], XtNmappedWhenManaged, True);
718 	    n++;
719 	    callbacks[0].closure = (XtPointer) (i - firstDay + 1);
720 	}
721 
722 	if ((i - 1) % 7 == 0) {
723 	    XtSetArg(bargs[n], XtNfromHoriz, NULL);
724 	    n++;
725 	} else {
726 	    XtSetArg(bargs[n], XtNfromHoriz, prevButton);
727 	    n++;
728 	}
729 
730 	if (i <= 7) {
731 	    XtSetArg(bargs[n], XtNfromVert, NULL);
732 	    n++;
733 	} else {
734 	    XtSetArg(bargs[n], XtNfromVert, GetWidgetFromList(daylist, i - 7));
735 	    n++;
736 	}
737 
738 	sprintf(buttonText, "%3.d", i - firstDay + 1);
739 	XtSetArg(bargs[n], XtNlabel, buttonText);
740 	n++;
741 
742 	/**       sprintf(buttonName,"%d",(i-1)%7 + 1);  **/
743 	sprintf(buttonName, "%d", i);
744 
745 	prevButton = XtCreateManagedWidget(buttonName, commandWidgetClass,
746 					   daynumbers, bargs, n);
747 
748 	(void) PushWidgetOnList(daylist, prevButton);
749     }
750 
751 }
752 
753 /*
754  * NewDayNumbers() - Changes the buttons to reflect chosen month.
755  */
756 
757 void
NewDayNumbers(numDays,firstDay)758 NewDayNumbers(numDays, firstDay)
759     Cardinal        numDays, firstDay;
760 {
761     Cardinal        numButtons = 42;
762     Arg             bargs[10];
763     int             n;
764     int             i;
765     char            buttonText[4];
766     char            buttonName[8];
767     void            EditDayEntry();
768     Widget          tempWidget = NULL;
769 
770     XtUnmapWidget(daynumbers);
771 
772     callbacks[0].callback = EditDayEntry;
773 
774     XtSetArg(bargs[0], XtNcallback, callbacks);
775 
776     for (i = 1; i <= numButtons; i++) {
777 	n = 1;
778 
779 	tempWidget = GetWidgetFromList(daylist, i);
780 
781 	if (i < firstDay || i > firstDay + numDays - 1) {
782 	    XtSetArg(bargs[n], XtNmappedWhenManaged, False);
783 	    n++;
784 	    callbacks[0].closure = NULL;
785 	} else {
786 	    XtSetArg(bargs[n], XtNmappedWhenManaged, True);
787 	    n++;
788 	    callbacks[0].closure = (XtPointer) (i - firstDay + 1);
789 	}
790 
791 	if ((i - 1) % 7 == 0) {
792 	    XtSetArg(bargs[n], XtNfromHoriz, NULL);
793 	    n++;
794 	} else {
795 	    XtSetArg(bargs[n], XtNfromHoriz, GetWidgetFromList(daylist, i - 1));
796 	    n++;
797 	}
798 
799 
800 	MarkDayEntry(tempWidget, False);
801 
802 	if (i <= 7) {
803 	    XtSetArg(bargs[n], XtNfromVert, NULL);
804 	    n++;
805 	} else {
806 	    XtSetArg(bargs[n], XtNfromVert, GetWidgetFromList(daylist, i - 7));
807 	    n++;
808 	}
809 
810 
811 	sprintf(buttonText, "%3.d", i - firstDay + 1);
812 	XtSetArg(bargs[n], XtNlabel, buttonText);
813 	n++;
814 
815 	sprintf(buttonName, "%d", i);
816 
817 	XtSetValues(tempWidget, bargs, n);
818     }
819 
820     if (dayEntryState == True) {
821 	n = 1;
822 	ShowEntries(NULL, NULL, on, &n);
823     }
824     XtMapWidget(daynumbers);
825 }
826 
827 /*
828  * CreateDayLabels() - Creates the day name labels (SUN,...).
829  */
830 
831 Widget
CreateDayLabels(parent)832 CreateDayLabels(parent)
833     Widget          parent;
834 {
835     Widget          prevButton = NULL, daynames;
836     Arg             bargs[10];
837     int             n;
838     int             i, day;
839     static char    *names[8] =
840     {NULL, "MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN"};
841 
842     /* end of declarations */
843 
844     n = 0;
845     daynames = XtCreateManagedWidget("daynames", formWidgetClass,
846 				     parent, bargs, n);
847 
848     for (i = 1; i <= 7; i++) {
849 	n = 0;
850 	XtSetArg(bargs[n], XtNfromHoriz, prevButton);
851 	n++;
852 	day = (i + appResources.firstDay - 1) % 7;
853 	day = day > 0 ? day : 7;
854 	prevButton = XtCreateManagedWidget(names[day],
855 				      labelWidgetClass, daynames, bargs, n);
856     }
857 
858     return daynames;
859 
860 }
861 
862 #else
863 
864 /*
865  * CreateDayNumbers() - Creates the buttons for the days of the month.
866  */
867 
868 void
CreateDayNumbers(parent,numDays,firstDay)869 CreateDayNumbers(parent, numDays, firstDay)
870     Widget          parent;
871     Cardinal        numDays, firstDay;
872 {
873     Widget          prevButton = NULL;
874     Cardinal        numButtons = 42;
875     Arg             bargs[20];
876     int             n;
877     int             i;
878     char            buttonText[10];
879     char            buttonName[8];
880     void            EditDayEntry();
881     XmString        xms;
882 
883 #ifdef notdef
884     if (firstDay + numDays - 1 > 35)
885 	numButtons = 42;
886     else
887 	numButtons = 35;
888 #endif
889 
890     daylist = CreateList(numButtons, sizeof(Widget));
891 
892     n = 0;
893     XtSetArg(bargs[n], XmNfractionBase, 42);
894     n++;
895     daynumbers = XtCreateManagedWidget("daynumbers", xmFormWidgetClass,
896 				       parent, bargs, n);
897 
898     callbacks[0].callback = EditDayEntry;
899 
900 
901     for (i = 1; i <= numButtons; i++) {
902 	n = 0;
903 
904 	if (i < firstDay || i > firstDay + numDays - 1) {
905 	    XtSetArg(bargs[n], XmNmappedWhenManaged, False);
906 	    n++;
907 	    callbacks[0].closure = NULL;
908 	} else {
909 	    XtSetArg(bargs[n], XmNmappedWhenManaged, True);
910 	    n++;
911 	    callbacks[0].closure = (XtPointer) (i - firstDay + 1);
912 	}
913 	XtSetArg(bargs[n], XmNactivateCallback, callbacks);
914 	n++;
915 
916 	XtSetArg(bargs[n], XmNleftAttachment, XmATTACH_POSITION);
917 	n++;
918 	XtSetArg(bargs[n], XmNleftPosition, ((i - 1) % 7) * 6);
919 	n++;
920 	XtSetArg(bargs[n], XmNrightAttachment, XmATTACH_POSITION);
921 	n++;
922 	XtSetArg(bargs[n], XmNrightPosition, (((i - 1) % 7) + 1) * 6);
923 	n++;
924 	XtSetArg(bargs[n], XmNtopAttachment, XmATTACH_POSITION);
925 	n++;
926 	XtSetArg(bargs[n], XmNtopPosition, ((int) ((i - 1) / 7)) * 7);
927 	n++;
928 	XtSetArg(bargs[n], XmNbottomAttachment, XmATTACH_POSITION);
929 	n++;
930 	XtSetArg(bargs[n], XmNbottomPosition, ((int) ((i - 1) / 7) + 1) * 7);
931 	n++;
932 
933 	sprintf(buttonText, "%2.d", i - firstDay + 1);
934 	xms = XMS(buttonText);
935 	XtSetArg(bargs[n], XmNlabelString, xms);
936 	n++;
937 
938 	/**       sprintf(buttonName,"%d",(i-1)%7 + 1);  **/
939 	sprintf(buttonName, "%d", i);
940 
941 	prevButton = XtCreateManagedWidget(buttonName, xmPushButtonWidgetClass,
942 					   daynumbers, bargs, n);
943 
944 	(void) PushWidgetOnList(daylist, prevButton);
945 	XmStringFree(xms);
946     }
947 }
948 
949 /*
950  * NewDayNumbers() - Changes the buttons to reflect chosen month.
951  */
952 
953 void
NewDayNumbers(numDays,firstDay)954 NewDayNumbers(numDays, firstDay)
955     Cardinal        numDays, firstDay;
956 {
957     Cardinal        numButtons = 42;
958     Arg             bargs[10];
959     int             i;
960     char            buttonText[4];
961     char            buttonName[8];
962     void            EditDayEntry();
963     int             n;
964     XmString        xms;
965     Widget          tempWidget = NULL;
966 
967     XtUnmapWidget(daynumbers);
968 
969     callbacks[0].callback = EditDayEntry;
970 
971     for (i = 1; i <= numButtons; i++) {
972 	n = 0;
973 
974 	tempWidget = GetWidgetFromList(daylist, i);
975 
976 	if (i < firstDay || i > firstDay + numDays - 1) {
977 	    XtSetArg(bargs[n], XmNmappedWhenManaged, False);
978 	    n++;
979 	    callbacks[0].closure = NULL;
980 	} else {
981 	    XtSetArg(bargs[n], XmNmappedWhenManaged, True);
982 	    n++;
983 	    callbacks[0].closure = (XtPointer) (i - firstDay + 1);
984 	}
985 	XtSetArg(bargs[n], XmNactivateCallback, callbacks);
986 	n++;
987 
988 	if ((i - 1) % 7 == 0) {
989 	    XtSetArg(bargs[n], XmNleftAttachment, XmATTACH_FORM);
990 	    n++;
991 	} else {
992 	    XtSetArg(bargs[n], XmNleftAttachment, XmATTACH_WIDGET);
993 	    n++;
994 	    XtSetArg(bargs[n], XmNleftWidget,
995 		     GetWidgetFromList(daylist, i - 1));
996 	    n++;
997 	}
998 
999 	MarkDayEntry(tempWidget, False);
1000 
1001 	if (i <= 7) {
1002 	    XtSetArg(bargs[n], XmNtopAttachment, XmATTACH_FORM);
1003 	    n++;
1004 	} else {
1005 	    XtSetArg(bargs[n], XmNtopAttachment, XmATTACH_WIDGET);
1006 	    n++;
1007 	    XtSetArg(bargs[n], XmNtopWidget, GetWidgetFromList(daylist, i - 7));
1008 	    n++;
1009 	}
1010 
1011 
1012 	sprintf(buttonText, "%2.d", i - firstDay + 1);
1013 	xms = XMS(buttonText);
1014 	XtSetArg(bargs[n], XmNlabelString, xms);
1015 	n++;
1016 
1017 	sprintf(buttonName, "%d", i);
1018 
1019 	XtSetValues(tempWidget, bargs, n);
1020 	XmStringFree(xms);
1021     }
1022 
1023     if (dayEntryState == True) {
1024 	n = 1;
1025 	ShowEntries(NULL, NULL, on, &n);
1026     }
1027     XtMapWidget(daynumbers);
1028 }
1029 
1030 /*
1031  * CreateDayLabels() - Creates the day name labels (SUN,...).
1032  */
1033 
1034 Widget
CreateDayLabels(parent)1035 CreateDayLabels(parent)
1036     Widget          parent;
1037 {
1038     Widget          prevButton = NULL, daynames;
1039     Arg             bargs[10];
1040     int             i, n, day;
1041     XtWidgetGeometry size;
1042     static char    *names[8] =
1043     {NULL, "MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN"};
1044 
1045     /* end of declarations */
1046 
1047     n = 0;
1048     XtSetArg(bargs[n], XmNfractionBase, 7);
1049     n++;
1050     daynames = XtCreateManagedWidget("daynames", xmFormWidgetClass,
1051 				     parent, bargs, n);
1052 
1053     for (i = 1; i <= 7; i++) {
1054 	n = 0;
1055 	XtSetArg(bargs[n], XmNleftAttachment, XmATTACH_POSITION);
1056 	n++;
1057 	XtSetArg(bargs[n], XmNleftPosition, i - 1);
1058 	n++;
1059 	XtSetArg(bargs[n], XmNrightAttachment, XmATTACH_POSITION);
1060 	n++;
1061 	XtSetArg(bargs[n], XmNrightPosition, i);
1062 	n++;
1063 
1064 	day = (i + appResources.firstDay - 1) % 7;
1065 	day = day > 0 ? day : 7;
1066 	prevButton = XtCreateManagedWidget(names[day],
1067 				    xmLabelWidgetClass, daynames, bargs, n);
1068     }
1069 
1070     size.request_mode = CWHeight;
1071     XtQueryGeometry(daynames, NULL, &size);
1072 
1073     n = 0;
1074     XtSetArg(bargs[n], XmNpaneMinimum, size.height);
1075     n++;
1076     XtSetArg(bargs[n], XmNpaneMaximum, size.height);
1077     n++;
1078     XtSetValues(daynames, bargs, n);
1079 
1080     return daynames;
1081 }
1082 
1083 #endif
1084 
1085 static struct tm *today = NULL;
1086 
1087 /*
1088  * gettime() - Updates the shared tm structure to the current time.
1089  */
1090 
1091 struct tm      *
gettime()1092 gettime()
1093 {
1094     time_t now;
1095 
1096     (void) time(&now);
1097     today = localtime(&now);
1098     return today;
1099 }
1100 
1101 /*
1102  * current_month() - Returns the number of the current month (1-12).
1103  */
1104 
1105 int
current_month()1106 current_month()
1107 {
1108     if (today == NULL)
1109 	(void) gettime();
1110     return (today->tm_mon + 1);
1111 }
1112 
1113 /*
1114  * current_day() - Returns the day of the month of the current day.
1115  */
1116 
1117 int
current_day()1118 current_day()
1119 {
1120     if (today == NULL)
1121 	(void) gettime();
1122     return (today->tm_mday);
1123 }
1124 
1125 /*
1126  * current_year() - Returns the current year (yyyy).
1127  */
1128 
1129 int
current_year()1130 current_year()
1131 {
1132     if (today == NULL)
1133 	(void) gettime();
1134     return (today->tm_year + 1900);
1135 }
1136 
1137 char            mon[] = {
1138     0,
1139     31, 29, 31, 30,
1140     31, 30, 31, 31,
1141     30, 31, 30, 31,
1142 };
1143 
1144 static int      calInit = 0;
1145 
1146 /*
1147  * NumberOfDays() - Returns the number of days for month of year.
1148  */
1149 
1150 int
NumberOfDays(m,y)1151 NumberOfDays(m, y)
1152     int             m, y;
1153 {
1154     if (calInit != y)
1155 	FirstDay(m, y);
1156     return mon[m];
1157 }
1158 
1159 /* should be called first */
1160 
1161 /*
1162  * FirstDay() - Returns the day of the week of the first day of the
1163  * given month and year.
1164  */
1165 
1166 int
FirstDay(m,y)1167 FirstDay(m, y)
1168     int             m, y;
1169 {
1170     register        d, i;
1171 
1172     calInit = y;
1173     d = jan1(y);
1174     mon[2] = 29;
1175     mon[9] = 30;
1176 
1177     switch ((jan1(y + 1) + 7 - d) % 7) {
1178 
1179 	/*
1180 	 * non-leap year
1181 	 */
1182     case 1:
1183 	mon[2] = 28;
1184 	break;
1185 
1186 	/*
1187 	 * 1752
1188 	 */
1189     default:
1190 	mon[9] = 19;
1191 	break;
1192 
1193 	/*
1194 	 * leap year
1195 	 */
1196     case 2:
1197 	;
1198     }
1199 
1200     for (i = 1; i < m; i++)
1201 	d += mon[i];
1202     d %= 7;
1203 
1204     d = d > 0 ? d : 7;		/* returns 1-7, not 0-6 */
1205 
1206     d = d + 1 - appResources.firstDay;
1207     return d > 0 ? d : 7 + d;
1208 
1209 }
1210 
1211 /*
1212  * jan1() - Returns day of the week of jan 1 of given year.
1213  */
1214 
1215 int
jan1(yr)1216 jan1(yr)
1217     int             yr;
1218 {
1219     register        y, d;
1220 
1221     /*
1222      * normal gregorian calendar one extra day per four years
1223      */
1224 
1225     y = yr;
1226     d = 4 + y + (y + 3) / 4;
1227 
1228     /*
1229      * julian calendar regular gregorian less three days per 400
1230      */
1231 
1232     if (y > 1800) {
1233 	d -= (y - 1701) / 100;
1234 	d += (y - 1601) / 400;
1235     }
1236     /*
1237      * great calendar changeover instant
1238      */
1239 
1240     if (y > 1752)
1241 	d += 3;
1242 
1243     return (d % 7);
1244 }
1245 
1246 /*
1247  * CurrentTic() - Updates current day.
1248  */
1249 
1250 void
CurrentTic(client_data,tid)1251 CurrentTic(client_data, tid)
1252     XtPointer       client_data;
1253     XtIntervalId   *tid;
1254 {
1255     int             day;
1256     char            sb[80];
1257     Arg             args[10];
1258     int             n;
1259 #ifndef ATHENA
1260     XmString        xms;
1261 #endif
1262 
1263     today = NULL;
1264     day = current_day();
1265     if (day != marked_day) {
1266 	if ((day == 1) &&
1267 	    ((displayedMonth != current_month()) ||
1268 	     (displayedYear != current_year()))) {
1269 	    displayedMonth = month = current_month();
1270 	    displayedYear = year = current_year();
1271 	    ChangeMonth();
1272 	}
1273 	marked_day = day;
1274 	if (appResources.markCurrent) {
1275 	    n = 1;
1276 	    ShowEntries(NULL, NULL, on, &n);
1277 	}
1278 	Fill_In_Date(sb);
1279 	n = 0;
1280 #ifdef ATHENA
1281 	XtSetArg(args[n], XtNlabel, sb);
1282 	n++;
1283 	XtSetValues(cdate, args, n);
1284 #else
1285 	xms = XMS(sb);
1286 	XtSetArg(args[n], XmNlabelString, xms);
1287 	n++;
1288 	XtSetValues(cdate, args, n);
1289 	XmStringFree(xms);
1290 #endif
1291     }
1292     XtAppAddTimeOut(XtWidgetToApplicationContext((Widget) (client_data)),
1293 		    appResources.updateCurrent * 1000, CurrentTic,
1294 		    client_data);
1295 }
1296 
1297 /*
1298  * is_today() - Returns true if the widget represents today.
1299  */
1300 
1301 Boolean
is_today(w)1302 is_today(w)
1303     Widget          w;
1304 {
1305     Widget          foo = GetWidgetFromList(daylist,
1306 	       FirstDay(displayedMonth, displayedYear) - 1 + current_day());
1307 
1308     if ((displayedMonth == current_month()) &&
1309 	(displayedYear == current_year())) {
1310 	if (w == foo) {
1311 	    return (True);
1312 	} else {
1313 	    return (False);
1314 	}
1315     } else {
1316 	return (False);
1317     }
1318 }
1319 
1320 /*
1321  * is_holiday() - Returns true if the widget is for a holiday.
1322  */
1323 
1324 Boolean
is_holiday(w)1325 is_holiday(w)
1326     Widget          w;
1327 {
1328     int             i;
1329     struct holiday *holi;
1330 
1331     for (i = 0; i < holilist->pos; i++) {
1332 	holi = *((Holiday *) holilist->list + i);
1333 	if (((GetWidgetFromList(daylist,
1334 				FirstDay(displayedMonth, displayedYear) -
1335 				1 + holi->day)) == w) &&
1336 	    (holi->month == displayedMonth) &&
1337 	    (holi->year == displayedYear))
1338 	    return (True);
1339     }
1340     return (False);
1341 }
1342 
1343 /*
1344  * MakeDayList() - Keeps a list of all days.
1345  */
1346 
1347 void
MakeDayList()1348 MakeDayList()
1349 {
1350     int             i;
1351     Widget          w;
1352     Arg             args[10];
1353     int             n;
1354 
1355     for (i = 1; i <= 42; i++) {
1356 	n = 0;
1357 	w = GetWidgetFromList(daylist, i);
1358 	allDaysList = (LList *) pput(w, allDaysKey, allDaysList);
1359 	allDaysList->data = XtMalloc(sizeof(MarkColors));
1360 	XtSetArg(args[n], XtNbackground, &DayBackground(allDaysList));
1361 	n++;
1362 	XtSetArg(args[n], XtNforeground, &(DayForeground(allDaysList)));
1363 	n++;
1364 	XtGetValues(w, args, n);
1365     }
1366 }
1367 
1368 #ifdef ATHENA
1369 
1370 /*
1371  * CreateCalendar() - Creates the main calendar pane and control areas.
1372  */
1373 
1374 Widget
CreateCalendar(toplevel)1375 CreateCalendar(toplevel)
1376     Widget          toplevel;
1377 {
1378     Widget          calendar, controls;
1379     Widget          prev_button, succ_button;
1380     Widget          quit_button;
1381     Widget          CreateCalendarFrame();
1382     Cardinal        numberOfDays, firstDay;
1383     Widget          frame;
1384 
1385     Arg             args[10];
1386     int             n;
1387     char            title[80];
1388 
1389     Widget          bcontrols;
1390 
1391     firstDay = FirstDay(month, year);
1392     numberOfDays = NumberOfDays(month, year);
1393 
1394     /*
1395      * Create the top level pane widget
1396      */
1397 
1398     frame = XtCreateWidget("xcalendar", panedWidgetClass, toplevel, NULL, 0);
1399 
1400     markedDaysKey = XtWindow(frame);
1401 
1402     /** create control panel **/
1403 
1404     n = 0;
1405     XtSetArg(args[n], XtNskipAdjust, True);
1406     n++;
1407     controls = XtCreateManagedWidget("controls", formWidgetClass, frame,
1408 				     args, n);
1409 
1410     /* prev button */
1411 
1412     n = 0;
1413     callbacks[0].callback = prevmonth;
1414     XtSetArg(args[n], XtNcallback, callbacks);
1415     n++;
1416     XtSetArg(args[n], XtNfromHoriz, NULL);
1417     n++;
1418     XtSetArg(args[n], XtNleft, XtChainLeft);
1419     n++;
1420     XtSetArg(args[n], XtNright, XtChainLeft);
1421     n++;
1422 
1423     prev_button = XtCreateManagedWidget("prev", commandWidgetClass,
1424 					controls, args, n);
1425 
1426     /* month label */
1427 
1428     sprintf(title, "%s %d", smonth[month], year);
1429 
1430     n = 0;
1431     XtSetArg(args[n], XtNlabel, title);
1432     n++;
1433     XtSetArg(args[n], XtNfromHoriz, prev_button);
1434     n++;
1435     XtSetArg(args[n], XtNleft, XtChainLeft);
1436     n++;
1437     XtSetArg(args[n], XtNright, XtChainRight);
1438     n++;
1439 
1440     date = XtCreateManagedWidget("date", labelWidgetClass, controls, args, n);
1441 
1442     XtAppAddActions(XtWidgetToApplicationContext(date), appActions, 1);
1443 
1444     XtAugmentTranslations(date, XtParseTranslationTable(defTranslations));
1445 
1446     /* next button */
1447 
1448     n = 0;
1449     callbacks[0].callback = succmonth;
1450     XtSetArg(args[n], XtNcallback, callbacks);
1451     n++;
1452     XtSetArg(args[n], XtNfromHoriz, date);
1453     n++;
1454     XtSetArg(args[n], XtNleft, XtChainRight);
1455     n++;
1456     XtSetArg(args[n], XtNright, XtChainRight);
1457     n++;
1458 
1459     succ_button = XtCreateManagedWidget("succ",
1460 					commandWidgetClass,
1461 					controls, args, n);
1462 
1463     /** end of control panel code **/
1464 
1465     /** create calendar form **/
1466 
1467     calendar = CreateCalendarFrame(frame, args, 0, numberOfDays, firstDay);
1468 
1469     n = 0;
1470     XtSetArg(args[n], XtNskipAdjust, True);
1471     n++;
1472     bcontrols = XtCreateManagedWidget("bcontrols", formWidgetClass,
1473 				      frame, args, n);
1474 
1475     n = 0;
1476     callbacks[0].callback = quit;
1477     XtSetArg(args[n], XtNcallback, callbacks);
1478     n++;
1479     XtSetArg(args[n], XtNfromHoriz, NULL);
1480     n++;
1481     XtSetArg(args[n], XtNleft, XtChainLeft);
1482     n++;
1483     XtSetArg(args[n], XtNright, XtChainLeft);
1484     n++;
1485 
1486     quit_button = XtCreateManagedWidget("quitButton", commandWidgetClass,
1487 					bcontrols, args, n);
1488 
1489     Fill_In_Date(title);
1490 
1491     n = 0;
1492     XtSetArg(args[n], XtNlabel, title);
1493     n++;
1494     XtSetArg(args[n], XtNfromHoriz, quit_button);
1495     n++;
1496     XtSetArg(args[n], XtNleft, XtChainLeft);
1497     n++;
1498     XtSetArg(args[n], XtNright, XtChainRight);
1499     n++;
1500 
1501     cdate = XtCreateManagedWidget("cdate", labelWidgetClass, bcontrols,
1502 				  args, n);
1503 
1504     XtAugmentTranslations(quit_button,
1505 			  XtParseTranslationTable(defTranslations));
1506 
1507     n = 0;
1508     callbacks[0].callback = help;
1509     XtSetArg(args[n], XtNcallback, callbacks);
1510     n++;
1511     XtSetArg(args[n], XtNfromHoriz, cdate);
1512     n++;
1513     XtSetArg(args[n], XtNleft, XtChainRight);
1514     n++;
1515     XtSetArg(args[n], XtNright, XtChainRight);
1516     n++;
1517 
1518     help_button = XtCreateManagedWidget("helpButton",
1519 					commandWidgetClass,
1520 					bcontrols, args, n);
1521 
1522     /** end of top level form **/
1523 
1524     XtInstallAllAccelerators(frame, frame);
1525 
1526     XtManageChild(frame);
1527     return (frame);
1528 }
1529 
1530 #else
1531 
1532 /*
1533  * HideSashes() - Removes Motif sashes from traversal list and view.
1534  */
1535 
1536 void
HideSashes(w)1537 HideSashes(w)
1538     Widget          w;
1539 {
1540     Widget         *children;
1541     int             num;
1542     Arg             args[10];
1543     int             n;
1544 
1545     n = 0;
1546     XtSetArg(args[n], XmNchildren, &children);
1547     n++;
1548     XtSetArg(args[n], XmNnumChildren, &num);
1549     n++;
1550     XtGetValues(w, args, n);
1551 
1552     while (num-- > 0)
1553 	if (XmIsSash(children[num])) {
1554 	    n = 0;
1555 	    XtSetArg(args[n], XmNmappedWhenManaged, False);
1556 	    n++;
1557 	    XtSetArg(args[n], XmNtraversalOn, False);
1558 	    n++;
1559 	    XtSetValues(children[num], args, n);
1560 	}
1561 }
1562 
1563 /*
1564  * CreateMotifCalendar() - Creates the main calendar pane and control areas.
1565  */
1566 
1567 Widget
CreateMotifCalendar(toplevel)1568 CreateMotifCalendar(toplevel)
1569     Widget          toplevel;
1570 {
1571     Widget          calendar, controls;
1572     Widget          prev_button, succ_button;
1573     Widget          quit_button;
1574     Widget          CreateCalendarFrame();
1575     Cardinal        numberOfDays, firstDay;
1576     Widget          frame;
1577 #ifndef ATHENA
1578     XmString        xms;
1579 #endif
1580     Arg             args[10];
1581     char            title[80];
1582     Widget          bcontrols;
1583     int             n;
1584     XtWidgetGeometry size;
1585 
1586     firstDay = FirstDay(month, year);
1587     numberOfDays = NumberOfDays(month, year);
1588 
1589     /*
1590      * Create the top level form widget
1591      */
1592 
1593     n = 0;
1594     frame = XtCreateWidget("xcalendar", xmPanedWindowWidgetClass, toplevel,
1595 			   args, n);
1596 
1597     markedDaysKey = XtWindow(frame);
1598 
1599     /** create control panel **/
1600 
1601     n = 0;
1602     controls = XtCreateManagedWidget("controls", xmFormWidgetClass, frame,
1603 				     args, n);
1604 
1605     /* prev button */
1606 
1607     n = 0;
1608     callbacks[0].callback = prevmonth;
1609     XtSetArg(args[n], XmNactivateCallback, callbacks);
1610     n++;
1611 
1612     prev_button = XtCreateManagedWidget("prev", xmPushButtonWidgetClass,
1613 					controls, args, n);
1614 
1615     /* next button */
1616 
1617     n = 0;
1618     callbacks[0].callback = succmonth;
1619     XtSetArg(args[n], XmNactivateCallback, callbacks);
1620     n++;
1621     XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM);
1622     n++;
1623 
1624     succ_button = XtCreateManagedWidget("succ",
1625 					xmPushButtonWidgetClass,
1626 					controls, args, n);
1627 
1628     /* month label */
1629 
1630     sprintf(title, "%s %d", smonth[month], year);
1631 
1632     n = 0;
1633     xms = XMS(title);
1634     XtSetArg(args[n], XmNlabelString, xms);
1635     n++;
1636     XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET);
1637     n++;
1638     XtSetArg(args[n], XmNleftWidget, prev_button);
1639     n++;
1640     XtSetArg(args[n], XmNrightAttachment, XmATTACH_WIDGET);
1641     n++;
1642     XtSetArg(args[n], XmNrightWidget, succ_button);
1643     n++;
1644 
1645     date = XtCreateManagedWidget("date", xmLabelWidgetClass, controls, args, n);
1646     XmStringFree(xms);
1647 
1648     XtAppAddActions(XtWidgetToApplicationContext(date), appActions, 1);
1649 
1650     XtAugmentTranslations(date, XtParseTranslationTable(defTranslations));
1651 
1652     size.request_mode = CWHeight;
1653     XtQueryGeometry(controls, NULL, &size);
1654 
1655     n = 0;
1656     XtSetArg(args[n], XmNpaneMinimum, size.height);
1657     n++;
1658     XtSetArg(args[n], XmNpaneMaximum, size.height);
1659     n++;
1660     XtSetValues(controls, args, n);
1661 
1662     /** end of control panel code **/
1663 
1664     /** create calendar form **/
1665 
1666     n = 0;
1667     calendar = CreateCalendarFrame(frame, args, n, numberOfDays, firstDay);
1668 
1669     n = 0;
1670     bcontrols = XtCreateManagedWidget("bcontrols", xmFormWidgetClass,
1671 				      frame, args, n);
1672 
1673     n = 0;
1674     callbacks[0].callback = quit;
1675     XtSetArg(args[n], XmNactivateCallback, callbacks);
1676     n++;
1677 
1678     quit_button = XtCreateManagedWidget("quitButton", xmPushButtonWidgetClass,
1679 					bcontrols, args, n);
1680 
1681     XtAugmentTranslations(quit_button,
1682 			  XtParseTranslationTable(defTranslations));
1683 
1684     n = 0;
1685     callbacks[0].callback = help;
1686     XtSetArg(args[n], XmNactivateCallback, callbacks);
1687     n++;
1688     XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM);
1689     n++;
1690 
1691     help_button = XtCreateManagedWidget("helpButton",
1692 					xmPushButtonWidgetClass,
1693 					bcontrols, args, n);
1694 
1695     Fill_In_Date(title);
1696     xms = XMS(title);
1697 
1698     n = 0;
1699     XtSetArg(args[n], XmNlabelString, xms);
1700     n++;
1701     XtSetArg(args[n], XmNleftAttachment, XmATTACH_WIDGET);
1702     n++;
1703     XtSetArg(args[n], XmNleftWidget, quit_button);
1704     n++;
1705     XtSetArg(args[n], XmNrightAttachment, XmATTACH_WIDGET);
1706     n++;
1707     XtSetArg(args[n], XmNrightWidget, help_button);
1708     n++;
1709     XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM);
1710     n++;
1711     XtSetArg(args[n], XmNbottomAttachment, XmATTACH_FORM);
1712     n++;
1713 
1714     cdate = XtCreateManagedWidget("cdate", xmLabelWidgetClass,
1715 				  bcontrols, args, n);
1716     XmStringFree(xms);
1717 
1718     size.request_mode = CWHeight;
1719     XtQueryGeometry(bcontrols, NULL, &size);
1720 
1721     n = 0;
1722     XtSetArg(args[n], XmNpaneMinimum, size.height);
1723     n++;
1724     XtSetArg(args[n], XmNpaneMaximum, size.height);
1725     n++;
1726     XtSetValues(bcontrols, args, n);
1727 
1728     /** end of top level form **/
1729 
1730     XtInstallAllAccelerators(frame, frame);
1731 
1732     HideSashes(frame);
1733     XtManageChild(frame);
1734     return (frame);
1735 }
1736 #endif
1737 
1738 /*
1739  * getmonthday() - Returns month or day string from the given list.
1740  */
1741 
1742 char           *
getmonthday(num,startptr)1743 getmonthday(num, startptr)
1744     int             num;	/* Month or day ordinal */
1745     char           *startptr;	/* String to pick it from */
1746 {
1747     static char     returnval[128];
1748     char           *start, *end;
1749     int             i;
1750 
1751     start = startptr;
1752     strcpy(returnval, "");
1753     for (i = 0; i < num; i++) {
1754 	end = strchr(start, '/');
1755 	if (end == (char *) NULL)
1756 	    return returnval;
1757 	start = end + 1;
1758     }
1759     end = strchr(start, '/');
1760     if (end == (char *) NULL)
1761 	strcpy(returnval, start);
1762     else {
1763 	char           *op;
1764 
1765 	op = returnval;
1766 	while (start < end)
1767 	    *(op++) = *(start++);
1768 	*op = '\0';
1769     }
1770     return returnval;
1771 }
1772 
1773 /*
1774  * Fill_In_Date() - Formats current date for display.
1775  */
1776 
1777 void
Fill_In_Date(sb)1778 Fill_In_Date(sb)
1779     char           *sb;
1780 {
1781     int             i, len, prev_len;
1782     char           *startp, *p;
1783     struct tm       tm;
1784     time_t          time_value;
1785 
1786 
1787 
1788     if (appResources.date == NULL) {
1789 	strcpy(sb, "");
1790 	return;
1791     }
1792     (void) time(&time_value);
1793     tm = *localtime(&time_value);
1794 
1795     startp = sb;
1796     for (p = appResources.date; p && *p; p++) {
1797 	if (*p != '%')
1798 	    *sb++ = *p;
1799 	else
1800 	    switch (*++p) {
1801 	    case 'M':
1802 		sb += strlen(strcpy(sb,
1803 				    getmonthday(tm.tm_mon,
1804 					(char *) appResources.monthnames)));
1805 		break;
1806 	    case 'm':
1807 		sb += strlen(strcpy(sb,
1808 				    getmonthday(tm.tm_mon,
1809 					  (char *) appResources.monthnms)));
1810 		break;
1811 	    case 'W':
1812 		sb += strlen(strcpy(sb,
1813 				    getmonthday(tm.tm_wday,
1814 					  (char *) appResources.daynames)));
1815 		break;
1816 	    case 'w':
1817 		sb += strlen(strcpy(sb,
1818 				    getmonthday(tm.tm_wday,
1819 					    (char *) appResources.daynms)));
1820 		break;
1821 	    case 'd':
1822 		if (tm.tm_mday >= 10)
1823 		    *sb++ = (tm.tm_mday / 10 + '0');
1824 		*sb++ = tm.tm_mday % 10 + '0';
1825 		break;
1826 	    case 'Y':
1827 		*sb++ = '1', *sb++ = '9';
1828 		/* fall thru */
1829 	    case 'y':
1830 		*sb++ = (tm.tm_year%100) / 10 + '0';
1831 		*sb++ = (tm.tm_year%100) % 10 + '0';
1832 		break;
1833 	    case '%':
1834 		*sb++ = *p;
1835 	otherwise:;		/* nothing */
1836 	    }
1837     }
1838     *sb = '\0';
1839     sb = startp;
1840 }
1841 
1842 /*
1843  * LoadHolidays() - Loads the holiday file.
1844  */
1845 
1846 void
LoadHolidays()1847 LoadHolidays()
1848 {
1849     char           *buf;
1850     int             n;
1851     int             len;
1852     char           *next;
1853     char           *tab;
1854     char           *start;
1855     struct holiday *holi;
1856 
1857     n = 2048;
1858     buf = XtMalloc(sizeof(char) * n);
1859 
1860     holilist = CreateList(1, sizeof(Holiday));
1861 
1862     len = read_file(appResources.holidayFile, buf, n);
1863     if (len == -1)
1864 	return;
1865     else if (len > n) {
1866 	buf = XtRealloc(buf, len + 1);
1867 	n = len + 1;
1868 	len = read_file(appResources.holidayFile, buf, n);
1869 	if (len == -1)
1870 	    return;
1871     }
1872 
1873     /* terminate `buf' with NULL */
1874     if (sizeof(buf) == len) {
1875       buf = XtRealloc(buf, len + 1);
1876     }
1877     buf[len] = NULL;
1878 
1879     start = buf;
1880 
1881     while (len > 0) {
1882 	next = strchr(buf, '\n');
1883 	tab = strchr(buf, '\t');
1884 	if (tab == NULL) {
1885 	    XtFree(start);
1886 	    return;
1887 	}
1888 	if (next != NULL) {
1889 	    next[0] = '\0';
1890 	}
1891 	holi = (struct holiday *) XtMalloc(sizeof(struct holiday));
1892 	holi->text = XtMalloc(sizeof(char) * strlen(tab));
1893 	sscanf(buf, "%d/%d/%d", &holi->month, &holi->day, &holi->year);
1894 	strcpy(holi->text, tab + 1);
1895 	(void) PushOnList(holilist, &holi);
1896 	if (next == NULL) {
1897 	    XtFree(start);
1898 	    return;
1899 	}
1900 	buf = next + 1;
1901 	len = strlen(buf);
1902     }
1903     XtFree(start);
1904 }
1905 
1906