From c8af480f52b46e556d23ef012f3987aa3a0fc25b Mon Sep 17 00:00:00 2001 From: Lukas Fleischer Date: Tue, 11 Jan 2011 22:10:48 +0000 Subject: Make parse_date accept several short forms. Short forms are only accepted in interactive mode (e.g. when using the "Go to" function, editing a recurrent item's end date, and so on). Samples: "1/1/30" for "01/01/2030", "26" for the 26th of the currently selected month/year or "3/1" for Mar 01 (or Jan 03, depending on the date format) of the currently selected year. --- ChangeLog | 14 ++++++++ src/args.c | 6 ++-- src/calcurse.h | 5 +-- src/calendar.c | 9 ++--- src/day.c | 4 +-- src/recur.c | 4 +-- src/utils.c | 101 ++++++++++++++++++++++++++++++++++----------------------- 7 files changed, 87 insertions(+), 56 deletions(-) diff --git a/ChangeLog b/ChangeLog index de62c30..e506a95 100755 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +2011-01-11 Lukas Fleischer + + * src/calcurse.h + * src/utils.c: Make parse_date accept several short forms, e.g. + "1/1/30" for "01/01/2030", "26" for the 26th of the currently + selected month/year or "3/1" for Mar 01 (or Jan 03, depending + on the date format) of the currently selected year. + + * src/args.c + * src/calendar.c + * src/day.c + * src/recur.c: Make everything work with the new parse_date + function accepting short forms. + 2010-11-04 Lukas Fleischer * src/utils.c: Added "backword-kill-word" functionality to diff --git a/src/args.c b/src/args.c index 1f4bd0e..f2c3361 100755 --- a/src/args.c +++ b/src/args.c @@ -1,4 +1,4 @@ -/* $calcurse: args.c,v 1.63 2010/05/26 18:18:28 culot Exp $ */ +/* $calcurse: args.c,v 1.64 2011/01/11 22:10:48 fleischer Exp $ */ /* * Calcurse - text-based organizer @@ -578,7 +578,7 @@ date_arg (char *ddate, int add_line, int print_note, struct conf *conf, else { /* a date was entered */ if (parse_date (ddate, conf->input_datefmt, (int *)&day.yyyy, - (int *)&day.mm, (int *)&day.dd)) + (int *)&day.mm, (int *)&day.dd, NULL)) { app_found = app_arg (add_line, &day, 0, print_note, conf, regex); } @@ -630,7 +630,7 @@ date_arg_extended (char *startday, char *range, int add_line, int print_note, if (startday != NULL) { if (parse_date (startday, conf->input_datefmt, (int *)&t.tm_year, - (int *)&t.tm_mon, (int *)&t.tm_mday)) + (int *)&t.tm_mon, (int *)&t.tm_mday, NULL)) { t.tm_year -= 1900; t.tm_mon--; diff --git a/src/calcurse.h b/src/calcurse.h index b6e233c..f301b2e 100644 --- a/src/calcurse.h +++ b/src/calcurse.h @@ -1,4 +1,4 @@ -/* $Id: calcurse.h,v 1.5 2010/03/22 08:16:33 culot Exp $ */ +/* $Id: calcurse.h,v 1.6 2011/01/11 22:10:48 fleischer Exp $ */ /* * Calcurse - text-based organizer @@ -873,7 +873,8 @@ long mystrtol (const char *); void print_bool_option_incolor (WINDOW *, unsigned, int, int); char *new_tempfile (const char *, int); void erase_note (char **, enum eraseflg); -int parse_date (char *, enum datefmt, int *, int *, int *); +int parse_date (char *, enum datefmt, int *, int *, int *, + struct date *); char *str_toupper (char *); void file_close (FILE *, const char *); void psleep (unsigned); diff --git a/src/calendar.c b/src/calendar.c index 085a239..c5aeae8 100755 --- a/src/calendar.c +++ b/src/calendar.c @@ -1,4 +1,4 @@ -/* $calcurse: calendar.c,v 1.38 2010/10/23 10:19:47 culot Exp $ */ +/* $calcurse: calendar.c,v 1.39 2011/01/11 22:10:48 fleischer Exp $ */ /* * Calcurse - text-based organizer @@ -646,11 +646,8 @@ calendar_change_day (int datefmt) wrong_day = 0; calendar_goto_today (); } - else if (strlen (selected_day) != LDAY - 1) - { - wrong_day = 1; - } - else if (parse_date (selected_day, datefmt, &dyear, &dmonth, &dday)) + else if (parse_date (selected_day, datefmt, &dyear, &dmonth, &dday, + calendar_get_slctd_day ())) { wrong_day = 0; /* go to chosen day */ diff --git a/src/day.c b/src/day.c index 4bcb5ec..17c2a31 100755 --- a/src/day.c +++ b/src/day.c @@ -1,4 +1,4 @@ -/* $calcurse: day.c,v 1.53 2010/03/20 10:54:44 culot Exp $ */ +/* $calcurse: day.c,v 1.54 2011/01/11 22:10:48 fleischer Exp $ */ /* * Calcurse - text-based organizer @@ -757,7 +757,7 @@ update_rept (struct rpt **rpt, const long start, struct conf *conf) int newmonth, newday, newyear; if (parse_date (timstr, conf->input_datefmt, - &newyear, &newmonth, &newday)) + &newyear, &newmonth, &newday, calendar_get_slctd_day ())) { t = start; lt = localtime (&t); diff --git a/src/recur.c b/src/recur.c index 34910a4..096c961 100755 --- a/src/recur.c +++ b/src/recur.c @@ -1,4 +1,4 @@ -/* $calcurse: recur.c,v 1.54 2010/03/20 10:54:47 culot Exp $ */ +/* $calcurse: recur.c,v 1.55 2011/01/11 22:10:48 fleischer Exp $ */ /* * Calcurse - text-based organizer @@ -971,7 +971,7 @@ recur_repeat_item (struct conf *conf) else { if (parse_date (user_input, conf->input_datefmt, - &year, &month, &day)) + &year, &month, &day, calendar_get_slctd_day ())) { t = p->start; lt = localtime (&t); diff --git a/src/utils.c b/src/utils.c index 243de4c..63f3320 100755 --- a/src/utils.c +++ b/src/utils.c @@ -1,4 +1,4 @@ -/* $calcurse: utils.c,v 1.86 2010/11/04 10:55:07 fleischer Exp $ */ +/* $calcurse: utils.c,v 1.87 2011/01/11 22:10:48 fleischer Exp $ */ /* * Calcurse - text-based organizer @@ -47,6 +47,8 @@ #include "calcurse.h" +#define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0) + /* General routine to exit calcurse properly. */ void exit_calcurse (int status) @@ -883,64 +885,81 @@ erase_note (char **note, enum eraseflg flag) /* * Convert a string containing a date into three integers containing the year, * month and day. + * + * If a pointer to a date structure containing the current date is passed as + * last parameter ("slctd_date"), the function will accept several short forms, + * e.g. "26" for the 26th of the current month/year or "3/1" for Mar 01 (or Jan + * 03, depending on the date format) of the current year. If a null pointer is + * passed, short forms won't be accepted at all. + * * Returns 1 if sucessfully converted or 0 if the string is an invalid date. */ int parse_date (char *date_string, enum datefmt datefmt, int *year, int *month, - int *day) + int *day, struct date *slctd_date) { - int in1, in2, in3; - int lyear, lmonth, lday; + char sep = (datefmt == DATEFMT_ISO) ? '-' : '/'; + char *p; + int in[3] = {0, 0, 0}, n = 0; + int d, m, y; - if (date_string == 0) - return 0; + if (!date_string) return 0; - if (datefmt == DATEFMT_ISO) - { - if (sscanf (date_string, "%d - %d - %d", &in1, &in2, &in3) < 3) - return 0; + /* parse string into in[], read up to three integers */ + for (p = date_string; *p; p++) { + if (*p == sep) { + if ((++n) > 2) return 0; } - else - { - if (sscanf (date_string, "%d / %d / %d", &in1, &in2, &in3) < 3) - return 0; + else if ((*p >= '0') && (*p <= '9')) { + in[n] = in[n] * 10 + (int)(*p - '0'); } - switch (datefmt) - { + else + return 0; + } + + if ((!slctd_date && n < 2) || in[n] == 0) return 0; + + /* convert into day, month and year, depending on the date format */ + switch (datefmt) { case DATEFMT_MMDDYYYY: - lmonth = in1; - lday = in2; - lyear = in3; + m = in[n > 0 ? 0 : 1]; + d = in[n > 0 ? 1 : 0]; + y = in[2]; break; case DATEFMT_DDMMYYYY: - lday = in1; - lmonth = in2; - lyear = in3; + d = in[0]; + m = in[1]; + y = in[2]; break; case DATEFMT_YYYYMMDD: - case DATEFMT_ISO: - lyear = in1; - lmonth = in2; - lday = in3; + case DATEFMT_ISO: + y = in[0]; + m = in[n - 1]; + d = in[n]; break; default: return 0; - } - - if (lyear < 1 || lyear > 9999 - || lmonth < 1 || lmonth > 12 - || lday < 1 || lday > 31) + } + + if (y > 0 && y < 100) { + /* convert "YY" format into "YYYY" */ + y += slctd_date->yyyy - slctd_date->yyyy % 100; + } + else if (n < 2) { + /* set year and, optionally, month if short from is used */ + y = slctd_date->yyyy; + if (n < 1) m = slctd_date->mm; + } + + /* check if date is valid, take leap years into account */ + if (y < 1902 || y > 2037 || m < 1 || m > 12 || d < 1 || + d > days[m - 1] + (m == 2 && isleap (y)) ? 1 : 0) return 0; - - if (year != NULL) - *year = lyear; - - if (month != NULL) - *month = lmonth; - - if (day != NULL) - *day = lday; - + + if (year) *year = y; + if (month) *month = m; + if (day) *day = d; + return 1; } -- cgit v1.2.3-70-g09d2