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 
9 #include "afni.h"
10 #include "afni_plugout.h"
11 #include "mcw_malloc.h"
12 extern char **Atlas_Names_List(ATLAS_LIST *atl);
13 
14 static THD_3dim_dataset *atlas_ovdset = NULL;
15 
16 static float Thval[9] = { 1.0 , 10.0 , 100.0 , 1000.0 , 10000.0 ,
17                          100000.0 , 1000000.0 , 10000000.0 , 100000000.0 } ;
18 
19 static int reset_func_range_ncall[MAX_CONTROLLERS] ; /* initialized to 0 by C */
20 
21 /*-------------------------------------------------------------------
22    This routine is also used by the macros
23       AFNI_SEE_FUNC_ON and AFNI_SEE_FUNC_OFF
24    as well as the MCW_bbox that it is attached to as the callback.
25 ---------------------------------------------------------------------*/
26 
AFNI_see_func_CB(Widget w,XtPointer cd,XtPointer cb)27 void AFNI_see_func_CB( Widget w, XtPointer cd, XtPointer cb )
28 {
29    Three_D_View *im3d = (Three_D_View *) cd ;
30    int old_val , new_val ;
31 
32 ENTRY("AFNI_see_func_CB") ;
33 
34    if( ! IM3D_OPEN(im3d) ) EXRETURN ;
35 
36    im3d->vinfo->stats_anat_ok =
37     im3d->vinfo->stats_func_ok =
38      im3d->vinfo->arang_func_ok =
39       im3d->vinfo->stats_thresh_ok = 0 ; /* 24 May 2019 */
40 
41    old_val = (im3d->vinfo->func_visible) ? 1 : 0 ;
42    new_val = MCW_val_bbox( im3d->vwid->view->see_func_bbox ) ;
43 
44    if( old_val != new_val ){
45 #if 0
46      STATUS_IM3D_TMASK(im3d) ;
47      STATUS("clear tmask") ;
48 #endif
49      im3d->vinfo->func_visible = (new_val == 1) ? True : False ;
50      if( ! ISVALID_3DIM_DATASET(im3d->fim_now) ){            /* 29 Apr 1997 */
51        im3d->vinfo->func_visible = False ; new_val = 0 ;
52        MCW_set_bbox( im3d->vwid->view->see_func_bbox , 0 ) ; /* 29 Jan 1999 */
53      }
54      IM3D_CLEAR_TMASK(im3d) ;               /* Mar 2013 */
55      IM3D_CLEAR_THRSTAT(im3d) ;          /* 12 Jun 2014 */
56      OVERLAY_SUMA ;                      /* 16 Jun 2003 */
57      AFNI_redisplay_func( im3d ) ;       /* 05 Mar 2002 */
58      im3d->vinfo->func_visible_count++ ; /* 03 Aug 2007 */
59      if( new_val == 0 ){                 /* 21 Jul 2014 */
60        XtSetSensitive(im3d->vwid->func->pbar_jumpto_thmax_pb,False) ;
61        XtSetSensitive(im3d->vwid->func->pbar_jumpto_thmin_pb,False) ;
62      } else {
63        AFNI_setup_thrstat(im3d,1) ;     /* 27 Jun 2019 */
64      }
65    }
66 
67    AFNI_fix_scale_size_direct(im3d) ;  /* 03 Jun 2019 */
68    RESET_AFNI_QUIT(im3d) ;
69    EXRETURN ;
70 }
71 
72 /*---------------------------------------------------------------------------*/
73 /* Callback for "A" and "B" buttons on top of threshold slider [02 Nov 2018] */
74 /*---------------------------------------------------------------------------*/
75 
AFNI_func_thrtop_CB(Widget w,XtPointer cd,XtPointer cb)76 void AFNI_func_thrtop_CB( Widget w, XtPointer cd, XtPointer cb )
77 {
78    Three_D_View *im3d = (Three_D_View *) cd ;
79 
80 ENTRY("AFNI_thrtop_CB") ;
81    if( !IM3D_OPEN(im3d) ) EXRETURN ;
82 
83    if( w == im3d->vwid->func->thrtop_alpha_pb ){
84 
85      MCW_invert_widget(w) ;
86      im3d->vinfo->thr_use_alpha = !im3d->vinfo->thr_use_alpha ;
87      PBAR_force_bigexpose(im3d->vwid->func->inten_pbar) ;
88 
89    } else if( w == im3d->vwid->func->thrtop_boxed_pb ){
90 
91      MCW_invert_widget(w) ;
92      im3d->vinfo->thr_use_boxed = !im3d->vinfo->thr_use_boxed ;
93 
94    }
95 
96    IM3D_CLEAR_TMASK(im3d) ;
97    IM3D_CLEAR_THRSTAT(im3d) ;
98    AFNI_setup_thrstat(im3d,0) ;
99    AFNI_redisplay_func(im3d) ;
100    AFNI_set_window_titles(im3d) ;
101    AFNI_fix_scale_size_direct(im3d) ;  /* 03 Jun 2019 */
102 
103    EXRETURN ;
104 }
105 
106 /*-----------------------------------------------------------------------*/
107 /*! Get the threshold automatically.  [05 Mar 2007]
108 -------------------------------------------------------------------------*/
109 
AFNI_get_autothresh(Three_D_View * im3d)110 float AFNI_get_autothresh( Three_D_View *im3d )
111 {
112    MRI_IMAGE *thrim ;
113    float thrval,pval=0.0f ; int ival ;
114 
115 ENTRY("AFNI_get_autothresh") ;
116 
117    if( !IM3D_OPEN(im3d) || !ISVALID_DSET(im3d->fim_now) ) RETURN(-1.0f) ;
118 
119    ival = im3d->vinfo->thr_index ;  /* threshold sub-brick index */
120 
121    if( DSET_BRICK_STATCODE(im3d->fim_now,ival) > 0 )
122      pval = THD_pval_to_stat( 1.e-3 ,
123                               DSET_BRICK_STATCODE(im3d->fim_now,ival) ,
124                               DSET_BRICK_STATAUX (im3d->fim_now,ival)  ) ;
125 
126    DSET_load( im3d->fim_now ) ;
127    thrim  = DSET_BRICK(im3d->fim_now,ival) ;
128    thrval = THD_cliplevel_abs( thrim , -0.500f ) ;
129    if( DSET_BRICK_FACTOR(im3d->fim_now,ival) > 0.0f )
130      thrval *= DSET_BRICK_FACTOR(im3d->fim_now,ival) ;
131 
132    if( pval > 0.0f )
133      thrval = (thrval <= 0.0f) ? pval : sqrt(thrval*pval) ;
134 
135    if( thrval == 0.0f ) thrval = -1.0f ;
136    RETURN(thrval) ;
137 }
138 
139 /*-----------------------------------------------------------------------*/
140 /*! 25 Jul 2007 */
141 
AFNI_func_autothresh_CB(Widget w,XtPointer cd,XtPointer cb)142 void AFNI_func_autothresh_CB( Widget w, XtPointer cd, XtPointer cb )
143 {
144    Three_D_View *im3d = (Three_D_View *)cd ;
145    float new_thresh ;
146 
147 ENTRY("AFNI_func_autothresh_CB") ;
148 
149    if( !IM3D_OPEN(im3d) ) EXRETURN ;
150 
151 #if 0
152    STATUS_IM3D_TMASK(im3d) ;
153    STATUS("clear tmask") ;
154 #endif
155    IM3D_CLEAR_TMASK(im3d) ;                                /* Mar 2013 */
156    IM3D_CLEAR_THRSTAT(im3d) ;                           /* 12 Jun 2014 */
157    new_thresh = AFNI_get_autothresh(im3d) ;
158    if( new_thresh > 0.0f ) AFNI_set_threshold(im3d,new_thresh) ;
159    AFNI_fix_scale_size_direct(im3d) ;  /* 03 Jun 2019 */
160    EXRETURN ;
161 }
162 
163 /*-----------------------------------------------------------------------*/
164 /*! 03 Dec 2013 */
165 
166 #define TFLASH(iq) \
167   do{ MCW_flash_widget(2,(iq)->vwid->func->thr_scale); BEEPIT; } while(0)
168 
AFNI_set_pval(Three_D_View * im3d,float pval)169 void AFNI_set_pval( Three_D_View *im3d , float pval )
170 {
171    float thresh ; int sig , scode ;
172 
173 ENTRY("AFNI_set_pval") ;
174 
175    if( !IM3D_OPEN(im3d) || pval <= 0.0f || pval >= 1.0f ) EXRETURN ;
176    if( DSET_BRICK_STATCODE(im3d->fim_now,im3d->vinfo->thr_index) <= 0 ){
177      TFLASH(im3d) ; EXRETURN ;
178    }
179 
180    scode = DSET_BRICK_STATCODE(im3d->fim_now,im3d->vinfo->thr_index) ;
181    sig   = THD_stat_is_2sided( scode , 0 ) ;
182    if( sig > 0 && im3d->vinfo->thr_sign > 0 && scode != FUNC_FT_TYPE )
183      pval *= 2.0f ;  /* Jan 2015 */
184 
185    thresh = THD_pval_to_stat( pval ,
186               DSET_BRICK_STATCODE(im3d->fim_now,im3d->vinfo->thr_index) ,
187               DSET_BRICK_STATAUX (im3d->fim_now,im3d->vinfo->thr_index)  ) ;
188    if( thresh < 0.0 ){ TFLASH(im3d); EXRETURN; }
189 
190    AFNI_set_threshold(im3d,thresh) ;
191    EXRETURN ;
192 }
193 
194 /*--- set threshold 16 Jul 2020 discoraj --------------------*/
195 
AFNI_func_setthresh_final_CB(Widget w,XtPointer cd,MCW_choose_cbs * cbs)196 void AFNI_func_setthresh_final_CB( Widget w, XtPointer cd, MCW_choose_cbs *cbs )
197 {
198    Three_D_View *im3d = (Three_D_View *)cd ;
199    float thresh ;
200    char *cpt ;
201    char contlab[2] , threshstr[32];
202    char drvmsg[256] = "SET_THRESHNEW ";
203 
204 ENTRY("AFNI_func_setthresh_final_CB") ;
205 
206    if( !IM3D_OPEN(im3d) ) EXRETURN ;
207 
208    if( cbs->reason  != mcwCR_string ||
209        cbs->cval    == NULL         ||
210        cbs->cval[0] == '\0'           ){ TFLASH(im3d); EXRETURN; }
211 
212    // get new threshold and no negatives to string
213    thresh = (float)strtod(cbs->cval,&cpt) ;
214    if( thresh < 0.0f ){ TFLASH(im3d); EXRETURN; }
215    sprintf(threshstr, "%f", thresh);
216 
217    // fix the stat if dataset changes...
218    im3d->vinfo->fix_qval   = 0 ;
219    im3d->vinfo->fixed_qval = 0.0f ;
220    im3d->vinfo->fix_pval   = 0 ;
221    im3d->vinfo->fixed_pval = 0.0f ;
222 
223    // get the controller label single letter only
224    memcpy( contlab, &AFNI_controller_label(im3d)[1], 1 );
225    contlab[1] = '\0';
226 
227    // combine everything into 1 string
228    strcat(drvmsg,contlab) ; strcat(drvmsg," ") ; strcat(drvmsg,threshstr) ;
229 
230    // drive to change the threshold
231    AFNI_driver(drvmsg);
232 
233    // fix pbar size
234    AFNI_fix_scale_size_direct(im3d) ;  /* 03 Jun 2019 */
235    EXRETURN ;
236 }
237 
238 /*---------- set threshold 16 Jul 2020 discoraj ----------------------*/
239 
AFNI_func_setthresh_CB(Widget w,XtPointer cd,XtPointer cb)240 void AFNI_func_setthresh_CB( Widget w, XtPointer cd, XtPointer cb )
241 {
242    Three_D_View *im3d = (Three_D_View *)cd ;
243 
244 ENTRY("AFNI_func_setthresh_CB") ;
245 
246    if( !IM3D_OPEN(im3d) ) EXRETURN ;
247 
248    MCW_choose_string(w,"Enter threshold",NULL,AFNI_func_setthresh_final_CB,cd) ;
249    EXRETURN ;
250 }
251 
252 /*-----------------------------------------------------------------------*/
253 
AFNI_func_setpval_final_CB(Widget w,XtPointer cd,MCW_choose_cbs * cbs)254 void AFNI_func_setpval_final_CB( Widget w, XtPointer cd, MCW_choose_cbs *cbs )
255 {
256    Three_D_View *im3d = (Three_D_View *)cd ;
257    float pval , thresh ;
258    int newdec , olddec , stop,smax , ival ;
259    char *cpt ;
260 
261 ENTRY("AFNI_func_setpval_final_CB") ;
262 
263    if( !IM3D_OPEN(im3d) ) EXRETURN ;
264 
265    if( cbs->reason  != mcwCR_string ||
266        cbs->cval    == NULL         ||
267        cbs->cval[0] == '\0'           ){ TFLASH(im3d); EXRETURN; }
268 
269    if( DSET_BRICK_STATCODE(im3d->fim_now,im3d->vinfo->thr_index) <= 0 ){
270      TFLASH(im3d) ; EXRETURN ;
271    }
272 
273    pval = (float)strtod(cbs->cval,&cpt) ;
274    if( pval >  0.0f && *cpt == '%'  ) pval *= 0.01f ;
275    if( pval <= 0.0f || pval >= 1.0f ){ TFLASH(im3d); EXRETURN; }
276 
277    im3d->vinfo->fix_qval   = 0 ;
278    im3d->vinfo->fixed_qval = 0.0f ;
279 
280    AFNI_set_pval(im3d,pval) ;
281    AFNI_fix_scale_size_direct(im3d) ;  /* 03 Jun 2019 */
282    EXRETURN ;
283 }
284 
285 /*-----------------------------------------------------------------------*/
286 
AFNI_func_setpval_CB(Widget w,XtPointer cd,XtPointer cb)287 void AFNI_func_setpval_CB( Widget w, XtPointer cd, XtPointer cb )
288 {
289    Three_D_View *im3d = (Three_D_View *)cd ;
290 
291 ENTRY("AFNI_func_setpval_CB") ;
292 
293    if( !IM3D_OPEN(im3d) ) EXRETURN ;
294 
295    MCW_choose_string( w, "Enter p-value", NULL, AFNI_func_setpval_final_CB,cd ) ;
296    EXRETURN ;
297 }
298 
299 /*-----------------------------------------------------------------------*/
300 
AFNI_func_setpval_001_CB(Widget w,XtPointer cd,XtPointer cb)301 void AFNI_func_setpval_001_CB( Widget w, XtPointer cd, XtPointer cb )
302 {
303    MCW_choose_cbs cbs ;
304 
305 ENTRY("AFNI_func_setpval_001_CB") ;
306 
307    cbs.reason = mcwCR_string ;
308    cbs.cval   = "0.001" ;
309    AFNI_func_setpval_final_CB( w , cd , &cbs ) ;
310    EXRETURN ;
311 }
312 
313 /*-----------------------------------------------------------------------*/
314 /*! 26 Feb 2014 */
315 
AFNI_set_qval(Three_D_View * im3d,float qval)316 void AFNI_set_qval( Three_D_View *im3d , float qval )
317 {
318    float zval , thresh ;
319 
320 ENTRY("AFNI_set_qval") ;
321 
322    if( !IM3D_OPEN(im3d) || qval <= 0.0f || qval >= 1.0f ) EXRETURN ;
323    if( DSET_BRICK_STATCODE(im3d->fim_now,im3d->vinfo->thr_index) <= 0 ){
324      TFLASH(im3d) ; EXRETURN ;
325    }
326 
327    zval   = qginv(0.5*qval) ;
328    thresh = THD_fdrcurve_zqtot( im3d->fim_now , im3d->vinfo->thr_index , zval ) ;
329    if( thresh <= 0.0 ){ TFLASH(im3d); EXRETURN; }
330 
331    AFNI_set_threshold(im3d,thresh) ;
332    EXRETURN ;
333 }
334 
335 /*-----------------------------------------------------------------------*/
336 
337 static char *yesno[2] = { "No" , "Yes" } ;
338 
AFNI_func_setqval_final_CB(Widget w,XtPointer cd,int nval,void ** val)339 void AFNI_func_setqval_final_CB( Widget w, XtPointer cd, int nval , void **val )
340 {
341    Three_D_View *im3d = (Three_D_View *)cd ;
342    float qval , zval , thresh ;
343    char *cpt ;
344 
345 ENTRY("AFNI_func_setqval_final_CB") ;
346 
347    if( !IM3D_OPEN(im3d) || nval != 2 || val == NULL ) EXRETURN ;
348 
349    if( DSET_BRICK_STATCODE(im3d->fim_now,im3d->vinfo->thr_index) <= 0 ){
350     TFLASH(im3d) ; EXRETURN ;
351    }
352 
353    qval = (float)strtod((char *)val[0],&cpt) ;
354    if( qval > 0.0f && *cpt == '%'  ) qval *= 0.01f ;
355    if( qval < 0.0f || qval >= 1.0f ){ TFLASH(im3d); EXRETURN; }
356 
357    im3d->vinfo->fix_qval   = ( qval > 0.0f && strcmp((char *)val[1],yesno[1]) == 0 ) ;
358    im3d->vinfo->fixed_qval = (im3d->vinfo->fix_qval) ? qval : 0.0f ;
359 
360    im3d->vinfo->fix_pval   = 0 ;
361    im3d->vinfo->fixed_pval = 0.0f ;
362 
363    if( qval > 0.0f ) AFNI_set_qval(im3d,qval) ;
364    EXRETURN ;
365 }
366 
367 /*-----------------------------------------------------------------------*/
368 
AFNI_func_setqval_CB(Widget w,XtPointer cd,XtPointer cb)369 void AFNI_func_setqval_CB( Widget w, XtPointer cd, XtPointer cb )
370 {
371    Three_D_View *im3d = (Three_D_View *)cd ;
372    int ifix ;
373 
374 ENTRY("AFNI_func_setqval_CB") ;
375 
376    if( !IM3D_OPEN(im3d) ) EXRETURN ;
377 
378    ifix = (im3d->vinfo->fix_qval) ? 1 : 0 ;
379 
380    MCW_choose_stuff( w , "FDR q-value Settings" ,
381                      AFNI_func_setqval_final_CB , im3d ,
382                        MSTUF_STRING  , "Set q-value"  ,
383                        MSTUF_STRLIST , "Keep fixed? " , 2 , ifix , yesno ,
384                      MSTUF_END ) ;
385    EXRETURN ;
386 }
387 
388 /*-----------------------------------------------------------------------*/
389 /*! 29 Jan 2008: add FDR curves to the functional dataset */
390 
AFNI_func_fdr_CB(Widget w,XtPointer cd,XtPointer cb)391 void AFNI_func_fdr_CB( Widget w, XtPointer cd, XtPointer cb )
392 {
393    Three_D_View *im3d = (Three_D_View *)cd ;
394    THD_3dim_dataset *dset ; int nf ;
395 
396 ENTRY("AFNI_func_fdr_CB") ;
397 
398    if( !IM3D_OPEN(im3d) || !ISVALID_DSET(im3d->fim_now) ) EXRETURN ;
399    dset = im3d->fim_now ;
400    SHOW_AFNI_PAUSE ;
401    nf = THD_create_all_fdrcurves(dset) ;
402    AFNI_set_thr_pval(im3d) ;
403    INFO_message("Computed %d FDR curves in %s [but not saved on disk]" ,
404                 nf , DSET_FILECODE(dset) ) ;
405    SHOW_AFNI_READY ;
406 
407    EXRETURN ;
408 }
409 
410 /*-----------------------------------------------------------------------*/
411 /*! 08 Aug 2007 */
412 
AFNI_func_thrsign_CB(MCW_arrowval * av,XtPointer cd)413 void AFNI_func_thrsign_CB( MCW_arrowval *av , XtPointer cd )
414 {
415    Three_D_View *im3d = (Three_D_View *) cd ;
416 
417 ENTRY("AFNI_func_thrsign_CB") ;
418 
419    if( !IM3D_OPEN(im3d) ) EXRETURN ;
420 
421    im3d->vinfo->thr_sign = av->ival ;
422 #if 0
423    STATUS_IM3D_TMASK(im3d) ;
424    STATUS("clear tmask") ;
425 #endif
426    IM3D_CLEAR_TMASK(im3d) ;                                /* Mar 2013 */
427    IM3D_CLEAR_THRSTAT(im3d) ;                           /* 12 Jun 2014 */
428    AFNI_setup_thrstat(im3d,0) ;
429    AFNI_set_thr_pval( im3d ) ;                             /* Jan 2015 */
430    AFNI_redisplay_func( im3d ) ;
431    AFNI_set_window_titles( im3d ) ;
432    AFNI_fix_scale_size_direct(im3d) ;  /* 03 Jun 2019 */
433    EXRETURN ;
434 }
435 
436 /*---------------------------------------------------------------------------*/
437 /* Re-imagined alpha callback for choosing Linear or Quadratic [28 Jun 2021] */
438 
AFNI_func_alpha_CB(MCW_arrowval * av,XtPointer cd)439 void AFNI_func_alpha_CB( MCW_arrowval *av , XtPointer cd )
440 {
441    Three_D_View *im3d = (Three_D_View *)cd ;
442 
443 ENTRY("AFNI_func_alpha_CB") ;
444 
445    if( !IM3D_OPEN(im3d) || !im3d->vinfo->thr_use_alpha ) EXRETURN ;
446 
447    IM3D_CLEAR_TMASK(im3d) ;
448    IM3D_CLEAR_THRSTAT(im3d) ;
449    AFNI_redisplay_func( im3d ) ;
450    AFNI_set_window_titles( im3d ) ;
451    EXRETURN ;
452 }
453 
454 #if 0 /*** old alpha stuff, now replaced by the 'A' button ***/
455 /*-----------------------------------------------------------------------*/
456 /*! 09 Dec 2014 */
457 
458 void AFNI_func_floor_CB( MCW_arrowval *av , XtPointer cd )
459 {
460    Three_D_View *im3d = (Three_D_View *)cd ;
461 
462 ENTRY("AFNI_func_floor_CB") ;
463 
464    if( !IM3D_OPEN(im3d) ) EXRETURN ;
465 
466    im3d->vinfo->thr_alpha_floor = av->ival * 0.2f ;
467 #if 0
468    STATUS_IM3D_TMASK(im3d) ;
469    STATUS("clear tmask") ;
470 #endif
471    IM3D_CLEAR_TMASK(im3d) ;
472    IM3D_CLEAR_THRSTAT(im3d) ;
473    AFNI_redisplay_func( im3d ) ;
474    AFNI_set_window_titles( im3d ) ;
475    EXRETURN ;
476 }
477 #endif /*------------- end of old alpha stuff ---------------------------*/
478 
479 /*-----------------------------------------------------------------------*/
480 /*! Set the threshold and slider.  [05 Mar 2007]
481 -------------------------------------------------------------------------*/
482 
AFNI_set_threshold(Three_D_View * im3d,float val)483 void AFNI_set_threshold( Three_D_View *im3d , float val )
484 {
485    int olddec,newdec , smax,stop , ival ;
486 
487 ENTRY("AFNI_set_threshold") ;
488 
489    if( !IM3D_OPEN(im3d) || val < 0.0f || val > THR_top_value ) EXRETURN;
490 
491    /* get current scale decimal setting */
492 
493    olddec = (int)rint( log10(im3d->vinfo->func_thresh_top) ) ;
494         if( olddec < 0             ) olddec = 0 ;
495    else if( olddec > THR_top_expon ) olddec = THR_top_expon ;
496    newdec = olddec ;
497 
498    if( val > 0.0f ){
499      newdec = (int)( log10(val) + 1.0 ) ;
500           if( newdec < 0             ) newdec = 0 ;
501      else if( newdec > THR_top_expon ) newdec = THR_top_expon ;
502      if( newdec != olddec )
503        AFNI_set_thresh_top( im3d , Thval[newdec] ) ;
504    }
505 
506    smax  = (int)rint( pow(10.0,THR_top_expon) ) ;
507    stop  = smax - 1 ;                             /* max slider value */
508 
509    ival = rint( val/(THR_factor*Thval[newdec]) ) ;
510         if( ival < 0    ) ival = 0    ;
511    else if( ival > stop ) ival = stop ;
512 
513 #if 0
514    STATUS_IM3D_TMASK(im3d) ;
515    STATUS("clear tmask") ;
516 #endif
517    IM3D_CLEAR_TMASK(im3d) ;                                /* Mar 2013 */
518    IM3D_CLEAR_THRSTAT(im3d) ;                           /* 12 Jun 2014 */
519    AFNI_setup_thrstat(im3d,0) ;
520    XmScaleSetValue( im3d->vwid->func->thr_scale , ival ) ;
521    AFNI_thr_scale_CB( im3d->vwid->func->thr_scale, (XtPointer)im3d, NULL ) ;
522    FIX_SCALE_SIZE(im3d) ;
523    AFNI_thresh_lock_carryout(im3d) ;
524    EXRETURN ;
525 }
526 
527 /*-----------------------------------------------------------------------
528    Called when the scale for the threshold is adjusted.
529    30 Oct 1996: changed scale factor from slider to threshold
530                 from 0.01 to 0.001 to allow for increased
531                 precision of scale (0..999 instead of 0..99).
532 -------------------------------------------------------------------------*/
533 
AFNI_thr_scale_CB(Widget w,XtPointer client_data,XtPointer call_data)534 void AFNI_thr_scale_CB( Widget w, XtPointer client_data, XtPointer call_data )
535 {
536    Three_D_View *im3d = (Three_D_View *) client_data ;
537    XmScaleCallbackStruct *cbs = (XmScaleCallbackStruct *) call_data ;
538    float fff ;
539    int ival ;
540 
541 ENTRY("AFNI_thr_scale_CB") ;
542 
543    if( ! IM3D_OPEN(im3d) ) EXRETURN ;
544 
545    if( cbs != NULL ) ival = cbs->value ;
546    else              XmScaleGetValue( w , &ival ) ;
547 
548    fff = THR_factor * ival ;
549    if( fff >= 0.0 && fff <= 1.0 ) im3d->vinfo->func_threshold = fff ;
550 
551    FIX_SCALE_VALUE(im3d) ;
552    FIX_SCALE_SIZE(im3d) ;   /* 09 May 2001 */
553 
554    AFNI_set_thr_pval( im3d ) ;
555 
556    MCW_discard_events_all( w , ButtonPressMask ) ;  /* 20 Mar 2007 */
557 
558 #if 0
559    STATUS_IM3D_TMASK(im3d) ;
560    STATUS("clear tmask") ;
561 #endif
562    IM3D_CLEAR_TMASK(im3d) ;                                /* Mar 2013 */
563    IM3D_CLEAR_THRSTAT(im3d) ;                           /* 12 Jun 2014 */
564    AFNI_setup_thrstat(im3d,0) ;
565    if( ! DOING_REALTIME_WORK ) AFNI_redisplay_func( im3d ) ;
566 
567    AFNI_thresh_lock_carryout(im3d) ;  /* 06 Feb 2004 */
568 
569    RESET_AFNI_QUIT(im3d) ;
570    EXRETURN ;
571 }
572 
573 /*--------------------------------------------------------------------
574   Called when the user drags the threshold scale at all, even
575   without releasing it.  Used to update the "p-value" interactively.
576 ----------------------------------------------------------------------*/
577 
AFNI_thr_scale_drag_CB(Widget w,XtPointer client_data,XtPointer call_data)578 void AFNI_thr_scale_drag_CB( Widget w, XtPointer client_data, XtPointer call_data )
579 {
580    Three_D_View *im3d = (Three_D_View *) client_data ;
581    XmScaleCallbackStruct *cbs = (XmScaleCallbackStruct *) call_data ;
582    float fff ;
583 
584 ENTRY("AFNI_thr_scale_drag CB") ;
585 
586    if( IM3D_OPEN(im3d) && ISVALID_3DIM_DATASET(im3d->fim_now) ){
587 
588       fff = THR_factor * cbs->value ;
589       if( fff >= 0.0 && fff <= 1.0 ) im3d->vinfo->func_threshold = fff ;
590 
591       FIX_SCALE_VALUE(im3d) ;
592       if( FUNC_HAVE_PVAL(DSET_BRICK_STATCODE(im3d->fim_now,im3d->vinfo->thr_index)) )
593         AFNI_set_thr_pval( im3d ) ;
594 
595       AFNI_thrdrag_lock_carryout( im3d ) ; /* 10 Feb 2004 */
596    }
597    EXRETURN ;
598 }
599 
600 /*-----------------------------------------------------------------------
601   Set the top value used on the threshold slider.
602   (Should be followed by a function redisplay if needed.)
603 -------------------------------------------------------------------------*/
604 
AFNI_set_thresh_itop(Three_D_View * im3d,int itop)605 void AFNI_set_thresh_itop( Three_D_View *im3d , int itop )
606 {
607    AFNI_set_thresh_top( im3d, Thval[itop] ) ;
608 }
609 
AFNI_set_thresh_top(Three_D_View * im3d,float tval)610 void AFNI_set_thresh_top( Three_D_View *im3d , float tval )
611 {
612    int decim ;
613 
614 ENTRY("AFNI_set_thresh_top") ;
615 
616    if( ! IM3D_OPEN(im3d) ) EXRETURN ;
617 
618    if( tval <= 0.0 ) tval = 1.0 ;
619 
620    decim = (2*THR_top_expon) - (int)(THR_top_expon + 0.01 + log10(tval)) ;
621    if( decim < 0 ) decim = 0 ;
622 
623    XtVaSetValues( im3d->vwid->func->thr_scale, XmNdecimalPoints, decim, NULL ) ;
624 
625    im3d->vinfo->func_thresh_top = tval ;
626 
627 #if 0
628    STATUS_IM3D_TMASK(im3d) ;
629    STATUS("clear tmask") ;
630 #endif
631    IM3D_CLEAR_TMASK(im3d) ;                                /* Mar 2013 */
632    IM3D_CLEAR_THRSTAT(im3d) ;                           /* 12 Jun 2014 */
633    AFNI_setup_thrstat(im3d,0) ;
634    FIX_SCALE_VALUE(im3d) ;
635    FIX_SCALE_SIZE(im3d) ;   /* 09 May 2001 */
636    AFNI_set_thr_pval( im3d ) ;
637 
638    /** fix the option menu at the bottom of the scale **/
639 
640    decim = THR_top_expon - decim ;
641    if( decim != im3d->vwid->func->thr_top_av->ival )
642      AV_assign_ival( im3d->vwid->func->thr_top_av , decim ) ;
643 
644    EXRETURN ;
645 }
646 
647 /*-----------------------------------------------------------------------
648   Return the label for the threshold top chooser.
649 -------------------------------------------------------------------------*/
650 
AFNI_thresh_tlabel_CB(MCW_arrowval * av,XtPointer junk)651 char * AFNI_thresh_tlabel_CB( MCW_arrowval *av , XtPointer junk )
652 {
653    static char tlab[8] ;
654    sprintf(tlab,"%d",av->ival) ;
655    return tlab ;
656 }
657 
658 /*-----------------------------------------------------------------------
659   Take action when the user changes the threshold top chooser.
660 -------------------------------------------------------------------------*/
661 
AFNI_thresh_top_CB(MCW_arrowval * av,XtPointer cd)662 void AFNI_thresh_top_CB( MCW_arrowval *av , XtPointer cd )
663 {
664    Three_D_View *im3d = (Three_D_View *) cd ;
665 
666 ENTRY("AFNI_thresh_top_CB") ;
667 
668    if( IM3D_OPEN(im3d) && im3d->vinfo->func_thresh_top != Thval[av->ival] ){
669 
670      AFNI_set_thresh_top( im3d , Thval[av->ival] ) ;
671      FIX_SCALE_SIZE(im3d) ;
672 
673      if( im3d->vinfo->func_visible ) AFNI_redisplay_func( im3d ) ;
674 
675      AFNI_thresh_lock_carryout(im3d) ;  /* 06 Feb 2004 */
676    }
677 
678    AFNI_fix_scale_size_direct(im3d) ;  /* 03 Jun 2019 */
679    EXRETURN ;
680 }
681 
682 /*-----------------------------------------------------------------------*/
683 /* Something silly from Ziad */
684 
AFNI_thresh_from_percentile(Three_D_View * im3d,float perc)685 float AFNI_thresh_from_percentile( Three_D_View *im3d, float perc)
686 {
687    float *fv, thresh=0.0;
688    int ithr;
689 
690    if (!(fv = get_3Dview_sort(im3d, "T"))) return(perc);
691 
692    ithr = (int)(perc*(float)(im3d->vinfo->N_th_sort-1)+0.5);
693    if (ithr < 0) {
694       thresh = fv[0]-1.0;
695    } else if (ithr > im3d->vinfo->N_th_sort) {
696       thresh = fv[im3d->vinfo->N_th_sort-1]+1.0;
697    } else {
698       thresh = fv[ithr];
699    }
700 
701    #if 0
702    INFO_message(  "Top val %f, bottom val %f\n"
703                   "Sorting on set of %d voxels out of %d voxels in grid.\n"
704                   "Thresholding bottom %f%% thresh=%f, ithr=%d.\n"
705                   ,
706                    fv[im3d->vinfo->N_th_sort-1], fv[0],
707                    im3d->vinfo->N_th_sort, DSET_NVOX(im3d->fim_now),
708                    100*perc, thresh, ithr
709                    );
710    #endif
711    return(thresh);
712 }
713 
714 /*-----------------------------------------------------------------------
715   Used to set the pval (significance) label at the bottom of the
716   threshold scale.  And the qval (FDR) label.
717 -------------------------------------------------------------------------*/
718 
AFNI_set_thr_pval(Three_D_View * im3d)719 void AFNI_set_thr_pval( Three_D_View *im3d )
720 {
721    float thresh , pval , zval , spval ;
722    char  buf[32] ; int sig , scode ;
723 
724 ENTRY("AFNI_set_thr_pval") ;
725 
726    if( ! IM3D_OPEN(im3d) || ! ISVALID_3DIM_DATASET(im3d->fim_now) ) EXRETURN ;
727 
728    thresh = get_3Dview_func_thresh(im3d,1);
729 
730    /* get the p-value that goes with this threshold, for this functional dataset */
731 
732    pval = THD_stat_to_pval( thresh ,
733               DSET_BRICK_STATCODE(im3d->fim_now,im3d->vinfo->thr_index) ,
734               DSET_BRICK_STATAUX (im3d->fim_now,im3d->vinfo->thr_index)  ) ;
735 
736    /* modify it if the threshold statistic is 2-sided but we are thresholding 1-sided */
737 
738    scode = DSET_BRICK_STATCODE(im3d->fim_now,im3d->vinfo->thr_index) ;
739    if( im3d->vinfo->thr_sign == 0 || scode == FUNC_FT_TYPE )
740      sig = 0 ;
741    else
742      sig = THD_stat_is_2sided( scode , 0 ) ;
743    spval = pval ; if( sig > 0 ) spval *= 0.5f ;             /* Jan 2015 */
744 
745    im3d->vinfo->func_pval = spval ;  /* 06 Feb 2004 -- changed to spval Jan 2015 */
746    im3d->vinfo->func_qval = 0.0f  ;  /* 23 Jan 2008 */
747 
748 if(PRINT_TRACING)
749 { char buf[128] ;
750   sprintf( buf, "thresh=%g  top=%g  pval=%g",
751            thresh,im3d->vinfo->func_thresh_top,spval ) ; STATUS(buf) ; }
752 
753    if( pval < 0.0 ){
754      strcpy( buf , THR_PVAL_LABEL_NONE ) ;
755    } else {
756      if( spval == 0.0 ){
757        strcpy( buf , "p=0" ) ;
758      } else if( spval >= 0.9999 ){
759        strcpy( buf , "p=1" ) ;
760      } else if( spval >= 0.0010 ){
761        char qbuf[20] ;
762        sprintf( qbuf , "%5.4f" , spval ) ;
763        strcpy(buf,"p=") ; strcat( buf , qbuf+1 ) ; /* qbuf+1 skips leading 0 */
764      } else {
765        int dec = (int)(0.999 - log10(spval)) ;
766        zval = spval * pow( 10.0 , (double) dec ) ;  /* between 1 and 10 */
767        if( dec < 10 ) sprintf( buf , "p=%3.1f-%1d" ,           zval , dec ) ;
768        else           sprintf( buf , "p=%1d.-%2d"  , (int)rint(zval), dec ) ;
769      }
770      if( im3d->vedset.code > 0 && im3d->fim_now->dblk->vedim != NULL )
771        strcat(buf,"*") ;  /* mark that are in clustering mode [05 Sep 2006] */
772      else if( im3d->vinfo->fix_pval && fabsf(im3d->vinfo->fixed_pval-pval)<1.e-4f )
773        strcat(buf,"f") ;
774    }
775 
776    /* 23 Jan 2007: q-value from FDR curve? */
777 
778    if( pval >= 0.0 ){
779      zval = THD_fdrcurve_zval( im3d->fim_now, im3d->vinfo->thr_index, thresh ) ;
780      if( zval > 0.0f ){
781        float qval = 2.0*qg(zval) ;         /* convert z back to FDR q */
782        im3d->vinfo->func_qval = qval ;
783        if( qval > 0.0f && qval < 0.9999 ){
784          char qbuf[20] ;
785          if( qval >= 0.0010 ) sprintf(qbuf,"%5.4f",qval) ;
786          else {
787            int dec = (int)(0.999 - log10(qval)) ;
788            zval = qval * pow( 10.0 , (double)dec ) ;  /* between 1 and 10 */
789            if( dec < 10 ) sprintf( qbuf, " %3.1f-%1d",            zval, dec );
790            else           sprintf( qbuf, " %1d.-%2d" , (int)rint(zval), dec );
791          }
792          strcat(buf,"\nq=") ; strcat(buf,qbuf+1) ;
793          if( im3d->vinfo->fix_qval && fabsf(im3d->vinfo->fixed_qval-qval)<1.e-4f )
794            strcat(buf,"f") ;
795        }
796      } else {
797        strcat(buf,"\nq=N/A") ;
798      }
799    }
800 
801    MCW_set_widget_label( im3d->vwid->func->thr_pval_label , buf ) ;
802 
803    if( im3d->vinfo->func_pval >= 0.0f && im3d->vinfo->func_pval <= 1.0f ){
804 #define EEEE 2.718282f /* e */
805 #define EINV 0.367879f /* 1/e */
806      char pstr[128] ; float mval ;
807      sprintf( pstr , "Uncorrected p=%.4e" , im3d->vinfo->func_pval ) ;
808      if( im3d->vinfo->func_pval > 0.0f && im3d->vinfo->func_pval < EINV &&
809          THD_stat_is_2sided( DSET_BRICK_STATCODE(im3d->fim_now,im3d->vinfo->thr_index),
810                              im3d->vinfo->thr_sign) > 0 )
811        sprintf(pstr+strlen(pstr)," alpha(p)=%.4e",
812                1/(1-1/(EEEE*im3d->vinfo->func_pval*log(im3d->vinfo->func_pval))) ) ;
813      if( im3d->vinfo->func_qval >= 0.0f && im3d->vinfo->func_qval <= 1.0f )
814        sprintf(pstr+strlen(pstr),"; FDR q=%.4e",im3d->vinfo->func_qval) ;
815      else
816        sprintf(pstr+strlen(pstr),"; FDR q=N/A") ;
817      mval = THD_mdfcurve_mval( im3d->fim_now, im3d->vinfo->thr_index ,
818                                               im3d->vinfo->func_pval  ) ;
819 #if 1
820      if( mval >= 0.0f )
821        sprintf(pstr+strlen(pstr),"; MDF=%.1f%%",100.0f*mval) ;
822      else
823        strcat(pstr,"; MDF=N/A") ;
824 #else
825        sprintf(pstr+strlen(pstr),"; MDF=%.1f%%",100.0f*mval) ;
826 #endif
827      MCW_register_hint( im3d->vwid->func->thr_pval_label , pstr ) ;
828    } else {
829      MCW_register_hint( im3d->vwid->func->thr_pval_label ,
830                         "Uncorrected p-value per voxel"    ) ;
831    }
832 
833    FIX_SCALE_SIZE(im3d) ;
834    EXRETURN ;
835 }
836 
837 /*---------------------------------------------------------------------------
838    30 Mar 2001: add range hints to a pbar
839 -----------------------------------------------------------------------------*/
840 
AFNI_hintize_pbar(MCW_pbar * pbar,float fac)841 void AFNI_hintize_pbar( MCW_pbar *pbar ,  float fac )
842 {
843    int ip , np ;
844    Widget w ;
845    char sbot[16],stop[16] , hint[64] , *sb,*st ;
846    float bot , top ;
847 
848 ENTRY("AFNI_hintize_pbar") ;
849 
850    if( pbar == NULL || fac == 0.0f ) EXRETURN ;  /* bad */
851 
852    if( PBAR_FULLRANGE ) fac = 1.0f ;     /* 03 Jun 2014 */
853 
854    if( pbar->bigmode ){
855      MCW_register_hint( pbar->panes[0] ,
856                         "Button-1=flip;  Button-3=menu" ) ;
857      pbar->bigfac = fac ;                      /* 11 Feb 2003 */
858    } else {
859      np = pbar->num_panes ;
860      for( ip=0 ; ip < np ; ip++ ){
861        w   = pbar->panes[ip] ;          /* the widget for the ip-th pane */
862        top = pbar->pval[ip]   * fac ;   /* scaled top value */
863        bot = pbar->pval[ip+1] * fac ;   /* scaled bot value */
864        AV_fval_to_char( bot , sbot ) ;  /* convert to a nice string */
865        AV_fval_to_char( top , stop ) ;
866        sb = (sbot[0] == ' ') ? sbot+1 : sbot ;  /* skip leading blanks */
867        st = (stop[0] == ' ') ? stop+1 : stop ;
868        sprintf(hint,"%s .. %s",sb,st) ;         /* create hint */
869        MCW_register_hint( w , hint ) ;          /* send to hint system */
870      }
871    }
872 
873    EXRETURN ;
874 }
875 
876 /*----------------------------------------------------------------------------
877   called when the pbar for the intensity mapping is adjusted
878   (thresholds or colors)
879 ------------------------------------------------------------------------------*/
880 
AFNI_inten_pbar_CB(MCW_pbar * pbar,XtPointer cd,int reason)881 void AFNI_inten_pbar_CB( MCW_pbar *pbar , XtPointer cd , int reason )
882 {
883    Three_D_View *im3d = (Three_D_View *)cd ;
884    float fac ;
885 
886 ENTRY("AFNI_inten_pbar_CB") ;
887 
888    if( ! IM3D_OPEN(im3d) ) EXRETURN ;
889 
890    if( PBAR_FULLRANGE && !IM3D_ULAY_COHERENT(im3d) ){ /* 10 Jun 2014 */
891      STATUS("incoherent ulay -- patching") ;
892      ERROR_message("AFNI_inten_pbar_CB: incoherent ulay -- patching") ;
893      AFNI_assign_ulay_bricks(im3d) ;
894    }
895 
896 #if 0
897    STATUS_IM3D_TMASK(im3d) ;
898    STATUS("clear tmask") ;
899 #endif
900    IM3D_CLEAR_TMASK(im3d) ;                                /* Mar 2013 */
901    IM3D_CLEAR_THRSTAT(im3d) ;                           /* 12 Jun 2014 */
902    AFNI_setup_thrstat(im3d,0) ;
903 
904 #if 0
905 INFO_message("AFNI_inten_pbar_CB(%d)",AFNI_controller_index(im3d)) ;
906 #endif
907    if( im3d->vinfo->func_visible ) AFNI_redisplay_func( im3d ) ;
908 
909    AFNI_hintize_pbar( pbar , FIM_RANGE(im3d) ) ;
910 
911    FIX_SCALE_SIZE(im3d) ;
912 
913    AFNI_pbar_lock_carryout(im3d) ; /* 07 Feb 2004 */
914 
915 #if 0
916    AFNI_set_scale_size_fix_timer(im3d) ;  /* 03 Jun 2019 */
917 #endif
918    EXRETURN ;
919 }
920 
921 /*----------------------------------------------------------------------------*/
922 
923 #if 0
924 void AFNI_iab_pbar_CB( MCW_pbar *pbar , XtPointer cd , int reason )
925 {
926    Three_D_View *im3d = (Three_D_View *)cd ;
927 
928 ENTRY("AFNI_iab_pbar_CB") ;
929 
930    if( pbar == NULL || !pbar->three_level || !IM3D_OPEN(im3d) ) EXRETURN ; /* error */
931 
932    switch( reason ){
933 
934      case pbCR_VALUE:{
935        float top,bot , ntop,nbot ;
936        ntop = top = pbar->pval[1] ; nbot = bot = pbar->pval[2] ;
937        switch( im3d->vwid->func->iab_bot_av->ival ){
938          case 1:          /* Bot = -Top */
939            if( top > 0.0f ) nbot = -top ; else ntop = -bot ;
940          break ;
941          case 0:          /* Bot = 0 */
942            if( top <= 0.0f ) ntop = -bot ;
943            nbot = 0.0f ;
944          break ;
945        }
946 
947        if( ntop != top || nbot != bot ){
948          float pval[4] ;
949          pval[0] = pbar->pval[0] ; pval[3] = pbar->pval[3] ;
950          pval[1] = ntop          ; pval[2] = nbot          ;
951          alter_MCW_pbar( pbar , 0 , pval ) ;
952        }
953      }
954      break ;
955 
956      case pbCR_COLOR: /* TBD */
957      break ;
958 
959    }
960 
961    FIX_SCALE_SIZE(im3d) ; EXRETURN ;
962 }
963 
964 /*----------------------------------------------------------------------------*/
965 
966 void AFNI_iab_av_CB( MCW_arrowval *av , XtPointer cd )
967 {
968    Three_D_View *im3d = (Three_D_View *)cd ;
969    MCW_pbar *pbar = im3d->vwid->func->iab_pbar ;
970 
971 ENTRY("AFNI_iab_av_CB") ;
972 
973    if( pbar == NULL ) EXRETURN ; /* error */
974 
975    if( av == im3d->vwid->func->iab_pow_av ){
976      float pval[4] , fac ;
977      fac = powf(10.0f,(float)av->ival) ;
978      pval[0] =  1.2f*fac ; pval[1] =  1.0f*fac ;
979      pval[2] = -1.0f*fac ; pval[3] = -1.2f*fac ;
980      HIDE_SCALE(im3d) ;
981      alter_MCW_pbar( pbar , 0 , pval ) ;
982      FIX_SCALE_SIZE(im3d) ;
983 
984    } else if( av == im3d->vwid->func->iab_bot_av ){
985 
986      if( av->ival != 2 ) AFNI_iab_pbar_CB(pbar,im3d,pbCR_VALUE) ;
987 
988    }
989 
990    EXRETURN ;
991 }
992 #endif
993 
994 /*-----------------------------------------------------------------------------
995   30 Mar 2001: rotate the colors on the pbar
996 -------------------------------------------------------------------------------*/
997 
AFNI_range_rotate_av_CB(MCW_arrowval * av,XtPointer cd)998 void AFNI_range_rotate_av_CB( MCW_arrowval *av , XtPointer cd )
999 {
1000    MCW_pbar *pbar = (MCW_pbar *) cd ;
1001    int ddd ;
1002 
1003 ENTRY("AFNI_range_rotate_av_CB") ;
1004 
1005    /* which way to rotate? */
1006 
1007    if( av->fval > av->old_fval ) ddd = +1 ;
1008    else                          ddd = -1 ;
1009 
1010    /* Shift+click ==> rotate by 4 (useful for bigmode) */
1011 
1012    if( av->xev.type == ButtonPress ){
1013      XButtonEvent *event = (XButtonEvent *) (&av->xev) ;
1014      if( event->state & ShiftMask ) ddd *= 4 ;
1015    }
1016 
1017    rotate_MCW_pbar( pbar , ddd ) ;
1018    EXRETURN ;
1019 }
1020 
1021 /*---------------------------------------------------------------------------
1022   called to set up the pbar for the intensity mapping
1023 -----------------------------------------------------------------------------*/
1024 
1025 /** 3/27/95: changed to allow different initializations
1026              for the [0,1] and the [-1,1] range pbars.  **/
1027 
1028 /** 6/01/95: changed to put the initialization constants
1029              in tables initialized in afni.c, not here. **/
1030 
AFNI_setup_inten_pbar(MCW_pbar * pbar)1031 void AFNI_setup_inten_pbar( MCW_pbar *pbar )
1032 {
1033   int np , i , jm , lcol ;
1034 
1035 ENTRY("AFNI_setup_inten_pbar") ;
1036 
1037   if( pbar == NULL ) EXRETURN ;
1038 
1039   jm   = pbar->mode ;
1040   lcol = pbar->dc->ovc->ncol_ov - 1 ;
1041 
1042   /** load the 'save' values for all possible pane counts **/
1043 
1044   for( np=NPANE_MIN ; np <= NPANE_MAX ; np++ ){
1045 
1046       for( i=0 ; i <= np ; i++ ){
1047          pbar->pval_save[np][i][0] = INIT_pval_sgn[np][i] ;
1048          pbar->pval_save[np][i][1] = INIT_pval_pos[np][i] ;
1049       }
1050 
1051       for( i=0 ; i <  np ; i++ ){
1052          pbar->ovin_save[np][i][0] = MIN( lcol , INIT_ovin_sgn[np][i] ) ;
1053          pbar->ovin_save[np][i][1] = MIN( lcol , INIT_ovin_pos[np][i] ) ;
1054       }
1055   }
1056 
1057   /** load the values for the current pane count **/
1058 
1059   np = pbar->num_panes ;
1060   jm = pbar->mode ;
1061 
1062   for( i=0 ; i <= np ; i++ ) pbar->pval[i]     = pbar->pval_save[np][i][jm] ;
1063   for( i=0 ; i <  np ; i++ ) pbar->ov_index[i] = pbar->ovin_save[np][i][jm] ;
1064 
1065   pbar->update_me = 1 ;
1066   EXRETURN ;
1067 }
1068 
1069 /*----------------------------------------------------------------------------
1070   called when the arrowval for the number of pbar panes is clicked
1071 ------------------------------------------------------------------------------*/
1072 
AFNI_inten_av_CB(MCW_arrowval * av,XtPointer cd)1073 void AFNI_inten_av_CB( MCW_arrowval *av , XtPointer cd )
1074 {
1075    MCW_pbar *pbar = (MCW_pbar *)cd ;
1076    Three_D_View *im3d = (Three_D_View *)pbar->parent ;
1077 
1078    if( !IM3D_OPEN(im3d) ) return ;
1079 
1080    if( PBAR_FULLRANGE && !IM3D_ULAY_COHERENT(im3d) ){ /* 10 Jun 2014 */
1081      STATUS("incoherent ulay -- patching") ;
1082      ERROR_message("AFNI_inten_av_CB: incoherent ulay -- patching") ;
1083      AFNI_assign_ulay_bricks(im3d) ;
1084    }
1085 
1086    if( PBAR_FULLRANGE ) AFNI_redisplay_func_ignore(1) ;
1087 
1088 #if 0
1089    STATUS_IM3D_TMASK(im3d) ;
1090    STATUS("clear tmask") ;
1091 #endif
1092    IM3D_CLEAR_TMASK(im3d) ;                                /* Mar 2013 */
1093    IM3D_CLEAR_THRSTAT(im3d) ;                           /* 12 Jun 2014 */
1094    AFNI_setup_thrstat(im3d,0) ;
1095    HIDE_SCALE(im3d) ;
1096    if( av->ival > NPANE_MAX ){
1097      int npane=pbar->num_panes , jm=pbar->mode ;
1098      float pmax,pmin ;
1099      pmax = (pbar->big31) ? pbar->bigtop : pbar->pval_save[npane][0    ][jm] ;
1100      pmin = (pbar->big31) ? pbar->bigbot : pbar->pval_save[npane][npane][jm] ;
1101      PBAR_set_bigmode( pbar , 1 , pmin,pmax ) ;
1102      AFNI_inten_pbar_CB( pbar , im3d , 0 ) ;
1103      POPUP_cursorize( pbar->panew ) ;  /* 08 Apr 2005 */
1104    } else {
1105      pbar->bigmode = 0 ;
1106      alter_MCW_pbar( pbar , av->ival , NULL ) ;
1107      NORMAL_cursorize( pbar->panew ) ;  /* 08 Apr 2005 */
1108    }
1109    FIX_SCALE_SIZE(im3d) ;
1110 
1111    if( PBAR_FULLRANGE ) AFNI_redisplay_func_ignore(0) ;
1112 
1113    if( PBAR_FULLRANGE ) AFNI_pbar_topset(im3d,im3d->vinfo->fim_range) ;
1114    else                 HINTIZE_pbar(im3d) ;
1115 
1116    AFNI_fix_scale_size_direct(im3d) ;  /* 03 Jun 2019 */
1117    return ;
1118 }
1119 
1120 /*----------------------------------------------------------------------------*/
1121 
AFNI_inten_av_texter(MCW_arrowval * av,XtPointer cd)1122 char * AFNI_inten_av_texter( MCW_arrowval *av , XtPointer cd )
1123 {
1124    static char buf[4] ;
1125    if( av->ival > NPANE_MAX ) strcpy (buf,"**") ;           /* label for  */
1126    else                       sprintf(buf,"%d",av->ival) ;  /* number of  */
1127    return buf ;                                             /* pbar panes */
1128 }
1129 
1130 /*---------------------------------------------------------------------
1131    Make a warped dataset whose grid corresponds to the anat_parent and
1132    whose data comes from the data_parent.
1133    Note that the assumption is made that data_parent and the warp parent
1134    of the anat_parent are both in the same coordinate system (up to the
1135    to_dicomm transformation of their dataxes structs).
1136 -----------------------------------------------------------------------*/
1137 
AFNI_follower_dataset(THD_3dim_dataset * anat_parent,THD_3dim_dataset * data_parent)1138 THD_3dim_dataset * AFNI_follower_dataset( THD_3dim_dataset *anat_parent ,
1139                                           THD_3dim_dataset *data_parent  )
1140 {
1141    THD_3dim_dataset *new_dset ;
1142    int ii ;
1143 
1144 ENTRY("AFNI_follower_dataset") ;
1145 
1146    /* sanity checks */
1147 
1148    if( ! ISVALID_3DIM_DATASET(anat_parent) ||
1149        ! ISVALID_3DIM_DATASET(data_parent)   ) RETURN(NULL) ;
1150 
1151    /* can't warp a time-dependent dataset (OK, maybe you can) */
1152 
1153    if( DSET_NUM_TIMES(data_parent) > 1 && ! GLOBAL_argopt.warp_4D ) RETURN(NULL) ;
1154 
1155 if(PRINT_TRACING)
1156 { char str[256] ;
1157   sprintf(str,"anat_parent=%s  data_parent=%s",
1158           DSET_HEADNAME(anat_parent) , DSET_HEADNAME(data_parent) ) ;
1159   STATUS(str); }
1160 
1161    /* make new dataset, copying appropriate fields from its various parents */
1162 
1163    new_dset = myXtNew( THD_3dim_dataset ) ; INIT_KILL( new_dset->kl ) ;
1164 
1165    new_dset->type      = data_parent->type ;        /* same data type */
1166    new_dset->func_type = data_parent->func_type ;
1167    new_dset->view_type = anat_parent->view_type ;   /* but different view type */
1168 
1169    /* use template space of parent to mark as TLRC/MNI/... */
1170    MCW_strncpy( new_dset->atlas_space ,
1171       anat_parent->atlas_space , THD_MAX_NAME ) ;
1172 
1173    new_dset->anat_parent = anat_parent ;            /* what else makes sense? */
1174 
1175    new_dset->tagset = NULL ;  /* Oct 1998 */
1176    new_dset->Label_Dtable = NULL;                  /* ZSS Feb 26 2010 */
1177 
1178    MCW_strncpy( new_dset->anat_parent_name ,
1179                 anat_parent->self_name , THD_MAX_NAME ) ;
1180 
1181    new_dset->anat_parent_idcode = anat_parent->idcode ;
1182 
1183    /* 11/09/94 addition: the data_parent may itself be a warp;
1184        in this case, we want the true warp parent to be the original data */
1185 
1186    new_dset->warp_parent =  (data_parent->warp_parent != NULL)
1187                           ? (data_parent->warp_parent) : (data_parent) ;
1188 
1189    MCW_strncpy( new_dset->warp_parent_name ,
1190                 new_dset->warp_parent->self_name , THD_MAX_NAME ) ;
1191 
1192    new_dset->warp_parent_idcode = new_dset->warp_parent->idcode ;
1193 
1194    new_dset->idcode = MCW_new_idcode() ;
1195 
1196    /* make the actual warp from the warp_parent to this dataset */
1197 
1198    new_dset->vox_warp       = NULL ;
1199    new_dset->warp           = myXtNew( THD_warp ) ;
1200    *(new_dset->warp)        = IDENTITY_WARP ;  /* start with (Dicom) identity */
1201    new_dset->self_warp      = NULL ;  /* 26 Aug 2002 */
1202 
1203    /* follow the links backward from desired view to original view */
1204 
1205    AFNI_concatenate_warp( new_dset->warp , anat_parent->warp ) ;
1206    AFNI_concatenate_warp( new_dset->warp , data_parent->warp ) ;
1207 
1208    /* reset the bounds in the new warp to be the same as in the anat_parent */
1209 
1210    if( ISVALID_WARP(anat_parent->warp) &&
1211        anat_parent->warp->type == new_dset->warp->type ){
1212 
1213       switch( anat_parent->warp->type ){
1214 
1215          case WARP_AFFINE_TYPE:
1216             COPY_LMAP_BOUNDS( new_dset->warp->rig_bod.warp ,
1217                               anat_parent->warp->rig_bod.warp ) ;
1218          break ;
1219 
1220          case WARP_TALAIRACH_12_TYPE:
1221             for( ii=0 ; ii < 12 ; ii++ )
1222                COPY_LMAP_BOUNDS( new_dset->warp->tal_12.warp[ii] ,
1223                                  anat_parent->warp->tal_12.warp[ii] ) ;
1224          break ;
1225       }
1226    }
1227 
1228    /* make up some names for this new dataset */
1229 
1230    MCW_strncpy( new_dset->self_name  ,
1231                 new_dset->warp_parent->self_name , THD_MAX_NAME ) ;
1232    ii = strlen( new_dset->self_name ) ;
1233    new_dset->self_name[ii++] = '@' ;
1234    MCW_strncpy( &(new_dset->self_name[ii]) ,
1235                 VIEW_typestr[new_dset->view_type] , THD_MAX_NAME-ii ) ;
1236 
1237    MCW_strncpy( new_dset->label1 , data_parent->label1 , THD_MAX_LABEL ) ;
1238    MCW_strncpy( new_dset->label2 , data_parent->label2 , THD_MAX_LABEL ) ;
1239 
1240    /* set the axes for this new dataset
1241       (same as anatomy parent, since that's the meaning of this routine) */
1242 
1243    new_dset->daxes     = myXtNew( THD_dataxes ) ; /* copy data axes of */
1244    *(new_dset->daxes)  = *(anat_parent->daxes)  ; /* anatomy parent   */
1245 
1246    new_dset->wod_daxes = NULL ;
1247    new_dset->wod_flag  = True ;
1248 
1249    /* 06 Aug 1996: added ability to use 3D+t datasets here */
1250 
1251    if( DSET_NUM_TIMES(data_parent) < 2 ){
1252       new_dset->taxis = NULL ;
1253    } else {
1254       new_dset->taxis  = myXtNew( THD_timeaxis ) ;  /* new */
1255     *(new_dset->taxis) = *(data_parent->taxis) ;  /* copy insides */
1256 
1257       new_dset->taxis->nsl     = 0 ;                      /* no slice stuff */
1258       new_dset->taxis->toff_sl = NULL ;
1259       new_dset->taxis->zorg_sl = 0.0 ;
1260       new_dset->taxis->dz_sl   = 0.0 ;
1261    }
1262 
1263    /* create a datablock and diskptr, in case the data is ever
1264       filled into memory (instead of wod) and written to disk */
1265 
1266    new_dset->dblk = myXtNew( THD_datablock ) ; INIT_KILL( new_dset->dblk->kl ) ;
1267 
1268    new_dset->dblk->type        = DATABLOCK_TYPE ;
1269    new_dset->dblk->nvals       = data_parent->dblk->nvals ;
1270    new_dset->dblk->malloc_type = DATABLOCK_MEM_UNDEFINED ;
1271    new_dset->dblk->natr        = new_dset->dblk->natr_alloc  = 0 ;
1272    new_dset->dblk->atr         = NULL ;
1273    new_dset->dblk->parent      = (XtPointer) new_dset ;
1274 
1275    new_dset->dblk->vedim = NULL ;  /* 05 Sep 2006 */
1276 
1277    if( data_parent->dblk->brick_lab == NULL ){
1278      THD_init_datablock_labels( new_dset->dblk ) ; /* 30 Nov 1997 */
1279    } else {
1280      THD_copy_datablock_auxdata( data_parent->dblk , new_dset->dblk ) ;
1281    }
1282 
1283    DSET_unlock(new_dset) ;  /* Feb 1998 */
1284 
1285    new_dset->dblk->diskptr               = myXtNew( THD_diskptr ) ;
1286    new_dset->dblk->diskptr->type         = DISKPTR_TYPE ;
1287    new_dset->dblk->diskptr->nvals        = data_parent->dblk->nvals ;
1288    new_dset->dblk->diskptr->rank         = 3 ;
1289    new_dset->dblk->diskptr->storage_mode = STORAGE_UNDEFINED ;
1290    new_dset->dblk->diskptr->byte_order   = THD_get_write_order() ;  /* 25 April 1998 */
1291    new_dset->dblk->diskptr->dimsizes[0]  = new_dset->daxes->nxx ;
1292    new_dset->dblk->diskptr->dimsizes[1]  = new_dset->daxes->nyy ;
1293    new_dset->dblk->diskptr->dimsizes[2]  = new_dset->daxes->nzz ;
1294 
1295    new_dset->dblk->brick_fac   = NULL ;  /* initialized below */
1296    new_dset->dblk->brick_bytes = NULL ;
1297    new_dset->dblk->brick       = NULL ;
1298    THD_init_datablock_brick( new_dset->dblk , -1 , data_parent->dblk ) ;
1299 
1300    new_dset->dblk->master_nvals = 0 ;     /* 11 Jan 1999 */
1301    new_dset->dblk->master_ival  = NULL ;
1302    new_dset->dblk->master_bytes = NULL ;
1303 
1304    /* create the names for storage on disk (if ever)
1305       -- note we put it in the same directory as the data_parent */
1306 
1307    THD_init_diskptr_names( new_dset->dblk->diskptr ,
1308                            data_parent->dblk->diskptr->directory_name , NULL ,
1309                            data_parent->dblk->diskptr->prefix ,
1310                            new_dset->view_type , True ) ;
1311 
1312    ADDTO_KILL( new_dset->dblk->kl , new_dset->dblk->diskptr ) ;
1313 
1314    /* oh yeah, set the new_dset kill list,
1315       copy statistics if available, and NULL out any unused stuff */
1316 
1317    ADDTO_KILL( new_dset->kl , new_dset->warp ) ;
1318    ADDTO_KILL( new_dset->kl , new_dset->daxes ) ;
1319    ADDTO_KILL( new_dset->kl , new_dset->dblk ) ;
1320 
1321    new_dset->stats = NULL ;
1322    AFNI_copy_statistics( data_parent , new_dset ) ;
1323 
1324    INIT_STAT_AUX( new_dset , MAX_STAT_AUX , data_parent->stat_aux ) ;
1325 
1326    new_dset->markers     = NULL ;  /* no markers */
1327    new_dset->death_mark  = 0 ;     /* don't kill me! */
1328    new_dset->tcat_list   = 0 ;
1329    new_dset->tcat_num    = 0 ;
1330    new_dset->tcat_len    = NULL ;
1331 
1332 #ifdef ALLOW_DATASET_VLIST
1333    new_dset->pts         = NULL ;
1334 #endif
1335 
1336    PARENTIZE(new_dset,data_parent->parent) ;
1337 
1338    tross_Copy_History( data_parent , new_dset ) ; /* 18 Oct 1999 */
1339 
1340    RETURN(new_dset) ;
1341 }
1342 
1343 /*------------------------------------------------------------------------
1344   Scan through a sessionlist and find any datasets that can be "filled in"
1345   as 'followers' (as in AFNI_follower_dataset).  That is, find any slots
1346   that are not now filled, but are "downstream" from original view data
1347   that has an anatomy parent:
1348 
1349   SPGR:   orig  acpc  ----
1350            /^\                <--- anatomy parent
1351             |                 <--- relationship
1352   FIM:    orig  ----  ----
1353 
1354   In this picture, the first blank in the FIM line can be filled in, using
1355   the fim+orig dataset as the data_parent and the spgr+acpc dataset as
1356   the anat_parent for the new fim+acpc dataset.
1357 
1358   The algorithm used to find slots that may be filled in is as simple as
1359   the picture above -- the 'orig' view is presumed to contain all the basic
1360   anatomy parent relationships.  This may not be true in the future
1361   (e.g., when registering one dataset to another, the 'rgst' view will
1362   then have a basic anatomy parent relationship).  I'll worry about
1363   that later, as well as about the possibility that the newly created
1364   datasets may spawn further possible offspring (e.g., if they themselves
1365   are anatomical images that fill in slots that will become anat_parents).
1366                                               -- RWCox, November, 1994 A.D.
1367 
1368   3 June 1998:
1369     The original version of this is renamed to be AFNI_make_descendants_old,
1370     and is modified to do a sweep starting at the "vbase" view.  Then
1371     we sweep twice, once from +orig and once again from +acpc.  This is
1372     to allow for creation of descendants from +acpc that do not have
1373     ancestors at +orig.
1374 ---------------------------------------------------------------------------*/
1375 
1376 void AFNI_make_descendants_old( THD_sessionlist * , int ) ; /* prototype */
1377 
AFNI_make_descendants(THD_sessionlist * ssl)1378 void AFNI_make_descendants( THD_sessionlist *ssl )
1379 {
1380    AFNI_make_descendants_old( ssl , VIEW_ORIGINAL_TYPE ) ;
1381 #if 0
1382    AFNI_make_descendants_old( ssl , VIEW_ACPCALIGNED_TYPE ) ; /* doesn't work */
1383 #endif
1384    return ;
1385 }
1386 
1387 /** In this routine, each occurence of vbase was originally VIEW_ORIGINAL_TYPE **/
1388 
AFNI_make_descendants_old(THD_sessionlist * ssl,int vbase)1389 void AFNI_make_descendants_old( THD_sessionlist *ssl , int vbase )
1390 {
1391    int iss , jdd , kvv , num_made=0 ;
1392    THD_session *ss, *temp_ss ;
1393    THD_3dim_dataset *orig_dset , *temp_dset, *temp_anat_dset ;
1394    THD_slist_find     find ;
1395    THD_3dim_dataset *anat_parent_dset;
1396 /*                  **orig_row ;*/
1397    int orig_row_key, anat_parent_row_key;
1398 
1399 ENTRY("AFNI_make_descendants_old") ;
1400 
1401    if( ! ISVALID_SESSIONLIST(ssl) ) EXRETURN ;
1402 
1403    /* loop over each session */
1404 
1405    for( iss=0 ; iss < ssl->num_sess ; iss++ ){
1406       ss = ssl->ssar[iss] ;
1407       if( !ISVALID_SESSION(ss) ) continue ;  /* no good ==> skip */
1408 
1409       if( ss == GLOBAL_library.session ) continue ; /* 21 Dec 2001 */
1410 
1411       /* loop over datasets in this session */
1412 
1413       for( jdd=0 ; jdd < ss->num_dsset ; jdd++ ){
1414         orig_dset = GET_SESSION_DSET(ss, jdd, vbase);
1415 /*         orig_dset = ss->dsset_xform_table[jdd][vbase] ; */ /* 03 Jun 98 */
1416          if( !ISVALID_3DIM_DATASET(orig_dset) ||              /* no good   */
1417              orig_dset->anat_parent == NULL   ||              /* no parent */
1418              orig_dset->anat_parent == orig_dset ) continue ; /* ==> skip  */
1419 
1420          if( DSET_in_global_session(orig_dset) ) continue ; /* 25 Dec 2001 */
1421 
1422          /* look for orig_dset's anat parent in this sessionlist */
1423 
1424          find = THD_dset_in_sessionlist( FIND_IDCODE ,
1425                                          &(orig_dset->anat_parent->idcode) ,
1426                                          ssl , iss ) ;
1427          if( find.dset == NULL )
1428             find = THD_dset_in_sessionlist( FIND_NAME ,
1429                                             orig_dset->anat_parent->self_name ,
1430                                             ssl , iss ) ;
1431 
1432          /* check for a good find; if it doesn't happen,
1433             then skip (this eventuality should never occur!) */
1434 
1435          if( find.dset       == NULL ||
1436              ISFUNC(find.dset)       ||  /* anat parent can't be a func! */
1437              find.view_index != vbase  ) continue ;
1438 
1439          /* make a pointer to the row of datasets of the anat
1440             parent (this is like the SPGR row in the picture above) */
1441 
1442    /* will need to change this test with updated session tables - drg 05/2010 */
1443          anat_parent_dset =
1444            GET_SESSION_DSET(ssl->ssar[find.sess_index], find.dset_index, vbase) ;
1445          if(orig_dset == anat_parent_dset) continue ;  /* 20 Jul 2010 */
1446 
1447          anat_parent_row_key = find.dset_index;
1448 /*         anat_parent_row =
1449            &(ssl->ssar[find.sess_index]->dsset_xform_table[find.dset_index][0]) ;*/
1450 
1451          /* pointer to row of datasets being operated on now
1452             (like the FIM row in the picture above)          */
1453          orig_row_key = jdd;
1454 /*         orig_row = &(ss->dsset_xform_table[jdd][0]) ; */
1455 /*         if( orig_row == anat_parent_row ) continue ;*/  /* 14 Dec 1999 */
1456 
1457          /* loop over downstream dataset positions (from orig_dset);
1458             those that don't exist yet, but have entries in the
1459             anat_parent_row can be brought into being now */
1460          temp_ss = ssl->ssar[find.sess_index];
1461 
1462          for( kvv=vbase+1 ; kvv <= LAST_VIEW_TYPE ; kvv++ ){
1463             if( GET_SESSION_DSET(ss, orig_row_key, kvv) != NULL ) continue ;
1464             temp_anat_dset = GET_SESSION_DSET(temp_ss, anat_parent_row_key, kvv);
1465             if( temp_anat_dset == NULL ) continue ;
1466 
1467             temp_dset = AFNI_follower_dataset( temp_anat_dset, orig_dset ) ;
1468 
1469             SET_SESSION_DSET(temp_dset, ss, orig_row_key, kvv);
1470 /*            orig_row[kvv] = AFNI_follower_dataset( anat_parent_row[kvv] ,
1471                                                    orig_dset ) ;*/
1472             num_made ++ ;
1473          }
1474       }  /* end of loop over datasets in this session */
1475 
1476    }  /* end of loop over sessions */
1477 
1478 if(PRINT_TRACING)
1479 { char str[256] ;
1480   sprintf(str,"total # descendants made = %d",num_made) ;
1481   STATUS(str) ; }
1482 
1483    EXRETURN ;
1484 }
1485 
1486 /*-----------------------------------------------------------------------
1487    Scan through a session and force any un-anat_parented functional
1488    datasets to have the first available parent, if any.
1489    (Note that only the dataset anat_parent pointer is set, not the
1490     anat_parent_name string, so that if the dataset is saved, no record
1491     of this will be kept.)
1492 
1493    06 Aug 1996: force adoption of anats as well if "do_anats" is True.
1494    03 Dec 1999: print messages about forced adoptions
1495 -------------------------------------------------------------------------*/
1496 
AFNI_force_adoption(THD_session * ss,RwcBoolean do_anats)1497 void AFNI_force_adoption( THD_session *ss , RwcBoolean do_anats )
1498 {
1499    int aa , ff , vv , apref=0 , aset=-1 ;
1500    THD_3dim_dataset *dset, *pref_dset, *anyanat_dset ;
1501    int quiet = !AFNI_noenv("AFNI_NO_ADOPTION_WARNING") ; /* 03 Dec 1999 */
1502    int first = 1 ;
1503 
1504 ENTRY("AFNI_force_adoption") ;
1505 
1506    if( ! ISVALID_SESSION(ss) || ss->num_dsset == 0 || ss->is_collection ) EXRETURN ;
1507 
1508    if( ss == GLOBAL_library.session ) EXRETURN ; /* 21 Dec 2001 */
1509 
1510    /* find a "preferred" parent (one with the most number of markers set) */
1511 
1512    for( aa=0 ; aa < ss->num_dsset ; aa++ ){
1513 
1514 if(PRINT_TRACING)
1515 { char str[256] ;
1516   sprintf(str,"scanning dataset %d for markers",aa) ; STATUS(str) ; }
1517       dset = GET_SESSION_DSET(ss, aa, 0);   /* original view */
1518 /*      dset = ss->dsset_xform_table[aa][0] ;*/   /* original view */
1519 
1520       if( ISVALID_3DIM_DATASET(dset) &&     /* if a good dataset */
1521           ISANAT(dset)               &&     /* and is anatomical */
1522           dset->markers != NULL        ){   /* and has markers   */
1523 
1524          if( dset->markers->numset > aset ){ /* and has more markers than before */
1525             apref = aa ;                     /* try this as our "preferred" parent */
1526             aset  = dset->markers->numset ;
1527          }
1528       }
1529    }
1530 
1531    /* count potential parents [08 Dec 1999: modified from 03 Dec 1999 code] */
1532 
1533    vv = 0 ;
1534    if( aset >= 0 ){
1535      for( aa=0 ; aa < ss->num_dsset ; aa++ ){
1536        dset = GET_SESSION_DSET(ss, aa, 0);
1537        if( ISVALID_DSET(dset)    &&
1538            ISANAT(dset)          &&
1539            dset->markers != NULL && dset->markers->numset >= aset ) vv++ ;
1540      }
1541    }
1542 
1543    quiet = ( quiet || vv <= 1 ) ; /* be quiet if ordered, or if no alternatives */
1544 
1545 if(aset >= 0 && PRINT_TRACING)
1546 { char str[256] ;
1547   THD_3dim_dataset *temp_dset;
1548   temp_dset = GET_SESSION_DSET(ss,apref,0);
1549   sprintf(str,"session %s: apref=%d [%s] aset=%d",
1550           ss->lastname,apref,DSET_HEADNAME(temp_dset),aset) ;
1551 /*  sprintf(str,"session %s: apref=%d [%s] aset=%d",
1552           ss->lastname,apref,DSET_HEADNAME(ss->dsset_xform_table[apref][0]),aset) ;*/
1553   STATUS(str) ; }
1554 
1555    /* scan through all datasets, all views */
1556 
1557    for( ff=0 ; ff < ss->num_dsset ; ff++ ){
1558       for( vv=VIEW_ORIGINAL_TYPE ; vv <= LAST_VIEW_TYPE ; vv++ ){
1559          dset = GET_SESSION_DSET(ss, ff, vv);    /* function that needs parent */
1560 /*         dset = ss->dsset_xform_table[ff][vv] ; */ /* function that needs parent */
1561 
1562          if( ! ISVALID_3DIM_DATASET(dset) ||
1563              dset->anat_parent != NULL      ) continue ; /* nothing to do */
1564 
1565          if( !do_anats && ISANAT(dset)      ) continue ; /* 28 Jul 2003 */
1566 
1567          if( DSET_in_global_session(dset) ) continue ; /* 25 Dec 2001 */
1568 
1569          pref_dset = GET_SESSION_DSET(ss,apref,vv);
1570 
1571          if( ISVALID_3DIM_DATASET(pref_dset) ){  /* if preferred is OK, */
1572             dset->anat_parent = pref_dset ;      /* use it here         */
1573          }
1574          else {
1575             for( aa=0 ; aa < ss->num_dsset ; aa++ ){          /* search for something, */
1576                anyanat_dset = GET_SESSION_DSET(ss, aa, vv);
1577                if( ISVALID_3DIM_DATASET(anyanat_dset)
1578                    && ISANAT(anyanat_dset)           ){  /* anything, and use it  */
1579                   dset->anat_parent = anyanat_dset ; break ;
1580                }
1581             }
1582          }
1583 
1584          if( !quiet && dset->anat_parent != NULL && dset->anat_parent != dset ){
1585             if( first ){
1586               first = 0 ;
1587               fprintf(stderr,
1588                       "\nDatasets with a 'forced adoption' of anat parent:\n") ;
1589             }
1590             fprintf(stderr,
1591                     " %s gets parent %s\n",
1592                     DSET_HEADNAME(dset) ,
1593                     DSET_HEADNAME(dset->anat_parent) ) ;
1594          }
1595       }
1596    }
1597 
1598    EXRETURN ;
1599 }
1600 
1601 #undef ALLOW_OLD_EDGIZE
1602 #ifdef ALLOW_OLD_EDGIZE
1603 /*-----------------------------------------------------------------------*/
1604 /* Hollow out the overlay in place -- 21 Mar 2005 - RWCox.
1605    An interior pixel is defined as one whose 4 nearest neighbors are
1606    all nonzero.  This editing is done in-place (in the input image).
1607 -------------------------------------------------------------------------*/
1608 
mri_edgize(MRI_IMAGE * im)1609 static void mri_edgize( MRI_IMAGE *im )
1610 {
1611    int ii , jj , nx,ny,nxy , joff ;
1612 
1613    if( im == NULL ) return ;
1614 
1615    nx = im->nx ; ny = im->ny ; nxy = nx * ny ;
1616    if( nx < 3 || ny < 3 ) return ;  /* no interior pixels at all?! */
1617 
1618    switch( im->kind ){
1619 
1620      case MRI_byte:{                             /* 09 Dec 2014 */
1621        byte *ajj , *ajm , *ajp , *atemp , *ar ;
1622        ar    = MRI_BYTE_PTR(im) ;
1623        atemp = (byte *)malloc(sizeof(byte)*nxy); if( atemp == NULL ) return;
1624        memcpy(atemp,ar,sizeof(byte)*nxy) ;
1625        for( jj=1 ; jj < ny-1 ; jj++ ){
1626          joff = jj * nx ;      /* offset into this row */
1627          ajj  = atemp + joff ; /* pointer to this row */
1628          ajm  = ajj-nx ;       /* pointer to last row */
1629          ajp  = ajj+nx ;       /* pointer to next row */
1630          for( ii=1 ; ii < nx-1 ; ii++ ){
1631            if( ajj[ii]   != 0 &&
1632                ajm[ii]   != 0 && ajp[ii]   != 0 &&
1633                ajj[ii+1] != 0 && ajj[ii-1] != 0   ) ar[ii+joff] = 0 ;
1634          }
1635        }
1636        free((void *)atemp) ;
1637      }
1638      return ;
1639 
1640      case MRI_short:{
1641        short *ajj , *ajm , *ajp , *atemp , *ar ;
1642        ar    = MRI_SHORT_PTR(im) ;
1643        atemp = (short *)malloc(sizeof(short)*nxy); if( atemp == NULL ) return;
1644        memcpy(atemp,ar,sizeof(short)*nxy) ;
1645        for( jj=1 ; jj < ny-1 ; jj++ ){
1646          joff = jj * nx ;      /* offset into this row */
1647          ajj  = atemp + joff ; /* pointer to this row */
1648          ajm  = ajj-nx ;       /* pointer to last row */
1649          ajp  = ajj+nx ;       /* pointer to next row */
1650          for( ii=1 ; ii < nx-1 ; ii++ ){
1651            if( ajj[ii]   != 0 &&
1652                ajm[ii]   != 0 && ajp[ii]   != 0 &&
1653                ajj[ii+1] != 0 && ajj[ii-1] != 0   ) ar[ii+joff] = 0 ;
1654          }
1655        }
1656        free((void *)atemp) ;
1657      }
1658      return ;
1659 
1660      case MRI_rgb:{
1661        rgbyte *ajj , *ajm , *ajp , *atemp , *ar ;
1662        ar    = (rgbyte *)MRI_RGB_PTR(im) ;
1663        atemp = (rgbyte *)malloc(sizeof(rgbyte)*nxy); if( atemp == NULL ) return;
1664        memcpy(atemp,ar,sizeof(rgbyte)*nxy) ;
1665        for( jj=1 ; jj < ny-1 ; jj++ ){
1666          joff = jj * nx ;
1667          ajj  = atemp + joff ;
1668          ajm  = ajj-nx ;
1669          ajp  = ajj+nx ;
1670          for( ii=1 ; ii < nx-1 ; ii++ ){
1671            if( !RGBZEQ(ajj[ii])   &&
1672                !RGBZEQ(ajm[ii])   && !RGBZEQ(ajp[ii])   &&
1673                !RGBZEQ(ajj[ii+1]) && !RGBZEQ(ajj[ii-1])   ) RGBZAS(ar[ii+joff]) ;
1674          }
1675        }
1676        free((void *)atemp) ;
1677      }
1678      return ;
1679 
1680    }
1681 
1682    return ; /* default im->kind case ==> do nothing */
1683 }
1684 #endif
1685 
1686 /*-----------------------------------------------------------------------*/
1687 
mri_edgize_outer(MRI_IMAGE * im)1688 static void mri_edgize_outer( MRI_IMAGE *im )
1689 {
1690    int ii , jj , nx,ny,nxy , joff ;
1691 
1692    if( im == NULL ) return ;
1693 
1694    nx = im->nx ; ny = im->ny ; nxy = nx * ny ;
1695    if( nx < 3 || ny < 3 ) return ;  /* no interior pixels at all?! */
1696 
1697    switch( im->kind ){
1698 
1699      default: break ;
1700 
1701      case MRI_byte:{                             /* 09 Dec 2014 */
1702        byte *ajj , *ajm , *ajp , *atemp , *ar ;
1703        ar    = MRI_BYTE_PTR(im) ;
1704 #if 0
1705        (void)THD_mask_remove_isolas( im->nx , im->ny , 1 , ar ) ; /* 02 Nov 2018 */
1706 #endif
1707        atemp = (byte *)calloc(sizeof(byte),nxy); if( atemp == NULL ) return;
1708        for( jj=1 ; jj < ny-1 ; jj++ ){
1709          joff = jj * nx ;      /* offset into this row */
1710          ajj  = ar    + joff ; /* pointer to this row */
1711          ajm  = ajj-nx ;       /* pointer to last row */
1712          ajp  = ajj+nx ;       /* pointer to next row */
1713          for( ii=1 ; ii < nx-1 ; ii++ ){
1714            if( ajj[ii] != 0 ){
1715              ajj[ii] = 1 ;
1716              if( ajm[ii]   == 0 || ajp[ii]   == 0 ||
1717                  ajj[ii+1] == 0 || ajj[ii-1] == 0   ) atemp[ii+joff] = 1 ;
1718            }
1719          }
1720          if( ajj[0] != 0 ){  /* deal with left edge of row */
1721            ajj[0] = 1 ;
1722            if( ajm[0] == 0 || ajp[0] == 0 || ajj[1] == 0 ) atemp[joff] = 1 ;
1723          }
1724          if( ajj[nx-1] != 0 ){  /* and right edge */
1725            ajj[nx-1] = 1 ;
1726            if( ajm[nx-1] == 0 || ajp[nx-1] == 0 || ajj[nx-2] == 0 ) atemp[nx-1+joff] = 1 ;
1727          }
1728        }
1729        /* deal with the top row */
1730        joff = 0 ; ajj  = ar + joff ; ajp = ajj+nx ;
1731        for( ii=1 ; ii < nx-1 ; ii++ ){
1732          if( ajj[ii] != 0 ){
1733            ajj[ii] = 1 ;
1734            if( ajp[ii]   == 0 || ajj[ii+1] == 0 || ajj[ii-1] == 0 ) atemp[ii+joff] = 1 ;
1735          }
1736        }
1737        /* deal with the bottom row */
1738        joff = (ny-1) * nx ; ajj  = ar + joff ; ajm  = ajj-nx ;
1739        for( ii=1 ; ii < nx-1 ; ii++ ){
1740          if( ajj[ii] != 0 ){
1741            ajj[ii] = 1 ;
1742            if( ajm[ii]   == 0 || ajj[ii+1] == 0 || ajj[ii-1] == 0 ) atemp[ii+joff] = 1 ;
1743          }
1744        }
1745        /* we do not deal with the 4 corner points -- let them eat cake */
1746 
1747        /* at this point, atemp = 1 only at edge points of clusters */
1748        /* now modify atemp so that only points that are zero AND are
1749           next to an edge point get a nonzero value == 'outer' edge */
1750 
1751        for( jj=1 ; jj < ny-1 ; jj++ ){
1752          joff = jj * nx ;      /* offset into this row */
1753          ajj  = atemp + joff ; /* pointer to this row */
1754          ajm  = ajj-nx ;       /* pointer to last row */
1755          ajp  = ajj+nx ;       /* pointer to next row */
1756          for( ii=1 ; ii < nx-1 ; ii++ ){
1757            if( ar[ii+joff] == 0 ){  /* not inside a blob */
1758              if( ajm[ii-1] != 0 || ajm[ii] != 0 || ajm[ii+1] != 0 ||
1759                  ajj[ii-1] != 0 || ajj[ii] != 0 || ajj[ii+1] != 0 ||
1760                  ajp[ii-1] != 0 || ajp[ii] != 0 || ajp[ii+1] != 0   ) ar[ii+joff] = 2 ;
1761            } else {
1762              ar[ii+joff] = 0 ;  /* inside a blob ==> zero out */
1763            }
1764          }
1765          if( ar[joff] == 0 ){   /* left edge of row */
1766            if( ajm[0] != 0 || ajm[0+1] != 0 ||
1767                ajj[0] != 0 || ajj[0+1] != 0 ||
1768                ajp[0] != 0 || ajp[0+1] != 0   ) ar[joff] = 2 ;
1769          } else {
1770            ar[joff] = 0 ;
1771          }
1772          if( ar[nx-1+joff] == 0 ){  /* right edge of row */
1773            if( ajm[nx-2] != 0 || ajm[nx-1] != 0 ||
1774                ajj[nx-2] != 0 || ajj[nx-1] != 0 ||
1775                ajp[nx-2] != 0 || ajp[nx-1] != 0   ) ar[nx-1+joff] = 2 ;
1776          } else {
1777            ar[nx-1+joff] = 0 ;
1778          }
1779        }
1780        /* deal with the bottom row */
1781        joff = 0 ; ajj = atemp + joff ; ajp = ajj+nx ;
1782        for( ii=1 ; ii < nx-1 ; ii++ ){
1783          if( ar[ii+joff] == 0 ){  /* not inside a blob */
1784            if( ajj[ii-1] != 0 || ajj[ii] != 0 || ajj[ii+1] != 0 ||
1785                ajp[ii-1] != 0 || ajp[ii] != 0 || ajp[ii+1] != 0   ) ar[ii+joff] = 2 ;
1786          } else {
1787            ar[ii+joff] = 0 ;  /* inside a blob ==> zero out */
1788          }
1789        }
1790        /* deal with the top row */
1791        joff = (ny-1) * nx ; ajj = atemp + joff ; ajm = ajj-nx ;
1792        for( ii=1 ; ii < nx-1 ; ii++ ){
1793          if( ar[ii+joff] == 0 ){  /* not inside a blob */
1794            if( ajm[ii-1] != 0 || ajm[ii] != 0 || ajm[ii+1] != 0 ||
1795                ajj[ii-1] != 0 || ajj[ii] != 0 || ajj[ii+1] != 0   ) ar[ii+joff] = 2 ;
1796          } else {
1797            ar[ii+joff] = 0 ;  /* inside a blob ==> zero out */
1798          }
1799        }
1800 
1801        free(atemp) ;
1802      }
1803      return ; /* end of MRI_byte */
1804 
1805    } /* end of switching */
1806 
1807    return ; /* default im->kind case ==> do nothing */
1808 }
1809 
1810 /*-----------------------------------------------------------------------*/
1811 /* Convert a paned color bar to a continuous color scale,
1812    for use with AFNI_newnewfunc_overlay [17 Jul 2019 - RWC]
1813 *//*---------------------------------------------------------------------*/
1814 
1815 #define NPANE_SUPERBIG 10001
1816 
AFNI_panes_to_bigcolor(MCW_pbar * pbar,rgbyte * bigcolor,int nbig)1817 void AFNI_panes_to_bigcolor( MCW_pbar *pbar , rgbyte *bigcolor , int nbig )
1818 {
1819    float *pval ;
1820    int *ovind , npan ;
1821    byte *r_ov , *g_ov , *b_ov ;
1822    rgbyte *col ; float *val , eps; int neq,ii,jj,kk ;
1823 
1824 ENTRY("AFNI_panes_to_bigcolor") ;
1825 
1826    if( pbar == NULL || bigcolor == NULL ) EXRETURN ;
1827 
1828         if( nbig < 16             ) nbig = NPANE_BIG ;
1829    else if( nbig > NPANE_SUPERBIG ) nbig = NPANE_SUPERBIG ;
1830 
1831    pval  = pbar->pval ;            /* [i] = bot of panel #i, i=0..npan */
1832    ovind = pbar->ov_index ;        /* [i] = color panel #i , i=0..npan-1 */
1833    npan  = pbar->num_panes ;       /* number of panes (duh) */
1834    r_ov  = pbar->dc->ovc->r_ov ;   /* [j] = R value of color #j */
1835    g_ov  = pbar->dc->ovc->g_ov ;   /* [j] = G value of color #j */
1836    b_ov  = pbar->dc->ovc->b_ov ;   /* [j] = B value of color #j */
1837 
1838    eps = 0.10f * fabsf(pval[0]-pval[npan]) / (float)nbig ;
1839    neq = 2 * npan ;
1840    col = (rgbyte *)malloc(sizeof(rgbyte)*neq) ;
1841    val = (float * )malloc(sizeof(float) *neq) ;
1842 
1843    jj = ovind[0] ; val[0] = pval[0] ;
1844    col[0].r = r_ov[jj] ; col[0].g = g_ov[jj] ; col[0].b = b_ov[jj] ;
1845    for( kk=ii=1 ; ii < npan ; ii++ ){
1846      jj = ovind[ii-1] ; val[kk] = pval[ii]+eps ;
1847      col[kk].r = r_ov[jj] ; col[kk].g = g_ov[jj] ; col[kk].b = b_ov[jj] ; kk++ ;
1848      jj = ovind[ii] ; val[kk] = pval[ii]-eps ;
1849      col[kk].r = r_ov[jj] ; col[kk].g = g_ov[jj] ; col[kk].b = b_ov[jj] ; kk++ ;
1850    }
1851    jj = ovind[npan-1] ; val[kk] = pval[npan] ;
1852    col[kk].r = r_ov[jj] ; col[kk].g = g_ov[jj] ; col[kk].b = b_ov[jj] ;
1853 
1854    PBAR_fill_bigmap( neq , val , col , bigcolor , nbig ) ;
1855 
1856    free(val) ; free(col) ;
1857    EXRETURN ;
1858 }
1859 
1860 /*-----------------------------------------------------------------------*/
1861 
1862 static int reject_zero = 0 ;
1863 
1864 #undef  ZREJ
1865 #define ZREJ(vvv) (reject_zero && (vvv)==0)   /* 20 Apr 2005 */
1866 
1867 #undef  THBOT
1868 #undef  THTOP
1869 #undef  THBIG
1870 #define THBIG    1.e+37f
1871 #define THBOT(t) ((thrsign==0 || thrsign==2) ? (-(t)) : (-THBIG))
1872 #define THTOP(t) ((thrsign==0 || thrsign==1) ? (t)    :  (THBIG))
1873 
1874 /*-----------------------------------------------------------------------*/
1875 /*!  Make a functional overlay -- very simple routine at present;
1876    n = slice index , br_fim = data structure to extract slice from.
1877   Note that imseq requires that the overlay be an image of shorts.
1878   This routine requires that the function and threshold images be bytes,
1879   shorts, or floats (complex-valued functional images are not supported).
1880   (The underlay image may be any legal type; this image is not used here.)
1881 -------------------------------------------------------------------------*/
1882 
AFNI_func_overlay(int n,FD_brick * br_fim)1883 MRI_IMAGE * AFNI_func_overlay( int n , FD_brick *br_fim )
1884 {
1885    Three_D_View *im3d ;
1886    MRI_IMAGE *im_thr , *im_fim , *im_ov , *im_noved=NULL ;
1887    short *ar_ov ;
1888    short fim_ovc[NPANE_MAX+1] ;  /* for the 'old' discrete pane colorization */
1889    float fim_thr[NPANE_MAX+1] ;
1890    rgbyte pane_bigcolor[NPANE_SUPERBIG] ;
1891    int npix , ii , lp , num_lp , ival , nbig ;
1892    float scale_factor , scale_thr ;
1893    MCW_pbar *pbar ;
1894    int simult_thr , need_thr ;
1895    int thrsign ;  /* 08 Aug 2007 */
1896 
1897 ENTRY("AFNI_func_overlay") ;
1898 
1899    /* sanity check */
1900 
1901    if( br_fim == NULL || n < 0 ) RETURN(NULL) ;  /* nothing to do */
1902 
1903    im3d = (Three_D_View *) br_fim->parent ;
1904    if( !IM3D_OPEN(im3d) ) RETURN(NULL) ;         /* should not happen */
1905 
1906    pbar = im3d->vwid->func->inten_pbar ;
1907 
1908    /* 22 May 2009: check if functional dataset is ready */
1909 
1910    if( !ISVALID_DSET(im3d->fim_now) ){
1911      AFNI_SEE_FUNC_OFF(im3d) ; RETURN(NULL) ;
1912    }
1913 
1914    reject_zero = VEDIT_good(im3d->vedset) ||         /* 09 Dec 2014 */
1915                  !AFNI_yesenv("AFNI_OVERLAY_ZERO") ; /* 20 Apr 2005 */
1916 
1917    ival = im3d->vinfo->thr_index ;  /* threshold sub-brick index */
1918 
1919    /* get the component images */
1920 
1921    ival = im3d->vinfo->thr_index ;  /* threshold sub-brick index */
1922    LOAD_DSET_VIEWS(im3d) ; /* 02 Nov 1996 */
1923 
1924    need_thr = (im3d->vinfo->func_threshold > 0.0) && im3d->vinfo->thr_onoff ;
1925    thrsign  = im3d->vinfo->thr_sign ; /* 08 Aug 2007 */
1926 
1927    /* 29 Mar 2005: make sure statistics of overlay dataset are ready */
1928 
1929    if( !DSET_LOADED(im3d->fim_now) ){
1930      DSET_load( im3d->fim_now ) ;
1931      if( !DSET_LOADED(im3d->fim_now) && im3d->fim_now->warp_parent != NULL )
1932        DSET_load( im3d->fim_now->warp_parent ) ;
1933      im3d->vinfo->stats_func_ok = im3d->vinfo->arang_func_ok = 0 ;
1934    }
1935    if( !im3d->vinfo->stats_func_ok || !im3d->vinfo->arang_func_ok
1936                                    || (!im3d->vinfo->stats_thresh_ok && need_thr) ){
1937      DSET_load( im3d->fim_now ) ;
1938      if( !DSET_LOADED(im3d->fim_now) && im3d->fim_now->warp_parent != NULL )
1939        DSET_load( im3d->fim_now->warp_parent ) ;
1940      AFNI_reset_func_range( im3d ) ;
1941    }
1942 
1943    /* get the threshold image? */
1944 
1945    if( need_thr ){
1946      STATUS("fetch im_thr") ;
1947      AFNI_set_ignore_vedit(1) ;  /* 20 Oct 2016 */
1948      im_thr = FD_warp_to_mri( n , ival , br_fim ) ;
1949      AFNI_set_ignore_vedit(0) ;
1950    } else{
1951      STATUS("don't need im_thr") ;
1952      im_thr = NULL ;
1953    }
1954 
1955 #if 1
1956    scale_thr = 1.0f ;   /* FD_warp_to_mri() already scales this */
1957 #else
1958    scale_thr = DSET_BRICK_FACTOR(br_fim->dset,ival) ;
1959    if( scale_thr == 0.0f ) scale_thr = 1.0f ;
1960 #endif
1961 
1962    /* get function image */
1963 
1964    { int ind ;
1965 
1966      ind = im3d->vinfo->fim_index ;
1967      if( ind >= DSET_NVALS(br_fim->dset) )
1968        ind = DSET_NVALS(br_fim->dset) - 1 ;
1969 
1970      STATUS("fetch im_fim") ;
1971      im_fim = FD_warp_to_mri( n, ind, br_fim ) ;  /* get func image */
1972      scale_factor = FIM_RANGE(im3d) ;
1973      if( scale_factor == 0.0 || PBAR_FULLRANGE ) scale_factor = 1.0f ;
1974 
1975      /* Get non-volume-edited image as well, maybe [05 Nov 2018] */
1976 
1977      if( im_fim != NULL             &&
1978          VEDIT_good(im3d->vedset)   &&
1979          im3d->vinfo->thr_use_alpha && pbar->bigmode ){
1980 
1981        AFNI_set_ignore_vedit(1) ;
1982        STATUS("fetch im_noved") ;
1983        im_noved = FD_warp_to_mri( n , ind , br_fim ) ;
1984        AFNI_set_ignore_vedit(0) ;
1985        if( mri_equal(im_fim,im_noved) ){ mri_free(im_noved); im_noved=NULL; }
1986      }
1987 
1988      /* set OLay label string, for display as text in GUI */
1989 
1990      AFNI_set_valabel( br_fim , n ,
1991                        (im_noved != NULL) ? im_noved : im_fim ,
1992                        im3d->vinfo->func_val ) ;
1993    }
1994 
1995    /* 04 Mar 2003: convert thresh to float if its datum is unacceptable */
1996    /* 21 Dec 2004: also allow RGB images as threshold via this mechanism :) */
1997 
1998    if( im_thr != NULL && !(im_thr->kind == MRI_float ||
1999                            im_thr->kind == MRI_short ||
2000                            im_thr->kind == MRI_byte    ) ){
2001 
2002      MRI_IMAGE *qim = mri_to_float(im_thr) ;
2003      STATUS("converted im_thr to floats") ;
2004      mri_free(im_thr) ; im_thr = qim ; scale_thr = 1.0f ;
2005    }
2006 
2007    /* set Thr label string, for display in GUI */
2008 
2009    AFNI_set_valabel( br_fim , n , im_thr , im3d->vinfo->thr_val ) ;
2010 
2011    /* if component images not good, quit now */
2012 
2013    if( im_fim == NULL ){
2014      STATUS("couldn't get Func image!") ;
2015      KILL_1MRI(im_thr) ; RETURN(NULL) ;
2016    }
2017 
2018    /* 15 Apr 2002: allow overlay image to be pure RBG (no colorscale) */
2019    /* 20 Dec 2004: allow thresholding of RGB overlays */
2020 
2021    if( im_fim->kind == MRI_rgb ){                  /* 15 Apr 2002: RGB overlays */
2022 
2023      if( im_thr != NULL && im_thr != im_fim ){          /* 20 Dec 2004 */
2024        float thresh = get_3Dview_func_thresh(im3d,1) / scale_thr ;
2025        float thb=THBOT(thresh) , tht=THTOP(thresh) ;    /* 08 Aug 2007 */
2026        mri_threshold( thb,tht , im_thr , im_fim ) ;     /* in place */
2027      }
2028 
2029      /* 27 Apr 2005: transform RGB func image in place? */
2030 
2031      mri_rgb_transform_nD( im_fim, 0, im3d->vwid->func->pbar_transform0D_func );
2032      mri_rgb_transform_nD( im_fim, 2, im3d->vwid->func->pbar_transform2D_func );
2033 
2034      if( im_thr != im_fim ) KILL_1MRI(im_thr) ;  /* toss the trash */
2035      RETURN(im_fim) ;
2036    }
2037 
2038    /* must be a scalar image at this point */
2039 
2040    if( ! AFNI_GOOD_FUNC_DTYPE(im_fim->kind) ){   /* should never happen! */
2041      MRI_IMAGE *qim = mri_to_float(im_fim) ;     /* (but fix it if it does) */
2042      STATUS("had to convert im_fim to floats?????") ;
2043      mri_free(im_fim) ; im_fim = qim ;
2044      if( im_noved != NULL ){ mri_free(im_noved); im_noved=NULL; }
2045    }
2046 
2047    /* 15 Jun 2000: transformation of functional image? */
2048 
2049    if( im3d->vwid->func->pbar_transform0D_func != NULL ){
2050      MRI_IMAGE *tim = mri_to_float(im_fim) ;
2051      STATUS("transform0D of im_fim") ;
2052 #if 0
2053      im3d->vwid->func->pbar_transform0D_func( tim->nvox , MRI_FLOAT_PTR(tim) ) ;
2054 #else
2055      AFNI_CALL_0D_function( im3d->vwid->func->pbar_transform0D_func ,
2056                             tim->nvox , MRI_FLOAT_PTR(tim)           ) ;
2057 #endif
2058      if( im_fim != im_thr ) mri_free(im_fim) ;
2059      im_fim = tim ;
2060 
2061      if( im_noved != NULL ){
2062        tim = mri_to_float(im_noved) ;
2063        AFNI_CALL_0D_function( im3d->vwid->func->pbar_transform0D_func ,
2064                               tim->nvox , MRI_FLOAT_PTR(tim)           ) ;
2065        mri_free(im_noved) ; im_noved = tim ;
2066      }
2067    }
2068 
2069    if( im3d->vwid->func->pbar_transform2D_func != NULL ){
2070      MRI_IMAGE *tim = mri_to_float(im_fim) ;
2071      STATUS("transform2D of im_fim") ;
2072 #if 0
2073      im3d->vwid->func->pbar_transform2D_func( tim->nx, tim->ny,
2074                                               tim->dx, tim->dy,
2075                                               MRI_FLOAT_PTR(tim) ) ;
2076 #else
2077      AFNI_CALL_2D_function( im3d->vwid->func->pbar_transform2D_func ,
2078                             tim->nx, tim->ny, tim->dx, tim->dy, MRI_FLOAT_PTR(tim) ) ;
2079 #endif
2080      if( im_fim != im_thr ) mri_free(im_fim) ;
2081      im_fim = tim ;
2082 
2083      if( im_noved != NULL ){
2084        tim = mri_to_float(im_noved) ;
2085        AFNI_CALL_2D_function( im3d->vwid->func->pbar_transform2D_func ,
2086                               tim->nx, tim->ny, tim->dx, tim->dy, MRI_FLOAT_PTR(tim) ) ;
2087        mri_free(im_noved) ; im_noved = tim ;
2088      }
2089    }
2090 
2091    /**---------- 30 Jan 2003:
2092                  if the pbar is in "big" mode,
2093                  then create an RGB overlay in a separate function ----------**/
2094 
2095    /* flag bits for using the newnew function (NFO = New Function Overlay?)  */
2096 
2097 #define NFO_ZBELOW_MASK  1
2098 #define NFO_ZABOVE_MASK  2
2099 #define NFO_ALIN_MASK    4   /* alpha = linear fade */
2100 #define NFO_AQUA_MASK    8   /* alpha = quadratic fade */
2101 #define NFO_USE_BOXED   16   /* not Boxster */
2102 #define NFO_POS_MASK   256
2103 
2104 #define ALWAYS_USE_BIGMODE 1  /* use the newnew function always [17 Jul 2019] */
2105 
2106    if( ALWAYS_USE_BIGMODE || pbar->bigmode ){ /*--- "continuous" colorscale --*/
2107 
2108      float thresh = get_3Dview_func_thresh(im3d,1) / scale_thr ;
2109      float thb=THBOT(thresh) , tht=THTOP(thresh) ; /* 08 Aug 2007 */
2110      int zbelow=0 , zabove=0 , flags ;
2111      rgbyte *bigcol=NULL ;
2112 
2113 if( PRINT_TRACING && im_thr != NULL )
2114 { char str[256] ; float tmax ;
2115   sprintf(str,"im_thr: nx=%d ny=%d kind=%s",
2116           im_thr->nx,im_thr->ny,MRI_TYPE_NAME(im_thr)) ; STATUS(str) ;
2117   tmax = (float)mri_maxabs(im_thr) ;
2118   sprintf(str,"maxabs(im_thr)=%g scale_thr=%g thresh=%g",tmax,scale_thr,thresh);
2119   STATUS(str) ;
2120   sprintf(str,"func_threshold=%g func_thresh_top=%g cont_perc_thr=%d",
2121           im3d->vinfo->func_threshold,im3d->vinfo->func_thresh_top,
2122           im3d->cont_perc_thr);
2123   STATUS(str);
2124 }
2125 
2126      /* Always use AFNI_newnewfunc_overlay() [05 Nov 2018] */
2127 
2128      if( !pbar->bigmode ){   /* manufacture a 'continuous' colormap */
2129 #if 1
2130        nbig = NPANE_SUPERBIG ;  /* this reduces inter-pane weird artifacts */
2131 #else
2132        nbig = NPANE_BIG ;
2133 #endif
2134        AFNI_panes_to_bigcolor( pbar , pane_bigcolor , nbig ) ;
2135        bigcol = pane_bigcolor ;
2136      } else {
2137        if( pbar->big30 ) reject_zero = VEDIT_good(im3d->vedset) ;
2138        if( pbar->big31 ){                              /* Feb 2012 */
2139          zbelow = !pbar->big32 ; zabove = !pbar->big30 ;
2140        } else {
2141          zbelow = (pbar->bigbot == 0.0f) ;
2142        }
2143        bigcol = pbar->bigcolor ; nbig = NPANE_BIG ;
2144      }
2145 
2146      /* set various rendering flags */
2147 
2148      flags = zbelow * NFO_ZBELOW_MASK + zabove * NFO_ZABOVE_MASK ;
2149 
2150      if( im3d->vinfo->thr_use_alpha ){     /* alpha fading? */
2151        int mm = im3d->vwid->func->thr_alpha_av->ival ;        /* 28 Jun 2021 */
2152        flags |= (mm == 0 ) ? NFO_ALIN_MASK : NFO_AQUA_MASK ;  /* fade method */
2153      }
2154 
2155      if( im3d->vinfo->use_posfunc   ) flags |= NFO_POS_MASK  ;  /* pos only FIM? */
2156      if( im3d->vinfo->thr_use_boxed ) flags |= NFO_USE_BOXED ;  /* boxing day?   */
2157 
2158      /* Is there in truth no beauty? */
2159 
2160      im_ov = AFNI_newnewfunc_overlay( im_thr , thb,tht ,
2161                                       im_fim , im_noved ,
2162                                       scale_factor*pbar->bigbot ,
2163                                       scale_factor*pbar->bigtop ,
2164                                       nbig , bigcol , flags ,
2165                                       im3d->vinfo->thr_alpha_floor , im3d->dc ) ;
2166      goto CLEANUP ;
2167    } /*-------------------- end of the new way of doing things ---------------*/
2168 
2169 #if (ALWAYS_USE_BIGMODE == 0)  /*------ cast aside code [17 Jul 2019] --------*/
2170 
2171    /** create output image the old way (indexes into overlay colors) **/
2172 
2173    npix  = im_fim->nx * im_fim->ny ;
2174    im_ov = mri_new( im_fim->nx , im_fim->ny , MRI_short ) ;
2175    ar_ov = MRI_SHORT_PTR( im_ov ) ;
2176 
2177    /* set overlay colors */
2178 
2179    num_lp = pbar->num_panes ;
2180 
2181    for( lp=0 ; lp < num_lp ; lp++ ) fim_ovc[lp] = pbar->ov_index[lp] ;
2182 
2183    fim_ovc[num_lp] = (im3d->vinfo->use_posfunc) ? (0) : (fim_ovc[num_lp-1]) ;
2184 
2185    /** process im_fim into overlay, depending on data type **/
2186 
2187    simult_thr = (im_thr != NULL) &&                     /* do threshold    */
2188                 (im3d->vinfo->func_threshold > 0.0) &&  /* simultaneously? */
2189                 (im_fim->kind == im_thr->kind) ;        /* (July 15, 1996) */
2190 
2191    switch( im_fim->kind ){
2192 
2193       default:                             /* should not happen! */
2194          if( im_thr != im_fim ) mri_free(im_thr) ;
2195          mri_free(im_fim) ; mri_free(im_ov) ; mri_free(im_noved) ;
2196          STATUS("bad im_fim->kind!") ;
2197       RETURN(NULL) ;
2198 
2199       case MRI_short:{
2200          short *ar_fim = MRI_SHORT_PTR(im_fim) ;
2201 
2202          for( lp=0 ; lp < num_lp ; lp++ )
2203            fim_thr[lp] = scale_factor * pbar->pval[lp+1] ;
2204 
2205          if( simult_thr ){
2206            float thresh = get_3Dview_func_thresh(im3d,1) / scale_thr ;
2207            float thb=THBOT(thresh) , tht=THTOP(thresh) ; /* 08 Aug 2007 */
2208            short *ar_thr = MRI_SHORT_PTR(im_thr) ;
2209            for( ii=0 ; ii < npix ; ii++ ){
2210              if( (ar_thr[ii] > thb && ar_thr[ii] < tht) || ZREJ(ar_fim[ii]) ){
2211                ar_ov[ii] = 0 ;
2212              } else {
2213                for( lp=0 ; lp < num_lp && ar_fim[ii] < fim_thr[lp] ; lp++ ) ; /*nada*/
2214                ar_ov[ii] = fim_ovc[lp] ;
2215              }
2216            }
2217          } else {
2218            for( ii=0 ; ii < npix ; ii++ ){
2219              if( ZREJ(ar_fim[ii]) ){
2220                ar_ov[ii] = 0 ;
2221              } else {
2222                for( lp=0 ; lp < num_lp && ar_fim[ii] < fim_thr[lp] ; lp++ ) ; /*nada*/
2223                ar_ov[ii] = fim_ovc[lp] ;
2224              }
2225            }
2226          }
2227       }
2228       break ;
2229 
2230       case MRI_byte:{
2231          byte *ar_fim = MRI_BYTE_PTR(im_fim) ;
2232 
2233          for( lp=0 ; lp < num_lp ; lp++ )
2234            fim_thr[lp] = (pbar->pval[lp+1] > 0.0) ? scale_factor*pbar->pval[lp+1]
2235                                                   : 0.0                          ;
2236 
2237          if( simult_thr ){
2238            float thresh = get_3Dview_func_thresh(im3d,1) / scale_thr ;
2239            float thb=THBOT(thresh) , tht=THTOP(thresh) ; /* 08 Aug 2007 */
2240            byte *ar_thr = MRI_BYTE_PTR(im_thr) ;
2241 
2242            for( ii=0 ; ii < npix ; ii++ ){
2243              if( ar_thr[ii] < tht || ZREJ(ar_fim[ii]) ){  /* assuming thb <= 0 */
2244                ar_ov[ii] = 0 ;
2245              } else {
2246                for( lp=0 ; lp < num_lp && ar_fim[ii] < fim_thr[lp] ; lp++ ) ; /*nada*/
2247                ar_ov[ii] = fim_ovc[lp] ;
2248              }
2249            }
2250          } else {
2251            for( ii=0 ; ii < npix ; ii++ ){
2252              if( ZREJ(ar_fim[ii]) ){
2253                ar_ov[ii] = 0 ;
2254              } else {
2255                for( lp=0 ; lp < num_lp && ar_fim[ii] < fim_thr[lp] ; lp++ ) ; /*nada*/
2256                ar_ov[ii] = fim_ovc[lp] ;
2257              }
2258            }
2259          }
2260       }
2261       break ;
2262 
2263       case MRI_float:{
2264          float *ar_fim = MRI_FLOAT_PTR(im_fim) ;
2265 
2266          for( lp=0 ; lp < num_lp ; lp++ )
2267            fim_thr[lp] = scale_factor * pbar->pval[lp+1] ;
2268 
2269          if( simult_thr ){
2270            float thresh = get_3Dview_func_thresh(im3d,1) ;
2271            float thb=THBOT(thresh) , tht=THTOP(thresh) ; /* 08 Aug 2007 */
2272            float *ar_thr = MRI_FLOAT_PTR(im_thr) ;
2273 
2274            for( ii=0 ; ii < npix ; ii++ ){
2275              if( (ar_thr[ii] > thb && ar_thr[ii] < tht) || ZREJ(ar_fim[ii])  ){
2276                ar_ov[ii] = 0 ;
2277              } else {
2278                for( lp=0 ; lp < num_lp && ar_fim[ii] < fim_thr[lp] ; lp++ ) ; /*nada*/
2279                ar_ov[ii] = fim_ovc[lp] ;
2280              }
2281            }
2282          } else {
2283            for( ii=0 ; ii < npix ; ii++ ){
2284              if( ZREJ(ar_fim[ii]) ){
2285                ar_ov[ii] = 0 ;
2286              } else {
2287                for( lp=0 ; lp < num_lp && ar_fim[ii] < fim_thr[lp] ; lp++ ) ; /*nada*/
2288                ar_ov[ii] = fim_ovc[lp] ;
2289              }
2290            }
2291          }
2292       }
2293       break ;
2294    }
2295 
2296    /** if have yet to do threshold, clip the overlay **/
2297 
2298    if( im_thr != NULL && im3d->vinfo->func_threshold > 0.0 && !simult_thr ){
2299 
2300      switch( im_thr->kind ){
2301 
2302        case MRI_short:{
2303          float thresh = get_3Dview_func_thresh(im3d,1) / scale_thr ;
2304          float thb=THBOT(thresh) , tht=THTOP(thresh) ; /* 08 Aug 2007 */
2305          short *ar_thr = MRI_SHORT_PTR(im_thr) ;
2306 
2307          for( ii=0 ; ii < npix ; ii++ )
2308            if( ar_thr[ii] > thb && ar_thr[ii] < tht ) ar_ov[ii] = 0 ;
2309        }
2310        break ;
2311 
2312        case MRI_byte:{
2313          float thresh = get_3Dview_func_thresh(im3d,1) / scale_thr ;
2314          float thb=THBOT(thresh) , tht=THTOP(thresh) ; /* 08 Aug 2007 */
2315          byte *ar_thr = MRI_BYTE_PTR(im_thr) ;
2316 
2317          for( ii=0 ; ii < npix ; ii++ )  /* assuming thb <= 0 */
2318            if( ar_thr[ii] < tht ) ar_ov[ii] = 0 ;
2319        }
2320        break ;
2321 
2322        case MRI_float:{
2323          float thresh = get_3Dview_func_thresh(im3d,1) ;
2324          float thb=THBOT(thresh) , tht=THTOP(thresh) ; /* 08 Aug 2007 */
2325          float *ar_thr = MRI_FLOAT_PTR(im_thr) ;
2326 
2327          for( ii=0 ; ii < npix ; ii++ )
2328            if( ar_thr[ii] > thb && ar_thr[ii] < tht ) ar_ov[ii] = 0 ;
2329        }
2330        break ;
2331      }
2332    }
2333 
2334    /* delete the overlay if it contains nothing */
2335 
2336    for( ii=0 ; ii < npix ; ii++ ) if( ar_ov[ii] != 0 ) break ;
2337    if( ii == npix ) KILL_1MRI(im_ov) ;  /* no nonzero values --> no overlay */
2338 
2339 #endif /*------------------------ ALWAYS_USE_BIGMODE -------------------------*/
2340 
2341    /** time to trot, Bwana **/
2342 
2343 CLEANUP:
2344    if( im_thr != NULL && im_thr != im_fim ) mri_free( im_thr ) ;
2345    mri_free( im_fim ) ; mri_free( im_noved ) ;
2346 
2347 #ifdef ALLOW_OLD_EDGIZE
2348    /* 21 Mar 2005: Hollow out overlay? */
2349    if( AFNI_yesenv("AFNI_EDGIZE_OVERLAY") ) mri_edgize(im_ov) ;
2350 #endif
2351 
2352    RETURN(im_ov) ;
2353 }
2354 
2355 #if 0  /******************* OBSOLETE FUNCTION - do not compile ***********/
2356 /*-----------------------------------------------------------------------*/
2357 /*! Make a functional overlay the new way (30 Jan 2003):
2358     - im_thr = threshold image (may be NULL)
2359     - thbot  = pixels with values in im_thr in range (thbot..thtop)
2360     - thtop  =  don't get overlay
2361     - im_fim = image to make overlay from (may not be NULL)
2362     - fimbot = pixel value to map to fimcolor[0]
2363     - fimtop = pixel value to map to fimcolor[NPANE_BIG-1]
2364 
2365   [08 Aug 2007 -- change 'thresh' to 'thbot,thtop']
2366 -------------------------------------------------------------------------*/
2367 
2368 MRI_IMAGE * AFNI_newfunc_overlay( MRI_IMAGE *im_thr , float thbot,float thtop,
2369                                   MRI_IMAGE *im_fim ,
2370                                   float fimbot, float fimtop, rgbyte *fimcolor,
2371                                   int flags )
2372 {
2373    MRI_IMAGE *im_ov ;
2374    byte *ovar ;
2375    int ii , npix , jj ;
2376    float fac , val ;
2377    int dothr = (thbot < thtop) ;                         /* 08 Aug 2007 */
2378 
2379    int zbelow = (flags & NFO_ZBELOW_MASK) != 0 ;  /* Feb 2012 */
2380    int zabove = (flags & NFO_ZABOVE_MASK) != 0 ;
2381 
2382    byte *bfim=NULL ; short *sfim=NULL ; float *ffim=NULL ; int kk ;
2383 
2384 ENTRY("AFNI_newfunc_overlay") ;
2385 
2386    if( im_fim == NULL || fimbot >= fimtop || fimcolor == NULL ) RETURN(NULL) ;
2387 
2388    /* create output image */
2389 
2390 STATUS("create output image") ;
2391    im_ov = mri_new_conforming( im_fim , MRI_rgb ) ;
2392    ovar  = MRI_RGB_PTR(im_ov) ;
2393    npix  = im_ov->nvox ;
2394    fac   = NPANE_BIG / (fimtop-fimbot) ; /* scale from data value to color index */
2395 
2396    kk = (int)im_fim->kind ;
2397    switch( kk ){
2398      default: mri_free(im_ov) ; RETURN(NULL) ;   /* should never happen! */
2399      case MRI_short: sfim = MRI_SHORT_PTR(im_fim) ; break ;
2400      case MRI_byte : bfim = MRI_BYTE_PTR (im_fim) ; break ;
2401      case MRI_float: ffim = MRI_FLOAT_PTR(im_fim) ; break ;
2402    }
2403 
2404 STATUS("colorization") ;
2405    for( ii=0 ; ii < npix ; ii++ ){
2406           if( kk == MRI_byte  ) val = (float)bfim[ii] ;
2407      else if( kk == MRI_short ) val = (float)sfim[ii] ;
2408      else                       val =        ffim[ii] ;
2409      if( ZREJ(val) || (zabove && val > fimtop) || (zbelow && val < fimbot) ) continue ;
2410      jj = (int)( fac*(fimtop-val) ) ;
2411      if( jj < 0 ) jj = 0 ; else if( jj > NPANE_BIG1 ) jj = NPANE_BIG1 ;
2412      ovar[3*ii  ] = fimcolor[jj].r ;
2413      ovar[3*ii+1] = fimcolor[jj].g ;
2414      ovar[3*ii+2] = fimcolor[jj].b ;
2415    }
2416 
2417    /** now apply threshold, if any **/
2418 
2419    if( dothr && im_thr != NULL ){
2420 STATUS("thresholdization") ;
2421      switch( im_thr->kind ){
2422 
2423        case MRI_short:{
2424          register float thb=thbot , tht=thtop ;
2425          register short *ar_thr = MRI_SHORT_PTR(im_thr) ;
2426          for( ii=0 ; ii < npix ; ii++ ){
2427            if( ar_thr[ii] > thb && ar_thr[ii] < tht )
2428              ovar[3*ii] = ovar[3*ii+1] = ovar[3*ii+2] = 0 ;
2429          }
2430        }
2431        break ;
2432 
2433        case MRI_byte:{
2434          register float thb=thbot , tht=thtop ;
2435          register byte *ar_thr = MRI_BYTE_PTR(im_thr) ;
2436          for( ii=0 ; ii < npix ; ii++ )  /* assuming thb <= 0 always */
2437            if( ar_thr[ii] < tht )
2438              ovar[3*ii] = ovar[3*ii+1] = ovar[3*ii+2] = 0 ;
2439        }
2440        break ;
2441 
2442        case MRI_float:{
2443          register float thb=thbot , tht=thtop ;
2444          register float *ar_thr = MRI_FLOAT_PTR(im_thr) ;
2445          for( ii=0 ; ii < npix ; ii++ )
2446            if( ar_thr[ii] > thb && ar_thr[ii] < tht )
2447              ovar[3*ii] = ovar[3*ii+1] = ovar[3*ii+2] = 0 ;
2448        }
2449        break ;
2450      }
2451    }
2452 
2453    RETURN(im_ov) ;
2454 }
2455 #endif /***************** OBSOLETE FUNCTION ********************/
2456 
2457 /*-----------------------------------------------------------------------*/
2458 /* This function is only used to alpha fade the pbar image.
2459    However, the macros below are used in AFNI_newnewfunc_overlay().
2460 *//*---------------------------------------------------------------------*/
2461 
2462 /* th  = threshold at this voxel
2463    fac = scales threshold to be between 0 and 1 */
2464 
2465 #define ALIN(th,fac) (th*fac)                     /* linear fading */
2466 #define AQUA(th,fac) (ALIN(th,fac)*ALIN(th,fac))  /* quadratic fading */
2467 
2468 /* alcode is internal to functions that use ALFA */
2469 
2470 #define ALFA(th,fac) (alcode==1) ? 255.0f*ALIN(th,fac)+af          \
2471                     :(alcode==2) ? 255.0f*AQUA(th,fac)+af : 0.0f
2472 
2473 /* convert alpha to a byte value for opacity '.a' in RGBA;
2474    max value set to 222 to try to make sure there is some
2475    distinction between above-threshold voxels and below threshold rebel scum */
2476 
2477 #define ALFABYTE(xx) (  ((xx) <   0.0) ? (byte)0                      \
2478                       : ((xx) > 222.0) ? (byte)222 : (byte)rintf(xx) )
2479 
2480 
AFNI_alpha_fade_mri(Three_D_View * im3d,MRI_IMAGE * im)2481 void AFNI_alpha_fade_mri( Three_D_View *im3d , MRI_IMAGE *im )
2482 {
2483    float af,th,fi,aa,rf,bf,gf ; int ii,jj,kk,nx,ny ;
2484    byte *iar ;
2485    const int alcode=1 ;  /* linear fading across color bar image */
2486 
2487    if( !IM3D_OPEN(im3d) || im == NULL || im->kind != MRI_rgb ) return ;
2488    if( im3d->vinfo->thr_use_alpha <= 0 ) return ;
2489 
2490    af  = 255.0f*im3d->vinfo->thr_alpha_floor ;
2491    nx  = im->nx ; if( nx < 2 ) return ;
2492    ny  = im->ny ;
2493    fi  = 0.995f/(nx-1) ;
2494    iar = MRI_RGB_PTR(im) ;
2495 
2496    for( kk=jj=0 ; jj < ny ; jj++ ){
2497      for( ii=0 ; ii < nx ; ii++,kk+=3 ){
2498        if( ii==0 ) continue ;
2499        th = 1.0f - ii*fi ;
2500        aa = ALFA(th,1.0f) ;
2501        if( aa < 255.0f ){
2502          rf = iar[kk] ; gf = iar[kk+1] ; bf = iar[kk+2] ;
2503          if( rf==  0.0f && gf==  0.0f && bf==  0.0f ) continue ;  /* don't alter */
2504          if( rf==255.0f && gf==255.0f && bf==255.0f ) continue ;  /* black or white */
2505          rf = (aa/255.0f)*rf + (255.0f-aa) ; iar[kk  ] = BYTEIZE(rf) ;
2506          gf = (aa/255.0f)*gf + (255.0f-aa) ; iar[kk+1] = BYTEIZE(gf) ;
2507          bf = (aa/255.0f)*bf + (255.0f-aa) ; iar[kk+2] = BYTEIZE(bf) ;
2508        }
2509      }
2510    }
2511    return ;
2512 }
2513 
2514 /*-----------------------------------------------------------------------*/
2515 /*! Make a functional overlay the new new way (08 Dec 2014):
2516     - im_thr   = threshold image (may be NULL)
2517     - thbot    = pixels with values in im_thr in range (thbot..thtop)
2518     - thtop    =  get translucent overlay values
2519     - im_fim   = image to make overlay from (may not be NULL)
2520     - fimbot   = pixel value to map to fimcolor[0]
2521     - fimtop   = pixel value to map to fimcolor[nfimc-1]
2522     - nfimc    = number of colors in the fimcolor array
2523     - fimcolor = continuous color scale
2524  ** Changed Nov 2018 to allow a mixture of the volume edited
2525     FIM (im_fim) and the non-volume edited FIM (im_noved) to
2526     determine color and alpha.
2527  ** The output image is in RGBA format.
2528 -------------------------------------------------------------------------*/
2529 
AFNI_newnewfunc_overlay(MRI_IMAGE * im_thr,float thbot,float thtop,MRI_IMAGE * im_fim,MRI_IMAGE * im_noved,float fimbot,float fimtop,int nfimc,rgbyte * fimcolor,int flags,float alpha_floor,MCW_DC * dc)2530 MRI_IMAGE * AFNI_newnewfunc_overlay( MRI_IMAGE *im_thr , float thbot,float thtop,
2531                                      MRI_IMAGE *im_fim , MRI_IMAGE *im_noved ,
2532                                      float fimbot, float fimtop,
2533                                      int nfimc , rgbyte *fimcolor,
2534                                      int flags , float alpha_floor , MCW_DC *dc )
2535 {
2536    MRI_IMAGE *im_ov ;
2537    rgba *ovar ;
2538    int ii , npix , jj , nfimc1 = nfimc-1 ;
2539    float fac , val , vval ;
2540    int dothr = (thbot < thtop) && (im_thr != NULL);  /* 08 Aug 2007 */
2541    int alcode=0 ;                                    /* 09 Dec 2014 */
2542    int do_pos = (flags & NFO_POS_MASK) != 0 ;        /* 12 Dec 2014 */
2543    int do_box = (flags & NFO_USE_BOXED)!= 0 ;        /* 02 Nov 2018 */
2544 
2545    int zbelow = (flags & NFO_ZBELOW_MASK) != 0 ;     /* Feb 2012 */
2546    int zabove = (flags & NFO_ZABOVE_MASK) != 0 ;
2547    byte *bfim=NULL ; short *sfim=NULL ; float *ffim=NULL ; int kf ;
2548    byte *bvim=NULL ; short *svim=NULL ; float *fvim=NULL ;
2549 
2550 ENTRY("AFNI_newnewfunc_overlay") ;
2551 
2552    if( im_fim == NULL || fimbot >= fimtop || fimcolor == NULL || nfimc < 2 ) RETURN(NULL) ;
2553 
2554    /* create output image */
2555 
2556 STATUS("create output image") ;
2557    im_ov = mri_new_conforming( im_fim , MRI_rgba ) ; /* zero filled */
2558    ovar  = MRI_RGBA_PTR(im_ov) ;      /* our job is to fill this up */
2559    npix  = im_ov->nvox ;
2560    fac   = nfimc / (fimtop-fimbot) ;  /* scale from data value to color index */
2561    kf    = (int)im_fim->kind ;        /* type of data in FIM */
2562 
2563    /* pointer for FIM data */
2564 
2565    switch( kf ){
2566      default: mri_free(im_ov) ; RETURN(NULL) ;   /* should never happen! */
2567      case MRI_short: sfim = MRI_SHORT_PTR(im_fim) ; break ;
2568      case MRI_byte : bfim = MRI_BYTE_PTR (im_fim) ; break ;
2569      case MRI_float: ffim = MRI_FLOAT_PTR(im_fim) ; break ;
2570    }
2571 
2572    /* setup pointer for non-volume-edited FIM data */
2573 
2574    if( im_noved == NULL || im_noved->kind != im_fim->kind )
2575      im_noved = im_fim ;     /* make it be the same as the FIM data */
2576 
2577    switch( kf ){
2578      case MRI_short: svim = MRI_SHORT_PTR(im_noved) ; break ;
2579      case MRI_byte : bvim = MRI_BYTE_PTR (im_noved) ; break ;
2580      case MRI_float: fvim = MRI_FLOAT_PTR(im_noved) ; break ;
2581    }
2582 
2583 STATUS("colorization") ;
2584    /* compute the color of each pixel */
2585    /* color comes from the non-volume-edited data if available */
2586    /* note that pixels skipped here will get 0 alpha (ovar initialized to 0) */
2587    for( ii=0 ; ii < npix ; ii++ ){
2588           if( kf == MRI_byte  ) vval = (float)bvim[ii] ;
2589      else if( kf == MRI_short ) vval = (float)svim[ii] ;
2590      else                       vval =        fvim[ii] ;
2591 
2592      if( ZREJ(vval) || (zabove && vval > fimtop) || (zbelow && vval < fimbot) ) continue ;
2593      if( do_pos && vval <= 0.0f ) continue ;  /* 12 Dec 2014 */
2594 
2595      jj = (int)( fac*(fimtop-vval) ) ;
2596 #if 0
2597      INFO_message("v=%f -> jj=%d  fimbot=%f fimtop=%f fac=%f nfimc=%d",vval,jj,fimbot,fimtop,fac,nfimc) ;
2598 #endif
2599      if( jj < 0 ) jj = 0 ; else if( jj > nfimc1 ) jj = nfimc1 ;
2600      ovar[ii].r = fimcolor[jj].r ; /* colorize */
2601      ovar[ii].g = fimcolor[jj].g ;
2602      ovar[ii].b = fimcolor[jj].b ;
2603      ovar[ii].a = 255 ;            /* default is opaque */
2604             /* but voxels skipped above are transparent */
2605    }
2606 
2607    /** now apply threshold, if any **/
2608 
2609         if( flags & NFO_ALIN_MASK ) alcode = 1 ;  /* linear fade below thresh */
2610    else if( flags & NFO_AQUA_MASK ) alcode = 2 ;  /* quadratic fade */
2611    else                             alcode = 0 ;  /* no fade = sharp cutoff */
2612 
2613    if( dothr ){
2614      MRI_IMAGE *eim=NULL ; byte *ear=NULL ;
2615      int do_edge = do_box ;
2616      float ft,fb,af ;
2617 
2618      /* scalings for alpha fading on the threshold value */
2619 
2620      ft = (thtop > 0.0f) ? (1.0f-alpha_floor)/thtop : 0.0f ;  /* for positive thr */
2621      fb = (thbot < 0.0f) ? (1.0f-alpha_floor)/thbot : 0.0f ;  /* for negative thr */
2622      af = 255.0f*alpha_floor ;  /* always 0 for now */
2623 
2624      if( do_edge ){  /* for later use in mri_edgize_outer() */
2625        eim = mri_new_conforming( im_fim , MRI_byte ) ; ear = MRI_BYTE_PTR(eim) ;
2626      }
2627 
2628 STATUS("threshold-ization and alpha-ization") ;
2629      switch( im_thr->kind ){ /* the kind of data in the threshold image */
2630 
2631        default: break ;  /* should not happen */
2632 
2633        /* in the following code,
2634           note that alcode==0 implies ALFA() = 0.0 implies not visible,
2635           whereas alcode==1 or ==2 implies 0 < ALFA() < 1 implies translucent */
2636 
2637        case MRI_short:{
2638          register float thb=thbot , tht=thtop , aa ; register int rej, vvz ;
2639          register short *ar_thr = MRI_SHORT_PTR(im_thr) ;
2640          for( ii=0 ; ii < npix ; ii++ ){
2641                 if( kf == MRI_byte  ){ val = (float)bfim[ii]; vval = (float)bvim[ii]; }
2642            else if( kf == MRI_short ){ val = (float)sfim[ii]; vval = (float)svim[ii]; }
2643            else                      { val =        ffim[ii]; vval =        fvim[ii]; }
2644            vvz = (val == 0.0f) && (vval != 0.0f) ;        /* was vedit-ed out? */
2645            rej = (ovar[ii].a == 0) || (ar_thr[ii] == 0) ; /* rejected out of hand */
2646            if( rej ){
2647                                         ovar[ii].a = 0 ;     /* transparent */
2648            } else if( ar_thr[ii] > 0 && (ar_thr[ii] < tht || vvz) ){  /* alpha */
2649              aa = ALFA(ar_thr[ii],ft) ; ovar[ii].a = ALFABYTE(aa) ;   /* fading */
2650            } else if( ar_thr[ii] < 0 && (ar_thr[ii] > thb || vvz) ){  /* if below */
2651              aa = ALFA(ar_thr[ii],fb) ; ovar[ii].a = ALFABYTE(aa) ;   /* thresh */
2652            } else if( do_edge ){
2653              if( !(do_pos && val <= 0.0f) ) ear[ii] = 1 ; /* not faded or vedit-ed */
2654            }
2655          }
2656        }
2657        break ;
2658 
2659        case MRI_byte:{
2660          register float thb=thbot , tht=thtop , aa ; register int rej, vvz ;
2661          register byte *ar_thr = MRI_BYTE_PTR(im_thr) ;
2662          for( ii=0 ; ii < npix ; ii++ ){ /* assuming thb <= 0 always */
2663                 if( kf == MRI_byte  ){ val = (float)bfim[ii]; vval = (float)bvim[ii]; }
2664            else if( kf == MRI_short ){ val = (float)sfim[ii]; vval = (float)svim[ii]; }
2665            else                      { val =        ffim[ii]; vval =        fvim[ii]; }
2666            vvz = (val == 0.0f) && (vval != 0.0f) ;        /* was vedit-ed out? */
2667            rej = (ovar[ii].a == 0) || (ar_thr[ii] == 0) ; /* rejected out of hand */
2668            if( rej ){
2669                                         ovar[ii].a = 0 ;     /* transparent */
2670            } else if( ar_thr[ii] > 0 && (ar_thr[ii] < tht || vvz) ){
2671              aa = ALFA(ar_thr[ii],ft) ; ovar[ii].a = ALFABYTE(aa) ;
2672            } else if( do_edge ){
2673              if( !(do_pos && val <= 0.0f) ) ear[ii] = 1 ; /* not faded or vedit-ed */
2674            }
2675          }
2676        }
2677        break ;
2678 
2679        case MRI_float:{
2680          register float thb=thbot , tht=thtop , aa ; register int rej, vvz ;
2681          register float *ar_thr = MRI_FLOAT_PTR(im_thr) ;
2682          for( ii=0 ; ii < npix ; ii++ ){
2683                 if( kf == MRI_byte  ){ val = (float)bfim[ii]; vval = (float)bvim[ii]; }
2684            else if( kf == MRI_short ){ val = (float)sfim[ii]; vval = (float)svim[ii]; }
2685            else                      { val =        ffim[ii]; vval =        fvim[ii]; }
2686            vvz = (val == 0.0f) && (vval != 0.0f) ;        /* was vedit-ed out? */
2687            rej = (ovar[ii].a == 0) || (ar_thr[ii] == 0) ; /* rejected out of hand */
2688            if( rej ){
2689                                         ovar[ii].a = 0 ;     /* transparent */
2690            } else if( ar_thr[ii] > 0 && (ar_thr[ii] < tht || vvz) ){
2691              aa = ALFA(ar_thr[ii],ft) ; ovar[ii].a = ALFABYTE(aa) ;
2692            } else if( ar_thr[ii] < 0 && (ar_thr[ii] > thb || vvz) ){
2693              aa = ALFA(ar_thr[ii],fb) ; ovar[ii].a = ALFABYTE(aa) ;
2694            } else if( do_edge ){
2695              if( !(do_pos && val <= 0.0f) ) ear[ii] = 1 ; /* not faded or vedit-ed */
2696            }
2697          }
2698        }
2699        break ;
2700      }
2701 
2702      /* process the edges of the above-threshold regions? [Boxes] */
2703 
2704      if( do_edge ){
2705        char *cpt ; byte rb=1,gb=1,bb=1 ;
2706        mri_edgize_outer(eim) ;  /* mark the edges of the unfaded regions */
2707        cpt = getenv("AFNI_FUNC_BOXED_COLOR") ;
2708        if( cpt != NULL ){
2709          float rf=0.005f, gf=0.005f, bf=0.005f ;
2710          DC_parse_color( dc , cpt , &rf,&gf,&bf ) ;
2711          rb = BYTEIZE(255.0f*rf); gb = BYTEIZE(255.0f*gf); bb = BYTEIZE(255.0f*bf);
2712        }
2713        for( ii=0 ; ii < npix ; ii++ ){
2714         if( ear[ii] ){ ovar[ii].r=rb; ovar[ii].g=gb; ovar[ii].b=bb; ovar[ii].a=254; }
2715        }
2716        mri_free(eim) ;
2717      }
2718    } /* end of threshold-ization and all the fun it has */
2719 
2720    RETURN(im_ov) ;
2721 }
2722 #undef ALIN  /* these are not used anywhere below */
2723 #undef AQUA
2724 #undef ALFA
2725 
2726 /*-----------------------------------------------------------------------
2727   Make an overlay from the TT atlas
2728    n = slice index; (ax_1,ax_2,ax_3) = slice orientation codes
2729    fov = functional overlay image previously computed
2730          if non-NULL, then fov will be overlaid, and will be returned
2731          if NULL, then a new image will be created and returned
2732    This function is called from AFNI_overlay, when making the combined
2733    overlay image for display in a viewer.
2734   -- 25 Jul 2001 - RWCox
2735 -------------------------------------------------------------------------*/
2736 
AFNI_ttatlas_overlay(Three_D_View * im3d,int n,int ax_1,int ax_2,int ax_3,MRI_IMAGE * fov)2737 MRI_IMAGE * AFNI_ttatlas_overlay( Three_D_View *im3d ,
2738                                   int n , int ax_1 , int ax_2 , int ax_3 ,
2739                                   MRI_IMAGE *fov )
2740 {
2741    THD_3dim_dataset *dseTT ;
2742    TTRR_params *ttp ;
2743    byte *b0=NULL , *brik,  *ovc  ;
2744    short *s0=NULL, *ovar, *val, *fovar ;
2745    float *f0=NULL;
2746    MRI_IMAGE *ovim=NULL, *b0im=NULL, *fovim=NULL, *b1im=NULL, *outim ;
2747    int gwin , fwin , nreg , ii,jj , nov ;
2748    int at_sbi, fim_type, at_vox, at_nsb;
2749    int jill = AFNI_yesenv("AFNI_JILL_TRAVESTY") ; /* Jill is trouble */
2750 
2751 ENTRY("AFNI_ttatlas_overlay") ;
2752 
2753    /* setup and sanity checks */
2754 
2755    if(jill) INFO_message("Starting AFNI_ttatlas_overlay");
2756 
2757    /* make sure we are actually drawing something */
2758 
2759    STATUS("checking if Atlas Colors is on") ;
2760    ttp = TTRR_get_params() ;
2761    if( ttp == NULL ){
2762      if( jill ) ININFO_message(" params are off - vamoose") ;
2763      RETURN(NULL) ;
2764    }
2765 
2766    STATUS("checking if Atlas dataset can be loaded") ;
2767 
2768    if((!atlas_ovdset) ||
2769       ( DSET_NVOX(atlas_ovdset) != DSET_NVOX(im3d->anat_now))){
2770        if(atlas_ovdset)
2771           DSET_unload(atlas_ovdset);
2772        dseTT = TT_retrieve_atlas_dset(Current_Atlas_Default_Name(),0);
2773        if( dseTT == NULL ) RETURN(NULL) ;
2774        DSET_load(dseTT) ;
2775        if(atlas_ovdset)    /* reset the atlas overlay dataset */
2776           DSET_unload(atlas_ovdset);
2777        atlas_ovdset = r_new_resam_dset ( dseTT, im3d->anat_now,  0, 0, 0, NULL,
2778                                        MRI_NN, NULL, 1, 0);
2779   if(jill)
2780       ININFO_message(" First time loading atlas dset");
2781 /*       DSET_unload(dseTT);*/
2782        if(!atlas_ovdset) {
2783          if(jill)
2784             ININFO_message(" Could not load atlas dset");
2785          RETURN(NULL);
2786        }
2787    }
2788 
2789    if( DSET_NVOX(atlas_ovdset) != DSET_NVOX(im3d->anat_now) ){
2790       WARNING_message(
2791          "Voxels do not match between resampled atlas and the underlay dataset");
2792       RETURN(NULL) ;
2793    }
2794    /* get slices from atlas dataset */
2795    STATUS("loading Atlas bricks") ;
2796 
2797    /* extract slice from right direction from atlas */
2798    b0im = AFNI_slice_flip( n , 0 , RESAM_NN_TYPE , ax_1,ax_2,ax_3 ,
2799                            atlas_ovdset ) ;
2800 
2801    if( b0im == NULL ) RETURN(NULL) ;  /* this is bad */
2802 
2803    /* make a new overlay image [shorts] for the atlas colors */
2804 
2805    STATUS("making new overlay for Atlas") ;
2806    ovim = mri_new_conforming( b0im , MRI_short ) ;
2807    ovar = MRI_SHORT_PTR(ovim) ;
2808    memset( ovar , 0 , ovim->nvox * sizeof(short) ) ; /* nugatory */
2809    /* actually, only needed b0im to get resampled grid dimensions */
2810    mri_free(b0im);
2811    if( jill )
2812      ININFO_message("ovim = %d x %d",ovim->nx,ovim->ny) ;
2813 
2814    /* fwin => input function 'wins' over Atlas - overlay image gets priority */
2815    /* gwin => earlier Atlas brick 'wins' over later Atlas brick */
2816 
2817    fwin = (ttp->meth == TTRR_METH_FGA) || (ttp->meth == TTRR_METH_FAG) ;
2818    gwin = (ttp->meth == TTRR_METH_FGA) || (ttp->meth == TTRR_METH_GAF) ;
2819 
2820    nreg = ttp->num ;    /* number of 'on' regions     */
2821    brik = ttp->ttbrik ; /* which sub-brick in atlas    */
2822    val  = ttp->ttval ;  /* which code in that sub-brick */
2823    ovc  = ttp->ttovc ;  /* which overlay color index   */
2824 
2825    /* loop over image voxels, find overlays from Atlas */
2826 
2827    STATUS("doing Atlas overlay") ;
2828    at_nsb = DSET_NVALS(atlas_ovdset);  /* number of atlas bricks */
2829    nov = 0;
2830    for( at_sbi=0; at_sbi < at_nsb; at_sbi++) { /* loop over bricks */
2831 
2832       /* extract atlas slice from volumne #at_sbi */
2833       b1im = AFNI_slice_flip( n,at_sbi,RESAM_NN_TYPE,ax_1,ax_2,ax_3,
2834                               atlas_ovdset);
2835       if( b1im == NULL ) continue ; /* this is bad */
2836 
2837       /* get pointer to slice's data */
2838       fim_type = b1im->kind ;
2839       b0 = NULL ; s0 = NULL ; f0 = NULL ;
2840       switch( fim_type ){
2841          case MRI_byte:  b0 = MRI_BYTE_PTR(b1im) ; break ;
2842          case MRI_short: s0 = MRI_SHORT_PTR(b1im); break ;
2843          case MRI_float: f0 = MRI_FLOAT_PTR(b1im); break ;
2844       }
2845       if( b0 == NULL && s0 == NULL && f0 == NULL ){ /* this is bad */
2846         ERROR_message("Atlas data type is illegal: %s",MRI_TYPE_NAME(b1im)) ;
2847         mri_free(b1im) ; continue ;
2848       }
2849 
2850       for( ii=0 ; ii < ovim->nvox ; ii++ ){ /* loop over voxels */
2851 
2852          /* if the overlay array is already set in the overlay */
2853          /* earlier atlas voxel, keep it (if gwin is also set) */
2854 
2855          if( ovar[ii] && gwin ) continue ;
2856 
2857          switch( fim_type ){ /* get the atlas value at this voxel */
2858            default:
2859            case MRI_byte:  at_vox = (int) b0[ii];      break ;
2860            case MRI_short: at_vox = (int) s0[ii];      break ;
2861            case MRI_float: at_vox = (int)(f0[ii]+.1f); break ;
2862          }
2863 
2864          /* check Atlas 'on' regions for hits */
2865          for( jj=0 ; jj < nreg ; jj++ ){
2866            if( at_vox == val[jj] ){ /* atlas value matches jj-th region in list */
2867              ovar[ii] = ovc[jj] ; nov++ ; break ;
2868            }
2869          }
2870 
2871       }
2872       mri_free(b1im) ; /* done with this atlas slice */
2873    }
2874 
2875    if(PRINT_TRACING)
2876       { char str[256]; sprintf(str,"Atlas overlaid %d pixels",nov); STATUS(str); }
2877    if(jill)
2878       ININFO_message(" Atlas overlaid %d image pixels out of %d",nov,ovim->nvox) ;
2879 
2880    if( mri_allzero(ovim) ){       /* if it is all zero, we are done here */
2881      mri_free(ovim) ; RETURN(NULL) ;
2882    }
2883 
2884    /* convert ovim from shorts to RGB at this point */
2885 
2886    fovim = ISQ_index_to_rgb( im3d->dc , 1 , ovim ) ;
2887    mri_free(ovim) ;
2888    ovim = fovim ; fovim = NULL ;
2889 
2890    /* setup input image for overlaying in RGB land */
2891 
2892    if( fov == NULL ){                   /* no input of existing overlay? */
2893      fovim = NULL ;
2894    } else if( fov->kind == MRI_short ){  /* should no longer be possible */
2895      fovim = ISQ_index_to_rgb( im3d->dc , 1 , ovim ) ; /* convert to RGB */
2896    } else if( IS_RGB_IMAGE(fov) ){
2897      fovim = fov ;
2898    } else {                                 /* someone is is BIG trouble */
2899      ERROR_message(" Atlas input overlay image kind illegal: %s",MRI_TYPE_NAME(fov)) ;
2900      fovim = NULL;
2901    }
2902 
2903    if( fovim == NULL ){  /* if there was no input overlay, return what we made */
2904       if(jill)
2905          ININFO_message(" No input overlay, that's okay - returning atlas overlay");
2906       RETURN(ovim);
2907    }
2908 
2909    /* at this point, ovim is RGB and fovim is RGB or RGBA */
2910 
2911    if( fovim->nvox != ovim->nvox ){                /* shouldn't happen!  */
2912      if(jill)
2913        ININFO_message(" freeing atlas ovim due to input grid mismatch :(");
2914      if( fovim != fov ) mri_free(fovim) ;
2915      mri_free(ovim); RETURN(NULL) ;
2916    }
2917 
2918    STATUS("merging input RGB* overlay with Atlas") ;
2919    if(jill)
2920      ININFO_message(" merging input %s overlay with Atlas",MRI_TYPE_NAME(fovim)) ;
2921 
2922    if( fwin )
2923      outim = ISQ_overlay( im3d->dc , ovim , fovim , 1.0f ) ;
2924    else
2925      outim = ISQ_overlay( im3d->dc , fovim , ovim , 1.0f ) ;
2926 
2927    if(jill)
2928        ININFO_message(" freeing ovim at normal return");
2929    mri_free(ovim); if( fovim != fov ) mri_free(fovim) ;
2930 
2931    if(jill)
2932       ININFO_message(" leaving AFNI_ttatlas_overlay");
2933    RETURN(outim);
2934 }
2935 
2936 /* use to force reload of atlas for new default */
reset_atlas_ovdset()2937 void reset_atlas_ovdset()
2938 {
2939    DSET_unload(atlas_ovdset);
2940    atlas_ovdset = NULL;
2941 }
2942 
2943 /* get the current resampled dataset used for overlay */
current_atlas_ovdset()2944 THD_3dim_dataset * current_atlas_ovdset()
2945 {
2946    return(atlas_ovdset);
2947 }
2948 
2949 /*---------------------------------------------------------------------*/
2950 
AFNI_resam_texter(MCW_arrowval * av,XtPointer junk)2951 char * AFNI_resam_texter( MCW_arrowval *av , XtPointer junk )
2952 {
2953    return RESAM_shortstr[av->ival] ;
2954 }
2955 
2956 /*---------------------------------------------------------------------*/
2957 
AFNI_resam_av_CB(MCW_arrowval * av,XtPointer cd)2958 void AFNI_resam_av_CB( MCW_arrowval *av , XtPointer cd )
2959 {
2960    Three_D_View *im3d = (Three_D_View *) cd ;
2961    int reunder , redisplay ;
2962 
2963 ENTRY("AFNI_resam_av_CB") ;
2964 
2965    /* sanity check */
2966 
2967    if( ! IM3D_OPEN(im3d) ) EXRETURN ;
2968 
2969    /* assign resampling type based on which arrowval, and redraw */
2970 
2971    if( av == im3d->vwid->dmode->func_resam_av ){
2972       STATUS("set func_resam_mode") ;
2973       im3d->vinfo->func_resam_mode = av->ival ;
2974       if( im3d->b123_fim != NULL ){
2975          im3d->b123_fim->resam_code =
2976           im3d->b231_fim->resam_code =
2977            im3d->b312_fim->resam_code = im3d->vinfo->func_resam_mode ;
2978       }
2979 
2980    } else if( av == im3d->vwid->dmode->thr_resam_av ){  /* 09 Dec 1997 */
2981       STATUS("set thr_resam_mode") ;
2982       im3d->vinfo->thr_resam_mode = av->ival ;
2983       if( im3d->b123_fim != NULL ){
2984          im3d->b123_fim->thr_resam_code =
2985           im3d->b231_fim->thr_resam_code =
2986            im3d->b312_fim->thr_resam_code = im3d->vinfo->thr_resam_mode ;
2987       }
2988 
2989    } else if( av == im3d->vwid->dmode->anat_resam_av ){
2990       STATUS("set anat_resam_mode") ;
2991       im3d->vinfo->anat_resam_mode = av->ival ;
2992       im3d->b123_anat->resam_code =
2993        im3d->b231_anat->resam_code =
2994         im3d->b312_anat->resam_code = im3d->vinfo->anat_resam_mode ;
2995    }
2996 
2997    SHOW_AFNI_PAUSE ;
2998 #if 0
2999    STATUS_IM3D_TMASK(im3d) ;
3000    STATUS("clear tmask") ;
3001 #endif
3002    IM3D_CLEAR_TMASK(im3d) ;                                /* Mar 2013 */
3003    IM3D_CLEAR_THRSTAT(im3d) ;                           /* 12 Jun 2014 */
3004    AFNI_setup_thrstat(im3d,0) ;
3005    im3d->vinfo->tempflag = 1 ;
3006    AFNI_modify_viewing( im3d , False ) ;  /* redisplay */
3007    SHOW_AFNI_READY ;
3008    RESET_AFNI_QUIT(im3d) ;
3009    EXRETURN ;
3010 }
3011 
3012 /*----------------------------------------------------------------------*/
3013 /*----- set the bricks to use for the underlay images -----*/
3014 
AFNI_assign_ulay_bricks(Three_D_View * im3d)3015 void AFNI_assign_ulay_bricks( Three_D_View *im3d )
3016 {
3017 ENTRY("AFNI_assign_ulay_bricks") ;
3018 
3019    if( ! IM3D_OPEN(im3d) ) EXRETURN ;
3020 
3021    im3d->vinfo->stats_anat_ok =
3022     im3d->vinfo->stats_func_ok =
3023      im3d->vinfo->arang_func_ok =
3024       im3d->vinfo->stats_thresh_ok = 0 ; /* 24 May 2019 */
3025 
3026    switch( im3d->vinfo->underlay_type ){
3027      default:
3028      case UNDERLAY_ANAT:                    /* set underlay to anat */
3029        STATUS("anatomy underlay") ;
3030        im3d->b123_ulay = im3d->b123_anat ;
3031        im3d->b231_ulay = im3d->b231_anat ;
3032        im3d->b312_ulay = im3d->b312_anat ;
3033      break ;
3034 
3035      case UNDERLAY_ALLFUNC:
3036        if( ISVALID_DSET(im3d->fim_now) ){
3037          STATUS("functional underlay") ;
3038          im3d->b123_ulay = im3d->b123_fim ;
3039          im3d->b231_ulay = im3d->b231_fim ;
3040          im3d->b312_ulay = im3d->b312_fim ;
3041        } else {
3042          STATUS("defaulted anatomy underlay") ;
3043          WARNING_message("invalid Overlay dataset") ;
3044          im3d->b123_ulay = im3d->b123_anat ;
3045          im3d->b231_ulay = im3d->b231_anat ;
3046          im3d->b312_ulay = im3d->b312_anat ;
3047 #ifdef USE_UNDERLAY_BBOX
3048          MCW_set_bbox( im3d->vwid->func->underlay_bbox , 1<<UNDERLAY_ANAT ) ;
3049 #else
3050          im3d->vinfo->underlay_type = UNDERLAY_ANAT ;
3051 #endif
3052        }
3053      break ;
3054    }
3055 
3056    EXRETURN ;
3057 }
3058 
3059 /*----------------------------------------------------------------------
3060    called when the underlay needs to be changed:
3061      -- when the underlay type is altered by a button press
3062      -- when a new set of images is to be displayed
3063      -- when the existing underlay has been altered in some hideous way
3064    if the calling widget "w" is NULL, then the calling routine is
3065    required to do the redrawing later
3066 ------------------------------------------------------------------------*/
3067 
AFNI_underlay_CB(Widget w,XtPointer cd,XtPointer cb)3068 void AFNI_underlay_CB( Widget w , XtPointer cd , XtPointer cb )
3069 {
3070    Three_D_View *im3d = (Three_D_View *)cd ;
3071    int bval , force_redraw=(cb != NULL) ;
3072    RwcBoolean seq_exist ;
3073 
3074 ENTRY("AFNI_underlay_CB") ;
3075 
3076    if( ! IM3D_OPEN(im3d) ) EXRETURN ;
3077 
3078    im3d->vinfo->stats_anat_ok =
3079     im3d->vinfo->stats_func_ok =
3080      im3d->vinfo->arang_func_ok =
3081       im3d->vinfo->stats_thresh_ok = 0 ; /* 24 May 2019 */
3082 
3083 #ifdef USE_UNDERLAY_BBOX
3084    if( w != NULL ) bval = AFNI_first_tog( LAST_UNDERLAY_TYPE+1 ,
3085                                           im3d->vwid->func->underlay_bbox->wbut ) ;
3086    else            bval = im3d->vinfo->underlay_type ;
3087 #else
3088    bval = im3d->vinfo->underlay_type ;
3089 #endif
3090 
3091    if( bval == im3d->vinfo->underlay_type && w != NULL && IM3D_ULAY_COHERENT(im3d) ) EXRETURN ;
3092 
3093    im3d->vinfo->underlay_type = bval ;
3094 
3095    AFNI_assign_ulay_bricks(im3d) ;  /* 10 Jun 2014 */
3096 
3097 #if 0
3098 INFO_message("AFNI_underlay_CB: anat:%p %p %p  fim:%p %p %p  ulay:%p %p %p" ,
3099              im3d->b123_anat , im3d->b231_anat , im3d->b312_anat ,
3100              im3d->b123_fim  , im3d->b231_fim  , im3d->b312_fim  ,
3101              im3d->b123_ulay , im3d->b231_ulay , im3d->b312_ulay  ) ;
3102 #endif
3103 
3104    /*--- May 1996: destroy useless graph windows ---*/
3105 
3106    im3d->ignore_seq_callbacks = AFNI_IGNORE_REDRAWS ;  /* 16 Feb 97 */
3107 
3108    if( !DSET_GRAPHABLE(im3d->b123_ulay->dset) || !BRICK_GRAPHABLE(im3d->b123_ulay) ){
3109       if( im3d->g123 != NULL ){
3110          drive_MCW_grapher( im3d->g123 , graDR_destroy , NULL ) ;
3111          im3d->g123 = NULL ;
3112       }
3113       XtSetSensitive( im3d->vwid->imag->graph_xyz_pb , False ) ;
3114    } else {
3115       XtSetSensitive( im3d->vwid->imag->graph_xyz_pb , True ) ;
3116    }
3117 
3118    if( !DSET_GRAPHABLE(im3d->b231_ulay->dset) || !BRICK_GRAPHABLE(im3d->b231_ulay) ){
3119       if( im3d->g231 != NULL ){
3120          drive_MCW_grapher( im3d->g231 , graDR_destroy , NULL ) ;
3121          im3d->g231 = NULL ;
3122       }
3123       XtSetSensitive( im3d->vwid->imag->graph_yzx_pb , False ) ;
3124    } else {
3125       XtSetSensitive( im3d->vwid->imag->graph_yzx_pb , True ) ;
3126    }
3127 
3128    if( !DSET_GRAPHABLE(im3d->b312_ulay->dset) || !BRICK_GRAPHABLE(im3d->b312_ulay) ){
3129       if( im3d->g312 != NULL ){
3130          drive_MCW_grapher( im3d->g312 , graDR_destroy , NULL ) ;
3131          im3d->g312 = NULL ;
3132       }
3133       XtSetSensitive( im3d->vwid->imag->graph_zxy_pb , False ) ;
3134    } else {
3135       XtSetSensitive( im3d->vwid->imag->graph_zxy_pb , True ) ;
3136    }
3137 
3138    /** 05 Mar 1997: disable viewers if x or y dimension is 1 pixel **/
3139 
3140    if( !BRICK_DRAWABLE(im3d->b123_ulay) ){
3141       if( im3d->s123 != NULL ){
3142          drive_MCW_imseq( im3d->s123 , isqDR_destroy , NULL ) ;
3143          im3d->s123 = NULL ;
3144       }
3145       XtSetSensitive( im3d->vwid->imag->image_xyz_pb , False ) ;
3146    } else {
3147       XtSetSensitive( im3d->vwid->imag->image_xyz_pb , True ) ;
3148    }
3149 
3150    if( !BRICK_DRAWABLE(im3d->b231_ulay) ){
3151       if( im3d->s231 != NULL ){
3152          drive_MCW_imseq( im3d->s231 , isqDR_destroy , NULL ) ;
3153          im3d->s231 = NULL ;
3154       }
3155       XtSetSensitive( im3d->vwid->imag->image_yzx_pb , False ) ;
3156    } else {
3157       XtSetSensitive( im3d->vwid->imag->image_yzx_pb , True ) ;
3158    }
3159 
3160    if( !BRICK_DRAWABLE(im3d->b312_ulay) ){
3161       if( im3d->s312 != NULL ){
3162          drive_MCW_imseq( im3d->s312 , isqDR_destroy , NULL ) ;
3163          im3d->s312 = NULL ;
3164       }
3165       XtSetSensitive( im3d->vwid->imag->image_zxy_pb , False ) ;
3166    } else {
3167       XtSetSensitive( im3d->vwid->imag->image_zxy_pb , True ) ;
3168    }
3169 
3170    im3d->ignore_seq_callbacks = AFNI_IGNORE_NOTHING ;  /* 16 Feb 97 */
3171 
3172    /*--- attach any changes to open image displays ---*/
3173 
3174    seq_exist = (im3d->s123 != NULL) || (im3d->s231 != NULL) || (im3d->s312 != NULL) ||
3175                (im3d->g123 != NULL) || (im3d->g231 != NULL) || (im3d->g312 != NULL)   ;
3176 
3177    /* set the title for all windows */
3178 
3179    AFNI_set_window_titles( im3d ) ;
3180 
3181    if( seq_exist ){
3182 
3183       im3d->ignore_seq_callbacks = AFNI_IGNORE_EVERYTHING ;
3184 #if 0
3185       STATUS_IM3D_TMASK(im3d) ;
3186       STATUS("clear tmask") ;
3187 #endif
3188       IM3D_CLEAR_TMASK(im3d) ;                                /* Mar 2013 */
3189       IM3D_CLEAR_THRSTAT(im3d) ;                           /* 12 Jun 2014 */
3190       AFNI_setup_thrstat(im3d,0) ;                         /* 27 Jun 2019 */
3191 
3192       if( im3d->s123 != NULL )
3193          drive_MCW_imseq( im3d->s123 , isqDR_newseq ,
3194                                        (XtPointer) im3d->b123_ulay ) ;
3195 
3196       if( im3d->s231 != NULL )
3197          drive_MCW_imseq( im3d->s231 , isqDR_newseq ,
3198                                        (XtPointer) im3d->b231_ulay ) ;
3199 
3200       if( im3d->s312 != NULL )
3201          drive_MCW_imseq( im3d->s312 , isqDR_newseq ,
3202                                        (XtPointer) im3d->b312_ulay ) ;
3203 
3204       if( im3d->g123 != NULL )
3205          drive_MCW_grapher( im3d->g123 , graDR_newdata ,
3206                                          (XtPointer) im3d->b123_ulay ) ;
3207 
3208       if( im3d->g231 != NULL )
3209          drive_MCW_grapher( im3d->g231 , graDR_newdata ,
3210                                          (XtPointer) im3d->b231_ulay ) ;
3211 
3212       if( im3d->g312 != NULL )
3213          drive_MCW_grapher( im3d->g312 , graDR_newdata ,
3214                                          (XtPointer) im3d->b312_ulay ) ;
3215 
3216       im3d->ignore_seq_callbacks = AFNI_IGNORE_REDRAWS ;
3217 
3218       /** July 1996: get the sequences to send their montaging status **/
3219 
3220       if( im3d->s123 != NULL )
3221          drive_MCW_imseq( im3d->s123 , isqDR_sendmontage , NULL ) ;
3222       else
3223          CLEAR_MONTAGE( im3d , im3d->b123_ulay ) ;
3224 
3225       if( im3d->s231 != NULL )
3226          drive_MCW_imseq( im3d->s231 , isqDR_sendmontage , NULL ) ;
3227       else
3228          CLEAR_MONTAGE( im3d , im3d->b231_ulay ) ;
3229 
3230       if( im3d->s312 != NULL )
3231          drive_MCW_imseq( im3d->s312 , isqDR_sendmontage , NULL ) ;
3232       else
3233          CLEAR_MONTAGE( im3d , im3d->b312_ulay ) ;
3234 
3235       im3d->ignore_seq_callbacks = AFNI_IGNORE_NOTHING ;
3236 
3237       if( w != NULL || force_redraw ){  /* a real callback */
3238           SHOW_AFNI_PAUSE ;
3239           AFNI_set_viewpoint( im3d , -1,-1,-1 , REDISPLAY_ALL ) ;
3240           SHOW_AFNI_READY ;
3241       }
3242    }
3243 
3244    /* Feb 1998: if a receiver is open
3245                 send it a message that something has altered */
3246 
3247    AFNI_process_alteration(im3d) ;
3248 
3249    HINTIZE_pbar(im3d) ; /* 15 Aug 2001 */
3250    FIX_SCALE_SIZE(im3d) ;
3251 
3252    EXRETURN ;
3253 }
3254 
3255 /*--------------------------------------------------------------------*/
3256 
AFNI_controller_label(Three_D_View * im3d)3257 char * AFNI_controller_label( Three_D_View *im3d )
3258 {
3259    static char clabel[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" ;
3260    static char str[8] ;
3261    int ic, ib;
3262 
3263    ic = AFNI_controller_index( im3d ) ;
3264    if( ic < 0 || ic > 26 ) strcpy (str,"    ") ;  /* shouldn't happen */
3265    else {
3266       if ((ib = get_user_np_bloc())>-1) { /* ZSS June 2011 */
3267                            sprintf(str,"[%c%d] ",clabel[ic], ib) ;
3268       } else {
3269                            sprintf(str,"[%c] ",clabel[ic]) ;
3270       }
3271    }
3272    return str ;
3273 }
3274 
3275 /*--------------------------------------------------------------------
3276   Set the titles in all windows
3277 ----------------------------------------------------------------------*/
3278 
3279 #undef  USE_TITLE2
3280 #define USE_TITLE2(ds)   ( ISVALID_DSET(ds)                     &&  \
3281                            AFNI_yesenv("AFNI_TITLE_LABEL2")     &&  \
3282                            *((ds)->label2) != '\0'              &&  \
3283                            strcmp( (ds)->label2 , "zyxt" ) != 0   )
3284 
AFNI_set_window_titles(Three_D_View * im3d)3285 void AFNI_set_window_titles( Three_D_View *im3d )
3286 {
3287    RwcBoolean redo_title ;
3288    char ttl[THD_MAX_NAME] , nam[THD_MAX_NAME] ;
3289    char *tnam , *clab ; int ilab ;
3290    char signum ; /* 08 Aug 2007 */
3291    int ninit=0;
3292 
3293 ENTRY("AFNI_set_window_titles") ;
3294 
3295    if( ! IM3D_OPEN(im3d) ) EXRETURN ;
3296 
3297    clab = AFNI_controller_label(im3d) ;
3298    ninit = strlen(clab)-1;
3299    switch( im3d->vinfo->thr_sign ){
3300      default: ilab = ninit -1; break ;
3301      case 1:  ilab = ninit ; clab[ninit] = '+' ; break ;
3302      case 2:  ilab = ninit ; clab[ninit] = '-' ; break ;
3303    }
3304    switch( im3d->vinfo->underlay_type ){  /* 08 May 2008 */
3305      default:               clab[++ilab] = 'u' ; break ;
3306      case UNDERLAY_ALLFUNC: clab[++ilab] = 'o' ; break ;
3307    }
3308    clab[++ilab] = ' ' ; clab[++ilab] = '\0' ;
3309 
3310    if( im3d->anat_wod_flag )
3311      sprintf(ttl , "{warp}%s%s: " , clab,GLOBAL_argopt.title_name) ;
3312    else
3313      sprintf(ttl , "%s%s: " , clab,GLOBAL_argopt.title_name) ;
3314 
3315    if( USE_TITLE2(im3d->anat_now) ){
3316      strcat( ttl , im3d->anat_now->label2 ) ;
3317    } else {
3318      strcpy( nam , im3d->anat_now->dblk->diskptr->directory_name ) ;
3319      strcat( nam , im3d->anat_now->dblk->diskptr->filecode ) ;
3320      tnam = THD_trailname(nam,SESSTRAIL+1) ;
3321      strcat( ttl , tnam ) ;
3322    }
3323 
3324    if( ISVALID_3DIM_DATASET(im3d->fim_now) ){
3325      strcat( ttl , " & " ) ;
3326      if( USE_TITLE2(im3d->fim_now) ){
3327        strcat( ttl , im3d->fim_now->label2 ) ;
3328      } else {
3329        strcat( ttl , im3d->fim_now->dblk->diskptr->filecode ) ;
3330      }
3331    }
3332 
3333    redo_title = (RwcBoolean) (strcmp(ttl,im3d->window_title) != 0 ) ;
3334    if( redo_title ){
3335      strcpy( im3d->window_title , ttl ) ;
3336      XtVaSetValues( im3d->vwid->top_shell , XmNtitle , ttl , NULL ) ;
3337 
3338      if( im3d->s123 != NULL )
3339        drive_MCW_imseq( im3d->s123 , isqDR_title , (XtPointer) ttl ) ;
3340 
3341      if( im3d->s231 != NULL )
3342        drive_MCW_imseq( im3d->s231 , isqDR_title , (XtPointer) ttl ) ;
3343 
3344      if( im3d->s312 != NULL )
3345        drive_MCW_imseq( im3d->s312 , isqDR_title , (XtPointer) ttl ) ;
3346 
3347      if( im3d->g123 != NULL )
3348        drive_MCW_grapher( im3d->g123 , graDR_title , (XtPointer) ttl ) ;
3349 
3350      if( im3d->g231 != NULL )
3351        drive_MCW_grapher( im3d->g231 , graDR_title , (XtPointer) ttl ) ;
3352 
3353      if( im3d->g312 != NULL )
3354        drive_MCW_grapher( im3d->g312 , graDR_title , (XtPointer) ttl ) ;
3355    }
3356 
3357    EXRETURN ;
3358 }
3359 
3360 /*--------------------------------------------------------------------*/
3361 /*! Determine if dset is in the AFNI global session - 21 Dec 2001.
3362 ----------------------------------------------------------------------*/
3363 
DSET_in_global_session(THD_3dim_dataset * dset)3364 int DSET_in_global_session( THD_3dim_dataset *dset )
3365 {
3366    THD_slist_find find ;
3367 
3368    if( !ISVALID_DSET(dset) ) return 0 ;
3369 
3370    find = THD_dset_in_session( FIND_IDCODE ,
3371                                &(dset->idcode) ,
3372                                GLOBAL_library.session ) ;
3373 
3374    return (find.dset != NULL) ;
3375 }
3376 
3377 /*--------------------------------------------------------------------
3378    used to select between sessions and datasets
3379 ----------------------------------------------------------------------*/
3380 
3381 /** labels for the chooser window **/
3382 
3383 static char *dset_choice[] = { "Session" , "Underlay" , "Overlay" , "Dataset" } ;
3384 
3385 /** max size of strings in the list **/
3386 
3387 #define STRLIST_SIZE      (THD_MAX_PREFIX+256)
3388 #define MAX_SESSTRAIL_LEN 96
3389 
AFNI_choose_dataset_CB(Widget w,XtPointer cd,XtPointer cb)3390 void AFNI_choose_dataset_CB( Widget w , XtPointer cd , XtPointer cb )
3391 {
3392    static char *strlist[THD_MAX_CHOICES] ;  /* strings to choose between */
3393    static int first_call = 1 ;              /* initialization flag */
3394 
3395    int num_str , ii , init_str , vv , jj ;
3396    char *label ;
3397    Widget wpar ;
3398    Three_D_View *im3d = (Three_D_View *) cd ;
3399    int llen , ltop ;
3400    int browse_select = 0 ;
3401    int is_other = 0 ;       /* 18 Dec 2007 */
3402    void (*cbfun)(Widget,XtPointer,MCW_choose_cbs *)=AFNI_finalize_dataset_CB;
3403    THD_3dim_dataset *temp_dset=NULL;
3404    int sesstrail = (strcmp(im3d->ss_now->sessname,"All_Datasets")==0) ;
3405    char *st=NULL , sst[STRLIST_SIZE+1] ;
3406 
3407 ENTRY("AFNI_choose_dataset_CB") ;
3408 
3409    /*--- initialize ---*/
3410 
3411    if( ! IM3D_OPEN(im3d) || w == (Widget)NULL ) EXRETURN ;
3412 
3413    sesstrail = (strcmp(im3d->ss_now->sessname,"All_Datasets")==0) ||
3414                AFNI_yesenv("AFNI_USE_SESSTRAIL") ;
3415 
3416    im3d->vinfo->stats_anat_ok =
3417     im3d->vinfo->stats_func_ok =
3418      im3d->vinfo->arang_func_ok =
3419       im3d->vinfo->stats_thresh_ok = 0 ; /* 24 May 2019 */
3420 
3421    if( GLOBAL_library.have_dummy_dataset ){  /* 26 Feb 2007: read session? */
3422      if( w == im3d->vwid->view->choose_sess_pb ||
3423          w == im3d->vwid->view->popchoose_sess_pb ){
3424 
3425        AFNI_read_sess_CB(im3d->vwid->dmode->read_sess_pb,(XtPointer)im3d,NULL) ;
3426 
3427      } else {
3428        BEEPIT ; WARNING_message("Can't choose dataset if all you have is Dummy") ;
3429      }
3430      EXRETURN ;
3431    }
3432 
3433 #if 0
3434    if( AFNI_splash_isopen() == 1 ){ BEEPIT ; EXRETURN ; }
3435 #endif
3436 
3437    /* how about a rescan ? ZSS - Fur Greg Detre */
3438 
3439    if( AFNI_yesenv("AFNI_RESCAN_AT_SWITCH") &&
3440       !(w == im3d->vwid->view->choose_sess_pb ||
3441         w == im3d->vwid->view->popchoose_sess_pb) ){
3442 
3443      STATUS("rescanning, per AFNI_RESCAN_AT_SWITCH") ;
3444      AFNI_rescan_CB( w , (XtPointer)im3d , NULL ) ;
3445    }
3446 
3447    if( first_call ){
3448      for( ii=0 ; ii < THD_MAX_CHOICES ; ii++ )
3449        strlist[ii] = (char*)XtMalloc( sizeof(char) * (STRLIST_SIZE+1) ) ;
3450      first_call = 0 ;
3451    }
3452 
3453    /*--- make a list of session names ---*/
3454 
3455    if( w == im3d->vwid->view->choose_sess_pb ||
3456        w == im3d->vwid->view->popchoose_sess_pb ){
3457 
3458       wpar    = im3d->vwid->view->choose_sess_pb ;
3459       num_str = GLOBAL_library.sslist->num_sess ;
3460       if( num_str < 1 ) EXRETURN ;
3461 
3462       for( ii=0 ; ii < num_str ; ii++ ){
3463          MCW_strncpy( strlist[ii] ,
3464                       GLOBAL_library.sslist->ssar[ii]->lastname ,
3465                       STRLIST_SIZE ) ;
3466       }
3467 
3468       init_str = im3d->vinfo->sess_num ;
3469       label    = dset_choice[0] ;
3470 
3471    /*--- make a list of anatomy names ---*/
3472 
3473    } else if( w == im3d->vwid->view->choose_anat_pb ||
3474               w == im3d->vwid->view->popchoose_anat_pb ){
3475 
3476       wpar    = im3d->vwid->view->choose_anat_pb ;
3477       num_str = im3d->ss_now->num_dsset ;
3478       if( num_str < 1 ) EXRETURN ;
3479 
3480       if( AFNI_yesenv("AFNI_DATASET_BROWSE") ) browse_select = 1 ;
3481       THD_set_oblique_report(num_str-1, -1);
3482       ltop = 4 ;
3483       for( ii=0 ; ii < num_str ; ii++ ){
3484            #if 0 /* No more of this stuff    ZSS Nov 2011 */
3485                THD_report_obliquity(GET_SESSION_DSET(im3d->ss_now,ii,0)) ;
3486            #endif
3487 
3488          for( vv=FIRST_VIEW_TYPE ; vv <= LAST_VIEW_TYPE ; vv++ )
3489             {
3490                temp_dset = GET_SESSION_DSET(im3d->ss_now, ii, vv);
3491 
3492                if( ISVALID_3DIM_DATASET(temp_dset) ) break ;
3493             }
3494 
3495          if( vv <= LAST_VIEW_TYPE ){
3496             llen = strlen( temp_dset->dblk->diskptr->prefix ) ;
3497             if( sesstrail ){
3498               st = THD_trailname(temp_dset->dblk->diskptr->directory_name,1) ;
3499               if( st != NULL ){
3500                 if( strlen(st) > MAX_SESSTRAIL_LEN )
3501                   st += (strlen(st)-MAX_SESSTRAIL_LEN) ;
3502                 llen += strlen(st) ;
3503               }
3504             }
3505             if( llen > ltop ) ltop = llen ;
3506          }
3507       }
3508       ltop = MIN(ltop,STRLIST_SIZE-24) ;  /* 06 Aug 2002 */
3509 
3510       for( ii=0 ; ii < num_str ; ii++ ){
3511          for( vv=FIRST_VIEW_TYPE ; vv <= LAST_VIEW_TYPE ; vv++ ) {
3512             temp_dset = GET_SESSION_DSET(im3d->ss_now, ii, vv);
3513             if( ISVALID_3DIM_DATASET(temp_dset) ) break ;
3514          }
3515 
3516          if( vv <= LAST_VIEW_TYPE ){
3517             if( sesstrail ){
3518               st = THD_trailname(temp_dset->dblk->diskptr->directory_name,1) ;
3519               if( st != NULL ){
3520                 if( strlen(st) > MAX_SESSTRAIL_LEN )
3521                   st += (strlen(st)-MAX_SESSTRAIL_LEN) ;
3522               }
3523             } else {
3524               st = "\0" ;
3525             }
3526             strcpy(sst,st) ; strcat(sst,temp_dset->dblk->diskptr->prefix) ;
3527             sprintf( strlist[ii] , "%-*s" , ltop,sst ) ;
3528 
3529             strcat( strlist[ii] , " [" ) ;
3530             strcat( strlist[ii] , DSET_PREFIXSTR(temp_dset) ) ;
3531 
3532             if( DSET_NUM_TIMES(temp_dset) > 1 ){
3533                int ll = strlen(strlist[ii]) ;
3534                sprintf( strlist[ii]+ll , ":3D+t:%d]" ,
3535                         DSET_NUM_TIMES(temp_dset) ) ;
3536             } else if( ISBUCKET(temp_dset) ){
3537                int ll = strlen(strlist[ii]) ;
3538                sprintf( strlist[ii]+ll , ":%d]" ,
3539                         DSET_NVALS(temp_dset) ) ;
3540             } else {
3541                strcat( strlist[ii] , "]" ) ;
3542             }
3543 
3544             if( DSET_GRAPHABLE(temp_dset) )
3545                strcat( strlist[ii] , "*" ) ;
3546 
3547             if( DSET_COMPRESSED(temp_dset) )
3548                strcat( strlist[ii] , "z" ) ;
3549 
3550             /* 20 Dec 2001: mark if this is a global dataset */
3551 
3552             if( DSET_in_global_session(temp_dset) )
3553               strcat( strlist[ii] , "G" ) ;
3554 
3555 
3556          } else {
3557 #if 1
3558 THD_3dim_dataset *qset ; static int first=1 ;
3559 if( first ){
3560  for( vv=FIRST_VIEW_TYPE ; vv <= LAST_VIEW_TYPE ; vv++ ){
3561   qset = GET_SESSION_DSET(im3d->ss_now, ii, vv);
3562   if( qset != NULL ){
3563    INFO_message("BAD dataset: type=%d view_type=%d ibk=%d bkt=%d",
3564                 qset->type , qset->view_type , qset->dblk != NULL , qset->dblk->type ) ;
3565   }
3566  }
3567  first=0 ;
3568 }
3569 #endif
3570             MCW_strncpy( strlist[ii] , "??*BAD*??" , THD_MAX_PREFIX ) ;
3571          }
3572       }
3573 
3574       init_str = im3d->vinfo->anat_num ;
3575       label    = dset_choice[1] ;
3576 
3577    /*--- make a list of function names ---*/
3578 
3579    } else {
3580       int nn=0 , ndset=0 ; THD_3dim_dataset **dset_list=NULL , *dset=NULL;
3581 
3582       is_other = !( w == im3d->vwid->view->choose_func_pb ||
3583                     w == im3d->vwid->view->popchoose_func_pb ) ;
3584 
3585       num_str = im3d->ss_now->num_dsset ;
3586       if( num_str < 1 ) EXRETURN ;
3587 
3588       if( is_other ){
3589         AFNI_dataset_choose_stuff *cs = (AFNI_dataset_choose_stuff *)cb ;
3590         if( cs == NULL ) EXRETURN ;
3591         ndset = cs->ndset ; if( ndset < 1 ) EXRETURN ;
3592         dset_list = cs->dset ; if( dset_list == NULL ) EXRETURN ;
3593         cbfun = cs->cb ; if( cbfun == NULL ) EXRETURN ;
3594         wpar = w ;
3595         /*** sesstrail = 0 ; ***/
3596       } else {
3597         if( AFNI_yesenv("AFNI_DATASET_BROWSE") ) browse_select = 1 ;
3598         wpar = im3d->vwid->view->choose_func_pb ;
3599         ndset = num_str ;
3600       }
3601 
3602       ltop = 4 ;
3603       for( ii=0 ; ii < ndset ; ii++ ){
3604         if( is_other ){
3605           dset = dset_list[ii] ;
3606         } else {
3607           for( vv=FIRST_VIEW_TYPE ; vv <= LAST_VIEW_TYPE ; vv++ ){
3608             dset = GET_SESSION_DSET(im3d->ss_now, ii, vv); if( ISVALID_DSET(dset) ) break;
3609 /*            dset = im3d->ss_now->dsset_xform_table[ii][vv]; if( ISVALID_DSET(dset) ) break;*/
3610           }
3611         }
3612         if( ISVALID_DSET(dset) ){
3613           llen = strlen( dset->dblk->diskptr->prefix ) ;
3614           if( sesstrail ){
3615             st = THD_trailname(dset->dblk->diskptr->directory_name,1) ;
3616             if( st != NULL ){
3617               if( strlen(st) > MAX_SESSTRAIL_LEN )
3618                 st += (strlen(st)-MAX_SESSTRAIL_LEN) ;
3619               llen += strlen(st) ;
3620             }
3621           }
3622           if( llen > ltop ) ltop = llen ;
3623         }
3624       }
3625       ltop = MIN(ltop,STRLIST_SIZE-24) ;  /* 06 Aug 2002 */
3626 
3627       for( ii=0 ; ii < ndset ; ii++ ){
3628 
3629          if( is_other ){
3630            dset = dset_list[ii] ; if( !ISVALID_DSET(dset) ) continue ;
3631          } else {
3632            for( vv=FIRST_VIEW_TYPE ; vv <= LAST_VIEW_TYPE ; vv++ ){
3633             dset = GET_SESSION_DSET(im3d->ss_now, ii, vv); if( ISVALID_DSET(dset) ) break;
3634 /*             dset = im3d->ss_now->dsset_xform_table[ii][vv]; if( ISVALID_DSET(dset) ) break;*/
3635            }
3636          }
3637 
3638          if( ISVALID_DSET(dset) ){
3639            if( sesstrail ){
3640              st = THD_trailname(dset->dblk->diskptr->directory_name,1) ;
3641              if( st != NULL ){
3642                if( strlen(st) > MAX_SESSTRAIL_LEN )
3643                  st += (strlen(st)-MAX_SESSTRAIL_LEN) ;
3644              }
3645            } else {
3646              st = "\0" ;
3647            }
3648            strcpy(sst,st) ; strcat(sst,dset->dblk->diskptr->prefix) ;
3649            sprintf( strlist[nn] , "%-*s" , ltop,sst ) ;
3650 
3651            strcat( strlist[nn] , " [" ) ;
3652            strcat( strlist[nn] , DSET_PREFIXSTR(dset) ) ;
3653 
3654            if( DSET_NUM_TIMES(dset) > 1 ){
3655              int ll = strlen(strlist[nn]) ;
3656              sprintf( strlist[nn]+ll , ":3D+t:%d]" , DSET_NUM_TIMES(dset) ) ;
3657            } else if( ISBUCKET(dset) ){
3658              int ll = strlen(strlist[nn]) ;
3659              sprintf( strlist[nn]+ll , ":%d]" , DSET_NVALS(dset) ) ;
3660            } else {
3661              strcat( strlist[nn] , "]" ) ;
3662            }
3663 
3664            if( DSET_COMPRESSED(dset) ) strcat( strlist[nn] , "z" ) ;
3665 
3666            /* 20 Dec 2001: mark if this is a global dataset */
3667 
3668            if( DSET_in_global_session(dset) ) strcat( strlist[nn] , "G" ) ;
3669 
3670          } else { /* should never happen */
3671 #if 1
3672 THD_3dim_dataset *qset ; static int first=1 ;
3673 if( first ){
3674  for( vv=FIRST_VIEW_TYPE ; vv <= LAST_VIEW_TYPE ; vv++ ){
3675   qset = GET_SESSION_DSET(im3d->ss_now,ii,vv) ;
3676   if( qset != NULL ){
3677    INFO_message("BAD dataset: type=%d view_type=%d ibk=%d bkt=%d",
3678                 qset->type , qset->view_type , qset->dblk != NULL , qset->dblk->type ) ;
3679   }
3680  }
3681  first=0 ;
3682 }
3683 #endif
3684            MCW_strncpy( strlist[nn] , "**?BAD?**" , THD_MAX_PREFIX ) ;
3685          }
3686 
3687          nn++ ;
3688       }
3689 
3690       if( nn < 1 ) EXRETURN ;
3691 
3692       if( is_other ){
3693         init_str = 0 ;
3694         label    = dset_choice[3] ;
3695       } else {
3696         init_str = im3d->vinfo->func_num ;
3697         label    = dset_choice[2] ;
3698       }
3699       num_str = nn ;
3700 
3701    }
3702 
3703    /*--- call the chooser ---*/
3704 
3705    MCW_set_browse_select( browse_select ) ;
3706 
3707    MCW_choose_strlist( wpar , label , num_str , init_str , strlist ,
3708                        cbfun , (XtPointer)im3d ) ;
3709 
3710    RESET_AFNI_QUIT(im3d) ;
3711    EXRETURN ;
3712 }
3713 
3714 /*-----------------------------------------------------------------------*/
3715 
AFNI_finalize_dataset_CB(Widget wcall,XtPointer cd,MCW_choose_cbs * cbs)3716 void AFNI_finalize_dataset_CB( Widget wcall ,
3717                                XtPointer cd , MCW_choose_cbs *cbs )
3718 {
3719    Three_D_View *im3d = (Three_D_View *)cd ;
3720    int old_sess , old_anat , old_func , old_view ;
3721    int new_sess=-1 , new_anat=-1 , new_func=-1 , new_view=-1 ;
3722    int ii , vv , ff ;
3723    THD_session *ss_new ;
3724    THD_3dim_dataset *temp_dset;
3725 
3726 ENTRY("AFNI_finalize_dataset_CB") ;
3727 
3728    if( ! IM3D_OPEN(im3d) ) EXRETURN ;
3729 
3730    old_sess = im3d->vinfo->sess_num ;     /* record current status */
3731    old_anat = im3d->vinfo->anat_num ;
3732    old_func = im3d->vinfo->func_num ;
3733    old_view = im3d->vinfo->view_type ;
3734 
3735    im3d->vinfo->stats_anat_ok =
3736     im3d->vinfo->stats_func_ok =
3737      im3d->vinfo->arang_func_ok =
3738       im3d->vinfo->stats_thresh_ok = 0 ; /* 24 May 2019 */
3739 
3740 #if 0
3741    STATUS_IM3D_TMASK(im3d) ;
3742    STATUS("clear tmask") ;
3743 #endif
3744    IM3D_CLEAR_TMASK(im3d) ;                                /* Mar 2013 */
3745    IM3D_CLEAR_THRSTAT(im3d) ;                           /* 12 Jun 2014 */
3746    AFNI_setup_thrstat(im3d,0) ;                         /* 27 Jun 2019 */
3747 
3748    /*--- switch sessions ---*/
3749 
3750    if( wcall == im3d->vwid->view->choose_sess_pb ){
3751 
3752       DISABLE_INSTACORR(im3d) ; DESTROY_ICOR_setup(im3d->iset) ; /* 08 May 2009 */
3753 
3754       new_sess = cbs->ival ;
3755       if( new_sess < 0 || new_sess >= GLOBAL_library.sslist->num_sess ){
3756          BEEPIT ;
3757          WARNING_message("bad session index when finalizing choice") ;
3758          EXRETURN ;  /* bad! */
3759       }
3760 
3761       ss_new = GLOBAL_library.sslist->ssar[new_sess] ;
3762 
3763       /* find an anat in new session to match current anat */
3764 
3765       temp_dset = GET_SESSION_DSET(ss_new, old_anat, old_view);
3766       if( ISVALID_3DIM_DATASET(temp_dset) ){  /* are OK */
3767         new_anat = old_anat ;
3768       } else {
3769         for( ii=0 ; ii < ss_new->num_dsset ; ii++ ) {
3770           temp_dset = GET_SESSION_DSET(ss_new, ii, old_view);
3771           if( ISVALID_3DIM_DATASET(temp_dset) ){ new_anat = ii ; break ; }
3772         }
3773       }
3774       if( new_anat < 0 ) new_anat = 0 ;  /* use 1st if no match */
3775 
3776       /* find a view to fit this chosen anat */
3777 
3778       temp_dset = GET_SESSION_DSET(ss_new, new_anat, old_view);
3779       if( ISVALID_3DIM_DATASET(temp_dset )) { /* are OK */
3780          new_view = old_view ;
3781       } else {
3782          for( vv=old_view-1 ; vv >= FIRST_VIEW_TYPE ; vv-- ) { /* look below */
3783             temp_dset = GET_SESSION_DSET(ss_new, new_anat, vv);
3784             if( ISVALID_3DIM_DATASET(temp_dset) ) break ;
3785          }
3786          if( vv >= FIRST_VIEW_TYPE ){  /* found it below */
3787             new_view = vv ;
3788          } else {                      /* look above */
3789             for( vv=old_view+1 ; vv <= LAST_VIEW_TYPE ; vv++ ) {
3790                temp_dset = GET_SESSION_DSET(ss_new, new_anat, vv);
3791                if( ISVALID_3DIM_DATASET(temp_dset) ) break ;
3792             }
3793 
3794             if( vv <= LAST_VIEW_TYPE ){  /* found it above */
3795                new_view = vv ;
3796             } else {
3797                BEEPIT ;
3798                WARNING_message("bad view code when finalizing choice") ;
3799                EXRETURN ;  /* bad news */
3800             }
3801          }
3802       }
3803 
3804       /* find a func in new session that fits the new view */
3805 
3806 #define FINDAFUNC
3807 #ifdef  FINDAFUNC
3808       temp_dset = GET_SESSION_DSET(ss_new, old_func, new_view);
3809       if( ISVALID_3DIM_DATASET(temp_dset) ){  /* are OK */
3810          new_func = old_func ;
3811       } else {
3812          for( ff=0 ; ff < ss_new->num_dsset ; ff++ ) { /* search */
3813             temp_dset = GET_SESSION_DSET(ss_new, ff, new_view);
3814             if( ISVALID_3DIM_DATASET(temp_dset) ) break ;
3815 /*            if( ISVALID_3DIM_DATASET(ss_new->dsset_xform_table[ff][new_view]) ) break ;*/
3816          }
3817 
3818          if( ff < ss_new->num_dsset ) new_func = ff ;  /* found one */
3819       }
3820       if( new_func < 0 ) new_func = 0 ;  /* no match */
3821 #else
3822       new_func = old_func ;
3823 #endif
3824 
3825    /*--- switch anatomy ---*/
3826 
3827    } else if( wcall == im3d->vwid->view->choose_anat_pb ){
3828 
3829       new_sess = old_sess ;
3830       ss_new   = GLOBAL_library.sslist->ssar[new_sess] ;
3831 
3832       new_anat = cbs->ival ;
3833       if( new_anat < 0 || new_anat >= ss_new->num_dsset ){
3834          BEEPIT ;
3835          WARNING_message("bad anat index when finalizing choice") ;
3836          EXRETURN ;  /* bad! */
3837       }
3838 
3839       /* find a view to fit this chosen anat */
3840       temp_dset = GET_SESSION_DSET(ss_new, new_anat, old_view);
3841 
3842       if( ISVALID_3DIM_DATASET(temp_dset) ){ /* are OK */
3843          new_view = old_view ;
3844       } else {
3845          for( vv=old_view-1 ; vv >= FIRST_VIEW_TYPE ; vv-- ) { /* look below */
3846             temp_dset = GET_SESSION_DSET(ss_new, new_anat, vv);
3847             if( ISVALID_3DIM_DATASET(temp_dset) ) break ;
3848          }
3849 
3850          if( vv >= FIRST_VIEW_TYPE ){  /* found it below */
3851             new_view = vv ;
3852          } else {                      /* look above */
3853             for( vv=old_view+1 ; vv <= LAST_VIEW_TYPE ; vv++ ){
3854                temp_dset = GET_SESSION_DSET(ss_new, new_anat, vv);
3855                if( ISVALID_3DIM_DATASET(temp_dset) ) break ;
3856             }
3857 
3858             if( vv <= LAST_VIEW_TYPE ){  /* found it above */
3859                new_view = vv ;
3860             } else {
3861                BEEPIT ;
3862                WARNING_message("bad func index when finalizing choice") ;
3863                EXRETURN ;  /* bad news */
3864             }
3865          }
3866       }
3867 
3868       /* find a func to match this view */
3869 
3870 #ifdef FINDAFUNC
3871      temp_dset = GET_SESSION_DSET(ss_new, old_func, new_view);
3872      if( ISVALID_3DIM_DATASET(temp_dset) ) {
3873          new_func = old_func ;
3874       } else {
3875          for( ff=0 ; ff < ss_new->num_dsset ; ff++ ) { /* search */
3876             temp_dset = GET_SESSION_DSET(ss_new, ff, new_view);
3877             if( ISVALID_3DIM_DATASET(temp_dset) ) break ;
3878 /*            if( ISVALID_3DIM_DATASET(ss_new->dsset_xform_table[ff][new_view]) ) break ;*/
3879          }
3880 
3881          if( ff < ss_new->num_dsset ) new_func = ff ;  /* found one */
3882       }
3883       if( new_func < 0 ) new_func = 0 ;  /* no match */
3884 #else
3885       new_func = old_func ;
3886 #endif
3887 
3888    /*--- switch function ---*/
3889 
3890    } else if( wcall == im3d->vwid->view->choose_func_pb ){
3891 
3892       new_sess = old_sess ;
3893       ss_new   = GLOBAL_library.sslist->ssar[new_sess] ;
3894 
3895       new_func = cbs->ival ;
3896       if( new_func < 0 || new_func >= ss_new->num_dsset ){  /* should not happen */
3897          BEEPIT ;
3898          WARNING_message("bad func index when finalizing choice!") ;
3899          EXRETURN ;  /* bad! */
3900       }
3901 
3902       /* find a view to fit this chosen func */
3903 
3904       temp_dset = GET_SESSION_DSET(ss_new, new_func, old_view);
3905       if( ISVALID_3DIM_DATASET(temp_dset) ) {
3906          new_view = old_view ;
3907       } else {
3908          for( vv=old_view-1 ; vv >= FIRST_VIEW_TYPE ; vv-- ) { /* look below */
3909             temp_dset = GET_SESSION_DSET(ss_new, new_func, vv);
3910             if( ISVALID_3DIM_DATASET(temp_dset) ) break ;
3911          }
3912 
3913          if( vv >= FIRST_VIEW_TYPE ){  /* found it below */
3914             new_view = vv ;
3915          } else {                      /* look above */
3916             for( vv=old_view+1 ; vv <= LAST_VIEW_TYPE ; vv++ ) {
3917                temp_dset = GET_SESSION_DSET(ss_new, new_func, vv);
3918                if( ISVALID_3DIM_DATASET(temp_dset) ) break ;
3919             }
3920 
3921             if( vv <= LAST_VIEW_TYPE ){  /* found it above */
3922                new_view = vv ;
3923             } else {                     /* should not happen */
3924                BEEPIT ;
3925                WARNING_message("bad view index when finalizing choice!") ;
3926                EXRETURN ;  /* bad news */
3927             }
3928          }
3929       }
3930 
3931       /* find an anat to go with the new view (this is NOT optional) */
3932 
3933       temp_dset = GET_SESSION_DSET(ss_new, old_anat, new_view);
3934       if( ISVALID_3DIM_DATASET(temp_dset) ) {
3935          new_anat = old_anat ;
3936       } else {
3937          for( ff=0 ; ff < ss_new->num_dsset ; ff++ ) { /* search */
3938             temp_dset = GET_SESSION_DSET(ss_new, ff, new_view);
3939             if( ISVALID_3DIM_DATASET(temp_dset) ) break ;
3940          }
3941 /*          if( ISVALID_3DIM_DATASET(ss_new->dsset_xform_table[ff][new_view]) ) break ; */
3942 
3943          if( ff < ss_new->num_dsset ) new_anat = ff ;  /* found one */
3944       }
3945       if( new_anat < 0 ){  /* should not happen */
3946          BEEPIT ;
3947          WARNING_message("bad anat index when finalizing choice!") ;
3948          EXRETURN ;  /* bad! */
3949       }
3950 
3951       /* 03 Aug 2007: turn 'See Overlay' on? */
3952 
3953       if( !im3d->vinfo->func_visible && im3d->vinfo->func_visible_count == 0 ){
3954         AFNI_SEE_FUNC_ON(im3d) ; OPEN_PANEL(im3d,func) ;
3955         im3d->vinfo->func_init_subbricks = 1 ;  /* 12 Jan 2017 */
3956         if( im3d->vwid->func->do_setup ){
3957           int ii = (int)AFNI_numenv("AFNI_THRESH_INIT_EXPON") ;
3958           if( ii > 0 && ii < THR_top_expon ) AFNI_set_thresh_itop(im3d,ii) ;
3959           im3d->vwid->func->do_setup = 0 ;
3960         }
3961       }
3962 
3963    /*--- switch to Hell? ---*/
3964 
3965    } else {
3966       BEEPIT ;
3967       WARNING_message("bad switch?!") ;
3968       EXRETURN ;  /* bad! */
3969    }
3970 
3971    /*--- make sure all values are set OK-ly ---*/
3972 
3973    if( new_view < 0 || new_sess < 0 || new_anat < 0 || new_func < 0 ){
3974      ERROR_message("Something bad happened when trying to 'Switch'\a") ;
3975      EXRETURN ;  /* bad! */
3976    }
3977 
3978    /*- beep & flash viewing control box if view type changes -*/
3979 
3980    if( old_view != new_view ){
3981      static int nwarn=0 ;
3982      MCW_set_bbox( im3d->vwid->view->view_bbox , 1 << new_view ) ;
3983      UNCLUSTERIZE(im3d) ;  /* 14 Feb 2008 */
3984 
3985      /* this stuff is for Adam Thomas -- 18 Oct 2006 */
3986 
3987      if( nwarn < 3 )
3988        WARNING_message("Forced switch from '%s' to '%s' [#%d]",
3989                        VIEW_typestr[old_view] , VIEW_typestr[new_view] , nwarn+1 ) ;
3990 
3991      if( AFNI_yesenv("AFNI_FLASH_VIEWSWITCH") ){
3992 
3993        if( nwarn==0 && wcall != NULL ){
3994          char str[256] ;
3995          sprintf(str," \nForced switch from\n  '%s'\nto\n  '%s'\n ",
3996                      VIEW_typestr[old_view] , VIEW_typestr[new_view] ) ;
3997          (void)MCW_popup_message( wcall, str, MCW_USER_KILL | MCW_TIMER_KILL ) ;
3998        }
3999 
4000        if( wcall != NULL ){
4001          for( ii=0 ; ii < 3 ; ii++ ){
4002            MCW_invert_widget(im3d->vwid->view->view_bbox->wframe ); RWC_sleep(16);
4003            MCW_invert_widget(im3d->vwid->view->view_bbox->wrowcol); RWC_sleep(16);
4004            MCW_invert_widget(wcall) ;
4005            MCW_invert_widget(im3d->vwid->view->view_bbox->wframe ); RWC_sleep(16);
4006            MCW_invert_widget(im3d->vwid->view->view_bbox->wrowcol); RWC_sleep(16);
4007            MCW_invert_widget(wcall) ;
4008          }
4009        }
4010      }
4011 
4012      nwarn++ ;  /* 16 Sep 2009 */
4013    }
4014 
4015    /*----- actually do the switch -----*/
4016 
4017    if( im3d->vinfo->sess_num != new_sess )  /* disable FIMage in a new session */
4018       im3d->fimdata->fimdset = NULL ;
4019 
4020    im3d->vinfo->view_type = new_view ;
4021    im3d->vinfo->sess_num  = new_sess ;
4022    im3d->vinfo->anat_num  = new_anat ;
4023    im3d->vinfo->func_num  = new_func ;
4024 
4025    if( new_func != old_func && im3d->vinfo->fim_autorange )  /* 20 Jun 2019 */
4026      reset_func_range_ncall[ AFNI_controller_index(im3d) ] = 0 ;
4027 
4028    SHOW_AFNI_PAUSE ;
4029    AFNI_initialize_view( im3d->anat_now , im3d ) ;
4030    SHOW_AFNI_READY ;
4031    FIX_SCALE_SIZE(im3d) ;
4032 
4033    if( AFNI_yesenv("AFNI_FLASH_VIEWSWITCH") && old_view != new_view ){ /* ending flash */
4034      BEEPIT ;
4035      for( ii=0 ; ii < 3 ; ii++ ){
4036        MCW_invert_widget( im3d->vwid->view->view_bbox->wframe ); RWC_sleep(16);
4037        MCW_invert_widget( im3d->vwid->view->view_bbox->wrowcol); RWC_sleep(16);
4038        MCW_invert_widget(wcall) ;
4039        MCW_invert_widget( im3d->vwid->view->view_bbox->wframe ); RWC_sleep(16);
4040        MCW_invert_widget( im3d->vwid->view->view_bbox->wrowcol); RWC_sleep(16);
4041        MCW_invert_widget(wcall) ;
4042      }
4043    }
4044 
4045    if( wcall == im3d->vwid->view->choose_func_pb &&
4046        AFNI_yesenv("AFNI_THRESH_AUTO")              ){  /* 05 Mar 2007 */
4047 
4048      float new_thresh = AFNI_get_autothresh(im3d) ;
4049      if( new_thresh > 0.0f ) AFNI_set_threshold(im3d,new_thresh) ;
4050    }
4051 
4052    if( wcall == im3d->vwid->view->choose_func_pb ){  /* ZSS 25 Feb 2010 */
4053       AFNI_set_dset_pbar((XtPointer)im3d);
4054    }
4055 
4056    /* check obliquity of overlay and underlay */
4057    /* pop up warning if necessary */
4058 
4059    if(wcall == im3d->vwid->view->choose_func_pb) {
4060      AFNI_check_obliquity(wcall,
4061             GET_SESSION_DSET(ss_new, new_func, 0),
4062             GET_SESSION_DSET(ss_new, new_anat, 0) );
4063    } else {
4064      AFNI_check_obliquity(wcall,
4065             GET_SESSION_DSET(ss_new, new_anat, 0),
4066             GET_SESSION_DSET(ss_new, new_func, 0) );
4067    }
4068    CLU_setup_alpha_tables(im3d) ;
4069 
4070    AFNI_fix_scale_size_direct(im3d) ;  /* 03 Jun 2019 */
4071    EXRETURN ;
4072 }
4073 
4074 /*-----------------------------------------------------------*/
4075 /* check dataset for obliquity and pop-up warning if oblique */
4076 
AFNI_check_obliquity(Widget w,THD_3dim_dataset * dset,THD_3dim_dataset * rset)4077 void AFNI_check_obliquity(Widget w, THD_3dim_dataset *dset,
4078                           THD_3dim_dataset *rset)
4079 {
4080    double angle;
4081    char str[1024], sidcombo[256], *sid1=NULL, *sid2=NULL;
4082    static char *warncombos=NULL;
4083    static int num_warn = 0;
4084 
4085    ENTRY("AFNI_check_obliquity");
4086    if( !ISVALID_DSET(dset) ) EXRETURN ;
4087 
4088    if(AFNI_yesenv("AFNI_NO_OBLIQUE_WARNING")) EXRETURN;
4089 
4090    if(AFNI_yesenv("AFNI_ONE_OBLIQUE_WARNING") && num_warn) EXRETURN;
4091 
4092    angle = dset_obliquity_angle_diff(dset, rset, OBLIQ_ANGLE_THRESH);
4093    if(angle == 0.0) EXRETURN ;
4094 
4095    /* A simple way to keep AFNI form complaining about obliquity all the time */
4096    sid1= DSET_IDCODE_STR(dset);
4097    if (rset) sid2 = DSET_IDCODE_STR(rset);
4098    else sid2 = "NA";
4099    if (!sid1) sid1="NO_ID1";
4100    if (!sid2) sid2="NO_ID2";
4101 
4102    if (strcmp(sid1,sid2)<0) {
4103       sprintf(sidcombo,"-%s_WITH_%s-", sid1, sid2);
4104    } else {
4105       sprintf(sidcombo,"-%s_WITH_%s-", sid2, sid1);
4106    }
4107 
4108    if (!warncombos) {
4109       warncombos = (char *)malloc(sizeof(char)*(strlen(sidcombo)+1));
4110       strcpy(warncombos,sidcombo);
4111    } else {
4112       if (strstr(warncombos,sidcombo)) EXRETURN;
4113       else {
4114          warncombos = (char *)realloc(warncombos,
4115                            sizeof(char)*(strlen(sidcombo)+strlen(warncombos)+1));
4116          warncombos = strcat(warncombos, sidcombo);
4117       }
4118    }
4119 
4120    if (AFNI_yesenv("AFNI_ONE_OBLIQUE_WARNING")) {
4121       snprintf( str, 1022*sizeof(char),
4122    " The underlay/overlay pair of datasets (%s/%s) have oblique angle \n"
4123    " difference of %f degrees. This may cause them to appear out of alignment \n"
4124    " in the viewer.\n"
4125    "\n"
4126    "  If you are performing spatial transformations on an oblique dset, \n"
4127    "  or viewing/combining it with volumes of differing obliquity,\n"
4128    "  you should consider running: \n"
4129    "     3dWarp -deoblique \n"
4130    "  on this and other oblique datasets in the same session.\n"
4131    "\n"
4132    " ** Other oblique warnings will be muted because AFNI_ONE_OBLIQUE_WARNING\n"     "    is set to YES. Consider setting it back to NO, obliquity warnings\n"
4133    "    are much less overwhelming now.\n",
4134          DSET_PREFIX(dset), rset ? DSET_PREFIX(rset):"NA",
4135          angle );
4136    } else {
4137       snprintf( str, 1022*sizeof(char),
4138    " The underlay/overlay pair of datasets (%s/%s) have oblique angle \n"
4139    " difference of %f degrees. This may cause them to appear out of alignment \n"
4140    " in the viewer.\n"
4141    "\n"
4142    "  If you are performing spatial transformations on an oblique dset, \n"
4143    "  or viewing/combining it with volumes of differing obliquity,\n"
4144    "  you should consider running: \n"
4145    "     3dWarp -deoblique \n"
4146    "  on this and other oblique datasets in the same session.\n"
4147    "\n"
4148    " ** Warnings for the same data pair will be muted.\n",
4149          DSET_PREFIX(dset), rset ? DSET_PREFIX(rset):"NA",
4150          angle);
4151    }
4152    (void) MCW_popup_message( w , str, MCW_USER_KILL | MCW_TIMER_KILL ) ;
4153 
4154    ++num_warn;
4155    EXRETURN ;
4156 }
4157 
4158 /*----------------------------------------------------------------------
4159    Routines to close and open a file selection
4160    dialog associated with the im3d viewer.
4161 ------------------------------------------------------------------------*/
4162 
AFNI_close_file_dialog_CB(Widget w,XtPointer cd,XtPointer cb)4163 void AFNI_close_file_dialog_CB( Widget w, XtPointer cd, XtPointer cb )
4164 {
4165    Three_D_View *im3d = (Three_D_View *) cd ;
4166 
4167 ENTRY("AFNI_close_file_dialog") ;
4168 
4169    if( IM3D_OPEN(im3d) && im3d->vwid->file_dialog != NULL )
4170      RWC_XtPopdown( im3d->vwid->file_dialog ) ;
4171 
4172    EXRETURN ;
4173 }
4174 
4175 /*----------------------------------------------------------------------
4176    After this is called, the calling routine must set the callbacks,
4177    window title, etc., appropriately.
4178 ------------------------------------------------------------------------*/
4179 
AFNI_make_file_dialog(Three_D_View * im3d)4180 void AFNI_make_file_dialog( Three_D_View *im3d )
4181 {
4182    Widget www ;
4183 
4184 ENTRY("AFNI_make_file_dialog") ;
4185 
4186    /*** make a new dialog? ***/
4187 
4188    if( im3d->vwid->file_dialog == NULL ){
4189       XmString oklabel , cancellabel ;
4190 
4191 STATUS("creating new dialog") ;
4192 
4193       im3d->vwid->file_dialog =
4194          XtVaCreatePopupShell(
4195            "menu" , xmDialogShellWidgetClass , im3d->vwid->top_shell ,
4196               XmNtitle , "GPL AFNI" ,
4197               XmNdeleteResponse , XmDO_NOTHING ,
4198               XmNinitialResourcesPersistent , False ,
4199               XmNkeyboardFocusPolicy , XmEXPLICIT ,
4200            NULL ) ;
4201 
4202       XmAddWMProtocolCallback(           /* make "Close" window menu work */
4203            im3d->vwid->file_dialog ,
4204            XmInternAtom( im3d->dc->display , "WM_DELETE_WINDOW" , False ) ,
4205            AFNI_close_file_dialog_CB , (XtPointer) im3d ) ;
4206 
4207       /** change button labels to conform to other AFNI dialogs **/
4208 
4209       oklabel     = XmStringCreateLtoR( "Set"  , XmFONTLIST_DEFAULT_TAG ) ;
4210       cancellabel = XmStringCreateLtoR( "Quit" , XmFONTLIST_DEFAULT_TAG ) ;
4211 
4212       im3d->vwid->file_sbox =
4213          XtVaCreateManagedWidget(
4214            "menu" , xmFileSelectionBoxWidgetClass , im3d->vwid->file_dialog ,
4215               XmNfileTypeMask      , XmFILE_ANY_TYPE ,
4216               XmNcancelLabelString , cancellabel ,
4217               XmNokLabelString     , oklabel ,
4218               XmNtraversalOn       , True ,
4219               XmNinitialResourcesPersistent , False ,
4220            NULL ) ;
4221 
4222       XmStringFree(oklabel) ; XmStringFree(cancellabel) ;
4223 
4224       im3d->vwid->file_cb = NULL ;
4225       im3d->vwid->file_cd = NULL ;
4226 
4227    } else if( im3d->vwid->file_cb != NULL ){
4228       Widget www ;
4229 
4230 STATUS("re-initializing old dialog") ;
4231 
4232       /*** re-initialize an old dialog to have no callbacks ***/
4233 
4234       XtRemoveCallback( im3d->vwid->file_sbox , XmNokCallback ,
4235                         im3d->vwid->file_cb , im3d->vwid->file_cd ) ;
4236 
4237       XtRemoveCallback( im3d->vwid->file_sbox , XmNcancelCallback ,
4238                         im3d->vwid->file_cb , im3d->vwid->file_cd ) ;
4239 
4240       XtRemoveCallback( im3d->vwid->file_sbox , XmNhelpCallback ,
4241                         im3d->vwid->file_cb , im3d->vwid->file_cd ) ;
4242 
4243       XtVaSetValues( im3d->vwid->file_sbox , XmNpattern,NULL , NULL ) ;
4244 
4245       im3d->vwid->file_cb = NULL ;
4246       im3d->vwid->file_cd = NULL ;
4247 
4248       XtVaSetValues(im3d->vwid->file_sbox,XmNfileTypeMask,XmFILE_ANY_TYPE,NULL);
4249    }
4250 
4251 #if 0  /* doesn't work, because the button is a gadget, not a widget */
4252    www = XtNameToWidget( im3d->vwid->file_sbox , "OK" ) ;
4253    if( www != NULL )
4254      MCW_set_widget_bg( www , MCW_hotcolor(www) , 0 ) ;
4255 #endif
4256 
4257    EXRETURN ;
4258 }
4259 
4260 /*----------------------------------------------------------------
4261   Start getting ready to read a new session in.  This
4262   is the CB for the "Read Sess" button.  We'll get a filename
4263   from the user, and process it in another routine.
4264 ------------------------------------------------------------------*/
4265 
AFNI_read_sess_CB(Widget w,XtPointer cd,XtPointer cb)4266 void AFNI_read_sess_CB( Widget w, XtPointer cd, XtPointer cb )
4267 {
4268    Three_D_View *im3d = (Three_D_View *)cd ;
4269    Widget www ;
4270 
4271 ENTRY("AFNI_read_sess_CB") ;
4272 
4273    if( !IM3D_OPEN(im3d) ) EXRETURN ;
4274 
4275    if( GLOBAL_library.sslist->num_sess >= THD_MAX_NUM_SESSION ){
4276       (void) MCW_popup_message( w ,
4277                                   "********************************\n"
4278                                   "** Maximum number of sessions **\n"
4279                                   "** would be exceeded.  Sorry! **\n"
4280                                   "********************************"
4281                                 , MCW_USER_KILL | MCW_TIMER_KILL ) ;
4282       EXRETURN ;
4283    }
4284 
4285    AFNI_make_file_dialog( im3d ) ;
4286 
4287    XtAddCallback( im3d->vwid->file_sbox , XmNokCallback ,
4288                   AFNI_finalize_read_sess_CB , cd ) ;
4289 
4290    XtAddCallback( im3d->vwid->file_sbox , XmNcancelCallback ,
4291                   AFNI_finalize_read_sess_CB , cd ) ;
4292 
4293    XtAddCallback( im3d->vwid->file_sbox , XmNhelpCallback ,
4294                   AFNI_finalize_read_sess_CB , cd ) ;
4295 
4296    XtVaSetValues(im3d->vwid->file_sbox,XmNfileTypeMask,XmFILE_DIRECTORY,NULL);
4297    MCW_set_widget_label( XtNameToWidget(im3d->vwid->file_sbox,"Items") ,
4298                          "Sessions" ) ;
4299 
4300    im3d->vwid->file_cb = AFNI_finalize_read_sess_CB ;
4301    im3d->vwid->file_cd = cd ;
4302 
4303    XtVaSetValues( im3d->vwid->file_dialog,
4304                      XmNtitle, "AFNI: Read Session",
4305                   NULL ) ;
4306 
4307    XtPopup( im3d->vwid->file_dialog , XtGrabNone ) ; RWC_sleep(1);
4308    RWC_visibilize_widget( im3d->vwid->file_dialog ) ; /* 09 Nov 1999 */
4309    NORMAL_cursorize( im3d->vwid->file_dialog ) ;
4310 
4311    EXRETURN ;
4312 }
4313 
4314 /*---------------------------------------------------------------------
4315    Got a button press from the file selection dialog,
4316    so process it (maybe read in a new session!)
4317 -----------------------------------------------------------------------*/
4318 
AFNI_finalize_read_sess_CB(Widget w,XtPointer cd,XtPointer cb)4319 void AFNI_finalize_read_sess_CB( Widget w, XtPointer cd, XtPointer cb )
4320 {
4321    Three_D_View *im3d = (Three_D_View *)cd ;
4322    XmFileSelectionBoxCallbackStruct *cbs = (XmFileSelectionBoxCallbackStruct *)cb ;
4323 
4324 ENTRY("AFNI_finalize_read_sess_CB") ;
4325 
4326    if( !IM3D_OPEN(im3d) || cbs == NULL ) EXRETURN ;  /* 04 Feb 2008 */
4327 
4328    switch( cbs->reason ){
4329 
4330       /** close the file selection dialog **/
4331 
4332       case XmCR_CANCEL:
4333          RWC_XtPopdown( im3d->vwid->file_dialog ) ;
4334       break ;
4335 
4336       /** try to read a new session **/
4337 
4338       case XmCR_OK:{
4339          char *text = NULL ;
4340          XmStringGetLtoR( cbs->value , XmFONTLIST_DEFAULT_TAG , &text ) ;
4341          if( text != NULL ){
4342 
4343             THD_session *new_ss = NULL ;
4344 
4345             /** if the user selected a file, strip it back to a directory **/
4346 
4347 if(PRINT_TRACING)
4348 { char str[256] ; sprintf(str,"input text = %s",text) ; STATUS(str) ; }
4349 
4350             if( THD_is_file(text) ){
4351                int ii = strlen(text)-1 ;
4352                for( ; ii > 0 && text[ii] != '/' ; ii-- ) text[ii] = '\0' ;
4353 
4354 if(PRINT_TRACING)
4355 { char str[256] ; sprintf(str,"defiled text = %s",text) ; STATUS(str) ; }
4356             }
4357 
4358             /** if the name given is a directory, try to read it **/
4359 
4360             if( THD_is_directory(text) ){
4361                int ii , eq=0 ;
4362                THD_session *old_ss ;
4363 
4364                /** 1st check if this is the same as some other session **/
4365 
4366 STATUS("comparing to other sessions") ;
4367                for( ii=0 ; ii < GLOBAL_library.sslist->num_sess ; ii++ ){
4368                   old_ss = GLOBAL_library.sslist->ssar[ii] ;
4369                   eq     = THD_equiv_files( old_ss->sessname , text ) ;
4370                   if( eq == 1 ) break ;
4371                }
4372 
4373                if( eq == 1 ){
4374 STATUS("illegal duplicate session") ;
4375                   BEEPIT ;
4376                   (void) MCW_popup_message( w ,
4377                                              "*******************************\n"
4378                                              "** Illegal duplicate session **\n"
4379                                              "*******************************"
4380                                             , MCW_USER_KILL | MCW_TIMER_KILL ) ;
4381                   break ;
4382                } else {
4383 STATUS("reading new session") ;
4384                   new_ss = THD_init_session( text ) ;  /*** Read session! ***/
4385                }
4386             } else { /** wasn't a directory!? **/
4387 
4388 STATUS("wasn't a directory") ;
4389                BEEPIT ;
4390                (void) MCW_popup_message( w ,
4391                                           "***********************************\n"
4392                                           "** Cannot find session directory **\n"
4393                                           "***********************************"
4394                                          , MCW_USER_KILL | MCW_TIMER_KILL ) ;
4395                break ;
4396             }
4397 
4398             /** OK, was a directory and we tried to read it **/
4399 
4400             if( new_ss == NULL || new_ss->num_dsset == 0 ){ /** failed to read anything **/
4401 
4402 STATUS("failed to read new session") ;
4403                BEEPIT ;
4404                (void) MCW_popup_message( w ,
4405                                            "******************************\n"
4406                                            "** Cannot read any datasets **\n"
4407                                            "******************************"
4408                                          , MCW_USER_KILL | MCW_TIMER_KILL ) ;
4409 
4410             } else if( GLOBAL_library.sslist->num_sess >= THD_MAX_NUM_SESSION ){
4411 
4412 STATUS("too many sessions") ;
4413                BEEPIT ;
4414                (void) MCW_popup_message( w ,
4415                                            "****************************\n"
4416                                            "** Max number of sessions **\n"
4417                                            "** exceeded -- Sorry!     **\n"
4418                                            "****************************"
4419                                          , MCW_USER_KILL | MCW_TIMER_KILL ) ;
4420 
4421             } else {  /** GOOD!  Actually process a new session.   **/
4422                       /** (The following is from AFNI_read_inputs) **/
4423                int qd , vv ;
4424                char str[356] ;  /* for messages */
4425                THD_3dim_dataset *dset ;
4426 
4427 STATUS("processing new session") ;
4428 
4429                new_ss->parent = NULL ;
4430 
4431                for( qd=0 ; qd < new_ss->num_dsset ; qd++ ){      /* parentize */
4432                  for( vv=0 ; vv <= LAST_VIEW_TYPE ; vv++ ){
4433                    dset = GET_SESSION_DSET(new_ss,qd,vv) ;
4434 /*                   dset = new_ss->dsset_xform_table[qd][vv] ;*/
4435                    if( dset != NULL ){
4436                      PARENTIZE( dset , NULL ) ;
4437                      AFNI_inconstancy_check(NULL,dset) ; /* 06 Sep 2006 */
4438                    }
4439                } }
4440                AFNI_inconstancy_check(im3d,NULL); /* 06 Sep 2006 */
4441 
4442                /* 20 Dec 2001: if have global datasets, put them in here */
4443 
4444                THD_append_sessions( new_ss , GLOBAL_library.session ) ;
4445 
4446                /* if we were living with a dummy, fix that */
4447 
4448                if( GLOBAL_library.have_dummy_dataset ) UNDUMMYIZE ;
4449 
4450                /* put the new session into place in the list of sessions */
4451 
4452 STATUS("adding new session to list") ;
4453                GLOBAL_library.sslist->ssar[GLOBAL_library.sslist->num_sess] = new_ss ;
4454                (GLOBAL_library.sslist->num_sess)++ ;
4455                THD_reconcile_parents( GLOBAL_library.sslist ) ;
4456                AFNI_force_adoption( new_ss , GLOBAL_argopt.warp_4D ) ; /* 28 Jan 2011 */
4457                AFNI_make_descendants( GLOBAL_library.sslist ) ;        /* 28 Jan 2011 */
4458 
4459                sprintf(str," \n Session #%2d"
4460                             "\n %s"
4461                             "\n %d datasets\n" ,
4462                        GLOBAL_library.sslist->num_sess ,
4463                        new_ss->sessname, new_ss->num_dsset ) ;
4464 
4465                (void) MCW_popup_message( im3d->vwid->dmode->read_sess_pb,
4466                                          str, MCW_USER_KILL | MCW_TIMER_KILL ) ;
4467 
4468 STATUS("rescanning timeseries files") ;
4469                AFNI_rescan_timeseries_CB(NULL,NULL,NULL) ;
4470 
4471                /* 28 Aug 2002: deal with warptables */
4472 
4473                if( new_ss->warptable != NULL ){
4474                  if( GLOBAL_library.warptable == NULL ) /* create global warptable */
4475                    GLOBAL_library.warptable = new_Htable(101) ;
4476                  subsume_Htable( new_ss->warptable , GLOBAL_library.warptable ) ;
4477                  destroy_Htable( new_ss->warptable ) ;
4478                  new_ss->warptable = NULL ;
4479                }
4480 
4481                RWC_XtPopdown( im3d->vwid->file_dialog ) ;
4482 
4483                /* 04 Feb 2008: switch to this session */
4484 
4485                if( !AFNI_noenv("AFNI_NEWSESSION_SWITCH") ){
4486                  MCW_choose_cbs cbs;
4487                  cbs.ival = GLOBAL_library.sslist->num_sess - 1 ;
4488                  AFNI_finalize_dataset_CB( im3d->vwid->view->choose_sess_pb,
4489                                            (XtPointer)im3d ,  &cbs          ) ;
4490                }
4491             } /* end of if we actually read a new session */
4492 
4493 STATUS("freeing 'text' variable") ;
4494             myXtFree(text) ;
4495          }
4496       }
4497       break ;
4498 
4499       case XmCR_HELP:
4500          (void) MCW_popup_message( w ,
4501                     "To read in a new session, use the\n"
4502                     "Directories and Sessions selectors,\n"
4503                     "and the Filter entry and button,\n"
4504                     "to get the 'Selection' box correct;\n"
4505                     "that is, 'Selection' should be the\n"
4506                     "be the name of the session directory.\n"
4507                     "Then press 'Set'.\n"
4508                     "\n"
4509                     "How to Use the 'Directories' list:\n"
4510                     " Click on or use arrow keys to select\n"
4511                     " a directory, then press 'Enter' or\n"
4512                     " double-click.  This will set the\n"
4513                     " Selection to that directory name,\n"
4514                     " and will show the sub-directories\n"
4515                     " in the Sessions list to the right.\n"
4516                     "-----------------------------------\n"
4517                     "N.B.: To see datasets in the new\n"
4518                     "      session, you must use the\n"
4519                     "      'Switch Session' button!\n"
4520                  , MCW_USER_KILL ) ;
4521       break ;
4522    }
4523    EXRETURN ;
4524 }
4525 
4526 /*----------------------------------------------------------------
4527   Start getting ready to read a new timeseries in.  This
4528   is the CB for the "Read 1D" button.  We'll get a filename
4529   from the user, and process it in another routine.
4530 ------------------------------------------------------------------*/
4531 
AFNI_read_1D_CB(Widget w,XtPointer cd,XtPointer cb)4532 void AFNI_read_1D_CB( Widget w, XtPointer cd, XtPointer cb )
4533 {
4534    Three_D_View *im3d = (Three_D_View *) cd ;
4535    XmString xstr ;
4536 
4537 ENTRY("AFNI_read_1D_CB") ;
4538 
4539    if( !IM3D_OPEN(im3d) ) EXRETURN ;
4540 
4541    AFNI_make_file_dialog( im3d ) ;
4542 
4543    XtAddCallback( im3d->vwid->file_sbox , XmNokCallback ,
4544                   AFNI_finalize_read_1D_CB , cd ) ;
4545 
4546    XtAddCallback( im3d->vwid->file_sbox , XmNcancelCallback ,
4547                   AFNI_finalize_read_1D_CB , cd ) ;
4548 
4549    XtAddCallback( im3d->vwid->file_sbox , XmNhelpCallback ,
4550                   AFNI_finalize_read_1D_CB , cd ) ;
4551 
4552    XtVaSetValues(im3d->vwid->file_sbox,XmNfileTypeMask,XmFILE_REGULAR,NULL);
4553    MCW_set_widget_label( XtNameToWidget(im3d->vwid->file_sbox,"Items") ,
4554                          "1D Files" ) ;
4555 
4556 
4557    /* 02 Feb 1998: put *.1D* in the filename pattern */
4558 
4559    xstr = XmStringCreateLtoR( "*.1D*" , XmFONTLIST_DEFAULT_TAG ) ;
4560    XtVaSetValues( im3d->vwid->file_sbox ,
4561                      XmNpattern , xstr ,
4562                   NULL ) ;
4563    XmStringFree(xstr) ;
4564 
4565    im3d->vwid->file_cb = AFNI_finalize_read_1D_CB ;
4566    im3d->vwid->file_cd = cd ;
4567 
4568    XtVaSetValues( im3d->vwid->file_dialog,
4569                      XmNtitle, "AFNI: Read 1D Timeseries",
4570                   NULL ) ;
4571 
4572    XtPopup( im3d->vwid->file_dialog , XtGrabNone ) ; RWC_sleep(1);
4573    RWC_visibilize_widget( im3d->vwid->file_dialog ) ; /* 09 Nov 1999 */
4574 
4575    EXRETURN ;
4576 }
4577 
4578 /*---------------------------------------------------------------------
4579    Got a button press from the file selection dialog,
4580    so process it (maybe read in a new timeseries!)
4581 -----------------------------------------------------------------------*/
4582 
AFNI_finalize_read_1D_CB(Widget w,XtPointer cd,XtPointer cb)4583 void AFNI_finalize_read_1D_CB( Widget w, XtPointer cd, XtPointer cb )
4584 {
4585    Three_D_View *im3d = (Three_D_View *) cd ;
4586    XmFileSelectionBoxCallbackStruct *cbs = (XmFileSelectionBoxCallbackStruct *) cb ;
4587 
4588 ENTRY("AFNI_finalize_read_1D_CB") ;
4589 
4590    if( !IM3D_OPEN(im3d) ) EXRETURN ;
4591 
4592    switch( cbs->reason ){
4593 
4594       /** close the file selection dialog **/
4595 
4596       case XmCR_CANCEL:
4597          RWC_XtPopdown( im3d->vwid->file_dialog ) ;
4598       break ;
4599 
4600       /** try to read a new timeseries **/
4601 
4602       case XmCR_OK:{
4603          char *text = NULL ;
4604          MRI_IMAGE *flim ;
4605          float *far ;
4606          int ii ;
4607 
4608          XmStringGetLtoR( cbs->value , XmFONTLIST_DEFAULT_TAG , &text ) ;
4609          flim = mri_read_1D( text ) ;
4610          if( flim == NULL || flim->nx < 2 ){
4611             BEEPIT ;
4612             (void) MCW_popup_message( w ,
4613                                        "********************************\n"
4614                                        "** Cannot read data from file **\n"
4615                                        "********************************"
4616                                       , MCW_USER_KILL | MCW_TIMER_KILL ) ;
4617             myXtFree(text) ;
4618             break ;
4619          }
4620 
4621          far = MRI_FLOAT_PTR(flim) ;
4622          for( ii=0 ; ii < flim->nvox ; ii++ )
4623             if( fabs(far[ii]) >= 33333.0 ) far[ii] = WAY_BIG ;
4624 
4625          PLUTO_register_timeseries( text , flim ) ;
4626          mri_free(flim) ;
4627          myXtFree(text) ;
4628          RWC_XtPopdown( im3d->vwid->file_dialog ) ;
4629       }
4630       break ;
4631 
4632       case XmCR_HELP:
4633          (void) MCW_popup_message( w ,
4634                     "To read in a new timeseries, use the\n"
4635                     "Directories and '1D Files' selectors,\n"
4636                     "and the Filter entry and button,\n"
4637                     "to get the 'Selection' box correct;\n"
4638                     "that is, 'Selection' should be the\n"
4639                     "be the name of the 1D file to read.\n"
4640                     "Then press 'Set'.\n"
4641                     "\n"
4642                     "How to Use the 'Directories' list:\n"
4643                     " Click on or use arrow keys to select\n"
4644                     " a directory, then press 'Enter' or\n"
4645                     " double-click.  This will set the\n"
4646                     " Selection to that directory name.\n"
4647                     " You must then choose the 1D file you\n"
4648                     " want from the '1D Files' list at the\n"
4649                     " right.\n"
4650                  , MCW_USER_KILL ) ;
4651       break ;
4652    }
4653    EXRETURN ;
4654 }
4655 
4656 /*--------------------------------------------------------------------
4657    26 Mar 2001: read a dataset from the Web
4658 ----------------------------------------------------------------------*/
4659 
AFNI_read_Web_CB(Widget w,XtPointer cd,XtPointer cb)4660 void AFNI_read_Web_CB( Widget w, XtPointer cd, XtPointer cb )
4661 {
4662    Three_D_View *im3d = (Three_D_View *) cd ;
4663    XmString xstr ;
4664 
4665 ENTRY("AFNI_read_Web_CB") ;
4666 
4667 #if 0
4668    if( AFNI_splash_isopen() == 1 ){ BEEPIT ; EXRETURN ; }
4669 #endif
4670 
4671    if( !IM3D_OPEN(im3d) ) EXRETURN ;
4672 
4673    MCW_choose_string( w ,
4674     "Complete http:// or ftp:// address of dataset (.HEAD or .mnc or .mnc.gz):\n"
4675     "Examples: ftp://afni.nimh.nih.gov/AFNI/data/astrip+orig.HEAD\n"
4676     "          https://afni.nimh.nih.gov/afni/norm305.mnc.gz"
4677      , NULL , AFNI_finalize_read_Web_CB , (XtPointer) im3d ) ;
4678 
4679    EXRETURN ;
4680 }
4681 
4682 /*--------------------------------------------------------------------*/
4683 
AFNI_finalize_read_Web_CB(Widget w,XtPointer cd,MCW_choose_cbs * cbs)4684 void AFNI_finalize_read_Web_CB( Widget w , XtPointer cd , MCW_choose_cbs *cbs )
4685 {
4686    Three_D_View *im3d = (Three_D_View *) cd ;
4687    THD_3dim_dataset *dset, *temp_dset ;
4688    RwcPointer_array *dsar ;
4689    THD_session *ss = GLOBAL_library.sslist->ssar[im3d->vinfo->sess_num] ;
4690    char str[256] ;
4691    int nds,dd,vv , nn, na=-1,nf=-1 ,nts ;
4692 
4693 ENTRY("AFNI_finalize_read_Web_CB") ;
4694 
4695    if( !IM3D_OPEN(im3d) ) EXRETURN ;
4696 
4697    if( cbs->reason  != mcwCR_string ||
4698        cbs->cval    == NULL         ||
4699        cbs->cval[0] == '\0'         ||
4700        (strstr(cbs->cval,"http://")==NULL && strstr(cbs->cval,"ftp://")==NULL) ){
4701 
4702       (void) MCW_popup_message( im3d->vwid->dmode->read_Web_pb ,
4703                                   " \n** Illegal URL **\n " ,
4704                                 MCW_USER_KILL | MCW_TIMER_KILL      ) ;
4705 
4706       BEEPIT ; EXRETURN ;
4707    }
4708 
4709    /** read a list of datasets? **/
4710 
4711    if( strstr(cbs->cval,"AFNILIST") != NULL ){
4712 
4713       SHOW_AFNI_PAUSE ;
4714       dsar = THD_fetch_many_datasets( cbs->cval ) ; /* get array of datasets */
4715       SHOW_AFNI_READY ;
4716       if( dsar == NULL || dsar->num == 0 ){
4717          (void) MCW_popup_message( im3d->vwid->dmode->read_Web_pb ,
4718                                      " \n"
4719                                      "** Can't get datasets **\n"
4720                                      "** from that URL!     **\n " ,
4721                                    MCW_USER_KILL | MCW_TIMER_KILL      ) ;
4722          BEEPIT ; EXRETURN ;
4723       }
4724 
4725    } else {  /** read one dataset **/
4726 
4727       SHOW_AFNI_PAUSE ;
4728       dset = THD_fetch_dataset( cbs->cval ) ;
4729       SHOW_AFNI_READY ;
4730       if( dset == NULL ){
4731         (void) MCW_popup_message( im3d->vwid->dmode->read_Web_pb ,
4732                                    " \n"
4733                                    "** Can't get a dataset **\n"
4734                                    "** from that URL!      **\n " ,
4735                                   MCW_USER_KILL | MCW_TIMER_KILL      ) ;
4736         BEEPIT ; EXRETURN ;
4737       }
4738       INIT_XTARR(dsar) ; ADDTO_XTARR(dsar,dset) ; XTARR_IC(dsar,0) = IC_DSET ;
4739    }
4740 
4741    /** loop over all datasets in array, place in current session **/
4742 
4743    for( nts=nds=dd=0 ; dd < dsar->num ; dd++ ){
4744 
4745       if( XTARR_IC(dsar,dd) == IC_FLIM ){  /* process a 1D file */
4746          AFNI_add_timeseries( (MRI_IMAGE *) XTARR_XT(dsar,dd) ) ;
4747          nts++ ; continue ;
4748       }
4749       if( XTARR_IC(dsar,dd) != IC_DSET ) continue ;    /* bad */
4750 
4751       dset = (THD_3dim_dataset *) XTARR_XT(dsar,dd) ;
4752       if( !ISVALID_DSET(dset) ) continue ;             /* bad */
4753       AFNI_inconstancy_check(NULL,dset) ;      /* 06 Sep 2006 */
4754       vv = dset->view_type ;
4755       nn = ss->num_dsset ;
4756       if( nn >= THD_MAX_SESSION_SIZE ){
4757         fprintf(stderr,"\a\n*** too many anatomical datasets!\n") ;
4758         DSET_delete(dset) ;  /* 01 Nov 2001 */
4759       } else {
4760           SET_SESSION_DSET(dset,ss,nn,vv) ;
4761 /*        ss->dsset_xform_table[nn][vv] = dset ;*/
4762         ss->num_dsset++ ; nds++ ;
4763         if( vv == im3d->vinfo->view_type && na == -1 ) na = nn ;
4764       }
4765    } /* end of loop over dd=datasets in dsar */
4766 
4767    FREE_XTARR(dsar) ;
4768    AFNI_inconstancy_check(im3d,NULL); /* 06 Sep 2006 */
4769 
4770    /*-- popup a message saying what happened --*/
4771 
4772    if( nts > 0 )
4773       sprintf(str," \n Read %d datasets and \n"
4774                      "      %d timeseries from\n"
4775                      " %s\n ",nds,nts,cbs->cval  ) ;
4776    else
4777       sprintf(str," \n Read %d datasets from\n"
4778                      " %s\n ",nds,cbs->cval    ) ;
4779 
4780    (void) MCW_popup_message( im3d->vwid->dmode->read_Web_pb ,
4781                              str , MCW_USER_KILL | MCW_TIMER_KILL ) ;
4782 
4783    if( nds == 0 ){ EXRETURN; }
4784 
4785    /*-- prepare to switch back to AFNI --*/
4786 
4787    if( na >= 0 ) im3d->vinfo->anat_num = na ; /* 1st new anat in current view */
4788    if( nf >= 0 ) im3d->vinfo->func_num = nf ; /* 1st new func in current view */
4789 
4790    if( GLOBAL_library.have_dummy_dataset ){   /* switch away from dummy dataset */
4791      UNDUMMYIZE ;
4792      if( na < 0 && ss->num_dsset > 1 ){
4793        im3d->vinfo->anat_num = 1 ;
4794        im3d->vinfo->func_num = 1 ;            /* 07 Sep 2006 (oops) */
4795        for( vv=0 ; vv <= LAST_VIEW_TYPE ; vv++ ){
4796          temp_dset = GET_SESSION_DSET(ss,1,vv);
4797          if( ISVALID_DSET(temp_dset) ){
4798             im3d->vinfo->view_type = vv; break;
4799          }
4800        }
4801      } else if( na < 0 ){                         /* should be impossible */
4802        (void) MCW_popup_message( im3d->vwid->dmode->read_Web_pb ,
4803                                  " \n** No datasets available **\n " ,
4804                                  MCW_USER_KILL | MCW_TIMER_KILL ) ;
4805      }
4806    }
4807 
4808    AFNI_initialize_view( NULL , im3d ) ;
4809    EXRETURN ;
4810 }
4811 
4812 /*----------------------------------------------------------------
4813    Obey the command to rescan the current session
4814 ------------------------------------------------------------------*/
4815 
AFNI_rescan_CB(Widget w,XtPointer cd,XtPointer cb)4816 void AFNI_rescan_CB( Widget w, XtPointer cd, XtPointer cb )
4817 {
4818    Three_D_View *im3d = (Three_D_View *)cd , *qq3d ;
4819    int cc ;
4820    char str[256+THD_MAX_NAME] ;
4821 
4822 ENTRY("AFNI_rescan_CB") ;
4823 
4824    if( !IM3D_OPEN(im3d) ) EXRETURN ;
4825 
4826    SHOW_AFNI_PAUSE ;
4827    cc = AFNI_rescan_session( im3d->vinfo->sess_num ) ;
4828    POPDOWN_strlist_chooser ;
4829    if( cc > 0 ){
4830       sprintf(str," \n"
4831                   " Added %d datasets to \n"
4832                   " %s\n" ,
4833              cc ,
4834              GLOBAL_library.sslist->ssar[im3d->vinfo->sess_num]->sessname ) ;
4835       (void) MCW_popup_message( w , str , MCW_USER_KILL | MCW_TIMER_KILL ) ;
4836    }
4837 
4838 #if 1
4839    for( cc=0 ; cc < MAX_CONTROLLERS ; cc++ ){    /* 31 Mar 1999 */
4840       qq3d = GLOBAL_library.controllers[cc] ;
4841       if( IM3D_OPEN(qq3d) ) AFNI_process_dsetchange( qq3d ) ;
4842    }
4843 #endif
4844 
4845    SHOW_AFNI_READY ;
4846    EXRETURN ;
4847 }
4848 
4849 /*----------------------------------------------------------------*/
4850 /* 10 Nov 2005: check periodically for updated datasets */
4851 
4852 static int block_rescan = 0 ;
AFNI_block_rescan(int bb)4853 void AFNI_block_rescan( int bb ){ block_rescan = bb ; }
4854 
AFNI_rescan_timeout_CB(XtPointer client_data,XtIntervalId * id)4855 void AFNI_rescan_timeout_CB( XtPointer client_data , XtIntervalId *id )
4856 {
4857   XtAppContext *apc = (XtAppContext *)client_data ;
4858 
4859 ENTRY("AFNI_rescan_timeout_CB") ;
4860   if( !block_rescan ) AFNI_rescan_all_CB(NULL,NULL,NULL) ;
4861   (void) XtAppAddTimeOut( *apc, 14999, AFNI_rescan_timeout_CB, apc ) ;
4862   EXRETURN ;
4863 }
4864 
4865 /*----------------------------------------------------------------*/
4866 
AFNI_rescan_all_CB(Widget w,XtPointer cd,XtPointer cb)4867 void AFNI_rescan_all_CB( Widget w, XtPointer cd, XtPointer cb )
4868 {
4869    int iss , cc=0 , uu=(w!=(Widget)NULL) , pp=0 ;
4870    Three_D_View *im3d ;
4871 
4872 ENTRY("AFNI_rescan_all_CB") ;
4873 
4874    for( iss=0 ; iss < GLOBAL_library.sslist->num_sess ; iss++ ){
4875      cc += AFNI_rescan_session( iss ) ;
4876      if( pp==0 && cc > 0 ){ SHOW_AFNI_PAUSE; pp=1; }
4877    }
4878    if( cc > 0 && uu ){
4879      char str[256] ;
4880      POPDOWN_strlist_chooser ;
4881      sprintf(str," \n"
4882                  " Added %d datasets total \n" , cc ) ;
4883      (void) MCW_popup_message( w , str , MCW_USER_KILL | MCW_TIMER_KILL ) ;
4884    } else if( cc == 0 && uu ){
4885      (void) MCW_popup_message( w ,
4886                                " \n Found no new datasets \n" ,
4887                                 MCW_USER_KILL | MCW_TIMER_KILL ) ;
4888    }
4889 
4890 #if 1
4891    if( cc > 0 ){
4892      for( cc=0 ; cc < MAX_CONTROLLERS ; cc++ ){    /* 31 Mar 1999 */
4893        im3d = GLOBAL_library.controllers[cc] ;
4894        if( IM3D_OPEN(im3d) ) AFNI_process_dsetchange( im3d ) ;
4895      }
4896    }
4897 #endif
4898 
4899    if( pp ) SHOW_AFNI_READY ;
4900    EXRETURN ;
4901 }
4902 
4903 /*----------------------------------------------------------------------*/
4904 /*!
4905   Re-read the session indexed by "sss".  THE OLD WAY.
4906   Much of this code is taken from AFNI_read_inputs.
4907   WARNING: this will do bad things if the user deletes the
4908            session directory or the current active datasets within it
4909            before trying this.  On the other hand, if the user is that
4910            stupid, bad things will probably have happened to him already
4911            (like being unable to open dataset files, or being unable to
4912            tie his shoes correctly, or being named Mike Beauchamp).
4913 ------------------------------------------------------------------------*/
4914 
AFNI_rescan_session_OLD(int sss)4915 static int AFNI_rescan_session_OLD( int sss )  /* the old way */
4916 {
4917    int vv , ii , cc , nold,nnew ;
4918    THD_session   *new_ss , *old_ss ;
4919    Three_D_View  *im3d ;
4920    MCW_idcode     anat_idcode[MAX_CONTROLLERS] ,
4921                   func_idcode[MAX_CONTROLLERS] ;
4922    THD_slist_find find ;
4923    THD_3dim_dataset *dset, *temp_dset ;
4924 
4925 ENTRY("AFNI_rescan_session_OLD") ;
4926 { char str[256]; sprintf(str,"session index %d\n",sss); STATUS(str); }
4927 
4928    if( GLOBAL_library.have_dummy_dataset ){ RETURN(0) ; }
4929 
4930 #if 0
4931 fprintf(stderr,"Enter AFNI_rescan_session_OLD on session index %d\n",sss) ;
4932 #endif
4933 
4934    /*--- sanity checks ---*/
4935 
4936    if( sss < 0 || sss >= GLOBAL_library.sslist->num_sess ){ RETURN(0) ; }
4937 
4938    old_ss = GLOBAL_library.sslist->ssar[sss] ;
4939    if( ! ISVALID_SESSION(old_ss) || old_ss->is_collection ){ RETURN(0); }
4940 
4941    if( old_ss == GLOBAL_library.session ) RETURN(0) ;  /* 21 Dec 2001 */
4942 
4943    if( ! THD_is_directory(old_ss->sessname) ) RETURN(0) ; /* 02 Jun 2016 */
4944 
4945    /*--- Make sure that the dataset choosers are closed.
4946          Since these are just instances of the generic strlist
4947          chooser, and we can't tell what is being chosen just now,
4948          we'll just forcibly close the strlist chooser no matter what. ---*/
4949 
4950    POPDOWN_strlist_chooser ;
4951 
4952    /*--- mark all datasets in the old session for deletion from memory ---*/
4953 
4954 STATUS("marking old session datasets") ;
4955 
4956    nold = old_ss->num_dsset ;
4957 
4958    for( ii=0 ; ii < old_ss->num_dsset ; ii++ )
4959       for( vv=0 ; vv <= LAST_VIEW_TYPE ; vv++ ){
4960          temp_dset = GET_SESSION_DSET(old_ss, ii, vv);
4961          if( ISVALID_3DIM_DATASET(temp_dset) ){
4962 /*         if( ISVALID_3DIM_DATASET(old_ss->dsset_xform_table[ii][vv]) )*/
4963             if( DSET_in_global_session(temp_dset) )
4964                SET_SESSION_DSET(NULL, old_ss, ii, vv);
4965 /*            if( DSET_in_global_session(old_ss->dsset_xform_table[ii][vv]) )*/
4966 /*               old_ss->dsset_xform_table[ii][vv] = NULL ; */  /* will be added back in later */
4967             else
4968                DSET_MARK_FOR_DEATH( temp_dset ) ;
4969 /*               DSET_MARK_FOR_DEATH( old_ss->dsset_xform_table[ii][vv] ) ;*/
4970          }
4971       }
4972    /*--- mark all descendants for purging as well ---*/
4973 
4974    AFNI_mark_for_death( GLOBAL_library.sslist ) ;
4975 
4976    /*--- but before actual deletion, find the
4977          active datasets in each main controller window ---*/
4978 
4979 STATUS("checking active controllers") ;
4980 
4981    for( cc=0 ; cc < MAX_CONTROLLERS ; cc++ ){
4982       ZERO_IDCODE(anat_idcode[cc]) ; ZERO_IDCODE(func_idcode[cc]) ;
4983       im3d = GLOBAL_library.controllers[cc] ;
4984       if( IM3D_OPEN(im3d) && im3d->vinfo->sess_num == sss ){
4985          anat_idcode[cc] = im3d->anat_now->idcode ;
4986 
4987          if( ISVALID_3DIM_DATASET(im3d->fim_now) )
4988            func_idcode[cc] = im3d->fim_now->idcode ;
4989 
4990          XmUpdateDisplay(im3d->vwid->top_shell) ;
4991       }
4992    }
4993 
4994    /*--- now can flush the old datasets, prior to reading again ---*/
4995 
4996    AFNI_andersonville( GLOBAL_library.sslist , False ) ; /* keep files! */
4997 
4998    /*--- now read in the session again ---*/
4999 
5000 STATUS("rescanning session now:") ;
5001 STATUS(old_ss->sessname) ;
5002 
5003    new_ss = THD_init_session( old_ss->sessname ) ;
5004 
5005    if( new_ss == NULL || new_ss->num_dsset <= 0 ){
5006       fprintf(stderr,"\n*** Fatal error: Rescan of session %s finds nothing!\n",
5007               old_ss->sessname ) ;
5008       EXIT(1) ;
5009    }
5010 
5011    myXtFree( old_ss ) ;  /* no longer need this */
5012 
5013    /* set parent pointers */
5014 
5015 STATUS("PARENTIZE-ing datasets in new session") ;
5016 
5017    new_ss->parent = NULL ;
5018    for( ii=0 ; ii < new_ss->num_dsset ; ii++ ){
5019      for( vv=0 ; vv <= LAST_VIEW_TYPE ; vv++ ){
5020        dset = GET_SESSION_DSET(new_ss, ii, vv);
5021 /*       dset = new_ss->dsset_xform_table[ii][vv] ;*/
5022        if( dset != NULL ){
5023          PARENTIZE( dset, NULL ) ;
5024 /*         PARENTIZE( new_ss->dsset_xform_table[ii][vv] , NULL ) ;*/
5025          AFNI_inconstancy_check(NULL,dset) ; /* 06 Sep 2006 */
5026        }
5027    } }
5028    AFNI_inconstancy_check(NULL,NULL);
5029 
5030    /* put the new session into place in the list of sessions */
5031 
5032    GLOBAL_library.sslist->ssar[sss] = new_ss ;
5033 
5034    /* 20 Dec 2001: add the global datasets back in, if any */
5035 
5036    THD_append_sessions( new_ss , GLOBAL_library.session ) ;
5037 
5038    /* assign the warp and anatomy parent pointers;
5039       then, make any datasets that don't exist but logically
5040       descend from the warp and anatomy parents just assigned */
5041 
5042    THD_reconcile_parents( GLOBAL_library.sslist ) ;
5043    AFNI_force_adoption( new_ss , GLOBAL_argopt.warp_4D ) ;
5044    AFNI_make_descendants( GLOBAL_library.sslist ) ;
5045 
5046    /* 28 Aug 2002: deal with warptables */
5047 
5048    if( new_ss->warptable != NULL ){
5049      if( GLOBAL_library.warptable == NULL ) /* create global warptable */
5050        GLOBAL_library.warptable = new_Htable(101) ;
5051      subsume_Htable( new_ss->warptable , GLOBAL_library.warptable ) ;
5052      destroy_Htable( new_ss->warptable ) ;
5053      new_ss->warptable = NULL ;
5054    }
5055 
5056    /*--- for each main controller window, must reset some pointers ---*/
5057 
5058 STATUS("fixing active controllers") ;
5059 
5060    for( cc=0 ; cc < MAX_CONTROLLERS ; cc++ ){
5061       im3d = GLOBAL_library.controllers[cc] ;
5062       if( IM3D_OPEN(im3d) && im3d->vinfo->sess_num == sss ){
5063          im3d->ss_now = new_ss ;
5064          vv           = im3d->vinfo->view_type ;  /* won't change this */
5065 
5066          im3d->fimdata->fimdset = NULL ;          /* disable FIMage */
5067 
5068          /* look for old anat dataset in new session */
5069 
5070          find = THD_dset_in_session( FIND_IDCODE ,
5071                                      &(anat_idcode[cc]) , new_ss ) ;
5072 
5073          /* if have it, use it, otherwise, pick first anat in this view */
5074 
5075          if( find.dset != NULL && find.view_index == vv ){
5076             im3d->vinfo->anat_num = find.dset_index ;
5077          } else {
5078             for( ii=0 ; ii < new_ss->num_dsset ; ii++ ) {
5079                temp_dset = GET_SESSION_DSET(new_ss, ii, vv);
5080                if( ISVALID_3DIM_DATASET(temp_dset)) break ;
5081 /*               if( ISVALID_3DIM_DATASET(new_ss->dsset_xform_table[ii][vv]) ) break ;*/
5082             }
5083             if( ii < new_ss->num_dsset ){
5084                im3d->vinfo->anat_num = ii ;
5085             } else {
5086                fprintf(stderr,
5087                        "\n*** Fatal error:"
5088                        " Cannot find anat dataset to switch to after"
5089                        " rescanning session %s\a\n",
5090                        new_ss->sessname ) ;
5091                EXIT(1) ;
5092             }
5093          }
5094 
5095          /* do the same for old func dataset, if any */
5096 
5097          if( ! ISZERO_IDCODE(func_idcode[cc]) ){
5098             find = THD_dset_in_session( FIND_IDCODE ,
5099                                         &(func_idcode[cc]) , new_ss ) ;
5100 
5101             if( find.dset != NULL && find.view_index == vv ){
5102                im3d->vinfo->func_num = find.dset_index ;
5103             } else {
5104                for( ii=0 ; ii < new_ss->num_dsset ; ii++ ) {
5105                   temp_dset = GET_SESSION_DSET(new_ss, ii, vv);
5106                   if( ISVALID_3DIM_DATASET(temp_dset) ) break ;
5107 /*                if( ISVALID_3DIM_DATASET(new_ss->dsset_xform_table[ii][vv]) ) break ;*/
5108                }
5109                if( ii < new_ss->num_dsset ){
5110                   im3d->vinfo->func_num = ii ;
5111                } else {
5112                   im3d->vinfo->func_num = 0 ;  /* no func is not fatal */
5113                }
5114             }
5115          } else {
5116             im3d->vinfo->func_num = 0 ;
5117          }
5118 
5119          /* switch this controller to the new datasets */
5120 
5121          AFNI_initialize_view( NULL , im3d ) ;
5122          XmUpdateDisplay(im3d->vwid->top_shell) ;
5123       }
5124    }
5125 
5126    nnew = new_ss->num_dsset ;
5127 
5128    RETURN( (nnew-nold) ) ;
5129 }
5130 
5131 /*----------------------------------------------------------------------*/
5132 /*!
5133   Re-read the session indexed by "sss".  THE NEW WAY.
5134   Much of this code is taken from AFNI_read_inputs().
5135 
5136   WARNING:
5137     - This will do bad things if the user deletes the session directory
5138       or the current active datasets within it before trying this.
5139     - On the other hand, if the user is that stupid, bad things will
5140       probably have happened to him already (like being unable to open
5141       dataset files, or being unable to tie his shoes correctly).
5142 
5143   28 Dec 2002: modified extensively to not clobber existing pointers
5144                to datasets, but instead to insert new datasets into the
5145                existing session -- RWCox (MX&HNY)
5146 ------------------------------------------------------------------------*/
5147 
AFNI_rescan_session_NEW(int sss)5148 static int AFNI_rescan_session_NEW( int sss )   /* the new way */
5149 {
5150    int vv , ii , nr , na_new=0 ;
5151    THD_session  *new_ss , *old_ss ;
5152    THD_slist_find find ;
5153    THD_3dim_dataset *new_dset, *temp_dset ;
5154 
5155 ENTRY("AFNI_rescan_session_NEW") ;
5156 { char str[256]; sprintf(str,"session index %d\n",sss); STATUS(str); }
5157 
5158    if( GLOBAL_library.have_dummy_dataset ){ RETURN(0); }
5159 
5160 #if 0
5161 fprintf(stderr,"Enter AFNI_rescan_session_NEW on session index %d\n",sss) ;
5162 #endif
5163 
5164    /*--- sanity checks ---*/
5165 
5166    if( sss < 0 || sss >= GLOBAL_library.sslist->num_sess ){ RETURN(0); }
5167 
5168    old_ss = GLOBAL_library.sslist->ssar[sss] ;
5169    if( ! ISVALID_SESSION(old_ss) || old_ss->is_collection ){ RETURN(0); }
5170 
5171                                      /* can't rescan global session */
5172    if( old_ss == GLOBAL_library.session ) RETURN(0); /* 21 Dec 2001 */
5173 
5174    if( ! THD_is_directory(old_ss->sessname) ) RETURN(0) ; /* 02 Jun 2016 */
5175 
5176    /*--- read in the session again, into a new THD_session struct ---*/
5177 
5178 STATUS("rescanning session now:") ;
5179 STATUS(old_ss->sessname) ;
5180 
5181    new_ss = THD_init_session( old_ss->sessname ) ;
5182    if( ! ISVALID_SESSION(new_ss) ){ RETURN(0); } /* this is BAD */
5183 
5184    /*--- scan datasets and remove those
5185          that already exist in this session ---*/
5186 
5187    for( ii=0 ; ii < new_ss->num_dsset ; ii++ ){
5188      for( vv=0 ; vv <= LAST_VIEW_TYPE ; vv++ ){
5189        new_dset = GET_SESSION_DSET(new_ss, ii, vv);
5190 /*     new_dset = new_ss->dsset_xform_table[ii][vv] ;*/
5191        if( ISVALID_DSET(new_dset) ){
5192          find = THD_dset_in_session( FIND_IDCODE, &(new_dset->idcode), old_ss );
5193          if( find.dset == NULL ){
5194           find = THD_dset_in_session(FIND_PREFIX, DSET_PREFIX(new_dset),old_ss);
5195           if( find.dset != NULL && find.view_index != vv ) find.dset = NULL ;
5196          }
5197          if( find.dset != NULL ){
5198            DSET_delete(new_dset);
5199            SET_SESSION_DSET(NULL, new_ss, ii, vv);
5200            /* new_ss->dsset_xform_table[ii][vv] = NULL;*/
5201          }
5202        }
5203      }
5204    }
5205 
5206    /*--- now scan survivors and put them
5207          at the end of the existing session ---*/
5208 
5209    for( ii=0 ; ii < new_ss->num_dsset ; ii++ ){
5210      for( vv=0 ; vv <= LAST_VIEW_TYPE ; vv++ )   /* see if row is empty */
5211        if( GET_SESSION_DSET(new_ss, ii, vv) != NULL ) break ;
5212 /*       if( new_ss->dsset_xform_table[ii][vv] != NULL ) break ;*/
5213      if( vv > LAST_VIEW_TYPE ) continue ;          /* empty row ==> skip  */
5214      AFNI_inconstancy_check(NULL,GET_SESSION_DSET(new_ss, ii,vv)) ;  /* 06 Sep 2006 */
5215 /*     AFNI_inconstancy_check(NULL,new_ss->dsset_xform_table[ii][vv]) ;*/  /* 06 Sep 2006 */
5216      nr = old_ss->num_dsset ;                      /* next row in old_ss  */
5217      if( nr >= THD_MAX_SESSION_SIZE ) break ;      /* old session is full */
5218      for( vv=0 ; vv <= LAST_VIEW_TYPE ; vv++ ) {    /* copy new row to old */
5219          temp_dset = GET_SESSION_DSET(new_ss, ii, vv);
5220          SET_SESSION_DSET(temp_dset, old_ss, nr, vv);
5221 /*       old_ss->dsset_xform_table[nr][vv] = new_ss->dsset_xform_table[ii][vv];*/
5222      }
5223      old_ss->num_dsset++ ;  na_new++ ;             /* 1 more row in old   */
5224    }
5225    if( na_new == 0 ) RETURN(0) ;                   /* 10 Nov 2005 */
5226    AFNI_inconstancy_check(NULL,NULL);              /* 06 Sep 2006 */
5227 
5228    /*-- 15 Jan 2003: purge all datasets from memory (for Hauke Heekeren) --*/
5229 
5230    for( ii=0 ; ii < old_ss->num_dsset ; ii++ )
5231      for( vv=0 ; vv <= LAST_VIEW_TYPE ; vv++ ) {
5232        temp_dset = GET_SESSION_DSET(old_ss, ii, vv);
5233        if( temp_dset != NULL ) DSET_unload(temp_dset);
5234 /*     if( old_ss->dsset_xform_table[ii][vv] != NULL ) DSET_unload(old_ss->dsset_xform_table[ii][vv]);*/
5235      }
5236    /* assign the warp and anatomy parent pointers;
5237       then, make any datasets that don't exist but logically
5238       descend from the warp and anatomy parents just assigned */
5239 
5240    THD_reconcile_parents( GLOBAL_library.sslist ) ;
5241    AFNI_force_adoption( old_ss , GLOBAL_argopt.warp_4D ) ;
5242    AFNI_make_descendants( GLOBAL_library.sslist ) ;
5243 
5244    /* 28 Aug 2002: deal with warptables */
5245 
5246    if( new_ss->warptable != NULL ){
5247      if( GLOBAL_library.warptable == NULL ) /* create global warptable */
5248        GLOBAL_library.warptable = new_Htable(101) ;
5249      subsume_Htable( new_ss->warptable , GLOBAL_library.warptable ) ;
5250      destroy_Htable( new_ss->warptable ) ;
5251      new_ss->warptable = NULL ;
5252    }
5253    free(new_ss) ;
5254 
5255    RETURN(na_new) ;
5256 }
5257 
5258 /*----------------------------------------------------------------------*/
5259 /*! Use the old or the new rescan session methods -- 07 Feb 2003.
5260 ------------------------------------------------------------------------*/
5261 
AFNI_rescan_session(int sss)5262 int AFNI_rescan_session( int sss )
5263 {
5264    char *eee = getenv("AFNI_RESCAN_METHOD") ;
5265    int use_new , use_rep ;
5266    static int first=1 ;
5267 
5268    use_rep = ( eee != NULL && strcasecmp(eee,"REPLACE") == 0 ) ;
5269 
5270    use_new = ( AFNI_yesenv("AFNI_AUTO_RESCAN")      ||
5271                AFNI_yesenv("AFNI_RESCAN_AT_SWITCH") || !use_rep ) ;
5272 
5273    if( use_rep && use_new && first ){  /* 07 Oct 2008 */
5274      WARNING_message(
5275        " \n"
5276        "   AFNI_RESCAN_METHOD = REPLACE is incompatible with\n"
5277        "   AFNI_AUTO_RESCAN = YES  and/or  AFNI_RESCAN_AT_SWITCH = YES" ) ;
5278      first = 0 ;
5279    }
5280 
5281    return (use_new) ? AFNI_rescan_session_NEW( sss )
5282                     : AFNI_rescan_session_OLD( sss ) ;
5283 }
5284 
5285 /*---------------------------------------------------------------
5286    Rescan for timeseries files
5287 -----------------------------------------------------------------*/
5288 
AFNI_rescan_timeseries_CB(Widget w,XtPointer cd,XtPointer cb)5289 void AFNI_rescan_timeseries_CB(Widget w, XtPointer cd, XtPointer cb)
5290 {
5291    int iss , inew , jold , nnew , nold , nadd ;
5292    THD_string_array *dlist ;
5293    THD_session *ss ;
5294    MRI_IMARR *newtsar ;
5295    MRI_IMAGE *newim , *oldim ;
5296    NI_ELARR  *newtsvar ;         /* 16 Jun 2020 */
5297    NI_element *newel , *oldel ;
5298 
5299 ENTRY("AFNI_rescan_timeseries_CB") ;
5300 
5301    /** assemble list of directories **/
5302 
5303    if( GLOBAL_library.have_dummy_dataset ){ EXRETURN ; }
5304 
5305    INIT_SARR( dlist ) ;
5306 
5307    for( iss=0 ; iss < GLOBAL_library.sslist->num_sess ; iss++ ){
5308       ss = GLOBAL_library.sslist->ssar[iss] ;
5309       if( ss->is_collection ) continue ;
5310       ADDTO_SARR(dlist,ss->sessname) ;
5311    }
5312 
5313    if( dlist->num == 0 ){ DESTROY_SARR(dlist) ; EXRETURN ; }
5314 
5315    /** read timeseries into a new array **/
5316 
5317    newtsar = THD_get_many_timeseries( dlist ) ;
5318    newtsvar = THD_get_many_tcsv( dlist ) ;
5319    DESTROY_SARR( dlist ) ;
5320 
5321    if( newtsar != NULL ){ /** check to see which ones are in the old list **/
5322 
5323      nnew = IMARR_COUNT(newtsar) ;
5324      nold = IMARR_COUNT(GLOBAL_library.timeseries) ;
5325 
5326      for( nadd=inew=0 ; inew < nnew ; inew++ ){
5327         newim = IMARR_SUBIMAGE(newtsar,inew) ;  /* new timeseries */
5328         for( jold=0 ; jold < nold ; jold++ ){
5329            oldim = IMARR_SUBIMAGE(GLOBAL_library.timeseries,jold) ; /* old one */
5330 
5331            if( oldim != NULL && oldim->name != NULL &&        /* break out of loop */
5332                strcmp(oldim->name,newim->name) == 0 ) break ; /* when new == old */
5333         }
5334 
5335         if( jold == nold ){
5336            ADDTO_IMARR(GLOBAL_library.timeseries,newim); nadd++;  /* is new */
5337         } else {
5338            mri_free(newim) ;                                      /* is old */
5339         }
5340      }
5341      if( nadd > 0 ) POPDOWN_timeseries_chooser ;
5342      FREE_IMARR(newtsar) ; newtsar = NULL ;
5343    }
5344 
5345    if( newtsvar != NULL ){  /* repeat for tcsv files */
5346 
5347      nnew = ELARR_COUNT(newtsvar) ;
5348      nold = ELARR_COUNT(GLOBAL_library.tcsv_data) ;
5349 
5350      for( nadd=inew=0 ; inew < nnew ; inew++ ){
5351         newel = ELARR_SUBEL(newtsvar,inew) ;  /* new data */
5352         for( jold=0 ; jold < nold ; jold++ ){
5353            oldel = ELARR_SUBEL(GLOBAL_library.tcsv_data,jold) ; /* old one */
5354 
5355            if( oldel != NULL &&                                     /* break out of loop */
5356                strcmp(oldel->filename,newel->filename) == 0 ) break ; /* when new == old */
5357         }
5358 
5359         if( jold == nold ){
5360            ADDTO_ELARR(GLOBAL_library.tcsv_data,newel); nadd++;  /* is new */
5361         } else {
5362            NI_free_element(newel) ;                             /* is old */
5363         }
5364      }
5365      /* if( nadd > 0 ) POPDOWN_timeseries_chooser ; */
5366      FREE_ELARR(newtsvar) ;
5367    }
5368 
5369    EXRETURN ;
5370 }
5371 
5372 /*---------------------------------------------------------------
5373    callback for the anatmode bbox
5374 -----------------------------------------------------------------*/
5375 
AFNI_anatmode_CB(Widget w,XtPointer cd,XtPointer cb)5376 void AFNI_anatmode_CB( Widget w, XtPointer cd, XtPointer cb )
5377 {
5378    Three_D_View *im3d = (Three_D_View *) cd ;
5379    int old_val , new_val ;
5380    THD_fvec3 fv ;
5381    THD_ivec3 iv ;
5382 
5383 ENTRY("AFNI_anatmode_CB") ;
5384 
5385    if( ! IM3D_OPEN(im3d) ) EXRETURN ;
5386 
5387    im3d->vinfo->stats_anat_ok =
5388     im3d->vinfo->stats_func_ok =
5389      im3d->vinfo->arang_func_ok =
5390       im3d->vinfo->stats_thresh_ok = 0 ; /* 24 May 2019 */
5391 
5392    old_val = 1 << im3d->vinfo->force_anat_wod ;
5393    new_val = MCW_val_bbox( im3d->vwid->dmode->anatmode_bbox ) ;
5394 
5395 if(PRINT_TRACING){
5396  char str[256] ; sprintf(str,"old_val=%d new_val=%d",old_val,new_val) ;
5397  STATUS(str) ; }
5398 
5399    if( new_val != old_val ){
5400      im3d->vinfo->force_anat_wod = (new_val != DMODE_BRICK_BVAL) ;
5401      SHOW_AFNI_PAUSE ;
5402      im3d->vinfo->tempflag = 1 ;           /* 15 Mar 2000 */
5403      AFNI_modify_viewing( im3d , True ) ;  /* redisplay */
5404      SHOW_AFNI_READY ;
5405    }
5406 
5407    RESET_AFNI_QUIT(im3d) ;
5408    EXRETURN ;
5409 }
5410 
5411 /*---------------------------------------------------------------
5412    callback for the funcmode bbox
5413 -----------------------------------------------------------------*/
5414 
AFNI_funcmode_CB(Widget w,XtPointer cd,XtPointer cb)5415 void AFNI_funcmode_CB( Widget w, XtPointer cd, XtPointer cb )
5416 {
5417    Three_D_View *im3d = (Three_D_View *) cd ;
5418    int old_val , new_val ;
5419    THD_fvec3 fv ;
5420    THD_ivec3 iv ;
5421 
5422 ENTRY("AFNI_funcmode_CB") ;
5423 
5424    if( ! IM3D_OPEN(im3d) ) EXRETURN ;
5425 
5426    im3d->vinfo->stats_anat_ok =
5427     im3d->vinfo->stats_func_ok =
5428      im3d->vinfo->arang_func_ok =
5429       im3d->vinfo->stats_thresh_ok = 0 ; /* 24 May 2019 */
5430 
5431    old_val = 1 << im3d->vinfo->force_func_wod ;
5432    new_val = MCW_val_bbox( im3d->vwid->dmode->funcmode_bbox ) ;
5433 
5434 if(PRINT_TRACING){
5435  char str[256] ; sprintf(str,"old_val=%d new_val=%d",old_val,new_val) ;
5436  STATUS(str) ; }
5437 
5438    if( new_val != old_val ){
5439      im3d->vinfo->force_func_wod = (new_val != DMODE_BRICK_BVAL) ;
5440      SHOW_AFNI_PAUSE ;
5441      im3d->vinfo->tempflag = 1 ;           /* 15 Mar 2000 */
5442      AFNI_modify_viewing( im3d , True ) ;  /* redisplay */
5443      SHOW_AFNI_READY ;
5444    }
5445 
5446    RESET_AFNI_QUIT(im3d) ;
5447    EXRETURN ;
5448 }
5449 
5450 /*----------------------------------------------------------------
5451    Used to force redisplay when some datamode parameters have
5452    been altered
5453 ------------------------------------------------------------------*/
5454 
AFNI_modify_viewing(Three_D_View * im3d,RwcBoolean rescaled)5455 void AFNI_modify_viewing( Three_D_View *im3d , RwcBoolean rescaled )
5456 {
5457    THD_fvec3 fv ;
5458    THD_ivec3 iv ;
5459 
5460 ENTRY("AFNI_modify_viewing") ;
5461 
5462    if( ! IM3D_OPEN(im3d) ) EXRETURN ;
5463 
5464    im3d->vinfo->stats_anat_ok =
5465     im3d->vinfo->stats_func_ok =
5466      im3d->vinfo->arang_func_ok =
5467       im3d->vinfo->stats_thresh_ok = 0 ; /* 24 May 2019 */
5468 
5469    /* set up datasets for new imaging */
5470 
5471    AFNI_setup_viewing( im3d , rescaled ) ;
5472 
5473    /* transform current POV to new indices */
5474 
5475    if( im3d->type == AFNI_3DDATA_VIEW ){            /* 19 Oct 1999 */
5476 
5477       LOAD_ANAT_VIEW(im3d) ;  /* 02 Nov 1996 */
5478       fv = THD_dicomm_to_3dmm(
5479              im3d->anat_now ,
5480              TEMP_FVEC3(im3d->vinfo->xi, im3d->vinfo->yj, im3d->vinfo->zk) ) ;
5481       iv = THD_3dmm_to_3dind( im3d->anat_now , fv ) ;
5482 
5483    } else {
5484 
5485       iv = TEMP_IVEC3( im3d->vinfo->i1 , im3d->vinfo->j2 , im3d->vinfo->k3 ) ;
5486    }
5487 
5488    /* and redisplay the images */
5489 
5490    DISABLE_LOCK ;
5491    AFNI_set_viewpoint( im3d, iv.ijk[0],iv.ijk[1],iv.ijk[2] , REDISPLAY_ALL ) ;
5492    ENABLE_LOCK ;
5493 
5494    SAVE_VPT(im3d) ;
5495    FIX_SCALE_SIZE(im3d) ;
5496    EXRETURN ;
5497 }
5498 
5499 /*--------------------------------------------------------------------
5500   23 Nov 1996: Setup to write out many datasets
5501 ----------------------------------------------------------------------*/
5502 
AFNI_write_many_dataset_CB(Widget w,XtPointer cd,XtPointer cb)5503 void AFNI_write_many_dataset_CB( Widget w, XtPointer cd, XtPointer cb )
5504 {
5505    Three_D_View *im3d = (Three_D_View *) cd ;
5506    static MCW_idcode * idclist  = NULL ;
5507    static char       **strlist  = NULL ;
5508    static int          num_dset = -1 ;
5509 
5510    int iss , id , vv , llen , ltop ;
5511    THD_session *ss ;
5512    THD_3dim_dataset *dset ;
5513    char nam[THD_MAX_NAME+16] , *tnam , qnam[THD_MAX_NAME+16] ;
5514 
5515 ENTRY("AFNI_write_many_dataset_CB") ;
5516 
5517    if( ! IM3D_OPEN(im3d) ) EXRETURN ;
5518    if( GLOBAL_library.have_dummy_dataset ){ EXRETURN ; }
5519 
5520    if( num_dset > 0 && strlist != NULL )
5521       for( id=0 ; id < num_dset ; id++ ) myXtFree(strlist[id]) ;
5522    myXtFree(idclist) ; myXtFree(strlist) ;
5523 
5524    vv = im3d->vinfo->view_type ;  /* select view type */
5525 
5526    /** scan once to find longest string name **/
5527 
5528    ltop = 4 ;
5529    for( iss=0 ; iss < GLOBAL_library.sslist->num_sess ; iss++ ){
5530       ss = GLOBAL_library.sslist->ssar[iss] ;
5531       if( ss->is_collection ) continue ;
5532 
5533       for( id=0 ; id < ss->num_dsset ; id++ ){
5534          dset = GET_SESSION_DSET(ss, id, vv);
5535 /*         dset = ss->dsset_xform_table[id][vv] ;*/
5536          if( DSET_WRITEABLE(dset) ){
5537             strcpy( nam , dset->dblk->diskptr->directory_name ) ;
5538             strcat( nam , dset->dblk->diskptr->filecode ) ;
5539             tnam = THD_trailname(nam,SESSTRAIL+1) ;
5540             llen = strlen(tnam) ; ltop = MAX(ltop,llen) ;
5541          }
5542       }
5543    }
5544    ltop = MIN(ltop,THD_MAX_NAME) ; /* 06 Aug 2002 */
5545 
5546    num_dset = 0 ;
5547    for( iss=0 ; iss < GLOBAL_library.sslist->num_sess ; iss++ ){
5548       ss = GLOBAL_library.sslist->ssar[iss] ;
5549       if( ss->is_collection ) continue ;
5550 
5551       /* check anat datasets */
5552 
5553       for( id=0 ; id < ss->num_dsset ; id++ ){
5554          dset = GET_SESSION_DSET(ss, id, vv);
5555 /*         dset = ss->dsset_xform_table[id][vv] ;*/
5556          if( DSET_WRITEABLE(dset) ){
5557             num_dset++ ;
5558             idclist = (MCW_idcode *) XtRealloc( (char *) idclist ,
5559                                                 sizeof(MCW_idcode) * num_dset ) ;
5560             strlist = (char **)      XtRealloc( (char *) strlist ,
5561                                                 sizeof(char *)     * num_dset ) ;
5562 
5563             strcpy( nam , dset->dblk->diskptr->directory_name ) ;
5564             strcat( nam , dset->dblk->diskptr->filecode ) ;
5565             tnam = THD_trailname(nam,SESSTRAIL+1) ;
5566 
5567             if( ISANAT(dset) ){
5568               if( ISANATBUCKET(dset) )         /* 30 Nov 1997 */
5569                  sprintf(qnam,"%-*s [%s:%d]" ,
5570                          ltop,tnam , ANAT_prefixstr[dset->func_type] , DSET_NVALS(dset) ) ;
5571 
5572               else if( DSET_NUM_TIMES(dset) == 1 )
5573                  sprintf(qnam,"%-*s [%s]" ,
5574                          ltop,tnam ,ANAT_prefixstr[dset->func_type] ) ;
5575 
5576               else
5577                  sprintf(qnam,"%-*s [%s:3D+t]" ,
5578                          ltop,tnam , ANAT_prefixstr[dset->func_type] ) ;
5579 
5580             } else if( ISFUNC(dset) ){
5581               if( ISFUNCBUCKET(dset) )             /* 30 Nov 1997 */
5582                  sprintf(qnam,"%-*s [%s:%d]" ,
5583                          ltop,tnam , FUNC_prefixstr[dset->func_type] , DSET_NVALS(dset) ) ;
5584 
5585               else if( DSET_NUM_TIMES(dset) == 1 )
5586                  sprintf(qnam,"%-*s [%s]" ,
5587                          ltop,tnam , FUNC_prefixstr[dset->func_type] ) ;
5588 
5589               else
5590                  sprintf(qnam,"%-*s [%s:3D+t]" ,
5591                          ltop,tnam , FUNC_prefixstr[dset->func_type] ) ;
5592             }
5593 
5594             strlist[num_dset-1] = XtNewString(qnam) ;
5595             idclist[num_dset-1] = dset->idcode ;
5596          }
5597       } /* end of loop over datasets */
5598 
5599    } /* end of loop over sessions */
5600 
5601    if( num_dset <= 0 ){
5602       (void) MCW_popup_message( w ,
5603                  "*******************************\n"
5604                  "** No datasets are available **\n"
5605                  "** to write out to disk.     **\n"
5606                  "*******************************"  ,
5607               MCW_USER_KILL | MCW_TIMER_KILL ) ;
5608       BEEPIT ; EXRETURN ;
5609    }
5610 
5611 #if 1
5612    MCW_choose_multi_strlist( w , "Datasets to Write" , mcwCT_multi_mode ,
5613                              num_dset , NULL , strlist ,
5614                              AFNI_do_many_writes , (XtPointer) idclist ) ;
5615 #else
5616    { THD_string_array *sar ;  /*** This code is for experiments only! ***/
5617      INIT_SARR(sar) ;
5618      for( id=0 ; id < num_dset ; id++ ) ADDTO_SARR(sar,strlist[id]) ;
5619 
5620      MCW_choose_multi_editable_strlist( w , "Datasets to Write" , mcwCT_multi_mode ,
5621                                         sar , NULL ,
5622                                         AFNI_do_many_writes , (XtPointer) idclist ) ;
5623    }
5624 #endif
5625 
5626    XtVaSetValues( w , XmNuserData , (XtPointer) im3d , NULL ) ;
5627 
5628    EXRETURN ;
5629 }
5630 
5631 /*--------------------------------------------------------------------*/
5632 
AFNI_do_many_writes(Widget wpar,XtPointer cd,MCW_choose_cbs * cbs)5633 void AFNI_do_many_writes( Widget wpar , XtPointer cd , MCW_choose_cbs *cbs )
5634 {
5635    MCW_idcode *idclist = (MCW_idcode *) cd ;
5636    Three_D_View *im3d = NULL , *qq3d ;
5637    THD_3dim_dataset *dset ;
5638    THD_dataxes      new_daxes ;
5639    int ib , resam_mode ;
5640    RwcBoolean good ;
5641    Widget wmsg ;
5642    int cc , ccanat[MAX_CONTROLLERS] , ccfunc[MAX_CONTROLLERS] ;
5643 
5644 ENTRY("AFNI_do_many_writes") ;
5645 
5646    XtVaGetValues( wpar , XmNuserData , &im3d , NULL ) ;
5647    if( ! IM3D_OPEN(im3d) ) EXRETURN ;
5648 
5649    SHOW_AFNI_PAUSE ;
5650 
5651    /** mark all controllers as untouched **/
5652 
5653    for( cc=0 ; cc < MAX_CONTROLLERS ; cc++ ) ccanat[cc] = ccfunc[cc] = 0 ;
5654 
5655    wmsg = MCW_popup_message( wpar ,
5656             "*******************************\n"
5657             "** Please wait for dataset   **\n"
5658             "** computations and disk I/O **\n"
5659             "*******************************" , MCW_CALLER_KILL ) ;
5660    AFNI_speak("Writing",0) ;
5661 
5662    /** loop through selected datasets and do the dirty work **/
5663 
5664    for( ib=0 ; ib < cbs->nilist ; ib++ ){
5665       dset = PLUTO_find_dset( idclist + cbs->ilist[ib] ) ;
5666       if( DSET_WRITEABLE(dset) ){
5667 
5668          fprintf(stderr,"-- writing dataset %s%s (%d of %d)\n" ,
5669                         dset->dblk->diskptr->directory_name ,
5670                         dset->dblk->diskptr->filecode ,
5671                         ib+1 , cbs->nilist ) ;
5672 
5673          new_daxes.type = DATAXES_TYPE ;
5674 
5675 #ifdef USE_WRITEOWNSIZE
5676          if( im3d->vinfo->writeownsize )
5677             THD_edit_dataxes( im3d->vinfo->resam_vox , dset->daxes , &new_daxes ) ;
5678          else
5679 #endif
5680             THD_edit_dataxes( im3d->vinfo->resam_vox ,
5681                               CURRENT_DAXES(im3d->anat_now) , &new_daxes ) ;
5682 
5683          resam_mode = (ISFUNC(dset)) ? im3d->vinfo->func_resam_mode
5684                                      : im3d->vinfo->anat_resam_mode ;
5685 
5686          good = AFNI_refashion_dataset( im3d , dset , &new_daxes , resam_mode ) ;
5687 
5688          /** if the output failed, put a message to the screen **/
5689 
5690          if( ! good ){  /* bad news! */
5691             char str[THD_MAX_NAME+128] ;
5692             sprintf( str , "**\n"      "** Attempt to write dataset\n"
5693                            "** %s%s\n" "** failed for unknown reasons!\n**" ,
5694                      dset->dblk->diskptr->directory_name ,
5695                      dset->dblk->diskptr->filecode ) ;
5696             (void) MCW_popup_message( wpar , str , MCW_USER_KILL | MCW_TIMER_KILL ) ;
5697 
5698             fprintf(stderr,"   [output of %s%s failed!]\n",
5699                            dset->dblk->diskptr->directory_name ,
5700                            dset->dblk->diskptr->filecode ) ;
5701 
5702           /** otherwise, check if the dataset just done is
5703               the active anatomy or function in any open controller window **/
5704 
5705          } else {
5706             for( cc=0 ; cc < MAX_CONTROLLERS ; cc++ ){
5707                qq3d = GLOBAL_library.controllers[cc] ;
5708                if( ! IM3D_OPEN(qq3d) ) continue ;
5709                if( dset == qq3d->anat_now ) ccanat[cc] = 1 ;  /* flag their  */
5710                if( dset == qq3d->fim_now  ) ccfunc[cc] = 1 ;  /* controllers */
5711             }
5712          }
5713       }
5714    }
5715 
5716    /** for any controllers whose active datasets were written out,
5717        we need to set the "See Brick" buttons to be sensitive.     **/
5718 
5719    for( cc=0 ; cc < MAX_CONTROLLERS ; cc++ ){
5720       qq3d = GLOBAL_library.controllers[cc] ;
5721       if( ! IM3D_OPEN(qq3d) ) continue ;
5722 
5723       if( ccfunc[cc] ){
5724 STATUS("resetting 'use func brick' button") ;
5725          XtSetSensitive( qq3d->vwid->dmode->funcmode_bbox->wbut[DMODE_BRICK] , True ) ;
5726          AFNI_reset_func_range( qq3d ) ;
5727          AFNI_set_viewpoint( qq3d , -1,-1,-1 , REDISPLAY_OVERLAY ) ;
5728       }
5729 
5730       if( ccanat[cc] ){
5731 STATUS("resetting 'use anat brick' button") ;
5732          XtSetSensitive( qq3d->vwid->dmode->anatmode_bbox->wbut[DMODE_BRICK] , True ) ;
5733       }
5734    }
5735 
5736    XtDestroyWidget( wmsg ) ;
5737    SHOW_AFNI_READY ;
5738    EXRETURN ;
5739 }
5740 
5741 /*--------------------------------------------------------------------------*/
5742 
5743 static THD_3dim_dataset *saveas_iset = NULL ;
5744 
AFNI_saveas_dataset_CB(Widget w,XtPointer cd,XtPointer cb)5745 void AFNI_saveas_dataset_CB( Widget w, XtPointer cd, XtPointer cb )
5746 {
5747    Three_D_View *im3d = (Three_D_View *) cd ;
5748    char *label ;
5749 
5750 ENTRY("AFNI_saveas_dataset_CB") ;
5751 
5752    saveas_iset = NULL ;
5753 
5754    if( ! IM3D_OPEN(im3d) || w == NULL ||
5755        ! XtIsWidget(w)   || ! XtIsRealized(w) ) EXRETURN ;
5756    if( GLOBAL_library.have_dummy_dataset ){ EXRETURN ; }
5757 
5758    if( w == im3d->vwid->dmode->saveas_anat_pb ){
5759      saveas_iset = im3d->anat_now ; label = "Underlay Prefix" ;
5760    } else if( w == im3d->vwid->dmode->saveas_func_pb ){
5761      saveas_iset = im3d->fim_now  ; label = "Overlay Prefix" ;
5762    } else {
5763      BEEPIT ; WARNING_message("SaveAs code improperly executed") ; EXRETURN ;
5764    }
5765 
5766    MCW_choose_string( w, label, NULL, AFNI_saveas_finalize_CB, NULL ) ;
5767 
5768    EXRETURN ;
5769 }
5770 
5771 /*--------------------------------------------------------------------------*/
5772 
AFNI_saveas_finalize_CB(Widget w,XtPointer cd,MCW_choose_cbs * cbs)5773 void AFNI_saveas_finalize_CB( Widget w , XtPointer cd , MCW_choose_cbs *cbs )
5774 {
5775    char *prefix ;
5776    THD_3dim_dataset *oset ;
5777 
5778 ENTRY("AFNI_saveas_finalize_CB") ;
5779 
5780    if( cbs->reason != mcwCR_string || saveas_iset == NULL ){
5781      BEEPIT; WARNING_message("SaveAs code improperly invoked"); EXRETURN;
5782    }
5783 
5784    prefix = cbs->cval ;
5785    if( !THD_filename_ok(prefix) ){
5786      BEEPIT; WARNING_message("SaveAs code improperly invoked"); EXRETURN;
5787    }
5788 
5789    DSET_load(saveas_iset) ;
5790    if( !DSET_LOADED(saveas_iset) ){
5791      BEEPIT; WARNING_message("SaveAs code improperly invoked"); EXRETURN;
5792    }
5793 
5794    MCW_invert_widget(w) ;
5795    oset = EDIT_full_copy( saveas_iset , prefix ) ;
5796    MCW_flash_widget(1,w) ;
5797    THD_force_ok_overwrite(1) ;
5798    DSET_write(oset) ;
5799    MCW_flash_widget(1,w) ;
5800    THD_force_ok_overwrite(0) ;
5801    WROTE_DSET(oset) ; DSET_delete(oset) ;
5802 
5803    saveas_iset = NULL ; POPDOWN_string_chooser ; MCW_invert_widget(w) ;
5804    EXRETURN ;
5805 }
5806 
5807 /*---------------------------------------------------------------------------*/
5808 
AFNI_writeout_dataset(THD_3dim_dataset * dset,char * prefix)5809 void AFNI_writeout_dataset( THD_3dim_dataset *dset , char *prefix )
5810 {
5811    THD_3dim_dataset *oset ;
5812 
5813 ENTRY("AFNI_writeout_dataset") ;
5814 
5815    if( !ISVALID_DSET(dset) || !THD_filename_ok(prefix) ) EXRETURN ;
5816    DSET_load(dset) ;            if( !DSET_LOADED(dset) ) EXRETURN ;
5817 
5818    oset = EDIT_full_copy( dset , prefix ) ;
5819    THD_force_ok_overwrite(1) ;
5820    DSET_write(oset) ;
5821    THD_force_ok_overwrite(0) ;
5822    WROTE_DSET(oset) ; DSET_delete(oset) ;
5823 
5824    EXRETURN ;
5825 }
5826 
5827 /*-----------------------------------------------------------------
5828     Obey the command to write out the current dataset
5829 -------------------------------------------------------------------*/
5830 
AFNI_write_dataset_CB(Widget w,XtPointer cd,XtPointer cb)5831 void AFNI_write_dataset_CB( Widget w, XtPointer cd, XtPointer cb )
5832 {
5833    Three_D_View *im3d = (Three_D_View *) cd ;
5834    THD_3dim_dataset *dset = NULL ;
5835    THD_dataxes        new_daxes ;
5836    Widget wmsg ;
5837    int resam_mode = 0;
5838    RwcBoolean good , destroy ;
5839 
5840 ENTRY("AFNI_write_dataset_CB") ;
5841 
5842    if( ! IM3D_VALID(im3d) || w == NULL ||
5843        ! XtIsWidget(w)    || ! XtIsRealized(w) ) EXRETURN ;
5844    if( GLOBAL_library.have_dummy_dataset ){ EXRETURN ; }
5845 
5846    if( w == im3d->vwid->dmode->write_anat_pb ){         /* write anatomy */
5847       dset       = im3d->anat_now ;
5848       resam_mode = im3d->vinfo->anat_resam_mode ;
5849 
5850    } else if( w == im3d->vwid->dmode->write_func_pb ){  /* write function */
5851       dset       = im3d->fim_now ;
5852       resam_mode = im3d->vinfo->func_resam_mode ;
5853    }
5854 
5855    if( ISVALID_DSET(dset) && dset->dblk->diskptr->allow_directwrite == 1 ){
5856      INFO_message("Direct write of dataset '%s'",DSET_BRIKNAME(dset)) ;
5857      if (!AFNI_yesenv("AFNI_GUI_WRITE_AS_DECONFLICT")) { /* ZSS April 11 2010 */
5858         DSET_overwrite(dset) ;
5859      } else {
5860         char pfx[THD_MAX_PREFIX] ; /* to hold old one */
5861         MCW_strncpy( pfx , DSET_PREFIX(dset) , THD_MAX_PREFIX ) ;
5862         DSET_write(dset);
5863         /* Now put old prefix back in case there was deconflicting */
5864         EDIT_dset_items( dset , ADN_prefix , pfx , ADN_none ) ;
5865      }
5866 
5867      EXRETURN ;
5868    }
5869 
5870    good = ISVALID_3DIM_DATASET(dset)     &&     /* check for bad data */
5871           resam_mode >= FIRST_RESAM_TYPE &&
5872           resam_mode <= LAST_RESAM_TYPE  &&
5873           im3d->vinfo->resam_vox > 0.0   &&
5874          !DSET_IS_MINC(dset)             &&      /* 29 Oct 2001 */
5875          !DSET_IS_ANALYZE(dset)          &&      /* 27 Aug 2002 */
5876          !DSET_IS_CTFSAM(dset)           &&
5877          !DSET_IS_CTFMRI(dset)           &&
5878          !DSET_IS_1D(dset)               &&
5879          !DSET_IS_NIFTI(dset)                   /* 28 Aug 2003 */
5880        ;
5881 
5882    destroy = !DSET_WRITEABLE(dset) ;      /* check for destruction */
5883 
5884    if( good && destroy ){
5885       if( GLOBAL_argopt.destruct ){
5886          (void) MCW_popup_message( w ,
5887                                    "******************************\n"
5888                                    "** Potentially destructive  **\n"
5889                                    "** dataset write initiated! **\n"
5890                                    "******************************"  ,
5891                                   MCW_USER_KILL | MCW_TIMER_KILL ) ;
5892       } else {
5893          good = False ;  /* destruction not OK */
5894       }
5895    }
5896 
5897    if( !good ){
5898 
5899        (void) MCW_popup_message( w ,
5900                  "****************************************************\n"
5901                  "** Cannot write dataset for one of these reasons: **\n"
5902                  "**   -- It isn't allowed to write data in the     **\n"
5903                  "**        Original View.                          **\n"
5904                  "**   -- It isn't allowed to overwrite data that   **\n"
5905                  "**        is not warped from some other dataset.  **\n"
5906                  "**   -- An internal program error has occured!    **\n"
5907                  "****************************************************"  ,
5908               MCW_USER_KILL | MCW_TIMER_KILL ) ;
5909 
5910        BEEPIT ; EXRETURN;
5911    }
5912 
5913    SHOW_AFNI_PAUSE ;
5914 
5915    wmsg = MCW_popup_message( w ,
5916             "*******************************\n"
5917             "** Please wait for dataset   **\n"
5918             "** computations and disk I/O **\n"
5919             "*******************************" , MCW_CALLER_KILL ) ;
5920 
5921    XtSetSensitive( im3d->vwid->top_shell , False ) ;
5922    XmUpdateDisplay( im3d->vwid->top_shell ) ;
5923 
5924    LOAD_DSET_VIEWS(im3d) ;  /* 02 Nov 1996 */
5925 
5926    new_daxes.type = DATAXES_TYPE ;
5927 
5928 #ifdef USE_WRITEOWNSIZE
5929    if( im3d->vinfo->writeownsize )
5930       THD_edit_dataxes( im3d->vinfo->resam_vox , dset->daxes , &new_daxes ) ;
5931    else
5932 #endif
5933       new_daxes = *CURRENT_DAXES(im3d->anat_now) ;
5934 
5935    good = AFNI_refashion_dataset( im3d , dset , &new_daxes , resam_mode ) ;
5936 
5937 if(PRINT_TRACING){
5938 if( good ){
5939    STATUS("successful refashioning") ;
5940 } else {
5941    STATUS("failed refashioning") ;
5942 }}
5943 
5944    if( good && ISFUNC(dset) ){
5945       AFNI_reset_func_range( im3d ) ;
5946       AFNI_set_viewpoint( im3d , -1,-1,-1 , REDISPLAY_OVERLAY ) ;  /* redraw */
5947    }
5948 
5949    XtSetSensitive( im3d->vwid->top_shell , True ) ;
5950 
5951    XtDestroyWidget( wmsg ) ;
5952    SHOW_AFNI_READY ;
5953 
5954    /* allow the "use data brick" button, if we just wrote the anat out */
5955 
5956    if( good && w == im3d->vwid->dmode->write_anat_pb ){
5957 STATUS("resetting 'use anat brick' button") ;
5958       XtSetSensitive( im3d->vwid->dmode->anatmode_bbox->wbut[DMODE_BRICK] , True ) ;
5959    }
5960 
5961    if( good && w == im3d->vwid->dmode->write_func_pb ){
5962 STATUS("resetting 'use func brick' button") ;
5963       XtSetSensitive( im3d->vwid->dmode->funcmode_bbox->wbut[DMODE_BRICK] , True ) ;
5964    }
5965 
5966    if( ! good ){  /* bad news! */
5967 
5968       BEEPIT ;
5969       (void) MCW_popup_message( w ,
5970                 "***************************************\n"
5971                 "** Attempt to write dataset failed   **\n"
5972                 "** for unknown reasons! Check files! **\n"
5973                 "***************************************"  ,
5974              MCW_USER_KILL ) ;
5975 
5976       dset->wod_flag = True ;
5977    }
5978 
5979    EXRETURN ;
5980 }
5981 
5982 /*------------------------------------------------------------------
5983    (re)compute and (re)write a dataset to disk, with the indicated
5984    geometric parameters.  Note that the filenames for the save should
5985    already be initialized in the dset->dblk->diskptr.  Also, note
5986    that the dataset's "permanent" dataxes will be remade to fit the
5987    new geometry.
5988 --------------------------------------------------------------------*/
5989 
5990 #define PICTURIZE(px) \
5991     ( XtVaSetValues( im3d->vwid->picture, XmNlabelInsensitivePixmap,px, NULL ) , \
5992       MCW_expose_widget( im3d->vwid->picture ) )
5993 
5994 #define UNPICTURIZE PICTURIZE(XmUNSPECIFIED_PIXMAP)
5995 
5996 /** 09 Dec 1997: resam_mode is now ignored **/
5997 
AFNI_refashion_dataset(Three_D_View * im3d,THD_3dim_dataset * dset,THD_dataxes * daxes,int resam_mode)5998 RwcBoolean AFNI_refashion_dataset( Three_D_View *im3d ,
5999                                 THD_3dim_dataset *dset ,
6000                                 THD_dataxes *daxes , int resam_mode )
6001 {
6002    THD_datablock *dblk  = dset->dblk ;
6003    THD_diskptr   *dkptr = dset->dblk->diskptr ;
6004    RwcBoolean good ;
6005    int npix , nx,ny,nz,nv , kk , ival , code , nzv , dsiz , isfunc , cmode ;
6006    MRI_IMAGE *im ;
6007    void *imar ;
6008    FILE *far ;
6009    float brfac_save ;
6010    int native_order , save_order ;  /* 23 Nov 1999 */
6011 
6012    RwcBoolean picturize ;
6013    Pixmap brain_pixmap=XmUNSPECIFIED_PIXMAP ;
6014 
6015 #ifndef DONT_USE_METER
6016    Widget meter = NULL ;
6017    int meter_perc , meter_pold ;
6018 #endif
6019 
6020 ENTRY("AFNI_refashion_dataset") ;
6021 
6022    picturize = IM3D_OPEN(im3d) && im3d->vwid->picture != NULL &&
6023                afni48_pixmap != XmUNSPECIFIED_PIXMAP ;
6024 
6025    if( picturize ){
6026       switch( ORIENT_xyz[daxes->zzorient] ){
6027          case 'x': brain_pixmap = afni48sag_pixmap     ; break ;
6028          case 'y': brain_pixmap = afni48cor_pixmap     ; break ;
6029          case 'z': brain_pixmap = afni48axi_pixmap     ; break ;
6030       }
6031    }
6032 
6033 #ifndef DONT_USE_METER
6034    meter = MCW_popup_meter( im3d->vwid->top_shell , METER_TOP_WIDE ) ;
6035    meter_pold = 0 ;
6036 #endif
6037 
6038    /* set up for warp-on-demand */
6039 
6040    dset->wod_daxes         = myXtNew(THD_dataxes) ; /* 02 Nov 1996 */
6041    dset->wod_daxes->type   = DATAXES_TYPE ;       /* 02 Nov 1996 */
6042    dset->vox_warp          = myXtNew(THD_warp) ;    /* 02 Nov 1996 */
6043    dset->self_warp         = NULL ;              /* 26 Aug 2002 */
6044 
6045    *(dset->wod_daxes)      = *daxes ;            /* copy insides of daxes */
6046    dset->wod_flag          = True ;              /* mark for warp-on-demand */
6047    dset->vox_warp->type    = ILLEGAL_TYPE ;      /* mark for recomputation */
6048 
6049    /* copy the new geometric information into various places */
6050 
6051    *(dset->daxes)     = *(daxes) ;               /* Make daxes permanent */
6052    dkptr->dimsizes[0] = dset->daxes->nxx ;       /* Will cause trouble */
6053    dkptr->dimsizes[1] = dset->daxes->nyy ;       /* if diskptr and     */
6054    dkptr->dimsizes[2] = dset->daxes->nzz ;       /* daxes don't match! */
6055 
6056    /* write the header out */
6057 
6058    THD_force_ok_overwrite(1);
6059    good = THD_write_3dim_dataset( NULL,NULL , dset , False ) ;
6060    THD_force_ok_overwrite(0);
6061    if( !good ){
6062      fprintf(stderr,"\a\n*** cannot write dataset header ***\n") ;
6063      if( picturize ) UNPICTURIZE ;
6064      RETURN(False) ;
6065    }
6066    STATUS("wrote output header file") ;
6067 
6068    /* purge the datablock that now exists,
6069       then delete the file on disk that now exists (if any) */
6070 
6071    DSET_unlock( dset ) ; /* Feb 1998 */
6072    PURGE_DSET( dset ) ;
6073    COMPRESS_unlink(dkptr->brick_name) ;
6074 
6075    /* refashion its brick data structure,
6076       which requires first saving in a temporary
6077       array the datum type for each sub-brick    */
6078 
6079    { int ibr ; int *typ ;
6080      typ = (int *) XtMalloc( sizeof(int) * dblk->nvals ) ;
6081      for( ibr=0 ; ibr < dblk->nvals ; ibr++ )
6082         typ[ibr] = DBLK_BRICK_TYPE(dblk,ibr) ;
6083      THD_init_datablock_brick( dblk , dblk->nvals , typ ) ;
6084      myXtFree( typ ) ;
6085    }
6086 
6087    /*-- 13 Mar 2006: check for free disk space --*/
6088 
6089    { int mm = THD_freemegabytes(dkptr->header_name) ;
6090      int rr = (int)(dblk->total_bytes/(1024*1024)) ;
6091      if( rr >= 666 )
6092        fprintf(stderr,"++ WARNING: output filesize %s will be %d Mbytes!\n"
6093                       "++ SUGGEST: increase voxel size to save disk space.\n",
6094                dkptr->brick_name , rr ) ;
6095      if( mm >= 0 && mm <= rr )
6096        WARNING_message("Disk space: writing file %s (%d MB),"
6097                        " but only %d free MB on disk"        ,
6098                dkptr->brick_name , rr , mm ) ;
6099    }
6100 
6101    dkptr->storage_mode = STORAGE_UNDEFINED ;       /* just for now */
6102    dblk->malloc_type   = DATABLOCK_MEM_UNDEFINED ;
6103 
6104    /*--- open the output file
6105          (N.B.: much of the following code is from THD_write_datablock) ---*/
6106 
6107    /*-- create directory if necessary --*/
6108 
6109    if( ! THD_is_directory(dkptr->directory_name) ){
6110       kk = mkdir( dkptr->directory_name , THD_MKDIR_MODE ) ;
6111       if( kk != 0 ){
6112          fprintf(stderr,
6113               "\a\n*** cannot mkdir new directory: %s\n",dkptr->directory_name) ;
6114          if( picturize ) UNPICTURIZE ;
6115          RETURN(False) ;
6116       }
6117       STATUS("created subdirectory") ;
6118    }
6119 
6120    /*-- open output file --*/
6121 
6122    cmode = THD_get_write_compression() ;
6123    far = COMPRESS_fopen_write( dkptr->brick_name , cmode ) ;
6124    if( far == NULL ){
6125       fprintf(stderr,
6126         "\a\n*** cannot open output file %s\n",dkptr->brick_name) ;
6127       if( picturize ) UNPICTURIZE ;
6128       RETURN(False) ;
6129    }
6130    STATUS("created output brick file") ;
6131 
6132    /*--------- now, create each slice and write it out ----------*/
6133 
6134    nx = dset->daxes->nxx ;
6135    ny = dset->daxes->nyy ;  npix = nx*ny ;
6136    nz = dset->daxes->nzz ;
6137    nv = dkptr->nvals     ;  nzv  = nz*nv ;
6138 
6139    isfunc = ISFUNC(dset) ;  /* 09 Dec 1997 */
6140    if( ! isfunc )
6141       resam_mode = im3d->vinfo->anat_resam_mode ;
6142 
6143    native_order = mri_short_order() ;                           /* 23 Nov 1999 */
6144    save_order   = (dkptr->byte_order > 0) ? dkptr->byte_order
6145                                           : THD_get_write_order() ;
6146 
6147    for( ival=0 ; ival < nv ; ival++ ){  /* for each sub-brick */
6148 
6149       dsiz = mri_datum_size( DSET_BRICK_TYPE(dset,ival) ) ;
6150 
6151       /** force return of unscaled slices for output **/
6152 
6153       brfac_save                   = DBLK_BRICK_FACTOR(dblk,ival) ;
6154       DBLK_BRICK_FACTOR(dblk,ival) = 0.0 ;
6155 
6156       if( isfunc )
6157          resam_mode = (DSET_BRICK_STATCODE(dset,ival) > 0)  /* 09 Dec 1997 */
6158                       ? im3d->vinfo->thr_resam_mode
6159                       : im3d->vinfo->func_resam_mode ;
6160 
6161       for( kk=0 ; kk < nz ; kk++ ){  /* for each slice */
6162 
6163          im = AFNI_dataset_slice( dset , 3 , kk , ival , resam_mode ) ;
6164 STATUS("have new image") ;
6165 
6166          if( im == NULL ){
6167             fprintf(stderr,"\a\n*** failure to compute dataset slice %d\n",kk) ;
6168             COMPRESS_fclose(far) ;
6169             COMPRESS_unlink( dkptr->brick_name ) ;
6170             if( picturize ) UNPICTURIZE ;
6171 #ifndef DONT_USE_METER
6172             MCW_popdown_meter(meter) ;
6173 #endif
6174             RETURN(False) ;
6175          }
6176 
6177 #ifdef AFNI_DEBUG
6178 { char str[256] ;
6179   sprintf(str,"writing slice %d: type=%s nx=%d ny=%d\n",
6180           kk,MRI_TYPE_NAME(im) , im->nx,im->ny ) ;
6181   STATUS(str) ; }
6182 #endif
6183 
6184          imar = mri_data_pointer(im) ;
6185          if( save_order != native_order ){                   /* 23 Nov 1999 */
6186             switch( im->kind ){
6187                default:                                   break ;
6188                case MRI_short:   mri_swap2(  npix,imar) ; break ;
6189                case MRI_float:
6190                case MRI_int:     mri_swap4(  npix,imar) ; break ;
6191                case MRI_complex: mri_swap4(2*npix,imar) ; break ;
6192             }
6193          }
6194          code = fwrite( imar , dsiz , npix , far ) ;
6195          mri_free(im) ;
6196 
6197          if( code != npix ){
6198             fprintf(stderr,
6199               "\a\n*** failure to write dataset slice %d (is disk full?)\n",kk) ;
6200             COMPRESS_fclose(far) ;
6201             COMPRESS_unlink( dkptr->brick_name ) ;
6202             if( picturize ) UNPICTURIZE ;
6203 #ifndef DONT_USE_METER
6204             MCW_popdown_meter(meter) ;
6205 #endif
6206             RETURN(False) ;
6207          }
6208 
6209          if( picturize && kk%7 == 0 ){
6210             Pixmap pp ;
6211             pp = (kk%2 == 0) ? brain_pixmap : afni48_pixmap ;
6212             PICTURIZE(pp) ;
6213             XmUpdateDisplay( im3d->vwid->picture ) ;
6214          }
6215 
6216 #ifndef DONT_USE_METER
6217          meter_perc = (int) ( 100.0 * (kk+ival*nz) / nzv ) ;
6218          if( meter_perc != meter_pold ){
6219             MCW_set_meter( meter , meter_perc ) ;
6220             meter_pold = meter_perc ;
6221          }
6222 #endif
6223 
6224       } /* end of loop over kk (z-direction) */
6225 
6226       /* restore the correct scaling of this sub-brick */
6227 
6228       DBLK_BRICK_FACTOR(dblk,ival) = brfac_save ;
6229 
6230    } /* end of loop over iv (nvals direction) */
6231    STATUS("all slices written") ;
6232 
6233    /*--------------------- done!!! ---------------------*/
6234 
6235    COMPRESS_fclose(far) ;
6236    STATUS("output file closed") ;
6237 
6238    if( picturize ) PICTURIZE(logo_pixmap) ;
6239 #ifndef DONT_USE_METER
6240    MCW_set_meter( meter , 100 ) ;
6241 #endif
6242 
6243    /*--- do a little surgery on the dataset's storage flags ---*/
6244 
6245    dkptr->storage_mode = STORAGE_BY_BRICK ;
6246 #if MMAP_THRESHOLD > 0
6247    dblk->malloc_type   = (dblk->total_bytes > MMAP_THRESHOLD)
6248                          ? DATABLOCK_MEM_MMAP : DATABLOCK_MEM_MALLOC ;
6249 
6250    if( cmode >= 0 ) dblk->malloc_type = DATABLOCK_MEM_MALLOC ;
6251    DBLK_mmapfix(dblk) ;  /* 28 Mar 2005 */
6252 #else
6253    dblk->malloc_type   = DATABLOCK_MEM_MALLOC ;
6254 #endif
6255 
6256    /*--- recompute the statistics and rewrite the header to hold them ---*/
6257 
6258    STATUS("recomputing statistics") ;
6259 
6260    THD_load_statistics( dset ) ;
6261 
6262    STATUS("rewriting header") ;
6263 
6264    tross_Append_History( dset , "AFNI: resampled and rewritten" ) ;
6265    DSET_overwrite(dset) ;
6266 
6267    STATUS("purging datablock") ;
6268 
6269    PURGE_DSET( dset ) ;
6270 
6271    if( picturize ) UNPICTURIZE ;
6272 #ifndef DONT_USE_METER
6273    MCW_popdown_meter(meter) ;
6274 #endif
6275 
6276    myXtFree(dset->wod_daxes) ; myXtFree(dset->vox_warp) ;  /* 02 Nov 1996 */
6277 
6278    RETURN(True) ;
6279 }
6280 
6281 /*------------------------------------------------------------------
6282   This routine is part of the inverse of AFNI_make_descendants:
6283   it will mark for death the descendants of datasets that are about
6284   to be destroyed themselves (as noted by their "death_marks").
6285 
6286   Note that this routine is not set up for recursive massacres:
6287   that is, it doesn't try to find grandchildren that should also
6288   be killed.  That could be done by calling this routine more
6289   than once, until no changes occur.
6290 
6291   Note also that this routine does not actually destroy any datasets.
6292   That is done by AFNI_andersonville.
6293 
6294   31 Jan 1995: altered to avoid destruction of a dataset without
6295                a warp parent, since that dataset cannot be recreated.
6296   21 Dec 2001: modified to use DSET_MARK_FOR_DEATH(), which will
6297                not let a dataset marked for immortality be killed.
6298 --------------------------------------------------------------------*/
6299 
AFNI_mark_for_death(THD_sessionlist * ssl)6300 void AFNI_mark_for_death( THD_sessionlist *ssl )
6301 {
6302    int iss , jdd , kvv , num_marked=0 ;
6303    THD_session *ss ;
6304    THD_3dim_dataset *dset ;
6305 
6306 ENTRY("AFNI_mark_for_death") ;
6307 
6308    if( ! ISVALID_SESSIONLIST(ssl) ) EXRETURN ;
6309 
6310    /* loop over each session */
6311 
6312    for( iss=0 ; iss < ssl->num_sess ; iss++ ){
6313       ss = ssl->ssar[iss] ;
6314       if( !ISVALID_SESSION(ss) ) continue ;  /* no good ==> skip */
6315       if( ss->is_collection    ) continue ;
6316 
6317       /* loop over datasets in this session */
6318 
6319       for( jdd=0 ; jdd < ss->num_dsset ; jdd++ ){
6320          for( kvv=FIRST_VIEW_TYPE ; kvv <= LAST_VIEW_TYPE ; kvv++ ){
6321             dset = GET_SESSION_DSET(ss, jdd, kvv);
6322 /*            dset = ss->dsset_xform_table[jdd][kvv] ;*/
6323 
6324             if( ISVALID_3DIM_DATASET(dset) &&                /* good dset */
6325                 dset->anat_parent != NULL  &&                /* has parent */
6326                 dset->anat_parent->death_mark == DOOMED &&   /* parent dies */
6327                 dset->warp_parent != NULL                 ){ /* is a warp child */
6328 
6329                DSET_MARK_FOR_DEATH(dset) ;
6330                num_marked ++ ;
6331             }
6332          }
6333       }
6334    }  /* end of loop over sessions */
6335 
6336 #ifdef AFNI_DEBUG
6337 { char str[256] ;
6338   sprintf(str,"total # descendants marked = %d",num_marked) ;
6339   STATUS(str) ; }
6340 #endif
6341 
6342    EXRETURN ;
6343 }
6344 
6345 /*-------------------------------------------------------------------
6346   Mass death
6347 ---------------------------------------------------------------------*/
6348 
AFNI_andersonville(THD_sessionlist * ssl,RwcBoolean kill_files)6349 void AFNI_andersonville( THD_sessionlist *ssl , RwcBoolean kill_files )
6350 {
6351    int iss , jdd , kvv , num_killed=0 ;
6352    THD_session *ss ;
6353    THD_3dim_dataset *dset ;
6354    RwcBoolean kill_me ;
6355 
6356 ENTRY("AFNI_andersonville") ;
6357 
6358    if( ! ISVALID_SESSIONLIST(ssl) ) EXRETURN ;
6359 
6360    /* loop over each session */
6361 
6362    for( iss=0 ; iss < ssl->num_sess ; iss++ ){
6363       ss = ssl->ssar[iss] ;
6364       if( !ISVALID_SESSION(ss) ) continue ;  /* no good ==> skip */
6365       if( ss->is_collection    ) continue ;
6366 
6367       if( ss == GLOBAL_library.session ) continue ; /* 21 Dec 2001 */
6368 
6369       /* loop over datasets in this session */
6370 
6371       for( jdd=0 ; jdd < ss->num_dsset ; jdd++ ){
6372          for( kvv=FIRST_VIEW_TYPE ; kvv <= LAST_VIEW_TYPE ; kvv++ ){
6373               dset = GET_SESSION_DSET(ss, jdd, kvv);
6374 /*            dset = ss->dsset_xform_table[jdd][kvv] ;*/
6375 
6376             if( ISVALID_3DIM_DATASET(dset) &&    /* good dset */
6377                 dset->death_mark == DOOMED   ){  /* alas, poor Yorick */
6378 
6379                kill_me = (kvv == VIEW_ORIGINAL_TYPE) ? False : kill_files ;
6380                THD_delete_3dim_dataset( dset , kill_me ) ;
6381                myXtFree( dset ) ;
6382                SET_SESSION_DSET(NULL, ss, jdd, kvv);
6383 /*               ss->dsset_xform_table[jdd][kvv] = NULL ;*/
6384                num_killed ++ ;
6385             }
6386          }
6387       }
6388 
6389    }  /* end of loop over sessions */
6390 
6391 #ifdef AFNI_DEBUG
6392   { char str[256] ;
6393     sprintf(str,"total # datasets killed = %d",num_killed) ;
6394     STATUS(str) ; }
6395 #endif
6396 
6397    EXRETURN ;
6398 }
6399 
6400 /*--------------------------------------------------------------*/
6401 
AFNI_imseq_clearstat(Three_D_View * im3d)6402 void AFNI_imseq_clearstat( Three_D_View *im3d )
6403 {
6404 
6405 ENTRY("AFNI_imseq_clearstat") ;
6406 
6407    if( ! IM3D_OPEN(im3d) ) EXRETURN ;
6408 
6409    if( im3d->s123 != NULL )
6410       drive_MCW_imseq( im3d->s123 , isqDR_clearstat , NULL ) ;
6411 
6412    if( im3d->s231 != NULL )
6413       drive_MCW_imseq( im3d->s231 , isqDR_clearstat , NULL ) ;
6414 
6415    if( im3d->s312 != NULL )
6416       drive_MCW_imseq( im3d->s312 , isqDR_clearstat , NULL ) ;
6417 
6418    EXRETURN ;
6419 }
6420 
6421 /****************************************************************
6422   3/24/95: range controls in func panel for user management
6423            of the conversion of pbar values [-1..1] to
6424            thresholds for the coloring of functional data
6425 *****************************************************************/
6426 
6427 /*--------------------------------------------------------------
6428   create label for range display in function control panel
6429 ----------------------------------------------------------------*/
6430 
AFNI_range_label(Three_D_View * im3d)6431 XmString AFNI_range_label( Three_D_View *im3d )
6432 {
6433    char anat_minch[10] = " --------" , anat_maxch[10] = " --------" ,
6434         fim_minch[10]  = " --------" , fim_maxch[10]  = " --------" ,
6435         thr_minch[10]  = " --------" , thr_maxch[10]  = " --------"   ;
6436    char buf[256] , qbuf[20] ;
6437    XmString xstr ;
6438    int iv ;
6439 
6440 ENTRY("AFNI_range_label") ;
6441 
6442    if( im3d != NULL && im3d->vinfo != NULL ){  /* 30 Mar 2005 */
6443      im3d->vinfo->stats_anat_ok =
6444       im3d->vinfo->stats_func_ok =
6445        im3d->vinfo->arang_func_ok =
6446         im3d->vinfo->stats_thresh_ok = 0 ;
6447    }
6448 
6449    /*** anat statistics ***/
6450 
6451    if( IM3D_OPEN(im3d) ){
6452 STATUS("RELOAD_STATS(anat_now)") ;
6453      RELOAD_STATS(im3d->anat_now) ;
6454    }
6455 
6456    if( IM3D_OPEN(im3d) &&
6457        ISVALID_3DIM_DATASET(im3d->anat_now) &&
6458        ISVALID_STATISTIC(im3d->anat_now->stats) ){
6459 
6460      iv = im3d->vinfo->anat_index ;
6461 
6462      if( DSET_VALID_BSTAT(im3d->anat_now,iv) ){
6463 STATUS("anat_now statistics") ;
6464        AV_fval_to_char( im3d->anat_now->stats->bstat[iv].min , qbuf ) ;
6465        sprintf( anat_minch , "%9.9s" , qbuf ) ;
6466        AV_fval_to_char( im3d->anat_now->stats->bstat[iv].max , qbuf ) ;
6467        sprintf( anat_maxch , "%9.9s" , qbuf ) ;
6468        im3d->vinfo->stats_anat_ok = 1 ;
6469      } else {
6470 STATUS("can't load anat_now bstat") ;
6471      }
6472    }
6473 
6474    /*** func statistics ***/
6475 
6476    if( IM3D_OPEN(im3d) ){
6477 STATUS("RELOAD_STATS(fim_now)") ;
6478      RELOAD_STATS(im3d->fim_now) ;
6479    }
6480 
6481    if( IM3D_OPEN(im3d) &&
6482        ISVALID_3DIM_DATASET(im3d->fim_now) &&
6483        ISVALID_STATISTIC(im3d->fim_now->stats) ){
6484 
6485      iv = im3d->vinfo->fim_index ;
6486 
6487      if( DSET_VALID_BSTAT(im3d->fim_now,iv) ){
6488 STATUS("fim_now statistics") ;
6489        AV_fval_to_char( im3d->fim_now->stats->bstat[iv].min , qbuf ) ;
6490        sprintf( fim_minch , "%9.9s" , qbuf ) ;
6491        AV_fval_to_char( im3d->fim_now->stats->bstat[iv].max , qbuf ) ;
6492        sprintf( fim_maxch , "%9.9s" , qbuf ) ;
6493        im3d->vinfo->stats_func_ok = 1 ;
6494      } else {
6495 STATUS("can't load fim_now bstat") ;
6496      }
6497 
6498      iv = im3d->vinfo->thr_index ;
6499 
6500      if( DSET_VALID_BSTAT(im3d->fim_now,iv) ){
6501 STATUS("thr_now statistics") ;
6502       AV_fval_to_char( im3d->fim_now->stats->bstat[iv].min , qbuf ) ;
6503       sprintf( thr_minch , "%9.9s" , qbuf ) ;
6504       AV_fval_to_char( im3d->fim_now->stats->bstat[iv].max , qbuf ) ;
6505       sprintf( thr_maxch , "%9.9s" , qbuf ) ;
6506       im3d->vinfo->stats_thresh_ok = 1 ;
6507      } else {
6508 STATUS("can't load thr_now bstat") ;
6509      }
6510    }
6511 
6512    /*** make label ***/
6513 
6514 STATUS("make buf label") ;
6515 
6516    sprintf( buf , "ULay %s:%s\nOLay %s:%s\nThr  %s:%s" ,
6517             anat_minch,anat_maxch, fim_minch,fim_maxch, thr_minch,thr_maxch ) ;
6518 
6519 STATUS(buf) ;
6520 
6521    xstr = XmStringCreateLtoR( buf , XmFONTLIST_DEFAULT_TAG ) ;
6522 
6523    RETURN(xstr) ;
6524 }
6525 
6526 /*-----------------------------------------------------------
6527    find the autorange (default value) and make a label for
6528    the autorange control widget
6529 -------------------------------------------------------------*/
6530 
AFNI_autorange_label(Three_D_View * im3d)6531 XmString AFNI_autorange_label( Three_D_View *im3d )
6532 {
6533    XmString xstr ;
6534    float rrr ;
6535    char buf[32] , qbuf[20] ;
6536 
6537 ENTRY("AFNI_autorange_label") ;
6538 
6539 /* INFO_message("---------- AFNI_autorange_label") ; */
6540 
6541    if( ! ISVALID_3DIM_DATASET(im3d->fim_now) ){  /* no function */
6542      rrr = DEFAULT_FIM_SCALE ;
6543    } else {
6544      RELOAD_STATS(im3d->fim_now) ;
6545      if( ISVALID_STATISTIC(im3d->fim_now->stats) ){
6546        float s1 , s2 ; int iv ;
6547 
6548        iv = im3d->vinfo->fim_index ;
6549 
6550        if( DSET_VALID_BSTAT(im3d->fim_now,iv) ){
6551          s1  = fabsf(im3d->fim_now->stats->bstat[iv].min) ,
6552          s2  = fabsf(im3d->fim_now->stats->bstat[iv].max) ;
6553          rrr = (s1 < s2) ? s2 : s1 ;                    /* largest fim */
6554        } else {
6555          rrr = DEFAULT_FIM_SCALE ;                      /* don't have brick stats */
6556        }
6557      } else {
6558        rrr = DEFAULT_FIM_SCALE ;                        /* don't have brick stats */
6559      }
6560    }
6561 #if 0
6562    if( rrr > 1.0f && rrr < DEFAULT_FIM_SCALE ){
6563      float ppp = AFNI_numenv("AFNI_AUTORANGE_POWER") ;
6564      if( ppp > 0.0f && ppp < 1.0f ) rrr = powf(rrr,ppp) ;
6565    }
6566 #endif
6567 
6568 /* ININFO_message("  old style rrr = %g",rrr) ; */
6569 
6570    /* Get the autorange as a percentage point of the nonzero values */
6571 
6572    if( im3d->fim_now->int_cmap == CONT_CMAP && AUTORANGE_PERC > 1 && AUTORANGE_PERC < 100 ){
6573      MRI_IMAGE *qim=NULL ; float qval ;
6574      if( !DSET_LOADED(im3d->fim_now) && DSET_TOTALBYTES(im3d->fim_now) < 66666666 )
6575        DSET_load(im3d->fim_now) ;
6576      if( DSET_LOADED(im3d->fim_now) ){
6577        qim = THD_extract_float_brick(im3d->vinfo->fim_index,im3d->fim_now) ;
6578      } else if( im3d->fim_now->warp_parent != NULL &&
6579                 DSET_LOADED(im3d->fim_now->warp_parent) ){
6580        qim = THD_extract_float_brick(im3d->vinfo->fim_index,im3d->fim_now->warp_parent) ;
6581      }
6582      if( qim != NULL ){
6583        qval = percentile_nzabs( qim->nvox, MRI_FLOAT_PTR(qim), AUTORANGE_PERC ) ;
6584        mri_free(qim) ;
6585        if( qval > 0.0f ) rrr = qval ;
6586      }
6587    }
6588 
6589    if( rrr == 0.0f ) rrr = DEFAULT_FIM_SCALE ;
6590 
6591    im3d->vinfo->fim_autorange = rrr ;
6592    im3d->vinfo->arang_func_ok = 1 ;
6593    AV_fval_to_char( rrr , qbuf ) ;
6594    sprintf( buf , "autoRange:%s" , qbuf ) ;
6595    xstr = XmStringCreateLtoR( buf , XmFONTLIST_DEFAULT_TAG ) ;
6596 
6597 #ifdef AFNI_DEBUG
6598 { STATUS(buf) ;
6599   sprintf(buf,"rrr=%g",rrr) ; STATUS(buf) ; }
6600 #endif
6601 
6602    RETURN(xstr) ;
6603 }
6604 
6605 /*----------------------------------------------------------------
6606    called when the user toggles the autorange button
6607 ------------------------------------------------------------------*/
6608 
AFNI_range_bbox_CB(Widget w,XtPointer cd,XtPointer cb)6609 void AFNI_range_bbox_CB( Widget w, XtPointer cd, XtPointer cb )
6610 {
6611    Three_D_View *im3d = (Three_D_View *) cd ;
6612    RwcBoolean new_auto ;
6613 
6614 ENTRY("AFNI_range_bbox_CB") ;
6615 
6616    if( ! IM3D_OPEN(im3d) ||
6617        w != im3d->vwid->func->range_bbox->wbut[RANGE_AUTOBUT] ) EXRETURN ;
6618 
6619    new_auto = (MCW_val_bbox(im3d->vwid->func->range_bbox) & RANGE_AUTOVAL) != 0 ;
6620 
6621    if( new_auto != im3d->vinfo->use_autorange ){  /* new button value */
6622 
6623       im3d->vinfo->use_autorange = new_auto ;
6624 
6625       im3d->vinfo->fim_range = (new_auto) ? (im3d->vinfo->fim_autorange)
6626                                           : (im3d->vwid->func->range_av->fval) ;
6627 
6628       if( PBAR_FULLRANGE && !IM3D_ULAY_COHERENT(im3d) ){ /* 10 Jun 2014 */
6629         STATUS("incoherent ulay -- patching") ;
6630         ERROR_message("AFNI_range_bbox_CB: incoherent ulay -- patching") ;
6631         AFNI_assign_ulay_bricks(im3d) ;
6632       }
6633 
6634       if( PBAR_FULLRANGE ){
6635         AFNI_redisplay_func_ignore(1) ;
6636         AFNI_pbar_topset(im3d,im3d->vinfo->fim_range) ;
6637         AFNI_redisplay_func_ignore(0) ;
6638       }
6639       else HINTIZE_pbar(im3d) ;
6640 
6641       AV_SENSITIZE( im3d->vwid->func->range_av , ! new_auto ) ;
6642 
6643       AFNI_redisplay_func( im3d ) ;
6644 
6645       AFNI_range_lock_carryout(im3d) ;  /* 23 Feb 2004 */
6646    }
6647 
6648    AFNI_fix_scale_size_direct(im3d) ;  /* 03 Jun 2019 */
6649    EXRETURN ;
6650 }
6651 
6652 /*----------------------------------------------------------------
6653    called when the user toggles the percentile button
6654 ------------------------------------------------------------------*/
6655 
AFNI_perc_bbox_CB(Widget w,XtPointer cd,XtPointer cb)6656 void AFNI_perc_bbox_CB( Widget w, XtPointer cd, XtPointer cb )
6657 {
6658    Three_D_View *im3d = (Three_D_View *) cd ;
6659 
6660 ENTRY("AFNI_perc_bbox_CB") ;
6661 
6662    if( ! IM3D_OPEN(im3d) ||
6663        w != im3d->vwid->func->perc_bbox->wbut[PERC_AUTOBUT] ) EXRETURN ;
6664 
6665    im3d->cont_perc_thr = MCW_val_bbox(im3d->vwid->func->perc_bbox);
6666    flush_3Dview_sort(im3d, "T");
6667 
6668    AFNI_redisplay_func( im3d ) ;
6669    AFNI_thresh_lock_carryout(im3d) ;
6670 
6671    EXRETURN ;
6672 }
6673 
6674 
6675 /*----------------------------------------------------------------
6676   called when the user (that rotten fellow) changes the fim range
6677 ------------------------------------------------------------------*/
6678 
AFNI_range_av_CB(MCW_arrowval * av,XtPointer cd)6679 void AFNI_range_av_CB( MCW_arrowval *av , XtPointer cd )
6680 {
6681    Three_D_View *im3d = (Three_D_View *) cd ;
6682 
6683 ENTRY("AFNI_range_av_CB") ;
6684 
6685    if( ! IM3D_OPEN(im3d) ) EXRETURN ;
6686 
6687    im3d->vinfo->stats_anat_ok =
6688     im3d->vinfo->stats_func_ok =
6689      im3d->vinfo->arang_func_ok =
6690       im3d->vinfo->stats_thresh_ok = 0 ; /* 24 May 2019 */
6691 
6692    im3d->vinfo->fim_range = av->fval ;
6693 
6694    if( PBAR_FULLRANGE && !IM3D_ULAY_COHERENT(im3d) ){ /* 10 Jun 2014 */
6695      STATUS("incoherent ulay -- patching") ;
6696      ERROR_message("AFNI_range_av_CB: incoherent ulay -- patching") ;
6697      AFNI_assign_ulay_bricks(im3d) ;
6698    }
6699 
6700    if( PBAR_FULLRANGE ){
6701      AFNI_redisplay_func_ignore(1) ;
6702      AFNI_pbar_topset(im3d,im3d->vinfo->fim_range) ;
6703      AFNI_redisplay_func_ignore(0) ;
6704    }
6705    else HINTIZE_pbar(im3d) ;
6706 
6707    AFNI_redisplay_func( im3d ) ;
6708 
6709    AFNI_range_lock_carryout(im3d) ;  /* 23 Feb 2004 */
6710 
6711    AFNI_fix_scale_size_direct(im3d) ;  /* 03 Jun 2019 */
6712    EXRETURN ;
6713 }
6714 
6715 /*----------------------------------------------------------------
6716    called when the user toggles the posfunc button
6717 ------------------------------------------------------------------*/
6718 
AFNI_inten_bbox_CB(Widget w,XtPointer cd,XtPointer cb)6719 void AFNI_inten_bbox_CB( Widget w, XtPointer cd, XtPointer cb )
6720 {
6721    Three_D_View *im3d = (Three_D_View *) cd ;
6722    RwcBoolean new_pos ;
6723    int jm ;
6724    MCW_pbar *pbar ;
6725 
6726 ENTRY("AFNI_inten_bbox_CB") ;
6727 
6728    if( ! IM3D_OPEN(im3d) ||
6729        w != im3d->vwid->func->inten_bbox->wbut[PBAR_MODEBUT] ) EXRETURN ;
6730 
6731    new_pos = (MCW_val_bbox(im3d->vwid->func->inten_bbox) & PBAR_MODEPOS) != 0 ;
6732 
6733    if( new_pos != im3d->vinfo->use_posfunc ){  /* new button value */
6734 
6735       im3d->vinfo->use_posfunc = new_pos ;   /* record for later use */
6736 
6737       pbar = im3d->vwid->func->inten_pbar ;
6738       jm   = pbar->mode = (new_pos) ? 1 : 0 ;  /* pbar mode */
6739 
6740       /* re-panel the pbar befitting its new mode */
6741 
6742       if( PBAR_FULLRANGE && !IM3D_ULAY_COHERENT(im3d) ){ /* 10 Jun 2014 */
6743         STATUS("incoherent ulay -- patching") ;
6744         ERROR_message("AFNI_inten_bbox_CB: incoherent ulay -- patching") ;
6745         AFNI_assign_ulay_bricks(im3d) ;
6746       }
6747 
6748       AFNI_redisplay_func_ignore(1) ;
6749 
6750       HIDE_SCALE(im3d) ;
6751       if( pbar->bigmode ){               /* 30 Jan 2003 */
6752         int npane=pbar->num_panes ;
6753         float pmin , pmax ;
6754         pmax = (pbar->big31) ? pbar->bigtop
6755                              : pbar->pval_save[npane][0    ][jm] ;
6756         pmin = (pbar->big31) ? ( (jm==1) ? 0.0f : -pmax )
6757                              : pbar->pval_save[npane][npane][jm] ;
6758         pbar->bigset = 0 ;
6759         PBAR_set_bigmode( pbar , 1 , pmin,pmax ) ;
6760         AFNI_inten_pbar_CB( pbar , im3d , 0 ) ;
6761       } else {
6762         alter_MCW_pbar( pbar , pbar->npan_save[jm] , NULL ) ;
6763       }
6764       FIX_SCALE_SIZE(im3d) ;
6765 
6766       /* set the count on the pbar control arrowval to match */
6767 
6768       if( pbar->bigmode )
6769         AV_assign_ival( im3d->vwid->func->inten_av, NPANE_MAX+1 ) ;
6770       else
6771         AV_assign_ival( im3d->vwid->func->inten_av, pbar->npan_save[jm] ) ;
6772 
6773       if( PBAR_FULLRANGE && !IM3D_IS_BIGTHREE(im3d) )
6774         AFNI_pbar_topset(im3d,im3d->vinfo->fim_range) ;
6775       else
6776         HINTIZE_pbar(im3d) ;
6777 
6778       AFNI_redisplay_func_ignore(0) ;
6779       AFNI_redisplay_func( im3d ) ;
6780       if( AFNI_count_controllers() > 1 && AFNI_check_pbar_lock() ) /* 03 Jul 2014 */
6781         AFNI_redisplay_func_all( im3d ) ;
6782    }
6783 
6784    AFNI_fix_scale_size_direct(im3d) ;  /* 03 Jun 2019 */
6785    EXRETURN ;
6786 }
6787 
6788 /*--------------------------------------------------------------
6789    Called to reset the range related functional stuff
6790 ----------------------------------------------------------------*/
6791 
AFNI_reset_func_range(Three_D_View * im3d)6792 void AFNI_reset_func_range( Three_D_View *im3d )
6793 {
6794    XmString xstr ;
6795    RwcBoolean  same ;
6796    int iqq = AFNI_controller_index(im3d) ;
6797 
6798 ENTRY("AFNI_reset_func_range") ;
6799 
6800    if( ! IM3D_OPEN(im3d) ) EXRETURN ;
6801 
6802    im3d->vinfo->stats_anat_ok =
6803     im3d->vinfo->stats_func_ok =
6804      im3d->vinfo->arang_func_ok =
6805       im3d->vinfo->stats_thresh_ok = 0 ; /* 24 May 2019 */
6806 
6807    if( PBAR_FULLRANGE && !IM3D_ULAY_COHERENT(im3d) ){ /* 10 Jun 2014 */
6808      STATUS("incoherent ulay -- patching") ;
6809      ERROR_message("AFNI_reset_func_range: incoherent ulay -- patching") ;
6810      AFNI_assign_ulay_bricks(im3d) ;
6811    }
6812 
6813    /*-- the range label widget --*/
6814 
6815    xstr = AFNI_range_label( im3d ) ;
6816    same = XmStringCompare( xstr , im3d->vinfo->old_range_label ) ;
6817 
6818    if( same == False ){
6819       XtVaSetValues( im3d->vwid->func->range_label ,    /* redisplay */
6820                         XmNlabelString , xstr ,         /* if changed */
6821                      NULL ) ;
6822       MCW_expose_widget( im3d->vwid->func->range_label ) ; /* redraw now! */
6823       XmStringFree(im3d->vinfo->old_range_label) ;         /* toss old */
6824       im3d->vinfo->old_range_label = xstr ;                /* new old */
6825    } else {
6826       XmStringFree( xstr ) ;  /* was same --> don't need this copy */
6827    }
6828 
6829    /*-- the autorange toggle widget --*/
6830 
6831    xstr = AFNI_autorange_label( im3d ) ;
6832    same = XmStringCompare( xstr , im3d->vinfo->autorange_label ) ;
6833 
6834    if( same == False ){
6835       Widget www = im3d->vwid->func->range_bbox->wbut[RANGE_AUTOBUT] ;
6836       XtVaSetValues( www , XmNlabelString , xstr , NULL ) ;
6837       MCW_expose_widget( www ) ;
6838       XmStringFree(im3d->vinfo->autorange_label) ;
6839       im3d->vinfo->autorange_label = xstr ;
6840    } else {
6841       XmStringFree( xstr ) ;  /* was same --> don't need this copy */
6842    }
6843 
6844    /*-- the functional range itself --*/
6845 
6846    im3d->vinfo->fim_range =
6847       (im3d->vinfo->use_autorange) ? (im3d->vinfo->fim_autorange)
6848                                    : (im3d->vwid->func->range_av->fval) ;
6849 
6850    if( PBAR_FULLRANGE && (reset_func_range_ncall[iqq]==0 || !IM3D_IS_BIGTHREE(im3d)) ){
6851      AFNI_redisplay_func_ignore(1) ;
6852      AFNI_pbar_topset(im3d,im3d->vinfo->fim_range) ;
6853      AFNI_redisplay_func_ignore(0) ; reset_func_range_ncall[iqq]++ ;
6854    }
6855    else HINTIZE_pbar(im3d) ;
6856 
6857    EXRETURN ;
6858 }
6859 
6860 /*--------------------------------------------------------------------
6861   30 Nov 1997:  Callback for when the a bucket chooser is altered;
6862                 will switch the viewing to a new sub-brick.
6863 ----------------------------------------------------------------------*/
6864 
AFNI_bucket_CB(MCW_arrowval * av,XtPointer cd)6865 void AFNI_bucket_CB( MCW_arrowval *av , XtPointer cd )
6866 {
6867    Three_D_View *im3d = (Three_D_View *) cd ;
6868    int doit=0 , iv , redisplay , dothr=0 ;
6869 
6870 ENTRY("AFNI_bucket_CB") ;
6871 
6872    if( ! IM3D_OPEN(im3d) ) EXRETURN ;
6873 
6874 #if 0
6875    STATUS_IM3D_TMASK(im3d) ;
6876    STATUS("clear tmask") ;
6877 #endif
6878    IM3D_CLEAR_TMASK(im3d) ;                                /* Mar 2013 */
6879    IM3D_CLEAR_THRSTAT(im3d) ;                           /* 12 Jun 2014 */
6880    AFNI_setup_thrstat(im3d,0) ;                         /* 27 Jun 2019 */
6881 
6882    im3d->vinfo->stats_anat_ok =
6883     im3d->vinfo->stats_func_ok =
6884      im3d->vinfo->arang_func_ok =
6885       im3d->vinfo->stats_thresh_ok = 0 ; /* 24 May 2019 */
6886 
6887    /** Anat sub-brick [29 Jul 2003: lock to time_index controller as well] **/
6888 
6889    if( av == im3d->vwid->func->anat_buck_av ){
6890      iv = av->ival ;
6891      if( iv >= 0 && iv < DSET_NVALS(im3d->anat_now) ){
6892        doit = (iv != im3d->vinfo->anat_index) ;
6893        im3d->vinfo->anat_index = iv ;
6894        redisplay = REDISPLAY_ALL ;
6895        if( doit && im3d->vinfo->time_on )
6896          AV_assign_ival( im3d->vwid->imag->time_index_av , iv ) ;
6897      }
6898    }
6899 
6900    /** Func sub-brick **/
6901 
6902    else if( av == im3d->vwid->func->fim_buck_av ){
6903      iv = av->ival ;
6904      if( iv >= 0 && iv < DSET_NVALS(im3d->fim_now) ){
6905        doit = (iv != im3d->vinfo->fim_index) ;
6906        im3d->vinfo->fim_index = iv ;
6907        redisplay = REDISPLAY_OVERLAY ;
6908        AFNI_enforce_throlayx(im3d) ; /* 13 Aug 2010 */
6909        if( doit && im3d->vinfo->time_on && DSET_NUM_TIMES(im3d->anat_now) == 1 )
6910          AV_assign_ival( im3d->vwid->imag->time_index_av , iv ) ;
6911      }
6912    }
6913 
6914    /** Thresh sub-brick **/
6915 
6916    else if( av == im3d->vwid->func->thr_buck_av ){
6917      iv = av->ival ;
6918      if( iv >= 0 && iv < DSET_NVALS(im3d->fim_now) ){
6919        doit = (iv != im3d->vinfo->thr_index) ;
6920        im3d->vinfo->thr_index = iv ;
6921        redisplay = REDISPLAY_OVERLAY ;
6922      }
6923      dothr = 1 ;
6924    }
6925 
6926    /** Change the view, if required **/
6927 
6928    if( doit ){
6929       SHOW_AFNI_PAUSE ;
6930       im3d->vinfo->tempflag = 1 ;
6931       AFNI_setup_viewing( im3d , False ) ;
6932       AFNI_set_viewpoint( im3d , -1,-1,-1 , redisplay ) ; /* redraw */
6933       if( redisplay == REDISPLAY_OVERLAY &&
6934           im3d->vinfo->func_visible        ) AFNI_process_funcdisplay(im3d) ;
6935       SHOW_AFNI_READY ;
6936    }
6937 
6938    if( dothr && AFNI_yesenv("AFNI_THRESH_AUTO") ){    /* 05 Mar 2007 */
6939      float new_thresh = AFNI_get_autothresh(im3d) ;
6940      if( new_thresh > 0.0f ) AFNI_set_threshold(im3d,new_thresh) ;
6941    } else if( dothr ){
6942      if( im3d->vinfo->fix_pval && im3d->vinfo->fixed_pval > 0.0f )
6943        AFNI_set_pval(im3d,im3d->vinfo->fixed_pval) ;
6944      else if( im3d->vinfo->fix_qval && im3d->vinfo->fixed_qval > 0.0f )
6945        AFNI_set_qval(im3d,im3d->vinfo->fixed_qval) ;
6946    }
6947 
6948 
6949    FIX_SCALE_SIZE(im3d) ;
6950    AFNI_fix_scale_size_direct(im3d) ;  /* 03 Jun 2019 */
6951    EXRETURN ;
6952 }
6953 
6954 /*--------------------------------------------------------------------------*/
6955 /*! Prepare a bucket label for a menu.
6956     21 Jun 2004: modified to allow label length to be different from 14.
6957 ----------------------------------------------------------------------------*/
6958 
6959 static int force_label_resize = 0 ;
AFNI_force_bucket_label_resize(int ff)6960 void AFNI_force_bucket_label_resize( int ff ){ force_label_resize = ff ; }
6961 
AFNI_bucket_label_CB(MCW_arrowval * av,XtPointer cd)6962 char * AFNI_bucket_label_CB( MCW_arrowval *av , XtPointer cd )
6963 {
6964    static THD_3dim_dataset *dset_last = NULL ;
6965    static int               nsiz_last = 4 ;
6966 
6967    THD_3dim_dataset *dset = (THD_3dim_dataset *) cd ;
6968    static char *fmt[3]={NULL,NULL,NULL}, sfmt[THD_MAX_SBLABEL],blab[26+THD_MAX_SBLABEL] ;
6969    int nlab ;
6970    static int nlab_old = 0 ;
6971 
6972 ENTRY("AFNI_bucket_label_CB") ;
6973 
6974    /** 04 May 2005: customize width to this dataset **/
6975 
6976    if( ISVALID_DSET(dset) && ( dset != dset_last || force_label_resize ) ){
6977      int nvals,kk,blw,mblw=4 ; char *lab ;
6978      dset_last = dset ;
6979      nvals = DSET_NVALS(dset) ;
6980      for( kk=0 ; kk < nvals ; kk++ ){
6981        lab = DSET_BRICK_LAB(dset,kk) ;
6982        if( lab != NULL ){ blw=strlen(lab) ; if(blw>mblw)mblw=blw ; }
6983      }
6984      if( mblw > THD_MAX_SBLABEL ) mblw = THD_MAX_SBLABEL ;
6985      nsiz_last = mblw ;
6986    }
6987 
6988    /* see if the environment overrides the above */
6989 
6990 #if 0
6991    nlab = (int)AFNI_numenv("AFNI_BUCKET_LABELSIZE") ;
6992         if( nlab <= 0 ) nlab = nsiz_last ;
6993    else if( nlab > 32 ) nlab = 32 ;
6994 #else
6995    nlab = nsiz_last ;
6996 #endif
6997 
6998    /* make the format for the label string: left justified, width=nlab */
6999 
7000    if( nlab != nlab_old ){
7001      nlab_old = nlab ;
7002      sprintf(sfmt,"%%-%d.%ds",nlab,nlab) ;
7003      if( fmt[0] == NULL ){
7004        fmt[0] = malloc(THD_MAX_SBLABEL); fmt[1] = malloc(THD_MAX_SBLABEL);
7005        fmt[2] = malloc(THD_MAX_SBLABEL);
7006      }
7007 
7008      /* and now the formats including the sub-brick index and the label */
7009 
7010 #ifdef USE_RIGHT_BUCK_LABELS
7011      sprintf(fmt[0],"%s #%%1d",sfmt) ;   /* if the #xxx goes to the right */
7012      sprintf(fmt[1],"%s #%%2d",sfmt) ;
7013      sprintf(fmt[2],"%s #%%3d",sfmt) ;
7014 #else
7015      sprintf(fmt[0],"#%%1d %s",sfmt) ;   /* if the #xxx goes to the left */
7016      sprintf(fmt[1],"#%%2d %s",sfmt) ;
7017      sprintf(fmt[2],"#%%3d %s",sfmt) ;
7018 #endif
7019    }
7020 
7021    /* now actually make the label for this particular sub-brick */
7022 
7023    if( ISVALID_3DIM_DATASET(dset) ){
7024 
7025 #ifdef USE_RIGHT_BUCK_LABELS
7026      if( DSET_NVALS(dset) < 10 )
7027        sprintf(blab, fmt[0] , DSET_BRICK_LABEL(dset,av->ival) , av->ival ) ;
7028      else if( DSET_NVALS(dset) < 100 )
7029        sprintf(blab, fmt[1] , DSET_BRICK_LABEL(dset,av->ival) , av->ival ) ;
7030      else
7031        sprintf(blab, fmt[2] , DSET_BRICK_LABEL(dset,av->ival) , av->ival ) ;
7032 #else
7033      if( DSET_NVALS(dset) < 10 )
7034        sprintf(blab, fmt[0] , av->ival , DSET_BRICK_LABEL(dset,av->ival) ) ;
7035      else if( DSET_NVALS(dset) < 100 )
7036        sprintf(blab, fmt[1] , av->ival , DSET_BRICK_LABEL(dset,av->ival) ) ;
7037      else
7038        sprintf(blab, fmt[2] , av->ival , DSET_BRICK_LABEL(dset,av->ival) ) ;
7039 #endif
7040    }
7041    else
7042      sprintf(blab," #%d ",av->ival) ; /* shouldn't happen, but you never know */
7043 
7044    RETURN(blab) ;
7045 }
7046 
7047 /*---------------------------------------------------------------
7048   Callback for the 'AFNI Tips' button [27 Jun 2011]
7049 -----------------------------------------------------------------*/
7050 
7051 #ifndef DONT_USE_HTMLWIN
7052 static int tips_open        = 0 ;
7053 static MCW_htmlwin *tips_hw = NULL ;
AFNI_tips_killfun(XtPointer junk)7054 void AFNI_tips_killfun( XtPointer junk ){
7055   tips_open = 0 ; tips_hw = NULL ; return ;
7056 }
7057 #endif
7058 
AFNI_tips_CB(Widget w,XtPointer cd,XtPointer cbd)7059 void AFNI_tips_CB( Widget w , XtPointer cd , XtPointer cbd )
7060 {
7061 #include "readme_afnigui.h"
7062    Three_D_View *im3d = (Three_D_View *)cd ;
7063    char *inf=NULL , *fpt=NULL ; int ii ;
7064 
7065 ENTRY("AFNI_tips_CB") ;
7066 
7067 #ifndef DONT_USE_HTMLWIN
7068    if( tips_open && tips_hw != NULL ){
7069      XMapRaised( XtDisplay(tips_hw->wshell) , XtWindow(tips_hw->wshell) ) ;
7070      EXRETURN ;
7071    } else if( !AFNI_noenv("AFNI_DONT_USE_HTMLWIN") ){
7072      fpt = THD_find_regular_file("afnigui.html", NULL) ;
7073      if( fpt != NULL && *fpt != '\0' ){
7074        inf = (char *)malloc(sizeof(char)*(strlen(fpt)+16)) ;
7075        strcpy(inf,"file:") ; strcat(inf,fpt) ; free(fpt) ;
7076        tips_hw = new_MCW_htmlwin( im3d->vwid->imag->topper, inf,
7077                                   AFNI_tips_killfun , NULL  ,
7078                                   NULL, 0   ) ;
7079        free(inf) ; tips_open = 1 ; EXRETURN ;
7080      }
7081    }
7082 #endif
7083 
7084    for( ii=0 ; readme_afnigui[ii] != NULL ; ii++ ){
7085      inf = THD_zzprintf( inf , " %s" , readme_afnigui[ii] ) ;
7086    }
7087    (void)new_MCW_textwin( im3d->vwid->imag->topper , inf , TEXT_READONLY ) ;
7088    free(inf) ; EXRETURN ;
7089 }
7090 
7091 /*---------------------------------------------------------------*/
7092 /* For the 'AFNI news' button [15 May 2019] */
7093 
7094 #undef  NEWS_LINK
7095 #define NEWS_LINK \
7096  "https://afni.nimh.nih.gov/pub/dist/src/AFNI_digest_history.txt"
7097 
AFNI_news_CB(Widget w,XtPointer cd,XtPointer cbd)7098 void AFNI_news_CB( Widget w , XtPointer cd , XtPointer cbd )
7099 {
7100    static int first=1 ;
7101    if( GLOBAL_browser != NULL ){
7102      if( first ){
7103        (void) MCW_popup_message( w , " \n"
7104                                      " * At this time, the news page is *\n"
7105                                      " * very limited.  We plan to make *\n"
7106                                      " * it much better REAL SOON NOW!! *\n" ,
7107                                 MCW_USER_KILL | MCW_TIMER_KILL ) ;
7108        first = 0 ; AFNI_sleep(666) ;
7109      }
7110      whereami_browser(NEWS_LINK) ;
7111    } else {
7112      (void) MCW_popup_message( w , " \n"
7113                                    " ** Can't find a Web browser :( **\n"
7114                                    " Try setting environment variable\n"
7115                                    "      AFNI_WEB_BROWSER\n"
7116                                    " to be the path to a browser\n"
7117                                    " command line path\n" ,
7118                               MCW_USER_KILL | MCW_TIMER_KILL ) ;
7119   }
7120 }
7121 
7122 /*---------------------------------------------------------------*/
7123 /* For the 'AFNI Forum' button [17 May 2019] */
7124 
7125 #undef  FORUM_LINK
7126 #define FORUM_LINK \
7127  "https://afni.nimh.nih.gov/afni/community/board/"
7128 
AFNI_forum_CB(Widget w,XtPointer cd,XtPointer cbd)7129 void AFNI_forum_CB( Widget w , XtPointer cd , XtPointer cbd )
7130 {
7131    if( GLOBAL_browser != NULL ){
7132      whereami_browser(FORUM_LINK) ;
7133    } else {
7134      (void) MCW_popup_message( w , " \n"
7135                                    " ** Can't find a Web browser :( **\n"
7136                                    " Try setting environment variable\n"
7137                                    "      AFNI_WEB_BROWSER\n"
7138                                    " to be the path to a browser\n"
7139                                    " command line path\n" ,
7140                               MCW_USER_KILL | MCW_TIMER_KILL ) ;
7141   }
7142 }
7143 
7144 /*---------------------------------------------------------------*/
7145 /* For the 'Prog Helps' button [17 May 2019] */
7146 
7147 #undef  PHELP_LINK
7148 #define PHELP_LINK \
7149  "https://afni.nimh.nih.gov/pub/dist/doc/htmldoc/programs/main_toc.html"
7150 
AFNI_phelp_CB(Widget w,XtPointer cd,XtPointer cbd)7151 void AFNI_phelp_CB( Widget w , XtPointer cd , XtPointer cbd )
7152 {
7153    if( GLOBAL_browser != NULL ){
7154      whereami_browser(PHELP_LINK) ;
7155    } else {
7156      (void) MCW_popup_message( w , " \n"
7157                                    " ** Can't find a Web browser :( **\n"
7158                                    " Try setting environment variable\n"
7159                                    "      AFNI_WEB_BROWSER\n"
7160                                    " to be the path to a browser\n"
7161                                    " command line path\n" ,
7162                               MCW_USER_KILL | MCW_TIMER_KILL ) ;
7163   }
7164 }
7165 
7166 /*---------------------------------------------------------------*/
7167 /* For the 'youtube' button [30 Apr 2020] discoraj */
7168 
7169 #undef  YTUBE_LINK
7170 #define YTUBE_LINK \
7171  "https://www.youtube.com/channel/UC40RiNZN7_dCuB6Lg7HJl1g"
7172 
AFNI_ytube_CB(Widget w,XtPointer cd,XtPointer cbd)7173 void AFNI_ytube_CB( Widget w , XtPointer cd , XtPointer cbd )
7174 {
7175    if( GLOBAL_browser != NULL ){
7176      whereami_browser(YTUBE_LINK) ;
7177    } else {
7178      (void) MCW_popup_message( w , " \n"
7179                                    " ** Can't find a Web browser :( **\n"
7180                                    " Try setting environment variable\n"
7181                                    "      AFNI_WEB_BROWSER\n"
7182                                    " to be the path to a browser\n"
7183                                    " command line path\n" ,
7184                               MCW_USER_KILL | MCW_TIMER_KILL ) ;
7185   }
7186 }
7187 
7188 /*---------------------------------------------------------------*/
7189 
7190 #include "PvalueStuff.h"
7191 
AFNI_pvalue_CB(Widget w,XtPointer cd,XtPointer cbd)7192 void AFNI_pvalue_CB( Widget w , XtPointer cd , XtPointer cbd )
7193 {
7194    Three_D_View *im3d = (Three_D_View *)cd ;
7195    char *inf=NULL ; int ii ;
7196 
7197 ENTRY("AFNI_pvalue_CB") ;
7198    if( !IM3D_OPEN(im3d) || w == NULL ) EXRETURN ;
7199 
7200    for( ii=0 ; PvalueStuff[ii] != NULL ; ii++ )
7201      inf = THD_zzprintf( inf , " %s" , PvalueStuff[ii] ) ;
7202    (void) new_MCW_textwin( im3d->vwid->imag->topper , inf , TEXT_READONLY ) ;
7203    free(inf) ;
7204    EXRETURN ;
7205 }
7206 
7207 /*--------------------------------------------------------------------*/
7208 /* Print list of AFNI papers [02 May 2014] */
7209 
AFNI_list_papers(Widget w)7210 void AFNI_list_papers( Widget w )
7211 {
7212 #include "afni_papers.h"
7213    int ii ;
7214 
7215    if( w != (Widget)NULL && XtIsWidget(w) ){  /* open a window */
7216      char *inf=NULL ;
7217      for( ii=0 ; afni_papers[ii] != NULL ; ii++ ){
7218        inf = THD_zzprintf( inf , " %s" , afni_papers[ii] ) ;
7219      }
7220 #ifdef DONT_USE_HTMLWIN
7221      (void) new_MCW_textwin( w , inf , TEXT_READONLY ) ;  /* plain text */
7222 #else
7223      { char *qqq = convert_text_to_html(inf) ;       /* HTML with links */
7224        (void)new_MCW_htmlwin( w , qqq , NULL,NULL,NULL,0 ) ;
7225        free(qqq) ;
7226      }
7227 #endif
7228      free(inf) ;
7229 
7230    } else {   /* write papers list to stdout */
7231 
7232      for( ii=0 ; afni_papers[ii] != NULL ; ii++ )
7233        fputs(afni_papers[ii],stdout) ;
7234 
7235    }
7236    return ;
7237 }
7238 
7239 /*--------------------------------------------------------------------*/
7240 
AFNI_papers_CB(Widget w,XtPointer cd,XtPointer cbd)7241 void AFNI_papers_CB( Widget w , XtPointer cd , XtPointer cbd )
7242 {
7243    Three_D_View *im3d = (Three_D_View *)cd ;
7244 
7245    if( IM3D_OPEN(im3d) )
7246      AFNI_list_papers( im3d->vwid->imag->topper ) ;
7247 
7248    return ;
7249 }
7250 
7251 /*---------------------------------------------------------------
7252   Callback for all actions in the misc menu
7253 -----------------------------------------------------------------*/
7254 
AFNI_misc_CB(Widget w,XtPointer cd,XtPointer cbd)7255 void AFNI_misc_CB( Widget w , XtPointer cd , XtPointer cbd )
7256 {
7257    Three_D_View *im3d = (Three_D_View *)cd ;
7258    XmAnyCallbackStruct *cbs = (XmAnyCallbackStruct *)cbd ;
7259    int ic ;
7260 
7261 ENTRY("AFNI_misc_CB") ;
7262 
7263    if( !IM3D_OPEN(im3d) || w == NULL ) EXRETURN ;
7264 
7265    ic = AFNI_controller_index(im3d) ;
7266 
7267    /*.........................................................*/
7268 
7269    if( w == im3d->vwid->dmode->misc_voxind_pb ){
7270       im3d->vinfo->show_voxind = MCW_val_bbox(im3d->vwid->dmode->misc_voxind_bbox);
7271       AFNI_set_viewpoint( im3d , -1,-1,-1 , REDISPLAY_OVERLAY ) ;
7272    }
7273 
7274    /*.........................................................*/
7275 
7276 #ifndef DONT_USE_HINTS
7277    else if( w == im3d->vwid->dmode->misc_hints_pb ){
7278       int val = MCW_val_bbox(im3d->vwid->dmode->misc_hints_bbox) ;
7279       if( val != GLOBAL_library.hints_on ){
7280          int ii ; Three_D_View *qq3d ;
7281          MCW_hint_toggle() ; GLOBAL_library.hints_on = val ;
7282          for( ii=0 ; ii < MAX_CONTROLLERS ; ii++ ){             /* this loop:  */
7283             qq3d = GLOBAL_library.controllers[ii] ;             /* 07 Aug 1999 */
7284             if( IM3D_VALID(qq3d) )
7285                MCW_set_bbox( qq3d->vwid->dmode->misc_hints_bbox , val ) ;
7286          }
7287       }
7288    }
7289 #endif
7290 
7291    /*.........................................................*/
7292 
7293    else if( w == im3d->vwid->dmode->misc_anat_info_pb ){
7294       char *inf ;
7295 STATUS("getting anat info") ;
7296       inf = THD_dataset_info( im3d->anat_now , 0 ) ;
7297       if( inf != NULL ){
7298          if( DSET_ARRAY(im3d->anat_now,0) == NULL ){
7299             inf = THD_zzprintf( inf , "\n*** Not loaded into memory.\n") ;
7300          } else if( im3d->anat_now->dblk->malloc_type == DATABLOCK_MEM_MALLOC ){
7301             if( DBLK_LOCKED(im3d->anat_now->dblk) )
7302                inf = THD_zzprintf( inf , "\n*** Locked into memory using malloc.\n") ;
7303             else
7304                inf = THD_zzprintf( inf , "\n*** Loaded into memory using malloc.\n") ;
7305          } else if( im3d->anat_now->dblk->malloc_type == DATABLOCK_MEM_MMAP ){
7306             inf = THD_zzprintf( inf , "\n*** Loaded into memory using mmap.\n") ;
7307          } else if( im3d->anat_now->dblk->malloc_type == DATABLOCK_MEM_SHARED ){
7308             inf = THD_zzprintf( inf , "\n*** Loaded into shared memory segment %d.\n",
7309                                 im3d->anat_now->dblk->shm_idint) ;
7310          }
7311          (void) new_MCW_textwin( im3d->vwid->imag->topper , inf , TEXT_READONLY ) ;
7312          free(inf) ;
7313       } else {
7314          BEEPIT ; WARNING_message("Can't get anat info") ;
7315       }
7316    }
7317 
7318    /*.........................................................*/
7319 
7320    else if( w == im3d->vwid->dmode->misc_func_info_pb ){
7321       char *inf ;
7322 STATUS("getting func info") ;
7323       inf = THD_dataset_info( im3d->fim_now , 0 ) ;
7324 STATUS("got func info") ;
7325       if( inf != NULL ){
7326          if( DSET_ARRAY(im3d->fim_now,0) == NULL ){
7327             inf = THD_zzprintf( inf , "\n*** Not loaded into memory.\n") ;
7328          } else if( im3d->fim_now->dblk->malloc_type == DATABLOCK_MEM_MALLOC ){
7329             if( DBLK_LOCKED(im3d->fim_now->dblk) )
7330                inf = THD_zzprintf( inf , "\n*** Locked into memory using malloc.\n") ;
7331             else
7332                inf = THD_zzprintf( inf , "\n*** Loaded into memory using malloc.\n") ;
7333          } else if( im3d->fim_now->dblk->malloc_type == DATABLOCK_MEM_MMAP ){
7334             inf = THD_zzprintf( inf , "\n*** Loaded into memory using mmap.\n") ;
7335          } else if( im3d->fim_now->dblk->malloc_type == DATABLOCK_MEM_SHARED ){
7336             inf = THD_zzprintf( inf , "\n*** Loaded into shared memory segment %d.\n",
7337                                 im3d->fim_now->dblk->shm_idint) ;
7338          }
7339          (void) new_MCW_textwin( im3d->vwid->imag->topper , inf , TEXT_READONLY ) ;
7340          free(inf) ;
7341       } else {
7342          BEEPIT ; WARNING_message("Can't get func info") ;
7343       }
7344    }
7345 
7346    /*.........................................................*/
7347 
7348    else if( w == im3d->vwid->dmode->misc_license_pb ){  /* 03 Dec 2000 */
7349 #include "license.h"
7350       char *inf=NULL ; int ii ;
7351       for( ii=0 ; license[ii] != NULL ; ii++ )
7352          inf = THD_zzprintf( inf , " %s" , license[ii] ) ;
7353       (void) new_MCW_textwin( im3d->vwid->imag->topper , inf , TEXT_READONLY ) ;
7354       free(inf) ;
7355    }
7356 
7357    /*.........................................................*/
7358 
7359    else if( w == im3d->vwid->dmode->misc_readme_env_pb ){  /* 05 Aug 2004 */
7360 #include "readme_env.h"
7361       char *inf=NULL ; int ii ;
7362       for( ii=0 ; readme_env[ii] != NULL ; ii++ )
7363         inf = THD_zzprintf( inf , " %s" , readme_env[ii] ) ;
7364       (void) new_MCW_textwin( im3d->vwid->imag->topper , inf , TEXT_READONLY ) ;
7365       free(inf) ;
7366    }
7367 
7368    /*.........................................................*/
7369 
7370    else if( w == im3d->vwid->dmode->misc_motd_pb ){  /* 29 Nov 2005 */
7371      AFNI_display_motd( im3d->vwid->imag->topper ) ;
7372    }
7373 
7374    /*.........................................................*/
7375 
7376    else if( w == im3d->vwid->dmode->misc_hist_pb ){  /* 05 Mar 2008 */
7377      AFNI_display_hist( im3d->vwid->imag->topper ) ;
7378    }
7379 
7380    /*.........................................................*/
7381 
7382    else if( w == im3d->vwid->dmode->misc_vcheck_pb ){  /* 11 Jan 2000 */
7383       FILE *fp = popen( "afni_vcheck" , "r" ); int vc;
7384       if( fp == NULL ){
7385          BEEPIT ;
7386          (void)  MCW_popup_message( im3d->vwid->imag->topper ,
7387                                      " \n"
7388                                      "* Cannot execute *\n"
7389                                      "* afni_vcheck!   *\n" ,
7390                                     MCW_USER_KILL | MCW_TIMER_KILL ) ;
7391       } else {
7392 #define ISIZE 1024
7393          char *info=(char *)malloc(sizeof(char)*ISIZE) ; int ninfo ;
7394          strcpy(info," \n     Output of Program afni_vcheck  \n"
7395                         "   ---------------------------------\n \n"   ) ;
7396          ninfo = strlen(info) ;
7397          while( afni_fgets(info+ninfo,ISIZE-ninfo,fp) != NULL ){
7398            ninfo = strlen(info) ;
7399            if( ninfo >= ISIZE-2 ) break ;
7400          }
7401          vc = pclose(fp) ;
7402          ninfo = strlen(info) ;
7403          if( ninfo+42 < ISIZE ){
7404                 if( vc > 0  ) strcat(info,"\n\n****** VERSIONS DON'T MATCH !! ******\n");
7405            else if( vc == 0 ) strcat(info,"\n\n****** VERSIONS MATCH OK !! ******\n") ;
7406          }
7407          (void) MCW_popup_message( im3d->vwid->imag->topper , info ,
7408                                    MCW_USER_KILL | MCW_TIMER_KILL   ) ;
7409          free(info) ;
7410 
7411          if( vc > 0 ) AFNI_vcheck_flasher(im3d) ;
7412       }
7413    }
7414 
7415    /*.........................................................*/
7416 
7417    else if( w == im3d->vwid->dmode->misc_purge_pb ){
7418      long long mb , ma ;
7419      mb = MCW_MALLOC_total ;
7420      AFNI_purge_dsets( 1 ) ;
7421      ma = MCW_MALLOC_total ;
7422      if( mb > 0 && ma > 0 )
7423        INFO_message("Purge: before=%s  after=%s  diff=%s",
7424                     commaized_integer_string(mb) ,
7425                     commaized_integer_string(ma) ,
7426                     commaized_integer_string(mb-ma) ) ;
7427    }
7428 
7429    /*.........................................................*/
7430 
7431 #ifdef USE_TRACING
7432    else if( w == im3d->vwid->dmode->misc_tracing_pb ){
7433       DBG_trace = (DBG_trace + 1) % 3 ;  /* Aug 23 1998: cycle between 0,1,2 */
7434       MCW_set_widget_label( im3d->vwid->dmode->misc_tracing_pb, DBG_label ) ; /* 01 Aug 1999 */
7435 
7436       XSynchronize( im3d->dc->display, (Bool)(DBG_trace==2) ) ; /* 01 Dec 1999 */
7437       if( DBG_trace == 2 ) STATUS("XSynchronize enabled") ;
7438       else                 STATUS("XSynchronize disabled") ;
7439    }
7440 #endif
7441 
7442    /*.........................................................*/
7443 
7444 #ifdef USING_MCW_MALLOC   /* 07 Mar 1999 */
7445    else if( MCW_MALLOC_enabled && w == im3d->vwid->dmode->misc_showmalloc_pb ){
7446       MCHECK ;
7447    }
7448 
7449    else if( MCW_MALLOC_enabled && w == im3d->vwid->dmode->misc_dumpmalloc_pb ){
7450       mcw_malloc_dump() ;
7451    }
7452 #endif
7453 
7454    /*.........................................................*/
7455 
7456 #ifdef USE_WRITEOWNSIZE
7457    else if( w == im3d->vwid->dmode->misc_writeownsize_pb ){
7458       im3d->vinfo->writeownsize = MCW_val_bbox( im3d->vwid->dmode->misc_writeownsize_bbox ) ;
7459    }
7460 #endif
7461 
7462    /*.........................................................*/
7463 
7464 #ifdef ALLOW_PLUGINS
7465    else if( w == im3d->vwid->dmode->misc_environ_pb ){ /* 20 Jun 2000 */
7466       static PLUGIN_interface *plint=NULL ;
7467       Widget wpop ;
7468 
7469       /* first time in: create interface like a plugin */
7470 
7471       if( plint == NULL ){
7472         plint = ENV_init() ;
7473         if( plint == NULL ){ BEEPIT; WARNING_message("WTF?!"); EXRETURN; }
7474         PLUG_setup_widgets( plint , GLOBAL_library.dc ) ;
7475       }
7476 
7477       /* code below is from PLUG_startup_plugin_CB() in afni_plugin.c */
7478 
7479       plint->im3d = im3d ;
7480       XtVaSetValues( plint->wid->shell ,
7481                       XmNtitle    , "AFNI Environmentalism", /* top of window */
7482                       XmNiconName , "Green AFNI"           , /* label on icon */
7483                      NULL ) ;
7484       PLUTO_cursorize( plint->wid->shell ) ;
7485 
7486       /*-- if possible, find where this popup should go --*/
7487 
7488       wpop = plint->wid->shell ;
7489 
7490       if( cbs != NULL && cbs->event != NULL
7491                       && cbs->event->type == ButtonRelease ){
7492 
7493          XButtonEvent *xev = (XButtonEvent *) cbs->event ;
7494          int xx = (int)xev->x_root , yy = (int)xev->y_root ;
7495          int ww,hh , sw,sh ;
7496 
7497          MCW_widget_geom( wpop , &ww,&hh , NULL,NULL ) ;
7498          sw = WidthOfScreen (XtScreen(wpop)) ;
7499          sh = HeightOfScreen(XtScreen(wpop)) ;
7500 
7501          if( xx+ww+3 >= sw && ww <= sw ) xx = sw-ww ;
7502          if( yy+hh+3 >= sh && hh <= sh ) yy = sh-hh ;
7503 
7504          XtVaSetValues( wpop , XmNx , xx , XmNy , yy , NULL ) ;
7505       } else if( im3d->vwid->butx >= 0 && im3d->vwid->buty >= 0 ){
7506          XtVaSetValues( wpop ,
7507                          XmNx , im3d->vwid->butx ,
7508                          XmNy , im3d->vwid->buty , NULL ) ; /* 17 May 2005 */
7509       }
7510 
7511       /*-- popup widgets --*/
7512 
7513       XtMapWidget( wpop ) ;  /* after this, is up to user */
7514       AFNI_sleep(1) ;
7515       RWC_visibilize_widget( wpop ) ;
7516    }
7517 
7518    /*.........................................................*/
7519 
7520    else if( w == im3d->vwid->dmode->misc_1dchain_pb ){ /* 07 Aug 2001 */
7521       static PLUGIN_interface *plint=NULL ;
7522       Widget wpop ;
7523 
7524       /* first time in: create interface like a plugin */
7525 
7526       if( plint == NULL ){
7527          plint = F1D_init() ;
7528          if( plint == NULL ){ BEEPIT; WARNING_message("WTF?!"); EXRETURN; }
7529          PLUG_setup_widgets( plint , GLOBAL_library.dc ) ;
7530       }
7531 
7532       if( cbs == NULL ) EXRETURN ;  /* only for a setup call */
7533 
7534       /* code below is from PLUG_startup_plugin_CB() in afni_plugin.c */
7535 
7536       plint->im3d = im3d ;
7537       XtVaSetValues( plint->wid->shell ,
7538                       XmNtitle     , "AFNI 1DChain Function", /* top of window */
7539                       XmNiconName  , "1DChain"              , /* label on icon */
7540                      NULL ) ;
7541       PLUTO_cursorize( plint->wid->shell ) ;
7542 
7543       /*-- if possible, find where this popup should go --*/
7544 
7545       wpop = plint->wid->shell ;
7546 
7547       if( cbs->event != NULL && cbs->event->type == ButtonRelease ){
7548 
7549          XButtonEvent *xev = (XButtonEvent *) cbs->event ;
7550          int xx = (int)xev->x_root , yy = (int)xev->y_root ;
7551          int ww,hh , sw,sh ;
7552 
7553          MCW_widget_geom( wpop , &ww,&hh , NULL,NULL ) ;
7554          sw = WidthOfScreen (XtScreen(wpop)) ;
7555          sh = HeightOfScreen(XtScreen(wpop)) ;
7556 
7557          if( xx+ww+3 >= sw && ww <= sw ) xx = sw-ww ;
7558          if( yy+hh+3 >= sh && hh <= sh ) yy = sh-hh ;
7559 
7560          XtVaSetValues( wpop , XmNx , xx , XmNy , yy , NULL ) ;
7561       }
7562 
7563       /*-- popup widgets --*/
7564 
7565       XtMapWidget( wpop ) ;  /* after this, is up to user */
7566       RWC_visibilize_widget( wpop ) ;
7567    }
7568 
7569    /*.........................................................*/
7570 
7571    else if( w == im3d->vwid->dmode->misc_2dchain_pb ){ /* 20 Jun 2000 */
7572       static PLUGIN_interface *plint=NULL ;
7573       Widget wpop ;
7574 
7575       /* first time in: create interface like a plugin */
7576 
7577       if( plint == NULL ){
7578          plint = F2D_init() ;
7579          if( plint == NULL ){ BEEPIT; WARNING_message("WTF?!"); EXRETURN; }
7580          PLUG_setup_widgets( plint , GLOBAL_library.dc ) ;
7581       }
7582 
7583       if( cbs == NULL ) EXRETURN ;  /* only for a setup call */
7584 
7585       /* code below is from PLUG_startup_plugin_CB() in afni_plugin.c */
7586 
7587       plint->im3d = im3d ;
7588       XtVaSetValues( plint->wid->shell ,
7589                       XmNtitle     , "AFNI 2DChain Function", /* top of window */
7590                       XmNiconName  , "2DChain"              , /* label on icon */
7591                      NULL ) ;
7592       PLUTO_cursorize( plint->wid->shell ) ;
7593 
7594       /*-- if possible, find where this popup should go --*/
7595 
7596       wpop = plint->wid->shell ;
7597 
7598       if( cbs->event != NULL && cbs->event->type == ButtonRelease ){
7599 
7600          XButtonEvent *xev = (XButtonEvent *) cbs->event ;
7601          int xx = (int)xev->x_root , yy = (int)xev->y_root ;
7602          int ww,hh , sw,sh ;
7603 
7604          MCW_widget_geom( wpop , &ww,&hh , NULL,NULL ) ;
7605          sw = WidthOfScreen (XtScreen(wpop)) ;
7606          sh = HeightOfScreen(XtScreen(wpop)) ;
7607 
7608          if( xx+ww+3 >= sw && ww <= sw ) xx = sw-ww ;
7609          if( yy+hh+3 >= sh && hh <= sh ) yy = sh-hh ;
7610 
7611          XtVaSetValues( wpop , XmNx , xx , XmNy , yy , NULL ) ;
7612       }
7613 
7614       /*-- popup widgets --*/
7615 
7616       XtMapWidget( wpop ) ;  /* after this, is up to user */
7617       RWC_visibilize_widget( wpop ) ;
7618    }
7619 
7620    /*.........................................................*/
7621 
7622    else if( w == im3d->vwid->func->icor_pb ){ /* 29 Apr 2009 */
7623       static PLUGIN_interface *plint[MAX_CONTROLLERS] ; static int first=1 ;
7624       Widget wpop ;
7625       char title[64] , *lc=AFNI_controller_label(im3d) ;
7626 
7627       if( first ){  /* initialize */
7628         int ii ;
7629         for( ii=0 ; ii < MAX_CONTROLLERS ; ii++ ) plint[ii] = NULL ;
7630         first = 0 ;
7631       }
7632 
7633       /* first time in for this controller: create interface like a plugin */
7634 
7635       if( plint[ic] == NULL ){
7636          plint[ic] = ICOR_init(lc) ;
7637          if( plint[ic] == NULL ){ BEEPIT; WARNING_message("WTF?!"); EXRETURN; }
7638          PLUG_setup_widgets( plint[ic] , GLOBAL_library.dc ) ;
7639          plint[ic]->im3d = im3d ;
7640       }
7641 
7642       if( cbs == NULL ){  /* synthetic call */
7643          XtUnmapWidget(plint[ic]->wid->shell) ; EXRETURN ;
7644       }
7645 
7646       /* code below is from PLUG_startup_plugin_CB() in afni_plugin.c */
7647 
7648       plint[ic]->im3d = im3d ;
7649       sprintf(title,"%sAFNI InstaCorr Setup Operations",lc) ;
7650       XtVaSetValues( plint[ic]->wid->shell ,
7651                       XmNtitle     , title       , /* top of window */
7652                       XmNiconName  , "InstaCorr" , /* label on icon */
7653                      NULL ) ;
7654       PLUTO_cursorize( plint[ic]->wid->shell ) ;
7655 
7656       /*-- if possible, find where this popup should go --*/
7657 
7658       wpop = plint[ic]->wid->shell ;
7659 
7660       if( cbs->event != NULL && cbs->event->type == ButtonRelease ){
7661 
7662          XButtonEvent *xev = (XButtonEvent *)cbs->event ;
7663          int xx = (int)xev->x_root , yy = (int)xev->y_root ;
7664          int ww,hh , sw,sh ;
7665 
7666          MCW_widget_geom( wpop , &ww,&hh , NULL,NULL ) ;
7667          sw = WidthOfScreen (XtScreen(wpop)) ;
7668          sh = HeightOfScreen(XtScreen(wpop)) ;
7669 
7670          if( xx+ww+3 >= sw && ww <= sw ) xx = sw-ww ;
7671          if( yy+hh+3 >= sh && hh <= sh ) yy = sh-hh ;
7672 
7673          XtVaSetValues( wpop , XmNx , xx , XmNy , yy , NULL ) ;
7674       }
7675 
7676       /*-- popup widgets --*/
7677 
7678       XtMapWidget( wpop ) ;  /* after this, is up to user */
7679       RWC_visibilize_widget( wpop ) ;
7680    }
7681 
7682    /*.........................................................*/
7683 
7684    else if( w == im3d->vwid->func->gicor_pb ){ /* 22 Dec 2009 */
7685       static PLUGIN_interface *plint=NULL ;
7686       Widget wpop ;
7687       char title[64] , *lc=AFNI_controller_label(im3d) ;
7688 
7689       if( cbs == NULL && plint != NULL ){  /* synthetic call */
7690          XtUnmapWidget(plint->wid->shell) ; EXRETURN ;
7691       }
7692 
7693       if( im3d->giset == NULL || !im3d->giset->ready ){
7694         if( cbs != NULL ){
7695           BEEPIT ;
7696           (void)  MCW_popup_message( im3d->vwid->func->gicor_pb ,
7697                                      " \n"
7698                                      " ***** AFNI: ***** \n"
7699                                      "   3dGroupInCorr   \n"
7700                                      " isn't connected!! \n " ,
7701                                       MCW_USER_KILL | MCW_TIMER_KILL ) ;
7702         }
7703         EXRETURN ;
7704       }
7705 
7706       /* first time in for this controller: create interface like a plugin */
7707 
7708       if( plint == NULL ){
7709          plint = GICOR_init(lc) ;
7710          if( plint == NULL ){ BEEPIT; WARNING_message("WTF?!"); EXRETURN; }
7711          PLUG_setup_widgets( plint , GLOBAL_library.dc ) ;
7712          plint->im3d = im3d ;
7713       }
7714 
7715       /* code below is from PLUG_startup_plugin_CB() in afni_plugin.c */
7716 
7717       plint->im3d = im3d ;
7718       sprintf(title,"%sAFNI Group InstaCorr Setup",lc) ;
7719       XtVaSetValues( plint->wid->shell ,
7720                       XmNtitle     , title       , /* top of window */
7721                       XmNiconName  , "GrpInCorr" , /* label on icon */
7722                      NULL ) ;
7723       PLUTO_cursorize( plint->wid->shell ) ;
7724 
7725       /*-- if possible, find where this popup should go --*/
7726 
7727       wpop = plint->wid->shell ;
7728 
7729       if( cbs->event != NULL && cbs->event->type == ButtonRelease ){
7730 
7731          XButtonEvent *xev = (XButtonEvent *)cbs->event ;
7732          int xx = (int)xev->x_root , yy = (int)xev->y_root ;
7733          int ww,hh , sw,sh ;
7734 
7735          MCW_widget_geom( wpop , &ww,&hh , NULL,NULL ) ;
7736          sw = WidthOfScreen (XtScreen(wpop)) ;
7737          sh = HeightOfScreen(XtScreen(wpop)) ;
7738 
7739          if( xx+ww+3 >= sw && ww <= sw ) xx = sw-ww ;
7740          if( yy+hh+3 >= sh && hh <= sh ) yy = sh-hh ;
7741 
7742          XtVaSetValues( wpop , XmNx , xx , XmNy , yy , NULL ) ;
7743       }
7744 
7745       /*-- popup widgets --*/
7746 
7747       XtMapWidget( wpop ) ;  /* after this, is up to user */
7748       RWC_visibilize_widget( wpop ) ;
7749    }
7750 
7751    /*.........................................................*/
7752 
7753    else if( w == im3d->vwid->func->icalc_pb ){ /* 18 Sep 2009 */
7754      Widget wtop ;
7755 
7756      if( im3d->vwid->func->iwid == NULL ){
7757        ICALC_make_widgets(im3d) ;
7758        if( im3d->vwid->func->iwid == NULL ){ BEEPIT; WARNING_message("WTF?!"); EXRETURN; }
7759      }
7760 
7761      if( im3d->icalc_setup == NULL )
7762        INIT_ICALC_setup(im3d->icalc_setup) ;
7763 
7764      if( !im3d->vwid->func->iwid->is_open ) INSTACALC_LABEL_OFF(im3d) ;
7765      im3d->icalc_setup->is_good = 0 ;
7766 
7767      wtop =  im3d->vwid->func->iwid->wtop ;
7768 
7769      if( cbs->event != NULL && cbs->event->type == ButtonRelease ){
7770        XButtonEvent *xev = (XButtonEvent *)cbs->event ;
7771        int xx=(int)xev->x_root , yy=(int)xev->y_root , ww,hh,sw,sh ;
7772        MCW_widget_geom( wtop , &ww,&hh , NULL,NULL ) ;
7773        sw = WidthOfScreen (XtScreen(wtop)) ;
7774        sh = HeightOfScreen(XtScreen(wtop)) ;
7775        if( xx+ww+3 >= sw && ww <= sw ) xx = sw-ww ;
7776        if( yy+hh+3 >= sh && hh <= sh ) yy = sh-hh ;
7777        XtVaSetValues( wtop , XmNx , xx , XmNy , yy , NULL ) ;
7778      }
7779 
7780      XtMapWidget(wtop) ; RWC_visibilize_widget( wtop ) ;
7781      XRaiseWindow( XtDisplay(wtop) , XtWindow(wtop) ) ;
7782      im3d->vwid->func->iwid->is_open = 1 ;
7783    }
7784 
7785    /*.........................................................*/
7786 
7787    else if( w == im3d->vwid->func->tstat_pb ){ /* 22 Mar 2018 */
7788       static PLUGIN_interface *plint[MAX_CONTROLLERS] ; static int first=1 ;
7789       Widget wpop ;
7790       char title[64] , *lc=AFNI_controller_label(im3d) ;
7791 
7792       if( first ){  /* initialize */
7793         int ii ;
7794         for( ii=0 ; ii < MAX_CONTROLLERS ; ii++ ) plint[ii] = NULL ;
7795         first = 0 ;
7796       }
7797 
7798       /* first time in for this controller: create interface like a plugin */
7799 
7800       if( plint[ic] == NULL ){
7801          plint[ic] = TSTAT_init(lc) ;
7802          if( plint[ic] == NULL ){ BEEPIT; WARNING_message("WTF?!"); EXRETURN; }
7803          PLUG_setup_widgets( plint[ic] , GLOBAL_library.dc ) ;
7804          plint[ic]->im3d = im3d ;
7805       }
7806 
7807       if( cbs == NULL ){  /* synthetic call */
7808          XtUnmapWidget(plint[ic]->wid->shell) ; EXRETURN ;
7809       }
7810 
7811       /* code below is from PLUG_startup_plugin_CB() in afni_plugin.c */
7812 
7813       plint[ic]->im3d = im3d ;
7814       sprintf(title,"%sAFNI Tstat Computations",lc) ;
7815       XtVaSetValues( plint[ic]->wid->shell ,
7816                       XmNtitle     , title       , /* top of window */
7817                       XmNiconName  , "InstaCorr" , /* label on icon */
7818                      NULL ) ;
7819       PLUTO_cursorize( plint[ic]->wid->shell ) ;
7820 
7821       /*-- if possible, find where this popup should go --*/
7822 
7823       wpop = plint[ic]->wid->shell ;
7824 
7825       if( cbs->event != NULL && cbs->event->type == ButtonRelease ){
7826 
7827          XButtonEvent *xev = (XButtonEvent *)cbs->event ;
7828          int xx = (int)xev->x_root , yy = (int)xev->y_root ;
7829          int ww,hh , sw,sh ;
7830 
7831          MCW_widget_geom( wpop , &ww,&hh , NULL,NULL ) ;
7832          sw = WidthOfScreen (XtScreen(wpop)) ;
7833          sh = HeightOfScreen(XtScreen(wpop)) ;
7834 
7835          if( xx+ww+3 >= sw && ww <= sw ) xx = sw-ww ;
7836          if( yy+hh+3 >= sh && hh <= sh ) yy = sh-hh ;
7837 
7838          XtVaSetValues( wpop , XmNx , xx , XmNy , yy , NULL ) ;
7839       }
7840 
7841       /*-- popup widgets --*/
7842 
7843       XtMapWidget( wpop ) ;  /* after this, is up to user */
7844       RWC_visibilize_widget( wpop ) ;
7845    }
7846 
7847    /*.........................................................*/
7848 
7849    else if( w == im3d->vwid->dmode->misc_plugout_pb ){ /* 07 Nov 2001 */
7850       AFNI_init_plugouts() ;
7851       XtSetSensitive(w,False) ;
7852       if( AFNI_have_niml() )  /* 02 Feb 2007 */
7853         XtSetSensitive(im3d->vwid->view->nimlpo_pb,False) ;
7854    }
7855 #endif /* ALLOW_PLUGINS */
7856 
7857    else if( w == im3d->vwid->dmode->misc_niml_pb ){ /* 02 Mar 2002 */
7858       AFNI_init_niml() ;
7859       XtSetSensitive(w,False) ;
7860       if( AFNI_have_plugouts() )  /* 02 Feb 2007 */
7861         XtSetSensitive(im3d->vwid->view->nimlpo_pb,False) ;
7862    }
7863 
7864    /*.........................................................*/
7865 
7866    /****----- Get Outta Here -----****/
7867 
7868    EXRETURN ;
7869 }
7870 
7871 /*---------------------------------------------------------------*/
7872 /* Find a sub-brick containing a given text in its label */
7873 
find_subbrick_with_label(THD_3dim_dataset * dset,char * lstr)7874 int find_subbrick_with_label( THD_3dim_dataset *dset , char *lstr )
7875 {
7876    int iv , nvals ;
7877 
7878    if( !ISVALID_DSET(dset) || lstr == NULL || *lstr == '\0' ) return -1 ;
7879 
7880    nvals = DSET_NVALS(dset) ;
7881    for( iv=0 ; iv < nvals ; iv++ ){
7882      if( strcasestr( DSET_BRICK_LABEL(dset,iv) , lstr ) != NULL )
7883        return iv ;
7884    }
7885    return -1 ;
7886 }
7887 
7888 /*-------- get a pair of indexes for OLay/Thr [11 Jan 2017] --------*/
7889 
find_reasonable_overlay_indexes(THD_3dim_dataset * dset)7890 int_pair find_reasonable_overlay_indexes( THD_3dim_dataset *dset )
7891 {
7892    int_pair ovp={-1,-1} ;
7893    int ith, iov ;
7894 
7895    if( !ISVALID_DSET(dset) ) return ovp ;
7896 
7897    iov = find_subbrick_with_label( dset , "Coef" ) ;
7898    if( iov < 0 )
7899      iov = find_subbrick_with_label( dset , "Beta" ) ;
7900    if( iov >= 0 ){
7901      ovp.i = iov ;
7902      if( iov+1 < DSET_NVALS(dset) ) ovp.j = iov+1 ;
7903      return ovp ;
7904    }
7905 
7906    iov = find_subbrick_with_label( dset , "Tstat" ) ;
7907    if( iov < 0 )
7908      iov = find_subbrick_with_label( dset , "Fstat" ) ;
7909    if( iov >= 0 ){
7910      ovp.i = ovp.j = iov ;
7911      return ovp ;
7912    }
7913 
7914    return ovp ;
7915 }
7916 
7917 /*---------------------------------------------------------------*/
7918 
AFNI_editenv_CB(Widget w,XtPointer cd,XtPointer cbd)7919 void AFNI_editenv_CB( Widget w , XtPointer cd , XtPointer cbd )
7920 {
7921    Three_D_View *im3d = (Three_D_View *) cd ;
7922 
7923    if( !IM3D_OPEN(im3d) ) return ;
7924    AFNI_misc_CB( im3d->vwid->dmode->misc_environ_pb ,
7925                  (XtPointer) im3d , (XtPointer) NULL ) ;
7926 }
7927 
7928 #ifdef USE_HIDDEN
7929 
7930 /*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
7931   May 1995: Hidden popup menu stuff
7932 :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
7933 
7934 #ifndef ALLOW_PLUGINS
7935 # undef WANT_RWCOX_IMAGE
7936 #endif
7937 
7938 #ifdef WANT_RWCOX_IMAGE
7939 void RWCOX_popper(void) ;
7940 #endif
7941 
7942 #ifdef USE_SKIT
7943 void SKIT_popper( Three_D_View * ) ;
7944 #endif
7945 
7946 static int    num_poem  = 0 ;    /* 15 Oct 2003 */
7947 static char **fname_poem=NULL ;
7948 static void AFNI_find_poem_files(void) ;
7949 
7950 #include "uscon.h"
7951 
7952 /*---------------------------------------------------------------
7953   Callback for all actions in the hidden popup
7954 -----------------------------------------------------------------*/
7955 
AFNI_hidden_CB(Widget w,XtPointer cd,XtPointer cbs)7956 void AFNI_hidden_CB( Widget w , XtPointer cd , XtPointer cbs )
7957 {
7958    Three_D_View *im3d = (Three_D_View *)cd ;
7959 
7960 ENTRY("AFNI_hidden_CB") ;
7961 
7962    if( ! IM3D_OPEN(im3d) || w == (Widget)NULL ) EXRETURN ;
7963 
7964 #ifdef ALLOW_DATASET_VLIST
7965    /****----- Read points -----****/
7966 
7967    if( w == im3d->vwid->prog->hidden_readpts_ijk_pb ||
7968        w == im3d->vwid->prog->hidden_readpts_xyz_pb   ){
7969 
7970       im3d->vwid->prog->hidden_code =
7971         (w == im3d->vwid->prog->hidden_readpts_ijk_pb) ? PTS_READ_IJK
7972                                                        : PTS_READ_XYZ ;
7973 
7974       POPDOWN_ovcolor_chooser ;
7975 
7976       MCW_choose_string( im3d->vwid->picture ,
7977 
7978             (im3d->vwid->prog->hidden_code == PTS_READ_IJK)
7979               ? "Enter IJK input filename:"
7980               : "Enter XYZ input filename:" ,
7981 
7982             NULL , AFNI_hidden_pts_CB , cd ) ;
7983    }
7984 
7985    /****----- Write points -----****/
7986 
7987    else if( w == im3d->vwid->prog->hidden_writepts_ijk_pb ||
7988             w == im3d->vwid->prog->hidden_writepts_xyz_pb   ){
7989 
7990       if( im3d->anat_now->pts == NULL || im3d->anat_now->pts->num <= 0 ){
7991          (void)  MCW_popup_message( im3d->vwid->picture ,
7992                                     "No points to write out!" ,
7993                                     MCW_USER_KILL | MCW_TIMER_KILL ) ;
7994          BEEPIT ; EXRETURN ;
7995       }
7996 
7997       POPDOWN_ovcolor_chooser ;
7998 
7999       im3d->vwid->prog->hidden_code =
8000         (w == im3d->vwid->prog->hidden_writepts_ijk_pb) ? PTS_WRITE_IJK
8001                                                         : PTS_WRITE_XYZ ;
8002 
8003       MCW_choose_string( im3d->vwid->picture ,
8004 
8005             (im3d->vwid->prog->hidden_code == PTS_WRITE_IJK)
8006               ? "Enter IJK output filename:"
8007               : "Enter XYZ output filename:" ,
8008 
8009             NULL , AFNI_hidden_pts_CB , cd ) ;
8010    }
8011 
8012    /****----- Show points -----****/
8013 
8014    else if( w == im3d->vwid->prog->hidden_colorpts_pb ){
8015 
8016       POPDOWN_string_chooser ;
8017 
8018       im3d->vwid->prog->hidden_code = PTS_SET_COLOR ;
8019 
8020       MCW_choose_ovcolor( im3d->vwid->picture ,
8021                           im3d->dc ,
8022                           im3d->vinfo->pts_color ,
8023                           AFNI_hidden_pts_CB , cd  ) ;
8024    }
8025 #endif /* ALLOW_DATASET_VLIST */
8026 
8027    /****----- Mission Statement -----****/
8028 
8029    if( w == im3d->vwid->prog->hidden_mission_pb ){
8030       (void)  MCW_popup_message( im3d->vwid->picture ,
8031                                     " \n"
8032                                     " AFNI Mission Statement\n"
8033                                     " ----------------------\n"
8034                                     " To empower neuroscientists\n"
8035                                     " to perform their own state-\n"
8036                                     " of-the-art data analyses and\n"
8037                                     " visualizations, so they will \n"
8038                                     " stop bugging me with their\n"
8039                                     " pitiful 'quick questions'.\n " ,
8040                                  MCW_USER_KILL | MCW_TIMER_KILL ) ;
8041    }
8042 
8043    else if( w == im3d->vwid->prog->hidden_uscon_pb ){  /* 30 Dec 2010 */
8044      char *inf=NULL ; int ii ;
8045      for( ii=0 ; uscon[ii] != NULL ; ii++ )
8046        inf = THD_zzprintf( inf , " %s" , uscon[ii] ) ;
8047      (void) new_MCW_textwin( im3d->vwid->imag->topper , inf , TEXT_READONLY ) ;
8048      free(inf) ;
8049    }
8050 
8051    else if( w == im3d->vwid->prog->hidden_usdecl_pb ){  /* 06 Jan 2011 */
8052      char *inf=NULL ; int ii ;
8053      for( ii=0 ; usdecl[ii] != NULL ; ii++ )
8054        inf = THD_zzprintf( inf , " %s" , usdecl[ii] ) ;
8055      (void) new_MCW_textwin( im3d->vwid->imag->topper , inf , TEXT_READONLY ) ;
8056      free(inf) ;
8057    }
8058 
8059    else if( w == im3d->vwid->prog->hidden_melter_pb ){   /* 18 Feb 2011 */
8060      MCW_melt_widget( im3d->vwid->top_form ) ;
8061      if( GLOBAL_library.have_sox && GLOBAL_library.local_display )
8062        AFNI_startup_sound(1) ;
8063      NI_sleep(111) ;
8064      if( GLOBAL_library.have_sox && GLOBAL_library.local_display )
8065        AFNI_startup_sound(1) ;
8066      MCW_set_widget_label(w,"Omega-13 is one use") ; SENSITIZE(w,0) ;
8067    }
8068 
8069    else if( w != NULL && w == im3d->vwid->prog->hidden_sound_pb ){ /* 20 Aug 2018 */
8070      if( GLOBAL_library.have_sox && GLOBAL_library.local_display ){
8071        AFNI_startup_sound(1) ;
8072        AFNI_startup_sound(1) ;
8073      } else {
8074        WARNING_message("sound playing not available :(") ;
8075      }
8076    }
8077 
8078    else if( w != NULL && w == im3d->vwid->prog->hidden_music_pb ){ /* 07 Aug 2019 */
8079      if( GLOBAL_library.sound_player != NULL && GLOBAL_library.local_display ){
8080         static int ncall=0 ;
8081         int nmusic = (int)AFNI_numenv("AFNI_MUSIC_SIZE") ;
8082         MRI_IMAGE *qim ; float *qar ; int ii ;
8083              if( nmusic <     4 ) nmusic = 321 ;
8084         else if( nmusic > 99999 ) nmusic = 99999 ;
8085         if( ncall == 0 )
8086           ININFO_message("Computing random music notes - about %d seconds worth",
8087                          (int)(nmusic*0.095f)) ;
8088         qim = jRandom1D(nmusic,2); qar = MRI_FLOAT_PTR(qim);        /* random */
8089         if( nmusic < 99 ) osfilt3_func( 2*nmusic , 0.0,1.0 , qar ); /* smooth */
8090         else              adpt_wt_mn9 ( 2*nmusic , 0.0,1.0 , qar );
8091         for( ii=0 ; ii < nmusic ; ii++ )                         /* correlate */
8092           qar[ii] += 0.222f * qar[ii+nmusic] ;
8093         mri_sound_play_append( "reverb 99 fade 0 0 2" );   /* sox only */
8094         if( ncall == 0 ) mri_play_sound_notify(1) ;    /* only the first time */
8095         mri_play_sound_rate_fac( 1.2468f ) ;
8096         mri_play_sound(qim,0) ;                 /* let the music sound forth! */
8097         mri_free(qim) ;                                       /* some cleanup */
8098         mri_sound_play_append( NULL ) ;
8099         mri_play_sound_notify(0) ;
8100         mri_play_sound_rate_fac( 1.0f ) ;
8101         ncall++ ;
8102      } else {
8103        WARNING_message("sound playing not available :(") ;
8104      }
8105    }
8106 
8107    else if( w == im3d->vwid->prog->hidden_gamberi_pb ){
8108      AFNI_speak( "The Rime of the Gamberi Cattivi" , 0 ) ;
8109      (void) MCW_popup_message( im3d->vwid->imag->topper ,
8110        " \n"
8111        "       The Rime of the Ancient Gamberi Cattivi\n"
8112        "       (with apologies to Coleridge and Dante)\n"
8113        "      -----------------------------------------\n\n"
8114        " Illuminato dal sole toscano,\n"
8115        " volsi lo sguardo all'orizzonte;\n"
8116        " nel mare bagnavo la mano,\n"
8117        " e al cielo volgevo la fronte.\n"
8118        " \n"
8119        " D'improvviso dal mare schiumante,\n"
8120        " due gamberi killer cattivi si avvicinarono.\n"
8121        " Uno stiletto mi poser d'innante,\n"
8122        " mentre i lunghi baffi neri si accarezzavano.\n"
8123        " \n"
8124        " Il piu giovane ordino:\n"
8125        "  \"La macchina fotografica dalla giacca sgancia!\"\n"
8126        " mentre la lama premeva forte la guancia.\n"
8127        " Prima di dichiarare \"Del Governo e proprieta,\n"
8128        " sul mio corpo il nemico passar dovra!\",\n"
8129        " il gambero malvagio nella bocca la camera si fionda\n"
8130        " e del Tirreno scuro e profondo ritorna a prender l'onda.\n"
8131        " \n"
8132        " Roberto Cox \"il Magnifico\" di Milwaukee e il dottor Emiliano\n"
8133        " corrono al grido di Ziad, ma e tutto invano.\n"
8134        " \n"
8135        " Ai nostri eroi non resta che accettare l'accaduto,\n"
8136        " e a tutta Italia AFNI e SUMA insegnare.\n"
8137        " Scusateci se lo stile e un po' caduto,\n"
8138        " ma e la scusa per l'anno prossimo a Pisa ritornare.\n" ,
8139                                  MCW_USER_KILL ) ;
8140    }
8141 
8142    else if( w == im3d->vwid->prog->hidden_hbmjust_pb ){
8143      (void)MCW_popup_message( im3d->vwid->imag->topper ,
8144              "  Why I Must Attend HBM - RWCox\n"
8145              "---------------------------------\n"
8146              "I have been asked to state\n"
8147              "why HBM is great,\n"
8148              "and why it is a must\n"
8149              "that I incur this cost.\n"
8150              "Brain Mappers all converge\n"
8151              "to show their best new work,\n"
8152              "exactly in my field:\n"
8153              "ways to make data yield\n"
8154              "news about brain function,\n"
8155              "providing a conjunction\n"
8156              "of doers and of thinkers --\n"
8157              "ideal for science drinkers.\n"
8158              "This meet is Number One:\n"
8159              "the best come here to run\n"
8160              "their latest, their greatest\n"
8161              "past the world's most smartest.\n"
8162              "There is where I can see\n"
8163              "what's new and important to me\n"
8164              "in my work for the NIMH\n"
8165              "and to show them my batch\n"
8166              "of newly warped brains\n"
8167              "and how this entrains\n"
8168              "a new way to make\n"
8169              "FMRI a piece of (nonlinear) cake.\n" , MCW_USER_KILL ) ;
8170    }
8171 
8172    else if( w == im3d->vwid->prog->hidden_ranpoem_pb ){
8173      static int *dold=NULL, ndold=0 ; int qq,dd ;
8174      char *poem ;
8175 
8176      if( num_poem < 0 ) EXRETURN ;
8177      if( num_poem == 0 ){
8178        AFNI_find_poem_files() ;
8179        if( num_poem <= 0 ){ num_poem = -1 ; EXRETURN ; }
8180      }
8181      if( ndold == 0 && num_poem > 1 ){
8182        ndold = num_poem/2 ;
8183        dold  = (int *) malloc(sizeof(int)*ndold) ;
8184        for( qq=0 ; qq < ndold ; qq++ ) dold[qq] = -1 ;
8185      }
8186    Retry_dd:
8187      dd = (lrand48() >> 8) % num_poem ;              /* pick random file */
8188      if( num_poem > 1 ){                       /* check if used recently */
8189        for( qq=0 ; qq < ndold && dold[qq] != dd ; qq++ ) ;       /* nada */
8190        if( qq < ndold ) goto Retry_dd ;                    /* was recent */
8191        for( qq=1 ; qq < ndold ; qq++ )        /* wasn't, so save in list */
8192          dold[qq-1] = dold[qq] ;
8193        dold[ndold-1] = dd ;
8194      }
8195      poem = AFNI_suck_file( fname_poem[dd] ) ;
8196      if( poem == NULL ) EXRETURN ;
8197      (void) MCW_popup_message( im3d->vwid->imag->topper, poem, MCW_USER_KILL );
8198      free( poem ) ;
8199    }
8200 
8201    /*------ Faces!  [17 Dec 2004] -----*/
8202 
8203    else if( w == im3d->vwid->prog->hidden_faces_pb && w != NULL ){
8204 
8205      AFNI_faceup() ;
8206    }
8207 
8208    /*------ Splashes!  [12 Sep 2007] -----*/
8209 
8210    else if( w == im3d->vwid->prog->hidden_splashes_pb && w != NULL ){
8211 
8212      AFNI_allsplash() ;
8213    }
8214 
8215    /*------ Browser [22 Apr 2005] -----*/
8216 
8217    else if( w == im3d->vwid->prog->hidden_browser_pb && w != NULL &&
8218             GLOBAL_browser != NULL ){
8219      whereami_browser("https://afni.nimh.nih.gov/afni/doc/program_help/index.html");
8220 #if 0
8221      char cmd[2345] ;
8222      sprintf(cmd ,
8223              "%s https://afni.nimh.nih.gov/afni/doc/program_help/index.html &" ,
8224              GLOBAL_browser ) ;
8225      system(cmd) ;
8226 #endif
8227    }
8228 
8229    /*------- random speaking --------*/
8230 
8231    else if( w == im3d->vwid->prog->hidden_speech_pb && w != NULL ){
8232      static char *words[] = { "What do you want?"               ,
8233                               "Nice to see you"                 ,
8234                               "Words fail me now"               ,
8235                               "I do not know what to say"       ,
8236                               "How are you feeling?"            ,
8237                               "Do you like, afnee?"             ,
8238                               "Do you use ess, pee, emm?"       ,
8239                               "Do you use eff, ess, ell?"       ,
8240                               "Exercise your hippocampus daily"
8241                             } ;
8242      if( AFNI_noenv("AFNI_SPEECH") )
8243        BEEPIT ;
8244      else {
8245        static int nold=-1 ;
8246        int nn = sizeof(words)/sizeof(char *) , jj ;
8247        do{ jj = lrand48()%nn ; } while( jj == nold ) ;
8248        AFNI_speak( words[jj] , 1 ) ; nold = jj ;
8249      }
8250    }
8251 
8252    /****----- Get Outta Here -----****/
8253 
8254    EXRETURN ;
8255 }
8256 
8257 /*--------------------------------------------------------------------------*/
8258 
AFNI_find_poem_files(void)8259 static void AFNI_find_poem_files(void)  /* 15 Oct 2003 */
8260 {
8261    char *epath , *elocal , *eee ;
8262    char edir[THD_MAX_NAME] , fdir[THD_MAX_NAME] , *udir , **ename ;
8263    int epos , ll , ii , id , npoem , nep ;
8264    char **fpoem ;
8265 
8266 ENTRY("AFNI_find_poem_files") ;
8267 
8268    if( num_poem != 0 ) EXRETURN ; /* should never happen */
8269 
8270    /*----- get path to search -----*/
8271 
8272                        epath = getenv("AFNI_PLUGINPATH") ;
8273    if( epath == NULL ) epath = getenv("AFNI_PLUGIN_PATH") ;
8274    if( epath == NULL ) epath = getenv("PATH") ;
8275    if( epath == NULL ){ num_poem=-1; EXRETURN ; }
8276 
8277    /*----- copy path list into local memory -----*/
8278 
8279    ll = strlen(epath) ;
8280    elocal = AFMALL( char,  sizeof(char) * (ll+2) ) ;
8281 
8282    /*----- put a blank at the end -----*/
8283 
8284    strcpy( elocal , epath ) ; elocal[ll] = ' ' ; elocal[ll+1] = '\0' ;
8285 
8286    /*----- replace colons with blanks -----*/
8287 
8288    for( ii=0 ; ii < ll ; ii++ )
8289       if( elocal[ii] == ':' ) elocal[ii] = ' ' ;
8290 
8291 
8292    /*----- extract blank delimited strings;
8293            use as directory names to look for files -----*/
8294 
8295    ename    = (char **) malloc(sizeof(char *)*2) ;
8296    ename[0] = (char *)  malloc(THD_MAX_NAME) ;
8297    ename[1] = (char *)  malloc(THD_MAX_NAME) ;
8298 
8299    epos = 0 ;
8300 
8301    do{
8302       ii = sscanf( elocal+epos , "%s%n" , edir , &id ); /* next substring */
8303       if( ii < 1 ) break ;                              /* none -> done   */
8304 
8305       /** check if edir occurs earlier in elocal **/
8306 
8307       eee = strstr( elocal , edir ) ;
8308       if( eee != NULL && (eee-elocal) < epos ){ epos += id ; continue ; }
8309 
8310       epos += id ;                                 /* char after last scanned */
8311 
8312       ii = strlen(edir) ;                          /* make sure name has   */
8313       if( edir[ii-1] != '/' ){                     /* a trailing '/' on it */
8314         edir[ii]  = '/' ; edir[ii+1] = '\0' ;
8315       }
8316 
8317       strcpy(fdir,edir) ; strcat(fdir,"funstuff") ;  /* 07 Oct 2011 */
8318       if( THD_is_directory(fdir) ){ strcat(fdir,"/"); udir = fdir; } else { udir = edir; }
8319 
8320       strcpy(ename[0],udir) ;
8321       strcat(ename[0],"poem_*.txt") ;        /* add filename pattern */
8322       nep = 1 ;
8323 
8324       MCW_file_expand( nep,ename, &npoem , &fpoem );   /* find files that match */
8325       if( npoem <= 0 ) continue ;                     /* no files found */
8326 
8327       /** add files we found to list **/
8328 
8329       if( fname_poem == NULL )
8330         fname_poem = (char **)malloc(sizeof(char *)*npoem) ;
8331       else
8332         fname_poem = (char **)realloc(fname_poem,sizeof(char *)*(num_poem+npoem));
8333 
8334       for( ii=0 ; ii < npoem ; ii++ ){
8335         fname_poem[num_poem++] = strdup(fpoem[ii]) ;
8336 
8337         if( udir == fdir ){          /* 07 Oct 2011 */
8338           char qnam[THD_MAX_NAME] ;
8339           strcpy(qnam,edir) ; strcat(qnam,THD_trailname(fpoem[ii],0)) ;
8340           if( THD_is_file(qnam) ) remove(qnam) ;
8341         }
8342       }
8343 
8344       MCW_free_expand( npoem , fpoem ) ;
8345 
8346    } while( epos < ll ) ;  /* scan until 'epos' is after end of epath */
8347 
8348    free(elocal) ; free(ename[0]) ; free(ename[1]) ; free(ename) ;
8349 
8350    if( num_poem == 0 ) num_poem = -1 ;
8351    EXRETURN ;
8352 }
8353 
8354 /*---------------------------------------------------------------------------*/
8355 /* 18 Feb 2014 */
8356 
8357 #ifdef USE_SKIT
AFNI_alter_controller_bg(Three_D_View * im3d,float fac)8358 static void AFNI_alter_controller_bg( Three_D_View *im3d , float fac )
8359 {
8360    if( !IM3D_OPEN(im3d) || fac < 0.0f || fac > 2.0f ) return ;
8361    MCW_scale_widget_bg( im3d->vwid->top_form, fac, im3d->dc ) ;
8362    return ;
8363 }
8364 #endif
8365 
8366 /*-----------------------------------------------------------------
8367   Event handler to find #3 button press for hidden popup
8368 -------------------------------------------------------------------*/
8369 
AFNI_hidden_EV(Widget w,XtPointer cd,XEvent * ev,RwcBoolean * continue_to_dispatch)8370 void AFNI_hidden_EV( Widget w , XtPointer cd ,
8371                     XEvent *ev , RwcBoolean *continue_to_dispatch )
8372 {
8373    Three_D_View *im3d = (Three_D_View *) cd ;
8374 
8375 ENTRY("AFNI_hidden_EV") ;
8376 
8377    if( ! IM3D_OPEN(im3d) ) EXRETURN ;
8378 
8379    /*** handle events ***/
8380 
8381    switch( ev->type ){
8382 
8383       /*----- take button press -----*/
8384 
8385       case ButtonPress:{
8386          XButtonEvent *event = (XButtonEvent *) ev ;
8387 
8388          if( event->button == Button3 ||
8389              (event->button == Button1 &&
8390               (event->state & (ShiftMask|ControlMask))) ){
8391 
8392             im3d->vwid->butx = event->x_root ;  /* 17 May 2005 */
8393             im3d->vwid->buty = event->y_root ;
8394             event->button    = Button3 ;                              /* fakeout */
8395             XmMenuPosition( im3d->vwid->prog->hidden_menu , event ) ; /* where */
8396             XtManageChild ( im3d->vwid->prog->hidden_menu ) ;         /* popup */
8397          }
8398 #ifdef WANT_RWCOX_IMAGE
8399          else if( !NO_frivolities && event->button == Button1 ) RWCOX_popper() ;
8400 #endif
8401 
8402 #ifdef USE_SKIT
8403          else if( !NO_frivolities && event->button == Button2 ) SKIT_popper(im3d) ;
8404          else if( !NO_frivolities && event->button == Button4 ) AFNI_alter_controller_bg(im3d,0.960000f) ;
8405          else if( !NO_frivolities && event->button == Button5 ) AFNI_alter_controller_bg(im3d,1.041667f) ;
8406 #endif
8407       }
8408       break ;
8409 
8410       /*----- take key press [09 Sep 2002] -----*/
8411 
8412       case KeyPress:{
8413          XKeyEvent *event = (XKeyEvent *) ev ;
8414          char           buf[32] ;
8415          KeySym         ks ;
8416          int            nbuf ;
8417 
8418          buf[0] = '\0' ;
8419          nbuf = XLookupString( event , buf , 32 , &ks , NULL ) ;
8420 
8421          switch( buf[0] ){
8422            case 'Q':
8423              exit(0) ;                         /* Death Now! */
8424 
8425            case 'q':
8426              AFNI_quit_CB( w , im3d, NULL ) ;  /* Close just this controller */
8427            break ;
8428 
8429            case 'f':
8430            case 'F':
8431              AFNI_faceup() ;                   /* Faces! [27 Dec 2004] */
8432            break ;
8433 
8434            case 'p':
8435            case 'P':
8436              AFNI_hidden_CB( im3d->vwid->prog->hidden_ranpoem_pb ,
8437                              (XtPointer)im3d , NULL ) ;
8438            break ;
8439 
8440            case 'g':
8441            case 'G':
8442              AFNI_hidden_CB( im3d->vwid->prog->hidden_gamberi_pb ,
8443                              (XtPointer)im3d , NULL ) ;
8444            break ;
8445          }
8446       }
8447       break ;
8448    }
8449 
8450    EXRETURN ;
8451 }
8452 
8453 /*-------------------------------------------------------------------*/
8454 
8455 #ifdef ALLOW_DATASET_VLIST
AFNI_hidden_pts_CB(Widget w,XtPointer cd,MCW_choose_cbs * cbs)8456 void AFNI_hidden_pts_CB( Widget w , XtPointer cd , MCW_choose_cbs *cbs )
8457 {
8458    Three_D_View *im3d = (Three_D_View *) cd ;
8459    THD_3dim_dataset *dset_now ;
8460    THD_fvec3 xyz_vec ;
8461    THD_ivec3 ijk_vec ;
8462    RwcBoolean ijk_option , pause_it ;
8463    FILE *fil ;
8464    THD_vector_list *sv ;
8465    int ii ;
8466 
8467 ENTRY("AFNI_hidden_pts_CB") ;
8468 
8469    if( ! IM3D_OPEN(im3d) ) EXRETURN ;
8470    dset_now = im3d->anat_now ;
8471    if( ! ISVALID_3DIM_DATASET(dset_now) ) EXRETURN ;
8472 
8473    ijk_option = False ;
8474    switch( im3d->vwid->prog->hidden_code ){  /* action set by user */
8475 
8476       /*---- Set Color ----*/
8477 
8478       case PTS_SET_COLOR:
8479          im3d->vinfo->pts_color   = cbs->ival ;
8480          im3d->vinfo->pts_visible = (cbs->ival > 0) ? True : False ;
8481          AFNI_set_viewpoint( im3d , -1,-1,-1 , REDISPLAY_OVERLAY ) ;  /* redraw */
8482       break ;
8483 
8484       /*---- READ pts int ----*/
8485 
8486       case PTS_READ_IJK:
8487          ijk_option = True ;   /* fall thru on purpose */
8488 
8489       case PTS_READ_XYZ:
8490 
8491          /** open input file **/
8492 
8493          fil = fopen( cbs->cval , "r" ) ;
8494          if( fil == NULL ){
8495             char buf[256] ;
8496             sprintf(buf,"Cannot open file\n %s\nfor reading!",cbs->cval) ;
8497             (void)  MCW_popup_message( im3d->vwid->picture , buf ,
8498                                        MCW_USER_KILL | MCW_TIMER_KILL ) ;
8499             BEEPIT ; EXRETURN ;
8500          }
8501 
8502          POPDOWN_string_chooser ;
8503 
8504          pause_it = ( THD_filesize(cbs->cval) > 99999 ) ;
8505          if( pause_it ) SHOW_AFNI_PAUSE ;
8506 
8507          /** read points **/
8508 
8509          INIT_VLIST(sv,dset_now) ;
8510          do {
8511             if( ijk_option )
8512                ii = fscanf( fil , " %d %d %d\n",
8513                      &(ijk_vec.ijk[0]),&(ijk_vec.ijk[1]),&(ijk_vec.ijk[2])) ;
8514             else
8515                ii = fscanf( fil , " %f %f %f\n",
8516                      &(xyz_vec.xyz[0]),&(xyz_vec.xyz[1]),&(xyz_vec.xyz[2])) ;
8517 
8518             if( ii == 3 ){                         /* all 3 good! */
8519                if( ijk_option ){ ADD_IVEC_TO_VLIST(sv,ijk_vec) ; }
8520                else            { ADD_FVEC_TO_VLIST(sv,xyz_vec) ; }
8521             } else if( ii == EOF ){                /* end of data! */
8522                fclose(fil) ;
8523                break ;                             /* exit do loop */
8524             } else {
8525                char buf[256] ;                     /* bad data! */
8526                fclose(fil) ;
8527                sprintf(buf,"Bad read in file\n %s\nat point # %d",
8528                        cbs->cval , sv->num + 1 ) ;
8529                (void)  MCW_popup_message( im3d->vwid->picture , buf ,
8530                                           MCW_USER_KILL | MCW_TIMER_KILL ) ;
8531                DESTROY_VLIST(sv) ;
8532                BEEPIT ; EXRETURN ;
8533             }
8534          } while (1) ;
8535 
8536          /** destroy any point sets in all current datasets **/
8537 
8538          for( ii=0 ; ii <= LAST_VIEW_TYPE ; ii++ ){
8539             if( ISVALID_3DIM_DATASET(im3d->anat_dset[ii]) ){
8540                DESTROY_VLIST( im3d->anat_dset[ii]->pts ) ;
8541                im3d->anat_dset[ii]->pts_original = False ;
8542             }
8543          }
8544 
8545          /** put new point set into current dataset **/
8546 
8547          dset_now->pts          = sv ;
8548          dset_now->pts_original = True ;
8549 
8550          AFNI_set_viewpoint( im3d , -1,-1,-1 , REDISPLAY_OVERLAY ) ;
8551          if( pause_it ) SHOW_AFNI_READY ;
8552       break ;  /* end of read pts */
8553 
8554       /*---- WRITE pts out ----*/
8555 
8556       case PTS_WRITE_IJK:
8557          ijk_option = True ;   /* fall thru on purpose */
8558 
8559       case PTS_WRITE_XYZ:
8560 
8561          sv = im3d->anat_now->pts ;
8562          if( sv == NULL || sv->num == 0 ){
8563             BEEPIT ; WARNING_message("Can't write -- no points!") ; EXRETURN ;
8564          }
8565 
8566          if( cbs->cval[0] == '|' ){  /* send to standard output */
8567             fil = stdout ;
8568          } else {
8569             if( THD_is_file(cbs->cval) ){
8570                char buf[256] ;
8571                sprintf(buf,"Desired output file\n %s\nalready exists!",cbs->cval);
8572                (void)  MCW_popup_message( im3d->vwid->picture , buf ,
8573                                           MCW_USER_KILL | MCW_TIMER_KILL ) ;
8574                BEEPIT ; EXRETURN ;
8575             }
8576 
8577             fil = fopen( cbs->cval , "w" ) ;
8578             if( fil == NULL ){
8579                char buf[256] ;
8580                sprintf(buf,"Cannot open file\n %s\nfor writing!",cbs->cval) ;
8581                (void)  MCW_popup_message( im3d->vwid->picture , buf ,
8582                                           MCW_USER_KILL | MCW_TIMER_KILL ) ;
8583                BEEPIT ; EXRETURN ;
8584             }
8585          }
8586 
8587          POPDOWN_string_chooser ;
8588 
8589          pause_it = ( sv->num > 6666 ) ;
8590          if( pause_it ) SHOW_AFNI_PAUSE ;
8591 
8592          if( ijk_option ){
8593             for( ii=0 ; ii < sv->num ; ii++ )
8594                fprintf(fil,"%d %d %d\n", sv->ijk[ii].ijk[0],
8595                                          sv->ijk[ii].ijk[1],
8596                                          sv->ijk[ii].ijk[2]  ) ;
8597          } else {
8598             for( ii=0 ; ii < sv->num ; ii++ )
8599                fprintf(fil,"%g %g %g\n", sv->xyz[ii].xyz[0],
8600                                          sv->xyz[ii].xyz[1],
8601                                          sv->xyz[ii].xyz[2]  ) ;
8602          }
8603 
8604          if( fil != stdout ) fclose(fil) ;
8605          if( pause_it ) SHOW_AFNI_READY ;
8606       break ;  /* end of write pts */
8607 
8608    } /* end of switch */
8609 
8610    EXRETURN ;
8611 }
8612 #endif
8613 
8614 /*====================================================================================*/
8615 #if defined(WANT_RWCOX_IMAGE) && defined(ALLOW_PLUGINS)
8616 
RWCOX_popper(void)8617 void RWCOX_popper(void)
8618 {
8619    AFNI_splashup() ;
8620    return ;
8621 }
8622 #endif /* WANT_RWCOX_IMAGE */
8623 /*====================================================================================*/
8624 #ifdef USE_SKIT
8625 #define NSKIT 50
8626 static char *skit[NSKIT][3] = {
8627    "artless" ,       "base-court" ,        "apple-john" ,
8628    "bawdy" ,         "bat-fowling" ,       "baggage" ,
8629    "beslubbering" ,  "beef-witted" ,       "barnacle" ,
8630    "bootless" ,      "beetle-headed" ,     "bladder" ,
8631    "churlish" ,      "boil-brained" ,      "boar-pig" ,
8632    "cockered" ,      "clapper-clawed" ,    "bugbear" ,
8633    "clouted" ,       "clay-brained" ,      "bum-bailey" ,
8634    "craven" ,        "common-kissing" ,    "canker-blossom" ,
8635    "currish" ,       "crook-pated" ,       "clack-dish" ,
8636    "dankish" ,       "dismal-dreaming" ,   "clotpole" ,
8637    "dissembling" ,   "dizzy-eyed" ,        "coxcomb" ,
8638    "droning" ,       "doghearted" ,        "codpiece" ,
8639    "errant" ,        "dread-bolted" ,      "death-token" ,
8640    "fawning" ,       "earth-vexing" ,      "dewberry" ,
8641    "fobbing" ,       "elf-skinned" ,       "flap-dragon" ,
8642    "froward" ,       "fat-kidneyed" ,      "flax-wench" ,
8643    "frothy" ,        "fen-sucked" ,        "flirt-gill" ,
8644    "gleeking" ,      "flap-mouthed" ,      "foot-licker" ,
8645    "goatish" ,       "fly-bitten" ,        "fustilarian" ,
8646    "gorbellied" ,    "folly-fallen" ,      "giglet" ,
8647    "impertinent" ,   "fool-born" ,         "gudgeon" ,
8648    "infectious" ,    "full-gorged" ,       "haggard" ,
8649    "jarring" ,       "guts-griping" ,      "harpy" ,
8650    "loggerheaded" ,  "half-faced" ,        "hedge-pig" ,
8651    "lumpish" ,       "hasty-witted" ,      "horn-beast" ,
8652    "mammering" ,     "hedge-born" ,        "hugger-mugger" ,
8653    "mangled" ,       "hell-hated" ,        "joithead" ,
8654    "mewling" ,       "idle-headed" ,       "lewdster" ,
8655    "paunchy" ,       "ill-breeding" ,      "lout" ,
8656    "pribbling" ,     "ill-nurtured" ,      "maggot-pie" ,
8657    "puking" ,        "knotty-pated" ,      "malt-worm" ,
8658    "puny" ,          "milk-livered" ,      "mammet" ,
8659    "qualling" ,      "motley-minded" ,     "measle" ,
8660    "rank" ,          "onion-eyed" ,        "minnow" ,
8661    "reeky" ,         "plume-plucked" ,     "miscreant" ,
8662    "roguish" ,       "pottle-deep" ,       "moldwarp" ,
8663    "ruttish" ,       "pox-marked" ,        "mumble-news" ,
8664    "saucy" ,         "reeling-ripe" ,      "nut-hook" ,
8665    "spleeny" ,       "rough-hewn" ,        "pigeon-egg" ,
8666    "spongy" ,        "rude-growing" ,      "pignut" ,
8667    "surly" ,         "rump-fed" ,          "puttock" ,
8668    "tottering" ,     "shard-borne" ,       "pumpion" ,
8669    "unmuzzled" ,     "sheep-biting" ,      "ratsbane" ,
8670    "vain" ,          "spur-galled" ,       "scut" ,
8671    "venomed" ,       "swag-bellied" ,      "skainsmate" ,
8672    "villainous" ,    "tardy-gaited" ,      "strumpet" ,
8673    "warped" ,        "tickle-brained" ,    "varlet" ,
8674    "wayward" ,       "toad-spotted" ,      "vassal" ,
8675    "weedy" ,         "unchin-snouted" ,    "whey-face" ,
8676    "yeasty" ,        "weather-bitten" ,    "wagtail"
8677 } ;
8678 
8679 static char skstr[512] ;
8680 
SKIT_popper(Three_D_View * im3d)8681 void SKIT_popper(Three_D_View *im3d)
8682 {
8683    int ii,jj,kk ;
8684 
8685    if( !IM3D_OPEN(im3d) ) return ;
8686 
8687    ii = lrand48() % NSKIT ; jj = lrand48() % NSKIT ; kk = lrand48() % NSKIT ;
8688    sprintf(skstr,"Randomly generated Shakespearean Insult:\n\n"
8689                  " Thou %s %s %s! \n" ,
8690            skit[ii][0] , skit[jj][1] , skit[kk][2] ) ;
8691 
8692    if( lrand48()%7 == 0 ){
8693       ii = strlen(skstr) ;
8694       sprintf( skstr+ii , "\n  [Data provided by Sandy Kindermann]" ) ;
8695    }
8696 
8697    (void)  MCW_popup_message( im3d->vwid->picture , skstr ,
8698                               MCW_USER_KILL | MCW_TIMER_KILL ) ;
8699 }
8700 #endif /* USE_SKIT */
8701 /*====================================================================================*/
8702 
8703 #endif /* USE_HIDDEN */
8704