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