]> git.deb.at Git - pkg/abook.git/blob - list.c
- mbswidth change to avoid empty translation unit warnings
[pkg/abook.git] / list.c
1
2 /*
3  * $Id$
4  *
5  * by JH <jheinonen@users.sourceforge.net>
6  *
7  * Copyright (C) Jaakko Heinonen
8  */
9
10 #include <stdio.h>
11 #include <string.h>
12 #include "abook.h"
13 #include <assert.h>
14 #include "ui.h"
15 #include "database.h"
16 #include "edit.h"
17 #include "list.h"
18 #include "misc.h"
19 #include "options.h"
20 #include "xmalloc.h"
21
22 #define MIN_EXTRA_COLUMN        ADDRESS /* 2 */
23 #define MAX_EXTRA_COLUMN        LAST_FIELD
24
25 int curitem = -1;
26 int first_list_item = -1;
27 char *selected = NULL;
28
29 int extra_column = -1;
30 int extra_alternative = -1;
31
32 extern int items;
33 extern list_item *database;
34 extern struct abook_field abook_fields[];
35
36 static WINDOW *list = NULL;
37
38 static int
39 init_extra_field(enum str_opts option)
40 {
41         int i, ret = -1;
42         char *option_str;
43
44         option_str = opt_get_str(option);
45
46         if(option_str && *option_str) {
47                 for(i = 0; i < ITEM_FIELDS; i++) {
48                         if(!strcasecmp(option_str, abook_fields[i].key)) {
49                                 ret = i;
50                                 break;
51                         }
52                 }
53                 if(ret < MIN_EXTRA_COLUMN || ret > MAX_EXTRA_COLUMN) {
54                         ret = -1;
55                 }
56         }
57
58         return ret;
59 }
60
61 void
62 init_list()
63 {
64         list = newwin(LIST_LINES, LIST_COLS, LIST_TOP, 0);
65         scrollok(list, TRUE);
66
67         /*
68          * init extra_column and extra alternative
69          */
70
71         extra_column = init_extra_field(STR_EXTRA_COLUMN);
72         extra_alternative = init_extra_field(STR_EXTRA_ALTERNATIVE);
73 }
74
75 void
76 close_list()
77 {
78         delwin(list);
79         list = NULL;
80 }
81
82 void
83 refresh_list()
84 {
85         int i, line;
86
87         werase(list);
88
89         ui_print_number_of_items();
90
91         if(list_is_empty()) {
92                 refresh();
93                 wrefresh(list);
94                 return;
95         }
96
97         if(curitem < 0)
98                 curitem = 0;
99
100         if(first_list_item < 0)
101                 first_list_item = 0;
102
103         if(curitem < first_list_item)
104                 first_list_item = curitem;
105         else if(curitem > LAST_LIST_ITEM)
106                 first_list_item = max(curitem - LIST_LINES + 1, 0);
107
108         for( line = 0, i = first_list_item ; i <= LAST_LIST_ITEM && i < items;
109                         line++, i++ ) {
110
111                 print_list_line(i, line, i == curitem);
112         }
113
114         if(opt_get_bool(BOOL_SHOW_CURSOR)) {
115                 wmove(list, curitem - first_list_item, 0);
116                 /* need to call refresh() to update the cursor positions */
117                 refresh();
118         }
119         wrefresh(list);
120 }
121
122 void
123 print_list_line(int i, int line, int highlight)
124 {
125         int extra = extra_column;
126         char tmp[MAX_EMAILSTR_LEN];
127         int real_emaillen = (extra_column > 0 || extra_alternative > 0) ?
128                 EMAILLEN : COLS - EMAILPOS;
129
130         scrollok(list, FALSE);
131         if(highlight)
132                 highlight_line(list, line);
133
134         if(selected[i])
135                 mvwaddch(list, line, 0, '*' );
136
137         mvwaddnstr(list, line, NAMEPOS, database[i][NAME],
138                 bytes2width(database[i][NAME], NAMELEN));
139         if(opt_get_bool(BOOL_SHOW_ALL_EMAILS))
140                 mvwaddnstr(list, line, EMAILPOS, database[i][EMAIL],
141                                 bytes2width(database[i][EMAIL], real_emaillen));
142         else {
143                 get_first_email(tmp, i);
144                 mvwaddnstr(list, line, EMAILPOS, tmp,
145                         bytes2width(tmp, real_emaillen));
146         }
147
148         if(extra < 0 || !database[i][extra])
149                 extra = extra_alternative;
150         if(extra >= 0)
151                 mvwaddnstr(list, line, EXTRAPOS,
152                         safe_str(database[i][extra]),
153                         bytes2width(safe_str(database[i][extra]), EXTRALEN));
154
155         scrollok(list, TRUE);
156         if(highlight)
157                 wstandend(list);
158 }
159
160
161 void
162 list_headerline()
163 {
164 #if defined(A_BOLD) && defined(A_NORMAL)
165         attrset(A_BOLD);
166 #endif
167         mvaddstr(2, NAMEPOS, abook_fields[NAME].name);
168         mvaddstr(2, EMAILPOS, abook_fields[EMAIL].name);
169         if(extra_column > 0)
170                 mvaddnstr(2, EXTRAPOS, abook_fields[extra_column].name,
171                                 COLS-EXTRAPOS);
172 #if defined(A_BOLD) && defined(A_NORMAL)
173         attrset(A_NORMAL);
174 #endif
175 }
176
177 void
178 scroll_up()
179 {
180         if(curitem < 1)
181                 return;
182
183         curitem--;
184
185         refresh_list();
186 }
187
188 void
189 scroll_down()
190 {
191         if(curitem > items - 2)
192                 return;
193
194         curitem++;
195
196         refresh_list();
197 }
198
199
200 void
201 page_up()
202 {
203         if(curitem < 1)
204                 return;
205
206         curitem = curitem == first_list_item ?
207                 ((curitem -= LIST_LINES) < 0 ? 0 : curitem) : first_list_item;
208
209         refresh_list();
210 }
211
212 void
213 page_down()
214 {
215         if(curitem > items - 2)
216                 return;
217
218         curitem = curitem == LAST_LIST_ITEM ?
219                 ((curitem += LIST_LINES) > LAST_ITEM ? LAST_ITEM : curitem) :
220                 min(LAST_LIST_ITEM, LAST_ITEM);
221
222         refresh_list();
223 }
224
225 void
226 select_none()
227 {
228         memset(selected, 0, items);
229 }
230
231 void
232 select_all()
233 {
234         memset(selected, 1, items);
235 }
236
237 void
238 move_curitem(int direction)
239 {
240         list_item tmp;
241
242         if( curitem < 0 || curitem > LAST_ITEM )
243                 return;
244
245         itemcpy(tmp, database[curitem]);
246
247         switch(direction) {
248                 case MOVE_ITEM_UP:
249                         if( curitem < 1 )
250                                 return;
251                         itemcpy(database[curitem], database[curitem - 1]);
252                         itemcpy(database[curitem-1], tmp);
253                         scroll_up();
254                         break;
255
256                 case MOVE_ITEM_DOWN:
257                         if( curitem >= LAST_ITEM )
258                                 return;
259                         itemcpy(database[curitem], database[curitem + 1]);
260                         itemcpy(database[curitem+1], tmp);
261                         scroll_down();
262                         break;
263         }
264 }
265
266 void
267 goto_home()
268 {
269         if(items > 0)
270                 curitem = 0;
271
272         refresh_list();
273 }
274
275 void
276 goto_end()
277 {
278         if(items > 0)
279                 curitem = LAST_ITEM;
280
281         refresh_list();
282 }
283
284
285 void
286 highlight_line(WINDOW *win, int line)
287 {
288         wstandout(win);
289
290         /*
291          * this is a tricky one
292          */
293 #if 0
294 /*#ifdef mvwchgat*/
295         mvwchgat(win, line, 0, -1,  A_STANDOUT, 0, NULL);
296 #else
297         /*
298          * buggy function: FIXME
299          */
300         scrollok(win, FALSE);
301         {
302                 int i;
303                 wmove(win, line, 0);
304                 for(i = 0; i < COLS; i++)
305                         waddch(win, ' ');
306         /*wattrset(win, 0);*/
307         }
308         scrollok(win, TRUE);
309 #endif
310 }
311
312 int
313 selected_items()
314 {
315         int i, n = 0;
316
317         for(i = 0; i < items; i++)
318                 if(selected[i])
319                         n++;
320
321         return n;
322 }
323
324 void
325 invert_selection()
326 {
327         int i;
328
329         if(items < 1)
330                 return;
331
332         for(i = 0; i < items; i++)
333                 selected[i] = !selected[i];
334 }
335
336 int
337 list_current_item()
338 {
339         return curitem;
340 }
341
342 int
343 list_is_empty()
344 {
345         return items < 1;
346 }
347
348 int
349 duplicate_item()
350 {
351         int i;
352         list_item item;
353
354         if(curitem < 0)
355                 return 1;
356
357         for(i = 0; i < ITEM_FIELDS; i++)
358                 item[i] = database[curitem][i] ? xstrdup(database[curitem][i]) :
359                         NULL;
360
361         if(add_item2database(item))
362                 return 1;
363
364         curitem = LAST_ITEM;
365         refresh_list();
366
367         return 0;
368 }
369