From adf29c8ee9a5fd4f224dd52f4399bf4550a3039a Mon Sep 17 00:00:00 2001
From: Lukas Fleischer <lfleischer@calcurse.org>
Date: Sun, 9 Oct 2016 20:19:15 +0200
Subject: Support dates when specifying start/end times

Add support for combined date/time or date-only strings when specifying
the start or end time of a new item.

This is a follow-up to 1f39b5c (Add support for moving items to another
day, 2016-09-30).

Signed-off-by: Lukas Fleischer <lfleischer@calcurse.org>
---
 src/ui-day.c | 57 +++++++++++++++++++++++++++------------------------------
 src/utils.c  |  8 ++++++--
 2 files changed, 33 insertions(+), 32 deletions(-)

(limited to 'src')

diff --git a/src/ui-day.c b/src/ui-day.c
index 0c31b3c..8f78082 100644
--- a/src/ui-day.c
+++ b/src/ui-day.c
@@ -89,7 +89,7 @@ static int day_edit_duration(int start, int dur, unsigned *new_duration)
 	const char *enter_str = _("Press [Enter] to continue");
 	const char *fmt_msg =
 	    _("You entered an invalid time, should be [hh:mm] or [hhmm]");
-	long newtime;
+	long newtime = start + dur;
 	unsigned hr, mn;
 
 	for (;;) {
@@ -113,6 +113,9 @@ static int day_edit_duration(int start, int dur, unsigned *new_duration)
 			     start) ? newtime - start : DAYINSEC +
 			    newtime - start;
 			break;
+		} else if (parse_datetime(timestr, &newtime)) {
+			*new_duration = newtime - start;
+			break;
 		} else {
 			status_mesg(fmt_msg, enter_str);
 			wgetch(win[KEY].p);
@@ -500,7 +503,7 @@ void ui_day_item_pipe(void)
  */
 void ui_day_item_add(void)
 {
-#define LTIME 6
+#define LTIME 16
 #define LDUR 12
 	const char *mesg_1 =
 	    _("Enter start time ([hh:mm] or [hhmm]), leave blank for an all-day event:");
@@ -514,11 +517,11 @@ void ui_day_item_add(void)
 	const char *enter_str = _("Press [Enter] to continue");
 	char item_time[LDUR] = "";
 	char item_mesg[BUFSIZ] = "";
-	time_t apoint_start;
-	unsigned heures, minutes;
+	time_t start = date2sec(*ui_calendar_get_slctd_day(), 0, 0), end;
 	unsigned apoint_duration;
 	unsigned end_h, end_m;
 	int is_appointment = 1;
+	int ret;
 	union aptev_ptr item;
 
 	/* Get the starting time */
@@ -531,7 +534,10 @@ void ui_day_item_add(void)
 			is_appointment = 0;
 			break;
 		}
-		if (parse_time(item_time, &heures, &minutes) == 1)
+		ret = parse_datetime(item_time, &start);
+		if (!(ret & 2))
+			is_appointment = 0;
+		if (ret)
 			break;
 		status_mesg(format_message_1, enter_str);
 		wgetch(win[KEY].p);
@@ -553,46 +559,37 @@ void ui_day_item_add(void)
 				apoint_duration = 0;
 				break;
 			}
-			if (*item_time == '+'
-			    && parse_duration(item_time + 1,
-					      &apoint_duration) == 1)
+			if (*item_time == '+' && parse_duration(item_time + 1,
+						&apoint_duration) == 1) {
+				apoint_duration *= MININSEC;
 				break;
+			}
 			if (parse_time(item_time, &end_h, &end_m) == 1) {
-				if (end_h < heures
-				    || ((end_h == heures)
-					&& (end_m < minutes))) {
-					apoint_duration =
-					    MININSEC - minutes + end_m +
-					    (24 + end_h -
-					     (heures + 1)) * MININSEC;
-				} else {
-					apoint_duration =
-					    MININSEC - minutes + end_m +
-					    (end_h -
-					     (heures + 1)) * MININSEC;
-				}
+				end = update_time_in_date(start, end_h, end_m);
+				apoint_duration = (end > start) ? end - start :
+					DAYINSEC + end - start;
+				break;
+			}
+			end = start;
+			if (parse_datetime(item_time, &end)) {
+				apoint_duration = end - start;
 				break;
 			}
 			status_mesg(format_message_2, enter_str);
 			wgetch(win[KEY].p);
 		}
-	} else {
-		heures = minutes = 0;
 	}
 
 	status_mesg(mesg_3, "");
 	if (getstring(win[STA].p, item_mesg, BUFSIZ, 0, 1) ==
 	    GETSTRING_VALID) {
-		apoint_start = date2sec(*ui_calendar_get_slctd_day(), heures,
-					minutes);
 		if (is_appointment) {
-			item.apt = apoint_new(item_mesg, 0L, apoint_start,
-					      min2sec(apoint_duration), 0L);
+			item.apt = apoint_new(item_mesg, 0L, start,
+					      apoint_duration, 0L);
 			if (notify_bar())
-				notify_check_added(item_mesg, apoint_start,
-						   0L);
+				notify_check_added(item_mesg, start, 0L);
 		} else {
-			item.ev = event_new(item_mesg, 0L, apoint_start, 1);
+			item.ev = event_new(item_mesg, 0L, start, 1);
 		}
 		io_set_modified();
 		day_process_storage(ui_calendar_get_slctd_day(), 0);
diff --git a/src/utils.c b/src/utils.c
index 335f325..9727c74 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -1112,7 +1112,8 @@ int parse_duration(const char *string, unsigned *duration)
  * updated and the date remains the same. If the string contains both a date
  * and a time, the time stamp is updated to match the given string.
  *
- * Returns 1 on success and 0 on failure.
+ * Returns a positive value on success and 0 on failure. The least-significant
+ * bit is set if the date was updated. Bit 1 is set if the time was updated.
  */
 int parse_datetime(const char *string, long *ts)
 {
@@ -1122,6 +1123,7 @@ int parse_datetime(const char *string, long *ts)
 	unsigned int hour, minute;
 	int year, month, day;
 	struct date new_date;
+	int ret = 0;
 
 	while (p) {
 		if (parse_date(p, conf.input_datefmt, &year, &month, &day,
@@ -1130,8 +1132,10 @@ int parse_datetime(const char *string, long *ts)
 			new_date.mm = month;
 			new_date.yyyy = year;
 			*ts = date2sec(new_date, 0, 0) + get_item_time(*ts);
+			ret |= 1;
 		} else if (parse_time(p, &hour, &minute) == 1) {
 			*ts = update_time_in_date(*ts, hour, minute);
+			ret |= 2;
 		} else {
 			return 0;
 		}
@@ -1139,7 +1143,7 @@ int parse_datetime(const char *string, long *ts)
 	}
 
 	mem_free(t);
-	return 1;
+	return ret;
 }
 
 void file_close(FILE * f, const char *pos)
-- 
cgit v1.2.3-70-g09d2