1 /*****************************************************************************
2    Major portions of this software are copyrighted by the Medical College
3    of Wisconsin, 1994-2000, and are released under the Gnu General Public
4    License, Version 2.  See the file README.Copyright for details.
5 ******************************************************************************/
6 
7 #undef MAIN
8 #include "afni.h"
9 #include <ctype.h>
10 
11 #ifndef ALLOW_PLUGINS
12 #  error "Plugins not properly set up -- see machdep.h"
13 #endif
14 
15 /*-- prototypes --*/
16 
17 static char * TAG_main( PLUGIN_interface * ) ;
18 
19 static void TAG_make_widgets(void) ;
20 
21 static void TAG_dset_CB    ( Widget , XtPointer , XtPointer ) ;
22 static void TAG_quit_CB    ( Widget , XtPointer , XtPointer ) ;
23 static void TAG_help_CB    ( Widget , XtPointer , XtPointer ) ;
24 static void TAG_set_CB     ( Widget , XtPointer , XtPointer ) ;
25 static void TAG_clear_CB   ( Widget , XtPointer , XtPointer ) ;
26 static void TAG_done_CB    ( Widget , XtPointer , XtPointer ) ;
27 static void TAG_tog_CB     ( Widget , XtPointer , XtPointer ) ;
28 static void TAG_read_CB    ( Widget , XtPointer , XtPointer ) ;
29 static void TAG_write_CB   ( Widget , XtPointer , XtPointer ) ;
30 static void TAG_copy_CB    ( Widget , XtPointer , XtPointer ) ;
31 static void TAG_save_CB    ( Widget , XtPointer , XtPointer ) ;
32 static void TAG_clearall_CB( Widget , XtPointer , XtPointer ) ;
33 static void TAG_add_CB     ( Widget , XtPointer , XtPointer ) ;
34 static void TAG_delete_CB  ( Widget , XtPointer , XtPointer ) ;
35 static void TAG_relabel_CB ( Widget , XtPointer , XtPointer ) ;
36 static void TAG_beep_CB    ( Widget , XtPointer , XtPointer ) ;
37 
38 static void TAG_value_CB ( MCW_arrowval * , XtPointer ) ;
39 static void TAG_columnize(void) ;
40 static void TAG_reset_widgets(void) ;
41 
42 static void TAG_onoff( int ) ;
43 
44 /*-- Widgets for the user interface --*/
45 
46 static Widget shell=NULL , thetop ;
47 static Widget dset_pb , info_lab ;
48 static Widget quit_pb, help_pb, read_pb, write_pb, copy_pb, save_pb, done_pb ;
49 static Widget set_pb, clear_pb, clearall_pb, add_pb, delete_pb, relabel_pb, beep_pb ;
50 static Widget scrollw, wframe, workwin ;
51 static Widget actar ;
52 
53 static Widget * tagtog ;      /* one for each possible tag */
54 static int    * toginv ;
55 static int      tognum = 4 ;  /* default number of active toggles */
56 
57 static THD_usertaglist * mytagset  = NULL ;  /* what we are working on */
58 static THD_usertaglist * oldtagset = NULL ;  /* in case of Quit */
59 
60 static PLUGIN_strval * file_strav ;
61 static PLUGIN_strval * label_strav ;
62 static MCW_arrowval  * value_av ;
63 
64 #define DEFAULT_INFOLAB "[No dataset has yet been selected]"
65 
66 static int      on_flag = 0 ;
67 static Widget * onoff_wid[] = {
68    &read_pb , &write_pb , &copy_pb     , &save_pb , &done_pb   ,
69    &set_pb  , &clear_pb , &clearall_pb ,
70    NULL } ;
71 
72 #define DSET_ON  SENSITIZE(dset_pb,True)
73 #define DSET_OFF do{ if( dset != NULL ) SENSITIZE(dset_pb,False) ; } while(0)
74 
75 #define POPUP_MESG(mm) MCW_popup_message(save_pb,(mm),MCW_USER_KILL|MCW_TIMER_KILL)
76 
77 /*-- Other Data --*/
78 
79 static PLUGIN_interface * plint = NULL ;
80 
81 static int   value_int   = 0 ;    /* from value_av */
82 static float value_float = 0.0 ;  /* ditto         */
83 static int   active_tog  = -1 ;   /* active toggle index */
84 
85 static int   editor_open = 0 ;    /* is the editor already on screen? */
86 
87 static MCW_DC * dc ;
88 static Three_D_View * im3d ;
89 static THD_3dim_dataset * dset = NULL ;
90 
91 /***********************************************************************
92    Set up the interface to the user.  Note that we bypass the
93    normal interface creation, and simply have the menu selection
94    directly call the main function, which will create a custom
95    set of interface widgets.
96 ************************************************************************/
97 
98 
99 DEFINE_PLUGIN_PROTOTYPE
100 
PLUGIN_init(int ncall)101 PLUGIN_interface * PLUGIN_init( int ncall )
102 {
103    if( ncall > 0 ) return NULL ;  /* only one interface */
104 
105    plint = PLUTO_new_interface( "Edit Tagset" , NULL , NULL ,
106                                 PLUGIN_CALL_IMMEDIATELY , TAG_main ) ;
107 
108    PLUTO_add_hint( plint , "Interactive Tagset Editor" ) ;
109 
110    PLUTO_set_sequence( plint , "A:misc" ) ;
111    return plint ;
112 }
113 
114 /*--------------------------------------------------------------------------*/
115 
TAG_main(PLUGIN_interface * plint)116 static char * TAG_main( PLUGIN_interface * plint )
117 {
118    int ii ;
119    XmString xstr ;
120 
121    /*-- sanity checks --*/
122 
123    if( ! IM3D_OPEN(plint->im3d) ) return "AFNI Controller\nnot opened?!" ;
124 
125    if( editor_open ){
126       XtMapWidget(shell) ;
127       XRaiseWindow( XtDisplay(shell) , XtWindow(shell) ) ;
128       return NULL ;
129    }
130 
131    im3d = plint->im3d ;  /* save for local use */
132 
133    /*-- create widgets, first time through --*/
134 
135    if( shell == NULL ){
136       dc = im3d->dc ;        /* save this too */
137       if( mytagset  == NULL ) mytagset  = myXtNew(THD_usertaglist) ;
138       if( oldtagset == NULL ) oldtagset = myXtNew(THD_usertaglist) ;
139       TAG_make_widgets() ;
140       PLUTO_set_topshell( plint , shell ) ;  /* 22 Sep 2000 */
141       RWC_visibilize_widget( shell ) ;       /* 27 Sep 2000 */
142    }
143 
144    /*-- set titlebar --*/
145 
146    { char ttl[PLUGIN_STRING_SIZE] ;
147      sprintf( ttl , "Tagset Editor %s" , AFNI_controller_label(im3d) ) ;
148      XtVaSetValues( shell , XmNtitle , ttl , NULL ) ;
149    }
150 
151    /*-- reset the info label --*/
152 
153    xstr = XmStringCreateLtoR( DEFAULT_INFOLAB , XmFONTLIST_DEFAULT_TAG ) ;
154    XtVaSetValues( info_lab , XmNlabelString , xstr , NULL ) ;
155    XmStringFree(xstr) ;
156 
157    /*-- pop the widgets up --*/
158 
159    TAG_onoff(0) ;                 /* widgets off until a dataset is selected */
160    DSET_ON ;
161    SENSITIZE(beep_pb,True) ;
162    tognum = mytagset->num ;
163    TAG_reset_widgets() ;
164 
165    XtMapWidget(shell) ;
166    PLUTO_cursorize(shell) ;
167 
168    /*-- misc initialization --*/
169 
170    dset         = NULL ;   /* not editing anything   */
171    editor_open  = 1 ;      /* editor is now open for business */
172 
173    active_tog = -1 ;
174    for( ii=0 ; ii < tognum ; ii++ ){
175       if( XmToggleButtonGetState( tagtog[ii] ) ){ active_tog = ii; break; }
176    }
177 
178    oldtagset->num = 0 ;
179    return NULL ;
180 }
181 
182 /*--------------------------------------------------------------------------
183      Make the plugin user interface
184 ----------------------------------------------------------------------------*/
185 
186 /*-- structures defining 1st set of action buttons --*/
187 
188 #define NACT1 7  /* number of action buttons */
189 
190 static MCW_action_item TAG_actor1[NACT1] = {
191  {"Quit",TAG_quit_CB,NULL,
192   "Discard changes\nand close Tag plugin" ,
193    "Discard changes & close",0} ,
194 
195  {"Help",TAG_help_CB,NULL,
196   "Displays more help" , "Displays more help",0} ,
197 
198  {"Read",TAG_read_CB,NULL,
199   "Read a tagset from disk" , "Read tagset from disk",0} ,
200 
201  {"Write",TAG_write_CB,NULL,
202   "Write the tagset to disk" , "Write tagset to disk",0} ,
203 
204  {"Copy",TAG_copy_CB,NULL,
205   "Copy tagset from another dataset" , "Copy from another dataset",0} ,
206 
207  {"Save",TAG_save_CB,NULL,
208   "Save tagset in dataset header" , "Save tagset in dataset header",0} ,
209 
210  {"Done",TAG_done_CB,NULL,
211   "Save changes in dataset\nand close Tag plugin" , "Save and close",1}
212 } ;
213 
214 /*-- structures defining 2nd set of action buttons --*/
215 
216 #define NACT2 7  /* number of action buttons */
217 
218 static MCW_action_item TAG_actor2[NACT2] = {
219 
220  {"Set",TAG_set_CB,NULL,
221   "Set the selected tag at the\ncurrent crosshair location" ,
222   "Sets selected tag" , 0 } ,
223 
224  {"Clear",TAG_clear_CB,NULL,
225   "Clears the selected tag\n(opposite of Set)" ,
226   "Clears selected tag" , 0 } ,
227 
228  {"Clr All",TAG_clearall_CB,NULL,
229   "Clears all tags (opposite of Set)" ,
230   "Clears all tags" , 0 } ,
231 
232  {"Add",TAG_add_CB,NULL,
233   "Add a new tag at\nthe end of list" ,
234   "Add new tag at end" , 0 } ,
235 
236  {"Delete",TAG_delete_CB,NULL,
237   "Remove the last\ntag from the list" ,
238   "Remove last tag" , 0 } ,
239 
240  {"Relabel",TAG_relabel_CB,NULL,
241   "Changes label of selected tag;\nUse after editing Tag Label\nstring field below",
242   "Changes label of selected tag", 0 } ,
243 
244  {"Beep",TAG_beep_CB,NULL, NULL , NULL , 0 }
245 } ;
246 
247 /*--------------------------------------------------------------------------*/
248 
TAG_make_widgets(void)249 static void TAG_make_widgets(void)
250 {
251    XmString xstr ;
252    char tlab[MAX_TAG_LABEL] ;
253    int ii , ww , hh ;
254    Pixel  fg_pix=0 ;
255    Widget wjunk ;
256 
257    /*** top level shell for window manager ***/
258 
259    shell =
260       XtVaAppCreateShell(
261            "AFNI" , "AFNI" , topLevelShellWidgetClass , dc->display ,
262 
263            XmNtitle             , "AFNI Editor" , /* top of window */
264            XmNiconName          , "Editor"      , /* label on icon */
265            XmNdeleteResponse    , XmDO_NOTHING  , /* deletion handled below */
266            XmNallowShellResize  , False ,         /* let code resize shell? */
267            XmNmappedWhenManaged , False ,         /* must map it manually */
268            XmNinitialResourcesPersistent , False ,
269       NULL ) ;
270 
271    DC_yokify( shell , dc ) ;
272 
273    if( afni48_good )             /* set icon pixmap */
274       XtVaSetValues( shell ,
275                         XmNiconPixmap , afni48_pixmap ,
276                      NULL ) ;
277 
278    if( MCW_isitmwm(shell) )      /* remove some MWM functions */
279       XtVaSetValues( shell ,
280                        XmNmwmFunctions , MWM_FUNC_MOVE     |
281                                          MWM_FUNC_CLOSE    |
282                                          MWM_FUNC_MINIMIZE |
283                                          MWM_FUNC_RESIZE    ,
284                      NULL ) ;
285 
286    XmAddWMProtocolCallback(      /* make "Close" window menu work */
287            shell ,
288            XmInternAtom( dc->display , "WM_DELETE_WINDOW" , False ) ,
289            TAG_quit_CB , (XtPointer) plint ) ;
290 
291    /*** form widget to hold all user interface stuff ***/
292 
293    thetop = XtVaCreateWidget(
294                  "AFNI" , xmFormWidgetClass , shell ,
295                      XmNborderWidth , 0 ,
296                      XmNborderColor , 0 ,
297                      XmNtraversalOn , True  ,
298                      XmNinitialResourcesPersistent , False ,
299                  NULL ) ;
300 
301    /*** pushbutton to select dataset for tagging ***/
302 
303    xstr = XmStringCreateLtoR( "Dataset" , XmFONTLIST_DEFAULT_TAG ) ;
304    dset_pb =  XtVaCreateManagedWidget(
305                 "AFNI" , xmPushButtonWidgetClass , thetop ,
306                    XmNlabelString , xstr ,
307                    XmNmarginHeight , 4 ,
308                    XmNmarginWidth  , 4 ,
309                    XmNtraversalOn , True  ,
310                    XmNinitialResourcesPersistent , False ,
311                    XmNleftAttachment , XmATTACH_FORM ,
312                    XmNtopAttachment  , XmATTACH_FORM ,
313                    XmNtopOffset      , 7 ,
314                    XmNleftOffset     , 5 ,
315                NULL ) ;
316    XmStringFree(xstr) ;
317 
318    XtAddCallback( dset_pb , XmNactivateCallback , TAG_dset_CB , NULL ) ;
319 
320    MCW_register_help( dset_pb , "Select dataset for tagging" ) ;
321    MCW_register_hint( dset_pb , "Select dataset" ) ;
322 
323    /*** label at top to let user know who we are ***/
324 
325    xstr = XmStringCreateLtoR( DEFAULT_INFOLAB , XmFONTLIST_DEFAULT_TAG ) ;
326    info_lab = XtVaCreateManagedWidget(
327                  "AFNI" , xmLabelWidgetClass , thetop ,
328                     XmNleftAttachment , XmATTACH_WIDGET ,
329                     XmNleftWidget     , dset_pb ,
330                     XmNleftOffset     , 10 ,
331                     XmNtopAttachment  , XmATTACH_FORM ,
332                     XmNtopOffset      , 5 ,
333                     XmNrightAttachment, XmATTACH_FORM ,
334                     XmNlabelString , xstr ,
335                     XmNmarginHeight , 1 ,
336                     XmNalignment , XmALIGNMENT_BEGINNING ,
337                     XmNrecomputeSize , True ,
338                     XmNinitialResourcesPersistent , False ,
339                  NULL ) ;
340    XmStringFree(xstr) ;
341    MCW_register_help( info_lab , "Shows dataset being tagged" ) ;
342    MCW_register_hint( info_lab , "Shows dataset being tagged" ) ;
343 
344    /*** separator for visual neatness ***/
345 
346    wjunk =  XtVaCreateManagedWidget(
347              "AFNI" , xmSeparatorWidgetClass , thetop ,
348                 XmNseparatorType , XmSINGLE_LINE ,
349                 XmNleftAttachment , XmATTACH_FORM ,
350                 XmNrightAttachment, XmATTACH_FORM ,
351                 XmNtopAttachment  , XmATTACH_WIDGET ,
352                 XmNtopWidget      , dset_pb ,
353                 XmNtopOffset      , 5 ,
354                 XmNinitialResourcesPersistent , False ,
355              NULL ) ;
356 
357    /*** 1st set of action buttons below the line ***/
358 
359    actar = MCW_action_area( thetop , TAG_actor1 , NACT1 ) ;
360 
361    XtVaSetValues( actar ,
362                      XmNleftAttachment , XmATTACH_FORM ,
363                      XmNrightAttachment, XmATTACH_FORM ,
364                      XmNtopAttachment  , XmATTACH_WIDGET ,
365                      XmNtopOffset      , 5 ,
366                      XmNtopWidget      , wjunk ,
367                   NULL ) ;
368 
369    quit_pb  = (Widget) TAG_actor1[0].data ;  /* save individual buttons */
370    help_pb  = (Widget) TAG_actor1[1].data ;
371    read_pb  = (Widget) TAG_actor1[2].data ;
372    write_pb = (Widget) TAG_actor1[3].data ;
373    copy_pb  = (Widget) TAG_actor1[4].data ;
374    save_pb  = (Widget) TAG_actor1[5].data ;
375    done_pb  = (Widget) TAG_actor1[6].data ;
376 
377    /*** separator for visual neatness ***/
378 
379    wjunk =  XtVaCreateManagedWidget(
380              "AFNI" , xmSeparatorWidgetClass , thetop ,
381                 XmNseparatorType  , XmSINGLE_LINE ,
382                 XmNleftAttachment , XmATTACH_FORM ,
383                 XmNrightAttachment, XmATTACH_FORM ,
384                 XmNtopAttachment  , XmATTACH_WIDGET ,
385                 XmNtopWidget      , actar ,
386                 XmNtopOffset      , 5 ,
387                 XmNinitialResourcesPersistent , False ,
388              NULL ) ;
389 
390    /*** 2nd set of action buttons ***/
391 
392    actar = MCW_action_area( thetop , TAG_actor2 , NACT2 ) ;
393 
394    XtVaSetValues( actar ,
395                      XmNleftAttachment , XmATTACH_FORM ,
396                      XmNrightAttachment, XmATTACH_FORM ,
397                      XmNtopAttachment  , XmATTACH_WIDGET ,
398                      XmNtopOffset      , 5 ,
399                      XmNtopWidget      , wjunk ,
400                   NULL ) ;
401 
402    set_pb     = (Widget) TAG_actor2[0].data ;  /* save individual buttons */
403    clear_pb   = (Widget) TAG_actor2[1].data ;
404    clearall_pb= (Widget) TAG_actor2[2].data ;
405    add_pb     = (Widget) TAG_actor2[3].data ;
406    delete_pb  = (Widget) TAG_actor2[4].data ;
407    relabel_pb = (Widget) TAG_actor2[5].data ;
408    beep_pb    = (Widget) TAG_actor2[6].data ;
409 
410    /*** separator for visual neatness ***/
411 
412    wjunk =  XtVaCreateManagedWidget(
413              "AFNI" , xmSeparatorWidgetClass , thetop ,
414                 XmNseparatorType  , XmSINGLE_LINE ,
415                 XmNleftAttachment , XmATTACH_FORM ,
416                 XmNrightAttachment, XmATTACH_FORM ,
417                 XmNtopAttachment  , XmATTACH_WIDGET ,
418                 XmNtopWidget      , actar ,
419                 XmNtopOffset      , 5 ,
420                 XmNinitialResourcesPersistent , False ,
421              NULL ) ;
422 
423    /*** string chooser for tagset filename ***/
424 
425    file_strav = new_PLUGIN_strval( thetop , "Tag File:  " ) ;
426    alter_PLUGIN_strval_width( file_strav , 37 ) ;
427 
428    MCW_reghelp_children( file_strav->rowcol ,
429                          "Use this to enter the tagset filename\n"
430                          "before using the Read or Write buttons.\n"
431                          "(Tagset filenames must end in '.tag'.)"
432                        ) ;
433    MCW_reghint_children( file_strav->rowcol , "Used with Read/Write buttons" ) ;
434 
435    XtVaSetValues( file_strav->rowcol ,
436                      XmNleftAttachment , XmATTACH_FORM ,
437                      XmNrightAttachment, XmATTACH_FORM ,
438                      XmNtopAttachment  , XmATTACH_WIDGET ,
439                      XmNtopOffset      , 5 ,
440                      XmNtopWidget      , wjunk ,
441                   NULL ) ;
442 
443    /*** string chooser for relabeling tags ***/
444 
445    label_strav = new_PLUGIN_strval( thetop , "Tag Label: " ) ;
446    alter_PLUGIN_strval_width( label_strav , 37 ) ;
447 
448    MCW_reghelp_children( label_strav->rowcol ,
449                          "Use this to enter the new tag label\n"
450                          "before using the Relabel button."
451                        ) ;
452    MCW_reghint_children( label_strav->rowcol , "Used with Relabel button" ) ;
453 
454    XtVaSetValues( label_strav->rowcol ,
455                      XmNleftAttachment , XmATTACH_FORM ,
456                      XmNrightAttachment, XmATTACH_FORM ,
457                      XmNtopAttachment  , XmATTACH_WIDGET ,
458                      XmNtopOffset      , 5 ,
459                      XmNtopWidget      , file_strav->rowcol ,
460                   NULL ) ;
461 
462    /*** arrowval to choose value that is drawn into dataset voxels ***/
463 
464    value_av = new_MCW_arrowval( thetop , "Tag Value: " ,
465                                 MCW_AV_downup , -32767,32767,value_int ,
466                                 MCW_AV_editext , 0 ,
467                                 TAG_value_CB , NULL , NULL,NULL ) ;
468 
469    MCW_reghelp_children( value_av->wrowcol ,
470                          "Use this to set the value that\n"
471                          "will be associated with a tag."
472                        ) ;
473    MCW_reghint_children( value_av->wrowcol , "Value associated with tag" ) ;
474 
475    XtVaSetValues( value_av->wrowcol ,
476                      XmNleftAttachment , XmATTACH_FORM ,
477                      XmNrightAttachment, XmATTACH_FORM ,
478                      XmNtopAttachment  , XmATTACH_WIDGET ,
479                      XmNtopOffset      , 5 ,
480                      XmNtopWidget      , label_strav->rowcol ,
481                   NULL ) ;
482 
483    /*** separator for visual neatness ***/
484 
485    wjunk = XtVaCreateManagedWidget(
486              "AFNI" , xmSeparatorWidgetClass , thetop ,
487                 XmNseparatorType , XmSINGLE_LINE ,
488                 XmNleftAttachment , XmATTACH_FORM ,
489                 XmNrightAttachment, XmATTACH_FORM ,
490                 XmNtopAttachment  , XmATTACH_WIDGET ,
491                 XmNtopWidget      , value_av->wrowcol ,
492                 XmNtopOffset      , 5 ,
493                 XmNinitialResourcesPersistent , False ,
494              NULL ) ;
495 
496    /*** scrolled window to hold the tag selectors ***/
497 
498    scrollw =
499          XtVaCreateWidget(
500            "AFNI" , xmScrolledWindowWidgetClass ,  thetop ,
501               XmNscrollingPolicy , XmAUTOMATIC ,
502               XmNleftAttachment  , XmATTACH_FORM ,
503               XmNrightAttachment , XmATTACH_FORM ,
504               XmNtopAttachment   , XmATTACH_WIDGET ,
505               XmNbottomAttachment, XmATTACH_FORM ,
506               XmNtopWidget       , wjunk ,
507               XmNtopOffset       , 5 ,
508               XmNtraversalOn , True  ,
509               XmNinitialResourcesPersistent , False ,
510            NULL ) ;
511 
512    wframe =
513          XtVaCreateWidget(
514            "AFNI" , xmFrameWidgetClass , scrollw ,
515                XmNshadowType , XmSHADOW_ETCHED_IN ,
516                XmNshadowThickness , 5 ,
517                XmNtraversalOn , True  ,
518                XmNinitialResourcesPersistent , False ,
519             NULL ) ;
520 
521    workwin =
522          XtVaCreateWidget(
523            "AFNI" , xmRowColumnWidgetClass , wframe ,
524               XmNpacking     , XmPACK_COLUMN ,
525               XmNnumColumns  , 1 ,
526               XmNorientation , XmVERTICAL ,
527               XmNtraversalOn , True  ,
528               XmNinitialResourcesPersistent , False ,
529            NULL ) ;
530 
531    XtVaGetValues( workwin , XmNforeground , &fg_pix , NULL ) ;
532 
533    XtVaSetValues( workwin ,
534                      XmNradioBehavior , True ,
535                      XmNradioAlwaysOne , False ,
536                      XmNspacing      , 1 ,
537                      XmNmarginHeight , 0 ,
538                      XmNmarginWidth  , 0 ,
539                   NULL ) ;
540 
541    /*** array of toggles for each possible tag ***/
542 
543    tagtog = (Widget *) XtMalloc( sizeof(Widget) * MAX_TAG_NUM ) ;
544    toginv = (int *)    XtMalloc( sizeof(int)    * MAX_TAG_NUM ) ;
545 
546    for( ii=0 ; ii < MAX_TAG_NUM ; ii++ ){
547       sprintf(tlab,"Tag #%d",ii) ;
548       xstr = XmStringCreateLtoR( tlab , XmFONTLIST_DEFAULT_TAG ) ;
549 
550       tagtog[ii] =
551            XtVaCreateWidget(
552               "dialog" , xmToggleButtonWidgetClass , workwin ,
553                  XmNlabelString    , xstr ,
554                  XmNvisibleWhenOff , True ,
555                  XmNmarginHeight   , 0 ,
556                  XmNmarginWidth    , 0 ,
557 #if 0
558                  XmNselectColor    , fg_pix ,
559 #endif
560                  XmNtraversalOn    , True  ,
561                  XmNinitialResourcesPersistent , False ,
562               NULL ) ;
563 
564       XmStringFree(xstr) ;
565       toginv[ii] = 0 ;
566       XtAddCallback( tagtog[ii] , XmNdisarmCallback , TAG_tog_CB , NULL ) ;
567 
568       if( ii < tognum ) XtManageChild( tagtog[ii] ) ;
569 
570       mytagset->tag[ii].set = 0 ;
571       mytagset->tag[ii].ti  = 0 ;
572       mytagset->tag[ii].x   = 0.0 ;
573       mytagset->tag[ii].y   = 0.0 ;
574       mytagset->tag[ii].z   = 0.0 ;
575       mytagset->tag[ii].val = 0.0 ;
576       strcpy( mytagset->tag[ii].label , tlab ) ;
577    }
578    mytagset->num = tognum ;
579    strcpy( mytagset->label , "Tar-Palantir" ) ;
580 
581    /*** that's almost all ***/
582 
583    XtManageChild( workwin ) ;
584    XtManageChild( wframe  ) ;
585    XtManageChild( scrollw ) ;
586    XtManageChild( thetop  ) ;
587 
588    XtRealizeWidget( shell ) ;  NI_sleep(1) ; /* will not be mapped */
589 
590    /** set up widths and heights **/
591 
592    { XmFontList xflist=(XmFontList)NULL ;
593 
594      for( ii=0 ; ii < MAX_TAG_LABEL-1 ; ii++ ) tlab[ii] = 'X' ;
595      tlab[MAX_TAG_LABEL-1] = '\0' ;
596 
597      xstr = XmStringCreateLtoR( tlab , XmFONTLIST_DEFAULT_TAG ) ;
598 
599      XtVaGetValues( thetop , XmNbuttonFontList , &xflist , NULL ) ;
600      hh = XmStringHeight( xflist , xstr ) ;
601      ww = XmStringWidth ( xflist , xstr ) ;
602      XmStringFree(xstr) ;
603    }
604 
605    XtVaSetValues( shell ,
606                      XmNminWidth  , ww+19*hh ,  /* semi-empirical numbers; */
607                      XmNwidth     , ww+23*hh ,  /* all primes (for luck)  */
608                      XmNminHeight , 23*hh ,
609                      XmNheight    , 29*hh ,
610                   NULL ) ;
611 
612    TAG_columnize() ;
613    return ;
614 }
615 
616 /*--------------------------------------------------------------------------*/
617 
TAG_redraw(void)618 static void TAG_redraw(void)
619 {
620    if( dset == NULL ) return ;
621 
622    if( dset->tagset == NULL ) dset->tagset = myXtNew(THD_usertaglist) ;
623 
624    *(dset->tagset) = *mytagset ;  /* copy all data in one swell foop */
625 
626    PLUTO_dset_redisplay_mode( dset , REDISPLAY_OVERLAY ) ;
627    return ;
628 }
629 
630 /*--------------------------------------------------------------------------*/
631 
TAG_quit_CB(Widget w,XtPointer client_data,XtPointer call_data)632 static void TAG_quit_CB( Widget w, XtPointer client_data, XtPointer call_data )
633 {
634    if( editor_open ){
635       if( dset != NULL && dset->tagset != NULL ){
636          *(dset->tagset) = *oldtagset ;
637          if( dset->tagset->num == 0 ) myXtFree(dset->tagset) ;
638          PLUTO_dset_redisplay_mode( dset , REDISPLAY_OVERLAY ) ;
639       }
640       XtUnmapWidget( shell ) ; editor_open = 0 ; dset = NULL ;
641       oldtagset->num = 0 ;
642    }
643    return ;
644 }
645 
646 /*--------------------------------------------------------------------------*/
647 
TAG_value_CB(MCW_arrowval * av,XtPointer cd)648 static void TAG_value_CB( MCW_arrowval * av , XtPointer cd )
649 {
650    value_int   = av->ival ;
651    value_float = av->fval ;
652 
653    if( !IM3D_OPEN(im3d) ){ BEEPIT ; TAG_quit_CB(NULL,NULL,NULL) ; return ; }
654    return ;
655 }
656 
657 /*--------------------------------------------------------------------------*/
658 
TAG_columnize(void)659 static void TAG_columnize(void)
660 {
661    int nc = (tognum < 21) ? 1 : 2 ;
662    XtVaSetValues( workwin , XmNnumColumns , nc , NULL ) ;
663    return ;
664 }
665 
666 /*--------------------------------------------------------------------------*/
667 
668 #define UNSET(j)                                                              \
669   do{ XmToggleButtonSetState( tagtog[(j)] , 0 , False ) ;                     \
670       mytagset->tag[(j)].set = 0 ;                                            \
671       if( active_tog == (j) ) active_tog = -1 ;                               \
672       if( toginv[(j)] ){ toginv[(j)] = 0; MCW_invert_widget( tagtog[(j)] ); } \
673   } while(0)
674 
675 /*--------------------------------------------------------------------------*/
676 
TAG_add_CB(Widget w,XtPointer client_data,XtPointer call_data)677 static void TAG_add_CB( Widget w, XtPointer client_data, XtPointer call_data )
678 {
679    if( !IM3D_OPEN(im3d) ){ BEEPIT ; TAG_quit_CB(NULL,NULL,NULL) ; return ; }
680 
681    if( tognum >= MAX_TAG_NUM ){
682       char buf[64] ;
683       sprintf(buf,"Maximum number of\nallowed tags is %d",MAX_TAG_NUM) ;
684       POPUP_MESG(buf) ; BEEPIT ;
685       return ;
686    }
687 
688    UNSET(tognum) ;
689    XtManageChild( tagtog[tognum] ) ;
690    tognum++ ; mytagset->num = tognum ; TAG_columnize() ; DSET_OFF ;
691    return ;
692 }
693 
694 /*--------------------------------------------------------------------------*/
695 
TAG_delete_CB(Widget w,XtPointer client_data,XtPointer call_data)696 static void TAG_delete_CB( Widget w, XtPointer client_data, XtPointer call_data )
697 {
698    if( !IM3D_OPEN(im3d) ){ BEEPIT ; TAG_quit_CB(NULL,NULL,NULL) ; return ; }
699 
700    if( tognum <= 1 ){
701       POPUP_MESG("You can't delete the\nonly remaining tag!") ;
702       BEEPIT ; return ;
703    }
704 
705    UNSET(tognum-1) ;
706    XtUnmanageChild( tagtog[tognum-1] ) ;
707    tognum-- ; mytagset->num = tognum ; TAG_columnize() ;
708    TAG_redraw() ; DSET_OFF ;
709    return ;
710 }
711 
712 /*--------------------------------------------------------------------------*/
713 
TAG_set_CB(Widget w,XtPointer client_data,XtPointer call_data)714 static void TAG_set_CB( Widget w, XtPointer client_data, XtPointer call_data )
715 {
716    int ii = active_tog ;
717 
718    if( !IM3D_OPEN(im3d) ){ BEEPIT ; TAG_quit_CB(NULL,NULL,NULL) ; return ; }
719 
720    if( ii < 0 || ii >= tognum ){
721       BEEPIT ;
722       POPUP_MESG( "Can't set a tag\nuntil one is selected" ) ;
723       return ;
724    }
725 
726    mytagset->tag[ii].set = 1 ;
727    mytagset->tag[ii].ti  = im3d->vinfo->time_index ;
728    mytagset->tag[ii].x   = im3d->vinfo->xi ;
729    mytagset->tag[ii].y   = im3d->vinfo->yj ;
730    mytagset->tag[ii].z   = im3d->vinfo->zk ;
731    mytagset->tag[ii].val = value_float ;
732 
733    if( !toginv[ii] ){ toginv[ii] = 1 ; MCW_invert_widget( tagtog[ii] ) ; }
734 
735    DSET_OFF ; TAG_redraw() ;
736    return ;
737 }
738 
739 /*--------------------------------------------------------------------------*/
740 
TAG_clear_CB(Widget w,XtPointer client_data,XtPointer call_data)741 static void TAG_clear_CB( Widget w, XtPointer client_data, XtPointer call_data )
742 {
743    int ii=active_tog , oldset ;
744 
745    if( !IM3D_OPEN(im3d) ){ BEEPIT ; TAG_quit_CB(NULL,NULL,NULL) ; return ; }
746 
747    if( ii < 0 || ii >= tognum ){
748       BEEPIT ;
749       POPUP_MESG( "Can't clear a tag\nuntil one is selected" ) ;
750       return ;
751    }
752 
753    oldset = mytagset->tag[ii].set ;
754    mytagset->tag[ii].set = 0 ;
755 
756    if( toginv[ii] ){ toginv[ii] = 0 ; MCW_invert_widget( tagtog[ii] ) ; }
757 
758    if( oldset ){ TAG_redraw() ; DSET_OFF ; }
759    return ;
760 }
761 
762 /*--------------------------------------------------------------------------*/
763 
TAG_clearall_CB(Widget w,XtPointer client_data,XtPointer call_data)764 static void TAG_clearall_CB( Widget w, XtPointer client_data, XtPointer call_data )
765 {
766    int ii , oldset=0 ;
767 
768    if( !IM3D_OPEN(im3d) ){ BEEPIT ; TAG_quit_CB(NULL,NULL,NULL) ; return ; }
769 
770    if( tognum < 1 ){ BEEPIT ; return ; }  /* should not occur */
771 
772    for( ii=0 ; ii < tognum ; ii++ ){
773       if( mytagset->tag[ii].set ) oldset++ ;
774       mytagset->tag[ii].set = 0 ;
775       if( toginv[ii] ){ toginv[ii] = 0 ; MCW_invert_widget( tagtog[ii] ) ; }
776    }
777 
778    if( oldset ){ TAG_redraw() ; DSET_OFF ; }
779    return ;
780 }
781 
782 /*--------------------------------------------------------------------------*/
783 
TAG_relabel_CB(Widget w,XtPointer client_data,XtPointer call_data)784 static void TAG_relabel_CB( Widget w, XtPointer client_data, XtPointer call_data )
785 {
786    char * str=get_PLUGIN_strval(label_strav) ;
787    int ii=active_tog , ll,kk,nn ;
788    XmString xstr ;
789 
790    if( !IM3D_OPEN(im3d) ){ BEEPIT ; TAG_quit_CB(NULL,NULL,NULL) ; return ; }
791 
792    if( str == NULL ){ BEEPIT ; return ; }  /* should not occur */
793 
794    if( str[0] == '\0' || ii < 0 || ii >= tognum ){
795       BEEPIT; XtFree(str);
796       POPUP_MESG( "Can't relabel a tag unless\n"
797                   "one is selected AND a new\n"
798                   "label is typed in" ) ;
799       return;
800    }
801 
802    ll = strlen(str) ;
803    if( ll >= MAX_TAG_LABEL ){ str[MAX_TAG_LABEL-1] = '\0'; ll = strlen(str); }
804    for( kk=nn=0 ; kk < ll ; kk++ ) if( isspace(str[kk]) ) nn++ ;
805    if( nn == ll ){
806       BEEPIT; XtFree(str);
807       POPUP_MESG( "Can't relabel a\ntag to all blanks!" ) ;
808       return ;
809    }
810 
811    xstr = XmStringCreateLtoR( str , XmFONTLIST_DEFAULT_TAG ) ;
812    XtVaSetValues( tagtog[ii] , XmNlabelString , xstr , NULL ) ;
813    XmStringFree(xstr) ;
814 
815    strcpy( mytagset->tag[ii].label , str ) ;
816    XtFree(str) ; DSET_OFF ;
817    return ;
818 }
819 
820 /*--------------------------------------------------------------------------*/
821 
TAG_tog_CB(Widget w,XtPointer client_data,XtPointer call_data)822 static void TAG_tog_CB( Widget w, XtPointer client_data, XtPointer call_data )
823 {
824    int ii ;
825 
826    if( !IM3D_OPEN(im3d) ){ BEEPIT ; TAG_quit_CB(NULL,NULL,NULL) ; return ; }
827 
828    for( ii=0 ; ii < tognum ; ii++ ){
829       if( XmToggleButtonGetState( tagtog[ii] ) ){  /* found it */
830          active_tog = ii ;
831          if( mytagset->tag[ii].set ){              /* if already set */
832             AFNI_jumpto_dicom( im3d , mytagset->tag[ii].x ,
833                                       mytagset->tag[ii].y , mytagset->tag[ii].z ) ;
834 
835             AV_assign_fval( value_av , mytagset->tag[ii].val ) ;
836             value_int   = value_av->ival ;
837             value_float = value_av->fval ;
838          }
839          return ;
840       }
841    }
842 
843    active_tog = -1 ; return ;  /* found nothing */
844 }
845 
846 /*--------------------------------------------------------------------------*/
847 
TAG_write_CB(Widget w,XtPointer client_data,XtPointer call_data)848 static void TAG_write_CB( Widget w, XtPointer client_data, XtPointer call_data )
849 {
850    char * str=get_PLUGIN_strval(file_strav) , * cpt ;
851    int ii , jj , ltop ;
852    FILE * fp ;
853 
854    if( !IM3D_OPEN(im3d) ){ BEEPIT ; TAG_quit_CB(NULL,NULL,NULL) ; return ; }
855 
856    if( str == NULL ){ BEEPIT ; return ; }  /* should not occur */
857 
858    if( str[0] == '\0' || tognum < 1 ){
859       XtFree(str) ; BEEPIT ;
860       POPUP_MESG( "Can't write tags to a file\n"
861                   "until a filename is typed in" ) ;
862       return ;
863    }
864 
865    cpt = strstr( str , ".tag" ) ;
866    if( cpt == NULL ){
867       ii = strlen(str) ;
868       cpt = XtMalloc(ii+8) ;
869       strcpy(cpt,str) ;
870       if( cpt[ii-1] != '.' ) strcat( cpt , "." ) ;
871       strcat( cpt , "tag" ) ;
872       XtFree(str) ;
873       str = cpt ;
874    }
875 
876    if( !THD_filename_ok(str) ){
877       XtFree(str) ; BEEPIT ;
878       POPUP_MESG( "The filename you entered\nhas illegal characters!" ) ;
879       return ;
880    }
881 
882    fp = fopen( str , "w" ) ;
883    if( fp == NULL ){
884       XtFree(str) ; BEEPIT ;
885       POPUP_MESG( "Can't open output file!\n" ) ;
886       return ;
887    }
888 
889    ltop = 6 ;
890    for( ii=0 ; ii < tognum ; ii++ ){
891       jj   = strlen( mytagset->tag[ii].label ) ;
892       ltop = MAX( jj , ltop ) ;
893    }
894 
895    cpt = XtMalloc( MAX_TAG_LABEL+256 ) ;
896 
897    strcpy(cpt,"# Label") ;
898    for( jj=strlen(cpt) ; jj < ltop+2 ; jj++ )
899       strcat( cpt , "_" ) ;
900    strcat(cpt,"  ") ;
901    strcat(cpt," _____x_____ _____y_____ _____z_____ ____val____ _t_") ;
902    fprintf(fp,"%s\n",cpt) ;
903 
904    for( ii=0 ; ii < tognum ; ii++ ){
905       strcpy( cpt , "'" ) ;
906       strcat( cpt , mytagset->tag[ii].label ) ;
907       strcat( cpt , "'" ) ;
908 
909       if( mytagset->tag[ii].set ){
910          for( jj=strlen(cpt) ; jj < ltop+4 ; jj++ )
911             strcat( cpt , " " ) ;
912 
913          fprintf(fp , "%s %11.4g %11.4g %11.4g %11.4g %3d\n" ,
914                  cpt, mytagset->tag[ii].x, mytagset->tag[ii].y, mytagset->tag[ii].z,
915                       mytagset->tag[ii].val, mytagset->tag[ii].ti ) ;
916       } else {
917          fprintf(fp , "%s\n" , cpt ) ;
918       }
919    }
920 
921    fclose(fp) ; XtFree(cpt) ;
922    fprintf(stderr,"Wrote tag file %s\n",str) ;
923    XtFree(str) ; return ;
924 }
925 
926 /*--------------------------------------------------------------------------*/
927 
TAG_reset_widgets(void)928 static void TAG_reset_widgets(void)
929 {
930    int ii ;
931    XmString xstr ;
932 
933    XtUnmanageChild(wframe) ;
934 
935    for( ii=0 ; ii < tognum ; ii++ ){
936 
937       XtManageChild( tagtog[ii] ) ;
938       XmToggleButtonSetState( tagtog[ii] , 0 , False ) ;
939 
940       if( mytagset->tag[ii].set && !toginv[ii] ){
941          toginv[ii] = 1; MCW_invert_widget( tagtog[ii] );
942       } else if( !mytagset->tag[ii].set && toginv[ii] ){
943          toginv[ii] = 0; MCW_invert_widget( tagtog[ii] );
944       }
945 
946       xstr = XmStringCreateLtoR( mytagset->tag[ii].label , XmFONTLIST_DEFAULT_TAG ) ;
947       XtVaSetValues( tagtog[ii] , XmNlabelString , xstr , NULL ) ;
948       XmStringFree(xstr) ;
949    }
950 
951    for( ; ii < MAX_TAG_NUM ; ii++ ){
952       UNSET(ii) ;
953       XtUnmanageChild( tagtog[ii] ) ;
954    }
955 
956    TAG_columnize() ; XtManageChild(wframe) ;
957    active_tog = -1 ; return ;
958 }
959 
960 /*--------------------------------------------------------------------------*/
961 
TAG_read_CB(Widget w,XtPointer client_data,XtPointer call_data)962 static void TAG_read_CB( Widget w, XtPointer client_data, XtPointer call_data )
963 {
964    char * str=get_PLUGIN_strval(file_strav) , * cpt , buf[256] , quote ;
965    int ii , jj , ntog , lbuf , kk ;
966    FILE * fp ;
967    char  new_label[MAX_TAG_LABEL] ;
968    float new_x , new_y , new_z , new_val ;
969    int   new_ti , new_set ;
970    XmString xstr ;
971 
972    /*-- sanity checks --*/
973 
974    if( !IM3D_OPEN(im3d) ){ BEEPIT ; TAG_quit_CB(NULL,NULL,NULL) ; return ; }
975 
976    if( str == NULL ){ BEEPIT ; return ; }  /* should not happen */
977 
978    if( str[0] == '\0' ){
979       XtFree(str) ; BEEPIT ;
980       POPUP_MESG( "Can't read a tagset until\nyou type in a filename" ) ;
981       return ;
982    }
983 
984    /*-- check for suffix on filename --*/
985 
986    cpt = strstr( str , ".tag" ) ;
987    if( cpt == NULL ){
988       ii = strlen(str) ;
989       cpt = XtMalloc(ii+8) ;
990       strcpy(cpt,str) ;
991       if( cpt[ii-1] != '.' ) strcat( cpt , "." ) ;
992       strcat( cpt , "tag" ) ;
993       XtFree(str) ;
994       str = cpt ;
995    }
996 
997    /*-- open file --*/
998 
999    fp = fopen( str , "r" ) ;
1000    if( fp == NULL ){
1001       XtFree(str) ; BEEPIT ;
1002       POPUP_MESG( "Can't open input file!" ) ;
1003       return ;
1004    }
1005 
1006    /*-- scan each line for a tag definition --*/
1007 
1008    ntog = 0 ;
1009    while( ntog < MAX_TAG_NUM ){
1010       cpt = afni_fgets( buf , 256 , fp ); /* read line from disk */
1011       if( cpt == NULL ) break ;           /* nothing => exit */
1012       if( buf[0] == '#'  ) continue ;     /* comment => skip this line */
1013       if( buf[0] == '\n' ) continue ;
1014       if( buf[0] == '\0' ) continue ;
1015 
1016       lbuf = strlen(buf) ;                /* skip whitespace at start */
1017       jj = 0 ;
1018       while( jj < lbuf && isspace(buf[jj]) ) jj++ ;
1019       if( jj == lbuf ) continue ;         /* was a blank line => skip */
1020       if( buf[jj] == '#'  ) continue ;    /* comment */
1021 
1022       /* scan for new label */
1023 
1024       if( buf[jj] == '\'' || buf[jj] == '\"' ){  /* scan to matching quote */
1025          quote = buf[jj] ; jj++ ; kk = jj ;
1026          while( kk < lbuf && buf[kk] != quote ) kk++ ;
1027          if( kk == lbuf ) kk-- ;
1028       } else {                                   /* scan to nonblank */
1029          kk = jj+1 ;
1030          while( kk < lbuf && !isspace(buf[kk]) ) kk++ ;
1031       }
1032       for( ii=0 ; ii < MAX_TAG_LABEL-1 && jj < kk ; ii++,jj++ )
1033          new_label[ii] = buf[jj] ;
1034       new_label[ii] = '\0' ;
1035       if( strlen(new_label) == 0 ) continue ;  /* error => skip */
1036       jj = kk+1 ;
1037 
1038       /* scan for x y z val ti */
1039 
1040       new_set = new_ti = 0 ;
1041       new_x   = new_y  = new_z = new_val = 0.0 ;
1042       if( jj < lbuf-4 ){
1043          kk = sscanf( buf+jj , "%f %f %f %f %d" ,
1044                       &new_x , &new_y , &new_z , &new_val , &new_ti ) ;
1045          if( kk >= 3 ) new_set = 1 ;  /* got x y z, at least */
1046       }
1047 
1048       /* set values */
1049 
1050       strcpy( mytagset->tag[ntog].label , new_label ) ;
1051       mytagset->tag[ntog].set = new_set ;
1052       mytagset->tag[ntog].ti  = new_ti  ;
1053       mytagset->tag[ntog].x   = new_x   ;
1054       mytagset->tag[ntog].y   = new_y   ;
1055       mytagset->tag[ntog].z   = new_z   ;
1056       mytagset->tag[ntog].val = new_val ;
1057       ntog++ ;
1058    }
1059 
1060    fclose(fp) ;  /* done with file */
1061 
1062    if( ntog == 0 ){                                 /* no tags ==> error */
1063       sprintf(buf,"Couldn't read tagset from\n"
1064                   "file %s" , str ) ;
1065       POPUP_MESG( buf ) ;
1066       BEEPIT ; XtFree(str) ; return ;
1067    }
1068 
1069    /*-- now reset the widgets --*/
1070 
1071    tognum = mytagset->num = ntog ;
1072    TAG_reset_widgets() ;
1073    TAG_redraw() ; DSET_OFF ; XtFree(str) ;
1074    return ;
1075 }
1076 
1077 /*--------------------------------------------------------------------------*/
1078 
TAG_get_dset_CB(int num,THD_3dim_dataset ** dslist,void * cd)1079 static void TAG_get_dset_CB( int num, THD_3dim_dataset ** dslist, void * cd )
1080 {
1081    char str[256] , * tnam ;
1082    XmString xstr ;
1083 
1084    /*-- sanity checks --*/
1085 
1086    if( !IM3D_OPEN(im3d) || !editor_open ){
1087       BEEPIT ; POPDOWN_strlist_chooser ;
1088       TAG_quit_CB(NULL,NULL,NULL) ; return ;
1089    }
1090 
1091    /* this should not occur: */
1092 
1093    if( num != 1 || dslist == NULL || !ISVALID_DSET(dslist[0]) ){ BEEPIT; return; }
1094 
1095    /* assign global variable */
1096 
1097    dset = dslist[0] ;
1098 
1099    /*-- change the informational label --*/
1100 
1101    sprintf(str,"%s%s", DSET_DIRNAME(dset) , DSET_FILECODE(dset) ) ;
1102    tnam = THD_trailname( str , SESSTRAIL+1 ) ;
1103    xstr = XmStringCreateLtoR( tnam , XmFONTLIST_DEFAULT_TAG ) ;
1104    XtVaSetValues( info_lab , XmNlabelString , xstr , NULL ) ;
1105    XmStringFree(xstr) ;
1106 
1107    /*-- if the new dataset has tags, use them --*/
1108 
1109    if( dset->tagset != NULL && dset->tagset->num > 0 ){
1110       *mytagset  = *(dset->tagset) ;  /* copy all data in one swell foop */
1111       *oldtagset = *mytagset ;        /* backup copy */
1112       tognum = mytagset->num ;
1113       TAG_reset_widgets() ;
1114    } else {
1115       oldtagset->num = 0 ;
1116       if( dset->tagset == NULL ){
1117          dset->tagset = myXtNew(THD_usertaglist) ;
1118          dset->tagset->num = 0 ;
1119       }
1120       if( tognum > 0 ) TAG_clearall_CB(NULL,NULL,NULL) ;
1121    }
1122 
1123    TAG_onoff( 1 ) ;
1124    return ;
1125 }
1126 
1127 /*--------------------------------------------------------------------------*/
1128 
TAG_check_dataset(THD_3dim_dataset * qset,void * cd)1129 static int TAG_check_dataset( THD_3dim_dataset * qset, void * cd )
1130 {
1131 #if 0
1132    return ISANAT(qset) ;
1133 #else
1134    return 1 ;  /* All of them, Frank */
1135 #endif
1136 }
1137 
TAG_check_copyset(THD_3dim_dataset * qset,void * cd)1138 static int TAG_check_copyset( THD_3dim_dataset * qset, void * cd )
1139 {
1140    return ( ISANAT(qset)         && !EQUIV_DSETS(qset,dset) &&
1141             qset->tagset != NULL && qset->tagset->num > 0      ) ;
1142 }
1143 
1144 /*--------------------------------------------------------------------------*/
1145 
TAG_dset_CB(Widget w,XtPointer client_data,XtPointer call_data)1146 static void TAG_dset_CB( Widget w, XtPointer client_data, XtPointer call_data )
1147 {
1148    /*-- sanity checks --*/
1149 
1150    if( !IM3D_OPEN(im3d) ){ BEEPIT ; TAG_quit_CB(NULL,NULL,NULL) ; return ; }
1151 
1152    /*-- just show a chooser, let the user commune with the list --*/
1153 
1154    PLUTO_popup_dset_chooser( help_pb , im3d->vinfo->view_type , 0 ,
1155                              TAG_check_dataset , TAG_get_dset_CB , NULL ) ;
1156 
1157    return ;
1158 }
1159 
1160 /*--------------------------------------------------------------------------*/
1161 
TAG_save_CB(Widget w,XtPointer client_data,XtPointer call_data)1162 static void TAG_save_CB( Widget w, XtPointer client_data, XtPointer call_data )
1163 {
1164    if( !IM3D_OPEN(im3d) ){ BEEPIT ; TAG_quit_CB(NULL,NULL,NULL) ; return ; }
1165 
1166    if( dset == NULL ) return ;  /* nothing to do */
1167 
1168    if( dset->tagset == NULL ){
1169       dset->tagset = myXtNew(THD_usertaglist) ;
1170       ADDTO_KILL( dset->kl , dset->tagset ) ;
1171    }
1172 
1173    *(dset->tagset) = *mytagset ;  /* copy all data in one swell foop */
1174    *oldtagset      = *mytagset ;  /* backup copy is replaced */
1175 
1176    putenv("AFNI_DECONFLICT=OVERWRITE") ;
1177    DSET_overwrite_header(dset) ;
1178    TAG_redraw() ; DSET_ON ;
1179    return ;
1180 }
1181 
1182 /*--------------------------------------------------------------------------*/
1183 
TAG_onoff(int on)1184 static void TAG_onoff( int on )
1185 {
1186    RwcBoolean sen ;
1187    int ii ;
1188 
1189    sen = (RwcBoolean) on ;
1190    for( ii=0 ; onoff_wid[ii] != NULL ; ii++ )
1191       SENSITIZE( *(onoff_wid[ii]) , sen ) ;    /* see xutil.h */
1192 
1193    on_flag = on ;
1194    return ;
1195 }
1196 
1197 /*--------------------------------------------------------------------------*/
1198 
TAG_done_CB(Widget w,XtPointer client_data,XtPointer call_data)1199 static void TAG_done_CB( Widget w, XtPointer client_data, XtPointer call_data )
1200 {
1201    TAG_save_CB(NULL,NULL,NULL) ; dset = NULL ;
1202    TAG_quit_CB(NULL,NULL,NULL) ;
1203    return ;
1204 }
1205 
1206 /*--------------------------------------------------------------------------*/
1207 
TAG_get_copy_CB(int num,THD_3dim_dataset ** dslist,void * cd)1208 static void TAG_get_copy_CB( int num, THD_3dim_dataset ** dslist, void * cd )
1209 {
1210    char str[256] , * tnam ;
1211    THD_3dim_dataset * qset ;
1212    XmString xstr ;
1213 
1214    /*-- sanity checks --*/
1215 
1216    if( !IM3D_OPEN(im3d) || !editor_open ){
1217       BEEPIT ; POPDOWN_strlist_chooser ;
1218       TAG_quit_CB(NULL,NULL,NULL) ; return ;
1219    }
1220 
1221    if( num != 1 || dslist == NULL || !ISVALID_DSET(dslist[0]) ){ BEEPIT; return; }
1222 
1223    qset = dslist[0] ; if( qset->tagset == NULL ){ BEEPIT; return; }
1224 
1225    *mytagset = *(qset->tagset) ;
1226    tognum    = mytagset->num ;
1227 
1228    TAG_reset_widgets() ; TAG_redraw() ; DSET_OFF ;
1229    return ;
1230 }
1231 
1232 /*--------------------------------------------------------------------------*/
1233 
TAG_copy_CB(Widget w,XtPointer client_data,XtPointer call_data)1234 static void TAG_copy_CB( Widget w, XtPointer client_data, XtPointer call_data )
1235 {
1236    /*-- sanity checks --*/
1237 
1238    if( !IM3D_OPEN(im3d) ){ BEEPIT ; TAG_quit_CB(NULL,NULL,NULL) ; return ; }
1239 
1240    /*-- just show a chooser, let the user commune with the list --*/
1241 
1242    PLUTO_popup_dset_chooser( help_pb , im3d->vinfo->view_type , 0 ,
1243                              TAG_check_copyset , TAG_get_copy_CB , NULL ) ;
1244 
1245    return ;
1246 }
1247 
1248 /*--------------------------------------------------------------------------*/
1249 
TAG_help_CB(Widget w,XtPointer client_data,XtPointer call_data)1250 static void TAG_help_CB( Widget w, XtPointer client_data, XtPointer call_data )
1251 {
1252    (void ) new_MCW_textwin( help_pb ,
1253 
1254      "This plugin can be used to attach a collection of 'tags' to an anatomical\n"
1255      "dataset.  Each tag has associated with it a label, a set of (x,y,z)\n"
1256      "coordinates, and a numerical value.  If a tag is 'set', then a marker will\n"
1257      "be displayed at its location when the dataset is being viewed, and when\n"
1258      "'See Markers' is enabled on the AFNI control panel.  Tags that are not set\n"
1259      "are not shown and are not used for any purpose.\n"
1260 
1261      "\n"
1262      "The first step in defining a set of tags for a dataset is to pick the\n"
1263      "dataset to be operated upon.  Normally, this would be the dataset that\n"
1264      "you are viewing in some window (otherwise you won't see the tags).\n"
1265      "Choosing a dataset for tag operations is done with the 'Dataset' button\n"
1266      "at the top of the plugin interface.  This will popup a chooser that\n"
1267      "lets you select any anatomical dataset.  After you select the dataset,\n"
1268      "its existing tags (if any) are loaded into the plugin and can then\n"
1269      "be modified.\n"
1270 
1271      "\n"
1272      "There are two rows of control buttons below the 'Dataset' choice button.\n"
1273      "The first row handles large operations on the whole set of tags.  The\n"
1274      "second row is for retail operations on the status of individual tags.\n"
1275      "Most of the control buttons are deactivated until you select a dataset.\n"
1276      "Below these rows is a set of data entry fields, and below that a list\n"
1277      "of all the tags currently defined (whether set or not -- tags that are\n"
1278      "set are shown in inverted colors).  Each entry in the tag list has a\n"
1279      "selection button.  At most one tag can be selected at a given time.\n"
1280      "\n"
1281 
1282      "Row 1 buttons are:\n"
1283      "-----------------\n"
1284      "'Quit': Exit the plugin without saving changes back to the dataset.\n"
1285      "\n"
1286      "'Help': Display this message.\n"
1287      "\n"
1288      "'Read': Read in a tagset description file, replacing the current tag\n"
1289      "        definitions.  Each line in a tagset file (extension '.tag')\n"
1290      "        defines one tag.  The first entry on a line is the tag label.\n"
1291      "        If the label contains any blanks, it should be enclosed in\n"
1292      "        quotes (either \"double\" or 'single' quotes will work).\n"
1293      "        Following the label, it is legal to put three numbers, which\n"
1294      "        will be interpreted as the (x,y,z) coordinates of the tag.\n"
1295      "        If these numbers are present, the tag will be set and displayed.\n"
1296      "\n"
1297      "'Write': Write the current set of tags to a '.tag' file, which can\n"
1298      "         later be read back in using the 'Read' button.\n"
1299      "   N.B.: Tag coordinates are stored in Dicom order\n"
1300      "              x = R-L coordinate (R < 0, L > 0)\n"
1301      "              y = A-P coordinate (A < 0, P > 0)\n"
1302      "              z = I-S coordinate (I < 0, S > 0)\n"
1303      "\n"
1304      "'Copy': Copy the set of tags from another dataset.\n"
1305      "\n"
1306      "'Save': Save the current set of tags into the dataset .HEAD file.\n"
1307      "        If this is not done before 'Quit', then changes made to the\n"
1308      "        tagset will not be saved.\n"
1309      "\n"
1310      "'Done': Combines the operations of 'Save' and then 'Quit'.\n"
1311      "\n"
1312 
1313      "Row 2 buttons are:\n"
1314      "-----------------\n"
1315      "'Set': Sets the selected tag to be at the current crosshair location.\n"
1316      "\n"
1317      "'Clear': Un-sets the current tag.\n"
1318      "\n"
1319      "'Clr All': Un-sets all tags.\n"
1320      "\n"
1321      "'Add': Adds 1 new tag to the end of the list.  There is a maximum of\n"
1322      "       100 tags allowed.\n"
1323      "\n"
1324      "'Delete': Deletes the last tag from the list.\n"
1325      "\n"
1326      "'Relabel': Changes the label of the selected tag.\n"
1327      "\n"
1328 
1329      "Data entry fields are:\n"
1330      "---------------------\n"
1331      "'Tag File': You enter the name of the tagset file for 'Read' and 'Write'\n"
1332      "            operations here.\n"
1333      "\n"
1334      "'Tag Label': You enter the new label for the selected tag here, for use\n"
1335      "             with the 'Relabel' operation.\n"
1336      "\n"
1337      "'Tag Value': You enter the numerical value to be attached to a tag here,\n"
1338      "             for use with the 'Set' operation.\n"
1339      "\n"
1340 
1341      "Nota Bene\n"
1342      "---------\n"
1343      "The tag value is not used for anything yet.  Any suggestions?\n"
1344      "\n"
1345      "By using the 'Add', 'Delete', and 'Relabel' buttons, it is possible to\n"
1346      "create your own collection of tag definitions.  However, it is generally\n"
1347      "easier to use an external editor (e.g., 'vi') to create a .tag file and\n"
1348      "then read it in with the 'Read' button.\n"
1349      "\n"
1350      "Once you make a change to a tagset, the 'Dataset' button will be disabled\n"
1351      "until 'Save' is used.  This is a safety measure to help prevent accidental\n"
1352      "loss of changes.  If you want to discard the changes, use 'Quit'.\n"
1353      "\n"
1354      "The color of a dataset tag is controlled by the 'Primary Markers' color,\n"
1355      "which is set on the 'Define Markers' control panel in the main AFNI control\n"
1356      "window.  The tags are displayed as a cross within a diamond.\n"
1357      "\n"
1358      "The program 3dTagalign will read the tag coordinates from one dataset and\n"
1359      "rotate/translate that dataset to match the tag coordinates from another\n"
1360      "dataset (in the least squares sense).  See '3dTagalign -help' for details.\n"
1361      "\n"
1362      "============================\n"
1363      "AUTHOR: RW Cox, October 1998\n"
1364      "============================\n"
1365 
1366     , TEXT_READONLY ) ;
1367    return ;
1368 }
1369 
1370 /*--------------------------------------------------------------------------*/
1371 
1372 #define NMSG 6
1373 
TAG_beep_CB(Widget w,XtPointer client_data,XtPointer call_data)1374 static void TAG_beep_CB( Widget w, XtPointer client_data, XtPointer call_data )
1375 {
1376    static int nbeep = 0 ;
1377    static char * msg[] = { "What did you expect,\na choir of angels?"                ,
1378                            "Apparently some people\ncan't take a hint."              ,
1379                            "You aren't tired\nof this game YET?!"                    ,
1380                            "I'm getting tired of\nthis.  I'm warning you!"           ,
1381                            "This is the last time!\nOnce more, and you'll be sorry!" ,
1382                            "You can't say I didn't warn you.\nNyah Nyah Nyah."
1383                          } ;
1384 
1385    POPUP_MESG( msg[nbeep] ) ; nbeep++ ; BEEPIT ;
1386 
1387    if( nbeep >= NMSG ) SENSITIZE(beep_pb,False) ;
1388    return ;
1389 }
1390