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