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>