1 /*
2  *  rolo - contact management software
3  *  Copyright (C) 2003  Andrew Hsu
4  *
5  *  This program is free software; you can redistribute it and/or
6  *  modify it under the terms of the GNU General Public License as
7  *  published by the Free Software Foundation; either version 2 of
8  *  the License, or (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18  *  02111-1307 USA
19  *
20  *  $Id: view.c,v 1.15 2003/05/20 01:08:52 ahsu Rel $
21  */
22 
23 #include "view.h"
24 #include <assert.h>
25 #include <limits.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <sys/stat.h>
30 #include <sys/types.h>
31 
32 #define MENU_BAR_STRING "i:Index  h:Help  1:Ident  2:Geo  3:Tel  4:Org  5:Misc"
33 #define HEADING_IDENT_STRING "IDENTIFICATION"
34 #define HEADING_GEO_STRING "GEOGRAPHIC POSITION"
35 #define HEADING_TEL_STRING "TELECOMMUNICATION"
36 #define HEADING_ORG_STRING "ORGANIZATION"
37 #define HEADING_MISC_STRING "MISCELLANEOUS"
38 
39 /*** PROTOTYPES ***/
40 static void print_header ();
41 static void print_footer (int entry_number, const char *fn);
42 static void view_ident ();
43 static void view_geo ();
44 static void view_tel ();
45 static void view_org ();
46 static void view_misc ();
47 static char *basename (const char *path);
48 static void view_left ();
49 static void view_right ();
50 
51 enum view_modes
52 { VIEW_IDENT = 1, VIEW_GEO, VIEW_TEL, VIEW_ORG, VIEW_MISC };
53 
54 /*** STATIC VARIABLES ***/
55 static WINDOW *win = NULL;
56 static WINDOW *sub = NULL;
57 static void (*display_help) (void);
58 static vc_component *g_v = NULL;
59 static int g_mode = 1;
60 
61 /***************************************************************************
62  */
63 
64 static void
view_left()65 view_left ()
66 {
67   switch (g_mode)
68     {
69     case VIEW_IDENT:
70       view_misc ();
71       break;
72     case VIEW_GEO:
73       view_ident ();
74       break;
75     case VIEW_TEL:
76       view_geo ();
77       break;
78     case VIEW_ORG:
79       view_tel ();
80       break;
81     case VIEW_MISC:
82       view_org ();
83       break;
84     default:
85       break;
86     }
87 }
88 
89 /***************************************************************************
90  */
91 
92 static void
view_right()93 view_right ()
94 {
95   switch (g_mode)
96     {
97     case VIEW_IDENT:
98       view_geo ();
99       break;
100     case VIEW_GEO:
101       view_tel ();
102       break;
103     case VIEW_TEL:
104       view_org ();
105       break;
106     case VIEW_ORG:
107       view_misc ();
108       break;
109     case VIEW_MISC:
110       view_ident ();
111       break;
112     default:
113       break;
114     }
115 }
116 
117 /***************************************************************************
118     Initialize the view window without displaying it to the
119     end-user.
120  */
121 
122 void
init_view()123 init_view ()
124 {
125   win = newwin (0, 0, 0, 0);
126   sub = derwin (win, LINES - 3, COLS, 1, 0);
127   print_header ();
128   keypad (win, TRUE);           /* enable keypad for use of arrow keys */
129 }
130 
131 /***************************************************************************
132  */
133 
134 static char *
basename(const char * path)135 basename (const char *path)
136 {
137   char *beginning = NULL;
138   char *retval = NULL;
139 
140   beginning = strrchr (path, '/');
141 
142   if (NULL == beginning)
143     {
144       retval = strdup (path);
145     }
146   else
147     {
148       retval = strdup (beginning);
149     }
150 
151   return retval;
152 }
153 
154 /***************************************************************************
155  */
156 
157 static void
view_ident()158 view_ident ()
159 {
160   vc_component *vc = NULL;
161   char *val = NULL;
162   int x = 0;
163   int y = 0;
164 
165   g_mode = VIEW_IDENT;
166 
167   werase (sub);
168 
169   x = (COLS - strlen (HEADING_IDENT_STRING)) / 2;
170   y = 1;
171 
172   wattron (sub, A_UNDERLINE);
173   mvwprintw (sub, y, x, HEADING_IDENT_STRING);
174   wstandend (sub);
175   wmove (sub, 3, 0);
176 
177   vc = vc_get_next_by_name (g_v, VC_FORMATTED_NAME);
178   val = vc_get_value (vc);
179   wprintw (sub, "Name         : %s\n", val ? val : "");
180 
181   vc = vc_get_next_by_name (g_v, VC_NICKNAME);
182   val = vc_get_value (vc);
183   wprintw (sub, "Nickname     : %s\n", val ? val : "");
184 
185   vc = vc_get_next_by_name (g_v, VC_BIRTHDAY);
186   val = vc_get_value (vc);
187   wprintw (sub, "Birthday     : %s\n", val ? val : "");
188 
189   wprintw (sub, "\n");
190 
191   vc = vc_get_next_by_name (g_v, VC_URL);
192   val = vc_get_value (vc);
193   wprintw (sub, "URL    : %s\n", val ? val : "");
194 
195   vc = vc_get_next_by_name (g_v, VC_PHOTO);
196   val = vc_get_value (vc);
197   wprintw (sub, "Photo  : %s\n", val ? val : "");
198 
199   vc = vc_get_next_by_name (g_v, VC_SOUND);
200   val = vc_get_value (vc);
201   wprintw (sub, "Sound  : %s\n", val ? val : "");
202 
203   wprintw (sub, "\n");
204 
205   vc = vc_get_next_by_name (g_v, VC_CATEGORIES);
206   val = vc_get_value (vc);
207   wprintw (sub, "Categories  : %s\n", val ? val : "");
208 
209   vc = vc_get_next_by_name (g_v, VC_REVISION);
210   val = vc_get_value (vc);
211   wprintw (sub, "Revision    : %s\n", val ? val : "");
212 
213   vc = vc_get_next_by_name (g_v, VC_NOTE);
214   val = vc_get_value (vc);
215   wprintw (sub, "Note        : %s\n", val ? val : "");
216 
217   touchwin (win);
218   wrefresh (sub);
219   wrefresh (win);
220 }
221 
222 /***************************************************************************
223  */
224 
225 static void
view_geo()226 view_geo ()
227 {
228   vc_component *vc = NULL;
229   char *str = NULL;
230   char *val = NULL;
231   int x = 0;
232   int y = 0;
233 
234   g_mode = VIEW_GEO;
235 
236   werase (sub);
237 
238   x = (COLS - strlen (HEADING_GEO_STRING)) / 2;
239   y = 1;
240 
241   wattron (sub, A_UNDERLINE);
242   mvwprintw (sub, y, x, HEADING_GEO_STRING);
243   wstandend (sub);
244   wmove (sub, 3, 0);
245 
246   vc = vc_get_next_by_name (g_v, VC_GEOGRAPHIC_POSITION);
247   val = vc_get_value (vc);
248 
249   str = get_val_struct_part (val, GEO_LATITUDE);
250   wprintw (sub, "Latitude   : %s\n", str ? str : "");
251   free (str);
252 
253   str = get_val_struct_part (val, GEO_LONGITUDE);
254   wprintw (sub, "Longitude  : %s\n", str ? str : "");
255   free (str);
256 
257   wprintw (sub, "\n");
258   vc = vc_get_next_by_name (g_v, VC_TIME_ZONE);
259   val = vc_get_value (vc);
260   wprintw (sub, "Time Zone  : %s\n", val ? val : "");
261 
262   wprintw (sub, "\n");
263 
264   vc = vc_get_next_by_name (g_v, VC_ADDRESS);
265   val = vc_get_value (vc);
266 
267   str = get_val_struct_part (val, ADR_PO_BOX);
268   wprintw (sub, "Post Office Box   : %s\n", str ? str : "");
269   free (str);
270 
271   str = get_val_struct_part (val, ADR_EXT_ADDRESS);
272   wprintw (sub, "Extended Address  : %s\n", str ? str : "");
273   free (str);
274 
275   str = get_val_struct_part (val, ADR_STREET);
276   wprintw (sub, "Street Address    : %s\n", str ? str : "");
277   free (str);
278 
279   str = get_val_struct_part (val, ADR_LOCALITY);
280   wprintw (sub, "Locality          : %s\n", str ? str : "");
281   free (str);
282 
283   str = get_val_struct_part (val, ADR_REGION);
284   wprintw (sub, "Region            : %s\n", str ? str : "");
285   free (str);
286 
287   str = get_val_struct_part (val, ADR_POSTAL_CODE);
288   wprintw (sub, "Postal Code       : %s\n", str ? str : "");
289   free (str);
290 
291   str = get_val_struct_part (val, ADR_COUNTRY);
292   wprintw (sub, "Country           : %s\n", str ? str : "");
293   free (str);
294 
295   wprintw (sub, "\n");
296   touchwin (win);
297   wrefresh (sub);
298   wrefresh (win);
299 }
300 
301 /***************************************************************************
302  */
303 
304 static void
view_tel()305 view_tel ()
306 {
307   vc_component *vc = NULL;
308   char *val = NULL;
309   int x = 0;
310   int y = 0;
311   int i = 0;
312 
313   g_mode = VIEW_TEL;
314 
315   werase (sub);
316 
317   x = (COLS - strlen (HEADING_TEL_STRING)) / 2;
318   y = 1;
319 
320   wattron (sub, A_UNDERLINE);
321   mvwprintw (sub, y, x, HEADING_TEL_STRING);
322   wstandend (sub);
323   wmove (sub, 3, 0);
324 
325   for (i = 1, vc = g_v; i <= 5; i++)
326     {
327       vc = vc_get_next_by_name (vc, VC_TELEPHONE);
328       val = vc_get_value (vc);
329       wprintw (sub, "Telephone #%i  : %s\n", i, val ? val : "");
330     }
331 
332   wprintw (sub, "\n");
333 
334   for (i = 1, vc = g_v; i <= 5; i++)
335     {
336       vc = vc_get_next_by_name (vc, VC_EMAIL);
337       val = vc_get_value (vc);
338       wprintw (sub, "Email Address #%i  : %s\n", i, val ? val : "");
339     }
340 
341   wprintw (sub, "\n");
342 
343   vc = vc_get_next_by_name (g_v, VC_MAILER);
344   val = vc_get_value (vc);
345   wprintw (sub, "Email Mailer      : %s\n", val ? val : "");
346 
347   touchwin (win);
348   wrefresh (sub);
349   wrefresh (win);
350 }
351 
352 /***************************************************************************
353  */
354 
355 static void
view_org()356 view_org ()
357 {
358   vc_component *vc = NULL;
359   char *str = NULL;
360   char *val = NULL;
361   int x = 0;
362   int y = 0;
363 
364   g_mode = VIEW_ORG;
365 
366   werase (sub);
367 
368   x = (COLS - strlen (HEADING_ORG_STRING)) / 2;
369   y = 1;
370 
371   wattron (sub, A_UNDERLINE);
372   mvwprintw (sub, y, x, HEADING_ORG_STRING);
373   wstandend (sub);
374   wmove (sub, 3, 0);
375 
376   vc = vc_get_next_by_name (g_v, VC_TITLE);
377   val = vc_get_value (vc);
378   wprintw (sub, "Title  : %s\n", val ? val : "");
379 
380   vc = vc_get_next_by_name (g_v, VC_ROLE);
381   val = vc_get_value (vc);
382   wprintw (sub, "Role   : %s\n", val ? val : "");
383 
384   wprintw (sub, "\n");
385 
386   vc = vc_get_next_by_name (g_v, VC_ORGANIZATION);
387   val = vc_get_value (vc);
388 
389   str = get_val_struct_part (val, ORG_NAME);
390   wprintw (sub, "Organization Name       : %s\n", str ? str : "");
391   free (str);
392 
393   str = get_val_struct_part (val, ORG_UNIT_1);
394   wprintw (sub, "Organizational Unit #1  : %s\n", str ? str : "");
395   free (str);
396 
397   str = get_val_struct_part (val, ORG_UNIT_2);
398   wprintw (sub, "Organizational Unit #2  : %s\n", str ? str : "");
399   free (str);
400 
401   str = get_val_struct_part (val, ORG_UNIT_3);
402   wprintw (sub, "Organizational Unit #3  : %s\n", str ? str : "");
403   free (str);
404 
405   str = get_val_struct_part (val, ORG_UNIT_4);
406   wprintw (sub, "Organizational Unit #4  : %s\n", str ? str : "");
407   free (str);
408 
409   wprintw (sub, "\n");
410 
411   vc = vc_get_next_by_name (g_v, VC_LOGO);
412   val = vc_get_value (vc);
413   wprintw (sub, "Logo  : %s\n", val ? val : "");
414 
415   vc = vc_get_next_by_name (g_v, VC_AGENT);
416   val = vc_get_value (vc);
417   wprintw (sub, "Agent  : %s\n", val ? val : "");
418 
419   touchwin (win);
420   wrefresh (sub);
421   wrefresh (win);
422 }
423 
424 /***************************************************************************
425  */
426 
427 static void
view_misc()428 view_misc ()
429 {
430   vc_component *vc = NULL;
431   char *str = NULL;
432   char *val = NULL;
433   int x = 0;
434   int y = 0;
435 
436   g_mode = VIEW_MISC;
437 
438   werase (sub);
439 
440   x = (COLS - strlen (HEADING_MISC_STRING)) / 2;
441   y = 1;
442 
443   wattron (sub, A_UNDERLINE);
444   mvwprintw (sub, y, x, HEADING_MISC_STRING);
445   wstandend (sub);
446   wmove (sub, 3, 0);
447 
448   vc = vc_get_next_by_name (g_v, VC_SORT_STRING);
449   val = vc_get_value (vc);
450   wprintw (sub, "Sort String  : %s\n", val ? val : "");
451 
452   vc = vc_get_next_by_name (g_v, VC_CLASS);
453   val = vc_get_value (vc);
454   wprintw (sub, "Class       : %s\n", val ? val : "");
455 
456   vc = vc_get_next_by_name (g_v, VC_KEY);
457   val = vc_get_value (vc);
458   wprintw (sub, "Public Key  : %s\n", val ? val : "");
459 
460   touchwin (win);
461   wrefresh (sub);
462   wrefresh (win);
463 }
464 
465 /***************************************************************************
466     Display the given vCard to the end-user.
467  */
468 
469 void
view_vcard(int entry_number,vc_component * v)470 view_vcard (int entry_number, vc_component * v)
471 {
472   vc_component *vc = NULL;
473   char *val = NULL;
474 
475   g_v = v;
476 
477   vc = vc_get_next_by_name (g_v, VC_FORMATTED_NAME);
478   val = vc_get_value (vc);
479   print_footer (entry_number, val ? val : "");
480 
481   switch (g_mode)
482     {
483     case VIEW_IDENT:
484       view_ident ();
485       break;
486     case VIEW_GEO:
487       view_geo ();
488       break;
489     case VIEW_TEL:
490       view_tel ();
491       break;
492     case VIEW_ORG:
493       view_org ();
494       break;
495     case VIEW_MISC:
496       view_misc ();
497       break;
498     default:
499       break;
500     }
501 
502 }
503 
504 /***************************************************************************
505     Prints the header to the window buffer, but does not display it
506     to the end-user.
507  */
508 
509 static void
print_header()510 print_header ()
511 {
512   char *header_str = NULL;
513   int i = 0;
514 
515   header_str = (char *) malloc (sizeof (char) * (COLS + 2));
516 
517   strncpy (header_str, MENU_BAR_STRING, COLS);
518 
519   for (i = strlen (MENU_BAR_STRING); i < COLS; i++)
520     {
521       header_str[i] = ' ';
522     }
523 
524   header_str[COLS] = '\n';
525   header_str[COLS + 1] = '\0';
526 
527   wattron (win, A_REVERSE);
528   wprintw (win, header_str);
529   wstandend (win);
530   free (header_str);
531 }
532 
533 /***************************************************************************
534     Prints the footer to the window buffer, but does not display it
535     to the end-user.  The contents of the footer depends on the
536     width of the screen.
537  */
538 
539 static void
print_footer(int entry_number,const char * fn)540 print_footer (int entry_number, const char *fn)
541 {
542   char *footer_str = NULL;
543   char *entry_block = NULL;
544   int entry_block_len = 0;
545   int i = 0;
546 
547   footer_str = (char *) malloc (sizeof (char) * (COLS + 2));
548 
549   /****************************************
550     initialize the footer string to dashes
551    ****************************************/
552 
553   for (i = 0; i < COLS; i++)
554     {
555       footer_str[i] = '-';
556     }
557 
558   if (NULL != fn)
559     {
560       entry_block_len = strlen (fn) + 18 + 3;   /* 3 for entry_number */
561     }
562   else
563     {
564       entry_block_len = 17 + 3; /* 3 for entry_number */
565     }
566 
567   /****************************************************
568     add the `entry' block only if there is enough room
569    ****************************************************/
570 
571   if (entry_block_len <= COLS)
572     {
573       entry_block = (char *) malloc (sizeof (char) * (entry_block_len + 1));
574 
575       if (NULL != fn)
576         {
577           sprintf (entry_block, "---[ entry %i: %s ]---", entry_number % 1000,
578                    fn);
579         }
580       else
581         {
582           sprintf (entry_block, "---[ entry %i ]---", entry_number % 1000);
583         }
584 
585       entry_block_len = strlen (entry_block);
586       for (i = 0; i < entry_block_len; i++)
587         {
588           footer_str[i] = entry_block[i];
589         }
590 
591       free (entry_block);
592     }
593 
594   footer_str[COLS] = '\n';
595   footer_str[COLS + 1] = '\0';
596 
597   wattron (win, A_REVERSE);
598   mvwprintw (win, LINES - 2, 0, footer_str);
599   wstandend (win);
600   free (footer_str);
601 }
602 
603 /***************************************************************************
604     Handle input from the end-user.
605  */
606 
607 int
process_view_commands()608 process_view_commands ()
609 {
610   bool done = FALSE;
611   int ch = 0;
612   int command = 0;
613 
614   while (!done)
615     {
616       ch = wgetch (win);
617 
618       switch (ch)
619         {
620         case '1':
621           view_ident ();
622           break;
623         case '2':
624           view_geo ();
625           break;
626         case '3':
627           view_tel ();
628           break;
629         case '4':
630           view_org ();
631           break;
632         case '5':
633           view_misc ();
634           break;
635         case KEY_DOWN:
636         case 'j':
637           command = VIEW_COMMAND_NEXT;
638           done = TRUE;
639           break;
640         case KEY_UP:
641         case 'k':
642           command = VIEW_COMMAND_PREVIOUS;
643           done = TRUE;
644           break;
645         case 'e':
646           command = VIEW_COMMAND_EDIT;
647           done = TRUE;
648           break;
649         case 'h':
650           (*display_help) ();
651           touchwin (win);
652           wrefresh (win);
653           wrefresh (sub);
654           break;
655         case 'i':
656         case 'q':
657           command = VIEW_COMMAND_INDEX;
658           g_mode = VIEW_IDENT;
659           done = TRUE;
660           break;
661         case 'V':
662           raw_view (g_v);
663           break;
664         case KEY_LEFT:
665           view_left ();
666           break;
667         case KEY_RIGHT:
668           view_right ();
669           break;
670         default:
671           beep ();
672           break;
673         }
674     }
675   return command;
676 }
677 
678 /***************************************************************************
679  */
680 
681 void
set_view_help_fcn(void (* fcn)(void))682 set_view_help_fcn (void (*fcn) (void))
683 {
684   display_help = fcn;
685 }
686 
687 /***************************************************************************
688  */
689 
690 void
raw_view(const vc_component * v)691 raw_view (const vc_component * v)
692 {
693   /* FIXME: have a simple scrolling raw display of the vcard */
694 }
695