3 * $Id: list.c,v 1.33 2006/09/05 08:21:35 jheinonen Exp $
5 * by JH <jheinonen@users.sourceforge.net>
7 * Copyright (C) Jaakko Heinonen
25 int first_list_item = -1;
26 char *selected = NULL;
28 extern abook_field_list *fields_list;
29 struct index_elem *index_elements = NULL;
31 static WINDOW *list = NULL;
35 index_elem_add(int type, char *a, char *b)
37 struct index_elem *tmp = NULL, *cur, *cur2;
45 tmp = xmalloc(sizeof(struct index_elem));
46 tmp->d.text = xstrdup(a);
48 case INDEX_FIELD: /* fall through */
50 find_field_number(a, &field);
53 len = (b && *b && is_number(b)) ? atoi(b) : 0;
54 tmp = xmalloc(sizeof(struct index_elem));
55 tmp->d.field.id = field;
56 tmp->d.field.len = len;
63 tmp->d.field.next = NULL;
65 if(!index_elements) { /* first element */
70 for(cur = index_elements; cur->next; cur = cur->next)
72 if(type != INDEX_ALT_FIELD)
74 else { /* add as an alternate field */
75 tmp->d.field.len = cur->d.field.len;
76 for(cur2 = cur; cur2->d.field.next; cur2 = cur2->d.field.next)
78 cur2->d.field.next = tmp;
83 parse_index_format(char *s)
85 char *p, *start, *lstart = NULL;
86 int in_field = 0, in_alternate = 0, in_length = 0, type;
91 if(*p == '{' && !in_field) {
93 index_elem_add(INDEX_TEXT, start, NULL);
96 } else if(*p == ':' && in_field && !in_alternate) {
100 } else if(*p == '|' && in_field) {
102 type = in_alternate ? INDEX_ALT_FIELD : INDEX_FIELD;
103 index_elem_add(type, start, in_length ? lstart : NULL);
107 } else if(*p == '}' && in_field) {
109 type = in_alternate ? INDEX_ALT_FIELD : INDEX_FIELD;
110 index_elem_add(type, start, in_length ? lstart : NULL);
112 in_field = in_alternate = in_length = 0;
117 index_elem_add(INDEX_TEXT, start, NULL);
123 assert(!index_elements);
124 parse_index_format(opt_get_str(STR_INDEX_FORMAT));
130 list = newwin(LIST_LINES, LIST_COLS, LIST_TOP, 0);
131 scrollok(list, TRUE);
142 get_list_field(int item, struct index_elem *e, struct list_field *res)
146 res->data = s = NULL;
148 do { /* find first non-empty field data in the alternate fields list */
149 s = db_fget_byid(item, e->d.field.id);
150 } while(!(s && *s) && ((e = e->d.field.next) != NULL));
156 get_field_info(e->d.field.id, NULL, NULL, &res->type);
160 print_list_field(int item, int line, int *x_pos, struct index_elem *e)
163 int width, x_start, mustfree = FALSE, len = abs(e->d.field.len);
166 get_list_field(item, e, &f);
174 if(f.type == FIELD_EMAILS && !opt_get_bool(BOOL_SHOW_ALL_EMAILS))
175 if((p = strchr(s, ',')) != NULL) {
176 s = xstrndup(s, p - s);
180 width = len ? bytes2width(s, len) : strwidth(s);
181 x_start = *x_pos + ((e->d.field.len < 0) ? len - width : 0);
182 if(width + x_start >= COLS)
183 width = COLS - x_start;
186 mvwaddnstr(list, line, x_start, s, width);
191 *x_pos += len ? len : width;
195 highlight_line(WINDOW *win, int line)
200 * this is a tricky one
204 mvwchgat(win, line, 0, -1, A_STANDOUT, 0, NULL);
207 * buggy function: FIXME
209 scrollok(win, FALSE);
213 for(i = 0; i < COLS; i++)
215 /*wattrset(win, 0);*/
222 print_list_line(int item, int line, int highlight)
224 struct index_elem *cur;
227 scrollok(list, FALSE);
229 highlight_line(list, line);
232 mvwaddch(list, line, 0, '*' );
234 for(cur = index_elements; cur; cur = cur->next)
237 mvwaddstr(list, line, x_pos, cur->d.text);
238 x_pos += strwidth(cur->d.text);
241 print_list_field(item, line, &x_pos, cur);
247 scrollok(list, TRUE);
259 ui_print_number_of_items();
261 if(list_is_empty()) {
270 if(first_list_item < 0)
273 if(curitem < first_list_item)
274 first_list_item = curitem;
275 else if(curitem > LAST_LIST_ITEM)
276 first_list_item = max(curitem - LIST_LINES + 1, 0);
278 for(line = 0, i = first_list_item;
279 i <= LAST_LIST_ITEM && i < db_n_items();
282 print_list_line(i, line, i == curitem);
285 if(opt_get_bool(BOOL_SHOW_CURSOR)) {
286 wmove(list, curitem - first_list_item, 0);
287 /* need to call refresh() to update the cursor positions */
296 struct index_elem *e;
297 int x_pos = 1, width;
300 #if defined(A_BOLD) && defined(A_NORMAL)
304 for(e = index_elements; e; e = e->next)
305 if(e->type == INDEX_TEXT)
306 x_pos += strwidth(e->d.text);
307 else if(e->type == INDEX_FIELD) {
308 get_field_info(e->d.field.id, NULL, &str, NULL);
309 width = e->d.field.len ? abs(e->d.field.len) : strwidth(str);
310 mvaddnstr(2, x_pos, str, width);
315 #if defined(A_BOLD) && defined(A_NORMAL)
334 if(curitem > db_n_items() - 2)
349 curitem = curitem == first_list_item ?
350 ((curitem -= LIST_LINES) < 0 ? 0 : curitem) : first_list_item;
358 if(curitem > db_n_items() - 2)
361 if(curitem == LAST_LIST_ITEM) {
362 if((curitem += LIST_LINES) > last_item())
363 curitem = last_item();
365 curitem = min(LAST_LIST_ITEM, last_item());
374 memset(selected, 0, db_n_items());
380 memset(selected, 1, db_n_items());
384 list_set_selection(int item, int value)
386 assert(is_valid_item(item));
388 selected[item] = !!value;
392 list_invert_curitem_selection()
394 assert(is_valid_item(curitem));
396 selected[curitem] = !selected[curitem];
400 move_curitem(int direction)
404 if(curitem < 0 || curitem > last_item())
408 item_copy(tmp, db_item_get(curitem));
414 item_copy(db_item_get(curitem),
415 db_item_get(curitem - 1));
416 item_copy(db_item_get(curitem-1), tmp);
421 if(curitem >= last_item())
423 item_copy(db_item_get(curitem),
424 db_item_get(curitem + 1));
425 item_copy(db_item_get(curitem + 1), tmp);
447 curitem = last_item();
457 for(i = 0; i < db_n_items(); i++)
472 for(i = 0; i < db_n_items(); i++)
473 selected[i] = !selected[i];
479 return db_n_items() < 1;
489 list_set_curitem(int i)
502 item = item_create();
503 item_duplicate(item, db_item_get(curitem));
504 if(add_item2database(item)) {
510 curitem = last_item();