1217309Snwhitehorn/* 2224014Snwhitehorn * $Id: calendar.c,v 1.62 2011/06/29 09:47:06 tom Exp $ 3217309Snwhitehorn * 4217309Snwhitehorn * calendar.c -- implements the calendar box 5217309Snwhitehorn * 6220749Snwhitehorn * Copyright 2001-2010,2011 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); 228217309Snwhitehorn dlg_draw_box(data->parent, 229217309Snwhitehorn data->y - MARGIN, data->x - MARGIN, 230217309Snwhitehorn data->height + (2 * MARGIN), data->width + (2 * MARGIN), 231217309Snwhitehorn menubox_border_attr, menubox_attr); /* border of daybox */ 232217309Snwhitehorn 233217309Snwhitehorn wattrset(data->window, menubox_attr); /* daynames headline */ 234217309Snwhitehorn for (x = 0; x < 7; x++) { 235217309Snwhitehorn mvwprintw(data->window, 236217309Snwhitehorn 0, (x + 1) * cell_wide, "%*.*s ", 237217309Snwhitehorn cell_wide - 1, 238217309Snwhitehorn cell_wide - 1, 239217309Snwhitehorn nameOfDayOfWeek(x)); 240217309Snwhitehorn } 241217309Snwhitehorn 242217309Snwhitehorn mday = ((6 + current->tm_mday - current->tm_wday) % 7) - 7; 243217309Snwhitehorn if (mday <= -7) 244217309Snwhitehorn mday += 7; 245217309Snwhitehorn /* mday is now in the range -6 to 0. */ 246217309Snwhitehorn week = (current->tm_yday + 6 + mday - current->tm_mday) / 7; 247217309Snwhitehorn 248217309Snwhitehorn for (y = 1; mday < last; y++) { 249217309Snwhitehorn wattrset(data->window, menubox_attr); /* weeknumbers headline */ 250217309Snwhitehorn mvwprintw(data->window, 251217309Snwhitehorn y, 0, 252217309Snwhitehorn "%*d ", 253217309Snwhitehorn cell_wide - 1, 254217309Snwhitehorn ++week); 255217309Snwhitehorn for (x = 0; x < 7; x++) { 256217309Snwhitehorn this_x = 1 + (x + 1) * cell_wide; 257217309Snwhitehorn ++mday; 258217309Snwhitehorn if (wmove(data->window, y, this_x) == ERR) 259217309Snwhitehorn continue; 260217309Snwhitehorn wattrset(data->window, item_attr); /* not selected days */ 261217309Snwhitehorn if (mday == day) { 262217309Snwhitehorn wattrset(data->window, item_selected_attr); /* selected day */ 263217309Snwhitehorn save_y = y; 264217309Snwhitehorn save_x = this_x; 265217309Snwhitehorn } 266217309Snwhitehorn if (mday > 0) { 267217309Snwhitehorn if (mday <= last) { 268217309Snwhitehorn wprintw(data->window, "%*d", cell_wide - 2, mday); 269217309Snwhitehorn } else if (mday == day) { 270217309Snwhitehorn wprintw(data->window, "%*d", cell_wide - 2, mday - last); 271217309Snwhitehorn } 272217309Snwhitehorn } else if (mday == day) { 273217309Snwhitehorn wprintw(data->window, "%*d", cell_wide - 2, mday + prev); 274217309Snwhitehorn } 275217309Snwhitehorn } 276217309Snwhitehorn wmove(data->window, save_y, save_x); 277217309Snwhitehorn } 278217309Snwhitehorn /* just draw arrows - scrollbar is unsuitable here */ 279217309Snwhitehorn dlg_draw_arrows(data->parent, TRUE, TRUE, 280217309Snwhitehorn data->x + ARROWS_COL, 281217309Snwhitehorn data->y - 1, 282217309Snwhitehorn data->y + data->height); 283217309Snwhitehorn 284217309Snwhitehorn return 0; 285217309Snwhitehorn} 286217309Snwhitehorn 287217309Snwhitehorn/* 288217309Snwhitehorn * Draw the month-of-year selection box 289217309Snwhitehorn */ 290217309Snwhitehornstatic int 291217309Snwhitehorndraw_month(BOX * data, struct tm *current) 292217309Snwhitehorn{ 293217309Snwhitehorn int month; 294217309Snwhitehorn 295217309Snwhitehorn month = current->tm_mon + 1; 296217309Snwhitehorn 297217309Snwhitehorn wattrset(data->parent, dialog_attr); /* Headline "Month" */ 298217309Snwhitehorn (void) mvwprintw(data->parent, data->y - 2, data->x - 1, _("Month")); 299217309Snwhitehorn dlg_draw_box(data->parent, 300217309Snwhitehorn data->y - 1, data->x - 1, 301217309Snwhitehorn data->height + 2, data->width + 2, 302217309Snwhitehorn menubox_border_attr, menubox_attr); /* borders of monthbox */ 303217309Snwhitehorn wattrset(data->window, item_attr); /* color the month selection */ 304217309Snwhitehorn mvwprintw(data->window, 0, 0, "%s", nameOfMonth(month - 1)); 305217309Snwhitehorn wmove(data->window, 0, 0); 306217309Snwhitehorn return 0; 307217309Snwhitehorn} 308217309Snwhitehorn 309217309Snwhitehorn/* 310217309Snwhitehorn * Draw the year selection box 311217309Snwhitehorn */ 312217309Snwhitehornstatic int 313217309Snwhitehorndraw_year(BOX * data, struct tm *current) 314217309Snwhitehorn{ 315217309Snwhitehorn int year = current->tm_year + 1900; 316217309Snwhitehorn 317217309Snwhitehorn wattrset(data->parent, dialog_attr); /* Headline "Year" */ 318217309Snwhitehorn (void) mvwprintw(data->parent, data->y - 2, data->x - 1, _("Year")); 319217309Snwhitehorn dlg_draw_box(data->parent, 320217309Snwhitehorn data->y - 1, data->x - 1, 321217309Snwhitehorn data->height + 2, data->width + 2, 322217309Snwhitehorn menubox_border_attr, menubox_attr); /* borders of yearbox */ 323217309Snwhitehorn wattrset(data->window, item_attr); /* color the year selection */ 324217309Snwhitehorn mvwprintw(data->window, 0, 0, "%4d", year); 325217309Snwhitehorn wmove(data->window, 0, 0); 326217309Snwhitehorn return 0; 327217309Snwhitehorn} 328217309Snwhitehorn 329217309Snwhitehornstatic int 330217309Snwhitehorninit_object(BOX * data, 331217309Snwhitehorn WINDOW *parent, 332217309Snwhitehorn int x, int y, 333217309Snwhitehorn int width, int height, 334217309Snwhitehorn BOX_DRAW box_draw, 335217309Snwhitehorn int code) 336217309Snwhitehorn{ 337217309Snwhitehorn data->parent = parent; 338217309Snwhitehorn data->x = x; 339217309Snwhitehorn data->y = y; 340217309Snwhitehorn data->width = width; 341217309Snwhitehorn data->height = height; 342217309Snwhitehorn data->box_draw = box_draw; 343217309Snwhitehorn 344217309Snwhitehorn data->window = derwin(data->parent, 345217309Snwhitehorn data->height, data->width, 346217309Snwhitehorn data->y, data->x); 347217309Snwhitehorn if (data->window == 0) 348217309Snwhitehorn return -1; 349217309Snwhitehorn (void) keypad(data->window, TRUE); 350217309Snwhitehorn 351217309Snwhitehorn dlg_mouse_setbase(getbegx(parent), getbegy(parent)); 352217309Snwhitehorn if (code == 'D') { 353217309Snwhitehorn dlg_mouse_mkbigregion(y + 1, x + MON_WIDE, height - 1, width - MON_WIDE, 354217309Snwhitehorn KEY_MAX, 1, MON_WIDE, 3); 355217309Snwhitehorn } else { 356217309Snwhitehorn dlg_mouse_mkregion(y, x, height, width, code); 357217309Snwhitehorn } 358217309Snwhitehorn 359217309Snwhitehorn return 0; 360217309Snwhitehorn} 361217309Snwhitehorn 362217309Snwhitehornstatic int 363217309SnwhitehornCleanupResult(int code, WINDOW *dialog, char *prompt, DIALOG_VARS * save_vars) 364217309Snwhitehorn{ 365217309Snwhitehorn if (dialog != 0) 366217309Snwhitehorn dlg_del_window(dialog); 367217309Snwhitehorn dlg_mouse_free_regions(); 368217309Snwhitehorn if (prompt != 0) 369217309Snwhitehorn free(prompt); 370217309Snwhitehorn dlg_restore_vars(save_vars); 371217309Snwhitehorn 372217309Snwhitehorn return code; 373217309Snwhitehorn} 374217309Snwhitehorn 375217309Snwhitehorn#define DrawObject(data) (data)->box_draw(data, ¤t) 376217309Snwhitehorn 377217309Snwhitehorn/* 378217309Snwhitehorn * Display a dialog box for entering a date 379217309Snwhitehorn */ 380217309Snwhitehornint 381217309Snwhitehorndialog_calendar(const char *title, 382217309Snwhitehorn const char *subtitle, 383217309Snwhitehorn int height, 384217309Snwhitehorn int width, 385217309Snwhitehorn int day, 386217309Snwhitehorn int month, 387217309Snwhitehorn int year) 388217309Snwhitehorn{ 389217309Snwhitehorn /* *INDENT-OFF* */ 390217309Snwhitehorn static DLG_KEYS_BINDING binding[] = { 391224014Snwhitehorn HELPKEY_BINDINGS, 392217309Snwhitehorn ENTERKEY_BINDINGS, 393217309Snwhitehorn DLG_KEYS_DATA( DLGK_ENTER, ' ' ), 394217309Snwhitehorn DLG_KEYS_DATA( DLGK_FIELD_NEXT, TAB ), 395217309Snwhitehorn DLG_KEYS_DATA( DLGK_FIELD_PREV, KEY_BTAB ), 396217309Snwhitehorn DLG_KEYS_DATA( DLGK_GRID_DOWN, 'j' ), 397217309Snwhitehorn DLG_KEYS_DATA( DLGK_GRID_DOWN, DLGK_MOUSE(KEY_NPAGE) ), 398217309Snwhitehorn DLG_KEYS_DATA( DLGK_GRID_DOWN, KEY_DOWN ), 399217309Snwhitehorn DLG_KEYS_DATA( DLGK_GRID_DOWN, KEY_NPAGE ), 400217309Snwhitehorn DLG_KEYS_DATA( DLGK_GRID_LEFT, '-' ), 401217309Snwhitehorn DLG_KEYS_DATA( DLGK_GRID_LEFT, 'h' ), 402217309Snwhitehorn DLG_KEYS_DATA( DLGK_GRID_LEFT, CHR_BACKSPACE ), 403217309Snwhitehorn DLG_KEYS_DATA( DLGK_GRID_LEFT, CHR_PREVIOUS ), 404217309Snwhitehorn DLG_KEYS_DATA( DLGK_GRID_LEFT, KEY_LEFT ), 405217309Snwhitehorn DLG_KEYS_DATA( DLGK_GRID_RIGHT, '+' ), 406217309Snwhitehorn DLG_KEYS_DATA( DLGK_GRID_RIGHT, 'l' ), 407217309Snwhitehorn DLG_KEYS_DATA( DLGK_GRID_RIGHT, CHR_NEXT ), 408217309Snwhitehorn DLG_KEYS_DATA( DLGK_GRID_RIGHT, KEY_NEXT ), 409217309Snwhitehorn DLG_KEYS_DATA( DLGK_GRID_RIGHT, KEY_RIGHT ), 410217309Snwhitehorn DLG_KEYS_DATA( DLGK_GRID_UP, 'k' ), 411217309Snwhitehorn DLG_KEYS_DATA( DLGK_GRID_UP, KEY_PPAGE ), 412217309Snwhitehorn DLG_KEYS_DATA( DLGK_GRID_UP, KEY_PREVIOUS ), 413217309Snwhitehorn DLG_KEYS_DATA( DLGK_GRID_UP, KEY_UP ), 414217309Snwhitehorn DLG_KEYS_DATA( DLGK_GRID_UP, DLGK_MOUSE(KEY_PPAGE) ), 415217309Snwhitehorn END_KEYS_BINDING 416217309Snwhitehorn }; 417217309Snwhitehorn /* *INDENT-ON* */ 418217309Snwhitehorn 419217309Snwhitehorn#ifdef KEY_RESIZE 420217309Snwhitehorn int old_height = height; 421217309Snwhitehorn int old_width = width; 422217309Snwhitehorn#endif 423217309Snwhitehorn BOX dy_box, mn_box, yr_box; 424217309Snwhitehorn int fkey; 425217309Snwhitehorn int key = 0; 426217309Snwhitehorn int key2; 427217309Snwhitehorn int step; 428217309Snwhitehorn int button; 429217309Snwhitehorn int result = DLG_EXIT_UNKNOWN; 430217309Snwhitehorn WINDOW *dialog; 431217309Snwhitehorn time_t now_time = time((time_t *) 0); 432217309Snwhitehorn struct tm current; 433217309Snwhitehorn int state = dlg_defaultno_button(); 434217309Snwhitehorn const char **buttons = dlg_ok_labels(); 435217309Snwhitehorn char *prompt = dlg_strclone(subtitle); 436217309Snwhitehorn int mincols = MIN_WIDE; 437217309Snwhitehorn char buffer[MAX_LEN]; 438217309Snwhitehorn DIALOG_VARS save_vars; 439217309Snwhitehorn 440217309Snwhitehorn dlg_save_vars(&save_vars); 441217309Snwhitehorn dialog_vars.separate_output = TRUE; 442217309Snwhitehorn 443217309Snwhitehorn dlg_does_output(); 444217309Snwhitehorn 445217309Snwhitehorn now_time = time((time_t *) 0); 446217309Snwhitehorn current = *localtime(&now_time); 447217309Snwhitehorn if (day < 0) 448217309Snwhitehorn day = current.tm_mday; 449217309Snwhitehorn if (month < 0) 450217309Snwhitehorn month = current.tm_mon + 1; 451217309Snwhitehorn if (year < 0) 452217309Snwhitehorn year = current.tm_year + 1900; 453217309Snwhitehorn 454217309Snwhitehorn /* compute a struct tm that matches the day/month/year parameters */ 455217309Snwhitehorn if (((year -= 1900) > 0) && (year < 200)) { 456217309Snwhitehorn /* ugly, but I'd like to run this on older machines w/o mktime -TD */ 457217309Snwhitehorn for (;;) { 458217309Snwhitehorn if (year > current.tm_year) { 459217309Snwhitehorn now_time += ONE_DAY * days_in_year(¤t, 0); 460217309Snwhitehorn } else if (year < current.tm_year) { 461217309Snwhitehorn now_time -= ONE_DAY * days_in_year(¤t, -1); 462217309Snwhitehorn } else if (month > current.tm_mon + 1) { 463217309Snwhitehorn now_time += ONE_DAY * days_in_month(¤t, 0); 464217309Snwhitehorn } else if (month < current.tm_mon + 1) { 465217309Snwhitehorn now_time -= ONE_DAY * days_in_month(¤t, -1); 466217309Snwhitehorn } else if (day > current.tm_mday) { 467217309Snwhitehorn now_time += ONE_DAY; 468217309Snwhitehorn } else if (day < current.tm_mday) { 469217309Snwhitehorn now_time -= ONE_DAY; 470217309Snwhitehorn } else { 471217309Snwhitehorn break; 472217309Snwhitehorn } 473217309Snwhitehorn current = *localtime(&now_time); 474217309Snwhitehorn } 475217309Snwhitehorn } 476217309Snwhitehorn dlg_button_layout(buttons, &mincols); 477217309Snwhitehorn 478217309Snwhitehorn#ifdef KEY_RESIZE 479217309Snwhitehorn retry: 480217309Snwhitehorn#endif 481217309Snwhitehorn 482217309Snwhitehorn dlg_auto_size(title, prompt, &height, &width, 0, mincols); 483217309Snwhitehorn height += MIN_HIGH - 1; 484217309Snwhitehorn dlg_print_size(height, width); 485217309Snwhitehorn dlg_ctl_size(height, width); 486217309Snwhitehorn 487217309Snwhitehorn dialog = dlg_new_window(height, width, 488217309Snwhitehorn dlg_box_y_ordinate(height), 489217309Snwhitehorn dlg_box_x_ordinate(width)); 490217309Snwhitehorn dlg_register_window(dialog, "calendar", binding); 491217309Snwhitehorn dlg_register_buttons(dialog, "calendar", buttons); 492217309Snwhitehorn 493217309Snwhitehorn /* mainbox */ 494217309Snwhitehorn dlg_draw_box(dialog, 0, 0, height, width, dialog_attr, border_attr); 495217309Snwhitehorn dlg_draw_bottom_box(dialog); 496217309Snwhitehorn dlg_draw_title(dialog, title); 497217309Snwhitehorn 498217309Snwhitehorn wattrset(dialog, dialog_attr); /* text mainbox */ 499217309Snwhitehorn dlg_print_autowrap(dialog, prompt, height, width); 500217309Snwhitehorn 501217309Snwhitehorn /* compute positions of day, month and year boxes */ 502217309Snwhitehorn memset(&dy_box, 0, sizeof(dy_box)); 503217309Snwhitehorn memset(&mn_box, 0, sizeof(mn_box)); 504217309Snwhitehorn memset(&yr_box, 0, sizeof(yr_box)); 505217309Snwhitehorn 506217309Snwhitehorn if (init_object(&dy_box, 507217309Snwhitehorn dialog, 508217309Snwhitehorn (width - DAY_WIDE) / 2, 509217309Snwhitehorn 1 + (height - (DAY_HIGH + BTN_HIGH + (5 * MARGIN))), 510217309Snwhitehorn DAY_WIDE, 511217309Snwhitehorn DAY_HIGH + 1, 512217309Snwhitehorn draw_day, 513217309Snwhitehorn 'D') < 0 514217309Snwhitehorn || DrawObject(&dy_box) < 0) { 515217309Snwhitehorn return CleanupResult(DLG_EXIT_ERROR, dialog, prompt, &save_vars); 516217309Snwhitehorn } 517217309Snwhitehorn 518217309Snwhitehorn if (init_object(&mn_box, 519217309Snwhitehorn dialog, 520217309Snwhitehorn dy_box.x, 521217309Snwhitehorn dy_box.y - (HDR_HIGH + 2 * MARGIN), 522217309Snwhitehorn (DAY_WIDE / 2) - MARGIN, 523217309Snwhitehorn HDR_HIGH, 524217309Snwhitehorn draw_month, 525217309Snwhitehorn 'M') < 0 526217309Snwhitehorn || DrawObject(&mn_box) < 0) { 527217309Snwhitehorn return CleanupResult(DLG_EXIT_ERROR, dialog, prompt, &save_vars); 528217309Snwhitehorn } 529217309Snwhitehorn 530217309Snwhitehorn if (init_object(&yr_box, 531217309Snwhitehorn dialog, 532217309Snwhitehorn dy_box.x + mn_box.width + 2, 533217309Snwhitehorn mn_box.y, 534217309Snwhitehorn mn_box.width, 535217309Snwhitehorn mn_box.height, 536217309Snwhitehorn draw_year, 537217309Snwhitehorn 'Y') < 0 538217309Snwhitehorn || DrawObject(&yr_box) < 0) { 539217309Snwhitehorn return CleanupResult(DLG_EXIT_ERROR, dialog, prompt, &save_vars); 540217309Snwhitehorn } 541217309Snwhitehorn 542217309Snwhitehorn while (result == DLG_EXIT_UNKNOWN) { 543217309Snwhitehorn BOX *obj = (state == sDAY ? &dy_box 544217309Snwhitehorn : (state == sMONTH ? &mn_box : 545217309Snwhitehorn (state == sYEAR ? &yr_box : 0))); 546217309Snwhitehorn 547217309Snwhitehorn button = (state < 0) ? 0 : state; 548217309Snwhitehorn dlg_draw_buttons(dialog, height - 2, 0, buttons, button, FALSE, width); 549217309Snwhitehorn if (obj != 0) 550217309Snwhitehorn dlg_set_focus(dialog, obj->window); 551217309Snwhitehorn 552217309Snwhitehorn key = dlg_mouse_wgetch(dialog, &fkey); 553217309Snwhitehorn if (dlg_result_key(key, fkey, &result)) 554217309Snwhitehorn break; 555217309Snwhitehorn 556217309Snwhitehorn if (fkey && (key >= DLGK_MOUSE(KEY_MIN) && key <= DLGK_MOUSE(KEY_MAX))) { 557217309Snwhitehorn key = dlg_lookup_key(dialog, key - M_EVENT, &fkey); 558217309Snwhitehorn } 559217309Snwhitehorn 560217309Snwhitehorn if ((key2 = dlg_char_to_button(key, buttons)) >= 0) { 561217309Snwhitehorn result = key2; 562217309Snwhitehorn } else if (fkey) { 563217309Snwhitehorn /* handle function-keys */ 564217309Snwhitehorn switch (key) { 565217309Snwhitehorn case DLGK_MOUSE('D'): 566217309Snwhitehorn state = sDAY; 567217309Snwhitehorn break; 568217309Snwhitehorn case DLGK_MOUSE('M'): 569217309Snwhitehorn state = sMONTH; 570217309Snwhitehorn break; 571217309Snwhitehorn case DLGK_MOUSE('Y'): 572217309Snwhitehorn state = sYEAR; 573217309Snwhitehorn break; 574217309Snwhitehorn case DLGK_ENTER: 575224014Snwhitehorn result = dlg_enter_buttoncode(button); 576217309Snwhitehorn break; 577217309Snwhitehorn case DLGK_FIELD_PREV: 578217309Snwhitehorn state = dlg_prev_ok_buttonindex(state, sMONTH); 579217309Snwhitehorn break; 580217309Snwhitehorn case DLGK_FIELD_NEXT: 581217309Snwhitehorn state = dlg_next_ok_buttonindex(state, sMONTH); 582217309Snwhitehorn break; 583217309Snwhitehorn#ifdef KEY_RESIZE 584217309Snwhitehorn case KEY_RESIZE: 585217309Snwhitehorn /* reset data */ 586217309Snwhitehorn height = old_height; 587217309Snwhitehorn width = old_width; 588217309Snwhitehorn /* repaint */ 589217309Snwhitehorn dlg_clear(); 590217309Snwhitehorn dlg_del_window(dialog); 591217309Snwhitehorn refresh(); 592217309Snwhitehorn dlg_mouse_free_regions(); 593217309Snwhitehorn goto retry; 594217309Snwhitehorn#endif 595217309Snwhitehorn default: 596217309Snwhitehorn step = 0; 597217309Snwhitehorn key2 = -1; 598217309Snwhitehorn if (is_DLGK_MOUSE(key)) { 599217309Snwhitehorn if ((key2 = dlg_ok_buttoncode(key - M_EVENT)) >= 0) { 600217309Snwhitehorn result = key2; 601217309Snwhitehorn break; 602217309Snwhitehorn } else if (key >= DLGK_MOUSE(KEY_MAX)) { 603217309Snwhitehorn state = sDAY; 604217309Snwhitehorn obj = &dy_box; 605217309Snwhitehorn key2 = 1; 606217309Snwhitehorn step = (key 607217309Snwhitehorn - DLGK_MOUSE(KEY_MAX) 608217309Snwhitehorn - day_cell_number(¤t)); 609217309Snwhitehorn } 610217309Snwhitehorn } 611217309Snwhitehorn if (obj != 0) { 612217309Snwhitehorn if (key2 < 0) 613217309Snwhitehorn step = next_or_previous(key, (obj == &dy_box)); 614217309Snwhitehorn if (step != 0) { 615217309Snwhitehorn struct tm old = current; 616217309Snwhitehorn 617217309Snwhitehorn /* see comment regarding mktime -TD */ 618217309Snwhitehorn if (obj == &dy_box) { 619217309Snwhitehorn now_time += ONE_DAY * step; 620217309Snwhitehorn } else if (obj == &mn_box) { 621217309Snwhitehorn if (step > 0) 622217309Snwhitehorn now_time += ONE_DAY * 623217309Snwhitehorn days_in_month(¤t, 0); 624217309Snwhitehorn else 625217309Snwhitehorn now_time -= ONE_DAY * 626217309Snwhitehorn days_in_month(¤t, -1); 627217309Snwhitehorn } else if (obj == &yr_box) { 628217309Snwhitehorn if (step > 0) 629217309Snwhitehorn now_time += (ONE_DAY 630217309Snwhitehorn * days_in_year(¤t, 0)); 631217309Snwhitehorn else 632217309Snwhitehorn now_time -= (ONE_DAY 633217309Snwhitehorn * days_in_year(¤t, -1)); 634217309Snwhitehorn } 635217309Snwhitehorn 636217309Snwhitehorn current = *localtime(&now_time); 637217309Snwhitehorn 638217309Snwhitehorn if (obj != &dy_box 639217309Snwhitehorn && (current.tm_mday != old.tm_mday 640217309Snwhitehorn || current.tm_mon != old.tm_mon 641217309Snwhitehorn || current.tm_year != old.tm_year)) 642217309Snwhitehorn DrawObject(&dy_box); 643217309Snwhitehorn if (obj != &mn_box && current.tm_mon != old.tm_mon) 644217309Snwhitehorn DrawObject(&mn_box); 645217309Snwhitehorn if (obj != &yr_box && current.tm_year != old.tm_year) 646217309Snwhitehorn DrawObject(&yr_box); 647217309Snwhitehorn (void) DrawObject(obj); 648217309Snwhitehorn } 649217309Snwhitehorn } else if (state >= 0) { 650217309Snwhitehorn if (next_or_previous(key, FALSE) < 0) 651217309Snwhitehorn state = dlg_prev_ok_buttonindex(state, sMONTH); 652217309Snwhitehorn else if (next_or_previous(key, FALSE) > 0) 653217309Snwhitehorn state = dlg_next_ok_buttonindex(state, sMONTH); 654217309Snwhitehorn } 655217309Snwhitehorn break; 656217309Snwhitehorn } 657217309Snwhitehorn } 658217309Snwhitehorn } 659217309Snwhitehorn 660217309Snwhitehorn#define DefaultFormat(dst, src) \ 661217309Snwhitehorn sprintf(dst, "%02d/%02d/%0d", \ 662217309Snwhitehorn src.tm_mday, src.tm_mon + 1, src.tm_year + 1900) 663217309Snwhitehorn#ifdef HAVE_STRFTIME 664217309Snwhitehorn if (dialog_vars.date_format != 0) { 665220749Snwhitehorn size_t used = strftime(buffer, 666220749Snwhitehorn sizeof(buffer) - 1, 667220749Snwhitehorn dialog_vars.date_format, 668220749Snwhitehorn ¤t); 669217309Snwhitehorn if (used == 0 || *buffer == '\0') 670217309Snwhitehorn DefaultFormat(buffer, current); 671217309Snwhitehorn } else 672217309Snwhitehorn#endif 673217309Snwhitehorn DefaultFormat(buffer, current); 674217309Snwhitehorn 675217309Snwhitehorn dlg_add_result(buffer); 676217309Snwhitehorn dlg_add_separator(); 677217309Snwhitehorn 678217309Snwhitehorn return CleanupResult(result, dialog, prompt, &save_vars); 679217309Snwhitehorn} 680