X-Git-Url: https://git.deb.at/?p=pkg%2Fabook.git;a=blobdiff_plain;f=edit.c;h=9a76c8a8970aadda843bd1b7ab7638f3e2c84ec1;hp=5edebec4d2fb2f01e1a6afcd47063d4fb55d5507;hb=HEAD;hpb=ceba9214d8bebe32d0c34c7a82916bcb9d798d69 diff --git a/edit.c b/edit.c index 5edebec..9a76c8a 100644 --- a/edit.c +++ b/edit.c @@ -9,81 +9,113 @@ #include #include +#include +#include #include "abook_curses.h" #include "ui.h" #include "abook.h" #include "database.h" +#include "gettext.h" #include "list.h" #include "edit.h" #include "misc.h" +#include "views.h" +#include "xmalloc.h" +#include "color.h" #ifdef HAVE_CONFIG_H # include "config.h" #endif +#if defined(HAVE_LOCALE_H) && defined(HAVE_SETLOCALE) +# include +#endif + + +static void locale_date(char *str, size_t str_len, int year, int month, int day); /* * some extern variables */ -extern struct abook_field abook_fields[]; - -extern list_item *database; -extern int curitem; -extern int items; +extern int views_count; WINDOW *editw; + static void -editor_tab(int tab) +editor_tab(const int tab) { - int i; - char *tab_names[] = { - "/ CONTACT \\", - "/ ADDRESS \\", - "/ PHONE \\", - "/ OTHER \\" - }; + int i, j; + int x_pos = 2; /* current x pos */ + char *tab_name; - mvwhline(editw, TABLINE+1, 0, UI_HLINE_CHAR, EDITW_COLS); + wattrset(editw, COLOR_PAIR(CP_TAB_BORDER)); + mvwhline(editw, TABLINE + 1, 0, UI_HLINE_CHAR, EDITW_COLS); - for(i=0; i < TABS; i++) - mvwaddstr(editw, TABLINE, 16 * i + 3, tab_names[i]); + for(i = 0; i < views_count; i++) { + view_info(i, &tab_name, NULL); + int width = strwidth(tab_name) + 5; - mvwaddstr(editw, TABLINE+1, 16 * tab + 2, "/ \\"); + if(x_pos + width + 1 > EDITW_COLS) { + statusline_addstr(_("Tab name too wide for screen")); + break; + } + + mvwaddch(editw, TABLINE + 1, x_pos, UI_TEE_CHAR); + mvwaddch(editw, TABLINE + 1, x_pos + width - 2, UI_TEE_CHAR); + + mvwaddch(editw, TABLINE, x_pos, UI_ULCORNER_CHAR); + mvwaddch(editw, TABLINE, x_pos + 1, UI_LBOXLINE_CHAR); + wattrset(editw, COLOR_PAIR(CP_TAB_LABEL)); + mvwaddstr(editw, TABLINE, x_pos + 2, tab_name); + wattrset(editw, COLOR_PAIR(CP_TAB_BORDER)); + mvwaddch(editw, TABLINE, x_pos + width - 3, UI_RBOXLINE_CHAR); + mvwaddch(editw, TABLINE, x_pos + width - 2, UI_URCORNER_CHAR); + + if(i == tab) { + mvwaddch(editw, TABLINE + 1, x_pos, UI_LRCORNER_CHAR); + for(j = 0; j < width - 3; j++) + mvwaddstr(editw, + TABLINE + 1, x_pos + j + 1, " "); + mvwaddch(editw, TABLINE + 1, x_pos + width - 2, + UI_LLCORNER_CHAR); + } + x_pos += width; + } } void get_first_email(char *str, int item) { - char *tmp; + char *tmp, *emails = db_email_get(item); - if(database[item][EMAIL] == NULL) { + if(!*emails) { *str = 0; return; } - strncpy(str, database[item][EMAIL], MAX_EMAIL_LEN); + strncpy(str, emails, MAX_EMAIL_LEN); + free(emails); if( (tmp = strchr(str, ',')) ) - *tmp=0; + *tmp = 0; else - str[MAX_EMAIL_LEN-1] = 0; + str[MAX_EMAIL_LEN - 1] = 0; } -static void -roll_emails(int item) +/* This only rolls emails from the 'email' field, not emails from any + * field of type FIELD_EMAILS. + * TODO: expand to ask for which field to roll if several are present? */ +void +roll_emails(int item, enum rotate_dir dir) { - char tmp[MAX_EMAILSTR_LEN]; - char *p; + abook_list *emails = csv_to_abook_list(db_fget(item, EMAIL)); - strcpy(tmp, database[item][EMAIL]); - - if( !(p = strchr(tmp, ',')) ) + if(!emails) return; - else - *p=0; - strcpy(database[item][EMAIL], p+1); - strcat(database[item][EMAIL], ","); - strcat(database[item][EMAIL], tmp); + free(db_fget(item, EMAIL)); + abook_list_rotate(&emails, dir); + db_fput(item, EMAIL, abook_list_to_csv(emails)); + abook_list_free(&emails); } static void @@ -91,21 +123,52 @@ init_editor() { clear(); editw = newwin(EDITW_LINES, EDITW_COLS, EDITW_TOP, EDITW_X); + notimeout(editw, TRUE); /* handling of escape key */ refresh_statusline(); } -/* - * we have to introduce edit_undo here - */ -static void edit_undo(int item, int mode); - enum { BACKUP_ITEM, RESTORE_ITEM, CLEAR_UNDO }; +static int +edit_undo(int item, int mode) +{ + static list_item backup = NULL; + static int backed_up_item = -1; + + switch(mode) { + case CLEAR_UNDO: + if(backup) { + item_empty(backup); + item_free(&backup); + } + break; + case BACKUP_ITEM: + if(backup) { + item_empty(backup); + item_free(&backup); + } + backup = item_create(); + item_duplicate(backup, db_item_get(item)); + backed_up_item = item; + break; + case RESTORE_ITEM: + if(backup) { + item_empty(db_item_get(backed_up_item)); + item_copy(db_item_get(backed_up_item), backup); + item_free(&backup); + return backed_up_item; + } + break; + default: + assert(0); + } + return item; +} static void close_editor() @@ -121,20 +184,20 @@ print_editor_header(int item) char *header; char email[MAX_EMAIL_LEN]; - if( (header = (char *)malloc(EDITW_COLS)) == NULL ) + if((header = xmalloc(EDITW_COLS)) == NULL) return; get_first_email(email, item); - if( *database[item][EMAIL] ) + if(*email) snprintf(header, EDITW_COLS, "%s <%s>", - database[item][NAME], + db_name_get(item), email); else - snprintf(header, EDITW_COLS, "%s", database[item][NAME]); + snprintf(header, EDITW_COLS, "%s", db_name_get(item)); - mvwaddstr(editw, 0, (EDITW_COLS - strlen(header)) / 2, - header); + wattrset(editw, COLOR_PAIR(CP_TAB_LABEL)); + mvwaddstr(editw, 0, (EDITW_COLS - strwidth(header)) / 2, header); free(header); } @@ -142,41 +205,73 @@ print_editor_header(int item) static void editor_print_data(int tab, int item) { - int i, j; + int j = 1, nb; int y, x; + abook_field_list *cur; + char *str; - for(i = 0, j = 1; i < ITEM_FIELDS; i++) { - if(abook_fields[i].tab != tab) - continue; + view_info(tab, NULL, &cur); - if(i==EMAIL) { /* special field */ - int k; - char emails[MAX_EMAILS][MAX_EMAIL_LEN]; - split_emailstr(item, emails); - getyx(editw, y, x); - mvwaddstr(editw, y+1, FIELDS_START_X, - "E-mail addresses:"); - for(k = 0; k < MAX_EMAILS; k++) { - getyx(editw, y, x); - mvwprintw(editw, y+1, FIELDS_START_X, - "%c -", '2' + k); - mvwprintw(editw, y +1, TAB_COLON_POS, - ": %s", emails[k]); - } - continue; - } + for(; cur; cur = cur->next) { if(j > 1) { - getyx(editw, y, x); y++; + getyx(editw, y, x); + y++; } else y = FIELDS_START_Y; - mvwprintw(editw, y, FIELDS_START_X, "%d - %s", - j, - abook_fields[i].name); + wattrset(editw, COLOR_PAIR(CP_FIELD_NAME)); + mvwprintw(editw, y, FIELDS_START_X, "%c - ", + (j < 10) ? '0' + j : 'A' + j - 10); + mvwaddnstr(editw, y, FIELDS_START_X + 4, cur->field->name, + bytes2width(cur->field->name, + FIELDNAME_MAX_WIDTH)); mvwaddch(editw, y, TAB_COLON_POS, ':'); - mvwaddstr(editw, y, TAB_COLON_POS + 2, - safe_str(database[item][i])); + + wattrset(editw, COLOR_PAIR(CP_FIELD_VALUE)); + if((cur->field->type == FIELD_EMAILS) || + (cur->field->type == FIELD_LIST)) { + abook_list *emails, *e; + + find_field_number(cur->field->key, &nb); + emails = csv_to_abook_list(db_fget_byid(item, nb)); + + for(e = emails; e; e = e->next) { + getyx(editw, y, x); + mvwaddnstr(editw, y + 1, TAB_COLON_POS + 2, + e->data, + bytes2width(e->data, + FIELD_MAX_WIDTH)); + mvwaddch(editw, y + 1, TAB_COLON_POS, + UI_VLINE_CHAR); + } + if(emails) { + mvwaddch(editw, y + 2, TAB_COLON_POS, + UI_LLCORNER_CHAR); + mvwhline(editw, y + 2, TAB_COLON_POS + 1, + UI_HLINE_CHAR, + EDITW_COLS - TAB_COLON_POS - 2); + } + abook_list_free(&emails); + } else if(cur->field->type == FIELD_DATE) { + int day, month, year; + char buf[64]; + + find_field_number(cur->field->key, &nb); + str = db_fget_byid(item, nb); + + if(parse_date_string(str, &day, &month, &year)) { + /* put locale representation of date in buf */ + locale_date(buf, sizeof(buf), year, month, day); + mvwaddnstr(editw, y, TAB_COLON_POS + 2, buf, + bytes2width(buf, FIELD_MAX_WIDTH)); + } + } else { + find_field_number(cur->field->key, &nb); + str = safe_str(db_fget_byid(item, nb)); + mvwaddnstr(editw, y, TAB_COLON_POS + 2, str, + bytes2width(str, FIELD_MAX_WIDTH)); + } j++; } @@ -184,176 +279,367 @@ editor_print_data(int tab, int item) /* * function: change_field - * + * * parameters: * (char *msg) * message to display as a prompt * (char **field) - * a pointer to pointer which will point a new string. if the latter + * a pointer to a pointer which will point a new string. if the latter * pointer != NULL it will be freed (if user doesn't cancel) - * + * (size_t max_len) + * maximum length of field to read from user + * * returns (int) * a nonzero value if user has cancelled and zero if user has typed a * valid string */ - static int -change_field(char *msg, char **field) +change_field(char *msg, char **field, size_t max_len) { - char tmp[MAX_FIELD_LEN]; - int max_len = MAX_FIELD_LEN; - int ret; + char *old; + int ret = 0; - if( !strncmp("E-mail", msg, 6) ) - max_len = MAX_EMAIL_LEN; + old = *field; - statusline_addstr(msg); - if( (ret = statusline_getnstr( tmp, max_len - 1, 0 ) ? 1:0 ) ) { - my_free(*field); - if( *tmp ) - *field = strdup(tmp); + *field = ui_readline(msg, old, max_len - 1, 0); + + if(*field) { + xfree(old); + if(!**field) + xfree(*field); + } else { + *field = old; + ret = 1; } clear_statusline(); refresh_statusline(); - return !ret; + return ret; } -static void -change_name_field(char **field) +static int +change_name_field(char *msg, char **field, size_t max_len) { char *tmp; + int ret; - tmp = strdup(*field); - change_field("Name: ", field); + tmp = xstrdup(*field); + ret = change_field(msg, field, max_len); - if( *field == NULL || ! **field ) { - my_free(*field); - *field = strdup(tmp); + if(*field == NULL || ! **field) { + xfree(*field); + *field = xstrdup(tmp); } - my_free(tmp); + xfree(tmp); + + return ret; } static void fix_email_str(char *str) { - for(; *str; str++ ) + for(; *str; str++) *str = *str == ',' ? '_' : *str; } static void -edit_emails(char c, int item) +edit_list(int item, int nb, int isemail) { - char *field = NULL; - char emails[MAX_EMAILS][MAX_EMAIL_LEN]; - char tmp[MAX_EMAILSTR_LEN] = ""; - int i, len; + char *field, *msg, *keys; + abook_list *list, *e; + int choice = 1, elem_count; + + list = csv_to_abook_list(db_fget_byid(item, nb)); + + for(e = list, elem_count = 0; e; e = e->next, elem_count++) + ; + + if(elem_count) { + keys = xstrndup(S_("keybindings_new_123456789|n123456789"), + elem_count + 1); + msg = strdup_printf(_("Choose %s to modify (<1>%s%c%s%s."), + isemail ? _("email") : _("item"), + (elem_count > 1) ? "-<" : "", + (elem_count > 1) ? '0' + elem_count : ')', + (elem_count > 1) ? ">)" : "", + (elem_count < MAX_LIST_ITEMS) ? + _(" or ew") : "" + ); + choice = statusline_askchoice( + msg, + keys, + (elem_count < MAX_LIST_ITEMS) ? 1 : 2 + ); + free(keys); + free(msg); + } - split_emailstr(item, emails); + if(choice == 0) + return; - if(change_field("E-mail: ", &field)) { -#ifdef DEBUG - fprintf(stderr, "change_field = TRUE\n"); -#endif + field = (choice > 1) ? + xstrdup(abook_list_get(list, choice - 2)->data) : + NULL; + + if(change_field(isemail ? _("E-mail: ") : _("Item: "), + &field, MAX_EMAIL_LEN)) return; /* user cancelled ( C-g ) */ - } - if(field) { - strncpy(emails[c - '2'], field, MAX_EMAIL_LEN); - fix_email_str(emails[c - '2']); - } else - *emails[c - '2'] = 0; - my_free(database[item][EMAIL]); + /* TODO if list item contains commas, should use quotes instead */ + if(field) + fix_email_str(field); - for(i = 0; i < MAX_EMAILS; i++) { - if( *emails[i] ) { - strcat(tmp, emails[i]); - strcat(tmp, ","); - } - } + if(choice == 1) + abook_list_append(&list, field); + else + abook_list_replace(&list, choice - 2, field); - len = strlen(tmp); - if(tmp[len -1] == ',') - tmp[len-1] =0; + if(field) + xfree(field); - database[item][EMAIL] = strdup(tmp); + field = abook_list_to_csv(list); + db_fput_byid(item, nb, field ? field : xstrdup("")); + abook_list_free(&list); } -static int -edit_field(int tab, char c, int item) +/* + * available %-sequences: + * - %y, %Y, %m, %M, %d, %D represent year, month, and day + * (the uppercase version telling to fill with leading zeros + * if necessary) + * - %I for ISO 8601 representation + */ +static size_t +format_date(char *str, size_t str_len, char *fmt, int year, int month, int day) { - int i, j; - int n = c - '1' + 1; - char *str; - - if(n < 1 || n > MAX_TAB_FIELDS) - return 0; + char *s = str; + size_t len; - edit_undo(item, BACKUP_ITEM); + while(*fmt && (s - str + 1 < str_len)) { + if(*fmt != '%') { + *s++ = *fmt++; + continue; + } - if(tab == TAB_CONTACT) { - switch(c) { - case '1': change_name_field(&database[item][NAME]); + len = str_len - (str - s); + switch(*++fmt) { + case 'y': s += snprintf(s, len, "%d", year); break; + case 'Y': s += snprintf(s, len, "%04d", year); break; + case 'm': s += snprintf(s, len, "%d", month); break; + case 'M': s += snprintf(s, len, "%02d", month); break; + case 'd': s += snprintf(s, len, "%d", day); break; + case 'D': s += snprintf(s, len, "%02d", day); break; + case 'I': s += format_date(s, len, + year ? "%Y-%M-%D" : "--%M-%D", + year, month, day); break; - case '2': - case '3': - case '4': - case '5': edit_emails(c, item); break; - default: return 0; + case '%': *s++ = '%'; break; + default: *s++ = '%'; *s++ = *fmt; break; } - return 1; + fmt++; } + *s = 0; + return s - str; +} - for(i=0, j=0; i< ITEM_FIELDS; i++) { - if(abook_fields[i].tab == tab) - j++; - if(j==n) - break; +/* + * str is a buffer of max length str_len, which, after calling, will + * contain a representation of the given [y, m, d] date using the + * current locale (as defined by LC_TIME). + * + * In the absence of any localization, use an ISO 8601 representation. + */ +static void +locale_date(char *str, size_t str_len, int year, int month, int day) +{ + char *fmt; + +#if defined(HAVE_LOCALE_H) && defined(HAVE_SETLOCALE) + fmt = year ? dcgettext(PACKAGE, "%Y-%M-%D", LC_TIME) : + dcgettext(PACKAGE, "--%M-%D", LC_TIME); +#else + fmt = "%I"; +#endif + format_date(str, str_len, fmt, year, month, day); +} + +static int is_valid_date(const int day, const int month, const int year) +{ + int valid = 1; + int month_length[13] = + { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + + /* + * leap year + */ + if ((!(year % 4)) && ((year % 100) || !(year % 400))) + month_length[2] = 29; + + if (month < 1 || month > 12) + valid = 0; + else if (day < 1 || day > month_length[month]) + valid = 0; + else if (year < 0) /* we don't accept negative year numbers */ + valid = 0; + + return valid; +} + +int +parse_date_string(char *str, int *day, int *month, int *year) +{ + int i = 0; + char buf[12], *s, *p; + + assert(day && month && year); + + if(!str || !*str) + return FALSE; + + p = s = strncpy(buf, str, sizeof(buf)); + + if(*s == '-' && *s++ == '-') { /* omitted year */ + *year = 0; + p = ++s; + i++; } - if(j!=n) - return 0; + while(*s) { + if(isdigit(*s)) { + s++; + continue; + } else if(*s == '-') { + if(++i > 3) + return FALSE; + *s++ = '\0'; + switch(i) { + case 1: *year = safe_atoi(p); break; + case 2: *month = safe_atoi(p); break; + } + p = s; + } else + return FALSE; + } - str = mkstr("%s: ", abook_fields[i].name); - change_field(str, &database[item][i]); + if (i != 2 || !*p) + return FALSE; - free(str); + *day = atoi(p); - return 1; + return is_valid_date(*day, *month, *year); } static void -edit_undo(int item, int mode) +edit_date(int item, int nb) { - int i; - static list_item *backup = NULL; + int i, date[3], old; + char *s = db_fget_byid(item, nb); + char *field[] = { N_("Day: "), N_("Month: "), N_("Year (optional): ") }; - switch(mode) { - case CLEAR_UNDO: - if(backup) { - free_list_item(backup[0]); - my_free(backup); + old = parse_date_string(s, &date[0], &date[1], &date[2]); + + for(i = 0; i < 3; i++) { + s = (old && date[i]) ? strdup_printf("%d", date[i]) : NULL; + if(change_field(gettext(field[i]), &s, 5)) + return; /* user aborted with ^G */ + + date[i] = (s && is_number(s)) ? atoi(s) : 0; + + if(!s) { + switch(i) { + case 0: db_fput_byid(item, nb, NULL); /*delete*/ + case 1: /* fall through */ return; } + } else + xfree(s); + } + + /* ISO 8601 date, of the YYYY-MM-DD or --MM-DD format */ + if(is_valid_date(date[0], date[1], date[2])) { + if(date[2]) + s = strdup_printf("%04d-%02d-%02d", + date[2], date[1], date[0]); + else + s = strdup_printf("--%02d-%02d", date[1], date[0]); + + db_fput_byid(item, nb, xstrdup(s)); + } else + statusline_msg(_("Invalid date")); +} + +/* input range: 1-9A-Z + * output range: 0-34 */ +static int +key_to_field_number(char c) +{ + int n = c - '1'; + if(n >= 0 && n < 9) + return n; + + n = c - 'A' + 9; + if(n > 8 && n < 35) + return n; + + return -1; +} + +static void +edit_field(int tab, char c, int item_number) +{ + ui_enable_mouse(FALSE); + int i = 0, number, idx; + char *msg; + abook_field_list *f; + list_item item; + + if((number = key_to_field_number(c)) < 0) + goto detachfield; + + edit_undo(item_number, BACKUP_ITEM); + + view_info(tab, NULL, &f); + + while(1) { + if(!f) + goto detachfield; + + if(i == number) break; - case BACKUP_ITEM: - if(backup) { - free_list_item(backup[0]); - my_free(backup); - } - backup = (list_item *)abook_malloc(sizeof(list_item)); - for(i = 0; i < ITEM_FIELDS; i++) - backup[0][i] = safe_strdup(database[item][i]); + + f = f->next; + i++; + } + + find_field_number(f->field->key, &idx); + + switch(f->field->type) { + case FIELD_STRING: + msg = strdup_printf("%s: ", f->field->name); + item = db_item_get(item_number); + if(strcmp(f->field->key, "name") == 0) + change_name_field(msg,&item[idx],MAX_FIELD_LEN); + else + change_field(msg,&item[idx],MAX_FIELD_LEN); + free(msg); break; - case RESTORE_ITEM: - if(backup) { - free_list_item(database[item]); - itemcpy(database[item], backup[0]); - my_free(backup); - } + case FIELD_LIST: + edit_list(item_number, idx, 0); break; + case FIELD_EMAILS: + edit_list(item_number, idx, 1); + break; + case FIELD_DATE: + edit_date(item_number, idx); + goto detachfield; + default: + assert(0); } + + detachfield: + if(opt_get_bool(BOOL_USE_MOUSE)) + ui_enable_mouse(TRUE); } static int @@ -363,7 +649,7 @@ edit_loop(int item) int c; werase(editw); - headerline(EDITOR_HELPLINE); + headerline(gettext(EDITOR_HELPLINE)); refresh_statusline(); print_editor_header(item); editor_tab(tab); @@ -373,26 +659,91 @@ edit_loop(int item) refresh(); wrefresh(editw); - switch( (c = getch()) ) { - case 'c': tab = TAB_CONTACT; break; - case 'a': tab = TAB_ADDRESS; break; - case 'p': tab = TAB_PHONE; break; - case 'o': tab = TAB_OTHER; break; - case KEY_LEFT: tab = tab == 0 ? MAX_TAB : tab - 1; + c = getch(); + if(c == '\033') { + statusline_addstr("ESC-"); + c = getch(); + clear_statusline(); + + /* Escaped bindings */ + switch(c) { + case 'r': roll_emails(item, ROTATE_RIGHT); break; + default: break; + } + + return item; + } + if(c == KEY_MOUSE) { + MEVENT event; + if(getmouse(&event) == OK) { + if(event.bstate & BUTTON1_CLICKED + || event.bstate & BUTTON1_DOUBLE_CLICKED) { + int window_y, window_x; + getbegyx(editw, window_y, window_x); + if(event.y == 0) { + /* if first row is selected, then go back to list */ + return -1; + } else if(event.y == window_y + TABLINE + || event.y == window_y + TABLINE + 1) { + char* tab_name; + int mouse_x = event.x; + int xpos = 2 + 1; /* look at editor_tab() and try out */ + int clicked_tab = 0; + while(clicked_tab < views_count) { + view_info(clicked_tab, &tab_name, NULL); + xpos += strwidth(tab_name) + 5; + /* fprintf(stderr, "trying tab %d\n", clicked_tab); */ + if(xpos >= mouse_x) { + break; /* clicked tab was found */ + } else { + /* try next tab */ + clicked_tab++; + } + } + if(clicked_tab < views_count) { + tab = clicked_tab; + } + } else if(event.y >= window_y + FIELDS_START_Y) { + /* is mouse in field area? */ + int j = 1 + event.y - window_y - FIELDS_START_Y; + /* field numbers start with 1, but if j='0', then char='0' */ + /* so fix this, by adding 1 to j */ + int field_char = (j < 10) ? '0' + j : 'A' + j - 10; + edit_field(tab, field_char, item); + } + } else if(event.bstate & BUTTON4_PRESSED) { + tab = tab == 0 ? views_count - 1 : tab - 1; + } + else if(event.bstate & BUTTON5_PRESSED) { + tab = tab == views_count - 1 ? 0 : tab + 1; + } + return item; + } + } + + /* No uppercase nor numeric key should be used in this menu, + * as they are reserved for field selection */ + switch(c) { + case 'h': + case KEY_LEFT: tab = tab == 0 ? views_count - 1 : tab - 1; break; - case KEY_RIGHT: tab = tab == MAX_TAB ? 0 : tab + 1; + case 'l': + case KEY_RIGHT: tab = tab == views_count - 1 ? 0 : tab + 1; break; + case KEY_UP: case '<': - case 'k': if(is_valid_item(item-1)) item--; break; + case 'k': if(is_valid_item(item - 1)) item--; break; + case KEY_DOWN: case '>': - case 'j': if(is_valid_item(item+1)) item++; break; - case 'r': roll_emails(item); break; + case 'j': if(is_valid_item(item + 1)) item++; break; + case 'r': roll_emails(item, ROTATE_LEFT); break; case '?': display_help(HELP_EDITOR); break; - case 'u': edit_undo(item, RESTORE_ITEM); break; + case 'u': item = edit_undo(item, RESTORE_ITEM); break; case 'm': launch_mutt(item); clearok(stdscr, 1); break; case 'v': launch_wwwbrowser(item); clearok(stdscr, 1); break; case 12 : clearok(stdscr, 1); break; /* ^L (refresh screen) */ - default: return edit_field(tab, c, item) ? item : -1; + case 'q': return -1; + default: edit_field(tab, c, item); } return item; @@ -401,17 +752,17 @@ edit_loop(int item) void edit_item(int item) { - if( item < 0 ) { - if( curitem < 0 ) + if(item < 0) { + if(list_get_curitem() < 0) return; else - item = curitem; + item = list_get_curitem(); } init_editor(); - while( (item = edit_loop(item)) >= 0 ) - curitem = item; /* hmm, this is not very clean way to go */ + while((item = edit_loop(item)) >= 0) + list_set_curitem(item); /* this is not very clean way to go */ close_editor(); } @@ -420,21 +771,20 @@ void add_item() { char *field = NULL; - list_item item; + list_item item = item_create(); - change_field("Name: ", &field); + change_field(_("Name: "), &field, MAX_FIELD_LEN); if( field == NULL ) return; - memset(item, 0, sizeof(item)); - - item[NAME] = field; + item_fput(item, NAME, field); add_item2database(item); + item_free(&item); - curitem = LAST_ITEM; + list_set_curitem(last_item()); - edit_item(LAST_ITEM); + edit_item(last_item()); }