Annotation of othersrc/dist/cdk/calendar.c, revision 1.1.1.1
1.1 garbled 1: #include <cdk.h>
2:
3: /*
4: * $Author: tom $
5: * $Date: 2000/02/18 23:20:55 $
6: * $Revision: 1.40 $
7: */
8:
9: /*
10: * Declare file local variables.
11: */
12: char *monthsOfTheYear[] = {"NULL", "January", "February", "March", "April",
13: "May", "June", "July", "August", "September",
14: "October", "November", "December"};
15: int daysOfTheMonth[] = {-1, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
16:
17: /*
18: * Declare file local prototypes.
19: */
20: static int isLeapYear (int year);
21: static int getMonthLength (int year, int month);
22: static int getMonthStartWeekday (int year, int month);
23: static time_t getCurrentTime (CDKCALENDAR *calendar);
24: static void verifyCalendarDate (CDKCALENDAR *calendar);
25: static void incrementCalendarDay (CDKCALENDAR *calendar, int adjust);
26: static void decrementCalendarDay (CDKCALENDAR *calendar, int adjust);
27: static void incrementCalendarMonth (CDKCALENDAR *calendar, int adjust);
28: static void decrementCalendarMonth (CDKCALENDAR *calendar, int adjust);
29: static void incrementCalendarYear (CDKCALENDAR *calendar, int adjust);
30: static void decrementCalendarYear (CDKCALENDAR *calendar, int adjust);
31: static void drawCDKCalendarField (CDKCALENDAR *calendar);
32:
33: DeclareCDKObjects(my_funcs,Calendar);
34:
35: /*
36: * This creates a calendar widget.
37: */
38: CDKCALENDAR *newCDKCalendar(CDKSCREEN *cdkscreen, int xplace, int yplace, char *title, int day, int month, int year, chtype dayAttrib, chtype monthAttrib, chtype yearAttrib, chtype highlight, boolean Box, boolean shadow)
39: {
40: /* Maintain the calendar information. */
41: CDKCALENDAR *calendar = newCDKObject(CDKCALENDAR, &my_funcs);
42: int parentWidth = getmaxx(cdkscreen->window);
43: int parentHeight = getmaxy(cdkscreen->window);
44: int boxWidth = 24;
45: int boxHeight = 11;
46: int xpos = xplace;
47: int ypos = yplace;
48: int len = 0;
49: int maxWidth = INT_MIN;
50: chtype *junk = 0;
51: char **temp = 0;
52: int x, y, z, junk2;
53: struct tm *dateInfo;
54: time_t clck;
55:
56: /* We need to determine the width of the calendar box. */
57: if (title != 0)
58: {
59: /* We need to split the title on \n. */
60: temp = CDKsplitString (title, '\n');
61: calendar->titleLines = CDKcountStrings (temp);
62:
63: /* For each element, determine the width. */
64: for (x=0; x < calendar->titleLines; x++)
65: {
66: junk = char2Chtype (temp[x], &len, &junk2);
67: maxWidth = MAXIMUM (maxWidth, len);
68: freeChtype (junk);
69: }
70:
71: /* Set the box width. */
72: boxWidth = MAXIMUM (maxWidth + 2, boxWidth);
73:
74: /* For each line in the title, convert from char * to chtype * */
75: for (x=0; x < calendar->titleLines; x++)
76: {
77: calendar->title[x] = char2Chtype (temp[x], &calendar->titleLen[x], &calendar->titlePos[x]);
78: calendar->titlePos[x] = justifyString (boxWidth, calendar->titleLen[x], calendar->titlePos[x]);
79: }
80: CDKfreeStrings (temp);
81: }
82: else
83: {
84: /* No title? Set the required variables. */
85: calendar->titleLines = 0;
86: }
87: boxHeight += calendar->titleLines;
88:
89: /*
90: * Make sure we didn't extend beyond the dimensions of the window.
91: */
92: boxWidth = MINIMUM (boxWidth, parentWidth);
93: boxHeight = MINIMUM (boxHeight, parentHeight);
94:
95: /* Rejustify the x and y positions if we need to. */
96: alignxy (cdkscreen->window, &xpos, &ypos, boxWidth, boxHeight);
97:
98: /* Create the calendar window. */
99: calendar->win = newwin (boxHeight + !!shadow, boxWidth + !!shadow, ypos, xpos);
100:
101: /* Is the window null? */
102: if (calendar->win == 0)
103: {
104: /* Clean up the pointers. */
105: free (calendar);
106:
107: /* Exit with null. */
108: return (0);
109: }
110: keypad (calendar->win, TRUE);
111: leaveok (calendar->win, TRUE);
112:
113: /* Set some variables. */
114: calendar->xOffset = (int)((boxWidth - 20) / 2);
115: calendar->fieldWidth = boxWidth - 2;
116:
117: /* Set the rest of the widget values. */
118: ScreenOf(calendar) = cdkscreen;
119: calendar->parent = cdkscreen->window;
120: calendar->labelWin = subwin (calendar->win, 1, calendar->fieldWidth-2, ypos + calendar->titleLines + 1, xpos + 2);
121: calendar->fieldWin = subwin (calendar->win, 7, 20, ypos + calendar->titleLines + 3, xpos + calendar->xOffset);
122: calendar->xpos = xpos;
123: calendar->ypos = ypos;
124: calendar->boxWidth = boxWidth;
125: calendar->boxHeight = boxHeight;
126: calendar->day = day;
127: calendar->month = month;
128: calendar->year = year;
129: calendar->dayAttrib = dayAttrib;
130: calendar->monthAttrib = monthAttrib;
131: calendar->yearAttrib = yearAttrib;
132: calendar->highlight = highlight;
133: calendar->width = boxWidth;
134: calendar->ULChar = ACS_ULCORNER;
135: calendar->URChar = ACS_URCORNER;
136: calendar->LLChar = ACS_LLCORNER;
137: calendar->LRChar = ACS_LRCORNER;
138: calendar->HChar = ACS_HLINE;
139: calendar->VChar = ACS_VLINE;
140: calendar->BoxAttrib = A_NORMAL;
141: calendar->exitType = vNEVER_ACTIVATED;
142: ObjOf(calendar)->box = Box;
143: calendar->shadow = shadow;
144: calendar->preProcessFunction = 0;
145: calendar->preProcessData = 0;
146: calendar->postProcessFunction = 0;
147: calendar->postProcessData = 0;
148:
149: /* Clear out the markers. */
150: for (z=0; z < MAX_YEARS; z++)
151: {
152: for (y=0; y < MAX_MONTHS; y++)
153: {
154: for (x=0; x < MAX_DAYS; x++)
155: {
156: calendar->marker[x][y][z] = 0;
157: }
158: }
159: }
160:
161: /* If the day/month/year values were 0, then use today's date. */
162: if ((calendar->day == 0) && (calendar->month == 0) && (calendar->year == 0))
163: {
164: time (&clck);
165: dateInfo = localtime (&clck);
166:
167: calendar->day = dateInfo->tm_mday;
168: calendar->month = dateInfo->tm_mon + 1;
169: calendar->year = dateInfo->tm_year + 1900;
170: }
171:
172: /* Verify the dates provided. */
173: verifyCalendarDate (calendar);
174:
175: /* Determine which day the month starts on. */
176: calendar->weekDay = getMonthStartWeekday (calendar->year, calendar->month);
177:
178: /* Clean the key bindings. */
179: cleanCDKObjectBindings (vCALENDAR, calendar);
180:
181: /* Register this baby. */
182: registerCDKObject (cdkscreen, vCALENDAR, calendar);
183:
184: /* Return the calendar pointer. */
185: return (calendar);
186: }
187:
188: /*
189: * This function lets the user play with this widget.
190: */
191: time_t activateCDKCalendar (CDKCALENDAR *calendar, chtype *actions)
192: {
193: /* Declare local variables. */
194: chtype input = 0;
195: time_t ret = -1;
196:
197: /* Draw the widget. */
198: drawCDKCalendar (calendar, ObjOf(calendar)->box);
199:
200: /* Check if 'actions' is null. */
201: if (actions == 0)
202: {
203: for (;;)
204: {
205: /* Get the input. */
206: wrefresh (calendar->win);
207: input = wgetch (calendar->win);
208:
209: /* Inject the character into the widget. */
210: ret = injectCDKCalendar (calendar, input);
211: if (calendar->exitType != vEARLY_EXIT)
212: {
213: return ret;
214: }
215: }
216: }
217: else
218: {
219: int length = chlen (actions);
220: int x =0;
221:
222: /* Inject each character one at a time. */
223: for (x=0; x < length; x++)
224: {
225: ret = injectCDKCalendar (calendar, actions[x]);
226: if (calendar->exitType != vEARLY_EXIT)
227: {
228: return ret;
229: }
230: }
231: }
232: return ret;
233: }
234:
235: /*
236: * This injects a single character into the widget.
237: */
238: time_t injectCDKCalendar (CDKCALENDAR *calendar, chtype input)
239: {
240: /* Declare local variables. */
241: int ppReturn = 1;
242:
243: /* Set the exit type. */
244: calendar->exitType = vEARLY_EXIT;
245:
246: /* Refresh the calendar field. */
247: drawCDKCalendarField (calendar);
248:
249: /* Check if there is a pre-process function to be called. */
250: if (calendar->preProcessFunction != 0)
251: {
252: /* Call the pre-process function. */
253: ppReturn = ((PROCESSFN)(calendar->preProcessFunction)) (vCALENDAR, calendar, calendar->preProcessData, input);
254: }
255:
256: /* Should we continue? */
257: if (ppReturn != 0)
258: {
259: /* Check a predefined binding. */
260: if (checkCDKObjectBind (vCALENDAR, calendar, input) != 0)
261: {
262: calendar->exitType = vEARLY_EXIT;
263: return 0;
264: }
265: else
266: {
267: switch (input)
268: {
269: case KEY_UP :
270: decrementCalendarDay (calendar, 7);
271: break;
272:
273: case KEY_DOWN :
274: incrementCalendarDay (calendar, 7);
275: break;
276:
277: case KEY_LEFT :
278: decrementCalendarDay (calendar, 1);
279: break;
280:
281: case KEY_RIGHT :
282: incrementCalendarDay (calendar, 1);
283: break;
284:
285: case 'n' : case KEY_NPAGE : case CONTROL('F'):
286: incrementCalendarMonth (calendar, 1);
287: break;
288:
289: case 'N' :
290: incrementCalendarMonth (calendar, 6);
291: break;
292:
293: case 'p' : case KEY_PPAGE : case CONTROL('B'):
294: decrementCalendarMonth (calendar, 1);
295: break;
296:
297: case 'P' :
298: decrementCalendarMonth (calendar, 6);
299: break;
300:
301: case '-' :
302: decrementCalendarYear (calendar, 1);
303: break;
304:
305: case '+' :
306: incrementCalendarYear (calendar, 1);
307: break;
308:
309: case 'T' : case 't' : case KEY_HOME:
310: setCDKCalendarDate (calendar, -1, -1, -1);
311: break;
312:
313: case KEY_ESC :
314: calendar->exitType = vESCAPE_HIT;
315: return (time_t)-1;
316:
317: case KEY_RETURN : case KEY_TAB : case KEY_ENTER :
318: calendar->exitType = vNORMAL;
319: return getCurrentTime (calendar);
320:
321: case CDK_REFRESH :
322: eraseCDKScreen (ScreenOf(calendar));
323: refreshCDKScreen (ScreenOf(calendar));
324: break;
325:
326: default :
327: Beep();
328: break;
329: }
330: }
331:
332: /* Should we do a post-process? */
333: if (calendar->postProcessFunction != 0)
334: {
335: ((PROCESSFN)(calendar->postProcessFunction)) (vCALENDAR, calendar, calendar->postProcessData, input);
336: }
337: }
338:
339: /* Set the exit type then exit. */
340: calendar->exitType = vEARLY_EXIT;
341: return -1;
342: }
343:
344: /*
345: * This moves the calendar field to the given location.
346: */
347: static void _moveCDKCalendar (CDKOBJS *object, int xplace, int yplace, boolean relative, boolean refresh_flag)
348: {
349: CDKCALENDAR *calendar = (CDKCALENDAR *)object;
350:
351: /*
352: * If this is a relative move, then we will adjust where we want
353: * to move to.
354: */
355: if (relative)
356: {
357: xplace += getbegx(calendar->win);
358: yplace += getbegy(calendar->win);
359: }
360:
361: /* Adjust the window if we need to. */
362: alignxy (WindowOf(calendar), &xplace, &yplace, calendar->boxWidth, calendar->boxHeight);
363:
364: /* Move the window to the new location. */
365: moveCursesWindow(calendar->win, xplace, yplace);
366:
367: /* Redraw the window, if they asked for it. */
368: if (refresh_flag)
369: {
370: drawCDKCalendar (calendar, ObjOf(calendar)->box);
371: }
372: }
373:
374: /*
375: * This draws the calendar widget.
376: */
377: static void _drawCDKCalendar (CDKOBJS *object, boolean Box)
378: {
379: CDKCALENDAR *calendar = (CDKCALENDAR *)object;
380: char *header = "Su Mo Tu We Th Fr Sa";
381: int headerLen = (int)strlen (header);
382: int x;
383:
384: /* Box the widget if asked. */
385: if (Box)
386: {
387: attrbox (calendar->win,
388: calendar->ULChar, calendar->URChar,
389: calendar->LLChar, calendar->LRChar,
390: calendar->HChar, calendar->VChar,
391: calendar->BoxAttrib,
392: calendar->shadow);
393: }
394:
395: /* Draw in the title. */
396: if (calendar->titleLines != 0)
397: {
398: for (x=0; x < calendar->titleLines; x++)
399: {
400: writeChtype (calendar->win,
401: calendar->titlePos[x],
402: x + 1,
403: calendar->title[x],
404: HORIZONTAL, 0,
405: calendar->titleLen[x]);
406: }
407: }
408:
409: /* Draw in the day-of-the-week header. */
410: writeChar (calendar->win,
411: calendar->xOffset, calendar->titleLines + 2,
412: header, HORIZONTAL, 0, headerLen);
413:
414: /* Draw in the calendar field. */
415: drawCDKCalendarField (calendar);
416: }
417:
418: /*
419: * This draws the month field.
420: */
421: static void drawCDKCalendarField (CDKCALENDAR *calendar)
422: {
423: /* Declare local variables. */
424: char *monthName = monthsOfTheYear[calendar->month];
425: int monthLength = getMonthLength (calendar->year, calendar->month);
426: int yearIndex = calendar->year - 1900;
427: int day;
428: int x, y;
429: char temp[20];
430: chtype marker;
431:
432: /* Get the length of the month. */
433: monthLength = getMonthLength (calendar->year, calendar->month);
434:
435: day = 1 - calendar->weekDay;
436:
437: for (x=1; x <= 6; x++)
438: {
439: for (y=0; y < 7; y++)
440: {
441: if (day >= 1 && day <= monthLength)
442: {
443: sprintf (temp, "%02d", day);
444:
445: if (calendar->day == day)
446: {
447: marker = calendar->highlight;
448: }
449: else
450: {
451: marker = calendar->marker[day][calendar->month][yearIndex] | calendar->dayAttrib;
452: }
453: writeCharAttrib(calendar->fieldWin, y*3, x, temp,
454: marker, HORIZONTAL, 0, 2);
455: }
456: else
457: {
458: writeChar(calendar->fieldWin, y*3, x, " ",
459: HORIZONTAL, 0, 2);
460: }
461: day++;
462: }
463: }
464:
465: /* Draw the month in. */
466: sprintf (temp, "%-9s", monthName);
467: writeChar (calendar->labelWin, 0, 0,
468: temp, HORIZONTAL, 0, 9);
469:
470: /* Draw the year in. */
471: sprintf (temp, "%4d", calendar->year);
472: writeChar (calendar->labelWin,
473: calendar->fieldWidth-4-2, 0,
474: temp, HORIZONTAL, 0, 4);
475:
476: /* Refresh the main window. */
477: wnoutrefresh (calendar->labelWin);
478: wnoutrefresh (calendar->fieldWin);
479: wnoutrefresh (calendar->win);
480: }
481:
482: /*
483: * This sets multiple attributes of the widget.
484: */
485: void setCDKCalendar (CDKCALENDAR *calendar, int day, int month, int year, chtype dayAttrib, chtype monthAttrib, chtype yearAttrib, chtype highlight, boolean Box)
486: {
487: setCDKCalendarDate (calendar, day, month, year);
488: setCDKCalendarDayAttribute (calendar, dayAttrib);
489: setCDKCalendarMonthAttribute (calendar, monthAttrib);
490: setCDKCalendarYearAttribute (calendar, yearAttrib);
491: setCDKCalendarHighlight (calendar, highlight);
492: setCDKCalendarBox (calendar, Box);
493: }
494:
495: /*
496: * This sets the date and some attributes.
497: */
498: void setCDKCalendarDate (CDKCALENDAR *calendar, int day, int month, int year)
499: {
500: /* Declare local variables. */
501: struct tm *dateInfo;
502: time_t clck;
503:
504: /*
505: * Get the current dates and set the default values for
506: * the day/month/year values for the calendar.
507: */
508: time (&clck);
509: dateInfo = localtime (&clck);
510:
511: /* Set the date elements if we need too. */
512: calendar->day = (day == -1 ? dateInfo->tm_mday : day);
513: calendar->month = (month == -1 ? dateInfo->tm_mon + 1 : month);
514: calendar->year = (year == -1 ? dateInfo->tm_year + 1900 : year);
515:
516: /* Verify the date information. */
517: verifyCalendarDate (calendar);
518:
519: /* Get the start of the current month. */
520: calendar->weekDay = getMonthStartWeekday (calendar->year, calendar->month);
521: }
522:
523: /*
524: * This returns the current date on the calendar.
525: */
526: void getCDKCalendarDate (CDKCALENDAR *calendar, int *day, int *month, int *year)
527: {
528: (*day) = calendar->day;
529: (*month) = calendar->month;
530: (*year) = calendar->year;
531: }
532:
533: /*
534: * This sets the attribute of the days in the calendar.
535: */
536: void setCDKCalendarDayAttribute (CDKCALENDAR *calendar, chtype attribute)
537: {
538: calendar->dayAttrib = attribute;
539: }
540: chtype getCDKCalendarDayAttribute (CDKCALENDAR *calendar)
541: {
542: return calendar->dayAttrib;
543: }
544:
545: /*
546: * This sets the attribute of the month names in the calendar.
547: */
548: void setCDKCalendarMonthAttribute (CDKCALENDAR *calendar, chtype attribute)
549: {
550: calendar->monthAttrib = attribute;
551: }
552: chtype getCDKCalendarMonthAttribute (CDKCALENDAR *calendar)
553: {
554: return calendar->monthAttrib;
555: }
556:
557: /*
558: * This sets the attribute of the year in the calendar.
559: */
560: void setCDKCalendarYearAttribute (CDKCALENDAR *calendar, chtype attribute)
561: {
562: calendar->yearAttrib = attribute;
563: }
564: chtype getCDKCalendarYearAttribute (CDKCALENDAR *calendar)
565: {
566: return calendar->yearAttrib;
567: }
568:
569: /*
570: * This sets the attribute of the highlight box.
571: */
572: void setCDKCalendarHighlight (CDKCALENDAR *calendar, chtype highlight)
573: {
574: calendar->highlight = highlight;
575: }
576: chtype getCDKCalendarHighlight (CDKCALENDAR *calendar)
577: {
578: return calendar->highlight;
579: }
580:
581: /*
582: * This sets the box attibute of the widget.
583: */
584: void setCDKCalendarBox (CDKCALENDAR *calendar, boolean Box)
585: {
586: ObjOf(calendar)->box = Box;
587: }
588: boolean getCDKCalendarBox (CDKCALENDAR *calendar)
589: {
590: return ObjOf(calendar)->box;
591: }
592:
593: /*
594: * These functions set the drawing characters of the widget.
595: */
596: void setCDKCalendarULChar (CDKCALENDAR *calendar, chtype character)
597: {
598: calendar->ULChar = character;
599: }
600: void setCDKCalendarURChar (CDKCALENDAR *calendar, chtype character)
601: {
602: calendar->URChar = character;
603: }
604: void setCDKCalendarLLChar (CDKCALENDAR *calendar, chtype character)
605: {
606: calendar->LLChar = character;
607: }
608: void setCDKCalendarLRChar (CDKCALENDAR *calendar, chtype character)
609: {
610: calendar->LRChar = character;
611: }
612: void setCDKCalendarVerticalChar (CDKCALENDAR *calendar, chtype character)
613: {
614: calendar->VChar = character;
615: }
616: void setCDKCalendarHorizontalChar (CDKCALENDAR *calendar, chtype character)
617: {
618: calendar->HChar = character;
619: }
620: void setCDKCalendarBoxAttribute (CDKCALENDAR *calendar, chtype character)
621: {
622: calendar->BoxAttrib = character;
623: }
624:
625: /*
626: * This sets the background color of the widget.
627: */
628: void setCDKCalendarBackgroundColor (CDKCALENDAR *calendar, char *color)
629: {
630: chtype *holder = 0;
631: int junk1, junk2;
632:
633: /* Make sure the color isn't null. */
634: if (color == 0)
635: {
636: return;
637: }
638:
639: /* Convert the value of the environment variable to a chtype. */
640: holder = char2Chtype (color, &junk1, &junk2);
641:
642: /* Set the widgets background color. */
643: wbkgd (calendar->win, holder[0]);
644: wbkgd (calendar->fieldWin, holder[0]);
645: wbkgd (calendar->labelWin, holder[0]);
646:
647: /* Clean up. */
648: freeChtype (holder);
649: }
650:
651: /*
652: * This erases the calendar widget.
653: */
654: static void _eraseCDKCalendar (CDKOBJS *object)
655: {
656: CDKCALENDAR *calendar = (CDKCALENDAR *)object;
657:
658: eraseCursesWindow (calendar->win);
659: }
660:
661: /*
662: * This destroys the calendar object pointer.
663: */
664: void destroyCDKCalendar (CDKCALENDAR *calendar)
665: {
666: int x;
667:
668: /* Erase the old calendar. */
669: eraseCDKCalendar (calendar);
670:
671: /* Free up the character pointers. */
672: for (x=0; x < calendar->titleLines; x++)
673: {
674: freeChtype (calendar->title[x]);
675: }
676:
677: /* Free up the window pointers. */
678: deleteCursesWindow (calendar->win);
679:
680: /* Unregister the object. */
681: unregisterCDKObject (vCALENDAR, calendar);
682:
683: /* Free the object pointer. */
684: free (calendar);
685: }
686:
687: /*
688: * This sets a marker on the calendar.
689: */
690: void setCDKCalendarMarker (CDKCALENDAR *calendar, int day, int month, int year, chtype marker)
691: {
692: int yearIndex = year-1900;
693:
694: /* Check to see if a marker has not already been set. */
695: if (calendar->marker[day][month][yearIndex] != 0)
696: {
697: chtype duplicateMarker = calendar->marker[day][month][yearIndex] | A_BLINK;
698: calendar->marker[day][month][yearIndex] = duplicateMarker;
699: }
700: else
701: {
702: calendar->marker[day][month][yearIndex] = marker;
703: }
704: }
705:
706: /*
707: * This sets a marker on the calendar.
708: */
709: void removeCDKCalendarMarker (CDKCALENDAR *calendar, int day, int month, int year)
710: {
711: int yearIndex = year-1900;
712: calendar->marker[day][month][yearIndex] = 0;
713: }
714:
715: /*
716: * This function sets the pre-process function.
717: */
718: void setCDKCalendarPreProcess (CDKCALENDAR *calendar, PROCESSFN callback, void *data)
719: {
720: calendar->preProcessFunction = callback;
721: calendar->preProcessData = data;
722: }
723:
724: /*
725: * This function sets the post-process function.
726: */
727: void setCDKCalendarPostProcess (CDKCALENDAR *calendar, PROCESSFN callback, void *data)
728: {
729: calendar->postProcessFunction = callback;
730: calendar->postProcessData = data;
731: }
732:
733: /*
734: * This makes sure that the dates provided exist.
735: */
736: static void verifyCalendarDate (CDKCALENDAR *calendar)
737: {
738: int monthLength;
739:
740: /* Make sure the given year is not less than 1900. */
741: if (calendar->year < 1900)
742: {
743: calendar->year = 1900;
744: }
745:
746: /* Make sure the month is within range. */
747: if (calendar->month > 12)
748: {
749: calendar->month = 12;
750: }
751: if (calendar->month < 1)
752: {
753: calendar->month = 1;
754: }
755:
756: /* Make sure the day given is within range of the month. */
757: monthLength = getMonthLength (calendar->year, calendar->month);
758: if (calendar->day < 1)
759: {
760: calendar->day = 1;
761: }
762: if (calendar->day > monthLength)
763: {
764: calendar->day = monthLength;
765: }
766: }
767:
768: /*
769: * This returns what day of the week the month starts on.
770: */
771: static int getMonthStartWeekday (int year, int month)
772: {
773: struct tm Date;
774:
775: /* Set the tm structure correctly. */
776: Date.tm_sec = 0;
777: Date.tm_min = 0;
778: Date.tm_hour = 10;
779: Date.tm_mday = 1;
780: Date.tm_mon = month-1;
781: Date.tm_year = year-1900;
782: Date.tm_isdst = 1;
783:
784: /* Call the mktime function to fill in the holes. */
785: if (mktime (&Date) == (time_t)-1)
786: {
787: return 0;
788: }
789: return Date.tm_wday;
790: }
791:
792: /*
793: * This function returns a 1 if it's a leap year and 0 if it's not.
794: */
795: static int isLeapYear (int year)
796: {
797: if (year % 4 == 0 ||
798: year % 4 == 0)
799: {
800: return 1;
801: }
802: return 0;
803: }
804:
805: /*
806: * This increments the current day by the given value.
807: */
808: static void incrementCalendarDay (CDKCALENDAR *calendar, int adjust)
809: {
810: int monthLength = getMonthLength (calendar->year, calendar->month);
811:
812: /* Make sure we adjust the day correctly. */
813: if (adjust + calendar->day > monthLength)
814: {
815: /* Have to increment the month by one. */
816: calendar->day = calendar->day + adjust - monthLength;
817: incrementCalendarMonth (calendar, 1);
818: }
819: else
820: {
821: calendar->day += adjust;
822: drawCDKCalendarField (calendar);
823: }
824: }
825:
826: /*
827: * This decrments the current day by the given value.
828: */
829: static void decrementCalendarDay (CDKCALENDAR *calendar, int adjust)
830: {
831: int monthLength;
832:
833: /* Make sure we adjust the day correctly. */
834: if (calendar->day-adjust < 1)
835: {
836: /* Set the day according to the length of the month. */
837: if (calendar->month == 1)
838: {
839: /* Make sure we aren't going past the year limit. */
840: if (calendar->year == 1900)
841: {
842: char *mesg[] = {"<C></U>Error", "Can not go past the year 1900"};
843: Beep();
844: popupLabel (ScreenOf(calendar), mesg, 2);
845: return;
846: }
847: monthLength = getMonthLength (calendar->year - 1, 12);
848: }
849: else
850: {
851: monthLength = getMonthLength (calendar->year, calendar->month - 1);
852: }
853: calendar->day = monthLength - (adjust - calendar->day);
854:
855: /* Have to decrement the month by one. */
856: decrementCalendarMonth (calendar, 1);
857: }
858: else
859: {
860: calendar->day -= adjust;
861: drawCDKCalendarField (calendar);
862: }
863: }
864:
865: /*
866: * This increments the current month by the given value.
867: */
868: static void incrementCalendarMonth (CDKCALENDAR *calendar, int adjust)
869: {
870: int monthLength;
871:
872: /* Are we at the end of the year. */
873: if (calendar->month + adjust > 12)
874: {
875: calendar->month = (calendar->month + adjust) - 12;
876: calendar->year++;
877: }
878: else
879: {
880: calendar->month += adjust;
881: }
882:
883: /* Get the length of the current month. */
884: monthLength = getMonthLength (calendar->year, calendar->month);
885: if (calendar->day > monthLength)
886: {
887: calendar->day = monthLength;
888: }
889:
890: /* Get the start of the current month. */
891: calendar->weekDay = getMonthStartWeekday (calendar->year, calendar->month);
892:
893: /* Redraw the calendar. */
894: drawCDKCalendar (calendar, ObjOf(calendar)->box);
895: }
896:
897: /*
898: * This decrements the current month by the given value.
899: */
900: static void decrementCalendarMonth (CDKCALENDAR *calendar, int adjust)
901: {
902: int monthLength;
903:
904: /* Are we at the end of the year. */
905: if (calendar->month <= adjust)
906: {
907: if (calendar->year == 1900)
908: {
909: char *mesg[] = {"<C></U>Error", "Can not go past the year 1900"};
910: Beep();
911: popupLabel (ScreenOf(calendar), mesg, 2);
912: return;
913: }
914: else
915: {
916: calendar->month = 13 - adjust;
917: calendar->year--;
918: }
919: }
920: else
921: {
922: calendar->month -= adjust;
923: }
924:
925: /* Get the length of the current month. */
926: monthLength = getMonthLength (calendar->year, calendar->month);
927: if (calendar->day > monthLength)
928: {
929: calendar->day = monthLength;
930: }
931:
932: /* Get the start of the current month. */
933: calendar->weekDay = getMonthStartWeekday (calendar->year, calendar->month);
934:
935: /* Redraw the calendar. */
936: drawCDKCalendar (calendar, ObjOf(calendar)->box);
937: }
938:
939: /*
940: * This increments the current year by the given value.
941: */
942: static void incrementCalendarYear (CDKCALENDAR *calendar, int adjust)
943: {
944: /* Increment the year. */
945: calendar->year += adjust;
946:
947: /* If we are in Feb make sure we don't trip into voidness. */
948: if (calendar->month == 2)
949: {
950: int monthLength = getMonthLength (calendar->year, calendar->month);
951: if (calendar->day > monthLength)
952: {
953: calendar->day = monthLength;
954: }
955: }
956:
957: /* Get the start of the current month. */
958: calendar->weekDay = getMonthStartWeekday (calendar->year, calendar->month);
959:
960: /* Redraw the calendar. */
961: drawCDKCalendar (calendar, ObjOf(calendar)->box);
962: }
963:
964: /*
965: * This decrements the current year by the given value.
966: */
967: static void decrementCalendarYear (CDKCALENDAR *calendar, int adjust)
968: {
969: /* Make sure we don't go out of bounds. */
970: if (calendar->year - adjust < 1900)
971: {
972: char *mesg[] = {"<C></U>Error", "Can not go past the year 1900"};
973: Beep();
974: popupLabel (ScreenOf(calendar), mesg, 2);
975: return;
976: }
977:
978: /* Decrement the year. */
979: calendar->year -= adjust;
980:
981: /* If we are in Feb make sure we don't trip into voidness. */
982: if (calendar->month == 2)
983: {
984: int monthLength = getMonthLength (calendar->year, calendar->month);
985: if (calendar->day > monthLength)
986: {
987: calendar->day = monthLength;
988: }
989: }
990:
991: /* Get the start of the current month. */
992: calendar->weekDay = getMonthStartWeekday (calendar->year, calendar->month);
993:
994: /* Redraw the calendar. */
995: drawCDKCalendar (calendar, ObjOf(calendar)->box);
996: }
997:
998: /*
999: * This returns the length of the current month.
1000: */
1001: static int getMonthLength (int year, int month)
1002: {
1003: int monthLength = daysOfTheMonth[month];
1004:
1005: if (month == 2)
1006: {
1007: monthLength += isLeapYear (year);
1008: }
1009: return monthLength;
1010: }
1011:
1012: /*
1013: * This returns what day of the week the month starts on.
1014: */
1015: static time_t getCurrentTime (CDKCALENDAR *calendar)
1016: {
1017: struct tm Date, *dateInfo;
1018: time_t clck;
1019:
1020: /* Determine the current time and determine if we are in DST. */
1021: time (&clck);
1022: dateInfo = localtime (&clck);
1023:
1024: /* Set the tm structure correctly. */
1025: Date.tm_sec = 1;
1026: Date.tm_min = 0;
1027: Date.tm_hour = 0;
1028: Date.tm_mday = calendar->day;
1029: Date.tm_mon = calendar->month-1;
1030: Date.tm_year = calendar->year-1900;
1031: Date.tm_isdst = dateInfo->tm_isdst;
1032:
1033: /* Call the mktime function to fill in the holes. */
1034: return mktime (&Date);
1035: }
CVSweb <webmaster@jp.NetBSD.org>