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