From 71c34ac7f9670a9c4cc2e9e38e3b231e6b855d4e Mon Sep 17 00:00:00 2001 From: Lars Henriksen Date: Thu, 30 Jan 2020 09:00:39 +0100 Subject: Refactor the repeat command Code duplication has been eliminated by calling update_rept() from the repeat command ui_day_item_repeat(). The repeat command asks for simple or advanced repetition. Signed-off-by: Lars Henriksen Signed-off-by: Lukas Fleischer --- src/recur.c | 3 +- src/ui-day.c | 250 ++++++++++++++++++++--------------------------------------- 2 files changed, 87 insertions(+), 166 deletions(-) diff --git a/src/recur.c b/src/recur.c index fcad296..e0a6b05 100644 --- a/src/recur.c +++ b/src/recur.c @@ -392,8 +392,7 @@ char recur_def2char(enum recur_type define) recur_char = 'Y'; break; default: - EXIT(_("unknown repetition type")); - return 0; + recur_char = 0; } return recur_char; diff --git a/src/ui-day.c b/src/ui-day.c index eff9d30..e359c82 100644 --- a/src/ui-day.c +++ b/src/ui-day.c @@ -544,10 +544,10 @@ static int edit_ilist(llist_t *ilist, int_list_t type) } else { status_mesg(msg_invalid, msg_cont); keys_wgetch(win[KEY].p); - mem_free(istr); - status_mesg(msg, ""); - istr = int2str(ilist, type); } + mem_free(istr); + status_mesg(msg, ""); + istr = int2str(ilist, type); } else if (ret == GETSTRING_ESC) break; } @@ -557,11 +557,12 @@ static int edit_ilist(llist_t *ilist, int_list_t type) return updated; } -static void update_rept(time_t start, long dur, struct rpt **rpt, llist_t *exc) +static int update_rept(time_t start, long dur, struct rpt **rpt, llist_t *exc, + int simple) { + int updated = 0; struct rpt nrpt; - char *msg_rpt_current = NULL; - char *msg_rpt_asktype = NULL; + char *types = NULL; char *freqstr = NULL; char *timstr = NULL; char *outstr = NULL; @@ -573,37 +574,37 @@ static void update_rept(time_t start, long dur, struct rpt **rpt, llist_t *exc) LLIST_INIT(&nrpt.bymonthday); /* Edit repetition type. */ - const char *msg_rpt_prefix = _("Enter the repetition type:"); - const char *msg_rpt_daily = _("(d)aily"); - const char *msg_rpt_weekly = _("(w)eekly"); - const char *msg_rpt_monthly = _("(m)onthly"); - const char *msg_rpt_yearly = _("(y)early"); - const char *msg_rpt_choice = _("[dwmy]"); + const char *msg_prefix = _("Repetition type:"); + const char *daily = _("(d)aily"); + const char *weekly = _("(w)eekly"); + const char *monthly = _("(m)onthly"); + const char *yearly = _("(y)early"); + const char *dwmy = _("[dwmy]"); /* Find the current repetition type. */ - const char *rpt_current; + const char *current; switch (recur_def2char((*rpt)->type)) { case 'D': - rpt_current = msg_rpt_daily; + current = daily; break; case 'W': - rpt_current = msg_rpt_weekly; + current = weekly; break; case 'M': - rpt_current = msg_rpt_monthly; + current = monthly; break; case 'Y': - rpt_current = msg_rpt_yearly; + current = yearly; break; default: - /* NOTREACHED, but makes the compiler happier. */ - rpt_current = msg_rpt_daily; + /* New item. */ + current = ""; } - asprintf(&msg_rpt_current, _("(p.t. %s)"), rpt_current); - asprintf(&msg_rpt_asktype, "%s %s, %s, %s, %s? %s", msg_rpt_prefix, - msg_rpt_daily, msg_rpt_weekly, msg_rpt_monthly, - msg_rpt_yearly, msg_rpt_current); - switch (status_ask_choice(msg_rpt_asktype, msg_rpt_choice, 4)) { + asprintf(&types, "%s %s, %s, %s, %s?", + msg_prefix, daily, weekly, monthly, yearly); + if (current[0]) + asprintf(&types, "%s (now %s)", types, current); + switch (status_ask_choice(types, dwmy, 4)) { case 1: nrpt.type = 'D'; break; @@ -622,8 +623,8 @@ static void update_rept(time_t start, long dur, struct rpt **rpt, llist_t *exc) nrpt.type = recur_char2def(nrpt.type); /* Edit frequency. */ - const char *msg_freq = _("Enter the repetition frequency:"); - const char *msg_wrong_freq = _("Invalid frequency."); + const char *msg_freq = _("Repetition frequency:"); + const char *msg_inv_freq = _("Invalid frequency."); do { status_mesg(msg_freq, ""); mem_free(freqstr); @@ -633,23 +634,23 @@ static void update_rept(time_t start, long dur, struct rpt **rpt, llist_t *exc) goto cleanup; } nrpt.freq = atoi(freqstr); - if (nrpt.freq == 0) { - status_mesg(msg_wrong_freq, msg_cont); + if (nrpt.freq <= 0) { + status_mesg(msg_inv_freq, msg_cont); keys_wait_for_any_key(win[KEY].p); } } - while (nrpt.freq == 0); + while (nrpt.freq <= 0); - /* Edit end date. */ + /* Edit until date. */ const char *msg_until_1 = - _("Enter end date or duration ('?' for input formats):"); + _("Until date or duration ('?' for input formats):"); const char *msg_help_1 = _("Date: %s (year or month may be omitted). Endless duration: 0."); const char *msg_help_2 = _("Duration in days: +dd. Duration in weeks and days: +??w??d."); - const char *msg_wrong_time = - _("Invalid date: end date must come after start date (%s)."); - const char *msg_wrong_date = _("Invalid date."); + const char *msg_inv_until = + _("Invalid date: until date must come after start date (%s)."); + const char *msg_inv_date = _("Invalid date."); for (;;) { mem_free(timstr); @@ -674,7 +675,7 @@ static void update_rept(time_t start, long dur, struct rpt **rpt, llist_t *exc) if (*timstr == '+') { unsigned days; if (!parse_date_duration(timstr + 1, &days, start)) { - status_mesg(msg_wrong_date, msg_cont); + status_mesg(msg_inv_date, msg_cont); keys_wgetch(win[KEY].p); continue; } @@ -687,7 +688,7 @@ static void update_rept(time_t start, long dur, struct rpt **rpt, llist_t *exc) int year, month, day; if (!parse_date(timstr, conf.input_datefmt, &year, &month, &day, ui_calendar_get_slctd_day())) { - status_mesg(msg_wrong_date, msg_cont); + status_mesg(msg_inv_date, msg_cont); keys_wgetch(win[KEY].p); continue; } @@ -701,11 +702,19 @@ static void update_rept(time_t start, long dur, struct rpt **rpt, llist_t *exc) mem_free(timstr); mem_free(outstr); timstr = date_sec2date_str(start, DATEFMT(conf.input_datefmt)); - asprintf(&outstr, msg_wrong_time, timstr); + asprintf(&outstr, msg_inv_until, timstr); status_mesg(outstr, msg_cont); keys_wgetch(win[KEY].p); } + if (simple) { + (*rpt)->type = nrpt.type; + (*rpt)->freq = nrpt.freq; + (*rpt)->until = nrpt.until; + updated = 1; + goto cleanup; + } + /* Edit exception list. */ recur_exc_dup(&nrpt.exc, exc); if (!edit_exc(&nrpt.exc)) @@ -779,9 +788,9 @@ static void update_rept(time_t start, long dur, struct rpt **rpt, llist_t *exc) recur_free_int_list(&(*rpt)->bymonthday); recur_int_list_dup(&(*rpt)->bymonthday, &nrpt.bymonthday); + updated = 1; cleanup: - mem_free(msg_rpt_current); - mem_free(msg_rpt_asktype); + mem_free(types); mem_free(freqstr); mem_free(timstr); mem_free(outstr); @@ -789,9 +798,12 @@ cleanup: recur_free_int_list(&nrpt.bywday); recur_free_int_list(&nrpt.bymonth); recur_free_int_list(&nrpt.bymonthday); + + return updated; } /* Edit an already existing item. */ +#define ADVANCED 0 void ui_day_item_edit(void) { struct recur_event *re; @@ -818,7 +830,7 @@ void ui_day_item_edit(void) update_desc(&re->mesg); break; case 2: - update_rept(re->day, -1, &re->rpt, &re->exc); + update_rept(re->day, -1, &re->rpt, &re->exc, ADVANCED); break; default: return; @@ -854,7 +866,8 @@ void ui_day_item_edit(void) break; case 4: need_check_notify = 1; - update_rept(ra->start, ra->dur, &ra->rpt, &ra->exc); + update_rept(ra->start, ra->dur, &ra->rpt, &ra->exc, + ADVANCED); break; case 5: need_check_notify = 1; @@ -904,6 +917,7 @@ void ui_day_item_edit(void) if (need_check_notify) notify_check_next_app(1); } +#undef ADVANCED /* Pipe an appointment or event to an external program. */ void ui_day_item_pipe(void) @@ -1165,161 +1179,69 @@ void ui_day_item_delete(unsigned reg) */ void ui_day_item_repeat(void) { - char user_input[BUFSIZ] = ""; - const char *msg_rpt_prefix = _("Enter the repetition type:"); - const char *msg_rpt_daily = _("(d)aily"); - const char *msg_rpt_weekly = _("(w)eekly"); - const char *msg_rpt_monthly = _("(m)onthly"); - const char *msg_rpt_yearly = _("(y)early"); - const char *msg_type_choice = _("[dwmy]"); - const char *mesg_freq_1 = _("Enter the repetition frequency:"); - const char *mesg_wrong_freq = _("Invalid frequency."); - const char *mesg_until_1 = _("Enter end date or duration ('?' for input formats):"); - const char *mesg_help_1 = _("Date: %s (year or month may be omitted). Endless duration: '0'."); - const char *mesg_help_2 = _("Duration in days: +dd. Duration in weeks and days: +??w??d."); - const char *mesg_wrong_1 = _("Invalid date."); - const char *mesg_wrong_2 = _("Press [ENTER] to continue."); - const char *wrong_type_1 = _("This item is already a repeated one."); - const char *wrong_type_2 = _("Press [ENTER] to continue."); - const char *mesg_older = _("Invalid date: end date must come after start date (%s)."); - - char *msg_asktype; - asprintf(&msg_asktype, "%s %s, %s, %s, %s", msg_rpt_prefix, - msg_rpt_daily, msg_rpt_weekly, msg_rpt_monthly, - msg_rpt_yearly); - - int type = 0, freq = 0; - int item_nb; + int item_nb, simple; struct day_item *p; - struct recur_apoint *ra; - time_t until; - unsigned days; + long dur; + struct rpt rpt, *r; + const char *already = _("Already repeated."); + const char *cont = _("Press any key to continue."); + const char *repetition = _("A (s)imple or (a)dvanced repetition?"); + const char *sa = _("[sa]"); if (day_item_count(0) <= 0) - goto cleanup; + return; item_nb = listbox_get_sel(&lb_apt); p = day_get_item(item_nb); if (p->type != APPT && p->type != EVNT) { - status_mesg(wrong_type_1, wrong_type_2); + status_mesg(already, cont); keys_wait_for_any_key(win[KEY].p); - goto cleanup; + return; } - switch (status_ask_choice(msg_asktype, msg_type_choice, 4)) { + switch (status_ask_choice(repetition, sa, 2)) { case 1: - type = RECUR_DAILY; + simple = 1; break; case 2: - type = RECUR_WEEKLY; - break; - case 3: - type = RECUR_MONTHLY; - break; - case 4: - type = RECUR_YEARLY; + simple = 0; break; default: - goto cleanup; - } - - while (freq == 0) { - status_mesg(mesg_freq_1, ""); - if (getstring(win[STA].p, user_input, BUFSIZ, 0, 1) != - GETSTRING_VALID) - goto cleanup; - freq = atoi(user_input); - if (freq == 0) { - status_mesg(mesg_wrong_freq, wrong_type_2); - keys_wait_for_any_key(win[KEY].p); - } - user_input[0] = '\0'; - } - - char *outstr, *datestr; - for (;;) { - status_mesg(mesg_until_1, ""); - if (getstring(win[STA].p, user_input, BUFSIZ, 0, 1) == GETSTRING_ESC) - goto cleanup; - if (strcmp(user_input, "") == 0 || strcmp(user_input, "0") == 0) { - until = 0; - break; - } - if (*user_input == '?') { - user_input[0] = '\0'; - asprintf(&outstr, mesg_help_1, DATEFMT_DESC(conf.input_datefmt)); - status_mesg(outstr, mesg_help_2); - mem_free(outstr); - wgetch(win[KEY].p); - continue; - } - if (*user_input == '+') { - if (!parse_date_duration(user_input + 1, &days, p->start)) { - status_mesg(mesg_wrong_1, mesg_wrong_2); - keys_wgetch(win[KEY].p); - continue; - } - /* Until is midnight of the day. */ - until = date_sec_change( - update_time_in_date(p->start, 0, 0), - 0, days - ); - } else { - int year, month, day; - if (!parse_date(user_input, conf.input_datefmt, - &year, &month, &day, ui_calendar_get_slctd_day())) { - status_mesg(mesg_wrong_1, mesg_wrong_2); - keys_wgetch(win[KEY].p); - continue; - } - struct date d = { day, month, year }; - until = date2sec(d, 0, 0); - } - /* Compare days (midnights) - until-day may equal start day. */ - if (until >= get_slctd_day()) - break; - - datestr = date_sec2date_str(p->start, DATEFMT(conf.input_datefmt)); - asprintf(&outstr, mesg_older, datestr); - status_mesg(outstr, wrong_type_2); - mem_free(datestr); - mem_free(outstr); - keys_wgetch(win[KEY].p); + return; } - /* Set the selected APP item. */ - struct day_item d = empty_day; - struct rpt rpt; - rpt.type = type; - rpt.freq = freq; - rpt.until = until; + if (p->type == APPT) + dur = p->item.apt->dur; + else + dur = -1; + rpt.type = -1; + rpt.freq = 1; + rpt.until = 0; LLIST_INIT(&rpt.bymonth); LLIST_INIT(&rpt.bywday); LLIST_INIT(&rpt.bymonthday); LLIST_INIT(&rpt.exc); + r = &rpt; + if (!update_rept(p->start, dur, &r, &rpt.exc, simple)) + return; + + struct day_item d = empty_day; if (p->type == EVNT) { struct event *ev = p->item.ev; d.item.rev = recur_event_new(ev->mesg, ev->note, ev->day, - ev->id, &rpt); - } else if (p->type == APPT) { + ev->id, &rpt); + } else { struct apoint *apt = p->item.apt; - d.item.rapt = ra = recur_apoint_new(apt->mesg, apt->note, + d.item.rapt = recur_apoint_new(apt->mesg, apt->note, apt->start, apt->dur, apt->state, &rpt); if (notify_bar()) - notify_check_repeated(ra); - } else { - EXIT(_("wrong item type")); - /* NOTREACHED */ + notify_check_repeated(d.item.rapt); } - day_set_sel_data(&d); ui_day_item_cut(REG_BLACK_HOLE); + day_set_sel_data(&d); io_set_modified(); - ui_calendar_monthly_view_cache_set_invalid(); - -cleanup: - mem_free(msg_asktype); } /* Delete an item and save it in a register. */ -- cgit v1.2.3-54-g00ecf