]> git.deb.at Git - pkg/abook.git/blob - edit.c
initial custom field support
[pkg/abook.git] / edit.c
1
2 /*
3  * $Id$
4  *
5  * by JH <jheinonen@users.sourceforge.net>
6  *
7  * Copyright (C) Jaakko Heinonen
8  */
9
10 #include <string.h>
11 #include <stdlib.h>
12 #include "abook_curses.h"
13 #include "ui.h"
14 #include "abook.h"
15 #include "database.h"
16 #include "list.h"
17 #include "edit.h"
18 #include "misc.h"
19 #ifdef HAVE_CONFIG_H
20 #       include "config.h"
21 #endif
22
23 /*
24  * some extern variables
25  */
26
27 extern struct abook_field abook_fields[];
28
29 extern list_item *database;
30 extern int curitem;
31 extern int items;
32
33 WINDOW *editw;
34
35 static void
36 editor_tab(int tab)
37 {
38         int i;
39         int spacing = 12;
40         char *tab_names[] = {
41                 "CONTACT",
42                 "ADDRESS",
43                 " PHONE ",
44                 " OTHER ",
45                 "CUSTOM "
46         };
47
48         mvwhline(editw, TABLINE+1, 0, UI_HLINE_CHAR, EDITW_COLS);
49         for(i=0; i < TABS; i++) {
50                 mvwaddch(editw,  TABLINE+1, spacing * i + 2,  UI_TEE_CHAR);
51                 mvwaddch(editw,  TABLINE+1, spacing * i + 12, UI_TEE_CHAR);
52         }
53
54         for(i=0; i < TABS; i++) {
55                 mvwaddch(editw,  TABLINE, spacing * i + 2,  UI_ULCORNER_CHAR);
56                 mvwaddch(editw,  TABLINE, spacing * i + 3,  UI_LBOXLINE_CHAR);
57                 mvwaddstr(editw, TABLINE, spacing * i + 4,  tab_names[i]);
58                 mvwaddch(editw,  TABLINE, spacing * i + 11, UI_RBOXLINE_CHAR);
59                 mvwaddch(editw,  TABLINE, spacing * i + 12, UI_URCORNER_CHAR);
60         }
61
62         mvwaddch(editw,  TABLINE+1, spacing * tab + 2, UI_LRCORNER_CHAR);
63         mvwaddstr(editw, TABLINE+1, spacing * tab + 3, "         ");
64         mvwaddch(editw,  TABLINE+1, spacing * tab + 12, UI_LLCORNER_CHAR);
65 }
66
67 void
68 get_first_email(char *str, int item)
69 {
70         char *tmp;
71
72         if(database[item][EMAIL] == NULL) {
73                 *str = 0;
74                 return;
75         }
76
77         strncpy(str, database[item][EMAIL], MAX_EMAIL_LEN);
78         if( (tmp = strchr(str, ',')) )
79                 *tmp=0;
80         else
81                 str[MAX_EMAIL_LEN-1] = 0;
82 }
83
84 static void
85 roll_emails(int item)
86 {
87         char tmp[MAX_EMAILSTR_LEN];
88         char *p;
89
90         strcpy(tmp, database[item][EMAIL]);
91
92         if( !(p = strchr(tmp, ',')) )
93                 return;
94         else
95                 *p=0;
96
97         strcpy(database[item][EMAIL], p+1);
98         strcat(database[item][EMAIL], ",");
99         strcat(database[item][EMAIL], tmp);     
100 }
101
102 static void
103 init_editor()
104 {
105         clear();
106         editw = newwin(EDITW_LINES, EDITW_COLS, EDITW_TOP, EDITW_X);
107
108         refresh_statusline();
109 }
110
111 /*
112  * we have to introduce edit_undo here
113  */
114 static void edit_undo(int item, int mode);
115
116 enum {
117         BACKUP_ITEM,
118         RESTORE_ITEM,
119         CLEAR_UNDO
120 };
121
122
123 static void
124 close_editor()
125 {
126         edit_undo(-1, CLEAR_UNDO);
127         delwin(editw);
128         refresh_screen();
129 }
130
131 static void
132 print_editor_header(int item)
133 {
134         char *header;
135         char email[MAX_EMAIL_LEN];
136
137         if( (header = (char *)malloc(EDITW_COLS)) == NULL )
138                 return;
139
140         get_first_email(email, item);
141
142         if( *database[item][EMAIL] )
143                 snprintf(header, EDITW_COLS, "%s <%s>",
144                                 database[item][NAME],
145                                 email);
146         else
147                 snprintf(header, EDITW_COLS, "%s", database[item][NAME]);
148
149         mvwaddstr(editw, 0, (EDITW_COLS - strlen(header)) / 2,
150                         header);
151
152         free(header);
153 }
154
155 static void
156 editor_print_data(int tab, int item)
157 {
158         int i, j;
159         int y, x;
160
161         for(i = 0, j = 1; i < ITEM_FIELDS; i++) {
162                 if(abook_fields[i].tab != tab)
163                         continue;
164
165                 if(i==EMAIL) { /* special field */
166                         int k;
167                         char emails[MAX_EMAILS][MAX_EMAIL_LEN];
168                         split_emailstr(item, emails);
169                         getyx(editw, y, x);
170                         mvwaddstr(editw, y+1, FIELDS_START_X,
171                                         "E-mail addresses:");
172                         for(k = 0; k < MAX_EMAILS; k++) {
173                                 getyx(editw, y, x);
174                                 mvwprintw(editw, y+1, FIELDS_START_X,
175                                 "%c -", '2' + k);
176                                 mvwprintw(editw, y +1, TAB_COLON_POS,
177                                                 ": %s", emails[k]);
178                         }
179                         continue;
180                 }
181
182                 if(j > 1) {
183                         getyx(editw, y, x); y++;
184                 } else
185                         y = FIELDS_START_Y;
186
187                 mvwprintw(editw, y, FIELDS_START_X, "%d - %s",
188                                 j,
189                                 abook_fields[i].name);
190                 mvwaddch(editw, y, TAB_COLON_POS, ':');
191                 mvwaddstr(editw, y, TAB_COLON_POS + 2,
192                                 safe_str(database[item][i]));
193
194                 j++;
195         }
196 }
197
198 /*
199  * function: change_field
200  *
201  * parameters:
202  *  (char *msg)
203  *   message to display as a prompt
204  *  (char **field)
205  *   a pointer to a pointer which will point a new string. if the latter
206  *   pointer != NULL it will be freed (if user doesn't cancel)
207  *
208  * returns (int)
209  *  a nonzero value if user has cancelled and zero if user has typed a
210  *  valid string
211  */
212
213 static int
214 change_field(char *msg, char **field)
215 {
216         int max_len = MAX_FIELD_LEN;
217         char *old;
218         int ret = 0;
219
220         if( !strncmp("E-mail", msg, 6) )
221                 max_len = MAX_EMAIL_LEN;
222
223         old = *field;
224
225         *field = ui_readline(msg, old, max_len - 1, 0);
226
227         if(*field) {
228                 free(old);
229                 if(!**field)
230                         my_free(*field);
231         } else {
232                 *field = old;
233                 ret = 1;
234         }
235
236         clear_statusline();
237         refresh_statusline();
238
239         return ret;
240 }
241
242 static void
243 change_name_field(char **field)
244 {
245         char *tmp;
246
247         tmp = strdup(*field);
248         change_field("Name: ", field);
249
250         if( *field == NULL || ! **field ) {
251                 my_free(*field);
252                 *field = strdup(tmp);
253         }
254
255         my_free(tmp);
256 }
257
258 static void
259 fix_email_str(char *str)
260 {
261         for(; *str; str++ )
262                 *str = *str == ',' ? '_' : *str;
263 }
264
265 static void
266 edit_emails(char c, int item)
267 {
268         char *field;
269         char emails[MAX_EMAILS][MAX_EMAIL_LEN];
270         char tmp[MAX_EMAILSTR_LEN] = "";
271         int i, len;
272         int email_num = c - '2';
273
274         split_emailstr(item, emails);
275         field = strdup(emails[email_num]);
276
277         if(change_field("E-mail: ", &field))
278                 return; /* user cancelled ( C-g ) */
279
280         if(field) {
281                 strncpy(emails[email_num], field, MAX_EMAIL_LEN);
282                 fix_email_str(emails[email_num]);
283         } else
284                 *emails[email_num] = 0;
285
286         my_free(database[item][EMAIL]);
287
288         for(i = 0; i < MAX_EMAILS; i++) {
289                 if( *emails[i] ) {
290                         strcat(tmp, emails[i]);
291                         strcat(tmp, ",");
292                 }
293         }
294
295         len = strlen(tmp);
296         if(tmp[len -1] == ',')
297                 tmp[len-1] =0;
298
299         database[item][EMAIL] = strdup(tmp);
300 }
301
302 static int
303 edit_field(int tab, char c, int item)
304 {
305         int i, j;
306         int n = c - '1' + 1;
307         char *str;
308
309         if(n < 1 || n > MAX_TAB_FIELDS)
310                 return 0;
311
312         edit_undo(item, BACKUP_ITEM);
313
314         if(tab == TAB_CONTACT) {
315                 switch(c) {
316                         case '1': change_name_field(&database[item][NAME]);
317                                   break;
318                         case '2':
319                         case '3':
320                         case '4':
321                         case '5': edit_emails(c, item); break;
322                         default: return 0;
323                 }
324                 return 1;
325         }
326
327         for(i=0, j=0; i< ITEM_FIELDS; i++) {
328                 if(abook_fields[i].tab == tab)
329                         j++;
330                 if(j==n)
331                         break;
332         }
333
334         if(j!=n)
335                 return 0;
336
337         str = mkstr("%s: ", abook_fields[i].name);
338         change_field(str, &database[item][i]);
339
340         free(str);
341
342         return 1;
343 }
344
345 static void
346 edit_undo(int item, int mode)
347 {
348         int i;
349         static list_item *backup = NULL;
350
351         switch(mode) {
352                 case CLEAR_UNDO:
353                         if(backup) {
354                                 free_list_item(backup[0]);
355                                 my_free(backup);
356                         }
357                         break;
358                 case BACKUP_ITEM:
359                         if(backup) {
360                                 free_list_item(backup[0]);
361                                 my_free(backup);
362                         }
363                         backup = (list_item *)abook_malloc(sizeof(list_item));
364                         for(i = 0; i < ITEM_FIELDS; i++)
365                                 backup[0][i] = safe_strdup(database[item][i]);
366                         break;
367                 case RESTORE_ITEM:
368                         if(backup) {
369                                 free_list_item(database[item]);
370                                 itemcpy(database[item], backup[0]);
371                                 my_free(backup);
372                         }
373                         break;
374         }
375 }
376
377 static int
378 edit_loop(int item)
379 {
380         static int tab = 0; /* first tab */
381         int c;
382
383         werase(editw);
384         headerline(EDITOR_HELPLINE);
385         refresh_statusline();
386         print_editor_header(item);
387         editor_tab(tab);
388         editor_print_data(tab, item);
389         wmove(editw, EDITW_LINES - 1, EDITW_COLS - 1);
390
391         refresh();
392         wrefresh(editw);
393
394         switch( (c = getch()) ) {
395                 case 'c': tab = TAB_CONTACT; break;
396                 case 'a': tab = TAB_ADDRESS; break;
397                 case 'p': tab = TAB_PHONE; break;
398                 case 'o': tab = TAB_OTHER; break;
399                 case 'h':
400                 case KEY_LEFT: tab = tab == 0 ? MAX_TAB : tab - 1;
401                                break;
402                 case 'l':
403                 case KEY_RIGHT: tab = tab == MAX_TAB ? 0 : tab + 1;
404                                 break;
405                 case KEY_UP:
406                 case '<':
407                 case 'k': if(is_valid_item(item-1)) item--; break;
408                 case KEY_DOWN:
409                 case '>':
410                 case 'j': if(is_valid_item(item+1)) item++; break;
411                 case 'r': roll_emails(item); break;
412                 case '?': display_help(HELP_EDITOR); break;
413                 case 'u': edit_undo(item, RESTORE_ITEM); break;
414                 case 'm': launch_mutt(item); clearok(stdscr, 1); break;
415                 case 'v': launch_wwwbrowser(item); clearok(stdscr, 1); break;
416                 case 12 : clearok(stdscr, 1); break; /* ^L (refresh screen) */
417                 default:  return edit_field(tab, c, item) ? item : -1;
418         }
419
420         return item;
421 }
422
423 void
424 edit_item(int item)
425 {
426         if( item < 0 ) {
427                 if( curitem < 0 )
428                         return;
429                 else
430                         item = curitem;
431         }
432
433         init_editor();
434
435         while( (item = edit_loop(item)) >= 0 )
436                 curitem = item; /* hmm, this is not very clean way to go */
437
438         close_editor();
439 }
440
441 void
442 add_item()
443 {
444         char *field = NULL;
445         list_item item;
446
447         change_field("Name: ", &field);
448
449         if( field == NULL )
450                 return;
451
452         memset(item, 0, sizeof(item));
453
454         item[NAME] = field;
455
456         add_item2database(item);
457
458         curitem = LAST_ITEM;
459
460         edit_item(LAST_ITEM);
461 }
462