1217309Snwhitehorn/* 2251843Sbapt * $Id: calendar.c,v 1.67 2013/03/17 15:03:41 tom Exp $ 3217309Snwhitehorn * 4217309Snwhitehorn * calendar.c -- implements the calendar box 5217309Snwhitehorn * 6251843Sbapt * Copyright 2001-2012,2013 Thomas E. Dickey 7217309Snwhitehorn * 8217309Snwhitehorn * This program is free software; you can redistribute it and/or modify 9217309Snwhitehorn * it under the terms of the GNU Lesser General Public License, version 2.1 10217309Snwhitehorn * as published by the Free Software Foundation. 11217309Snwhitehorn * 12217309Snwhitehorn * This program is distributed in the hope that it will be useful, but 13217309Snwhitehorn * WITHOUT ANY WARRANTY; without even the implied warranty of 14217309Snwhitehorn * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15217309Snwhitehorn * Lesser General Public License for more details. 16217309Snwhitehorn * 17217309Snwhitehorn * You should have received a copy of the GNU Lesser General Public 18217309Snwhitehorn * License along with this program; if not, write to 19217309Snwhitehorn * Free Software Foundation, Inc. 20217309Snwhitehorn * 51 Franklin St., Fifth Floor 21217309Snwhitehorn * Boston, MA 02110, USA. 22217309Snwhitehorn */ 23217309Snwhitehorn 24217309Snwhitehorn#include <dialog.h> 25217309Snwhitehorn#include <dlg_keys.h> 26217309Snwhitehorn 27217309Snwhitehorn#include <time.h> 28217309Snwhitehorn 29217309Snwhitehorn#define ONE_DAY (60 * 60 * 24) 30217309Snwhitehorn 31217309Snwhitehorn#define MON_WIDE 4 /* width of a month-name */ 32217309Snwhitehorn#define DAY_HIGH 6 /* maximum lines in day-grid */ 33217309Snwhitehorn#define DAY_WIDE (8 * MON_WIDE) /* width of the day-grid */ 34217309Snwhitehorn#define HDR_HIGH 1 /* height of cells with month/year */ 35217309Snwhitehorn#define BTN_HIGH 1 /* height of button-row excluding margin */ 36217309Snwhitehorn 37217309Snwhitehorn/* two more lines: titles for day-of-week and month/year boxes */ 38217309Snwhitehorn#define MIN_HIGH (DAY_HIGH + 2 + HDR_HIGH + BTN_HIGH + (7 * MARGIN)) 39217309Snwhitehorn#define MIN_WIDE (DAY_WIDE + (4 * MARGIN)) 40217309Snwhitehorn 41217309Snwhitehorntypedef enum { 42217309Snwhitehorn sMONTH = -3 43217309Snwhitehorn ,sYEAR = -2 44217309Snwhitehorn ,sDAY = -1 45217309Snwhitehorn} STATES; 46217309Snwhitehorn 47217309Snwhitehornstruct _box; 48217309Snwhitehorn 49217309Snwhitehorntypedef int (*BOX_DRAW) (struct _box *, struct tm *); 50217309Snwhitehorn 51217309Snwhitehorntypedef struct _box { 52217309Snwhitehorn WINDOW *parent; 53217309Snwhitehorn WINDOW *window; 54217309Snwhitehorn int x; 55217309Snwhitehorn int y; 56217309Snwhitehorn int width; 57217309Snwhitehorn int height; 58217309Snwhitehorn BOX_DRAW box_draw; 59217309Snwhitehorn} BOX; 60217309Snwhitehorn 61217309Snwhitehornstatic const char * 62217309SnwhitehornnameOfDayOfWeek(int n) 63217309Snwhitehorn{ 64217309Snwhitehorn static const char *table[7] 65217309Snwhitehorn#ifndef ENABLE_NLS 66217309Snwhitehorn = 67217309Snwhitehorn { 68217309Snwhitehorn "Sunday", 69217309Snwhitehorn "Monday", 70217309Snwhitehorn "Tuesday", 71217309Snwhitehorn "Wednesday", 72217309Snwhitehorn "Thursday", 73217309Snwhitehorn "Friday", 74217309Snwhitehorn "Saturday" 75217309Snwhitehorn } 76217309Snwhitehorn#endif 77217309Snwhitehorn ; 78217309Snwhitehorn const char *result = 0; 79217309Snwhitehorn 80217309Snwhitehorn if (n >= 0 && n < 7) { 81217309Snwhitehorn#ifdef ENABLE_NLS 82217309Snwhitehorn if (table[n] == 0) { 83217309Snwhitehorn nl_item items[7] = 84217309Snwhitehorn { 85217309Snwhitehorn ABDAY_1, ABDAY_2, ABDAY_3, ABDAY_4, ABDAY_5, ABDAY_6, ABDAY_7 86217309Snwhitehorn }; 87217309Snwhitehorn table[n] = nl_langinfo(items[n]); 88217309Snwhitehorn } 89217309Snwhitehorn#endif 90217309Snwhitehorn result = table[n]; 91217309Snwhitehorn } 92217309Snwhitehorn if (result == 0) { 93217309Snwhitehorn result = "?"; 94217309Snwhitehorn } 95217309Snwhitehorn return result; 96217309Snwhitehorn} 97217309Snwhitehorn 98217309Snwhitehornstatic const char * 99217309SnwhitehornnameOfMonth(int n) 100217309Snwhitehorn{ 101217309Snwhitehorn static const char *table[12] 102217309Snwhitehorn#ifndef ENABLE_NLS 103217309Snwhitehorn = 104217309Snwhitehorn { 105217309Snwhitehorn "January", 106217309Snwhitehorn "February", 107217309Snwhitehorn "March", 108217309Snwhitehorn "April", 109217309Snwhitehorn "May", 110217309Snwhitehorn "June", 111217309Snwhitehorn "July", 112217309Snwhitehorn "August", 113217309Snwhitehorn "September", 114217309Snwhitehorn "October", 115217309Snwhitehorn "November", 116217309Snwhitehorn "December" 117217309Snwhitehorn } 118217309Snwhitehorn#endif 119217309Snwhitehorn ; 120217309Snwhitehorn const char *result = 0; 121217309Snwhitehorn 122217309Snwhitehorn if (n >= 0 && n < 12) { 123217309Snwhitehorn#ifdef ENABLE_NLS 124217309Snwhitehorn if (table[n] == 0) { 125217309Snwhitehorn nl_item items[12] = 126217309Snwhitehorn { 127217309Snwhitehorn MON_1, MON_2, MON_3, MON_4, MON_5, MON_6, 128217309Snwhitehorn MON_7, MON_8, MON_9, MON_10, MON_11, MON_12 129217309Snwhitehorn }; 130217309Snwhitehorn table[n] = nl_langinfo(items[n]); 131217309Snwhitehorn } 132217309Snwhitehorn#endif 133217309Snwhitehorn result = table[n]; 134217309Snwhitehorn } 135217309Snwhitehorn if (result == 0) { 136217309Snwhitehorn result = "?"; 137217309Snwhitehorn } 138217309Snwhitehorn return result; 139217309Snwhitehorn} 140217309Snwhitehorn 141217309Snwhitehornstatic int 142217309Snwhitehorndays_in_month(struct tm *current, int offset /* -1, 0, 1 */ ) 143217309Snwhitehorn{ 144217309Snwhitehorn static const int nominal[] = 145217309Snwhitehorn { 146217309Snwhitehorn 31, 28, 31, 30, 31, 30, 147217309Snwhitehorn 31, 31, 30, 31, 30, 31 148217309Snwhitehorn }; 149217309Snwhitehorn int year = current->tm_year; 150217309Snwhitehorn int month = current->tm_mon + offset; 151217309Snwhitehorn int result; 152217309Snwhitehorn 153217309Snwhitehorn while (month < 0) { 154217309Snwhitehorn month += 12; 155217309Snwhitehorn year -= 1; 156217309Snwhitehorn } 157217309Snwhitehorn while (month >= 12) { 158217309Snwhitehorn month -= 12; 159217309Snwhitehorn year += 1; 160217309Snwhitehorn } 161217309Snwhitehorn result = nominal[month]; 162217309Snwhitehorn if (month == 1) 163217309Snwhitehorn result += ((year % 4) == 0); 164217309Snwhitehorn return result; 165217309Snwhitehorn} 166217309Snwhitehorn 167217309Snwhitehornstatic int 168217309Snwhitehorndays_in_year(struct tm *current, int offset /* -1, 0, 1 */ ) 169217309Snwhitehorn{ 170217309Snwhitehorn int year = current->tm_year + 1900 + offset; 171217309Snwhitehorn 172217309Snwhitehorn return ((year % 4) == 0) ? 366 : 365; 173217309Snwhitehorn} 174217309Snwhitehorn 175217309Snwhitehornstatic int 176217309Snwhitehornday_cell_number(struct tm *current) 177217309Snwhitehorn{ 178217309Snwhitehorn int cell; 179217309Snwhitehorn cell = current->tm_mday - ((6 + current->tm_mday - current->tm_wday) % 7); 180217309Snwhitehorn if ((current->tm_mday - 1) % 7 != current->tm_wday) 181217309Snwhitehorn cell += 6; 182217309Snwhitehorn else 183217309Snwhitehorn cell--; 184217309Snwhitehorn return cell; 185217309Snwhitehorn} 186217309Snwhitehorn 187217309Snwhitehornstatic int 188217309Snwhitehornnext_or_previous(int key, int two_d) 189217309Snwhitehorn{ 190217309Snwhitehorn int result = 0; 191217309Snwhitehorn 192217309Snwhitehorn switch (key) { 193217309Snwhitehorn case DLGK_GRID_UP: 194217309Snwhitehorn result = two_d ? -7 : -1; 195217309Snwhitehorn break; 196217309Snwhitehorn case DLGK_GRID_LEFT: 197217309Snwhitehorn result = -1; 198217309Snwhitehorn break; 199217309Snwhitehorn case DLGK_GRID_DOWN: 200217309Snwhitehorn result = two_d ? 7 : 1; 201217309Snwhitehorn break; 202217309Snwhitehorn case DLGK_GRID_RIGHT: 203217309Snwhitehorn result = 1; 204217309Snwhitehorn break; 205217309Snwhitehorn default: 206217309Snwhitehorn beep(); 207217309Snwhitehorn break; 208217309Snwhitehorn } 209217309Snwhitehorn return result; 210217309Snwhitehorn} 211217309Snwhitehorn 212217309Snwhitehorn/* 213217309Snwhitehorn * Draw the day-of-month selection box 214217309Snwhitehorn */ 215217309Snwhitehornstatic int 216217309Snwhitehorndraw_day(BOX * data, struct tm *current) 217217309Snwhitehorn{ 218217309Snwhitehorn int cell_wide = MON_WIDE; 219217309Snwhitehorn int y, x, this_x = 0; 220217309Snwhitehorn int save_y = 0, save_x = 0; 221217309Snwhitehorn int day = current->tm_mday; 222217309Snwhitehorn int mday; 223217309Snwhitehorn int week; 224217309Snwhitehorn int last = days_in_month(current, 0); 225217309Snwhitehorn int prev = days_in_month(current, -1); 226217309Snwhitehorn 227217309Snwhitehorn werase(data->window); 228251843Sbapt dlg_draw_box2(data->parent, 229251843Sbapt data->y - MARGIN, data->x - MARGIN, 230251843Sbapt data->height + (2 * MARGIN), data->width + (2 * MARGIN), 231251843Sbapt menubox_attr, 232251843Sbapt menubox_border_attr, 233251843Sbapt menubox_border2_attr); 234217309Snwhitehorn 235251843Sbapt (void) wattrset(data->window, menubox_attr); /* daynames headline */ 236217309Snwhitehorn for (x = 0; x < 7; x++) { 237217309Snwhitehorn mvwprintw(data->window, 238217309Snwhitehorn 0, (x + 1) * cell_wide, "%*.*s ", 239217309Snwhitehorn cell_wide - 1, 240217309Snwhitehorn cell_wide - 1, 241217309Snwhitehorn nameOfDayOfWeek(x)); 242217309Snwhitehorn } 243217309Snwhitehorn 244217309Snwhitehorn mday = ((6 + current->tm_mday - current->tm_wday) % 7) - 7; 245217309Snwhitehorn if (mday <= -7) 246217309Snwhitehorn mday += 7; 247217309Snwhitehorn /* mday is now in the range -6 to 0. */ 248217309Snwhitehorn week = (current->tm_yday + 6 + mday - current->tm_mday) / 7; 249217309Snwhitehorn 250217309Snwhitehorn for (y = 1; mday < last; y++) { 251251843Sbapt (void) wattrset(data->window, menubox_attr); /* weeknumbers headline */ 252217309Snwhitehorn mvwprintw(data->window, 253217309Snwhitehorn y, 0, 254217309Snwhitehorn "%*d ", 255217309Snwhitehorn cell_wide - 1, 256217309Snwhitehorn ++week); 257217309Snwhitehorn for (x = 0; x < 7; x++) { 258217309Snwhitehorn this_x = 1 + (x + 1) * cell_wide; 259217309Snwhitehorn ++mday; 260217309Snwhitehorn if (wmove(data->window, y, this_x) == ERR) 261217309Snwhitehorn continue; 262251843Sbapt (void) wattrset(data->window, item_attr); /* not selected days */ 263217309Snwhitehorn if (mday == day) { 264251843Sbapt (void) wattrset(data->window, item_selected_attr); /* selected day */ 265217309Snwhitehorn save_y = y; 266217309Snwhitehorn save_x = this_x; 267217309Snwhitehorn } 268217309Snwhitehorn if (mday > 0) { 269217309Snwhitehorn if (mday <= last) { 270217309Snwhitehorn wprintw(data->window, "%*d", cell_wide - 2, mday); 271217309Snwhitehorn } else if (mday == day) { 272217309Snwhitehorn wprintw(data->window, "%*d", cell_wide - 2, mday - last); 273217309Snwhitehorn } 274217309Snwhitehorn } else if (mday == day) { 275217309Snwhitehorn wprintw(data->window, "%*d", cell_wide - 2, mday + prev); 276217309Snwhitehorn } 277217309Snwhitehorn } 278217309Snwhitehorn wmove(data->window, save_y, save_x); 279217309Snwhitehorn } 280217309Snwhitehorn /* just draw arrows - scrollbar is unsuitable here */ 281217309Snwhitehorn dlg_draw_arrows(data->parent, TRUE, TRUE, 282217309Snwhitehorn data->x + ARROWS_COL, 283217309Snwhitehorn data->y - 1, 284217309Snwhitehorn data->y + data->height); 285217309Snwhitehorn 286217309Snwhitehorn return 0; 287217309Snwhitehorn} 288217309Snwhitehorn 289217309Snwhitehorn/* 290217309Snwhitehorn * Draw the month-of-year selection box 291217309Snwhitehorn */ 292217309Snwhitehornstatic int 293217309Snwhitehorndraw_month(BOX * data, struct tm *current) 294217309Snwhitehorn{ 295217309Snwhitehorn int month; 296217309Snwhitehorn 297217309Snwhitehorn month = current->tm_mon + 1; 298217309Snwhitehorn 299251843Sbapt (void) wattrset(data->parent, dialog_attr); /* Headline "Month" */ 300217309Snwhitehorn (void) mvwprintw(data->parent, data->y - 2, data->x - 1, _("Month")); 301251843Sbapt dlg_draw_box2(data->parent, 302251843Sbapt data->y - 1, data->x - 1, 303251843Sbapt data->height + 2, data->width + 2, 304251843Sbapt menubox_attr, 305251843Sbapt menubox_border_attr, 306251843Sbapt menubox_border2_attr); 307251843Sbapt (void) wattrset(data->window, item_attr); /* color the month selection */ 308217309Snwhitehorn mvwprintw(data->window, 0, 0, "%s", nameOfMonth(month - 1)); 309217309Snwhitehorn wmove(data->window, 0, 0); 310217309Snwhitehorn return 0; 311217309Snwhitehorn} 312217309Snwhitehorn 313217309Snwhitehorn/* 314217309Snwhitehorn * Draw the year selection box 315217309Snwhitehorn */ 316217309Snwhitehornstatic int 317217309Snwhitehorndraw_year(BOX * data, struct tm *current) 318217309Snwhitehorn{ 319217309Snwhitehorn int year = current->tm_year + 1900; 320217309Snwhitehorn 321251843Sbapt (void) wattrset(data->parent, dialog_attr); /* Headline "Year" */ 322217309Snwhitehorn (void) mvwprintw(data->parent, data->y - 2, data->x - 1, _("Year")); 323251843Sbapt dlg_draw_box2(data->parent, 324251843Sbapt data->y - 1, data->x - 1, 325251843Sbapt data->height + 2, data->width + 2, 326251843Sbapt menubox_attr, 327251843Sbapt menubox_border_attr, 328251843Sbapt menubox_border2_attr); 329251843Sbapt (void) wattrset(data->window, item_attr); /* color the year selection */ 330217309Snwhitehorn mvwprintw(data->window, 0, 0, "%4d", year); 331217309Snwhitehorn wmove(data->window, 0, 0); 332217309Snwhitehorn return 0; 333217309Snwhitehorn} 334217309Snwhitehorn 335217309Snwhitehornstatic int 336217309Snwhitehorninit_object(BOX * data, 337217309Snwhitehorn WINDOW *parent, 338217309Snwhitehorn int x, int y, 339217309Snwhitehorn int width, int height, 340217309Snwhitehorn BOX_DRAW box_draw, 341217309Snwhitehorn int code) 342217309Snwhitehorn{ 343217309Snwhitehorn data->parent = parent; 344217309Snwhitehorn data->x = x; 345217309Snwhitehorn data->y = y; 346217309Snwhitehorn data->width = width; 347217309Snwhitehorn data->height = height; 348217309Snwhitehorn data->box_draw = box_draw; 349217309Snwhitehorn 350217309Snwhitehorn data->window = derwin(data->parent, 351217309Snwhitehorn data->height, data->width, 352217309Snwhitehorn data->y, data->x); 353217309Snwhitehorn if (data->window == 0) 354217309Snwhitehorn return -1; 355217309Snwhitehorn (void) keypad(data->window, TRUE); 356217309Snwhitehorn 357217309Snwhitehorn dlg_mouse_setbase(getbegx(parent), getbegy(parent)); 358217309Snwhitehorn if (code == 'D') { 359217309Snwhitehorn dlg_mouse_mkbigregion(y + 1, x + MON_WIDE, height - 1, width - MON_WIDE, 360217309Snwhitehorn KEY_MAX, 1, MON_WIDE, 3); 361217309Snwhitehorn } else { 362217309Snwhitehorn dlg_mouse_mkregion(y, x, height, width, code); 363217309Snwhitehorn } 364217309Snwhitehorn 365217309Snwhitehorn return 0; 366217309Snwhitehorn} 367217309Snwhitehorn 368217309Snwhitehornstatic int 369217309SnwhitehornCleanupResult(int code, WINDOW *dialog, char *prompt, DIALOG_VARS * save_vars) 370217309Snwhitehorn{ 371217309Snwhitehorn if (dialog != 0) 372217309Snwhitehorn dlg_del_window(dialog); 373217309Snwhitehorn dlg_mouse_free_regions(); 374217309Snwhitehorn if (prompt != 0) 375217309Snwhitehorn free(prompt); 376217309Snwhitehorn dlg_restore_vars(save_vars); 377217309Snwhitehorn 378217309Snwhitehorn return code; 379217309Snwhitehorn} 380217309Snwhitehorn 381217309Snwhitehorn#define DrawObject(data) (data)->box_draw(data, ¤t) 382217309Snwhitehorn 383217309Snwhitehorn/* 384217309Snwhitehorn * Display a dialog box for entering a date 385217309Snwhitehorn */ 386217309Snwhitehornint 387217309Snwhitehorndialog_calendar(const char *title, 388217309Snwhitehorn const char *subtitle, 389217309Snwhitehorn int height, 390217309Snwhitehorn int width, 391217309Snwhitehorn int day, 392217309Snwhitehorn int month, 393217309Snwhitehorn int year) 394217309Snwhitehorn{ 395217309Snwhitehorn /* *INDENT-OFF* */ 396217309Snwhitehorn static DLG_KEYS_BINDING binding[] = { 397224014Snwhitehorn HELPKEY_BINDINGS, 398217309Snwhitehorn ENTERKEY_BINDINGS, 399217309Snwhitehorn DLG_KEYS_DATA( DLGK_ENTER, ' ' ), 400217309Snwhitehorn DLG_KEYS_DATA( DLGK_FIELD_NEXT, TAB ), 401217309Snwhitehorn DLG_KEYS_DATA( DLGK_FIELD_PREV, KEY_BTAB ), 402217309Snwhitehorn DLG_KEYS_DATA( DLGK_GRID_DOWN, 'j' ), 403217309Snwhitehorn DLG_KEYS_DATA( DLGK_GRID_DOWN, DLGK_MOUSE(KEY_NPAGE) ), 404217309Snwhitehorn DLG_KEYS_DATA( DLGK_GRID_DOWN, KEY_DOWN ), 405217309Snwhitehorn DLG_KEYS_DATA( DLGK_GRID_DOWN, KEY_NPAGE ), 406217309Snwhitehorn DLG_KEYS_DATA( DLGK_GRID_LEFT, '-' ), 407217309Snwhitehorn DLG_KEYS_DATA( DLGK_GRID_LEFT, 'h' ), 408217309Snwhitehorn DLG_KEYS_DATA( DLGK_GRID_LEFT, CHR_BACKSPACE ), 409217309Snwhitehorn DLG_KEYS_DATA( DLGK_GRID_LEFT, CHR_PREVIOUS ), 410217309Snwhitehorn DLG_KEYS_DATA( DLGK_GRID_LEFT, KEY_LEFT ), 411217309Snwhitehorn DLG_KEYS_DATA( DLGK_GRID_RIGHT, '+' ), 412217309Snwhitehorn DLG_KEYS_DATA( DLGK_GRID_RIGHT, 'l' ), 413217309Snwhitehorn DLG_KEYS_DATA( DLGK_GRID_RIGHT, CHR_NEXT ), 414217309Snwhitehorn DLG_KEYS_DATA( DLGK_GRID_RIGHT, KEY_NEXT ), 415217309Snwhitehorn DLG_KEYS_DATA( DLGK_GRID_RIGHT, KEY_RIGHT ), 416217309Snwhitehorn DLG_KEYS_DATA( DLGK_GRID_UP, 'k' ), 417217309Snwhitehorn DLG_KEYS_DATA( DLGK_GRID_UP, KEY_PPAGE ), 418217309Snwhitehorn DLG_KEYS_DATA( DLGK_GRID_UP, KEY_PREVIOUS ), 419217309Snwhitehorn DLG_KEYS_DATA( DLGK_GRID_UP, KEY_UP ), 420217309Snwhitehorn DLG_KEYS_DATA( DLGK_GRID_UP, DLGK_MOUSE(KEY_PPAGE) ), 421217309Snwhitehorn END_KEYS_BINDING 422217309Snwhitehorn }; 423217309Snwhitehorn /* *INDENT-ON* */ 424217309Snwhitehorn 425217309Snwhitehorn#ifdef KEY_RESIZE 426217309Snwhitehorn int old_height = height; 427217309Snwhitehorn int old_width = width; 428217309Snwhitehorn#endif 429217309Snwhitehorn BOX dy_box, mn_box, yr_box; 430217309Snwhitehorn int fkey; 431217309Snwhitehorn int key = 0; 432217309Snwhitehorn int key2; 433217309Snwhitehorn int step; 434217309Snwhitehorn int button; 435217309Snwhitehorn int result = DLG_EXIT_UNKNOWN; 436217309Snwhitehorn WINDOW *dialog; 437217309Snwhitehorn time_t now_time = time((time_t *) 0); 438217309Snwhitehorn struct tm current; 439251843Sbapt int state = dlg_default_button(); 440217309Snwhitehorn const char **buttons = dlg_ok_labels(); 441217309Snwhitehorn char *prompt = dlg_strclone(subtitle); 442217309Snwhitehorn int mincols = MIN_WIDE; 443217309Snwhitehorn char buffer[MAX_LEN]; 444217309Snwhitehorn DIALOG_VARS save_vars; 445217309Snwhitehorn 446217309Snwhitehorn dlg_save_vars(&save_vars); 447217309Snwhitehorn dialog_vars.separate_output = TRUE; 448217309Snwhitehorn 449217309Snwhitehorn dlg_does_output(); 450217309Snwhitehorn 451217309Snwhitehorn now_time = time((time_t *) 0); 452217309Snwhitehorn current = *localtime(&now_time); 453217309Snwhitehorn if (day < 0) 454217309Snwhitehorn day = current.tm_mday; 455217309Snwhitehorn if (month < 0) 456217309Snwhitehorn month = current.tm_mon + 1; 457217309Snwhitehorn if (year < 0) 458217309Snwhitehorn year = current.tm_year + 1900; 459217309Snwhitehorn 460217309Snwhitehorn /* compute a struct tm that matches the day/month/year parameters */ 461217309Snwhitehorn if (((year -= 1900) > 0) && (year < 200)) { 462217309Snwhitehorn /* ugly, but I'd like to run this on older machines w/o mktime -TD */ 463217309Snwhitehorn for (;;) { 464217309Snwhitehorn if (year > current.tm_year) { 465217309Snwhitehorn now_time += ONE_DAY * days_in_year(¤t, 0); 466217309Snwhitehorn } else if (year < current.tm_year) { 467217309Snwhitehorn now_time -= ONE_DAY * days_in_year(¤t, -1); 468217309Snwhitehorn } else if (month > current.tm_mon + 1) { 469217309Snwhitehorn now_time += ONE_DAY * days_in_month(¤t, 0); 470217309Snwhitehorn } else if (month < current.tm_mon + 1) { 471217309Snwhitehorn now_time -= ONE_DAY * days_in_month(¤t, -1); 472217309Snwhitehorn } else if (day > current.tm_mday) { 473217309Snwhitehorn now_time += ONE_DAY; 474217309Snwhitehorn } else if (day < current.tm_mday) { 475217309Snwhitehorn now_time -= ONE_DAY; 476217309Snwhitehorn } else { 477217309Snwhitehorn break; 478217309Snwhitehorn } 479217309Snwhitehorn current = *localtime(&now_time); 480217309Snwhitehorn } 481217309Snwhitehorn } 482217309Snwhitehorn dlg_button_layout(buttons, &mincols); 483217309Snwhitehorn 484217309Snwhitehorn#ifdef KEY_RESIZE 485217309Snwhitehorn retry: 486217309Snwhitehorn#endif 487217309Snwhitehorn 488217309Snwhitehorn dlg_auto_size(title, prompt, &height, &width, 0, mincols); 489217309Snwhitehorn height += MIN_HIGH - 1; 490217309Snwhitehorn dlg_print_size(height, width); 491217309Snwhitehorn dlg_ctl_size(height, width); 492217309Snwhitehorn 493217309Snwhitehorn dialog = dlg_new_window(height, width, 494217309Snwhitehorn dlg_box_y_ordinate(height), 495217309Snwhitehorn dlg_box_x_ordinate(width)); 496217309Snwhitehorn dlg_register_window(dialog, "calendar", binding); 497217309Snwhitehorn dlg_register_buttons(dialog, "calendar", buttons); 498217309Snwhitehorn 499217309Snwhitehorn /* mainbox */ 500251843Sbapt dlg_draw_box2(dialog, 0, 0, height, width, dialog_attr, border_attr, border2_attr); 501251843Sbapt dlg_draw_bottom_box2(dialog, border_attr, border2_attr, dialog_attr); 502217309Snwhitehorn dlg_draw_title(dialog, title); 503217309Snwhitehorn 504251843Sbapt (void) wattrset(dialog, dialog_attr); /* text mainbox */ 505217309Snwhitehorn dlg_print_autowrap(dialog, prompt, height, width); 506217309Snwhitehorn 507217309Snwhitehorn /* compute positions of day, month and year boxes */ 508217309Snwhitehorn memset(&dy_box, 0, sizeof(dy_box)); 509217309Snwhitehorn memset(&mn_box, 0, sizeof(mn_box)); 510217309Snwhitehorn memset(&yr_box, 0, sizeof(yr_box)); 511217309Snwhitehorn 512217309Snwhitehorn if (init_object(&dy_box, 513217309Snwhitehorn dialog, 514217309Snwhitehorn (width - DAY_WIDE) / 2, 515217309Snwhitehorn 1 + (height - (DAY_HIGH + BTN_HIGH + (5 * MARGIN))), 516217309Snwhitehorn DAY_WIDE, 517217309Snwhitehorn DAY_HIGH + 1, 518217309Snwhitehorn draw_day, 519217309Snwhitehorn 'D') < 0 520217309Snwhitehorn || DrawObject(&dy_box) < 0) { 521217309Snwhitehorn return CleanupResult(DLG_EXIT_ERROR, dialog, prompt, &save_vars); 522217309Snwhitehorn } 523217309Snwhitehorn 524217309Snwhitehorn if (init_object(&mn_box, 525217309Snwhitehorn dialog, 526217309Snwhitehorn dy_box.x, 527217309Snwhitehorn dy_box.y - (HDR_HIGH + 2 * MARGIN), 528217309Snwhitehorn (DAY_WIDE / 2) - MARGIN, 529217309Snwhitehorn HDR_HIGH, 530217309Snwhitehorn draw_month, 531217309Snwhitehorn 'M') < 0 532217309Snwhitehorn || DrawObject(&mn_box) < 0) { 533217309Snwhitehorn return CleanupResult(DLG_EXIT_ERROR, dialog, prompt, &save_vars); 534217309Snwhitehorn } 535217309Snwhitehorn 536217309Snwhitehorn if (init_object(&yr_box, 537217309Snwhitehorn dialog, 538217309Snwhitehorn dy_box.x + mn_box.width + 2, 539217309Snwhitehorn mn_box.y, 540217309Snwhitehorn mn_box.width, 541217309Snwhitehorn mn_box.height, 542217309Snwhitehorn draw_year, 543217309Snwhitehorn 'Y') < 0 544217309Snwhitehorn || DrawObject(&yr_box) < 0) { 545217309Snwhitehorn return CleanupResult(DLG_EXIT_ERROR, dialog, prompt, &save_vars); 546217309Snwhitehorn } 547217309Snwhitehorn 548251843Sbapt dlg_trace_win(dialog); 549217309Snwhitehorn while (result == DLG_EXIT_UNKNOWN) { 550217309Snwhitehorn BOX *obj = (state == sDAY ? &dy_box 551217309Snwhitehorn : (state == sMONTH ? &mn_box : 552217309Snwhitehorn (state == sYEAR ? &yr_box : 0))); 553217309Snwhitehorn 554217309Snwhitehorn button = (state < 0) ? 0 : state; 555217309Snwhitehorn dlg_draw_buttons(dialog, height - 2, 0, buttons, button, FALSE, width); 556217309Snwhitehorn if (obj != 0) 557217309Snwhitehorn dlg_set_focus(dialog, obj->window); 558217309Snwhitehorn 559217309Snwhitehorn key = dlg_mouse_wgetch(dialog, &fkey); 560217309Snwhitehorn if (dlg_result_key(key, fkey, &result)) 561217309Snwhitehorn break; 562217309Snwhitehorn 563217309Snwhitehorn if (fkey && (key >= DLGK_MOUSE(KEY_MIN) && key <= DLGK_MOUSE(KEY_MAX))) { 564217309Snwhitehorn key = dlg_lookup_key(dialog, key - M_EVENT, &fkey); 565217309Snwhitehorn } 566217309Snwhitehorn 567217309Snwhitehorn if ((key2 = dlg_char_to_button(key, buttons)) >= 0) { 568217309Snwhitehorn result = key2; 569217309Snwhitehorn } else if (fkey) { 570217309Snwhitehorn /* handle function-keys */ 571217309Snwhitehorn switch (key) { 572217309Snwhitehorn case DLGK_MOUSE('D'): 573217309Snwhitehorn state = sDAY; 574217309Snwhitehorn break; 575217309Snwhitehorn case DLGK_MOUSE('M'): 576217309Snwhitehorn state = sMONTH; 577217309Snwhitehorn break; 578217309Snwhitehorn case DLGK_MOUSE('Y'): 579217309Snwhitehorn state = sYEAR; 580217309Snwhitehorn break; 581217309Snwhitehorn case DLGK_ENTER: 582224014Snwhitehorn result = dlg_enter_buttoncode(button); 583217309Snwhitehorn break; 584217309Snwhitehorn case DLGK_FIELD_PREV: 585217309Snwhitehorn state = dlg_prev_ok_buttonindex(state, sMONTH); 586217309Snwhitehorn break; 587217309Snwhitehorn case DLGK_FIELD_NEXT: 588217309Snwhitehorn state = dlg_next_ok_buttonindex(state, sMONTH); 589217309Snwhitehorn break; 590217309Snwhitehorn#ifdef KEY_RESIZE 591217309Snwhitehorn case KEY_RESIZE: 592217309Snwhitehorn /* reset data */ 593217309Snwhitehorn height = old_height; 594217309Snwhitehorn width = old_width; 595217309Snwhitehorn /* repaint */ 596217309Snwhitehorn dlg_clear(); 597217309Snwhitehorn dlg_del_window(dialog); 598217309Snwhitehorn refresh(); 599217309Snwhitehorn dlg_mouse_free_regions(); 600217309Snwhitehorn goto retry; 601217309Snwhitehorn#endif 602217309Snwhitehorn default: 603217309Snwhitehorn step = 0; 604217309Snwhitehorn key2 = -1; 605217309Snwhitehorn if (is_DLGK_MOUSE(key)) { 606217309Snwhitehorn if ((key2 = dlg_ok_buttoncode(key - M_EVENT)) >= 0) { 607217309Snwhitehorn result = key2; 608217309Snwhitehorn break; 609217309Snwhitehorn } else if (key >= DLGK_MOUSE(KEY_MAX)) { 610217309Snwhitehorn state = sDAY; 611217309Snwhitehorn obj = &dy_box; 612217309Snwhitehorn key2 = 1; 613217309Snwhitehorn step = (key 614217309Snwhitehorn - DLGK_MOUSE(KEY_MAX) 615217309Snwhitehorn - day_cell_number(¤t)); 616217309Snwhitehorn } 617217309Snwhitehorn } 618217309Snwhitehorn if (obj != 0) { 619217309Snwhitehorn if (key2 < 0) 620217309Snwhitehorn step = next_or_previous(key, (obj == &dy_box)); 621217309Snwhitehorn if (step != 0) { 622217309Snwhitehorn struct tm old = current; 623217309Snwhitehorn 624217309Snwhitehorn /* see comment regarding mktime -TD */ 625217309Snwhitehorn if (obj == &dy_box) { 626217309Snwhitehorn now_time += ONE_DAY * step; 627217309Snwhitehorn } else if (obj == &mn_box) { 628217309Snwhitehorn if (step > 0) 629217309Snwhitehorn now_time += ONE_DAY * 630217309Snwhitehorn days_in_month(¤t, 0); 631217309Snwhitehorn else 632217309Snwhitehorn now_time -= ONE_DAY * 633217309Snwhitehorn days_in_month(¤t, -1); 634217309Snwhitehorn } else if (obj == &yr_box) { 635217309Snwhitehorn if (step > 0) 636217309Snwhitehorn now_time += (ONE_DAY 637217309Snwhitehorn * days_in_year(¤t, 0)); 638217309Snwhitehorn else 639217309Snwhitehorn now_time -= (ONE_DAY 640217309Snwhitehorn * days_in_year(¤t, -1)); 641217309Snwhitehorn } 642217309Snwhitehorn 643217309Snwhitehorn current = *localtime(&now_time); 644217309Snwhitehorn 645217309Snwhitehorn if (obj != &dy_box 646217309Snwhitehorn && (current.tm_mday != old.tm_mday 647217309Snwhitehorn || current.tm_mon != old.tm_mon 648217309Snwhitehorn || current.tm_year != old.tm_year)) 649217309Snwhitehorn DrawObject(&dy_box); 650217309Snwhitehorn if (obj != &mn_box && current.tm_mon != old.tm_mon) 651217309Snwhitehorn DrawObject(&mn_box); 652217309Snwhitehorn if (obj != &yr_box && current.tm_year != old.tm_year) 653217309Snwhitehorn DrawObject(&yr_box); 654217309Snwhitehorn (void) DrawObject(obj); 655217309Snwhitehorn } 656217309Snwhitehorn } else if (state >= 0) { 657217309Snwhitehorn if (next_or_previous(key, FALSE) < 0) 658217309Snwhitehorn state = dlg_prev_ok_buttonindex(state, sMONTH); 659217309Snwhitehorn else if (next_or_previous(key, FALSE) > 0) 660217309Snwhitehorn state = dlg_next_ok_buttonindex(state, sMONTH); 661217309Snwhitehorn } 662217309Snwhitehorn break; 663217309Snwhitehorn } 664217309Snwhitehorn } 665217309Snwhitehorn } 666217309Snwhitehorn 667217309Snwhitehorn#define DefaultFormat(dst, src) \ 668217309Snwhitehorn sprintf(dst, "%02d/%02d/%0d", \ 669217309Snwhitehorn src.tm_mday, src.tm_mon + 1, src.tm_year + 1900) 670217309Snwhitehorn#ifdef HAVE_STRFTIME 671217309Snwhitehorn if (dialog_vars.date_format != 0) { 672220749Snwhitehorn size_t used = strftime(buffer, 673220749Snwhitehorn sizeof(buffer) - 1, 674220749Snwhitehorn dialog_vars.date_format, 675220749Snwhitehorn ¤t); 676217309Snwhitehorn if (used == 0 || *buffer == '\0') 677217309Snwhitehorn DefaultFormat(buffer, current); 678217309Snwhitehorn } else 679217309Snwhitehorn#endif 680217309Snwhitehorn DefaultFormat(buffer, current); 681217309Snwhitehorn 682217309Snwhitehorn dlg_add_result(buffer); 683217309Snwhitehorn dlg_add_separator(); 684251843Sbapt dlg_add_last_key(-1); 685217309Snwhitehorn 686217309Snwhitehorn return CleanupResult(result, dialog, prompt, &save_vars); 687217309Snwhitehorn} 688