Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / programs / dtappbuilder / src / ab / ab_bil.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: ab_bil.c /main/3 1995/11/06 17:12:37 rswiston $
26  *
27  * @(#)ab_bil.c 1.85 22 May 1995
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  * File: ab_bil.c - functions dealing with bil files
45  */
46 #include <stdio.h>
47 #include <sys/times.h>
48 #include <time.h>
49 #include <sys/param.h>          /* MAXPATHLEN */
50 #include <errno.h>
51 #include <ab_private/obj.h>
52 #include <ab_private/trav.h>
53 #include <ab_private/bil.h>
54 #include <ab_private/objxm.h>
55 #include <ab_private/abobj.h>
56 #include <ab_private/abobj_set.h>
57 #include <ab_private/brws.h>
58 #include <ab_private/proj.h>
59 #include <ab_private/conn.h>
60 #include <ab_private/ui_util.h>
61 #include <ab_private/ab.h>
62 #include <ab_private/ab_bil.h>
63 #include "../libABobj/objP.h"
64 #include "palette_ui.h"
65
66 /* REMIND: #ifdef DEBUG */
67 typedef struct
68 {
69     double      startSeconds;
70     double      endSeconds;
71     double      elapsedSeconds;
72 } ABTimedIntervalRec, *ABTimedInterval;
73
74 typedef struct
75 {
76     ABTimedIntervalRec  realTime;
77     ABTimedIntervalRec  CPUTime;
78 } ABProfiledIntervalRec, *ABProfiledInterval;
79
80 static int get_cur_times(double *realTimeOut, double *cpuTimeOut);
81 static int get_start_times(ABProfiledInterval);
82 static int get_end_times(ABProfiledInterval);
83 static int calc_elapsed_times(ABProfiledInterval);
84 static int print_load_stats(
85                 ABObj                   tree,
86                 ABProfiledInterval      totalTime,
87                 ABProfiledInterval      loadTime,
88                 ABProfiledInterval      configTime
89                 );
90
91 char    Buf[MAXPATHLEN];        /* Work buffer */
92
93 /*
94  * Loads in a new project, replacing the current project.
95  * Chdirs to the directory where the project is. Called 
96  * from the 'File->Open Project' and 'Project->Open'
97  * (Project Organizer) menus, and the cmd-line (dtbuilder.c).
98  */
99 int 
100 ab_load_bil_file(
101     STRING      fileName,
102     FILE        *inFile,
103     BOOL        BufferDrop
104 )
105 {
106     int                         rc = 0;         /* return code */
107     ABObj                       newProject = NULL;
108     ABObj                       mod = NULL;
109     STRING                      init_msg = NULL;
110     STRING                      modfile = NULL;
111     int                         pLinesRead = 0;
112     ABProfiledIntervalRec       totalTime;
113     ABProfiledIntervalRec       loadTime;
114     ABProfiledIntervalRec       configTime;
115     XmString                    xm_buf = (XmString) NULL;
116     int                         NoWrite = 0;
117     int                         len = 0;
118     STRING                      errmsg = NULL;
119     BOOL                        read_OK, write_OK;
120     AB_TRAVERSAL                trav;
121
122     get_start_times(&totalTime);
123
124     get_start_times(&loadTime);
125     rc = bil_load_file_and_resolve_all(fileName, inFile, &newProject);
126     if (newProject == NULL)
127     {
128         return rc;
129     }
130
131     /* If BufferDrop is TRUE, then that means that
132      * ab_load_bil_file() is being called due to
133      * a buffer drop (i.e. a .bix dtmail attachment).
134      * In that case, we don't need to check whether
135      * the modules are read-only, since there aren't
136      * .bil files associated with the modules.
137      */
138     if (!BufferDrop)
139     {
140         /* Check if any of the modules are read-only. If so, post
141          * a message.
142          */
143         for (trav_open(&trav, newProject, AB_TRAV_MODULES);
144             (mod = trav_next(&trav)) != NULL; )
145         {
146             if (!obj_is_defined(mod))
147             {
148                continue;
149             }
150         
151             modfile = obj_get_file(mod);
152             abio_access_file(modfile, &read_OK, &write_OK);
153             if (!write_OK && !util_strempty(modfile))
154             {
155                 obj_set_read_only(mod, TRUE);
156
157                 len = len + strlen(modfile) + 2;
158                 /*
159                 ** Is this the first read-only file we've encountered? 
160                 ** If so, initialize the notice message.
161                 */
162                 if (NoWrite == 0)
163                 {
164                     /* The first thing in the message is 
165                      * some general text. 
166                      */
167                     init_msg = catgets(Dtb_project_catd, 100, 38, "The following modules are read-only.\nIf you edit these modules, you\nwill not be able to save your edits.");
168
169                     /* If we have an old buffer lying around, free it */
170                     if (errmsg != (STRING) NULL) 
171                         util_free(errmsg);
172  
173                     /* Now create a new buffer of the proper size */
174                     len = strlen(init_msg) + strlen(modfile) + 3;
175                     errmsg = (STRING) util_malloc(len);
176  
177                     /*
178                     ** Put the general text plus name of the first 
179                     ** read-only file into the notice message.
180                     */
181                     sprintf(errmsg, "%s\n\n%s", init_msg, modfile);
182                 }
183                 else
184                 {
185                     errmsg = (STRING) realloc(errmsg, len);
186                     strcat(errmsg, "\n");
187                     strcat(errmsg, modfile);
188                 }
189                 NoWrite++;
190             }
191         }
192     }
193
194     if (!util_strempty(errmsg))
195     {
196         util_set_help_data(catgets(Dtb_project_catd, 100, 92,
197             "Any changes made to a read-only module cannot be saved,\nunless you save the module to a different file name."),
198             NULL, NULL);
199         util_puts(errmsg);
200         util_free(errmsg);
201     }
202     get_end_times(&loadTime);
203
204     if( obj_get_num_children(newProject) == 0 )
205     {
206         sprintf(Buf, catgets(Dtb_project_catd, 100, 23,
207                 "%s: Empty project file loaded."), fileName);
208         xm_buf = XmStringCreateLocalized(Buf);
209         dtb_palette_empty_proj_msg_initialize(&dtb_palette_empty_proj_msg);
210         (void)dtb_show_modal_message(dtb_get_toplevel_widget(),
211                 &dtb_palette_empty_proj_msg, xm_buf, NULL, NULL);
212         XmStringFree(xm_buf);
213     }
214
215     if (util_get_verbosity() >= 5)
216         obj_tree_print(newProject);
217
218     /* Destroy the old project, first. Then initialize
219      * the project to be the one just created.  This
220      * also sets the current module to NULL, since a
221      * module has not been shown yet.
222      */
223     proj_destroy_project(proj_get_project());
224     proj_set_project(newProject);
225
226 /* REMIND: Check this out later */
227
228     get_start_times(&configTime);
229     objxm_tree_configure(newProject, OBJXM_CONFIG_BUILD);
230     get_end_times(&configTime);
231
232     abobj_update_proj_name(newProject);
233     abobj_update_palette_title(newProject);
234     obj_tree_update_clients(newProject);
235
236 #ifdef DEBUG
237     get_end_times(&totalTime);
238     print_load_stats(newProject, &totalTime, &loadTime, &configTime);
239 #endif /* DEBUG */
240
241
242     return 0;
243 }
244
245
246 int 
247 ab_import_bil_file(
248     STRING      fileName,
249     FILE        *inFile,
250     BOOL        ImportByCopy
251 )
252 {
253     int                 return_value = 0;
254     AB_TRAVERSAL        trav;
255     ABObj               project = proj_get_project();
256     ABObj               module = NULL;
257     ABObjList           loaded_comp_objs = NULL;
258     ABObj               loaded_module = NULL;
259     STRING              file = NULL;
260
261     /*
262      * XmConfigured flags is not getting set properly.  If it's already
263      * here, we'll assume it's configured.
264      */
265     for (trav_open(&trav, project, AB_TRAV_MODULES);
266         (module= trav_next(&trav)) != NULL; )
267     {
268         obj_set_flag(module, XmConfiguredFlag);
269     }
270     trav_close(&trav);
271
272     if (bil_load_file(fileName, inFile, project, &loaded_comp_objs)
273         == NULL)
274     {
275         return_value = -1;
276         goto epilogue;
277     }
278
279     /* loaded_module will point to the module that was
280      * created.
281      */
282     loaded_module = NULL;
283     if (objlist_get_num_objs(loaded_comp_objs) >= 1)
284     {
285         loaded_module = objlist_get_obj(loaded_comp_objs, 0, NULL);
286     }
287
288     if (loaded_module != NULL)
289     {
290         if (ImportByCopy)
291         {
292             obj_set_file(loaded_module, (String) NULL);
293         }
294         else    /* Import by reference */
295         {
296             /* Convert the imported module's file field to a
297              * path that is relative to the directory in which
298              * the project is stored.
299              */
300             file = proj_cvt_mod_file_to_rel_path(fileName,
301                         obj_get_file(project));
302             obj_set_file(loaded_module, file);
303             util_free(file);
304         }
305
306         /*
307          * configure anything that's not marked as configured
308          */
309         abobj_show_tree(loaded_module, TRUE);
310         obj_tree_update_clients(loaded_module);
311         proj_set_cur_module(loaded_module);
312     }
313
314 epilogue:
315     objlist_destroy(loaded_comp_objs);
316     return return_value;
317 }
318
319
320 static int
321 get_start_times(ABProfiledInterval interval)
322 {
323     return get_cur_times(&(interval->realTime.startSeconds),
324                          &(interval->CPUTime.startSeconds));
325 }
326
327
328 static int
329 get_end_times(ABProfiledInterval interval)
330 {
331     return get_cur_times(&(interval->realTime.endSeconds),
332                          &(interval->CPUTime.endSeconds));
333 }
334
335
336 static int
337 calc_elapsed_times(ABProfiledInterval interval)
338 {
339     interval->realTime.elapsedSeconds =
340         interval->realTime.endSeconds - interval->realTime.startSeconds;
341     interval->CPUTime.elapsedSeconds =
342         interval->CPUTime.endSeconds - interval->CPUTime.startSeconds;
343     return 0;
344 }
345
346
347 /* REMIND: #ifdef DEBUG */
348 static int
349 print_load_stats(
350         ABObj                   tree,
351         ABProfiledInterval      totalTime,
352         ABProfiledInterval      loadTime,
353         ABProfiledInterval      configTime
354 )
355 {
356     ABProfiledIntervalRec       otherTimeRec;
357     ABProfiledInterval          otherTime = &otherTimeRec;
358
359     /*
360      * Print out statistics about load
361      */
362     calc_elapsed_times(totalTime);
363     calc_elapsed_times(loadTime);
364     calc_elapsed_times(configTime);
365     otherTime->realTime.elapsedSeconds = 
366                 (totalTime->realTime.elapsedSeconds
367                         - loadTime->realTime.elapsedSeconds
368                         - configTime->realTime.elapsedSeconds);
369     otherTime->CPUTime.elapsedSeconds = 
370                 (totalTime->CPUTime.elapsedSeconds
371                         - loadTime->CPUTime.elapsedSeconds
372                         - configTime->CPUTime.elapsedSeconds);
373
374     fprintf(stderr, "\nLoad Times (Real/CPU) seconds:\n");
375     fprintf(stderr, "          Total: (%lg/%lg)\n", 
376         totalTime->realTime.elapsedSeconds,
377         totalTime->CPUTime.elapsedSeconds);
378     fprintf(stderr, "    Actual load: (%lg/%lg)\n",
379         loadTime->realTime.elapsedSeconds,
380         loadTime->CPUTime.elapsedSeconds);
381     fprintf(stderr, "         Config: (%lg/%lg)\n",
382         configTime->realTime.elapsedSeconds,
383         configTime->CPUTime.elapsedSeconds);
384     fprintf(stderr, "          Other: (%lg/%lg)\n",
385         otherTime->realTime.elapsedSeconds,
386         otherTime->CPUTime.elapsedSeconds);
387
388     fprintf(stderr, "Number of objects loaded - salient:%d   total:%d\n",
389         trav_count(tree, AB_TRAV_SALIENT),
390         trav_count(tree, AB_TRAV_ALL));
391
392     return 0;
393 }
394 /* REMIND: #endif DEBUG */
395
396
397 static int
398 get_cur_times(double *realTimeOut, double *cpuTimeOut)
399 {
400     static BOOL initialized = FALSE;
401     static long ticks_per_second = 1;
402     struct tms  timeInfo;
403     double      realTime;
404     double      cpuTime;
405     if (!initialized)
406     {
407         initialized = TRUE;
408         ticks_per_second = sysconf(_SC_CLK_TCK);
409     }
410
411     realTime = times(&timeInfo);
412     cpuTime = timeInfo.tms_utime + timeInfo.tms_stime
413                         + timeInfo.tms_cutime + timeInfo.tms_cstime;
414     *realTimeOut  = realTime / ticks_per_second;
415     *cpuTimeOut = cpuTime / ticks_per_second;
416
417     return 0;
418 }
419
420
421 /* Called by the 'File->Open Project' callback and the 
422  * 'Project->Open' callback.  NOT called when a project
423  * is loaded from the command-line.
424  */
425 int
426 ab_check_and_open_bip(
427     STRING      fileName
428 )
429 {
430     DTB_MODAL_ANSWER    answer = DTB_ANSWER_NONE;
431     BOOL                read_OK, write_OK;
432     int                 iRet = 0;
433     XmString            xm_buf = (XmString) NULL;
434     DtbObjectHelpData   help_data = NULL;
435
436     abio_access_file(fileName, &read_OK, &write_OK);
437     if (read_OK)
438     {
439         if (write_OK)
440         {
441             iRet = ab_load_project(fileName, NULL, FALSE);
442         }
443         else    /* Read-only file */
444         {
445             /* You can read it but you can't write to it. */
446             sprintf(Buf, catgets(Dtb_project_catd, 100, 17,
447                 "The file %s is a read-only file.\nYou may open the project\nor cancel the operation."), fileName);
448             xm_buf = XmStringCreateLocalized(Buf);
449             dtb_palette_open_ro_proj_msg_initialize(
450                         &dtb_palette_open_ro_proj_msg);
451
452             help_data = (DtbObjectHelpData) util_malloc(sizeof(DtbObjectHelpDataRec));
453             help_data->help_text = catgets(Dtb_project_catd, 100, 90,
454                 "Opening a read-only project means that any changes that\naffect the project (.bip) file, such as creation of a\nnew module or creation of a cross-module connection,\ncannot be saved, unless you save the project to a\ndifferent file name. You have the option of continuing\nwith the open operation or cancelling it.");
455             help_data->help_volume = "";
456             help_data->help_locationID = "";
457             
458             answer = dtb_show_modal_message(dtb_get_toplevel_widget(),
459                 &dtb_palette_open_ro_proj_msg, xm_buf, help_data, NULL);
460
461             util_free(help_data);
462             XmStringFree(xm_buf);
463             switch (answer)
464             {
465                     case DTB_ANSWER_ACTION1:
466                         iRet = ab_load_project(fileName, NULL, FALSE);
467                         break;
468
469                     case DTB_ANSWER_CANCEL:
470                         break;
471
472                     case DTB_ANSWER_HELP:
473                         break;
474             }
475         }
476     }
477     else 
478     {
479         sprintf(Buf, catgets(Dtb_project_catd, 100, 20,
480                 "%s does not have read permission."), fileName);
481         xm_buf = XmStringCreateLocalized(Buf);
482         dtb_palette_error_msg_initialize(&dtb_palette_error_msg);
483         (void)dtb_show_modal_message(dtb_get_toplevel_widget(),
484                         &dtb_palette_error_msg, xm_buf, NULL, NULL);
485         XmStringFree(xm_buf);
486         iRet = -1;
487     }
488
489     return (iRet); 
490 }
491
492 int
493 ab_load_project(
494     STRING      fileName,
495     FILE        *inFile,
496     BOOL        BufferDrop
497 )
498 {
499     int         ret = 0;
500
501     ab_set_busy_cursor(TRUE);
502     ui_sync_display_of_widget(AB_toplevel);
503     
504     if ((ret = ab_load_bil_file(fileName, inFile, BufferDrop)) != -1)
505     {
506         proj_show_proj_dir();
507         objxm_tree_configure(proj_get_project(), OBJXM_CONFIG_BUILD);
508         /* Popup the Project Organizer */
509         proj_show_dialog();
510     }
511
512     ab_set_busy_cursor(FALSE);
513
514     return (ret);
515 }
516
517 /* Calls ab_import_bil_file().  Called by the File->Import->Module
518  * callback and the Module->Import callback.  NOT called when
519  * a project is loaded from the command-line.
520  */
521 int
522 ab_check_and_import_bil(
523     STRING      fileName,
524     BOOL        ImportByCopy
525 )
526 {
527     BOOL                read_OK, write_OK;
528     DTB_MODAL_ANSWER    answer = DTB_ANSWER_NONE;
529     ABObj               project = proj_get_project();
530     int                 iRet = 0;
531     XmString            xm_buf = (XmString) NULL;
532     DtbObjectHelpData   help_data = NULL;
533
534     abio_access_file(fileName, &read_OK, &write_OK);
535     if (read_OK)
536     {
537         if (ImportByCopy)
538         {
539                 iRet = ab_import_module(fileName, NULL, TRUE);
540         }
541         else    /* Importing by Reference. Have to check permissions. */
542         {
543             if (write_OK)
544             {
545                 /* The file is readable and writable, can be opened, 
546                  * and is a valid module file, so import it.
547                  */
548                 iRet = ab_import_module(fileName, NULL, FALSE);
549             }
550             else
551             {
552                 /* You can read it but you can't write to it. */
553                 sprintf(Buf, catgets(Dtb_project_catd, 100, 21,
554                             "The file %s is a read-only file.\n\
555                             You may import the module or cancel\n\
556                             the operation."), fileName);
557                 xm_buf = XmStringCreateLocalized(Buf);
558                 dtb_palette_import_ro_msg_initialize(
559                                 &dtb_palette_import_ro_msg);
560
561                 help_data = (DtbObjectHelpData) util_malloc(sizeof(DtbObjectHelpDataRec));
562                 help_data->help_text = catgets(Dtb_project_catd, 100, 91,
563                     "Importing a read-only module means that any changes\nthat affect the module cannot be saved, unless you\nsave the module to a different file name. You have\nthe option of continuing with the import operation\nor cancelling it.");
564
565                 help_data->help_volume = "";
566                 help_data->help_locationID = "";
567
568                 answer = dtb_show_modal_message(dtb_get_toplevel_widget(),
569                         &dtb_palette_import_ro_msg, xm_buf, help_data, NULL);
570
571                 util_free(help_data);
572                 XmStringFree(xm_buf);
573                 switch (answer)
574                 {
575                     case DTB_ANSWER_ACTION1:
576                         iRet = ab_import_module(fileName, NULL, ImportByCopy);
577                         break;
578
579                     case DTB_ANSWER_CANCEL:
580                     case DTB_ANSWER_HELP:
581                         break;
582                 }
583             }
584         }
585     }
586     else
587     {
588         sprintf(Buf, catgets(Dtb_project_catd, 100, 9,
589                 "%s does not have read permission."), fileName);
590         xm_buf = XmStringCreateLocalized(Buf);  
591         dtb_palette_error_msg_initialize(&dtb_palette_error_msg);
592         (void)dtb_show_modal_message(dtb_get_toplevel_widget(),
593                         &dtb_palette_error_msg, xm_buf, NULL, NULL);
594         XmStringFree(xm_buf);
595         iRet = -1;
596     }
597
598     return (iRet);
599 }
600
601 int
602 ab_import_module(
603     STRING      fileName,
604     FILE        *inFile,
605     BOOL        ImportByCopy
606 )
607 {
608     int         iRet = 0;
609
610     ab_set_busy_cursor(TRUE);
611     ui_sync_display_of_widget(AB_toplevel);
612
613     iRet = ab_import_bil_file(fileName, inFile, ImportByCopy);
614     if (iRet != -1)
615     {
616         abobj_set_save_needed(proj_get_project(), TRUE);
617     }
618     ab_set_busy_cursor(FALSE);
619
620     return (iRet);
621 }