Spelling fixes
[oweals/cde.git] / cde / programs / dtappbuilder / src / ab / proj.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these libraries and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /*
24  *      $XConsortium: proj.c /main/3 1995/11/06 17:45:35 rswiston $
25  *
26  *      @(#)proj.c      1.50 17 May 1994
27  *
28  *      RESTRICTED CONFIDENTIAL INFORMATION:
29  *
30  *      The information in this document is subject to special
31  *      restrictions in a confidential disclosure agreement between
32  *      HP, IBM, Sun, USL, SCO and Univel.  Do not distribute this
33  *      document outside HP, IBM, Sun, USL, SCO, or Univel without
34  *      Sun's specific written approval.  This document and all copies
35  *      and derivative works thereof must be returned or destroyed at
36  *      Sun's request.
37  *
38  *      Copyright 1993 Sun Microsystems, Inc.  All rights reserved.
39  *
40  */
41
42
43 #include <stdio.h>
44 #include <sys/param.h>
45 #include <errno.h>
46 #include <Xm/Xm.h>
47 #include <Xm/BulletinB.h>
48 #include <Xm/SelectioB.h>
49 #include <ab_private/ab.h> 
50 #include <ab_private/bil.h> 
51 #include <ab_private/abobj.h> 
52 #include <ab_private/abobj_set.h> 
53 #include <ab_private/appfw.h> 
54 #include <ab_private/objxm.h>
55 #include <ab_private/brwsP.h>
56 #include <ab_private/projP.h> 
57 #include <ab_private/cgen.h>
58 #include <ab_private/ui_util.h>
59 #include <ab_private/x_util.h>
60 #include <ab_private/trav.h>
61 #include <ab_private/abio.h>
62 #include <ab_private/ab_bil.h>
63 #include <ab_private/proj.h>
64 #include <ab_private/obj.h>
65 #include <ab_private/abuil_load.h>
66 #include <ab_private/pal.h>
67 #include "proj_ui.h"
68 #include "dtbuilder.h"
69
70 /*************************************************************************
71 **                                                                      **
72 **       Private Function Declarations                                  **
73 **                                                                      **
74 **************************************************************************/
75 static Vwr      create_proj_struct();
76
77 static void     create_proj_ui_handles(
78                     Vwr         v
79                 );
80
81 /*
82  * Action Procs for project window.
83  */
84 static void     select_module(
85                     Widget w, 
86                     XEvent *ev, 
87                     String *params, 
88                     int nparams
89                 );
90
91 static void     toggle_select_module(
92                     Widget w, 
93                     XEvent *ev, 
94                     String *params, 
95                     int nparams
96                 );
97
98 static void     show_module(
99                     Widget w, 
100                     XEvent *ev, 
101                     String *params, 
102                     int nparams
103                 );
104
105 static void     enable_proj_actions(
106                     Widget widget
107                 );
108
109 static void     disable_proj_actions(
110                     Widget widget
111                 );
112
113 static void     no_module_selected(
114                     DtbProjProjMainInfo proj_d
115                 );
116
117 static void     one_module_selected(
118                     DtbProjProjMainInfo proj_d
119                 );
120
121 static void     mult_module_selected(
122                     DtbProjProjMainInfo proj_d
123                 );
124
125 static void     update_menu_items(
126                     int         old_count,
127                     int         new_count
128                 );
129
130 static void     pointer_motion_proc(
131                     Widget widget,
132                     XEvent *event,
133                     String *params,
134                     int num_params
135                 );
136                     
137 static void     popdown_proj_window(
138                     Widget      widget,
139                     XtPointer   client_data,
140                     XtPointer   call_data
141                 );
142
143 static void     import_uil(
144                     STRING      uil_file_name
145                 );
146
147 /*
148  * Object notification callbacks
149  */
150 static int      projP_obj_renameOCB(
151                     ObjEvAttChangeInfo  info
152                 );
153
154 static int      projP_obj_destroyOCB(
155                     ObjEvDestroyInfo    info
156                 );
157
158 static int      projP_obj_updateOCB(
159                     ObjEvUpdateInfo     info
160                 );
161
162 /*
163  * Functions for supporting rubber banding
164  */
165 static void     project_bpress(
166                     Widget widget, 
167                     XEvent *event, 
168                     String *params, 
169                     int num_params
170                 );
171
172 static int      project_select_rband(
173                     VNode       vnode
174                 );
175
176 static void     projP_drawarea_button_drag(
177                     Widget widget,
178                     XtPointer client_data,
179                     XEvent *event,
180                     Boolean *cont_dispatch
181                 );
182
183 static void     project_rband(
184                     Widget      widget,
185                     XEvent      *event,
186                     XRectangle  *rb_rect,
187                     XtPointer   client_data
188                 );
189
190 /*************************************************************************
191 **                                                                      **
192 **       Data                                                           **
193 **                                                                      **
194 **************************************************************************/
195
196 /*
197  * Project window Actions
198  */
199 static XtActionsRec projwin_actions[] = {
200     {"ModButtonPress",   (XtActionProc)project_bpress },
201     {"ModSelect",        (XtActionProc)select_module },
202     {"ModToggleSelect",  (XtActionProc)toggle_select_module },
203     {"ModShowModule",    (XtActionProc)show_module },
204     {"ModPointerMotion", (XtActionProc)pointer_motion_proc}
205 };
206
207 /* 
208  * Translations for module subwindow of Project Organizer 
209  */
210 static String base_translations =
211      "Shift <Btn1Down>:         ModButtonPress() \n\
212      <Btn1Down>:                ModButtonPress() \n\
213       Shift <Btn1Down>,<Btn1Up>: ModToggleSelect() \n\
214      <Btn1Down>,<Btn1Up>:       ModSelect() \n\
215      <Btn1Up>(2):               ModShowModule() \n\
216      <Motion>:                  ModPointerMotion() ";
217
218 static String btn2_adjust_translations =
219     "\n<Btn2Down>:                ModButtonPress() \n\
220        <Btn2Down>,<Btn2Up>:       ModToggleSelect() ";
221
222 static XtTranslations proj_transtbl = NULL;
223
224
225 /*
226  * Static variables used for rubber banding
227  */
228 static XRectangle       *rband_rect = NULL;
229 static Boolean          mselect_adjust = False;
230
231 char                    Buf[MAXPATHLEN];        /* Work buffer */
232
233 /*************************************************************************
234 **
235 **       Function Definitions
236 **
237 **************************************************************************/
238 static int      select_fn(
239                     VNode       module
240                 );
241
242 /*
243  * Project Window Xt callbacks
244  */
245
246 /*
247  * Popup the project window by managing the container child of the
248  * Dialog shell.
249  */
250 void
251 proj_show_dialog()
252 {
253     ABObj               proj = proj_get_project();
254     BrowserUiObj        ui;
255     ChooserInfo         info = NULL;
256  
257     if (AB_proj_window == NULL)
258     {
259         if (!Proj_viewer)
260             Proj_viewer = create_proj_struct();
261
262         create_proj_ui_handles(Proj_viewer);
263         proj_add_objects(proj);
264
265         /* Check if the shared file chooser is already
266          * up when the Project Organizer is displayed.
267          * If it is, then find out which one is up and
268          * set the appropriate menu items inactive.
269          */
270         if ((AB_generic_chooser != NULL) &&
271             XtIsManaged(AB_generic_chooser))
272         {
273             XtVaGetValues(AB_generic_chooser,
274                                 XmNuserData, &info,
275                                 NULL);
276             proj_set_menus(info->chooser_type, FALSE);
277         }
278         /* When the Project Organizer is first brought
279          * up, no modules are selected so certain menu
280          * items (like Module ->Save/Save As) should be
281          * made inactive.
282          */
283         update_menu_items(0, 0);
284     }
285     ab_show_window(AB_proj_window);
286     abobj_update_proj_name( proj );
287 }
288
289 /*
290  * projP_store_viewer
291  * Create callback for project window widgets
292  */
293 void
294 projP_store_viewer(
295     Widget      widget,
296     XtPointer   client_data,
297     XtPointer   call_data
298 )
299 {
300     char        *tmp_str = (char *)client_data;
301
302     /*
303     widget_str = strtok(tmp_str, "+");
304     */
305
306     /*
307      * If project viewer structure has not been initialized,
308      * do it now
309      */
310     if (!Proj_viewer)
311     {
312         Proj_viewer = create_proj_struct();
313     }
314
315     XtVaSetValues(widget, XmNuserData, (XtPointer)Proj_viewer, NULL);
316
317 }
318
319 /*
320  * Create viewer data structure for project window
321  */
322 static Vwr
323 create_proj_struct()
324 {
325     Vwr                 v;
326     extern VMethods     projP_methods;
327
328     v = vwr_create(projP_methods);
329
330     return(v);
331 }
332
333 static void
334 popdown_proj_window(
335     Widget      widget,
336     XtPointer   client_data,
337     XtPointer   call_data
338 )
339 {
340     ui_win_show(widget, False, XtGrabNone);
341 }
342
343 static void
344 create_proj_ui_handles(
345     Vwr         v
346 )
347 {
348     Widget      draw_area = NULL;
349     BrowserUiObj ui;
350
351
352     dtbProjProjMainInfo_clear(&dtb_proj_proj_main);
353
354     /*
355      * Create ui handle struct for project window
356      */
357     ui = aob_create_ui_obj();
358
359     (void)dtb_proj_proj_main_initialize(&dtb_proj_proj_main, AB_toplevel);
360     ui->shell = dtb_proj_proj_main.proj_main;
361     AB_proj_window = dtb_proj_proj_main.proj_main_mainwin;
362
363     ab_register_window(AB_proj_window, AB_WIN_WINDOW, 
364         WindowHidden, AB_toplevel, AB_WPOS_TILE_VERTICAL,
365         popdown_proj_window, NULL);
366
367     /*
368      * WORKAROUND FOR BUG
369      * Until the generated code sets XmNmenuHelpWidget properly,
370      * this is a workaround.
371      */
372     XtVaSetValues(dtb_proj_proj_main.menubar,
373         XmNmenuHelpWidget, dtb_proj_proj_main.menubar_items.Help_item,
374         NULL);
375
376     XtRealizeWidget(ui->shell);
377
378     ui->ip = (void *)&dtb_proj_proj_main;
379         
380     v->ui_handle = (void *)ui;
381
382     if (!(draw_area = brws_draw_area(v)))  
383     {
384         fprintf(stderr, "Can't find draw area widget for project\n");
385         return;
386     }
387
388     /*
389      * Set event handler on draw area for dragging/rubber banding
390      */
391     XtAddEventHandler(draw_area, 
392                 Button1MotionMask | Button2MotionMask, False,
393                 projP_drawarea_button_drag, (XtPointer)NULL);
394
395     brwsP_make_drawarea_snap(v, draw_area);
396
397     setup_vwr_graphics(v);
398
399     enable_proj_actions(draw_area);
400 }
401
402 void
403 proj_add_objects
404 (
405     AB_OBJ      *obj
406 )
407 {
408     AB_OBJ              *project;
409     Vwr                 viewer;
410     ViewerMethods       *m;
411
412     if (!Proj_viewer)
413         return;
414 /*
415         Proj_viewer = create_proj_struct();
416 */
417
418     /*
419      * Get project object
420      */
421     project = obj_get_project(obj);
422
423     viewer = Proj_viewer;
424
425     m = viewer->methods;
426     (*m->insert_tree)(viewer, obj);
427
428     /*
429      * Erase/redraw viewer
430      */
431     if (viewer->ui_handle)
432     {
433         /*
434          * Don't need to erase viewer as a new node is 
435          * added to end of the array of nodes in project window
436         erase_viewer(viewer);
437          */
438         draw_viewer(viewer);
439     }
440 }
441
442 void
443 proj_delete_objects
444 (
445     AB_OBJ      *obj
446 )
447 {
448     AB_OBJ              *project;
449     Vwr                 viewer;
450     ViewerMethods       *m;
451
452     if (!Proj_viewer)
453         return;
454
455     /*
456      * Get project object
457      */
458     project = obj_get_project(obj);
459
460     viewer = Proj_viewer;
461
462     m = viewer->methods;
463     (*m->remove_tree)(viewer, obj);
464
465     /*
466      * Erase/redraw viewer
467      */
468     if (viewer->ui_handle)
469     {
470         erase_viewer(viewer);
471         draw_viewer(viewer);
472     }
473 }
474
475 /*
476  * Register project actions with Xt
477  */
478 void
479 proj_register_actions(
480     XtAppContext app
481 )
482 {
483     XtAppAddActions(app, projwin_actions, XtNumber(projwin_actions));
484 }
485
486 /*
487  * Enable project window actions
488  */
489 static void
490 enable_proj_actions(
491     Widget widget
492 )
493 {
494     if (proj_transtbl == NULL)
495     {
496         String     translations;
497         int        len;
498
499         len = strlen(base_translations) + 1;
500
501         if (AB_btn1_transfer == True) /* Button2 can be used for ADJUST */
502             len += strlen(btn2_adjust_translations);
503
504         translations = (String)util_malloc(len*sizeof(char));
505         if (translations == NULL)
506             return; /* yikes */
507
508         strcpy(translations, base_translations);
509         if (AB_btn1_transfer == True) /* Button2 can be used for ADJUST */ 
510             strcat(translations, btn2_adjust_translations);
511
512         proj_transtbl = XtParseTranslationTable(translations);
513
514         util_free(translations);
515     }
516
517     /* enable build mode behavior */
518     XtVaSetValues(widget, 
519                 XtNtranslations, proj_transtbl,
520                 NULL);
521 }
522
523 /*
524  * Disable project window actions
525  */
526 static void
527 disable_proj_actions(
528     Widget widget
529 )
530 {
531 }
532
533 /*
534  * Action: Select module in project window
535  */
536 static void
537 select_module(
538     Widget widget, 
539     XEvent *event, 
540     String *params, 
541     int num_params
542 )
543 {
544     Vwr         v = NULL;
545     VNode       selected_node;
546     VMethods    m;
547     AB_OBJ      *obj;
548
549     XtVaGetValues(widget, XmNuserData, &v, NULL); 
550
551     if (!v)
552         return;
553
554     selected_node = vwr_locate_node(v, 
555                         event->xbutton.x, event->xbutton.y);
556     
557     if (selected_node)
558     {
559         VNode   *selected_nodes = NULL;
560         int     num_selected = 0;
561
562         if (!(m = v->methods))
563             return;
564         
565         /* USE METHODS !! */
566         obj = (AB_OBJ *)selected_node->obj_data;
567
568         if (!obj)
569             return;
570
571         /*
572          * Deselect all selected module nodes
573          * Select the module node
574          */
575         aob_deselect_all_nodes(v, TRUE);
576         proj_select(obj);
577
578         vwr_get_cond(v->current_tree, &selected_nodes, 
579                         &num_selected, select_fn);
580         
581         if (selected_nodes)
582             free((char *)selected_nodes);
583
584         update_menu_items(0, num_selected);
585     }
586 }
587
588 /*
589  * Action: Toggle select module in project window
590  */
591 static void
592 toggle_select_module(
593     Widget widget, 
594     XEvent *event, 
595     String *params, 
596     int num_params
597 )
598 {
599     Vwr         v = NULL;
600     VNode       selected_node;
601     VMethods    m;
602     AB_OBJ      *obj;
603
604     XtVaGetValues(widget, XmNuserData, &v, NULL); 
605
606     if (!v)
607         return;
608
609     selected_node = vwr_locate_node(v, 
610                         event->xbutton.x, event->xbutton.y);
611     
612     if (selected_node)
613     {
614         VNode   *selected_nodes = NULL;
615         int     num_selected = 0;
616
617         if (!(m = v->methods))
618             return;
619         
620         /* USE METHODS !! */
621         obj = (AB_OBJ *)selected_node->obj_data;
622
623         if (!obj)
624             return;
625
626         /*
627          * Toggle select the module node
628          */
629         if (BRWS_NODE_STATE_IS_SET(selected_node, BRWS_NODE_SELECTED))
630             proj_deselect(obj);
631         else
632             proj_select(obj);
633
634         vwr_get_cond(v->current_tree, &selected_nodes, 
635                         &num_selected, select_fn);
636         
637         if (selected_nodes)
638             free((char *)selected_nodes);
639
640         update_menu_items(0, num_selected);
641     }
642 }
643
644 /*
645  * Action: Show the module when double-clicked on.
646  */
647 static void
648 show_module(
649     Widget widget, 
650     XEvent *event, 
651     String *params, 
652     int num_params
653 )
654 {
655     Vwr         v = NULL;
656     VNode       selected_node;
657     VMethods    m;
658     ABObj       obj;
659     ABObj       winobj;
660     AB_TRAVERSAL trav;
661  
662     XtVaGetValues(widget, XmNuserData, &v, NULL);
663
664     if (!v)
665         return;
666
667     selected_node = vwr_locate_node(v,
668                         event->xbutton.x, event->xbutton.y);
669
670     if (selected_node)
671     {
672         VNode   *selected_nodes = NULL;
673         int     num_selected = 0;
674  
675         if (!(m = v->methods))
676             return;
677
678         /* USE METHODS !! */
679         obj = (ABObj) selected_node->obj_data;
680  
681         if (!obj)
682             return;
683
684         /*
685          * Set busy cursor before this potentially
686          * lengthy operation
687          */
688         ab_set_busy_cursor(TRUE);
689
690         /* If the module is already showing, then
691          * make all of its windows come to the fore-
692          * ground.
693          */
694         if (obj_has_flag(obj, MappedFlag))
695         {
696             for (trav_open(&trav, obj, AB_TRAV_WINDOWS);
697                 (winobj = trav_next(&trav)) != NULL; )
698             {
699                 if (obj_has_flag(winobj, MappedFlag))
700                     ui_win_front(objxm_get_widget(winobj));
701             }
702             trav_close(&trav);
703             proj_set_cur_module(obj);
704         }    
705         else if( abobj_show_tree(obj, TRUE) == -1 )
706         {
707            if (util_get_verbosity() > 0)
708              fprintf(stderr,"show_module: error in abobj_show_tree\n");
709         }
710         else 
711         {
712             proj_set_cur_module(obj);
713         }
714
715         vwr_get_cond(v->current_tree, &selected_nodes,
716                         &num_selected, select_fn);
717
718         if (selected_nodes)                        
719             free((char *)selected_nodes);
720  
721         update_menu_items(0, num_selected);
722
723         /*
724          * Unset busy cursor
725          */
726         ab_set_busy_cursor(FALSE);
727
728     }
729 }
730
731 static int
732 select_fn(
733     VNode       module
734 )
735 {
736     if (BRWS_NODE_STATE_IS_SET(module, BRWS_NODE_SELECTED))
737         return (1);
738
739     return (0);
740 }
741
742 static int
743 project_select_rband(
744     VNode       vnode
745 )
746 {
747
748     if (!vnode || !rband_rect)
749         return (0);
750
751     if (((int)rband_rect->x <= vnode->x) && 
752         ((int)(rband_rect->x + (short)rband_rect->width) >= (vnode->x + vnode->width)) &&
753         ((int)rband_rect->y <= vnode->y) &&
754         ((int)(rband_rect->y + (short)rband_rect->height) >= vnode->y + vnode->height))
755         return (1);
756                  
757     return (0);
758 }
759
760 /*
761  * Update the sensitivity of menu items depending on
762  * the old/new count of modules selected.
763  * 
764  * NOTE: Currently, this proc does not use the old_count 
765  * param. It will, in future use it for optimization.
766  */
767 static void
768 update_menu_items(
769     int         old_count,
770     int         new_count
771 )
772 {
773     if (new_count == 0)
774     {
775         no_module_selected(&dtb_proj_proj_main);
776         return;
777     }
778
779     if (new_count == 1)
780     {
781         one_module_selected(&dtb_proj_proj_main);
782         return;
783     }
784
785     mult_module_selected(&dtb_proj_proj_main);
786 }
787
788 /*
789  * no_module_selected()
790  * No module is currently selected, so desensitize all
791  * relevant menu items
792  */
793 static void
794 no_module_selected(
795     DtbProjProjMainInfo proj_w
796 )
797 {
798     ProjModMenubuttonMenuItems  menu_rec;
799
800     if (!proj_w)
801         return;
802     
803     menu_rec = &(proj_w->menubar_Module_item_mod_menubutton_menu_items);
804
805     ui_set_active(menu_rec->Save_item, FALSE);
806     ui_set_active(menu_rec->Save_As_item, FALSE);
807     ui_set_active(menu_rec->Show_item, FALSE);
808     ui_set_active(menu_rec->Hide_item, FALSE);
809     ui_set_active(menu_rec->Browse_item, FALSE);
810     ui_set_active(menu_rec->Export_item, FALSE);
811     ui_set_active(menu_rec->Remove_item, FALSE);
812 }
813
814 /*
815  * one_module_selected()
816  * One module is currently selected, so make all
817  * menu items sensitive
818  */
819 static void
820 one_module_selected(
821     DtbProjProjMainInfo proj_w
822 )
823 {
824     ProjModMenubuttonMenuItems  menu_rec;
825     ChooserInfo                 info = NULL;
826
827     if (!proj_w) return;
828     
829     menu_rec = &(proj_w->menubar_Module_item_mod_menubutton_menu_items);
830
831     ui_set_active(menu_rec->Show_item, TRUE);
832     ui_set_active(menu_rec->Hide_item, TRUE);
833     ui_set_active(menu_rec->Browse_item, TRUE);
834     ui_set_active(menu_rec->Remove_item, TRUE);
835
836     /* If the FSB has not been created yet or if it has
837      * been created but it is not displayed, then make
838      * the menu items active.
839      */
840     if ((AB_generic_chooser == NULL) ||
841         !XtIsManaged(AB_generic_chooser))
842     {
843         ui_set_active(menu_rec->Save_item, TRUE);
844         ui_set_active(menu_rec->Save_As_item, TRUE);
845         ui_set_active(menu_rec->Import_item, TRUE);
846         ui_set_active(menu_rec->Export_item, TRUE);
847     }
848     else if (XtIsManaged(AB_generic_chooser))
849     {
850         XtVaGetValues(AB_generic_chooser, XmNuserData, &info, NULL);
851         if (info->chooser_type == AB_EXPORT_CHOOSER)
852         {
853             ui_set_active(menu_rec->Export_item, TRUE);
854         }
855         else if (info->chooser_type == AB_SAVE_PROJ_AS_CHOOSER)
856         {
857             ui_set_active(menu_rec->Save_item, TRUE);
858             ui_set_active(menu_rec->Save_As_item, TRUE);
859         }
860         else if (info->chooser_type == AB_IMPORT_CHOOSER)
861         {
862             ui_set_active(menu_rec->Import_item, TRUE);
863         }
864     }
865 }
866
867 /*
868  * mult_module_selected()
869  * Multiple modules are currently selected.
870  * We desensitize the Save/Save As/Export buttons
871  * because the choossers cannot handle multiple 
872  * saves at the moment...
873  */
874 static void
875 mult_module_selected(
876     DtbProjProjMainInfo proj_w
877 )
878 {
879     ProjModMenubuttonMenuItems  menu_rec;
880
881     if (!proj_w)
882         return;
883     
884     menu_rec = &(proj_w->menubar_Module_item_mod_menubutton_menu_items);
885
886     ui_set_active(menu_rec->Save_item, FALSE);
887     ui_set_active(menu_rec->Save_As_item, FALSE);
888     ui_set_active(menu_rec->Export_item, FALSE);
889     ui_set_active(menu_rec->Show_item, TRUE);
890     ui_set_active(menu_rec->Hide_item, TRUE);
891     ui_set_active(menu_rec->Browse_item, TRUE);
892     ui_set_active(menu_rec->Remove_item, TRUE);
893 }
894
895 int
896 proj_init(
897 )
898 {
899     obj_add_rename_callback(projP_obj_renameOCB, "PROJ");
900     obj_add_destroy_callback(projP_obj_destroyOCB, "PROJ");
901     obj_add_update_callback(projP_obj_updateOCB, "PROJ");
902
903     AB_project = obj_create(AB_TYPE_PROJECT, NULL);
904     obj_set_name(AB_project, "project");
905     abobj_show_tree(AB_project, TRUE);
906
907     return 0;
908 }
909
910 /* This destroys the current project and creates
911  * a new default project named "project" since
912  * dtbuilder can never have a NULL project.
913  */
914 int
915 proj_destroy_project(
916     ABObj       proj
917 )
918 {
919     obj_set_flag(proj, BeingDestroyedFlag);
920     obj_destroy(proj);
921     proj_create_new_proj(NULL);
922     return OK;
923 }
924
925 int
926 proj_set_project(
927     ABObj       proj
928 )
929 {
930     if (proj != NULL)
931     {
932         /*
933          * Update project window and browsers
934          */
935         AB_project = proj;
936
937         /* Initialize the current module to NULL,
938          * since no modules are showing yet.
939          */
940         proj_set_cur_module(NULL);
941
942         cgen_notify_new_project(AB_project);
943         appfw_notify_new_project(AB_project);
944
945         return OK;
946     }
947     return -1;
948 }
949
950 ABObj
951 proj_get_project(
952 )
953 {
954     return AB_project;
955 }
956
957 int
958 proj_set_cur_module(
959     ABObj       module
960 )
961 {
962     if ( (module != NULL) && (obj_get_type(module) != AB_TYPE_MODULE) )
963         return -1;
964
965     AB_cur_module = module;
966     if (module != NULL)
967         ab_update_stat_region(AB_STATUS_CUR_MODULE, obj_get_name(module));
968     else
969         ab_update_stat_region(AB_STATUS_CUR_MODULE, NULL);
970         
971     return OK;
972 }
973
974 ABObj
975 proj_get_cur_module(
976 )
977 {
978     return AB_cur_module;
979 }
980
981 int
982 proj_rename_module(
983     ABObj    module,
984     STRING   name
985 )
986 {
987     if ( !obj_is_module(module) )
988         return -1;
989
990     abobj_set_name(module, name);
991
992     if (abobj_update_module_name(module) == -1)
993         return -1;
994
995     /* Update the browser */
996     brws_update_node(module);
997
998     /* Update the project window */
999     proj_update_node(module);
1000
1001     if (module == proj_get_cur_module())
1002     {
1003         if (ab_update_stat_region(AB_STATUS_CUR_MODULE, name) == -1)
1004             return -1;
1005     }
1006     return 0;
1007 }
1008
1009 /*
1010  * Action: Update "Module Path:" in the project window
1011  *         whenever the user moves the pointer over a
1012  *         module icon.
1013  */
1014 static void
1015 pointer_motion_proc(
1016     Widget widget, 
1017     XEvent *event, 
1018     String *params, 
1019     int num_params
1020 )
1021 {
1022     Vwr                 v = NULL;
1023     VNode               node_under_pointer = NULL;
1024     ABObj               obj = NULL;
1025     XMotionEvent        *mevent = (XMotionEvent*)event;
1026     char                mod_path[MAXPATHLEN] = "";
1027
1028     util_dprintf(2, "pointer_motion_proc:\n");
1029     XtVaGetValues(widget, XmNuserData, &v, NULL); 
1030
1031     if (!v)
1032         return;
1033
1034     node_under_pointer = vwr_locate_node(v, 
1035                         mevent->x, mevent->y);
1036     if (node_under_pointer != NULL)
1037     {
1038         /* USE METHODS !! */
1039         obj = (AB_OBJ *)node_under_pointer->obj_data;
1040         
1041         if (!obj)
1042             return;
1043
1044         util_dprintf(2, "\tmodule name is %s\n", obj_get_name(obj));
1045
1046         /* If the module has not been saved, file will be NULL */
1047         if (obj_get_file(obj) != NULL)
1048         {
1049             util_get_dir_name_from_path(obj_get_file(obj), mod_path,
1050                         MAXPATHLEN);
1051         }
1052         else
1053         {
1054             strcpy(mod_path, ".");
1055         }
1056
1057         util_dprintf(2, "\tmodule path is %s\n", mod_path);
1058
1059         if (!util_strempty(mod_path))
1060         {
1061             util_dprintf(2, "\tupdating the project window status region\n");
1062             proj_update_stat_region(PROJ_STATUS_MOD_PATH, mod_path);
1063         }
1064     }
1065     else
1066     {
1067         /* If we're not over a node, clear out the module
1068          * path status label in the project window.
1069          */
1070         util_dprintf(2, "\tpointer is not positioned over a node\n");
1071         proj_update_stat_region(PROJ_STATUS_MOD_PATH, NULL);
1072     }
1073 }
1074
1075
1076 static void
1077 import_uil(
1078     STRING      uil_file_name
1079 )
1080 {
1081     ABObj       project = proj_get_project();
1082     ABObjPtr    uil_interface;
1083  
1084     if ((uil_interface = abuil_get_uil_file(uil_file_name, project))
1085             == (ABObjPtr) NULL)
1086     {
1087         fprintf(stderr, "Failed to import %s.\n", uil_file_name);
1088         return;
1089     }
1090     else
1091         fprintf(stderr, "Successfully imported %s.\n", uil_file_name);
1092  
1093     obj_set_flag(project, SaveNeededFlag);
1094  
1095     /*
1096      * Realize the tree
1097      */
1098     abobj_show_tree(uil_interface, TRUE);
1099     abobj_set_save_needed(project, TRUE);
1100 }
1101
1102 void
1103 proj_open_proj_okCB(
1104     Widget      widget,
1105     XtPointer   client_data,
1106     XmSelectionBoxCallbackStruct *call_data
1107 )
1108 {
1109     STRING              proj_filename = (STRING) NULL;
1110     XmString            xm_buf = (XmString) NULL;
1111     DtbObjectHelpData   help_data = NULL;
1112
1113     proj_filename = (STRING)objxm_xmstr_to_str(call_data->value);
1114
1115     /* If the file chooser selection text field is empty, return */
1116     if ( util_strempty(proj_filename) )
1117     {
1118         dtb_proj_no_name_msg_initialize(&dtb_proj_no_name_msg);
1119         (void)dtb_show_modal_message(widget,
1120                         &dtb_proj_no_name_msg, NULL, NULL, NULL);
1121     }
1122     else if (!util_file_exists(proj_filename))
1123     {
1124         sprintf(Buf, catgets(Dtb_project_catd, 100, 8,
1125                 "The file %s does not exist."), proj_filename);
1126         util_printf_err(Buf);
1127     }
1128     else if (!util_file_is_regular_file(proj_filename))
1129     {
1130         sprintf(Buf, catgets(Dtb_project_catd, 100, 69,
1131                 "Cannot open %s.\n%s is not a regular file."),
1132                 proj_filename, proj_filename);
1133         xm_buf = XmStringCreateLocalized(Buf);
1134         dtb_proj_error_msg_initialize(&dtb_proj_error_msg);
1135
1136         help_data = (DtbObjectHelpData) util_malloc(sizeof(DtbObjectHelpDataRec));
1137         help_data->help_text = catgets(Dtb_project_catd, 100, 89,
1138             "The file you specified is a directory or\nanother special file.");
1139         help_data->help_volume = "";
1140         help_data->help_locationID = "";
1141
1142         (void)dtb_show_modal_message(widget,
1143                         &dtb_proj_error_msg, xm_buf, help_data, NULL);
1144
1145         util_free(help_data);
1146         XmStringFree(xm_buf);
1147     }
1148     else
1149     {   
1150         XtUnmanageChild(widget);        /* pop down the chooser */
1151         ab_check_and_open_bip(proj_filename); 
1152     }    
1153 }
1154
1155 void
1156 proj_cancelCB(
1157     Widget              widget,
1158     XtPointer           client_data,
1159     XmSelectionBoxCallbackStruct *call_data
1160 )
1161 {
1162     /* Pop down the file chooser.  This must be done
1163      * explicitly because the file chooser autoUnmanage
1164      * resource was set to FALSE.
1165      */
1166     XtUnmanageChild(widget);
1167 }
1168
1169
1170 void
1171 proj_import_okCB(
1172     Widget                              widget,
1173     XtPointer                           client_data,
1174     XmSelectionBoxCallbackStruct        *call_data
1175 )
1176 {
1177     STRING      file_name = (STRING) NULL;
1178     XmString    xm_buf = (XmString) NULL;
1179     BOOL        read_OK, write_OK;
1180     DtbObjectHelpData   help_data = NULL;
1181
1182     if (call_data->reason != XmCR_OK)
1183     {
1184         return;
1185     }
1186
1187     file_name = (STRING)objxm_xmstr_to_str(call_data->value);
1188
1189     /* If the file chooser selection text field is empty,
1190      * return, leaving the chooser up to give the user 
1191      * another try.
1192      */
1193     if (util_strempty(file_name))
1194     {
1195         dtb_proj_no_name_msg_initialize(&dtb_proj_no_name_msg);
1196         (void)dtb_show_modal_message(widget,
1197                         &dtb_proj_no_name_msg, NULL, NULL, NULL);
1198     }
1199     else if (!util_file_exists(file_name))
1200     {
1201         /* If the file specified does not exist, keep up the file
1202          * chooser so that the user can specify another file.
1203          */
1204         sprintf(Buf, catgets(Dtb_project_catd, 100, 8,
1205                 "The file %s does not exist."), file_name);
1206         util_printf_err(Buf);
1207     }
1208     else if (!util_file_is_regular_file(file_name))
1209     {
1210         sprintf(Buf, catgets(Dtb_project_catd, 100, 70,
1211                 "Cannot import %s.\n%s is not a regular file."),
1212                 file_name, file_name);
1213         xm_buf = XmStringCreateLocalized(Buf);
1214         dtb_proj_error_msg_initialize(&dtb_proj_error_msg);
1215
1216         help_data = (DtbObjectHelpData) util_malloc(sizeof(DtbObjectHelpDataRec));
1217         help_data->help_text = catgets(Dtb_project_catd, 100, 89, 
1218             "The file you specified is a directory or\nanother special file.");
1219         help_data->help_volume = ""; 
1220         help_data->help_locationID = ""; 
1221  
1222         (void)dtb_show_modal_message(widget,
1223                         &dtb_proj_error_msg, xm_buf, help_data, NULL);
1224
1225         util_free(help_data);
1226         XmStringFree(xm_buf);
1227     }
1228     else
1229     {
1230         ChooserInfo     info = NULL;
1231
1232         XtVaGetValues(AB_generic_chooser,
1233                         XmNuserData, &info,
1234                         NULL);
1235         
1236         if (info->ImportAsBil)
1237         {
1238             /* Pop down the file chooser */
1239             XtUnmanageChild(widget);
1240             ab_check_and_import_bil(file_name, info->ImportByCopy);
1241         }
1242         else    /* Import as UIL */
1243         {
1244             abio_access_file(file_name, &read_OK, &write_OK);
1245             if (read_OK)
1246             {
1247                 /* Pop down the file chooser */
1248                 XtUnmanageChild(widget);
1249                 import_uil(file_name);
1250             }
1251             else
1252             {
1253                 sprintf(Buf, catgets(Dtb_project_catd, 100, 9,
1254                         "%s does not have read permission."),
1255                         file_name);
1256                 util_printf_err(Buf);
1257             }
1258         }
1259     }
1260 }
1261
1262 /*
1263  * Object rename callback
1264  * Update project organizer when module is renamed.
1265  */
1266 static int
1267 projP_obj_renameOCB(
1268     ObjEvAttChangeInfo    info
1269 )
1270 {
1271     ABObj       obj = info->obj;
1272     char        *name;
1273
1274     /*
1275      * We only care about modules and projects here
1276      */
1277     if (!obj || (!obj_is_module(obj) && !obj_is_project(obj)))
1278         return (0);
1279
1280     /*
1281      * Update the module name only if the old name is not NULL.
1282      *
1283      * If the old name is NULL that means this is a new object.
1284      * and we let the update callback handle that.
1285      */
1286     if (info->old_name != NULL)
1287         proj_update_node(obj);
1288
1289
1290     return (0);
1291 }
1292
1293 /*
1294  * Object destroy callback
1295  * Remove viewer nodes from project organizer when module is destroyed.
1296  */
1297 static int
1298 projP_obj_destroyOCB(
1299     ObjEvDestroyInfo    info
1300 )
1301 {
1302     ABObj       obj = info->obj;
1303
1304     if (!obj || (!obj_is_module(obj) && !obj_is_project(obj)))
1305         return (0);
1306
1307     if (obj->projwin_data)
1308     {
1309         ABObj   proj = obj_get_project(obj);
1310
1311         if (!proj)
1312             return (0);
1313
1314         /*
1315          * If the project is being destroyed, skip if the object passed in is
1316          * not the project itself. We do this so that proj_delete_objects() is
1317          * not called for every module in the project. Instead, it is called
1318          * just once for the project.
1319          */
1320         if (obj_has_flag(proj, BeingDestroyedFlag) && !obj_is_project(obj))
1321             return (0);
1322
1323         proj_delete_objects(obj);
1324     }
1325
1326     return (0);
1327 }
1328
1329 /*
1330  * projP_obj_updateOCB
1331  * Update project organizer when new modules are added
1332  */
1333 static int
1334 projP_obj_updateOCB(
1335     ObjEvUpdateInfo     info
1336 )
1337 {
1338     ABObj       obj = info->obj;
1339
1340
1341     /*
1342      * We should only care about modules and projects
1343      * here.
1344      */
1345     if (!obj || (!obj_is_module(obj) && !obj_is_project(obj)))
1346         return (0);
1347
1348     proj_add_objects(obj);
1349
1350     return (0);
1351 }
1352
1353 /*
1354  * Action: mouse button down on browser
1355  */
1356 static void
1357 project_bpress(
1358     Widget widget, 
1359     XEvent *event, 
1360     String *params, 
1361     int num_params
1362 )
1363 {
1364     XButtonEvent        *bevent;
1365
1366     if (event->type == ButtonPress)
1367     {
1368         bevent = (XButtonEvent*)event;
1369
1370         if (bevent->state == 0 && bevent->button == 1)/* RUBBERBAND SELECT */
1371         {
1372             if (ui_initiate_rubberband(widget, True, 
1373                         project_rband, (XtPointer)NULL) == ERROR)
1374             {
1375                 if (util_get_verbosity() > 0)
1376                     fprintf(stderr,"project organizer: couldn't begin rubberbanding\n");
1377             }
1378             else
1379                 mselect_adjust = False;
1380         }
1381         else if (bevent->button == 2 || /* RUBBERBAND ADJUST SELECT */
1382                  (bevent->button == 1 && (bevent->state & ShiftMask)))
1383         {
1384             if (ui_initiate_rubberband(widget, True, 
1385                         project_rband, (XtPointer)NULL) == ERROR)
1386             {
1387                 if (util_get_verbosity() > 0)
1388                     fprintf(stderr,"project organizer: couldn't begin rubberbanding\n");
1389             }
1390             else
1391                 mselect_adjust = True;
1392         }
1393     }
1394 }
1395
1396 /*
1397  * EventHandler: project organizer draw area drag action ...
1398  */
1399 static void
1400 projP_drawarea_button_drag(
1401     Widget widget,
1402     XtPointer client_data,
1403     XEvent *event,
1404     Boolean *cont_dispatch
1405 )
1406 {
1407     if (event->type == MotionNotify)
1408     {
1409         if (((XMotionEvent*)event)->state & Button1Mask) /* RUBBERBAND SELECT */
1410         {
1411             ui_button_drag(widget, event, client_data);
1412         }
1413         else if (((XMotionEvent*)event)->state & Button2Mask) /* RUBBERBAND ADJUST */
1414         {
1415             ui_button_drag(widget, event, client_data);
1416         }
1417     }
1418 }
1419
1420
1421 static void
1422 project_rband(
1423     Widget      widget,
1424     XEvent      *event,
1425     XRectangle  *rb_rect,
1426     XtPointer   client_data
1427 )
1428 {
1429     Vwr         v = NULL;
1430     VNode       *selected_nodes = NULL;
1431     VMethods    m;
1432     ABSelectedRec       old_sel, 
1433                         new_sel;
1434     XRectangle  tmp_rect;
1435     int         num_selected = 0,
1436                 num_cur_selected = 0,
1437                 i;
1438
1439     XtVaGetValues(widget, XmNuserData, &v, NULL); 
1440
1441     if (!v)
1442         return;
1443
1444     if (!(m = v->methods))
1445         return;
1446     
1447     /* If rubberband was drawn from lower-right to upper-left,
1448      * translate rect so that x,y is upper-left point in rectangle.
1449      */
1450     if (rect_right(rb_rect) < rb_rect->x ||
1451         rect_bottom(rb_rect) < rb_rect->y)
1452     {
1453         tmp_rect.x = rect_right(rb_rect);
1454         tmp_rect.y = rect_bottom(rb_rect);
1455         tmp_rect.width = rb_rect->x - tmp_rect.x;
1456         tmp_rect.height = rb_rect->y - tmp_rect.y;
1457         rb_rect = &tmp_rect;
1458     }
1459
1460     /*
1461      * Important: set rband_rect so that
1462      * the function 'project_select_rband' can see it.
1463      */
1464     rband_rect = rb_rect;
1465
1466     /*
1467      * Get list of currently selected modules in project
1468      * organizer
1469      */
1470     vwr_get_cond(v->current_tree, &selected_nodes, 
1471                         &num_selected, select_fn);
1472
1473     if (mselect_adjust)
1474         /*
1475          * If select adjust, remember how many modules are currently
1476          * selected
1477          */
1478         num_cur_selected = num_selected;
1479     else
1480     {
1481         /*
1482          * If not select adjust, the current select count is reset
1483          */
1484         num_cur_selected = 0;
1485
1486         /*
1487          * Deselect all currently selected nodes
1488          */
1489         for (i=0; i < num_selected; ++i)
1490         {
1491             ABObj       obj;
1492
1493             /*
1494              * Get ABObj
1495              */
1496             obj = (ABObj)selected_nodes[i]->obj_data;
1497
1498             if (!obj)
1499                 continue;
1500
1501             proj_deselect(obj);
1502         }
1503     }
1504
1505     /*
1506      * Free up node list if it contained anything
1507      */
1508     if (selected_nodes)
1509         util_free(selected_nodes);
1510
1511     /*
1512      * Get nodes in browser that are within the
1513      * rubber band rectangle.
1514      */
1515     vwr_get_cond(v->current_tree, &selected_nodes, 
1516                         &num_selected, project_select_rband);
1517     
1518     /*
1519      * Update (activate/deactivate) project organizer menu items
1520      */
1521     update_menu_items(0, num_cur_selected + num_selected);
1522
1523     /*
1524      * Return if no selected nodes
1525      */
1526     if (num_selected == 0) {
1527         free(selected_nodes);
1528         return;
1529     }
1530
1531     /*
1532      * For each object enclosed in rubber band rectangle
1533      */
1534     for (i=0; i < num_selected; ++i)
1535     {
1536         ABObj   obj;
1537         int     j;
1538
1539         /*
1540          * Get ABObj
1541          */
1542         obj = (ABObj)selected_nodes[i]->obj_data;
1543
1544         if (!obj)
1545             continue;
1546
1547         proj_select(obj);
1548     }
1549
1550     /*
1551      * Unset rband_rect
1552      */
1553     rband_rect = NULL;
1554
1555     /*
1556      * Free up node list if it contained anything
1557      */
1558     if (selected_nodes)
1559         util_free(selected_nodes);
1560 }
1561
1562 void
1563 proj_unmap_chooserCB(
1564     Widget      chooser,
1565     XtPointer   clientData,
1566     XtPointer   callData
1567 )
1568 {
1569     ChooserInfo info = NULL;
1570
1571     XtVaGetValues(AB_generic_chooser, XmNuserData, &info, NULL);
1572
1573     /* Destroy the "extra" file chooser child if one
1574      * exists (i.e. Save Project As, Import Module, etc.)
1575      */
1576     if (info->child != NULL)
1577     {
1578         XtDestroyWidget(info->child);
1579     }
1580
1581     /* Set the appropriate File menu items and Project
1582      * Organizer Project and Module menu items active.
1583      */
1584     pal_set_File_menu(info->chooser_type, TRUE);
1585     proj_set_menus(info->chooser_type, TRUE);
1586 }