dtfile: remove register keyword
[oweals/cde.git] / cde / programs / dthello / dthello.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these libraries and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /*                                                                      *
24  * (c) Copyright 1993, 1994 Hewlett-Packard Company                     *
25  * (c) Copyright 1993, 1994 International Business Machines Corp.       *
26  * (c) Copyright 1993, 1994 Sun Microsystems, Inc.                      *
27  * (c) Copyright 1993, 1994 Novell, Inc.                                *
28  */
29 #ifdef VERBOSE_REV_INFO
30 static char rcsid[] = "$TOG: dthello.c /main/9 1998/04/20 12:52:17 mgreess $";
31 #endif /* VERBOSE_REV_INFO */
32 /******************************<+>*************************************
33  **********************************************************************
34  **
35  **  File:        dthello.c
36  **
37  **  Project:     HP Visual User Environment
38  **
39  **  Description:
40  **  -----------
41  **  This file implements the startup transition for the DT 
42  **  environment
43  **
44  **
45  **********************************************************************
46  **
47  **     (c) Copyright 1990, 1991, 1992 Hewlett-Packard Company
48  **     All rights reserved
49  **
50  **********************************************************************
51  ******************************<+>*************************************/
52
53 /*
54  * Notes on conditional compilation:
55  *
56  * AUTO_TOP     If defined, the dthello window will automatically
57  *              raise itself over any window that obscures it.
58  *
59  * BLOCK_CENTER_FILES
60  *              If defined, dthello will center the text from
61  *              input files as a block as opposed to line-by-line.
62  */
63
64 /*
65  * Included Files:
66  */
67
68 #include <stdio.h>
69 #include <stdlib.h>
70 #include <unistd.h>
71 #include <X11/Xlib.h>
72 #include <X11/Intrinsic.h>
73 #include <X11/StringDefs.h>
74 #include <X11/Xutil.h>
75 #include <Xm/MwmUtil.h>
76 #include <sys/signal.h>
77 #include <Xm/Xm.h>
78 #include <Dt/GetDispRes.h>
79 #include <limits.h>
80 #include <locale.h>
81 #ifndef NO_MESSAGE_CATALOG
82 # include <nl_types.h>
83 #endif
84
85 #include <Dt/EnvControlP.h>
86 #include "dthello.h"
87
88 #ifndef NO_MESSAGE_CATALOG
89 # define GETMESSAGE(set, number, string)    GetMessage(set, number, string)
90 #else
91 # define GETMESSAGE(set, number, string)    string
92 #endif
93
94 #if !defined(NL_CAT_LOCALE)
95 #define NL_CAT_LOCALE 0
96 #endif
97
98 /* 
99  * Globals
100  */
101 Window              welcome;            /* Welcome window ID */
102 Display            *dpy;                /* X server connection */
103 struct globalStruct vhGD;
104 int                 x_offset = 0;       /* for left-justifying text */
105 int                 box_line_width = 0; /* for drawing a box */
106 XFontSet            fontset;            /* Font descriptor for ILS */
107 unsigned long       textHeight;         /* Font size parameters */
108 unsigned long       fg, bg;             /* Pixel values */
109 Boolean             colorSuccess = True; /* Success at allocating colors */
110 XGCValues           gcv;                /* Struct for creating GC */
111 unsigned int        totalHeight;        /* total Height used for text */
112 unsigned int        displayHeight;      /* height of display in pixels */
113 int                 maxWidth;           /* max width of lines read in from file */
114 unsigned int        displayWidth;       /* width of display in pixels */
115 GC                  gc;                 /* GC to draw with */
116
117 static XrmOptionDescRec optTable[] = {
118 {"-font",       "*vfont",       XrmoptionSepArg,        (XtPointer) NULL},
119 {"-fnt",        "*vfont",       XrmoptionSepArg,        (XtPointer) NULL},
120 };
121 static int noptTable = sizeof(optTable)/sizeof(optTable[0]);
122
123 ArgSpec argSpecs[] =
124 {
125     {"-bground", 8},    /* background color */
126 #define BG_ARG          0
127
128     {"-fground", 8},    /* foreground color */
129 #define FG_ARG          1
130
131     {"-string", 7},     /* string to display */
132 #define STRING_ARG      2
133
134     {"-fnt", 4},        /* font to use */
135 #define FONT_ARG        3
136
137     {"-timeout", 8},    /* timeout amount in seconds*/
138 #define TIME_ARG        4
139
140     {"-file", 5},       /* file */
141 #define FILE_ARG        5
142
143 };
144
145 char          *ppchFileNames[MAX_FILES]; /* names of files to print */
146 unsigned char *ppchText[MAX_LINES]; /* text lines to print out */
147 int            numFiles;            /* number of files to print */
148 int numLines;                       /* number of text lines to print out */
149 #ifdef BLOCK_CENTER_FILES
150 int            centerLines;         /* number of text lines to print centered */
151 #endif /* BLOCK_CENTER_FILES */
152 char *progName;                     /* who we are */
153 char          *fontArg;             /* font argument */
154 int            sizeFontArg;
155 char          *stringArg;           /* string argument */
156 int            sizeStringArg;
157 char          *bgArg;               /* background argument */
158 int            sizeBgArg;
159 char          *fgArg;               /* foreground argument */
160 int            sizeFgArg;
161 char          *xoffsetArg;          /* text x_offset argument */
162 int            sizeXoffsetArg;
163 char          *timeArg;             /* timeout argument, in seconds */
164 int            sizeTimeArg;
165 int            sizeFileArg;
166 Boolean        Done;                /* while painting text */
167
168 static VhResourceEntry restable[] = {
169     { vNbackground,  vCBackground, &bgArg,              &sizeBgArg      },
170     { vNforeground,  vCForeground, &fgArg,              &sizeFgArg      },
171     { vNfont,        vCFont,       &fontArg,            &sizeFontArg    },
172     { vNxoffset,     vCXoffset,    &xoffsetArg,         &sizeXoffsetArg },
173     { vNstring,      vCString,     &stringArg,          &sizeStringArg  },
174     { vNfile,        vCFile,       &ppchFileNames[0],   &sizeFileArg    },
175     { vNtimeout,     vCTimeout,    &timeArg,            &sizeTimeArg    },
176 };
177
178 void
179 Usage(void)
180 {
181       fprintf(stderr, (char *) GETMESSAGE (4, 4, 
182 "usage: %s [-display <display>] [-bground <color>] [-fground <color>]\n"),
183                   progName);
184       fprintf(stderr, "%s", (char *) GETMESSAGE (4, 5, 
185 "\t[-font <font>] [-string <message>] [-timeout <seconds>] [-file <name>]\n"));
186 }
187
188 \f
189 /*************************************<->*************************************
190  *
191  *  main (argc, argv)
192  *
193  *
194  *  Description:
195  *  -----------
196  *  This is the main routine that does almost all the work.
197  *
198  *  Inputs:
199  *  ------
200  *  argc = Std C argument count
201  *  argv = Std C argument vector
202  *
203  *  Outputs:
204  *  --------
205  *  Exit code
206  *
207  *  Comments:
208  *  ---------
209  *  This works by creating an override-redirect window the size of
210  *  the screen and painting a message on it. At the same time, a 
211  *  1x1 window is created that will be picked up by the window 
212  *  manager.  When the window manager reparents the little window,
213  *  this program exits.
214  *
215  *  Synopsis:
216  *  ---------
217  *  dthello [-display <display>] [-fground <color>] [-bground <color>]
218  *           [-font <fontname>] [-string <message>] [-file <filename>]
219  *           [-timeout <seconds>]
220  * 
221  *************************************<->***********************************/
222 int
223 main (int argc, char **argv)
224 {
225     Window      wmwin;          /* Window ID for wm */
226     XEvent      event;          /* Event received */
227     unsigned long mask;         /* mask for window attribs */
228     XSetWindowAttributes xwa;   /* Set Window Attribute struct */
229     int         argn;           /* temp for parsing args */
230     XColor      colorDef;       /* for parsing/allocating colors */
231     Colormap    colormap;       /* color map of screen */
232     Atom        xaMwmHints;     /* mwm hints atom */
233     PropMotifWmHints  mwmHints; /* mwm hints structure */
234     Visual *pdv;                /* X visual structure */
235     FILE        *fp;            /* file pointer */
236     int         i;              /* loop index */
237     char        *default_string;        /* default message */
238     XtAppContext appcontext;
239     char        *def_str;
240     char        **missing_clist;
241     int         missing_count;
242     XFontSetExtents *extents;
243
244     XtSetLanguageProc( NULL, NULL, NULL );
245
246     /*
247      * Initialization
248      */
249     /*
250      * Set up NLSPATH, app-defaults, etc. for this DT client.
251      */
252     _DtEnvControl(DT_ENV_SET);
253
254     /*
255      * Process command line arguments
256      */
257     progName = argv[0];
258     /* fontArg = DEFAULT_FONT; */
259     bgArg = NULL;
260     fgArg = NULL;
261     timeArg = DEFAULT_TIME;
262     numFiles = 0;
263     sizeFileArg = 0;
264
265     /*
266      * Initialize  Toolkit, open display
267      */
268     XtToolkitInitialize();
269     appcontext = XtCreateApplicationContext();
270
271     dpy = XtOpenDisplay (appcontext, NULL, argv[0], DTHELLO_CLASS_NAME, 
272                          optTable, noptTable, (int *)(&argc), argv);
273
274     if (dpy == NULL) 
275     {
276         setlocale(LC_ALL, "");
277         fprintf(stderr, (char *) 
278             GETMESSAGE(4, 1, "%s: can't open display\n"), progName);
279         exit(1);
280     }
281
282     default_string = strdup (
283     ((char *)GETMESSAGE(2, 3, 
284                         "Starting the\nCommon Desktop Environment\n\n")));
285
286     stringArg = default_string;
287
288     /*
289      * Find appropriate default font
290      * and offset from the left side of the screen
291      */
292
293     switch (_DtGetDisplayResolution(dpy, XDefaultScreen(dpy)))
294     {
295         case LOW_RES_DISPLAY:
296                 fontArg = DEFAULT_FONT_SMALL;
297                 x_offset = DEFAULT_XOFFSET_SMALL;
298                 box_line_width = BOX_LINE_WIDTH_SMALL;
299                 break;
300         
301         case MED_RES_DISPLAY:
302                 fontArg = DEFAULT_FONT_MEDIUM;
303                 x_offset = DEFAULT_XOFFSET_MEDIUM;
304                 box_line_width = BOX_LINE_WIDTH_MEDIUM;
305                 break;
306
307         case HIGH_RES_DISPLAY:
308                 fontArg = DEFAULT_FONT_LARGE;
309                 x_offset = DEFAULT_XOFFSET_LARGE;
310                 box_line_width = BOX_LINE_WIDTH_LARGE;
311                 break;
312         default:
313                 fontArg = DEFAULT_FONT_SMALL;
314                 x_offset = DEFAULT_XOFFSET_SMALL;
315                 box_line_width = BOX_LINE_WIDTH_SMALL;
316                 break;
317     }
318
319     /*
320      * Fetch resources
321      */
322     VhGetResources (dpy, progName, DTHELLO_CLASS, 
323                         restable, XtNumber(restable));
324
325     /* assign the x_offset to the value set in the resource list if given by the user */
326     /* RK 11.06.93                                                                    */
327     if( xoffsetArg != NULL)
328         x_offset = atoi(xoffsetArg);
329     if (x_offset < 0)
330     {
331         x_offset = -x_offset;
332     }
333
334     if (sizeFileArg != 0)
335     {
336         numFiles = 1;
337     }
338
339     /*
340      * Parse remaining command line arguments
341      */
342     for (argn = 1; argn < argc; argn++)
343     {
344         if ((*argv[argn] == '-') &&
345             (argn+1 < argc))
346         {
347             if (ArgMatch (argv[argn], BG_ARG))
348             {
349                 bgArg = argv[++argn];
350                 continue;
351             }
352
353             else if (ArgMatch (argv[argn], FG_ARG))
354             {
355                 fgArg = argv[++argn];
356                 continue;
357             }
358
359             else if (ArgMatch (argv[argn], STRING_ARG))
360             {
361                 stringArg = argv[++argn];
362                 continue;
363             }
364
365             else if (ArgMatch (argv[argn], FONT_ARG))
366             {
367                 fontArg = argv[++argn];
368                 continue;
369             }
370
371             else if (ArgMatch (argv[argn], TIME_ARG))
372             {
373                 timeArg = argv[++argn];
374                 if (atoi(timeArg) <= 0)
375                 {
376                     fprintf (stderr, (char *) 
377                         GETMESSAGE(4, 2, "%s: timeout must be positive\n"),
378                         argv[0]);
379                     timeArg = DEFAULT_TIME;
380                 }
381                 continue;
382             }
383
384             else if (ArgMatch (argv[argn], FILE_ARG))
385             {
386                 argn++;
387                 if (numFiles < MAX_FILES)
388                 {
389                     ppchFileNames[numFiles] = (char *) argv[argn];
390                     numFiles++;
391                 }
392                 else
393                 {
394                   fprintf(stderr, (char *) GETMESSAGE(4, 3, 
395                       "%1$s: Maxiumum of %2$d files allowed, skipping %3$s\n"), 
396                       argv[0], MAX_FILES, argv[argn]);
397                 }
398                 continue;
399             }
400
401             else
402             {
403                 Usage();
404                 exit(1);
405             }
406         }
407         else
408         {
409             Usage();
410             exit(1);
411         }
412     }
413
414
415     displayHeight = XDisplayHeight (dpy, XDefaultScreen(dpy));
416     displayWidth = XDisplayWidth (dpy, XDefaultScreen(dpy));
417
418     /*
419      * Set default fg/bg colors if not specified.
420      * (adjust for low-color systems)
421      */
422
423     pdv = XDefaultVisual(dpy, XDefaultScreen(dpy));
424
425     /*
426      * Set default colors if not specified on command line.
427      */
428     if ((XDefaultDepth(dpy, XDefaultScreen(dpy)) <= 4) ||
429         (pdv->class == StaticGray) ||
430         (pdv->class == GrayScale))
431     {
432         /*
433          * B&W, GrayScale, or low-color systems
434          */
435         if (!bgArg)
436         {
437             bgArg = DEFAULT_LOW_BG;
438         }
439
440         if (!fgArg)
441         {
442             fgArg = DEFAULT_LOW_FG;
443         }
444     }
445     else
446     {
447         /*
448          * Medium- to High-color systems
449          */
450         if (!bgArg)
451         {
452             bgArg = DEFAULT_BG;
453         }
454
455         if (!fgArg)
456         {
457             fgArg = DEFAULT_FG;
458         }
459     }
460
461     /*
462      * Load the font.
463      */
464     if ((fontset = XCreateFontSet(dpy, fontArg, &missing_clist, &missing_count,
465                                   &def_str)) == NULL)
466     {
467         fprintf(stderr, (char *) 
468             GETMESSAGE (4, 6, "%1$s: display %2$s doesn't know font %3$s\n"),
469                 argv[0], DisplayString(dpy), fontArg);
470
471         if ((fontset = XCreateFontSet(dpy, DEFAULT_FONT, &missing_clist,
472                                         &missing_count, &def_str)) == NULL)
473         {
474             fprintf(stderr, (char *)
475             GETMESSAGE (4, 6, "%1$s: display %2$s doesn't know font %3$s\n"),
476                     argv[0], DisplayString(dpy), DEFAULT_FONT);
477         }
478   
479         if ((NULL == fontset) &&
480             (fontset = XCreateFontSet(dpy, FIXED_FONT, &missing_clist,
481                                       &missing_count, &def_str)) == NULL)
482         {
483             fprintf(stderr, (char *)
484             GETMESSAGE (4, 6, "%1$s: display %2$s doesn't know font %3$s\n"),
485                     argv[0], DisplayString(dpy), FIXED_FONT);
486             exit(1);
487         }
488     }
489     extents = XExtentsOfFontSet(fontset);
490     textHeight = extents->max_ink_extent.height;
491
492     /*
493      * Print the copyright file by default if no other file
494      * specified
495      */
496 #ifdef DEFAULT_FILE
497     if (numFiles == 0)
498     {
499         ppchFileNames[numFiles] = (char *) DEFAULT_FILE;
500         numFiles = 1;
501     }
502 #endif
503
504     /*
505      * Break the text string up into separate lines
506      * and place into message buffer.
507      */
508     SeparateTextLines ((unsigned char *)stringArg);
509
510 #ifdef BLOCK_CENTER_FILES
511     centerLines = numLines;
512 #endif /* BLOCK_CENTER_FILES */
513
514     for (i = 0; i < numFiles; i++)
515     {
516         maxWidth = 0;
517         if (!(fp = fopen ((char *)ppchFileNames[i], "r")))
518         {
519             fprintf (stderr, (char *) 
520                 GETMESSAGE (4, 7, "%1$s: unable to open file %2$s\n"),
521                 argv[0], ppchFileNames[i]);
522         }
523         else
524         {
525             /* 
526              * read in lines
527              */
528             ReadInTextLines (fp, fontset, (unsigned int *)&maxWidth);
529         }
530     }
531
532     /*
533      * Get the colors 
534      */
535     colormap = XDefaultColormap (dpy, XDefaultScreen(dpy));
536
537     /* 
538      * Get background color
539      */
540     if (!XParseColor (dpy, colormap, bgArg, &colorDef))
541     {
542         /* failed to get background color, try low color default */
543         colorSuccess = False; 
544         fprintf(stderr, (char *) GETMESSAGE (4, 8, 
545             "%1$s: can't set background to %2$s, using %3$s.\n"),
546                     argv[0], bgArg, DEFAULT_LOW_BG);
547         XParseColor (dpy, colormap, DEFAULT_LOW_BG, &colorDef);
548     }
549     XAllocColor (dpy, colormap, &colorDef);
550
551     bg = colorDef.pixel;
552
553     /* 
554      * Get foreground color
555      */
556     if (!XParseColor (dpy, colormap, fgArg, &colorDef))
557     {
558         /* failed to get foreground color, try low color default */
559         colorSuccess = False; 
560         fprintf(stderr, (char *) GETMESSAGE (4, 9, 
561             "%1$s: can't set foreground to %2$s, using %3$s.\n"),
562                     argv[0], fgArg, DEFAULT_LOW_FG);
563         XParseColor (dpy, colormap, DEFAULT_LOW_FG, &colorDef);
564     }
565     XAllocColor (dpy, colormap, &colorDef);
566
567     fg = colorDef.pixel;
568
569     /* 
570      * Create 1x1 window to catch reparenting action of window manager
571      * Request no mwm decoration to reduce flash.
572      * Request no mwm functions to avoid icon in icon box.
573      */
574     wmwin = XCreateSimpleWindow(dpy, DefaultRootWindow(dpy),
575                               0, 0, 1, 1, 0, bg, bg);
576
577     xaMwmHints = XInternAtom (dpy, _XA_MOTIF_WM_HINTS, 0);
578
579     mwmHints.flags = MWM_HINTS_DECORATIONS | MWM_HINTS_FUNCTIONS;
580     mwmHints.decorations = 0;
581     mwmHints.functions = 0;
582
583     XChangeProperty (dpy, wmwin, xaMwmHints, xaMwmHints, 32, 
584         PropModeReplace, (unsigned char *) &mwmHints, 
585         sizeof(PropMotifWmHints)/sizeof(long));
586
587     XSelectInput (dpy, wmwin, StructureNotifyMask);
588
589     XMapWindow(dpy, wmwin);
590
591     /* 
592      * Create override-redirect window for display of transition
593      * message.
594      */
595
596     welcome = XCreateSimpleWindow (dpy, DefaultRootWindow (dpy), 0, 0,
597         displayWidth, displayHeight, 0, bg, bg);
598
599     mask = CWOverrideRedirect | CWEventMask | CWCursor;
600
601     xwa.override_redirect = 1;
602 #ifdef AUTO_TOP
603     xwa.event_mask = ExposureMask | VisibilityChangeMask;
604 #else /* AUTO_TOP */
605     xwa.event_mask = ExposureMask;
606 #endif /* AUTO_TOP */
607     xwa.cursor = GetHourGlass (dpy);
608
609     XChangeWindowAttributes (dpy, welcome, mask, &xwa);
610
611     XMapWindow(dpy, welcome);
612     /*
613      * Event loop for painting text
614      */
615
616     Done = True;
617
618     while (Done) 
619     {
620         /*
621          * Get the next event
622          */
623         /* XNextEvent(dpy, &event); */
624
625         XtAppNextEvent(appcontext, &event);
626
627         if (event.type == Expose && 
628             event.xexpose.window == welcome &&
629             event.xexpose.count == 0) 
630         {
631
632             /*
633              * Remove any other pending Expose events from the queue 
634              */
635             while (XCheckTypedEvent(dpy, Expose, &event));
636
637             /*
638              * Create the GC for drawing the box and painting the text.
639              */
640             gcv.foreground = fg;
641             gcv.background = bg;
642             gc = XCreateGC(dpy, welcome, (GCForeground | GCBackground), &gcv);
643             XClearWindow(dpy, welcome);
644             DrawBox();
645             PaintText();
646             XFlush(dpy);
647             Done = False;
648         }
649     } /* end while */
650
651     /* 
652      * set up the timeout
653      */
654     signal (SIGALRM, (void (*)()) CatchAlarm);
655     alarm (atoi(timeArg));
656
657     /*
658      * Event loop
659      */
660     while (True) 
661     {
662         /*
663          * Get the next event
664          */
665         /* XNextEvent(dpy, &event); */
666
667         XtAppNextEvent(appcontext, &event);
668
669         if (event.type == ReparentNotify &&
670             event.xany.window == wmwin)
671         {
672             /*
673              * this is our cue...exit, stage left
674              */
675             alarm(0);
676             break;
677         }
678         else
679         {
680                 /* normal color serving process */
681                 XtDispatchEvent(&event);                
682         }
683
684     } /* end while */
685
686     exit(0);
687 }
688
689 \f
690 /*************************************<->*************************************
691  *
692  *  ArgMatch (pch, arn)
693  *
694  *
695  *  Description:
696  *  -----------
697  *  This function determines if a string matches a predefined switch.
698  *
699  *  Inputs:
700  *  ------
701  *  pch = candidate string
702  *  arn = number of switch we are trying to match.
703  *
704  *  Outputs:
705  *  --------
706  *  Return = True if match succeeds.
707  *
708  *  Comments:
709  *  ---------
710  *  Would need work to be localized.
711  *
712  *************************************<->***********************************/
713 int
714 ArgMatch (char *pch, int arn)
715 {
716     int rval = False;
717
718     if (!strncmp(pch, argSpecs[arn].name, argSpecs[arn].len))
719     {
720         rval = True;
721     }
722
723     return (rval);
724 }
725
726 \f
727 /*************************************<->*************************************
728  *
729  *  SkipWhitespace (*pch)
730  *
731  *
732  *  Description:
733  *  -----------
734  *  This procedure scans a string and returns a pointer to the first
735  *  non-whitespace character.
736  *
737  *  Inputs:
738  *  ------
739  *  pch = pointer to string to scan
740  *
741  *  Outputs:
742  *  --------
743  *  Return = pointer to first non-white character
744  *
745  *  Comments:
746  *  ---------
747  *  Skips blanks and horizontal tabs.
748  *
749  *************************************<->***********************************/
750 unsigned char *
751 SkipWhitespace (unsigned char *pch)
752 {
753     int chlen;
754
755     if (pch)
756     {
757         while ((*pch != '\0') &&
758                ((chlen = mblen ((char *)pch, MB_CUR_MAX)) == 1) &&
759                ((*pch == '\t') || (*pch == ' ')))
760         {
761                 pch += chlen;
762         }
763     }
764     return (pch);
765 }
766
767
768 \f
769 /*************************************<->*************************************
770  *
771  *  KillNewlines (*pch)
772  *
773  *
774  *  Description:
775  *  -----------
776  *  This procedure scans a string and replaces the first newline
777  *  with a NULL.
778  *
779  *  Inputs:
780  *  ------
781  *  pch = pointer to string to scan
782  *
783  *  Outputs:
784  *  --------
785  *  pch = modified
786  *
787  *  Comments:
788  *  ---------
789  *
790  *************************************<->***********************************/
791 void
792 KillNewlines (unsigned char *pch)
793 {
794     int chlen;
795
796     if (pch)
797     {
798         while (*pch != '\0')
799         {
800             if (((chlen = mblen ((char *)pch, MB_CUR_MAX)) == 1) &&
801                 (*pch == '\n'))
802             {
803                 *pch = '\0';
804                 break;
805             }
806             pch += chlen;
807         }
808     }
809 }
810
811 \f
812 /*************************************<->*************************************
813  *
814  *  ReadInTextLines (fp, font, pMaxWidth)
815  *
816  *
817  *  Description:
818  *  -----------
819  *  This procedure reads in lines from a file for the message to 
820  *  display.
821  *
822  *  Inputs:
823  *  ------
824  *  pchIn = pointer to message string
825  *  font = font structure to be used to print with
826  *  pMaxWidth = width of largest line
827  *
828  *  Outputs:
829  *  --------
830  *  Return = none
831  *  modifies global numLines
832  *
833  *  Comments:
834  *  ---------
835  *  Global data ppchText is modified by this routine to contain 
836  *  copies of the text lines from pchIn. pchIn is not modified.
837  *
838  *************************************<->***********************************/
839 void
840 ReadInTextLines (FILE *fp, XFontSet fontset, unsigned int *pMaxWidth)
841 {
842     unsigned int width;
843     int allowedLines;
844
845     /* count the number of lines in the file */
846     allowedLines = (displayHeight - (2 * box_line_width))/ textHeight;
847
848     while (numLines < allowedLines)
849     {
850         ppchText[numLines] = (unsigned char *) malloc (1+MAX_COLUMNS);
851         if (!ppchText[numLines] ||
852             !fgets ((char *)ppchText[numLines], MAX_COLUMNS, fp))
853         {
854             break;
855         }
856         KillNewlines (ppchText[numLines]);
857 #ifndef BLOCK_CENTER_FILES
858         ppchText[numLines] = SkipWhitespace (ppchText[numLines]);
859 #endif /* not BLOCK_CENTER_FILES */
860         width = XmbTextEscapement(fontset, (char *)(ppchText[numLines]),
861                         strlen((char *)ppchText[numLines]));
862         if (width > *pMaxWidth)
863         {
864             *pMaxWidth = width;
865         }
866         numLines++;
867     }
868 }
869
870 \f
871 /*************************************<->*************************************
872  *
873  *  SeparateTextLines (pchIn)
874  *
875  *
876  *  Description:
877  *  -----------
878  *  This procedure takes a message string and separates it into
879  *  text lines based on the presence of new line characters.
880  *
881  *  Inputs:
882  *  ------
883  *  pchIn = pointer to message string
884  *
885  *  Outputs:
886  *  --------
887  *  Return = none
888  *
889  *  Comments:
890  *  ---------
891  *  Global data ppchText is modified by this routine to contain 
892  *  copies of the text lines from pchIn. pchIn is not modified.
893  *
894  *************************************<->***********************************/
895 void
896 SeparateTextLines (unsigned char *pchIn)
897 {
898     unsigned char *pch, *pch1, *pch2;
899     unsigned char *pchInEnd;
900     int i, chlen = 0;
901
902     /* count the number of new line characters in the string */
903
904     numLines = 1;
905     for (pch = pchIn; *pch; )
906     {
907         if (((chlen = mblen ((char *)pch, MB_CUR_MAX)) == 1) &&
908             (*pch == '\n'))
909         {
910             numLines++;
911         }
912         pch += chlen;
913     }
914
915     if ((chlen == 1) && (*(pch-1) == '\n'))
916     {
917         numLines--;             /* don't count terminating newline */
918     }
919
920     pch2 = pch1 = pchIn;
921     pchInEnd = pchIn + strlen((char *)pchIn);
922
923     for (i = 0; (i < numLines) && (pch1 < pchInEnd); i++)
924     {
925         while ((*pch2 != '\0') &&
926                !(((chlen = mblen ((char *)pch2, MB_CUR_MAX)) == 1) &&
927                  (*pch2 == '\n')))
928         {
929             pch2 += chlen;
930         }
931         if (*pch2 == '\n')
932         {
933             *pch2 = '\0';
934         }
935
936         ppchText[i] = (unsigned char *) malloc (1+strlen ((char *)pch1));
937         if (ppchText[i])
938         {
939             strcpy ((char *)ppchText[i], (char *)pch1);
940         }
941         else
942         {
943             fprintf (stderr, (char *) GETMESSAGE (4, 10, 
944                 "%s: Insufficient memory (SeparateTextLines)\n"), 
945                 progName);
946             exit (1);
947         }
948
949         /* advance pointers */
950         pch1 = ++pch2;
951   
952     }
953 }
954
955
956 \f
957 /*************************************<->*************************************
958  *
959  *  CatchAlarm (sig)
960  *
961  *
962  *  Description:
963  *  -----------
964  *  This function catches the SIG_ALRM signal generated when the
965  *  timer expires.
966  *
967  *  Inputs:
968  *  ------
969  *  sig = signal number
970  *
971  *  Outputs:
972  *  --------
973  *  Return = none
974  *
975  *  Comments:
976  *  ---------
977  *
978  *************************************<->***********************************/
979 void
980 CatchAlarm ( int sig)
981 {
982     /* timer expired, exit */
983     exit(0);
984 }
985
986 \f
987 /*************************************<->*************************************
988  *
989  *  Cursor GetHourGlass ()
990  *
991  *
992  *  Description:
993  *  -----------
994  *  Builds and returns the appropriate Hourglass cursor
995  *
996  *
997  *  Inputs:
998  *  ------
999  *  dpy = display
1000  * 
1001  *  Outputs:
1002  *  -------
1003  *  Return = cursor.
1004  *
1005  *  Comments:
1006  *  --------
1007  *  None. (None doesn't count as a comment)
1008  * 
1009  *************************************<->***********************************/
1010
1011 #define time32_width 32
1012 #define time32_height 32
1013 #define time32_x_hot 15
1014 #define time32_y_hot 15
1015 static unsigned char time32_bits[] = {
1016    0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0x7f, 0xfe, 0xff, 0xff, 0x7f,
1017    0x8c, 0x00, 0x00, 0x31, 0x4c, 0x00, 0x00, 0x32, 0x4c, 0x00, 0x00, 0x32,
1018    0x4c, 0x00, 0x00, 0x32, 0x4c, 0x00, 0x00, 0x32, 0x4c, 0x00, 0x00, 0x32,
1019    0x8c, 0x00, 0x00, 0x31, 0x0c, 0x7f, 0xfe, 0x30, 0x0c, 0xfe, 0x7f, 0x30,
1020    0x0c, 0xfc, 0x3f, 0x30, 0x0c, 0xf8, 0x1f, 0x30, 0x0c, 0xe0, 0x07, 0x30,
1021    0x0c, 0x80, 0x01, 0x30, 0x0c, 0x80, 0x01, 0x30, 0x0c, 0x60, 0x06, 0x30,
1022    0x0c, 0x18, 0x18, 0x30, 0x0c, 0x04, 0x20, 0x30, 0x0c, 0x02, 0x40, 0x30,
1023    0x0c, 0x01, 0x80, 0x30, 0x8c, 0x00, 0x00, 0x31, 0x4c, 0x80, 0x01, 0x32,
1024    0x4c, 0xc0, 0x03, 0x32, 0x4c, 0xf0, 0x1f, 0x32, 0x4c, 0xff, 0xff, 0x32,
1025    0xcc, 0xff, 0xff, 0x33, 0x8c, 0xff, 0xff, 0x31, 0xfe, 0xff, 0xff, 0x7f,
1026    0xfe, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00};
1027
1028 #define time32m_width 32
1029 #define time32m_height 32
1030 static unsigned char time32m_bits[] = {
1031    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
1032    0xcf, 0x00, 0x00, 0xf3, 0x6e, 0x00, 0x00, 0x76, 0x6e, 0x00, 0x00, 0x76,
1033    0x6e, 0x00, 0x00, 0x76, 0x6e, 0x00, 0x00, 0x76, 0x6e, 0x00, 0x00, 0x76,
1034    0xce, 0x00, 0x00, 0x73, 0x8e, 0x7f, 0xfe, 0x71, 0x0e, 0xff, 0xff, 0x70,
1035    0x0e, 0xfe, 0x7f, 0x70, 0x0e, 0xfc, 0x3f, 0x70, 0x0e, 0xf8, 0x1f, 0x70,
1036    0x0e, 0xe0, 0x07, 0x70, 0x0e, 0xe0, 0x07, 0x70, 0x0e, 0x78, 0x1e, 0x70,
1037    0x0e, 0x1c, 0x38, 0x70, 0x0e, 0x06, 0x60, 0x70, 0x0e, 0x03, 0xc0, 0x70,
1038    0x8e, 0x01, 0x80, 0x71, 0xce, 0x00, 0x00, 0x73, 0x6e, 0x80, 0x01, 0x76,
1039    0x6e, 0xc0, 0x03, 0x76, 0x6e, 0xf0, 0x1f, 0x76, 0x6e, 0xff, 0xff, 0x76,
1040    0xee, 0xff, 0xff, 0x77, 0xcf, 0xff, 0xff, 0xf3, 0xff, 0xff, 0xff, 0xff,
1041    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
1042
1043
1044 #define time16_x_hot 7
1045 #define time16_y_hot 7
1046 #define time16_width 16
1047 #define time16_height 16
1048 static unsigned char time16_bits[] = {
1049    0x00, 0x00, 0xfe, 0x7f, 0x14, 0x28, 0x14, 0x28, 0x14, 0x28, 0x24, 0x24,
1050    0x44, 0x22, 0x84, 0x21, 0x84, 0x21, 0x44, 0x22, 0x24, 0x24, 0x14, 0x28,
1051    0x94, 0x29, 0xd4, 0x2b, 0xfe, 0x7f, 0x00, 0x00};
1052
1053 #define time16m_width 16
1054 #define time16m_height 16
1055 static unsigned char time16m_bits[] = {
1056    0xff, 0xff, 0xff, 0xff, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x7f,
1057    0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x7f,
1058    0xfe, 0x7f, 0xfe, 0x7f, 0xff, 0xff, 0xff, 0xff};
1059
1060
1061 Cursor GetHourGlass (Display *dpy)
1062 {
1063     unsigned char *bits;
1064     unsigned char *maskBits;
1065     unsigned int width;
1066     unsigned int height;
1067     unsigned int xHotspot;
1068     unsigned int yHotspot;
1069     Pixmap       pixmap;
1070     Pixmap       maskPixmap;
1071     XColor       xcolors[2];
1072     unsigned int cWidth;
1073     unsigned int cHeight;
1074     int          useLargeCursors = 0;
1075     Cursor       waitCursor;
1076
1077     if (XQueryBestCursor (dpy, DefaultRootWindow(dpy), 
1078         32, 32, &cWidth, &cHeight))
1079     {
1080         if ((cWidth >= 32) && (cHeight >= 32))
1081         {
1082             useLargeCursors = 1;
1083         }
1084     }
1085
1086     if (useLargeCursors)
1087     {
1088         width = time32_width;
1089         height = time32_height;
1090         bits = time32_bits;
1091         maskBits = time32m_bits;
1092         xHotspot = time32_x_hot;
1093         yHotspot = time32_y_hot;
1094     }
1095     else
1096     {
1097         width = time16_width;
1098         height = time16_height;
1099         bits = time16_bits;
1100         maskBits = time16m_bits;
1101         xHotspot = time16_x_hot;
1102         yHotspot = time16_y_hot;
1103     }
1104
1105     pixmap = XCreateBitmapFromData (dpy, 
1106                      DefaultRootWindow(dpy), (char *)bits, 
1107                      width, height);
1108
1109     maskPixmap = XCreateBitmapFromData (dpy, 
1110                      DefaultRootWindow(dpy), (char *)maskBits, 
1111                      width, height);
1112
1113     xcolors[0].pixel = BlackPixelOfScreen(DefaultScreenOfDisplay(dpy));
1114     xcolors[1].pixel = WhitePixelOfScreen(DefaultScreenOfDisplay(dpy));
1115
1116     XQueryColors (dpy, 
1117                   DefaultColormapOfScreen(DefaultScreenOfDisplay
1118                                           (dpy)), xcolors, 2);
1119
1120     waitCursor = XCreatePixmapCursor (dpy, pixmap, maskPixmap,
1121                                       &(xcolors[0]), &(xcolors[1]),
1122                                       xHotspot, yHotspot);
1123     XFreePixmap (dpy, pixmap);
1124     XFreePixmap (dpy, maskPixmap);
1125
1126     return (waitCursor);
1127 }
1128
1129 #ifndef NO_MESSAGE_CATALOG
1130 /*****************************************************************************
1131  *
1132  * Function: GetMessage
1133  *
1134  * Parameters:
1135  *
1136  *   int        set -           The message catalog set number.
1137  *
1138  *   int        n -             The message number.
1139  *
1140  *   char       *s -            The default message if the message is not
1141  *                              retrieved from a message catalog.
1142  *
1143  * Returns: the string for set 'set' and number 'n'.
1144  *
1145  *****************************************************************************/
1146
1147 char * 
1148 GetMessage(
1149         int set,
1150         int n,
1151         char *s )
1152 {
1153         char *msg;
1154         char *lang;
1155         nl_catd catopen();
1156         char *catgets();
1157         static int first = 1;
1158         static nl_catd nlmsg_fd;
1159         if ( first ) 
1160         {
1161                 first = 0;
1162
1163                 lang = (char *) getenv ("LANG");
1164
1165                 if (!lang || !(strcmp (lang, "C"))) 
1166                         /*
1167                          * If LANG is not set or if LANG=C, then there
1168                          * is no need to open the message catalog - just
1169                          * return the built-in string "s".
1170                          */
1171                         nlmsg_fd = (nl_catd)-1;
1172                 else
1173                         nlmsg_fd = catopen("dthello", NL_CAT_LOCALE);
1174         }
1175         msg=catgets(nlmsg_fd,set,n,s);
1176         return (msg);
1177 }
1178 #endif
1179
1180 \f
1181 /*************************************<->*************************************
1182  *
1183  *  void VhGetResources
1184  *
1185  *
1186  *  Description:
1187  *  -----------
1188  *  Gets the resources for the client
1189  *
1190  *
1191  *  Inputs:
1192  *  ------
1193  * 
1194  *  Outputs:
1195  *  -------
1196  *
1197  *  Comments:
1198  *  --------
1199  * 
1200  *************************************<->***********************************/
1201
1202 void 
1203 VhGetResources(Display *dpy, char *name, char *class, 
1204     VhResourceEntry *res, int num)
1205 {
1206 #define INIT_SIZE   256
1207 #define SRCH_SIZE   20
1208     int i;
1209     XrmValue xrmv;
1210     XrmQuark  Qtype, Qstring, Qname, Qclass;
1211     XrmQuark Qnres[4], Qcres[4];
1212     XrmHashTable searchList[SRCH_SIZE];
1213
1214     /*
1215      * We only deal with string-type resources
1216      */
1217
1218     Qstring = XrmStringToQuark (XtRString);
1219
1220     /*
1221      * Get resource search list for "dthello"
1222      */
1223     XrmStringToQuarkList (name, Qnres);
1224     XrmStringToQuarkList (class, Qcres);
1225
1226     if (XrmQGetSearchList(XtDatabase(dpy), Qnres, Qcres, searchList,
1227                         SRCH_SIZE))
1228     {
1229         /*
1230          * Look for all resources at this level
1231          */
1232
1233         for (i = 0; i < num; i++)
1234         {
1235             Qname = XrmStringToQuark (res[i].resname);
1236             Qclass = XrmStringToQuark (res[i].resclass);
1237
1238             if ((XrmQGetSearchResource (searchList, Qname, Qclass, 
1239                                   &Qtype, &xrmv)) &&
1240                 (Qtype == Qstring))
1241             {
1242                 *(res[i].ppvalue) = (char *) xrmv.addr;
1243                 *res[i].size = (int) xrmv.size;
1244             }
1245         }
1246     }
1247 }
1248
1249 void
1250 PaintText( void )
1251 {
1252             int i, x, y;
1253             XFontSetExtents *extents;
1254
1255             /* 
1256              * Paint the string onto the screen
1257              */
1258
1259
1260             y = (displayHeight - totalHeight) / 2;
1261             if (y < 0)
1262             {
1263                y = 0;
1264             }
1265
1266             /* adjust origin by font metric */
1267             extents = XExtentsOfFontSet(fontset);
1268             y += -(extents->max_logical_extent.y);
1269
1270             x = box_line_width + x_offset;
1271
1272             for (i = 0; i < numLines; i++)
1273             {
1274                 /* draw the string */
1275                 XmbDrawString (dpy, welcome, fontset, gc, x, y, 
1276                         (char *)(ppchText[i]), strlen((char *)ppchText[i]));
1277
1278                 /* move to next "line" */
1279                 y += textHeight;
1280             }
1281 }
1282 void
1283 DrawBox( void )
1284 {
1285         int LTX, LTY, RTX, RTY, LBX, LBY, RBX, RBY;
1286         int L_middle;  /* pixels to the midpoint of the line width */
1287
1288         Boolean useDecoration = True;
1289
1290         /* compute the height of the font */
1291         totalHeight = textHeight * numLines;
1292
1293         /* 
1294          * Set limits
1295          */
1296         if ((( 2 * box_line_width ) + x_offset + maxWidth) > displayWidth)
1297         {
1298                 useDecoration = False;
1299                 x_offset = 0;
1300         }
1301
1302         if (!useDecoration)
1303                 return;
1304
1305         L_middle = box_line_width / 2;
1306         /********************************************************
1307         +----------------------------------------------+
1308         | (LTX, LTY)                        (RTX, RTY) |
1309         |                                              |
1310         |   (Draw counterclockwise, beginning from     |
1311         |    top left.)                                |
1312         |                                              |
1313         |                                              |
1314         |                                              |
1315         |                                              |
1316         |                                              |
1317         |                                              |
1318         | (LBX, LBY)                        (RBX, RBY) |
1319         +----------------------------------------------+
1320         ********************************************************/
1321         LTX = 0;
1322         LTY = 0;
1323
1324         RTX = displayWidth;
1325         RTY = 0;
1326
1327         LBX = 0;
1328         LBY = displayHeight;
1329
1330         RBX = displayWidth ;
1331         RBY = displayHeight;
1332
1333         XSetLineAttributes(dpy, gc, box_line_width, LineSolid, CapButt, JoinMiter);
1334         XDrawLine(dpy, welcome, gc, 
1335                                   LTX, LTY + L_middle,
1336                                   RTX, RTY + L_middle);
1337
1338         XDrawLine(dpy, welcome, gc, 
1339                                 RTX - L_middle, RTY, 
1340                                 RBX - L_middle, RBY);
1341
1342         XDrawLine(dpy, welcome, gc, 
1343                                 RBX, RBY - L_middle, 
1344                                 LBX, LBY - L_middle);
1345
1346         XDrawLine(dpy, welcome, gc, 
1347                                 LBX + L_middle, LBY, 
1348                                 LTX + L_middle, LTY);
1349
1350 }
1351
1352 int
1353 Xestrcmp(const char * const s1, const char * const s2)
1354 {
1355     if (s1 == s2) return 0;
1356     {
1357         const char * p1 = (s1) ? s1 : "";
1358         const char * p2 = (s2) ? s2 : "";
1359
1360         return strcmp((char *)p1, (char *)p2);
1361     }
1362 }
1363
1364 /**************         eof          ******************/