Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / programs / dtappbuilder / src / abmf / utils.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: utils.c /main/3 1995/11/06 18:16:13 rswiston $
26  * 
27  * @(#)utils.c  3.76 16 Feb 1994        cde_app_builder/src/abmf
28  * 
29  * RESTRICTED CONFIDENTIAL INFORMATION:
30  * 
31  * The information in this document is subject to special restrictions in a
32  * confidential disclosure agreement between HP, IBM, Sun, USL, SCO and
33  * Univel.  Do not distribute this document outside HP, IBM, Sun, USL, SCO,
34  * or Univel without Sun's specific written approval.  This document and all
35  * copies and derivative works thereof must be returned or destroyed at Sun's
36  * request.
37  * 
38  * Copyright 1993 Sun Microsystems, Inc.  All rights reserved.
39  * 
40  */
41
42
43 /*
44  * Main utility functions.
45  */
46
47 #include <sys/param.h>
48 #include <stdio.h>
49 #include <stdlib.h>
50 #include <ctype.h>
51 #include <string.h>
52 #include <ab_private/XmAll.h>
53 #include <ab/util_types.h>
54 #include <ab_private/istr.h>
55 #include <ab_private/abio.h>
56 #include <ab_private/trav.h>
57 #include <ab_private/objxm.h>
58 #include "abmfP.h"
59 #include "motifdefsP.h"
60 #include "write_cP.h"
61 #include "write_codeP.h"
62 #include "obj_namesP.h"
63 #include "utilsP.h"
64
65
66 STRING  nlstr = "\n";
67 STRING  nlstr2 = "\n\n";
68
69 static int      find_base_file_name(STRING path, int *startPtr, int *lenPtr);
70
71 /*
72  * Miscellaneous utility functions.
73  */
74
75 /*
76  * Return the printed representation of a boolean.
77  */
78 STRING
79 abmfP_boolean_string(int i)
80 {
81     return i ? "True" : "False";
82 }
83
84
85 /*
86  * Check a string to see if contains a legal identifier.
87  */
88 int
89 abmfP_identifier_ok(STRING s)
90 {
91     return ab_c_ident_is_ok(s);
92 }
93
94
95 /*
96  * Capitalize the first letter of the given string.
97  */
98 STRING
99 abmfP_capitalize_first_char(STRING str)
100 {
101     static char         name[MAXPATHLEN] = "";
102
103     if (str == NULL)
104         return str;
105
106     if (isupper(str[0]))
107         return str;
108
109     if (str != name)    /* if we get called w/our own buffer, don't copy */
110     {
111         strcpy(name, str);
112     }
113     name[0] = toupper(str[0]);
114
115     return name;
116 }
117
118
119 /*
120  * Makes the 1st char lower case
121  */
122 STRING
123 abmfP_uncapitalize_first_char(STRING str)
124 {
125     static char         name[MAXPATHLEN] = "";
126
127     if (str == NULL)
128         return str;
129
130     if (islower(str[0]))
131         return str;
132
133     if (str != name)    /* if we get called w/our own buffer, don't copy */
134     {
135         strcpy(name, str);
136     }
137     name[0] = tolower(str[0]);
138
139     return name;
140 }
141
142
143 ABObj
144 abmfP_obj_find_codegen_parent(ABObj obj)
145 {
146     ABObj       cgParent = obj->parent;
147     while ((cgParent != NULL) && obj_has_flag(cgParent, NoCodeGenFlag))
148     {
149         cgParent = cgParent->parent;
150     }
151     return cgParent;
152 }
153
154 /*
155  * Return TRUE if all items have the same Widget Class
156  */
157 BOOL
158 abmfP_items_are_homogeneous(
159     ABObj       obj
160 )
161 {
162     AB_TRAVERSAL        trav;
163     ABObj               item;
164     BOOL                same = TRUE;
165     STRING              ref_classname;
166
167     trav_open(&trav, obj, AB_TRAV_ITEMS_FOR_OBJ);
168     item = trav_next(&trav);
169     if (item != NULL)
170     {
171         ref_classname = obj_get_class_name(item);
172         for (;(item = trav_next(&trav)) != NULL; )
173             if (util_strcmp(ref_classname, obj_get_class_name(item)) != 0)
174             {
175                 same = FALSE;
176                 break;
177             }
178     }
179     trav_close(&trav);
180     return same;
181 }
182
183 BOOL
184 abmfP_items_have_mnemonics(
185     ABObj       obj
186 )
187 {
188     AB_TRAVERSAL        trav;
189     ABObj               item; 
190     BOOL                has_mnemonics = False;
191
192     for (trav_open(&trav, obj, AB_TRAV_ITEMS_FOR_OBJ);
193         (item = trav_next(&trav)) != NULL;)
194         if (obj_get_mnemonic(item) != NULL)
195         {
196             has_mnemonics = True;
197             break;
198         }
199     trav_close(&trav);
200     return has_mnemonics;
201 }
202
203 BOOL
204 abmfP_items_have_accelerators(
205     ABObj       obj
206 )
207 {
208     AB_TRAVERSAL        trav; 
209     ABObj               item;
210     BOOL                has_accel = False;
211  
212     for (trav_open(&trav, obj, AB_TRAV_ITEMS_FOR_OBJ); 
213         (item = trav_next(&trav)) != NULL;)
214         if (obj_get_accelerator(item) != NULL)
215         { 
216             has_accel = True; 
217             break; 
218         } 
219     trav_close(&trav); 
220     return has_accel;
221 }
222
223
224 /*
225  * Returns TRUE if the objects represent the same UI element.
226  * 
227  * This shouldn't really be necessary - there should be NO duplicate objects,
228  * just multiple references to the same object.
229  */
230 int
231 abmfP_obj_is_duplicate(ABObj obj, ABObj dupObj)
232 {
233     return (obj == dupObj);
234 }
235
236
237 BOOL
238 abmfP_parent_is_class(ABObj obj, STRING classname)
239 {
240     if ((abmfP_parent(obj) == NULL)
241         || (obj_get_class_name(obj) == NULL)
242         || (obj_get_class_name(abmfP_parent(obj)) == NULL))
243     {
244         return FALSE;
245     }
246     if (util_streq(obj_get_class_name(abmfP_parent(obj)), classname))
247     {
248         return TRUE;
249     }
250     if (abmfP_parent(obj))
251         return abmfP_parent_is_class(abmfP_parent(obj), classname);
252     return FALSE;
253 }
254
255
256 /*
257  * Return the actual control object.
258  * 
259  * Since most controls have been converted to multiple toolkit objects (e.g., to
260  * add captions) except oblong, menu buttons, get the object that actually
261  * implements the type.
262  * 
263  * The opposite of this is abmfP_get_container_object.
264  */
265 ABObj
266 abmfP_get_actual_control(ABObj parent)
267 {
268     ABObj               obj = objxm_comp_get_subobj(parent, AB_CFG_OBJECT_OBJ);
269     return obj;
270 }                               /* abmfP_get_actual_control */
271
272
273 /*
274  * Gets the object that is or contains all of the subobjects that make up a
275  * particular type of object.
276  * 
277  * For instance, if a gauge is represented by a container that has a label and a
278  * gauge, this function will return the container object if any of the
279  * subobjects is passed in (or if the container itself is passed in).  This
280  * function works on any type of object.
281  * 
282  * The opposite function is abmfP_get_actual_control
283  */
284 ABObj
285 abmfP_get_whole_object(ABObj obj)
286 {
287     return obj_get_root(obj);
288 }
289
290
291 /*
292  * Returns the object that the callback has been "associated with."
293  * Normally the module it is declare in, or the project for cross-module
294  * conn's.
295  *
296  * Returns NULL if the callback is not found.
297  */
298 ABObj
299 abmfP_find_callback_scope(ABObj obj, STRING callbackName)
300 {
301     ABObj       scopeObj = NULL;
302     ABObj       objModule = obj_get_module(obj);
303     ABObj       objProject= obj_get_project(obj);
304     StringList  callbackList = NULL;
305     AB_TRAVERSAL        trav;
306     ABObj       curModule= NULL;
307
308     if ((objModule != NULL) && (mfobj_get_module_data(objModule) != NULL))
309     {
310         callbackList = mfobj_get_module_data(objModule)->callbacks;
311         if (strlist_str_exists(callbackList, callbackName))
312         {
313             scopeObj = objModule;
314         }
315     }
316
317     if ((scopeObj == NULL) && (objProject != NULL))
318     {
319         for (trav_open(&trav, objProject, AB_TRAV_MODULES);
320             (scopeObj == NULL) && ((curModule = trav_next(&trav)) != NULL); )
321         {
322             if (mfobj_get_module_data(curModule) != NULL)
323             {
324                 callbackList = mfobj_get_module_data(curModule)->callbacks;
325                 if (strlist_str_exists(callbackList, callbackName))
326                 {
327                     scopeObj = curModule;
328                 }
329             }
330         }
331         trav_close(&trav);
332
333         if (scopeObj == NULL)
334         {
335            callbackList = mfobj_get_proj_data(objProject)->callbacks;
336            if (strlist_str_exists(callbackList, callbackName))
337            {
338                scopeObj = NULL;
339            }
340         }
341     }
342
343     return scopeObj;
344 }
345
346 int
347 find_longest_label(STRING * label)
348 {
349     int                 len1,
350                         len2,
351                         longest,
352                         i = 0;
353
354     len1 = len2 = 0;
355     for (; label[i]; i++)
356     {
357         len1 = strlen(label[i]);
358         if (len1 > len2)
359         {
360             len2 = len1;
361             longest = i;
362         }
363     }
364     return longest;
365 }
366
367 /*************************************************************************
368  **                                                                     **
369  **     MEMORY ALLOCATION                                               **
370  **                                                                     **
371  *************************************************************************/
372
373 /*
374  * Version of calloc() with error checking.
375  */
376 void               *
377 abmfP_calloc(size_t n, size_t size)
378 {
379     char               *p;
380
381     if (p = (STRING) calloc(n, size))
382         return p;
383     util_error(catgets(Dtb_project_catd, 1, 83, "calloc: out of memory"));
384     return NULL;
385 }
386
387 /*
388  * Version of malloc() with error checking.
389  */
390 void               *
391 abmfP_malloc(size_t size)
392 {
393     void               *p;
394
395     if (p = malloc(size))
396         return p;
397     util_error(catgets(Dtb_project_catd, 1, 84, "malloc: out of memory"));
398     return NULL;
399 }
400
401 /*
402  * Version of realloc() with error checking.
403  */
404 void               *
405 abmfP_realloc(void *buf, unsigned int size)
406 {
407     void               *p;
408
409     if (p = realloc(buf, size))
410         return p;
411     util_error(catgets(Dtb_project_catd, 1, 85, "realloc: out of memory"));
412     return NULL;
413 }
414
415
416 /*
417  * Return the window parent of an object.
418  */
419 ABObj
420 abmfP_get_window_parent(ABObj obj)
421 {
422     if (obj_is_top_level(obj))
423         return NULL;
424     else if (abmfP_parent(obj) && obj_is_top_level(abmfP_parent(obj)))
425         return abmfP_parent(obj);
426     else if (abmfP_parent(obj))
427         return abmfP_get_window_parent(abmfP_parent(obj));
428     return ((ABObj) NULL);
429 }
430
431
432 /*
433  * Return the window pane of an object.
434  */
435 ABObj
436 abmfP_get_window_pane(ABObj obj)
437 {
438     if (abmfP_parent(obj) == NULL)
439     {
440         return ((ABObj) NULL);
441     }
442     if (obj_is_top_level(obj))
443         return NULL;
444     else if (obj_is_pane(abmfP_parent(obj)) || obj_is_top_level(abmfP_parent(obj)))
445         return abmfP_parent(obj);
446
447     return abmfP_get_window_pane(abmfP_parent(obj));
448 }
449
450
451 /*
452  * Copy one file to another.
453  */
454 int
455 abmfP_filecopy(STRING file1, STRING file2)
456 {
457     FILE               *inp;
458     FILE               *outp;
459     int                 c;
460
461     if ((inp = util_fopen_locked(file1, "r")) == NULL ||
462         (outp = util_fopen_locked(file2, "w")) == NULL)
463         return ERROR;
464
465     while ((c = fgetc(inp)) != EOF)
466         fputc(c, outp);
467
468     fclose(inp);
469     fclose(outp);
470     return TRUE;
471 }
472
473 /*
474  * assigns names to object without them. This is a safty measure.
475  */
476 int
477 abmfP_assign_widget_names(ABObj root)
478 {
479     int                 iReturn = 0;
480     ABObj               win_obj;
481     static int          i = 0;
482     char                Buf[64];
483     AB_TRAVERSAL        trav;
484
485     /*
486      * Base windows
487      */
488     for (trav_open(&trav, root, AB_TRAV_WINDOWS), i = 1;
489          (win_obj = trav_next(&trav)) != NULL;)
490     {
491         if (obj_get_name(win_obj) == NULL)
492         {                       /* Only assign once */
493             sprintf(Buf, "%s%d", "widget", i);
494             obj_set_name(win_obj, Buf);
495         }
496         i++;
497     }
498     trav_close(&trav);
499     return iReturn;
500 }
501
502
503 abmfP_tree_set_written(ABObj root, BOOL written)
504 {
505     AB_TRAVERSAL        trav;
506     ABObj               obj = NULL;
507
508     for (trav_open(&trav, root, AB_TRAV_ALL);
509          (obj = trav_next(&trav)) != NULL;)
510     {
511         obj_set_was_written(obj, written);
512     }
513     trav_close(&trav);
514     return 0;
515 }
516
517
518 abmfP_obj_set_items_written(ABObj rootObj, BOOL written)
519 {
520     AB_TRAVERSAL        trav;
521     ABObj               obj = NULL;
522
523     for (trav_open(&trav, rootObj, AB_TRAV_ITEMS_FOR_OBJ);
524          (obj = trav_next(&trav)) != NULL;)
525     {
526         obj_set_was_written(obj, written);
527     }
528     trav_close(&trav);
529
530     return 0;
531 }
532
533
534 /*
535  * gets the #define string for the file
536  */
537 STRING
538 abmfP_get_define_from_file_name(STRING fileName)
539 {
540     static char define[MAX_NAME_SIZE];
541     int         fileNameLen= strlen(fileName);
542     int         iFileName= 0;
543     int         iDefine= 0;
544     char        fileNameChar= 0;
545
546     strcpy(define, "_");
547     iDefine= 1;
548     for (iFileName= 0; iFileName < fileNameLen; ++iFileName)
549     {
550         fileNameChar= fileName[iFileName];
551         if (isalnum(fileNameChar))
552         {
553             define[iDefine++]= toupper(fileNameChar);
554         }
555         else
556         {
557             if (define[iDefine-1] != '_')
558             {
559                 define[iDefine++]= '_';
560             }
561         }
562     }
563     if ((iDefine > 0) && (define[iDefine-1] != '_'))
564     {
565         define[iDefine++]= '_';
566     }
567     define[iDefine]= 0;
568     return define;
569 }
570
571
572 BOOL
573 abmfP_file_name_is_bitmap(STRING fileName)
574 {
575     return util_file_name_has_extension(fileName, "xbm");
576 }
577
578
579 BOOL
580 abmfP_file_name_is_xpm(STRING fileName)
581 {
582     return util_file_name_has_extension(fileName, "pm");
583 }
584
585
586 STRING
587 abmfP_cvt_file_name_to_bitmap_data_vars(
588                 STRING  path,
589                 STRING  *widthVarPtr,
590                 STRING  *heightVarPtr,
591                 STRING  *bitsVarPtr
592 )
593 {
594 #define widthVar (*widthVarPtr)
595 #define heightVar (*heightVarPtr)
596 #define bitsVar (*bitsVarPtr)
597     static char widthVarBuf[256];
598     static char heightVarBuf[256];
599     static char bitsVarBuf[256];
600     int         baseIndex = -1;
601     int         baseLen = -1;
602     char        *nameStart = NULL;
603
604     widthVar = heightVar = bitsVar = NULL;
605
606     find_base_file_name(path, &baseIndex, &baseLen);
607     nameStart = &(path[baseIndex]);
608
609     strncpy(widthVarBuf, nameStart, baseLen);
610     widthVarBuf[baseLen]= 0;
611     strcpy(heightVarBuf, widthVarBuf);
612     strcpy(bitsVarBuf, widthVarBuf);
613
614     strcat(widthVarBuf, "_width");
615     strcpy(widthVarBuf, ab_make_valid_c_ident(widthVarBuf));
616
617     strcat(heightVarBuf, "_height");
618     strcpy(heightVarBuf, ab_make_valid_c_ident(heightVarBuf));
619
620     strcat(bitsVarBuf, "_bits");
621     strcpy(bitsVarBuf, ab_make_valid_c_ident(bitsVarBuf));
622
623     widthVar = widthVarBuf;
624     heightVar = heightVarBuf;
625     bitsVar = bitsVarBuf;
626
627     return 0;
628 #undef widthVar
629 #undef heightVar
630 #undef bitsVar
631 }
632
633
634 STRING
635 abmfP_cvt_file_name_to_xpm_data_var(STRING path)
636 {
637     static char varName[256];
638     int         baseStart = -1;
639     int         baseLen = -1;
640
641     *varName = 0;
642     find_base_file_name(path, &baseStart, &baseLen);
643     if (baseLen > 0)
644     {
645         strncpy(varName, path+baseStart, baseLen);
646         varName[baseLen]= 0;
647         strcat(varName, "_pm");
648     }
649     return ab_make_valid_c_ident(varName);
650 }
651
652
653 int
654 abmfP_obj_set_subobjs_written(ABObj obj, BOOL written)
655 {
656     AB_TRAVERSAL        trav;
657     ABObj               subObj= NULL;
658
659     for (trav_open(&trav, obj, AB_TRAV_ALL);
660         (subObj= trav_next(&trav)) != NULL; )
661     {
662         if (   (subObj == obj)
663             || (obj_get_root(subObj) != obj))
664         {
665             continue;
666         }
667         obj_set_was_written(subObj, written);
668     }
669     trav_close(&trav);
670     return 0;
671 }
672
673
674 BOOL
675 abmfP_objs_in_same_struct(ABObj obj1, ABObj obj2)
676 {
677     ABObj       structObj1= abmfP_obj_get_struct_obj(obj1);
678     ABObj       structObj2= abmfP_obj_get_struct_obj(obj2);
679     return ((structObj1 != NULL) && (structObj1 == structObj2));
680 }
681
682
683 BOOL
684 abmfP_objs_in_same_substruct(ABObj obj1, ABObj obj2)
685 {
686    ABObj        structObj1 = abmfP_obj_get_substruct_obj(obj1);
687    ABObj        structObj2 = abmfP_obj_get_substruct_obj(obj2);
688    return ((structObj1 != NULL) && (structObj1 == structObj2));
689 }
690
691
692 /*
693  * We have two types of structures:
694  *      - one structure for each window
695  *      - one structure for all the menus in an interface
696  */
697 ABObj
698 abmfP_obj_get_struct_obj(ABObj obj)
699 {
700     ABObj       structObj = NULL;
701
702     if (mfobj_has_flags(obj, CGenFlagStructObjValid))
703     {
704         goto epilogue;
705     }
706
707     for (structObj = obj; 
708          structObj != NULL && !abmfP_obj_is_struct_obj(structObj); 
709          structObj = abmfP_parent(structObj)
710         ) ;
711
712     /*
713      * Save the data
714      */
715     mfobj_set_flags(obj, CGenFlagStructObjValid);
716     mfobj_data(obj)->struct_obj = structObj;
717
718 epilogue:
719     return mfobj_data(obj)->struct_obj;
720 }
721
722
723 /*
724  * Currently, only items go in substructs. List items don't however,
725  * because they don't cause widgets to be created.
726  */
727 ABObj
728 abmfP_obj_get_substruct_obj(ABObj obj)
729 {
730     ABObj       substructObj = NULL;
731
732     if (mfobj_has_flags(obj, CGenFlagSubstructObjValid))
733     {
734         goto epilogue;
735     }
736
737     if (obj_is_item(obj))
738     {
739         ABObj   parent = abmfP_parent(obj);
740         if (parent != NULL)
741         {
742             substructObj = obj_get_root(parent);
743         }
744         if (   (substructObj != NULL) 
745             && (!abmfP_obj_is_substruct_obj(substructObj)) )
746         {
747             substructObj = NULL;
748         }
749     }
750
751     /*
752      * Save the data
753      */
754     mfobj_set_flags(obj, CGenFlagSubstructObjValid);
755     mfobj_data(obj)->substruct_obj = substructObj;
756
757 epilogue:
758     return mfobj_data(obj)->substruct_obj;
759 }
760
761
762 int
763 abmfP_get_num_substruct_fields(ABObj obj)
764 {
765     int         numFields = 0;
766     ABObj       substruct = abmfP_obj_get_substruct_obj(obj);
767     AB_TRAVERSAL        trav;
768     ABObj               subobj = NULL;
769
770     /*
771      * Don't
772      */
773     for (trav_open(&trav, substruct, AB_TRAV_UI);
774         (subobj = trav_next(&trav)) != NULL; )
775     {
776         if (abmfP_obj_has_substruct_field(subobj))
777         {
778             if (subobj == obj)
779             {
780                 ++numFields;
781             }
782             else if (abmfP_obj_get_substruct_obj(subobj) == obj)
783             {
784                 ++numFields;
785             }
786         }
787     }
788     trav_close(&trav);
789
790     return numFields;
791 }
792
793 STRING          
794 abmfP_convert_wclass_ptr_to_name(WidgetClass wclass)
795 {
796     STRING      wclass_name= NULL;
797
798     if (wclass == xmCascadeButtonWidgetClass)
799     {
800         wclass_name= istr_string(abmfP_xmCascadeButton);
801     }
802     else if (wclass == xmScrolledWindowWidgetClass)
803     {
804         wclass_name= istr_string(abmfP_xmScrolledWindow);
805     }
806     else if (wclass == xmToggleButtonWidgetClass)
807     {
808         wclass_name= istr_string(abmfP_xmToggleButton);
809     }
810
811     return wclass_name;
812 }
813
814
815 /*
816  * Finds the primary window for the application.
817  * Finds the base window whose name is alphabetically first
818  */
819 ABObj
820 abmfP_get_root_window(ABObj project)
821 {
822     static ABObj        root_window= NULL;
823     AB_TRAVERSAL        trav;
824     ABObj               window= NULL;
825
826     if (root_window != NULL)
827     {
828         return root_window;
829     }
830
831     if (obj_get_root_window(project) == NULL)
832     {
833         for (trav_open(&trav, project, AB_TRAV_WINDOWS);
834             (window= trav_next(&trav)) != NULL; )
835         {
836             if (!obj_is_base_win(window))
837             {
838                 continue;
839             }
840             if (root_window == NULL)
841             {
842                 root_window = window;
843             }
844             else
845             {
846                 if (   (!obj_is_initially_visible(root_window))
847                     && (obj_is_initially_visible(window)) )
848                 {
849                     root_window = window;
850                 }
851                 else if (util_strcmp(
852                     obj_get_name(window), obj_get_name(root_window)) < 0)
853                 {
854                     root_window= window;
855                 }
856             }
857         }
858         trav_close(&trav);
859     } /* root_window == NULL */
860
861     if (obj_get_root_window(project) != NULL)
862     {
863         root_window= obj_get_root_window(project);
864     }
865     
866     return root_window;
867 }
868
869
870 /* 
871  * Essentially, all salient UI objects have create procs.
872  *
873  * The exceptions are:
874  *      - MENU references not salient, but have create procs
875  *      - ITEMs are salient, but do not have create procs
876  *              (they are created in their parent's proc)
877  */
878 BOOL
879 abmfP_obj_has_create_proc(ABObj obj)
880 {
881     if (obj_is_menu(obj))
882     {
883         /*
884          * menus are considered virtual, in that the "menu" doesn't
885          * actually exist - the menu references do.  We write a create
886          * proc for each menu reference.
887          */
888         return (obj_is_ref(obj) && (abmfP_obj_get_struct_obj(obj) != NULL));
889     }
890     if (obj_is_virtual(obj))
891     {
892         /* virtual objects never get written */
893         return FALSE;
894     }
895     if (obj_is_item(obj))
896     {
897         return FALSE;
898     }
899     
900     return obj_is_salient_ui(obj);
901 }
902
903
904 /*
905  * create procs take a pointer to the struct we're going to fill in.
906  */
907 STRING
908 abmfP_obj_get_create_proc_instance_param_type(ABObj obj)
909 {
910     ABObj       structObj = NULL;
911
912     structObj = abmfP_obj_get_struct_obj(obj);
913     if (structObj == NULL)
914     {
915         return "Widget *";
916     }
917
918     return abmfP_get_c_struct_ptr_type_name(structObj);
919 }
920
921
922 BOOL
923 abmfP_obj_create_proc_has_instance_param(ABObj obj)
924 {
925     return TRUE;
926 }
927
928
929 BOOL
930 abmfP_obj_create_proc_has_name_param(ABObj obj)
931 {
932     return FALSE;
933 }
934
935
936 /* 
937  * - topmost object in structure requires a parent from client
938  * - menus need parents because, if they are shared, each instance
939  *   will have a different parent
940  */
941 BOOL
942 abmfP_obj_create_proc_has_parent_param(ABObj obj)
943 {
944     return TRUE;
945 }
946
947
948 int
949 abmfP_obj_get_num_create_proc_return_widgets(ABObj obj)
950 {
951     int         numWidgets = 0;
952
953     numWidgets = 0;
954
955     return numWidgets;
956 }
957
958
959 /*
960  * which_param is 0..n-1 params
961  */
962 STRING
963 abmfP_obj_get_create_proc_return_widget_name(ABObj obj, int which_param)
964 {
965     STRING      paramName = NULL;
966
967     if (which_param > 0)
968     {
969         return NULL;
970     }
971
972     if (abmfP_obj_is_substruct_obj(obj))
973     {
974         return abmfP_get_c_substruct_ptr_type_name(obj);
975     }
976     else if (abmfP_obj_is_struct_obj(obj))
977     {
978         return abmfP_get_c_struct_ptr_type_name(obj);
979     }
980
981     return paramName;
982 }
983
984
985 BOOL
986 abmfP_obj_create_proc_has_submenu_params(ABObj obj)
987 {
988     return FALSE;
989     /* return (abmfP_obj_has_menu(obj) || abmfP_obj_has_item_with_menu(obj)); */
990 }
991
992
993 int
994 abmfP_get_num_cp_submenu_params(ABObj obj)
995 {
996     return 0;
997     /*
998     AB_TRAVERSAL        trav;
999     ABObj               item;
1000     int                 numSubmenus = 0;
1001
1002     if (abmfP_obj_has_menu(obj))
1003     {
1004         ++numSubmenus;
1005     }
1006
1007     for (trav_open(&trav, obj, AB_TRAV_ITEMS_FOR_OBJ);
1008         (item = trav_next(&trav)) != NULL; )
1009     {
1010         if (abmfP_obj_has_menu(item))
1011         {
1012             ++numSubmenus;
1013         }
1014     }
1015     trav_close(&trav);
1016
1017     return numSubmenus;
1018     */
1019 }
1020
1021
1022 STRING
1023 abmfP_get_cp_submenu_param_name(ABObj obj, int whichParam)
1024 {
1025     ABObj       paramObj = abmfP_get_cp_submenu_param_obj(obj, whichParam);
1026     if (paramObj == NULL)
1027     {
1028         return NULL;
1029     }
1030     return abmfP_get_c_field_name(paramObj);
1031 }
1032
1033
1034 STRING
1035 abmfP_get_cp_submenu_param_type_name(ABObj obj, int whichParam)
1036 {
1037     return abmfP_str_widget;
1038 }
1039
1040
1041 ABObj
1042 abmfP_get_cp_submenu_param_obj(ABObj obj, int whichParam)
1043 {
1044     int                 curParam = -1;
1045     ABObj               menu = NULL;
1046     ABObj               paramObj = NULL;
1047     AB_TRAVERSAL        trav;
1048     ABObj               item = NULL;
1049
1050     if ((menu = obj_get_menu(obj)) != NULL)
1051     {
1052         ++curParam;
1053         if (curParam == whichParam)
1054         {
1055             paramObj = menu;
1056             goto epilogue;
1057         }
1058     }
1059
1060     for (trav_open(&trav, obj, AB_TRAV_ITEMS_FOR_OBJ);
1061         (item = trav_next(&trav)) != NULL; )
1062     {
1063         if ((menu = obj_get_menu(item)) != NULL)
1064         {
1065             ++curParam;
1066             if (curParam == whichParam)
1067             {
1068                 paramObj = menu;
1069                 break;
1070             }
1071         }
1072     }
1073     trav_close(&trav);
1074
1075 epilogue:
1076     return paramObj;
1077 }
1078
1079
1080 BOOL
1081 abmfP_obj_has_menu(ABObj obj)
1082 {
1083     return (obj_get_menu(obj) != NULL);
1084 }
1085
1086
1087 BOOL
1088 abmfP_obj_has_item_with_menu(ABObj obj)
1089 {
1090     BOOL                itemHasMenu = FALSE;
1091     AB_TRAVERSAL        trav;
1092     ABObj               item;
1093
1094     for (trav_open(&trav, obj, AB_TRAV_ITEMS_FOR_OBJ);
1095         (item = trav_next(&trav)) != NULL; )
1096     {
1097         if (abmfP_obj_has_menu(item))
1098         {
1099             itemHasMenu = TRUE;
1100             break;
1101         }
1102     }
1103     trav_close(&trav);
1104
1105     return itemHasMenu;
1106 }
1107
1108
1109 BOOL
1110 abmfP_module_has_menu_struct(ABObj obj)
1111 {
1112     static ABObj        lastModule = NULL;
1113     static BOOL         lastModuleHadMenuStruct = FALSE;
1114     ABObj               module = obj_get_module(obj);
1115     BOOL                hasMenuStruct = FALSE;
1116
1117     if (module == lastModule)
1118     {
1119         hasMenuStruct = lastModuleHadMenuStruct;
1120     }
1121     else
1122     {
1123         hasMenuStruct = (trav_count(module, AB_TRAV_MENUS) > 0);
1124         lastModule = module;
1125         lastModuleHadMenuStruct = hasMenuStruct;
1126     }
1127
1128     return hasMenuStruct;
1129 }
1130
1131
1132
1133 BOOL
1134 abmfP_obj_has_glyph_label(ABObj obj)
1135 {
1136     return (   (obj_get_label(obj) != NULL)
1137             && (obj_get_label_type(obj) == AB_LABEL_GLYPH));
1138 }
1139
1140
1141 BOOL
1142 abmfP_obj_has_item_with_glyph_label(ABObj obj)
1143 {
1144     AB_TRAVERSAL        trav;
1145     ABObj               item = NULL;
1146     BOOL                doesIt = FALSE;
1147
1148     for (trav_open(&trav, obj, AB_TRAV_ITEMS_FOR_OBJ);
1149         (item = trav_next(&trav)) != NULL; )
1150     {
1151         if (abmfP_obj_has_glyph_label(item))
1152         {
1153             doesIt = TRUE;
1154             break;
1155         }
1156     }
1157     trav_close(&trav);
1158
1159     return doesIt;
1160 }
1161
1162
1163 BOOL
1164 abmfP_obj_has_string_label(ABObj obj)
1165 {
1166     return (   (obj_get_label(obj) != NULL)
1167             && (obj_get_label_type(obj) == AB_LABEL_STRING));
1168 }
1169
1170
1171 BOOL
1172 abmfP_obj_has_item_with_string_label(ABObj obj)
1173 {
1174     AB_TRAVERSAL        trav;
1175     ABObj               item = NULL;
1176     BOOL                doesIt = FALSE;
1177
1178     for (trav_open(&trav, obj, AB_TRAV_ITEMS_FOR_OBJ);
1179         (item = trav_next(&trav)) != NULL; )
1180     {
1181         if (abmfP_obj_has_string_label(item))
1182         {
1183             doesIt = TRUE;
1184             break;
1185         }
1186     }
1187     trav_close(&trav);
1188
1189     return doesIt;
1190 }
1191
1192 BOOL
1193 abmfP_proj_needs_session_save(ABObj proj)
1194 {
1195     AB_SESSIONING_METHOD        ss_mthd;
1196
1197     if (!proj)
1198         return (FALSE);
1199
1200     if (!obj_is_project(proj))
1201     {
1202         proj = obj_get_project(proj);
1203
1204         if (!proj || !obj_is_project(proj))
1205             return (FALSE);
1206     }
1207
1208     ss_mthd = obj_get_sessioning_method(proj);
1209
1210     switch (ss_mthd)  {
1211     case AB_SESSIONING_UNDEF:
1212     case AB_SESSIONING_NONE:
1213         return (FALSE);
1214     case AB_SESSIONING_CMDLINE:
1215     case AB_SESSIONING_FILE:
1216     case AB_SESSIONING_CMDLINE_AND_FILE:
1217         return (TRUE);
1218     default:
1219         return (FALSE);
1220     }
1221
1222 }
1223
1224
1225 BOOL
1226 abmfP_proj_needs_session_restore(ABObj proj)
1227 {
1228     AB_SESSIONING_METHOD        ss_mthd;
1229
1230     if (!proj)
1231         return (FALSE);
1232
1233     if (!obj_is_project(proj))
1234     {
1235         proj = obj_get_project(proj);
1236
1237         if (!proj || !obj_is_project(proj))
1238             return (FALSE);
1239     }
1240
1241     ss_mthd = obj_get_sessioning_method(proj);
1242
1243     switch (ss_mthd)  {
1244     case AB_SESSIONING_UNDEF:
1245     case AB_SESSIONING_NONE:
1246     case AB_SESSIONING_CMDLINE:
1247         return (FALSE);
1248     case AB_SESSIONING_FILE:
1249     case AB_SESSIONING_CMDLINE_AND_FILE:
1250         return (TRUE);
1251     default:
1252         return (FALSE);
1253     }
1254 }
1255
1256 BOOL
1257 abmfP_obj_needs_centering_handler(ABObj obj)
1258 {
1259     AB_ATTACH_TYPE      left_attach_type,
1260                         top_attach_type;
1261
1262     if (!obj)
1263         return (FALSE);
1264
1265     left_attach_type = obj_get_attach_type(obj, AB_CP_WEST);
1266     top_attach_type = obj_get_attach_type(obj, AB_CP_NORTH);
1267
1268     if ((left_attach_type == AB_ATTACH_CENTER_GRIDLINE) || 
1269         (top_attach_type == AB_ATTACH_CENTER_GRIDLINE))
1270         return (TRUE);
1271     else
1272         return (FALSE);
1273 }
1274
1275 STRING
1276 abmfP_obj_get_centering_type(ABObj obj)
1277 {
1278     AB_ATTACH_TYPE      left_attach_type,
1279                         top_attach_type;
1280
1281     if (!obj || !abmfP_obj_needs_centering_handler(obj))
1282         return("DTB_CENTER_NONE");
1283     
1284     left_attach_type = obj_get_attach_type(obj, AB_CP_WEST);
1285     top_attach_type = obj_get_attach_type(obj, AB_CP_NORTH);
1286
1287     if ((left_attach_type == AB_ATTACH_CENTER_GRIDLINE) && 
1288         (top_attach_type != AB_ATTACH_CENTER_GRIDLINE))
1289         return("DTB_CENTER_POSITION_VERT");
1290
1291     if ((left_attach_type != AB_ATTACH_CENTER_GRIDLINE) && 
1292         (top_attach_type == AB_ATTACH_CENTER_GRIDLINE))
1293         return("DTB_CENTER_POSITION_HORIZ");
1294
1295     if ((left_attach_type == AB_ATTACH_CENTER_GRIDLINE) && 
1296         (top_attach_type == AB_ATTACH_CENTER_GRIDLINE))
1297         return("DTB_CENTER_POSITION_BOTH");
1298 }
1299
1300 BOOL
1301 abmfP_obj_needs_align_handler(ABObj obj)
1302 {
1303     AB_GROUP_TYPE       type;
1304
1305     if (!obj || !obj_is_group(obj))
1306         return (FALSE);
1307
1308     type = obj_get_group_type(obj);
1309
1310     if (type != AB_GROUP_IGNORE)
1311         return (TRUE);
1312     else
1313         return (FALSE);
1314 }
1315
1316 STRING
1317 abmfP_obj_get_group_type(ABObj obj)
1318 {
1319
1320     AB_GROUP_TYPE       type;
1321
1322     if (!obj || !abmfP_obj_needs_align_handler(obj))
1323         return("DTB_GROUP_NONE");
1324     
1325     type = obj_get_group_type(obj);
1326
1327     switch (type)
1328     {
1329         case AB_GROUP_IGNORE:
1330             return("DTB_GROUP_NONE");
1331         case AB_GROUP_ROWS:
1332             return("DTB_GROUP_ROWS");
1333         case AB_GROUP_COLUMNS:
1334             return("DTB_GROUP_COLUMNS");
1335         case AB_GROUP_ROWSCOLUMNS:
1336             return("DTB_GROUP_ROWSCOLUMNS");
1337     }
1338 }
1339
1340 STRING
1341 abmfP_obj_get_row_align_type(ABObj obj)
1342 {
1343     AB_GROUP_TYPE       group_type;
1344     AB_ALIGNMENT        align_type;
1345
1346     if (!obj)
1347         return("DTB_ALIGN_NONE");
1348     
1349     group_type = obj_get_group_type(obj);
1350
1351     if ((group_type == AB_GROUP_COLUMNS) || (group_type == AB_GROUP_IGNORE))
1352         return("DTB_ALIGN_NONE");
1353
1354     align_type = obj_get_row_align(obj);
1355
1356     switch (align_type)
1357     {
1358         case AB_ALIGN_TOP:
1359             return("DTB_ALIGN_TOP");
1360         case AB_ALIGN_HCENTER:
1361             return("DTB_ALIGN_HCENTER");
1362         case AB_ALIGN_BOTTOM:
1363             return("DTB_ALIGN_BOTTOM");
1364         default:
1365             return("DTB_ALIGN_NONE");
1366     }
1367 }
1368
1369 STRING
1370 abmfP_obj_get_col_align_type(ABObj obj)
1371 {
1372     AB_GROUP_TYPE       group_type;
1373     AB_ALIGNMENT        align_type;
1374
1375     if (!obj)
1376         return("DTB_ALIGN_NONE");
1377     
1378     group_type = obj_get_group_type(obj);
1379
1380     if ((group_type == AB_GROUP_ROWS) || (group_type == AB_GROUP_IGNORE))
1381         return("DTB_ALIGN_NONE");
1382
1383     align_type = obj_get_col_align(obj);
1384
1385     switch (align_type)
1386     {
1387         case AB_ALIGN_LEFT:
1388             return("DTB_ALIGN_LEFT");
1389         case AB_ALIGN_LABELS:
1390             return("DTB_ALIGN_LABELS");
1391         case AB_ALIGN_VCENTER:
1392             return("DTB_ALIGN_VCENTER");
1393         case AB_ALIGN_RIGHT:
1394             return("DTB_ALIGN_RIGHT");
1395         default:
1396             return("DTB_ALIGN_NONE");
1397     }
1398 }
1399
1400
1401 /*
1402  * Returns the starting index and length of the base file name
1403  * sans leading path and trailing extension.
1404  *
1405  */
1406 static int
1407 find_base_file_name(STRING path, int *startPtr, int *lenPtr)
1408 {
1409 #define start (*startPtr)
1410 #define len (*lenPtr)
1411     char        *slashPtr = NULL;
1412     char        *dotPtr = NULL;
1413     int         slashChar = -1;
1414     int         dotChar = -1;
1415
1416     slashPtr = strrchr(path, '/');
1417     if (slashPtr != NULL)
1418     {
1419         /*
1420          * handle strings of the form subdir//x.ext
1421          */
1422         while (((*slashPtr) == '/') && ((*slashPtr) != 0))
1423         {
1424             ++slashPtr;
1425         }
1426         --slashPtr;             /* point to last slash */
1427         slashChar = *slashPtr;
1428         *slashPtr = 0;
1429     }
1430
1431     start = 0;
1432     if (slashPtr != NULL)
1433     {
1434         start = ((int)(slashPtr - path)) + 1;
1435     }
1436
1437     dotPtr = strrchr(&(path[start]), '.');
1438     if (dotPtr != NULL)
1439     {
1440         dotChar = *dotPtr;
1441         *dotPtr = 0;
1442     }
1443
1444     len = strlen(&path[start]);
1445
1446     /*
1447      * Restore the string
1448      */
1449     if (slashPtr != NULL)
1450     {
1451         *slashPtr = (char)slashChar;
1452     }
1453     if (dotPtr != NULL)
1454     {
1455         *dotPtr = (char)dotChar;
1456     }
1457
1458     return 0;
1459 #undef start
1460 #undef len
1461 }
1462
1463 BOOL
1464 abmfP_proj_has_message(ABObj proj)
1465 {
1466     ABObj               obj = (ABObj) NULL;
1467     AB_TRAVERSAL        trav;
1468     int                 i = 0;
1469     BOOL                hasMsg = FALSE;
1470
1471     if (!proj)
1472         return (FALSE);
1473
1474     if (!obj_is_project(proj))
1475     {
1476         proj = obj_get_project(proj);
1477
1478         if (!proj || !obj_is_project(proj))
1479             return (FALSE);
1480     }
1481
1482     for (trav_open(&trav, proj, AB_TRAV_SALIENT_UI); 
1483         ((obj = trav_next(&trav)) != NULL) && !hasMsg; )
1484     {
1485         if (obj_is_message(obj))
1486           hasMsg = TRUE;
1487     }
1488
1489     return (hasMsg);
1490 }
1491
1492
1493 /*
1494 ** 4/30/95 bfreeman - Temporary. This is obj_get_refs_to's territory! But, I
1495 ** wasn't able to get the refs to menu items out of obj_get_refs_to()...the
1496 ** objects just aren't there.
1497 **
1498 ** Returns an ABObjList containing all of the references to obj
1499 **
1500 ** Example use:
1501 **
1502 **    ABObjList refList = abmfP_find_refs_to(obj);
1503 **    ABObj      refObj = NULL;
1504 **    int       numRefs = objlist_get_num_objs(refList);
1505 **    int             i = 0;
1506 **
1507 **    if ((refList != NULL) && (numRefs > 0))
1508 **    {
1509 **      for (i = 0; i < numRefs; ++i)
1510 **      {
1511 **          refObj = objlist_get_obj(refList, i, NULL);
1512 **
1513 **          --- use refObj, it refers to obj ---
1514 **                  
1515 **      }
1516 **    }
1517 **    objlist_destroy(refList);
1518 **
1519 **
1520 ** Note: May return NULL and it is the responsibility of the caller to
1521 **       destroy the ABObjList.
1522 */
1523 ABObjList
1524 abmfP_find_refs_to(ABObj obj)
1525 {
1526     AB_TRAVERSAL  moduleTrav;
1527     ABObjList     refList = NULL;
1528     ABObj         refObj  = NULL;
1529     
1530     if (obj == NULL)
1531         return NULL;
1532
1533     refList = objlist_create();
1534     
1535     for (trav_open(&moduleTrav, obj_get_module(obj), AB_TRAV_UI);
1536          ((refObj = trav_next(&moduleTrav)) != NULL); )
1537     {
1538         if (obj_is_ref(refObj) && (refObj->ref_to == obj))
1539         {
1540             objlist_add_obj(refList, refObj, NULL);
1541         }
1542     }
1543     trav_close(&moduleTrav);
1544
1545     return refList;
1546 }
1547
1548