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();