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