1 /* -*- Mode: C++-C -*-
2 *
3 * Copyright 1994 Christopher B. Liebman
4 *
5 * Permission to use, copy, modify, distribute, and sell this software
6 * and its documentation for any purpose is hereby granted without fee,
7 * provided that the above copyright notice appear in all copies and that
8 * both that copyright notice and this permission notice appear in
9 * supporting documentation, and that the name Christopher B. Liebman not
10 * be used in advertising or publicity pertaining to distribution of this
11 * software without specific, written prior permission.
12 *
13 * THIS SOFTWARE IS PROVIDED `AS-IS'. CHRISTOPHER B. LIEBMAN, DISCLAIMS
14 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT
15 * LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
16 * PARTICULAR PURPOSE, OR NONINFRINGEMENT. IN NO EVENT SHALL CHRISTOPHER
17 * B. LIEBMAN, BE LIABLE FOR ANY DAMAGES WHATSOEVER, INCLUDING SPECIAL,
18 * INCIDENTAL OR CONSEQUENTIAL DAMAGES, INCLUDING LOSS OF USE, DATA, OR
19 * PROFITS, EVEN IF ADVISED OF THE POSSIBILITY THEREOF, AND REGARDLESS OF
20 * WHETHER IN AN ACTION IN CONTRACT, TORT OR NEGLIGENCE, ARISING OUT OF
21 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 *
23 * Author : Chris Liebman
24 * Created On : Tue Jan 11 14:11:30 1994
25 * Last Modified By: Chris Liebman
26 * Last Modified On: Mon Mar 7 16:56:37 1994
27 * Update Count : 130
28 * Status : Released
29 *
30 * HISTORY
31 * 13-Feb-1994 Chris Liebman
32 * Last Modified: Sun Feb 13 00:40:08 1994 #111 (Chris Liebman)
33 * Added new command support and support to annotate mail items.
34 *
35 * 8-Feb-1994 Chris Liebman
36 * Last Modified: Sat Feb 5 22:03:01 1994 #82 (Chris Liebman)
37 * Added new command line options. Added new Tiled widget.
38 *
39 * 2-Feb-1994 Chris Liebman
40 * Last Modified: Tue Feb 1 14:41:17 1994 #72 (Chris Liebman)
41 * Added annotation support.
42 *
43 * 31-Jan-1994 Chris Liebman
44 * Last Modified: Sun Jan 30 02:05:43 1994 #67 (Chris Liebman)
45 * New search code.
46 * Command line options.
47 * New resources.
48 * List Commad support.
49 *
50 * 24-Jan-1994 Chris Liebman
51 * Last Modified: Sun Jan 23 18:46:43 1994 #18 (Chris Liebman)
52 * Added new bindings.
53 *
54 * 20-Jan-1994 Chris Liebman
55 * Last Modified: Tue Jan 18 17:14:31 1994 #9 (Chris Liebman)
56 * Added new closeness resource and some cleanups.
57 *
58 * 14-Jan-1994 Chris Liebman
59 * Last Modified: Fri Jan 14 09:59:56 1994 #4 (Chris Liebman)
60 * Added ignoreMessageBindings resource.
61 *
62 * PURPOSE
63 * This is xfaces initialization.
64 */
65
66 #ifndef lint
67 static char *RCSid = "$Id: main.c,v 1.29 1994/03/08 02:19:48 liebman Exp $";
68 #endif
69
70 #include "faces.h"
71 #include <pwd.h>
72 #ifdef __STDC__
73 #include <stdlib.h>
74 #endif
75
76 /*
77 * The resources.
78 */
79
80 FacesResourcesRec TheFacesResources;
81
82 /*
83 * This is ugly but it will remove some error messages when
84 * some options are not compiled in.
85 */
86
87 #ifdef SHAPE
88 #ifdef XPM
89 #define IMAGE_TYPES "xpm-shape:xpm:xbm-shape:xbm"
90 #else /* XPM*/
91 #define IMAGE_TYPES "xbm-shape:xbm"
92 #endif /* XPM */
93 #else /* SHAPE */
94 #ifdef XPM
95 #define IMAGE_TYPES "xpm:xbm"
96 #else /* XPM*/
97 #define IMAGE_TYPES "xbm"
98 #endif /* XPM*/
99 #endif /* SHAPE */
100
101 #ifdef XFACE
102 #define IMAGE_SEARCH "beforeImage\nresource\nfacedb\nx-face\nafterImage"
103 #else /* XFACE */
104 #define IMAGE_SEARCH "beforeImage\nresource\nfacedb\nafterImage"
105 #endif /* XFACE */
106 #define SOUND_SEARCH "beforeSound\nresource\nfacedb\nafterSound"
107 #define COMMAND_SEARCH "beforeCommand\nresource\nafterCommand"
108
109 /*
110 * Here is a description of our resources for the toolkit.
111 */
112
113 static Boolean defFalse = False;
114 static Boolean defTrue = True;
115 #define XtNvolume "volume" /* Int: volume for bell */
116 #define XtCVolume "Volume"
117
118 #define offset(field) XtOffset(FacesResources, field)
119 static XtResource FacesResourcesList[] =
120 {
121 {
122 "spoolFile", "SpoolFile", XtRString, sizeof(String),
123 offset(spool_file), XtRString, NULL
124 },
125 {
126 "spoolDir", "SpoolDir", XtRString, sizeof(String),
127 offset(spool_dir), XtRString, "/usr/spool/mail"
128 },
129 {
130 "popHost", "PopHost", XtRString, sizeof(String),
131 offset(pop_host), XtRString, NULL
132 },
133 {
134 "popAuthFile", "PopAuthFile", XtRString, sizeof(String),
135 offset(pop_auth_file), XtRString, NULL
136 },
137 {
138 "popPort", "PopPort", XtRInt, sizeof(int),
139 offset(pop_port), XtRString, "110"
140 },
141 {
142 "listCommand", "Command", XtRString, sizeof(String),
143 offset(list_command), XtRString, NULL
144 },
145 {
146 "imagePath", "Path", XtRString, sizeof(String),
147 offset(image_path), XtRString, "/usr/images"
148 },
149 {
150 "soundPath", "Path", XtRString, sizeof(String),
151 offset(sound_path), XtRString, "/usr/sounds"
152 },
153 {
154 "facedbPath", "Path", XtRString, sizeof(String),
155 offset(facedb_path), XtRString, "/usr/local/faces"
156 },
157 {
158 "machine", "Path", XtRString, sizeof(String),
159 offset(machine), XtRString, "machine.tab"
160 },
161 {
162 "people", "Path", XtRString, sizeof(String),
163 offset(people), XtRString, "people.tab"
164 },
165 {
166 "update", "Update", XtRInt, sizeof(int),
167 offset(update), XtRString, "60"
168 },
169 {
170 XtNvolume, XtCVolume, XtRInt, sizeof(int),
171 offset(volume), XtRString, "33"
172 },
173 {
174 "fromField", "FromField", XtRString, sizeof(String),
175 offset(from_field), XtRString, "From "
176 },
177 {
178 "noMailImage", "Image", XtRString, sizeof(String),
179 offset(no_mail_image), XtRString, "nomail"
180 },
181 {
182 "noMailSound", "Sound", XtRString, sizeof(String),
183 offset(no_mail_sound), XtRString, NULL
184 },
185 {
186 "keepOrder", "KeepOrder", XtRBoolean, sizeof(Boolean),
187 offset(keep_order), XtRBoolean, (caddr_t) &defFalse
188 },
189 {
190 "compressImages", "CompressImages", XtRBoolean, sizeof(Boolean),
191 offset(compress_images), XtRBoolean, (caddr_t) &defTrue
192 },
193 {
194 "useSound", "UseSound", XtRBoolean, sizeof(Boolean),
195 offset(use_sound), XtRBoolean, (caddr_t) &defTrue
196 },
197 {
198 "useShape", "UseShape", XtRBoolean, sizeof(Boolean),
199 offset(use_shape), XtRBoolean, (caddr_t) &defTrue
200 },
201 {
202 "useCommands", "UseCommands", XtRBoolean, sizeof(Boolean),
203 offset(use_commands), XtRBoolean, (caddr_t) &defFalse
204 },
205 {
206 "useContentLength", "UseContentLength", XtRBoolean, sizeof(Boolean),
207 offset(use_content_length), XtRBoolean, (caddr_t) &defFalse
208 },
209 {
210 "shapeBorders", "ShapeBorders", XtRBoolean, sizeof(Boolean),
211 offset(shape_borders), XtRBoolean, (caddr_t) &defTrue
212 },
213 {
214 "shapeInternal", "ShapeInternal", XtRBoolean, sizeof(Boolean),
215 offset(shape_internal), XtRBoolean, (caddr_t) &defTrue
216 },
217 {
218 "closeness", "Closeness", XtRInt, sizeof(int),
219 offset(closeness), XtRString, (caddr_t) "40000"
220 },
221 {
222 "imageTypes", "ImageTypes", XtRString, sizeof(String),
223 offset(image_types_str), XtRString, IMAGE_TYPES
224 },
225 {
226 "imageSearch", "Search", XtRString, sizeof(String),
227 offset(image_search_str), XtRString, IMAGE_SEARCH
228 },
229 {
230 "soundSearch", "Search", XtRString, sizeof(String),
231 offset(sound_search_str), XtRString, SOUND_SEARCH
232 },
233 {
234 "commandSearch", "Search", XtRString, sizeof(String),
235 offset(command_search_str), XtRString, COMMAND_SEARCH
236 },
237 {
238 "ignoreMessageBindings", "IgnoreBindings", XtRString, sizeof(String),
239 offset(ignore_message_bindings_str), XtRString, NULL
240 },
241 {
242 "beforeImageBindings", "ImageBindings", XtRString, sizeof(String),
243 offset(before_image_bindings_str), XtRString, NULL
244 },
245 {
246 "afterImageBindings", "ImageBindings", XtRString, sizeof(String),
247 offset(after_image_bindings_str), XtRString, NULL
248 },
249 {
250 "beforeSoundBindings", "SoundBindings", XtRString, sizeof(String),
251 offset(before_sound_bindings_str), XtRString, NULL
252 },
253 {
254 "afterSoundBindings", "SoundBindings", XtRString, sizeof(String),
255 offset(after_sound_bindings_str), XtRString, NULL
256 },
257 {
258 "beforeCommandBindings", "CommandBindings", XtRString, sizeof(String),
259 offset(before_command_bindings_str), XtRString, NULL
260 },
261 {
262 "afterCommandBindings", "CommandBindings", XtRString, sizeof(String),
263 offset(after_command_bindings_str), XtRString, NULL
264 },
265 {
266 "annotationCount", "Count", XtRInt, sizeof(int),
267 offset(annotation_count), XtRString, "1"
268 },
269 {
270 "unknownAnnotationCount", "Count", XtRInt, sizeof(int),
271 offset(unknown_annotation_count), XtRString, "1"
272 },
273 {
274 "annotationAbove", "AnnotationAbove", XtRBoolean, sizeof(Boolean),
275 offset(annotation_above), XtRString, "False"
276 },
277 {
278 "background", "Background", XtRPixel, sizeof(Pixel),
279 offset(background), XtRString, XtDefaultBackground
280 },
281 {
282 "shapeExtra", "Shape", XtRBoolean, sizeof(Boolean),
283 offset(shape_extra), XtRString, "True"
284 },
285 {
286 "pathByChdir", "PathByChdir", XtRBoolean, sizeof(Boolean),
287 offset(path_by_chdir), XtRString, "True"
288 },
289 {
290 "lookupHostname", "LookupHostname", XtRBoolean, sizeof(Boolean),
291 offset(lookup_hostname), XtRString, "False"
292 },
293 };
294
295 #undef offset
296
297 static XrmOptionDescRec options[] =
298 {
299 {
300 "-c", "frame.maxWidth", XrmoptionSepArg, NULL
301 },
302 {
303 "-e", "listCommand", XrmoptionSepArg, NULL
304 },
305 {
306 "-f", "facedbPath", XrmoptionSepArg, NULL
307 },
308 {
309 "-h", "frame.tileHeight", XrmoptionSepArg, NULL
310 },
311 {
312 "-p", "update", XrmoptionSepArg, NULL
313 },
314 {
315 "-s", "spoolFile", XrmoptionSepArg, NULL
316 },
317 {
318 "-w", "frame.tileWidth", XrmoptionSepArg, NULL
319 },
320 {
321 "-C", "compressImages", XrmoptionNoArg, "False"
322 },
323 {
324 "-K", "keepOrder", XrmoptionNoArg, "True"
325 },
326 {
327 "-S", "shapeExtra", XrmoptionNoArg, "False"
328 },
329 {
330 "-pop", "popHost", XrmoptionSepArg, NULL
331 }
332 };
333
334
335 static Atom wm_delete_window;
336
337 static void
quit(w,event,params,num_params)338 quit (w, event, params, num_params)
339 Widget w;
340 XEvent *event;
341 String *params;
342 Cardinal *num_params;
343 {
344 if (event->type == ClientMessage &&
345 event->xclient.data.l[0] != wm_delete_window)
346 {
347 XBell (XtDisplay(w), 0);
348 return;
349 }
350
351
352 /*
353 * First suspend layout. Then cleanup.
354 */
355
356 XtVaSetValues(TheFrame, XtNlayout, False, NULL);
357
358 MailBoxClear();
359 MailBoxClean();
360
361 XCloseDisplay (XtDisplay(w));
362 exit (0);
363 }
364
365 static XtActionsRec xfaces_actions[] =
366 {
367 { "quit", quit },
368 };
369
370 /*
371 * Here are the main widgets.
372 */
373
374 Widget TheTopLevel; /* The top level shell widget. */
375 Widget TheFrame; /* A frame to hold the faces. */
376
377 FaceImage *NoMailImage = NULL;
378 FaceSound *NoMailSound = NULL;
379
380 void
CheckMailNow()381 CheckMailNow()
382 {
383 /*
384 * First suspend layout.
385 */
386
387 XtVaSetValues(TheFrame, XtNlayout, False, NULL);
388
389 /*
390 * Wipe the current face display list.
391 */
392
393 MailBoxClear();
394
395 /*
396 * Process items.
397 */
398
399 #ifdef POP
400 if (TheFacesResources.pop_host)
401 {
402 PopCheck();
403 }
404 else
405 #endif
406 if (TheFacesResources.list_command)
407 {
408 CmdCheck();
409 }
410 else
411 {
412 MailCheck();
413 }
414
415 /*
416 * Build the FaceDisplay list from the item list.
417 */
418
419 MailBoxClean();
420
421 /*
422 * Now resume layout.
423 */
424
425 XtVaSetValues(TheFrame, XtNlayout, True, NULL);
426
427 /*
428 * Shape the window.
429 */
430
431 #ifdef SHAPE
432 FaceShapeCreate();
433 #endif
434
435
436 }
437
438 static void StartTimer();
439
440 /*
441 * Check for changes to the mail spool file and kick the
442 * timer again.
443 */
444
445 /* ARGSUSED */
446 static void
CheckMail(data,id)447 CheckMail( data, id )
448 caddr_t data;
449 XtIntervalId *id;
450 {
451
452 CheckMailNow();
453
454 /*
455 * Restart the timer.
456 */
457
458 StartTimer(TheFacesResources.update);
459
460 return;
461 }
462
463 static void
StartTimer(secs)464 StartTimer(secs)
465 int secs;
466 {
467 (void) XtAddTimeOut((unsigned long) secs * 1000,
468 CheckMail,
469 (caddr_t) NULL );
470 }
471
472 /*
473 * Here is the main routine.
474 */
475
476 int
main(argc,argv)477 main(argc, argv)
478 int argc;
479 char *argv[];
480 {
481 char *name;
482 char *home;
483 struct passwd *pw;
484 FacesResources fr = &TheFacesResources;
485
486 /*
487 * Create the top level widget.
488 */
489
490 TheTopLevel = XtInitialize(NULL, XFACES_CLASS,
491 options, XtNumber(options),
492 &argc, argv);
493
494 /*
495 * Load any application resources.
496 */
497
498 XtGetApplicationResources( TheTopLevel,
499 fr,
500 FacesResourcesList,
501 XtNumber(FacesResourcesList),
502 NULL,
503 0 );
504
505 /*
506 * This is a hack so that f.delete will do something useful in this
507 * single-window application.
508 */
509
510 XtAppAddActions (XtWidgetToApplicationContext(TheTopLevel),
511 xfaces_actions, XtNumber(xfaces_actions));
512
513 XtOverrideTranslations(TheTopLevel,
514 XtParseTranslationTable ("<Message>WM_PROTOCOLS: quit()"));
515
516 /*
517 * If the spool file is null then create one from the
518 * user name.
519 */
520
521 if (fr->spool_file == NULL)
522 {
523 if ((name = getlogin()) == NULL)
524 {
525 pw = getpwuid(getuid());
526 if (pw != NULL || pw->pw_name != NULL)
527 {
528 name = pw->pw_name;
529 }
530 else
531 {
532 name = "nobody";
533 }
534 endpwent();
535 }
536
537 fr->spool_file = XtMalloc(strlen(fr->spool_dir)+ strlen(name) + 2);
538 (void) sprintf(fr->spool_file, "%s/%s", fr->spool_dir, name);
539 }
540
541 if (fr->pop_auth_file == NULL)
542 {
543 home = getenv("HOME");
544 if (home == NULL)
545 {
546 home = "/tmp";
547 }
548
549 fr->pop_auth_file = XtMalloc(strlen(home) + 30);
550 sprintf(fr->pop_auth_file, "%s/.popauth", home);
551 }
552
553 /*
554 * Initialize the image types.
555 */
556
557 FaceImageXbmInit();
558 #ifdef XPM
559 FaceImageXpmInit();
560 #endif
561 #ifdef IKON
562 FaceImageIkonInit();
563 #endif
564
565 /*
566 * Initialize the search types.
567 */
568
569 FaceSearchBindingInit();
570 FaceSearchFacedbInit();
571 FaceSearchResourceInit();
572 FaceSearchUserHostInit();
573 #ifdef XFACE
574 FaceSearchXFaceInit();
575 #endif
576
577 /*
578 * Parse up the image/sound paths.
579 */
580
581 fr->image_path_str = XtNewString(fr->image_path);
582 fr->sound_path_str = XtNewString(fr->sound_path);
583 fr->facedb_path_str = XtNewString(fr->facedb_path);
584
585 fr->image_paths = PathParse(fr->image_path_str);
586 fr->sound_paths = PathParse(fr->sound_path_str);
587 fr->facedb_paths = PathParse(fr->facedb_path_str);
588
589 /*
590 * Parse the image types.
591 */
592
593 fr->image_types_str = XtNewString(fr->image_types_str);
594 fr->image_types = FaceImageTypeListParse(fr->image_types_str);
595
596 /*
597 * Create binding lists.
598 */
599
600 fr->ignore_message_bindings =FaceBindingParse(fr->ignore_message_bindings_str, 0, 0);
601 fr->before_image_bindings = FaceBindingParse(fr->before_image_bindings_str, 1, 1);
602 fr->after_image_bindings = FaceBindingParse(fr->after_image_bindings_str, 1, 1);
603 fr->before_sound_bindings = FaceBindingParse(fr->before_sound_bindings_str, 1,1 );
604 fr->after_sound_bindings =FaceBindingParse(fr->after_sound_bindings_str, 1, 1);
605 /* fr->command_bindings = FaceBindingParse(fr->command_bindings_str, 1, 0); */
606
607 /*
608 * Parse the search instructions.
609 */
610
611 fr->image_search_str = XtNewString(fr->image_search_str);
612 fr->image_search = FaceSearchParse(fr->image_search_str, FormatImage);
613 fr->sound_search_str = XtNewString(fr->sound_search_str);
614 fr->sound_search = FaceSearchParse(fr->sound_search_str, FormatAudio);
615 fr->command_search_str = XtNewString(fr->command_search_str);
616 fr->command_search = FaceSearchParse(fr->command_search_str, FormatCommand);
617
618 /*
619 * Now we create a box to keep our faces in.
620 */
621
622 TheFrame = XtVaCreateManagedWidget("frame", tiledWidgetClass,
623 TheTopLevel, NULL);
624
625 /*
626 * Initialize the face list.
627 */
628
629 #ifdef SOUND
630 FaceSoundInit();
631 #endif /* SOUND */
632 FaceActionsInit();
633 FaceDisplayInit();
634 FaceAnnotateInit();
635 MailItemInit();
636
637 XtRealizeWidget(TheTopLevel);
638
639 wm_delete_window = XInternAtom (XtDisplay(TheTopLevel),
640 "WM_DELETE_WINDOW",
641 False);
642
643 (void) XSetWMProtocols (XtDisplay(TheTopLevel), XtWindow(TheTopLevel),
644 &wm_delete_window, 1);
645
646 /*
647 * Set the initial shape.
648 */
649
650 #ifdef SHAPE
651 FaceShapeCreate();
652 #endif
653
654 /*
655 * Kick off the timer. (we start the timer with one second so that the
656 * the shape stuff will get flushed first.
657 */
658
659 StartTimer(1);
660
661 /*
662 * Ok, we are all set up!
663 */
664
665 XtMainLoop();
666
667 return 0;
668 }
669
670 void
regerror(s)671 regerror(s)
672 String s;
673 {
674 fprintf(stderr, "regerror: %s\n", s);
675 abort();
676 }
677