Initial import of the CDE 2.1.30 sources from the Open Group.
[oweals/cde.git] / cde / programs / dtscreen / resource.c
1 /* $XConsortium: resource.c /main/4 1996/06/19 09:47:56 mustafa $ */
2 /*
3  */
4 /*                                                                      *
5  * (c) Copyright 1993, 1994 Hewlett-Packard Company                     *
6  * (c) Copyright 1993, 1994 International Business Machines Corp.       *
7  * (c) Copyright 1993, 1994 Sun Microsystems, Inc.                      *
8  * (c) Copyright 1993, 1994 Novell, Inc.                                *
9  */
10 /*-
11  * resource.c - resource management for dtscreen, the X Window System lockscreen.
12  *
13  * Copyright (c) 1991 by Patrick J. Naughton.
14  *
15  * See dtscreen.c for copying information.
16  *
17  * Revision History:
18  * 25-Sep-91: added worm mode.
19  * 06-Jun-91: Added flame mode.
20  * 16-May-91: Added random mode and pyro mode.
21  * 26-Mar-91: CheckResources: delay must be >= 0.
22  * 29-Oct-90: Added #include <ctype.h> for missing isupper() on some OS revs.
23  *            moved -mode option, reordered Xrm database evaluation.
24  * 28-Oct-90: Added text strings.
25  * 26-Oct-90: Fix bug in mode specific options.
26  * 31-Jul-90: Fix ':' handling in parsefilepath
27  * 07-Jul-90: Created from resource work in dtscreen.c
28  *
29  */
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include "dtscreen.h"
34 #include <netdb.h>
35 #include <math.h>
36 #include <ctype.h>
37
38 #include <X11/Xresource.h>
39
40 /*              include file for message texts          */
41 #include <limits.h>
42 #include <nl_types.h>
43 #define MF_DTSCREEN "dtscreen.cat"
44
45 #include <locale.h>
46 extern nl_catd  scmc_catd;   /* Cat descriptor for scmc conversion */
47
48 /*
49  * Declare external interface routines for supported screen savers.
50  */
51
52 extern void inithop();
53 extern void drawhop();
54
55 extern void initlife();
56 extern void drawlife();
57
58 extern void initqix();
59 extern void drawqix();
60
61 extern void initimage();
62 extern void drawimage();
63
64 extern void initblank();
65 extern void drawblank();
66
67 extern void initswarm();
68 extern void drawswarm();
69
70 extern void initrotor();
71 extern void drawrotor();
72
73 extern void initpyro();
74 extern void drawpyro();
75
76 extern void initflame();
77 extern void drawflame();
78
79 extern void initworm();
80 extern void drawworm();
81
82 typedef struct {
83     char       *cmdline_arg;
84     void        (*lp_init) ();
85     void        (*lp_callback) ();
86     int         def_delay;
87     int         def_batchcount;
88     float       def_saturation;
89     char       *desc;
90 }           LockStruct;
91
92 static char randomstring[] = "random";
93
94 static LockStruct LockProcs[] = {
95     {"hop", inithop, drawhop, 0, 1000, 1.0, "Hopalong iterated fractals"},
96     {"qix", initqix, drawqix, 30000, 64, 1.0, "Spinning lines a la Qix(tm)"},
97     {"image", initimage, drawimage, 2000000, 8, 0.3, "Random bouncing image"},
98     {"life", initlife, drawlife, 1000000, 100, 1.0, "Conway's game of Life"},
99     {"swarm", initswarm, drawswarm, 10000, 100, 1.0, "Swarm of bees"},
100     {"rotor", initrotor, drawrotor, 10000, 4, 0.4, "Rotor"},
101     {"pyro", initpyro, drawpyro, 15000, 40, 1.0, "Fireworks"},
102     {"flame", initflame, drawflame, 10000, 20, 1.0, "Cosmic Flame Fractals"},
103     {"worm", initworm, drawworm, 10000, 20, 1.0, "Wiggly Worms"},
104     {"blank", initblank, drawblank, 5000000, 1, 1.0, "Blank screen"},
105     {randomstring, NULL, NULL, 0, 0, 0.0, "Random mode"},
106 };
107 #define NUMPROCS (sizeof LockProcs / sizeof LockProcs[0])
108
109
110 extern char *getenv();
111
112 #ifndef DEF_FILESEARCHPATH
113 #define DEF_FILESEARCHPATH "/usr/lib/X11/%T/%N%S"
114 #endif
115 #define DEF_DISPLAY     ":0"
116 #define DEF_MODE        "swarm"
117 #define DEF_BG          "White"
118 #define DEF_FG          "Black"
119 #define DEF_BC          "100"   /* vectors (or whatever) per batch */
120 #define DEF_DELAY       "200000"/* microseconds between batches */
121 #define DEF_NICE        "10"    /* dtscreen process nicelevel */
122 #define DEF_SAT         "1.0"   /* color ramp saturation 0->1 */
123 #define DEF_CLASSNAME   "Dtscreen"
124
125 static char *classname;
126 static char modename[1024];
127 static char modeclass[1024];
128
129 static XrmOptionDescRec genTable[] = {
130     {"-mode", ".mode", XrmoptionSepArg, (caddr_t) NULL},
131     {"-mono", ".mono", XrmoptionNoArg, (caddr_t) "on"},
132     {"+mono", ".mono", XrmoptionNoArg, (caddr_t) "off"},
133     {"-nice", ".nice", XrmoptionSepArg, (caddr_t) NULL},
134     {"-create",  ".create", XrmoptionNoArg, (caddr_t) "on"},
135 };
136 #define genEntries (sizeof genTable / sizeof genTable[0])
137
138 /*************************************************************/
139 /** This table was changed for AIX.  In order to read these **/
140 /** command line options properly, the specifier field must **/
141 /** be built on the fly.                                    **/
142 /*************************************************************/
143 static XrmOptionDescRec modeTable[] = {
144     {"-delay",      NULL, XrmoptionSepArg, (caddr_t) NULL},
145     {"-batchcount", NULL, XrmoptionSepArg, (caddr_t) NULL},
146     {"-saturation", NULL, XrmoptionSepArg, (caddr_t) NULL},
147 };
148 #define modeEntries (sizeof modeTable / sizeof modeTable[0])
149
150 static XrmOptionDescRec cmdlineTable[] = {
151     {"-display", ".display", XrmoptionSepArg, (caddr_t) NULL},
152     {"-xrm",     NULL,       XrmoptionResArg, (caddr_t) NULL},
153 };
154 #define cmdlineEntries (sizeof cmdlineTable / sizeof cmdlineTable[0])
155
156 static XrmOptionDescRec nameTable[] = {
157     {"-name", ".name", XrmoptionSepArg, (caddr_t) NULL},
158 };
159
160
161 typedef struct {
162     char       *opt;
163     char       *desc;
164 }           OptionStruct;
165
166 static OptionStruct opDesc[] = {
167     {"-help", "print out this message"},
168     {"-resources", "print default resource file to standard output"},
169     {"-display displayname", "X server to contact"},
170     {"-/+mono", "turn on/off monochrome override"},
171     {"-delay usecs", "microsecond delay between screen updates"},
172     {"-batchcount num", "number of things per batch"},
173     {"-nice level", "nice level for dtscreen process"},
174     {"-saturation value", "saturation of color ramp"},
175     {"-create", "create a window in which to draw"},
176 };
177 #define opDescEntries (sizeof opDesc / sizeof opDesc[0])
178
179 char       *display;
180 char       *mode;
181 float       saturation;
182 int         nicelevel;
183 int         delay;
184 int         batchcount;
185 Bool        mono;
186 Bool        create;
187
188
189 #define t_String        0
190 #define t_Float         1
191 #define t_Int           2
192 #define t_Bool          3
193
194 typedef struct {
195     caddr_t    *var;
196     char       *name;
197     char       *class;
198     char       *def;
199     int         type;
200 }           argtype;
201
202 static argtype genvars[] = {
203     {(caddr_t *) &nicelevel, "nice", "Nice", DEF_NICE, t_Int},
204     {(caddr_t *) &mono, "mono", "Mono", "off", t_Bool},
205     {(caddr_t *) &create, "create", "Create", "off", t_Bool},
206 };
207 #define NGENARGS (sizeof genvars / sizeof genvars[0])
208
209 static argtype modevars[] = {
210     {(caddr_t *) &delay, "delay", "Delay", DEF_DELAY, t_Int},
211     {(caddr_t *) &batchcount, "batchcount", "BatchCount", DEF_BC, t_Int},
212     {(caddr_t *) &saturation, "saturation", "Saturation", DEF_SAT, t_Float},
213 };
214 #define NMODEARGS (sizeof modevars / sizeof modevars[0])
215
216
217 static void
218 Syntax(badOption)
219     char       *badOption;
220 {
221     int         col, len, i;
222
223 #ifdef MIT_R5
224     fprintf(stderr, "%s:  bad command line option:  %s.\n\n",
225             ProgramName, badOption);
226 #else
227     fprintf(stderr, catgets(scmc_catd, 2, 1,
228         "%s:  Bad command line option:  %s.\n\n"), 
229         ProgramName, badOption);
230 #endif
231
232     fprintf(stderr, "usage:  %s", ProgramName);
233     col = 8 + strlen(ProgramName);
234     for (i = 0; i < opDescEntries; i++) {
235         len = 3 + strlen(opDesc[i].opt);        /* space [ string ] */
236         if (col + len > 79) {
237             fprintf(stderr, "\n   ");   /* 3 spaces */
238             col = 3;
239         }
240         fprintf(stderr, " [%s]", opDesc[i].opt);
241         col += len;
242     }
243
244     len = 8 + strlen(LockProcs[0].cmdline_arg);
245     if (col + len > 79) {
246         fprintf(stderr, "\n   ");       /* 3 spaces */
247         col = 3;
248     }
249     fprintf(stderr, " [-mode %s", LockProcs[0].cmdline_arg);
250     col += len;
251     for (i = 1; i < NUMPROCS; i++) {
252         len = 3 + strlen(LockProcs[i].cmdline_arg);
253         if (col + len > 79) {
254             fprintf(stderr, "\n   ");   /* 3 spaces */
255             col = 3;
256         }
257         fprintf(stderr, " | %s", LockProcs[i].cmdline_arg);
258         col += len;
259     }
260     fprintf(stderr, "]\n");
261
262 #ifdef MIT_R5
263     fprintf(stderr, "\nType %s -help for a full description.\n\n",
264             ProgramName);
265 #else
266     fprintf(stderr, catgets(scmc_catd, 2, 2,
267         "\nType %s -help for a full description.\n\n"), 
268         ProgramName);
269 #endif
270     exit(1);
271 }
272
273 static void
274 Help()
275 {
276     int         i;
277
278 #ifdef MIT_R5
279     fprintf(stderr, "usage:\n        %s [-options ...]\n\n", ProgramName);
280     fprintf(stderr, "where options include:\n");
281
282 #else
283     fprintf(stderr, catgets(scmc_catd, 2, 3,
284         "Usage:\n        %s [-options ...]\n\n\
285         where options include:\n"), ProgramName);
286 #endif
287
288     for (i = 0; i < opDescEntries; i++) {
289         fprintf(stderr, "    %-28s %s\n", opDesc[i].opt, opDesc[i].desc);
290     }
291
292 #ifdef MIT_R5
293     fprintf(stderr, "    %-28s %s\n", "-mode mode", "animation mode");
294     fprintf(stderr, "    where mode is one of:\n");
295 #else
296     fprintf(stderr, catgets(scmc_catd, 2, 5, 
297          "    %-28s %s\n\t where mode is one of:\n"), 
298          "-mode mode", "animation mode");
299 #endif
300     for (i = 0; i < NUMPROCS; i++) {
301         fprintf(stderr, "          %-23s %s\n",
302                 LockProcs[i].cmdline_arg, LockProcs[i].desc);
303     }
304     putc('\n', stderr);
305
306     exit(0);
307 }
308
309 static void
310 DumpResources()
311 {
312     int         i;
313
314     printf("%s.mode: %s\n", classname, DEF_MODE);
315
316     for (i = 0; i < NGENARGS; i++)
317         printf("%s.%s: %s\n",
318                classname, genvars[i].name, genvars[i].def);
319
320     for (i = 0; i < NUMPROCS - 1; i++) {
321         printf("%s.%s.%s: %d\n", classname, LockProcs[i].cmdline_arg,
322                "delay", LockProcs[i].def_delay);
323         printf("%s.%s.%s: %d\n", classname, LockProcs[i].cmdline_arg,
324                "batchcount", LockProcs[i].def_batchcount);
325         printf("%s.%s.%s: %g\n", classname, LockProcs[i].cmdline_arg,
326                "saturation", LockProcs[i].def_saturation);
327     }
328     exit(0);
329 }
330
331
332 static void
333 LowerString(s)
334     char       *s;
335 {
336
337     while (*s) {
338         if (isupper(*s))
339             *s += ('a' - 'A');
340         s++;
341     }
342 }
343
344 static void
345 GetResource(database, parentname, parentclass,
346             name, class, valueType, def, valuep)
347     XrmDatabase database;
348     char       *parentname;
349     char       *parentclass;
350     char       *name;
351     char       *class;
352     int         valueType;
353     char       *def;
354     caddr_t    *valuep;         /* RETURN */
355 {
356     char       *type;
357     XrmValue    value;
358     char       *string;
359     char        buffer[1024];
360     char        fullname[1024];
361     char        fullclass[1024];
362     int         len;
363
364     sprintf(fullname, "%s.%s", parentname, name);
365     sprintf(fullclass, "%s.%s", parentclass, class);
366     if (XrmGetResource(database, fullname, fullclass, &type, &value)) {
367         string = value.addr;
368         len = value.size;
369     } else {
370         string = def;
371         len = strlen(string);
372     }
373     (void) strncpy(buffer, string, sizeof(buffer));
374     buffer[sizeof(buffer) - 1] = '\0';
375
376     switch (valueType) {
377     case t_String:
378         {
379             char       *s;
380             s = (char *) malloc(len + 1);
381             if (s == (char *) NULL)
382 #ifdef MIT_R5
383                 error("%s: GetResource - couldn't allocate memory");
384 #else
385             {
386                 fprintf(stderr, catgets(scmc_catd, 2, 18, 
387                      "%s: GetResource - couldn't allocate memory.\n"),ProgramName);
388                 exit(1);
389             }
390 #endif
391             (void) strncpy(s, string, len);
392             s[len] = '\0';
393             *((char **) valuep) = s;
394         }
395         break;
396     case t_Bool:
397         LowerString(buffer);
398         *((int *) valuep) = (!strcmp(buffer, "true") ||
399                              !strcmp(buffer, "on") ||
400                              !strcmp(buffer, "enabled") ||
401                              !strcmp(buffer, "yes")) ? True : False;
402         break;
403     case t_Int:
404         *((int *) valuep) = atoi(buffer);
405         break;
406     case t_Float:
407         *((float *) valuep) = (float) atof(buffer);
408         break;
409     }
410 }
411
412
413 static      XrmDatabase
414 parsefilepath(xfilesearchpath, TypeName, ClassName)
415     char       *xfilesearchpath;
416     char       *TypeName;
417     char       *ClassName;
418 {
419     XrmDatabase database = NULL;
420     char        appdefaults[1024];
421     char       *src;
422     char       *dst;
423
424     src = xfilesearchpath;
425     appdefaults[0] = '\0';
426     dst = appdefaults;
427     while (1) {
428         if (*src == '%') {
429             src++;
430             switch (*src) {
431             case '%':
432             case ':':
433                 *dst++ = *src++;
434                 *dst = '\0';
435                 break;
436             case 'T':
437                 (void) strcat(dst, TypeName);
438                 src++;
439                 dst += strlen(TypeName);
440                 break;
441             case 'N':
442                 (void) strcat(dst, ClassName);
443                 src++;
444                 dst += strlen(ClassName);
445                 break;
446             case 'S':
447                 src++;
448                 break;
449             default:
450                 src++;
451                 break;
452             }
453         } else if (*src == ':') {
454             database = XrmGetFileDatabase(appdefaults);
455             if (database == NULL) {
456                 dst = appdefaults;
457                 src++;
458             } else
459                 break;
460         } else if (*src == '\0') {
461             database = XrmGetFileDatabase(appdefaults);
462             break;
463         } else {
464             *dst++ = *src++;
465             *dst = '\0';
466         }
467     }
468     return database;
469 }
470
471 /*******************************************************************/
472 /** screenIOErrorHandler                                          **/
473 /**                                                               **/
474 /** this function will exit cleanly when the connection is broken **/
475 /*******************************************************************/
476 static int screenIOErrorHandler(dpy)
477         Display *dpy;
478 {
479         exit(1);
480         return 1;
481 }
482
483 static void
484 open_display()
485 {
486     if (display != NULL) {
487         char       *colon = strchr(display, ':');
488         int         n = colon - display;
489
490         if (colon == NULL)
491 #ifdef MIT_R5
492             error("%s: Malformed -display argument, \"%s\"\n", display);
493 #else
494         {
495             fprintf(stderr, catgets(scmc_catd, 2, 19,
496                 "%s: Malformed -display argument:  %s.\n"), ProgramName,display);
497             exit(1);
498         }
499 #endif
500
501     } else
502         display = ":0.0";
503     if (!(dsp = XOpenDisplay(display)))
504 #ifdef MIT_R5
505         error("%s: unable to open display %s.\n", display);
506 #else
507     {
508         fprintf(stderr, catgets(scmc_catd, 2, 17,
509                 "%s: Unable to open display %s.\n"),ProgramName, display);
510         exit(1);
511     }
512 #endif
513
514     XSetIOErrorHandler(screenIOErrorHandler);
515 }
516
517 void
518 printvar(class, var)
519     char       *class;
520     argtype     var;
521 {
522     switch (var.type) {
523     case t_String:
524         fprintf(stderr, "%s.%s: %s\n",
525                 class, var.name, *((char **) var.var));
526         break;
527     case t_Bool:
528         fprintf(stderr, "%s.%s: %s\n",
529                 class, var.name, *((int *) var.var)
530                 ? "True" : "False");
531         break;
532     case t_Int:
533         fprintf(stderr, "%s.%s: %d\n",
534                 class, var.name, *((int *) var.var));
535         break;
536     case t_Float:
537         fprintf(stderr, "%s.%s: %g\n",
538                 class, var.name, *((float *) var.var));
539         break;
540     }
541 }
542
543
544 void
545 GetResources(argc, argv)
546     int         argc;
547     char       *argv[];
548 {
549     XrmDatabase RDB = NULL;
550     XrmDatabase modeDB = NULL;
551     XrmDatabase nameDB = NULL;
552     XrmDatabase cmdlineDB = NULL;
553     XrmDatabase generalDB = NULL;
554     XrmDatabase homeDB = NULL;
555     XrmDatabase applicationDB = NULL;
556     XrmDatabase serverDB = NULL;
557     XrmDatabase userDB = NULL;
558     char        userfile[1024];
559     char       *homeenv;
560     char       *userpath;
561     char       *env;
562     char       *serverString;
563     int         i;
564     /***************************/
565     /** new variables for AIX **/
566     /***************************/
567     char        delaySpecifier[64];
568     char        batchcountSpecifier[64];
569     char        saturationSpecifier[64];
570
571     XrmInitialize();
572
573     for (i = 0; i < argc; i++) {
574         if (!strncmp(argv[i], "-help", strlen(argv[i])))
575             Help();
576         /* NOTREACHED */
577     }
578
579     /*
580      * get -name arg from command line so you can have different resource
581      * files for different configurations/machines etc...
582      */
583     XrmParseCommand(&nameDB, nameTable, 1, ProgramName,
584                     &argc, argv);
585     GetResource(nameDB, ProgramName, "*", "name", "Name", t_String,
586                 DEF_CLASSNAME, &classname);
587
588     homeenv = getenv("HOME");
589     if (!homeenv)
590         homeenv = "";
591
592     env = getenv("XFILESEARCHPATH");
593     applicationDB = parsefilepath(env ? env : DEF_FILESEARCHPATH,
594                                   "app-defaults", classname);
595
596     XrmParseCommand(&cmdlineDB, cmdlineTable, cmdlineEntries, ProgramName,
597                     &argc, argv);
598
599     userpath = getenv("XUSERFILESEARCHPATH");
600     if (!userpath) {
601         env = getenv("XAPPLRESDIR");
602         if (env)
603             sprintf(userfile, "%s/%%N:%s/%%N", env, homeenv);
604         else
605             sprintf(userfile, "%s/%%N", homeenv);
606         userpath = userfile;
607     }
608     userDB = parsefilepath(userpath, "app-defaults", classname);
609
610     (void) XrmMergeDatabases(applicationDB, &RDB);
611     (void) XrmMergeDatabases(userDB, &RDB);
612     (void) XrmMergeDatabases(cmdlineDB, &RDB);
613
614     env = getenv("DISPLAY");
615     GetResource(RDB, ProgramName, classname, "display", "Display", t_String,
616                 env ? env : DEF_DISPLAY, &display);
617     open_display();
618     serverString = XResourceManagerString(dsp);
619     if (serverString) {
620         serverDB = XrmGetStringDatabase(serverString);
621         (void) XrmMergeDatabases(serverDB, &RDB);
622     } else {
623         char        buf[1024];
624         sprintf(buf, "%s/.Xdefaults", homeenv);
625         homeDB = XrmGetFileDatabase(buf);
626         (void) XrmMergeDatabases(homeDB, &RDB);
627     }
628
629     XrmParseCommand(&generalDB, genTable, genEntries, ProgramName, &argc, argv);
630     (void) XrmMergeDatabases(generalDB, &RDB);
631
632     GetResource(RDB, ProgramName, classname, "mode", "Mode", t_String,
633                 DEF_MODE, (caddr_t *) &mode);
634
635     /*
636      * if random< mode, then just grab a random entry from the table
637      */
638     if (!strcmp(mode, randomstring))
639         mode = LockProcs[random() % (NUMPROCS - 2)].cmdline_arg;
640
641     sprintf(modename, "%s.%s", ProgramName, mode);
642     sprintf(modeclass, "%s.%s", classname, mode);
643
644
645     /*********************************************************************/
646     /** New code for AIX                                                **/
647     /** We must build the specifier fields of the modeTable on the fly. **/
648     /*********************************************************************/
649     sprintf(delaySpecifier,      ".%s.delay",      mode);
650     sprintf(batchcountSpecifier, ".%s.batchcount", mode);
651     sprintf(saturationSpecifier, ".%s.saturation", mode);
652     modeTable[0].specifier = delaySpecifier;
653     modeTable[1].specifier = batchcountSpecifier;
654     modeTable[2].specifier = saturationSpecifier;
655
656
657     XrmParseCommand(&modeDB, modeTable, modeEntries, ProgramName, &argc, argv);
658     (void) XrmMergeDatabases(modeDB, &RDB);
659
660     /* Parse the rest of the command line */
661     for (argc--, argv++; argc > 0; argc--, argv++) {
662         if (**argv != '-')
663             Syntax(*argv);
664         switch (argv[0][1]) {
665         case 'r':
666             DumpResources();
667             /* NOTREACHED */
668         default:
669             Syntax(*argv);
670             /* NOTREACHED */
671         }
672     }
673
674     /* the RDB is set, now query load the variables from the database */
675
676     for (i = 0; i < NGENARGS; i++)
677         GetResource(RDB, ProgramName, classname,
678                     genvars[i].name, genvars[i].class,
679                     genvars[i].type, genvars[i].def, genvars[i].var);
680
681     for (i = 0; i < NMODEARGS; i++)
682         GetResource(RDB, modename, modeclass,
683                     modevars[i].name, modevars[i].class,
684                     modevars[i].type, modevars[i].def, modevars[i].var);
685
686     (void) XrmDestroyDatabase(RDB);
687
688 }
689
690
691 CheckResources()
692 {
693     int         i;
694
695     if (batchcount < 1)
696         Syntax("-batchcount argument must be positive.");
697     if (saturation < 0.0 || saturation > 1.0)
698         Syntax("-saturation argument must be between 0.0 and 1.0.");
699     if (delay < 0)
700         Syntax("-delay argument must be positive.");
701
702     for (i = 0; i < NUMPROCS; i++) {
703         if (!strncmp(LockProcs[i].cmdline_arg, mode, strlen(mode))) {
704             init = LockProcs[i].lp_init;
705             callback = LockProcs[i].lp_callback;
706             break;
707         }
708     }
709     if (i == NUMPROCS) {
710 #ifdef MIT_R5
711         fprintf(stderr, "Unknown mode: ");
712 #else
713         fprintf(stderr, catgets(scmc_catd, 2, 7, 
714              "Unknown mode: "));
715 #endif
716         Syntax(mode);
717     }
718 }