1 /*
2 * xhime - Himechan for X Window System
3 * Copyright(C) 1994-1996,1998 `Shochan'Shoichi-NAKAYAMA (PED02616@nifty.ne.jp)
4 *
5 * Original version for PC-9801 "Resident Himechan Ver1.10"
6 * Copyright(C) 1994 MSP-Iris(Mapletown Network: MAP4370)
7 */
8 static char rcsid[] ="$Header: /home/naka/xhime/xhime1.51/RCS/xhime.c,v 1.42 1998/09/11 11:57:51 naka Exp $";
9
10 char
11 *Copyright = "xhime version 1.51 by `Shochan' Shoichi-NAKAYAMA (C) 1994-1996,1998\n Original: `rhime.exe' by MSP-Iris (C) 1994\n";
12
13 #include <X11/Xlib.h>
14 #include <X11/Xutil.h>
15 #include <X11/keysym.h>
16 #include <X11/Xos.h>
17
18 #ifdef SHAPE
19 #include <X11/extensions/shape.h>
20 #endif/*SHAPE*/
21
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <signal.h>
25 #include <ctype.h> /* defined in X11/Xos.h ? */
26 #include <string.h>/* defined in X11/Xos.h ? */
27 #include <limits.h>
28 #include <stdarg.h>
29 #include <sys/time.h>/* defined in X11/Xos.h */
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #ifndef O_RDONLY
33 #include <fcntl.h>
34 #endif/*!O_RDONLY*/
35
36 #define DOUBLEQUOTE '\"' /* " <- for hilit comment (^^ */
37
38 #ifndef MIN
39 #define MIN(a, b) ((a)<(b) ? (a):(b))
40 #endif/*!MIN*/
41
42 #ifndef MAX
43 #define MAX(a, b) ((a)>(b) ? (a):(b))
44 #endif/*!MAX*/
45
46 #ifndef MAILSPOOL_PATH
47 #define MAILSPOOL_PATH "/usr/spool/mail/"
48 #endif/*!MAILSPOOL_PATH*/
49
50 #ifndef AUDIO_DEVICE
51 #define AUDIO_DEVICE "/dev/audio"
52 #endif/*!AUDIO_DEVICE*/
53
54 #define AUD_NONE 0
55 #define AUD_BELL 1
56 #define AUD_DEV 2
57 #define AUD_CMD 3
58
59 #ifndef XHIMEDAT_PATH
60 #define XHIMEDAT_PATH "/usr/X11R6/lib/X11/xhime"
61 #endif/*!XHIMEDAT_PATH*/
62
63 char *XHIMEDAT = XHIMEDAT_PATH;
64 char *DisplayName = "";
65 char *ProgramName = NULL;
66 char *Geometry = NULL;
67 char *DataName = "rh110.xhm";
68 char *ActionKey = "Return";
69 char *AudioCommand = "showaudio";
70 char *AudioDevice = AUDIO_DEVICE;
71 char *AudioDataName = "IKEIKE_J.au";
72 char AudioDataPath[256] = "";
73 char *Background = "black";
74 char *MailPathArg = NULL;
75 Bool Debug = False;
76 Bool NoShape = False;
77 Bool UseWM = False;
78 Bool Rhime = True;
79 Bool Biff = False;
80 int Audio = AUD_NONE;
81 int ActionState = 1;
82 int MAX_AUSIZE = 65536;
83 Bool FocusDebug = False;
84
85 #define DEF_INT_TIME_MS 125
86 #define DEF_MAIL_CHECK_INT_TIME_MS 30000 /* 30sec. */
87 #define FOCUS_CHECK_INTERVAL_TIME_MS 500
88 int MAIL_CHECK_INTERVAL_TIME_MS = DEF_MAIL_CHECK_INT_TIME_MS;
89 int INTERVAL_TIME_MS = DEF_INT_TIME_MS;
90 int FocusCheckCountMax = FOCUS_CHECK_INTERVAL_TIME_MS / DEF_INT_TIME_MS;
91 int MailCheckCountMax = DEF_MAIL_CHECK_INT_TIME_MS / DEF_INT_TIME_MS;
92 int NCOLORS, NCELLS, NPATTERNS, NSTATES;
93 int WIDTH, HEIGHT;
94
95 #define H_OFF 0 /*window height OFFSET no use*/
96 #define MOVECHECK_MASK 0
97 /*#define MOVECHECK_MASK (UseWM ? StructureNotifyMask : 0)*/
98 #define EVENT_MASK (KeyPressMask|ButtonPressMask|ButtonReleaseMask|PointerMotionMask|MOVECHECK_MASK)
99 #define FOCUS_EVENT_MASK (KeyPressMask|StructureNotifyMask)
100
101 Display *MyDisplay;
102 int MyScreen;
103 unsigned int MyDepth;
104 Window MyWindow;
105 int Myx, Myy;
106 KeySym ActionKeysym;
107
108 #define IDLE 0
109 #define ACTION 1
110 int State = IDLE;
111 int PatternNumber = 0;
112 #define ACT_NONE 0
113 #define ACT_KEY 1
114 #define ACT_MAIL 2
115 int ActionFlag = ACT_NONE;
116
117 /* -- */
118 void
Error(char * fmt,...)119 Error(char *fmt, ...)
120 {
121 va_list args;
122
123 fprintf(stderr, "%s: ", ProgramName);
124
125 va_start(args, fmt);
126 fmt = (char *)va_arg(args, char *);
127 vfprintf(stderr, fmt, args);
128 va_end(args);
129
130 fprintf(stderr, "\n");
131 }
132
133 void
ErrorExit(char * fmt,...)134 ErrorExit(char *fmt, ...)
135 {
136 va_list args;
137
138 fprintf(stderr, "%s: ", ProgramName);
139
140 va_start(args, fmt);
141 fmt = (char *)va_arg(args, char *);
142 vfprintf(stderr, fmt, args);
143 va_end(args);
144
145 fprintf(stderr, "\n");
146 exit(1);
147 }
148
149 #define CALLOC(p, nelem, elsize) \
150 do {\
151 if (p) ErrorExit("not null pointer");\
152 if ((nelem)*(elsize) > 0) {\
153 if (! ((p) = (void *)calloc((unsigned)(nelem), (unsigned)(elsize))) )\
154 ErrorExit("cannot alocate memory");\
155 }else {\
156 ErrorExit("invalid memory size '%d'", (nelem)*(elsize));\
157 }\
158 } while (0)
159
160 #define FREE(p) do {if (p) { free(p); (p) = NULL; } } while (0)
161
162 #ifdef GET_DEBUG
163 #define DEBUG_PUTC(c) putchar(c)
164 #define DEBUG_PUTS(c) fputs(c, stdout)
165 #else
166 #define DEBUG_PUTC(c)
167 #define DEBUG_PUTS(c)
168 #endif/*GET_DEBUG*/
169
170 typedef struct {
171 char name[256];
172 int x;
173 int y;
174 int nmask;
175 int *mask_num;
176 int width;
177 int height;
178 char **pxl;
179 Pixmap pixmap;
180 Pixmap mask;
181 }CELL;
182
183 CELL *Cell = NULL;
184
185 typedef struct {
186 char c;
187 char type[3];
188 char name[256];
189 GC GC;
190 }COLOR;
191
192 COLOR *DummyColor = NULL;
193 COLOR *ColorN = NULL;
194 COLOR *ColorD = NULL;
195 COLOR *ColorB = NULL;
196 COLOR **Color = &ColorN;
197
198 typedef struct {
199 int num;
200 int x;
201 int y;
202 }PATTERN;
203
204 PATTERN *Pattern = NULL;
205
206 typedef struct {
207 int start;
208 int end;
209 int next_state;
210 }STATES;
211
212 STATES *States = NULL;
213
214
215 int
Skip(fp)216 Skip(fp)
217 FILE *fp;
218 {
219 int flg = 1, c;
220
221 DEBUG_PUTC('<');
222 while (EOF != (c = getc(fp))) {
223 DEBUG_PUTC(c);
224 if (isspace(c)) continue;
225 if (c == ',' && flg) {
226 flg = 0;
227 continue;
228 }
229 break;
230 }
231 DEBUG_PUTC('>');
232
233 if (c == EOF) ErrorExit("eof");
234
235 ungetc(c, fp);
236 return (c);
237 }
238
239 int
Found(fp,f)240 Found(fp, f)
241 FILE *fp;
242 int f;
243 {
244 int c;
245
246 while (EOF != (c = getc(fp)) && c != f);
247 if (c == EOF) {
248 ErrorExit("not found char '%c'", f);
249 }
250 return (c);
251 }
252
253 int
GetStr(fp,str,len)254 GetStr(fp, str, len)
255 FILE *fp;
256 char *str;
257 int len;
258 {
259 int i = 0, c;
260
261 DEBUG_PUTC('<');
262 while (EOF != (c = getc(fp))) {
263 DEBUG_PUTC(c);
264 if (isspace(c) || c == ',' || c == DOUBLEQUOTE) break;
265 if (i++ < len - 1) {
266 *str++ = c;
267 }
268 }
269 DEBUG_PUTC('>');
270
271 if (c == EOF) ErrorExit("not found string");
272
273 ungetc(c, fp);
274 *str = '\0';
275 return (c);
276 }
277
278 int
GetInt(fp,value)279 GetInt(fp, value)
280 FILE *fp;
281 int *value;
282 {
283 char buf[24];
284 int c = GetStr(fp, buf, sizeof(buf));
285 *value = atoi(buf);
286 return (c);
287 }
288
289 int
GetDefinedInt(fp,msg)290 GetDefinedInt(fp, msg)
291 FILE *fp;
292 char *msg;
293 {
294 static char define[] = "#define";
295 char line[256];
296 int value;
297
298 for (;;) {
299 if (!fgets(line, sizeof(line), fp)) {
300 ErrorExit("not found #define");
301 }
302
303 if (strncmp(line, define, sizeof(define)-1) == 0) {
304 if (sscanf(line, "#define %*s %d", &value) != 1) {
305 ErrorExit("cannot read '%s'", msg);
306 }
307
308 if (Debug) printf("%s = %d\n", msg, value);
309 break;
310 }
311 }
312 return (value);
313 }
314
315 void
GetColor(fp,color,ncolors)316 GetColor(fp, color, ncolors)
317 FILE *fp;
318 COLOR *color;
319 int ncolors;
320 {
321 int i;
322
323 for (i = 0; i < ncolors; i++, color++) {
324 Found(fp, DOUBLEQUOTE);
325 if ((color->c = getc(fp)) == EOF) ErrorExit("eof");
326 Skip(fp);
327 GetStr(fp, color->type, sizeof(color->type));
328 Skip(fp);
329 GetStr(fp, color->name, sizeof(color->name));
330 Found(fp, DOUBLEQUOTE);
331
332 if (Debug) printf("%c %s %s\n", color->c, color->type, color->name);
333 }
334 }
335
336 int
GetXpm(fp,cell,color)337 GetXpm(fp, cell, color)
338 FILE *fp;
339 CELL *cell;
340 COLOR *color;
341 {
342 static char XPM[] = "/* XPM */";
343 int ncolors, chars_per_pixel;
344 char **yp = NULL;
345 char line[80];
346 int x, y;
347
348 for (;;) {
349 if (!fgets(line, sizeof(line), fp)) {
350 ErrorExit("not found XPM header");
351 }
352 if (strncmp(line, XPM, sizeof(XPM)-1) == 0) break;
353 }
354 Found(fp, '{');
355 Found(fp, DOUBLEQUOTE);
356 GetInt(fp, &cell->width); Skip(fp);
357 GetInt(fp, &cell->height); Skip(fp);
358 GetInt(fp, &ncolors); Skip(fp);
359 GetInt(fp, &chars_per_pixel);
360 if (Debug) printf("width=%d, height=%d, ncolors=%d, %d(chars/pixel)\n",
361 cell->width, cell->height, ncolors, chars_per_pixel);
362 if (chars_per_pixel != 1) {
363 ErrorExit("not supported XPM (chars/pixel != 1)");
364 }
365 Found(fp, DOUBLEQUOTE);
366
367 CALLOC(color, ncolors, sizeof(*color));
368 GetColor(fp, color, ncolors);
369
370 CALLOC(cell->pxl, cell->height, sizeof(cell->pxl));
371 yp = cell->pxl;
372 for (y = 0; y < cell->height; y++, yp++) {
373 char *xp = NULL;
374
375 Found(fp, DOUBLEQUOTE);
376 CALLOC(*yp, cell->width + 1, sizeof(char));
377 xp = *yp;
378 for (x = 0; x < cell->width; x++) {
379 int c = getc(fp);
380 if (EOF == c) ErrorExit("eof");
381 DEBUG_PUTC(c);
382 *xp++ = c;
383 }
384 Found(fp, DOUBLEQUOTE);
385 DEBUG_PUTC('\n');
386 }
387 Found(fp, '}');
388
389 return (ncolors);
390 }
391
392 char OpenDataName[256] = "";
393 #define STR_TAIL(p) (*(p) ? *((char *)(p) + strlen(p) - 1): *(p) )
394
395 FILE*
OpenData(fname,mode)396 OpenData(fname, mode)
397 char *fname;
398 char *mode;
399 {
400 FILE *fp = stdin;
401 strncpy(OpenDataName, fname, sizeof(OpenDataName));
402 if (strcmp(fname, "-") != 0) {
403 if (Debug) fprintf(stderr, "Data Searching...\n\tCurrent '%s'\n", fname);
404 if ((fp = fopen(fname, mode)) == NULL) {
405 if (*fname == '/' ) {
406 ErrorExit("cannot open file '%s'", fname);
407 }else {
408 char path[256];
409 strncpy(path, fname, sizeof(path));
410 if (XHIMEDAT) {
411 strncpy(path, XHIMEDAT, sizeof(path));
412 if (STR_TAIL(path) != '/') strncat(path, "/", sizeof(path));
413 strncat(path, fname, sizeof(path));
414 fp = fopen(path, mode);
415 if (Debug) fprintf(stderr, "\tXHIMEDAT '%s'\n", path);
416 }
417 if (fp == NULL && strrchr(ProgramName, '/') != NULL) {
418 strncpy(path, ProgramName, sizeof(path));
419 *(strrchr(path, '/') + 1) = '\0';
420 strncat(path, fname, sizeof(path));
421 fp = fopen(path, mode);
422 if (Debug) fprintf(stderr, "\tProgram '%s'\n", path);
423 }
424 if (fp == NULL) {
425 ErrorExit("cannot open file '%s'", path);
426 }
427 strncpy(OpenDataName, path, sizeof(OpenDataName));
428 }
429 }
430 }
431 return (fp);
432 }
433
434
435
436 int
GetData(fname)437 GetData(fname)
438 char *fname;
439 {
440 FILE *fp = NULL;
441 char buf[256];
442 int c, i, j;
443 char *s = (char *)getenv("XHIMEDAT");
444
445 if (s) XHIMEDAT = s;
446 fp = OpenData(fname, "r");
447
448 if (!fgets(buf, sizeof(buf), fp)) {
449 ErrorExit("cannot read");
450 }
451 if (strncmp(buf, "/* xhime */", 11) != 0) {
452 ErrorExit("not found xhime header");
453 }
454
455 NCOLORS = GetDefinedInt(fp, "NCOLORS");
456 CALLOC(ColorN, NCOLORS, sizeof(*ColorN));
457 CALLOC(ColorB, NCOLORS, sizeof(*ColorB));
458 CALLOC(ColorD, NCOLORS, sizeof(*ColorD));
459
460 GetColor(fp, ColorN, NCOLORS);
461 GetColor(fp, ColorB, NCOLORS);
462 GetColor(fp, ColorD, NCOLORS);
463
464 WIDTH = GetDefinedInt(fp, "WIDTH");
465 HEIGHT = GetDefinedInt(fp, "HEIGHT");
466 NCELLS = GetDefinedInt(fp, "NCELLS");
467 CALLOC(Cell, NCELLS, sizeof(*Cell));
468 {
469 CELL *clp = Cell;
470 Found(fp, '{');
471 for (i = 0; i < NCELLS; i++, clp++) {
472 Found(fp, DOUBLEQUOTE);
473 GetStr(fp, clp->name, sizeof(clp->name)); Skip(fp);
474 GetInt(fp, &clp->x); Skip(fp);
475 GetInt(fp, &clp->y); c = Skip(fp);
476
477 if (Debug) printf("%d: %s (%d,%d) ", i, clp->name, clp->x, clp->y);
478
479 if (c != DOUBLEQUOTE) {
480 int *mp;
481
482 CALLOC(clp->mask_num, NCELLS, sizeof(clp->mask_num));
483
484 mp = clp->mask_num;
485 for (j = 0; j < NCELLS; j++, mp++) {
486 if (c == DOUBLEQUOTE) break;
487
488 GetInt(fp, mp); c = Skip(fp);
489 if (*mp < 0 || NCELLS <= *mp) {
490 ErrorExit("mask number error '%d'", *mp);
491 }
492 if (Debug) printf(" %d", *mp);
493 }
494 clp->nmask = j;
495 }
496 if (Debug) printf("\n");
497 Found(fp, DOUBLEQUOTE);
498 }
499 }
500
501 if ((INTERVAL_TIME_MS = GetDefinedInt(fp, "INTERVAL_TIME_MS") ) <= 0) {
502 ErrorExit("invalid INTERVAL_TIME_MS number");
503 }
504 NPATTERNS = GetDefinedInt(fp, "NPATTERNS");
505 if (NPATTERNS <= 0) {
506 ErrorExit("invalid NPATTERNS number");
507 }
508
509 CALLOC(Pattern, NPATTERNS, sizeof(*Pattern));
510 {
511 PATTERN *pp = Pattern;
512 Found(fp, '{');
513 for (i = 0; i < NPATTERNS; i++, pp++) {
514 Found(fp, '{'); Skip(fp);
515 GetInt(fp, &pp->num); Skip(fp);
516 GetInt(fp, &pp->x); Skip(fp);
517 GetInt(fp, &pp->y);
518
519 if (Debug) printf("%d %d %d\n", pp->num, pp->x, pp->y);
520 if (pp->num < 0 || NCELLS <= pp->num) {
521 ErrorExit("invalid cell number '%d'", pp->num);
522 }
523 }
524 }
525
526 NSTATES = GetDefinedInt(fp, "NSTATES");
527 CALLOC(States, NSTATES, sizeof(*States));
528 {
529 STATES *sp = States;
530 Found(fp, '{');
531 for (i = 0; i < NSTATES; i++, sp++) {
532 Found(fp, '{'); Skip(fp);
533 GetInt(fp, &sp->start); Skip(fp);
534 GetInt(fp, &sp->end); Skip(fp);
535 GetInt(fp, &sp->next_state);
536
537 if (Debug) printf("%d %d %d\n", sp->start, sp->end, sp->next_state);
538
539 if (sp->start < 0 || NPATTERNS <= sp->start) {
540 ErrorExit("invalid pattern number '%d'", sp->start);
541 }
542 if (sp->end < 0 || sp->end < sp->start) {
543 ErrorExit("invalid pattern number '%d'", sp->end);
544 }
545 if (sp->next_state < 0 || NSTATES <= sp->next_state) {
546 ErrorExit("invalid state number '%d'", sp->next_state);
547 }
548 }
549 if (ActionState >= NSTATES) ActionState = 0;
550 }
551
552 {
553 CELL *clp = Cell;
554 for (j = 0; j < NCELLS; j++, clp++) {
555 FILE *fpx = fp;
556
557 if (strcmp(clp->name, "-") != 0) {
558 fpx = OpenData(clp->name, "r");
559 }
560 if (Debug) printf("%d: xpmfile='%s'\n", j, clp->name);
561 if (GetXpm(fpx, clp, DummyColor) != NCOLORS) {
562 ErrorExit("invalid ncolors '%s'", clp->name);
563 }
564 FREE(DummyColor);
565 if (fpx != fp) fclose(fpx);
566 }
567 }
568
569 if (fp != stdin) fclose(fp);
570 }
571 /* -- */
572 char MailPath[256] = MAILSPOOL_PATH;
573
574 void
GetMailPath()575 GetMailPath()
576 {
577 if (MailPathArg) {
578 strncpy(MailPath, MailPathArg, sizeof(MailPath));
579 }else if (getenv("MAIL")) {
580 strncpy(MailPath, (char *)getenv("MAIL"), sizeof(MailPath));
581 }else {
582 if (STR_TAIL(MailPath) != '/') strncat(MailPath, "/", sizeof(MailPath));
583 strncat(MailPath, (char *)getenv("USER"), sizeof(MailPath));
584 }
585 if (Debug) fprintf(stderr, "MailPath '%s'\n", MailPath);
586 }
587
588 Bool
CheckMail()589 CheckMail()
590 {
591 static int mail_size = 0;
592 struct stat f_stat;
593
594 if (stat(MailPath, &f_stat) == 0) {
595 if (f_stat.st_size != mail_size && f_stat.st_size != 0) {
596 mail_size = f_stat.st_size;
597 if (Debug) fprintf(stderr, "mail arrived\n");
598 return (True);
599 }
600 }
601 return (False);
602 }
603 /* -- */
604 char *Au;
605 int Ausize = 0;
606
607 void
ReadAudioFile()608 ReadAudioFile()
609 {
610 if (Audio == AUD_DEV || Audio == AUD_CMD) {
611 FILE *fp = OpenData( AudioDataName, "r");
612
613 strncpy(AudioDataPath, OpenDataName, sizeof(AudioDataPath));
614 if (Audio == AUD_DEV) {
615 CALLOC(Au, MAX_AUSIZE, sizeof(*Au));
616 Ausize = fread(&Au[0], 1, MAX_AUSIZE, fp);
617 if (Debug) fprintf( stderr, "Ausize = %d\n", Ausize );
618 }
619 fclose(fp);
620 }
621 }
622
623 void
PlayAudioFile()624 PlayAudioFile()
625 {
626 int pid;
627 if (Audio == AUD_BELL) {
628 if (ActionFlag == ACT_MAIL) XBell(MyDisplay, 0);
629 }else if ((pid = fork()) == 0) {
630 signal(SIGALRM, SIG_IGN);
631 if (Audio == AUD_CMD) {
632 if (execlp(AudioCommand, AudioDataPath, AudioDataPath, NULL) == -1) {
633 Error("cannot exec '%s %s'", AudioCommand, AudioDataPath);
634 }
635 }else if (Audio == AUD_DEV) {
636 FILE *fpau = fopen(AudioDevice, "wb+");
637 if (fpau) {
638 fwrite(&Au[0], 1, Ausize, fpau); fflush(fpau); fclose(fpau);
639 }else {
640 Error("cannot open file '%s'", AudioDevice);
641 }
642 FREE(Au);
643 }
644 _exit(0);
645 }else if (pid < 0) {
646 Error("cannot fork");
647 }else {
648 /* wait() in ResetChild() ^^; */
649 }
650 }
651 /* -- */
652
653 int
SetMask(cell,xbm,width,height)654 SetMask(cell, xbm, width, height)
655 CELL *cell;
656 unsigned char *xbm;
657 unsigned int width, height;
658 {
659 static unsigned char BITON[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0};
660 int w = cell->width;
661 int h = cell->height;
662 int xs = cell->x;
663 int ys = cell->y;
664 char **yp = cell->pxl;
665 int x, y, i;
666
667 xbm += ((ys*width/8) + xs/8);
668 for (y = ys; y < ys+h; y++, yp++) {
669 unsigned char *xbm_back = xbm;
670 char *xp = *yp;
671 for (x = xs; x < xs+w; x+=8) {
672 unsigned char c = 0;
673 for (i = 0; i < 8; i++) {
674 c |= (BITON[ (*xp != ' ') ? i : 8 ]);
675 xp++;
676 }
677 *xbm++ = c;
678 }
679 xbm = xbm_back + (width/8);
680 }
681 }
682
683 int
GetPointerPosition(win,x,y)684 GetPointerPosition(win, x, y)
685 Window win;
686 int *x, *y;
687 {
688 Window root, child;
689 int wx, wy;
690 unsigned int key;
691
692 return (XQueryPointer(MyDisplay, win, &root, &child, x, y, &wx, &wy, &key));
693 }
694
695 int
GetPixelIndex(color,ncolors,c)696 GetPixelIndex(color, ncolors, c)
697 COLOR *color;
698 int ncolors;
699 char *c;
700 {
701 int i;
702 for (i = 0; i < ncolors; i++) {
703 if (color[i].c == *c) return (i);
704 }
705 return (-1);
706 }
707
708 void
MakePixmap()709 MakePixmap()
710 {
711 XGCValues GCValues;
712 char *xbm = NULL;
713 int xbm_size = ((WIDTH+7)/8)*HEIGHT;
714 int i;
715
716 CALLOC(xbm, xbm_size, sizeof(*xbm));
717
718 GCValues.function = GXcopy;
719 GCValues.fill_style = FillTiled;
720
721 for (i = 0; i < NCELLS; i++) {
722 CELL *clp = &Cell[i];
723 int width = clp->width;
724 int height = clp->height;
725 char **yp = clp->pxl;
726 int x, y;
727
728 clp->pixmap = XCreatePixmap(MyDisplay, MyWindow, width, height, MyDepth);
729
730 for (y = 0; y < height; y++, yp++) {
731 char *xp = *yp;
732 for (x = 0; x < width; x++, xp++) {
733 int c = GetPixelIndex(*Color, NCOLORS, xp);
734 if (c == -1) {
735 ErrorExit("invalid pixel char '%c'", *xp);
736 }
737 XDrawPoint(MyDisplay, clp->pixmap, (*Color + c)->GC, x, y);
738 }
739 }
740
741 #ifdef SHAPE
742 if (!NoShape) {
743 int *mp = clp->mask_num, k;
744 for (k = 0; k < xbm_size; k++) xbm[k] = 0;
745 for (k = 0; k < clp->nmask; k++, mp++) {
746 SetMask(&Cell[*mp], xbm, WIDTH, HEIGHT);
747 }
748 SetMask(clp, xbm, WIDTH, HEIGHT);
749 clp->mask = XCreateBitmapFromData(MyDisplay, MyWindow, xbm,
750 WIDTH, HEIGHT);
751 }
752 #endif/*SHAPE*/
753 }
754 FREE(xbm);
755 }
756
757 Bool
Draw(no)758 Draw(no)
759 int no;
760 {
761 static int no_back = -1;
762 Bool flag = (no_back != no);
763 int offset_x = 0, offset_y = 0;
764 static int ptx_back = -1, pty_back = -1;
765
766 if (UseWM) {
767 if ( ptx_back != Pattern[PatternNumber].x
768 || pty_back != Pattern[PatternNumber].y) {
769 ptx_back = Pattern[PatternNumber].x;
770 pty_back = Pattern[PatternNumber].y;
771 flag = True;
772 }
773 offset_x = ptx_back;
774 offset_y = pty_back + H_OFF;
775 }
776
777 if (flag) {
778 CELL *clp = &Cell[no];
779
780 #ifdef SHAPE
781 if (!NoShape) {
782 XShapeCombineMask(MyDisplay, MyWindow, ShapeBounding,
783 offset_x, offset_y, clp->mask, ShapeSet);
784 }
785 #endif/*SHAPE*/
786
787 XCopyArea(MyDisplay, clp->pixmap, MyWindow, (*Color)->GC,
788 0, 0, clp->width, clp->height,
789 offset_x + clp->x, offset_y + clp->y);
790 no_back = no;
791 }
792 return (flag);
793 }
794
795 void
DrawPattern()796 DrawPattern()
797 {
798 static int ptx_back = -1, pty_back = -1;
799 Bool flush;
800 STATES *sp = &States[State];
801
802 if (State == IDLE) {
803 if (ActionFlag) {
804 if (Audio) PlayAudioFile();
805 ActionFlag = ACT_NONE;
806 State = ActionState;
807 PatternNumber = States[State].start;
808 }else if (PatternNumber > sp->end) {
809 State = sp->next_state;
810 PatternNumber = States[State].start;
811 }
812 }else {
813 if (PatternNumber > sp->end) {
814 ActionFlag = ACT_NONE;
815 State = sp->next_state;
816 PatternNumber = States[State].start;
817 }
818 }
819
820 flush = Draw(Pattern[PatternNumber].num);
821
822 if (!UseWM) {
823 if (ptx_back != Pattern[PatternNumber].x
824 || pty_back != Pattern[PatternNumber].y) {
825 ptx_back = Pattern[PatternNumber].x;
826 pty_back = Pattern[PatternNumber].y;
827 XMoveWindow(MyDisplay, MyWindow, Myx + ptx_back, Myy + pty_back);
828 flush = True;
829 }
830 }
831
832 if (flush) XFlush(MyDisplay);
833
834 pause();
835
836 PatternNumber++;
837 }
838
839 #define N_CHILD 10
840 typedef struct {
841 Window window;
842 Window child [N_CHILD];
843 Window child2[N_CHILD];
844 }FOCUS;
845
846 FOCUS MyFocus = {None, None, None};
847 FOCUS MyFocusBack = {None, None, None};
848 FOCUS MyFocusBack2= {None, None, None};
849
850 Bool
ErrWindow(win)851 ErrWindow(win)
852 Window win;
853 {
854 int i;
855
856 if (win == None) return (True);
857
858 if (win == MyFocus.window) {
859 if (FocusDebug) fprintf(stderr, "<%x>\n", win); return (False);
860 }else if (win == MyFocusBack.window) {
861 if (FocusDebug) fprintf(stderr, "b<%x>\n", win); return (False);
862 }else if (win == MyFocusBack2.window) {
863 if (FocusDebug) fprintf(stderr, "bb<%x>\n", win); return (False);
864 }
865 for (i = 0; i < N_CHILD; i++) {
866 if (win == MyFocus.child[i]) {
867 if (FocusDebug) fprintf(stderr, "child<%x>\n", win); return (False);
868 }else if (win == MyFocus.child2[i]) {
869 if (FocusDebug) fprintf(stderr, "child2<%x>\n", win); return (False);
870 }else if (win == MyFocusBack.child[i]) {
871 if (FocusDebug) fprintf(stderr, "bchild<%x>\n", win); return (False);
872 }else if (win == MyFocusBack.child2[i]) {
873 if (FocusDebug) fprintf(stderr, "bchild2<%x>\n", win); return (False);
874 }else if (win == MyFocusBack2.child[i]) {
875 if (FocusDebug) fprintf(stderr, "bbchild<%x>\n", win); return (False);
876 }else if (win == MyFocusBack2.child2[i]) {
877 if (FocusDebug) fprintf(stderr, "bbchild2<%x>\n",win); return (False);
878 }
879 }
880 return (True);
881 }
882
883 int
MyErrorHandler(display,myerr)884 MyErrorHandler(display, myerr)
885 Display *display;
886 XErrorEvent *myerr;
887 {
888 if (ErrWindow(myerr->resourceid)) {
889 char msg[256];
890
891 XGetErrorText(display, myerr->error_code, msg, sizeof(msg));
892 Error("Error code %s", msg);
893 Error("Resouce id %x", myerr->resourceid);
894 exit(1);
895 }
896 MyFocusBack.window = None;
897 return (0);
898 }
899
900 KeySym
GetKeysym(key)901 GetKeysym(key)
902 char *key;
903 {
904 KeySym sym = XStringToKeysym(key);
905
906 if (sym == NoSymbol) ErrorExit("not found keysym '%s'", key);
907 return (sym);
908 }
909
910 Bool
CheckEvent()911 CheckEvent()
912 {
913 static int drag_x = -1, drag_y = -1;
914 XEvent event;
915 Bool flag = True;
916 int ix = 0;
917
918 while (XEventsQueued(MyDisplay, QueuedAfterReading) > 0) {
919 XNextEvent(MyDisplay, &event);
920 switch(event.type) {
921 case DestroyNotify:
922 if (event.xdestroywindow.window == MyFocusBack.window) {
923 MyFocusBack.window = None;
924 }else {
925 int i;
926 for (i = 0; i < N_CHILD; i++) {
927 if (event.xdestroywindow.window == MyFocusBack.child[i]) {
928 MyFocusBack.child[i] = None;
929 break;
930 }else if (event.xdestroywindow.window == MyFocusBack.child2[i]) {
931 MyFocusBack.child2[i] = None;
932 break;
933 }
934 }
935 }
936 if (FocusDebug) {
937 fprintf(stderr, "destory(%x)%s\n", event.xdestroywindow.window,
938 (event.xdestroywindow.window==MyFocusBack.window) ? "-":"");
939 }
940 break;
941 case KeyPress:
942 if (FocusDebug) {
943 fprintf(stderr, "win=%x, keycode=%d, keysym=%x\n",
944 event.xkey.window, event.xkey.keycode,
945 XKeycodeToKeysym(MyDisplay, event.xkey.keycode, ix) );
946 }
947 if (XKeycodeToKeysym(MyDisplay, event.xkey.keycode, ix) == ActionKeysym){
948 ActionFlag = ACT_KEY;
949 }
950 break;
951 case ButtonPress:
952 if (event.xbutton.button == Button1) {
953 drag_x = event.xbutton.x;
954 drag_y = event.xbutton.y;
955 }else if (event.xbutton.button == Button2) {
956 XMapRaised(MyDisplay, MyWindow);
957 }else {
958 flag = False;
959 }
960 break;
961 case ButtonRelease:
962 drag_x = drag_y = -1;
963 break;
964 case MotionNotify:
965 if (drag_x >= 0 && drag_y >= 0) {
966 while (XCheckWindowEvent(MyDisplay, MyWindow,
967 PointerMotionMask, &event)) {
968 }
969 GetPointerPosition(MyWindow, &Myx, &Myy);
970 Myx -= drag_x;
971 Myy -= drag_y;
972 XMoveWindow(MyDisplay, MyWindow, Myx, Myy);
973 }
974 break;
975 case MappingNotify:
976 XRefreshKeyboardMapping((XMappingEvent*)&event);
977 ActionKeysym = GetKeysym(ActionKey);
978 break;
979 /**
980 case ConfigureNotify:
981 if (UseWM) {
982 if (event.xconfigure.window == MyWindow && State == IDLE) {
983 Myx = event.xconfigure.x;
984 Myy = event.xconfigure.y;
985 if (Debug) fprintf(stderr, "%d %d %d\n",
986 Myx, Myy, event.xconfigure.send_event);
987 }
988 }
989 break;
990 **/
991 default:
992 break;
993 }
994 }
995
996 if (Rhime) {
997 static int focus_check_count = 0;
998
999 if (++focus_check_count >= FocusCheckCountMax) {
1000 int rever_to;
1001
1002 focus_check_count = 0;
1003
1004 XGetInputFocus(MyDisplay, &MyFocus.window, &rever_to);
1005
1006 if ( MyFocus.window != MyFocusBack.window
1007 && MyFocus.window != None
1008 && MyFocus.window != PointerRoot
1009 && MyFocus.window != MyWindow) {
1010 Window root, parent, *children, *children2;
1011 unsigned int nchildren, nchildren2;
1012 unsigned int i, j;
1013
1014 if (FocusDebug) fprintf(stderr, "<%x", MyFocus.window);
1015 XSelectInput(MyDisplay, MyFocus.window, FOCUS_EVENT_MASK);
1016
1017 for ( i = 0; i < N_CHILD; i++) MyFocus.child [i] = None;
1018 for ( j = 0; j < N_CHILD; j++) MyFocus.child2[j] = None;
1019
1020 if (XQueryTree(MyDisplay, MyFocus.window,
1021 &root, &parent, &children, &nchildren)) {
1022 for (i = j = 0; i < MIN(N_CHILD, nchildren); i++) {
1023 MyFocus.child[i] = children[i];
1024 XSelectInput(MyDisplay, children[i], FOCUS_EVENT_MASK);
1025 if (FocusDebug) fprintf(stderr, ",%x", children[i]);
1026
1027 if (XQueryTree(MyDisplay, children[i],
1028 &root, &parent, &children2, &nchildren2)) {
1029 for ( ; j < MIN(N_CHILD, nchildren2); j++) {
1030 MyFocus.child2[j] = children2[j];
1031 XSelectInput(MyDisplay, children2[j], FOCUS_EVENT_MASK);
1032 if (FocusDebug) fprintf(stderr, ";%x", children2[j]);
1033 }
1034 XFree(children2);
1035 }
1036 }
1037 XFree(children);
1038 }
1039 if (FocusDebug) fprintf(stderr, ">\n");
1040
1041 if (FocusDebug) fprintf(stderr, "(");
1042 if (MyFocusBack.window != None) {
1043 XSelectInput(MyDisplay, MyFocusBack.window, 0);
1044 if (FocusDebug) fprintf(stderr, "%x", MyFocusBack.window);
1045 }
1046 for (i = 0; i < N_CHILD; i++) {
1047 if (MyFocusBack.child [i] != None) {
1048 XSelectInput(MyDisplay, MyFocusBack.child [i], 0);
1049 if (FocusDebug) fprintf(stderr, ",%x", MyFocusBack.child [i]);
1050 }
1051 if (MyFocusBack.child2[i] != None) {
1052 XSelectInput(MyDisplay, MyFocusBack.child2[i], 0);
1053 if (FocusDebug) fprintf(stderr, ";%x", MyFocusBack.child2[i]);
1054 }
1055 }
1056 if (FocusDebug) fprintf(stderr, ")\n");
1057
1058 MyFocusBack2.window = MyFocusBack.window;
1059 MyFocusBack.window = MyFocus.window;
1060 for (i = 0; i < N_CHILD; i++) {
1061 MyFocusBack2.child [i] = MyFocusBack.child [i];
1062 MyFocusBack2.child2[i] = MyFocusBack.child2[i];
1063 MyFocusBack.child [i] = MyFocus.child [i];
1064 MyFocusBack.child2[i] = MyFocus.child2[i];
1065 }
1066 }
1067 }
1068 }
1069
1070 if (Biff) {
1071 static int mail_check_count = INT_MAX - 1;
1072 if (++mail_check_count >= MailCheckCountMax) {
1073 mail_check_count = 0;
1074 if (CheckMail()) ActionFlag = ACT_MAIL;
1075 }
1076 }
1077 return (flag);
1078 }
1079
1080 void
Animation()1081 Animation()
1082 {
1083 struct itimerval itime;
1084
1085 timerclear(&itime.it_interval);
1086 timerclear(&itime.it_value);
1087
1088 itime.it_interval.tv_usec = INTERVAL_TIME_MS*1000L;
1089 itime.it_value.tv_usec = INTERVAL_TIME_MS*1000L;
1090
1091 setitimer(ITIMER_REAL, &itime, 0);
1092
1093 FocusCheckCountMax = FOCUS_CHECK_INTERVAL_TIME_MS / INTERVAL_TIME_MS;
1094 MailCheckCountMax = MAIL_CHECK_INTERVAL_TIME_MS / INTERVAL_TIME_MS;
1095 do {
1096 DrawPattern();
1097 } while (CheckEvent());
1098 }
1099
1100 void
AllocColors()1101 AllocColors()
1102 {
1103 Colormap colormap = DefaultColormap(MyDisplay, MyScreen);
1104 XColor color;
1105 XGCValues values;
1106 COLOR *cp = *Color;
1107 int i;
1108
1109 for (i = 0; i < NCOLORS; i++, cp++) {
1110 char *name = cp->name;
1111
1112 if (Background && i == 0) name = Background;
1113
1114 if (XParseColor(MyDisplay, colormap, name, &color)) {
1115 if (XAllocColor(MyDisplay, colormap, &color) == 0) {
1116 ErrorExit("cannot allocate color '%s'", name);
1117 }
1118
1119 values.foreground = color.pixel;
1120 cp->GC = XCreateGC(MyDisplay, MyWindow, GCForeground, &values);
1121 }else {
1122 ErrorExit("cannot parse color '%s'", name);
1123 }
1124 }
1125 }
1126
1127 void
InitScreen()1128 InitScreen()
1129 {
1130 Window root;
1131 XSizeHints sizehints;
1132 XSetWindowAttributes attributes;
1133 unsigned long mask;
1134 int eventbase, errorbase;
1135 unsigned long black;
1136
1137 if ((MyDisplay = XOpenDisplay(DisplayName)) == NULL) {
1138 if (!DisplayName || (DisplayName && *DisplayName == '\0')) {
1139 char *p = (char *)getenv("DISPLAY");
1140 ErrorExit("cannot open display '%s'", (p ? p : "(null)"));
1141 }else {
1142 ErrorExit("cannot open display '%s'", DisplayName);
1143 }
1144 }
1145
1146 ActionKeysym = GetKeysym(ActionKey);
1147
1148 #ifdef SHAPE
1149 if (!NoShape && !XShapeQueryExtension(MyDisplay, &eventbase, &errorbase)) {
1150 Error("Display not suported shape extension");
1151 NoShape = True;
1152 }
1153 #endif/*SHAPE*/
1154
1155 MyScreen = DefaultScreen(MyDisplay);
1156 MyDepth = DefaultDepth(MyDisplay, MyScreen);
1157 root = RootWindow(MyDisplay, MyScreen);
1158
1159 if (Geometry) {
1160 char ge[256];
1161 sprintf(ge, "%dx%d+0+0", WIDTH, HEIGHT);
1162 if (XGeometry(MyDisplay, MyScreen, Geometry, ge, 1, 1, 1, 0, 0, &Myx, &Myy,
1163 &sizehints.width, &sizehints.height) & (XValue|YValue)
1164 == 0) {
1165 Geometry = NULL;
1166 }
1167 }
1168 if (!Geometry) {
1169 GetPointerPosition(root, &Myx, &Myy);
1170 Myx -= (WIDTH /2);
1171 Myy -= (HEIGHT/2);
1172 }
1173 mask = CWSaveUnder | CWOverrideRedirect;
1174 attributes.save_under = True;
1175 attributes.override_redirect = !UseWM;
1176
1177 MyWindow = XCreateWindow(MyDisplay, root, Myx, Myy, WIDTH, HEIGHT + H_OFF,
1178 0, MyDepth, InputOutput, CopyFromParent,
1179 mask, &attributes);
1180
1181 sizehints.flags = PMinSize | PMaxSize;
1182 sizehints.min_width = sizehints.max_width = WIDTH;
1183 sizehints.min_height = sizehints.max_height = HEIGHT + H_OFF;
1184
1185 XSetStandardProperties(MyDisplay, MyWindow, ProgramName, ProgramName, None,
1186 NULL, 0, &sizehints);
1187
1188 /* black = BlackPixel(MyDisplay, MyScreen);
1189 XSetWindowBackgroundPixmap(MyDisplay, MyWindow, black); perfomance bad! */
1190 XSetWindowBackgroundPixmap(MyDisplay, MyWindow, None);
1191 AllocColors();
1192
1193 XSelectInput(MyDisplay, MyWindow, EVENT_MASK);
1194 XSelectInput(MyDisplay, root, KeyPressMask);
1195
1196 XFlush(MyDisplay);
1197
1198 XSetErrorHandler(MyErrorHandler);
1199 }
1200
1201
1202 char *OptionsAre[] = {
1203 "-help Print usage message and exit\n",
1204 "-display <host:n> Specify the host and display number\n",
1205 "-geometry <+X+Y> Specify the geometry\n",
1206 "-key <keyname> Specify the keysym of the special key\n",
1207 "-nokey Don't check for the special key\n",
1208 #ifdef SHAPE
1209 "-noshape Don't use shape extension\n",
1210 #endif/*SHAPE*/
1211 "-bg <color> Specify the background color\n",
1212 "[-N | -B | -D] Draw in normal, brighter, or darker colors\n",
1213 "-<statenumber> Specify the action state\n",
1214 "-use_wm Use window manager\n",
1215 "-audio <audiofile> Specify audio file\n",
1216 " [-audev <dev>|-aucmd <cmd>]\n",
1217 " Specify audio device or command\n",
1218 " -showaudio the same as ``-aucmd showaudio''\n",
1219 "-biff Enable biff feature\n",
1220 " -file <mailfile> Specify the mail file\n",
1221 " -update <sec> Specify the mail polling interval\n",
1222 " -nobell Don't ring the bell when mails arrive\n",
1223 NULL,
1224 };
1225
1226 void
PrintUsage()1227 PrintUsage()
1228 {
1229 char **p = OptionsAre;
1230 fprintf(stderr, "%s", Copyright);
1231 fprintf(stderr, "usage: %s [<options>] [<filename.xhm>]\n", ProgramName);
1232 fprintf(stderr, " options are:\n");
1233 while (*p) fprintf(stderr, " %s", *p++);
1234 return;
1235 }
1236
1237 #define MissingArg(argv) ErrorExit("missing argument to %s", (argv))
1238 #define CheckArg(argc, argv) do{if((argc)<= 0) MissingArg(argv);}while(0)
1239
1240 void
GetOptions(argc,argv)1241 GetOptions(argc, argv)
1242 int argc;
1243 char **argv;
1244 {
1245 Bool bell = True;
1246
1247 ProgramName = *argv;
1248
1249 while (--argc > 0) {
1250 argv++;
1251 if (strcmp(*argv, "-display") == 0) {
1252 CheckArg(--argc, argv); DisplayName = *++argv;
1253 }else if (strcmp(*argv, "-geometry") == 0) {
1254 CheckArg(--argc, *argv); Geometry = *++argv;
1255 }else if (strcmp(*argv, "-key") == 0) {
1256 CheckArg(--argc, *argv); ActionKey = *++argv;
1257 }else if (strcmp(*argv, "-bg") == 0) {
1258 CheckArg(--argc, *argv); Background = *++argv;
1259 #ifdef SHAPE
1260 }else if (strcmp(*argv, "-noshape") == 0) {
1261 NoShape = True;
1262 }else if (strcmp(*argv, "-shape") == 0) {
1263 NoShape = False;
1264 #endif/*SHAPE*/
1265 }else if (strcmp(*argv, "-use_wm") == 0) {
1266 UseWM = True; NoShape = True;
1267 }else if (strcmp(*argv, "-audio") == 0) {
1268 Audio = AUD_DEV;
1269 CheckArg(--argc, *argv); AudioDataName = *++argv;
1270 }else if (strcmp(*argv, "-audev") == 0) {
1271 Audio = AUD_DEV;
1272 CheckArg(--argc, *argv); AudioDevice = *++argv;
1273 }else if (strcmp(*argv, "-max_ausize") == 0) {
1274 CheckArg(--argc, *argv); MAX_AUSIZE = atoi(*++argv);
1275 }else if (strcmp(*argv, "-showaudio") == 0) {
1276 Audio = AUD_CMD;
1277 }else if (strcmp(*argv, "-noshowaudio") == 0) {
1278 Audio = AUD_DEV;
1279 }else if ( strcmp(*argv, "-nokey" ) == 0
1280 || strcmp(*argv, "-nohime") == 0) {
1281 Rhime = False;
1282 }else if ( strcmp(*argv, "-aucmd" ) == 0
1283 || strcmp(*argv, "-mscript" ) == 0) {
1284 Audio = AUD_CMD;
1285 CheckArg(--argc, *argv); AudioCommand = *++argv;
1286 }else if (strcmp(*argv, "-biff") == 0) {
1287 Biff = True;
1288 }else if (strcmp(*argv, "-nobiff") == 0) {
1289 Biff = False;
1290 }else if (strcmp(*argv, "-nobell") == 0) {
1291 bell = False;
1292 }else if ( strcmp(*argv, "-update") == 0
1293 || strcmp(*argv, "-mtime" ) == 0) {
1294 Biff = True;
1295 CheckArg(--argc, *argv);
1296 MAIL_CHECK_INTERVAL_TIME_MS = atoi(*++argv) * 1000;
1297 }else if ( strcmp(*argv, "-file") == 0
1298 || strcmp(*argv, "-mail") == 0) {
1299 Biff = True;
1300 CheckArg(--argc, *argv); MailPathArg = *++argv;
1301 }else if (strcmp(*argv, "-debug") == 0) {
1302 Debug = True;
1303 }else if (strcmp(*argv, "-focusdebug") == 0) {
1304 FocusDebug = True;
1305 }else if (strcmp(*argv, "-N") == 0) {
1306 Color = &ColorN;
1307 }else if (strcmp(*argv, "-B") == 0) {
1308 Color = &ColorB;
1309 }else if (strcmp(*argv, "-D") == 0) {
1310 Color = &ColorD;
1311 }else if (strcmp(*argv, "-") == 0 && argc == 1) {
1312 DataName = "-";
1313 }else if (strncmp(*argv, "-", 1) == 0) {
1314 if ('0' <= *(*argv + 1) && *(*argv + 1) <= '9') {
1315 ActionState = atoi(*argv + 1);
1316 }else {
1317 PrintUsage(ProgramName);
1318 exit(0);
1319 }
1320 }else if (argc == 1) {
1321 DataName = *argv;
1322 }
1323 }
1324
1325 if (Biff && bell && Audio == AUD_NONE) Audio = AUD_BELL;
1326
1327 GetData(DataName);
1328 }
1329
1330 void
ResetChild()1331 ResetChild()
1332 {
1333 int stat;
1334 wait(&stat);
1335 #ifdef NO_SIGACTION
1336 #if defined(SYSV) || defined(XSYSV_SIG)
1337 signal(SIGCHLD, ResetChild);
1338 #endif/*SYSV || XSYSV_SIG*/
1339 #endif/*NO_SIGACTION*/
1340 if (Debug) fprintf(stderr, "SIGCHLD caught\n");
1341 }
1342
1343 void
ResetAlarm()1344 ResetAlarm()
1345 {
1346 #ifdef NO_SIGACTION
1347 #if defined(SYSV) || defined(XSYSV_SIG)
1348 signal(SIGALRM, ResetAlarm);
1349 #endif/*SYSV || XSYSV_SIG*/
1350 #endif/*NO_SIGACTION*/
1351 }
1352
1353 void
Exit()1354 Exit()
1355 {
1356 if (MyDisplay) {
1357 XDestroyWindow(MyDisplay, MyWindow);
1358 XCloseDisplay(MyDisplay);
1359 }
1360 exit(0);
1361 }
1362
1363 int
main(argc,argv)1364 main(argc, argv)
1365 int argc;
1366 char *argv[];
1367 {
1368 GetOptions(argc, argv);
1369
1370 InitScreen();
1371 MakePixmap();
1372
1373 if (Biff) GetMailPath();
1374 if (Audio) ReadAudioFile();
1375
1376 #ifdef NO_SIGACTION
1377 signal(SIGALRM, ResetAlarm);
1378 signal(SIGCHLD, ResetChild);
1379 #else
1380 {
1381 static struct sigaction alrm, chld;
1382 alrm.sa_handler = ResetAlarm;
1383 chld.sa_handler = ResetChild;
1384 sigaction(SIGALRM, &alrm, NULL);
1385 sigaction(SIGCHLD, &chld, NULL);
1386 }
1387 #endif/*NO_SIGACTION*/
1388
1389 signal(SIGINT, Exit);
1390 signal(SIGTERM, Exit);
1391 signal(SIGQUIT, Exit);
1392
1393 XMapWindow(MyDisplay, MyWindow);
1394 Animation();
1395
1396 Exit();
1397 }
1398