From: Cedric Duval Date: Fri, 25 Aug 2006 22:51:00 +0000 (+0000) Subject: Support for 'date' field type. X-Git-Tag: upstream/0.6.1~2^2~103 X-Git-Url: https://git.deb.at/w?a=commitdiff_plain;h=20ea61a5f77f0f8c1354dc326a74f9a6c8362d6a;p=pkg%2Fabook.git Support for 'date' field type. ISO 8601 parsing from Jaakko. --- diff --git a/abookrc.5 b/abookrc.5 index 7c24baf..7c66ef7 100644 --- a/abookrc.5 +++ b/abookrc.5 @@ -35,7 +35,7 @@ are on lines beginning with '#'. .TP \fBfield\fP \fIidentifier\fP = \fIhuman_readable_name\fP [ , \fItype\fP ] Defines a new custom field. \fItype\fP can be one of 'string' (default) -, 'emails', 'list', or 'day'. +, 'emails', 'list', or 'date'. .TP \fBview\fP \fIview name\fP = \fIfield1\fP [ , \fIfield2\fP, ... ] @@ -165,7 +165,7 @@ Defines if the cursor is visible in main display. Default is false. # Declare a few custom fields field pager = Pager field address_lines = Address, list -field birthday = Birthday, day +field birthday = Birthday, date # Define how fields should be displayed in tabs view CONTACT = name, email diff --git a/database.c b/database.c index 1b337c6..632ad56 100644 --- a/database.c +++ b/database.c @@ -57,7 +57,7 @@ abook_field standard_fields[] = { {"nick", N_("Nickname/Alias"), FIELD_STRING}, /* NICK */ {"url", N_("URL"), FIELD_STRING}, /* URL */ {"notes", N_("Notes"), FIELD_STRING}, /* NOTES */ - {"anniversary", N_("Anniversary day"), FIELD_DAY}, /* ANNIVERSARY */ + {"anniversary", N_("Anniversary day"), FIELD_DATE}, /* ANNIVERSARY */ {0} /* ITEM_FIELDS */ }; @@ -177,8 +177,8 @@ declare_new_field(char *key, char *name, char *type, int accept_standard) f->type = FIELD_EMAILS; else if(0 == strcasecmp("list", type)) f->type = FIELD_LIST; - else if(0 == strcasecmp("day", type)) - f->type = FIELD_DAY; + else if(0 == strcasecmp("date", type)) + f->type = FIELD_DATE; else return _("unknown type"); @@ -428,7 +428,7 @@ validate_item(list_item item) case FIELD_STRING: max_field_len = MAX_FIELD_LEN; break; - case FIELD_DAY: + case FIELD_DATE: break; default: assert(0); diff --git a/database.h b/database.h index 0660992..0304841 100644 --- a/database.h +++ b/database.h @@ -43,7 +43,7 @@ enum { FIELD_STRING = 1, FIELD_EMAILS, FIELD_LIST, - FIELD_DAY, + FIELD_DATE, }; enum { diff --git a/edit.c b/edit.c index c7a62e4..a08fdc9 100644 --- a/edit.c +++ b/edit.c @@ -33,6 +33,8 @@ extern int views_count; WINDOW *editw; +static int parse_date_string(char *s, int *day, int *month, int *year); + static void editor_tab(const int tab) @@ -240,6 +242,22 @@ editor_print_data(int tab, int item) EDITW_COLS - TAB_COLON_POS - 2); } abook_list_free(&emails); + } else if(cur->field->type == FIELD_DATE) { + int day, month, year; + char buf[12]; + + find_field_number(cur->field->key, &nb); + if((str = db_fget_byid(item, nb)) != NULL) + strncpy(buf, str, sizeof(buf)); + + if(str && parse_date_string(buf, &day, &month, &year)) { + str = strdup_printf(year ? " %04d-%02d-%02d" : + "%c%02d-%02d", year ? year : ' ', + month, day); + mvwaddnstr(editw, y, TAB_COLON_POS + 2, str, + bytes2width(str, FIELD_MAX_WIDTH)); + free(str); + } } else { find_field_number(cur->field->key, &nb); str = safe_str(db_fget_byid(item, nb)); @@ -378,6 +396,113 @@ edit_list(int item, int nb, int isemail) abook_list_free(&list); } +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; +} + +static int +parse_date_string(char *s, int *day, int *month, int *year) +{ + int i = 0; + char *p = s; + assert(s && day && month && year); + + if(*s == '-' && *s++ == '-') { /* omitted year */ + *year = 0; + p = ++s; + i++; + } + + while(*s) { + if(isdigit(*s)) { + s++; + continue; + } else if(*s == '-') { + if(++i > 3) + return FALSE; + *s++ = '\0'; + switch(i) { + case 1: *year = atoi(p); break; + case 2: *month = atoi(p); break; + } + p = s; + } else + return FALSE; + } + + if (i != 2 || !*p) + return FALSE; + + *day = atoi(p); + + return is_valid_date(*day, *month, *year); +} + +static int +is_number(char *s) +{ + char *p; + + for(p = s; *p; p++) + if(!isdigit(*p)) + return FALSE; + return TRUE; +} + +static void +edit_date(int item, int nb) +{ + int i, date[3], old = FALSE; + char buf[12], *s = db_fget_byid(item, nb); + char *field[] = { N_("Day: "), N_("Month: "), N_("Year (optional): ") }; + + if(s) { + strncpy(buf, s, sizeof(buf)); + old = parse_date_string(buf, &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])) { + s = strdup_printf(date[2] ? "%04d-%02d-%02d" : "%c-%02d-%02d", + date[2] ? date[2] : '-', 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 */ @@ -439,9 +564,8 @@ edit_field(int tab, char c, int item_number) case FIELD_EMAILS: edit_list(item_number, idx, 1); break; - case FIELD_DAY: - statusline_msg(_("sorry, input for this field type is " - "not yet implemented")); + case FIELD_DATE: + edit_date(item_number, idx); return; default: assert(0); diff --git a/sample.abookrc b/sample.abookrc index 315192d..b324f92 100644 --- a/sample.abookrc +++ b/sample.abookrc @@ -19,12 +19,12 @@ # # syntax: field = [ , ] # -# with being one of 'string' (default), 'emails', 'list', or 'day' +# with being one of 'string' (default), 'emails', 'list', or 'date' # # Example of field definitions: field pager = Pager field address_lines = Address, list -field birthday = Birthday, day +field birthday = Birthday, date # Defining a view/tab