summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/args.c147
-rw-r--r--src/calcurse.h7
-rw-r--r--src/ui-calendar.c6
3 files changed, 106 insertions, 54 deletions
diff --git a/src/args.c b/src/args.c
index b1bf5ec..d85e099 100644
--- a/src/args.c
+++ b/src/args.c
@@ -44,6 +44,14 @@
#include "calcurse.h"
+/* Input types for parse_datetimearg() */
+enum {
+ ARG_DATE,
+ ARG_DATE_TIME,
+ ARG_TIME,
+ ARG_ERR
+};
+
/* Long options */
enum {
OPT_FILTER_TYPE = 1000,
@@ -277,23 +285,53 @@ date_arg_from_to(long from, long to, int add_line, const char *fmt_apt,
}
/*
- * Convert a string with a date into the Unix time for midnight of that day.
+ * Convert a string with a (local time) date, date-time or time into
+ * the Unix time for that point in time as follows:
+ * - a date only is converted to midnight (beginning) of that day
+ * - a date-time is converted to that day and time
+ * - a time only is converted to that time of the current day
* The date format is taken from the user configuration.
+ * The type of the input string is returned in the type argument.
*/
-static time_t parse_datearg(const char *str)
+
+static time_t parse_datetimearg(const char *str, int *type)
{
+ char *date = mem_strdup(str);
+ *type = ARG_ERR;
+ char *time;
struct date day;
-
- if (parse_date(str, conf.input_datefmt,
- (int *)&day.yyyy, (int *)&day.mm, (int *)&day.dd, NULL))
- return date2sec(day, 0, 0);
- else
+ unsigned hour, min;
+ time_t ret;
+
+ time = strchr(date, ' ');
+ if (time) { /* Date and time? */
+ *time++ = '\0';
+ if (!parse_time(time, &hour, &min))
+ return -1;
+ if (!parse_date(date, conf.input_datefmt,
+ (int *)&day.yyyy, (int *)&day.mm, (int *)&day.dd, NULL))
+ return -1;
+ ret = date2sec(day, hour, min);
+ *type = ARG_DATE_TIME;
+ } else /* Date?*/ if (parse_date(date, conf.input_datefmt,
+ (int *)&day.yyyy, (int *)&day.mm, (int *)&day.dd, NULL)) {
+ ret = date2sec(day, 0, 0);
+ *type = ARG_DATE;
+ } else /* Time? */ if (parse_time(date, &hour, &min)) {
+ ret = date2sec(*ui_calendar_get_today(), hour, min);
+ *type = ARG_TIME;
+ } else
return -1;
+ return ret;
}
+/*
+ * Parse a "from,to" date range.
+ * For an open-end range no change occurs at the open end.
+ */
static int parse_daterange(const char *str, time_t *date_from, time_t *date_to)
{
- int ret = 0;
+ int type, ret = 0;
char *s = mem_strdup(str);
char *p = strchr(s, ',');
@@ -304,21 +342,17 @@ static int parse_daterange(const char *str, time_t *date_from, time_t *date_to)
p++;
if (*s != '\0') {
- *date_from = parse_datearg(s);
+ *date_from = parse_datetimearg(s, &type);
if (*date_from == -1)
goto cleanup;
- } else {
- *date_from = -1;
}
if (*p != '\0') {
- *date_to = parse_datearg(p);
+ *date_to = parse_datetimearg(p, &type);
if (*date_to == -1)
goto cleanup;
- /* One second before next midnight. */
- *date_to = date_sec_change(*date_to, 0, 1) - 1;
- } else {
- *date_to = -1;
+ if (type == ARG_DATE)
+ *date_to = ENDOFDAY(*date_to);
}
ret = 1;
@@ -390,7 +424,7 @@ int parse_args(int argc, char **argv)
const char *cfile = NULL, *ifile = NULL, *confdir = NULL;
int non_interactive = 1;
- int ch, cpid;
+ int ch, cpid, type;
regex_t reg;
char buf[BUFSIZ];
struct tm tm;
@@ -497,9 +531,9 @@ int parse_args(int argc, char **argv)
EXIT_IF(range == 0, _("invalid range: %s"),
optarg);
} else {
- from = parse_datearg(optarg);
- EXIT_IF(from == -1, _("invalid date: %s"),
- optarg);
+ from = parse_datetimearg(optarg, &type);
+ EXIT_IF(from == -1 || type != ARG_DATE,
+ _("invalid date: %s"), optarg);
}
filter.type_mask |= TYPE_MASK_CAL;
@@ -544,8 +578,9 @@ int parse_args(int argc, char **argv)
case 's':
if (!optarg)
optarg = "today";
- from = parse_datearg(optarg);
- EXIT_IF(from == -1, _("invalid date: %s"), optarg);
+ from = parse_datetimearg(optarg, &type);
+ EXIT_IF(from == -1 || type != ARG_DATE,
+ _("invalid date: %s"), optarg);
filter.type_mask |= TYPE_MASK_CAL;
query = 1;
break;
@@ -606,78 +641,84 @@ int parse_args(int argc, char **argv)
filter.regex = ®
filter_opt = 1;
break;
- /* Assume that the date argument is midnight of the given day. */
+ /*
+ * A date only is a time span (a day) and interpreted thus:
+ * "to" means "to end of day"
+ * "after" means "from start of next day"
+ */
case OPT_FILTER_START_FROM:
- /* Midnight. */
- filter.start_from = parse_datearg(optarg);
+ filter.start_from = parse_datetimearg(optarg, &type);
EXIT_IF(filter.start_from == -1,
_("invalid date: %s"), optarg);
filter_opt = 1;
break;
case OPT_FILTER_START_TO:
- filter.start_to = parse_datearg(optarg);
+ filter.start_to = parse_datetimearg(optarg, &type);
EXIT_IF(filter.start_to == -1,
_("invalid date: %s"), optarg);
- /* Next midnight less one second. */
- filter.start_to = date_sec_change(filter.start_to, 0, 1) - 1;
+ if (type == ARG_DATE)
+ filter.start_to = ENDOFDAY(filter.start_to);
filter_opt = 1;
break;
case OPT_FILTER_START_AFTER:
- filter.start_from = parse_datearg(optarg);
+ filter.start_from = parse_datetimearg(optarg, &type);
EXIT_IF(filter.start_from == -1,
_("invalid date: %s"), optarg);
- /* Next midnight (belongs to the next day). */
- filter.start_from = date_sec_change(filter.start_from, 0, 1);
+ if (type == ARG_DATE)
+ filter.start_from = NEXTDAY(filter.start_from);
+ else
+ filter.start_from++;
filter_opt = 1;
break;
case OPT_FILTER_START_BEFORE:
- filter.start_to = parse_datearg(optarg);
+ filter.start_to = parse_datetimearg(optarg, &type);
EXIT_IF(filter.start_to == -1,
_("invalid date: %s"), optarg);
- /* One second before midnight. */
filter.start_to--;
filter_opt = 1;
break;
case OPT_FILTER_START_RANGE:
- EXIT_IF(!parse_daterange(optarg, &filter.start_from,
- &filter.start_to),
+ /* Set initialization values in case of open-end range. */
+ filter.start_from = filter.start_to = -1;
+ EXIT_IF(!parse_daterange(optarg, &filter.start_from, &filter.start_to),
_("invalid date range: %s"), optarg);
filter_opt = 1;
break;
case OPT_FILTER_END_FROM:
- /* Midnight. */
- filter.end_from = parse_datearg(optarg);
+ filter.end_from = parse_datetimearg(optarg, &type);
EXIT_IF(filter.end_from == -1,
_("invalid date: %s"), optarg);
filter_opt = 1;
break;
case OPT_FILTER_END_TO:
- filter.end_to = parse_datearg(optarg);
+ filter.end_to = parse_datetimearg(optarg, &type);
EXIT_IF(filter.end_to == -1,
_("invalid date: %s"), optarg);
- /* Next midnight less one second. */
- filter.end_to = date_sec_change(filter.end_to, 0, 1) - 1;
+ if (type == ARG_DATE)
+ filter.end_to = ENDOFDAY(filter.end_to);
filter_opt = 1;
break;
case OPT_FILTER_END_AFTER:
- filter.end_from = parse_datearg(optarg);
+ filter.end_from = parse_datetimearg(optarg, &type);
EXIT_IF(filter.end_from == -1,
_("invalid date: %s"), optarg);
- /* Next midnight (belongs to the next day). */
- filter.end_from = date_sec_change(filter.end_from, 0, 1);
+ if (type == ARG_DATE)
+ filter.end_from = NEXTDAY(filter.end_from);
+ else
+ filter.end_from++;
filter_opt = 1;
break;
case OPT_FILTER_END_BEFORE:
- filter.end_to = parse_datearg(optarg);
+ filter.end_to = parse_datetimearg(optarg, &type);
EXIT_IF(filter.end_to == -1,
_("invalid date: %s"), optarg);
- /* One second before midnight. */
filter.end_to--;
filter_opt = 1;
break;
case OPT_FILTER_END_RANGE:
- EXIT_IF(!parse_daterange(optarg, &filter.end_from,
- &filter.end_to),
+ /* Set default values in case of open-ended range. */
+ filter.start_from = filter.start_to = -1;
+ EXIT_IF(!parse_daterange(optarg, &filter.end_from, &filter.end_to),
_("invalid date range: %s"), optarg);
filter_opt = 1;
break;
@@ -696,13 +737,15 @@ int parse_args(int argc, char **argv)
filter_opt = 1;
break;
case OPT_FROM:
- from = parse_datearg(optarg);
- EXIT_IF(from == -1, _("invalid date: %s"), optarg);
+ from = parse_datetimearg(optarg, &type);
+ EXIT_IF(from == -1 || type != ARG_DATE,
+ _("invalid date: %s"), optarg);
query_range = 1;
break;
case OPT_TO:
- to = parse_datearg(optarg);
- EXIT_IF(to == -1, _("invalid date: %s"), optarg);
+ to = parse_datetimearg(optarg, &type);
+ EXIT_IF(to == -1 || type != ARG_DATE,
+ _("invalid date: %s"), optarg);
query_range = 1;
break;
case OPT_DAYS:
@@ -790,7 +833,7 @@ int parse_args(int argc, char **argv)
if (from == -1)
from = get_today();
if (to == -1)
- to = from;
+ to = ENDOFDAY(from);
EXIT_IF(to < from, _("end date cannot come before start date"));
if (range > 0)
to = date_sec_change(from, 0, range - 1);
diff --git a/src/calcurse.h b/src/calcurse.h
index 8626393..c6ddc8d 100644
--- a/src/calcurse.h
+++ b/src/calcurse.h
@@ -137,10 +137,12 @@
/*
* Note the difference between the number of seconds in a day and daylength
* in seconds. The two may differ when DST is in effect (daylength is either
- * 23, 24 or 25 hours. The argument to DAYLEN is of type time_t.
+ * 23, 24 or 25 hours. The argument "date" is assumed to be of type time_t.
*/
#define DAYINSEC (DAYINMIN * MININSEC)
-#define DAYLEN(date) (date_sec_change((date), 0, 1) - (date))
+#define NEXTDAY(date) date_sec_change((date), 0, 1)
+#define DAYLEN(date) (NEXTDAY(date) - (date))
+#define ENDOFDAY(date) (NEXTDAY(date) - 1)
#define HOURINSEC (HOURINMIN * MININSEC)
#define MAXDAYSPERMONTH 31
@@ -760,6 +762,7 @@ int ui_calendar_get_view(void);
void ui_calendar_start_date_thread(void);
void ui_calendar_stop_date_thread(void);
void ui_calendar_set_current_date(void);
+struct date *ui_calendar_get_today(void);
void ui_calendar_set_first_day_of_week(enum wday);
void ui_calendar_change_first_day_of_week(void);
unsigned ui_calendar_week_begins_on_monday(void);
diff --git a/src/ui-calendar.c b/src/ui-calendar.c
index a668efb..407f294 100644
--- a/src/ui-calendar.c
+++ b/src/ui-calendar.c
@@ -144,6 +144,12 @@ void ui_calendar_set_current_date(void)
pthread_mutex_unlock(&date_thread_mutex);
}
+/* Return the current date. */
+struct date *ui_calendar_get_today(void)
+{
+ return &today;
+}
+
/* Needed to display sunday or monday as the first day of week in calendar. */
void ui_calendar_set_first_day_of_week(enum wday first_day)
{