Initial import of the CDE 2.1.30 sources from the Open Group.
[oweals/cde.git] / cde / programs / dtappbuilder / src / libABobjXm / objxm_util.c
1
2 /*
3  *    $XConsortium: objxm_util.c /main/4 1995/11/06 18:47:59 rswiston $
4  *
5  * @(#)objxm_util.c     1.23 15 Feb 1994    cde_app_builder/src/libABobjXm
6  *
7  *     RESTRICTED CONFIDENTIAL INFORMATION:
8  *    
9  *    The information in this document is subject to special
10  *    restrictions in a confidential disclosure agreement between
11  *    HP, IBM, Sun, USL, SCO and Univel.  Do not distribute this
12  *    document outside HP, IBM, Sun, USL, SCO, or Univel without
13  *    Sun's specific written approval.  This document and all copies
14  *    and derivative works thereof must be returned or destroyed at
15  *    Sun's request.
16  *
17  *    Copyright 1993 Sun Microsystems, Inc.  All rights reserved.
18  *
19  */
20
21
22 /*
23  ***********************************************************************
24  * objxm_util.c - general Motif utility routines
25  *
26  *
27  ***********************************************************************
28  */
29
30 #include <stdio.h>
31 #include <sys/stat.h>
32 #include <sys/param.h>
33 #include <X11/Intrinsic.h>
34 #include <X11/StringDefs.h>
35 #include <Xm/MenuShell.h>
36 #include <Dt/xpm.h>
37 #include <ab_private/obj.h>
38 #include <ab_private/trav.h>
39 #include "objxmP.h"
40
41 #define BUF_SIZE        512
42 #define LG_BUF_SIZE     1024
43
44 /*
45  * Public symbols
46  */
47 ObjxmFilenameToPixmapFunc       ObjxmP_filename_to_pixmap_cb = NULL;
48
49 /*
50  * Post instantiate func, which can be registered via
51  */
52 ObjxmPostInstantiateFunc        ObjxmP_post_instantiate_cb = NULL;
53
54
55 /*************************************************************************
56 **                                                                      **
57 **       Private Function Declarations                                  **
58 **                                                                      **
59 *************************************************************************/ 
60
61 static int      indent(
62                     FILE *file, int spaces
63                 );
64
65 static int      convert_filebase_to_pixmap(
66                     Widget      widget,
67                     STRING      filebase,
68                     Pixmap      *pixmap_p
69                 );
70 static int      convert_file_to_pixmap(
71                     Widget      widget,
72                     STRING      filename,
73                     Pixmap      *pixmap_p
74                 );
75 static int      load_pixmap(
76                     Widget      widget,
77                     STRING      filebase,
78                     STRING      ext,
79                     Pixmap      *pixmap_p
80                 );
81
82
83 /*************************************************************************
84 **                                                                      **
85 **       Function Definitions                                           **
86 **                                                                      **
87 *************************************************************************/ 
88
89 /*
90  * Hook to add routine to convert filenames to callbacks.
91  * NULL callback reinstates default conversion method.
92  */
93 extern int      
94 objxm_set_cvt_filename_to_pixmap_callback(
95     ObjxmFilenameToPixmapFunc   filename_to_pixmap_cb
96 )
97 {
98     ObjxmP_filename_to_pixmap_cb = filename_to_pixmap_cb;
99     return 0;
100 }
101
102 /*
103  * Hook to add post instantiate routine
104  * NULL callback reinstates default conversion method.
105  */
106 extern int      
107 objxm_set_post_instantiate_callback(
108     ObjxmPostInstantiateFunc    post_instantiate_cb
109 )
110 {
111     ObjxmP_post_instantiate_cb = post_instantiate_cb;
112     return 0;
113 }
114
115 /*
116  * Determine if a color name exists in the rgb database
117  */
118 BOOL
119 objxm_color_exists(
120     String      colorname
121 )
122 {
123     static Colormap     colormap = NULL;
124     static Display      *display = NULL;
125     XColor              color;
126     XColor              exact_color;
127  
128     if (display == NULL) /* dtbuilder doesn't handle multiple displays */
129     {
130         display = XtDisplay(ObjxmP_toplevel);
131         colormap = XDefaultColormap(display, XDefaultScreen(display));
132     }
133     return(XLookupColor(display, colormap, colorname, &exact_color, &color));
134 }
135
136
137 /*
138  * Use the Xt Resource converter to convert a colorname to a pixel.
139  * This has the advantage of caching the value and automatically
140  * taking care to Free the pixel when the associated widget is
141  * destroyed.
142  */
143 int
144 objxm_name_to_pixel(
145     Widget      widget,
146     String      colorname,
147     Pixel       *pixel_p
148 )
149 {
150     XrmValue src, dst;
151
152     src.size = strlen(colorname) + 1;
153     src.addr = (XPointer)colorname;
154     dst.size = sizeof(Pixel);
155     dst.addr = (XPointer)pixel_p;
156
157     if (XtConvertAndStore(widget, XtRString, &src, XtRPixel, &dst))
158         return OK;
159     else
160         return ERR;
161 }
162
163 int
164 objxm_filebase_to_pixmap(
165     Widget      widget,
166     STRING      filebase,
167     Pixmap      *pixmap_p
168 )
169 {
170     int         status = 0;                 /* return code */
171
172     if (util_strempty(filebase))
173         return ERR_BAD_PARAM2;
174
175     *pixmap_p = NULL;
176
177     /* Use Pixmap conversion callback if it exists */
178     if (ObjxmP_filename_to_pixmap_cb != NULL)
179     {
180         return(ObjxmP_filename_to_pixmap_cb(widget, filebase, pixmap_p));
181     }
182     else /* Use internal conversion routine */
183         return (convert_filebase_to_pixmap(widget, filebase, pixmap_p));
184
185 }
186
187
188 STRING
189 objxm_pixmap_conversion_error_msg(
190     ABObj       obj,
191     STRING      filebase,
192     int         status
193 )
194 {
195     char        static buf[LG_BUF_SIZE];
196     char        buf2[BUF_SIZE];
197     char        file_buf[BUF_SIZE];
198
199     if (obj != NULL)
200         sprintf(buf, catgets(OBJXM_MESSAGE_CATD, 203, 14,
201                 "Warning: %s :\n"), util_strsafe(obj_get_name(obj)));
202     else
203         strcpy(buf, "");
204
205     sprintf(buf2, catgets(OBJXM_MESSAGE_CATD, 203, 15,
206                 "Graphic File base '%s'\ncould not be converted to a Pixmap because\n"), filebase);
207     strcat(buf, buf2);
208
209     if (status == ERR_BAD_PARAM2)
210         strcat(buf, catgets(OBJXM_MESSAGE_CATD, 203, 16,
211                 "File base is an empty string."));
212     else
213     {
214         strcat(buf, catgets(OBJXM_MESSAGE_CATD, 203, 17,
215                 "None of the following files could be converted to a Pixmap:\n"));
216
217         if ((int)(strlen(buf) + (4 * (strlen(filebase) + 4))) > LG_BUF_SIZE)
218             strcat(buf, catgets(OBJXM_MESSAGE_CATD, 203, 18,
219                 "filenames too long to display\n"));
220         else
221         {
222             sprintf(file_buf,"%s.pm\n%s.xpm\n%s.bm\n%s.xbm\n",
223                 filebase, filebase, filebase, filebase);
224
225             strcat(buf, file_buf);
226         }
227     }
228
229     util_set_help_data(catgets(OBJXM_MESSAGE_CATD, 203, 20,
230         "The graphic file name specified could not be converted\ninto a pixmap. App Builder searches for a file of the\nform Filename.pm, Filename.xpm, Filename.bm, and\nFilename.xbm.\n\nEither none of those files exists in the directory specified\n(via the Graphic Filename field or if no path was specified,\nthen the current working directory), or a file exists but may\nbe corrupt."), NULL, NULL);
231
232     return(buf);
233 }
234
235 /*
236  * Given the 'base' graphic filename, attempt to load in an appropriate
237  * Pixmap with the following rules:
238  *      If display is color (depth > 1), try loading the following filenames
239  *      in sequence until 1 succeeds:
240  *              base.pm, base.xpm (XPM), base.bm, base.xbm (Bitmap)
241  *              
242  *      If display is monochrome, try loading in the following sequence
243  *      until 1 succeeds:
244  *              base.bm, base.xbm (Bitmap), base.pm, base.xpm (XPM)
245  *
246  */
247 static int
248 convert_filebase_to_pixmap(
249     Widget      widget,
250     STRING      filebase,
251     Pixmap      *pixmap_p
252 )
253 {
254     int status;
255
256     if (ObjxmP_visual_depth > 1) /* Color - Try XPM First */
257     {
258         if ((status = load_pixmap(widget, filebase, ".pm", pixmap_p)) != OK)
259             if ((status = load_pixmap(widget, filebase, ".xpm", pixmap_p)) != OK)
260                 if ((status = load_pixmap(widget, filebase, ".bm", pixmap_p)) != OK)
261                     status = load_pixmap(widget, filebase, ".xbm", pixmap_p);
262     }
263     else /* Monochrome - Try Bitmap First */
264     {
265         if ((status = load_pixmap(widget, filebase, ".bm", pixmap_p)) != OK) 
266             if ((status = load_pixmap(widget, filebase, ".xbm", pixmap_p)) != OK) 
267                 if ((status = load_pixmap(widget, filebase, ".pm", pixmap_p)) != OK) 
268                     status = load_pixmap(widget, filebase, ".xpm", pixmap_p); 
269     }
270     return status;
271 }
272
273
274 /*
275  * Attempt to dynamically read a bitmap file and load it into a Pixmap
276  */
277 static int
278 convert_file_to_pixmap(
279     Widget      widget,
280     STRING      filename,
281     Pixmap      *pixmap_p
282 )
283 {
284     int         rc = 0;                 /* return code */
285     Screen      *screen = NULL; 
286     Pixel       fgPixel = 0;
287     Pixel       bgPixel = 0; 
288
289     *pixmap_p = NULL;
290
291     /*
292      * Get default values
293      */
294     screen = XtScreen(widget);
295     fgPixel = WhitePixelOfScreen(screen);
296     bgPixel = BlackPixelOfScreen(screen);
297
298     /*
299      * Get proper colors for widget
300      */
301     XtVaGetValues(widget,
302         XmNforeground, &fgPixel,
303         XmNbackground, &bgPixel,
304         NULL);
305
306     /*
307      * In CDE, XmGetPixmap handles .xpm files, as well.
308      */
309     *pixmap_p = XmGetPixmap(screen, filename, fgPixel, bgPixel);
310     if ((*pixmap_p == NULL) || (*pixmap_p == XmUNSPECIFIED_PIXMAP))
311     {
312         return -1;
313     }
314     return 0;
315 }
316
317     
318 static int
319 load_pixmap(
320     Widget      widget,
321     STRING      filebase,
322     STRING      ext,
323     Pixmap      *pixmap_p
324 )
325 {
326     char            filename[BUF_SIZE];
327     int             status;
328
329     if ((int)(strlen(filebase) + strlen(ext) + 1) > BUF_SIZE)
330         return ERR;
331
332     strcpy(filename, filebase);
333     strcat(filename, ext);
334     return(status = convert_file_to_pixmap(widget, filename, pixmap_p));
335 }
336
337
338
339 XFontStruct *
340 objxm_fontlist_to_font(
341     XmFontList  fontlist
342 )
343 {
344     XmFontContext       context;
345     XFontStruct         *font;
346     XmStringCharSet     charset;
347
348     if (!fontlist)
349         return NULL;
350
351     XmFontListInitFontContext(&context, fontlist);
352
353     if (XmFontListGetNextFont(context, &charset, &font))
354     {
355         XmFontListFreeFontContext(context);
356         XtFree(charset);
357         return(font);
358     }
359     else if (util_get_verbosity() > 0)
360     {
361         util_puts_err("objxm_fontlist_to_font: could not convert fontlist\n");
362     }
363
364     XmFontListFreeFontContext(context);
365     return NULL;
366
367 }
368
369 XmString
370 objxm_str_to_xmstr(
371     Widget   widget,
372     String   string
373 )
374 {
375     XrmValue src, dst;
376     XmString xmstr;
377
378     if (util_strempty(string))
379         return((XmString)NULL);
380
381     src.size = strlen(string) + 1;
382     src.addr = (XPointer)string;
383     dst.size = sizeof(XmString);
384     dst.addr = (XPointer)&xmstr;
385
386     if (XtConvertAndStore(widget, XtRString, &src, XmRXmString, &dst))
387         return(xmstr);
388     else
389         return((XmString)NULL);
390
391 }
392
393
394 STRING
395 objxm_xmstr_to_str(
396     XmString    xmstr
397 )
398 {
399     XmStringContext   context;
400     XmStringCharSet   char_set_tag;
401     XmStringDirection dir;
402     Boolean           sep;
403     Boolean           status = FALSE;
404     char              buf[MAXPATHLEN], *seg, *p;
405
406     p = buf;
407     if (XmStringInitContext(&context, xmstr))
408     {
409         while(XmStringGetNextSegment(context, &seg,
410                         &char_set_tag, &dir, &sep))
411         {
412             p += (strlen(strcpy(p, seg)));
413             if (sep == TRUE)
414             {
415                 *p++ = '\n';
416                 *p   = '\0';
417             }
418             XtFree(seg);
419         }
420         XmStringFreeContext(context);
421         return((STRING)XtNewString(buf));
422     }
423     if (util_get_verbosity() > 0)
424     {
425         util_puts_err("objxm_xmstr_to_str: could not convert xmstring\n");
426     }
427     return NULL;
428
429 }
430
431 /*
432  * Given an Accelerator String (translation Table syntax), return
433  * the string that should be displayed inside the item containing the
434  * accelerator
435  */
436 String
437 objxm_accel_to_acceltext(
438     String      accelstr
439 )
440 {
441     char        buf[128];
442     static char acceltext[128];
443     char        *p;     
444
445     if (util_strempty(accelstr))
446         return NULL;
447
448     strcpy(buf, accelstr);
449
450     p = strtok(buf, "<");
451     if (p != NULL)
452     {
453         strcpy(acceltext, p);
454         while(p != NULL)
455         {
456             /* Replace any "<..>" with "+" */
457             p = strtok(NULL, ">");
458             if (p != NULL)
459             {
460                 strcat(acceltext,"+");
461                 p = strtok(NULL, "<");
462                 if (p != NULL)
463                     strcat(acceltext, p);
464             }
465         }
466     }
467     return acceltext;
468
469 }
470
471 unsigned char
472 objxm_linestyle_to_enum(
473     AB_LINE_TYPE        linestyle
474 )
475 {
476     unsigned char value;
477
478     switch(linestyle)
479     {
480         case AB_LINE_SINGLE_LINE:
481             value = XmSINGLE_LINE;
482             break;
483         case AB_LINE_DOUBLE_LINE:
484             value = XmDOUBLE_LINE;
485             break;
486         case AB_LINE_SINGLE_DASHED_LINE:
487             value = XmSINGLE_DASHED_LINE;
488             break;
489         case AB_LINE_DOUBLE_DASHED_LINE:
490             value = XmDOUBLE_DASHED_LINE;
491             break;
492         case AB_LINE_NONE:
493             value = XmNO_LINE;
494             break;
495         case AB_LINE_ETCHED_IN:
496             value = XmSHADOW_ETCHED_IN;
497             break;
498         case AB_LINE_ETCHED_OUT:
499             value = XmSHADOW_ETCHED_OUT;
500             break;
501         case AB_LINE_ETCHED_IN_DASH:
502             value = XmSHADOW_ETCHED_IN_DASH;
503             break;
504         case AB_LINE_ETCHED_OUT_DASH:
505             value = XmSHADOW_ETCHED_OUT_DASH;
506             break;
507         default:
508             return (unsigned char)-1;
509
510     }
511     return value;
512 }
513
514 BOOL
515 objxm_is_menu_widget(
516     Widget      widget
517 )
518 {
519     /* If MenuShell OR MenuPane, return TRUE..*/
520     if (XtIsSubclass(widget, xmMenuShellWidgetClass) ||
521             XtIsSubclass(XtParent(widget), xmMenuShellWidgetClass))
522             return TRUE;
523
524     return FALSE;
525
526 }
527
528 /*
529  ***********************************************************************
530  * 
531  *  Debugging routines
532  *
533  ***********************************************************************
534  */
535
536 int
537 objxm_print(ABObj obj)
538 {
539     return objxm_print_indented(obj, 0, util_get_verbosity());
540 }
541
542 int 
543 objxm_print_indented(ABObj obj, int spaces, int verbosity)
544 {
545     obj_print_indented(obj, spaces, verbosity);
546     if (verbosity >= 4)
547     {
548         ArgList args= objxm_obj_get_ui_args(obj);
549         int     num_args= objxm_get_num_args(args);
550         objxm_dump_arglist_indented(obj, args, num_args, spaces);
551         util_dprintf(0, "\n");
552     }
553     return 0;
554 }
555
556
557 int
558 objxm_tree_print(ABObj obj)
559 {
560     objxm_tree_print_indented(obj, 0, util_get_verbosity());
561     util_dprintf(0,"\n");
562     return 0;
563 }
564
565
566 int
567 objxm_tree_print_indented(ABObj obj, int spaces, int verbosity)
568 {
569     AB_TRAVERSAL        trav;
570     ABObj               child = NULL;
571
572     objxm_print_indented(obj, spaces, verbosity);
573
574     for (trav_open(&trav, obj, AB_TRAV_CHILDREN);
575         (child= trav_next(&trav)) != NULL; )
576     {
577         objxm_tree_print_indented(child, spaces+4, verbosity);
578     }
579     trav_close(&trav);
580
581     return 0;
582 }
583
584
585 static int
586 indent (FILE *file, int spaces)
587 {
588     int i= 0;
589     for (i= 0; i < spaces; ++i)
590     {
591         fputc(' ', file);
592     }
593     return 0;
594 }
595