From 34712e643c1fb47216d035e2703aacf64003d4fe Mon Sep 17 00:00:00 2001 From: Felicity Tarnell Date: Sat, 8 Mar 2014 12:18:22 +0000 Subject: [PATCH] New time format: "1h30m7s". This is fairly flexible, so you could say 10s1h, or even 1h1h1h (which is equivalent to 3h). Time parsing is now implemented by a single function, so there should be no inconsistencies. The old [[HH:]MM:]SS syntax is still supported, but not used in prompts. --- Makefile.in | 2 +- functions.c | 111 ++++++++-------------------------------------------- str.c | 78 ++++++++++++++++++++++++++++++++++++ str.h | 6 ++- ui.c | 49 +++++++++-------------- ui.h | 2 +- 6 files changed, 119 insertions(+), 129 deletions(-) diff --git a/Makefile.in b/Makefile.in index f407378..1324e86 100644 --- a/Makefile.in +++ b/Makefile.in @@ -12,7 +12,7 @@ VPATH = @top_srcdir@ CC = @CC@ MAKEDEPEND = @CC@ -M -CPPFLAGS = @CPPFLAGS@ -D_XOPEN_SOURCE=700 -D_XOPEN_SOURCE_EXTENDED +CPPFLAGS = @CPPFLAGS@ -D_XOPEN_SOURCE_EXTENDED CFLAGS = @CFLAGS@ -I@top_srcdir@ -I@top_builddir@ LDFLAGS = @LDFLAGS@ LIBS = @LIBS@ diff --git a/functions.c b/functions.c index d91f9e3..2ee9194 100644 --- a/functions.c +++ b/functions.c @@ -332,9 +332,7 @@ wchar_t *new; void kedtime() { -wchar_t *new, old[64]; time_t n; -int h, m, s; if (!curent) { drawstatus(L"No entry selected."); @@ -344,22 +342,13 @@ int h, m, s; n = curent->en_secs; if (curent->en_started) n += time(NULL) - curent->en_started; - h = n / (60 * 60); - n %= (60 * 60); - m = n / 60; - n %= 60; - s = n; - swprintf(old, wsizeof(old), L"%02d:%02d:%02d", h, m, s); - if ((new = prompt(L"Duration [HH:MM:SS]:", old, NULL)) == NULL) - return; - - if (!swscanf(new, L"%d:%d:%d", &h, &m, &s)) { - free(new); + if ((n = prduration(L"Duration:", n)) == (time_t) -1) { drawstatus(L"Invalid duration."); + return; } - curent->en_secs = (h * 60 * 60) + (m * 60) + s; + curent->en_secs = n; if (curent->en_started) time(&curent->en_started); @@ -421,47 +410,17 @@ entry_t *en; void kaddtime() { -wchar_t *tstr; -int h = 0, m = 0, s = 0, secs; +time_t secs; if (!curent) { drawstatus(L"No entry selected."); return; } - if ((tstr = prompt(L"Time to add ([[HH:]MM:]SS):", NULL, NULL)) == NULL) - return; - - if (!*tstr) { - drawstatus(L""); - free(tstr); + if ((secs = prduration(L"Time to add:", 0)) == (time_t) -1) { + drawstatus(L"Invalid time format."); return; } - if (swscanf(tstr, L"%d:%d:%d", &h, &m, &s) != 3) { - h = 0; - if (swscanf(tstr, L"%d:%d", &m, &s) != 2) { - m = 0; - if (swscanf(tstr, L"%d", &s) != 1) { - free(tstr); - drawstatus(L"Invalid time format."); - return; - } - } - } - - free(tstr); - - if (m >= 60) { - drawstatus(L"Minutes cannot be more than 59."); - return; - } - - if (s >= 60) { - drawstatus(L"Seconds cannot be more than 59."); - return; - } - - secs = s + m*60 + h*60*60; curent->en_secs += secs; save(); } @@ -469,48 +428,19 @@ int h = 0, m = 0, s = 0, secs; void kdeltime() { -wchar_t *tstr; -int h = 0, m = 0, s = 0, secs; +time_t secs; if (!curent) { drawstatus(L"No entry selected."); return; } - if ((tstr = prompt(L"Time to subtract, ([[HH:]MM:]SS):", NULL, NULL)) == NULL) - return; - - if (!*tstr) { - drawstatus(L""); - free(tstr); - return; - } - - if (swscanf(tstr, L"%d:%d:%d", &h, &m, &s) != 3) { - h = 0; - if (swscanf(tstr, L"%d:%d", &m, &s) != 2) { - m = 0; - if (swscanf(tstr, L"%d", &s) != 1) { - free(tstr); - drawstatus(L"Invalid time format."); - return; - } - } - } - - free(tstr); - if (m >= 60) { - drawstatus(L"Minutes cannot be more than 59."); - return; - } - - if (s >= 60) { - drawstatus(L"Seconds cannot be more than 59."); + if ((secs = prduration(L"Time to subtract:", 0)) == (time_t) -1) { + drawstatus(L"Invalid time format."); return; } entry_account(curent); - secs = s + m*60 + h*60*60; if (curent->en_secs - secs < 0) { drawstatus(L"Remaining time cannot be less than zero."); return; @@ -526,7 +456,8 @@ kmerge() entry_t *en, *ten; int nmarked = 0; wchar_t pr[128]; -int h, m, s = 0; +wchar_t *ct; +int s = 0; if (!curent) { drawstatus(L"No entry selected."); @@ -550,13 +481,11 @@ int h, m, s = 0; return; } - h = s / (60 * 60); - s %= (60 * 60); - m = s / 60; - s %= 60; + ct = maketime(s); + swprintf(pr, wsizeof(pr), L"Merge %d marked entries [%ls] into current entry?", + nmarked, ct); + free(ct); - swprintf(pr, wsizeof(pr), L"Merge %d marked entries [%02d:%02d:%02d] into current entry?", - nmarked, h, m, s); if (!yesno(pr)) return; @@ -699,15 +628,7 @@ wchar_t *name; return; } - if (itime) { - duration = time(NULL) - itime; - } else { - int h, m, s; - if (prduration(L"Duration [HH:MM:SS]:", &h, &m, &s) == -1) - return; - - duration = (h * 60 * 60) + (m * 60) + s; - } + duration = time(NULL) - itime; itime = 0; running->en_secs += (time(NULL) - running->en_started); diff --git a/str.c b/str.c index 9082c4f..98c29ff 100644 --- a/str.c +++ b/str.c @@ -133,3 +133,81 @@ wchar_t **p; free(*vec); } +time_t +parsetime(tm) + wchar_t *tm; +{ +int h = 0, m = 0, s = 0; +time_t i = 0, r = 0; + +/* The empty string is not a valid duration */ + if (!*tm) + return (time_t) -1; +/* Check for "hh:mm:ss" or "mm:ss" */ + if (swscanf(tm, L"%d:%d:%d", &h, &m, &s) == 3) + return (h * 60 * 60) + (m * 60) + s; + + if (swscanf(tm, L"%d:%d", &m, &s) == 2) + return (m * 60) + s; + +/* + * The string could either be a format like 3h10m, or a simle number like 47 + * (meaning seconds), which is also handled here. This is effectively an + * implementation of atoi with special meaning for 'h', 'm' and 's' characters. + * + * Note that we make no attempt to handle overflow. + */ + for (; *tm; tm++) { + switch (*tm) { + case L'h': + r += i * (60 * 60); + i = 0; + continue; + + case L'm': + r += i * 60; + i = 0; + continue; + + case L's': + r += i; + i = 0; + continue; + } + + if (wcschr(L"0123456789", *tm) == NULL) + return (time_t) -1; + + i *= 10; + i += *tm - L'0'; + } + + return r + i; +} + +wchar_t * +maketime(tm) + time_t tm; +{ +wchar_t res[64] = {}; +wchar_t t[16]; + + if (tm >= (60 * 60)) { + swprintf(t, wsizeof(t), L"%dh", tm / (60 * 60)); + wcslcat(res, t, sizeof(res)); + tm %= (60 * 60); + } + + if (tm >= 60) { + swprintf(t, wsizeof(t), L"%dm", tm / 60); + wcslcat(res, t, sizeof(res)); + tm %= 60; + } + + if (tm) { + swprintf(t, wsizeof(t), L"%ds", tm); + wcslcat(res, t, sizeof(res)); + } + + return wcsdup(res); +} diff --git a/str.h b/str.h index c0823b0..857d03f 100644 --- a/str.h +++ b/str.h @@ -15,7 +15,9 @@ #include "wide.h" -size_t tokenise(const wchar_t *, wchar_t ***result); -void tokfree(wchar_t ***); +size_t tokenise (const wchar_t *, wchar_t ***result); +void tokfree (wchar_t ***); +time_t parsetime (wchar_t *); +wchar_t *maketime (time_t); #endif /* !TTS_STR_H */ diff --git a/ui.c b/ui.c index 99181f5..7b51771 100644 --- a/ui.c +++ b/ui.c @@ -14,6 +14,7 @@ #include "ui.h" #include "tts.h" #include "style.h" +#include "str.h" WINDOW *titwin, *statwin, *listwin; int in_curses; @@ -601,15 +602,23 @@ chtype oldbg; wbkgdset(listwin, oldbg); } -int -prduration(pr, hh, mm, ss) +time_t +prduration(pr, def) wchar_t *pr; - int *hh, *mm, *ss; + time_t def; { +wchar_t *defstr = NULL; wchar_t *tstr; -int h, m, s; - if ((tstr = prompt(pr, L"00:00:00", NULL)) == NULL) +time_t ret; + + defstr = maketime(def); + + if ((tstr = prompt(pr, defstr, NULL)) == NULL) { + free(defstr); return -1; + } + + free(defstr); if (!*tstr) { drawstatus(L"No duration entered"); @@ -617,33 +626,13 @@ int h, m, s; return -1; } - if (swscanf(tstr, L"%d:%d:%d", &h, &m, &s) != 3) { - h = 0; - if (swscanf(tstr, L"%d:%d", &m, &s) != 2) { - m = 0; - if (swscanf(tstr, L"%d", &s) != 1) { - free(tstr); - drawstatus(L"Invalid time format."); - return -1; - } - } + if ((ret = parsetime(tstr)) == (time_t) -1) { + free(tstr); + drawstatus(L"Invalid time format."); + return -1; } free(tstr); - if (m >= 60) { - drawstatus(L"Minutes cannot be more than 59."); - return -1; - } - - if (s >= 60) { - drawstatus(L"Seconds cannot be more than 59."); - return -1; - } - - *hh = h; - *mm = m; - *ss = s; - return 0; + return ret; } - diff --git a/ui.h b/ui.h index 648bf35..a32602f 100644 --- a/ui.h +++ b/ui.h @@ -30,7 +30,7 @@ void drawheader (void); void drawentries (void); wchar_t *prompt (wchar_t const *, wchar_t const *, history_t *); -int prduration (wchar_t *prompt, int *h, int *m, int *s); +time_t prduration (wchar_t *prompt, time_t def); int yesno (wchar_t const *); void errbox (wchar_t const *, ...); void verrbox (wchar_t const *, va_list);