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