1 
2 /*-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+*/
3 /*   This is the mother goddess of all FMRI programs, so bow down before it!  */
4 /*-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+*/
5 /*   Look on my works, Ye Mighty, and despair!                                */
6 /*-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+*/
7 
8 /*****************************************************************************
9    Major portions of this software are copyrighted by the Medical College
10    of Wisconsin, 1994-2000, and are released under the Gnu General Public
11    License, Version 2 (or later).  See the file README.Copyright for details.
12 ******************************************************************************/
13 
14 /**********************************************************************/
15 /* MCW/GPL/NIH AFNI:                                                  */
16 /*    Analysis of Functional NeuroImages                              */
17 /*                                                                    */
18 /* Author: Robert W. Cox, PhD                                         */
19 /*         Scientific and Statistical Computing Core                  */
20 /*         National Institute of Mental Health                        */
21 /*         Bethesda, MD 20892  USA                                    */
22 /*                                                                    */
23 /* Acknowledgments:                                                   */
24 /*   + This program would have been much more difficult had           */
25 /*     not Andrzej Jesmanowicz forged the way with FD.                */
26 /*   + Many neuroscientists have made helpful suggestions along       */
27 /*     the way, including Jeff Binder, Ted DeYoe, Jim Hyde, Steve     */
28 /*     Rao, and Elliot Stein.                                         */
29 /*   + Thanks are also due to Mike Beauchamp, who is perhaps the most */
30 /*     sophisticated user of AFNI that I've met, and who has found    */
31 /*     many bugs or gotchas in this code.                             */
32 /*   + Doug Ward of MCW has contributed much to the overall package.  */
33 /*   + Ziad Saad of NIH has also contributed many useful suggestions. */
34 /*   + Peter Bandettini of NIH has asked many many "quick" questions. */
35 /*   + Sean and Alex Bellgowan have contributed in their own way.     */
36 /**********************************************************************/
37 
38 /* the definition below is used in some header files,
39    and it indicates that the main() program is in this file */
40 
41 #define MAIN
42 
43 #include "afni.h"
44 #include <X11/keysym.h>  /* 20 Feb 2003 */
45 #include "afni_plugout.h"
46 #include "readme_afnigui.h"
47 #include "readme_env.h"
48 
49 /*------------------------------------------------------*/
50 /* if the compiler wants to 'show off' the name of this
51    edition of AFNI, then turn that macro into a string. */
52 
53 /* SHSTRING comes from mrilib.h via debugtrace.h */
54 
55 #ifdef SHOWOFF
56 # undef  SHSH
57 # undef  SHSHSH
58 # undef  SHSTRING
59 # define SHSH(x)   #x
60 # define SHSHSH(x) SHSH(x)
61 # define SHSTRING  SHSHSH(SHOWOFF)   /* now in "quotes" */
62 #else
63 # undef  SHSTRING
64 #endif
65 /*------------------------------------------------------*/
66 
67 #if 0  /* ANNOUNCEMENT IS NOT USED  28 Dec 2015 [rickr] */
68 #ifdef SHSTRING
69 
70 #define ANNOUNCEMENT                                                           \
71  "GPL AFNI: Analysis of Functional NeuroImages, by RW Cox (" COXEMAIL ")\n"    \
72  "This is Version " VERSION               "\n"                                 \
73  "[[Precompiled binary " SHSTRING ": " __DATE__ "]]\n\n"                       \
74  " ** This software was designed to be used only for research purposes. **\n"  \
75  " ** Clinical uses are not recommended, and have never been evaluated. **\n"  \
76  " ** This software comes with no warranties of any kind whatsoever,    **\n"  \
77  " ** and may not be useful for anything.  Use it at your own risk!     **\n"  \
78  " ** If these terms are not acceptable, you aren't allowed to use AFNI.**\n"  \
79  " ** See 'Define Datamode->Misc->License Info' for more details.       **\n\n"\
80  " **** If you DO find AFNI useful, please cite this paper:\n"                 \
81  "    RW Cox. AFNI: Software for analysis and visualization of\n"              \
82  "    functional magnetic resonance neuroimages.\n"                            \
83  "    Computers and Biomedical Research, 29:162-173, 1996.\n\n"                \
84  " **** If you find SUMA useful, citing this paper also would be nice:\n"      \
85  "    ZS Saad, RC Reynolds, B Argall, S Japee, RW Cox.\n"                      \
86  "    SUMA: An Interface For Surface-Based Intra- And Inter-Subject Analysis\n"\
87  "    With AFNI. 2nd IEEE International Symposium on Biomedical Imaging:\n"    \
88  "    Macro to Nano 2, 1510-1513, 2004.\n\n"
89 
90 #else
91 
92 #define ANNOUNCEMENT                                                           \
93  "GPL AFNI: Analysis of Functional NeuroImages, by RW Cox (" COXEMAIL ")\n"    \
94  "This is Version " AVERZHN " -- compiled " __DATE__  "\n\n"                   \
95  " ** This software was designed to be used only for research purposes. **\n"  \
96  " ** Clinical uses are not recommended, and have never been evaluated. **\n"  \
97  " ** This software comes with no warranties of any kind whatsoever,    **\n"  \
98  " ** and may not be useful for anything.  Use it at your own risk!     **\n"  \
99  " ** If these terms are not acceptable, you aren't allowed to use AFNI.**\n"  \
100  " ** See 'Define Datamode->Misc->License Info' for more details.       **\n\n"\
101  " **** If you DO find AFNI useful, please cite this paper:\n"                 \
102  "    RW Cox. AFNI: Software for analysis and visualization of\n"              \
103  "    functional magnetic resonance neuroimages.\n"                            \
104  "    Computers and Biomedical Research, 29:162-173, 1996.\n\n"                \
105  " **** If you find SUMA useful, citing this paper also would be nice:\n"      \
106  "    ZS Saad, RC Reynolds, B Argall, S Japee, RW Cox.\n"                      \
107  "    SUMA: An Interface For Surface-Based Intra- And Inter-Subject Analysis\n"\
108  "    With AFNI. 2nd IEEE International Symposium on Biomedical Imaging:\n"    \
109  "    Macro to Nano 2, 1510-1513, 2004.\n\n"
110 
111 #endif /* SHSTRING */
112 #endif /* if 0 - for SHSTRING and ANNOUNCEMENT */
113 
114 /*------------------------------------------------------*/
115 
116 #ifdef AFNI_DEBUG
117 #  define USE_TRACING
118 #  define REPORT_PROGRESS(str)  /* nada */
119 #else
120 #  define REPORT_PROGRESS(str)  \
121     do{ if(AFNI_VERBOSE){fputs(str,stderr);fflush(stderr);} } while(0)
122 #endif
123 
124 /*------------------------------------------------------*/
125 
126 #define EMPTY_STRING(str) ((str)[0] = '\0')
127 
128 #undef IMAGEIZE_CROSSHAIRS  /* disable crosshairs drawn into overlay pixels */
129 
130 #define USE_SIDES  /* 01 Dec 1999: replace "left is xxx" */
131                    /* labels with "sides" labels.        */
132 
133 void AFNI_print_startup_tip(int) ;
134 
135 #include "afni_startup_tips.h"  /* where the tips and goodbye messages live */
136 
137 int num_bysub     = 0 ;     /* 01 Feb 2018 */
138 char **bysub      = NULL ;
139 int num_bysub_dir = 0 ;     /* 15 Apr 2019 */
140 char **bysub_dir  = NULL ;
141 
142 /*-----------------------------------------------------------------------
143    Fallback resources for AFNI.  May be overridden by the user's
144    .Xdefaults file, or other resource sources.  AFNI does not come
145    with an "app-defaults" file, since that would be too much like work.
146    (And would require sysadmin privileges to install.)
147 -------------------------------------------------------------------------*/
148 
149 /*----- things to change the default font sizes -----*/
150 
151 static void AFNI_set_4fonts(char *AA,char *BB, char *CC, char *DD) ;
152 
153 #define XXX_PLUS_FONTS \
154    AFNI_set_4fonts(                                                     \
155      "-adobe-courier-bold-r-normal--24-240-75-75-m-150-iso8859-1"   ,   \
156      "-adobe-courier-bold-r-normal--20-140-100-100-m-110-iso8859-1" ,   \
157      "-adobe-courier-bold-r-normal--17-120-100-100-m-100-iso8859-1" ,   \
158      "-adobe-courier-bold-r-normal--14-100-100-100-m-90-iso8859-1"   )
159 
160 #define XXX_MINUS_FONTS \
161    AFNI_set_4fonts("8x13bold","7x13","6x10","5x8")
162 
163 #define XXX_BIG_FONTS                                                   \
164    AFNI_set_4fonts(                                                     \
165      "-adobe-courier-bold-r-normal--34-240-100-100-m-200-iso8859-1" ,   \
166      "-adobe-courier-bold-r-normal--24-240-75-75-m-150-iso8859-1"   ,   \
167      "-adobe-courier-bold-r-normal--20-140-100-100-m-110-iso8859-1" ,   \
168      "-adobe-courier-bold-r-normal--17-120-100-100-m-100-iso8859-1"  )
169 
170 #define XXX_NORM_FONTS \
171    AFNI_set_4fonts("9x15bold","8x13bold","7x13","6x10")
172 
173 static char *FALLback[] =
174   {   "AFNI*fontList:              9x15bold=charset1"    , /* normal font */
175       "AFNI*pbar*fontList:         6x10=charset1"        , /* next to pbar */
176       "AFNI*imseq*fontList:        7x13=charset1"        , /* on imseq */
177       "AFNI*font8*fontList:        8x13bold=charset1"    , /* smaller fonts */
178       "AFNI*font7*fontList:        7x13=charset1"        ,  /* for various */
179       "AFNI*font6*fontList:        6x10=charset1"        ,  /* usages */
180       "AFNI*background:            gray22"               , /* background clr */
181       "AFNI*menu*background:       gray4"                , /* bkgd in menus */
182       "AFNI*menu*foreground:       #ffdd22"              , /* menu text color */
183       "AFNI*borderColor:           gray19"               , /* same as bkgd! */
184       "AFNI*foreground:            yellow"               , /* normal text */
185       "AFNI*borderWidth:           0"                    , /* don't change! */
186       "AFNI*troughColor:           blue3"                , /* in sliders */
187       "AFNI*XmLabel.translations:  #override<Btn2Down>:" , /* Motif 2.0 bug */
188       "AFNI*help*background:       black"                , /* for help */
189       "AFNI*help*foreground:       #ffffff"              ,
190       "AFNI*help*helpborder:       False"                ,
191       "AFNI*help*waitPeriod:       1066"                 ,
192       "AFNI*help*fontList:         9x15bold=charset1"    ,
193       "AFNI*cluefont:              9x15bold"             , /* for popup */
194       "AFNI*bigtext*fontList:      10x20=charset1"       , /* hints */
195       "AFNI*help*cancelWaitPeriod: 333"                  ,
196 #if 0
197       "AFNI*clustA*fontList:       9x15bold=charset1"    , /* for Clusterize */
198       "AFNI*clustB*fontList:       9x15bold=charset1"    ,
199       "AFNI*clustA*background:     gray22"               ,
200       "AFNI*clustB*background:     gray1"                ,
201       "AFNI*clustA*foreground:     yellow"               ,
202       "AFNI*clustB*foreground:     white"                ,
203 #endif
204 
205       "AFNI*XmList.translations: #augment"                /* 24 Feb 2007 */
206            "<Btn4Down>: ListPrevItem()\\n"                /* for scrollwheel */
207            "<Btn5Down>: ListNextItem()"                  ,
208 
209       "AFNI*XmText.translations: #augment"
210            "<Btn4Down>: previous-line() scroll-one-line-down()\\n"
211            "<Btn5Down>: next-line() scroll-one-line-up()"          ,
212 #if 0
213       "AFNI*XmScrollBar.translations: #augment"
214            "<Btn4Down>: IncrementUpOrLeft(0) IncrementUpOrLeft(1)\\n"
215            "<Btn5Down>: IncrementDownOrRight(1) IncrementDownOrRight(0)" ,
216 #endif
217 
218    NULL } ;
219 
220 /* The trick to using multiple Xt translations in the fallback resources
221    above is to separate them not with '\n' but with '\\n'.  Ugghhhhhhh.  */
222 
223 /*-----------------------------------------------------------------------*/
224 static int    new_FALLback_num = 0 ;    /* for -XXX option [24 Mar 2016] */
225 static char **new_FALLback     = NULL ;
226 static char  *xrdb_old         = NULL ;
227 static char  *xrdb_pg          = NULL ;
228 
229 /*-----------------------------------------------------------------------*/
230 
equiv_FALLback(char * n1,char * n2)231 static int equiv_FALLback( char *n1 , char *n2 ) /* check if 2 strings */
232 {                                                /* start the same */
233    char *c1,*c2 , *d1,*d2 ; int ee ;
234    if( n1 == NULL || *n1 == '\0' ) return 1 ;
235    if( n2 == NULL || *n2 == '\0' ) return 1 ;
236    if( strcmp(n1,n2) == 0        ) return 1 ;
237    d1 = strdup(n1) ; c1 = strchr(d1,':') ;
238    d2 = strdup(n2) ; c2 = strchr(d2,':') ;
239    if( c1 == NULL || c2 == NULL  ){ free(d1); free(d2); return 1; }
240    *c1 = '\0' ; *c2 = '\0' ;
241    ee = strcmp(d1,d2) ; free(d1) ; free(d2) ;
242    return (ee==0) ;
243 }
244 
245 /*-----------------------------------------------------------------------*/
246 
247 /*-----------------------------------------------------------------------*/
248 
249 #define ADDTO_FALLback_one(nameval)                                            \
250  do{ int nf ;                                                                  \
251      nf = new_FALLback_num ;                                                   \
252      new_FALLback = (char **)realloc( new_FALLback , sizeof(char *)*(nf+2) ) ; \
253      new_FALLback[nf]   = strdup(nameval) ;                                    \
254      new_FALLback[nf+1] = NULL ; new_FALLback_num = nf+1 ;                     \
255  } while(0)
256 
257 #define ADDTO_FALLback_pair(name,val)                                          \
258  do{ char *str=malloc(strlen(name)+strlen(val)+16) ;                           \
259      strcpy(str,name) ; strcat(str,":   ") ; strcat(str,val) ;                 \
260      ADDTO_FALLback_one(str) ;                                                 \
261  } while(0)
262 
263 /*-----------------------------------------------------------------------*/
264 
AFNI_set_4fonts(char * AA,char * BB,char * CC,char * DD)265 static void AFNI_set_4fonts(char *AA,char *BB, char *CC, char *DD)
266 {
267    ADDTO_FALLback_pair("AFNI*fontList"        , AA) ;
268    ADDTO_FALLback_pair("AFNI*help*fontList"   , AA) ;
269    ADDTO_FALLback_pair("AFNI*bigtext*fontList", AA) ;
270    ADDTO_FALLback_pair("AFNI*cluefont"        , BB) ;
271    ADDTO_FALLback_pair("AFNI*font8*fontList"  , BB) ;
272    ADDTO_FALLback_pair("AFNI*imseq*fontList"  , CC) ;
273    ADDTO_FALLback_pair("AFNI*font7*fontList"  , CC) ;
274    ADDTO_FALLback_pair("AFNI*font6*fontList"  , DD) ;
275    ADDTO_FALLback_pair("AFNI*pbar*fontList"   , DD) ;
276 
277    /*** INFO_message("AFNI_set_4fonts: %s %s %s %s",AA,BB,CC,DD) ; ***/
278 }
279 
280 /*-----------------------------------------------------------------------*/
281 
282 static int XXX_set_default = 0 ; /* 08 Apr 2016 */
283 
process_XXX_options(int argc,char * argv[])284 static void process_XXX_options( int argc , char *argv[] )
285 {
286    int nopt=1 ;
287 
288    while( nopt < argc ){
289 
290      if( strcasecmp(argv[nopt],"-big") == 0 ){  /* 17 Mar 2020 */
291        XXX_BIG_FONTS ; nopt++ ; continue ;      /* simpler font size options */
292      }
293      if( strcasecmp(argv[nopt],"-plus") == 0 ){
294        static int nplus=0 ;
295        if( nplus == 0 ){ XXX_PLUS_FONTS ; }
296        else            { XXX_BIG_FONTS ;  }
297        nopt++ ; nplus++ ; continue ;
298      }
299      if( strcasecmp(argv[nopt],"-minus") == 0 ){
300        XXX_MINUS_FONTS ; nopt++ ; continue ;
301      }
302      if( strcasecmp(argv[nopt],"-norm") == 0 ){  /* 10 Apr 2020 */
303        XXX_NORM_FONTS ; nopt++ ; continue ;
304      }
305 
306      if( strncasecmp(argv[nopt],"-XXX",4) != 0 ){ nopt++; continue; }
307 
308      if( strcasecmp(argv[nopt],"-XXX") == 0 ){
309        if( ++nopt >= argc ){
310          WARNING_message("no argument after '%s' :-(",argv[nopt-1]) ;
311          break ;
312        }
313        if( strncasecmp(argv[nopt],"default",7) == 0 ){ /* 08 Apr 2016 */
314          if( THD_find_executable("xrdb") != NULL ){
315            int qq ;
316            XXX_set_default = 1 ;
317            for( qq=0 ; FALLback[qq] != NULL ; qq++ )
318              ADDTO_FALLback_one(FALLback[qq]) ;
319          }
320        } else if( strchr(argv[nopt],':') != NULL ){
321          ADDTO_FALLback_one(argv[nopt]) ;
322        }
323        nopt++ ; continue ;
324      }
325 
326      if( strcasecmp(argv[nopt],"-XXXnpane") == 0 ){  /* 06 May 2016 */
327        int np ;
328        if( ++nopt >= argc ){
329          WARNING_message("no argument after '%s' :-(",argv[nopt-1]) ;
330          break ;
331        }
332        np = (int)strtod(argv[nopt],NULL) ;
333        if( np < 256 || np > NPANE_BIGGEST ){
334          WARNING_message("value '%s' after '%s' is illegal -- ignoring",argv[nopt],argv[nopt-1]) ;
335        } else {
336          if( np%2 == 1 ) np++ ;
337          if( np > NPANE_BIGGEST ) np = NPANE_BIGGEST ;
338          npane_big = np ;
339        }
340        nopt++ ; continue ;
341      }
342 
343      if( strcasecmp(argv[nopt],"-XXXbgcolor") == 0 ){
344        if( ++nopt >= argc ){
345          WARNING_message("no argument after '%s' :-(",argv[nopt-1]) ;
346          break ;
347        }
348        ADDTO_FALLback_pair("AFNI*background"     ,argv[nopt]) ;
349        ADDTO_FALLback_pair("AFNI*menu*background",argv[nopt]) ;
350        ADDTO_FALLback_pair("AFNI*help*background",argv[nopt]) ;
351        nopt++ ; continue ;
352      }
353 
354      if( strcasecmp(argv[nopt],"-XXXfgcolor") == 0 ){
355        if( ++nopt >= argc ){
356          WARNING_message("no argument after '%s' :-(",argv[nopt-1]) ;
357          break ;
358        }
359        ADDTO_FALLback_pair("AFNI*foreground"     ,argv[nopt]) ;
360        ADDTO_FALLback_pair("AFNI*menu*foreground",argv[nopt]) ;
361        ADDTO_FALLback_pair("AFNI*help*foreground",argv[nopt]) ;
362        nopt++ ; continue ;
363      }
364 
365      if( strcasecmp(argv[nopt],"-XXXfontsize") == 0 ){
366        if( ++nopt >= argc ){
367          WARNING_message("no argument after '%s' :-(",argv[nopt-1]) ;
368          break ;
369        }
370        if( strcasecmp(argv[nopt],"plus") == 0 || strcmp(argv[nopt],"+") == 0 ){
371          static int nplus=0 ;
372          if( nplus == 0 ){ XXX_PLUS_FONTS ; }
373          else            { XXX_BIG_FONTS ;  }
374          nplus++ ;
375        } else if( strcasecmp(argv[nopt],"minus") == 0 || strcmp(argv[nopt],"-") == 0 ){
376          XXX_MINUS_FONTS ;
377        } else if( strcasecmp(argv[nopt],"big") == 0 || strcmp(argv[nopt],"++") == 0 ){
378          XXX_PLUS_FONTS ;
379        } else {
380          WARNING_message("Don't understand '%s' after option '%s'",
381                          argv[nopt] , argv[nopt-1] ) ;
382        }
383 
384        nopt++ ; continue ;
385      }
386 
387      if( strcasecmp(argv[nopt],"-XXXfontA") == 0 ){
388        char *fn ;
389        if( ++nopt >= argc ){
390          WARNING_message("no argument after '%s' :-(",argv[nopt-1]) ;
391          break ;
392        }
393        fn = (char *)malloc(sizeof(char)*(strlen(argv[nopt])+32)) ;
394        sprintf(fn,"%s=charset1",argv[nopt]) ;
395        ADDTO_FALLback_pair("AFNI*fontList"        ,fn) ;
396        ADDTO_FALLback_pair("AFNI*help*fontList"   ,fn) ;
397        ADDTO_FALLback_pair("AFNI*bigtext*fontList",fn) ;
398        ADDTO_FALLback_pair("AFNI*cluefont"        ,fn) ;
399        free(fn) ; nopt++ ; continue ;
400      }
401 
402      if( strcasecmp(argv[nopt],"-XXXfontB") == 0 ){
403        char *fn ;
404        if( ++nopt >= argc ){
405          WARNING_message("no argument after '%s' :-(",argv[nopt-1]) ;
406          break ;
407        }
408        fn = (char *)malloc(sizeof(char)*(strlen(argv[nopt])+32)) ;
409        sprintf(fn,"%s=charset1",argv[nopt]) ;
410        ADDTO_FALLback_pair("AFNI*font8*fontList",fn) ;
411        free(fn) ; nopt++ ; continue ;
412      }
413 
414      if( strcasecmp(argv[nopt],"-XXXfontC") == 0 ){
415        char *fn ;
416        if( ++nopt >= argc ){
417          WARNING_message("no argument after '%s' :-(",argv[nopt-1]) ;
418          break ;
419        }
420        fn = (char *)malloc(sizeof(char)*(strlen(argv[nopt])+32)) ;
421        sprintf(fn,"%s=charset1",argv[nopt]) ;
422        ADDTO_FALLback_pair("AFNI*imseq*fontList",fn) ;
423        ADDTO_FALLback_pair("AFNI*font7*fontList",fn) ;
424        free(fn) ; nopt++ ; continue ;
425      }
426 
427      if( strcasecmp(argv[nopt],"-XXXfontD") == 0 ){
428        char *fn ;
429        if( ++nopt >= argc ){
430          WARNING_message("no argument after '%s' :-(",argv[nopt-1]) ;
431          break ;
432        }
433        fn = (char *)malloc(sizeof(char)*(strlen(argv[nopt])+32)) ;
434        sprintf(fn,"%s=charset1",argv[nopt]) ;
435        ADDTO_FALLback_pair("AFNI*font6*fontList",fn) ;
436        ADDTO_FALLback_pair("AFNI*pbar*fontList" ,fn) ;
437        free(fn) ; nopt++ ; continue ;
438      }
439 
440    }
441 
442    return ;
443 }
444 
445 /*----------------------------------------------------------------------------
446    Global variables that used to be local variables in main(),
447    but since the advent of the splash screen and startup code
448    in MAIN_workprocess() are needed in more than one place.
449 ------------------------------------------------------------------------------*/
450 
451 static XtAppContext   MAIN_app ;
452 static XtErrorHandler MAIN_old_handler ;   /* no longer used */
453 static Three_D_View  *MAIN_im3d ;
454 static MCW_DC *       MAIN_dc ;
455 static Widget         MAIN_shell=NULL ;
456 static int            MAIN_argc ;
457 static char         **MAIN_argv ;
458 static RwcBoolean        MAIN_workprocess( XtPointer ) ;
459 
460 /*----- Stuff saved from the '-com' command line arguments [29 Jul 2005] -----*/
461 
462 static int COM_num = 0 ;
463 #define MAX_N_COM 1024
464 static char *COM_com[MAX_N_COM] ;  /* max of 1024 commands allowed!!! */
465 static char comsep = ';' ;         /* command separator: 22 Feb 2007 */
466 
467 static int recursed_ondot = 0 ;  /* 18 Feb 2007 */
468 
469 /* ---------------------------------------------------------------------- */
470 /* just display the AFNI version                      26 Oct 2015 [rickr] */
471 /* (since writing to stdout, do not interfere with print-and-exit funcs)  */
472 
473 #include "RomanImperator.h"  /* RWC Nov 2018 */
474 
show_AFNI_version(void)475 void show_AFNI_version(void)
476 {
477   char *rimp = AFNI_VERSION_RomanImperator ;
478   char vvvv[1024] ;
479 
480   if( rimp != NULL && *rimp != '\0' ){ sprintf(vvvv,"%s '%s'",AVERZHN,rimp); }
481   else                               { strcpy(vvvv,AVERZHN) ; }
482 
483 #ifdef SHSTRING
484      printf( "Precompiled binary " SHSTRING ": " __DATE__ " (Version %s)\n",vvvv ) ;
485 #else
486      printf( "Compile date = " __DATE__ " " __TIME__ " (Version %s)\n",vvvv) ;
487 #endif
488 }
489 
490 // [PT: Oct 7, 2019] functions to plot just the basic info, without
491 // sep parsing needs: version number and package num
show_AFNI_package(void)492 void show_AFNI_package(void)
493 {
494 #ifdef SHSTRING
495    printf(SHSTRING "\n");
496 #else
497    printf( "Compiled: " __DATE__ );
498 #endif
499 }
500 
show_AFNI_vnum(void)501 void show_AFNI_vnum(void)
502 {
503    printf(AVERZHN "\n");
504 }
505 
506 // [PT: Oct 17, 2019] useful to be able to get the 'readme_afnigui.h'
507 // info at the command line (ambitions to parse it for the HTML RST
508 // pages).  This is called via the -tips option.
show_AFNI_readme_gui(void)509 void show_AFNI_readme_gui(void)
510 {
511    int ii;
512 
513    for( ii=0 ; readme_afnigui[ii] != NULL ; ii++ ){
514      printf( "%s" , readme_afnigui[ii] ) ;
515    }
516 }
517 
518 // [PT: Oct 21, 2019] useful to be able to get the 'readme_env.h' info
519 // at commandline; also for HTML RST parsing.  This is called via the
520 // -env option.
show_AFNI_readme_env(void)521 void show_AFNI_readme_env(void)
522 {
523    int ii;
524 
525    for( ii=0 ; readme_env[ii] != NULL ; ii++ ){
526      printf( "%s" , readme_env[ii] ) ;
527    }
528 }
529 
530 /********************************************************************
531    Print out some help information and then quit quit quit
532 *********************************************************************/
533 
AFNI_syntax(void)534 void AFNI_syntax(void)
535 {
536 /*   printf(ANNOUNCEMENT) ;*/
537 
538    if( AFNI_yesenv("AFNI_POMOC") )  /* for the Web -help page */
539      printf(
540       " **** At the bottom of this Web page are some slide images to\n"
541       "    outline the usage of the AFNI Graphical User Interface (GUI).\n"
542       "\n"
543      ) ;
544    else
545      printf(
546       " **** Help for all AFNI programs can be found at the Web page\n"
547       "    https://afni.nimh.nih.gov/pub/dist/doc/program_help/index.html\n"
548       "\n"
549      ) ;
550 
551    printf(
552      "----------------------------------------------------------------\n"
553      "USAGE 1: read in sessions of 3D datasets (created by to3d, etc.)\n"
554      "----------------------------------------------------------------\n"
555      "   afni [options] [session_directory ...]\n"
556      "\n"
557      "   -bysub       This new [01 Feb 2018] option allows you to have 'sessions'\n"
558      "    *OR*          made up from files scattered across multiple directories.\n"
559      "   -BIDS          The purpose of this option is to gather all the datasets\n"
560      "                  corresponding to a single subject identifier, as is done\n"
561      "                  in the BIDS file hierarchy -- http://bids.neuroimaging.io/\n"
562      "             **** There are two methods for using this option.\n"
563      "    method (1) ** In the first method, you put one or more subject identifiers,\n"
564      "     [OLDER]      which are of the form 'sub-XXX' where 'XXX' is some\n"
565      "                  subject code (it does not have to be exactly 3 characters).\n"
566      "                 ++ If an identifier does NOT start with 'sub-', then that\n"
567      "                    4 letter string will be added to the front. This allows\n"
568      "                    you to specify your subjects by their numbers 'XXX' alone.\n"
569      "    method (2) ** In the second method, you put one or more directory names,\n"
570      "     [NEWER]      and all immediate sub-directories whose name starts with\n"
571      "                  'sub-' will be included. With this method, you can end up\n"
572      "                  reading in an entire BIDS hierarchy of datasets, which\n"
573      "                  might take a significant amount of time if there are many\n"
574      "                  subjects.\n"
575      "               **** Note that if an identifier following '-bysub' on the\n"
576      "                    command line is a directory name that starts with 'sub-',\n"
577      "                    it will be treated using method (1), not using method (2).\n"
578      "  both methods ** In either method, the list of names following '-bysub' ends\n"
579      "                  with any argument that starts with '-' (or with the end of\n"
580      "                  all command line arguments).\n"
581      "    method (2) ** Each directory on the command line (after all options, and\n"
582      "                  including any directories directly after the '-bysub' option)\n"
583      "                  will be scanned recursively (down the file tree) for\n"
584      "                  subdirectories whose name matches each 'sub-XXX' identifier\n"
585      "                  exactly. All such subdirectories will have all their\n"
586      "                  datasets read in (recursively down the file tree) and\n"
587      "                  put into a single session for viewing in AFNI.\n"
588      "                ++ In addition, all datasets from all subjects will be\n"
589      "                   available in the 'All_Datasets' session in the GUI.\n"
590      "                   (Unless environment variable AFNI_ALL_DATASETS is set to NO)\n"
591      "                ++ If you do NOT put any directories or subject identifiers\n"
592      "                   directly after the '-bysub' (or '-BIDS') option, the\n"
593      "                   program will act as if you put '.' there, and it will\n"
594      "                   search below the current working directory - the directory\n"
595      "                   you were 'in' when you started the AFNI GUI.\n"
596      "    method (1) ** If a directory on the command line after this option does\n"
597      "                  NOT have any subdirectories that match any of the '-bysub'\n"
598      "                  identifiers, then that directory will be read in the normal\n"
599      "                  way, with all the datasets in that particular directory\n"
600      "                  (but not subdirectories) read into the session.\n"
601      "  both methods ** Please note that '-bysub' sessions will NOT be rescanned\n"
602      "                  for new datasets that might get placed there after the\n"
603      "                  AFNI GUI starts, unlike normal (single directory) sessions.\n"
604      "    method (1) ** Example (method 1):\n"
605      "                    afni -bysub 10506 50073 - ~/data/OpenFMRI/ds000030\n"
606      "                  This will open the data for subjects 10506 and 50073 from\n"
607      "                  the data at the specified directory -- presumably the\n"
608      "                  data downloaded from https://openfmri.org/dataset/ds000030/\n"
609      "                ++ If directory sub-10506 is found and has (say) sub-directories\n"
610      "                     anat beh dwi func\n"
611      "                   all AFNI-readable datasets from these sub-directories will\n"
612      "                   be input and collected into one session, to be easily\n"
613      "                   viewed together.\n"
614      "                ++ Because of the recursive search, if a directory named (e.g.)\n"
615      "                     derivatives/sub-10506\n"
616      "                   is found underneath ~/data/OpenFMRI/ds000030, all the\n"
617      "                   datasets found underneath that will also be put into the\n"
618      "                   same session, so they can be viewed with the 'raw' data.\n"
619      "                ++ In this context, 'dataset' also means .png and .jpg files\n"
620      "                   found in the sub-XXX directories. These images can be\n"
621      "                   opened in the AFNI GUI using the Axial image viewer.\n"
622      "                   (You might want to turn the AFNI crosshairs off!)\n"
623      "              ++++ If you do NOT want .png and .jpg files read into AFNI,\n"
624      "                   set Unix environment variable AFNI_IMAGE_DATASETS to 'NO'.\n"
625      "                ++ You can put multiple subject IDs after '-bysub', as\n"
626      "                   in the example above. You can also use the '-bysub' option\n"
627      "                   more than once, if you like. Each distinct subect ID will\n"
628      "                   get a distinct AFNI session in the GUI.\n"
629      "    method (2) ** Example (method 2):\n"
630      "                    afni -bysub ~/data/OpenFMRI/ds000030\n"
631      "                  This will read in all datasets from all subjects. In this\n"
632      "                  particular example, there are hundreds of subjects, so this\n"
633      "                  command may not actually be a good idea - unless you want to\n"
634      "                  go get a cup of chai or coffee, and then sip it very slowly.\n"
635      "               ** Example (method 2):\n"
636      "                    afni -BIDS\n"
637      "                  This will read all 'sub-*' directories from the current\n"
638      "                  working directory, and is the same as 'afni -BIDS .' \n"
639      "                  As noted earlier, this recursive operation may take a long\n"
640      "                  time (especially if the datasets are compressed), as AFNI\n"
641      "                  reads the headers from ALL datasets as it finds them,\n"
642      "                  to build a table for you to use in the 'OverLay' and\n"
643      "                  'UnderLay' dataset choosers.\n"
644      "\n"
645      "   -all_dsets   Read in all datasets from all listed folders together.\n"
646      "                  Has the same effect as choosing 'All_Datasets' in the GUI.\n"
647      "                  Example: afni -all_dsets dir1 dir2 dir3\n"
648      "                  Can be set to default in .afnirc with ALL_DSETS_STARTUP = YES.\n"
649      "                  Overidden silently by AFNI_ALL_DATASETS = NO.\n"
650      "\n"
651 #if MMAP_THRESHOLD > 0
652      "   -purge       Conserve memory by purging unused datasets from memory.\n"
653      "                  [Use this if you run out of memory when running AFNI.]\n"
654      "                  [This will slow the code down, so use only if needed.]\n"
655 #else
656      "   -nopurge     Disable the automatic purging of unused datasets from\n"
657      "                  memory, which is invoked when you switch datasets.\n"
658 #endif
659      "                  [When a dataset is needed, it will be re-read from disk.]\n"
660      "\n"
661      "   -posfunc     Start up the color 'pbar' to use only positive function values.\n"
662      "\n"
663      "   -R           Recursively search each session_directory for more session\n"
664      "                  subdirectories.\n"
665      "       WARNING: This will descend the entire filesystem hierarchy from\n"
666      "                  each session_directory given on the command line.  On a\n"
667      "                  large disk, this may take a long time.  To limit the\n"
668      "                  recursion to 5 levels (for example), use -R5.\n"
669      "             ** Use of '-bysub' disables recursive descent, since '-bysub'\n"
670      "                will do that for you.\n"
671 #if 0
672      "\n"
673      "   -ignore N    Tells the program to 'ignore' the first N points in\n"
674      "                  time series for graphs and FIM calculations.\n"
675      "\n"
676      "   -im1 N       Tells the program to use image N as the first one for\n"
677      "                  graphs and FIM calculations (same as '-ignore N-1')\n"
678      "\n"
679      "   -tlrc_small  These options set whether to use the 'small' or 'big'\n"
680      "   -tlrc_big      Talairach brick size.  The compiled in default for\n"
681      "                  the program is now 'big', unlike AFNI 1.0x.\n"
682 #endif
683      "\n"
684 #ifndef WARP_4D
685      "   -warp_4D     Allows the program to Talairach transform and write\n"
686      "                  to disk 3D+time datasets.  Note that the resulting\n"
687      "                  disk files will be gigantic (100s of Megabytes).\n"
688      "\n"
689 #endif
690      "   -no1D        Tells AFNI not to read *.1D timeseries files from\n"
691      "                  the dataset directories.  The *.1D files in the\n"
692      "                  directories listed in the AFNI_TSPATH environment\n"
693      "                  variable will still be read (if this variable is\n"
694      "                  not set, then './' will be scanned for *.1D files).\n"
695      "\n"
696      "   -nocsv       Each of these option flags does the same thing (i.e.,\n"
697      "   -notsv         they are synonyms): each tells AFNI not to read\n"
698      "   -notcsv        *.csv or *.tsv files from the dataset directories.\n"
699 #if 0
700      "\n"
701      "   -noqual      Tells AFNI not to enforce the 'quality' checks when\n"
702      "                  making the transformations to +acpc and +tlrc.\n"
703 #endif
704      "\n"
705      "   -unique      Tells the program to create a unique set of colors\n"
706      "                  for each AFNI controller window.  This allows\n"
707      "                  different datasets to be viewed with different\n"
708      "                  grayscales or colorscales.  Note that -unique\n"
709      "                  will only work on displays that support 12 bit\n"
710      "                  PseudoColor (e.g., SGI workstations) or TrueColor.\n"
711      "\n"
712      "   -orient code Tells afni the orientation in which to display\n"
713      "                  x-y-z coordinates (upper left of control window).\n"
714      "                  The code must be 3 letters, one each from the\n"
715      "                  pairs {R,L} {A,P} {I,S}.  The first letter gives\n"
716      "                  the orientation of the x-axis, the second the\n"
717      "                  orientation of the y-axis, the third the z-axis:\n"
718      "                   R = right-to-left         L = left-to-right\n"
719      "                   A = anterior-to-posterior P = posterior-to-anterior\n"
720      "                   I = inferior-to-superior  S = superior-to-inferior\n"
721      "                  The default code is RAI ==> DICOM order.  This can\n"
722      "                  be set with the environment variable AFNI_ORIENT.\n"
723      "                  As a special case, using the code 'flipped' is\n"
724      "                  equivalent to 'LPI' (this is for Steve Rao).\n"
725      "\n"
726 #ifdef ALLOW_PLUGINS
727      "   -noplugins   Tells the program not to load plugins.\n"
728      "                  (Plugins can also be disabled by setting the\n"
729      "                   environment variable AFNI_NOPLUGINS.)\n"
730      "\n"
731      "   -seehidden   Tells the program to show you which plugins\n"
732      "                  are hidden.\n"
733      "\n"
734      "   -DAFNI_ALLOW_ALL_PLUGINS=YES\n"
735      "                Tells the program NOT to hide plugins from you.\n"
736      "                  Note that there are a lot of hidden plugins,\n"
737      "                  most of which are not very useful!\n"
738      "\n"
739      "   -yesplugouts Tells the program to listen for plugouts.\n"
740      "                  (Plugouts can also be enabled by setting the\n"
741      "                   environment variable AFNI_YESPLUGOUTS.)\n"
742      "\n"
743      "   -YESplugouts Makes the plugout code print out lots of messages\n"
744      "                  (useful for debugging a new plugout).\n"
745      "\n"
746      "   -noplugouts  Tells the program NOT to listen for plugouts.\n"
747      "                  (This option is available to override\n"
748      "                   the AFNI_YESPLUGOUTS environment variable.)\n"
749      "\n"
750 #endif
751      "   -skip_afnirc Tells the program NOT to read the file .afnirc\n"
752      "                  in the home directory.  See README.setup for\n"
753      "                  details on the use of .afnirc for initialization.\n"
754      "\n"
755      "   -layout fn   Tells AFNI to read the initial windows layout from\n"
756      "                  file 'fn'.  If this option is not given, then\n"
757      "                  environment variable AFNI_LAYOUT_FILE is used.\n"
758      "                  If neither is present, then AFNI will do whatever\n"
759      "                  it feels like.\n"
760      "\n"
761      "   -niml        If present, turns on listening for NIML-formatted\n"
762      "                  data from SUMA.  Can also be turned on by setting\n"
763      "                  environment variable AFNI_NIML_START to YES.\n"
764      "%s"
765      "   -list_ports  List all port assignments and quit\n"
766      "   -port_number PORT_NAME: Give port number for PORT_NAME and quit\n"
767      "   -port_number_quiet PORT_NAME: Same as -port_number but writes out \n"
768      "                                    number only\n"
769      "   -available_npb: Find the first available block of port numbers, \n"
770      "                   print it to stdout and quit\n"
771      "                   The value can be used to set the -npb option for\n"
772      "                   a new set of chatty AFNI/SUMA/etc group.\n"
773      "   -available_npb_quiet: Just print the block number to stdout and quit.\n"
774      "\n"
775      "   -com ccc     This option lets you specify 'command strings' to\n"
776      "                  drive AFNI after the program startup is completed.\n"
777      "                  Legal command strings are described in the file\n"
778      "                  README.driver.  More than one '-com' option can\n"
779      "                  be used, and the commands will be executed in\n"
780      "                  the order they are given on the command line.\n"
781      "            N.B.: Most commands to AFNI contain spaces, so the 'ccc'\n"
782      "                  command strings will need to be enclosed in quotes.\n"
783      "\n"
784      "   -comsep 'c'  Use character 'c' as a separator for commands.\n"
785      "                  In this way, you can put multiple commands in\n"
786      "                  a single '-com' option.  Default separator is ';'.\n"
787      "            N.B.: The command separator CANNOT be alphabetic or\n"
788      "                  numeric (a..z, A..Z, 0..9) or whitespace or a quote!\n"
789      "            N.B.: -comsep should come BEFORE any -com option that\n"
790      "                  uses a non-semicolon separator!\n"
791      "\n"
792      "   Example: -com 'OPEN_WINDOW axialimage; SAVE_JPEG axialimage zork; QUIT'\n"
793      "   N.B.: You can also put startup commands (one per line) in\n"
794      "         the file '~/.afni.startup_script'.  For example,\n"
795      "            OPEN_WINDOW axialimage\n"
796      "         to always open the axial image window on startup.\n"
797      "\n"
798      " * If no session_directories are given, then the program will use\n"
799      "    the current working directory (i.e., './').\n"
800      " * The maximum number of sessions is now set to  %d.\n"
801      " * The maximum number of datasets per session is %d.\n"
802      " * To change these maximums, you must edit file '3ddata.h' and then\n"
803      "    recompile this program.\n"
804      "\n"
805      "Global Options (available to all AFNI/SUMA programs)\n"
806      "%s\n%s"
807      , get_np_help() ,
808      THD_MAX_NUM_SESSION , THD_MAX_SESSION_SIZE ,
809      SUMA_Offset_SLines(get_help_help(),3), get_gopt_help()
810    ) ;
811 
812 #if 0
813    printf(
814      "\n"
815      "-----------------------------------------------------\n"
816      "USAGE 2: read in images for 'quick and dirty' viewing\n"
817      "-----------------------------------------------------\n"
818      "** Most advanced features of AFNI will be disabled **\n"
819      "** The aiv program can be used now instead of AFNI **\n"
820      "\n"
821      "   afni -im [options] im1 im2 im3 ...\n"
822      "\n"
823      "   -im          Flag to read in images instead of 3D datasets\n"
824      "                  (Talaraich and functional stuff won't work)\n"
825      "   -dy yratio   Tells afni the downscreen pixel size is 'yratio' times\n"
826      "                  the across-screen (x) pixel dimension (default=1.0)\n"
827      "   -dz zratio   Tells afni the slice thickness is 'zratio' times\n"
828      "                  the x pixel dimension (default=1.0)\n"
829      "   -orient code Tells afni the orientation of the input images.\n"
830      "                  The code must be 3 letters, one each from the\n"
831      "                  pairs {R,L} {A,P} {I,S}.  The first letter gives\n"
832      "                  the orientation of the x-axis, the second the\n"
833      "                  orientation of the y-axis, the third the z-axis:\n"
834      "                   R = right-to-left         L = left-to-right\n"
835      "                   A = anterior-to-posterior P = posterior-to-anterior\n"
836      "                   I = inferior-to-superior  S = superior-to-inferior\n"
837      "                  (the default code is ASL ==> sagittal images).\n"
838      "                  Note that this use of '-orient' is different from\n"
839      "                  the use when viewing datasets.\n"
840      "   -resize      Tells afni that all images should be resized to fit\n"
841      "                  the size of the first one, if they don't already fit\n"
842      "                  (by default, images must all 'fit' or afni will stop)\n"
843      "   -datum type  Tells afni to convert input images into the type given:\n"
844      "                  byte, short, float, complex are the legal types.\n"
845      " The image files (im1 ...) are the same formats as accepted by to3d.\n"
846      "\n"
847      " New image display options (alternatives to -im) [19 Oct 1999]:\n"
848      "   -tim         These options tell AFNI to arrange the input images\n"
849      "   -tim:nt      into a internal time-dependent dataset.  Suppose that\n"
850      "   -zim:nz      there are N input 2D slices on the command line.\n"
851      "              * -tim alone means these are N points in time (1 slice).\n"
852      "              * -tim:nt means there are nt points in time (nt is\n"
853      "                  an integer > 1), so there are N/nt slices in space,\n"
854      "                  and the images on the command line are input in\n"
855      "                  time order first (like -time:tz in to3d).\n"
856      "              * -zim:nz means there are nz slices in space (nz is\n"
857      "                  an integer > 1), so there are N/nz points in time,\n"
858      "                  and the images on the command line are input in\n"
859      "                  slice order first (like -time:zt in to3d).\n"
860      "\n"
861      " N.B.: You may wish to use the -ignore option to set the number of\n"
862      "        initial points to ignore in the time series graph if you use\n"
863      "        -tim or -zim, since there is no way to change this from\n"
864      "        within an AFNI run (the FIM menus are disabled).\n"
865      " N.B.: The program 'aiv' (AFNI image viewer) can also be used to\n"
866      "        get a quick look at images (but not time series graphs).\n"
867    ) ;
868 #endif
869 
870    printf(
871      "\n"
872      "-------------------------------------------------------\n"
873      "USAGE 2: read in datasets specified on the command line\n"
874      "-------------------------------------------------------\n"
875      "\n"
876      "  afni -dset [options] dname1 dname2 ...\n"
877      "\n"
878      "where 'dname1' is the name of a dataset, etc.  With this option, only\n"
879      "the chosen datasets are read in, and they are all put in the same\n"
880      "'session'.  Follower datasets are not created.\n"
881      "\n"
882      "* If you wish to be very tricksy, you can read in .1D files as datasets\n"
883      "  using the \\' transpose syntax, as in\n"
884      "     afni Fred.1D\\'\n"
885      "  However, this isn't very useful (IMHO).\n"
886      "\n"
887      "* AFNI can also read image files (.jpg and .png) from the command line.\n"
888      "  For just viewing images, the 'aiv' program (AFNI image viewer) is\n"
889      "  simpler; but unlike aiv, you can do basic image processing on an\n"
890      "  image 'dataset' using the AFNI GUI's feature. Sample command:\n"
891      "     afni *.jpg\n"
892      "  Each image file is a single 'dataset'; to switch between images,\n"
893      "  use the 'Underlay' button. To view an image, open the 'Axial' viewer.\n"
894      "\n");
895     printf(MASTER_HELP_STRING);   putchar('\n');
896     printf(CATENATE_HELP_STRING); putchar('\n');
897     printf(CALC_HELP_STRING);     putchar('\n');
898 
899    printf(
900      "\n"
901      "-------------------------------\n"
902      "GENERAL OPTIONS (for any usage)\n"
903      "-------------------------------\n"
904      "\n"
905      "   -papers      Prints out the list of AFNI papers, and exits.\n"
906      "\n"
907      "   -q           Tells afni to be 'quiet' on startup\n"
908      "\n"
909      "   -Dname=val   Sets environment variable 'name' to 'val' inside AFNI;\n"
910      "                  will supersede any value set in .afnirc.\n"
911      "\n"
912      "   -gamma gg    Tells afni that the gamma correction factor for the\n"
913      "                  monitor is 'gg' (default gg is 1.0; greater than\n"
914      "                  1.0 makes the image contrast larger -- this may\n"
915      "                  also be adjusted interactively)\n"
916      "\n"
917      "   -install     Tells afni to install a new X11 Colormap.  This only\n"
918      "                  means something for PseudoColor displays.  Also, it\n"
919      "                  usually cause the notorious 'technicolor' effect.\n"
920      "\n"
921      "   -ncolors nn  Tells afni to use 'nn' gray levels for the image\n"
922      "                  displays (default is %d)\n"
923      "\n"
924      "   -xtwarns     Tells afni to show any Xt warning messages that may\n"
925      "                  occur; the default is to suppress these messages.\n"
926 #ifdef USE_TRACING
927      "   -XTWARNS     Trigger a debug trace when an Xt warning happens.\n"
928      "\n"
929 #endif
930      "   -tbar name   Uses 'name' instead of 'AFNI' in window titlebars.\n"
931      "\n"
932      "   -flipim and  The '-flipim' option tells afni to display images in the\n"
933      "\n"
934      "   -noflipim      'flipped' radiology convention (left on the right).\n"
935      "                  The '-noflipim' option tells afni to display left on\n"
936      "                  the left, as neuroscientists generally prefer.  This\n"
937      "                  latter mode can also be set by the Unix environment\n"
938      "                  variable 'AFNI_LEFT_IS_LEFT'.  The '-flipim' mode is\n"
939      "                  the default.\n"
940      "\n"
941 #ifdef USE_TRACING
942      "   -trace       Turns routine call tracing on, for debugging purposes.\n"
943      "   -TRACE       Turns even more verbose tracing on, for more debugging.\n"
944 #endif
945 #ifdef USING_MCW_MALLOC
946      "   -nomall      Disables use of the mcw_malloc() library routines.\n"
947      "\n"
948 #endif
949      "   -motif_ver   Show the applied motif version string.\n"
950      "\n"
951      "   -no_detach   Do not detach from the terminal.\n"
952      "\n"
953      "   -get_processed_env   Show applied AFNI/NIFTI environment varables.\n"
954      "\n"
955      "   -global_opts Show options that are global to all AFNI programs.\n"
956      "\n"
957      "   -goodbye [n] Print a 'goodbye' message and exit (just for fun).\n"
958      "                If an integer is supplied afterwards, will print that\n"
959      "                many (random) goodbye messages.\n"
960      "\n"
961      "   -startup [n] Similar to '-goodbye', but for startup tips.\n"
962      "                [If you want REAL fun, use '-startup ALL'.]\n"
963      "\n"
964      "   -julian      Print out the current Julian date and exit.\n"
965      "\n"
966      "   -ver         Print the current AFNI version and compile date, then exit.\n"
967      "                Useful to check how up-to-date you are (or aren't).\n"
968      "\n"
969      "   -vnum        Print just the current AFNI version number (i.e.,\n"
970      "                AFNI_A.B.C), then exit.\n"
971      "\n"
972      "   -package     Print just the current AFNI package (i.e., \n"
973      "                linux_ubuntu_12_64, macos_10.12_local, etc.),\n"
974      "                then exit.\n"
975      "\n"
976      "   -tips        Print the tips for the GUI, such as key presses\n"
977      "                and other useful advice.  This is the same file that\n"
978      "                would be displayed with the 'AFNI Tips' button in the\n"
979      "                GUI controller.  Exit after display.\n"
980      "\n"
981      "   -env         Print the environment variables for AFNI, which a user\n"
982      "                might set in their ~/.afnirc file (wait, you *do*\n"
983      "                have one on your computer, right?).\n"
984      "                Exit after display.\n"
985      "\n"
986      "\n"
987      "N.B.: Many of these options, as well as the initial color set up,\n"
988      "      can be controlled by appropriate X11 resources.  See the\n"
989      "      files AFNI.Xdefaults and README.environment for instructions\n"
990      "      and examples.\n"
991 
992      , DEFAULT_NGRAY
993    ) ;
994 
995    printf("\n"
996     "-----------------------------------------------------------\n"
997     "Options that affect X11 Display properties: '-XXXsomething'\n"
998     "-----------------------------------------------------------\n"
999     "\n"
1000     "My intent with these options is that you use them in aliases\n"
1001     "or shell scripts, to let you setup specific appearances for\n"
1002     "multiple copies of AFNI.  For example, put the following\n"
1003     "command in your shell startup file (e.g., ~/.cshrc or ~/.bashrc)\n"
1004     "   alias ablue afni -XXXfgcolor white -XXXbgcolor navyblue\n"
1005     "Then the command 'ablue' will start AFNI with a blue background\n"
1006     "and using white for the default text color.\n"
1007     "\n"
1008     "Note that these options set 'properties' on the X11 server,\n"
1009     "which might survive after AFNI exits (especially if AFNI crashes).\n"
1010     "If for some reason these settings cause trouble after AFNI\n"
1011     "exits, use the option '-XXX defaults' to reset the X11\n"
1012     "properties for AFNI back to their default values.\n"
1013     "\n"
1014     "Also note that each option is of the form '-XXXsomething', followed\n"
1015     "by a single argument.\n"
1016     "\n"
1017     " -XXXfgcolor colorname = set the 'foreground' color (text color)\n"
1018     "                         to 'colorname'\n"
1019     "                         [default = yellow]\n"
1020     "                         ++ This should be a bright color, to contrast\n"
1021     "                            the background color.\n"
1022     "                         ++ You can find a list of X11 color names at\n"
1023     "                              https://en.wikipedia.org/wiki/X11_color_names\n"
1024     "                            However, if you use a name like Dark Cyan\n"
1025     "                            (with a space inside the name), you must\n"
1026     "                            put the name in quotes: 'Dark Cyan', or remove\n"
1027     "                            the space: DarkCyan.\n"
1028     "                         ++ Another way to specify X11 colors is in hexadecimal,\n"
1029     "                            as in '#rgb' or '#rrggbb', where the letters shown\n"
1030     "                            are replaced by hex values from 0 to f.  For example,\n"
1031     "                            '#ffcc00' is an orange-yellow mixture.\n"
1032     "\n"
1033     " -XXXbgcolor colorname = set the 'background' color to 'colorname'\n"
1034     "                         [default = gray22]\n"
1035     "                         ++ This should be a somewhat dark color,\n"
1036     "                            or parts of the interface may be hard\n"
1037     "                            to read.\n"
1038     "                         ++ EXAMPLE:\n"
1039     "                              afni -XXXfgcolor #00ffaa -XXXbgcolor #330000 -plus\n"
1040     "                            You can create command aliases to open AFNI with\n"
1041     "                            different color schemes, to make your life simpler.\n"
1042     "\n"
1043     " -XXXfontsize plus     = set all the X11 fonts used by AFNI to be one\n"
1044     "   *OR*                  size larger ('plus') or to be one size smaller\n"
1045     " -XXXfontsize minus      ('minus').  The 'plus' version I find useful for\n"
1046     "   *OR*                  a screen resolution of about 100 dots per inch\n"
1047     " -XXXfontsize big        (40 dots per cm) -- you can find what the system\n"
1048     "   *OR*                  thinks your screen resolution is by the command\n"
1049     " -big                      xdpyinfo | grep -i resolution\n"
1050     "   *OR*                  ++ Applying 'plus' twice is the same as 'big'.\n"
1051     " -plus                   ++ Using 'big' will use large Adobe Courier fonts.\n"
1052     "   *OR*                  ++ Alternatively, you can control each of the 4 fonts\n"
1053     " -minus                     that AFNI uses, via the 4 following options ...\n"
1054     "   *OR*                  ++ You can also set the fontsize for your copy\n"
1055     " -norm                      of AFNI in your ~/.afnirc file by setting\n"
1056     "                            environment variable AFNI_FONTSIZE to one of:\n"
1057     "                              big *OR* minus *or* plus\n"
1058     "                         ++ Using 'norm' gives the default AFNI font sizes.\n"
1059     "\n"
1060     " -XXXfontA fontname    = set the X11 font name for the main AFNI\n"
1061     "                         controller\n"
1062     "                         [default = 9x15bold]\n"
1063     "                         ++ To see a list of all X11 font names, type the command\n"
1064     "  xlsfonts | more\n"
1065     "                            *or* more elaborately (to show only fixed width fonts):\n"
1066     "  xlsfonts | grep -e '-[cm]-' | grep -e '-iso8859-1$' | grep -e '-medium-' \\\n"
1067     "           | grep -e '-r-normal-' | grep -v -e '-0-0-' | sort -t '-' -k 8 -n | uniq\n"
1068     "                         ++ It is best to use a fixed width font\n"
1069     "                            (e.g., not Helvetica), or the AFNI buttons\n"
1070     "                            won't line up nicely!\n"
1071     "                         ++ If you use an illegal font name here, you\n"
1072     "                            might make it hard to use the AFNI GUI!\n"
1073     "                         ++ The default fonts are chosen for 'normal' screen\n"
1074     "                            resolutions (about 72 dots per inch = 28 dots per cm).\n"
1075     "                            For higher resolutions ('Retina'), you might\n"
1076     "                            want to use larger fonts.  Adding these\n"
1077     "                            '-XXXfont?' options is one way to address this\n"
1078     "                            problem. (Also see '-plus' above.)\n"
1079     "                         ++ An example of two quite large fonts on my computer\n"
1080     "                            (which at this time has a 108 dot per inch display):\n"
1081     "       '-adobe-courier-bold-r-normal--34-240-100-100-m-200-iso8859-1\n"
1082     "       '-b&h-lucidatypewriter-medium-r-normal-sans-34-240-100-100-m-200-iso8859-1'\n"
1083     "                            Note that to use the latter font on the command line,\n"
1084     "                            you have to enclose the name in quotes, as shown above,\n"
1085     "                            since the 'foundry name' includes the character '&'.\n"
1086     "                            To use it in an alias, you need to do something like\n"
1087     "  alias abig -XXXfontA '-b\\&h-lucidatypewriter-medium-r-normal-sans-34-240-100-100-m-200-iso8859-1'\n"
1088     "                         ++ When setting the fonts, it is often helpful\n"
1089     "                            to set the colors as well.\n"
1090     "\n"
1091     " -XXXfontB fontname    = set the X11 font name for somewhat smaller text\n"
1092     "                         [default = 8x13bold]\n"
1093     "\n"
1094     " -XXXfontC fontname    = set the X11 font name for even smaller text\n"
1095     "                         [default = 7x13]\n"
1096     "\n"
1097     " -XXXfontD fontname    = set the X11 font name for the smallest text\n"
1098     "                         [default = 6x10]\n"
1099     "\n"
1100     " -XXX defaults         = set the X11 properties to the AFNI defaults\n"
1101     "                         (the purpose of this is to restore things )\n"
1102     "                         (to normal if the X11 settings get mangled)\n"
1103     "\n"
1104     " -XXXnpane P           = set the number of 'panes' in the continuous\n"
1105     "                         colorscale to the value 'P', where P is an\n"
1106     "                         even integer between 256 and 2048 (inclusive).\n"
1107     "                         Probably will work best if P is an integral\n"
1108     "                         multiple of 256 (e.g., 256, 512, 1024, 2048).\n"
1109     "                         [This option is for the mysterious Dr ZXu.]\n"
1110     "\n"
1111    ) ;
1112 
1113    printf("\n"
1114     "--------------------------------------\n"
1115     "Educational and Informational Material\n"
1116     "--------------------------------------\n"
1117     "* The presentations used in our AFNI teaching classes at the NIH can\n"
1118     "   all be found at\n"
1119     " https://afni.nimh.nih.gov/pub/dist/edu/latest/      (PowerPoint directories)\n"
1120     " https://afni.nimh.nih.gov/pub/dist/edu/latest/afni_handouts/ (PDF directory)\n"
1121      "\n"
1122     "* And for the interactive AFNI program in particular, see\n"
1123     " https://afni.nimh.nih.gov/pub/dist/edu/latest/afni01_intro/afni01_intro.pdf\n"
1124     " https://afni.nimh.nih.gov/pub/dist/edu/latest/afni03_interactive/afni03_interactive.pdf\n"
1125      "\n"
1126     "* For the -help on all AFNI programs, plus the README files, and more, please see\n"
1127     " https://afni.nimh.nih.gov/pub/dist/doc/program_help/index.html\n"
1128      "\n"
1129     "* For indvidualized help with AFNI problems, and to keep up with AFNI news, please\n"
1130     "   use the AFNI Message Board:\n"
1131     " https://afni.nimh.nih.gov/afni/community/board/\n"
1132      "\n"
1133     "* If an AFNI program crashes, please include the EXACT error messages it outputs\n"
1134     "   in your message board posting, as well as any other information needed to\n"
1135     "   reproduce the problem.  Just saying 'program X crashed, what's the problem?'\n"
1136     "   is not helpful at all!  In all message board postings, detail and context\n"
1137     "   are highly relevant.\n"
1138      "\n"
1139     "* Also, be sure your AFNI distribution is up-to-date.  You can check the date\n"
1140     "   on your copy with the command 'afni -ver'.  If it is more than a few months\n"
1141     "   old, you should update your AFNI binaries and try the problematic command\n"
1142     "   again -- it is quite possible the problem you encountered was already fixed!\n"
1143 #if 0
1144     "\n"
1145     "* For some fun, see this image:\n"
1146     " https://afni.nimh.nih.gov/pub/dist/doc/program_help/images/afni_splashes.gif\n"
1147 #endif
1148    ) ;
1149 
1150    AFNI_list_papers(NULL) ;  /* 02 May 2014 */
1151    printf(
1152     "\n"
1153     "POSTERS on varied subjects from the AFNI development group can be found at\n"
1154     "  * https://afni.nimh.nih.gov/sscc/posters\n"
1155    ) ;
1156 
1157    /*........................................................................*/
1158 #undef  NSLIDE
1159 #define NSLIDE 34
1160    if( AFNI_yesenv("AFNI_POMOC") ){  /* for the Web -help page */
1161      int ii ;
1162      printf("\n"
1163             "------------------------------------------------------------------------------------\n"
1164             "                  SLIDE IMAGES to help with learning the AFNI GUI\n"
1165             "           https://afni.nimh.nih.gov/pub/dist/doc/program_help/images/afni03/\n"
1166             "------------------------------------------------------------------------------------\n"
1167      ) ;
1168      for( ii=1 ; ii <= NSLIDE ; ii++ ){
1169        printf(
1170         "https://afni.nimh.nih.gov/pub/dist/doc/program_help/images/afni03/Slide%02d.png\n"
1171         "------------------------------------------------------------------------------------\n"
1172         , ii ) ;
1173      }
1174    } else {
1175      printf("\n"
1176             "SLIDE IMAGES to help with learning the AFNI GUI can be found at\n"
1177             "  * https://afni.nimh.nih.gov/pub/dist/doc/program_help/images/afni03/\n"
1178      ) ;
1179    }
1180    printf("\n") ;
1181    /*........................................................................*/
1182 
1183    exit(0) ;
1184 }
1185 
1186 /*----------------------------------------------------------------------
1187    parse command line switches and store results in a data structure
1188 ------------------------------------------------------------------------*/
1189 
AFNI_parse_args(int in_argc,char * in_argv[])1190 void AFNI_parse_args( int in_argc , char *in_argv[] )
1191 {
1192    int narg = 1 ;
1193    char *env_orient , *env ;
1194    int    argc=in_argc ,   new_argc      ; /* 18 Nov 1999 */
1195    char **argv=in_argv , **new_argv=NULL ;
1196 
1197 ENTRY("AFNI_parse_args") ;
1198 
1199    if( argc > 1 && strcmp(argv[1],"-help")    == 0 ) AFNI_syntax() ;
1200 
1201    GLOBAL_argopt.dz       = 1.0 ;          /* set up defaults */
1202    GLOBAL_argopt.dy       = 1.0 ;
1203    GLOBAL_argopt.ignore   = INIT_ignore ;
1204    GLOBAL_argopt.elide_quality  = 0 ;      /* Dec 1997 */
1205    GLOBAL_argopt.no_frivolities = 0 ;      /* 01 Aug 1998 */
1206    GLOBAL_argopt.install_cmap   = 0 ;      /* 14 Sep 1998 */
1207    GLOBAL_argopt.read_1D        = 1 ;      /* 27 Jan 2000 */
1208    GLOBAL_argopt.read_tcsv      = 1 ;      /* 16 Jun 2020 */
1209 
1210    GLOBAL_argopt.enable_suma    = 1 ;      /* 29 Aug 2001 */
1211    GLOBAL_argopt.disable_done   = 0 ;      /* 21 Aug 2008 */
1212 
1213    GLOBAL_argopt.yes_niml       = AFNI_yesenv("AFNI_NIML_START") ;
1214    /* GLOBAL_argopt.port_niml      = 0 ;      10 Dec 2002 - Blocked, ZSS 2011*/
1215 
1216 #if 0
1217    GLOBAL_argopt.allow_rt = 0 ;            /* April 1997 */
1218 #else                                      /* 09 Oct 2000 */
1219    GLOBAL_argopt.allow_rt = AFNI_yesenv("AFNI_REALTIME_Activate") ;
1220    GLOBAL_argopt.no_frivolities = (GLOBAL_argopt.allow_rt != 0) ;
1221 #endif
1222 
1223    SESSTRAIL = 1 ;
1224    env = getenv( "AFNI_SESSTRAIL" ) ;
1225    if( env != NULL ){
1226      SESSTRAIL = strtol(env,NULL,10) ;
1227           if( SESSTRAIL < 0 ) SESSTRAIL = 0 ;  /* 24 Aug 2000 */
1228      else if( SESSTRAIL > 4 ) SESSTRAIL = 4 ;  /* 30 May 2018 */
1229    }
1230 
1231    GLOBAL_argopt.elide_quality = AFNI_yesenv("AFNI_MARKERS_NOQUAL") ;
1232 
1233    /* 24 Sep 2000: get the default layout name (add $HOME) */
1234 
1235    { char *lf = getenv("AFNI_LAYOUT_FILE") ;
1236      if( lf != NULL ){
1237         char *eh = getenv("HOME") , *ff ;
1238         int ll = strlen(lf) + 8 ;
1239         if( eh != NULL ) ll += strlen(eh) ;
1240         ff = AFMALL(char, ll) ;
1241         if( eh != NULL && lf[0] != '/' ){ strcpy(ff,eh) ; strcat(ff,"/") ; }
1242         else                            { ff[0] = '\0' ; }
1243         strcat(ff,lf) ;
1244         GLOBAL_argopt.layout_fname = ff ;
1245      }
1246    }
1247 
1248    /* 21 Jan 2003: get the startup script name */
1249 
1250    { char *lf = getenv("AFNI_STARTUP_SCRIPT") ;
1251      if( lf == NULL ) lf = ".afni.startup_script" ;
1252      if( lf != NULL ){
1253        char *eh = NULL , *ff ;
1254        int ll = strlen(lf) + 8 ;
1255        if( !THD_is_file(lf) && lf[0] == '.' ){
1256          if( THD_is_file(lf+1) ) lf = lf+1 ;
1257        }
1258        if( !THD_is_file(lf) && lf[0] != '/' ) eh = getenv("HOME") ;
1259        if( eh != NULL ) ll += strlen(eh) ;
1260        ff = AFMALL(char, ll) ;
1261        if( eh != NULL ){ strcpy(ff,eh) ; strcat(ff,"/") ; }
1262        else            { ff[0] = '\0' ; }
1263        strcat(ff,lf) ;
1264        GLOBAL_argopt.script_fname = ff ;
1265      }
1266    }
1267 
1268    /*-- 18 Nov 1999: Allow setting of options from environment --*/
1269 
1270    env = getenv( "AFNI_OPTIONS" ) ;
1271    if( env != NULL )
1272      prepend_string_to_args( env, in_argc, in_argv, &new_argc, &new_argv ) ;
1273    if( new_argv != NULL ){
1274      MAIN_argc = argc = new_argc ;
1275      MAIN_argv = argv = new_argv ;
1276    }
1277 
1278 #ifdef ALLOW_PLUGINS
1279    GLOBAL_argopt.noplugins  =  AFNI_yesenv( "AFNI_NOPLUGINS" ) ;
1280    GLOBAL_argopt.noplugouts = !AFNI_yesenv( "AFNI_YESPLUGOUTS" ) ;
1281 #endif
1282 
1283    env_orient = getenv( "AFNI_ORIENT" ) ;
1284 
1285    GLOBAL_argopt.read_sessions = True ;        /* exactly one of these should be True */
1286    GLOBAL_argopt.read_images   = False ;
1287    GLOBAL_argopt.read_dsets    = False ;       /* 17 Mar 2000 */
1288 
1289    GLOBAL_argopt.datum         = ILLEGAL_TYPE ;
1290 
1291    GLOBAL_argopt.gamma         = INIT_gamma ;
1292    GLOBAL_argopt.gsfac         = 0.0 ;
1293    GLOBAL_argopt.ncolor        = INIT_ngray ;
1294 #if MMAP_THRESHOLD > 0
1295    GLOBAL_argopt.auto_purge    = INIT_purge ;
1296 #else
1297    GLOBAL_argopt.auto_purge    = (RwcBoolean)!AFNI_noenv("AFNI_AUTOPURGE") ;
1298 #endif
1299    GLOBAL_argopt.resize_images = False ;       /* False means all images must match */
1300    GLOBAL_argopt.keep_logo     = False ;       /* For making pretty pictures? */
1301    GLOBAL_argopt.pos_func      = INIT_posfunc ;/* Positive valued functions? */
1302    GLOBAL_argopt.recurse       = 0 ;           /* Recurse on session directories? */
1303    GLOBAL_argopt.xtwarns       = 0     ;       /* > 0 means keep Xt warnings turned on */
1304    GLOBAL_argopt.destruct      = False ;       /* True means allow overwrite of datasets */
1305                                                /* (Not yet properly implemented!) */
1306 
1307    GLOBAL_argopt.tlrc_big      = INIT_tlrc_big ; /* use the big Talairach box? */
1308 #ifndef WARP_4D
1309    GLOBAL_argopt.warp_4D       = False ;
1310 #else
1311    GLOBAL_argopt.warp_4D       = True ;
1312 #endif
1313 
1314    GLOBAL_argopt.unique_dcs    = False ;  /* 06 Nov 1996 */
1315 
1316    strcpy(GLOBAL_argopt.orient_code,"---") ;
1317 
1318    strcpy(GLOBAL_argopt.title_name,"AFNI") ;           /* default title bar name */
1319 
1320    GLOBAL_argopt.left_is_left      = AFNI_yesenv( "AFNI_LEFT_IS_LEFT" ) ;
1321    GLOBAL_argopt.left_is_posterior = AFNI_yesenv( "AFNI_LEFT_IS_POSTERIOR" ) ;
1322 
1323    GLOBAL_argopt.read_tim = 0 ;   /* 19 Oct 1999 */
1324 
1325    GLOBAL_argopt.cat_sess = !AFNI_noenv("AFNI_ALL_DATASETS") ; /* 02 Jun 2016 */
1326 
1327    /* 04/06/2020 discoraj */
1328    GLOBAL_argopt.all_dsets_startup = AFNI_yesenv("ALL_DSETS_STARTUP") ;
1329 
1330    while( narg < argc ){
1331 
1332       if( argv[narg][0] != '-' ) break ;   /* no - ==> quit */
1333 
1334 #ifdef USE_TRACING
1335       if( strncmp(argv[narg],"-trace",5) == 0 ){
1336          DBG_trace = 1 ;
1337          narg++ ; continue ;
1338       }
1339       if( strncmp(argv[narg],"-TRACE",5) == 0 ){  /* 23 Aug 1998 */
1340          DBG_trace = 2 ;
1341          if( MAIN_shell != NULL )
1342             XSynchronize(XtDisplay(MAIN_shell),TRUE) ; /* 01 Dec 1999 */
1343          narg++ ; continue ;
1344       }
1345 #endif
1346 
1347 #if 0
1348       /*----- -Dname=val -- set environment variable [22 Mar 2005] -----*/
1349 
1350       if( strncmp(argv[narg],"-D",2) == 0 && strchr(argv[narg],'=') != NULL ){
1351         (void) AFNI_setenv( argv[narg]+2 ) ;
1352         narg++ ; continue ;                 /* go to next arg */
1353       }
1354 #endif
1355 
1356       /*-----   -bysub or -BIDS  -----*/
1357 
1358       if( strcasecmp(argv[narg],"-bysub") == 0 ||
1359           strcasecmp(argv[narg],"-BIDS")  == 0   ){  /* 01 Feb 2018 */
1360         int bb ; char **alist ; int nba,nta,aa , inc_narg ;
1361 
1362         narg++ ;
1363         if( narg >= argc || argv[narg][0] == '-' ){     /* trickery to use */
1364           alist = (char **)malloc(sizeof(char *)*1) ;   /* "." if aren't */
1365           alist[0] = "." ; nba = 0 ; nta = 1 ;          /* any args here */
1366           inc_narg = 0 ;
1367         } else {                                 /* scan the full arg list */
1368           alist = argv ; nba = narg ; nta = argc ; inc_narg = 1 ;
1369         }
1370 
1371         for( aa=nba ;                             /* loop over args */
1372              aa < nta && alist[aa][0] != '-' ;    /* following option */
1373              aa++ , narg += inc_narg           ){
1374 
1375           if( THD_is_directory(alist[aa])        &&
1376               strncmp(alist[aa],"sub-",4) != 0   &&    /* method 2 */
1377               alist[aa][0]                != '-'   ){  /* find all sub- names [15 Apr 2019] */
1378 
1379             char *cmd=NULL , *flist=NULL , *qmd=NULL ; NI_str_array *qsar=NULL ; int qq ;
1380             cmd = (char *)malloc(sizeof(char)*(128+strlen(alist[aa]))) ;
1381             sprintf( cmd, "find %s -maxdepth 1 -type d -name 'sub-*'", alist[aa] ) ;
1382             flist = THD_suck_pipe( cmd ) ; free(cmd) ;
1383             if( flist == NULL || strlen(flist) < 4 ){
1384               WARNING_message("-bysub: Didn't find any 'sub-*' under %s",alist[aa]) ;
1385               continue ;
1386             }
1387             qsar = NI_decode_string_list( flist , ";" ) ;
1388             if( qsar == NULL || qsar->num == 0 ){    /* should never happen */
1389               WARNING_message("-bysub: Didn't find any 'sub-*' under %s",alist[aa]) ;
1390               free(flist) ;
1391               continue ;
1392             }
1393             for( qq=0 ; qq < qsar->num ; qq++ ){
1394               cmd = qsar->str[qq] ; if( cmd == NULL ) continue ;
1395               bb  = strlen(cmd) ;   if( bb  <  2    ) continue ;
1396               if( cmd[bb-1] == '/' ) cmd[bb-1] = '\0' ;
1397               qmd = strrchr(cmd,'/') ;
1398               if( qmd != NULL ){ qmd++ ; } else { cmd = qmd ; }
1399               bysub = (char **)realloc(bysub,sizeof(char *)*(num_bysub+1)) ;
1400               bysub[num_bysub++] = strdup(qmd) ;
1401               bysub_dir = (char **)realloc(bysub_dir,sizeof(char *)*(num_bysub_dir+1)) ;
1402               bysub_dir[num_bysub_dir++] = strdup(alist[aa]) ;
1403             }
1404 
1405           } else {                             /* method 1: a sub-XXX name */
1406 
1407             bysub = (char **)realloc(bysub,sizeof(char *)*(num_bysub+1)) ;
1408             if( strncmp(alist[aa],"sub-",4) == 0 ){
1409               bysub[num_bysub] = strdup(alist[aa]) ;
1410             } else {
1411               bysub[num_bysub] = (char *)malloc(sizeof(char)*(strlen(alist[aa])+8)) ;
1412               sprintf( bysub[num_bysub] , "sub-%s" , alist[aa] ) ;
1413             }
1414             bb = strlen(bysub[num_bysub]) ;
1415             if( bb > 1 && bysub[num_bysub][bb-1] == '/' )
1416               bysub[num_bysub][bb-1] = '\0' ;
1417             num_bysub++ ;
1418           }
1419 
1420         } /* end of loop over -bysub args */
1421 
1422         if( alist != argv ) free(alist) ;
1423         if( narg < argc && strcmp(argv[narg],"-") == 0 ) narg++ ;
1424         continue ;
1425       }
1426 
1427       if( strcmp(argv[narg],"-seehidden") == 0 ){
1428         first_plugin_check = 1 ;
1429         narg++ ; continue ;
1430       }
1431 
1432       /*----- -layout (23 Sep 2000) -----*/
1433 
1434       if( strcmp(argv[narg],"-layout") == 0 ){
1435          if( narg+1 >= argc ) ERROR_exit("need an argument after -layout!") ;
1436          GLOBAL_argopt.layout_fname = argv[++narg] ;  /* just a pointer */
1437          narg++ ; continue ;  /* go to next arg */
1438       }
1439 
1440       /*----- -no1D option (27 Jan 2000) ----- */
1441 
1442       if( strncmp(argv[narg],"-no1D",5) == 0 ){
1443          GLOBAL_argopt.read_1D = 0 ;
1444          narg++ ; continue ;  /* go to next arg */
1445       }
1446 
1447       /*----- -notcsv option (16 Jun 2020) ----- */
1448 
1449       if( strncmp(argv[narg],"-notcsv",7) == 0 ||
1450           strncmp(argv[narg],"-notsv" ,6) == 0 ||
1451           strncmp(argv[narg],"-nocsv" ,6) == 0   ){
1452          GLOBAL_argopt.read_tcsv = 0 ;
1453          narg++ ; continue ;  /* go to next arg */
1454       }
1455 
1456       /*----- -skip_afnirc option (14 Jul 1998) -----*/
1457 
1458       if( strncmp(argv[narg],"-skip_afnirc",12) == 0 ){
1459          GLOBAL_argopt.skip_afnirc  = 1 ;
1460          narg++ ; continue ;  /* go to next arg */
1461       }
1462 
1463       /*----- -rt option -----*/
1464 
1465       if( strncmp(argv[narg],"-rt",3) == 0 ){
1466          GLOBAL_argopt.allow_rt       = -1 ;
1467          GLOBAL_argopt.no_frivolities =  1 ;
1468 #if 0
1469 #ifdef USE_TRACING
1470          DBG_trace                    =  0 ;  /* 26 Jan 2001 */
1471 #endif
1472 #endif
1473          narg++ ; continue ;  /* go to next arg */
1474       }
1475 
1476       if( strncmp(argv[narg],"-nort",5) == 0 ){  /* 09 Oct 2000 */
1477          GLOBAL_argopt.allow_rt       = 0 ;
1478          GLOBAL_argopt.no_frivolities = 0 ;
1479          narg++ ; continue ;  /* go to next arg */
1480       }
1481 
1482       /*----- -noqual -----*/
1483 
1484       if( strncmp(argv[narg],"-noqual",6) == 0 ){
1485          GLOBAL_argopt.elide_quality = 1 ;
1486          narg++ ; continue ;  /* go to next arg */
1487       }
1488 
1489       /*---- -agni [29 Aug 2001] or -suma -----*/
1490 
1491       if( strcmp(argv[narg],"-agni")==0 || strcmp(argv[narg],"-suma")==0 ){
1492          fprintf(stderr,"\n-agni/-suma are now turned on by default\n") ;
1493          GLOBAL_argopt.enable_suma = 1 ;
1494          narg++ ; continue ;  /* go to next arg */
1495       }
1496 
1497       /*---- -comsep c [22 Feb 2007] ----*/
1498 
1499       if( strcmp(argv[narg],"-comsep") == 0 ){
1500         char cc ;
1501         if( ++narg >= argc ) ERROR_exit("need an argument after -comsep") ;
1502         cc = argv[narg][0] ;
1503         if( cc=='\0' || isalnum(cc) || isspace(cc) || cc=='\'' || cc=='\"' )
1504           ERROR_message("Illegal character after -comsep") ;
1505         else
1506           comsep = cc ;
1507 
1508         narg++ ; continue ;
1509       }
1510 
1511       /*---- -com ccc [29 Jul 2005] ----*/
1512 
1513       if( strcmp(argv[narg],"-com") == 0 ){
1514         int ii , ll ; char *cm , *cs , *cq ;
1515         if( ++narg >= argc ) ERROR_exit("need an argument after -com!");
1516         cm = argv[narg] ; ll = strlen(cm) ; cs = strchr(cm,comsep) ;
1517              if( ll > 1024   ) ERROR_message("argument after -com is too long:\n'%s'" ,argv[narg] );
1518         else if( ll <   3   ) ERROR_message ("argument after -com is too short:\n'%s'",argv[narg] );
1519         else if( cs == NULL ) {
1520            if (COM_num < MAX_N_COM) COM_com[ COM_num++ ] = strdup(argv[narg]) ;
1521            else ERROR_message("Too many commands (max allowed=%d)",MAX_N_COM);
1522         } else {  /* 22 Feb 2007: break into sub-commands */
1523           cq = cm = strdup(argv[narg]) ;
1524           for( ii=ll-1 ; isspace(cm[ii]) ; ii-- ) cm[ii] = '\0' ; /* trim end */
1525           cs = strchr(cm,comsep) ;
1526           while(1){
1527             *cs = '\0' ;  /* NUL terminate command at separator */
1528             for( ; *cm != '\0' && isspace(*cm) ; cm++ ) ; /* trim front */
1529             ll = strlen(cm) ;
1530             if( ll > 2 && ll <= 1024 ) {
1531                if (COM_num < MAX_N_COM) COM_com[ COM_num++ ] = strdup(cm) ;
1532                else ERROR_message("Too many commands in total.");
1533             } cm = cs+1 ; if( *cm == '\0' ) break ;  /* reached the end */
1534             cs = strchr(cm,comsep) ;               /* search for next sep */
1535             if( cs == NULL ) cs = cm + strlen(cm) ;
1536           }
1537           free(cq) ;
1538         }
1539 
1540         narg++ ; continue ;  /* go to next arg */
1541       }
1542 
1543       /*---- -disable_done [21 Aug 2008, rickr] ----*/
1544       /*     This flag disables use of the "done" and X buttons.
1545              Close afni via plugout_drive or kill.                  */
1546 
1547       if( strcmp(argv[narg],"-disable_done") == 0 ){
1548          GLOBAL_argopt.disable_done = 1 ;
1549          narg++ ; continue ;
1550       }
1551 
1552       /*---- -niml [28 Feb 2002] -----*/
1553 
1554       if( strcmp(argv[narg],"-niml") == 0 ){
1555          if( GLOBAL_argopt.yes_niml )
1556            fprintf(stderr,"\n-niml is already turned on\n") ;
1557          GLOBAL_argopt.yes_niml++ ;
1558          narg++ ; continue ;  /* go to next arg */
1559       }
1560 
1561       if( strcmp(argv[narg],"-noniml") == 0 ){
1562          GLOBAL_argopt.yes_niml-- ;
1563          if( GLOBAL_argopt.yes_niml < 0 ) GLOBAL_argopt.yes_niml = 0 ;
1564          narg++ ; continue ;  /* go to next arg */
1565       }
1566 
1567       /*----- -tbar 'name' option -----*/
1568 
1569       if( strncmp(argv[narg],"-tbar",5) == 0 ){
1570          if( narg+1 >= argc ) ERROR_exit("need an argument after -tbar!");
1571          MCW_strncpy(GLOBAL_argopt.title_name,argv[++narg],32) ;
1572          narg++ ; continue ;  /* go to next arg */
1573       }
1574 
1575       /*----- -xtwarns option -----*/
1576 
1577       if( strncmp(argv[narg],"-xtwarns",6) == 0 ){
1578          GLOBAL_argopt.xtwarns = 1 ;
1579          narg++ ; continue ;  /* go to next arg */
1580       }
1581 
1582       if( strncmp(argv[narg],"-XTWARNS",6) == 0 ){
1583          GLOBAL_argopt.xtwarns = 2 ;
1584          narg++ ; continue ;  /* go to next arg */
1585       }
1586 
1587       /*----- -XXX [24 Mar 2016] -----*/
1588 
1589       if( strncasecmp(argv[narg],"-XXX",4) == 0 ){  /* all -XXX options are */
1590         narg += 2 ; continue ;                      /* followed by one arg */
1591       }
1592       if( strcasecmp(argv[narg],"-big")   == 0 ){ narg++; continue; }
1593       if( strcasecmp(argv[narg],"-plus")  == 0 ){ narg++; continue; }
1594       if( strcasecmp(argv[narg],"-minus") == 0 ){ narg++; continue; }
1595       if( strcasecmp(argv[narg],"-norm")  == 0 ){ narg++; continue; }
1596 
1597       /*----- -destruct option -----*/
1598 
1599       if( strncmp(argv[narg],"-destruct",6) == 0 ){   /** has no effect at present **/
1600          fprintf(stderr,"\n** -destruct option not implemented at present! **\n") ;
1601          GLOBAL_argopt.destruct = False ;
1602          narg++ ; continue ;  /* go to next arg */
1603       }
1604 
1605       /*----- -posfunc option -----*/
1606 
1607       if( strncmp(argv[narg],"-posfunc",6) == 0 ){
1608          GLOBAL_argopt.pos_func = True ;
1609          narg++ ; continue ;  /* go to next arg */
1610       }
1611 
1612       /*----- -R option -----*/
1613 
1614       if( strncmp(argv[narg],"-R",2) == 0 ){
1615          int ll = strlen(argv[narg]) ;
1616          if( ll == 2 ) GLOBAL_argopt.recurse = 999 ;
1617          else {
1618             ll = strtol( argv[narg]+2 , NULL , 10 ) ;
1619             if( ll > 0 ) GLOBAL_argopt.recurse = ll ;
1620             else ERROR_exit("illegal -R option!") ;
1621          }
1622          narg++ ; continue ;  /* go to next arg */
1623       }
1624 
1625       /*----- -tlrc_big option -----*/
1626 
1627       if( strncmp(argv[narg],"-tlrc_big",7) == 0 ){
1628          GLOBAL_argopt.tlrc_big = True ;
1629          narg++ ; continue ;  /* go to next arg */
1630       }
1631 
1632       /*----- -unique option (06 Nov 1996) -----*/
1633 
1634       if( strncmp(argv[narg],"-unique",5) == 0 ){
1635          GLOBAL_argopt.unique_dcs = True ;
1636          narg++ ; continue ;  /* go to next arg */
1637       }
1638 
1639       /*----- -install option (14 Sep 1998) -----*/
1640 
1641       if( strncmp(argv[narg],"-install",5) == 0 ){
1642          GLOBAL_argopt.install_cmap = True ;
1643          narg++ ; continue ;  /* go to next arg */
1644       }
1645 
1646 #ifndef WARP_4D
1647       /*----- -warp_4D option -----*/
1648 
1649       if( strncmp(argv[narg],"-warp_4D",7) == 0 ){
1650          GLOBAL_argopt.warp_4D = True ;
1651          narg++ ; continue ;  /* go to next arg */
1652       }
1653 #endif
1654 
1655       /*----- -tlrc_small option -----*/
1656 
1657       if( strncmp(argv[narg],"-tlrc_small",7) == 0 ){
1658          GLOBAL_argopt.tlrc_big = False ;
1659          narg++ ; continue ;  /* go to next arg */
1660       }
1661 
1662       /*----- -logo option -----*/
1663 
1664       if( strncmp(argv[narg],"-logo",4) == 0 ){
1665          GLOBAL_argopt.keep_logo = True ;
1666          narg++ ; continue ;  /* go to next arg */
1667       }
1668 
1669       /*----- -resize option -----*/
1670 
1671       if( strncmp(argv[narg],"-resize",4) == 0 ){
1672          GLOBAL_argopt.resize_images = True ;
1673          narg++ ; continue ;  /* go to next arg */
1674       }
1675 
1676       /*----- -purge option -----*/
1677 
1678       if( strncmp(argv[narg],"-purge",4) == 0 ){
1679          GLOBAL_argopt.auto_purge = True ;
1680          narg++ ; continue ;  /* go to next arg */
1681       }
1682       if( strncmp(argv[narg],"-nopurge",6) == 0 ){
1683          GLOBAL_argopt.auto_purge = False ;
1684          narg++ ; continue ;  /* go to next arg */
1685       }
1686 
1687 #ifdef ALLOW_PLUGINS
1688       /*----- -noplugins option -----*/
1689 
1690       if( strncmp(argv[narg],"-noplugins",10) == 0 ){
1691          GLOBAL_argopt.noplugins = 1 ;
1692          narg++ ; continue ;  /* go to next arg */
1693       }
1694 
1695       /*----- -noplugouts option -----*/
1696 
1697       if( strncmp(argv[narg],"-noplugouts",10) == 0 ){
1698          GLOBAL_argopt.noplugouts = 1 ;
1699          narg++ ; continue ;  /* go to next arg */
1700       }
1701 
1702       /*----- -yesplugouts option -----*/
1703 
1704       if( strncmp(argv[narg],"-yesplugouts",10) == 0 ){
1705          GLOBAL_argopt.noplugouts   = 0 ;
1706          GLOBAL_argopt.plugout_code = 0 ;
1707          narg++ ; continue ;  /* go to next arg */
1708       }
1709 
1710       /*----- -yesplugouts option -----*/
1711 
1712       if( strncmp(argv[narg],"-YESplugouts",10) == 0 ){
1713          GLOBAL_argopt.noplugouts   = 0 ;
1714          GLOBAL_argopt.plugout_code = 1 ;
1715          narg++ ; continue ;  /* go to next arg */
1716       }
1717 #endif
1718 
1719       /*----- -flipim option -----*/
1720 
1721       if( strncmp(argv[narg],"-flipim",5) == 0 ){
1722          GLOBAL_argopt.left_is_left = 0 ;
1723          narg++ ; continue ;  /* go to next arg */
1724       }
1725 
1726       /*----- -noflipim option -----*/
1727 
1728       if( strncmp(argv[narg],"-noflipim",5) == 0 ){
1729          GLOBAL_argopt.left_is_left = 1 ;
1730          narg++ ; continue ;  /* go to next arg */
1731       }
1732 
1733       /*----- -orient code option -----*/
1734 
1735       if( strncmp(argv[narg],"-orient",4) == 0 ){
1736          if( narg+1 >= argc ) ERROR_exit("need an argument after -orient!");
1737 
1738          MCW_strncpy(GLOBAL_argopt.orient_code,argv[++narg],4) ;
1739          narg++ ; continue ;  /* go to next arg */
1740       }
1741 
1742       /*----- -ignore # option -----*/
1743 
1744       if( strncmp(argv[narg],"-ignore",4) == 0 ){
1745          float val ;
1746          if( narg+1 >= argc ) ERROR_exit("need an argument after -ignore!");
1747 
1748          val = strtod( argv[++narg] , NULL ) ;
1749          if( val >= 0 ) GLOBAL_argopt.ignore = (int) val ;
1750          else fprintf(stderr,
1751                 "\n** WARNING: -ignore value %s illegal\n", argv[narg]);
1752 
1753          narg++ ; continue ;  /* go to next arg */
1754       }
1755 
1756       /*----- -im1 # option [must come before '-im' option!] -----*/
1757 
1758       if( strncmp(argv[narg],"-im1",4) == 0 ){
1759          float val ;
1760          if( narg+1 >= argc ) ERROR_exit("need an argument after -im1!");
1761 
1762          val = strtod( argv[++narg] , NULL ) ;
1763          if( val >= 1 ) GLOBAL_argopt.ignore = (int) (val-1.0) ;
1764          else fprintf(stderr,
1765                 "\n** WARNING: -ignore value %s illegal\n", argv[narg]);
1766 
1767          narg++ ; continue ;  /* go to next arg */
1768       }
1769 
1770 
1771       /*----- -dy # option -----*/
1772 
1773       if( strncmp(argv[narg],"-dy",3) == 0 ){
1774          float val ;
1775          if( narg+1 >= argc ) ERROR_exit("need an argument after -dy!");
1776 
1777          val = strtod( argv[++narg] , NULL ) ;
1778          if( val > 0 ) GLOBAL_argopt.dy = val ;
1779          else fprintf(stderr,
1780                 "\n** WARNING: -dy value %s illegal\n", argv[narg]);
1781 
1782          narg++ ; continue ;  /* go to next arg */
1783       }
1784 
1785       /*----- -dz # option -----*/
1786 
1787       if( strncmp(argv[narg],"-dz",3) == 0 ){
1788          float val ;
1789          if( narg+1 >= argc ) ERROR_exit("need an argument after -dz!");
1790 
1791          val = strtod( argv[++narg] , NULL ) ;
1792          if( val > 0 ) GLOBAL_argopt.dz = val ;
1793          else fprintf(stderr,
1794                 "\n** WARNING: -dz value %s illegal\n", argv[narg]);
1795 
1796          narg++ ; continue ;  /* go to next arg */
1797       }
1798 
1799       /*----- -gamma # option -----*/
1800 
1801       if( strncmp(argv[narg],"-gamma",4) == 0 ){
1802          float val ;
1803          if( narg+1 >= argc ) ERROR_exit("need an argument after -gamma!");
1804 
1805          val = strtod( argv[++narg] , NULL ) ;
1806          if( val > 0 ) GLOBAL_argopt.gamma = val ;
1807          else fprintf(stderr,
1808                 "\n** WARNING: -gamma value %s illegal\n", argv[narg]);
1809 
1810          narg++ ; continue ;  /* go to next arg */
1811       }
1812 
1813 #ifdef USE_GSFAC
1814       /*----- -gsfac # option -----*/
1815 
1816       if( strncmp(argv[narg],"-gsfac",4) == 0 ){
1817          float val ;
1818          if( narg+1 >= argc ) ERROR_exit("need an argument after -gsfac!");
1819 
1820          val = strtod( argv[++narg] , NULL ) ;
1821          if( val != 0 ) GLOBAL_argopt.gsfac = val ;
1822          else fprintf(stderr,
1823                 "\n** WARNING: -gsfac value %s illegal\n", argv[narg]);
1824 
1825          narg++ ; continue ;  /* go to next arg */
1826       }
1827 #endif
1828 
1829       /*----- -datum type option -----*/
1830 
1831       if( strncmp(argv[narg],"-datum",6) == 0 ){
1832          if( ++narg >= argc ) ERROR_exit("need an argument after -datum!") ;
1833 
1834          if( strcmp(argv[narg],"short") == 0 ){
1835             GLOBAL_argopt.datum= MRI_short ;
1836          } else if( strcmp(argv[narg],"float") == 0 ){
1837             GLOBAL_argopt.datum= MRI_float ;
1838          } else if( strcmp(argv[narg],"complex") == 0 ){
1839             GLOBAL_argopt.datum= MRI_complex ;
1840          } else if( strcmp(argv[narg],"byte") == 0 ){
1841             GLOBAL_argopt.datum= MRI_byte ;
1842          } else {
1843             char buf[1024] ;
1844             sprintf(buf,"-datum of type '%s' is not supported in AFNI!",
1845                    argv[narg] ) ;
1846             ERROR_exit(buf) ;
1847          }
1848          narg++ ; continue ;  /* go to next arg */
1849       }
1850 
1851       /*----- -ncolor # option -----*/
1852 
1853       if( strncmp(argv[narg],"-ncolor",3) == 0 ){
1854          float val ;
1855          if( narg+1 >= argc ) ERROR_exit("need an argument after -ncolor!");
1856 
1857          val = strtod( argv[++narg] , NULL ) ;
1858          if( val > 2 ) GLOBAL_argopt.ncolor = val ;
1859          else fprintf(stderr,
1860                 "\n** WARNING: -ncolor value %s illegal\n", argv[narg]);
1861 
1862          narg++ ; continue ;  /* go to next arg */
1863       }
1864 
1865       /*----- -dset option [17 Mar 2000] -----*/
1866 
1867       if( strncmp(argv[narg],"-dset",5) == 0 ){
1868          GLOBAL_argopt.read_images   = False ;
1869          GLOBAL_argopt.read_sessions = False ;
1870          GLOBAL_argopt.read_dsets    = True  ;
1871          narg++ ; continue ;  /* go to next arg */
1872       }
1873 
1874       /*----- -im option -----*/
1875 
1876       if( strncmp(argv[narg],"-im",3) == 0 ){
1877          fprintf(stderr,
1878           "\n** WARNING: option '%s' for viewing plain images is old and not very useful\n" ,
1879           argv[narg] ) ;
1880          GLOBAL_argopt.read_images   = True ;
1881          GLOBAL_argopt.read_sessions = False ;
1882          GLOBAL_argopt.read_dsets    = False ;       /* 17 Mar 2000 */
1883          narg++ ; continue ;  /* go to next arg */
1884       }
1885 
1886       /*----- -tim option [19 Oct 1999] -----*/
1887 
1888       if( strncmp(argv[narg],"-tim",4)==0 || strncmp(argv[narg],"-zim",4)==0 ){
1889          int ll=strlen(argv[narg]) , nn ;
1890 
1891          GLOBAL_argopt.read_images   = True ;
1892          GLOBAL_argopt.read_sessions = False ;
1893          GLOBAL_argopt.read_dsets    = False ;  /* 17 Mar 2000 */
1894          GLOBAL_argopt.read_tim      = 1 ;
1895 
1896          if( ll > 5 && argv[narg][4] == ':' ){         /* 20 Oct 1999 */
1897             nn = strtol( argv[narg]+5 , NULL , 10 ) ;
1898             if( nn > 1 ){
1899                GLOBAL_argopt.read_tim = nn ; /* will be nz or nt */
1900             } else {
1901                ERROR_exit("Illegal value in %s",argv[narg]);
1902             }
1903          }
1904 
1905          /* negate flag for time-order first (-tim) vs z-order first (-zim) */
1906 
1907          if( strncmp(argv[narg],"-tim",4)==0 && GLOBAL_argopt.read_tim > 1 )
1908             GLOBAL_argopt.read_tim = - GLOBAL_argopt.read_tim ;
1909 
1910          narg++ ; continue ;  /* go to next arg */
1911       }
1912 
1913       /* -port_number and quit */
1914       if( strncmp(argv[narg],"-port_number", 8) == 0) {
1915          int pp = 0;
1916          if( ++narg >= argc )
1917             ERROR_exit("need an argument after -port_number!");
1918          pp = get_port_named(argv[narg]);
1919          if (strcmp(argv[narg-1], "-port_number_quiet")) {
1920             fprintf(stdout, "\nPort %s: %d\n", argv[narg], pp);
1921          } else {
1922             fprintf(stdout, "%d\n", pp);
1923          }
1924          if (pp < 1) exit(1);
1925          else exit(0);
1926       }
1927 
1928       /*----- -nomall option -----*/
1929 
1930       if( strncmp(argv[narg],"-nomall",5) == 0 ){    /* was handled in main() */
1931          narg++ ; continue ;  /* go to next arg */
1932       }
1933 
1934       /*----- -motif_ver option -----*/
1935 
1936       if( strncmp(argv[narg],"-motif_ver",10) == 0 ){/* was handled in main() */
1937          narg++ ; continue ;  /* go to next arg */
1938       }
1939 
1940       /*----- -no_detach option -----*/
1941 
1942       if( strncmp(argv[narg],"-no_detach",7) == 0 ){/* was handled in main() */
1943          narg++ ; continue ;  /* go to next arg */
1944       }
1945 
1946       /*----- -q option -----*/
1947 
1948       if( strcmp(argv[narg],"-q") == 0 ){            /* was handled in main() */
1949          narg++ ; continue ;  /* go to next arg */
1950       }
1951 
1952       /*----- all data sets 04/06/2020 discoraj -----*/
1953       if( strcmp(argv[narg],"-all_dsets") == 0 ){
1954 
1955           // check for env variable that overides -all_dsets
1956           if( AFNI_noenv("AFNI_ALL_DATASETS") ){
1957               fprintf(stderr,
1958                   "\n\n** WARNING: option -all_dsets is ignored silently.") ;
1959               fprintf(stderr,"\n            AFNI_ALL_DATASETS = NO.\n") ;
1960               GLOBAL_argopt.all_dsets_startup = 0 ;
1961            }
1962            else { GLOBAL_argopt.all_dsets_startup = 1 ; }
1963 
1964          GLOBAL_argopt.all_dsets_startup = 1 ;
1965          narg++ ; continue ;  /* go to next arg */
1966       }
1967 
1968       /*----- -- option -----*/
1969 
1970       if( strcmp(argv[narg],"--") == 0 ){
1971          narg++ ; break ;  /* end of args */
1972       }
1973 
1974       /*----- if we get here, bad news for America! -----*/
1975 
1976       ERROR_message("Unknown option %s ***",argv[narg]) ;
1977       suggest_best_prog_option(argv[0], argv[narg]);
1978       ERROR_exit   ("Try 'afni -help' for a list of command line options.") ;
1979 
1980    } /* end of loop over argv's starting with '-' */
1981 
1982    if( num_bysub > 0 && GLOBAL_argopt.recurse ){  /* 01 Feb 2018 */
1983      WARNING_message("-bysub disables -R option") ;
1984      GLOBAL_argopt.recurse = 0 ;
1985    }
1986 
1987 #if 0
1988 #ifdef USE_TRACING
1989    if( ALLOW_realtime ) DBG_trace = 0 ; /* 26 Jan 2001 */
1990 #endif
1991 #endif
1992 
1993    /** 16 July 1997: orientation code change **/
1994 
1995    if( GLOBAL_argopt.orient_code[0] == '-' ){
1996       if( GLOBAL_argopt.read_images )
1997          strcpy(GLOBAL_argopt.orient_code,"ASL") ;
1998       else if( env_orient != NULL )
1999          MCW_strncpy(GLOBAL_argopt.orient_code,env_orient,4) ;
2000       else
2001          strcpy(GLOBAL_argopt.orient_code,"RAI") ;
2002    }
2003 
2004    THD_coorder_fill( GLOBAL_argopt.orient_code , &GLOBAL_library.cord ) ;
2005 
2006 #if 0
2007 fprintf(stderr,"\ncoorder: signs = %d %d %d  order = %d %d %d\n" ,
2008         GLOBAL_library.cord.xxsign ,
2009         GLOBAL_library.cord.yysign ,
2010         GLOBAL_library.cord.zzsign ,
2011         GLOBAL_library.cord.first ,
2012         GLOBAL_library.cord.second ,
2013         GLOBAL_library.cord.third   ) ;
2014 #endif
2015 
2016    GLOBAL_argopt.first_file_arg = narg ;  /* rest of args must be files (I hope) */
2017 
2018    EXRETURN ;
2019 }
2020 
2021 /*-----------------------------------------------------------------------
2022    This routine is used if hiding Xt warnings is enabled.
2023    It does very little -- it replaces the default Xt warning handler.
2024 -------------------------------------------------------------------------*/
2025 
AFNI_handler(char * msg)2026 void AFNI_handler(char *msg){
2027    if( GLOBAL_argopt.xtwarns > 0 &&
2028        msg != NULL               &&
2029        strstr(msg,"Attempt to add wrong") == NULL ){
2030      ERROR_message("Xt message: %s", msg ) ;
2031      TRACEBACK ;
2032    }
2033    return ;
2034 }
2035 
2036 /*-----------------------------------------------------------------------*/
2037 /*! Avoid fatal X11 errors.  Stupid thing is so touchy sometimes. */
2038 
AFNI_xerrhandler(Display * d,XErrorEvent * x)2039 int AFNI_xerrhandler( Display *d , XErrorEvent *x ){
2040   if( GLOBAL_argopt.xtwarns > 0 ){
2041     char buf[1024] = "(null)" ;
2042     if( x != NULL && d != NULL ) XGetErrorText( d,x->error_code , buf,255 ) ;
2043     ERROR_message( "Intercepted fatal X11 error: %s\n",buf) ;
2044     TRACEBACK ;
2045   }
2046   return 0 ;
2047 }
2048 
2049 /*-----------------------------------------------------------------------*/
2050 /* Signal handler for fatal errors; prints out some info before death. */
2051 
2052 #include <signal.h>
AFNI_sigfunc(int sig)2053 void AFNI_sigfunc(int sig)
2054 {
2055    char *sname ;
2056    static volatile int fff=0 ;
2057    if( fff ) _exit(1) ; else fff = 1 ;
2058    switch(sig){
2059       default:      sname = "unknown" ; break ;
2060       case SIGINT:  sname = "SIGINT"  ; break ;
2061       case SIGPIPE: sname = "SIGPIPE" ; break ;
2062       case SIGSEGV: sname = "SIGSEGV" ; break ;
2063       case SIGBUS:  sname = "SIGBUS"  ; break ;
2064       case SIGTERM: sname = "SIGTERM" ; break ;
2065    }
2066    fprintf(stderr,"\nFatal Signal %d (%s) received\n",sig,sname); fflush(stderr);
2067    TRACEBACK ;
2068    fprintf(stderr,"** AFNI version = " AVERZHN "  Compile date = " __DATE__ "\n" );
2069 #ifdef SHSTRING
2070    fprintf(stderr,"** [[Precompiled binary " SHSTRING ": " __DATE__ "]]\n") ;
2071 #endif
2072    fprintf(stderr,"** AFNI Program Is Dead :-( **\n") ;
2073    fflush(stderr) ;
2074    if( sig != SIGINT && sig != SIGTERM ){  /* add crashlog [13 Apr 2015] */
2075      FILE *dfp ; char *home , fname[1024] ;
2076      fprintf(stderr,"** If you report this crash to the AFNI message\n"
2077                     "** board, please copy the error messages EXACTLY.\n") ;
2078      home = getenv("HOME") ;
2079      if( home != NULL ){
2080        strcpy(fname,home) ; strcat(fname,"/.afni.crashlog") ;
2081      } else {
2082        strcpy(fname,".afni.crashlog") ;
2083      }
2084      dfp = fopen( fname , "a" ) ;
2085      if( dfp != NULL ){
2086        fprintf(dfp,"\n*********-----------------------------------------------*********") ;
2087        fprintf(dfp,"\nFatal Signal %d (%s) received\n",sig,sname); fflush(stderr);
2088 #ifdef USE_TRACING
2089        DBG_tfp = dfp ; DBG_traceback() ; DBG_tfp = stderr ;
2090 #endif
2091        fprintf(dfp,"** AFNI version = " AVERZHN "  Compile date = " __DATE__ "\n" );
2092 #ifdef SHSTRING
2093        fprintf(dfp,"** [[Precompiled binary " SHSTRING ": " __DATE__ "]]\n") ;
2094 #endif
2095        fprintf(dfp,"** AFNI Program Hideous Death **\n") ;
2096        fclose(dfp) ;
2097        fprintf(stderr,"** Crash log appended to file %s\n",fname) ;
2098      }
2099    }
2100    exit(1) ;
2101 }
2102 
2103 /*----------------------------------------------------------------------------*/
2104 /* The functions below implement the delayed quit feature:
2105      - when signal SIGQUIT==3 is sent to AFNI, AFNI_sigfunc_quit() gets called
2106      - which uses alarm() to send signal SIGALRM after 5 sec
2107      - which invokes AFNI_sigfunc_alrm() == this function
2108      - which says something cute and dies
2109    This catenation of events is for Jerzy 'the Mad Pole' Bodurka.
2110 ------------------------------------------------------------------------------*/
2111 
2112 extern int selenium_close(void) ;
2113 
2114 /* the goodbye messages are now stored in afni_startup_tips.h */
2115 
AFNI_sigfunc_alrm(int sig)2116 void AFNI_sigfunc_alrm(int sig)
2117 {
2118    int nn ;
2119 
2120 #ifdef NGBY
2121    /* this first part is to print out 1 or more goodbye messages */
2122 
2123    srand48((long)time(NULL)+(long)getpid()) ; /* reset random number generator */
2124    nn = (lrand48()>>3) % NGBY ;               /* first message index */
2125 
2126    if( !AFNI_yesenv("AFNI_NEVER_SAY_GOODBYE") ){
2127      if( nn < NGBY ){
2128 #undef  NDUN
2129 #define NDUN (sizeof(dun)/sizeof(char *))
2130        static char *dun[] = { "is done" , "wraps up"   , "concludes" ,
2131                               "is over" , "terminates" , "finishes"   } ;
2132        if( sig >= 0 ){
2133          printf("\n** AFNI %s: %s!  [%d/%d]\n\n" ,
2134                 dun[lrand48()%NDUN],gby[nn],nn+1,NGBY) ;
2135        } else {
2136          int kk ;
2137          int dn=AFNI_find_relprime_random(NGBY), ktop=(-sig < NGBY) ? -sig : NGBY ;
2138          for( kk=0 ; kk < ktop ; kk++ ){
2139            printf( "%s!\n\n" , gby[nn] + ((gby[nn][0]=='\n') ? 1 : 0) ) ;
2140            nn = (nn+dn)%NGBY ;
2141          }
2142        }
2143      }
2144      /** MCHECK ; **/
2145    }
2146 #endif /* NGBY */
2147 
2148    /* meltdown controller on exit? (disabled) */
2149 #if 0
2150    if( sig <= 0 && !NO_frivolities ){
2151      Three_D_View *im3d = AFNI_find_open_controller() ;
2152      char *eee = getenv("AFNI_SPLASH_MELT") ;
2153      if( eee == NULL ) eee = "?" ; else eee[0] = toupper(eee[0]) ;
2154      if( im3d   != NULL  && MCW_widget_visible(im3d->vwid->top_shell) &&
2155          eee[0] != 'N'   && (eee[0] == 'Y' || lrand48()%19==0)           ){
2156        int jj ;
2157        XMapRaised( XtDisplay(im3d->vwid->top_shell) ,
2158                    XtWindow(im3d->vwid->top_shell)   ) ; /* raise controller */
2159        AFNI_sleep(111);
2160        MCW_melt_widget( im3d->vwid->top_form ) ;
2161      }
2162      sig = 0 ;
2163    }
2164 #endif
2165 
2166    selenium_close(); /* close any selenium opened browser windows if open */
2167    exit(sig);
2168 }
2169 
2170 /*-------------------------------------------------------------------------*/
2171 /* Called for sig=3 (cf. main() function) */
2172 
AFNI_sigfunc_quit(int sig)2173 void AFNI_sigfunc_quit(int sig)
2174 {
2175   unsigned int nsec = (unsigned int)AFNI_numenv("AFNI_SIGQUIT_DELAY") ;
2176   if( nsec == 0 || nsec > 30 ) nsec = 5 ;
2177   fprintf(stderr,
2178           "\n** AFNI received QUIT signal ==> exit in %u seconds! **\n",nsec) ;
2179   signal(SIGALRM,AFNI_sigfunc_alrm) ;  /* call the actual death dealer */
2180   (void)alarm(nsec) ;                  /* after a quick cigarette break */
2181   return ;
2182 }
2183 
2184 /*-------------------------------------------------------------------------*/
2185 /*! Check if a particular option is present; 1=yes, 0=no.  [15 Jan 2004]
2186 ---------------------------------------------------------------------------*/
2187 
check_string(char * targ,int ns,char * ss[])2188 static int check_string( char *targ , int ns , char *ss[] )
2189 {
2190    int ii , lt ;
2191    if( targ == NULL || *targ == '\0' || ns <= 0 || ss == NULL ) return 0 ;
2192    lt = strlen(targ) ;
2193    for( ii=0 ; ii < ns ; ii++ )
2194      if( ss[ii] != NULL && strncmp(ss[ii],targ,lt) == 0 ) return 1 ;
2195    return 0 ;
2196 }
2197 
2198 /*----------------------------------------------------------------------------*/
2199 /*-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+*/
2200 /*=============================================================================
2201   The new (and improved) AFNI main program.
2202     02 Aug 1999: Have moved much of the startup into a work process.
2203 ==============================================================================*/
2204 /*-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+*/
2205 /*----------------------------------------------------------------------------*/
2206 
main(int argc,char * argv[])2207 int main( int argc , char *argv[] )
2208 {
2209    int ii ; int dienow=0 ;
2210 
2211    /*--- help the pitiful user? ---*/
2212 
2213    if( argc > 1 && strcasecmp(argv[1],"-help")    == 0 ) AFNI_syntax() ;
2214 
2215    if( argc > 1 && strncasecmp(argv[1],"-goodbye",6) == 0 ){
2216      printf("\n") ;
2217      if( argc > 2 && strcasecmp(argv[2],"ALL") == 0 ){ /* 30 Jan 2018 */
2218        AFNI_sigfunc_alrm(-666666) ;
2219      } else {
2220        ii = (argc > 2 ) ? abs((int)rintf((strtod(argv[2],NULL)))) : 0 ;
2221        AFNI_sigfunc_alrm(-ii) ;
2222      }
2223    }
2224 
2225    if( argc > 1 && strncasecmp(argv[1],"-startup",6) == 0 ){ /* 05 Jan 2018 */
2226      int jj ;
2227      if( argc > 2 && strcasecmp(argv[2],"ALL") == 0 ){
2228        for( jj=0 ; jj < NTIP ; jj ++ ) AFNI_print_startup_tip(jj) ;
2229      } else {
2230        srand48((long)time(NULL)+(long)getpid()) ;
2231        ii = (argc > 2 ) ? abs((int)rintf((strtod(argv[2],NULL)))) : 1 ;
2232        for( jj=0 ; jj < ii ; jj++ ) AFNI_print_startup_tip(-1) ;
2233      }
2234      exit(0) ;
2235    }
2236 
2237    if( argc > 1 && strcasecmp(argv[1],"-julian") == 0 ){ /* 30 Oct 2018 */
2238      printf("%s days since noon 01 Jan 4713 BC\n",julian_date_string()) ;
2239      exit(0) ;
2240    }
2241 
2242    /** Check for -version [15 Aug 2003] **/
2243 
2244 
2245    if( check_string("-ver"    ,argc,argv) || check_string("--ver"    ,argc,argv) ||
2246        check_string("-version",argc,argv) || check_string("--version",argc,argv)   ){
2247       show_AFNI_version() ;
2248       dienow++ ;
2249    }
2250 
2251    if( check_string("-vnum" , argc, argv) ) {
2252       show_AFNI_vnum();
2253       dienow++ ;
2254    }
2255 
2256    if( check_string("-package" , argc, argv) ) {
2257       show_AFNI_package();
2258       dienow++ ;
2259    }
2260 
2261    if( check_string("-tips" , argc, argv) ) {
2262       show_AFNI_readme_gui();
2263       dienow++ ;
2264    }
2265 
2266    if( check_string("-env" , argc, argv) ) {
2267       show_AFNI_readme_env();
2268       dienow++ ;
2269    }
2270 
2271    /** MOTD output **/
2272 
2273    if( check_string("--motd",argc,argv) || check_string("-motd",argc,argv) ){   /* 29 Nov 2005 */
2274      AFNI_display_motd(NULL) ; dienow++ ;
2275    }
2276 
2277    /** just print the SHOWOFF string [26 Oct 2004] **/
2278 
2279    if( check_string("-show",argc,argv) || check_string("--show",argc,argv) ){
2280 #ifdef SHSTRING
2281       printf( SHSTRING "\n" ) ;
2282 #else
2283       printf("Unknown\n") ;
2284 #endif
2285       dienow++ ;
2286    }
2287 
2288    /** debug stuff **/
2289 
2290 #ifdef USING_MCW_MALLOC
2291    if( !check_string("-nomall",argc,argv) && !check_string("-rt",argc,argv) )
2292      enable_mcw_malloc() ;
2293 #endif
2294 
2295 #ifdef USE_TRACING
2296    if( check_string("-trace",argc,argv) ) DBG_trace = 1 ;
2297    if( check_string("-TRACE",argc,argv) ) DBG_trace = 2 ;
2298 #endif
2299 
2300    if( check_string("-motif_ver",argc,argv) ) {
2301      show_motif_version_string() ;
2302      dienow++ ;
2303    }
2304 
2305    /* check the processed environment, the afni way: machdep/prefilter
2306     * and the common main() way: prefilter/machdep  19 Sep 2013 [rickr] */
2307 
2308    if( check_string("-get_processed_env_afni",argc,argv) ) {
2309      AFNI_prefilter_args( &argc , &argv );
2310      machdep();
2311      system("env | grep -e '^AFNI' -e '^NIFTI' | sort");
2312      dienow++ ;
2313    }
2314    else if( check_string("-get_processed_env",argc,argv) ) {
2315      machdep();
2316      AFNI_prefilter_args( &argc , &argv );
2317      system("env | grep -e '^AFNI' -e '^NIFTI' | sort");
2318      dienow++ ;
2319    }
2320 
2321    if( check_string("-global_opts",argc,argv) ) {      /* list global */
2322      fputs(SUMA_Offset_SLines(get_help_help(),3),
2323                                     stdout);   /* opts used by all AFNI progs */
2324      fputs(get_gopt_help(), stdout);
2325      dienow++ ;
2326    }
2327 
2328    if( check_string("-papers",argc,argv) ){  /* list AFNI papers */
2329      AFNI_list_papers(NULL) ; dienow++ ;
2330    }
2331 
2332    /* getting text output, should be early      23 Oct 2015 [rickr] */
2333 
2334    if( check_string("-available_npb_quiet", argc, argv) ) {
2335       fprintf(stdout,"%d\n",get_available_npb());
2336       dienow++ ;
2337    } else if( check_string("-available_npb", argc, argv) ) {
2338       fprintf(stdout,
2339               "\nFirst available npb: %d\n",get_available_npb());
2340       dienow++ ;
2341    }
2342 
2343    /* -list_ports list and quit */
2344    if( check_string("-list_ports", argc, argv) ) {
2345       show_ports_list(); dienow++ ;
2346    }
2347 
2348    /*** if ordered, die right now ***/
2349 
2350    if( dienow ) exit(0) ;  /* farewell, cruel world */
2351 
2352    /***----- otherwise, perhaps become all detached from reality -----***/
2353 
2354    /* no version until after quick exit checks      23 Oct 2015 [rickr] */
2355    if( ! check_string("-q",argc,argv) ) show_AFNI_version() ;
2356 
2357    /* Since AFNI_DETACH is applied before machdep() or other my_getenv
2358       calls, -D cannot be used to apply this env var, so add an option.
2359                                                      7 Mar 2014 [rickr] */
2360 
2361    if( ! check_string("-no_detach",argc,argv) ) {
2362       PUTENV("AFNI_DETACH","YES") ;            /* Apr 2013 */
2363       { char *eee = getenv("AFNI_DETACH") ;    /* 31 May 2011 */
2364         if( YESSISH(eee) ){
2365           ii = (int)fork();
2366           if( ii != 0 ){         /* parent process dies now */
2367             AFNI_sleep(2345) ;   /* msec */
2368             fprintf(stderr,"++ AFNI is detached from terminal.\n") ;
2369             _exit(0) ;
2370           }
2371         }
2372       }
2373    }
2374 
2375    /*------------- Initialize some more stuff -------------*/
2376 
2377    machdep() ;
2378 /*** INFO_message("before prefilter: argc=%d argv=%p",argc,(void *)argv) ; ***/
2379    AFNI_prefilter_args( &argc , &argv ) ;  /* 11 Dec 2007 */
2380 /*** INFO_message("after prefilter: argc=%d argv=%p",argc,(void *)argv) ; ***/
2381 
2382    THD_load_datablock_verbose(1) ; /* 21 Aug 2002 */
2383 
2384    signal(SIGINT ,AFNI_sigfunc) ;  /* may be superseded by mainENTRY below */
2385    signal(SIGBUS ,AFNI_sigfunc) ;
2386    signal(SIGSEGV,AFNI_sigfunc) ;
2387    signal(SIGTERM,AFNI_sigfunc) ;
2388 
2389    first_plugin_check = -1 ;  /* 16 Nov 2016 */
2390 
2391 #if 0
2392 #ifdef USE_TRACING
2393    if( ALLOW_realtime ) DBG_trace = 0 ; /* 26 Jan 2001 */
2394 #endif
2395 #endif
2396 
2397    /** 25 Oct 2001: check for -q (quiet) option right away **/
2398 
2399    GLOBAL_argopt.quiet = AFNI_yesenv("AFNI_QUIET") ;
2400    if( AFNI_VERBOSE && check_string("-q",argc,argv) ) GLOBAL_argopt.quiet = 1;
2401 
2402    /** 12 Dec 2002: scan for "-rt" now,
2403                     to see if we want to start the version check **/
2404 
2405    GLOBAL_argopt.allow_rt = check_string("-rt",argc,argv) ;
2406 
2407    if( !GLOBAL_argopt.quiet && !ALLOW_realtime )
2408 #if 1 /* 30 Dec 2015 */
2409      AFNI_start_version_check() ;               /* 21 Nov 2002 */
2410 #else
2411      AFNI_start_compile_date_check() ;          /* 17 Jun 2014 */
2412 #endif
2413 
2414 #ifdef DARWIN
2415    if( 0 && !THD_is_directory("/sw/bin") && !AFNI_noenv("AFNI_IMSAVE_WARNINGS") )
2416      WARNING_message("On Mac OS X, it helps if you install the fink software:\n"
2417                      "            cf. http://fink.sourceforge.net/\n"
2418                      "            and then do\n"
2419                      "            fink install netpbm\n" ) ;
2420 #endif
2421 
2422    /** Start the debug traceback stuff (also resets signal handler) **/
2423 
2424    mainENTRY("AFNI:main") ; /* 26 Jan 2001: replace ENTRY w/ mainENTRY */
2425 
2426    signal(SIGQUIT,AFNI_sigfunc_quit) ;  /* For Jerzy -- 09 Jan 2008 */
2427 
2428    /** set the function to call if run out of memory when creating datasets **/
2429 
2430    THD_set_freeup( AFNI_purge_unused_dsets ) ;  /* 18 Oct 2001 */
2431 
2432 #if 0
2433    if( argc > 1 ) AFNI_logger("afni",argc,argv) ; /* 14 Aug 2001 */
2434 #endif
2435 
2436 #if 0                                          /* now in machdep() */
2437    srand48((long)time(NULL)+(long)getpid()) ;  /* initialize random number generator */
2438 #endif
2439 
2440    REPORT_PROGRESS( "\n" ) ;
2441 
2442    /*-- Be friendly or trivial --*/
2443 
2444    if( check_string("-trivia",argc,argv) ){   /* 27 Nov 2007 */
2445      char **triv ; int ntriv,tt ;
2446      ntriv = AFNI_get_todays_trivia( &triv ) ;
2447      for( tt=0 ; tt < ntriv ; tt++ ){
2448        REPORT_PROGRESS(triv[tt]) ; REPORT_PROGRESS("\n") ;
2449      }
2450      REPORT_PROGRESS( "\n" ) ; exit(0) ;
2451    }
2452 
2453    { char *sf = AFNI_get_friend() ;
2454      REPORT_PROGRESS( sf ) ;
2455      REPORT_PROGRESS( "\n\n" ) ;
2456      if( check_string("-friend",argc,argv) ) exit(0) ;
2457    }
2458 
2459    /*----- tell the user who we are -----*/
2460 
2461 /*   REPORT_PROGRESS( ANNOUNCEMENT ) ;*/
2462 
2463    /*-------------------------------------------------------------*/
2464    /*------------ initialize the controllers list ----------------*/
2465 
2466    for( ii=0 ; ii < MAX_CONTROLLERS ; ii++ )
2467      GLOBAL_library.controllers[ii] = NULL ;
2468    GLOBAL_library.dc = NULL ;
2469 
2470    GLOBAL_library.controller_lock = 0 ; ENABLE_LOCK ;
2471    GLOBAL_library.time_lock = 0 ;                      /* 03 Nov 1998 */
2472    GLOBAL_library.ijk_lock  = 0 ;                      /* 11 Sep 2000 */
2473    GLOBAL_library.zoompan_lock = 0 ;                   /* 10 Dec 2019 */
2474    SET_FIM_bkthr(10.0) ;                               /* 02 Jun 1999 */
2475 
2476    GLOBAL_library.hints_on  = 0 ;                      /* 07 Aug 1999 */
2477 
2478 #ifdef ALLOW_PLUGINS
2479    GLOBAL_library.plugins   = NULL ;
2480 #endif
2481 
2482    GLOBAL_library.session   = NULL ;                   /* 20 Dec 2001 */
2483    GLOBAL_library.warptable = NULL ;                   /* 28 Aug 2002 */
2484 
2485    GLOBAL_library.realtime_status   = NULL ;           /* 01 Jun 2009 */
2486    GLOBAL_library.realtime_callback = NULL ;
2487 
2488    /*--------------------------------------------------------------------*/
2489    /*--- initialize X, toplevel window, defaults, and display context ---*/
2490 
2491    REPORT_PROGRESS("Initializing: X11");
2492 
2493    /*--- check for font size environment control [06 Nov 2018] ---*/
2494 
2495    { char *ep = getenv("AFNI_FONTSIZE") ;
2496      if( ep != NULL ){
2497             if( strcasecmp(ep,"minus") == 0 ) XXX_MINUS_FONTS ;
2498        else if( strcasecmp(ep,"plus")  == 0 ) XXX_PLUS_FONTS ;
2499        else if( strcasecmp(ep,"big")   == 0 ) XXX_BIG_FONTS ;
2500        else if( strcasecmp(ep,"norm")  == 0 ) XXX_NORM_FONTS ;
2501      }
2502    }
2503 
2504    /*--- look for -XXX options before starting X11 [24 Mar 2016] ---*/
2505 
2506    process_XXX_options( argc , argv ) ;  /* will set new_FALLback */
2507 
2508    if( new_FALLback != NULL ){  /* if found any -XXX options, merge them */
2509      int qq,pp ;
2510      if( ! AFNI_yesenv("AFNI_DONT_USE_XRDB") )
2511        xrdb_pg = THD_find_executable("xrdb") ;
2512 
2513      /* can't find xrdb executable ==> merge FALLback strings */
2514 
2515      if( xrdb_pg == NULL ){
2516        for( qq=0 ; FALLback[qq] != NULL ; qq++ ){
2517          for( pp=0 ; new_FALLback[pp] != NULL ; pp++ ){
2518            if( equiv_FALLback( new_FALLback[pp] , FALLback[qq] ) ) break ;
2519          }
2520          if( new_FALLback[pp] == NULL )
2521            ADDTO_FALLback_one(FALLback[qq]) ;
2522        }
2523        for( qq=0 ; new_FALLback[qq] != NULL ; qq++ )
2524          ININFO_message("new_FALLback[%d] = \"%s\"",qq,new_FALLback[qq]) ;
2525 
2526      } else {  /* use xrdb to merge X11 resources */
2527 
2528 #define XXXSIZ 4096
2529        char *xpg , *xout=NULL ; FILE *fp ;
2530        xpg = malloc(strlen(xrdb_pg)+64) ;
2531 
2532        /* get the current resources settings */
2533 
2534        sprintf(xpg,"%s -query",xrdb_pg) ;
2535        fp = popen(xpg,"r") ;
2536        if( fp != NULL ){
2537          xout = (char *)malloc(sizeof(char)*XXXSIZ) ; xout[0] = '\0' ;
2538          while( fgets(xout+strlen(xout),XXXSIZ-2,fp) != NULL ){
2539            xout = (char *)realloc(xout,sizeof(char)*(strlen(xout)+XXXSIZ)) ;
2540          }
2541          (void)pclose(fp) ;
2542          if( *xout != '\0' ) xrdb_old = xout ;
2543        }
2544 
2545        /* set the new ones */
2546 
2547        sprintf(xpg,"%s -override -",xrdb_pg) ;
2548        fp = popen( xpg , "w" ) ;
2549        if( fp != NULL ){
2550          for( pp=0 ; new_FALLback[pp] != NULL ; pp++ )
2551            fprintf(fp,"%s\n",new_FALLback[pp]) ;
2552          (void)pclose(fp) ;
2553        }
2554 
2555        /* don't need new_FALLback any more */
2556 
2557        for( pp=0 ; new_FALLback[pp] != NULL ; pp++ ) free(new_FALLback[pp]) ;
2558        free(new_FALLback) ; new_FALLback = NULL ; free(xpg) ;
2559 #undef XXXSIZ
2560      }
2561    }
2562 
2563    /*--- now ready to start X11 for true --*/
2564 
2565 #ifdef DARWIN
2566    { char *eee = getenv("DYLD_LIBRARY_PATH") ;
2567      char *fff = getenv("AFNI_SKIP_DYLD_WARNING") ;
2568      if( (fff == NULL || toupper(*fff) != 'Y') &&
2569          (eee == NULL || strstr(eee,"flat_namespace") == NULL) ){
2570        int vmajor=0, vminor=0 , vmicro=0 ;
2571 #if 0
2572        eee = get_XQuartz_version() ;  /* Check XQuartz version [27 Jan 2017] */
2573        if( eee != NULL && isdigit(*eee) ){
2574          sscanf(eee,"%d.%d.%d",&vmajor,&vminor,&vmicro) ;
2575          /* INFO_message("XQuartz version: %d %d %d",vmajor,vminor,vmicro) ; */
2576        }
2577 #endif
2578        if( vmajor == 0 || vminor == 0 || vmajor > 2                   ||
2579            (vmajor == 2 && vminor >  7)                               ||
2580            (vmajor == 2 && vminor == 7 && (vmicro > 9 || vmicro == 0))  ){
2581          fprintf(stderr,
2582           "\n"
2583           "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"
2584           "++ If you are using XQuartz 2.7.10 (or later), and AFNI crashes when\n"
2585           " + opening windows, or you cannot type text into AFNI popup windows,\n"
2586           " + you might need to set an environment variable to solve this problem:\n"
2587           " +   setenv DYLD_LIBRARY_PATH /opt/X11/lib/flat_namespace    # tcsh\n"
2588           " +   export DYLD_LIBRARY_PATH=/opt/X11/lib/flat_namespace    # bash\n"
2589           " + This command is best put in your startup ~/.cshrc file, so that\n"
2590           " + it will be invoked for every (t)csh shell you open (mutatis mutandis\n"
2591           " + for the bash shell, of course).\n"
2592           " +\n"
2593           " + If things are OK and you want to avoid having this warning message\n"
2594           " + pollute your terminal, use this:\n"
2595           " +   setenv AFNI_SKIP_DYLD_WARNING YES                       # tcsh\n"
2596           " +   export AFNI_SKIP_DYLD_WARNING=YES                       # bash\n\n"
2597           "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"
2598          ) ;
2599        }
2600      }
2601    }
2602 #endif
2603 
2604    memset(&MAIN_app, 0, sizeof(MAIN_app)) ;  /* 11 Feb 2009 [lesstif patrol] */
2605    MAIN_shell = XtVaAppInitialize( &MAIN_app , "AFNI" , NULL , 0 ,
2606                                    &argc , argv ,
2607                                    (new_FALLback!=NULL)?new_FALLback:FALLback ,
2608                                    NULL ) ;
2609 
2610    if( MAIN_shell == NULL ) ERROR_exit("Cannot initialize X11") ;
2611 
2612 #if 1
2613    { Display *dpy = XtDisplay(MAIN_shell) ;
2614      char msg[1024] , *xsv ; int xvr ;
2615      xsv = XServerVendor(dpy) ; xvr = XVendorRelease(dpy) ;
2616      if( xsv != NULL ){ sprintf(msg,"[%s v %d]",xsv,xvr); REPORT_PROGRESS(msg); }
2617    }
2618 #endif
2619 
2620    { char *eee = getenv("DISPLAY") ;  /* Sound stuff [20 Aug 2018] */
2621      GLOBAL_library.local_display = (eee == NULL) || (strstr(eee,":0") != NULL ) ;
2622      GLOBAL_library.have_sox      = ( THD_find_executable("sox") != NULL ) ;
2623      GLOBAL_library.sound_player  = get_sound_player() ;
2624      sound_set_note_ADSR(1) ;
2625      sound_set_note_waveform(SOUND_WAVEFORM_TRIANGLE) ;
2626    }
2627 
2628    /* if we used xrdb to set X11 resources, re-set them back to their old
2629       state so that other AFNIs don't use these new settings by default   */
2630 
2631    if( xrdb_old != NULL && !XXX_set_default ){  /* 24 Mar 2016 */
2632      FILE *fp ; char *xpg ;
2633      xpg = malloc(strlen(xrdb_pg)+64) ;
2634      sprintf(xpg,"%s -override -",xrdb_pg) ;
2635      fp = popen( xpg , "w" ) ;
2636      if( fp != NULL ){
2637        fprintf(fp,"%s",xrdb_old) ;
2638        (void)pclose(fp) ;
2639      }
2640      free(xpg) ;
2641    }
2642 
2643 #ifdef USE_TRACING
2644    if( DBG_trace == 2 ){                           /* 01 Dec 1999 */
2645      XSynchronize(XtDisplay(MAIN_shell),TRUE) ;
2646      STATUS("XSynchronize is enabled") ;
2647    }
2648 #endif
2649    XtVaSetValues( MAIN_shell, XmNkeyboardFocusPolicy,XmEXPLICIT , NULL ) ;
2650 
2651    MAIN_argc = argc ; MAIN_argv = argv ;  /* what's left after XtVaAppInit */
2652 
2653    REPORT_PROGRESS(".") ;
2654 
2655    /** set default values of some environment variables [22 Jun 2004] **/
2656 
2657    PUTENV("AFNI_LEFT_IS_LEFT","YES") ;     /* 20 Jun 2019 */
2658    PUTENV("AFNI_CROSSHAIR_LINES","YES") ;
2659    PUTENV("AFNI_ALWAYS_LOCK","YES") ;
2660    PUTENV("AFNI_IMAGE_SAVESQUARE","YES") ;
2661    PUTENV("AFNI_DECONFLICT","OVERWRITE") ; /* 24 Sep 2007 */
2662    PUTENV("AFNI_X11_REDECORATE","NO") ;
2663    PUTENV("AFNI_RESCAN_AT_SWITCH","YES") ; /* 16 Nov 2007 */
2664    PUTENV("AFNI_VIDEO_DELAY","33") ;       /* 20 Aug 2009 */
2665    PUTENV("AFNI_GRAPH_FADE","YES") ;          /* Apr 2013 */
2666    PUTENV("AFNI_MPEG_DATASETS","NO") ;        /* Feb 2015 */
2667    PUTENV("AFNI_FLASH_VIEWSWITCH","NO") ;  /* 14 Apr 2016 */
2668    PUTENV("AFNI_DATASET_BROWSE","YES") ;   /* 07 Nov 2018 */
2669    PUTENV("AFNI_VERSION_CHECK","NO") ;     /* 04 Jan 2019 */
2670    PUTENV("AFNI_PBAR_FULLRANGE","YES") ;   /* 03 Jun 2014 */
2671 
2672    PUTENV("AFNI_COLORSCALE_DEFAULT","Reds_and_Blues_Inv") ; /* 24 May 2019 */
2673    PUTENV("AFNI_THRESH_TOP_EXPON"  , "5" ) ;
2674    PUTENV("AFNI_THRESH_INIT_EXPON" , "1" ) ;
2675    PUTENV("AFNI_AUTORANGE_PERC"    , "0" ) ;
2676 
2677    PUTENV("AFNI_FIX_SCALE_SIZE"  , "YES" ) ;  /* (from Lucca) */
2678    PUTENV("AFNI_OPACITY_LOCK"    , "YES" ) ;
2679 
2680    PUTENV("AFNI_INSTACORR_JUMP", "YES" ) ;  /* 24 Sep 2021 */
2681 
2682 #if 0
2683    PUTENV("AFNI_IMAGE_LABEL_MODE","1") ;
2684    PUTENV("AFNI_IMAGE_LABEL_SIZE","2") ;
2685    PUTENV("AFNI_IMAGE_LABEL_SETBACK","01") ;
2686    PUTENV("AFNI_IMAGE_LABEL_COLOR","yellow") ;
2687 #endif
2688 
2689    /*-- 04 Jun 1999: modify order of loading arguments and defaults --*/
2690 
2691    if( ! GLOBAL_argopt.skip_afnirc ){
2692      char *sysenv = getenv("AFNI_SYSTEM_AFNIRC") ;        /* 12 Apr 2000 */
2693      if( sysenv != NULL ) AFNI_process_environ(sysenv) ;  /* 12 Apr 2000 */
2694 
2695      AFNI_process_environ(NULL) ;                         /* 07 Jun 1999 */
2696    } else {
2697      AFNI_mark_environ_done() ;                           /* 16 Apr 2000 */
2698    }
2699 
2700    /*-- 30 Apr 2015: some messages about obsolete environment variables --*/
2701 
2702    if( getenv("AFNI_SLAVE_THRTIME") != NULL ){
2703      WARNING_message("environment variable AFNI_SLAVE_THRTIME is no longer used!") ;
2704      WARNING_message(" -- see AFNI_SLAVE_FUNCTIME and AFNI_SLAVE_THROLAY instead") ;
2705    }
2706 
2707    if( getenv("AFNI_SLAVE_BUCKETS_TOO") != NULL ){  /* 30 May 2015 */
2708      WARNING_message("environment variable AFNI_SLAVE_BUCKETS_TOO is no longer used!") ;
2709      WARNING_message(" -- see AFNI_SLAVE_FUNCTIME and AFNI_SLAVE_THROLAY instead") ;
2710    }
2711 
2712    /* set top exponent for threshold slider [04 Nov 2010] -- for Allison */
2713 
2714    { static float tval[9] = { 1.0f , 10.0f , 100.0f , 1000.0f , 10000.0f ,
2715                               100000.0f , 1000000.0f , 10000000.0f , 100000000.0f } ;
2716      ii = AFNI_numenv("AFNI_THRESH_TOP_EXPON") ;
2717           if( ii < 4 ) ii = 4 ;
2718      else if( ii > 6 ) ii = 6 ;
2719      THR_top_expon = ii ;
2720      THR_factor    = 1.0f / tval[ii] ;
2721      THR_top_value = tval[ii] - 1.0f ;
2722    }
2723 
2724    PBAR_FULLRANGE = AFNI_yesenv("AFNI_PBAR_FULLRANGE") ; /* 03 Jun 2014 */
2725 
2726    AUTORANGE_PERC = (float)AFNI_numenv("AFNI_AUTORANGE_PERC") ; /* 24 May 2019 */
2727 
2728    AFNI_load_defaults( MAIN_shell ) ;
2729 
2730    if( ! GLOBAL_argopt.skip_afnirc ){          /* this line added 14 Jul 1998 */
2731       char *home = getenv("HOME") ; char fname[1024] ;
2732       char *sysenv = getenv("AFNI_SYSTEM_AFNIRC") ;       /* 12 Apr 2000 */
2733 
2734       GPT = NULL ;  /* 19 Dec 1997 */
2735 
2736       if( sysenv != NULL )                                 /* 12 Apr 2000 */
2737         AFNI_process_setup( sysenv , SETUP_INIT_MODE , NULL ) ;
2738 
2739       if( home != NULL ){ strcpy(fname,home) ; strcat(fname,"/.afnirc") ; }
2740       else              { strcpy(fname,".afnirc") ; }
2741       AFNI_process_setup( fname , SETUP_INIT_MODE , NULL ) ;
2742 
2743 #ifdef AFNI_DEBUG
2744       home = dump_PBAR_palette_table(0) ;
2745       if( home != NULL ){ puts(home) ; free(home) ; }
2746 #endif
2747 
2748    } else {                                    /* these lines also 14 Jul 1998 */
2749       REPORT_PROGRESS( "[skip .afnirc]" ) ;
2750    }
2751 
2752    /*--- finally, read the command line for other options ---*/
2753 
2754    AFNI_parse_args( argc , argv ) ;  /* after Xt init above, only my args left */
2755 
2756    /*-- disable X11 and Xt error messages and crashes (we hope) --*/
2757 
2758    (void) XSetErrorHandler( AFNI_xerrhandler ) ;      /* 26 Jun 2003 */
2759    (void) XtAppSetErrorHandler(MAIN_app,AFNI_handler) ;
2760 
2761    if( GLOBAL_argopt.xtwarns != 1 )
2762      (void) XtAppSetWarningHandler(MAIN_app,AFNI_handler) ;  /* turn off */
2763 
2764    /* FIM background threshold */
2765 
2766    { char *lenv = getenv("AFNI_FIM_BKTHR") ;          /* 04 Jun 1999 */
2767      if( lenv != NULL ){
2768        float bk = strtod(lenv,NULL) ;
2769        if( bk >= 0.0 && bk < 100.0 ) SET_FIM_bkthr(bk) ;
2770      }
2771    }
2772 
2773    /* locking? */
2774 
2775    if( AFNI_yesenv("AFNI_ALWAYS_LOCK") ){
2776      for( ii=0 ; ii < MAX_CONTROLLERS ; ii++ )
2777        GLOBAL_library.controller_lock |= (1<<ii) ;
2778    }
2779 
2780    if( AFNI_yesenv("AFNI_TIME_LOCK") ){
2781        GLOBAL_library.time_lock = 1 ;
2782    }
2783 
2784    if( AFNI_yesenv("AFNI_ZOOM_LOCK") ){    /* 10 Dec 2019 */
2785        GLOBAL_library.zoompan_lock = 1 ;
2786    }
2787 
2788    /* default opacity [06 Jun 2019] */
2789 
2790    { int opval = (int)AFNI_numenv("AFNI_DEFAULT_OPACITY") ;
2791      if( opval > 0 && opval <= 9 )
2792        GLOBAL_library.opacity_setting = opval ;
2793      else
2794        GLOBAL_library.opacity_setting = 6 ;
2795    }
2796 
2797    /*-- now create first display context: MAIN_dc --*/
2798 
2799    GLOBAL_library.dc = MAIN_dc =
2800         MCW_new_DC( MAIN_shell , GLOBAL_argopt.ncolor ,
2801                     INIT_ncolovr , INIT_colovr , INIT_labovr ,
2802                     GLOBAL_argopt.gamma , GLOBAL_argopt.install_cmap ) ;
2803 
2804    memplot_to_X11_set_DC(MAIN_dc) ; /* 30 Apr 2012 */
2805 
2806    /* for the old PseudoColor world (does anyone live there anymore?) */
2807 
2808    if( MAIN_dc->depth < 9 && MAIN_dc->visual_class != TrueColor && GLOBAL_argopt.unique_dcs ){
2809      GLOBAL_argopt.unique_dcs = False ;
2810      REPORT_PROGRESS("[-unique off]") ;
2811    }
2812 
2813    /*------------------------------------*/
2814    /*------- take it away, Goldie -------*/
2815    /*------------------------------------*/
2816 
2817 #if 0
2818    (void) XtAppAddWorkProc( MAIN_app, MAIN_workprocess, NULL ) ;
2819 #else
2820    PLUTO_register_workproc( MAIN_workprocess , NULL ) ; /* rest of startup */
2821 #endif
2822 
2823    MCW_disable_help() ;
2824 
2825 STATUS("start XtAppMainLoop") ;
2826 
2827    XtAppMainLoop(MAIN_app) ;  /* never returns */
2828    AFexit(0) ;                /* should never be reached */
2829 }
2830 
2831 
2832 #undef HUBERIZE
2833 #ifdef HUBERIZE
2834 #include "huber.c"  /* this is useless drivel */
2835 #endif
2836 
2837 /*---------------------------------------------------------------------------------
2838    Xt work process to do most of the initialization stuff.
2839    (So we can so a splash screen to pacify and amuse the user.)
2840 -----------------------------------------------------------------------------------*/
2841 
2842 #define REFRESH XmUpdateDisplay(MAIN_im3d->vwid->top_shell)
2843 
MAIN_workprocess(XtPointer fred)2844 static RwcBoolean MAIN_workprocess( XtPointer fred )
2845 {
2846    static int MAIN_calls = 0 ;  /* controls what happens */
2847    static int nosplash = 0 ;
2848    static double eltime=0.0 , max_splash=3.0 ;
2849    int ii ;
2850 
2851 ENTRY("MAIN_workprocess") ;  /* 23 Jan 2001: added ENTRY/RETURN to this routine */
2852 
2853 if(PRINT_TRACING){ char str[256]; sprintf(str,"MAIN_calls=%d",MAIN_calls); STATUS(str); }
2854 
2855    switch( MAIN_calls ){
2856 
2857       /*============================================================================
2858          This code is executed at the end (when MAIN_calls gets too big).
2859         ============================================================================*/
2860 
2861       default:{
2862 STATUS("default call") ;
2863 
2864          RETURN(True) ;  /* I hope this keeps you happy, Ziad :-) */
2865       }
2866       break ;
2867 
2868       /*============================================================================
2869          Stuff to popup the AFNI splash screen (see afni_splash.[ch]).
2870         ============================================================================*/
2871 
2872       case 0:{
2873 STATUS("call 0") ;
2874 
2875 #ifdef NO_FRIVOLITIES
2876         nosplash = 1 ;
2877 #else
2878         nosplash = AFNI_yesenv("AFNI_NOSPLASH") ;
2879 #endif
2880         if( !nosplash ){
2881           char *hh ;
2882           AFNI_splashup() ; eltime = COX_clock_time() ;
2883           hh = getenv("AFNI_SPLASHTIME") ;
2884           if( hh != NULL ){
2885             max_splash = strtod(hh,NULL) ;
2886             if( max_splash > 9.0 ) max_splash = 9.0 ;
2887           }
2888         }
2889       }
2890       break ;
2891 
2892       /*** For the Mac users! ***/
2893 
2894       case 1:
2895 #if 0
2896         AFNI_speak("[[volm 0.65; inpt PHON; rate -10; pbas +5]]1AEf=nnnIY",0) ;  /* fall thru */
2897 #endif
2898 
2899 #if 1
2900         if( check_string("-com",MAIN_argc,MAIN_argv) == 0 &&
2901             GLOBAL_library.local_display                  &&
2902             GLOBAL_library.have_sox                       &&
2903             AFNI_yesenv("AFNI_STARTUP_SOUND")               ) AFNI_startup_sound(1) ;
2904 #endif
2905 
2906       case 2:
2907       case 3:
2908       case 4:
2909       case 5:
2910       case 6:
2911       case 7:
2912       case 8:
2913       case 9:
2914       case 10:
2915 STATUS("sleep call") ;
2916         if( !nosplash) AFNI_sleep(1) ; /* burn some time to let splash windo popup */
2917       break ;
2918 
2919       /*============================================================================
2920          Next, create the first AFNI controller window.
2921         ============================================================================*/
2922 
2923       case 11:{
2924 
2925         int do_images ;                           /* 19 Oct 1999 */
2926 
2927 STATUS("call 11") ;
2928 
2929         REPORT_PROGRESS(". Widgets") ;
2930 
2931         MCW_enable_help() ;
2932 
2933         do_images = GLOBAL_argopt.read_images ;
2934 
2935         MAIN_im3d = new_AFNI_controller( MAIN_shell , MAIN_dc ,
2936                                          do_images ? AFNI_IMAGES_VIEW
2937                                                    : AFNI_3DDATA_VIEW ) ;
2938 
2939         GLOBAL_library.controllers[0] = MAIN_im3d ;
2940 
2941         REPORT_PROGRESS(".") ;
2942 
2943         /* Always turn off Drag-n-Drop (courtesy the Motif FAQ) */
2944 
2945         XtVaSetValues( XmGetXmDisplay(XtDisplay(MAIN_im3d->vwid->top_shell)) ,
2946                           XmNdragInitiatorProtocolStyle , XmDRAG_NONE ,
2947                           XmNdragReceiverProtocolStyle  , XmDRAG_NONE ,
2948                        NULL ) ;
2949       }
2950       break ;
2951 
2952       /*============================================================================
2953          Next, read the input files -- may take a while --
2954          which is one reason why we need a splash screen (the other is it's fun)
2955         ============================================================================*/
2956 
2957       case 12:{
2958 
2959 STATUS("call 12") ;
2960 
2961         REPORT_PROGRESS(". Input files:") ;
2962 
2963         AFNI_read_inputs( MAIN_argc , MAIN_argv ) ;
2964 
2965         if( GLOBAL_library.have_dummy_dataset   &&
2966             MAIN_im3d->type == AFNI_3DDATA_VIEW    ){
2967 
2968           XtSetSensitive( MAIN_im3d->vwid->prog->clone_pb , False ) ;
2969           MAIN_im3d->dummied = 1 ;  /* 27 Jan 2004 */
2970           MCW_set_widget_bg( MAIN_im3d->vwid->view->sess_lab ,
2971                              MCW_hotcolor(MAIN_im3d->vwid->view->sess_lab) , 0 ) ;
2972         }
2973       }
2974       break ;
2975 
2976       /*============================================================================
2977          Next, setup the plugins, and things like that ...
2978         ============================================================================*/
2979 
2980       case 13:{
2981 
2982 STATUS("call 13") ;
2983 
2984         /* registered transformation functions, etc. */
2985 
2986         GLOBAL_library.registered_0D.num = 0 ;               /* initialize registry */
2987         GLOBAL_library.registered_1D.num = 0 ;               /* initialize registry */
2988         GLOBAL_library.registered_2D.num = 0 ;               /* initialize registry */
2989 
2990         GLOBAL_library.registered_fim.num = 0 ;              /* 30 Jan 2000 */
2991 
2992         GLOBAL_library.registered_slice_proj.num = 0 ;       /* 31 Jan 2002 */
2993 
2994         /* these functions are now in afni_transforms.c [01 Feb 2002] */
2995 
2996         AFNI_register_0D_function( "Log10" , log10_func ) ;
2997         AFNI_register_0D_function( "SSqrt" , ssqrt_func ) ;
2998         AFNI_register_0D_function( "Abs"   , absval_func ) ; /* 20 Oct 2020 */
2999 
3000         AFNI_register_1D_function( "Median3"   , median3_func) ;
3001 #if 0
3002         AFNI_register_1D_function( "OSfilt3"   , osfilt3_func) ;
3003 #endif
3004         AFNI_register_1D_function( "AdptMean9" , adpt_wt_mn9 ) ;       /* 04 Sep 2009 */
3005         AFNI_register_1D_function( "AdptMean19", adpt_wt_mn19 );       /* 29 Sep 2016 */
3006 
3007         { int nad = (int)AFNI_numenv("AFNI_AdptMeanWidth1D") ;         /* 30 Sep 2016 */
3008           char lab[32] ;                                      /* user specified width */
3009           if( nad > 3 && nad != 9 && nad != 19 && nad < 100 ){
3010             if( nad%2 == 0 ){ nad++; INFO_message("increased AFNI_AdptMeanWidth1D to %d",nad); }
3011             sprintf(lab,"AdptMean%d",nad) ;
3012             AFNI_register_1D_function( lab , adpt_wt_mnXX ) ;
3013             adpt_wt_mnXX(nad,0.0,0.0,NULL) ;
3014           }
3015         }
3016 
3017         AFNI_register_1D_function( "Despike9"  , despike9_func);       /* 08 Oct 2010 */
3018         AFNI_register_1D_function( "Despike25" , DES_despike25);       /* 18 May 2018 */
3019         AFNI_register_1D_function( "HRF decon" , hrfdecon_func);       /* 29 Oct 2010 */
3020         AFNI_register_1D_function( "|FFT()|"   , absfft_func ) ;
3021 #if 0
3022         AFNI_register_1D_function( "ZeroToOne" , ztone_func  ) ;       /* 02 Sep 2009 */
3023         AFNI_register_1D_function( "Normlz_L1" , L1normalize_func  ) ; /* 03 Sep 2009 */
3024         AFNI_register_1D_function( "Normlz_L2" , L2normalize_func  ) ; /* 03 Sep 2009 */
3025 #endif
3026 
3027         F1D_null() ; /* should be last 1D func - 20 Oct 2020 */
3028 
3029         AFNI_register_2D_function( "Median9" , median9_box_func ) ;
3030         AFNI_register_2D_function( "Winsor9" , winsor9_box_func ) ;
3031         AFNI_register_2D_function( "OSfilt9" , osfilt9_box_func ) ;
3032 
3033         AFNI_register_2D_function( "Median21"  , median21_box_func );
3034         AFNI_register_2D_function( "Winsor21"  , winsor21_box_func );
3035         AFNI_register_2D_function( "AdptMean21", adapt_mean_21_box_func ); /* 04 Sep 2009 */
3036 
3037         AFNI_register_2D_function( "abs[FFT2D]" , fft2D_absfunc   );
3038         AFNI_register_2D_function( "arg[FFT2D]" , fft2D_phasefunc );
3039         AFNI_register_2D_function( "Sharpness"  , sharpness2D_func);   /* 28 Oct 2014 */
3040 
3041         F2D_null() ; /* should be last 2D func - 20 Oct 2020 */
3042 
3043         /* 01 Feb 2000: see afni_fimfunc.c */
3044 
3045         AFNI_register_fimfunc("Spearman CC",1,(generic_func *)spearman_fimfunc,NULL);
3046         AFNI_register_fimfunc("Quadrant CC",1,(generic_func *)quadrant_fimfunc,NULL);
3047 
3048         /* 31 Jan 2002 */
3049 
3050         AFNI_register_slice_proj( "Minimum" , min_proj   ) ;
3051         AFNI_register_slice_proj( "Maximum" , max_proj   ) ;
3052         AFNI_register_slice_proj( "Mean"    , mean_proj  ) ;
3053 
3054         AFNI_register_slice_proj( "Median"  , qmed_float   ) ; /* cs_qmed.c */
3055         AFNI_register_slice_proj( "OSfilt"  , osfilt_proj  ) ; /* 07 Dec 2007 */
3056         AFNI_register_slice_proj( "Extreme" , extreme_proj ) ; /* 02 Feb 2002 */
3057         AFNI_register_slice_proj( "MAD"     , mad_proj     ) ; /* 07 Dec 2007 */
3058 
3059         AFNI_register_slice_proj( "AdptMean", adaptive_weighted_mean ) ; /* 04 Sep 2009 */
3060 
3061 #ifdef HUBERIZE
3062         AFNI_register_1D_funcstr( "Huber Fit" , huber_func ) ;
3063 #endif
3064 
3065         /** find and load the plugins at last! **/
3066 
3067 #ifdef ALLOW_PLUGINS
3068         if( MAIN_im3d->type == AFNI_3DDATA_VIEW ){
3069           int nplug = 0 ;
3070           char str[1024] ;
3071 
3072           if( ! GLOBAL_argopt.noplugins ){
3073 STATUS("initialize plugins") ;
3074             GLOBAL_library.plugins = PLUG_get_many_plugins( MAIN_argv[0] ) ;
3075             AFNI_plugin_button( MAIN_im3d ) ;
3076           }
3077 
3078           if( GLOBAL_library.plugins != NULL ) nplug = GLOBAL_library.plugins->num ;
3079           sprintf(str,"\n Plugins       = %d libraries read",nplug) ;
3080           REPORT_PROGRESS(str) ;
3081           if( nplug == 0 && ! GLOBAL_argopt.noplugins )  /* 18 May 2005 */
3082             REPORT_PROGRESS(
3083                       "\n ** Your Unix path must include the AFNI binary directory"
3084                       "\n ** OR you must setenv AFNI_PLUGINPATH to that directory!");
3085 
3086           /** and plugouts! **/
3087 
3088           if( !GLOBAL_argopt.noplugouts ){  /* June 1997 */
3089             AFNI_init_plugouts() ;
3090             if( MAIN_im3d->vwid->dmode->misc_plugout_pb != NULL ) /* 07 Nov 2001 */
3091               XtSetSensitive(MAIN_im3d->vwid->dmode->misc_plugout_pb,False) ;
3092             REPORT_PROGRESS("\n Plugouts      = listening for connections") ;
3093           }
3094         }
3095 #endif
3096 
3097         TT_setup_popup_func( AFNI_popup_message ) ;  /* 26 May 2006 */
3098 
3099         /* 04/06/2020 discoraj */
3100         if( GLOBAL_argopt.all_dsets_startup ){
3101             ii = AFNI_find_session( "All_Datasets") ;
3102             if( ii >= 0 ) MAIN_im3d->vinfo->sess_num = ii ;
3103         }
3104       }
3105       break ;
3106 
3107       /*============================================================================
3108          Next, do the initial setup on entering the initial view.
3109         ============================================================================*/
3110 
3111       case 14:{
3112 
3113 STATUS("call 14") ;
3114 
3115         OPEN_CONTROLLER( MAIN_im3d ) ;
3116 
3117         if( GLOBAL_argopt.only_images ){   /* 24 Feb 2017 */
3118           AV_assign_ival( MAIN_im3d->vwid->imag->crosshair_av,0) ;
3119           MAIN_im3d->vinfo->crosshair_visible = False ;
3120 #if 0
3121           GLOBAL_argopt.left_is_left = 0 ;
3122           putenv("AFNI_LEFT_IS_LEFT=NO" ) ;
3123 #endif
3124         }
3125         if( AFNI_yesenv("AFNI_CROSSHAIRS_OFF") )
3126           MAIN_im3d->vinfo->crosshair_visible = False ;
3127 
3128         AFNI_initialize_controller( MAIN_im3d ) ;  /* decide what to see */
3129         AFNI_initialize_view( NULL, MAIN_im3d ) ;  /* set up to see it */
3130 
3131         /*--- Other small and quick startup stuff before AFNI can go ---*/
3132 
3133 STATUS("initialize help") ;
3134 
3135         MCW_help_CB( MAIN_im3d->vwid->top_shell,NULL,NULL ); /* initialize help */
3136 
3137 #if 0
3138         { char str[64] ;
3139           sprintf(str,"\n -orient       = %s", GLOBAL_library.cord.orcode ) ;
3140           REPORT_PROGRESS(str) ;
3141         }
3142 #endif
3143 
3144         /* initialize hints */
3145 
3146 STATUS("initialize hints") ;
3147 
3148         GLOBAL_library.hints_on = !AFNI_noenv("AFNI_HINTS") ;
3149         if( !GLOBAL_library.hints_on ) MCW_hint_toggle() ;
3150 
3151         if( MAIN_im3d->vwid->dmode->misc_hints_pb != NULL )
3152           MCW_set_bbox( MAIN_im3d->vwid->dmode->misc_hints_bbox ,
3153                         GLOBAL_library.hints_on ) ;
3154 
3155         /* Feb 1998: setup write compression from environment */
3156         /*           (read de-compression always works)       */
3157 
3158 STATUS("initialize compression mode (if any)") ;
3159 
3160         ii = THD_enviro_write_compression() ;
3161         if( ii >= 0 && ii <= COMPRESS_LASTCODE ){
3162           char str[256] ;
3163           sprintf(str,"\n write compress= %s", COMPRESS_enviro[ii]) ;
3164           REPORT_PROGRESS(str) ;
3165         }
3166 
3167         if( ALLOW_realtime > 0 )
3168           REPORT_PROGRESS("\nRT: AFNI realtime plugin is active; cf. README.realtime document") ;
3169 
3170         /* 23 Sep 2000: this function will be called 0.123 seconds
3171                         from now to initialize the window layouts, if any  */
3172 
3173         if( GLOBAL_argopt.layout_fname != NULL &&
3174             MAIN_im3d->type == AFNI_3DDATA_VIEW   ){
3175 
3176 STATUS("start user's layout timer") ;
3177 
3178           (void) XtAppAddTimeOut( MAIN_app , 123 ,
3179                                   AFNI_startup_layout_CB , GLOBAL_argopt.layout_fname ) ;
3180 
3181         } else if (MAIN_im3d->type == AFNI_3DDATA_VIEW){ /* ZSS Dec 02 2010. */
3182 
3183 STATUS("start default layout timer") ;
3184 
3185           (void) XtAppAddTimeOut( MAIN_app , 123 ,
3186                                   AFNI_startup_layout_CB ,
3187                                   "GIMME_SOMETHING" ) ;
3188         }
3189 
3190         /* 21 Jan 2003: this function will be called 0.246 seconds
3191                         from now to run the startup script commands, if any */
3192 
3193         if( GLOBAL_argopt.script_fname != NULL &&
3194             MAIN_im3d->type == AFNI_3DDATA_VIEW   ){
3195 
3196 STATUS("start script timeout") ;
3197 
3198           (void) XtAppAddTimeOut( MAIN_app , 246 ,
3199                                   AFNI_startup_script_CB , GLOBAL_argopt.script_fname ) ;
3200         }
3201 
3202         if( MAIN_im3d->vwid->func->do_setup ){
3203           int ii = (int)AFNI_numenv("AFNI_THRESH_INIT_EXPON") ;
3204           if( ii > 0 && ii < THR_top_expon ) AFNI_set_thresh_itop(MAIN_im3d,ii) ;
3205           MAIN_im3d->vwid->func->do_setup = 0 ;
3206         }
3207 
3208         /* this function will be called 1.666 seconds from now to finalize
3209            anything else that needs fixing up once AFNI is fully started   */
3210 
3211 STATUS("start startup timeout") ;
3212 
3213         PICTURE_ON(MAIN_im3d) ;
3214         (void) XtAppAddTimeOut( MAIN_app, 1666, AFNI_startup_timeout_CB, MAIN_im3d ) ;
3215 
3216         (void) TRUST_host(NULL) ; /* 21 Feb 2001: initialize trust mechanism */
3217 
3218         /* see if there is an initial FIM ideal timeseries */
3219 
3220         { char *eee = getenv( "AFNI_FIM_IDEAL" ) ;
3221           static MRI_IMAGE *tsim ;
3222           tsim = mri_read_1D( eee ) ;
3223           if( tsim != NULL ){
3224             float *far = MRI_FLOAT_PTR(tsim) ; int ii ; char *tname ;
3225             for( ii=0 ; ii < tsim->nvox ; ii++ )
3226                if( fabs(far[ii]) >= 33333.0 ) far[ii] = WAY_BIG ;
3227             tname = THD_trailname(eee,1) ;
3228             mri_add_name( tname , tsim ) ;
3229             AFNI_fimmer_setref( MAIN_im3d , tsim ) ;
3230           }
3231         }
3232 
3233         /* 05 Mar 2007: auto-threshold? */
3234 
3235         if( AFNI_yesenv("AFNI_THRESH_AUTO") ){
3236           float new_thresh = AFNI_get_autothresh(MAIN_im3d) ;
3237           if( new_thresh > 0.0f ) AFNI_set_threshold(MAIN_im3d,new_thresh) ;
3238         }
3239 
3240         PUTENV("AFNI_DECONFLICT","OVERWRITE") ; /* 24 Sep 2007 */
3241         putenv("AFNI_IS_RUNNING=YES") ;         /* 08 Jun 2007 */
3242 
3243         memplot_topshell_setsaver( ".jpg" , memplot_to_jpg ) ; /* 05 Dec 2007 */
3244         memplot_topshell_setsaver( ".png" , memplot_to_png ) ;
3245 
3246         REPORT_PROGRESS("\n") ;
3247 
3248         { long long lfs = AFNI_logfilesize(); /* 17 Oct 2007 */
3249           if( lfs > 10000000 ){
3250             char msg[1024] ;
3251             sprintf(msg,"\n++ WARNING: ~/.afni.log is now %s (%s) bytes long!"
3252                         "\n +          (Is that you, Kevin?)\n" ,
3253                     commaized_integer_string(lfs) ,
3254                     approximate_number_string((double)lfs) ) ;
3255             REPORT_PROGRESS(msg) ;
3256           }
3257         }
3258 
3259         if( AFNI_yesenv("AFNI_ENFORCE_ASPECT") ){ /* 10 May 2018 */
3260           REPORT_PROGRESS(
3261             "\n++ NOTICE: AFNI_ENFORCE_ASPECT no longer has any effect!\n") ;
3262         }
3263 
3264         /* X11_SET_NEW_PLOT ; */
3265 
3266 STATUS("exit call 14") ;
3267 
3268       }
3269       break ;  /* end of 14th entry case */
3270 
3271       /*============================================================================*/
3272 #if 0
3273       case 15:{  /* not used at present, but ready to be added when needed */
3274 STATUS("call 15") ;
3275       }
3276       break ;
3277 #endif
3278    }
3279 
3280    MAIN_calls++ ; RETURN(False) ;
3281 }
3282 
3283 /*-------------------------------------------------------------------------*/
3284 
random_goodbye(void)3285 static char * random_goodbye(void)
3286 {
3287    static char *bye[] = { "[[volm 0.64]] Farewell",
3288                           "[[volm 0.64]] Goodbye" ,
3289                           "[[volm 0.64]] Until next time" } ;
3290    int nn = sizeof(bye)/sizeof(char *) ;
3291    return bye[ lrand48() % nn ] ;
3292 }
3293 
3294 /*-------------------------------------------------------------------------
3295    Callback for the quit button.  If called with the widget == NULL,
3296    resets the button to the lowercase state.
3297 ---------------------------------------------------------------------------*/
3298 
AFNI_quit_CB(Widget wcall,XtPointer cd,XtPointer cbs)3299 void AFNI_quit_CB( Widget wcall , XtPointer cd , XtPointer cbs )
3300 {
3301    Three_D_View *im3d = (Three_D_View *)cd ;
3302    XmPushButtonCallbackStruct *pbcbs = (XmPushButtonCallbackStruct *)cbs ;
3303 
3304 ENTRY("AFNI_quit_CB") ;
3305 
3306    if( cd == NULL ) AFexit(0) ;  /* 27 Jul 2015 */
3307 
3308    if( ! IM3D_OPEN(im3d) ) EXRETURN ;
3309 
3310    /* NULL widget --> reset button to lowercase */
3311 
3312    if( wcall == NULL ){
3313       if( im3d->vwid->prog->quit_first == False ){
3314          MCW_set_widget_label( im3d->vwid->prog->quit_pb , "done " ) ;
3315          im3d->vwid->prog->quit_first = True ;
3316          if( im3d->vwid->picture != NULL && !GLOBAL_argopt.keep_logo )
3317            PICTURE_OFF( im3d ) ;
3318       }
3319       EXRETURN ;
3320    }
3321 
3322    /* Press of button with Shift or Control key pressed --> Death Now */
3323 
3324    if( pbcbs != NULL                       &&
3325        pbcbs->event != NULL                &&
3326        pbcbs->event->type == ButtonRelease &&
3327        ((XButtonEvent *)(pbcbs->event))->state &  /* note single & here! */
3328        (ShiftMask|ControlMask|Button2Mask|Button3Mask) ){
3329 
3330       XtCloseDisplay( XtDisplay(im3d->vwid->top_shell) ) ;
3331 #if 0
3332       AFNI_speak(random_goodbye(),0) ;
3333 #endif
3334       AFexit(0) ;
3335    }
3336 
3337    /* First press --> just change button label */
3338 
3339    if( wcall == im3d->vwid->prog->quit_pb && im3d->vwid->prog->quit_first ){
3340       MCW_set_widget_label( im3d->vwid->prog->quit_pb , "DONE " ) ;
3341       im3d->vwid->prog->quit_first = False ;
3342       if( im3d->vwid->picture != NULL ) PICTURE_ON( im3d ) ;
3343 
3344       /* if not re-pressed in 5 seconds, will reset to lowercase */
3345 
3346       (void) XtAppAddTimeOut(
3347                XtWidgetToApplicationContext(im3d->vwid->prog->quit_pb) ,
3348                5000 , AFNI_quit_timeout_CB , im3d ) ;
3349 
3350       EXRETURN ;
3351    }
3352 
3353    /* close window callback OR button already uppercase --> close window */
3354 
3355    /* if no controller windows will be left, exit the program */
3356 
3357    if( AFNI_count_controllers() <= 1 ){
3358       XtCloseDisplay( XtDisplay(im3d->vwid->top_shell) ) ;
3359       AFNI_speak(random_goodbye(),0) ;
3360       STATUS("calling exit(0) -- farewell cruel world!") ;
3361       AFexit(0) ;
3362 
3363    } else {  /* otherwise, patch up the other windows and continue */
3364 
3365       CLOSE_CONTROLLER(im3d) ;     /* close window */
3366       AFNI_controller_clonify() ;  /* let other controllers know */
3367    }
3368    EXRETURN ;
3369 }
3370 
3371 /*----------------------------------------------------------------------
3372   Timeout routine to change 'DONE' button label back to 'done'
3373   after 5 seconds have passed.
3374 ------------------------------------------------------------------------*/
3375 
AFNI_quit_timeout_CB(XtPointer client_data,XtIntervalId * id)3376 void AFNI_quit_timeout_CB( XtPointer client_data , XtIntervalId *id )
3377 {
3378    Three_D_View *im3d = (Three_D_View *)client_data ;
3379 ENTRY("AFNI_quit_timeout_CB") ;
3380    RESET_AFNI_QUIT(im3d) ;
3381    EXRETURN ;
3382 }
3383 
3384 /*----------------------------------------------------------------------*/
3385 
AFNI_vcheck_flasher(Three_D_View * im3d)3386 void AFNI_vcheck_flasher( Three_D_View *im3d )
3387 {
3388    int pp ;
3389    if( im3d == NULL || vers_pixmap == XmUNSPECIFIED_PIXMAP ) return ;
3390 
3391    for( pp=0 ; pp < 19 ; pp++ ){
3392      PICTURE_SET(im3d,vers_pixmap) ;
3393        XmUpdateDisplay(im3d->vwid->top_shell); AFNI_sleep(166);
3394      PICTURE_OFF(im3d) ;
3395        XmUpdateDisplay(im3d->vwid->top_shell); AFNI_sleep(166);
3396    }
3397    logo_pixmap = vers_pixmap ;     /* replace logo with version warning */
3398    return ;
3399 }
3400 
3401 /*----------------------------------------------------------------------*/
3402 /* the tips are stored in afni_startup_tips.h */
3403 
AFNI_print_startup_tip(int qq)3404 void AFNI_print_startup_tip(int qq) /* 03 Jan 2018 */
3405 {
3406    int nn = (lrand48()>>3) % NTIP ;
3407 
3408    if( qq >= 0 && qq < NTIP ) nn = qq ;
3409 
3410    if( tip[nn] != NULL )
3411      fprintf( stdout , "\n\n"
3412               "------------------------- AFNI Startup Tip (%d/%d)----------------------------\n"
3413               "%s\n"
3414               "-------------------------------------------------------------------------------\n" ,
3415               nn+1 , NTIP , tip[nn] ) ;
3416    return ;
3417 }
3418 
3419 /*-------------------------------------------------------------------------
3420   This function is called periodically to do unimportant stuff [Oct 2019]
3421 ---------------------------------------------------------------------------*/
3422 
AFNI_periodic_timeout_CB(XtPointer client_data,XtIntervalId * id)3423 void AFNI_periodic_timeout_CB( XtPointer client_data , XtIntervalId *id )
3424 {
3425    int qq ; Three_D_View *qq3d ;
3426 
3427 ENTRY("AFNI_periodic_timeout_CB") ;
3428 
3429    /* turn off the 'working' pictures and reset to normal cursor */
3430 
3431    SHOW_AFNI_READY ;
3432 
3433    /* restart timer */
3434 
3435    (void) XtAppAddTimeOut( MAIN_app, 9999, AFNI_periodic_timeout_CB, MAIN_im3d ) ;
3436    EXRETURN ;
3437 }
3438 
3439 /*----------------------------------------------------------------------
3440   This function is called about 1 s after AFNI startup is completed.
3441   It's original purpose was to make sure that the help window was
3442   popped down - the help initializing routine does this, too, but
3443   it didn't work properly on the old Tektronix X-terminal at MCW.
3444   Thus, the timeout - waiting a little made things work OK.
3445 ------------------------------------------------------------------------*/
3446 
AFNI_startup_timeout_CB(XtPointer client_data,XtIntervalId * id)3447 void AFNI_startup_timeout_CB( XtPointer client_data , XtIntervalId *id )
3448 {
3449    Three_D_View *im3d = (Three_D_View *)client_data ;
3450    int vv ;
3451 
3452 ENTRY("AFNI_startup_timeout_CB") ;
3453 
3454    /*--- make sure help window is popped down ---*/
3455 
3456 #if 0
3457    MCW_help_CB( MAIN_im3d->vwid->top_shell,NULL,NULL ); /* initialize help */
3458 #endif
3459 
3460    MCW_help_CB(NULL,NULL,NULL) ;
3461 
3462    /*--- test geometry of main window [08 Aug 2016]
3463          if it is negative territory, move it back to positive land;
3464          this is to (hopefull) fix a peculiarity in XQuartz on El Capitan ---*/
3465 
3466    { Position xroot,yroot ;
3467      WAIT_for_window( MAIN_im3d->vwid->top_shell ) ;
3468      XtTranslateCoords( MAIN_im3d->vwid->top_shell , 0,0, &xroot , &yroot ) ;
3469 #if 0
3470 INFO_message("AFNI controller xroot=%d yroot=%d",(int)xroot,(int)yroot) ;
3471 #endif
3472      if( xroot < 0 || yroot < 0 ){
3473        INFO_message("AFNI was off screen at x=%d y=%d -- repositioning" ,
3474                    (int)xroot , (int)yroot ) ;
3475        XtVaSetValues( MAIN_im3d->vwid->top_shell, XmNx,20, XmNy,20, NULL ) ;
3476        REFRESH ;
3477      }
3478    }
3479 
3480    /*--- tell user if any mixed-type datasets transpired [06 Sep 2006] ---*/
3481 
3482    AFNI_inconstancy_check( im3d , NULL ) ;
3483 
3484    /*--- NIML listening on [moved here 17 Mar 2002] ---*/
3485 
3486    if( MAIN_im3d->type == AFNI_3DDATA_VIEW && GLOBAL_argopt.yes_niml ){
3487      AFNI_init_niml() ;
3488      if( MAIN_im3d->vwid->dmode->misc_niml_pb != NULL )
3489        XtSetSensitive(MAIN_im3d->vwid->dmode->misc_niml_pb,False) ;
3490    } else if( 0 && get_user_np() > 0 ){  /* 10 Dec 2002 -- ZSS June 2011 */
3491       /* No need to warn anymore, -np can be set by environment
3492         variables too. */
3493       fprintf(stderr,
3494          "** WARNING: -np was given, but NIML is turned off.\n") ;
3495    }
3496 
3497    if( AFNI_have_niml() && AFNI_have_plugouts() )  /* 02 Feb 2007 */
3498      XtSetSensitive(MAIN_im3d->vwid->view->nimlpo_pb,False) ;
3499 
3500    if( !AFNI_noenv("AFNI_STARTUP_WARNINGS") ){  /* 22 Jul 2003 */
3501 
3502 #ifdef LESSTIF_VERSION /* 13 Jan 2003: If LessTif was used for this AFNI */
3503     #ifndef USING_LESSTIF   /* Lesstif is good for you!
3504                                Keep the warning if the proper
3505                                -DUSING_LESSTIF was not used
3506                                when compiling  */
3507     (void) MCW_popup_message( MAIN_im3d->vwid->picture ,
3508                                  " \n"
3509                                  "*** WARNING:                ***\n"
3510                                  "*** This  copy of AFNI  was ***\n"
3511                                  "*** built using the LessTif ***\n"
3512                                  "*** library, but without the***\n"
3513                                  "*** -DUSING_LESSTIF flag at ***\n"
3514                                  "*** compile time.           ***\n"
3515                                  "*** You will find problems; ***\n"
3516                                  "*** AFNI works with either  ***\n"
3517                                  "*** Motif or OpenMotif, or  ***\n"
3518                                  "*** Lesstif with the proper ***\n"
3519                                  "*** compiler flag.          ***\n" ,
3520                               MCW_USER_KILL | MCW_TIMER_KILL ) ;
3521     #endif
3522 #endif
3523 
3524 #ifdef BAD_BUTTON3_POPUPS /* 21 Jul 2003: If this is a stupid system */
3525 
3526     (void) MCW_popup_message( MAIN_im3d->vwid->imag->topper,
3527                               " \n"
3528                               "*** WARNING:                  ***\n"
3529                               "*** This computer system has  ***\n"
3530                               "*** a bug with Button-3 popup ***\n"
3531                               "*** menus -- to use a button  ***\n"
3532                               "*** on such a menu, you have  ***\n"
3533                               "*** to keep Button-3 pressed  ***\n"
3534                               "*** down and then click the   ***\n"
3535                               "*** menu button with Button-1 ***\n"
3536                               "*** at the same time.         ***\n" ,
3537                               MCW_USER_KILL | MCW_TIMER_KILL ) ;
3538 #endif
3539    }
3540 
3541    if( recursed_ondot ) /* 18 Feb 2007 */
3542     (void) MCW_popup_message( MAIN_im3d->vwid->picture ,
3543                               " \n"
3544                               "++ NOTICE:                              ++\n"
3545                               "++ No data was found in './' directory, ++\n"
3546                               "++ so its subdirectories were searched  ++\n"
3547                               "++ for dataset files.                   ++\n " ,
3548                               MCW_USER_KILL | MCW_TIMER_KILL ) ;
3549    else if( !ALLOW_realtime                    &&
3550             GLOBAL_library.have_dummy_dataset  &&
3551             MAIN_im3d->type == AFNI_3DDATA_VIEW   ){
3552     int horz = MAIN_im3d->vwid->view->session_horz ; /* 29 Apr 2010 */
3553     char hstr[1024] ;
3554     sprintf( hstr ,
3555              "***** NOTICE *** UWAGA *** AVVISO *** WARNUNG *** RABHADH *****\n"
3556              "                                                               \n"
3557              "++ No valid datasets were found.  A dummy dataset has been   ++\n"
3558              "++ created for your viewing pleasure :-)  To read in a real  ++\n"
3559              "%s"
3560              "\n"
3561              "** Or, quit AFNI and restart it with the name of a dataset   **\n"
3562              "** directory on the command line, as in                      **\n"
3563              "\n"
3564              "     afni name_of_data_directory                               \n"
3565              "                                                               \n"
3566              "++ For general AFNI program help, see the Web page           ++\n"
3567              "\n"
3568              "   https://afni.nimh.nih.gov/pub/dist/doc/program_help/index.html   \n"
3569              "%s"
3570              "\n"
3571              "++ [To close this message window, left-click inside of it.]  ++\n"
3572             ,
3573       (horz)
3574            ? "++ dataset directory, use the 'Read' button near 'DataDir'.  ++\n"
3575            : "++ dataset directory, use the 'Read New Directory' button,   ++\n"
3576              "++ located below the 'Data Directory' label.                 ++\n" ,
3577       (GLOBAL_browser == NULL)
3578            ? " "
3579            : "\n"
3580              "++ which you can open by right-clicking on the logo space to ++\n"
3581              "++ the right of the 'done' button, and from the resulting    ++\n"
3582              "++ popup menu, choose the 'Web Browser: Help' item.          ++\n"
3583            ) ;
3584      (void)MCW_popup_message( MAIN_im3d->vwid->prog->quit_pb,hstr,MCW_USER_KILL ) ;
3585      MCW_flash_widget_list( 9 , MAIN_im3d->vwid->view->sess_lab ,
3586                                 MAIN_im3d->vwid->view->choose_sess_pb ,
3587                                 MAIN_im3d->vwid->view->read_sess_pb ,
3588                             NULL ) ;                           /* 12 Feb 2010 */
3589    }
3590 
3591    /*--- 05 May 2009: make sure the Cluster widgets show up properly ---*/
3592 
3593    AFNI_vedit_CB( im3d->vwid->func->options_vedit_av , im3d ) ;
3594 
3595    /* 21 Nov 2002: check the AFNI version */
3596 
3597 /* changed if 0 to if 1 to revert to version_check()   30 Dec 2015 */
3598 #if 1
3599    /* do nothing if AFNI_start_version_check() says inactive */
3600    vv = AFNI_version_check() ;
3601 
3602    if( vv && vers_pixmap != XmUNSPECIFIED_PIXMAP )     /* 08 Aug 2005 */
3603      AFNI_vcheck_flasher(im3d) ;
3604 
3605 #else
3606 
3607    vv = AFNI_compile_date_check() ;  /* 17 Jun 2014 */
3608    if( vv >= 93 ){
3609      /* fixed %31 to /31   28 Dec 2015 [rickr] */
3610      WARNING_message(
3611        "Your copy of AFNI is over %d months old -- please update it (if practicable)." ,
3612        vv / 31 ) ;
3613      if( im3d->vwid->tips_pb != NULL ){
3614        char msg[1024] ;
3615        sprintf( msg, " \n"
3616                      " Your copy of AFNI is over %d months old.\n"
3617                      "   Please update it (if practicable).\n "  , vv / 31 ) ;
3618        (void) MCW_popup_message( im3d->vwid->tips_pb , msg ,
3619                                  MCW_USER_KILL | MCW_TIMER_KILL ) ;
3620      }
3621    } else if( vv < 0 ){
3622      INFO_message("You are %d days AHEAD of the official AFNI compile date -- impressive!",-vv) ;
3623    }
3624 #endif
3625 
3626    /*--- finish up getting AFNI ready to be presented to the world ---*/
3627 
3628    if( im3d->vwid->tips_pb != NULL && lrand48()%2==0 )
3629      MCW_flash_widget(1,im3d->vwid->tips_pb) ;
3630 
3631    SHOW_AFNI_READY ;
3632    RESET_AFNI_QUIT(im3d) ;
3633    PICTURE_OFF(im3d) ;
3634 
3635    if( im3d->vwid->tips_pb != NULL && lrand48()%2==0 )
3636      MCW_flash_widget(1,im3d->vwid->tips_pb) ;
3637 
3638    /*--- 29 Jul 2005: run any driver commands from the command line ---*/
3639 
3640    for( vv=0 ; vv < COM_num ; vv++ ){
3641      AFNI_driver(COM_com[vv]) ; free(COM_com[vv]) ;
3642    }
3643 
3644    /*--- 29 Nov 2005: Message Of The Day -- did it change? ---*/
3645 
3646    if( GLOBAL_motd != NULL && !AFNI_noenv("AFNI_MOTD_CHECK") )
3647      AFNI_display_motd( im3d->vwid->imag->topper ) ;
3648 
3649    /*--- 09 Nov 2005: start checking periodically for updated datasets ---*/
3650 
3651    if( AFNI_yesenv("AFNI_AUTO_RESCAN") )
3652     (void) XtAppAddTimeOut( MAIN_app,29999, AFNI_rescan_timeout_CB,&MAIN_app );
3653 
3654    AFNI_coord_filer_setup(im3d) ; /* 07 May 2010 */
3655 
3656    /*--- 12 May 2010: As the last printout, say when this version was created ---*/
3657 
3658    fprintf(stderr,"\n++ NOTE: This version of AFNI was built " __DATE__ " ++\n" ) ;
3659 
3660    if( MAIN_im3d->type == AFNI_3DDATA_VIEW &&
3661       !AFNI_yesenv("AFNI_ENABLE_MARKERS")    )
3662      fprintf(stderr,"++ NOTE: 'Define Markers' is hidden: right-click 'DataDir' to see it\n") ;
3663 
3664    if( MAIN_im3d->type == AFNI_3DDATA_VIEW && first_plugin_check < 0 && !GLOBAL_argopt.noplugins )
3665      fprintf(stderr,"++ NOTE: Use '-seehidden' option to see which plugins are hidden\n") ;
3666 
3667 #if 0
3668    /**--- Apr 2013: delete this message in a few months ---**/
3669 
3670    if( __DATE__[10] == '3' && (__DATE__[0] == 'A' || __DATE__[0] == 'M') )
3671      fprintf(stderr,
3672        "++ NOTE: Graph viewer threshold 'fading' is now on by default.  To turn it off,\n"
3673        "         press the 'F' key in a graph viewer window, or set environment variable\n"
3674        "         AFNI_GRAPH_FADE to NO.  -- [Apr 2013]\n"
3675        "++ NOTE: The AFNI GUI now detaches itself from the terminal at startup, so that\n"
3676        "         it is no longer necessary or useful to start the program with the '&'\n"
3677        "         key at the end of the command line.  To disable this feature, set\n"
3678        "         environment variable AFNI_DETACH to NO.  To kill all running copies\n"
3679        "         of AFNI, you could use the Unix command 'killall afni'. -- [Apr 2013]\n"
3680      ) ;
3681 #endif
3682 
3683    if( AFNI_check_environ_done() == 0 )
3684      fprintf(stderr,
3685        "++ NOTE: you may want to consider creating a '.afnirc' file in your home\n"
3686        "         directory, to control AFNI's setup.  For more details, see\n"
3687        "   https://afni.nimh.nih.gov/pub/dist/doc/program_help/README.environment.html\n") ;
3688 
3689 
3690    /*--- splash window down -- moved here 29 May 2013 ---*/
3691 
3692 #ifndef NO_FRIVOLITIES
3693    if( lrand48()%17 == 3 )
3694      INFO_message("Want your picture in the AFNI splash screen? Email us a square JPEG!") ;
3695 #endif
3696 
3697    AFNI_splashdown(); STATUS("splashed down");
3698 
3699    /* Startup tip message [03 Jan 2018] */
3700 
3701    if( !ALLOW_realtime                        &&
3702        !AFNI_yesenv("AFNI_NEVER_SAY_GOODBYE") &&
3703         MAIN_im3d->type == AFNI_3DDATA_VIEW     ) AFNI_print_startup_tip(-1) ;
3704 
3705    /* this is for me, myself, and I only! */
3706 
3707    { char *eee = getenv("USER") ;
3708      set_program_name("afni") ;
3709 #ifdef USE_TRACING
3710      if( eee != NULL && strcmp(eee,"rwcox") == 0 ) atexit(clock_time_atexit) ;
3711 #endif
3712    }
3713 
3714    /* Start timer to repeatedly fix threshold scale sizes [05 Jun 2019] */
3715 
3716    if( ! AFNI_yesenv("AFNI_DONT_FIX_SCALE_SIZE") )
3717      AFNI_fix_scale_size_timer_CB(NULL,NULL) ;
3718 
3719    /*--- and AWAY WE GO (how sweet it is!) ---*/
3720 
3721    MPROBE ;                       /* check mcw_malloc() for integrity */
3722 
3723    /*--- Start period timeout [17 Oct 2019] ---*/
3724 
3725    (void) XtAppAddTimeOut( MAIN_app, 9999, AFNI_periodic_timeout_CB, MAIN_im3d ) ;
3726    EXRETURN ;
3727 }
3728 
3729 /*----------------------------------------------------------------------
3730    Return the underlay or overlay brick and the sub-brick index that
3731    the user had selected in the 'Underlay' and 'Overlay' menus.
3732 
3733    So whether or not the user has bkgd:ULay or bkgd:OLay is irrelevant
3734    to what gets returned.
3735 
3736    The returned structure is brr
3737    brr->dset will contain the dset selected as underlay if
3738       type  ==  isqCR_getulayim
3739               and         the dset selected as overlay if
3740       type  ==  isqCR_getolayim
3741 
3742    brr = br if type is set to anything other than isqCR_get[uo]ayim
3743 
3744    See also Get_UO_Dset
3745 ----------------------------------------------------------------------*/
3746 
Get_FD_Brick_As_Selected(FD_brick * br,int type,int * rival)3747 FD_brick *Get_FD_Brick_As_Selected(FD_brick *br, int type, int *rival)
3748 {
3749    Three_D_View *im3d = (Three_D_View *)br->parent ;
3750    FD_brick *brr=NULL ;
3751    int ival , banat , uu=im3d->vinfo->underlay_type ;
3752 
3753    banat = EQUIV_DSETS(br->dset,im3d->anat_now) ;
3754    switch( type ){
3755      case isqCR_getulayim: brr = (banat) ? br : br->brother ; break ;
3756      case isqCR_getolayim: brr = (banat) ? br->brother : br ; break ;
3757    }
3758    if( brr == NULL ) brr = br ; /* I wish it was 'brr' right now -- July 2014 */
3759 
3760    /*** decide which 3D brick to extract data from (ival) ***/
3761 
3762    if( EQUIV_DSETS(im3d->anat_now,im3d->fim_now) ){ /* RWCox [03 Jul 2014] */
3763      if( type == isqCR_getolayim )                /* datasets are the same */
3764        ival = im3d->vinfo->fim_index ;  /* so need to be careful with ival */
3765      else if( type == isqCR_getulayim || uu == UNDERLAY_ANAT )
3766        ival = im3d->vinfo->anat_index ;
3767      else
3768        ival = im3d->vinfo->fim_index ;
3769     } else {                                      /* the old (Ziad's) way */
3770      if( EQUIV_DSETS(brr->dset,im3d->anat_now) )      /* underlay dataset */
3771        ival = im3d->vinfo->anat_index ;
3772      else if( EQUIV_DSETS(brr->dset,im3d->fim_now) )   /* overlay dataset */
3773        ival = im3d->vinfo->fim_index ;
3774      else
3775        ival = 0 ;                                     /* shouldn't happen */
3776    }
3777 
3778    if( br->deltival != 0 && DSET_NVALS(brr->dset) > 1 ){  /* 23 Feb 2011 */
3779             /*    This is for allowing montage to cycle trough sub-bricks */
3780       ival += br->deltival ;
3781       ININFO_message("afni: deltival changes ival to %d",ival) ;
3782       if( ival < 0 || ival >= DSET_NVALS(brr->dset) ) RETURN( NULL ) ;
3783    }
3784 
3785         if( type == isqCR_getqimage       ) ival = -1; /* get empty image */
3786    else if( ival >= DSET_NVALS(brr->dset) ) ival = brr->dset->dblk->nvals-1;
3787 
3788    *rival = ival;
3789    /*
3790    fprintf(stderr,"Get_FD_Brick_As_Selected:\n"
3791                   "     br->dset %s, brr->dset %s\n"
3792                   "     anat_now %s, fim_now   %s\n"
3793                   "     banat = %d, ival = %d\n"
3794                   "     type %d (%s)\n",
3795                   DSET_PREFIX(br->dset), DSET_PREFIX(brr->dset),
3796                   DSET_PREFIX(im3d->anat_now), DSET_PREFIX(im3d->fim_now),
3797                   banat, ival,
3798                   type,
3799                   type == isqCR_getulayim ? "getULAY" :
3800                            type == isqCR_getolayim ? "getOLAY" : "Other");
3801    */
3802    return(brr);
3803 }
3804 
3805 /*
3806    Return the overlay or underaly dset currently selected and set
3807    the sub-brick number.
3808 
3809    Peculiar input:
3810    UOlay:  'O' --> Return the overlay
3811            'U'     Return the underlay
3812    AsSet: 1 --> Return the dataset that is set by the 'Underlay'
3813                       or 'Overlay' selectors.
3814                 0 --> Return the 'displayed' overlay or underlay dset.
3815                       This means, take into account the bkgd:ULay or bkgd:OLay
3816                       setting.
3817 */
Get_UO_Dset(FD_brick * br,char UOlay,byte AsSet,int * rival)3818 THD_3dim_dataset *Get_UO_Dset(FD_brick *br, char UOlay,
3819                               byte AsSet, int *rival)
3820 {
3821    Three_D_View *im3d = (Three_D_View *)br->parent ;
3822    FD_brick *brt=NULL;
3823    THD_3dim_dataset *dset=NULL;
3824 
3825    /* set up with basics */
3826    if (UOlay=='O') {
3827       dset = im3d->fim_now;
3828       *rival = im3d->vinfo->fim_index;
3829    } else {
3830       dset = im3d->anat_now;
3831       *rival = im3d->vinfo->anat_index;
3832    }
3833 
3834    /* now allow for things like deltival, and other stuff */
3835    if (AsSet) { /* as selected in 'Underlay' and 'Overlay' */
3836       if (!(brt = Get_FD_Brick_As_Selected(br,
3837                   UOlay=='O' ? isqCR_getolayim : isqCR_getulayim, rival))) {
3838          ERROR_message("Case 1: Failed to select brick, returning defaults");
3839          return(dset);
3840       }
3841    } else { /* as displayed, works OK, not well tested for rival below */
3842       if (EQUIV_DSETS(br->dset,im3d->anat_now)) {
3843          /* vanilla */
3844          if (!(brt = Get_FD_Brick_As_Selected(br,
3845                   UOlay=='O' ? isqCR_getolayim : isqCR_getulayim, rival))) {
3846             ERROR_message("Case 2: Failed to select brick, returning defaults");
3847             return(dset);
3848          }
3849       } else {
3850          /* Olay as Ulay: always return the overlay */
3851          if (!(brt = Get_FD_Brick_As_Selected(br, isqCR_getolayim, rival))) {
3852             ERROR_message("Case 3: Failed to select brick, returning defaults");
3853             return(dset);
3854          }
3855       }
3856    }
3857    if (brt) dset = brt->dset;
3858    return(dset);
3859 }
3860 
3861 /*!
3862    Return 0 if FD_brick is not in montage mode.
3863           1 if Axial montage
3864           2 if Sagittal montage
3865           4 if Coronal montage
3866 */
FD_brick_montized(FD_brick * br)3867 int FD_brick_montized(FD_brick *br )
3868 {
3869    Three_D_View *im3d = (Three_D_View *)br->parent ;
3870 
3871    if ( (br == im3d->b123_anat || br == im3d->b123_fim) &&
3872         (im3d->s123->mont_nx > 1|| im3d->s123->mont_ny > 1) ) {
3873       return(1); /* Axial brick and in montage */
3874    }
3875    if ( (br == im3d->b231_anat || br == im3d->b231_fim) &&
3876         (im3d->s231->mont_nx > 1|| im3d->s231->mont_ny > 1) ) {
3877       return(2);  /* Sagittal brick and in montage */
3878    }
3879    if ( (br == im3d->b312_anat || br == im3d->b312_fim) &&
3880         (im3d->s312->mont_nx > 1|| im3d->s312->mont_ny > 1) ) {
3881       return(4);  /* Coronal brick and in montage */
3882    }
3883    return(0);
3884 }
3885 
3886 /*----------------------------------------------------------------------
3887    Fill the various possible string values used in an imseq getlabel.
3888    Return value is 0 if things are good, 1 if things are bad.
3889 ------------------------------------------------------------------------*/
3890 
3891 #define LPART_SLICE_INDEX 0  /* %i% */
3892 #define LPART_SLICE_COORD 1  /* %s% */
3893 #define LPART_TIME_INDEX  2  /* %l% */
3894 #define LPART_TIME_COORD  3  /* %t% */
3895 #define NUM_LPART         4
3896 
AFNI_brick_to_label_parts(int n,FD_brick * br,char ** lpart)3897 int AFNI_brick_to_label_parts( int n , FD_brick *br , char **lpart )
3898 {
3899    Three_D_View *im3d = (Three_D_View *)br->parent ;
3900    char *lab , *dd , *eee=NULL , str[256] ;
3901    THD_ivec3 iv,ivp,ivm ;
3902    THD_fvec3 fv,fvp,fvm ;
3903    float dxyz , cc ;
3904    int ii, ival;
3905    double dval;
3906    THD_3dim_dataset *dset=br->dset ;
3907    int nnn ; char *fmt ;
3908 
3909    if( lpart == NULL || im3d->type != AFNI_3DDATA_VIEW ) return 1 ;
3910 
3911    /* format slice index */
3912 
3913    LOAD_IVEC3(iv,0,0,n) ;
3914    ivp = THD_fdind_to_3dind( br , iv ) ;
3915 
3916    if( n == 0 ) LOAD_IVEC3(iv,0,0,1) ;
3917    else         LOAD_IVEC3(iv,0,0,n-1) ;
3918    ivm = THD_fdind_to_3dind( br , iv ) ;
3919 
3920    nnn = MAX(br->n1,br->n2) ; nnn = MAX(nnn,br->n3) ;
3921    fmt =  (nnn < 10)    ? "#%1d"
3922         : (nnn < 100)   ? "#%02d"
3923         : (nnn < 1000)  ? "#%03d"
3924         : (nnn < 10000) ? "#%04d"
3925         : (nnn < 100000)? "#%05d"
3926         :                 "#%06d" ;
3927    if( ivm.ijk[0] != ivp.ijk[0] ){
3928      sprintf(str,fmt,ivp.ijk[0]) ;
3929    } else if( ivm.ijk[1] != ivp.ijk[1] ){
3930      sprintf(str,fmt,ivp.ijk[1]) ;
3931    } else if( ivm.ijk[2] != ivp.ijk[2] ){
3932      sprintf(str,fmt,ivp.ijk[2]) ;
3933    } else {
3934      sprintf(str,fmt,nnn) ; /* should be impossible */
3935    }
3936    strcpy( lpart[LPART_SLICE_INDEX] , str ) ;
3937 
3938    /* slice coordinate */
3939 
3940    fvp = THD_3dind_to_3dmm ( dset , ivp ) ;
3941    fvp = THD_3dmm_to_dicomm( dset , fvp ) ;
3942 
3943    fvm = THD_3dind_to_3dmm ( dset , ivm ) ;
3944    fvm = THD_3dmm_to_dicomm( dset , fvm ) ;
3945 
3946    dxyz = MIN(br->del1,br->del2) ;
3947    dxyz = MIN(dxyz    ,br->del3) ; dxyz *= 0.1f ;
3948    if( dxyz <= 1.e-4f ) dxyz = 1.e-4f ;
3949 
3950    if( fabs(fvm.xyz[0]-fvp.xyz[0]) > dxyz ){ /* +=R -=L */
3951      cc = fvp.xyz[0] ;
3952      dd = ( cc >= 0.0 ) ? "L" : "R" ;
3953    } else if( fabs(fvm.xyz[1]-fvp.xyz[1]) > dxyz ){ /* +=P -=A */
3954      cc = fvp.xyz[1] ;
3955      dd = ( cc >= 0.0 ) ? "P" : "A" ;
3956    } else if( fabs(fvm.xyz[2]-fvp.xyz[2]) > dxyz ){ /* +=S -=I */
3957      cc = fvp.xyz[2] ;
3958      dd = ( cc >= 0.0 ) ? "S" : "I" ;
3959    } else {
3960      cc = 0.0f ; dd = "" ; /* should be impossible */
3961    }
3962 
3963    sprintf(str,"%6.2f",fabs(cc)) ;
3964    for( ii=strlen(str)-1 ; ii > 0 && str[ii] == '0' ; ii-- ) str[ii] = '\0' ;
3965    if( str[ii] == '.' ) str[ii] = '\0' ;
3966    strcat(str, dd) ;
3967    strcpy( lpart[LPART_SLICE_COORD] , str ) ;
3968 
3969    /* time index */
3970 
3971    nnn = DSET_NVALS(dset) ;
3972    fmt =  (nnn < 10)    ? "#%1d"
3973         : (nnn < 100)   ? "#%02d"
3974         : (nnn < 1000)  ? "#%03d"
3975         : (nnn < 10000) ? "#%04d"
3976         : (nnn < 100000)? "#%05d"
3977         :                 "#%06d" ;
3978    sprintf(str,fmt,im3d->vinfo->time_index) ;
3979    strcpy( lpart[LPART_TIME_INDEX] , str ) ;
3980 
3981    /* time coord */
3982 
3983    cc = DSET_TIMEORIGIN(dset) + im3d->vinfo->time_index * DSET_TR(dset) ;
3984 
3985    sprintf(str,"%-16.5f",cc) ; /* %- means will be left justified, not right */
3986    for( ii=strlen(str)-1 ;
3987         ii > 0 && (str[ii] == '0' || str[ii] == ' ') ; ii-- ) str[ii] = '\0' ;
3988    if( str[ii] == '.' ) str[ii] = '\0' ;
3989    strcpy( lpart[LPART_TIME_COORD] , str ) ;
3990 
3991    return 0 ;
3992 }
3993 
3994 /*----------------------------------------------------------------------
3995    routine to extract a plane of data from a 3D brick
3996    (used as a "get_image" routine for an MCW_imseq)
3997 ------------------------------------------------------------------------*/
3998 
AFNI_brick_to_mri(int n,int type,FD_brick * br)3999 XtPointer AFNI_brick_to_mri( int n , int type , FD_brick *br )
4000 {
4001    MRI_IMAGE *im ;
4002    MCW_imseq_status *stat ;
4003    int i1,i2,jb,bb , dd1,dd2,tt1,tt2 ;
4004 
4005 ENTRY("AFNI_brick_to_mri") ;
4006 
4007 if(PRINT_TRACING){ char str[1024] ; sprintf(str,"n=%d type=%d",n,type) ; STATUS(str) ; }
4008 
4009    if( br == NULL ){  /* should never happen */
4010      ERROR_message("AFNI_brick_to_mri: bad FD_brick :-(") ; RETURN(NULL) ;
4011    }
4012 
4013    /*-------------------------------------------------*/
4014    /*-------- May 1996: graph callbacks first --------*/
4015 
4016    if( type == graCR_getlabel ){                  /* 18 Apr 2011 */
4017      char *lab = DSET_BRICK_LABEL(br->dset,n) ;
4018      RETURN( (XtPointer)lab ) ;
4019    }
4020 
4021    if( type == graCR_getstatus ){
4022       MCW_grapher_status *grstat = myXtNew( MCW_grapher_status ) ;
4023 
4024       grstat->num_total  = grstat->num_series = br->dset->dblk->nvals ;
4025       grstat->nx         = br->n1 ;
4026       grstat->ny         = br->n2 ;
4027       grstat->nz         = br->n3 ;
4028 
4029       grstat->send_CB    = AFNI_gra_send_CB ;
4030       grstat->parent     = (XtPointer) br ;
4031       grstat->aux        = NULL ;
4032 
4033       grstat->transforms0D = & (GLOBAL_library.registered_0D) ;
4034       grstat->transforms1D = & (GLOBAL_library.registered_1D) ;
4035 
4036       MCW_strncpy( grstat->namecode , br->namecode , 32 ) ;
4037 
4038       RETURN( (XtPointer) grstat ) ;
4039    }
4040 
4041    if( type == graCR_getseries ){
4042       Three_D_View *im3d = (Three_D_View *)br->parent ;
4043       MCW_grapher *grapher = UNDERLAY_TO_GRAPHER(im3d,br) ;
4044 
4045       im = FD_brick_to_series( n , br ) ; if( im == NULL ) RETURN(NULL) ;
4046       im->flags = 1 ;
4047 
4048       if( grapher->thresh_fade && im3d->vinfo->func_visible ){  /* Mar 2013 */
4049         int nsl = n / (br->n1 * br->n2) ;
4050 #if 0
4051 INFO_message("thresh_fade: nsl=%d",nsl) ;
4052 #endif
4053         if( br->ntmask != nsl ){
4054           FD_brick *br_fim = UNDERLAY_TO_OVERLAY(im3d,br) ;
4055           MRI_IMAGE *fov = AFNI_func_overlay(nsl,br_fim) ;
4056           STATUS("clear overlay tmask") ;
4057           CLEAR_TMASK(br) ;
4058 #if 0
4059 ININFO_message("  get new tmask") ;
4060 #endif
4061           if( fov != NULL ){
4062             br->tmask  = ISQ_binarize_overlay(fov) ;
4063             STATUSp("new tmask",br->tmask) ;
4064             br->ntmask = nsl ; mri_free(fov) ;
4065           }
4066         }
4067         if( br->tmask != NULL ){
4068           byte *tar = MRI_BYTE_PTR(br->tmask) ;
4069           int ij = n % (br->n1 * br->n2) ;
4070           im->flags = (int)tar[ij] ;
4071 #if 0
4072 ININFO_message("  set tsim flags=%d at ij=%d",im->flags) ;
4073 #endif
4074         }
4075       }
4076 
4077       RETURN( (XtPointer)im ) ;
4078    }
4079 
4080    /*----------------------------------------*/
4081    /*-------- Now do imseq callbacks --------*/
4082 
4083    /*--- set the sub-brick (ival) index shift ---*/
4084 
4085    if( type == isqCR_deltival ){  /* 23 Feb 2011 */
4086      Three_D_View *im3d = (Three_D_View *)br->parent ;
4087      FD_brick *brfim ;
4088      br->deltival = n ;
4089      brfim = UNDERLAY_TO_OVERLAY(im3d,br) ;
4090      if( brfim != NULL ) brfim->deltival = n ;
4091      RETURN( NULL ) ;
4092    }
4093 
4094    if( n < 0 || n >= br->n3 ) RETURN(NULL) ;
4095 
4096    /*--- overlay # n ---*/
4097 
4098    if( type == isqCR_getoverlay  ){
4099       Three_D_View *im3d = (Three_D_View *)br->parent ;
4100 
4101 STATUS("get overlay") ;
4102 
4103       im = AFNI_overlay( n , br ) ;
4104       if( !AFNI_noenv("AFNI_VALUE_LABEL") ) AFNI_do_bkgd_lab( im3d ) ;
4105       RETURN( (XtPointer) im ) ;
4106    }
4107 
4108    /*--- status ---*/
4109 
4110    if( type == isqCR_getstatus ){
4111 
4112 STATUS("get status") ;
4113 
4114       stat = myXtNew( MCW_imseq_status ) ;
4115 
4116       stat->num_total  = br->n3 ;
4117       stat->num_series = br->n3 ;
4118       stat->send_CB    = AFNI_seq_send_CB ;
4119       stat->parent     = (XtPointer) br ;
4120       stat->aux        = NULL ;
4121 
4122       stat->transforms0D = & (GLOBAL_library.registered_0D) ;
4123       stat->transforms2D = & (GLOBAL_library.registered_2D) ;
4124       stat->slice_proj   = & (GLOBAL_library.registered_slice_proj) ;
4125 
4126       RETURN( (XtPointer) stat ) ;
4127    }
4128 
4129    /*--- 26 Feb 2001: return a memplot drawing struct ---*/
4130    /*--- 22 Mar 2002: add crosshairs to surface stuff ---*/
4131 
4132 #define RX 0.2
4133    if( type == isqCR_getmemplot ){
4134      Three_D_View *im3d = (Three_D_View *)br->parent ;
4135      THD_3dim_dataset *udset = im3d->anat_now ; /* 07 Jan 2008 */
4136 #ifdef IMAGEIZE_CROSSHAIRS  /* disable crosshairs drawn into overlay pixels */
4137      int do_xhar=(im3d->vinfo->crosshair_visible && AFNI_yesenv("AFNI_CROSSHAIR_LINES"));
4138 #else
4139      int do_xhar=(im3d->vinfo->crosshair_visible) ;
4140 #endif
4141      int do_surf;
4142      MEM_plotdata *mp ;
4143      AFNI_surface_widgets *swid = im3d->vwid->view->swid ;  /* 19 Aug 2002 */
4144      THD_session *suss=im3d->ss_now ;                       /* 20 Jan 2004 */
4145      THD_dataxes *daxes=CURRENT_DAXES(udset) ;
4146 
4147      if( !IM3D_OPEN(im3d) )     RETURN(NULL) ;
4148 
4149      /* 20 Jan 2004: surfaces are now in the session, not on the dataset! */
4150 
4151      do_surf = SUMA_ENABLED && SESSION_HAS_SUMA(suss) ;
4152      if( !do_surf && !do_xhar ) RETURN(NULL) ;  /* nothing to do */
4153 
4154      /* get ready to plot */
4155 
4156 STATUS("creating memplot for image overlay") ;
4157      create_memplot_surely( "SUMA_plot" , 1.0 ) ;
4158      mp = get_active_memplot() ;
4159 
4160      /* plot surface stuff, if any (this is long) */
4161 
4162     if( do_surf ){
4163      int ks , qs , rs ;
4164      int kbest=-1 , ibest=-1 ;              /* 24 Feb 2003 */
4165      int nsurf; SUMA_surface **aglist=NULL; /* 07 Apr 2014 */
4166 
4167      AFNI_get_xhair_node( im3d , &kbest , &ibest ) ;   /* 24 Feb 2003 */
4168 
4169      /* Find all the surfaces to draw -- more complex after 07 Apr 2014 */
4170 
4171      nsurf = suss->su_num ;
4172      for( qs=0 ; qs < suss->su_nummask ; qs++ )
4173        nsurf += suss->su_mask[qs]->num_surf ;
4174 
4175      aglist = (SUMA_surface **)calloc(nsurf,sizeof(SUMA_surface *)) ;
4176 
4177      for( qs=0 ; qs < suss->su_num ; qs++ ){
4178        aglist[qs] = suss->su_surf[qs] ;
4179      }
4180      for( ks=qs,qs=0 ; qs < suss->su_nummask ; qs++ ){
4181        for( rs=0 ; rs < suss->su_mask[qs]->num_surf ; rs++ ){
4182          aglist[ks] = suss->su_mask[qs]->surf[rs] ;
4183        }
4184      }
4185 
4186      for( ks=0 ; ks < nsurf ; ks++ ){      /* 14 Aug 2002: loop over surfaces */
4187       SUMA_surface *ag = aglist[ks] ; SUMA_mask *msk = NULL ;
4188       int nn , ii,jj , relxyz=0 ;
4189       SUMA_ixyz *nod ;
4190       THD_ivec3 iv,ivp,ivm ;
4191       THD_fvec3 fv,fvp,fvm ;
4192       float s1=1.0/br->n1 , s2=1.0/br->n2 , dxyz ;
4193       float rr_box=1.0,gg_box=0.0,bb_box=0.0 ;   /* white */
4194       float rr_lin=0.4,gg_lin=0.0,bb_lin=0.7 ;   /* dark blue */
4195       float rr_led=1.0,gg_led=0.0,bb_led=0.0 ;
4196       char str[128] , *eee ;
4197       float rx=RX ;         /* default rectangle halfsize */
4198       int   kkk=0 ;
4199       float xyz=0.0,xyzp=0.0,xyzm=0.0 , rxm,rxp ;
4200       int skip_boxes=1 , skip_lines=0 , skip_lcen=0, skip_ledg=1 ;
4201       float boxsize=RX , linewidth=0.0 ;      /* 23 Feb 2003 */
4202       int firstb ;                            /* 23 Jan 2004 */
4203       float xrel=0.0f,yrel=0.0f,zrel=0.0f ;
4204 
4205       if( ag == NULL ) continue ;             /* skip this non-existent one */
4206       nn = ag->num_ixyz ; nod = ag->ixyz ;
4207       if( nn < 1 || nod == NULL ) continue ;  /* nothing can be done */
4208 
4209       if( ag->parent_type == SUMA_MASK_TYPE ){        /* relative coords */
4210         relxyz = 1 ; msk = (SUMA_mask *)ag->parent ;  /* in a mask surf? */
4211         xrel = msk->show_cen.xyz[0] - msk->init_cen.xyz[0] ;
4212         yrel = msk->show_cen.xyz[1] - msk->init_cen.xyz[1] ;
4213         zrel = msk->show_cen.xyz[2] - msk->init_cen.xyz[2] ;
4214 /** INFO_message("SUMA_mask draw: xyz rel = %g %g %g",xrel,yrel,zrel) ; **/
4215       }
4216 
4217       /* define parameters for node boxes and triangle lines */
4218 
4219 STATUS("defining surface drawing parameters") ;
4220       if( swid != NULL && ks < swid->nrow ){     /* 19 Aug 2002: the new way */
4221         int cc, dd ;                             /*           to set colors: */
4222                                                  /* from the surface widgets */
4223 
4224         cc = MCW_val_bbox(swid->surf_bbox[ks]) ; /* 19 Feb 2003: skip it all? */
4225         if( cc == 0 ){
4226           skip_boxes = skip_lines = 1 ;
4227         } else {                                 /* see what is turned on */
4228           cc = swid->surf_node_av[ks]->ival ;
4229           skip_boxes = (cc == 0) ;
4230           if( !skip_boxes ){
4231             rr_box = DCOV_REDBYTE(im3d->dc,cc)   / 255.0 ;
4232             gg_box = DCOV_GREENBYTE(im3d->dc,cc) / 255.0 ;
4233             bb_box = DCOV_BLUEBYTE(im3d->dc,cc)  / 255.0 ;
4234           }
4235           cc = swid->surf_line_av[ks]->ival ;
4236           dd = swid->surf_ledg_av[ks]->ival ;             /* 26 Feb 2003 */
4237           skip_lcen  = (cc == 0) ;
4238           skip_ledg  = (dd == 0) ;
4239           skip_lines = (skip_lcen && skip_ledg) ;
4240           if( cc > 0 ){
4241             rr_lin = DCOV_REDBYTE(im3d->dc,cc)   / 255.0 ;
4242             gg_lin = DCOV_GREENBYTE(im3d->dc,cc) / 255.0 ;
4243             bb_lin = DCOV_BLUEBYTE(im3d->dc,cc)  / 255.0 ;
4244           }
4245           if( dd > 0 ){                                   /* 26 Feb 2003 */
4246             rr_led = DCOV_REDBYTE(im3d->dc,dd)   / 255.0 ;
4247             gg_led = DCOV_GREENBYTE(im3d->dc,dd) / 255.0 ;
4248             bb_led = DCOV_BLUEBYTE(im3d->dc,dd)  / 255.0 ;
4249           }
4250           boxsize   = swid->boxsize_av->ival   * 0.1   ;  /* 23 Feb 2003 */
4251           linewidth = swid->linewidth_av->ival * 0.002 ;
4252         }
4253 
4254       } else if( msk != NULL ){ /* set from inside the surf struct [Apr 2014] */
4255 
4256         DC_parse_color( im3d->dc , ag->line_color , &rr_lin,&gg_lin,&bb_lin ) ;
4257         DC_parse_color( im3d->dc , ag->box_color  , &rr_box,&gg_box,&bb_box ) ;
4258         linewidth = ag->line_width * 0.002f ;
4259         skip_boxes = 1 ; skip_lines = 0 ; skip_lcen = 0; skip_ledg = 1 ;
4260 
4261       } else {                                   /* the old way    */
4262                                                  /* to set colors:  */
4263         rgbyte bcolor , lcolor ;                 /* from environment */
4264         AFNI_get_suma_color( ks , &bcolor , &lcolor ) ;
4265         if( bcolor.r == 1 && bcolor.g == 1 && bcolor.b == 1 ){
4266           skip_boxes = 1 ;                  /* don't do boxes */
4267         } else {
4268           rr_box = bcolor.r / 255.0f ;
4269           gg_box = bcolor.g / 255.0f ;
4270           bb_box = bcolor.b / 255.0f ;
4271         }
4272         if( lcolor.r == 1 && lcolor.g == 1 && lcolor.b == 1 ){
4273           skip_lines = 1 ;                  /* don't do lines */
4274         } else {
4275           rr_lin = lcolor.r / 255.0f ;
4276           gg_lin = lcolor.g / 255.0f ;
4277           bb_lin = lcolor.b / 255.0f ;
4278         }
4279 
4280         eee = getenv("AFNI_SUMA_BOXSIZE") ;  /* maybe set boxsize? */
4281         if( eee != NULL ){
4282           float val=strtod(eee,NULL) ;
4283           if( val > 0.0 ) boxsize = val ;
4284         } else if( swid != NULL ){
4285           boxsize = swid->boxsize_av->ival * 0.1 ;
4286         }
4287 
4288         eee = getenv( "AFNI_SUMA_LINESIZE" ) ; /* maybe set linewidth? */
4289         if( eee != NULL ){
4290           float val = strtod(eee,NULL) ;
4291           if( val < 0.0 || val > 0.1 ) val = 0.0 ;
4292           linewidth = val ;
4293         } else if( swid != NULL ){
4294           linewidth = swid->linewidth_av->ival * 0.002 ;
4295         }
4296       }
4297 
4298       if( skip_boxes && skip_lines ) continue ; /* nothing to do? */
4299 
4300       /** 21 Mar 2002:
4301           We calculate plotting coordinates in "fdfind" coordinates,
4302           which are floating point indexes into the FD_brick.  However,
4303           these run from 0..n1-1 (in x), which are the centers of the
4304           voxels.  In turn these must be mapped to screen locations.
4305           For example, with n1=5, we have these voxels
4306 
4307               0   1   2   3   4    = index of voxel
4308             ---------------------
4309             |   |   |   |   |   |
4310             ---------------------
4311            0.0                 1.0 = screen coordinate (for memplot)
4312 
4313           Thus voxel index i maps to screen location (i+0.5)/n1.
4314           Previously, I forgot the +0.5, which didn't matter much,
4315           until the introduction of the image zoom feature last week. **/
4316 
4317       rx  = boxsize ;                /* 23 Feb 2003 */
4318       rxm = rx-0.5 ; rxp = rx+0.5 ;  /* The 0.5 voxel shift */
4319 
4320       /* find DICOM coordinates of next slice and previous slice */
4321 
4322       LOAD_IVEC3(iv,0,0,n+1) ;                     /* next */
4323       ivp = THD_fdind_to_3dind( br , iv ) ;
4324       fvp = THD_3dind_to_3dmm ( udset , ivp ) ;
4325       fvp = THD_3dmm_to_dicomm( udset , fvp ) ;
4326       LOAD_IVEC3(iv,0,0,n-1) ;                     /* previous */
4327       ivm = THD_fdind_to_3dind( br , iv ) ;
4328       fvm = THD_3dind_to_3dmm ( udset , ivm ) ;
4329       fvm = THD_3dmm_to_dicomm( udset , fvm ) ;
4330 
4331       /* threshold for determining which axis this slice is along */
4332 
4333       dxyz = MIN(br->del1,br->del2) ;
4334       dxyz = MIN(dxyz    ,br->del3) ; dxyz *= 0.1f ;
4335 
4336       set_color_memplot(rr_box,gg_box,bb_box) ;  /* box drawing colors */
4337       set_thick_memplot(0.0) ;
4338       firstb = 1 ;                               /* 23 Jan 2004 */
4339 
4340       /* find nodes inside this slice */
4341 
4342       if( skip_boxes ) STATUS("finding slice planes") ;
4343       else             STATUS("drawing node boxes") ;
4344 
4345       if( fabs(fvm.xyz[0]-fvp.xyz[0]) > dxyz ){               /* search x */
4346          float xb=fvm.xyz[0] , xt=fvp.xyz[0] , xm,xw ;        /* range of  */
4347          float nodx,nody,nodz ;
4348          if( xb > xt ){ float t=xb ; xb=xt ; xt=t ; }         /* x in slice */
4349          xm = 0.5*(xb+xt); xw = 0.25*(xt-xb); xb = xm-xw; xt = xm+xw;
4350 STATUS(" - x plane") ;
4351          if( !skip_boxes ){
4352           for( ii=0 ; ii < nn ; ii++ ){
4353             nodx = nod[ii].x ; nody = nod[ii].y ; nodz = nod[ii].z ;
4354             if( relxyz ){ nodx += xrel ; nody += yrel ; nodz += zrel ; }
4355             if( nodx >= xb && nodx <= xt ){         /* inside?  */
4356                LOAD_FVEC3(fv,nodx,nody,nodz) ;                /* convert  */
4357                fv = THD_dicomm_to_3dmm( udset , fv ) ;        /* coords   */
4358                fv = THD_3dmm_to_3dfind( udset , fv ) ;        /* to slice */
4359                fv = THD_3dfind_to_fdfind( br , fv ) ;         /* indexes  */
4360 
4361                if( firstb ){
4362                  plotline_memplot( s1*(fv.xyz[0]-rxm), 1.0-s2*(fv.xyz[1]-rxm),
4363                                    s1*(fv.xyz[0]+rxp), 1.0-s2*(fv.xyz[1]+rxp)  );
4364                  firstb = 0 ;
4365                }
4366 
4367                plotrect_memplot( s1*(fv.xyz[0]-rxm), 1.0-s2*(fv.xyz[1]-rxm),
4368                                  s1*(fv.xyz[0]+rxp), 1.0-s2*(fv.xyz[1]+rxp)  ) ;
4369 
4370                if( ks == kbest && nod[ii].id == ibest ){   /* 24 Feb 2003 */
4371                  plotline_memplot( s1*(fv.xyz[0]-rxm), 1.0-s2*(fv.xyz[1]-rxm),
4372                                    s1*(fv.xyz[0]+rxp), 1.0-s2*(fv.xyz[1]+rxp)  );
4373                  plotline_memplot( s1*(fv.xyz[0]-rxm), 1.0-s2*(fv.xyz[1]+rxp),
4374                                    s1*(fv.xyz[0]+rxp), 1.0-s2*(fv.xyz[1]-rxm)  );
4375                  plotline_memplot( s1*(fv.xyz[0]-rxm), 1.0-s2*(fv.xyz[1]+0.5),
4376                                    s1*(fv.xyz[0]+rxp), 1.0-s2*(fv.xyz[1]+0.5)  );
4377                  plotline_memplot( s1*(fv.xyz[0]+0.5), 1.0-s2*(fv.xyz[1]-rxm),
4378                                    s1*(fv.xyz[0]+0.5), 1.0-s2*(fv.xyz[1]+rxp)  );
4379                }
4380             }
4381           }
4382          }
4383          kkk = 0; xyz = xm; xyzp = xt; xyzm = xb;  /* for the triangles/lines below */
4384       }
4385       else if( fabs(fvm.xyz[1]-fvp.xyz[1]) > dxyz ){          /* search y */
4386          float yb=fvm.xyz[1] , yt=fvp.xyz[1] , ym,yw ;
4387          float nodx,nody,nodz ;
4388          if( yb > yt ){ float t=yb ; yb=yt ; yt=t ; }
4389          ym = 0.5*(yb+yt); yw = 0.25*(yt-yb); yb = ym-yw; yt = ym+yw;
4390 STATUS(" - y plane") ;
4391          if( !skip_boxes ){
4392           for( ii=0 ; ii < nn ; ii++ ){
4393             nodx = nod[ii].x ; nody = nod[ii].y ; nodz = nod[ii].z ;
4394             if( relxyz ){ nodx += xrel ; nody += yrel ; nodz += zrel ; }
4395             if( nody >= yb && nody <= yt ){
4396                LOAD_FVEC3(fv,nodx,nody,nodz) ;
4397                fv = THD_dicomm_to_3dmm( udset , fv ) ;
4398                fv = THD_3dmm_to_3dfind( udset , fv ) ;
4399                fv = THD_3dfind_to_fdfind( br , fv ) ;
4400 
4401                if( firstb ){
4402                  plotline_memplot( s1*(fv.xyz[0]-rxm), 1.0-s2*(fv.xyz[1]-rxm),
4403                                    s1*(fv.xyz[0]+rxp), 1.0-s2*(fv.xyz[1]+rxp)  );
4404                  firstb = 0 ;
4405                }
4406 
4407                plotrect_memplot( s1*(fv.xyz[0]-rxm), 1.0-s2*(fv.xyz[1]-rxm),
4408                                  s1*(fv.xyz[0]+rxp), 1.0-s2*(fv.xyz[1]+rxp)  ) ;
4409 
4410                if( ks == kbest && nod[ii].id == ibest ){   /* 24 Feb 2003 */
4411                  plotline_memplot( s1*(fv.xyz[0]-rxm), 1.0-s2*(fv.xyz[1]-rxm),
4412                                    s1*(fv.xyz[0]+rxp), 1.0-s2*(fv.xyz[1]+rxp)  );
4413                  plotline_memplot( s1*(fv.xyz[0]-rxm), 1.0-s2*(fv.xyz[1]+rxp),
4414                                    s1*(fv.xyz[0]+rxp), 1.0-s2*(fv.xyz[1]-rxm)  );
4415                  plotline_memplot( s1*(fv.xyz[0]-rxm), 1.0-s2*(fv.xyz[1]+0.5),
4416                                    s1*(fv.xyz[0]+rxp), 1.0-s2*(fv.xyz[1]+0.5)  );
4417                  plotline_memplot( s1*(fv.xyz[0]+0.5), 1.0-s2*(fv.xyz[1]-rxm),
4418                                    s1*(fv.xyz[0]+0.5), 1.0-s2*(fv.xyz[1]+rxp)  );
4419                }
4420             }
4421           }
4422          }
4423          kkk = 1; xyz = ym; xyzp = yt; xyzm = yb;  /* for the triangles/lines below */
4424       }
4425       else if( fabs(fvm.xyz[2]-fvp.xyz[2]) > dxyz ){          /* search z */
4426          float zb=fvm.xyz[2] , zt=fvp.xyz[2] , zm,zw ;
4427          float nodx,nody,nodz ;
4428          if( zb > zt ){ float t=zb ; zb=zt ; zt=t ; }
4429          zm = 0.5*(zb+zt); zw = 0.25*(zt-zb); zb = zm-zw; zt = zm+zw;
4430 STATUS(" - z plane") ;
4431          if( !skip_boxes ){
4432           for( ii=0 ; ii < nn ; ii++ ){
4433             nodx = nod[ii].x ; nody = nod[ii].y ; nodz = nod[ii].z ;
4434             if( relxyz ){ nodx += xrel ; nody += yrel ; nodz += zrel ; }
4435             if( nodz >= zb && nodz <= zt ){
4436                LOAD_FVEC3(fv,nod[ii].x,nod[ii].y,nod[ii].z) ;
4437                fv = THD_dicomm_to_3dmm( udset , fv ) ;
4438                fv = THD_3dmm_to_3dfind( udset , fv ) ;
4439                fv = THD_3dfind_to_fdfind( br , fv ) ;
4440 
4441                if( firstb ){
4442                  plotline_memplot( s1*(fv.xyz[0]-rxm), 1.0-s2*(fv.xyz[1]-rxm),
4443                                    s1*(fv.xyz[0]+rxp), 1.0-s2*(fv.xyz[1]+rxp)  );
4444                  firstb = 0 ;
4445                }
4446 
4447                plotrect_memplot( s1*(fv.xyz[0]-rxm), 1.0-s2*(fv.xyz[1]-rxm),
4448                                  s1*(fv.xyz[0]+rxp), 1.0-s2*(fv.xyz[1]+rxp)  ) ;
4449 
4450                if( ks == kbest && nod[ii].id == ibest ){   /* 24 Feb 2003 */
4451                  plotline_memplot( s1*(fv.xyz[0]-rxm), 1.0-s2*(fv.xyz[1]-rxm),
4452                                    s1*(fv.xyz[0]+rxp), 1.0-s2*(fv.xyz[1]+rxp)  );
4453                  plotline_memplot( s1*(fv.xyz[0]-rxm), 1.0-s2*(fv.xyz[1]+rxp),
4454                                    s1*(fv.xyz[0]+rxp), 1.0-s2*(fv.xyz[1]-rxm)  );
4455                  plotline_memplot( s1*(fv.xyz[0]-rxm), 1.0-s2*(fv.xyz[1]+0.5),
4456                                    s1*(fv.xyz[0]+rxp), 1.0-s2*(fv.xyz[1]+0.5)  );
4457                  plotline_memplot( s1*(fv.xyz[0]+0.5), 1.0-s2*(fv.xyz[1]-rxm),
4458                                    s1*(fv.xyz[0]+0.5), 1.0-s2*(fv.xyz[1]+rxp)  );
4459                }
4460             }
4461           }
4462          }
4463          kkk = 2; xyz = zm; xyzp = zt; xyzm = zb;  /* for the triangles/lines below */
4464       }
4465 
4466       /* 10 Mar 2002:
4467          For each triangle that crosses the plane of the slice,
4468          plot a line segment at the intersection of the plane and triangle.
4469          The plane is along DICOM axis #kkk at coordinate xyz;
4470          these variables were set just above in the node display code. */
4471 
4472       if( !skip_lines && ag->num_ijk > 0 && ag->ijk != NULL ){
4473         SUMA_ijk *tr = ag->ijk ;        /* triangle list  */
4474         int      ntr = ag->num_ijk ;    /* number of triangles */
4475         int id,jd,kd ;
4476         THD_fvec3 fvijk[3] ;
4477         float ci,cj,ck , xlev ;
4478         int ilev ;
4479 
4480         for( ilev=0 ; ilev <= 2 ; ilev++ ){  /* 26 Feb 2003: loop over levels: */
4481                                              /* slice center, top & bot edges  */
4482           if( ilev == 0 ){
4483             if( skip_lcen ) continue ;  /* don't do center plane */
4484             xlev = xyz ;
4485             set_color_memplot(rr_lin,gg_lin,bb_lin) ;  /* line drawing colors */
4486             set_thick_memplot(linewidth) ;
4487           } else {
4488             if( skip_ledg ) continue ;  /* don't do edge planes */
4489             xlev = (ilev == 1) ? xyzp : xyzm ;
4490             set_color_memplot(rr_led,gg_led,bb_led) ;
4491             set_thick_memplot(0.0) ;
4492           }
4493 
4494 STATUS("drawing triangle lines") ;
4495 
4496           /* loop over triangles */
4497 
4498           for( ii=0 ; ii < ntr ; ii++ ){
4499 
4500             /* get indexes of triangle's nodes (from their id's) */
4501 
4502             id = SUMA_find_node_id(ag,tr[ii].id); if( id < 0 ) continue;
4503             jd = SUMA_find_node_id(ag,tr[ii].jd); if( jd < 0 ) continue;
4504             kd = SUMA_find_node_id(ag,tr[ii].kd); if( kd < 0 ) continue;
4505 
4506             /* load DICOM coords of triangle's nodes */
4507 
4508             LOAD_FVEC3(fvijk[0], nod[id].x, nod[id].y, nod[id].z) ;
4509             LOAD_FVEC3(fvijk[1], nod[jd].x, nod[jd].y, nod[jd].z) ;
4510             LOAD_FVEC3(fvijk[2], nod[kd].x, nod[kd].y, nod[kd].z) ;
4511 
4512             if( relxyz ){  /* 07 Apr 2014 */
4513               fvijk[0].xyz[0] += xrel; fvijk[1].xyz[0] += xrel; fvijk[2].xyz[0] += xrel;
4514               fvijk[0].xyz[1] += yrel; fvijk[1].xyz[1] += yrel; fvijk[2].xyz[1] += yrel;
4515               fvijk[0].xyz[2] += zrel; fvijk[1].xyz[2] += zrel; fvijk[2].xyz[2] += zrel;
4516             }
4517 
4518             /* want 1 node on one size of plane, and 2 on the other */
4519 
4520             ci = fvijk[0].xyz[kkk] - xlev;      /* differences from center */
4521             cj = fvijk[1].xyz[kkk] - xlev;      /* of current slice plane */
4522             ck = fvijk[2].xyz[kkk] - xlev;
4523             jj = 4*(ci > 0.0) + 2*(cj > 0.0) + (ck > 0.0) ;
4524             if( jj == 0 || jj == 7 ) continue ; /* all have same sign */
4525 
4526             /* setup id,jd,kd so fvijk[id] is on one side of plane,
4527                and so that fvijk[jd] and fvijk[kd] are on other side */
4528 
4529             switch( jj ){
4530                case 6:
4531                case 1: id = 2 ; jd = 0 ; kd = 1 ; break ;  /* kd is the 1 */
4532                case 5:
4533                case 2: id = 1 ; jd = 0 ; kd = 2 ; break ;  /* jd is the 1 */
4534                case 4:
4535                case 3: id = 0 ; jd = 1 ; kd = 2 ; break ;  /* id is the 1 */
4536             }
4537 
4538             /* linearly interpolate between fvijk[id] and fvijk[jd]
4539                to find the point where this line hits the slice plane */
4540 
4541             ci = fvijk[id].xyz[kkk] - xlev;
4542             cj = fvijk[id].xyz[kkk] - fvijk[jd].xyz[kkk] ;
4543             if( cj == 0.0 ) continue ;            /* should not happen */
4544             ck = ci / cj ;
4545             if( ck < 0.0 || ck > 1.0 ) continue ; /* should not happen */
4546             cj = 1.0 - ck ;
4547             fvp = SCLADD_FVEC3(cj,fvijk[id],ck,fvijk[jd]) ;
4548 
4549             /* linearly interpolate between fvijk[id] and fvijk[kd] */
4550 
4551             cj = fvijk[id].xyz[kkk] - fvijk[kd].xyz[kkk] ;
4552             if( cj == 0.0 ) continue ;
4553             ck = ci / cj ;
4554             if( ck < 0.0 || ck > 1.0 ) continue ;
4555             cj = 1.0 - ck ;
4556             fvm = SCLADD_FVEC3(cj,fvijk[id],ck,fvijk[kd]) ;
4557 
4558             /* transform interpolated points to FD_brick coords */
4559 
4560             fvp = THD_dicomm_to_3dmm( udset , fvp ) ;
4561             if( fvp.xyz[0] < daxes->xxmin ||
4562                 fvp.xyz[0] > daxes->xxmax ||
4563                 fvp.xyz[1] < daxes->yymin ||
4564                 fvp.xyz[1] > daxes->yymax ||
4565                 fvp.xyz[2] < daxes->zzmin ||
4566                 fvp.xyz[2] > daxes->zzmax   ) continue ;  /* 08 Jan 2004 */
4567             fvp = THD_3dmm_to_3dfind( udset , fvp ) ;
4568             fvp = THD_3dfind_to_fdfind( br , fvp ) ;
4569 
4570             fvm = THD_dicomm_to_3dmm( udset , fvm ) ;
4571             if( fvm.xyz[0] < daxes->xxmin ||
4572                 fvm.xyz[0] > daxes->xxmax ||
4573                 fvm.xyz[1] < daxes->yymin ||
4574                 fvm.xyz[1] > daxes->yymax ||
4575                 fvm.xyz[2] < daxes->zzmin ||
4576                 fvm.xyz[2] > daxes->zzmax   ) continue ;  /* 08 Jan 2004 */
4577             fvm = THD_3dmm_to_3dfind( udset , fvm ) ;
4578             fvm = THD_3dfind_to_fdfind( br , fvm ) ;
4579 
4580             /* plot a line segment between them, in the plane of the slice */
4581             /* [21 Mar 2002: include the 0.5 shift mentioned way up above] */
4582 
4583             plotline_memplot( s1*(fvp.xyz[0]+0.5) , 1.0-s2*(fvp.xyz[1]+0.5) ,
4584                               s1*(fvm.xyz[0]+0.5) , 1.0-s2*(fvm.xyz[1]+0.5)  ) ;
4585 
4586           } /* end of loop over triangles */
4587           set_thick_memplot(0.0) ;              /* 15 Jan 2003 */
4588         } /* end of loop over levels: 26 Feb 2003 */
4589       } /* end of if over doing lines */
4590      } /* end of loop over surface index ks */
4591     } /* end of plotting surface stuff */
4592 
4593      /*----- put crosshairs on with lines, if desired -----*/
4594      /****** 22 Mar 2002: adapted from pixel overlay  ******/
4595 
4596      if( do_xhar ){
4597       MCW_grapher *grapher = UNDERLAY_TO_GRAPHER(im3d,br) ;
4598       float thth = (float)AFNI_numenv("AFNI_CROSSHAIR_THICKNESS") ;
4599 
4600       THD_ivec3 ib = THD_3dind_to_fdind( br ,
4601                                          TEMP_IVEC3( im3d->vinfo->i1 ,
4602                                                      im3d->vinfo->j2 ,
4603                                                      im3d->vinfo->k3  ) ) ;
4604 STATUS("drawing crosshairs") ;
4605 
4606       if( thth < 0.0f || thth > 0.05f ) thth = 0.0f ;
4607       set_thick_memplot(thth) ;
4608 
4609       if( n == ib.ijk[2] || im3d->vinfo->xhairs_all ){
4610          int jp,ip , jcen,icen , gappp , jj,ii ;
4611          int idown,iup,iskip , jdown,jup,jskip , imon,jmon ;
4612          int a1 = br->a123.ijk[0] ,   /* x axis of the brick?    */
4613              ax = abs(a1) - 1       ; /* 0,1,2 for dataset x,y,z */
4614          int a2 = br->a123.ijk[1] ,   /* y axis of the brick?    */
4615              ay = abs(a2) - 1       ; /* 0,1,2 for dataset x,y,z */
4616          int a3 = br->a123.ijk[2] ,   /* z axis of the brick?    */
4617              az = abs(a3) - 1       ; /* 0,1,2 for dataset x,y,z */
4618 
4619          int gap,icr,jcr , nx=br->n1 , ny=br->n2 ;
4620 
4621          float rr,gg,bb ;             /* colors */
4622          float s1=1.0/br->n1 , s2=1.0/br->n2 ;  /* scale pixels to plot coords */
4623 #define PSX(i) (s1*((i)+0.5))
4624 #define PSY(j) (1.0-s2*((j)+0.5))
4625 
4626          /* spatial orientations of image axes */
4627 
4628          int ox = (ax==0) ? br->dset->daxes->xxorient :
4629                   (ax==1) ? br->dset->daxes->yyorient : br->dset->daxes->zzorient ;
4630 
4631          int oy = (ay==0) ? br->dset->daxes->xxorient :
4632                   (ay==1) ? br->dset->daxes->yyorient : br->dset->daxes->zzorient ;
4633 
4634          jp = im3d->vinfo->crosshair_ovcolor ;
4635          rr = DCOV_REDBYTE  (im3d->dc,jp) / 255.0 ;
4636          gg = DCOV_GREENBYTE(im3d->dc,jp) / 255.0 ;
4637          bb = DCOV_BLUEBYTE (im3d->dc,jp) / 255.0 ;
4638          set_color_memplot(rr,gg,bb) ;
4639 
4640          gap  = (grapher==NULL) ? im3d->vinfo->crosshair_gap : (grapher->mat+1)/2 ;
4641 
4642          icen = ib.ijk[0] ;  /* x-index of image pixel at focus */
4643          jcen = ib.ijk[1] ;  /* y-index */
4644 
4645          /** initialize montage steps **/
4646 
4647          if( im3d->vinfo->xhairs_show_montage ){           /* in "Multi" mode */
4648             iskip = im3d->vinfo->xhairs_nskip.ijk[ax] + 1 ;
4649             jskip = im3d->vinfo->xhairs_nskip.ijk[ay] + 1 ;
4650             if( a1 > 0 ){
4651                idown = im3d->vinfo->xhairs_ndown.ijk[ax] ;
4652                iup   = im3d->vinfo->xhairs_nup.ijk[ax] ;
4653             } else {
4654                iup   = im3d->vinfo->xhairs_ndown.ijk[ax] ;
4655                idown = im3d->vinfo->xhairs_nup.ijk[ax] ;
4656             }
4657             if( a2 > 0 ){
4658                jdown = im3d->vinfo->xhairs_ndown.ijk[ay] ;
4659                jup   = im3d->vinfo->xhairs_nup.ijk[ay] ;
4660             } else {
4661                jup   = im3d->vinfo->xhairs_ndown.ijk[ay] ;
4662                jdown = im3d->vinfo->xhairs_nup.ijk[ay] ;
4663             }
4664 
4665          } else {                                          /* in "Single" Mode */
4666            idown = iup = jdown = jup = iskip = jskip = 0 ;
4667            if( grapher != NULL ){ idown=-(iup+1); jdown=-(jup+1); } /* skip lines? */
4668          }
4669 
4670          /* draw vertical lines first */
4671 
4672          if( (im3d->vinfo->xhairs_orimask & (1<<oy)) != 0 ){
4673            for( imon=-idown ; imon <= iup ; imon++ ){
4674              icr = icen + imon * iskip ;
4675 
4676              if( im3d->vinfo->xhairs_periodic ){
4677                 while( icr < 0 )   icr += nx ;
4678                 while( icr >= nx ) icr -= nx ;
4679              } else {
4680                 if( icr < 0 || icr >= nx ) continue ;
4681              }
4682 
4683              gappp = (abs(icr-icen) <= gap) ? gap : -1 ; /* no gap if far from center */
4684 
4685              if( gappp < 0 ){  /* no gap => 1 vertical line */
4686 
4687                 plotline_memplot( PSX(icr) , 0.0 , PSX(icr) , 1.0 ) ;
4688 
4689              } else {          /* gap => 2 vertical lines */
4690 
4691                 jj = jcen-gappp-1 ;
4692                 if( jj >= 0 )
4693                   plotline_memplot( PSX(icr) , 1.0 , PSX(icr) , PSY(jj+0.5) ) ;
4694 
4695                 jj = jcen+gappp+1 ;
4696                 if( jj < ny )
4697                   plotline_memplot( PSX(icr) , PSY(jj-0.5) , PSX(icr) , 0.0 ) ;
4698              }
4699 
4700            }
4701          }
4702 
4703          /* draw horizontal lines */
4704 
4705          if( (im3d->vinfo->xhairs_orimask & (1<<ox)) != 0 ){  /* 31 Dec 1998 */
4706            for( jmon=-jdown ; jmon <= jup ; jmon++ ){
4707              jcr = jcen + jmon * jskip ;
4708              if( im3d->vinfo->xhairs_periodic ){
4709                 while( jcr < 0 )   jcr += ny ;
4710                 while( jcr >= ny ) jcr -= ny ;
4711              } else {
4712                 if( jcr < 0 || jcr >= ny ) continue ;
4713              }
4714 
4715              gappp = (abs(jcr-jcen) <= gap) ? gap : -1 ; /* no gap if far from center */
4716 
4717              if( gappp < 0 ){  /* no gap => 1 horizontal line */
4718 
4719                 plotline_memplot( 0.0 , PSY(jcr) , 1.0 , PSY(jcr) ) ;
4720 
4721              } else {          /* gap => 2 horizontal lines */
4722 
4723                 ii = icen-gappp-1 ;
4724                 if( ii >= 0 )
4725                   plotline_memplot( 0.0 , PSY(jcr) , PSX(ii+0.5) , PSY(jcr) ) ;
4726 
4727                 ii = icen+gappp+1 ;
4728                 if( ii < nx )
4729                   plotline_memplot( PSX(ii-0.5) , PSY(jcr) , 1.0 , PSY(jcr) ) ;
4730              }
4731            }
4732          }
4733 
4734          /* draw grapher frame, if needed */
4735 
4736          if( grapher != NULL ){
4737             int gs = gap , gb = (grapher->mat +2)/2 ;
4738 
4739             jcr = jcen ; icr = icen ;
4740 
4741             ip = icr - gb ; if( ip < 0   ) ip = 0 ;
4742             ii = icr + gs ; if( ii >= nx ) ii = nx-1 ;
4743 
4744             jp = jcr - gb ; if( jp <  0  ) jp = 0 ;
4745             jj = jcr + gs ; if( jj >= ny ) jj = ny-1 ;
4746 
4747             plotline_memplot( PSX(ip+0.5),PSY(jp+0.5) , PSX(ii-0.5),PSY(jp+0.5) ) ;
4748             plotline_memplot( PSX(ii-0.5),PSY(jp+0.5) , PSX(ii-0.5),PSY(jj-0.5) ) ;
4749             plotline_memplot( PSX(ii-0.5),PSY(jj-0.5) , PSX(ip+0.5),PSY(jj-0.5) ) ;
4750             plotline_memplot( PSX(ip+0.5),PSY(jj-0.5) , PSX(ip+0.5),PSY(jp+0.5) ) ;
4751 
4752          } /* end if "if grapher exists" */
4753 
4754       } /* end of "if correct slice" (or do all slices) */
4755      } /* end of crosshairs */
4756 
4757      /*----- return the completed plot -----*/
4758 
4759      if( MEMPLOT_NLINE(mp) < 1 ) DESTROY_MEMPLOT(mp) ;
4760 
4761      RETURN(mp) ; /* will be destroyed in imseq */
4762    }
4763 
4764    /*--- 20 Sep 2001: image label ---*/
4765 
4766    if( type == isqCR_getlabel ){
4767       Three_D_View *im3d = (Three_D_View *) br->parent ;
4768       char *lab , str[2048] , *dd , *eee=NULL;
4769       char labstrf[256]={""}, labstra[256]={""};
4770       THD_ivec3 iv,ivp,ivm ;
4771       THD_fvec3 fv,fvp,fvm ;
4772       float dxyz , cc ;
4773       int ii, ival;
4774       double dval;
4775       THD_3dim_dataset *dset=NULL ;
4776 
4777       if( im3d->type != AFNI_3DDATA_VIEW ) RETURN(NULL) ;
4778 
4779       LOAD_IVEC3(iv,0,0,n) ;
4780       ivp = THD_fdind_to_3dind( br , iv ) ;
4781 
4782       if( n == 0 ) LOAD_IVEC3(iv,0,0,1) ;
4783       else         LOAD_IVEC3(iv,0,0,n-1) ;
4784       ivm = THD_fdind_to_3dind( br , iv ) ;
4785 
4786       if( AFNI_yesenv("AFNI_IMAGE_LABEL_IJK") ){ /* 27 Feb 2017 */
4787 
4788         int nnn ; char *fmt ;
4789         nnn = MAX(br->n1,br->n2) ; nnn = MAX(nnn,br->n3) ;
4790         fmt =  (nnn < 10)  ? "#%1d"
4791              : (nnn < 100) ? "#%02d"
4792              : (nnn < 1000)? "#%03d"
4793              :               "#%04d" ;
4794 
4795         if( ivm.ijk[0] != ivp.ijk[0] ){
4796           sprintf(str,fmt,ivp.ijk[0]) ;
4797 
4798         } else if( ivm.ijk[1] != ivp.ijk[1] ){
4799           sprintf(str,fmt,ivp.ijk[1]) ;
4800 
4801         } else if( ivm.ijk[2] != ivp.ijk[2] ){
4802           sprintf(str,fmt,ivp.ijk[2]) ;
4803 
4804         } else {  /* should never happen */
4805           RETURN(NULL) ;
4806         }
4807 
4808       } else {
4809         fvp = THD_3dind_to_3dmm ( br->dset , ivp ) ;
4810         fvp = THD_3dmm_to_dicomm( br->dset , fvp ) ;
4811 
4812         fvm = THD_3dind_to_3dmm ( br->dset , ivm ) ;
4813         fvm = THD_3dmm_to_dicomm( br->dset , fvm ) ;
4814 
4815         dxyz = MIN(br->del1,br->del2) ;
4816         dxyz = MIN(dxyz    ,br->del3) ; dxyz *= 0.1 ;
4817 
4818         if( fabs(fvm.xyz[0]-fvp.xyz[0]) > dxyz ){ /* +=R -=L */
4819            cc = fvp.xyz[0] ;
4820            dd = ( cc >= 0.0 ) ? "L" : "R" ;
4821         } else if( fabs(fvm.xyz[1]-fvp.xyz[1]) > dxyz ){ /* +=P -=A */
4822            cc = fvp.xyz[1] ;
4823            dd = ( cc >= 0.0 ) ? "P" : "A" ;
4824         } else if( fabs(fvm.xyz[2]-fvp.xyz[2]) > dxyz ){ /* +=S -=I */
4825            cc = fvp.xyz[2] ;
4826            dd = ( cc >= 0.0 ) ? "S" : "I" ;
4827         } else {
4828           RETURN(NULL) ;   /* should never happen */
4829         }
4830 
4831         sprintf(str,"%3.2f",fabs(cc)) ;
4832         for( ii=strlen(str)-1 ; ii > 0 && str[ii] == '0' ; ii-- ) str[ii] = '\0' ;
4833         if( str[ii] == '.' ) str[ii] = '\0' ;
4834         strcat(str, dd) ;
4835       }
4836 
4837       if (!FD_brick_montized(br)){ /* Show labels if any.  ZSS Dec. 2011*/
4838          dset = Get_UO_Dset(br, 'U', 1, &ival);
4839          if ((dval = (double)THD_get_voxel_dicom(dset,
4840                               im3d->vinfo->xi,
4841                               im3d->vinfo->yj,
4842                               im3d->vinfo->zk, ival))>0.0) {
4843             AFNI_get_dset_val_label_maybeCR(dset,    /* Dec 7 2011 ZSS/DRG 2021 */
4844                                     dval, labstra);
4845          }
4846          dset = Get_UO_Dset(br, 'O', 1, &ival);
4847          if ((dval = (double)THD_get_voxel_dicom(dset,
4848                               im3d->vinfo->xi,
4849                               im3d->vinfo->yj,
4850                               im3d->vinfo->zk, ival))>0.0) {
4851             AFNI_get_dset_val_label_maybeCR(dset,    /* Dec 7 2011 ZSS/DRG 2021 */
4852                                     dval, labstrf);
4853 
4854          }
4855 
4856          if (labstrf[0] != '\0' || labstra[0] != '\0') {
4857             strcat(str, " \\noesc ");
4858             if (!strcmp(labstrf, labstra)) {
4859                strcat(str, "U+O:");
4860                strncat(str, labstra, 126*sizeof(char));
4861             } else {
4862                if (labstra[0] != '\0') {
4863                   strcat(str, "U:");
4864                   strncat(str, labstra, 126*sizeof(char));
4865                }
4866                if (labstrf[0] != '\0') {
4867                   strcat(str, labstra[0] != '\0' ? " O:" : "O:");
4868                   strncat(str, labstrf, 126*sizeof(char));
4869                }
4870             }
4871          }
4872       }
4873 
4874       lab = strdup(str) ;
4875 
4876       RETURN(lab) ;
4877    }
4878 
4879    /*--- underlay image # n ---*/
4880    if( type == isqCR_getimage  || type == isqCR_getqimage ||
4881        type == isqCR_getulayim || type == isqCR_getolayim   ){
4882 
4883       Three_D_View *im3d = (Three_D_View *)br->parent ;
4884       FD_brick *brr=NULL ;
4885       int ival;
4886 
4887       if (!(brr = Get_FD_Brick_As_Selected(br, type, &ival))) RETURN(NULL);
4888 
4889 #if 0
4890 INFO_message("%s: brr=%p  ival=%d",
4891               (type == isqCR_getimage ) ? "isqCR_getimage"
4892             : (type == isqCR_getqimage) ? "isqCR_getqimage"
4893             : (type == isqCR_getulayim) ? "isqCR_getulayim"
4894             : (type == isqCR_getolayim) ? "isqCR_getolayim" : "unknown" , brr , ival ) ;
4895 #endif
4896 
4897 if(PRINT_TRACING)
4898 { char str[256] ;
4899   sprintf(str,"getting image n1=%d n2=%d ival=%d",br->n1,br->n2,ival) ;
4900   STATUS(str) ; }
4901 
4902       LOAD_DSET_VIEWS(im3d) ;  /* 02 Nov 1996 */
4903 
4904       AFNI_set_ignore_vedit(1) ; /* 28 Jan 2008 */
4905       im = FD_warp_to_mri( n , ival , brr ) ; /* get image from dataset */
4906       AFNI_set_ignore_vedit(0) ;
4907 
4908       if( ival < 0 ) RETURN( (XtPointer) im ) ;  /* return fake image */
4909 
4910       /* Load value of current pixel into display label */
4911       /* April 1996: only if image is at current slice  */
4912 
4913       if( brr == br ){
4914         char buf[64] = "\0" ; int ibest=-1 ;
4915         AFNI_set_valabel( br , n , im , buf ) ;
4916         if( buf[0] != '\0' ){
4917           if( im3d->vinfo->underlay_type == UNDERLAY_ANAT )
4918             strcpy( im3d->vinfo->anat_val , buf ) ;
4919           else
4920             im3d->vinfo->anat_val[0] = '\0' ;
4921 
4922           if( !AFNI_noenv("AFNI_VALUE_LABEL") ) AFNI_do_bkgd_lab( im3d ) ;
4923 
4924           if( im->kind != MRI_complex && im->kind != MRI_rgb ){
4925             char qbuf[64] = "bg =" ;
4926             strcat(qbuf,buf) ; strcpy(buf,qbuf) ;
4927           }
4928           AFNI_get_xhair_node( im3d , NULL , &ibest ) ;   /* 21 Feb 2003 */
4929           if( ibest >= 0 ){
4930             char qbuf[64]; sprintf(qbuf,"\nxh = #%d",ibest); strcat(buf,qbuf);
4931           }
4932           MCW_set_widget_label( im3d->vwid->imag->pop_bkgd_lab , buf ) ;
4933           XtManageChild( im3d->vwid->imag->pop_bkgd_lab ) ;
4934         }
4935       }
4936 
4937       RETURN( (XtPointer) im ) ;
4938    }
4939 
4940 STATUS("get something else, but I don't care!") ;
4941 
4942    RETURN( NULL ) ;
4943 }
4944 
4945 /*-----------------------------------------------------------------------------*/
4946 
4947 #undef   PFVAL
4948 #if 1
4949 # define PFVAL(vv,bb) strcpy((bb),AV_uformat_fval(vv))
4950 #else
4951 # define PFVAL(vv,bb) AV_fval_to_char((vv),(bb))
4952 #endif
4953 
4954 /*-----------------------------------------------------------------------------*/
4955 /*! Set a value label when the nsl-th image is in "im".
4956 *//*---------------------------------------------------------------------------*/
4957 
AFNI_set_valabel(FD_brick * br,int nsl,MRI_IMAGE * im,char * blab)4958 void AFNI_set_valabel( FD_brick *br , int nsl , MRI_IMAGE *im , char *blab )
4959 {
4960    Three_D_View *im3d = (Three_D_View *) br->parent ;
4961    THD_ivec3 ib ;
4962 
4963 ENTRY("AFNI_set_valabel") ;
4964 
4965    if( ! IM3D_VALID(im3d) || ! im3d->vwid->imag->do_bkgd_lab ||
4966        im == NULL         || blab == NULL                      ) EXRETURN ;
4967 
4968    /* convert current voxel index location to FD_brick indexes */
4969 
4970    ib = THD_3dind_to_fdind( br , TEMP_IVEC3( im3d->vinfo->i1 ,
4971                                              im3d->vinfo->j2 ,
4972                                              im3d->vinfo->k3  ) ) ;
4973 
4974    /* if the input image slice index (nsl) doesn't match the current
4975       location of the crosshairs, then we don't care about this image */
4976 
4977    if( nsl != ib.ijk[2] ) EXRETURN ;
4978 
4979    /* otherwise, extract a value from the image and put into blab */
4980 
4981    switch( im->kind ){
4982       default: strcpy(blab,":(") ;
4983 
4984       case MRI_byte:{
4985          int val = MRI_BYTE_2D(im , ib.ijk[0],ib.ijk[1]) ;
4986          sprintf( blab , "%d" , val ) ;
4987       }
4988       break ;
4989 
4990       case MRI_short:{
4991          int val = MRI_SHORT_2D(im , ib.ijk[0],ib.ijk[1]) ;
4992          sprintf( blab , "%d" , val ) ;
4993       }
4994       break ;
4995 
4996       case MRI_int:{
4997          int val = MRI_INT_2D(im , ib.ijk[0],ib.ijk[1]) ;
4998          sprintf( blab , "%d" , val ) ;
4999       }
5000       break ;
5001 
5002       case MRI_float:{
5003          float val = MRI_FLOAT_2D(im , ib.ijk[0],ib.ijk[1]) ;
5004          PFVAL(val,blab) ;
5005       }
5006       break ;
5007 
5008       case MRI_complex:{
5009          int iblab ; char qbuf[16] ; complex val ;
5010          val = MRI_COMPLEX_2D(im , ib.ijk[0],ib.ijk[1]) ;
5011          PFVAL(val.r,blab) ; iblab = strlen(blab) ;
5012          if( val.i >= 0.0 ) blab[iblab++] = '+' ;
5013          PFVAL(val.i,blab+iblab) ; iblab = strlen(blab) ;
5014          blab[iblab++] = 'I' ; blab[iblab++] = '\0' ;
5015       }
5016       break ;
5017 
5018       case MRI_rgb:{
5019          byte *rgb = MRI_RGB_PTR(im) ;
5020          int ii = ib.ijk[0] + im->nx * ib.ijk[1] ;
5021          sprintf(blab,"(%d,%d,%d)",(int)rgb[3*ii],(int)rgb[3*ii+1],(int)rgb[3*ii+2]) ;
5022       }
5023       break ;
5024    }
5025    EXRETURN ;
5026 }
5027 
5028 /*----------------------------------------------------------------------
5029    read image files directly into a 3D dataset.
5030    this will be incomplete, but is enough for display purposes.
5031 ------------------------------------------------------------------------*/
5032 
AFNI_read_images(int nf,char * fname[])5033 THD_3dim_dataset * AFNI_read_images( int nf , char *fname[] )
5034 {
5035    MRI_IMAGE *im , *shim ;
5036    char *bar ;
5037    int nx , ny , nz , lf , kz , kim , npix,ii ;
5038    MRI_IMARR *arr ;
5039    char str[256] ;
5040    THD_3dim_dataset *dset ;
5041    int datum = GLOBAL_argopt.datum , dsize ;
5042 
5043    int nvals , nzz , nzin=0 ;  /* 19 Oct 1999 */
5044    float dx=0.0, dy=0.0 , dz=0.0 ;  /* 29 Jul 2002 */
5045 
5046 ENTRY("AFNI_read_images") ;
5047 
5048    /*----- see if there are any images to read! -----*/
5049 
5050    if( nf < 1 ) ERROR_exit("No images on command line!?") ;
5051 
5052    /* count total number of images */
5053 
5054    nz = 0 ;
5055    for( lf=0 ; lf < nf ; lf++ ){
5056      if( THD_is_directory(fname[lf]) ){  /* 21 Feb 2007 */
5057        fprintf(stderr,
5058                "\n** Fatal Error: %s is a directory, not an image file!",
5059                fname[lf]) ;
5060        exit(1) ;
5061      }
5062      ii = mri_imcount( fname[lf] ) ;
5063      if( ii == 0 )
5064        ERROR_exit("Illegal image file specifier: %s",fname[lf]) ;
5065      nz += ii ;
5066    }
5067    if( nz == 1 ) nz = 2 ;  /* special case for just one image */
5068 
5069    /*--- read 1st file to get sizes ---*/
5070 
5071 STATUS("read first file") ;
5072    arr = mri_read_file( fname[0] ) ;
5073    if( arr == NULL || arr->num == 0 )
5074      ERROR_exit("Cannot read first image file: %s",fname[0]) ;
5075 
5076    im = arr->imarr[0] ;
5077    nx = im->nx ;
5078    ny = im->ny ; npix = nx * ny ;
5079 
5080    if( im->dw > 0.0 ){
5081      dx = fabs(im->dx); dy = fabs(im->dy); dz = fabs(im->dz);  /* 29 Jul 2002 */
5082    }
5083 
5084    if( datum < 0 ) datum = im->kind ;
5085    if( ! AFNI_GOOD_DTYPE(datum) )
5086      ERROR_exit("Illegal datum type found in image") ;
5087 
5088    dsize = mri_datum_size( (MRI_TYPE) datum ) ;
5089    bar   = (char *) malloc( dsize * nx*ny*nz ) ;
5090    if( bar == NULL )
5091      ERROR_exit("Can't malloc memory for image input :-( !!!") ;
5092 
5093    /*--- read all files, convert if needed, put in the cube ---*/
5094 
5095    REPORT_PROGRESS("\nReading unoriented image data") ;
5096    kz = 0 ;
5097    for( lf=0 ; lf < nf ; lf++ ){
5098 
5099       /** read the file (except the first, which we already have **/
5100 
5101       if( lf != 0 ){
5102 STATUS("read next file") ;
5103          arr = mri_read_file( fname[lf] ) ;
5104          if( arr == NULL || arr->num == 0 )
5105            ERROR_exit("Cannot read image file: %s",fname[lf]) ;
5106       }
5107 
5108       /** for each image in file ... **/
5109 
5110       for( kim=0 ; kim < arr->num ; kim++ ){
5111          im = arr->imarr[kim] ;
5112 
5113          /** check if image matches dimensions of first slice **/
5114 
5115          if( im->nx != nx || im->ny != ny ){
5116             if( ! GLOBAL_argopt.resize_images ){
5117                sprintf(str, "Image size mismatch:\n"
5118                            " ** expected nx=%d ny=%d but got nx=%d ny=%d in file %s" ,
5119                            nx,ny,im->nx,im->ny , fname[lf] ) ;
5120                ERROR_exit(str) ;
5121             } else {
5122                MRI_IMAGE *rim ;
5123                rim = mri_resize( im , nx , ny ) ;
5124                mri_free( im ) ;
5125                im = rim ;
5126             }
5127          }
5128 
5129          /** check if image data type matches the kind we want **/
5130 
5131          if( im->kind == datum ){
5132             shim = im ;
5133          } else {
5134             shim = mri_to_mri( datum , im ) ;
5135             if( shim == NULL ) ERROR_exit("Illegal datum convert!") ;
5136             mri_free( im ) ;
5137          }
5138 
5139          /** copy bytes from slice into the "bar" brick **/
5140 
5141          memcpy( bar + dsize*npix*kz , mri_data_pointer(shim) , dsize*npix ) ;
5142          kz++ ;
5143 
5144          mri_free(shim) ;
5145          if( kz%100 == 1 ) REPORT_PROGRESS(".") ;
5146       }
5147       FREE_IMARR(arr) ;  /* not DESTROY_IMARR, since images are already gone */
5148    }
5149 
5150    /*** special case of one input image: duplicate the image data ***/
5151 
5152    if( kz == 1 && nz == 2 ){
5153      memcpy( bar + dsize*npix , bar , dsize*npix ) ;
5154    }
5155 
5156    /*** tell the user what all we've read ***/
5157 
5158    sprintf(str,": nx=%d ny=%d nslice=%d (%s)",nx,ny,nz,MRI_TYPE_name[datum]) ;
5159    REPORT_PROGRESS(str) ;
5160 
5161    /*- 19 Oct 1999: if we are doing a -tim read,
5162                     then have to setup the time and z dimensions -*/
5163 
5164    if( GLOBAL_argopt.read_tim != 0 ){
5165 
5166       if( GLOBAL_argopt.read_tim > 0 ){          /* 20 Oct 1999 */
5167          nzin  = nzz = GLOBAL_argopt.read_tim ;  /* -zim:nzz */
5168          nvals = nz / nzz ;
5169 
5170          if( nvals*nzz != nz )
5171             fprintf(stderr,
5172                     "\n** Warning: -zim:%d does not evenly divide"
5173                     "number of 2D slices read=%d\n",
5174                     nzz , nz ) ;
5175 
5176       } else {
5177          nvals = - GLOBAL_argopt.read_tim ;      /* -tim:nvals */
5178          nzin  = nzz = nz / nvals ;
5179 
5180          if( nvals*nzz != nz )
5181             fprintf(stderr,
5182                     "\n** Warning: -tim:%d does not evenly divide"
5183                     "number of 2D slices read=%d\n",
5184                     nvals , nz ) ;
5185       }
5186 
5187       if( nvals == 1 ){
5188          fprintf(stderr,
5189                  "\n** Error: -tim or -zim has only 1 point in time!\n") ;
5190          exit(1) ;
5191       }
5192 
5193       if( nzz == 1 ) nzz = 2 ;  /* can't have just 1 slice */
5194 
5195    } else {   /* the old code */
5196       nvals = 1 ;
5197       nzz   = nz ;
5198    }
5199 
5200    /*--- now create the rest of the data structure, as far as we can ---*/
5201 
5202    dset                = myXtNew( THD_3dim_dataset ) ;
5203    dset->dblk          = myXtNew( THD_datablock ) ;
5204    dset->daxes         = myXtNew( THD_dataxes ) ;
5205    dset->dblk->diskptr = myXtNew( THD_diskptr ) ;
5206    dset->markers       = NULL ;
5207    dset->warp          = NULL ;
5208    dset->vox_warp      = NULL ;
5209    dset->self_warp     = NULL ;  /* 26 Aug 2002 */
5210    dset->warp_parent   = NULL ;
5211    dset->anat_parent   = NULL ;
5212    dset->stats         = NULL ;
5213    dset->death_mark    = 0 ;
5214    dset->tcat_list     = NULL ;  /* 04 Aug 2004 */
5215    dset->tcat_num      = 0 ;
5216    dset->tcat_len      = NULL ;
5217    dset->taxis         = NULL ;
5218    dset->tagset        = NULL ;  /* Oct 1998 */
5219    dset->Label_Dtable  = NULL;    /* ZSS Feb 26 2010 */
5220    ZERO_STAT_AUX( dset ) ;
5221 #ifdef ALLOW_DATASET_VLIST
5222    dset->pts           = NULL ;
5223 #endif
5224 
5225    INIT_KILL(dset->kl) ;
5226    INIT_KILL(dset->dblk->kl) ;
5227 
5228    dset->dblk->diskptr->type         = DISKPTR_TYPE ;
5229    dset->dblk->diskptr->rank         = 3 ;
5230    dset->dblk->diskptr->nvals        = nvals ;  /* modified 19 Oct 1999 */
5231    dset->dblk->diskptr->dimsizes[0]  = nx ;
5232    dset->dblk->diskptr->dimsizes[1]  = ny ;
5233    dset->dblk->diskptr->dimsizes[2]  = nzz ;    /* modified 19 Oct 1999 */
5234    dset->dblk->diskptr->storage_mode = STORAGE_UNDEFINED ;
5235    dset->dblk->diskptr->byte_order   = THD_get_write_order() ;  /* 25 April 1998 */
5236 
5237    dset->dblk->vedim = NULL ;  /* 05 Sep 2006 */
5238 
5239    EMPTY_STRING(dset->dblk->diskptr->prefix) ;
5240    EMPTY_STRING(dset->dblk->diskptr->viewcode) ;
5241    EMPTY_STRING(dset->dblk->diskptr->filecode) ;
5242    EMPTY_STRING(dset->dblk->diskptr->directory_name) ;
5243    EMPTY_STRING(dset->dblk->diskptr->header_name) ;
5244    EMPTY_STRING(dset->dblk->diskptr->brick_name) ;
5245 
5246    dset->dblk->type        = DATABLOCK_TYPE ;
5247    dset->dblk->nvals       = nvals ;            /* modified 19 Oct 1999 */
5248 
5249    /** here is where we attach "bar" to the dataset **/
5250 
5251    dset->dblk->malloc_type  = DATABLOCK_MEM_MALLOC ;
5252    dset->dblk->brick_fac    = NULL ; /* let THD_init_datablock_brick do these */
5253    dset->dblk->brick_bytes  = NULL ;
5254    dset->dblk->brick        = NULL ;
5255 
5256    DSET_lock(dset) ;  /* Feb 1998: lock into memory */
5257 
5258    dset->dblk->brick_lab      = NULL ; /* 30 Nov 1997 */
5259    dset->dblk->brick_keywords = NULL ;
5260    dset->dblk->brick_statcode = NULL ;
5261    dset->dblk->brick_stataux  = NULL ;
5262    dset->keywords             = NULL ;
5263 
5264    THD_init_datablock_brick( dset->dblk , datum , NULL ) ;
5265 
5266    if( nvals == 1 ){
5267 
5268       mri_fix_data_pointer( bar , DSET_BRICK(dset,0) ) ;  /* the attachment! */
5269 
5270    } else {   /* 19 Oct 1999: make up a lot of bricks and attach them all */
5271               /* 20 Oct 1999: allow for the 3rd dimension as well         */
5272 
5273       int iv , jj , kk ;
5274       char *qbar ;
5275 
5276       for( iv=0 ; iv < nvals ; iv++ ){
5277          qbar = (char *) malloc( dsize*npix*nzz ) ;  /* space for nzz slices */
5278 
5279          if( GLOBAL_argopt.read_tim > 0 ){
5280             for( jj=0 ; jj < nzz ; jj++ ){              /* copy slices */
5281                kk = MIN(jj,nzin-1) ;
5282                memcpy( qbar + jj*dsize*npix ,
5283                        bar + (iv*nzin+kk)*dsize*npix , dsize*npix ) ;
5284             }
5285          } else {
5286             for( jj=0 ; jj < nzz ; jj++ ){              /* copy slices */
5287                kk = MIN(jj,nzin-1) ;
5288                memcpy( qbar + jj*dsize*npix ,
5289                        bar + (kk*nvals+iv)*dsize*npix , dsize*npix ) ;
5290             }
5291          }
5292 
5293          mri_fix_data_pointer( qbar , DSET_BRICK(dset,iv) ) ;
5294       }
5295 
5296       free(bar) ;  /* not needed no more no how */
5297 
5298       EDIT_dset_items( dset , ADN_ntt,nvals , ADN_ttdel,1.0 , ADN_none ) ;
5299    }
5300 
5301    dset->dblk->natr   = dset->dblk->natr_alloc = 0 ;
5302    dset->dblk->atr    = NULL ;
5303    dset->dblk->parent = (XtPointer) dset ;
5304 
5305    dset->daxes->type  = DATAXES_TYPE ;
5306    dset->daxes->nxx   = nx ;
5307    dset->daxes->nyy   = ny ;
5308    dset->daxes->nzz   = nzz ;        /* modified 19 Oct 1999 */
5309    dset->daxes->xxdel = 1.0 ;        /* arbitary units */
5310    dset->daxes->yydel = GLOBAL_argopt.dy ;  /* these allow user to alter */
5311    dset->daxes->zzdel = GLOBAL_argopt.dz ;  /* the images' aspect ratio */
5312    dset->daxes->xxorg = dset->daxes->yyorg = dset->daxes->zzorg = 0.0 ;
5313    dset->daxes->parent= (XtPointer) dset ;
5314 
5315    if( dx > 0.0 ) dset->daxes->xxdel = dx ;  /* 29 Jul 2002 */
5316    if( dy > 0.0 ) dset->daxes->yydel = dy ;
5317    if( dz > 0.0 ) dset->daxes->zzdel = dz ;
5318 
5319    dset->idcode = MCW_new_idcode() ;
5320    ZERO_IDCODE(dset->anat_parent_idcode) ;
5321    ZERO_IDCODE(dset->warp_parent_idcode) ;
5322 
5323    /* set the daxes orientation codes from the command line argument */
5324 
5325 #define ORCODE(aa) \
5326   ( (aa)=='R' ? ORI_R2L_TYPE : (aa)=='L' ? ORI_L2R_TYPE : \
5327     (aa)=='P' ? ORI_P2A_TYPE : (aa)=='A' ? ORI_A2P_TYPE : \
5328     (aa)=='I' ? ORI_I2S_TYPE : (aa)=='S' ? ORI_S2I_TYPE : ILLEGAL_TYPE )
5329 
5330 #define OR3OK(x,y,z) ( ((x)&6) + ((y)&6) + ((z)&6) == 6 )
5331 
5332    { char acod ;
5333      int xx,yy,zz ;
5334 
5335      acod = toupper(GLOBAL_argopt.orient_code[0]) ; xx = ORCODE(acod) ;
5336      acod = toupper(GLOBAL_argopt.orient_code[1]) ; yy = ORCODE(acod) ;
5337      acod = toupper(GLOBAL_argopt.orient_code[2]) ; zz = ORCODE(acod) ;
5338 
5339      if( xx < 0 || yy < 0 || zz < 0 || ! OR3OK(xx,yy,zz) )
5340        ERROR_exit("Unusable -orient code!") ;
5341 
5342      dset->daxes->xxorient = xx ;
5343      dset->daxes->yyorient = yy ;
5344      dset->daxes->zzorient = zz ;
5345    }
5346 
5347    if( !ISVALID_MAT44(dset->daxes->ijk_to_dicom) )  /* 15 Dec 2005 */
5348      THD_daxes_to_mat44( dset->daxes ) ;
5349 
5350    dset->wod_flag  = False ;  /* no warp-on-demand */
5351    dset->wod_daxes = NULL ;   /* 02 Nov 1996 */
5352 
5353    dset->type      = GEN_ANAT_TYPE ;
5354    dset->view_type = dset->func_type = 0 ;
5355 
5356    MCW_strncpy(  dset->self_name , fname[0]             , THD_MAX_NAME  ) ;
5357    MCW_strncpy(  dset->label1    , "Image Display Mode" , THD_MAX_LABEL ) ;
5358    EMPTY_STRING( dset->label2 ) ;
5359    EMPTY_STRING( dset->warp_parent_name ) ;
5360    EMPTY_STRING( dset->anat_parent_name ) ;
5361 
5362    RETURN( dset ) ;
5363 }
5364 
5365 /*----------------------------------------------------------------------*/
5366 /* Jumpto current cluster peak */
5367 
AFNI_jumpto_clus(Three_D_View * im3d)5368 void AFNI_jumpto_clus( Three_D_View *im3d )  /* 19 Oct 2012 */
5369 {
5370   int ic ; float px,py,pz , xx,yy,zz ;
5371   AFNI_clu_widgets *cwid = im3d->vwid->func->cwid ;
5372   mri_cluster_detail *cld = im3d->vwid->func->clu_det ;
5373   if( cwid == NULL || cld == NULL ) return ;
5374   ic = AFNI_clus_find_xyz_nearest( im3d,
5375                            im3d->vinfo->xi, im3d->vinfo->yj, im3d->vinfo->zk ) ;
5376   if( ic < 0 ) return ;
5377   AFNI_clus_action_CB( cwid->clu_jump_pb[ic] , (XtPointer)im3d , (XtPointer)666 ) ;
5378   return ;
5379 }
5380 
5381 /*----------------------------------------------------------------------*/
5382 /* Jumpto nearby cluster peak */
5383 
AFNI_jumpto_clus_nearby(Three_D_View * im3d,int dci)5384 void AFNI_jumpto_clus_nearby( Three_D_View *im3d , int dci ) /* 29 Apr 2019 */
5385 {
5386   int ic,nic,nclu ; float px,py,pz , xx,yy,zz ;
5387   AFNI_clu_widgets *cwid = im3d->vwid->func->cwid ;
5388   mri_cluster_detail *cld = im3d->vwid->func->clu_det ;
5389   MCW_cluster_array *clar ; MCW_cluster *cl ;
5390 
5391   if( cwid == NULL || cld == NULL ) return ;
5392   clar = im3d->vwid->func->clu_list ; if( clar == NULL ) return ;
5393   nclu = clar->num_clu ;              if( nclu == 0    ) return ;
5394   ic = AFNI_clus_find_xyz( im3d,
5395                            im3d->vinfo->xi, im3d->vinfo->yj, im3d->vinfo->zk ) ;
5396   if( ic >= 0 ){
5397     nic = ic + dci ;
5398     if( nic >= nclu  ) nic = nic % nclu ;
5399     else if( nic < 0 ) nic = (nic + 99*nclu) % nclu ;
5400   } else {
5401     nic = AFNI_clus_find_xyz_nearest( im3d,
5402                            im3d->vinfo->xi, im3d->vinfo->yj, im3d->vinfo->zk ) ;
5403   }
5404   if( nic < 0 ) return ;
5405   AFNI_clus_action_CB( cwid->clu_jump_pb[nic], (XtPointer)im3d, (XtPointer)666 ) ;
5406   return ;
5407 }
5408 
5409 /*----------------------------------------------------------------------
5410    respond to events that one of the MCW_imseq's sends to us
5411 ------------------------------------------------------------------------*/
5412 
AFNI_seq_send_CB(MCW_imseq * seq,FD_brick * br,ISQ_cbs * cbs)5413 void AFNI_seq_send_CB( MCW_imseq *seq , FD_brick *br , ISQ_cbs *cbs )
5414 {
5415    Three_D_View *im3d = (Three_D_View *) seq->parent ;
5416 
5417 ENTRY("AFNI_seq_send_CB") ;
5418 
5419 if(PRINT_TRACING)
5420 { char str[256] ; sprintf(str,"reason=%d",cbs->reason) ; STATUS(str) ; }
5421 
5422    if( ! IM3D_VALID(im3d) ||
5423        (   im3d->ignore_seq_callbacks == AFNI_IGNORE_EVERYTHING
5424         && cbs->reason                != isqCR_getxynim        ) ){
5425 
5426      STATUS("ignoring call") ; EXRETURN ;
5427    }
5428 
5429    switch( cbs->reason ){
5430 
5431       default: break ;
5432 
5433       case isqCR_destroy:{
5434          MCW_imseq *sxyz = im3d->s123 ,
5435                    *syzx = im3d->s231 ,
5436                    *szxy = im3d->s312  ;
5437          Widget w ;
5438          int a3 = br->a123.ijk[2] ,   /* z axis of the brick?    */
5439              az = abs(a3) - 1       ; /* 0,1,2 for dataset x,y,z */
5440 
5441               if( seq == sxyz ){
5442                  w = im3d->vwid->imag->image_xyz_pb ; im3d->s123 = NULL ; }
5443          else if( seq == syzx ){
5444                  w = im3d->vwid->imag->image_yzx_pb ; im3d->s231 = NULL ; }
5445          else if( seq == szxy ){
5446                  w = im3d->vwid->imag->image_zxy_pb ; im3d->s312 = NULL ; }
5447          else
5448                  EXRETURN ;  /* something goofy happened? */
5449 
5450          myXtFree( seq->status ) ; /* 28 Sep 1998: via Purify */
5451          myXtFree( seq ) ;
5452          MCW_invert_widget(w) ;  /* back to normal */
5453          NORMAL_cursorize(w) ;   /* 20 Jul 2005 */
5454          INIT_BKGD_LAB(im3d) ;
5455          AFNI_view_setter(im3d,NULL) ;
5456 
5457          /* July 1996: redraw if we just lost a crosshair montage
5458             (it would have been in the z direction of the brick) */
5459 
5460          if( im3d->vinfo->xhairs_ndown.ijk[az] > 0 ||
5461              im3d->vinfo->xhairs_nup.ijk[az]   > 0   ){
5462 
5463 if(PRINT_TRACING)
5464 { char str[256] ;
5465   sprintf(str,"imseq close on axis %d --> lost xhairs in that direction",az) ;
5466   STATUS(str) ; }
5467 
5468             CLEAR_MONTAGE(im3d,br) ;
5469 
5470             if( im3d->vinfo->xhairs_show_montage &&
5471                 im3d->ignore_seq_callbacks == AFNI_IGNORE_NOTHING ){
5472 
5473                AFNI_set_viewpoint( im3d , -1,-1,-1 , REDISPLAY_OVERLAY ) ;
5474             }
5475          }
5476       }
5477       MPROBE ;
5478       break ;  /* end of destroy */
5479 
5480       case isqCR_buttonmove:{  /* 17 Mar 2010: InstaCorr on the go go go! */
5481         XMotionEvent *xev = (XMotionEvent *)cbs->event ;
5482 
5483         if( im3d->ignore_seq_callbacks != AFNI_IGNORE_NOTHING    ) EXRETURN ;
5484         if( !(xev->state&ShiftMask) || !(xev->state&ControlMask) ) EXRETURN ;
5485 
5486         if( cbs->xim >= 0 && cbs->xim < br->n1 &&
5487             cbs->yim >= 0 && cbs->yim < br->n2 &&
5488             cbs->nim >= 0 && cbs->nim < br->n3   ){  /* inside brick? */
5489 
5490           THD_ivec3 id ; int qq , ii,jj,kk ;
5491 
5492           /* find location in underlay dataset */
5493 
5494           id = THD_fdind_to_3dind(br,TEMP_IVEC3(cbs->xim,cbs->yim,cbs->nim));
5495           UNLOAD_IVEC3(id,ii,jj,kk) ;
5496 
5497           qq = AFNI_icor_setref_anatijk(im3d,ii,jj,kk) ;
5498           if( qq > 0 && im3d->giset == NULL ) AFNI_icor_setref_locked(im3d) ;
5499         }
5500       }
5501       MPROBE ;
5502       break ;  /* end of button move (while clicked down) */
5503 
5504       case isqCR_buttonpress:{
5505          XButtonEvent *xev = (XButtonEvent *)cbs->event ;
5506          int doing_icor = ( (xev->state&ShiftMask) && (xev->state&ControlMask) ) ;
5507          int doing_jump = AFNI_yesenv("AFNI_INSTACORR_JUMP") ;
5508 
5509 if(PRINT_TRACING){
5510  char str[256] ;
5511  sprintf(str,"isqCR_buttonpress: button=%d state=%x",(int)xev->button,xev->state) ;
5512  STATUS(str) ; }
5513 
5514          im3d->vwid->butx = xev->x_root ;  /* 17 May 2005 */
5515          im3d->vwid->buty = xev->y_root ;
5516          switch( xev->button ){
5517 
5518             default: EXRETURN ;  /* unused button */
5519 
5520             case Button3:{  /* popup menu */
5521                XtVaSetValues( im3d->vwid->imag->popmenu ,
5522                                  XmNuserData , (XtPointer) seq ,   /* who */
5523                               NULL ) ;
5524                XmMenuPosition( im3d->vwid->imag->popmenu , xev ) ; /* where */
5525                XtManageChild ( im3d->vwid->imag->popmenu ) ;       /* pop */
5526             }
5527             break ;
5528 
5529             case Button1:{   /* set viewpoint? set InstaCorr? */
5530                THD_ivec3 id ;
5531 
5532                /* April 1996:  only use this button press if
5533                                it is inside the confines of the brick */
5534 
5535 if(PRINT_TRACING)
5536 { char str[256] ;
5537   sprintf(str,"Button1 at %d %d %d",
5538           cbs->xim,cbs->yim,cbs->nim) ; STATUS(str) ; }
5539 
5540                if( cbs->xim >= 0 && cbs->xim < br->n1 &&
5541                    cbs->yim >= 0 && cbs->yim < br->n2 &&
5542                    cbs->nim >= 0 && cbs->nim < br->n3   ){
5543 
5544                   /* get index triple in 3D dataset from viewing FD brick */
5545 
5546                   id = THD_fdind_to_3dind(
5547                           br , TEMP_IVEC3(cbs->xim,cbs->yim,cbs->nim) );
5548 
5549 if(PRINT_TRACING)
5550 { char str[256] ;
5551   sprintf(str," 3D dataset coordinates %d %d %d",
5552           id.ijk[0],id.ijk[1],id.ijk[2] ) ; STATUS(str) ; }
5553 
5554                   /* jump viewpoint (crosshairs) to the selected point */
5555 
5556                   if( !doing_icor || (doing_icor && doing_jump) ){
5557                     SAVE_VPT(im3d) ;  /* save current location as jumpback */
5558 
5559                     if( im3d->ignore_seq_callbacks == AFNI_IGNORE_NOTHING ){
5560 
5561                       /* 20 Feb 2003: set plane from which viewpoint is controlled */
5562 
5563                       AFNI_view_setter(im3d,seq) ;
5564                       AFNI_set_viewpoint(
5565                          im3d , id.ijk[0] , id.ijk[1] , id.ijk[2] ,
5566                          (im3d->vinfo->crosshair_visible==True) ?
5567                          REDISPLAY_OVERLAY : REDISPLAY_OPTIONAL ) ;
5568                     }
5569                   }
5570 
5571                   /* 08 May 2009: if Shift+Control both pressed, do InstaCorr */
5572 
5573                   if( doing_icor ){
5574                     int qq = AFNI_icor_setref_anatijk(im3d,id.ijk[0],id.ijk[1],id.ijk[2]) ;
5575                     if( qq > 0 && im3d->giset == NULL ) AFNI_icor_setref_locked(im3d) ; /* 15 May 2009 */
5576                   }
5577                }
5578             } /* end of button 1 */
5579             break ;
5580          } /* end of switch on which button */
5581       }
5582       break ;  /* end of button press */
5583 
5584       case isqCR_newimage:{
5585          THD_ivec3 id ;
5586 
5587          id = THD_fdind_to_3dind( br, TEMP_IVEC3(-99999,-99999,cbs->nim) );
5588 
5589 if(PRINT_TRACING)
5590 { char str[256] ;
5591   sprintf(str,"newimage input %d -> %d %d %d",
5592           cbs->nim , id.ijk[0],id.ijk[1],id.ijk[2] ) ;
5593   STATUS(str) ; }
5594 
5595          if( im3d->ignore_seq_callbacks == AFNI_IGNORE_NOTHING ){
5596 
5597             /* 20 Feb 2003: set plane from which viewpoint is controlled */
5598 
5599             AFNI_view_setter(im3d,seq) ;
5600             AFNI_set_viewpoint(
5601                im3d , id.ijk[0] , id.ijk[1] , id.ijk[2] ,
5602                (im3d->vinfo->crosshair_visible==True) ?
5603                REDISPLAY_OVERLAY : REDISPLAY_OPTIONAL ) ;
5604          }
5605       }
5606       break ;  /* end of new image */
5607 
5608       /** July 1996: an image viewer changed montage layout **/
5609 
5610       case isqCR_newmontage:{
5611          THD_ivec3 *minf = (THD_ivec3 *) cbs->userdata ;
5612          int ndown = minf->ijk[0], nup = minf->ijk[1], nskip = minf->ijk[2] ;
5613          int a3 = br->a123.ijk[2] ,   /* z axis of the brick?    */
5614              az = abs(a3) - 1       ; /* 0,1,2 for dataset x,y,z */
5615 
5616 if(PRINT_TRACING)
5617 { char str[256] ;
5618   sprintf(str,"newmontage: ndown=%d nup=%d nskip=%d a3=%d (on axis az=%d)",
5619           ndown,nup,nskip,a3,az) ; STATUS(str) ; }
5620 
5621          im3d->vinfo->xhairs_nskip.ijk[az] = nskip ;
5622 
5623          if( a3 > 0 ){
5624             im3d->vinfo->xhairs_ndown.ijk[az] = ndown ;
5625             im3d->vinfo->xhairs_nup.ijk[az]   = nup ;
5626          } else {
5627             im3d->vinfo->xhairs_ndown.ijk[az] = nup ;
5628             im3d->vinfo->xhairs_nup.ijk[az]   = ndown ;
5629          }
5630 
5631          if( im3d->ignore_seq_callbacks == AFNI_IGNORE_NOTHING )
5632             AFNI_set_viewpoint( im3d , -1,-1,-1 , REDISPLAY_OVERLAY ) ;
5633       }
5634       break ;
5635 
5636       /* 30 Dec 1998: return the current focus position */
5637 
5638       case isqCR_getxynim:{
5639          THD_ivec3 ib ;
5640 
5641          ib = THD_3dind_to_fdind( br , TEMP_IVEC3( im3d->vinfo->i1 ,
5642                                                    im3d->vinfo->j2 ,
5643                                                    im3d->vinfo->k3  ) ) ;
5644 
5645          cbs->xim = ib.ijk[0] ; cbs->yim = ib.ijk[1] ; cbs->nim = ib.ijk[2] ;
5646       }
5647       break ;  /* end of getxynim */
5648 
5649       /* Arrowpad stuff */
5650 
5651       case isqCR_appress:{
5652          if( im3d->ignore_seq_callbacks == AFNI_IGNORE_NOTHING ){
5653             AFNI_view_setter(im3d,seq) ;
5654             AFNI_crosshair_gap_CB( NULL , (XtPointer) im3d ) ;
5655          }
5656       }
5657       break ;  /* end of arrowpad center key press */
5658 
5659       case isqCR_dxplus:
5660       case isqCR_dxminus:
5661       case isqCR_dyplus:
5662       case isqCR_dyminus:{
5663          THD_ivec3 ib , id ;
5664          XButtonEvent *xev = (XButtonEvent *) cbs->event ;
5665          int step = 1 ;
5666          THD_dataxes *daxes ;
5667 
5668          if( xev != NULL &&
5669              ( xev->type == ButtonPress ||
5670                xev->type == ButtonRelease ) &&
5671              (xev->state & (ShiftMask | ControlMask)) ) step = INIT_bigscroll ;
5672 
5673          ib = THD_3dind_to_fdind( br , TEMP_IVEC3( im3d->vinfo->i1 ,
5674                                                    im3d->vinfo->j2 ,
5675                                                    im3d->vinfo->k3  ) ) ;
5676          switch( cbs->reason ){
5677             case isqCR_dxplus:   ib.ijk[0] += step ; break ;
5678             case isqCR_dxminus:  ib.ijk[0] -= step ; break ;
5679             case isqCR_dyplus:   ib.ijk[1] += step ; break ;
5680             case isqCR_dyminus:  ib.ijk[1] -= step ; break ;
5681          }
5682 
5683          id = THD_fdind_to_3dind( br , ib ) ;
5684 
5685          /* 13 May 2003: allow for wraparound */
5686 
5687          LOAD_DSET_VIEWS(im3d) ;  /* 20 Nov 2003 */
5688          daxes = CURRENT_DAXES(im3d->anat_now) ;
5689               if( id.ijk[0] <  0          ) id.ijk[0] += daxes->nxx ;
5690          else if( id.ijk[0] >= daxes->nxx ) id.ijk[0] -= daxes->nxx ;
5691               if( id.ijk[1] <  0          ) id.ijk[1] += daxes->nyy ;
5692          else if( id.ijk[1] >= daxes->nyy ) id.ijk[1] -= daxes->nyy ;
5693               if( id.ijk[2] <  0          ) id.ijk[2] += daxes->nzz ;
5694          else if( id.ijk[2] >= daxes->nzz ) id.ijk[2] -= daxes->nzz ;
5695 
5696          if( im3d->ignore_seq_callbacks == AFNI_IGNORE_NOTHING ){
5697 
5698             /* 20 Feb 2003: set plane from which viewpoint is controlled */
5699 
5700             AFNI_view_setter(im3d,seq) ;
5701             AFNI_set_viewpoint(
5702                im3d , id.ijk[0] , id.ijk[1] , id.ijk[2] ,
5703                (im3d->vinfo->crosshair_visible==True) ?
5704                REDISPLAY_OVERLAY : REDISPLAY_OPTIONAL ) ;
5705          }
5706       }
5707       break ;  /* end of arrowpad arrow press */
5708 
5709       case isqCR_keypress:{
5710 #if 1
5711         switch( cbs->key ){  /* 05 Mar 2007: keys that AFNI needs */
5712                                        /* to process, not imseq.c */
5713           case 'U':
5714           case 'u':{
5715             int uu = im3d->vinfo->underlay_type ; /* toggle Overlay as Underlay */
5716             uu = (uu+1) % (LAST_UNDERLAY_TYPE+1) ;
5717 #ifdef USE_UNDERLAY_BBOX
5718             MCW_set_bbox( im3d->vwid->func->underlay_bbox , 1<<uu ) ;
5719             AFNI_underlay_CB( im3d->vwid->func->underlay_bbox->wbut[0] , im3d , NULL ) ;
5720 #else
5721             im3d->vinfo->underlay_type = uu ;
5722             AFNI_underlay_CB( NULL , im3d , (XtPointer)666 ) ;
5723             if( cbs->key == 'U' ){
5724               int qq ; Three_D_View *qq3d ;
5725               for( qq=0 ; qq < MAX_CONTROLLERS ; qq++ ){
5726                 qq3d = GLOBAL_library.controllers[qq] ;
5727                 if( qq3d == im3d || !IM3D_OPEN(qq3d) ) continue ;
5728                 qq3d->vinfo->underlay_type = uu ;
5729                 AFNI_underlay_CB( NULL , qq3d , (XtPointer)666 ) ;
5730               }
5731             }
5732 #endif
5733           }
5734           break ;
5735 
5736           case 'o':{                              /* turn overlay on or off */
5737             int ov = MCW_val_bbox( im3d->vwid->view->see_func_bbox ) ;
5738             MCW_set_bbox( im3d->vwid->view->see_func_bbox , !ov ) ;
5739             AFNI_see_func_CB( NULL , im3d , NULL ) ;
5740           }
5741           break ;
5742 
5743           case '{':    /* Actually: Mod+Button4/5 = Mod+ScrollWheel */
5744           case '}':{   /* Change the threshold slider up or down */
5745             int scl ; float fff,dff,nff ;
5746             XmScaleGetValue( im3d->vwid->func->thr_scale , &scl ) ;
5747             fff = scl * im3d->vinfo->func_thresh_top * THR_factor ;
5748             dff = im3d->vinfo->func_thresh_top * 0.01f ;
5749             if( cbs->key == '{' ) dff = -dff ;
5750             nff = fff+dff ;
5751                  if( nff < 0.0f          ) nff = 0.0f ;
5752             else if( nff > THR_top_value ) nff = THR_top_value ;
5753             if( nff != fff ) AFNI_set_threshold( im3d , nff ) ;
5754           }
5755           break ;
5756 
5757           case 'j':   /* jump to cluster peak -- for Dale [17 Oct 2012] */
5758             AFNI_jumpto_clus(im3d) ;
5759           break ;
5760 
5761           case 'N':   /* jump to nearby cluster [29 Apr 2019] */
5762           case 'n':{                     /* (for John Butman) */
5763             int dci = (cbs->key == 'n') ? 1 : -1 ;
5764             AFNI_jumpto_clus_nearby(im3d,dci) ;
5765           }
5766           break ;
5767 
5768           case 'f':{  /* flash cluster [17 Oct 2012] */
5769             int ic ; float px,py,pz , xx,yy,zz ;
5770             AFNI_clu_widgets *cwid = im3d->vwid->func->cwid ;
5771             mri_cluster_detail *cld = im3d->vwid->func->clu_det ;
5772             if( cwid == NULL || cld == NULL ){ BEEPIT ; break ; }
5773             ic = AFNI_clus_find_xyz( im3d ,
5774                                      im3d->vinfo->xi , im3d->vinfo->yj , im3d->vinfo->zk ) ;
5775             if( ic < 0 ){ BEEPIT ; break ; }
5776             AFNI_clus_action_CB( cwid->clu_flsh_pb[ic] , (XtPointer)im3d , NULL ) ;
5777           }
5778           break ;
5779 
5780         }
5781 
5782 #else /* OLD OLD OLD */
5783         MCW_grapher *grapher = VIEWER_TO_GRAPHER(im3d,seq) ;
5784         if( grapher != NULL ){
5785           char buf[2] ;
5786           buf[0] = cbs->key ; buf[1] = '\0' ;
5787           GRA_handle_keypress( grapher , buf , cbs->event ) ;
5788         }
5789 #endif
5790       }
5791       break ; /* end of keyboard press */
5792 
5793       /*--- 20 Feb 2003: keypress while in button2 mode ---*/
5794 
5795       case isqCR_button2_key:{
5796         KeySym ks = (KeySym) cbs->key ;
5797 
5798         switch( ks ){
5799           case XK_Delete:
5800             AFNI_process_drawing( im3d , UNDO_MODE , 0,NULL,NULL,NULL ) ;
5801           break ;
5802 
5803           case XK_F4:
5804           case XK_F3:  /* 13 Sep 2008 */
5805             AFNI_process_drawing( im3d ,
5806              (ks==XK_F3) ? DECVAL_MODE : INCVAL_MODE , 0,NULL,NULL,NULL ) ;
5807           break ;
5808         }
5809       }
5810       break ; /* end of button2 mode keypress */
5811 
5812       /*--- Feb 1998: list of coordinates from button2 drawing ---*/
5813 
5814       case isqCR_button2_points:{
5815          int npts = cbs->key , zim = cbs->nim ;
5816          int *xyout = (int *) cbs->userdata ;
5817          THD_ivec3 id ;
5818          int nvec , ii , xim,yim , fixed_plane ;
5819          int *xdset , *ydset , *zdset ;
5820 
5821          if( zim >= 0 && zim < br->n3 && npts > 0 ){  /* if input is good */
5822 
5823             /* make space for translated coordinates */
5824 
5825             xdset = (int *) malloc( npts * sizeof(int) ) ;
5826             ydset = (int *) malloc( npts * sizeof(int) ) ;
5827             zdset = (int *) malloc( npts * sizeof(int) ) ;
5828 
5829             /* translate coordinates to dataset xyz indices,
5830                casting out any that are outside the dataset brick */
5831 
5832             nvec = 0 ;
5833             for( ii=0 ; ii < npts ; ii++ ){
5834                xim = xyout[2*ii] ; yim = xyout[2*ii+1] ;
5835 
5836                /* skip points not in the volume */
5837 
5838                if( xim >= 0 && xim < br->n1 && yim >= 0 && yim < br->n2 ){
5839 
5840                   id = THD_fdind_to_3dind( br , TEMP_IVEC3(xim,yim,zim) );
5841                   xdset[nvec] = id.ijk[0] ;
5842                   ydset[nvec] = id.ijk[1] ;
5843                   zdset[nvec] = id.ijk[2] ;
5844 
5845                   /* skip sequentially duplicate points */
5846 
5847                   if( nvec == 0                    ||
5848                       xdset[nvec] != xdset[nvec-1] ||
5849                       ydset[nvec] != ydset[nvec-1] ||
5850                       zdset[nvec] != zdset[nvec-1]   ) nvec++ ;
5851                }
5852             }
5853 
5854             /* send coordinates to processing routine */
5855 
5856             fixed_plane = abs(br->a123.ijk[2]) ;
5857 
5858             if( nvec > 0 ) AFNI_process_drawing( im3d ,
5859                                                  PLANAR_MODE+fixed_plane ,
5860                                                  nvec,xdset,ydset,zdset ) ;
5861 
5862             /* free coordinate memory */
5863 
5864             free(xdset) ; free(ydset) ; free(zdset) ;
5865          }
5866       }
5867       break ; /* end of button2 coordinates */
5868 
5869       /*--- 22 Aug 1998: redraw everything ---*/
5870 
5871       case isqCR_force_redisplay:{
5872          AFNI_view_setter(im3d,seq) ;
5873          PLUTO_force_redisplay() ;  /* see afni_plugin.c */
5874          PLUTO_force_rebar() ;      /* ditto [23 Aug 1998] */
5875       }
5876       break ; /* end of forced redisplay */
5877 
5878       /*--- 06 Jun 2019: force opacity change ---*/
5879 
5880       case isqCR_opacitychange:{
5881         int opval = cbs->nim ;
5882         if( opval > 0 && opval <= 9 && opval != GLOBAL_library.opacity_setting ){
5883           GLOBAL_library.opacity_setting = opval ;
5884           PLUTO_force_opacity_change() ;
5885         }
5886       }
5887       break ; /* end of opacity change */
5888 
5889       /*--- 10 Dec 2019: zoom change ---*/
5890 
5891       case isqCR_zoomchange:{
5892         AFNI_zoompan_lock_carryout(im3d) ;
5893       }
5894       break ; /* end of opacity change */
5895 
5896       /*--- 26 Apr 2007: time indexing ---*/
5897 
5898       case isqCR_setindex:{
5899          MCW_arrowval *tav = im3d->vwid->imag->time_index_av ;
5900          MCW_arrowval *aav = im3d->vwid->func->anat_buck_av ;
5901          int new_index = im3d->vinfo->anat_index + cbs->key ;
5902 
5903          if( new_index != im3d->vinfo->anat_index ){
5904            if( im3d->vinfo->time_on ){
5905              AV_assign_ival( tav , new_index ) ;               /* set time_index */
5906              AFNI_time_index_CB( tav, (XtPointer) im3d ); /* will set anat_index */
5907            } else {
5908              AV_assign_ival( aav, new_index ) ;       /* set anat index directly */
5909              AFNI_bucket_CB( aav, im3d ) ;
5910            }
5911          }
5912       }
5913       break ;
5914 
5915       /*--- raise the controller [17 Jun 2011] ---*/
5916 
5917       case isqCR_raiseupthedead:{
5918         if( IM3D_OPEN(im3d) ) XMapRaised( XtDisplay(im3d->vwid->top_shell) ,
5919                                           XtWindow(im3d->vwid->top_shell)   ) ;
5920       }
5921       break ;
5922 
5923       /*--- cycle global range [03 Feb 2013] ---*/
5924       case isqCR_globalrange:{
5925           int ig;
5926           THD_cycle_image_globalrange();
5927           ig = THD_get_image_globalrange();
5928           THD_set_image_globalrange_env(ig);
5929           ENV_globalrange_view( "AFNI_IMAGE_GLOBALRANGE" );
5930       }
5931       break ;
5932 
5933       /*--- reset global range to use new environment value set elsewhere [03 Feb 2013] ---*/
5934       case isqCR_resetglobalrange:{
5935           int ig;
5936           ig = THD_get_image_globalrange();
5937           THD_set_image_globalrange_env(ig);
5938           ENV_globalrange_view( "AFNI_IMAGE_GLOBALRANGE" );
5939       }
5940       break ;
5941 
5942    }  /* end of switch on reason for call */
5943 
5944    EXRETURN ;
5945 }
5946 
5947 /*----------------------------------------------------------------------
5948    respond to events that one of the MCW_grapher's sends to us
5949 ------------------------------------------------------------------------*/
5950 
AFNI_gra_send_CB(MCW_grapher * grapher,FD_brick * br,GRA_cbs * cbs)5951 void AFNI_gra_send_CB( MCW_grapher *grapher , FD_brick *br , GRA_cbs *cbs )
5952 {
5953    Three_D_View *im3d = (Three_D_View *)grapher->parent ;
5954 
5955 ENTRY("AFNI_gra_send_CB") ;
5956 
5957 if(PRINT_TRACING)
5958 { char str[256] ; sprintf(str,"reason=%d",cbs->reason) ; STATUS(str) ; }
5959 
5960    if( ! IM3D_VALID(im3d) ||
5961        (im3d->ignore_seq_callbacks==AFNI_IGNORE_EVERYTHING) ) EXRETURN ;
5962 
5963    switch( cbs->reason ){
5964 
5965       default: break ;  /* unimplemented reasons */
5966 
5967       /*** 17 Jun 2011 ***/
5968 
5969       case graCR_raiseupthedead:{
5970         if( IM3D_OPEN(im3d) ) XMapRaised( XtDisplay(im3d->vwid->top_shell) ,
5971                                           XtWindow(im3d->vwid->top_shell)   ) ;
5972       }
5973       break ;
5974 
5975       /*** Death ***/
5976 
5977       case graCR_destroy:{
5978          MCW_grapher *gxyz = im3d->g123 ,
5979                      *gyzx = im3d->g231 ,
5980                      *gzxy = im3d->g312  ;
5981          MCW_imseq *seq = GRAPHER_TO_VIEWER(im3d,grapher) ;
5982          Widget w ;
5983 
5984               if( grapher == gxyz ){
5985                  w = im3d->vwid->imag->graph_xyz_pb ; im3d->g123 = NULL ;
5986                  STATUS("destruction of g123") ;
5987          }
5988          else if( grapher == gyzx ){
5989                  w = im3d->vwid->imag->graph_yzx_pb ; im3d->g231 = NULL ;
5990                  STATUS("destruction of g231") ;
5991          }
5992          else if( grapher == gzxy ){
5993                  w = im3d->vwid->imag->graph_zxy_pb ; im3d->g312 = NULL ;
5994                  STATUS("destruction of g312") ;
5995          }
5996          else
5997                  EXRETURN ;  /* something goofy happened? */
5998 
5999          myXtFree( grapher->status ) ;  /* 08 Mar 1999: via mcw_malloc.c */
6000          myXtFree( grapher ) ;          /* free the data space */
6001          MCW_invert_widget(w) ;         /* back to normal */
6002          NORMAL_cursorize(w) ;          /* 20 Jul 2005 */
6003 
6004          /* redisplay the crosshairs, if needed */
6005 
6006          if( seq != NULL && im3d->vinfo->crosshair_visible==True &&
6007              im3d->ignore_seq_callbacks == AFNI_IGNORE_NOTHING     )
6008 
6009             drive_MCW_imseq( seq , isqDR_overlay , (XtPointer) -1 ) ;
6010       }
6011       MPROBE ;
6012       break ;  /* end of destroy */
6013 
6014       /*** User sets new location ***/
6015 
6016       case graCR_newxyzm:{
6017          THD_ivec3 id ;
6018 
6019          if( cbs->xcen >= 0 && cbs->xcen < br->n1 &&
6020              cbs->ycen >= 0 && cbs->ycen < br->n2 &&
6021              cbs->zcen >= 0 && cbs->zcen < br->n3   ){
6022 
6023             id = THD_fdind_to_3dind(
6024                     br , TEMP_IVEC3(cbs->xcen,cbs->ycen,cbs->zcen) );
6025 
6026 if(PRINT_TRACING)
6027 { char str[256] ;
6028   sprintf(str," 3D dataset coordinates %d %d %d",
6029           id.ijk[0],id.ijk[1],id.ijk[2] ) ; STATUS(str) ; }
6030 
6031             if( im3d->ignore_seq_callbacks == AFNI_IGNORE_NOTHING ){
6032                AFNI_view_setter(im3d,NULL) ;
6033                AFNI_set_viewpoint(
6034                   im3d ,
6035                   id.ijk[0] , id.ijk[1] , id.ijk[2] ,
6036                   (im3d->vinfo->crosshair_visible==True) ?
6037                   REDISPLAY_OVERLAY : REDISPLAY_OPTIONAL ) ;
6038             }
6039          }
6040       }
6041       break ; /* end of newxyzm */
6042 
6043       /*** User asks for a reference function ***/
6044 
6045       case graCR_pickref:{
6046 
6047 STATUS("graCR_pickref") ;
6048 
6049          if( IMARR_COUNT(GLOBAL_library.timeseries) > 0 ){
6050             int init_ts = AFNI_ts_in_library( im3d->fimdata->fimref ) ;
6051 
6052             MCW_choose_timeseries( grapher->fdw_graph , "FIM Reference Vector" ,
6053                                    GLOBAL_library.timeseries , init_ts ,
6054                                    AFNI_fimmer_pickref_CB , (XtPointer) im3d ) ;
6055          } else {
6056             (void) MCW_popup_message(
6057                       grapher->option_rowcol ,
6058                       "No timeseries library\nexists to pick from!" ,
6059                       MCW_USER_KILL | MCW_TIMER_KILL ) ;
6060          }
6061       }
6062       break ; /* end of pickref */
6063 
6064       /*** User asks for an ort function ***/
6065 
6066       case graCR_pickort:{
6067 
6068 STATUS("graCR_pickort") ;
6069 
6070          if( IMARR_COUNT(GLOBAL_library.timeseries) > 0 ){
6071             int init_ts = AFNI_ts_in_library( im3d->fimdata->fimort ) ;
6072 
6073             MCW_choose_timeseries( grapher->fdw_graph , "FIM Ort Vector" ,
6074                                    GLOBAL_library.timeseries , init_ts ,
6075                                    AFNI_fimmer_pickort_CB , (XtPointer) im3d ) ;
6076          } else {
6077             (void) MCW_popup_message(
6078                       grapher->option_rowcol ,
6079                       "No timeseries library\nexists to pick from!" ,
6080                       MCW_USER_KILL | MCW_TIMER_KILL ) ;
6081          }
6082       }
6083       break ; /* end of pickort */
6084 
6085 
6086       /*** User asks to clear FIM ***/
6087 
6088       case graCR_clearfim:{
6089          AFNI_fimmer_setref( im3d , NULL ) ;
6090          im3d->fimdata->refadd_count = 0 ;
6091       }
6092       break ; /* end of clearfim */
6093 
6094       /*** User asks to clear Ort ***/
6095 
6096       case graCR_clearort:{
6097          AFNI_fimmer_setort( im3d , NULL ) ;
6098       }
6099       break ; /* end of clearfim */
6100 
6101       /*** 27 Jan 2004:
6102            User toggled WinAver on in one graph window,
6103            so we toggle it off in the other windows.    ***/
6104 
6105       case graCR_winaver:{
6106         if( im3d->g123 != NULL && im3d->g123 != grapher )
6107           drive_MCW_grapher( im3d->g123 , graDR_winaver , 0 ) ;
6108         if( im3d->g231 != NULL && im3d->g231 != grapher )
6109           drive_MCW_grapher( im3d->g231 , graDR_winaver , 0 ) ;
6110         if( im3d->g312 != NULL && im3d->g312 != grapher )
6111           drive_MCW_grapher( im3d->g312 , graDR_winaver , 0 ) ;
6112       }
6113       break ; /* end of winaver */
6114 
6115       /*** 12 Nov 1996:
6116            User supplies a timeseries to add to the global library ***/
6117 
6118       case graCR_timeseries_library:{
6119          MRI_IMAGE *tsim = (MRI_IMAGE *) cbs->userdata ;
6120 
6121          AFNI_add_timeseries( tsim ) ;
6122       }
6123       break ; /* end of timeseries_library */
6124 
6125       /*** User supplies a timeseries for FIM (equals or add) ***/
6126 
6127       case graCR_refadd:
6128       case graCR_refequals:{
6129          MRI_IMAGE *tsim = (MRI_IMAGE *) cbs->userdata ;
6130          MRI_IMAGE *qim , *sim ;
6131          float *sar , *qar ;
6132 
6133          if( tsim != NULL ){
6134             qim = mri_to_float( tsim ) ;        /* make a copy of input */
6135             if( im3d->fimdata->fimref == NULL   ||
6136                 cbs->reason == graCR_refequals  ||
6137                 im3d->fimdata->refadd_count < 1   ){
6138 
6139                /** equals **/
6140 
6141                AFNI_fimmer_setref( im3d , qim ) ;
6142                im3d->fimdata->refadd_count = 1 ;
6143 
6144             } else {
6145                int jj,ii , nxs , nyy , nxq , nxx , npix ;
6146                float fs , fq ;
6147 
6148                /** average **/
6149 
6150                sim  = mri_to_float( im3d->fimdata->fimref ) ; /* add into this copy */
6151                sar  = MRI_FLOAT_PTR(sim) ;
6152                qar  = MRI_FLOAT_PTR(qim) ;
6153                nxs  = sim->nx ; nxq = qim->nx ; nxx = MIN(nxs,nxq) ;
6154                nyy  = MIN( sim->ny , qim->ny ) ;
6155                npix = MIN( sim->nvox , qim->nvox ) ;
6156 
6157                fq = 1.0/( im3d->fimdata->refadd_count + 1.0 ) ;
6158                fs = 1.0 - fq ;
6159 
6160                for( jj=0 ; jj < nyy ; jj++ ){
6161                   for( ii=0 ; ii < nxx ; ii++ ){
6162                      if( sar[ii+jj*nxs] >= WAY_BIG || qar[ii+jj*nxq] >= WAY_BIG )
6163                         sar[ii+jj*nxs] = WAY_BIG ;
6164                      else
6165                         sar[ii+jj*nxs] = fs * sar[ii+jj*nxs] + fq * qar[ii+jj*nxq] ;
6166                   }
6167                }
6168                mri_free( qim ) ;
6169 
6170                AFNI_fimmer_setref( im3d , sim ) ;  /* since caller may free it later */
6171                im3d->fimdata->refadd_count++ ;
6172             }
6173          }
6174       }
6175       break ;
6176 
6177       /*** User asks to smooth reference ***/
6178 
6179       case graCR_refsmooth:{
6180          if( im3d->fimdata->fimref != NULL ){
6181             MRI_IMAGE *sim = mri_to_float(im3d->fimdata->fimref) ; /* copy */
6182             float *sar = MRI_FLOAT_PTR(sim) ;
6183             float aa,bb,cc ;
6184             int ii,jj , nx=sim->nx , ny=sim->ny ;
6185 
6186             for( jj=0 ; jj < ny ; jj++ ){
6187                bb = sar[jj*nx] ; cc = sar[1+jj*nx] ;
6188                for( ii=1 ; ii < nx-1 ; ii++ ){
6189                   aa = bb ; bb = cc ; cc = sar[ii+1+jj*nx] ;
6190                   if( aa < WAY_BIG && bb < WAY_BIG &&
6191                       cc < WAY_BIG && ii > im3d->fimdata->init_ignore )
6192                      sar[ii+jj*nx] = OSFILT(aa,bb,cc) ;
6193                }
6194             }
6195             AFNI_fimmer_setref( im3d , sim ) ;
6196          }
6197       }
6198       break ;
6199 
6200       /*** User asks to do fim! ***/
6201 
6202       case graCR_dofim:{
6203          AFNI_fimmer_execute( im3d , cbs->key , cbs->mat ) ;
6204       }
6205       break ; /* end of dofim */
6206 
6207       /*** User sets initial ignore count ***/
6208 
6209       case graCR_setignore:{
6210          AFNI_fimmer_setignore( im3d , cbs->key ) ;
6211       }
6212       break ;
6213 
6214       /*** User sets the polort order [27 May 1999] ***/
6215 
6216       case graCR_polort:{
6217          AFNI_fimmer_setpolort( im3d , cbs->key ) ;
6218       }
6219       break ;
6220 
6221       /*** User sets time_index (from graph) ***/
6222       /*** 24 Jan 2001: or bucket index      ***/
6223       /*** 29 Jul 2003: time_index and anat_index are almost merged now ***/
6224 
6225       case graCR_setindex:{
6226          MCW_arrowval *tav = im3d->vwid->imag->time_index_av ;
6227          MCW_arrowval *aav = im3d->vwid->func->anat_buck_av ;
6228          int new_index = cbs->key ;
6229 
6230          if( new_index != im3d->vinfo->anat_index ){
6231            if( im3d->vinfo->time_on ){
6232              AV_assign_ival( tav , new_index ) ;               /* set time_index */
6233              AFNI_time_index_CB( tav, (XtPointer) im3d ); /* will set anat_index */
6234            } else {
6235              AV_assign_ival( aav, new_index ) ;       /* set anat index directly */
6236              AFNI_bucket_CB( aav, im3d ) ;
6237            }
6238          }
6239       }
6240       break ;
6241 
6242       /*** Feb 1998: user clicked button2 ***/
6243 
6244       case graCR_button2_points:{
6245          THD_ivec3 id ;
6246          int fixed_plane ;
6247 
6248          if( cbs->xcen >= 0 && cbs->xcen < br->n1 &&
6249              cbs->ycen >= 0 && cbs->ycen < br->n2 &&
6250              cbs->zcen >= 0 && cbs->zcen < br->n3   ){
6251 
6252             /* translate image to dataset coordinates */
6253 
6254             id = THD_fdind_to_3dind(
6255                     br , TEMP_IVEC3(cbs->xcen,cbs->ycen,cbs->zcen) );
6256 
6257             /* send a single point */
6258 
6259             fixed_plane = abs(br->a123.ijk[2]) ;
6260 
6261             AFNI_process_drawing( im3d , SINGLE_MODE + fixed_plane ,
6262                                   1, &id.ijk[0], &id.ijk[1], &id.ijk[2] ) ;
6263          }
6264       }
6265       break ;
6266 
6267    } /* end of switch on callback reasons */
6268 
6269   EXRETURN ;
6270 }
6271 
6272 /*----------------------------------------------------------------------*/
6273 /*! Report on datasets with mixed type sub-bricks,
6274     as they tend to cause problems. */
6275 
AFNI_inconstancy_check(Three_D_View * im3d,THD_3dim_dataset * dset)6276 void AFNI_inconstancy_check( Three_D_View *im3d , THD_3dim_dataset *dset )
6277 {
6278    static int    nbad = 0 ;
6279    static char **sbad = NULL ;
6280 
6281 ENTRY("AFNI_inconstancy_check") ;
6282 
6283    if( dset == NULL ){
6284      char *msg ; int ii,nn ; Widget wp ;
6285      if( nbad == 0 || sbad == NULL ) EXRETURN ; /* nothing to report */
6286      if( !IM3D_OPEN(im3d) ) im3d =AFNI_find_open_controller();
6287      wp = im3d->vwid->imag->crosshair_label ;
6288      BEEPIT ;
6289      STATUS("creating inconstancy message") ;
6290      for(ii=nn=0;ii<nbad;ii++) nn += strlen(sbad[ii]) ;
6291      nn += 255+4*nbad ; msg = malloc(nn) ;
6292      sprintf(msg,
6293             "\n========== Datasets With Inconstant Data Types =========\n\n");
6294      for(ii=0;ii<nbad;ii++) sprintf(msg+strlen(msg)," %s\n",sbad[ii]) ;
6295      sprintf(msg+strlen(msg),
6296             "\n===== This is known as the Mike Beauchamp SINdrome =====\n"
6297               "===== Funky things may happen with these datasets! =====\n" ) ;
6298      MCW_textwin_setbig(1) ;
6299      (void)new_MCW_textwin( wp , msg , TEXT_READONLY ) ;
6300      free((void *)msg) ;
6301      for(ii=0;ii<nbad;ii++)free((void *)sbad[ii]);
6302      free((void *)sbad) ; nbad=0 ; sbad=NULL ;
6303      BEEPIT ;
6304      EXRETURN ;
6305    } else if( ISVALID_DSET(dset) && !DSET_datum_constant(dset) ){
6306      char *str = DSET_BRIKNAME(dset) ;
6307      sbad = (char **)realloc((void *)sbad,sizeof(char *)*(nbad+1)) ;
6308      sbad[nbad++] = strdup(str) ;
6309    }
6310    EXRETURN ;
6311 }
6312 
6313 /*----------------------------------------------------------------------------
6314    read the files specified on the command line and create the data structures
6315 ------------------------------------------------------------------------------*/
6316 
AFNI_read_inputs(int argc,char * argv[])6317 void AFNI_read_inputs( int argc , char *argv[] )
6318 {
6319    int id , last_color ;
6320    RwcBoolean isfunc ;
6321 
6322 
6323 ENTRY("AFNI_read_inputs") ;
6324 
6325    /* create empty library of dataset sessions */
6326 
6327    GLOBAL_library.sslist = myXtNew( THD_sessionlist ) ;
6328    GLOBAL_library.sslist->type = SESSIONLIST_TYPE ;
6329    BLANK_SESSIONLIST(GLOBAL_library.sslist) ;
6330    GLOBAL_library.sslist->parent = NULL ;
6331    GLOBAL_argopt.only_images = 0 ;  /* 24 Feb 2017 */
6332 
6333    /*----- read files -----*/
6334 
6335    if( GLOBAL_argopt.first_file_arg >= argc && GLOBAL_argopt.read_images ){
6336       ERROR_exit("No image files on command line!!") ;
6337    }
6338 
6339    /*--- read directly from images (the old-fashioned way) ---*/
6340 
6341    if( GLOBAL_argopt.read_images ){  /* pretty much obsolete */
6342       THD_3dim_dataset *dset ;
6343       THD_session *new_ss ;
6344       int vv ;
6345       int gnim ;  /* 16 Mar 1998: names from globbing */
6346       char **gname ;
6347 
6348       MCW_warn_expand(1) ;  /* 13 Jul 2001 */
6349 
6350       MCW_file_expand( argc - GLOBAL_argopt.first_file_arg ,
6351                        &(argv[GLOBAL_argopt.first_file_arg]) ,
6352                        &gnim , &gname ) ;
6353 
6354       MCW_warn_expand(0) ;  /* 13 Jul 2001 */
6355 
6356       if( gnim < 1 )
6357         ERROR_exit("No valid filenames on command line?!") ;
6358 
6359       dset = AFNI_read_images( gnim , gname ) ;
6360 
6361       if( dset == NULL )
6362         ERROR_exit("Could not form 3D dataset from images!" ) ;
6363 
6364       MCW_free_expand( gnim , gname ) ;
6365 
6366       /* set up minuscule session and session list */
6367 
6368       new_ss              = myXtNew( THD_session ) ;
6369       new_ss->type        = SESSION_TYPE ;
6370       new_ss->dsrow       = NULL;  /* row of datasets across spaces not defined yet */
6371       BLANK_SESSION(new_ss) ;
6372       new_ss->num_dsset   = 1 ;
6373       SET_SESSION_DSET(dset, new_ss, 0,0);
6374 /*      new_ss->dsset_xform_table[0][0] = dset ;*/
6375       new_ss->parent      = NULL ;
6376 
6377       MCW_strncpy( new_ss->sessname ,
6378                    argv[GLOBAL_argopt.first_file_arg] , THD_MAX_NAME ) ;
6379       MCW_strncpy( new_ss->lastname ,
6380                    argv[GLOBAL_argopt.first_file_arg] , THD_MAX_NAME ) ;
6381 
6382       GLOBAL_library.sslist->num_sess   = 1 ;
6383       GLOBAL_library.sslist->ssar[0]    = new_ss ;
6384       GLOBAL_library.have_dummy_dataset = 1 ;
6385 
6386    } /** end of images input **/
6387 
6388    /*--- sessions of 3D datasets (from to3d or other AFNI programs) ---*/
6389 
6390    else if( GLOBAL_argopt.read_sessions ){   /*--- the usual method ---*/
6391 
6392       char str[256] ;
6393       RwcBoolean good ;
6394       int num_ss , qd , qs , vv=0 , no_args , jj , nskip_noanat=0 ;
6395       THD_string_array *flist , *dlist=NULL , *elist=NULL , *qlist ;
6396       char *dname , *eee ;
6397       THD_session *new_ss ;
6398       THD_session **new_ssar=NULL ; int num_ssar , qss ;
6399       int num_dsets=0 ;       /* 04 Jan 2000 */
6400       THD_session *gss=NULL ; /* 11 May 2002: global session */
6401       THD_session *dss=NULL ; /* 28 Aug 2003: session for command-line datasets */
6402       THD_3dim_dataset *temp_dset=NULL; /* 16 Jul 2010: place holder dummy datasets */
6403 
6404       THD_session *css=NULL ; /* 02 Jun 2016: catenated sessions */
6405       int       do_css=GLOBAL_argopt.cat_sess ;
6406       int      num_css=0 ;
6407 
6408       /*-- 20 Dec 2001: Try to read a "global" session --*/
6409       /*-- 11 May 2002: Move read global session up here --*/
6410 
6411       eee = getenv( "AFNI_GLOBAL_SESSION" ) ;   /* where it's supposed to be */
6412       if( eee != NULL ){
6413          THD_3dim_dataset *dset ;
6414          STATUS("reading global session") ;
6415          gss =
6416           GLOBAL_library.session = THD_init_session( eee ); /* try to read datasets */
6417 
6418          if( gss != NULL ){                               /* got at least one */
6419             REPORT_PROGRESS("[Global]") ;
6420             gss->parent = NULL ;                          /* parentize them */
6421             for( qd=0 ; qd < gss->num_dsset ; qd++ )
6422               for( vv=0 ; vv <= LAST_VIEW_TYPE ; vv++ ){
6423                 dset = GET_SESSION_DSET(gss, qd, vv) ;
6424 /*                dset = gss->dsset_xform_table[qd][vv] ;*/
6425                 if( dset != NULL ){
6426                   PARENTIZE( dset , NULL ) ;
6427                   DSET_MARK_FOR_IMMORTALITY( dset ) ;
6428                   AFNI_inconstancy_check(NULL,dset) ; /* 06 Sep 2006 */
6429                 }
6430               }
6431          } else {
6432            sprintf(str,"\n** No datasets in AFNI_GLOBAL_SESSION=%s",eee) ;
6433            REPORT_PROGRESS(str) ;
6434          }
6435       }
6436 
6437       /* 28 Aug 2003:
6438          set up session for datasets from command line (vs. directories) */
6439 
6440       dss         = myXtNew( THD_session ) ;
6441       dss->type   = SESSION_TYPE ;
6442       dss->parent = NULL ;
6443       dss->ndsets = 0;
6444       dss->dsrow  = NULL;
6445       BLANK_SESSION(dss) ;
6446       MCW_strncpy( dss->sessname , "fromCLI" , THD_MAX_NAME ) ;
6447       MCW_strncpy( dss->lastname , "fromCLI" , THD_MAX_NAME ) ;
6448 
6449       if( do_css ){  /* catenated sessions [02 Jun 2016] */
6450         css         = myXtNew( THD_session ) ;
6451         css->type   = SESSION_TYPE ;
6452         css->parent = NULL ;
6453         css->ndsets = 0;
6454         css->dsrow  = NULL;
6455         BLANK_SESSION(css) ;
6456         css->is_collection = 1 ; /* 01 Feb 2018 */
6457         MCW_strncpy( css->sessname , "All_Datasets" , THD_MAX_NAME ) ;
6458         MCW_strncpy( css->lastname , "All_Datasets" , THD_MAX_NAME ) ;
6459       }
6460 
6461       /* now get the list of strings to read as directories */
6462 
6463       num_ss  = argc - GLOBAL_argopt.first_file_arg ;
6464       no_args = (num_ss < 1) ;
6465 
6466       INIT_SARR(dlist) ;
6467 
6468       /** 15 Apr 2018: put in any bysub dirs **/
6469 
6470       for( id=0; id < num_bysub_dir; id++ ){ ADDTO_SARR(dlist,bysub_dir[id]); }
6471 
6472       if( no_args && num_bysub_dir <= 0 ){
6473          if( GLOBAL_argopt.recurse > 0 ){
6474 STATUS("no args: recursion on ./") ;
6475             flist = THD_get_all_subdirs( GLOBAL_argopt.recurse , "./" ) ;
6476             if( flist != NULL ){
6477                for( jj=0 ; jj < flist->num ; jj++ ){
6478                  ADDTO_SARR(dlist,flist->ar[jj]) ;
6479                }
6480                DESTROY_SARR(flist) ;
6481             }
6482          } else {
6483 STATUS("no args: using ./") ;
6484            ADDTO_SARR(dlist,"./") ;
6485            elist = THD_get_all_subdirs( 1 , "./" ) ;  /* 18 Feb 2007 */
6486          }
6487       } else {
6488          for( id=0 ; id < num_ss ; id++ ){
6489             if( GLOBAL_argopt.recurse > 0 ){
6490                flist = THD_get_all_subdirs( GLOBAL_argopt.recurse ,
6491                                             argv[GLOBAL_argopt.first_file_arg+id] ) ;
6492                if( flist != NULL ){
6493                   for( jj=0 ; jj < flist->num ; jj++ ){
6494                     ADDTO_SARR(dlist,flist->ar[jj]) ;
6495                   }
6496                   DESTROY_SARR(flist) ;
6497                }
6498             } else {
6499               ADDTO_SARR(dlist,argv[GLOBAL_argopt.first_file_arg+id]) ;
6500             }
6501          }
6502       }
6503 
6504       if( dlist->num < 1 ) ADDTO_SARR(dlist,"./") ;  /* just in case */
6505 
6506       /** 09 Sep 1998: eliminate duplicates from the directory list **/
6507 
6508 STATUS("normalizing directory list") ;
6509       qlist = THD_normalize_flist( dlist ) ;
6510       if( qlist != NULL ){ DESTROY_SARR(dlist); dlist = qlist; }
6511 
6512       if( dlist->num == 1 && css != NULL && gss == NULL ){ /* 02 Jun 2016 */
6513         myXtFree(css) ; do_css = 0 ; num_css = 0 ;
6514       }
6515 
6516       REFRESH ;
6517 
6518       /*----- read each session, set parents, put into session list -----*/
6519 
6520       GLOBAL_argopt.only_images = 1 ;  /* 24 Feb 2017 */
6521 
6522       qlist = dlist ;
6523    RESTART_DIRECTORY_SCAN:   /* 18 Feb 2007 */
6524       num_ss = qlist->num ;
6525 
6526       for( id=0 ; id < num_ss ; id++ ){
6527 
6528 if(PRINT_TRACING)
6529 { char str[256] ;
6530   sprintf(str,"try to read directory %s",qlist->ar[id]) ; STATUS(str) ; }
6531 
6532          dname  = qlist->ar[id] ;
6533          new_ss = NULL ;
6534 
6535          if( new_ssar != NULL ) free(new_ssar) ; /* 01 Feb 2018 */
6536          new_ssar = NULL ; num_ssar = 0 ;
6537 
6538          if( THD_is_directory(dname) ){   /* directory? read session(s) */
6539            static int first=1 ;
6540 
6541            for( qss=0 ; qss < num_bysub ; qss++ ){   /* bysub [01 Feb 2018] */
6542              if( first ){ fprintf(stderr,"[bysub/BIDS]"); first = 0; }
6543              new_ss = THD_init_session_bysub(dname,bysub[qss]) ;
6544              if( new_ss != NULL ){
6545                new_ssar = (THD_session **)realloc( new_ssar ,
6546                                                    sizeof(THD_session *)*(num_ssar+1) ) ;
6547                new_ssar[num_ssar++] = new_ss ;
6548                fprintf(stderr,"+%s",bysub[qss]) ;
6549              }
6550            }
6551            if( num_ssar == 0 ){                  /* bysub did nothing, try again */
6552              new_ss = THD_init_session(dname) ;
6553              if( new_ss != NULL ){
6554                new_ssar = (THD_session **)malloc(sizeof(THD_session *)) ;
6555                new_ssar[0] = new_ss ; num_ssar = 1 ;
6556                fprintf(stderr,"+%s",dname) ;
6557              }
6558            }
6559          }
6560 
6561          REFRESH ;
6562 
6563          if( new_ssar == NULL && !THD_is_directory(dname) ){ /* 28 Aug 2003 */
6564            STATUS("trying to read it as a dataset file") ;
6565            qd = dss->num_dsset ;
6566            if( qd < THD_MAX_SESSION_SIZE ){
6567              THD_3dim_dataset *dset = THD_open_dataset( dname ) ;
6568              if( ISVALID_DSET(dset) ){
6569                STATUS("it IS a dataset file!") ;
6570                SET_SESSION_DSET(dset, dss, qd, dset->view_type);
6571 /*               dss->dsset_xform_table[qd][dset->view_type] = dset ;*/
6572                dss->num_dsset ++ ;
6573                if( dset->dblk->diskptr->storage_mode != STORAGE_BY_IMAGE_FILE )
6574                  GLOBAL_argopt.only_images = 0 ;  /* 24 Feb 2017 */
6575                AFNI_inconstancy_check(NULL,dset) ; /* 06 Sep 2006 */
6576              } else if( qlist == dlist ){
6577                fprintf(stderr,
6578                        "\n** Couldn't open %s as session OR as dataset!" ,
6579                        dname ) ;
6580              }
6581            }
6582          }
6583 
6584          if( new_ssar != NULL && num_ssar > 0 ){ /* got something? */
6585            THD_3dim_dataset *dset ;
6586 
6587            GLOBAL_argopt.only_images = 0 ;  /* 24 Feb 2017 */
6588 
6589            /* set parent pointers */
6590 
6591            for( qss=0 ; qss < num_ssar ; qss++ ){  /* 01 Feb 2018 */
6592              new_ss = new_ssar[qss] ;
6593              new_ss->parent = NULL ;
6594              for( qd=0 ; qd < new_ss->num_dsset ; qd++ ){
6595                for( vv=0 ; vv <= LAST_VIEW_TYPE ; vv++ ){
6596                    dset = GET_SESSION_DSET(new_ss, qd, vv);
6597 /*                 dset = new_ss->dsset_xform_table[qd][vv] ;*/
6598                  if( dset != NULL ){
6599                    PARENTIZE( dset , NULL ) ;
6600                    AFNI_inconstancy_check(NULL,dset) ; /* 06 Sep 2006 */
6601                  }
6602              } }
6603 
6604              /* put the new session into place in the list of sessions */
6605 
6606              GLOBAL_library.sslist->ssar[(GLOBAL_library.sslist->num_sess)++] = new_ss ;
6607              if( qlist == elist ) recursed_ondot++ ;  /* 18 Feb 2007 */
6608 
6609              sprintf(str,"\n session #%3d  = %s ==> %d dataset%s" ,
6610                      GLOBAL_library.sslist->num_sess ,
6611                      new_ss->lastname , new_ss->num_dsset ,
6612                      (new_ss->num_dsset > 1) ? "s" : " " ) ;
6613              REPORT_PROGRESS(str) ;
6614 
6615              num_dsets += new_ss->num_dsset ;
6616 
6617              /* 28 Aug 2002: add any inter-dataset warps to global warptable */
6618 
6619              if( new_ss->warptable != NULL ){
6620                if( GLOBAL_library.warptable == NULL ) /* create global warptable */
6621                  GLOBAL_library.warptable = new_Htable(101) ;
6622                subsume_Htable( new_ss->warptable , GLOBAL_library.warptable ) ;
6623                destroy_Htable( new_ss->warptable ) ;
6624                new_ss->warptable = NULL ;
6625              }
6626 
6627              /* 02 Jun 2016: catenate this session with the css (all datasets) */
6628 
6629              if( do_css )
6630                THD_append_sessions( css , new_ss ) ; num_css++ ;
6631 
6632              /* 11 May 2002: put global datasets into session now */
6633 
6634              if( new_ss != NULL && gss != NULL )
6635                THD_append_sessions( new_ss , gss ) ;
6636 
6637              /* if we've maxed out on sessions */
6638 
6639              if( GLOBAL_library.sslist->num_sess == THD_MAX_NUM_SESSION ){
6640                sprintf(str,"\n *** reached max no. sessions (%d) ***",
6641                      THD_MAX_NUM_SESSION) ;
6642                REPORT_PROGRESS(str) ;
6643                goto END_OF_ID_LOOP ; /* exit loop over id [bad news, baby] */
6644              }
6645            } /* end of loop over array of new sessions */
6646 
6647          } else if( num_bysub == 0 ){   /* 18 Feb 2007: do -R2 on "./" if no data found */
6648            if( qlist == dlist && elist != NULL ){
6649              fprintf(stderr,"\n** Searching subdirectories of './' for data") ;
6650              qlist = elist; goto RESTART_DIRECTORY_SCAN;
6651            }
6652          }
6653 
6654       }  /*----- end of id loop (over input directory names) -----*/
6655 
6656 END_OF_ID_LOOP:  /* for the bad news above [01 Feb 2018] */
6657 
6658       /* 28 Aug 2003: if have datasets in session dss, use it */
6659 
6660       if( dss->num_dsset > 0 ){
6661         if( GLOBAL_library.sslist->num_sess < THD_MAX_NUM_SESSION ){
6662           if( do_css ){ /* 02 Jun 2016 */
6663             THD_append_sessions(css,dss); num_css++;
6664           }
6665           GLOBAL_library.sslist->ssar[(GLOBAL_library.sslist->num_sess)++] = dss ;
6666           num_dsets += dss->num_dsset ;
6667           sprintf(str,"\n session #%3d  = %s ==> %d dataset%s" ,
6668                   GLOBAL_library.sslist->num_sess, dss->sessname, dss->num_dsset,
6669                   (dss->num_dsset > 1) ? "s" : " " ) ;
6670           REPORT_PROGRESS(str) ;
6671           if( gss != NULL ) THD_append_sessions( dss , gss ) ;
6672         } else {
6673           fprintf(stderr,"\n** Can't use command line datasets: session overflow!\n") ;
6674           free(dss) ;
6675         }
6676       } else {
6677         free(dss) ;
6678       }
6679 
6680       if( gss != NULL && do_css ){
6681         THD_append_sessions(css,gss); num_css++;
6682       }
6683 
6684       /* 11 May 2002: if have global session but no others, use it */
6685 
6686       if( gss != NULL && GLOBAL_library.sslist->num_sess == 0 ){
6687 
6688         GLOBAL_library.sslist->ssar[(GLOBAL_library.sslist->num_sess)++] = gss ;
6689 
6690         sprintf(str,"\n AFNI_GLOBAL_SESSION = %s %d datasets" ,
6691                 gss->sessname , gss->num_dsset ) ;
6692 
6693         num_dsets += gss->num_dsset ;
6694 
6695         REPORT_PROGRESS(str) ;
6696       }
6697 
6698       /* add the catenated session list, if nontrivial */
6699       /* only if do_css             7 Mar 2018 [rickr] */
6700 
6701       if( css && do_css ) {
6702          if( num_css > 1 && GLOBAL_library.sslist->num_sess < THD_MAX_NUM_SESSION ){
6703            GLOBAL_library.sslist->ssar[(GLOBAL_library.sslist->num_sess)++] = css ;
6704            sprintf(str,"\n Catenated %d sessions = %s has %d datasets" ,
6705                    num_css , css->sessname , css->num_dsset ) ;
6706            REPORT_PROGRESS(str) ;
6707          } else {
6708            myXtFree(css) ;
6709          }
6710       }
6711 
6712       /** if nothing read yet, try some canonical files [22 Oct 2019] **/
6713 
6714       if( GLOBAL_library.sslist->num_sess <= 0 ){
6715       }
6716 
6717       /**** if nothing read at all, make up something ****/
6718 
6719       GLOBAL_library.have_dummy_dataset = 0 ;
6720 
6721       if( GLOBAL_library.sslist->num_sess <= 0 ){
6722 #define NCANON 3  /* added 22 Oct 2019 */
6723          static char *cds[NCANON] = { "MNI152_2009_template_SSW.nii.gz" ,
6724                                       "MNI_N27.nii.gz" ,
6725                                       "TT_N27_SSW.nii.gz" } ;
6726 
6727          char *aaa = THD_find_executable( "afni" ) ;
6728          char *snam = dlist->ar[0] ; /* 10 Mar 2002 */
6729          char *cpt ; int found_canon=0 ;
6730 
6731          temp_dset = NULL ;               /* this will be the made up dataset */
6732 
6733          if( aaa != NULL && *aaa != '\0' ){  /* try to find canonical dataset */
6734            char *ddd ; int lll , ccc ;      /* from afni executable directory */
6735            lll = strlen(aaa) ;
6736            ddd = malloc(sizeof(char)*(lll+64)) ;
6737            strcpy(ddd,aaa) ;
6738            for( ccc=0 ; ccc < NCANON ; ccc++ ){
6739              strcpy( ddd+(lll-4) , cds[ccc] ) ;   /* cut off the last 4 chars */
6740              temp_dset = THD_open_dataset( ddd ) ;
6741              if( temp_dset != NULL ) break ;
6742            }
6743            found_canon = (temp_dset != NULL) ;   /* found a canonical dataset */
6744          }
6745 
6746          if( !THD_is_directory(snam) ) snam = "./" ;
6747 
6748          REPORT_PROGRESS("\n** No datasets found -- making up something **") ;
6749 
6750          /** manufacture a minimal session **/
6751 
6752          new_ss         = myXtNew( THD_session ) ;
6753          new_ss->type   = SESSION_TYPE ;
6754          new_ss->parent = NULL ;
6755          BLANK_SESSION(new_ss) ;
6756          MCW_strncpy( new_ss->sessname, snam, THD_MAX_NAME ); /* pretend dummy session */
6757          MCW_strncpy( new_ss->lastname, snam, THD_MAX_NAME ); /* is first argv dir */
6758          GLOBAL_library.sslist->num_sess   = 1 ;
6759          GLOBAL_library.sslist->ssar[0]    = new_ss ;
6760 
6761          /** if nothing yet, make up  a minimal dataset [cf. thd_dumdset.c] **/
6762 
6763          new_ss->num_dsset = 1 ;
6764          GLOBAL_argopt.only_images = 0 ;  /* 24 Feb 2017 */
6765 
6766          cpt = getenv("AFNI_DUMMY_DATASET") ; /* specify type of dummy dset */
6767 
6768          if( temp_dset == NULL && cpt != NULL &&
6769              ( strcasecmp(cpt,"RWCOX")==0 || strcasecmp(cpt,"OLD")==0 ) ){
6770            temp_dset = THD_dummy_RWCOX();
6771            SET_SESSION_DSET(temp_dset,new_ss, 0, 0); /* the olden way */
6772            GLOBAL_library.have_dummy_dataset = 1 ;
6773 
6774          } else if( temp_dset == NULL ){
6775            temp_dset = THD_dummy_N27();
6776            SET_SESSION_DSET(temp_dset,new_ss, 0, 0);   /* 12 Feb 2010 */
6777            SET_SESSION_DSET(temp_dset,new_ss, 0, 2);
6778            GLOBAL_library.have_dummy_dataset = 1 ;
6779          } else {              /* use canonical dataset [22 Oct 2019] */
6780            SET_SESSION_DSET(temp_dset,new_ss, 0, 0);
6781            SET_SESSION_DSET(temp_dset,new_ss, 0, 2);
6782          }
6783 
6784          if( !found_canon ) DSET_lock(temp_dset) ; /* lock into memory */
6785          PARENTIZE( temp_dset , NULL ) ;
6786 
6787       } else {  /* 04 Jan 2000: show total number of datasets */
6788 
6789          if( GLOBAL_argopt.only_images ) /* 24 Feb 2017 */
6790            sprintf(str,"\n image count   = %d" , num_dsets ) ;
6791          else
6792            sprintf(str,"\n dataset count = %d" , num_dsets ) ;
6793          GLOBAL_num_dsets = num_dsets ;
6794          REPORT_PROGRESS(str) ;
6795       }
6796 
6797       /*** read all timeseries files from all directories ***/
6798 
6799 STATUS("reading timeseries files") ;
6800 
6801       /* 27 Jan 2000: allow skipping *.1D files from dataset directories */
6802       /* 10 Feb 2016: broke sometime - allow skipping */
6803       if(GLOBAL_argopt.read_1D)
6804          GLOBAL_library.timeseries = THD_get_many_timeseries(qlist);
6805       else
6806          GLOBAL_library.timeseries = NULL;
6807       REFRESH ;
6808       if( GLOBAL_library.timeseries == NULL )     /* empty but not NULL */
6809          INIT_IMARR(GLOBAL_library.timeseries) ;
6810       sprintf( str , "\n Timeseries.1D = %d files read" ,
6811                IMARR_COUNT(GLOBAL_library.timeseries) ) ;
6812       REPORT_PROGRESS(str) ;
6813 
6814       /* 16 Jun 2020: same stuff for *.tsv and *.csv files */
6815       if(GLOBAL_argopt.read_tcsv)
6816          GLOBAL_library.tcsv_data = THD_get_many_tcsv(qlist);
6817       else
6818          GLOBAL_library.tcsv_data = NULL;
6819       REFRESH ;
6820       if( GLOBAL_library.tcsv_data == NULL )     /* empty but not NULL */
6821          INIT_ELARR(GLOBAL_library.tcsv_data) ;
6822       sprintf( str , "\n .[tc]sv data  = %d files read" ,
6823                ELARR_COUNT(GLOBAL_library.tcsv_data) ) ;
6824       REPORT_PROGRESS(str) ;
6825 
6826       /*** throw away the list of directories that were scanned ***/
6827 
6828       DESTROY_SARR(dlist) ;
6829       if( elist != NULL ){ DESTROY_SARR(elist); }  /* 18 Feb 2007 */
6830 
6831       /* assign the warp and anatomy parent pointers;
6832          then, make any datasets that don't exist but logically
6833          descend from the warp and anatomy parents just assigned */
6834 
6835       if( !GLOBAL_library.have_dummy_dataset ){
6836 
6837         STATUS("checking idcodes for duplicates") ;
6838         THD_check_idcodes( GLOBAL_library.sslist ) ;     /* 08 Jun 1999 */
6839 
6840         STATUS("reconciling parent pointers") ;
6841         THD_reconcile_parents( GLOBAL_library.sslist ) ;
6842 
6843         STATUS("forcible adoption of unparented datasets") ;
6844         for( id=0 ; id < GLOBAL_library.sslist->num_sess ; id++ ){ /* functions w/o parents, */
6845           new_ss = GLOBAL_library.sslist->ssar[id] ;               /* forcibly get one */
6846           AFNI_force_adoption( new_ss , GLOBAL_argopt.warp_4D ) ;
6847        }
6848 
6849       } /* end of if don't have dummy dataset */
6850 
6851       if( GLOBAL_library.session != NULL )
6852          AFNI_force_adoption( GLOBAL_library.session , GLOBAL_argopt.warp_4D ) ;
6853 
6854 STATUS("making descendant datasets") ;
6855 
6856       AFNI_make_descendants( GLOBAL_library.sslist ) ;
6857 
6858    } /** end of sessions input **/
6859 
6860    else if( GLOBAL_argopt.read_dsets ){  /* 17 Mar 2000 */
6861 
6862       int nds = argc - GLOBAL_argopt.first_file_arg ;
6863       char str[256] ;
6864       THD_3dim_dataset *dset ;
6865       RwcPointer_array *dsar ;
6866       MRI_IMARR *webtsar ;        /* 26 Mar 2001 */
6867       THD_session *new_ss ;
6868       int ii,nerr=0,vv,nn , dd ;
6869 
6870       if( nds <= 0 ){
6871          fprintf(stderr,"\a\n** No datasets on command line?!\n"); exit(1);
6872       }
6873       nds = 0 ;
6874 
6875       /* set up minuscule session and session list */
6876 
6877       new_ss             = myXtNew( THD_session ) ;
6878       new_ss->type       = SESSION_TYPE ;
6879       BLANK_SESSION(new_ss) ;
6880       new_ss->parent     = NULL ;
6881 
6882       strcpy( new_ss->sessname , "." ) ;
6883       strcpy( new_ss->lastname , "." ) ;
6884 
6885       GLOBAL_library.sslist->num_sess   = 1 ;
6886       GLOBAL_library.sslist->ssar[0]    = new_ss ;
6887       GLOBAL_library.have_dummy_dataset = 0 ;
6888 
6889       /* read datasets from command line */
6890 
6891 STATUS("reading commandline dsets") ;
6892 
6893       INIT_IMARR(webtsar) ; /* 26 Mar 2001 */
6894 
6895       for( ii=GLOBAL_argopt.first_file_arg ; ii < argc ; ii++ ){
6896 
6897          /** 23 Mar 2001: modified code to deal with an array of
6898                           datasets, rather than just one at a time **/
6899 
6900          if( strstr(argv[ii],"://")      != NULL &&
6901              strstr(argv[ii],"AFNILIST") != NULL   ){ /** 23 Mar 2001: read from Web list **/
6902 
6903             dsar = THD_fetch_many_datasets( argv[ii] ) ;
6904             if( dsar == NULL || dsar->num == 0 ){
6905               fprintf(stderr,"\a\n** Can't read datasets from %s\n",argv[ii]) ;
6906               nerr++ ; continue ; /* next ii */
6907             }
6908 
6909          } else { /** read from one file (local or Web), make a small array **/
6910 
6911             dset = THD_open_dataset( argv[ii] ) ;
6912             if( dset == NULL ){
6913                fprintf(stderr,"\a\n** Can't read dataset %s\n",argv[ii]) ;
6914                nerr++ ; continue ; /* next ii */
6915             }
6916             INIT_XTARR(dsar) ; ADDTO_XTARR(dsar,dset) ;
6917             XTARR_IC(dsar,0) = IC_DSET ;
6918          }
6919 
6920          for( dd=0 ; dd < dsar->num ; dd++ ){  /* over all entries in array */
6921 
6922             /* 26 Mar 2001: might get some 1D files, too */
6923 
6924             if( XTARR_IC(dsar,dd) == IC_FLIM ){  /* save 1D file for later */
6925                MRI_IMAGE *im = (MRI_IMAGE *) XTARR_XT(dsar,dd) ;
6926                ADDTO_IMARR(webtsar,im) ;
6927                continue ;              /* next one */
6928             }
6929             if( XTARR_IC(dsar,dd) != IC_DSET ){
6930               fprintf(stderr,"\n** Unknown filetype returned from %s\n",argv[ii]) ;
6931                nerr++ ; continue ;   /* bad */
6932             }
6933 
6934             /* get to here ==> have a dataset */
6935 
6936             dset = (THD_3dim_dataset *) XTARR_XT(dsar,dd) ;
6937             if( !ISVALID_DSET(dset) ) continue ;            /* bad */
6938             AFNI_inconstancy_check(NULL,dset) ; /* 06 Sep 2006 */
6939             nds++ ;   /* increment count of dataset */
6940             REFRESH ;
6941             vv = dset->view_type ;
6942             nn = new_ss->num_dsset ;
6943             if( nn >= THD_MAX_SESSION_SIZE ){
6944               fprintf(stderr,"\a\n** too many datasets!\n") ;
6945               nerr++ ;
6946             } else {
6947               SET_SESSION_DSET(dset, new_ss, nn, vv);
6948 /*              new_ss->dsset_xform_table[nn][vv] = dset ; */
6949               new_ss->num_dsset ++ ;
6950             }
6951          } /* end of loop over dd=datasets in dsar */
6952 
6953          FREE_XTARR(dsar) ;  /* don't need array no more */
6954 
6955       } /* end of loop over ii=command line arguments past options */
6956 
6957       if( nerr > 0 ){
6958         fprintf(stderr,"** FATAL ERRORS on input\n") ; exit(1) ;  /* bad */
6959       }
6960 
6961       sprintf(str,"\n dataset count = %d" , nds ) ;
6962       if( new_ss->num_dsset == 0 ){
6963         fprintf(stderr,"\n** No datasets read from the list!\n") ;
6964         exit(1) ;
6965       }
6966       REPORT_PROGRESS(str) ;
6967 
6968 STATUS("reading timeseries files") ;
6969 
6970       GLOBAL_library.timeseries = THD_get_many_timeseries( NULL ) ;
6971 
6972       REFRESH ;
6973 
6974       if( GLOBAL_library.timeseries == NULL )
6975          INIT_IMARR(GLOBAL_library.timeseries) ;
6976 
6977       /* 26 Mar 2001: store timeseries fetched from the Web */
6978 
6979       for( dd=0 ; dd < IMARR_COUNT(webtsar) ; dd++ )
6980          AFNI_add_timeseries( IMARR_SUBIMAGE(webtsar,dd) ) ;
6981 
6982       FREE_IMARR(webtsar) ;
6983 
6984       sprintf( str , "\n Timeseries.1D = %d files read" ,
6985                IMARR_COUNT(GLOBAL_library.timeseries) ) ;
6986       REPORT_PROGRESS(str) ;
6987 
6988       /* assign the warp and anatomy parent pointers;
6989          then, make any datasets that don't exist but logically
6990          descend from the warp and anatomy parents just assigned */
6991 
6992 STATUS("checking idcodes for duplicates") ;
6993 
6994       THD_check_idcodes( GLOBAL_library.sslist ) ;
6995 
6996 #if 0
6997 STATUS("reconciling parent pointers") ;
6998 
6999       THD_reconcile_parents( GLOBAL_library.sslist ) ; /* parents from .HEAD files */
7000 
7001 STATUS("forcible adoption of unparented datasets") ;
7002 
7003       for( id=0 ; id < GLOBAL_library.sslist->num_sess ; id++ ){  /* functions w/o parents, */
7004          new_ss = GLOBAL_library.sslist->ssar[id] ;               /* forcibly get one */
7005          AFNI_force_adoption( new_ss , GLOBAL_argopt.warp_4D ) ;
7006       }
7007 #endif
7008 
7009    }  /** end of read datasets from command line **/
7010 
7011    else {  /* should never occur! */
7012 
7013      fprintf(stderr,"\a\n** Illegal Usage configuration detected!\n"); exit(1);
7014    }
7015 
7016    /** done at last **/
7017 
7018    MPROBE ; EXRETURN ;
7019 }
7020 
7021 /*--------------------------------------------------------------------------
7022   Final adjustments before a controller is opened for use - 15 Jun 2000
7023 ----------------------------------------------------------------------------*/
7024 
AFNI_startup_3dview(Three_D_View * im3d)7025 void AFNI_startup_3dview( Three_D_View *im3d )
7026 {
7027    static int old_0D_num=0 , old_2D_num=0 ;
7028 
7029 ENTRY("AFNI_startup_3dview") ;
7030 
7031    if( ! IM3D_VALID(im3d) ) EXRETURN ;
7032 
7033    /* the pbar Tran 0D menu */
7034 
7035    if( GLOBAL_library.registered_0D.num != old_0D_num ){
7036       old_0D_num = GLOBAL_library.registered_0D.num ;
7037       refit_MCW_optmenu( im3d->vwid->func->pbar_transform0D_av ,
7038                            0 ,                                 /* new minval */
7039                            GLOBAL_library.registered_0D.num ,  /* new maxval */
7040                            0 ,                                 /* new inival */
7041                            0 ,                                 /* new decim? */
7042                            ISQ_transform_label ,               /* text func  */
7043                            &(GLOBAL_library.registered_0D)     /* text data  */
7044                         ) ;
7045       XtManageChild( im3d->vwid->func->pbar_transform0D_av->wrowcol ) ;
7046    } else {
7047       if( old_0D_num == 0 )
7048         XtUnmanageChild( im3d->vwid->func->pbar_transform0D_av->wrowcol ) ;
7049    }
7050 
7051    im3d->vwid->func->pbar_transform0D_index = 0 ;
7052    im3d->vwid->func->pbar_transform0D_func  = NULL ;
7053 
7054    /* the pbar Tran 2D menu */
7055 
7056    if( GLOBAL_library.registered_2D.num != old_2D_num ){
7057       old_2D_num = GLOBAL_library.registered_2D.num ;
7058       refit_MCW_optmenu( im3d->vwid->func->pbar_transform2D_av ,
7059                            0 ,                                 /* new minval */
7060                            GLOBAL_library.registered_2D.num ,  /* new maxval */
7061                            0 ,                                 /* new inival */
7062                            0 ,                                 /* new decim? */
7063                            ISQ_transform_label ,               /* text func  */
7064                            &(GLOBAL_library.registered_2D)     /* text data  */
7065                         ) ;
7066       XtManageChild( im3d->vwid->func->pbar_transform2D_av->wrowcol ) ;
7067    } else {
7068       if( old_2D_num == 0 )
7069         XtUnmanageChild( im3d->vwid->func->pbar_transform2D_av->wrowcol ) ;
7070    }
7071 
7072    im3d->vwid->func->pbar_transform2D_index = 0 ;
7073    im3d->vwid->func->pbar_transform2D_func  = NULL ;
7074 
7075    /* 08 Apr 2005: the cursor on the pbar? */
7076 
7077    if( im3d->vwid->func->inten_pbar->bigmode )
7078      POPUP_cursorize( im3d->vwid->func->inten_pbar->panew ) ;
7079 
7080    POPUP_cursorize( im3d->vwid->view->sess_lab ) ; /* 30 Apr 2010 */
7081 
7082    /* Hey Rocky!  Watch me pull a rabbit out of my hat! */
7083 
7084    EXRETURN ;
7085 }
7086 
7087 /*--------------------------------------------------------------------------
7088    delete the viewers associated with this controller panel
7089 ---------------------------------------------------------------------------*/
7090 
AFNI_closedown_3dview(Three_D_View * im3d)7091 void AFNI_closedown_3dview( Three_D_View *im3d )
7092 {
7093 ENTRY("AFNI_closedown_3dview") ;
7094 
7095    if( ! IM3D_VALID(im3d) ) EXRETURN ;
7096 /* Mar 1999: shutoff receivers, if any */
7097 
7098    AFNI_receive_destroy( im3d ) ;
7099 
7100    /* destroy any viewers attached */
7101 
7102    drive_MCW_imseq( im3d->s123 , isqDR_destroy , NULL ) ;
7103    drive_MCW_imseq( im3d->s231 , isqDR_destroy , NULL ) ;
7104    drive_MCW_imseq( im3d->s312 , isqDR_destroy , NULL ) ;
7105 
7106    drive_MCW_grapher( im3d->g123 , graDR_destroy , NULL ) ;
7107    drive_MCW_grapher( im3d->g231 , graDR_destroy , NULL ) ;
7108    drive_MCW_grapher( im3d->g312 , graDR_destroy , NULL ) ;
7109 
7110    /* erase FD bricks */
7111 
7112    DESTROY_FD_BRICK(im3d->b123_anat) ;
7113    DESTROY_FD_BRICK(im3d->b231_anat) ;
7114    DESTROY_FD_BRICK(im3d->b312_anat) ;
7115 
7116    DESTROY_FD_BRICK(im3d->b123_fim)  ;
7117    DESTROY_FD_BRICK(im3d->b231_fim)  ;
7118    DESTROY_FD_BRICK(im3d->b312_fim)  ;
7119 
7120    im3d->b123_ulay = im3d->b231_ulay = im3d->b312_ulay = NULL ;
7121 
7122    if( XtIsManaged(im3d->vwid->view->frame) == True )
7123      AFNI_controller_panel_CB( NULL , im3d , NULL ) ;
7124 
7125    /* null out montage info */
7126 
7127    LOAD_IVEC3(im3d->vinfo->xhairs_ndown,0,0,0) ;
7128    LOAD_IVEC3(im3d->vinfo->xhairs_nup  ,0,0,0) ;
7129    LOAD_IVEC3(im3d->vinfo->xhairs_nskip,0,0,0) ;
7130 
7131    /* de-fim */
7132 
7133    AFNI_fimmer_setref(im3d,NULL) ; CLEAR_FIMDATA(im3d) ;
7134 
7135    /* Jul 2010 */
7136 
7137    CLU_free_table(im3d->vwid->func->clu_tabNN1_1sid); im3d->vwid->func->clu_tabNN1_1sid = NULL;
7138    CLU_free_table(im3d->vwid->func->clu_tabNN2_1sid); im3d->vwid->func->clu_tabNN2_1sid = NULL;
7139    CLU_free_table(im3d->vwid->func->clu_tabNN3_1sid); im3d->vwid->func->clu_tabNN3_1sid = NULL;
7140 
7141    CLU_free_table(im3d->vwid->func->clu_tabNN1_2sid); im3d->vwid->func->clu_tabNN1_2sid = NULL;
7142    CLU_free_table(im3d->vwid->func->clu_tabNN2_2sid); im3d->vwid->func->clu_tabNN2_2sid = NULL;
7143    CLU_free_table(im3d->vwid->func->clu_tabNN3_2sid); im3d->vwid->func->clu_tabNN3_2sid = NULL;
7144 
7145    CLU_free_table(im3d->vwid->func->clu_tabNN1_bsid); im3d->vwid->func->clu_tabNN1_bsid = NULL;
7146    CLU_free_table(im3d->vwid->func->clu_tabNN2_bsid); im3d->vwid->func->clu_tabNN2_bsid = NULL;
7147    CLU_free_table(im3d->vwid->func->clu_tabNN3_bsid); im3d->vwid->func->clu_tabNN3_bsid = NULL;
7148 
7149    if( im3d->vwid->func->clu_mask != NULL ){
7150      free(im3d->vwid->func->clu_mask) ; im3d->vwid->func->clu_mask = NULL ;
7151    }
7152 
7153    RESET_AFNI_QUIT(im3d) ;
7154 
7155    im3d->anat_now = im3d->fim_now = NULL ;
7156    AFNI_SEE_FUNC_OFF(im3d) ;   /* 22 May 2009 */
7157 
7158    AFNI_purge_unused_dsets() ;
7159 
7160    /* 19 Aug 2002: close surface widgets, too */
7161 
7162    if( im3d->vwid->view->swid != NULL )
7163      XtUnmapWidget( im3d->vwid->view->swid->wtop ) ;
7164 
7165    im3d->vinfo->fix_qval   = 0 ;    /* 27 Feb 2014 */
7166    im3d->vinfo->fixed_qval = 0.0f ;
7167    im3d->vinfo->fix_pval   = 0 ;    /* 27 Feb 2014 */
7168    im3d->vinfo->fixed_pval = 0.0f ;
7169 
7170    MPROBE ;
7171    EXRETURN ;
7172 }
7173 
7174 /*-------------------------------------------------------------------------
7175   Open or close the viewing controls panel
7176 ---------------------------------------------------------------------------*/
7177 
AFNI_controller_panel_CB(Widget wcall,XtPointer cd,XtPointer cbs)7178 void AFNI_controller_panel_CB( Widget wcall , XtPointer cd , XtPointer cbs )
7179 {
7180    Three_D_View *im3d = (Three_D_View *)cd ;
7181 
7182 ENTRY("AFNI_controller_panel_CB") ;
7183 
7184    if( ! IM3D_OPEN(im3d) || im3d->vwid->prog->panel_pb == NULL ) EXRETURN ;
7185 
7186    /** if view frame is open, close it and all its children **/
7187 
7188    if( XtIsManaged(im3d->vwid->view->frame) == True ){
7189 
7190       if( XtIsManaged(im3d->vwid->marks->frame) == True ){
7191          AFNI_marks_action_CB( NULL , (XtPointer) im3d , NULL ) ;
7192       }
7193 
7194       if( XtIsManaged(im3d->vwid->func->frame) ){
7195          CLOSE_PANEL(im3d,func) ;
7196       }
7197 
7198       if( XtIsManaged(im3d->vwid->dmode->frame) ){
7199          CLOSE_PANEL(im3d,dmode) ;
7200       }
7201 
7202       XtUnmanageChild(im3d->vwid->view->frame) ;
7203       if( im3d->vwid->prog->panel_pb_inverted ){
7204          MCW_invert_widget(im3d->vwid->prog->panel_pb) ;
7205          im3d->vwid->prog->panel_pb_inverted = False ;
7206       }
7207       XtUnmanageChild(im3d->vwid->forum_pb) ;
7208       XtUnmanageChild(im3d->vwid->phelp_pb) ;
7209       XtUnmanageChild(im3d->vwid->ytube_pb) ;
7210 
7211       SHIFT_TIPS( im3d , TIPS_TOTAL_SHIFT ) ;
7212       SHIFT_NEWS( im3d , TIPS_TOTAL_SHIFT ) ;
7213 
7214    } else {  /** open the view frame (but not its children) **/
7215 
7216       XtManageChild(im3d->vwid->view->frame) ;
7217       if( ! im3d->vwid->prog->panel_pb_inverted ){
7218          MCW_invert_widget(im3d->vwid->prog->panel_pb) ;
7219          im3d->vwid->prog->panel_pb_inverted = True ;
7220       }
7221       XtManageChild(im3d->vwid->forum_pb) ;
7222       XtManageChild(im3d->vwid->phelp_pb) ;
7223       XtManageChild(im3d->vwid->ytube_pb) ;
7224 
7225 
7226       SHIFT_TIPS( im3d , (im3d->vwid->view->marks_enabled) ? TIPS_MINUS_SHIFT
7227                                                            : TIPS_PLUS_SHIFT ) ;
7228       SHIFT_NEWS( im3d , (im3d->vwid->view->marks_enabled) ? TIPS_MINUS_SHIFT
7229                                                            : TIPS_PLUS_SHIFT ) ;
7230    }
7231 
7232    RESET_AFNI_QUIT(im3d) ;
7233    EXRETURN ;
7234 }
7235 
7236 /*-------------------------------------------------------------------------
7237   Called when the user selects a new option for crosshair visibility
7238 ---------------------------------------------------------------------------*/
7239 
AFNI_crosshair_visible_CB(MCW_arrowval * av,XtPointer client_data)7240 void AFNI_crosshair_visible_CB( MCW_arrowval *av , XtPointer client_data )
7241 {
7242    Three_D_View *im3d = (Three_D_View *) client_data ;
7243    int val , omold ;
7244 
7245 ENTRY("AFNI_crosshair_visible_CB") ;
7246 
7247    if( ! IM3D_VALID(im3d) ) EXRETURN ;
7248 
7249    if( av->ival == av->old_ival ) EXRETURN ;
7250 
7251    switch( av->ival ){
7252       case AFNI_XHAIRS_OFF:
7253          im3d->vinfo->crosshair_visible   = False ;
7254          im3d->vinfo->xhairs_show_montage = False ;
7255       break ;
7256 
7257       case AFNI_XHAIRS_SINGLE:
7258          im3d->vinfo->crosshair_visible   = True ;
7259          im3d->vinfo->xhairs_show_montage = False ;
7260       break ;
7261 
7262       default:                                     /* 31 Dec 1998:  */
7263       case AFNI_XHAIRS_MULTI:                      /*   new options */
7264          im3d->vinfo->crosshair_visible   = True ; /*   like Multi  */
7265          im3d->vinfo->xhairs_show_montage = True ;
7266       break ;
7267    }
7268 
7269    /* 31 Dec 1998: only allow crosshairs of some orientations */
7270 
7271    omold = im3d->vinfo->xhairs_orimask ;  /* 02 Jun 1999 */
7272 
7273    switch( av->ival ){
7274       default:                im3d->vinfo->xhairs_orimask = ORIMASK_ALL  ; break;
7275       case AFNI_XHAIRS_LR_AP: im3d->vinfo->xhairs_orimask = ORIMASK_LR_AP; break;
7276       case AFNI_XHAIRS_LR_IS: im3d->vinfo->xhairs_orimask = ORIMASK_LR_IS; break;
7277       case AFNI_XHAIRS_AP_IS: im3d->vinfo->xhairs_orimask = ORIMASK_AP_IS; break;
7278       case AFNI_XHAIRS_LR:    im3d->vinfo->xhairs_orimask = ORIMASK_LR   ; break;
7279       case AFNI_XHAIRS_AP:    im3d->vinfo->xhairs_orimask = ORIMASK_AP   ; break;
7280       case AFNI_XHAIRS_IS:    im3d->vinfo->xhairs_orimask = ORIMASK_IS   ; break;
7281    }
7282 
7283    AFNI_set_viewpoint( im3d , -1,-1,-1 , REDISPLAY_OVERLAY ) ;
7284 
7285    /* 02 Jun 1999: if xhairs layout has changed, send a notice */
7286 
7287    if( omold != im3d->vinfo->xhairs_orimask ) AFNI_process_viewpoint( im3d ) ;
7288 
7289    RESET_AFNI_QUIT(im3d) ;
7290    EXRETURN ;
7291 }
7292 
7293 /*-----------------------------------------------------------------*/
7294 
AFNI_wrap_bbox_CB(Widget w,XtPointer client_data,XtPointer call_data)7295 void AFNI_wrap_bbox_CB( Widget w ,
7296                         XtPointer client_data , XtPointer call_data )
7297 {
7298    Three_D_View *im3d = (Three_D_View *) client_data ;
7299    int bval ;
7300 
7301 ENTRY("AFNI_wrap_bbox_CB") ;
7302 
7303    if( ! IM3D_VALID(im3d) ) EXRETURN ;
7304 
7305    bval = MCW_val_bbox( im3d->vwid->imag->wrap_bbox ) ;
7306 
7307    if( (RwcBoolean) bval == im3d->vinfo->xhairs_periodic ) EXRETURN ;
7308 
7309    im3d->vinfo->xhairs_periodic = (RwcBoolean) bval ;
7310 
7311    if( w != NULL ){
7312       drive_MCW_imseq( im3d->s123, isqDR_periodicmont, (XtPointer)ITOP(bval) );
7313       drive_MCW_imseq( im3d->s231, isqDR_periodicmont, (XtPointer)ITOP(bval) );
7314       drive_MCW_imseq( im3d->s312, isqDR_periodicmont, (XtPointer)ITOP(bval) );
7315    }
7316 
7317    RESET_AFNI_QUIT(im3d) ;
7318    EXRETURN ;
7319 }
7320 
7321 /*-----------------------------------------------------------------*/
7322 
AFNI_xhall_bbox_CB(Widget w,XtPointer client_data,XtPointer call_data)7323 void AFNI_xhall_bbox_CB( Widget w ,
7324                          XtPointer client_data , XtPointer call_data )
7325 {
7326    Three_D_View *im3d = (Three_D_View *) client_data ;
7327    int bval ;
7328 
7329 ENTRY("AFNI_xhall_bbox_CB") ;
7330 
7331    if( ! IM3D_VALID(im3d) ) EXRETURN ;
7332 
7333    bval = MCW_val_bbox( im3d->vwid->imag->xhall_bbox ) ;
7334 
7335    if( (RwcBoolean) bval == im3d->vinfo->xhairs_all ) EXRETURN ;
7336 
7337    im3d->vinfo->xhairs_all = (RwcBoolean) bval ;
7338 
7339    if( im3d->vinfo->crosshair_visible ){
7340       AFNI_set_viewpoint( im3d , -1,-1,-1 , REDISPLAY_OVERLAY ) ;
7341    }
7342 
7343    RESET_AFNI_QUIT(im3d) ;
7344    EXRETURN ;
7345 }
7346 
7347 /*------------------------------------------------------------------------*/
7348 
AFNI_crosshair_color_CB(MCW_arrowval * av,XtPointer client_data)7349 void AFNI_crosshair_color_CB( MCW_arrowval *av , XtPointer client_data )
7350 {
7351    Three_D_View *im3d = (Three_D_View *) client_data ;
7352    int ipx = av->ival ;
7353 
7354 ENTRY("AFNI_crosshair_color_CB") ;
7355 
7356    if( ! IM3D_VALID(im3d) ) EXRETURN ;
7357 
7358    im3d->vinfo->crosshair_ovcolor = ipx ;
7359    if( im3d->vinfo->crosshair_visible ){
7360       AFNI_set_viewpoint( im3d , -1,-1,-1 , REDISPLAY_OVERLAY ) ;
7361    }
7362 
7363    RESET_AFNI_QUIT(im3d) ;
7364    EXRETURN ;
7365 }
7366 
7367 /*------------------------------------------------------------------------*/
7368 
AFNI_crosshair_gap_CB(MCW_arrowval * av,XtPointer client_data)7369 void AFNI_crosshair_gap_CB( MCW_arrowval *av ,  XtPointer client_data )
7370 {
7371    Three_D_View *im3d = (Three_D_View *) client_data ;
7372    int ipx ;
7373 
7374 ENTRY("AFNI_crosshair_gap_CB") ;
7375 
7376    if( ! IM3D_VALID(im3d) ) EXRETURN ;
7377 
7378    if( av != NULL ){
7379       ipx = av->ival ;
7380    } else {
7381       if( im3d->vinfo->crosshair_gap_old > 0 ){
7382          ipx = im3d->vinfo->crosshair_gap_old ;
7383          im3d->vinfo->crosshair_gap_old = 0 ;
7384       } else {
7385          im3d->vinfo->crosshair_gap_old = im3d->vinfo->crosshair_gap ;
7386          ipx = 0 ;
7387       }
7388    }
7389 
7390    im3d->vinfo->crosshair_gap = ipx ;
7391    if( im3d->vinfo->crosshair_visible ){
7392       AFNI_set_viewpoint( im3d , -1,-1,-1 , REDISPLAY_OVERLAY ) ;
7393    }
7394 
7395    RESET_AFNI_QUIT(im3d) ;
7396    EXRETURN ;
7397 }
7398 
7399 /*------------------------------------------------------------------------*/
7400 
AFNI_time_index_set_fstep(Three_D_View * im3d,int istep)7401 void AFNI_time_index_set_fstep( Three_D_View *im3d , int istep )
7402 {
7403    MCW_arrowval *av ; char lll[16] ;
7404 
7405 ENTRY("AFNI_time_index_set_fstep") ;
7406 
7407    if( ! IM3D_VALID(im3d) ) EXRETURN ;
7408 
7409    if( istep < 1 ) istep = 1 ; else if( istep > 9 ) istep = 9 ;
7410 
7411    av = im3d->vwid->imag->time_index_av ;
7412 
7413    if( istep == 1 ) strcpy(lll, "Index ") ;
7414    else             sprintf(lll,"Idx[%d]",istep) ;
7415 
7416    MCW_set_widget_label( av->wlabel , lll ) ;
7417    av->fstep = (istep == 1) ? 0.0f : (float)istep ;
7418    EXRETURN ;
7419 }
7420 
7421 /*------------------------------------------------------------------------*/
7422 
7423 static char *yesno[2] = { "No" , "Yes" } ;
7424 static char *throx[3] = { "free" , " == " , " +1 " } ;
7425 
AFNI_time_index_step_CB(Widget w,XtPointer cd,int nval,void ** val)7426 void AFNI_time_index_step_CB( Widget w, XtPointer cd, int nval , void **val )
7427 {
7428    Three_D_View *im3d = (Three_D_View *)cd ;
7429    char *cpt , cmd[128] ; MCW_bbox *bb ; int ib ;
7430 
7431 ENTRY("AFNI_time_index_step_CB") ;
7432 
7433    if( ! IM3D_VALID(im3d) || nval != 3 || val == NULL ) EXRETURN ;
7434 
7435    AFNI_time_index_set_fstep( im3d , (int)(intptr_t)val[0] ) ;
7436 
7437    sprintf(cmd,"AFNI_SLAVE_FUNCTIME %s",(char *)val[1]) ;
7438    (void)AFNI_setenv(cmd) ;
7439 
7440    cpt = (char *)val[2] ;
7441    bb  = im3d->vwid->func->thr_olayx_bbox ; ib = MCW_val_bbox(bb) ;
7442    if( strcmp(cpt,throx[1]) == 0 ){        /* Thr = OLay */
7443      if( ib != 1 ) MCW_set_bbox(bb,1) ;
7444    } else if( strcmp(cpt,throx[2]) == 0 ){ /* Thr = Olay + 1 */
7445      if( ib != 2 ) MCW_set_bbox(bb,2) ;
7446    } else {                                /* Thr = free and wild */
7447      if( ib != 0 ) MCW_set_bbox(bb,0) ;
7448    }
7449    AFNI_throlayx_change_CB(NULL,im3d,NULL) ;
7450    EXRETURN ;
7451 }
7452 
7453 /*------------------------------------------------------------------------*/
7454 
AFNI_time_index_EV(Widget w,XtPointer cd,XEvent * ev,RwcBoolean * continue_to_dispatch)7455 void AFNI_time_index_EV( Widget w , XtPointer cd ,
7456                          XEvent *ev , RwcBoolean *continue_to_dispatch )
7457 {
7458    Three_D_View *im3d = (Three_D_View *)cd ;
7459 
7460 ENTRY("AFNI_time_index_EV") ;
7461 
7462    if( ! IM3D_OPEN(im3d) ) EXRETURN ;
7463 
7464    /*** handle events ***/
7465 
7466    switch( ev->type ){
7467 
7468      /*----- take button press -----*/
7469 
7470      case ButtonPress:{
7471        XButtonEvent *event = (XButtonEvent *)ev ;
7472 
7473        if( event->button == Button3 ){
7474          int istep = (int)im3d->vwid->imag->time_index_av->fstep ;
7475          int sftin , thrin ;
7476 
7477          if( istep < 1 ) istep = 1 ; else if( istep > 9 ) istep = 9 ;
7478          sftin = ( !AFNI_noenv("AFNI_SLAVE_FUNCTIME") ) ? 1 : 0 ;
7479          thrin = im3d->vinfo->thr_olayx ; if( thrin < 0 || thrin > 2 ) thrin = 0 ;
7480 
7481          MCW_choose_stuff( im3d->vwid->imag->time_index_av->wlabel ,
7482                              "Time Index Stepping" ,
7483                              AFNI_time_index_step_CB , im3d ,
7484                              MSTUF_INT ,     "Index Step     " , 1 , 9     , istep ,
7485                              MSTUF_STRLIST , "SLAVE_FUNCTIME " , 2 , sftin , yesno ,
7486                              MSTUF_STRLIST , "Thr = Olay?+1? " , 3 , thrin , throx ,
7487                            MSTUF_END ) ;
7488        } else if( event->button == Button4 ){
7489          int istep = (int)im3d->vwid->imag->time_index_av->fstep ;
7490          if( istep < 1 ) istep = 1 ; else if( istep > 9 ) istep = 9 ;
7491          AFNI_time_index_set_fstep( im3d , istep-1 ) ;
7492        } else if( event->button == Button5 ){
7493          int istep = (int)im3d->vwid->imag->time_index_av->fstep ;
7494          if( istep < 1 ) istep = 1 ; else if( istep > 9 ) istep = 9 ;
7495          AFNI_time_index_set_fstep( im3d , istep+1 ) ;
7496        } else {
7497          (void) MCW_popup_message(
7498                    im3d->vwid->imag->time_index_av->wlabel ,
7499                    (event->button == Button1) ?  " \n I really wish you "
7500                                                  "\n wouldn't do that! \n "
7501                                               :  " \n   Why do you "
7502                                                  "\n torment me so? \n "
7503                  , MCW_USER_KILL | MCW_QUICK_KILL ) ;
7504        }
7505      }
7506      break ;
7507    }
7508 
7509    EXRETURN ;
7510 }
7511 
7512 /*------------------------------------------------------------------------*/
7513 
AFNI_time_index_CB(MCW_arrowval * av,XtPointer client_data)7514 void AFNI_time_index_CB( MCW_arrowval *av ,  XtPointer client_data )
7515 {
7516    Three_D_View *im3d = (Three_D_View *) client_data ;
7517    int ipx ;
7518 
7519 ENTRY("AFNI_time_index_CB") ;
7520 
7521    if( ! IM3D_OPEN(im3d) ) EXRETURN ;
7522 
7523    ipx = av->ival ;
7524    if( ipx >= im3d->vinfo->top_index )    /* don't let index be too big */
7525      ipx = im3d->vinfo->top_index - 1 ;
7526 
7527    im3d->vinfo->time_index = ipx ;        /* change time index */
7528 
7529    /* 29 Jul 2003: slave underlay and overlay to time_index (maybe) */
7530 
7531    im3d->vinfo->anat_index = ipx ;
7532    if( im3d->vinfo->anat_index >= DSET_NVALS(im3d->anat_now) )
7533      im3d->vinfo->anat_index = DSET_NVALS(im3d->anat_now) - 1 ;
7534    AV_assign_ival( im3d->vwid->func->anat_buck_av , im3d->vinfo->anat_index ) ;
7535 
7536    if( ISVALID_DSET(im3d->fim_now)       &&
7537        DSET_NVALS(im3d->fim_now) > 1     &&
7538        !AFNI_noenv("AFNI_SLAVE_FUNCTIME")  ){
7539 
7540      im3d->vinfo->fim_index = ipx ;
7541      if( im3d->vinfo->fim_index >= DSET_NVALS(im3d->fim_now) )
7542        im3d->vinfo->fim_index = DSET_NVALS(im3d->fim_now) - 1 ;
7543      AV_assign_ival( im3d->vwid->func->fim_buck_av , im3d->vinfo->fim_index ) ;
7544 
7545 #if 0
7546      if( AFNI_yesenv("AFNI_SLAVE_THRTIME") ){   /* 24 Jan 2005 - RWCox */
7547        im3d->vinfo->thr_index = ipx ;
7548        if( im3d->vinfo->thr_index >= DSET_NVALS(im3d->fim_now) )
7549          im3d->vinfo->thr_index = DSET_NVALS(im3d->fim_now) - 1 ;
7550        AV_assign_ival( im3d->vwid->func->thr_buck_av , im3d->vinfo->thr_index ) ;
7551      } else {
7552        AFNI_enforce_throlayx(im3d) ;  /* 13 Aug 2010 */
7553      }
7554 #else
7555        AFNI_enforce_throlayx(im3d) ;
7556 #endif
7557    }
7558 
7559    im3d->vinfo->tempflag = 1 ;
7560    AFNI_modify_viewing( im3d , False ) ;  /* setup new bricks to view */
7561 
7562    if( im3d->vinfo->fix_pval && im3d->vinfo->fixed_pval > 0.0f )
7563      AFNI_set_pval(im3d,im3d->vinfo->fixed_pval) ;
7564    else if( im3d->vinfo->fix_qval && im3d->vinfo->fixed_qval > 0.0f )
7565      AFNI_set_qval(im3d,im3d->vinfo->fixed_qval) ;
7566 
7567    if( ISVALID_DSET(im3d->fim_now)       &&   /* if time index on */
7568        DSET_NUM_TIMES(im3d->fim_now) > 1   )  /* function changed */
7569      AFNI_process_funcdisplay( im3d ) ;       /* notify receivers */
7570 
7571    AFNI_time_lock_carryout( im3d ) ;  /* 03 Nov 1998 */
7572    AFNI_process_timeindex ( im3d ) ;  /* 29 Jan 2003 */
7573 
7574    RESET_AFNI_QUIT(im3d) ;
7575    EXRETURN ;
7576 }
7577 
7578 /*-------------------------------------------------------------------------*/
7579 /* Set rinfo label in an image viewer */
7580 
AFNI_set_rinfo_labels(Three_D_View * im3d)7581 void AFNI_set_rinfo_labels( Three_D_View *im3d )
7582 {
7583    float angle ;
7584    char *label ;
7585    MCW_imseq   *ssss ;
7586 
7587    if( !IM3D_OPEN(im3d) ) return ;
7588 
7589    angle = THD_compute_oblique_angle(im3d->anat_now->daxes->ijk_to_dicom_real,0) ;
7590    label = (angle < 1.0f) ? "Card" : "Obliq" ;
7591 
7592    ssss = im3d->s123 ;
7593    if( ssss != NULL && ISQ_REALZ(ssss) )
7594      drive_MCW_imseq( ssss , isqDR_rinfolabel , label ) ;
7595 
7596    ssss = im3d->s231 ;
7597    if( ssss != NULL && ISQ_REALZ(ssss) )
7598      drive_MCW_imseq( ssss , isqDR_rinfolabel , label ) ;
7599 
7600    ssss = im3d->s312 ;
7601    if( ssss != NULL && ISQ_REALZ(ssss) )
7602      drive_MCW_imseq( ssss , isqDR_rinfolabel , label ) ;
7603 
7604    return ;
7605 }
7606 
7607 /*-------------------------------------------------------------------------
7608    Start a view (12-3, 23-1, or 31-2)
7609 ---------------------------------------------------------------------------*/
7610 
7611 static char * AFNI_image_help =
7612  "Button 1      = Set crosshair location\n"
7613  "Button 3      = Pop up image menu\n"
7614  "Shift+Button2 = drag crop region\n"
7615  "Scrollwheel   = change slice up/down\n"
7616  "Alt/Opt-Scrollwheel = adjust threshold\n"
7617  "\n"
7618  "q   = close window          a = fix aspect ratio\n"
7619  "p   = toggle panning mode   c = crop image mode\n"
7620  "s   = sharpen image         m = toggle Min-to-Max\n"
7621  "D   = open Disp panel       M = open Montage panel\n"
7622  "S   = Save image            l = left-right mirror\n"
7623  "[   = time index down 1     ] = time index up 1\n"
7624  "i/I = image frac down/up  z/Z = zoom out/in\n"
7625  "> = Page Up   = forward  1 image (e.g., slice)\n"
7626  "< = Page Down = backward 1 image (e.g., slice)\n"
7627  "Ctrl+m = cycle through image global range settings\n"
7628  "o = toggle (color) overlay on/off\n"
7629  "u = toggle background from underlay/overlay dataset\n"
7630  "U = toggle background in ALL image viewers\n"
7631  "e = toggle edge detection in underlay\n"
7632  "#/3 = toggle underlay/overlay checkerboard display\n"
7633  "4 or 5 or 6 = slider for merging ULay/OLay images\n"
7634  "v/V = Video image sequence up/down\n"
7635  "r/R = Ricochet image sequence up/down\n"
7636  "Del = drawing undo       F1 = Help!\n"
7637  "F2  = drawing pencil     F3 = drawing value --\n"
7638  "F4  = drawing value ++   F5 = Meltdown!!\n"
7639  "Left/Right/Up/Down arrow keys\n"
7640  "    = move crosshairs OR pan zoomed image\n"
7641  "Shift+keyboard arrow keys = pan crop region around\n"
7642  "Ctrl+keyboard arrow keys  = expand/shrink crop region\n"
7643  "Shift+Home = center crop region on current crosshairs\n"
7644  "--- THESE NEXT KEYSTROKES OPERATE WITH CLUSTERIZE ---\n"
7645  "j = Jump to nearest cluster's peak (or cmass)\n"
7646  "f = Flash current cluster (if Xhairs inside one)\n"
7647  "n/N = Jump to next/previous cluster's peak/cmass"
7648 ;
7649 
7650 static char * AFNI_arrowpad_help =
7651    "THD_compute_oblique_angle(dset->daxes->ijk_to_dicom_realClick arrows to scroll crosshair position\n"
7652    "Click button to open/close crosshair gap " ;
7653 
7654 static char * AFNI_arrowpad_hint[] = {
7655   "Scroll crosshairs down" ,
7656   "Scroll crosshairs up" ,
7657   "Scroll crosshairs left" ,
7658   "Scroll crosshairs right" ,
7659   "Close/open crosshairs gap"
7660 } ;
7661 
7662 #undef  WID2EV
7663 #define WID2EV(w,ev) XtVaSetValues( (w), XmNx,(int)((ev)->x_root)-24,       \
7664                                          XmNy,(int)((ev)->y_root)-4 , NULL )
7665 
7666 /*.........................................................................*/
7667 
AFNI_view_xyz_CB(Widget w,XtPointer client_data,XtPointer call_data)7668 void AFNI_view_xyz_CB( Widget w ,
7669                        XtPointer client_data , XtPointer call_data )
7670 {
7671    Three_D_View *im3d = (Three_D_View *)client_data ;
7672    MCW_imseq   *sxyz , *syzx , *szxy , **snew = NULL ;
7673    MCW_grapher *gxyz , *gyzx , *gzxy , **gnew = NULL ;
7674    Widget        pboff , pb_xyz , pb_yzx , pb_zxy ;
7675    Widget        groff , gr_xyz , gr_yzx , gr_zxy ;
7676    FD_brick    *brnew ;
7677    int mirror=0 ;
7678    int m2m=0 ;     /* 04 Nov 2003 */
7679    int c2c=0 ;     /* 17 Sep 2007 */
7680    XmPushButtonCallbackStruct *cbs = (XmPushButtonCallbackStruct *)call_data ;
7681    XButtonEvent *event = NULL ;
7682 
7683 ENTRY("AFNI_view_xyz_CB") ;
7684 
7685    if( ! IM3D_OPEN(im3d) ) EXRETURN ;
7686 
7687    if( cbs != NULL ) event = (XButtonEvent *)cbs->event ;
7688 
7689     sxyz = im3d->s123 ; gxyz = im3d->g123 ;
7690     syzx = im3d->s231 ; gyzx = im3d->g231 ;
7691     szxy = im3d->s312 ; gzxy = im3d->g312 ;
7692 
7693     pb_xyz = im3d->vwid->imag->image_xyz_pb ;
7694     pb_yzx = im3d->vwid->imag->image_yzx_pb ;
7695     pb_zxy = im3d->vwid->imag->image_zxy_pb ;
7696 
7697     gr_xyz = im3d->vwid->imag->graph_xyz_pb ;
7698     gr_yzx = im3d->vwid->imag->graph_yzx_pb ;
7699     gr_zxy = im3d->vwid->imag->graph_zxy_pb ;
7700 
7701     /* handle case of button press of already
7702        open window by bringing that window to the top */
7703 
7704     if( w == pb_xyz && sxyz != NULL ){
7705        if( ISQ_REALZ(sxyz) ){
7706           if( AFNI_yesenv("AFNI_IMAGRA_CLOSER") )
7707             drive_MCW_imseq( sxyz , isqDR_destroy , NULL ) ;
7708           else
7709             XMapRaised( XtDisplay(sxyz->wtop) , XtWindow(sxyz->wtop) ) ;
7710        }
7711        EXRETURN ;
7712     } else if( w == pb_yzx && syzx != NULL ){
7713        if( ISQ_REALZ(syzx) ){
7714           if( AFNI_yesenv("AFNI_IMAGRA_CLOSER") )
7715             drive_MCW_imseq( syzx , isqDR_destroy , NULL ) ;
7716           else
7717             XMapRaised( XtDisplay(syzx->wtop) , XtWindow(syzx->wtop) ) ;
7718        }
7719        EXRETURN ;
7720     } else if( w == pb_zxy && szxy != NULL ){
7721        if( ISQ_REALZ(szxy) ){
7722           if( AFNI_yesenv("AFNI_IMAGRA_CLOSER") )
7723             drive_MCW_imseq( szxy , isqDR_destroy , NULL ) ;
7724           else
7725             XMapRaised( XtDisplay(szxy->wtop) , XtWindow(szxy->wtop) ) ;
7726        }
7727        EXRETURN ;
7728     } else if( w == gr_xyz && gxyz != NULL ){
7729        if( GRA_REALZ(gxyz) ){
7730           if( AFNI_yesenv("AFNI_IMAGRA_CLOSER") )
7731             drive_MCW_grapher( gxyz , graDR_destroy , NULL ) ;
7732           else
7733             XMapRaised( XtDisplay(gxyz->fdw_graph) , XtWindow(gxyz->fdw_graph) ) ;
7734        }
7735        EXRETURN ;
7736     } else if( w == gr_yzx && gyzx != NULL ){
7737        if( GRA_REALZ(gyzx) ){
7738           if( AFNI_yesenv("AFNI_IMAGRA_CLOSER") )
7739             drive_MCW_grapher( gyzx , graDR_destroy , NULL ) ;
7740           else
7741             XMapRaised( XtDisplay(gyzx->fdw_graph) , XtWindow(gyzx->fdw_graph) ) ;
7742        }
7743        EXRETURN ;
7744     } else if( w == gr_zxy && gzxy != NULL ){
7745        if( GRA_REALZ(gzxy) ){
7746           if( AFNI_yesenv("AFNI_IMAGRA_CLOSER") )
7747             drive_MCW_grapher( gzxy , graDR_destroy , NULL ) ;
7748           else
7749             XMapRaised( XtDisplay(gzxy->fdw_graph) , XtWindow(gzxy->fdw_graph) ) ;
7750        }
7751        EXRETURN ;
7752     }
7753 
7754     /* button pressed and window not open, so prepare to open it */
7755 
7756     m2m = AFNI_yesenv("AFNI_IMAGE_MINTOMAX") ;
7757     c2c = AFNI_yesenv("AFNI_IMAGE_CLIPPED") ;  /* 17 Sep 2007 */
7758 
7759     if( !IM3D_ULAY_COHERENT(im3d) ){           /* 10 Jun 2014 */
7760       STATUS("incoherent ulay -- patching") ;
7761       ERROR_message("AFNI_view_xyz_CB: incoherent ulay -- patching") ;
7762       AFNI_assign_ulay_bricks(im3d) ;
7763     }
7764 
7765     if( w == pb_xyz && sxyz == NULL ){         /* axial image */
7766        snew  = &(im3d->s123) ;
7767        brnew = im3d->b123_ulay ;
7768        pboff = pb_xyz ;
7769        mirror= GLOBAL_argopt.left_is_left ;
7770 
7771     } else if( w == pb_yzx && syzx == NULL ){  /* sagittal image */
7772        snew  = &(im3d->s231) ;
7773        brnew = im3d->b231_ulay ;
7774        pboff = pb_yzx ;
7775        mirror= GLOBAL_argopt.left_is_posterior ;
7776 
7777     } else if( w == pb_zxy && szxy == NULL ){  /* coronal image */
7778        snew  = &(im3d->s312) ;
7779        brnew = im3d->b312_ulay ;
7780        pboff = pb_zxy ;
7781        mirror= GLOBAL_argopt.left_is_left ;
7782 
7783     } else if( w == gr_xyz && gxyz == NULL ){  /* axial graph */
7784        gnew  = &(im3d->g123) ;
7785        brnew = im3d->b123_ulay ;
7786        pboff = gr_xyz ;
7787        mirror= GLOBAL_argopt.left_is_left ;
7788 
7789     } else if( w == gr_yzx && gyzx == NULL ){  /* sagittal graph */
7790        gnew  = &(im3d->g231) ;
7791        brnew = im3d->b231_ulay ;
7792        pboff = gr_yzx ;
7793        mirror= GLOBAL_argopt.left_is_posterior ;
7794 
7795     } else if( w == gr_zxy && gzxy == NULL ){  /* coronal graph */
7796        gnew  = &(im3d->g312) ;
7797        brnew = im3d->b312_ulay ;
7798        pboff = gr_zxy ;
7799        mirror= GLOBAL_argopt.left_is_left ;
7800 
7801     } else
7802        EXRETURN ;  /* something funny */
7803 
7804     /** Mar 1997: don't open if x or y dimension is 1 **/
7805 
7806     if( snew != NULL && (brnew->n1 < 2 || brnew->n2 < 2) ) EXRETURN  ;
7807 
7808     SHOW_AFNI_PAUSE ;
7809 
7810     if( snew != NULL ){
7811 STATUS("opening an image window") ;
7812       MCW_invert_widget(pboff) ;
7813       POPUP_cursorize(pboff) ;   /* 20 Jul 2005 */
7814       *snew = open_MCW_imseq( im3d->dc, AFNI_brick_to_mri, (XtPointer) brnew ) ;
7815 
7816       (*snew)->parent = (XtPointer)im3d ;
7817 
7818       INIT_BKGD_LAB(im3d) ;
7819 
7820       drive_MCW_imseq( *snew, isqDR_imhelptext, (XtPointer) AFNI_image_help ) ;
7821       drive_MCW_imseq( *snew, isqDR_arrowpadon, (XtPointer) AFNI_arrowpad_help ) ;
7822       drive_MCW_imseq( *snew, isqDR_arrowpadhint , (XtPointer) AFNI_arrowpad_hint );
7823 STATUS("realizing new image viewer") ;
7824       drive_MCW_imseq( *snew, isqDR_ignore_redraws, (XtPointer) 1 ) ; /* 16 Aug 2002 */
7825       drive_MCW_imseq( *snew, isqDR_realize, NULL ) ;
7826       AFNI_sleep(17) ;                                                /* 17 Oct 2005 */
7827       drive_MCW_imseq( *snew, isqDR_title, (XtPointer) im3d->window_title ) ;
7828 if( !AFNI_yesenv("TMONT") )
7829       drive_MCW_imseq( *snew, isqDR_periodicmont,
7830                       (XtPointer)ITOP(im3d->vinfo->xhairs_periodic) );
7831       drive_MCW_imseq( *snew , isqDR_allowmerger , NULL ) ;           /* 25 Aug 2014 */
7832       AFNI_set_rinfo_labels( im3d ) ;                                 /* 11 Mar 2020 */
7833 
7834       /* 09 Oct 1998: force L-R mirroring on axial and coronal images? */
7835       /* 04 Nov 2003: or min-to-max on grayscaling? */
7836 
7837       if( mirror || m2m || c2c ){
7838          ISQ_options opt ;
7839 
7840 STATUS("setting image view to be L-R mirrored") ;
7841 
7842          ISQ_DEFAULT_OPT(opt) ;
7843          if( mirror ) opt.mirror = TRUE ;
7844          if( m2m    ) opt.scale_range = ISQ_RNG_MINTOMAX ;
7845          if( c2c    ) opt.scale_range = ISQ_RNG_CLIPPED ;
7846          drive_MCW_imseq( *snew,isqDR_options  ,(XtPointer) &opt ) ;
7847       }
7848 
7849 #if 0
7850       /* 23 Jan 2003: set default save? */
7851 
7852       drive_MCW_imseq( *snew , isqDR_setimsave ,
7853                        (XtPointer)getenv("AFNI_DEFAULT_IMSAVE") ) ;
7854 #endif
7855 
7856 #ifdef USE_SIDES
7857 #undef  LL
7858 #undef  RR
7859 #undef  AA
7860 #undef  PP
7861 #undef  SS
7862 #undef  II
7863 #define LL 0
7864 #define RR 1
7865 #define AA 2
7866 #define PP 3
7867 #define SS 4
7868 #define II 5
7869       if( !AFNI_yesenv("AFNI_NO_SIDES_LABELS") ){
7870          static char *ssix[6] = { "Left"     , "Right"     ,
7871                                   "Anterior" , "Posterior" ,
7872                                   "Superior" , "Inferior"   } ;
7873          char *ws[4] ;
7874 
7875          if( *snew == im3d->s123 ){
7876            ws[0] = ssix[RR]; ws[1] = ssix[AA]; ws[2] = ssix[LL]; ws[3] = ssix[PP];
7877          } else if( *snew == im3d->s231 ){
7878            ws[0] = ssix[AA]; ws[1] = ssix[SS]; ws[2] = ssix[PP]; ws[3] = ssix[II];
7879          } else if( *snew == im3d->s312 ){
7880            ws[0] = ssix[RR]; ws[1] = ssix[SS]; ws[2] = ssix[LL]; ws[3] = ssix[II];
7881          } else {
7882            ws[0] = ws[1] = ws[2] = ws[3] = NULL ;
7883          }
7884 
7885 STATUS("setting image viewer 'sides'") ;
7886 
7887          drive_MCW_imseq( *snew,isqDR_winfosides,(XtPointer)ws ) ;
7888 
7889          /* 10 Dec 2007: label image orientation */
7890 
7891          if( *snew == im3d->s123 )
7892            drive_MCW_imseq( *snew,isqDR_winfoprefix,(XtPointer)"Axial" ) ;
7893          else if( *snew == im3d->s231 )
7894            drive_MCW_imseq( *snew,isqDR_winfoprefix,(XtPointer)"Sagittal" ) ;
7895          else if( *snew == im3d->s312 )
7896            drive_MCW_imseq( *snew,isqDR_winfoprefix,(XtPointer)"Coronal" ) ;
7897 
7898       }
7899 #undef LL
7900 #undef RR
7901 #undef AA
7902 #undef PP
7903 #undef SS
7904 #undef II
7905 #endif
7906 
7907       AFNI_toggle_drawing( im3d ) ;
7908 
7909 #ifndef DONT_INSTALL_ICONS
7910       if( afni48_good ){
7911          Pixmap pm = XmUNSPECIFIED_PIXMAP ;
7912 
7913               if( w == pb_xyz ) pm = afni48axi_pixmap ;
7914          else if( w == pb_yzx ) pm = afni48sag_pixmap ;
7915          else if( w == pb_zxy ) pm = afni48cor_pixmap ;
7916 
7917          drive_MCW_imseq( *snew, isqDR_icon , (XtPointer) pm ) ;
7918       }
7919 #endif
7920       { int ii=AFNI_controller_index(im3d) ;
7921         if( ii >= 0 )
7922          drive_MCW_imseq( *snew, isqDR_bgicon, (XtPointer)afni16_pixmap[ii] ) ;
7923       }
7924 
7925       if( AFNI_yesenv("AFNI_OPACITY_LOCK") )                 /* 06 Jun 2019 */
7926         drive_MCW_imseq( *snew, isqDR_setopacity,
7927                          (XtPointer)ITOP(GLOBAL_library.opacity_setting) );
7928 
7929       drive_MCW_imseq( *snew, isqDR_ignore_redraws, (XtPointer) 0 ) ; /* 16 Aug 2002 */
7930 
7931       AFNI_view_setter ( im3d , *snew ) ;
7932       AFNI_range_setter( im3d , *snew ) ;  /* 04 Nov 2003 */
7933       AFNI_sleep(17) ;                     /* 17 Oct 2005 */
7934       if( event != NULL ) WID2EV( (*snew)->wtop , event ) ;  /* 23 Nov 2010 */
7935 
7936     } /* end of creating a new image viewer */
7937 
7938     /** Don't forget to send information like the reference timeseries ... **/
7939 
7940     if( gnew != NULL && DSET_GRAPHABLE(brnew->dset) ){
7941        MCW_grapher *gr ;
7942 
7943 STATUS("opening a graph window") ;
7944 
7945        MCW_invert_widget(pboff) ;
7946        POPUP_cursorize(pboff) ;   /* 20 Jul 2005 */
7947        gr = new_MCW_grapher( im3d->dc , AFNI_brick_to_mri , (XtPointer) brnew ) ;
7948        drive_MCW_grapher( gr, graDR_title, (XtPointer) im3d->window_title );
7949        drive_MCW_grapher( gr, graDR_addref_ts, (XtPointer) im3d->fimdata->fimref );
7950        drive_MCW_grapher( gr, graDR_setignore, (XtPointer)ITOP(im3d->fimdata->init_ignore) );
7951        drive_MCW_grapher( gr, graDR_polort, (XtPointer)ITOP(im3d->fimdata->polort) );
7952        drive_MCW_grapher( gr, graDR_setindex , (XtPointer)ITOP(im3d->vinfo->time_index) );
7953 
7954        if( im3d->type == AFNI_IMAGES_VIEW )
7955           drive_MCW_grapher( gr , graDR_fim_disable , NULL ) ; /* 19 Oct 1999 */
7956 
7957        if( mirror )                                            /* 12 Jul 2000 */
7958           drive_MCW_grapher( gr , graDR_mirror , (XtPointer) 1 ) ;
7959 
7960        /* 07 Aug 2001: set global baseline level, if possible */
7961 
7962        if( ISVALID_STATISTIC(brnew->dset->stats) ){
7963          char *eee = getenv( "AFNI_GRAPH_GLOBALBASE" ) ;  /* 08 Mar 2002 */
7964          if( eee == NULL ){                               /* skip this? */
7965            float vbot=WAY_BIG ; int ii ;
7966            for( ii=0 ; ii < brnew->dset->stats->nbstat ; ii++ )
7967              if( ISVALID_BSTAT(brnew->dset->stats->bstat[ii]) )
7968                vbot = MIN( vbot , brnew->dset->stats->bstat[ii].min ) ;
7969 
7970            if( vbot < WAY_BIG )
7971              drive_MCW_grapher( gr, graDR_setglobalbaseline, (XtPointer)&vbot );
7972          }
7973        }
7974 
7975 STATUS("realizing new grapher") ;
7976 
7977        drive_MCW_grapher( gr , graDR_realize , NULL ) ;
7978 
7979        *gnew = gr ;
7980        (*gnew)->parent = (XtPointer) im3d ;
7981 
7982 #ifndef DONT_INSTALL_ICONS
7983       if( afni48_good ){
7984          Pixmap pm = XmUNSPECIFIED_PIXMAP ;
7985 
7986               if( w == gr_xyz ) pm = afni48graaxi_pixmap ;
7987          else if( w == gr_yzx ) pm = afni48grasag_pixmap ;
7988          else if( w == gr_zxy ) pm = afni48gracor_pixmap ;
7989 
7990          drive_MCW_grapher( gr , graDR_icon , (XtPointer) pm ) ;
7991       }
7992 #endif
7993 
7994       AFNI_sleep(17) ;
7995       if( event != NULL ) WID2EV( gr->fdw_graph , event ) ;  /* 23 Nov 2010 */
7996 
7997     } /* end of creating a new graph viewer */
7998 
7999    /*-- force a jump to the viewpoint of the current location --*/
8000 
8001    XSync( im3d->dc->display , False ) ;
8002    AFNI_set_viewpoint( im3d , -1,-1,-1 , REDISPLAY_ALL ) ;
8003 
8004    SHOW_AFNI_READY ;
8005    RESET_AFNI_QUIT(im3d) ;
8006 
8007    MPROBE ;
8008    EXRETURN ;
8009 }
8010 
8011 /*--------------------------------------------------------------------------*/
8012 /* Button-3 click on an Image or Graph button:
8013    recall the corresponding window from offscreen purgatory.  [13 Jul 2005]
8014 ----------------------------------------------------------------------------*/
8015 
8016 #undef  GETWIN
8017 #define GETWIN(w)                                             \
8018   do{ XtVaSetValues( (w) , XmNx,(int)(event->x_root),         \
8019                            XmNy,(int)(event->y_root), NULL ); \
8020       XMapRaised( XtDisplay(w) , XtWindow(w) ) ;              \
8021   } while(0)
8022 
AFNI_viewbut_EV(Widget w,XtPointer cd,XEvent * ev,RwcBoolean * continue_to_dispatch)8023 void AFNI_viewbut_EV( Widget w , XtPointer cd ,
8024                       XEvent *ev , RwcBoolean *continue_to_dispatch )
8025 {
8026    Three_D_View *im3d = (Three_D_View *)cd ;
8027    XButtonEvent *event=(XButtonEvent *)ev ;
8028 
8029    MCW_imseq   *sxyz , *syzx , *szxy ;
8030    MCW_grapher *gxyz , *gyzx , *gzxy ;
8031    Widget      pb_xyz , pb_yzx , pb_zxy ;
8032    Widget      gr_xyz , gr_yzx , gr_zxy ;
8033 
8034 ENTRY("AFNI_viewbut_EV") ;
8035 
8036    if( ev->type != ButtonPress || !IM3D_OPEN(im3d) ) EXRETURN ;
8037    if( event->button != Button3 ) EXRETURN ;
8038 
8039    sxyz = im3d->s123 ; gxyz = im3d->g123 ;  /* viewer structs */
8040    syzx = im3d->s231 ; gyzx = im3d->g231 ;
8041    szxy = im3d->s312 ; gzxy = im3d->g312 ;
8042 
8043    pb_xyz = im3d->vwid->imag->image_xyz_pb ;  /* buttons */
8044    pb_yzx = im3d->vwid->imag->image_yzx_pb ;
8045    pb_zxy = im3d->vwid->imag->image_zxy_pb ;
8046 
8047    gr_xyz = im3d->vwid->imag->graph_xyz_pb ;
8048    gr_yzx = im3d->vwid->imag->graph_yzx_pb ;
8049    gr_zxy = im3d->vwid->imag->graph_zxy_pb ;
8050 
8051    /* if the input Widget matches a button, and the item is open, get it */
8052 
8053         if( w == pb_xyz && ISQ_REALZ(sxyz) ) GETWIN(sxyz->wtop) ;
8054    else if( w == pb_yzx && ISQ_REALZ(syzx) ) GETWIN(syzx->wtop) ;
8055    else if( w == pb_zxy && ISQ_REALZ(szxy) ) GETWIN(szxy->wtop) ;
8056    else if( w == gr_xyz && GRA_REALZ(gxyz) ) GETWIN(gxyz->fdw_graph) ;
8057    else if( w == gr_yzx && GRA_REALZ(gyzx) ) GETWIN(gyzx->fdw_graph) ;
8058    else if( w == gr_zxy && GRA_REALZ(gzxy) ) GETWIN(gzxy->fdw_graph) ;
8059 
8060    EXRETURN ;
8061 }
8062 
8063 /*------------------------------------------------------------------------*/
8064 
8065 static int ignore_redisplay_func = 0 ;  /* 03 Jun 2014 */
AFNI_redisplay_func_ignore(int ig)8066 void AFNI_redisplay_func_ignore( int ig ){ ignore_redisplay_func = ig ; }
8067 
AFNI_redisplay_func(Three_D_View * im3d)8068 void AFNI_redisplay_func( Three_D_View *im3d )  /* 05 Mar 2002 */
8069 {
8070 ENTRY("AFNI_redisplay_func") ;
8071    if( !ignore_redisplay_func && IM3D_OPEN(im3d) && IM3D_IMAGIZED(im3d) ){
8072      AFNI_set_viewpoint( im3d , -1,-1,-1 , REDISPLAY_ALL ) ;
8073      AFNI_process_funcdisplay( im3d ) ;
8074    }
8075    EXRETURN ;
8076 }
8077 
8078 /*------------------------------------------------------------------------*/
8079 
AFNI_redisplay_func_all(Three_D_View * im3d)8080 void AFNI_redisplay_func_all( Three_D_View *im3d )  /* 03 Jul 2014 */
8081 {
8082    Three_D_View *qq3d ; int ii ;
8083 
8084 ENTRY("AFNI_redisplay_func_all") ;
8085 
8086    ignore_redisplay_func = 0 ;
8087    for( ii=0 ; ii < MAX_CONTROLLERS ; ii++ ){
8088       qq3d = GLOBAL_library.controllers[ii] ;
8089       if( !IM3D_OPEN(qq3d) || qq3d == im3d ) continue ;
8090       IM3D_CLEAR_TMASK(qq3d) ;
8091       IM3D_CLEAR_THRSTAT(qq3d) ;
8092       AFNI_redisplay_func(qq3d) ;
8093    }
8094 
8095    EXRETURN ;
8096 }
8097 
8098 /*------------------------------------------------------------------------*/
8099 
AFNI_do_bkgd_lab(Three_D_View * im3d)8100 void AFNI_do_bkgd_lab( Three_D_View *im3d )
8101 {
8102    char str[256] ;
8103    char labstrf[256]={""}, labstra[256]={""};
8104    char strhint[256]={"Values at crosshairs voxel"};
8105 
8106 ENTRY("AFNI_do_bkgd_lab") ;
8107 
8108    if( !IM3D_VALID(im3d) || !im3d->vwid->imag->do_bkgd_lab ) EXRETURN ;
8109 
8110    AFNI_get_dset_val_label(im3d->anat_now,         /* 26 Feb 2010 ZSS */
8111                            strtod(im3d->vinfo->anat_val, NULL), labstra);
8112    AFNI_get_dset_val_label(im3d->fim_now,         /* 26 Feb 2010 ZSS */
8113                            strtod(im3d->vinfo->func_val, NULL), labstrf);
8114 
8115 #define VSTR(x) ( ((x)[0] == '\0') ? ("?") : (x) )
8116 
8117    sprintf(str,"ULay = %s %s\n"
8118                "OLay = %s %s\n"
8119                "Thr  = %s" ,
8120            VSTR(im3d->vinfo->anat_val), labstra,
8121            VSTR(im3d->vinfo->func_val), labstrf,
8122            VSTR(im3d->vinfo->thr_val ) ) ;
8123 
8124 #undef VSTR
8125 
8126    if (labstra[0] != '\0' || labstrf[0] != '\0') { /* 26 Feb 2010 ZSS */
8127       sprintf(strhint,"Values at crosshairs: "
8128                       "%s%s%s%s",
8129                       (labstra[0] == '\0') ? "OLay=":"ULay=",
8130                       labstra,
8131                       (labstra[0] != '\0' && labstrf[0] != '\0') ? ", OLay=":"",
8132                       labstrf);
8133       MCW_register_hint( im3d->vwid->func->bkgd_lab, strhint);
8134    }
8135 
8136    MCW_set_widget_label( im3d->vwid->func->bkgd_lab , str ) ;
8137    XtManageChild( im3d->vwid->func->bkgd_lab ) ;
8138    FIX_SCALE_SIZE(im3d) ;
8139    EXRETURN ;
8140 }
8141 
8142 /*------------------------------------------------------------------------*/
8143 /*! Set the grayscale range in the image window, maybe.  [04 Nov 2003]
8144 --------------------------------------------------------------------------*/
8145 
AFNI_range_setter(Three_D_View * im3d,MCW_imseq * seq)8146 void AFNI_range_setter( Three_D_View *im3d , MCW_imseq *seq )
8147 {
8148    float rng[3] = {0.0f,0.0f,0.0f} ;
8149    int ival ;
8150    FD_brick *br ;
8151    THD_3dim_dataset *ds ;
8152    static int first=1 ;
8153    static THD_3dim_dataset *last_ds   = NULL ;
8154    static int               last_ival = -1 ;
8155    static float             last_tc   = 0.0f ;
8156    float min = 0.0, max = 0.0;
8157 
8158 ENTRY("AFNI_range_setter") ;
8159 
8160    if( !IM3D_VALID(im3d) || !ISQ_VALID(seq) ) EXRETURN ;
8161 
8162    if( !IM3D_ULAY_COHERENT(im3d) ){           /* 10 Jun 2014 */
8163      STATUS("AFNI_range_setter: incoherent ulay -- patching") ;
8164      ERROR_message("incoherent ulay -- patching") ;
8165      AFNI_assign_ulay_bricks(im3d) ;
8166    }
8167 
8168    br = (FD_brick *)im3d->b123_ulay ; if( br == NULL ) EXRETURN ;
8169    ds = br->dset ;                    if( ds == NULL ) EXRETURN ;
8170 
8171    if( EQUIV_DSETS(ds,im3d->anat_now) )      /* underlay dataset */
8172      ival = im3d->vinfo->anat_index ;
8173    else if( EQUIV_DSETS(ds,im3d->fim_now) )  /* overlay dataset */
8174      ival = im3d->vinfo->fim_index ;
8175    else
8176      ival = 0 ;                              /* shouldn't happen */
8177 
8178    if( !EQUIV_DSETS(ds,last_ds) || last_ival != ival ){  /* 14 Sep 2007 */
8179      float tc=0.0f ;
8180      if( DSET_INMEMORY(ds) ){
8181        if( !DSET_BRICK_LOADED(ds,ival) ) DSET_load(ds) ;
8182        if( DSET_BRICK_LOADED(ds,ival) ){
8183          float ff = DSET_BRICK_FACTOR(ds,ival) ;
8184          tc = mri_min( DSET_BRICK(ds,ival) ) ;
8185          if( tc < 0.0f ) tc = 0.0f ;
8186          else            tc = mri_topclip( DSET_BRICK(ds,ival) ) ;
8187          if( ff > 0.0f ) tc *= ff ;
8188        }
8189      }
8190      last_ds = ds ; last_ival = ival ; last_tc = tc ;
8191    }
8192    drive_MCW_imseq( seq , isqDR_settopclip , (XtPointer)(&last_tc) ) ;
8193 
8194    /* if default slice-based AFNI_IMAGE_GLOBALRANGE, just return */
8195    if( !THD_get_image_globalrange() ){ first=1; EXRETURN ; }
8196 
8197    if( ISVALID_STATISTIC(ds->stats)){
8198      if((THD_get_image_globalrange()==1)     /* user wants sub-brick range */
8199        && ISVALID_BSTAT(ds->stats->bstat[ival])){
8200         rng[0] = ds->stats->bstat[ival].min ;
8201         rng[1] = ds->stats->bstat[ival].max ;
8202      }
8203      else {         /* user wants range scaling by whole dataset */
8204        if(THD_dset_minmax(ds, 1, &min, &max)) {
8205         rng[0] = min ;
8206         rng[1] = max ;
8207        }
8208        else {  /* no good dset range, so revert to sub-brick range */
8209         rng[0] = ds->stats->bstat[ival].min ;
8210         rng[1] = ds->stats->bstat[ival].max ;
8211        }
8212      }
8213 
8214      /* first time globalrange has been set to something? */
8215      if( first ){
8216        INFO_message(
8217    "AFNI_IMAGE_GLOBALRANGE is no longer slice-based ==> reset image range to %g .. %g",
8218         rng[0],rng[1] ) ;
8219        first = 0 ;
8220      }
8221    }
8222    rng[2] = 1.0f ;  /* 21 Dec 2006: do NOT redisplay image */
8223 
8224    drive_MCW_imseq( seq , isqDR_setrange , (XtPointer) rng ) ;
8225    EXRETURN ;
8226 }
8227 
8228 /*-----------------------------------------------------------------------*/
8229 /* reset globalrange - called by environment GUI and plugout driver */
ENV_globalrange_view(char * vname)8230 void ENV_globalrange_view( char *vname ) /* no longer static definition */
8231 {
8232    Three_D_View *im3d ;
8233    int ii , gbr ;
8234    char sgr_str[64];
8235 
8236    /* reset image_globalrange */
8237    THD_set_image_globalrange(-1);
8238 #if 0
8239    sprintf(sgr_str,"AFNI_IMAGE_GLOBALRANGE=%s",vname);
8240 printf("setting env %s\n",sgr_str);
8241    AFNI_setenv(sgr_str);
8242 #endif
8243 
8244    gbr = THD_get_image_globalrange(); /* resets from environment variable setting */
8245 
8246    for( ii=0 ; ii < MAX_CONTROLLERS ; ii++ ){
8247      im3d = GLOBAL_library.controllers[ii] ;
8248      if( ! IM3D_VALID(im3d) ) continue ;
8249      if( gbr ){
8250        AFNI_range_setter( im3d , im3d->s123 ) ;
8251        AFNI_range_setter( im3d , im3d->s231 ) ;
8252        AFNI_range_setter( im3d , im3d->s312 ) ;
8253        drive_MCW_imseq( im3d->s123 , isqDR_display , (XtPointer)(-1) ) ;
8254        drive_MCW_imseq( im3d->s231 , isqDR_display , (XtPointer)(-1) ) ;
8255        drive_MCW_imseq( im3d->s312 , isqDR_display , (XtPointer)(-1) ) ;
8256      } else {
8257        drive_MCW_imseq( im3d->s123 , isqDR_setrange , (XtPointer)NULL ) ;
8258        drive_MCW_imseq( im3d->s231 , isqDR_setrange , (XtPointer)NULL ) ;
8259        drive_MCW_imseq( im3d->s312 , isqDR_setrange , (XtPointer)NULL ) ;
8260      }
8261    }
8262    return ;
8263 }
8264 
8265 /* set environment variable too */
THD_set_image_globalrange_env(int ig)8266 void THD_set_image_globalrange_env(int ig)
8267 {
8268    THD_set_image_globalrange(ig);
8269    switch(ig) {
8270       default:
8271       case 0:
8272          AFNI_setenv("AFNI_IMAGE_GLOBALRANGE=SLICE");
8273          break;
8274       case 1:
8275          AFNI_setenv("AFNI_IMAGE_GLOBALRANGE=VOLUME");
8276          break;
8277       case 2:
8278          AFNI_setenv("AFNI_IMAGE_GLOBALRANGE=DSET");
8279          break;
8280    }
8281   ENV_globalrange_view( "AFNI_IMAGE_GLOBALRANGE" );
8282 }
8283 
8284 /*------------------------------------------------------------------------*/
8285 /*! Define the view_setter code, which says which image viewer plane
8286     was used to set the current viewpoint.  [26 Feb 2003]
8287 --------------------------------------------------------------------------*/
8288 
AFNI_view_setter(Three_D_View * im3d,MCW_imseq * seq)8289 void AFNI_view_setter( Three_D_View *im3d , MCW_imseq *seq )
8290 {
8291    MCW_imseq *sxyz, *syzx, *szxy ;
8292    int val=-1 ;
8293 
8294 ENTRY("AFNI_view_setter") ;
8295 
8296    if( !IM3D_VALID(im3d) ) EXRETURN ;
8297 
8298    sxyz = im3d->s123 ; syzx = im3d->s231 ; szxy = im3d->s312 ;
8299 
8300    if( !ISQ_REALZ(seq) ){
8301      int code = 4*(sxyz!=NULL) + 2*(syzx!=NULL) + (szxy!=NULL) ;
8302      switch(code){
8303        case 4: val = AXIAL   ; break ;
8304        case 2: val = SAGITTAL; break ;
8305        case 1: val = CORONAL ; break ;
8306      }
8307    } else {
8308           if( seq == sxyz ) val = AXIAL   ;
8309      else if( seq == syzx ) val = SAGITTAL;
8310      else if( seq == szxy ) val = CORONAL ;
8311    }
8312 
8313    im3d->vinfo->view_setter = val ;
8314    EXRETURN ;
8315 }
8316 
8317 /*------------------------------------------------------------------------*/
8318 
AFNI_set_index_viewpoint(Three_D_View * im3d,int ijk,int redisplay_option)8319 void AFNI_set_index_viewpoint( Three_D_View *im3d ,
8320                                int ijk, int redisplay_option )  /* ZSS July 2010 */
8321 {
8322    int nij, ni, ii, jj, kk;
8323 
8324    if (  ijk<0 || !im3d ||
8325          !IM3D_VALID(im3d) ||
8326          !ISVALID_3DIM_DATASET(im3d->anat_now)) return;
8327 
8328    if (ijk < DSET_NVOX(im3d->anat_now)) {
8329 
8330       ni = DSET_NX(im3d->anat_now);
8331       nij = (ni * DSET_NY(im3d->anat_now));
8332 
8333       kk = (ijk / nij);
8334       jj = (ijk % nij);
8335       ii = (jj % ni);
8336       jj = (jj / ni);
8337 
8338       AFNI_set_viewpoint( im3d, ii, jj, kk, redisplay_option );
8339    }
8340 
8341    return;
8342 }
8343 
8344 /*------------------------------------------------------------------------*/
8345 
AFNI_check_for_multiple_vedits(Three_D_View * im3d)8346 void AFNI_check_for_multiple_vedits( Three_D_View *im3d )
8347 {
8348    static int first=1 ;
8349    Three_D_View *qq3d ; int qq ;
8350 
8351 ENTRY("AFNI_check_for_multiple_vedits") ;
8352 
8353    if( !first || !IM3D_VALID(im3d) ) EXRETURN ;
8354 
8355    for( qq=0 ; qq < MAX_CONTROLLERS ; qq++ ){
8356      qq3d = GLOBAL_library.controllers[qq] ;
8357      if( !IM3D_OPEN(qq3d) ) continue ;
8358      if( qq3d == im3d     ) continue ;
8359      if( qq3d->vedset.code <= 0 || qq3d->vedset.ival < 0 ) continue ;
8360      if( qq3d->fim_now == im3d->fim_now ){
8361 #undef  MCMESS
8362 #define MCMESS " \n"                      \
8363                " Multiple Clusterize \n"  \
8364                " operations are open \n"  \
8365                " on the same Overlay \n"  \
8366                " dataset -- they may \n"  \
8367                " conflict & confuse! \n "
8368        AFNI_popup_message( MCMESS ) ;
8369        WARNING_message   ( MCMESS ) ;
8370        first = 0 ; break ;
8371 #undef MCMESS
8372      }
8373    }
8374    EXRETURN ;
8375 }
8376 
8377 /*------------------------------------------------------------------------*/
8378 
AFNI_set_viewpoint(Three_D_View * im3d,int xx,int yy,int zz,int redisplay_option)8379 void AFNI_set_viewpoint( Three_D_View *im3d ,
8380                          int xx,int yy,int zz , int redisplay_option )
8381 {
8382    int old_i1 , old_j2 , old_k3 , i1,j2,k3 ;
8383    int dim1,dim2,dim3 , isq_driver , do_lock , new_xyz ;
8384    int newti ;            /* 24 Jan 2001 */
8385    int ihave , doflash ;  /* 02 Mar 2011 */
8386 
8387    THD_dataxes *daxes ;
8388    THD_fvec3 fv ;
8389    THD_ivec3 old_ib , new_ib , old_id , new_id ;
8390 
8391 #undef  EXRR
8392 #define EXRR do{ recurse-- ; EXRETURN ; } while(0)
8393    static int recurse=0 ;
8394    if( recurse > 1 ) return ;  /* changed from 3 to 1 [16 Sep 2009] */
8395    recurse++ ;
8396 
8397 ENTRY("AFNI_set_viewpoint") ;
8398 
8399 if(PRINT_TRACING)
8400 { char str[256] ;
8401   sprintf(str,"input xx=%d yy=%d zz=%d",xx,yy,zz) ;
8402   STATUS(str) ; }
8403 
8404    if( ! IM3D_VALID(im3d) || ! ISVALID_3DIM_DATASET(im3d->anat_now) ) EXRR ;
8405 
8406    /** 02 Nov 1996:
8407          Attach view-specific dataxes and warps to the datasets **/
8408 
8409    LOAD_DSET_VIEWS(im3d) ;
8410 
8411    /** find if input points are inside axes of current display **/
8412 
8413    daxes = CURRENT_DAXES(im3d->anat_now) ;
8414    dim1  = daxes->nxx ; dim2 = daxes->nyy ; dim3 = daxes->nzz ;
8415 
8416    /** save old ijk coordinates **/
8417 
8418    old_i1 = im3d->vinfo->i1 ;
8419    old_j2 = im3d->vinfo->j2 ;
8420    old_k3 = im3d->vinfo->k3 ;
8421 
8422    /** get and store new ijk coordinates **/
8423 
8424    i1 = im3d->vinfo->i1 = (xx < 0 || xx >= dim1) ? (old_i1) : xx ;
8425    j2 = im3d->vinfo->j2 = (yy < 0 || yy >= dim2) ? (old_j2) : yy ;
8426    k3 = im3d->vinfo->k3 = (zz < 0 || zz >= dim3) ? (old_k3) : zz ;
8427 
8428    /** determine redisplay mode for image viewers **/
8429 
8430    new_xyz =
8431     do_lock = !( i1 == old_i1 && j2 == old_j2 && k3 == old_k3 ) ;  /* 11 Nov 1996 */
8432 
8433    if( !redisplay_option && !new_xyz ) EXRR ;
8434 
8435    ihave      = (im3d->s123 != NULL || im3d->s231 != NULL || im3d->s312 != NULL);
8436    doflash    = (redisplay_option == REDISPLAY_FLASH) ;
8437    isq_driver = (redisplay_option == REDISPLAY_ALL) ? isqDR_display
8438                                                     : isqDR_overlay ;
8439 
8440    if( !AFNI_noenv("AFNI_VALUE_LABEL") && new_xyz && !ihave )
8441      isq_driver = isqDR_display ;         /* 08 Mar 2002 */
8442 
8443    LOAD_IVEC3(old_id,old_i1,old_j2,old_k3) ;
8444    LOAD_IVEC3(new_id,    i1,    j2,    k3) ;
8445 
8446 #ifdef AFNI_DEBUG
8447 STATUS(" ") ;
8448 DUMP_IVEC3("  old_id",old_id) ;
8449 DUMP_IVEC3("  new_id",new_id) ;
8450 #endif
8451 
8452    /** store new xyz coordinates into im3d struct **/
8453 
8454    if( im3d->type == AFNI_3DDATA_VIEW ){
8455      fv = THD_3dind_to_3dmm ( im3d->anat_now , new_id ) ;
8456      fv = THD_3dmm_to_dicomm( im3d->anat_now , fv     ) ;
8457      im3d->vinfo->xi = fv.xyz[0] ;  /* set display coords */
8458      im3d->vinfo->yj = fv.xyz[1] ;  /* to Dicom standard  */
8459      im3d->vinfo->zk = fv.xyz[2] ;
8460    }
8461 
8462    /* clear labels */
8463 
8464    im3d->vinfo->func_val[0] = im3d->vinfo->thr_val[0] = '\0' ;
8465    if( do_lock || isq_driver==isqDR_display )
8466       im3d->vinfo->anat_val[0] = '\0';
8467    if( !AFNI_noenv( "AFNI_VALUE_LABEL") ) AFNI_do_bkgd_lab( im3d ) ;
8468 
8469    /*--- 05 Sep 2006: volume edit on demand? ---*/
8470 
8471    if( IM3D_IMAGIZED(im3d) && im3d->vinfo->thr_onoff    &&
8472        ihave               && im3d->vinfo->func_visible && !doflash ){
8473      int changed=0 ;
8474      if( VEDIT_good(im3d->vedset) ){
8475        STATUS("starting vedit") ;
8476        im3d->vedset.ival = im3d->vinfo->fim_index ;
8477        switch( VEDIT_CODE(im3d->vedset) ){
8478          case VEDIT_CLUST:  /* params 2,3,6 set in afni_cluster.c */
8479            im3d->vedset.param[0] = (float)im3d->vinfo->thr_index ;
8480            im3d->vedset.param[1] = get_3Dview_func_thresh(im3d,1);
8481            im3d->vedset.param[4] = im3d->vinfo->thr_sign ;
8482            im3d->vedset.param[5] = im3d->vinfo->use_posfunc ;
8483            im3d->vedset.exinfo   = NULL ;
8484          break ;
8485        }
8486        if( !im3d->vedskip ){
8487          byte *mmm = (im3d->vednomask) ? NULL : im3d->vwid->func->clu_mask ;
8488          changed = AFNI_vedit( im3d->fim_now , im3d->vedset , mmm ) ;
8489        }
8490        if( !DSET_VEDIT_good(im3d->fim_now) ){
8491          STATUS("vedit not completed") ;
8492          UNCLUSTERIZE(im3d) ;
8493        } else if( changed ){
8494          mri_cluster_detail *cld ; int nc ; char *rrr ;
8495          STATUS("vedit completed") ;
8496          VEDIT_cluster_helpize(im3d);
8497          if( im3d->vwid->func->clu_rep != NULL ){
8498            free(im3d->vwid->func->clu_rep); im3d->vwid->func->clu_rep = NULL;
8499          }
8500          rrr = mri_clusterize_report() ;
8501          if( rrr != NULL && *rrr != '\0' ) im3d->vwid->func->clu_rep = strdup(rrr) ;
8502          DESTROY_CLARR(im3d->vwid->func->clu_list) ;
8503          im3d->vwid->func->clu_list = mri_clusterize_array(1) ;
8504          AFNI_cluster_dispize(im3d,0);  /* display the results */
8505          AFNI_check_for_multiple_vedits(im3d) ;  /* 24 Jul 2014 */
8506          STATUS("vedit processed") ;
8507        }
8508        IM3D_CLEAR_THRSTAT(im3d) ;  /* 12 Jun 2014 */
8509      } else {
8510        UNCLUSTERIZE(im3d) ;  /* macro-ized 13 Feb 2008 */
8511      }
8512    }
8513 
8514    /*--- 12 Jun 2014: thresholded statistics on fim ---*/
8515 
8516    AFNI_setup_thrstat(im3d,0) ;  /* function-ized 27 Jun 2019 */
8517 
8518    /*--- redraw images now ---*/
8519 
8520    im3d->ignore_seq_callbacks = AFNI_IGNORE_EVERYTHING ;
8521 
8522    if( !IM3D_ULAY_COHERENT(im3d) ){           /* 10 Jun 2014 */
8523      STATUS("AFNI_set_viewpoint: incoherent ulay -- patching") ;
8524      ERROR_message("incoherent ulay -- patching") ;
8525      AFNI_assign_ulay_bricks(im3d) ;
8526    }
8527 
8528    if( im3d->s123 != NULL || im3d->g123 != NULL ){
8529       int xyzm[4] ;
8530 
8531       old_ib = THD_3dind_to_fdind( im3d->b123_ulay , old_id ) ;
8532       new_ib = THD_3dind_to_fdind( im3d->b123_ulay , new_id ) ;
8533 
8534 #ifdef AFNI_DEBUG
8535 STATUS(" ") ;
8536 DUMP_IVEC3(" redraw s123 old_ib",old_ib) ;
8537 DUMP_IVEC3("             new_ib",new_ib) ;
8538 #endif
8539 
8540       if( redisplay_option || old_ib.ijk[2] != new_ib.ijk[2] )
8541          drive_MCW_imseq( im3d->s123 ,
8542                           isq_driver , (XtPointer)ITOP(new_ib.ijk[2]) ) ;
8543 
8544 
8545       xyzm[0] = new_ib.ijk[0] ; xyzm[1] = new_ib.ijk[1] ;
8546       xyzm[2] = new_ib.ijk[2] ; xyzm[3] = 0 ;
8547 
8548       if( im3d->g123 != NULL && !doflash &&
8549           ( im3d->g123->never_drawn || redisplay_option == REDISPLAY_ALL ||
8550             new_xyz                 || im3d->g123->thresh_fade             ) )
8551          drive_MCW_grapher( im3d->g123 , graDR_redraw , (XtPointer) xyzm ) ;
8552    }
8553 
8554    if( im3d->s231 != NULL || im3d->g231 != NULL ){
8555       int xyzm[4] ;
8556 
8557       old_ib = THD_3dind_to_fdind( im3d->b231_ulay , old_id ) ;
8558       new_ib = THD_3dind_to_fdind( im3d->b231_ulay , new_id ) ;
8559 
8560 #ifdef AFNI_DEBUG
8561 STATUS(" ") ;
8562 DUMP_IVEC3(" redraw s231 old_ib",old_ib) ;
8563 DUMP_IVEC3("             new_ib",new_ib) ;
8564 #endif
8565 
8566       if( redisplay_option || old_ib.ijk[2] != new_ib.ijk[2] )
8567          drive_MCW_imseq( im3d->s231 ,
8568                           isq_driver , (XtPointer)ITOP(new_ib.ijk[2]) ) ;
8569 
8570       xyzm[0] = new_ib.ijk[0] ; xyzm[1] = new_ib.ijk[1] ;
8571       xyzm[2] = new_ib.ijk[2] ; xyzm[3] = 0 ;
8572 
8573       if( im3d->g231 != NULL && !doflash &&
8574           ( im3d->g231->never_drawn || redisplay_option == REDISPLAY_ALL ||
8575             new_xyz                 || im3d->g231->thresh_fade             ) )
8576          drive_MCW_grapher( im3d->g231 , graDR_redraw , (XtPointer) xyzm ) ;
8577    }
8578 
8579    if( im3d->s312 != NULL || im3d->g312 != NULL ){
8580       int xyzm[4] ;
8581 
8582       old_ib = THD_3dind_to_fdind( im3d->b312_ulay , old_id ) ;
8583       new_ib = THD_3dind_to_fdind( im3d->b312_ulay , new_id ) ;
8584 
8585 #ifdef AFNI_DEBUG
8586 STATUS(" ") ;
8587 DUMP_IVEC3(" redraw s312 old_ib",old_ib) ;
8588 DUMP_IVEC3("             new_ib",new_ib) ;
8589 #endif
8590 
8591       if( redisplay_option || old_ib.ijk[2] != new_ib.ijk[2] )
8592          drive_MCW_imseq( im3d->s312 ,
8593                           isq_driver , (XtPointer)ITOP(new_ib.ijk[2]) ) ;
8594 
8595       xyzm[0] = new_ib.ijk[0] ; xyzm[1] = new_ib.ijk[1] ;
8596       xyzm[2] = new_ib.ijk[2] ; xyzm[3] = 0 ;
8597 
8598       if( im3d->g312 != NULL && !doflash &&
8599           ( im3d->g312->never_drawn || redisplay_option == REDISPLAY_ALL ||
8600             new_xyz                 || im3d->g312->thresh_fade             ) )
8601          drive_MCW_grapher( im3d->g312 , graDR_redraw , (XtPointer) xyzm ) ;
8602    }
8603 
8604    im3d->ignore_seq_callbacks = AFNI_IGNORE_NOTHING ;
8605 
8606    /*--- redraw coordinate display now ---*/
8607 
8608    if( !doflash && (redisplay_option || new_xyz) ){
8609       AFNI_crosshair_relabel( im3d ) ;  /* 12 Mar 2004: moved this to a function, too */
8610       AFNI_do_bkgd_lab( im3d ) ;        /* 08 Mar 2002: moved labelizing to function */
8611    }
8612 
8613    /* 24 Jan 2001: set grapher index based on type of dataset */
8614 
8615    newti = im3d->vinfo->anat_index ;
8616 
8617    if( newti >= 0 && !doflash ){  /* ITOP = Integer to Pointer cast */
8618      drive_MCW_grapher( im3d->g123, graDR_setindex, (XtPointer)ITOP(newti) );
8619      drive_MCW_grapher( im3d->g231, graDR_setindex, (XtPointer)ITOP(newti) );
8620      drive_MCW_grapher( im3d->g312, graDR_setindex, (XtPointer)ITOP(newti) );
8621    }
8622 
8623    if( do_lock && !doflash )        /* 11 Nov 1996 */
8624      AFNI_space_lock_carryout( im3d ) ;  /* 04 Nov 1996 */
8625 
8626    /** Feb 1998: if desired, send coordinates to receiver **/
8627    /** Mar 1999: do it in an external routine, not here.  **/
8628 
8629    if( !doflash ){
8630      if( new_xyz ) AFNI_process_viewpoint( im3d ) ;
8631      else          AFNI_process_redisplay( im3d ) ;
8632    }
8633 
8634    if( !doflash && AFNI_HAVE_WAMI_WIDGET(im3d) ){
8635 
8636       char *tlab = AFNI_ttatlas_query( im3d ) ;
8637 
8638       AFNI_alter_wami_text(im3d, tlab);
8639 
8640       if (tlab) free(tlab) ;
8641    }
8642 
8643    /*** 15 Jan 2014 **/
8644 
8645    AFNI_sleep(1) ;
8646    if( im3d->s123 != NULL && im3d->s123->crop_autocenter )
8647      ISQ_adjust_crop( im3d->s123 , 0,0,0,0 , 1 ) ;
8648    if( im3d->s231 != NULL && im3d->s231->crop_autocenter )
8649      ISQ_adjust_crop( im3d->s231 , 0,0,0,0 , 1 ) ;
8650    if( im3d->s312 != NULL && im3d->s312->crop_autocenter )
8651      ISQ_adjust_crop( im3d->s312 , 0,0,0,0 , 1 ) ;
8652 
8653    EXRR ;
8654 }
8655 #undef EXRR
8656 
8657 /*----------------------------------------------------------------------------
8658    get the n-th overlay as an MRI_IMAGE *
8659    (return NULL if none;  the result must be mri_free-d by the user)
8660    NOTE: most of the code in this function is no longer executed
8661          under 'normal' circumstances
8662 ------------------------------------------------------------------------------*/
8663 
AFNI_overlay(int n,FD_brick * br)8664 MRI_IMAGE * AFNI_overlay( int n , FD_brick *br )
8665 {
8666    Three_D_View *im3d = (Three_D_View *) br->parent ;
8667    MRI_IMAGE *im = NULL , *fov = NULL ;
8668    register short *oar ;
8669    int ii,jj , npix , xx,yy,zz , nx,ny , gap,ovc , icr,jcr,kcr ;
8670    RwcBoolean ovgood ;
8671    THD_ivec3 ib ;
8672    THD_3dim_dataset *dset ;
8673    FD_brick *br_fim ;
8674    int do_xhar=0 ;            /* 22 Mar 2002 */
8675    MRI_IMAGE *rgbov = NULL ;  /* 30 Jan 2003 */
8676    int jill = im3d->vinfo->see_ttatlas && AFNI_yesenv("AFNI_JILL_TRAVESTY") ; /* Jill is trouble */
8677 
8678 ENTRY("AFNI_overlay") ;
8679 
8680    if( ! IM3D_OPEN(im3d) ) RETURN(NULL) ;
8681 
8682    /*--- check if crosshairs, markers, or functions are visible ---*/
8683 
8684 #ifdef IMAGEIZE_CROSSHAIRS  /* since this is disabled, do_xhar is always 0 */
8685    do_xhar = (im3d->vinfo->crosshair_visible && !AFNI_yesenv("AFNI_CROSSHAIR_LINES")) ;
8686 #endif
8687 
8688    dset = im3d->anat_now ;
8689 
8690    ovgood =  do_xhar   /* crosshairs in overlay pixels? */            ||
8691 
8692             (  dset->markers != NULL       &&  /* Talairach */
8693               (dset->markers->numset > 0)  &&   /* markers? */
8694               (im3d->vwid->marks->ov_visible == True) )               ||
8695 
8696             (  dset->tagset != NULL  &&        /* user-input tags? */
8697                dset->tagset->num > 0 &&
8698                (im3d->vwid->marks->tag_visible == True) )             ||
8699 
8700 #ifdef ALLOW_DATASET_VLIST  /* other random points? */
8701             ( dset->pts != NULL && im3d->vinfo->pts_visible == True ) ||
8702 #endif
8703 
8704             ( im3d->vinfo->func_visible == True ) /* overlay on? */   ||
8705 
8706             ( im3d->vinfo->see_ttatlas &&    /* Atlas colors on? */
8707               im3d->anat_now->view_type == VIEW_TALAIRACH_TYPE ) ;
8708 
8709    if( ! ovgood ) RETURN(NULL) ;  /* nothing is asked of us! */
8710 
8711    /*-- at least one source of an overlay is present --*/
8712 
8713 if(PRINT_TRACING)
8714 { char str[256] ; sprintf(str,"n1=%d n2=%d",br->n1,br->n2) ; STATUS(str) ; }
8715 
8716    LOAD_DSET_VIEWS(im3d) ;  /* 02 Nov 1996 */
8717 
8718    /*----- get functional overlay, if desired -----*/
8719      /* Due to the ALWAYS_USE_BIGMODE change in afni_func.c, the  */
8720      /* return from AFNI_func_overlay() is now always RGBA format */
8721 
8722    if( im3d->vinfo->func_visible ){
8723       br_fim = UNDERLAY_TO_OVERLAY(im3d,br) ;    /* get overlay FD brick struct */
8724       fov    = AFNI_func_overlay( n , br_fim ) ; /* get overlay image (afni_func.c) */
8725       /* get rid of it if it contains nothing [12 Feb 2020] */
8726       if( fov != NULL && mri_allzero(fov) ){
8727         mri_free(fov) ; fov = NULL ;
8728       }
8729 
8730         /* in the olden days, fov might be shorts (indexes to colors),
8731            or might be RGB, but now it is always RGBA. However, the older
8732            codes below are built around short (indexed) overlays, and so
8733            we set aside the RGBA output to build the (obsolescent) short
8734            overlays, and then merge the RGBA and short overlay images later */
8735 
8736         /* so if by some weird chance (or later code change), we still get
8737            a color-indexed overlay image back here, convert it to RGB now  */
8738 
8739       if( fov != NULL && fov->kind == MRI_short ){        /* should not happen */
8740         rgbov = ISQ_index_to_rgb( im3d->dc , 1 , fov ) ;  /* conversion to RGB */
8741         mri_free(fov) ; fov = NULL ;
8742       } else if( fov != NULL && IS_RGB_TYPE(fov->kind) ){ /* should happen */
8743         rgbov = fov ; fov = NULL ;
8744       } else if( fov != NULL ){                           /* should NEVER happen */
8745         ERROR_message("AFNI_func_overlay returns illegal image type: %s",MRI_TYPE_NAME(fov)) ;
8746         mri_free(fov) ; fov = rgbov = NULL ;
8747       }
8748 
8749       if( jill ){
8750         if( rgbov == NULL ) INFO_message("AFNI_func_overlay is NULL") ;
8751         else                INFO_message("AFNI_func_overlay is %s",MRI_TYPE_NAME(rgbov)) ;
8752       }
8753 
8754       /* at this point, the functional overlay is in rgbov (which might be NULL) */
8755       /* and the color index overlay image (fov) is NULL for sure */
8756    }
8757 
8758    /*----- 25 Jul 2001: get an atlas overlay, if desired and possible -----*/
8759    /*-----              which will be merged with functional overlay  -----*/
8760 
8761    if( im3d->vinfo->see_ttatlas &&
8762        im3d->anat_now->view_type == VIEW_TALAIRACH_TYPE ){
8763 
8764       MRI_IMAGE *tov ;
8765 
8766       int ax_1 = br->a123.ijk[0] ;
8767       int ax_2 = br->a123.ijk[1] ;
8768       int ax_3 = br->a123.ijk[2] ;
8769 
8770       /* if rgbov is non-NULL, the return will be rgbov again,
8771          after suitable editing; otherwise, the return is a new image;
8772          however, if nothing is overlaid, then tov will be returned NULL */
8773 
8774       tov = AFNI_ttatlas_overlay( im3d , n , ax_1 , ax_2 , ax_3 , rgbov ) ;
8775 
8776       /* if tov came back as shorts, convert it to RGB [old code] */
8777       /* if it came back as RGB(A), it is the new RGB(A) overlay */
8778       /* [this latter situation should be what happens nowadays] */
8779 
8780       if( tov != NULL && tov->kind == MRI_short ){ /* should not happen */
8781         if( jill ) WARNING_message("AFNI_ttatlas_overlay returned a short-valued image!") ;
8782         mri_free(rgbov) ;
8783         rgbov = ISQ_index_to_rgb( im3d->dc , 1 , tov ) ;
8784         mri_free(tov) ;
8785       } else if( tov != NULL && IS_RGB_TYPE(tov->kind) && tov != rgbov ){
8786           if( jill && rgbov != NULL ) ININFO_message(" replacing rgbov with AFNI_ttatlas_tov combo") ;
8787           else if( jill )             ININFO_message(" making rgbov = AFNI_ttatlas_tov output") ;
8788         if( rgbov != NULL ) mri_free(rgbov) ;  /* might happen??? */
8789         rgbov = tov ;
8790       }
8791 
8792       /* at this point, rgbov is the merged functional + atlas overlay */
8793    }
8794 
8795    /*----- now set up short (indexed) overlay image as the functional
8796            overlay (if present), or as a new blank image (otherwise) -----*/
8797 
8798    if( fov != NULL ){ /* if short overlay already exists [not any more] */
8799 
8800 if(PRINT_TRACING)
8801 { char str[256] ;
8802 sprintf(str,"new overlay from AFNI_func_overlay: nx=%d ny=%d\n",fov->nx,fov->ny) ;
8803 STATUS(str) ; }
8804 
8805       im  = fov ; ovgood = True ;
8806       oar = MRI_SHORT_PTR(im) ;
8807 
8808    } else {   /* this should be the case from now on [13 Feb 2020] */
8809 
8810 STATUS("new overlay is created de novo") ;
8811       im  = mri_new( br->n1 , br->n2 , MRI_short ) ; ovgood = False ;
8812       oar = MRI_SHORT_PTR(im) ;
8813    }
8814 
8815    nx     = im->nx ;
8816    ny     = im->ny ;
8817    npix   = nx * ny ;
8818    im->dx = br->del1 ;  /* load dimensions (not that anyone cares) */
8819    im->dy = br->del2 ;
8820    im->dz = br->del3 ;
8821 
8822    /*----- put crosshairs on image directly, if desired (and allowed) -----*/
8823 
8824 #ifdef IMAGEIZE_CROSSHAIRS  /* this is now disabled, far above */
8825    if( do_xhar ){
8826       MCW_grapher *grapher = UNDERLAY_TO_GRAPHER(im3d,br) ;
8827 
8828       ib = THD_3dind_to_fdind( br ,
8829                               TEMP_IVEC3( im3d->vinfo->i1 ,
8830                                           im3d->vinfo->j2 ,
8831                                           im3d->vinfo->k3  ) ) ;
8832 
8833       /** April 1996: Only put crosshairs on if image number
8834                       matches current slice number of viewpoint.
8835                       (This allows for the montage multislice view) **/
8836 
8837       /** July 1996: Allow for multiple crosshairs to indicate
8838                      the location of montage multislice views. **/
8839 
8840       /** Aug 1996: Allow for periodic (wrap) or non-periodic montages.
8841                     Also, if in "Single" mode and also are graphing,
8842                     then only draw the grapher frame, not the crosshairs. **/
8843 
8844       /** Dec 1998: Allow for user to turn off some directions of crosshairs **/
8845 
8846       if( n == ib.ijk[2] || im3d->vinfo->xhairs_all ){
8847          int jp,ip , jcen,icen , gappp ;
8848          int idown,iup,iskip , jdown,jup,jskip , imon,jmon ;
8849          int a1 = br->a123.ijk[0] ,   /* x axis of the brick?    */
8850              ax = abs(a1) - 1       ; /* 0,1,2 for dataset x,y,z */
8851          int a2 = br->a123.ijk[1] ,   /* y axis of the brick?    */
8852              ay = abs(a2) - 1       ; /* 0,1,2 for dataset x,y,z */
8853          int a3 = br->a123.ijk[2] ,   /* z axis of the brick?    */
8854              az = abs(a3) - 1       ; /* 0,1,2 for dataset x,y,z */
8855 
8856          /* 31 Dec 1998: spatial orientations of image axes */
8857 
8858          int ox = (ax==0) ? br->dset->daxes->xxorient :
8859                   (ax==1) ? br->dset->daxes->yyorient : br->dset->daxes->zzorient ;
8860 
8861          int oy = (ay==0) ? br->dset->daxes->xxorient :
8862                   (ay==1) ? br->dset->daxes->yyorient : br->dset->daxes->zzorient ;
8863 
8864          ovc  = im3d->vinfo->crosshair_ovcolor ;
8865          gap  = (grapher==NULL) ? im3d->vinfo->crosshair_gap : (grapher->mat+1)/2 ;
8866          icen = ib.ijk[0] ;
8867          jcen = ib.ijk[1] ;
8868 
8869          /** initialize montage steps **/
8870 
8871          if( im3d->vinfo->xhairs_show_montage ){           /* in "Multi" mode */
8872             iskip = im3d->vinfo->xhairs_nskip.ijk[ax] + 1 ;
8873             jskip = im3d->vinfo->xhairs_nskip.ijk[ay] + 1 ;
8874             if( a1 > 0 ){
8875                idown = im3d->vinfo->xhairs_ndown.ijk[ax] ;
8876                iup   = im3d->vinfo->xhairs_nup.ijk[ax] ;
8877             } else {
8878                iup   = im3d->vinfo->xhairs_ndown.ijk[ax] ;
8879                idown = im3d->vinfo->xhairs_nup.ijk[ax] ;
8880             }
8881             if( a2 > 0 ){
8882                jdown = im3d->vinfo->xhairs_ndown.ijk[ay] ;
8883                jup   = im3d->vinfo->xhairs_nup.ijk[ay] ;
8884             } else {
8885                jup   = im3d->vinfo->xhairs_ndown.ijk[ay] ;
8886                jdown = im3d->vinfo->xhairs_nup.ijk[ay] ;
8887             }
8888 
8889 if(PRINT_TRACING)
8890 { char str[256] ;
8891   sprintf(str,"montage xhairs: ax   =%d ay   =%d az =%d",ax,ay,az)       ; STATUS(str);
8892   sprintf(str,"                iskip=%d idown=%d iup=%d",iskip,idown,iup); STATUS(str);
8893   sprintf(str,"                jskip=%d jdown=%d jup=%d",jskip,jdown,jup); STATUS(str);
8894   sprintf(str,"orimask=%d ox=%d oy=%d",im3d->vinfo->xhairs_orimask,ox,oy); STATUS(str);
8895 }
8896 
8897          } else {                                          /* in "Single" Mode */
8898            idown = iup = jdown = jup = iskip = jskip = 0 ;
8899            if( grapher != NULL ){ idown=-(iup+1); jdown=-(jup+1); } /* skip lines? */
8900          }
8901 
8902          /* draw vertical lines first */
8903 
8904          if( (im3d->vinfo->xhairs_orimask & (1<<oy)) != 0 ){  /* 31 Dec 1998 */
8905             for( imon=-idown ; imon <= iup ; imon++ ){
8906                icr = icen + imon * iskip ;
8907 
8908                if( im3d->vinfo->xhairs_periodic ){
8909                   while( icr < 0 )   icr += nx ;
8910                   while( icr >= nx ) icr -= nx ;
8911                } else {
8912                   if( icr < 0 || icr >= nx ) continue ;
8913                }
8914 
8915                gappp = (abs(icr-icen) <= gap) ? gap : -1 ; /* no gap if far from center */
8916 
8917                /* if lines are closely packed, only do alternate pixels */
8918 
8919                if( idown+iup > 0 && iskip == 1 && icr != icen ){
8920                   for( jj=(imon+idown)%2 ; jj < ny ; jj+=2 )
8921                      if( abs(jj-jcen) > gappp ) oar[icr+nx*jj] = ovc ;
8922                } else {
8923                   for( jj=0 ; jj < ny ; jj++ )
8924                      if( abs(jj-jcen) > gappp ) oar[icr+nx*jj] = ovc ;
8925                }
8926             }
8927          }
8928 
8929          /* draw horizontal lines */
8930 
8931          if( (im3d->vinfo->xhairs_orimask & (1<<ox)) != 0 ){  /* 31 Dec 1998 */
8932             for( jmon=-jdown ; jmon <= jup ; jmon++ ){
8933                jcr = jcen + jmon * jskip ;
8934                if( im3d->vinfo->xhairs_periodic ){
8935                   while( jcr < 0 )   jcr += ny ;
8936                   while( jcr >= ny ) jcr -= ny ;
8937                } else {
8938                   if( jcr < 0 || jcr >= ny ) continue ;
8939                }
8940 
8941                gappp = (abs(jcr-jcen) <= gap) ? gap : -1 ;  /* no gap if far from center */
8942 
8943                /* if lines are closely packed, only do alternate pixels */
8944 
8945                if( jdown+jup > 0 && jskip == 1 && jcr != jcen ){
8946                   for( ii=(jmon+jdown)%2 ; ii < nx ; ii+=2 )
8947                      if( abs(ii-icen) > gappp ) oar[ii+nx*jcr] = ovc ;
8948                } else {
8949                   for( ii=0 ; ii < nx ; ii++ )
8950                      if( abs(ii-icen) > gappp ) oar[ii+nx*jcr] = ovc ;
8951                }
8952             }
8953          }
8954 
8955          /* draw grapher frame, if needed */
8956 
8957          if( grapher != NULL ){
8958             int gs = gap , gb = (grapher->mat +2)/2 ;
8959 
8960             jcr = jcen ; icr = icen ;
8961 
8962             ip = icr - gb ; if( ip <  0  ) ip += nx ;
8963             ii = icr + gs ; if( ii >= nx ) ii -= nx ;
8964             for( jj=jcr-gb ; jj <= jcr+gs ; jj++ ){
8965                jp = jj ; if( jp <  0  ) jp += ny ;
8966                     else if( jp >= ny ) jp -= ny ;
8967                oar[ip+nx*jp] = ovc ;
8968                oar[ii+nx*jp] = ovc ;
8969             }
8970 
8971             jp = jcr - gb ; if( jp <  0  ) jp += ny ;
8972             jj = jcr + gs ; if( jj >= ny ) jj -= ny ;
8973             for( ii=icr-gb ; ii <= icr+gs ; ii++ ){
8974               ip = ii ; if( ip <  0  ) ip += nx ;
8975                    else if( ip >= nx ) ip -= nx ;
8976               oar[ip+nx*jp] = ovc ;
8977               oar[ip+nx*jj] = ovc ;
8978             }
8979          } /* end if "if grapher exists" */
8980 
8981          ovgood = True ;
8982       } /* end of "if correct slice" */
8983 
8984    } /* end of crosshairs */
8985 #endif
8986 
8987    /*----- put Talairach markers on, if desired [ancient code] -----*/
8988 
8989    if( im3d->anat_now->markers != NULL &&
8990        im3d->anat_now->markers->numset > 0 &&
8991        (im3d->vwid->marks->ov_visible == True) ){
8992 
8993       THD_marker_set     *markers = im3d->anat_now->markers ;
8994       AFNI_marks_widgets *marks   = im3d->vwid->marks ;
8995       AFNI_ovtemplate    *tem     = &(marks->ov_mask) ;
8996       int xbase , ybase , zbase , color ;
8997       THD_ivec3 ib ;
8998 
8999       /* do secondary points first */
9000 
9001       color = marks->ov_scolor ;
9002 
9003       for( jj=0 ; jj < MARKS_MAXNUM ; jj++ ){
9004          if( markers->valid[jj] &&     /* is point set? */
9005              color > 0          &&     /* will show up? */
9006              !marks->isprimary[jj] ){  /* is secondary? */
9007 
9008             ib = THD_3dmm_to_3dind( br->dset ,
9009                                     TEMP_FVEC3( markers->xyz[jj][0] ,
9010                                                 markers->xyz[jj][1] ,
9011                                                 markers->xyz[jj][2]  ) ) ;
9012             ib = THD_3dind_to_fdind( br , ib ) ;
9013 
9014             xbase = ib.ijk[0] ;  /* coordinates */
9015             ybase = ib.ijk[1] ;  /* in and out */
9016             zbase = ib.ijk[2] ;  /* of plane  */
9017 
9018             if( zbase == n ){  /* in this display plane */
9019                ovgood = True ;
9020                for( ii=0 ; ii < tem->numpix ; ii++ ){
9021                   xx = xbase + tem->dx[ii] ;
9022                   yy = ybase + tem->dy[ii] ;
9023                   if( xx >= 0 && xx < nx && yy >=0 && yy < ny )
9024                                               oar[xx+nx*yy] = color ;
9025                }
9026             }
9027          } /* end if point set, and secondary */
9028       } /* end for loop over all secondary points */
9029 
9030       /* duplicate above for primary points */
9031 
9032       color = marks->ov_pcolor ;
9033 
9034       for( jj=0 ; jj < MARKS_MAXNUM ; jj++ ){
9035          if( markers->valid[jj] &&     /* is point set? */
9036              color > 0          &&     /* will show up? */
9037              marks->isprimary[jj]  ){  /* is primary? */
9038 
9039             ib = THD_3dmm_to_3dind( br->dset ,
9040                                     TEMP_FVEC3( markers->xyz[jj][0] ,
9041                                                 markers->xyz[jj][1] ,
9042                                                 markers->xyz[jj][2]  ) ) ;
9043             ib = THD_3dind_to_fdind( br , ib ) ;
9044 
9045             xbase = ib.ijk[0] ;  /* coordinates */
9046             ybase = ib.ijk[1] ;  /* in and out */
9047             zbase = ib.ijk[2] ;  /* of plane  */
9048 
9049             if( zbase == n ){  /* in this display plane */
9050                ovgood = True ;
9051                for( ii=0 ; ii < tem->numpix ; ii++ ){
9052                   xx = xbase + tem->dx[ii] ;
9053                   yy = ybase + tem->dy[ii] ;
9054                   if( xx >= 0 && xx < nx && yy >=0 && yy < ny )
9055                                               oar[xx+nx*yy] = color ;
9056                }
9057             }
9058          } /* end if point set, and primary */
9059       } /* end for loop over all secondary points */
9060 
9061    } /* end if markers to be shown */
9062 
9063    /*----- put tags on, if desired [also ancient code] -----*/
9064 
9065    if( im3d->anat_now->tagset != NULL  &&
9066        im3d->anat_now->tagset->num > 0 &&
9067        (im3d->vwid->marks->tag_visible == True) ){
9068 
9069       static AFNI_ovtemplate *tem = NULL ;
9070       static int            npold = -1 ;
9071 
9072       THD_usertaglist *tl = im3d->anat_now->tagset ;
9073       int xbase , ybase , zbase , color , np ;
9074       THD_ivec3 ib ;
9075       THD_fvec3 fb ;
9076 
9077       if( tem == NULL ) tem = myXtNew(AFNI_ovtemplate) ; /* once only */
9078       np = MAX(nx,ny)/64 ; np = MAX(np,2) ;
9079       if( np != npold ){ npold = np ; AFNI_make_tagmask(np,0,tem) ; }
9080 
9081       color = im3d->vwid->marks->ov_pcolor ;  /* doesn't have its own color */
9082 
9083       for( jj=0 ; jj < tl->num ; jj++ ){
9084          if( tl->tag[jj].set && color > 0 ){
9085 
9086             fb = THD_dicomm_to_3dmm( br->dset, TEMP_FVEC3( tl->tag[jj].x ,
9087                                                            tl->tag[jj].y ,
9088                                                            tl->tag[jj].z  ) );
9089             ib = THD_3dmm_to_3dind( br->dset , fb ) ;
9090             ib = THD_3dind_to_fdind( br , ib ) ;
9091 
9092             xbase = ib.ijk[0] ;  /* coordinates */
9093             ybase = ib.ijk[1] ;  /* in and out */
9094             zbase = ib.ijk[2] ;  /* of plane  */
9095 
9096             if( zbase == n ){  /* in this display plane */
9097                ovgood = True ;
9098                for( ii=0 ; ii < tem->numpix ; ii++ ){
9099                   xx = xbase + tem->dx[ii] ;
9100                   yy = ybase + tem->dy[ii] ;
9101                   if( xx >= 0 && xx < nx && yy >=0 && yy < ny )
9102                                               oar[xx+nx*yy] = color ;
9103                }
9104             }
9105          }
9106       }
9107    } /* end if tags to be shown */
9108 
9109 #ifdef ALLOW_DATASET_VLIST  /* this is currently disabled in 3ddata.h */
9110    /*----- May 1995: additional points (single pixels) -----*/
9111 
9112    if( im3d->vinfo->pts_visible   &&
9113        dset->pts != NULL          &&
9114        im3d->vinfo->pts_color > 0   ){
9115 
9116       int color , jj ;
9117       THD_ivec3 ib ;
9118 
9119       color = im3d->vinfo->pts_color ;
9120 
9121       for( jj=0 ; jj < dset->pts->num ; jj++ ){
9122          ib = THD_3dind_to_fdind( br , dset->pts->ijk[jj] ) ;
9123          if( ib.ijk[2] == n ){
9124             oar[ ib.ijk[0] + nx * ib.ijk[1] ] = color ;
9125             ovgood = True ;
9126          }
9127       }
9128    }
9129 #endif
9130 
9131    /*----- return overlay (kill it if nothing happened) -----*/
9132         /* [this should be the 'normal' case these days] */
9133 
9134    if( !ovgood ) KILL_1MRI(im) ;
9135 
9136    /* 30 Jan 2003:
9137       If the functional overlay is in RGB format,
9138       then must meld that with the short color index image */
9139 
9140    if( rgbov != NULL ){
9141      if( im != NULL ){ /* if short overlay is present */
9142        MRI_IMAGE *qim ;
9143        qim = ISQ_overlay( im3d->dc , rgbov , im , 1.0f ) ;
9144        mri_free(rgbov); mri_free(im); rgbov = qim;
9145      }
9146      im = rgbov ; /* overlay is now the RGB(A) image */
9147    }
9148 
9149    RETURN( im ) ;
9150 }
9151 
9152 /*------------------------------------------------------------------------*/
9153 
AFNI_crosshair_label(Three_D_View * im3d)9154 XmString AFNI_crosshair_label( Three_D_View *im3d )
9155 {
9156    char buf[128] ;
9157    XmString xstr ;
9158    static char *RR="[R]" , *LL="[L]" ,
9159                *PP="[P]" , *AA="[A]" ,
9160                *SS="[S]" , *II="[I]" , *ZZ="   " ;
9161    char *xx , *yy , *zz ;
9162    float xval,yval,zval ;
9163 
9164 ENTRY("AFNI_crosshair_label") ;
9165 
9166    if( ! IM3D_VALID(im3d) ) RETURN( NULL );
9167 
9168    if( ! IM3D_OPEN(im3d) ){
9169 
9170       buf[0] = '\0' ;
9171       if( im3d->type != AFNI_IMAGES_VIEW ) strcat(buf," \n") ;
9172       strcat(buf, "1234567890123456789\n"
9173                   "1234567890123456789\n"
9174                   "1234567890123456789"  ) ;
9175 
9176    } else if( im3d->type == AFNI_IMAGES_VIEW || im3d->vinfo->show_voxind ){
9177       int ixyz = DSET_ixyz_to_index( im3d->anat_now ,
9178                     im3d->vinfo->i1, im3d->vinfo->j2, im3d->vinfo->k3 ) ;
9179 
9180 STATUS("voxel indexes") ;
9181 
9182       if( ISVALID_3DIM_DATASET(im3d->fim_now) &&
9183           im3d->vinfo->func_visible && DSET_INMEMORY(im3d->fim_now) ){
9184          THD_fvec3 fv ;
9185          THD_ivec3 iv ;
9186          int flag , fxyz ;
9187 
9188          flag = im3d->fim_now->wod_flag ;
9189          im3d->fim_now->wod_flag = False ;
9190 
9191          fv = THD_dicomm_to_3dmm( im3d->fim_now ,
9192                                   TEMP_FVEC3(im3d->vinfo->xi,im3d->vinfo->yj,im3d->vinfo->zk) ) ;
9193          iv = THD_3dmm_to_3dind( im3d->fim_now , fv ) ;
9194          fxyz = DSET_ixyz_to_index( im3d->fim_now , iv.ijk[0],iv.ijk[1],iv.ijk[2] ) ;
9195 
9196          im3d->fim_now->wod_flag = flag ;
9197 
9198          sprintf( buf , "Ul=%d Ol=%d\nx: Ul=%4d Ol=%4d\ny: Ul=%4d Ol=%4d\nz: Ul=%4d Ol=%4d" ,
9199                   ixyz , fxyz ,
9200                   im3d->vinfo->i1,iv.ijk[0] ,
9201                   im3d->vinfo->j2,iv.ijk[1] ,
9202                   im3d->vinfo->k3,iv.ijk[2]  ) ;
9203       } else {
9204          sprintf( buf , "index %d:\nvoxel x = %4d\nvoxel y = %4d\nvoxel z = %4d" ,
9205                   ixyz , im3d->vinfo->i1 , im3d->vinfo->j2 , im3d->vinfo->k3  ) ;
9206       }
9207    } else {
9208       char bxyz[3][32] , *cname, obl[8] ;
9209       float angle=0.0;
9210 
9211 STATUS("voxel coordinates") ;
9212 
9213       xval = im3d->vinfo->xi ;
9214       yval = im3d->vinfo->yj ;
9215       zval = im3d->vinfo->zk ;
9216 
9217       xx = (xval==0.0) ? (ZZ) : ( (xval<0.0) ? (RR) : (LL) ) ;
9218       yy = (yval==0.0) ? (ZZ) : ( (yval<0.0) ? (AA) : (PP) ) ;
9219       zz = (zval==0.0) ? (ZZ) : ( (zval<0.0) ? (II) : (SS) ) ;
9220 
9221       /** 16 July 1997 **/
9222 #if 1
9223       sprintf( bxyz[0] , "=%9.3f mm %s" ,
9224                GLOBAL_library.cord.xxsign * xval , xx ) ;
9225 
9226       sprintf( bxyz[1] , "=%9.3f mm %s" ,
9227                GLOBAL_library.cord.yysign * yval , yy ) ;
9228 
9229       sprintf( bxyz[2] , "=%9.3f mm %s" ,
9230                GLOBAL_library.cord.zzsign * zval , zz ) ;
9231 
9232       if( strcmp(GLOBAL_library.cord.orcode,"RAI") == 0 )
9233         cname = "=DICOM" ;
9234       else if( strcmp(GLOBAL_library.cord.orcode,"LPI") == 0 )
9235         cname = "=SPM  " ;
9236       else
9237         cname = "      " ;
9238 
9239 
9240       if (dset_obliquity(im3d->anat_now, &angle)==1) sprintf(obl," *");
9241       else obl[0]='\0';
9242 
9243       sprintf( buf , "[order: %s%s%s]\nx %17s\ny %17s\nz %17s"   ,
9244                GLOBAL_library.cord.orcode       , cname , obl,
9245                bxyz[GLOBAL_library.cord.first]  ,
9246                bxyz[GLOBAL_library.cord.second] ,
9247                bxyz[GLOBAL_library.cord.third]   ) ;
9248 #else
9249       sprintf( buf , "x =%9.3f mm %s\ny =%9.3f mm %s\nz =%9.3f mm %s" ,
9250                xval,xx , yval,yy , zval,zz ) ;
9251 #endif
9252    }
9253 
9254    xstr = XmStringCreateLtoR( buf , XmFONTLIST_DEFAULT_TAG ) ;
9255 
9256    RETURN( xstr ) ;
9257 }
9258 
9259 /*-------------------------------------------------------------------------
9260    handle the selection of a marker name by the user
9261    (using the toggle buttons from the control panel or the popup menu)
9262 ---------------------------------------------------------------------------*/
9263 
AFNI_marktog_CB(Widget w,XtPointer client_data,XtPointer call_data)9264 void AFNI_marktog_CB( Widget w ,
9265                       XtPointer client_data , XtPointer call_data )
9266 {
9267    Three_D_View *im3d                = (Three_D_View *)client_data ;
9268    XmToggleButtonCallbackStruct *cbs = (XmToggleButtonCallbackStruct *)call_data;
9269 
9270    int bval , ip , xx=-1 , yy=-1 , zz=-1 ;
9271    Widget *other_tog=NULL ;
9272 
9273 ENTRY("AFNI_marktog_CB") ;
9274 
9275    if( ! IM3D_OPEN(im3d) || im3d->anat_now->markers == NULL ) EXRETURN ;
9276 
9277    switch( cbs->reason ){
9278 
9279       default:  EXRETURN ;  /* error */
9280 
9281       /** case XmCR_ACTIVATE: **/
9282       case XmCR_DISARM:   /* button on the control panel */
9283          bval      = AFNI_first_tog( MARKS_MAXNUM ,
9284                                      im3d->vwid->marks->tog ) ;
9285 #ifdef POPTOG
9286          other_tog = im3d->vwid->marks->poptog ;
9287 #endif
9288       break ;
9289 
9290 #ifdef POPTOG
9291       case XmCR_VALUE_CHANGED:  /* button on the menu panel */
9292          bval = AFNI_first_tog( MARKS_MAXNUM ,
9293                                 im3d->vwid->marks->poptog ) ;
9294          other_tog = im3d->vwid->marks->tog ;
9295       break ;
9296 #endif
9297    }
9298 
9299    /* bval      = index of toggle that is set (-1 if none)
9300       other_tog = pointer to other set of toggles;
9301                   set those buttons to match now */
9302 
9303    if( other_tog != NULL )
9304      AFNI_set_tog( bval , MARKS_MAXNUM , other_tog ) ;
9305 
9306    /* set point overlay colors based on bval */
9307 
9308    for( ip=0 ; ip < MARKS_MAXNUM ; ip++ )
9309       im3d->vwid->marks->isprimary[ip] = False ;
9310 
9311    if( bval >= 0 ){
9312       im3d->vwid->marks->isprimary[bval] = True ;
9313 
9314       if( im3d->anat_now->markers->valid[bval] ){  /* jump to this point */
9315          THD_ivec3 ib ;
9316 
9317          LOAD_ANAT_VIEW(im3d) ;  /* 02 Nov 1996 */
9318          ib = THD_3dmm_to_3dind(
9319                  im3d->anat_now ,
9320                  TEMP_FVEC3( im3d->anat_now->markers->xyz[bval][0] ,
9321                              im3d->anat_now->markers->xyz[bval][1] ,
9322                              im3d->anat_now->markers->xyz[bval][2]  )) ;
9323 
9324          xx = ib.ijk[0] ; yy = ib.ijk[1] ; zz = ib.ijk[2] ;  /* jump is below */
9325          SAVE_VPT(im3d) ;  /* save current location as jumpback point */
9326       }
9327    }
9328 
9329    if( im3d->anat_now->markers->numset > 0 ){
9330       AFNI_set_viewpoint( im3d , xx,yy,zz , REDISPLAY_OVERLAY ) ;  /* redraw */
9331    }
9332 
9333    RESET_AFNI_QUIT(im3d) ;
9334    EXRETURN ;
9335 }
9336 
AFNI_set_tog(int nset,int ntog,Widget * tog)9337 void AFNI_set_tog( int nset , int ntog , Widget *tog )
9338 {
9339    int ib ;
9340 
9341 ENTRY("AFNI_set_tog") ;
9342 
9343    for( ib=0 ; ib < ntog ; ib++ )
9344       XmToggleButtonSetState( tog[ib] , ib==nset , False ) ;
9345 
9346    EXRETURN ;
9347 }
9348 
AFNI_first_tog(int ntog,Widget * tog)9349 int AFNI_first_tog( int ntog , Widget *tog )
9350 {
9351    int ib ;
9352 
9353 ENTRY("AFNI_first_tog") ;
9354 
9355    for( ib=0 ; ib < ntog ; ib++ )
9356       if( XmToggleButtonGetState(tog[ib]) ) break ;
9357 
9358    if( ib >= ntog ) ib = -1 ;
9359    RETURN(ib) ;
9360 }
9361 
9362 #if 0
9363 int AFNI_all_tog( int ntog , Widget *tog )
9364 {
9365    int ib , val = 0 ;
9366 
9367    for( ib=0 ; ib < ntog ; ib++ )
9368       if( XmToggleButtonGetState(tog[ib]) ) val |= (1<<ib) ;
9369    return val ;
9370 }
9371 #endif
9372 
9373 /*-------------------------------------------------------------------------
9374    handle pushbuttons for marks actions:  set and clear markers, etc.
9375 ---------------------------------------------------------------------------*/
9376 
AFNI_marks_action_CB(Widget w,XtPointer client_data,XtPointer call_data)9377 void AFNI_marks_action_CB( Widget w ,
9378                            XtPointer client_data , XtPointer call_data )
9379 {
9380    Three_D_View *im3d = (Three_D_View *) client_data ;
9381    int itog , ipt , setmask , vwarp ;
9382    RwcBoolean sens , transformable ;
9383    THD_marker_set *markers ;
9384    AFNI_marks_widgets *marks ;
9385    THD_fvec3 fv ;
9386 
9387 ENTRY("AFNI_marks_action_CB") ;
9388 
9389    /* sanity check */
9390 
9391    if( ! IM3D_OPEN(im3d) ) EXRETURN ;
9392 
9393    marks = im3d->vwid->marks ;
9394 
9395    /*------ done button (it used to exist) -----*/
9396 
9397    if( w == NULL ){  /* close down */
9398 
9399       RwcBoolean redisplay ;
9400 
9401       MCW_set_bbox( marks->edits_bbox , 0 ) ;
9402       AFNI_marks_edits_CB( NULL , (XtPointer) im3d , NULL ) ;
9403 
9404       MCW_set_bbox( im3d->vwid->view->see_marks_bbox ,
9405                     marks->old_visible ? 1 : 0 ) ;
9406       AFNI_see_marks_CB( NULL , (XtPointer) im3d , NULL ) ;
9407 
9408       redisplay = ! marks->old_visible ;
9409 
9410       for( ipt=0 ; ipt < MARKS_MAXNUM ; ipt++ ){  /* all display as */
9411          redisplay = ( redisplay ||  marks->isprimary[ipt] == True ) ;
9412          marks->isprimary[ipt] = False ;          /* secondary now */
9413       }
9414 
9415       CLOSE_PANEL(im3d,marks) ;  /* close this panel */
9416 
9417       if( redisplay )
9418          AFNI_set_viewpoint( im3d , -1,-1,-1 , REDISPLAY_OVERLAY ) ;  /* redraw */
9419 
9420       /* save markers as they exist now, if any changes made */
9421 
9422       if( im3d->anat_now->markers != NULL && marks->changed ){
9423 #if 0
9424          (void) MCW_popup_message(
9425                    im3d->vwid->view->define_marks_pb ,
9426                    "Saved changed markers\nto dataset disk file." ,
9427                    MCW_USER_KILL | MCW_TIMER_KILL ) ;
9428 #endif
9429 
9430          tross_Append_History( im3d->anat_now , "AFNI: markers were edited" ) ;
9431          DSET_overwrite_header(im3d->anat_now) ;
9432       }
9433 
9434       EXRETURN ;
9435    }
9436 
9437    /*----- quality button (only on when all markers are defined) -----*/
9438 
9439    if( w == marks->action_quality_pb ){
9440       transformable = AFNI_marks_quality_check(True,im3d) ;
9441       SENSITIZE( marks->transform_pb , transformable ) ;
9442       EXRETURN ;
9443    }
9444 
9445    /*----- if here, either a Set or a Clear -----*/
9446 
9447    markers = im3d->anat_now->markers ;
9448    if( markers == NULL ) EXRETURN ;  /* should not happen */
9449 
9450    /* find which point is active (i.e., which toggle is set, if any) */
9451 
9452    itog = AFNI_first_tog( MARKS_MAXNUM , marks->tog ) ;
9453 
9454    if( itog < 0 || ! marks->editable ){
9455       BEEPIT ; EXRETURN ;
9456    }
9457 
9458    ipt = itog ;  /* index of point to deal with */
9459 
9460    /*----- set button pressed -----*/
9461 
9462 #ifdef POPTOG
9463    if( w == marks->action_set_pb || w == marks->pop_set_pb ){
9464 #else
9465    if( w == marks->action_set_pb ){
9466 #endif
9467 
9468       if( ! markers->valid[ipt] ) (markers->numset) ++ ;  /* newly set */
9469 
9470 if(PRINT_TRACING)
9471 { char str[256] ;
9472   sprintf(str,"set #%d numset=%d",ipt,markers->numset) ;
9473   STATUS(str) ; }
9474 
9475       markers->valid[ipt] = True ;
9476 
9477       LOAD_ANAT_VIEW(im3d) ;  /* 02 Nov 1996 */
9478       fv = THD_3dind_to_3dmm( im3d->anat_now ,    /* convert to mm */
9479                               TEMP_IVEC3( im3d->vinfo->i1 ,
9480                                           im3d->vinfo->j2 ,
9481                                           im3d->vinfo->k3  ) ) ;
9482 
9483       markers->xyz[ipt][0] = fv.xyz[0] ;  /* mm in local x,y,z */
9484       markers->xyz[ipt][1] = fv.xyz[1] ;
9485       markers->xyz[ipt][2] = fv.xyz[2] ;
9486 
9487       /* invert colors to mark that the point is set */
9488 
9489       if( ! marks->inverted[itog] ){
9490          MCW_invert_widget( marks->tog[itog] ) ;
9491 #ifdef POPTOG
9492          MCW_invert_widget( marks->poptog[itog] ) ;
9493 #endif
9494          marks->inverted[itog] = True ;
9495       }
9496 
9497       marks->changed = True ;  /* set or reset a marker --> a change */
9498    }
9499 
9500    /*----- clear button pressed -----*/
9501 
9502    else if( w == marks->action_clear_pb || w == marks->pop_clear_pb ){
9503 
9504       if( ! markers->valid[ipt] ){
9505          EXRETURN ;
9506       } else {
9507          (markers->numset) -- ;   /* newly unset --> sub one from count */
9508          marks->changed = True ;  /* cleared a set marker --> a change */
9509       }
9510 
9511 if(PRINT_TRACING)
9512 { char str[256] ;
9513   sprintf(str,"clr #%d numset=%d",ipt,markers->numset) ;
9514   STATUS(str) ; }
9515 
9516       markers->valid[ipt] = False ;
9517 
9518       /* restore colors to mark that the point is unset */
9519 
9520       if( marks->inverted[itog] ){
9521          MCW_invert_widget( marks->tog[itog] ) ;
9522 #ifdef POPTOG
9523          MCW_invert_widget( marks->poptog[itog] ) ;
9524 #endif
9525          marks->inverted[itog] = False ;
9526       }
9527    }
9528 
9529    /*--- allow transformation if all marks are set, etc. ---*/
9530 
9531    vwarp         = WARPED_VIEW(im3d->vinfo->view_type) ;
9532    transformable = marks->editable                         &&
9533                    (markers->aflags[1] != MARKACTION_NONE) &&
9534                    (markers->numdef == markers->numset)    &&
9535                    ISVALID_VIEW(vwarp)                       ;
9536 
9537    SENSITIZE( marks->action_quality_pb , transformable ) ;
9538    SENSITIZE( marks->transform_pb      , False ) ;  /* require QC first */
9539 
9540    /*--- force a redraw ---*/
9541 
9542    AFNI_set_viewpoint( im3d , -1,-1,-1 , REDISPLAY_OVERLAY ) ;
9543    RESET_AFNI_QUIT(im3d) ;
9544    EXRETURN ;
9545 }
9546 
9547 /*-----------------------------------------------------------------------
9548   change the resampling size
9549 -------------------------------------------------------------------------*/
9550 
9551 void AFNI_resam_vox_av_CB( MCW_arrowval *av , XtPointer cd )
9552 {
9553    Three_D_View *im3d = (Three_D_View *) cd ;
9554 
9555 ENTRY("AFNI_resam_vox_av_CB") ;
9556 
9557    if( ! IM3D_OPEN(im3d) ) EXRETURN ;
9558 
9559    if( av == im3d->vwid->dmode->resam_vox_av ){
9560       im3d->vinfo->resam_vox = av->fval ;
9561       SHOW_AFNI_PAUSE ;
9562       im3d->vinfo->tempflag = 1 ;
9563       AFNI_modify_viewing( im3d , True ) ;  /* redisplay */
9564       SHOW_AFNI_READY ;
9565    }
9566    RESET_AFNI_QUIT(im3d) ;
9567    EXRETURN ;
9568 }
9569 
9570 /*------------------------------------------------------------------------
9571    handle the changing arrowvals for marker display controls
9572      (set colors and sizes of markers)
9573 --------------------------------------------------------------------------*/
9574 
9575 void AFNI_marks_disp_av_CB( MCW_arrowval *av , XtPointer client_data )
9576 {
9577    Three_D_View *im3d = (Three_D_View *) client_data ;
9578    int ipx = av->ival ;
9579 
9580 ENTRY("AFNI_marks_disp_av_CB") ;
9581 
9582    if( ! IM3D_OPEN(im3d) ) EXRETURN ;
9583 
9584           if( av == im3d->vwid->marks->disp_pcolor_av ){
9585 
9586             im3d->vwid->marks->ov_pcolor = ipx ;
9587 
9588    } else if( av == im3d->vwid->marks->disp_scolor_av ){
9589 
9590             im3d->vwid->marks->ov_scolor = ipx ;
9591 
9592    } else if( av == im3d->vwid->marks->disp_size_av ){
9593 
9594             im3d->vwid->marks->ov_size = ipx ;
9595 
9596             AFNI_make_ptmask( im3d->vwid->marks->ov_size ,
9597                               im3d->vwid->marks->ov_gap ,
9598                                &(im3d->vwid->marks->ov_mask) ) ;
9599 
9600    } else if( av == im3d->vwid->marks->disp_gap_av ){
9601 
9602             im3d->vwid->marks->ov_gap = ipx ;
9603 
9604             AFNI_make_ptmask( im3d->vwid->marks->ov_size ,
9605                               im3d->vwid->marks->ov_gap ,
9606                                &(im3d->vwid->marks->ov_mask) ) ;
9607 
9608    } else
9609       EXRETURN ;  /* some error */
9610 
9611    /* force a redraw if any points are set */
9612 
9613    if( im3d->anat_now->tagset != NULL ||
9614       (im3d->anat_now->markers != NULL && im3d->anat_now->markers->numset > 0) ){
9615 
9616       AFNI_set_viewpoint( im3d , -1,-1,-1 , REDISPLAY_OVERLAY ) ;
9617    }
9618 
9619    RESET_AFNI_QUIT(im3d) ;
9620    EXRETURN ;
9621 }
9622 
9623 /*------------------------------------------------------------------------*/
9624 
9625 #define PUTPIX(x,y) (tem->dx[npix] = (x) , tem->dy[npix++] = (y))
9626 #define CHKPIX      if( npix >= MAXOVPIX ) break
9627 
9628 void AFNI_make_ptmask( int size , int gap , AFNI_ovtemplate *tem )
9629 {
9630    register int ix , npix=0 , ax ;
9631 
9632 ENTRY("AFNI_make_ptmask") ;
9633 
9634    for( ix=-size ; ix <= size ; ix++ ){
9635       PUTPIX(ix,-size) ; CHKPIX ;
9636       PUTPIX(ix, size) ; CHKPIX ;
9637       ax = abs(ix) ;
9638       if( ax != size ){ PUTPIX( size,ix); CHKPIX; PUTPIX(-size,ix); CHKPIX; }
9639       if( ax >  gap  ){ PUTPIX(ix,0)    ; CHKPIX; PUTPIX(0,ix)    ; CHKPIX; }
9640    }
9641 
9642    tem->numpix = npix ;
9643    EXRETURN ;
9644 }
9645 
9646 /*-------------  October 1998 --------------------------------------------*/
9647 
9648 void AFNI_make_tagmask( int size , int gap , AFNI_ovtemplate *tem )
9649 {
9650    register int ix , npix=0 , ax ;
9651 
9652 ENTRY("AFNI_make_tagmask") ;
9653 
9654    PUTPIX(-size,0) ; PUTPIX(size,0) ;
9655    for( ix=-size+1 ; ix < size ; ix++ ){
9656       ax = abs(ix) ;
9657       PUTPIX(ix,ax-size) ; CHKPIX ;
9658       PUTPIX(ix,size-ax) ; CHKPIX ;
9659 
9660       if( ax > gap ){ PUTPIX(ix,0); CHKPIX; PUTPIX(0,ix); CHKPIX; }
9661    }
9662 
9663    tem->numpix = npix ;
9664    EXRETURN ;
9665 }
9666 
9667 
9668 /*========================================================================
9669    routines to switch "views" on a dataset
9670 ==========================================================================*/
9671 
9672 void AFNI_switchview_CB( Widget w ,
9673                          XtPointer client_data , XtPointer call_data )
9674 {
9675    Three_D_View *im3d = (Three_D_View *) client_data ;
9676    int bval ;
9677 
9678 ENTRY("AFNI_switchview_CB") ;
9679 
9680    if( ! IM3D_OPEN(im3d) ) EXRETURN ;
9681 
9682    bval = AFNI_first_tog( LAST_VIEW_TYPE+1 ,
9683                           im3d->vwid->view->view_bbox->wbut ) ;
9684 
9685    if( bval < 0 || bval == im3d->vinfo->view_type ) EXRETURN ;
9686    if( im3d->anat_dset[bval] == NULL ) EXRETURN ;
9687 
9688    SHOW_AFNI_PAUSE ;
9689 
9690    DISABLE_INSTACORR(im3d) ; DESTROY_ICOR_setup(im3d->iset) ; /* 08 May 2009 */
9691 
9692    POPDOWN_strlist_chooser ;                        /* might be choosing datasets */
9693    UNCLUSTERIZE(im3d) ;                             /* 13 Feb 2008 */
9694 
9695    im3d->vinfo->view_type = bval ;                  /* set the new view type */
9696    AFNI_initialize_view( im3d->anat_now , im3d ) ;  /* and initialize it */
9697 
9698    SHOW_AFNI_READY ;
9699    RESET_AFNI_QUIT(im3d) ;
9700    EXRETURN ;
9701 }
9702 
9703 /*--------------------------------------------------------
9704   Routines to clear out datasets
9705 ----------------------------------------------------------*/
9706 
9707 void AFNI_purge_unused_dsets(void)
9708 {
9709    AFNI_purge_dsets( 0 ) ;
9710 }
9711 
9712 void AFNI_purge_dsets( int doall )
9713 {
9714    int icc , iss , idd , ivv ;
9715    Three_D_View *im3d ;
9716    THD_session  *sess ;
9717    THD_sessionlist *ssl = GLOBAL_library.sslist ;
9718    THD_3dim_dataset *dset ;
9719 
9720 ENTRY("AFNI_purge_dsets") ;
9721 
9722    /*-- sanity check --*/
9723 
9724    if( ! ISVALID_SESSIONLIST(ssl) || ssl->num_sess <= 0 ) EXRETURN ;
9725 
9726    /*-- for each session in the list --*/
9727 
9728    for( iss=0 ; iss < ssl->num_sess ; iss++ ){
9729       sess = ssl->ssar[iss] ;
9730 
9731       /*-- for each anat dataset in the session --*/
9732 
9733       for( idd=0 ; idd < sess->num_dsset ; idd++ ){
9734          for( ivv=FIRST_VIEW_TYPE ; ivv <= LAST_VIEW_TYPE ; ivv++ ){
9735             dset = GET_SESSION_DSET(sess,idd,ivv) ;
9736 /*            dset = sess->dsset_xform_table[idd][ivv] ; */
9737             if( dset == NULL ) continue ;
9738             if( doall ){ PURGE_DSET(dset) ; continue ; }
9739 
9740             /*-- for each controller now running --*/
9741 
9742             for( icc=0 ; icc < MAX_CONTROLLERS ; icc++ ){
9743                im3d = GLOBAL_library.controllers[icc] ;
9744                if( IM3D_VALID(im3d) &&
9745                    ((dset==im3d->anat_now) ||
9746                     (dset==im3d->fim_now)  ||
9747                     (dset==im3d->fimdata->fimdset)) ) break ;
9748             }
9749 
9750             /*-- if didn't find it, purge it --*/
9751             if( icc == MAX_CONTROLLERS ){ PURGE_DSET(dset) ; }
9752          }
9753       }
9754 
9755    } /* end of loop over sessions */
9756    EXRETURN ;
9757 }
9758 
9759 /*---------------------------------------------------------------------
9760    setup for viewing, given the choices in im3d->vinfo
9761    (the indexes of the desired session and datasets, that is)
9762 -----------------------------------------------------------------------*/
9763 
9764 void AFNI_initialize_view( THD_3dim_dataset *old_anat, Three_D_View *im3d )
9765 {
9766    int vvv , itog , lll , sss , aaa , fff , id ;
9767    THD_3dim_dataset     *dset , *new_anat , *new_func ;
9768    THD_marker_set       *markers ;
9769    AFNI_viewing_widgets *view ;
9770    AFNI_marks_widgets   *marks ;
9771    THD_fvec3 fv ;
9772    THD_ivec3 iv ;
9773    static int first_image=1 ; /* 02 Feb 2018 */
9774 
9775 ENTRY("AFNI_initialize_view") ;
9776 
9777    if( ! IM3D_VALID(im3d) ) EXRETURN ;
9778 
9779    vvv = im3d->vinfo->view_type ;  /* locations of new data to view */
9780    sss = im3d->vinfo->sess_num ;
9781    aaa = im3d->vinfo->anat_num ;
9782    fff = im3d->vinfo->func_num ;
9783 
9784 if(PRINT_TRACING)
9785 { char str[256] ;
9786   sprintf(str,"view=%d session=%d anat=%d func=%d",vvv,sss,aaa,fff);
9787   STATUS(str) ; }
9788 
9789    new_anat = GET_SESSION_DSET(GLOBAL_library.sslist->ssar[sss], aaa, vvv) ;
9790    new_func = GET_SESSION_DSET(GLOBAL_library.sslist->ssar[sss], fff, vvv) ;
9791 
9792 /*   new_anat = GLOBAL_library.sslist->ssar[sss]->dsset_xform_table[aaa][vvv] ;
9793    new_func = GLOBAL_library.sslist->ssar[sss]->dsset_xform_table[fff][vvv] ;
9794 */
9795    AFNI_vedit_clear( im3d->fim_now ) ;  /* 05 Sep 2006 */
9796 
9797    /*----------------------------------------------*/
9798    /*--- if the old dataset has markers and the
9799          marker panel is open, shut it down now ---*/
9800 
9801    if( old_anat != NULL     && /** old_anat->markers != NULL && **/
9802        old_anat != new_anat && XtIsManaged(im3d->vwid->marks->frame) ){
9803 
9804       AFNI_marks_action_CB( NULL, (XtPointer) im3d, NULL) ; /* "done" */
9805    }
9806 
9807    if( GLOBAL_argopt.auto_purge == True ){ /* purge old datasets? */
9808 
9809 STATUS("purging old datasets from memory (maybe)") ;
9810 
9811       im3d->anat_now = new_anat ;
9812       im3d->fim_now  = new_func ;
9813       AFNI_purge_unused_dsets() ;
9814    }
9815 
9816    /*---------------------------------------------------------*/
9817    /* set the new datasets that we will deal with from now on */
9818 
9819    for( id=0 ; id <= LAST_VIEW_TYPE ; id++ ){
9820      im3d->anat_dset[id] = GET_SESSION_DSET(GLOBAL_library.sslist->ssar[sss], aaa, id) ;
9821      im3d->fim_dset[id]  = GET_SESSION_DSET(GLOBAL_library.sslist->ssar[sss], fff, id) ;
9822 
9823 /*     im3d->anat_dset[id] = GLOBAL_library.sslist->ssar[sss]->dsset_xform_table[aaa][id] ;
9824      im3d->fim_dset[id]  = GLOBAL_library.sslist->ssar[sss]->dsset_xform_table[fff][id] ;
9825 */
9826      if( ISVALID_3DIM_DATASET(im3d->anat_dset[id]) )
9827        SENSITIZE( im3d->vwid->view->view_bbox->wbut[id], True ) ;
9828      else
9829        SENSITIZE( im3d->vwid->view->view_bbox->wbut[id], False) ;
9830    }
9831 
9832    im3d->anat_now = im3d->anat_dset[vvv] ;
9833    im3d->fim_now  = im3d->fim_dset[vvv] ;
9834    im3d->ss_now   = GLOBAL_library.sslist->ssar[sss] ;
9835 
9836    if( !ISVALID_DSET(im3d->fim_now) ) AFNI_SEE_FUNC_OFF(im3d) ;  /* 22 May 2009 */
9837 
9838    SENSITIZE( im3d->vwid->func->clu_rowcol , DSET_INMEMORY(im3d->fim_now) ) ;
9839 
9840    if( !DSET_INMEMORY(im3d->fim_now) ) UNCLUSTERIZE(im3d) ; /* 14 Feb 2008 */
9841 
9842    /*------------------------------------------------*/
9843    /*--- if markers are defined, then set them up ---*/
9844 
9845    dset    = im3d->anat_now ;
9846    markers = dset->markers ;
9847    view    = im3d->vwid->view ;
9848    marks   = im3d->vwid->marks ;
9849 
9850    if( markers == NULL ){   /*--------- markers NOT defined ---------*/
9851 
9852 STATUS("turning markers off") ;
9853 
9854       /* turn controls off */
9855 
9856 #if 0
9857       SENSITIZE( view->define_marks_pb , False ) ;
9858       SENSITIZE( view->see_marks_bbox->wrowcol , False ) ;
9859 #endif
9860 
9861       marks->editable = False ;
9862 
9863       vvv = MCW_val_bbox( view->see_marks_bbox ) ;
9864       marks->tag_visible = marks->ov_visible = (vvv) ? True : False ;
9865 
9866       XtUnmanageChildren( marks->always_popup    , marks->num_always_popup    ) ;
9867       XtUnmanageChildren( marks->sometimes_popup , marks->num_sometimes_popup ) ;
9868 
9869    } else {   /*------------- markers ARE defined ----------------*/
9870 
9871 STATUS("turning markers on") ;
9872 
9873       /* turn controls on */
9874 
9875       SENSITIZE( view->define_marks_pb , True ) ;
9876       SENSITIZE( view->see_marks_bbox->wrowcol , True ) ;
9877 
9878       vvv = MCW_val_bbox( view->see_marks_bbox ) ;
9879       marks->tag_visible = marks->ov_visible = (vvv) ? True : False ;
9880 
9881       marks->editable = False ;
9882       MCW_set_bbox( marks->edits_bbox , 0 ) ;
9883 
9884 #ifdef POPTOG
9885       SENSITIZE( marks->pop_set_pb   , marks->editable ) ;
9886       SENSITIZE( marks->pop_clear_pb , marks->editable ) ;
9887 #endif
9888 
9889       /* copy help into location where MCW_help will find it */
9890 
9891       for( itog=0 ; itog < MARKS_MAXNUM ; itog++ ){
9892          MCW_strncpy( &(marks->tog_help[itog][0]) ,
9893                       &(markers->help[itog][0]) , MARKS_MAXHELP ) ;
9894       }
9895 
9896       /* copy the non-empty labels into the toggle labels,
9897          and make the toggle buttons active (panel AND popup) */
9898 
9899       XtManageChildren( marks->always_popup ,
9900                         marks->num_always_popup ) ;
9901 
9902       for( itog=0 ; itog < MARKS_MAXNUM ; itog++ ){
9903          lll = strlen( &(markers->label[itog][0]) ) ;
9904 
9905          if( lll == 0 ){
9906             XtUnmanageChild( marks->tog[itog] ) ;   /* empty label! */
9907 #ifdef POPTOG
9908             XtUnmanageChild( marks->poptog[itog] ) ;
9909 #endif
9910          } else {
9911             MCW_set_widget_label( marks->tog[itog] ,
9912                                   &(markers->label[itog][0]) ) ;
9913             SENSITIZE( marks->tog[itog] , True ) ;
9914             XtManageChild( marks->tog[itog] ) ;
9915 
9916 #ifdef POPTOG
9917             MCW_set_widget_label( marks->poptog[itog] ,
9918                                   &(markers->label[itog][0]) ) ;
9919             SENSITIZE( marks->poptog[itog] , True ) ;
9920             XtManageChild( marks->poptog[itog] ) ;
9921 #endif
9922 
9923             if( markers->valid[itog] && ! marks->inverted[itog] ){
9924                MCW_invert_widget( marks->tog[itog] ) ;
9925 #ifdef POPTOG
9926                MCW_invert_widget( marks->poptog[itog] ) ;
9927 #endif
9928                marks->inverted[itog] = True ;
9929             }
9930 
9931             if( ! markers->valid[itog] && marks->inverted[itog] ){
9932                MCW_invert_widget( marks->tog[itog] ) ;
9933 #ifdef POPTOG
9934                MCW_invert_widget( marks->poptog[itog] ) ;
9935 #endif
9936                marks->inverted[itog] = False ;
9937             }
9938          }
9939       } /* end of loop over markers */
9940 
9941    } /* end of dealing with markers */
9942 
9943    /*------------------------------*/
9944    /*----- set up for viewing -----*/
9945 
9946    AFNI_setup_viewing( im3d , True ) ;
9947    AFNI_set_rinfo_labels( im3d ) ;      /* 11 Mar 2020 */
9948 
9949    /*-----------------------------------------------------*/
9950    /*----- reset viewpoint to same Dicom coordinates -----*/
9951 
9952    if( im3d->type == AFNI_3DDATA_VIEW ){
9953       fv = AFNI_transform_vector(
9954               old_anat ,
9955               TEMP_FVEC3( im3d->vinfo->xi, im3d->vinfo->yj, im3d->vinfo->zk ),
9956               dset ) ;
9957 
9958       LOAD_ANAT_VIEW(im3d) ;  /* 02 Nov 1996 */
9959       fv = THD_dicomm_to_3dmm( dset , fv ) ;
9960       iv = THD_3dmm_to_3dind( dset , fv ) ;
9961    } else {
9962       LOAD_IVEC3( iv, im3d->vinfo->i1, im3d->vinfo->j2, im3d->vinfo->k3 ) ;
9963    }
9964 
9965    /* 27 Jan 2004: set coordinate to center of dataset
9966                    if we were formerly looking at the dummy dataset */
9967 
9968    if( (im3d->dummied && !GLOBAL_library.have_dummy_dataset) ||
9969        AFNI_yesenv("AFNI_RECENTER_VIEWING")                    ){
9970      im3d->dummied = 0 ;
9971      LOAD_IVEC3( iv , im3d->anat_now->daxes->nxx/2 ,
9972                       im3d->anat_now->daxes->nyy/2 ,
9973                       im3d->anat_now->daxes->nzz/2  ) ;
9974    }
9975 
9976    DISABLE_LOCK ;  /* 11 Nov 1996 */
9977 
9978    CLU_setup_alpha_tables(im3d) ;  /* Jul 2010 */
9979 
9980    AFNI_view_setter(im3d,NULL) ;
9981    AFNI_set_viewpoint( im3d, iv.ijk[0],iv.ijk[1],iv.ijk[2] , REDISPLAY_ALL ) ;
9982 
9983    ENABLE_LOCK ;   /* 11 Nov 1996 */
9984 
9985    SAVE_VPT(im3d) ;  /* save current location as jumpback */
9986 
9987 #if 0 /* no longer needed */
9988    if( first_image                &&
9989        GLOBAL_argopt.left_is_left &&
9990        im3d->anat_now->dblk->diskptr->storage_mode == STORAGE_BY_IMAGE_FILE ){
9991 
9992      first_image = 0 ;
9993      (void) MCW_popup_message( im3d->vwid->picture ,
9994                                  " \n"
9995                                  "*****--- WARNING: ---*****\n"
9996                                  "  Image viewing is set to\n"
9997                                  "  Left-is-Left, so that\n"
9998                                  "  viewing .jpg or .png\n"
9999                                  "  'datasets' might show\n"
10000                                  "  as reflected left-right.\n"
10001                                  "  To fix this, press the\n"
10002                                  "  l (lower case L) key\n"
10003                                  "  when the mouse cursor\n"
10004                                  "  focus is over the image\n"
10005                                  "  viewer window.\n"
10006                                , MCW_USER_KILL | MCW_TIMER_KILL ) ;
10007    }
10008 #endif
10009 
10010    EXRETURN ;
10011 }
10012 
10013 /*----------------------------------------------------------------------*/
10014 /*! Find the warp that takes one dataset to another, if it exists.
10015     [28 Aug 2002]
10016 ------------------------------------------------------------------------*/
10017 
10018 THD_warp * AFNI_find_warp( THD_3dim_dataset *dset_to , THD_3dim_dataset *dset_from )
10019 {
10020    THD_warp *swarp = NULL ;
10021    char idkey[256] ;
10022 
10023    if( GLOBAL_library.warptable == NULL ||
10024        dset_to   == NULL                ||
10025        dset_from == NULL                  ) return NULL ;
10026 
10027    sprintf(idkey,"%s,%s",dset_to->idcode.str,dset_from->idcode.str) ;
10028    swarp = (THD_warp *) findin_Htable( idkey , GLOBAL_library.warptable ) ;
10029    return swarp ;
10030 }
10031 
10032 /*----------------------------------------------------------------------------*/
10033 /* Set up the thresholded statistic on the fim [moved here 27 Jun 2019] */
10034 
10035 #undef  THBOT
10036 #undef  THTOP
10037 #undef  THBIG
10038 #define THBIG    1.e+37f
10039 #define THBOT(t) ((im3d->vinfo->thr_sign==0 || im3d->vinfo->thr_sign==2) ? (-(t)) : (-THBIG))
10040 #define THTOP(t) ((im3d->vinfo->thr_sign==0 || im3d->vinfo->thr_sign==1) ? (t)    :  (THBIG))
10041 
10042 void AFNI_setup_thrstat( Three_D_View *im3d , int force )
10043 {
10044 ENTRY("AFNI_setup_thrstat") ;
10045 
10046    if( ! IM3D_OPEN(im3d) ) EXRETURN ;
10047 
10048    if( im3d->vinfo->func_visible ){
10049      float thr,thbot,thtop,fac ; MRI_IMAGE *thim , *ovim ; float_pair ovmm ;
10050      thr   = get_3Dview_func_thresh(im3d,1) ;
10051      thbot = THBOT(thr) ; thtop = THTOP(thr) ;
10052      DSET_load(im3d->fim_now) ; /* 24 Jun 2019 */
10053      if( force || im3d->vinfo->fim_index != im3d->fim_thrindex ||
10054                   FLDIF(thbot,im3d->fim_thrbot) || FLDIF(thtop,im3d->fim_thrtop) ){
10055        ovim = AFNI_dataset_displayim(im3d->fim_now,im3d->vinfo->fim_index) ;
10056        thim = AFNI_dataset_displayim(im3d->fim_now,im3d->vinfo->thr_index) ;
10057        IM3D_CLEAR_THRSTAT(im3d) ;
10058        if( ovim != NULL && thim != NULL ){
10059          im3d->fim_thrbot = thbot ; im3d->fim_thrtop = thtop ;
10060          fac = DSET_BRICK_FACTOR(im3d->fim_now,im3d->vinfo->thr_index) ;
10061          if( fac > 0.0f ){ thbot /= fac ; thtop /= fac ; }
10062          ovmm = mri_threshold_minmax(thbot,thtop,thim,ovim) ;
10063          im3d->fim_thresh_min = ovmm.a ; im3d->fim_thresh_max = ovmm.b ;
10064          fac = DSET_BRICK_FACTOR(im3d->fim_now,im3d->vinfo->fim_index) ;
10065          if( fac > 0.0f ){ im3d->fim_thresh_min *= fac ; im3d->fim_thresh_max *= fac ; }
10066        }
10067        if( im3d->fim_thresh_min <= im3d->fim_thresh_max ){
10068          char str[256] ; int_pair mij = mri_threshold_minmax_indexes() ;
10069          sprintf(str,"OLay thresholded range: %f : %f",im3d->fim_thresh_min,im3d->fim_thresh_max ) ;
10070          MCW_register_hint( im3d->vwid->func->range_label , str ) ;
10071          im3d->fim_thresh_min_ijk = mij.i ;
10072          im3d->fim_thresh_max_ijk = mij.j ;
10073          im3d->fim_thrindex = im3d->vinfo->fim_index ;
10074        } else {
10075          MCW_register_hint( im3d->vwid->func->range_label , "OLay thresholded range: unknown" ) ;
10076          im3d->fim_thrindex = -1 ;
10077        }
10078        SENSITIZE(im3d->vwid->func->pbar_jumpto_thmax_pb,(im3d->fim_thresh_max_ijk > 0)) ;
10079        SENSITIZE(im3d->vwid->func->pbar_jumpto_thmin_pb,
10080                    (im3d->fim_thresh_min_ijk > 0)
10081                 && (im3d->fim_thresh_min_ijk != im3d->fim_thresh_max_ijk) ) ;
10082      }
10083    } else {
10084      IM3D_CLEAR_THRSTAT(im3d) ;  /* 12 Jun 2014 */
10085      MCW_register_hint( im3d->vwid->func->range_label , "OLay thresholded range: unknowable" ) ;
10086    }
10087 
10088    EXRETURN ;
10089 }
10090 
10091 #undef  THBOT
10092 #undef  THTOP
10093 #undef  THBIG
10094 
10095 /*----------------------------------------------------------------------
10096    set the stage for viewing:
10097      -- prepare for warp-on-demand image production
10098      -- setup the viewing FD_bricks
10099      -- attach them to the viewing windows
10100      -- turn widget controls on and off, based on data status
10101 
10102    02 Nov 1996: set up view specific viewing stuff in im3d,
10103                 rather than in the datasets.  This is to allow
10104                 for the possibility that more than one im3d
10105                 may be looking at the same dataset at once.
10106 
10107    30 Nov 1997: add bucket stuff
10108 ------------------------------------------------------------------------*/
10109 
10110 void AFNI_setup_viewing( Three_D_View *im3d , RwcBoolean rescaled )
10111 {
10112    FD_brick **fbr ;
10113    XmString xstr ;
10114    RwcBoolean  same , dont_fix_pts , writer ,
10115             anat_brick_possible , func_brick_possible ;
10116    int      val , top ;
10117 
10118    static THD_3dim_dataset *old_fim  = NULL ; /* 12 Dec 2001 */
10119    static Three_D_View     *old_im3d = NULL ; /* 29 Jan 2002 */
10120    static THD_3dim_dataset *old_anat = NULL ; /* 12 Dec 2001 */
10121    static int         old_anat_nvals = -1 ;   /* 21 Jul 2009 */
10122    static int         old_func_nvals = -1 ;   /* 21 Jul 2009 */
10123 
10124 ENTRY("AFNI_setup_viewing") ;
10125 
10126    if( ! IM3D_VALID(im3d) ) EXRETURN ;
10127 
10128    /*-----------------------------------------------------*/
10129    /*--- set up the anat w-o-d axes and viewing bricks ---*/
10130 
10131    anat_brick_possible = DSET_INMEMORY(im3d->anat_now) ;
10132 
10133    /*- The Ides of March, 2000: allow switching back to "view brick" -*/
10134 
10135    if( anat_brick_possible         &&
10136        im3d->vinfo->force_anat_wod &&
10137        im3d->vinfo->tempflag == 0  &&
10138        !AFNI_noenv("AFNI_VIEW_ANAT_BRICK") ){
10139 
10140 STATUS("setting anatmode_bbox back to 'View ULay Data Brick'") ;
10141       im3d->vinfo->force_anat_wod = 0 ;
10142       MCW_set_bbox( im3d->vwid->dmode->anatmode_bbox , DMODE_BRICK_BVAL ) ;
10143    }
10144 
10145    im3d->anat_wod_flag = ( im3d->vinfo->force_anat_wod ||       /* 02 Nov 1996 */
10146                            !anat_brick_possible          ) ;
10147 
10148    if( im3d->anat_wod_flag )                                    /* 02 Nov 1996 */
10149       THD_edit_dataxes( im3d->vinfo->resam_vox ,
10150                         im3d->anat_now->daxes , im3d->wod_daxes ) ;
10151    else
10152       *(im3d->wod_daxes) = *(im3d->anat_now->daxes) ;
10153 
10154    im3d->anat_voxwarp->type =
10155      im3d->fim_voxwarp->type = ILLEGAL_TYPE ;                   /* 02 Nov 1996 */
10156 
10157    LOAD_ANAT_VIEW(im3d) ;                                       /* 02 Nov 1996 */
10158 
10159    fbr = THD_setup_bricks( im3d->anat_now ) ;
10160    if( fbr == NULL ){
10161      ERROR_message("THD_setup_bricks of anat_now fails!") ; EXRETURN ;
10162    }
10163    DESTROY_FD_BRICK(im3d->b123_anat) ; im3d->b123_anat = fbr[0] ;
10164    DESTROY_FD_BRICK(im3d->b231_anat) ; im3d->b231_anat = fbr[1] ;
10165    DESTROY_FD_BRICK(im3d->b312_anat) ; im3d->b312_anat = fbr[2] ;
10166    myXtFree(fbr) ;
10167 
10168    im3d->b123_anat->parent =
10169      im3d->b231_anat->parent =
10170        im3d->b312_anat->parent = (XtPointer) im3d ;
10171 
10172    im3d->b123_anat->resam_code =
10173      im3d->b231_anat->resam_code =
10174        im3d->b312_anat->resam_code = im3d->vinfo->anat_resam_mode ;
10175 
10176    im3d->b123_anat->thr_resam_code =     /* 30 Jul 2003 */
10177      im3d->b231_anat->thr_resam_code =
10178        im3d->b312_anat->thr_resam_code = im3d->vinfo->anat_resam_mode ;
10179 
10180    /* 30 Nov 1997: don't go past end of dataset */
10181 
10182    if( im3d->vinfo->anat_index >= DSET_NVALS(im3d->anat_now) )
10183      im3d->vinfo->anat_index = DSET_NVALS(im3d->anat_now) - 1 ;
10184 
10185    /*-----------------------------------------------------*/
10186    /*--- set up the func w-o-d axes and viewing bricks ---*/
10187 
10188    if( ISVALID_3DIM_DATASET(im3d->fim_now) ){  /* that is, if we have func */
10189 
10190 STATUS("function brick setup") ;
10191 
10192       /*-- access data in dataset im3d->fim_now IF AND ONLY IF
10193              1) its actual data axes are the same as the wod_daxes
10194              2) it has actual data
10195              3) the user hasn't officially declared for warp-on-demand
10196              4) the dataset doesn't have a warp to bring it into
10197                 alignment with the current anat dataset (self_warp)    --*/
10198 
10199 STATUS("deciding whether to use function WOD") ;
10200 
10201       func_brick_possible =
10202          EQUIV_DATAXES( im3d->fim_now->daxes , im3d->wod_daxes ) &&   /* 02 Nov 1996 */
10203          DSET_INMEMORY( im3d->fim_now ) ;
10204 
10205       /*- 27 Aug 2002: see if there is a self_warp from
10206                        fim_now back to anat_now; if so, install it;
10207                        this is a coordinate-to-coordinate tranformation,
10208                        and requires warp-on-demand viewing              -*/
10209 
10210       { THD_warp *swarp = AFNI_find_warp( im3d->anat_now , im3d->fim_now ) ;
10211         im3d->fim_selfwarp = swarp ;  /* transform from fim to anat coords */
10212         if( swarp != NULL ) func_brick_possible = 0 ;   /* require warp-on-demand */
10213       }
10214 
10215       /*- The Ides of March, 2000: allow switching back to "view brick" -*/
10216 
10217       if( func_brick_possible                       &&
10218           ( ( im3d->vinfo->force_func_wod  &&
10219               im3d->vinfo->tempflag == 0   &&
10220               !AFNI_noenv("AFNI_VIEW_FUNC_BRICK") ) ||
10221             ( !im3d->anat_wod_flag         &&              /* 08 Aug 2003 */
10222               im3d->anat_now == im3d->fim_now     )   ) ){
10223 
10224 STATUS("setting funcmode_bbox back to 'View Func Data Brick'") ;
10225          im3d->vinfo->force_func_wod = 0 ;
10226          MCW_set_bbox( im3d->vwid->dmode->funcmode_bbox , DMODE_BRICK_BVAL ) ;
10227       }
10228 
10229       if( func_brick_possible && ! im3d->vinfo->force_func_wod ){
10230 STATUS("not forcing function WOD") ;
10231         im3d->fim_wod_flag = False ;   /* 02 Nov 1996 */
10232       } else {
10233 STATUS("forcing function WOD") ;
10234         im3d->fim_wod_flag = True ;    /* 02 Nov 1996 */
10235       }
10236 
10237       LOAD_FUNC_VIEW(im3d) ;  /* 02 Nov 1996 */
10238 
10239       fbr = THD_setup_bricks( im3d->fim_now ) ;
10240       if( fbr == NULL ){
10241         fprintf(stderr,"THD_setup_bricks of fim_now fails!\n") ; EXRETURN ;
10242       }
10243       DESTROY_FD_BRICK(im3d->b123_fim) ; im3d->b123_fim = fbr[0] ;
10244       DESTROY_FD_BRICK(im3d->b231_fim) ; im3d->b231_fim = fbr[1] ;
10245       DESTROY_FD_BRICK(im3d->b312_fim) ; im3d->b312_fim = fbr[2] ;
10246       myXtFree(fbr) ;
10247 
10248       im3d->b123_fim->brother = (XtPointer)im3d->b123_anat ;
10249       im3d->b231_fim->brother = (XtPointer)im3d->b231_anat ;
10250       im3d->b312_fim->brother = (XtPointer)im3d->b312_anat ;
10251 
10252       im3d->b123_anat->brother = (XtPointer)im3d->b123_fim ;
10253       im3d->b231_anat->brother = (XtPointer)im3d->b231_fim ;
10254       im3d->b312_anat->brother = (XtPointer)im3d->b312_fim ;
10255 
10256       im3d->b123_fim->parent =
10257         im3d->b231_fim->parent =
10258           im3d->b312_fim->parent = (XtPointer) im3d ;
10259 
10260       im3d->b123_fim->resam_code =
10261         im3d->b231_fim->resam_code =
10262           im3d->b312_fim->resam_code = im3d->vinfo->func_resam_mode ;
10263 
10264       im3d->b123_fim->thr_resam_code =     /* 09 Dec 1997 */
10265         im3d->b231_fim->thr_resam_code =
10266           im3d->b312_fim->thr_resam_code = im3d->vinfo->thr_resam_mode ;
10267 
10268       /* 30 Nov 1997: don't go past end of bucket */
10269 
10270       if( im3d->vinfo->fim_index >= DSET_NVALS(im3d->fim_now) )
10271           im3d->vinfo->fim_index = DSET_NVALS(im3d->fim_now) - 1 ;
10272 
10273       if( im3d->vinfo->thr_index >= DSET_NVALS(im3d->fim_now) )
10274           im3d->vinfo->thr_index = DSET_NVALS(im3d->fim_now) - 1 ;
10275 
10276       /* first time in for this controller (or if so ordered),
10277          set fim_index and thr_index to reasonable values (IMHO)
10278          -- modified 12 Jan 2017 to define 'reasonable' more reasonably */
10279 
10280       { static int first=1, ffim[MAX_CONTROLLERS] ; int qq ;
10281         if( first ){
10282           first=0; for( qq=0; qq < MAX_CONTROLLERS; qq++ ) ffim[qq]=1;
10283         }
10284         qq = AFNI_controller_index(im3d) ;
10285         if( ffim[qq] || im3d->vinfo->func_init_subbricks ){
10286           int_pair otp = find_reasonable_overlay_indexes(im3d->fim_now) ;
10287           if( otp.i >= 0 ) im3d->vinfo->fim_index = otp.i ;
10288           if( otp.j >= 0 ) im3d->vinfo->thr_index = otp.j ;
10289           ffim[qq] = 0 ;
10290         }
10291       }
10292 
10293       im3d->vinfo->func_init_subbricks = 0 ;  /* 12 Jan 2017 */
10294 
10295       /* 29 Jan 2008: enable/disable the FDR-izing button */
10296 
10297       { int scod=DSET_BRICK_STATCODE(im3d->fim_now,im3d->vinfo->thr_index) ,
10298             doit=FUNC_IS_STAT(scod) && DSET_INMEMORY(im3d->fim_now) ;
10299         XtSetSensitive( im3d->vwid->func->thr_fdr_pb , (RwcBoolean)doit ) ;
10300       }
10301 
10302    } else {   /* 29 Jul 2003: no longer possible */
10303 
10304 STATUS("no function dataset") ;
10305 
10306       DESTROY_FD_BRICK(im3d->b123_fim) ; im3d->b123_fim = NULL ;
10307       DESTROY_FD_BRICK(im3d->b231_fim) ; im3d->b231_fim = NULL ;
10308       DESTROY_FD_BRICK(im3d->b312_fim) ; im3d->b312_fim = NULL ;
10309 
10310       func_brick_possible = False ;
10311    }
10312 
10313    /*------------------------------------------------------------------*/
10314    /*--- set widget sensitivity based on kind of data now available ---*/
10315 
10316 STATUS("turning widgets on and/or off:") ;
10317 
10318    /*--- datamode controls ---*/
10319 
10320 STATUS(" -- datamode widgets") ;
10321 
10322    if( anat_brick_possible ){
10323      SENSITIZE( im3d->vwid->dmode->anatmode_bbox->wbut[DMODE_BRICK] , True ) ;
10324    } else {
10325      SENSITIZE( im3d->vwid->dmode->anatmode_bbox->wbut[DMODE_BRICK] , False ) ;
10326      MCW_set_bbox( im3d->vwid->dmode->anatmode_bbox , DMODE_WOD_BVAL ) ;
10327      im3d->vinfo->force_anat_wod = 1 ;
10328    }
10329 
10330    if( func_brick_possible ){
10331      SENSITIZE( im3d->vwid->dmode->funcmode_bbox->wbut[DMODE_BRICK] , True ) ;
10332    } else {
10333      SENSITIZE( im3d->vwid->dmode->funcmode_bbox->wbut[DMODE_BRICK] , False ) ;
10334      MCW_set_bbox( im3d->vwid->dmode->funcmode_bbox , DMODE_WOD_BVAL ) ;
10335      im3d->vinfo->force_func_wod = 1 ;
10336    }
10337 
10338    AV_SENSITIZE( im3d->vwid->dmode->anat_resam_av , im3d->anat_wod_flag ) ;
10339 
10340    AV_SENSITIZE( im3d->vwid->dmode->resam_vox_av , im3d->anat_wod_flag ) ;
10341 
10342    /* Jan 31, 1995: don't allow writes of datasets without warp parents */
10343    /* Jun 22, 1995: allow it if destruct mode is actuated!              */
10344 
10345    if( GLOBAL_argopt.destruct ){  /* not currently implemented */
10346      writer = True ;
10347    } else {
10348      writer = (RwcBoolean) DSET_WRITEABLE(im3d->anat_now) ;  /* mod 26 Mar 2001 */
10349    }
10350 
10351    SENSITIZE( im3d->vwid->dmode->write_anat_pb , writer ) ;
10352 
10353    if( GLOBAL_argopt.destruct ){  /* not currently implemented */
10354      writer = (RwcBoolean) ISVALID_3DIM_DATASET(im3d->fim_now) ;
10355    } else {
10356      writer = (RwcBoolean) DSET_WRITEABLE(im3d->fim_now) ;  /* mod 26 Mar 2001 */
10357    }
10358 
10359    SENSITIZE( im3d->vwid->dmode->write_func_pb , writer ) ;
10360 
10361    /* 18 Oct 2010: SaveAs buttons on or off? */
10362 
10363    writer = DSET_INMEMORY(im3d->anat_now) ;
10364    SENSITIZE( im3d->vwid->dmode->saveas_anat_pb , writer ) ;
10365 
10366    writer = DSET_INMEMORY(im3d->fim_now) ;
10367    SENSITIZE( im3d->vwid->dmode->saveas_func_pb , writer ) ;
10368 
10369    /*--- function controls (always see them) ---*/
10370 
10371    {  RwcBoolean have_fim = ISVALID_3DIM_DATASET(im3d->fim_now) ;
10372       RwcBoolean have_thr = have_fim ;
10373 
10374       static int first=1, zfim[MAX_CONTROLLERS] ; int qq ;
10375       if( first ){
10376         first=0; for( qq=0; qq < MAX_CONTROLLERS; qq++ ) zfim[qq]=1;
10377       }
10378 
10379 STATUS(" -- function widgets ON") ;
10380 
10381       SENSITIZE( im3d->vwid->view->define_func_pb      , True ) ;  /* always on */
10382       SENSITIZE( im3d->vwid->view->see_func_bbox->wtop , True ) ;
10383 
10384       /* setup threshold slider to be always on */
10385 
10386       XtManageChild( im3d->vwid->func->thr_rowcol ) ;
10387       qq = AFNI_controller_index(im3d) ;
10388       if( zfim[qq] && ISVALID_DSET(im3d->fim_now) ){
10389 STATUS(" -- set threshold to zero (startup)") ;
10390         XmScaleSetValue( im3d->vwid->func->thr_scale , 1 ) ;
10391         im3d->vinfo->func_threshold = THR_factor ; zfim[qq] = 0 ;
10392       }
10393       FIX_SCALE_SIZE(im3d) ; FIX_SCALE_VALUE(im3d) ;
10394 
10395       /* turn on various ways of making function into underlay */
10396 
10397 #ifdef USE_UNDERLAY_BBOX
10398       SENSITIZE( im3d->vwid->func->underlay_bbox->wbut[UNDERLAY_ALLFUNC], have_fim ) ;
10399 #endif
10400 
10401       /* set underlay type back to anat if no function */
10402 
10403       if( ! have_fim ) im3d->vinfo->underlay_type = UNDERLAY_ANAT ;
10404 
10405       /* allow resample control only if we are using w-o-d */
10406 
10407       AV_SENSITIZE( im3d->vwid->dmode->func_resam_av,
10408                     have_fim && im3d->fim_wod_flag ) ;
10409 
10410       AV_SENSITIZE( im3d->vwid->dmode->thr_resam_av,    /* 09 Dec 1997 */
10411                     have_fim && im3d->fim_wod_flag ) ;
10412 
10413       /** Mar 1996: modify the threshold scale stuff **/
10414       /** Oct 1996: increase decim by 1 to allow for
10415                     new precision 0..999 of scale (used to be 0..99) **/
10416       /** Nov 1997: the scale precision is now set by macro THR_top_expon,
10417                     and its settings are done in routine AFNI_set_thresh_top **/
10418 
10419 #if 0
10420       if( have_thr ){
10421         int iv = im3d->vinfo->thr_index , jj ;
10422 
10423         jj = DSET_BRICK_STATCODE(im3d->fim_now,iv) ;
10424         if( jj > 0 )
10425           MCW_set_widget_label( im3d->vwid->func->thr_label ,
10426                                 FUNC_label[jj] ) ;
10427         else
10428           MCW_set_widget_label( im3d->vwid->func->thr_label ,
10429                                 DSET_BRICK_LABEL(im3d->fim_now,iv) ) ;
10430       }
10431 #endif
10432 
10433       /* set the pval label at the bottom of the scale */
10434 
10435       AFNI_set_thr_pval( im3d ) ;
10436 
10437       /*** 29 Jul 2003: always do buckets now ***/
10438 
10439       XtManageChild( im3d->vwid->func->anat_buck_av->wrowcol ) ;
10440       XtManageChild( im3d->vwid->func->fim_buck_av->wrowcol  ) ;
10441       XtManageChild( im3d->vwid->func->thr_buck_av->wrowcol  ) ;
10442 
10443       /** 12 Dec 2001: only refit menus if dataset has changed **/
10444 
10445       if( have_fim &&
10446           (im3d->fim_now != old_fim || im3d != old_im3d ||
10447            DSET_NVALS(im3d->fim_now) != old_func_nvals )  ){
10448         refit_MCW_optmenu( im3d->vwid->func->fim_buck_av ,
10449                            0 ,                            /* new minval */
10450                            DSET_NVALS(im3d->fim_now)-1 ,  /* new maxval */
10451                            im3d->vinfo->fim_index ,       /* new inival */
10452                            0 ,                            /* new decim? */
10453                            AFNI_bucket_label_CB ,         /* text routine */
10454                            im3d->fim_now                  /* text data */
10455                          ) ;
10456         refit_MCW_optmenu( im3d->vwid->func->thr_buck_av ,
10457                            0 ,                            /* new minval */
10458                            DSET_NVALS(im3d->fim_now)-1 ,  /* new maxval */
10459                            im3d->vinfo->thr_index ,       /* new inival */
10460                            0 ,                            /* new decim? */
10461                            AFNI_bucket_label_CB ,         /* text routine */
10462                            im3d->fim_now                  /* text data */
10463                          ) ;
10464       }
10465 
10466       if( im3d->anat_now != old_anat || im3d != old_im3d ||
10467           DSET_NVALS(im3d->anat_now) != old_anat_nvals     ){
10468         refit_MCW_optmenu( im3d->vwid->func->anat_buck_av ,
10469                            0 ,                             /* new minval */
10470                            DSET_NVALS(im3d->anat_now)-1 ,  /* new maxval */
10471                            im3d->vinfo->anat_index ,       /* new inival */
10472                            0 ,                             /* new decim? */
10473                            AFNI_bucket_label_CB ,          /* text routine */
10474                            im3d->anat_now                  /* text data */
10475                          ) ;
10476       }
10477 
10478       XtManageChild( im3d->vwid->func->buck_rowcol ) ;  /* make itvisible */
10479       XtManageChild( im3d->vwid->func->buck_frame ) ;
10480    }
10481 
10482    /*--- set the function type bboxes based on the current
10483          viewing set up (which may have changed due to lack of function) ---*/
10484 
10485 STATUS(" -- function underlay widgets") ;
10486 
10487 #ifdef USE_UNDERLAY_BBOX
10488    MCW_set_bbox( im3d->vwid->func->underlay_bbox , 1 << im3d->vinfo->underlay_type ) ;
10489 #endif
10490 
10491    AFNI_assign_ulay_bricks(im3d) ;   /* 10 Jun 2014 */
10492 
10493    /*--------------------------------------------------------*/
10494    /*--- 3/24/95: deal with the new range widgets in func ---*/
10495 
10496    AFNI_reset_func_range( im3d ) ;
10497 
10498 #ifdef ALLOW_DATASET_VLIST
10499    /*---------------------------------------------------------*/
10500    /*--- May 1995: if points exist in some other dataset   ---*/
10501    /*---           associated with this one, but not here, ---*/
10502    /*---           transform the points to this dataset.   ---*/
10503 
10504    dont_fix_pts = ! rescaled ;  /* if didn't rescale, don't need to fix */
10505 
10506    if( im3d->anat_now->pts == NULL ){
10507       int ii ;
10508       THD_3dim_dataset *dset_orig = NULL ;
10509       THD_fvec3 fv ;
10510 
10511 STATUS(" -- scanning for points in other datasets") ;
10512       for( ii=0 ; ii <= LAST_VIEW_TYPE ; ii++ ){
10513          if( ISVALID_3DIM_DATASET(im3d->anat_dset[ii]) &&
10514              im3d->anat_dset[ii]->pts != NULL &&
10515              im3d->anat_dset[ii]->pts_original == True ){
10516 
10517             dset_orig = im3d->anat_dset[ii] ;
10518             break ;
10519          }
10520       }
10521 
10522       if( dset_orig != NULL ){
10523 STATUS(" -- processing points in other dataset") ;
10524 
10525          dont_fix_pts                 = True ;   /* fixing here, so not later */
10526          im3d->anat_now->pts_original = False ;
10527          INIT_VLIST( im3d->anat_now->pts , im3d->anat_now ) ;
10528 
10529          for( ii=0 ; ii < dset_orig->pts->num ; ii++ ){
10530             fv = THD_3dmm_to_dicomm( dset_orig , dset_orig->pts->xyz[ii] ) ;
10531             fv = AFNI_transform_vector( dset_orig , fv  , im3d->anat_now ) ;
10532             fv = THD_dicomm_to_3dmm( im3d->anat_now , fv ) ;
10533             ADD_FVEC_TO_VLIST( im3d->anat_now->pts , fv ) ;
10534          }
10535       }
10536    }
10537 
10538    /*--------------------------------------------------*/
10539    /*--- May 1995: if points exist in this dataset, ---*/
10540    /*---           load their 3dind coordinates.    ---*/
10541 
10542    if( im3d->anat_now->pts != NULL && ! dont_fix_pts ){
10543       int ii ;
10544 STATUS(" -- processing points in this dataset") ;
10545 
10546       for( ii=0 ; ii < im3d->anat_now->pts->num ; ii++ )
10547          im3d->anat_now->pts->ijk[ii] =
10548             THD_3dmm_to_3dind( im3d->anat_now , im3d->anat_now->pts->xyz[ii] ) ;
10549    }
10550 #endif /* ALLOW_DATASET_VLIST */
10551 
10552    /*------ 06 Mar 2002: turn "SUMA to" on image popup on or off ------*/
10553 
10554    if( im3d->vwid->imag->pop_sumato_pb != NULL ){
10555      if( SESSION_HAS_SUMA(im3d->ss_now) )
10556        XtManageChild( im3d->vwid->imag->pop_sumato_pb ) ;
10557      else
10558        XtUnmanageChild( im3d->vwid->imag->pop_sumato_pb ) ;
10559    }
10560 
10561    /*------ 01 May 2002: turn "Jump to (MNI)" on or off ------*/
10562 
10563    if( im3d->vwid->imag->pop_mnito_pb != NULL ){
10564      if( CAN_TALTO(im3d) )
10565        XtManageChild( im3d->vwid->imag->pop_mnito_pb ) ;
10566      else
10567        XtUnmanageChild( im3d->vwid->imag->pop_mnito_pb ) ;
10568    }
10569 
10570    /*-------------------------------------------------------------------*/
10571    /*--- Sep 1995: turn "Go to atlas position" button on
10572          image popup on or off ---*/
10573 
10574 STATUS(" -- managing Go to atlas position button, etc") ;
10575 
10576    if( im3d->vwid->imag->pop_talto_pb != NULL ){
10577      if( CAN_TALTO(im3d) ){
10578        XtSetSensitive( im3d->vwid->imag->pop_talto_pb , True ) ;
10579        if( im3d->vwid->imag->pop_whereami_pb != NULL )
10580          XtSetSensitive( im3d->vwid->imag->pop_whereami_pb , True ); /* 10 Jul 2001 */
10581        if( im3d->vwid->imag->pop_ttren_pb != NULL )
10582          XtSetSensitive( im3d->vwid->imag->pop_ttren_pb ,              /* 12 Jul 2001 */
10583                          im3d->vinfo->view_type==VIEW_TALAIRACH_TYPE); /* 01 Aug 2001 */
10584      } else {
10585        XtSetSensitive( im3d->vwid->imag->pop_talto_pb, False ) ;
10586        if( im3d->vwid->imag->pop_whereami_pb != NULL )
10587          XtSetSensitive( im3d->vwid->imag->pop_whereami_pb, False ); /* 10 Jul 2001 */
10588        if( im3d->vwid->imag->pop_ttren_pb != NULL )
10589          XtSetSensitive( im3d->vwid->imag->pop_ttren_pb , False ); /* 12 Jul 2001 */
10590      }
10591    }
10592 
10593    if( im3d->vwid->imag->pop_instacorr_pb != NULL ){
10594      if( ISREADY_EITHER_ICOR(im3d) ) ENABLE_INSTACORR(im3d) ;
10595      else                           DISABLE_INSTACORR(im3d) ;
10596    }
10597 
10598    /*--- 25 Jul 2001: sensitize 'See TT Atlas Regions' button ---*/
10599 
10600 #if 1
10601    XtSetSensitive( im3d->vwid->func->see_ttatlas_bbox->wrowcol ,
10602           (RwcBoolean)( im3d->anat_now->view_type == VIEW_TALAIRACH_TYPE &&
10603           TT_retrieve_atlas_dset(Current_Atlas_Default_Name(), 0) != NULL) ) ;
10604 #else
10605    XtSetSensitive( im3d->vwid->func->see_ttatlas_bbox->wrowcol , False ) ;
10606 #endif
10607 
10608    /*------------------------------------*/
10609    /*--- May 1996: Time index control ---*/
10610    /*--- Mar 1997: Allow FIM also     ---*/
10611 
10612 #if 0
10613    top = DSET_NUM_TIMES(im3d->anat_now) ;
10614    if( ISVALID_3DIM_DATASET(im3d->fim_now) )
10615       top = MAX( top , DSET_NUM_TIMES(im3d->fim_now) ) ;
10616 #else
10617    top = DSET_NVALS(im3d->anat_now) ;
10618    if( ISVALID_3DIM_DATASET(im3d->fim_now) )
10619       top = MAX( top , DSET_NVALS(im3d->fim_now) ) ;
10620 #endif
10621 
10622    if( top > 1 ){
10623      MCW_arrowval *tav = im3d->vwid->imag->time_index_av ;
10624 STATUS(" -- turning time index control on") ;
10625 
10626      AV_SENSITIZE( tav , True ) ; im3d->vinfo->time_on = 1 ;
10627      tav->fmax = tav->imax = top - 1 ; im3d->vinfo->top_index = top ;
10628      if( im3d->vinfo->time_index > tav->imax ){
10629        im3d->vinfo->time_index = tav->imax ;
10630        AV_assign_ival( tav , tav->imax ) ;
10631        AFNI_process_timeindex(im3d) ;       /* 29 Jan 2003 */
10632      }
10633    } else {
10634 STATUS(" -- turning time index control off") ;
10635      AV_SENSITIZE( im3d->vwid->imag->time_index_av , False ) ;
10636      im3d->vinfo->time_on = 0 ;
10637    }
10638 
10639    /*--------------------------------------------------------------*/
10640    /*--- 19 Nov 1996: Set FIM-able dataset to this, if possible ---*/
10641 
10642    if( DSET_GRAPHABLE(im3d->anat_now) )
10643      im3d->fimdata->fimdset = im3d->anat_now ;
10644 
10645    ALLOW_COMPUTE_FIM(im3d) ;
10646 
10647    /*----------------------------------------------------------------*/
10648    /*--- 19 Aug 2002: enable/disable surface chooser button, etc. ---*/
10649 
10650    AFNI_update_surface_widgets( im3d ) ;
10651 
10652    /*------------------------------------------*/
10653    /*--- attach to viewing windows (if any) ---*/
10654 
10655    AFNI_underlay_CB( NULL , im3d , NULL ) ;
10656 
10657    /* 04 Nov 2003: set range for image grayscaling? */
10658 
10659    AFNI_range_setter( im3d , im3d->s123 ) ;
10660    AFNI_range_setter( im3d , im3d->s231 ) ;
10661    AFNI_range_setter( im3d , im3d->s312 ) ;
10662 
10663    im3d->vinfo->tempflag = 0 ;
10664 
10665    old_im3d = im3d ;
10666    old_fim  = im3d->fim_now ;   /* remembrance */
10667    old_anat = im3d->anat_now ;
10668 
10669    old_anat_nvals = DSET_NVALS(im3d->anat_now) ; /* 21 Jul 2009 */
10670 
10671    /* This next line can fail if fim_now is NULL.
10672    fim_now can be NULL if you switch to tlrc view and
10673    for some reason, the transform fails on the fim image.
10674    We have seen this happen when:
10675       1st volume in list is anat and has a +orig only.
10676       2nd volume in list is anat2 and has a +orig and +tlrc
10677       3rd volume in list is a functional dset  (selected as overlay)
10678    You switch to anat2 and select TLRC view, BOOM.
10679    Our guess is that since the first dset has no tlrc xform,
10680    the third one, which is the overlay seems to get no TLRC daddy,
10681    even if the second anat has a tlrc xform .
10682    Should be able to test this hypothesis by expressly setting the
10683    anat parent of all volumes to that of the anat with the TLRC xform....
10684 
10685       ZSS, RICKR, with no time to fix this quite yet.    July 28 2009 */
10686 
10687    /** 10 Aug 2009: the fix is below -- RWCox **/
10688 
10689    if( ISVALID_DSET(im3d->fim_now) )
10690      old_func_nvals = DSET_NVALS(im3d->fim_now) ;
10691    else
10692      old_func_nvals = -1 ;
10693 
10694    /* DRG 25 Apr 2016  */
10695    /*   extra fix for percentile flag not working with warp-on-demand switch views */
10696    if(DSET_ONDISK(im3d->fim_now)) {
10697      MCW_set_bbox( im3d->vwid->func->perc_bbox ,
10698                  (im3d->cont_perc_thr) ? (1) : (0) ) ;
10699       SENSITIZE( im3d->vwid->func->perc_bbox->wbut[PERC_AUTOBUT] , TRUE ) ;
10700    }
10701    else {
10702       MCW_set_bbox( im3d->vwid->func->perc_bbox , 0 ) ;
10703       im3d->cont_perc_thr = 0;
10704       SENSITIZE( im3d->vwid->func->perc_bbox->wbut[PERC_AUTOBUT] , False ) ;
10705    }
10706 
10707    IM3D_CLEAR_THRSTAT(im3d) ;    /* 12 Jun 2014 */
10708    AFNI_setup_thrstat(im3d,1) ;  /* 27 Jun 2019 */
10709 
10710    AFNI_sleep(13) ;              /* 18 Oct 2005: for luck */
10711 
10712    EXRETURN ;
10713 }
10714 
10715 /*-----------------------------------------------------------------------
10716   Tell if AFNI_transform_vector can take a vector from old_dset
10717   to new_dset coordinates -- 09 Jul 2001 -- RWCox.
10718 -------------------------------------------------------------------------*/
10719 
10720 int AFNI_can_transform_vector( THD_3dim_dataset *old_dset ,
10721                                THD_3dim_dataset *new_dset  )
10722 {
10723    if( old_dset==NULL || new_dset==NULL  ) return 0 ;
10724 
10725    if( old_dset == new_dset->warp_parent ) return 1 ;
10726 
10727    if( old_dset->warp_parent == new_dset ) return 1 ;
10728 
10729    if( old_dset->warp_parent == new_dset->warp_parent &&
10730        old_dset->warp_parent != NULL                   ) return 1 ;
10731 
10732    if( new_dset->view_type   == VIEW_ORIGINAL_TYPE &&
10733        old_dset->view_type   != VIEW_ORIGINAL_TYPE &&
10734        old_dset->anat_parent != NULL               &&
10735        old_dset->anat_parent->warp_parent != NULL      ) return 1 ;
10736 
10737    if( old_dset->view_type   == VIEW_ORIGINAL_TYPE &&
10738        new_dset->view_type   != VIEW_ORIGINAL_TYPE &&
10739        new_dset->anat_parent != NULL               &&
10740        new_dset->anat_parent->warp_parent != NULL      ) return 1 ;
10741 
10742    return 0 ;
10743 }
10744 
10745 /*-----------------------------------------------------------------------
10746   Eventually, will warp an input Dicom vector from one dataset to another.
10747 -------------------------------------------------------------------------*/
10748 
10749 THD_fvec3 AFNI_transform_vector( THD_3dim_dataset *old_dset ,
10750                                  THD_fvec3 old_fv ,
10751                                  THD_3dim_dataset *new_dset  )
10752 {
10753    if( old_dset==NULL || new_dset==NULL || old_dset==new_dset ) return old_fv ;
10754 
10755    if( old_dset == new_dset->warp_parent ){
10756 
10757       return AFNI_forward_warp_vector( new_dset->warp , old_fv ) ;
10758 
10759    } else if( old_dset->warp_parent == new_dset ){
10760 
10761       return AFNI_backward_warp_vector( old_dset->warp , old_fv ) ;
10762 
10763    } else if( old_dset->warp_parent == new_dset->warp_parent &&
10764               old_dset->warp_parent != NULL ){
10765 
10766       THD_fvec3 par_fv ;
10767       par_fv = AFNI_backward_warp_vector( old_dset->warp , old_fv ) ;
10768       return   AFNI_forward_warp_vector ( new_dset->warp , par_fv ) ;
10769    }
10770 
10771    /*-- 09 Jul 2001:
10772         If old_dset is in +tlrc/+acpc and new_dset is in +orig,
10773         see if can find anat_parent to do the job for us --*/
10774 
10775    if( new_dset->view_type   == VIEW_ORIGINAL_TYPE &&
10776        old_dset->view_type   != VIEW_ORIGINAL_TYPE &&
10777        old_dset->anat_parent != NULL               &&
10778        old_dset->anat_parent->warp_parent != NULL      ){
10779 
10780       return AFNI_backward_warp_vector( old_dset->anat_parent->warp , old_fv ) ;
10781    }
10782 
10783    /*-- If old_dset is +orig and new_dset is +tlrc/+acpc, try anat_parent --*/
10784 
10785    if( old_dset->view_type   == VIEW_ORIGINAL_TYPE &&
10786        new_dset->view_type   != VIEW_ORIGINAL_TYPE &&
10787        new_dset->anat_parent != NULL               &&
10788        new_dset->anat_parent->warp_parent != NULL      ){
10789 
10790       return AFNI_forward_warp_vector( new_dset->anat_parent->warp , old_fv ) ;
10791    }
10792 
10793    /*-- 28 Aug 2002: see if there is a special warp between datasets --*/
10794 
10795    { THD_warp *swarp = AFNI_find_warp(new_dset,old_dset) ;
10796      if( swarp != NULL ) return AFNI_forward_warp_vector( swarp , old_fv ) ;
10797      swarp = AFNI_find_warp(old_dset,new_dset) ;
10798      if( swarp != NULL ) return AFNI_backward_warp_vector( swarp, old_fv ) ;
10799    }
10800 
10801    /*-- default is no change --*/
10802 
10803    return old_fv ;
10804 }
10805 
10806 /*------------------------------------------------------------------------
10807   09 May 2001: fix a Solaris stupidity, where the scale is resized
10808                improperly when the Define Function panel is opened!
10809 --------------------------------------------------------------------------*/
10810 
10811 #ifdef FIX_SCALE_SIZE_LATER
10812 static void fixscale( XtPointer client_data , XtIntervalId *id )
10813 {
10814    Three_D_View *im3d = (Three_D_View *) client_data ;
10815    AFNI_fix_scale_size_direct(im3d) ;  /* 03 Jun 2019 */
10816 #if 0
10817    XtVaSetValues( im3d->vwid->func->thr_scale , XmNscaleWidth,24 , NULL ) ;
10818 #endif
10819 }
10820 #endif
10821 
10822 /*------------------------------------------------------------------------*/
10823 
10824 void AFNI_define_CB( Widget w , XtPointer client_data , XtPointer call_data )
10825 {
10826    Three_D_View *im3d = (Three_D_View *)client_data ;
10827    int vwarp ;
10828 
10829 ENTRY("AFNI_define_CB") ;
10830 
10831    if( ! IM3D_OPEN(im3d) ) EXRETURN ;
10832 
10833    /*-----  define marks panel -----*/
10834 
10835    if( w == im3d->vwid->view->define_marks_pb ){
10836 
10837       AFNI_viewing_widgets  *view  = im3d->vwid->view  ;
10838       AFNI_marks_widgets    *marks = im3d->vwid->marks ;
10839 
10840       if( XtIsManaged(marks->frame) == True ){  /* close it down */
10841 
10842 STATUS("closing marks") ;
10843 
10844          AFNI_marks_action_CB( NULL , (XtPointer) im3d , NULL ) ;
10845 
10846       } else {                                  /* open it up */
10847 
10848         static int first=1 ;  /* 21 Sep 2007 */
10849 
10850 STATUS("opening marks") ;
10851 
10852          marks->old_visible = marks->ov_visible ;
10853          marks->ov_visible  = True ;
10854          marks->changed     = False ;  /* not changed yet! */
10855 
10856          MCW_set_bbox( marks->edits_bbox , 0 ) ;
10857          AFNI_marks_edits_CB( NULL , (XtPointer) im3d , NULL ) ;
10858 
10859          MCW_set_bbox( view->see_marks_bbox , 1 ) ;
10860          if( marks->old_visible != marks->ov_visible )
10861             AFNI_see_marks_CB( NULL , (XtPointer) im3d , NULL ) ;
10862 
10863          /* Oct 1998: turn off some controls if no markers present */
10864 
10865          if( im3d->anat_now->markers == NULL ){
10866             SENSITIZE( marks->edits_bbox->wrowcol , False ) ;
10867             SENSITIZE( marks->tlrc_big_bbox->wrowcol , False ) ;
10868             AV_SENSITIZE( marks->disp_scolor_av , False ) ;
10869             AV_SENSITIZE( marks->disp_size_av   , False ) ;
10870             AV_SENSITIZE( marks->disp_gap_av    , False ) ;
10871             SENSITIZE( marks->action_rowcol , False ) ;
10872             SENSITIZE( marks->transform_pb , False ) ;
10873          } else {
10874             vwarp = WARPED_VIEW(im3d->vinfo->view_type) ;
10875             SENSITIZE( marks->edits_bbox->wrowcol ,
10876                             (RwcBoolean) ISVALID_VIEW(vwarp) ) ;
10877             SENSITIZE( marks->tlrc_big_bbox->wrowcol ,
10878                        (RwcBoolean) (vwarp==VIEW_TALAIRACH_TYPE) ) ;
10879             AV_SENSITIZE( marks->disp_scolor_av , True ) ;
10880             AV_SENSITIZE( marks->disp_size_av   , True ) ;
10881             AV_SENSITIZE( marks->disp_gap_av    , True ) ;
10882             SENSITIZE( marks->action_rowcol , True ) ;
10883          }
10884 
10885    /*** I don't know why this is needed, but it prevents the
10886         marks panels geometry from getting screwed up, so it's here ***/
10887 
10888 #ifndef USING_LESSTIF
10889 #define REMANAGE_MARKS 1
10890 #else
10891 #define REMANAGE_MARKS 0
10892 #endif
10893 
10894 #if 1
10895        { static int first=1 ;
10896          if( REMANAGE_MARKS || first ){               /* CYGWIN: must do 1st time in */
10897            XtUnmanageChild( marks->rowcol ) ;         /* but not on later times --   */
10898            XtUnmanageChild( marks->tog_rowcol ) ;     /* probably a LessTif bug      */
10899            XtUnmanageChild( marks->control_rowcol ) ;
10900            XtUnmanageChild( marks->control_frame ) ;
10901            XtUnmanageChild( marks->tog_frame ) ;
10902            first = 0 ;
10903          }
10904        }
10905 #endif
10906 
10907          OPEN_PANEL(im3d,marks) ;
10908 
10909 #if 1
10910 #if 0
10911          XFlush( XtDisplay(marks->rowcol) ) ; XSync( XtDisplay(marks->rowcol),False ) ;
10912 #endif
10913          if( im3d->anat_now->markers != NULL ){  /* Oct 1998 */
10914             XtManageChild( marks->tog_rowcol ) ;
10915             XtManageChild( marks->tog_frame ) ;
10916          }
10917          XtManageChild( marks->control_rowcol ) ;
10918          XtManageChild( marks->control_frame ) ;
10919          XtManageChild( marks->rowcol ) ;
10920 #endif
10921 
10922       /* redraw markers if not visible already (if there are any to redraw) */
10923 
10924          if( marks->old_visible != True &&
10925              im3d->anat_now->markers != NULL &&
10926              im3d->anat_now->markers->numset > 0 )
10927            AFNI_set_viewpoint( im3d , -1,-1,-1 , REDISPLAY_OVERLAY ) ;
10928 
10929          if( first && im3d->anat_now->markers == NULL ){ /* 21 Sep 2007 */
10930            first = 0 ;
10931            (void)MCW_popup_message(
10932                   im3d->vwid->view->define_marks_pb ,
10933                     " \n"
10934                     " No Talairach markers defined for Underlay. \n"
10935                     " You can add markers to a dataset via\n"
10936                     "   3drefit -markers datasetname\n"
10937                     " and then re-starting this AFNI program.\n" ,
10938                   MCW_USER_KILL | MCW_TIMER_KILL ) ;
10939          }
10940       }
10941 
10942       EXRETURN ;
10943    }
10944 
10945    /*----- define function panel -----*/
10946 
10947    if( w == im3d->vwid->view->define_func_pb ){
10948       AFNI_viewing_widgets  *view  = im3d->vwid->view  ;
10949       AFNI_function_widgets *func  = im3d->vwid->func ;
10950 
10951       if( XtIsManaged(func->frame) ){
10952 
10953 STATUS("closing function") ;
10954 
10955          CLOSE_PANEL(im3d,func) ;
10956       } else {
10957 
10958 STATUS("opening function" ) ;
10959 
10960 #ifndef USING_LESSTIF
10961 #define REMANAGE_FUNC
10962 #endif
10963 
10964 #ifdef REMANAGE_FUNC
10965 STATUS("unmanaging children") ;
10966          XtUnmanageChild( im3d->vwid->func->rowcol ) ;
10967          XtUnmanageChild( im3d->vwid->func->thr_rowcol ) ;
10968          XtUnmanageChild( im3d->vwid->func->inten_rowcol ) ;
10969          XtUnmanageChild( im3d->vwid->func->options_rowcol ) ;
10970 #endif
10971 
10972 STATUS("opening panel") ;
10973          OPEN_PANEL(im3d,func) ;
10974 
10975 #ifdef REMANAGE_FUNC
10976 STATUS("remanaging children") ;
10977          XtManageChild( im3d->vwid->func->thr_rowcol ) ;
10978          XtManageChild( im3d->vwid->func->inten_rowcol ) ;
10979          XtManageChild( im3d->vwid->func->options_rowcol ) ;
10980          XtManageChild( im3d->vwid->func->rowcol ) ;
10981 #endif
10982          HIDE_SCALE(im3d) ;
10983          im3d->vwid->func->inten_pbar->update_me = 2 ;
10984          update_MCW_pbar( im3d->vwid->func->inten_pbar ) ;
10985          FIX_SCALE_SIZE(im3d) ; FIX_SCALE_VALUE(im3d) ;
10986 
10987         /* first time open? do some setup finalization [24 May 2019] */
10988         if( im3d->vwid->func->do_setup ){
10989           int ii = (int)AFNI_numenv("AFNI_THRESH_INIT_EXPON") ;
10990           if( ii > 0 && ii < THR_top_expon ) AFNI_set_thresh_itop(im3d,ii) ;
10991           im3d->vwid->func->do_setup = 0 ;
10992         }
10993 
10994 #ifdef FIX_SCALE_SIZE_LATER
10995         (void) XtAppAddTimeOut( MAIN_app,50,fixscale,im3d ) ; /* 09 May 2001 */
10996 #else
10997          AFNI_fix_scale_size_direct(im3d) ;  /* 03 Jun 2019 */
10998 #endif
10999 
11000 /***     XtManageChild( im3d->vwid->func->inten_bbox->wrowcol ) ; ***/
11001       }
11002 
11003       EXRETURN ;
11004    }
11005 
11006    /*-- define datamode panel --*/
11007 
11008    if( w == im3d->vwid->view->define_dmode_pb ){
11009       AFNI_viewing_widgets  *view  = im3d->vwid->view  ;
11010       AFNI_datamode_widgets *dmode = im3d->vwid->dmode ;
11011 
11012       if( XtIsManaged(dmode->frame) ){
11013 
11014 STATUS("closing dmode") ;
11015 
11016          CLOSE_PANEL(im3d,dmode) ;
11017       } else {
11018 
11019 STATUS("opening dmode" ) ;
11020 
11021          OPEN_PANEL(im3d,dmode) ;
11022       }
11023 
11024       EXRETURN ;
11025    }
11026 
11027    RESET_AFNI_QUIT(im3d) ;
11028    EXRETURN ;
11029 }
11030 
11031 /*--------------------------------------------------------------------*/
11032 
11033 void AFNI_marks_edits_CB( Widget w ,
11034                           XtPointer client_data , XtPointer call_data )
11035 {
11036    Three_D_View *im3d = (Three_D_View *) client_data ;
11037    AFNI_marks_widgets *marks ;
11038    int bval , vwarp ;
11039    RwcBoolean transformable ;
11040 
11041 ENTRY("AFNI_marks_edits_CB") ;
11042 
11043    if( ! IM3D_OPEN(im3d) ) EXRETURN ;
11044 
11045    marks = im3d->vwid->marks ;
11046    bval  = MCW_val_bbox( marks->edits_bbox ) ;
11047 
11048    marks->editable = (bval == 0) ? (False) : (True) ;
11049 
11050    if( im3d->anat_now->markers == NULL ) EXRETURN ;
11051 
11052    /*----- allow transformation if
11053              edits are allowed, AND
11054              the markers are flagged for it, AND
11055              all the markers are defined  ----------*/
11056 
11057    vwarp = WARPED_VIEW(im3d->vinfo->view_type) ;
11058 
11059    transformable =
11060       marks->editable                                         &&
11061       (im3d->anat_now->markers->aflags[1] != MARKACTION_NONE) &&
11062       (im3d->anat_now->markers->numdef == im3d->anat_now->markers->numset) &&
11063       ISVALID_VIEW(vwarp) ;
11064 
11065    /* turn some buttons on or off, depending on editability */
11066 
11067    SENSITIZE( marks->tog_frame         , True ) ;
11068    SENSITIZE( marks->action_set_pb     , marks->editable ) ;
11069    SENSITIZE( marks->action_clear_pb   , marks->editable ) ;
11070 #ifdef POPTOG
11071    SENSITIZE( marks->pop_set_pb        , marks->editable ) ;
11072    SENSITIZE( marks->pop_clear_pb      , marks->editable ) ;
11073 #endif
11074    SENSITIZE( marks->action_quality_pb , transformable ) ;
11075    SENSITIZE( marks->transform_pb      , False ) ;  /* require QC first */
11076 
11077    if( ! marks->editable ){
11078       AFNI_set_tog( -1 , MARKS_MAXNUM , marks->tog ) ;    /* none will */
11079 #ifdef POPTOG
11080       AFNI_set_tog( -1 , MARKS_MAXNUM , marks->poptog ) ; /* be "on" */
11081 #endif
11082    }
11083 
11084    RESET_AFNI_QUIT(im3d) ;
11085    EXRETURN ;
11086 }
11087 
11088 /*-----------------------------------------------------------------*/
11089 
11090 void AFNI_see_marks_CB( Widget w ,
11091                         XtPointer client_data , XtPointer call_data )
11092 {
11093    Three_D_View *im3d = (Three_D_View *) client_data ;
11094    AFNI_marks_widgets *marks ;
11095    AFNI_viewing_widgets *view ;
11096    int bval ;
11097 
11098 ENTRY("AFNI_see_marks_CB") ;
11099 
11100    if( ! IM3D_OPEN(im3d) ) EXRETURN ;
11101 
11102    view  = im3d->vwid->view ;
11103    marks = im3d->vwid->marks ;
11104    bval  = MCW_val_bbox( view->see_marks_bbox ) ;
11105 
11106    marks->tag_visible = marks->ov_visible = (bval == 0) ? (False) : (True) ;
11107 
11108    if( w != NULL )
11109       AFNI_set_viewpoint( im3d , -1,-1,-1 , REDISPLAY_OVERLAY ) ;
11110 
11111    RESET_AFNI_QUIT(im3d) ;
11112    EXRETURN ;
11113 }
11114 
11115 /*------------------------------------------------------------------------
11116   Event handler to find #3 button press for crosshair label [12 Mar 2004]
11117 --------------------------------------------------------------------------*/
11118 
11119 void AFNI_crosshair_EV( Widget w , XtPointer cd ,
11120                         XEvent *ev , RwcBoolean *continue_to_dispatch )
11121 {
11122    Three_D_View *im3d = (Three_D_View *)cd ;
11123 
11124 ENTRY("AFNI_crosshair_EV") ;
11125 
11126    if( ! IM3D_OPEN(im3d) ) EXRETURN ;
11127 
11128    /*** handle events ***/
11129 
11130    switch( ev->type ){
11131 
11132      /*----- take button press -----*/
11133 
11134      case ButtonPress:{
11135        XButtonEvent *event = (XButtonEvent *)ev ;
11136 
11137        if( event->button == Button3 ||
11138            (event->button == Button1 &&
11139             (event->state & (ShiftMask|ControlMask))) ){
11140 
11141          im3d->vwid->butx = event->x_root ;  /* 17 May 2005 */
11142          im3d->vwid->buty = event->y_root ;
11143          event->button    = Button3 ;                                /* fake  */
11144          XmMenuPosition( im3d->vwid->imag->crosshair_menu , event ); /* where */
11145          XtManageChild ( im3d->vwid->imag->crosshair_menu ) ;        /* popup */
11146        }
11147 
11148        else if( event->button == Button1 ) {
11149          static int nn=0 ;
11150          if( nn < 9 )
11151           (void) MCW_popup_message( im3d->vwid->imag->crosshair_label ,
11152                                    " The road goes ever on and on\n"
11153                                    " Out from the door from where it began.\n"
11154                                    " Now, far ahead the road has gone\n"
11155                                    " And I must follow if I can.\n"
11156                                    " Pursuing it with eager feet\n"
11157                                    " Until it meets some other way\n"
11158                                    " Where many paths and errands meet\n"
11159                                    " And whither then I cannot say." ,
11160                                 MCW_USER_KILL | MCW_TIMER_KILL ) ;
11161          nn++ ;
11162        }
11163      }
11164      break ;
11165 
11166      /*----- take key press -----*/
11167 
11168 #if 0
11169      case KeyPress:{
11170        XKeyEvent *event = (XKeyEvent *) ev ;
11171        char      buf[32] ;
11172        KeySym    ks ;
11173        int       nbuf ;
11174 
11175        buf[0] = '\0' ;
11176        nbuf = XLookupString( event , buf , 32 , &ks , NULL ) ;
11177 
11178        switch( buf[0] ){
11179          default: break ;
11180        }
11181      }
11182      break ;
11183 #endif
11184    }
11185 
11186    EXRETURN ;
11187 }
11188 
11189 /*------------------------------------------------------------------*/
11190 /* Redraw the crosshair label in this controller [12 Mar 2004]
11191 --------------------------------------------------------------------*/
11192 
11193 void AFNI_crosshair_relabel( Three_D_View *im3d )
11194 {
11195    XmString xstr ;
11196    RwcBoolean same ;
11197 
11198 ENTRY("AFNI_crosshair_relabel") ;
11199 
11200    if( !IM3D_OPEN(im3d) ) EXRETURN ;
11201    xstr = AFNI_crosshair_label( im3d ) ; if( xstr == NULL ) EXRETURN ;
11202    if( im3d->vinfo->old_crosshair_label == (XmString)NULL ) /* shouldn't */
11203      same = False ;                                         /* happen   */
11204    else
11205      same = XmStringCompare( xstr , im3d->vinfo->old_crosshair_label ) ;
11206 
11207    if( same == False ){
11208       XtVaSetValues( im3d->vwid->imag->crosshair_label ,       /* redisplay */
11209                         XmNlabelString , xstr ,                /* if changed */
11210                      NULL ) ;
11211       MCW_expose_widget( im3d->vwid->imag->crosshair_label ) ; /* redraw now! */
11212       if( im3d->vinfo->old_crosshair_label != (XmString)NULL )
11213         XmStringFree(im3d->vinfo->old_crosshair_label) ;       /* toss old */
11214       im3d->vinfo->old_crosshair_label = xstr ;                /* new old */
11215    } else {
11216       XmStringFree( xstr ) ;  /* was same --> don't need this copy */
11217    }
11218 
11219    EXRETURN ;
11220 }
11221 
11222 /*------------------------------------------------------------------
11223   callback for crosshair label popup menu [12 Mar 2004]
11224 --------------------------------------------------------------------*/
11225 
11226 static char *last_jumpto_xyz_string = NULL ;  /* 23 Sep 2008 */
11227 static char *last_jumpto_ijk_string = NULL ;
11228 static char *last_mnito_string      = NULL ;
11229 static char *last_sumato_string     = NULL ;
11230 static char jumpstring[128];                  /* 13 Jun 2014 */
11231 
11232 static char *last_jumpto_ijk_olay_string = NULL ;  /* 20 Apr 2016 */
11233 
11234 void AFNI_crosshair_pop_CB( Widget w ,
11235                             XtPointer client_data , XtPointer call_data )
11236 {
11237    Three_D_View *im3d = (Three_D_View *)client_data ;
11238    static char *cord_dicom="RAI" , *cord_spm="LPI" ;
11239    char *val=NULL ;
11240    int ii ;
11241 
11242 ENTRY("AFNI_crosshair_pop_CB") ;
11243 
11244    if( !IM3D_OPEN(im3d) ) EXRETURN ;
11245 
11246    /*-- jumpto stuff added 01 Aug 2011 --*/
11247 
11248    if( w == im3d->vwid->imag->crosshair_jtxyz_pb ){
11249      char tbuf[128] ;
11250      sprintf(tbuf , "Enter new x y z (%s mm):" , GLOBAL_library.cord.orcode ) ;
11251      MCW_choose_string( im3d->vwid->imag->crosshair_label , tbuf ,
11252                         last_jumpto_xyz_string,
11253                         AFNI_jumpto_CB, (XtPointer) im3d ) ;
11254      EXRETURN ;
11255    } else if ( w == im3d->vwid->imag->crosshair_jtijk_pb ){
11256      MCW_choose_string( im3d->vwid->imag->crosshair_label , "Enter new i j k (UnderLay):" ,
11257                         last_jumpto_ijk_string ,
11258                         AFNI_jumpto_ijk_CB , (XtPointer) im3d ) ;
11259      EXRETURN ;
11260    } else if ( w == im3d->vwid->imag->crosshair_jtijk_olay_pb ){  /* 20 Apr 2016 */
11261      MCW_choose_string( im3d->vwid->imag->crosshair_label , "Enter new i j k (OverLay):" ,
11262                         last_jumpto_ijk_olay_string ,
11263                         AFNI_jumpto_ijk_olay_CB , (XtPointer) im3d ) ;
11264      EXRETURN ;
11265    }
11266 
11267    /*-- the other options --*/
11268 
11269         if( w == im3d->vwid->imag->crosshair_dicom_pb ) val = cord_dicom ;
11270    else if( w == im3d->vwid->imag->crosshair_spm_pb   ) val = cord_spm   ;
11271    else if( w == im3d->vwid->imag->crosshair_ijk_pb   ){  /* 04 Oct 2010 */
11272      im3d->vinfo->show_voxind = 1 ;
11273      POPDOWN_string_chooser ;
11274      AFNI_crosshair_relabel(im3d) ;
11275      MCW_set_bbox(im3d->vwid->dmode->misc_voxind_bbox,1) ;
11276    }
11277 
11278    if( val != NULL ){
11279      POPDOWN_string_chooser ;
11280      MCW_strncpy(GLOBAL_argopt.orient_code,val,4) ;
11281      THD_coorder_fill( GLOBAL_argopt.orient_code , &GLOBAL_library.cord ) ;
11282      im3d->vinfo->show_voxind = 0 ;
11283      MCW_set_bbox(im3d->vwid->dmode->misc_voxind_bbox,0) ;
11284      for( ii=0 ; ii < MAX_CONTROLLERS ; ii++ ){
11285        AFNI_crosshair_relabel  ( GLOBAL_library.controllers[ii] );
11286        AFNI_clus_update_widgets( GLOBAL_library.controllers[ii] ); /* 21 Dec 2007 */
11287      }
11288    }
11289 
11290    EXRETURN ;
11291 }
11292 
11293 /*------------------------------------------------------------------
11294   callback for non-marker buttons on the popup
11295 --------------------------------------------------------------------*/
11296 
11297 void AFNI_imag_pop_CB( Widget w ,
11298                        XtPointer client_data , XtPointer call_data )
11299 {
11300    Three_D_View *im3d = (Three_D_View *)client_data ;
11301    MCW_imseq *seq=NULL ;
11302 
11303 ENTRY("AFNI_imag_pop_CB") ;
11304 
11305    if( ! IM3D_OPEN(im3d) ) EXRETURN ;
11306 
11307    XtVaGetValues( im3d->vwid->imag->popmenu, XmNuserData, &seq, NULL ) ;
11308    AFNI_view_setter(im3d,seq) ;
11309 
11310    /*-- jump back to old location --*/
11311 
11312    if( w == im3d->vwid->imag->pop_jumpback_pb ){
11313      int ii,jj,kk ;
11314 
11315      ii = im3d->vinfo->i1_old ;  /* extract old place */
11316      jj = im3d->vinfo->j2_old ;
11317      kk = im3d->vinfo->k3_old ;
11318 
11319      SAVE_VPT(im3d) ;  /* save current place as old one */
11320      AFNI_set_viewpoint( im3d , ii,jj,kk , REDISPLAY_OVERLAY ) ; /* jump */
11321    }
11322 
11323    /*-- switch window display mode --*/
11324 
11325    else if( w == im3d->vwid->imag->pop_imageonly_pb ){
11326       if( ISQ_REALZ(seq) )
11327          drive_MCW_imseq( seq , isqDR_onoffwid , (XtPointer) isqDR_togwid ) ;
11328    }
11329 
11330    /*-- jump to a point --*/
11331 
11332    else if( w == im3d->vwid->imag->pop_jumpto_pb &&
11333             im3d->type == AFNI_3DDATA_VIEW         ){
11334 
11335       char tbuf[128] ;
11336 
11337       if( ISQ_REALZ(seq) ){
11338         sprintf(tbuf , "Enter new x y z (%s mm):" , GLOBAL_library.cord.orcode ) ;
11339         MCW_choose_string( seq->wbar , tbuf , last_jumpto_xyz_string ,
11340                            AFNI_jumpto_CB , (XtPointer) im3d ) ;
11341       }
11342    }
11343 
11344    else if( w == im3d->vwid->imag->pop_jumpto_ijk_pb &&
11345             im3d->type == AFNI_3DDATA_VIEW             ){
11346 
11347       if( ISQ_REALZ(seq) ){
11348          MCW_choose_string( seq->wbar , "Enter new i j k (UnderLay):" , last_jumpto_ijk_string ,
11349                             AFNI_jumpto_ijk_CB , (XtPointer) im3d ) ;
11350       }
11351    }
11352 
11353    else if( w == im3d->vwid->imag->pop_jumpto_ijk_olay_pb &&
11354             im3d->type == AFNI_3DDATA_VIEW                  ){  /* 20 Apr 2016 */
11355 
11356       if( ISQ_REALZ(seq) ){
11357          MCW_choose_string( seq->wbar , "Enter new i j k (OverLay):" , last_jumpto_ijk_olay_string ,
11358                             AFNI_jumpto_ijk_olay_CB , (XtPointer) im3d ) ;
11359       }
11360    }
11361 
11362    /*-- 01 May 2002: jump to MNI coordinates --*/
11363 
11364    else if( w == im3d->vwid->imag->pop_mnito_pb &&
11365             im3d->type == AFNI_3DDATA_VIEW        ){
11366       /* configure menu to show what space coordinates might be in */
11367       if( ISQ_REALZ(seq) && CAN_TALTO(im3d) ){
11368          sprintf(jumpstring,"Enter %s x,y,z (LPI mm):", get_jump_space());
11369          MCW_choose_string( seq->wbar , jumpstring ,
11370                             last_mnito_string ,
11371                             AFNI_mnito_CB , (XtPointer) im3d ) ;
11372       } else {
11373          BEEPIT ; /* should never happen */
11374       }
11375    }
11376 
11377    /*-- 19 Oct 2012: jump to cluster peak --*/
11378 
11379    else if( w == im3d->vwid->imag->pop_jumpto_clus_pb &&
11380             im3d->type == AFNI_3DDATA_VIEW            ){
11381      AFNI_jumpto_clus(im3d) ;
11382    }
11383 
11384    /*-- 06 Mar 2002: jump to a node in a surface --*/
11385 
11386    else if( w == im3d->vwid->imag->pop_sumato_pb &&
11387             SESSION_HAS_SUMA(im3d->ss_now)       &&
11388             im3d->type == AFNI_3DDATA_VIEW         ){
11389 
11390       if( ISQ_REALZ(seq) ){
11391          MCW_choose_string( seq->wbar , "Enter SUMA node ID:" , last_sumato_string ,
11392                             AFNI_sumato_CB , (XtPointer) im3d ) ;
11393       }
11394    }
11395 
11396    /*-- jump to a predetermined atlas-based anatomical reference point --*/
11397 
11398    else if( w == im3d->vwid->imag->pop_talto_pb &&
11399             im3d->type == AFNI_3DDATA_VIEW      &&
11400             CAN_TALTO(im3d)                       ){
11401 
11402       {  /* initialize labels */
11403          char **at_labels=NULL ;
11404          int iii , flipxy=(GLOBAL_library.cord.xxsign < 0 && GLOBAL_library.cord.yysign < 0);
11405          char title_str[256];
11406 
11407          at_labels = atlas_chooser_formatted_labels( Current_Atlas_Default_Name() , flipxy ) ;
11408          if( ISQ_REALZ(seq) && at_labels ){
11409            if( AFNI_yesenv("AFNI_DATASET_BROWSE") ) MCW_set_browse_select(1) ;
11410 
11411            sprintf(title_str, "Brain Structure (%s) [%s]",
11412                         Current_Atlas_Default_Name() ,
11413                         (flipxy) ? "SPM order" : "DICOM order"
11414                    ) ;
11415            MCW_choose_strlist( seq->wbar ,
11416                        title_str ,
11417                        atlas_n_points(Current_Atlas_Default_Name()) ,
11418                        atlas_current_structure ,
11419                        at_labels ,
11420                        AFNI_talto_CB , (XtPointer) im3d ) ;
11421             for (iii=0; iii<atlas_n_points(Current_Atlas_Default_Name()); ++iii) {
11422                if (at_labels[iii]) free(at_labels[iii]);
11423             }
11424             free(at_labels); at_labels=NULL;
11425          }
11426       }
11427    }
11428 
11429    /*---- 10 Jul 2001: Talairach "Where Am I?" ----*/
11430 
11431    else if( w == im3d->vwid->imag->pop_whereami_pb &&
11432             w != NULL                              &&
11433             im3d->type == AFNI_3DDATA_VIEW         &&
11434             CAN_TALTO(im3d)                          ){
11435 
11436       char *tlab ;
11437       tlab = AFNI_ttatlas_query( im3d ) ;
11438       if (AFNI_wami_output_mode() == 0) { /* old spice */
11439 
11440       /*- if one is already open, kill it -*/
11441 
11442       if( im3d->vwid->imag->pop_whereami_twin != NULL ){
11443          MCW_textwinkill_CB(NULL,
11444                             (XtPointer)im3d->vwid->imag->pop_whereami_twin,NULL);
11445          im3d->vwid->imag->pop_whereami_twin = NULL ;
11446       }
11447 
11448       /*- get TT atlas location, if any -*/
11449 
11450       /*- open a window to show it -*/
11451 
11452       if( tlab != NULL ){
11453          char *eee = getenv("AFNI_TTATLAS_FONTSIZE") ;
11454 
11455          if( eee != NULL ){
11456                 if( *eee == 'B' || *eee == 'b' || isdigit(*eee) ) MCW_textwin_setbig( 1);
11457            else if( *eee == 'S' || *eee == 's' || *eee == '-'   ) MCW_textwin_setbig(-1);
11458          }
11459 
11460          im3d->vwid->imag->pop_whereami_twin =
11461            new_MCW_textwin_2001( im3d->vwid->imag->crosshair_label , tlab ,
11462                                  TEXT_READONLY , AFNI_pop_whereami_kill , im3d ) ;
11463 
11464 #if 0
11465          /* 31 Jul 2001: NULL out the pointer when the window is destroyed */
11466 
11467          NULLIFY_ON_DESTROY( im3d->vwid->imag->pop_whereami_twin ,
11468                              im3d->vwid->imag->pop_whereami_twin->wshell ) ;
11469 #endif
11470 
11471          XtVaSetValues( im3d->vwid->imag->pop_whereami_twin->wtext ,
11472                           XmNresizeHeight , True ,
11473                           XmNresizeWidth  , True ,
11474                         NULL ) ;
11475 
11476          MCW_register_hint( im3d->vwid->imag->pop_whereami_twin->wtext ,
11477                             "Use BHelp for documentation" ) ;
11478 
11479          MCW_register_help( im3d->vwid->imag->pop_whereami_twin->wtext ,
11480           "Lists the brain structures near the crosshair focus point\n"
11481           "according to a set of atlases defined in AFNI_atlas_spaces.niml\n"
11482           "and limited by the environment variable,AFNI_ATLAS_LIST.\n"
11483           "The default list includes the original Talairach Daemon database\n"
11484           "(kindly provided by Jack Lancaster and Peter Fox of RIC UTHSCSA,\n"
11485           "the cytoarchitectonic and macrolabel atlases provided by Simon\n"
11486           "Eickhoff and Karl Zilles, and the probabilistic atlases provided\n"
11487           "Rutvik Desai.\n"
11488           "\n"
11489           "The search is conducted outwards from the focus point, until\n"
11490           "9 different structures are found, or a 7.5 mm radius is reached,\n"
11491           "whichever occurs first. (Distances are rounded to nearest 1 mm,\n"
11492           "by default.) The defaults can be adjusted with AFNI environment\n"
11493           "Please see whereami help, README.environment for more details.\n"
11494           "\n"
11495           "In the database, voxels may have multiple labels for a particular\n"
11496           "atlas. For example, the voxels may a larger scale 'gyral' name\n"
11497           "and a finer scale 'area' name.  Locations that are doubly labeled\n"
11498           "will appear with a listing like\n"
11499           "    Within 2 mm: Right Precuneus -AND- Right Brodmann area 31\n"
11500           "A list of all the labels for the principal default atlas is\n"
11501           "presented by the 'Go to atlas location' control or from the\n"
11502           "command line program, 'whereami -show_atlas_code', for any atlas.\n"
11503           "Note Very Well:\n"
11504           "* The Atlas is only useful as a ROUGH guide to determining where\n"
11505           "    you are in any individual brain.  Do not rely exclusively on\n"
11506           "    the Atlas for brain region identification: you must use your\n"
11507           "    knowledge, skills, and abilities as well.\n"
11508           "* Do NOT use this feature for surgical or therapeutic planning!!!"
11509          ) ;
11510       }
11511       } else { /* web */
11512          AFNI_alter_wami_text(im3d, tlab);
11513       } /* web */
11514       if (tlab) free(tlab) ;
11515    }
11516 
11517    /*---- 12 Jul 2001 ----*/
11518 
11519    else if( w == im3d->vwid->imag->pop_ttren_pb           &&
11520             w != NULL                                     &&
11521             im3d->type == AFNI_3DDATA_VIEW                &&
11522             im3d->vinfo->view_type == VIEW_TALAIRACH_TYPE && /* 01 Aug 2001 */
11523             CAN_TALTO(im3d)                                 ){
11524 
11525       TTRR_popup( im3d ) ;
11526 
11527       if( im3d->vinfo->see_ttatlas == 0 ){  /* 03 Aug 2007: for the Daniel */
11528         MCW_set_bbox( im3d->vwid->func->see_ttatlas_bbox , 1 ) ;
11529         im3d->vinfo->see_ttatlas = 1 ;
11530       }
11531    }
11532 
11533    /*---- 05 Nov 2003: start the Edit Environment pseudo-plugin ----*/
11534 
11535    else if( w == im3d->vwid->imag->pop_environment_pb &&
11536             w != NULL                                   ){
11537 
11538      AFNI_misc_CB( im3d->vwid->dmode->misc_environ_pb ,
11539                    (XtPointer) im3d , (XtPointer) NULL ) ;
11540    }
11541 
11542    /*---- 17 May 2005: open Draw Dataset plugin ----*/
11543 
11544    else if( w == im3d->vwid->imag->pop_drawdataset_pb &&
11545             w != NULL                                   ){
11546 
11547      char cmd[128] , cc='A'+AFNI_controller_index(im3d) ;
11548      int xx,yy ;
11549 
11550 #if 0
11551      MCW_widget_geom(im3d->vwid->top_shell,NULL,NULL,&xx,&yy); xx+=29; yy+=19;
11552 #else
11553      xx = im3d->vwid->butx ; yy = im3d->vwid->buty ;
11554 #endif
11555      sprintf(cmd,"OPEN_WINDOW %c.plugin.Draw_Dataset geom=+%d+%d",cc,xx,yy) ;
11556      (void) AFNI_driver(cmd) ;
11557    }
11558 
11559    /*---- 06 May 2009: set InstaCorr point ----*/
11560 
11561    else if( w == im3d->vwid->imag->pop_instacorr_pb && w != NULL ){
11562      int qq = AFNI_icor_setref(im3d) ;
11563      if( qq > 0 && im3d->giset == NULL ) AFNI_icor_setref_locked(im3d) ; /* 15 May 2009 */
11564    }
11565 
11566    /*---- 08 May 2009: jump to InstaCorr point ----*/
11567 
11568    else if( w == im3d->vwid->imag->pop_icorrjump_pb &&
11569             w != NULL && ISREADY_EITHER_ICOR(im3d) ){
11570      int ii,jj,kk ;
11571 
11572      ii = im3d->vinfo->i1_icor ;  /* extract icor place */
11573      jj = im3d->vinfo->j2_icor ;
11574      kk = im3d->vinfo->k3_icor ;
11575      if( ii >= 0 && jj >= 0 && kk >=0 ){
11576        SAVE_VPT(im3d) ;
11577 #if 0  /* OLD */
11578        AFNI_set_viewpoint( im3d , ii,jj,kk , REDISPLAY_OVERLAY ) ;
11579 #else  /* NEW [27 Sep 2021] */
11580        AFNI_jumpto_dicom( im3d, im3d->vinfo->xi_icor,im3d->vinfo->yj_icor,im3d->vinfo->zk_icor) ;
11581 #endif
11582      }
11583    }
11584 
11585    /*---- Apr 2013: set 3dGroupInCorr Apair point ----*/
11586 
11587    else if( w == im3d->vwid->imag->pop_icorrapair_pb && w != NULL ){
11588      AFNI_gicor_setapair_xyz( im3d , im3d->vinfo->xi ,
11589                                      im3d->vinfo->yj , im3d->vinfo->zk ) ;
11590    }
11591 
11592    else if( w == im3d->vwid->imag->pop_icorramirr_pb && w != NULL ){
11593      if( im3d->giset != NULL && GICOR_apair_allow_bit(im3d->giset) ){
11594        GICOR_flip_apair_mirror_bit(im3d->giset) ;
11595        MCW_set_widget_label( w , GICOR_apair_mirror_bit(im3d->giset)
11596                                  ? "GIC: Apair MirrorON*"
11597                                  : "GIC: Apair MirrorOFF" ) ;
11598        SENSITIZE_INSTACORR_GROUP(im3d,im3d->giset->ready) ;
11599      }
11600    }
11601 
11602    /*--- unmap of the popup itself [elided] ---*/
11603 
11604    /*--- exit ---*/
11605 
11606    RESET_AFNI_QUIT(im3d) ;
11607    EXRETURN ;
11608 }
11609 
11610 /*---------------------------------------------------------------------
11611    called when the talto chooser is set - now "Go to Atlas position"
11612    for generic atlas usage
11613 -----------------------------------------------------------------------*/
11614 
11615 void AFNI_talto_CB( Widget w , XtPointer cd , MCW_choose_cbs *cbs )
11616 {
11617    Three_D_View *im3d = (Three_D_View *) cd ;
11618    THD_dataxes  *daxes ;
11619    float xx,yy,zz ;
11620    int nn , ii,jj,kk ;
11621    ATLAS_POINT *tto_list=NULL;
11622    THD_fvec3 fv,tv ; THD_ivec3 iv ;
11623 
11624 ENTRY("AFNI_talto_CB") ;
11625 
11626    /* check for errors */
11627 
11628    if( ! IM3D_OPEN(im3d) || im3d->type != AFNI_3DDATA_VIEW ) EXRETURN ;
11629 
11630    if( !CAN_TALTO(im3d)             ||
11631        cbs->reason != mcwCR_integer   ){
11632 
11633       POPDOWN_strlist_chooser ;
11634       BEEPIT ; WARNING_message("Can't 'Go to Atlas position'!?") ;
11635       EXRETURN ;
11636    }
11637 
11638    if (!(tto_list = atlas_points(Current_Atlas_Default_Name()))) {
11639       BEEPIT ; WARNING_message("Can't get atlas: %s", Current_Atlas_Default_Name()) ;
11640       EXRETURN ;
11641    }
11642 
11643    nn = cbs->ival ;
11644    if( nn < 0 || nn >= atlas_n_points(Current_Atlas_Default_Name()) ) EXRETURN ;
11645    atlas_current_structure = nn ;  /* index for structure in list for atlas */
11646 
11647    /* transform point from Dicom to local coords and go there */
11648 
11649    xx = tto_list[nn].xx ; yy = tto_list[nn].yy ; zz = tto_list[nn].zz ;
11650 
11651    LOAD_ANAT_VIEW(im3d) ;  /* 02 Nov 1996 */
11652 
11653    LOAD_FVEC3(tv,xx,yy,zz) ; /* Talairach coords */
11654 
11655    /* 09 Jul 2001: if not now viewing in Talairach coordinates,
11656                    then transform vector to current coordinates */
11657 
11658    if( im3d->anat_now->view_type != VIEW_TALAIRACH_TYPE )
11659       tv = AFNI_transform_vector( im3d->anat_dset[VIEW_TALAIRACH_TYPE] ,
11660                                   tv , im3d->anat_now ) ;
11661 
11662    fv = THD_dicomm_to_3dmm( im3d->anat_now , tv ) ;
11663    iv = THD_3dmm_to_3dind ( im3d->anat_now , fv ) ;
11664    ii = iv.ijk[0] ; jj = iv.ijk[1] ; kk = iv.ijk[2] ;
11665 
11666    daxes = CURRENT_DAXES(im3d->anat_now) ;
11667    if( ii >= 0 && ii < daxes->nxx &&
11668        jj >= 0 && jj < daxes->nyy && kk >= 0 && kk < daxes->nzz   ){
11669 
11670       SAVE_VPT(im3d) ;
11671       AFNI_set_viewpoint( im3d , ii,jj,kk , REDISPLAY_ALL ) ; /* jump */
11672    } else {
11673       BEEPIT ; WARNING_message("Bad 'Go atlas position' coordinates!?") ;
11674    }
11675    EXRETURN ;
11676 }
11677 
11678 /*-------------------------------------------------------------------------
11679    10 Jul 2001
11680 ---------------------------------------------------------------------------*/
11681 
11682 void AFNI_pop_whereami_kill( Three_D_View *im3d )
11683 {
11684    if( im3d == NULL ) return ;
11685 
11686    MCW_unregister_hint( im3d->vwid->imag->pop_whereami_twin->wtext ) ;
11687    MCW_unregister_help( im3d->vwid->imag->pop_whereami_twin->wtext ) ;
11688 
11689    im3d->vwid->imag->pop_whereami_twin = NULL ;
11690    return ;
11691 }
11692 
11693 
11694 /*-------------------------------------------------------------------------
11695    A newer output form for whereami
11696 ---------------------------------------------------------------------------*/
11697 static int htmlwami_open        = 0 ;
11698 
11699 void AFNI_htmlwami_killfun( XtPointer pp ){
11700    Three_D_View *im3d = (Three_D_View *)pp;
11701 
11702    if (!im3d) return;
11703 
11704    im3d->vwid->imag->pop_whereami_htmlwin=NULL;
11705    /* not there yet
11706    MCW_unregister_hint( im3d->vwid->imag->pop_whereami_twin->wtext ) ;
11707    MCW_unregister_help( im3d->vwid->imag->pop_whereami_twin->wtext ) ;
11708    */
11709 
11710    htmlwami_open = 0 ; return ;
11711 }
11712 
11713 void AFNI_htmlwami_CB( Widget w , XtPointer cd , XtPointer cbd )
11714 {
11715    Three_D_View *im3d = (Three_D_View *)cd ;
11716    char *uinf=(char *)cbd , *inf=NULL ; int ii ;
11717    MCW_htmlwin *htmlwami_hw = im3d->vwid->imag->pop_whereami_htmlwin;
11718 
11719    ENTRY("AFNI_htmlwami_CB") ;
11720 
11721    if( uinf != NULL && *uinf != '\0' ){
11722       inf = (char *)malloc(sizeof(char)*(strlen(uinf)+16)) ;
11723       strcpy(inf,"wami:") ; strcat(inf,uinf) ;
11724    }
11725 
11726    if( htmlwami_open && htmlwami_hw != NULL ){
11727      XMapRaised( XtDisplay(htmlwami_hw->wshell), XtWindow(htmlwami_hw->wshell)) ;
11728      MCW_htmlwin_alter( htmlwami_hw , inf );
11729      EXRETURN ;
11730    } else {
11731      htmlwami_hw = new_MCW_htmlwin( im3d->vwid->imag->topper, inf,
11732                                AFNI_htmlwami_killfun , im3d  , NULL, 0    ) ;
11733      im3d->vwid->imag->pop_whereami_htmlwin = htmlwami_hw;
11734    }
11735    free(inf) ; inf = NULL ; htmlwami_open = 1 ;
11736 
11737    EXRETURN ;
11738 }
11739 
11740 void AFNI_alter_wami_text(Three_D_View *im3d, char *utlab)
11741 {
11742    char *tlab=NULL;
11743 
11744    ENTRY("AFNI_alter_wami_text");
11745 
11746    if (!im3d || !im3d->vwid || !im3d->vwid->imag) EXRETURN;
11747 
11748    if (!utlab) tlab = "\n** Can not use whereami functionality with this dataset**<br>\n"
11749    "Please set AFNI_ATLAS_LIST and AFNI_TEMPLATE_SPACE_LIST appropriately<br>\n"
11750    "Also set the space of the dataset to a corresponding space<br>\n" ;
11751    else tlab = utlab;
11752 
11753    if (AFNI_wami_output_mode() == 0) {
11754       if (!im3d->vwid->imag->pop_whereami_twin) EXRETURN;
11755       MCW_textwin_alter( im3d->vwid->imag->pop_whereami_twin , tlab ) ;
11756    } else {
11757       AFNI_htmlwami_CB( NULL , (XtPointer)im3d , (XtPointer) tlab );
11758    }
11759    EXRETURN;
11760 }
11761 
11762 
11763 /*-------------------------------------------------------------------------*/
11764 
11765 char * AFNI_ttatlas_query( Three_D_View *im3d )
11766 {
11767    static int have_TT = 1 ;
11768    THD_3dim_dataset *dset;
11769    ATLAS_LIST *atlas_alist;
11770 
11771    if( !IM3D_OPEN(im3d) || !CAN_TALTO(im3d) ) return NULL ;
11772 
11773    set_TT_whereami_version(0,0);
11774    set_wami_web_reqtype(WAMI_WEB_STRUCT); /* set web atlas output to simple structure */
11775 
11776 #if 0
11777    /*-- make sure we have the TT atlas --*/
11778    have_TT = 0;
11779    if( TT_retrieve_atlas_dset("TT_Daemon",0)){
11780       have_TT = 1 ;
11781    }
11782    if( !have_TT ) return NULL ;
11783 #endif
11784 
11785    if( have_TT ){
11786      THD_fvec3 tv ; char *tlab ;
11787 
11788      /*-- current position --*/
11789 
11790      LOAD_FVEC3(tv,im3d->vinfo->xi,im3d->vinfo->yj,im3d->vinfo->zk) ;
11791 
11792      /*-- transform to Talairach, if needed --*/
11793 
11794      if( im3d->anat_now->view_type != VIEW_TALAIRACH_TYPE )
11795         tv = AFNI_transform_vector( im3d->anat_now , tv ,
11796                                     im3d->anat_dset[VIEW_TALAIRACH_TYPE] ) ;
11797 
11798      /*-- get result string --*/
11799      /* use space of "talairach view" dataset */
11800      /* will want to change this for flexibility not to use preset xform */
11801      dset = im3d->anat_dset[VIEW_TALAIRACH_TYPE];
11802 
11803      atlas_alist = get_G_atlas_list(); /* get the whole atlas list */
11804 
11805      tlab = TT_whereami( tv.xyz[0] , tv.xyz[1] , tv.xyz[2],
11806                          THD_get_space(dset)  , env_atlas_list() );
11807 
11808      return tlab ;
11809    }
11810 
11811    return NULL ;
11812 }
11813 
11814 /*-------------------------------------------------------------------------
11815   See the TT atlas in the overlay? -- 25 Jul 2001
11816 ---------------------------------------------------------------------------*/
11817 
11818 void AFNI_see_ttatlas_CB( Widget w, XtPointer cd, XtPointer cb)
11819 {
11820    Three_D_View *im3d = (Three_D_View *) cd ;
11821    int newsee = MCW_val_bbox(im3d->vwid->func->see_ttatlas_bbox) ;
11822 
11823    if( newsee == im3d->vinfo->see_ttatlas ) return ;
11824 
11825    im3d->vinfo->see_ttatlas = newsee ;
11826 
11827    if( im3d->anat_now->view_type == VIEW_TALAIRACH_TYPE )
11828       AFNI_set_viewpoint( im3d , -1,-1,-1 , REDISPLAY_OVERLAY ) ;  /* redraw */
11829 
11830    return ;
11831 }
11832 
11833 /*---------------------------------------------------------------------
11834    called when the mnito chooser is set - 01 May 2002
11835 -----------------------------------------------------------------------*/
11836 
11837 void AFNI_mnito_CB( Widget w , XtPointer cd , MCW_choose_cbs *cbs )
11838 {
11839    Three_D_View *im3d = (Three_D_View *) cd ;
11840    float xx,yy,zz, xout, yout, zout;
11841    char dum1[32],dum2[32];
11842    int nn ;
11843    THD_fvec3 tv ;
11844 
11845 ENTRY("AFNI_mnito_CB") ;
11846 
11847    if( ! IM3D_OPEN(im3d) || im3d->type != AFNI_3DDATA_VIEW ) EXRETURN ;
11848 
11849    if( !CAN_TALTO(im3d) || cbs->reason != mcwCR_string  ){   /* error */
11850       POPDOWN_string_chooser ;
11851       BEEPIT ; WARNING_message("Can't 'MNI To'!?") ;
11852       EXRETURN ;
11853    }
11854 
11855    if( last_mnito_string != NULL ) free(last_mnito_string) ;
11856    last_mnito_string = strdup(cbs->cval) ;
11857 
11858    nn = sscanf( cbs->cval , "%f%[ ,]%f%[ ,]%f" , &xx,dum1,&yy,dum2,&zz ) ;
11859    if( nn != 5 ){ BEEPIT ; WARNING_message("bad 'MNI To' entries!?") ; EXRETURN ; }
11860 
11861    xx = -xx, yy = -yy;  /* LPI to RAI coordinates */
11862    LOAD_ANAT_VIEW(im3d) ;
11863 /*  tv = THD_mni_to_tta( tv ) ; */ /* Talairach coords */
11864    /* transform the MNI coordinates to whatever space the +tlrc view is in */
11865    if(wami_xform_xyz(xx, yy, zz, &xout, &yout, &zout, get_jump_space(),
11866       THD_get_space(im3d->anat_dset[VIEW_TALAIRACH_TYPE]))!=0) {
11867          BEEPIT ; WARNING_message("'MNI To' failed!?") ;
11868    }
11869    LOAD_FVEC3(tv,xout,yout,zout) ;    /* load vector with new coordinates
11870                                          in dset's std space of tlrc view */
11871 
11872    /* transform from +tlrc view space to current view (maybe orig) if needed */
11873    if( im3d->anat_now->view_type != VIEW_TALAIRACH_TYPE )
11874       tv = AFNI_transform_vector( im3d->anat_dset[VIEW_TALAIRACH_TYPE] ,
11875                                   tv , im3d->anat_now ) ;
11876 
11877    nn = AFNI_jumpto_dicom( im3d , tv.xyz[0], tv.xyz[1], tv.xyz[2] ) ;
11878    if( nn < 0 ){ BEEPIT ; WARNING_message("'MNI To' failed!?") ; }
11879 
11880    RESET_AFNI_QUIT(im3d) ;
11881    EXRETURN ;
11882 }
11883 
11884 /*---------------------------------------------------------------------
11885    called when the jumpto chooser is set
11886 -----------------------------------------------------------------------*/
11887 
11888 void AFNI_jumpto_CB( Widget w , XtPointer cd , MCW_choose_cbs *cbs )
11889 {
11890    Three_D_View *im3d = (Three_D_View *) cd ;
11891    float xx,yy,zz ;
11892    char dum1[32],dum2[32];
11893    int nn ;
11894 
11895 ENTRY("AFNI_jumpto_CB") ;
11896 
11897    if( ! IM3D_OPEN(im3d) || im3d->type != AFNI_3DDATA_VIEW ) EXRETURN ;
11898    if( cbs->reason != mcwCR_string ) EXRETURN ;  /* error */
11899 
11900    if( last_jumpto_xyz_string != NULL ) free(last_jumpto_xyz_string) ;
11901    last_jumpto_xyz_string = strdup(cbs->cval) ;
11902 
11903    nn = sscanf( cbs->cval , "%f%[ ,]%f%[ ,]%f" , &xx,dum1,&yy,dum2,&zz ) ;
11904    if( nn != 5 ){ BEEPIT ; WARNING_message("bad Jumpto entries!?") ; EXRETURN ; }
11905 
11906    THD_coorder_to_dicom( &GLOBAL_library.cord , &xx,&yy,&zz ) ;
11907 
11908    SAVE_VPT(im3d) ;  /* save current place as old one */
11909    nn = AFNI_jumpto_dicom( im3d , xx,yy,zz ) ;
11910    if( nn < 0 ){ BEEPIT ; WARNING_message("Jumpto failed!") ; }
11911 
11912    RESET_AFNI_QUIT(im3d) ;
11913    EXRETURN ;
11914 }
11915 
11916 /*---------------------------------------------------------------------*/
11917 
11918 int AFNI_jumpto_dicom_OLD( Three_D_View *im3d , float xx, float yy, float zz )
11919 {
11920    THD_dataxes  *daxes ;
11921    THD_fvec3 fv ; THD_ivec3 iv ;
11922    int ii,jj,kk ;
11923 
11924 ENTRY("AFNI_jumpto_dicom_OLD") ;
11925 
11926    LOAD_ANAT_VIEW(im3d) ;  /* 02 Nov 1996 */
11927 
11928    fv = THD_dicomm_to_3dmm( im3d->anat_now , TEMP_FVEC3(xx,yy,zz) ) ;
11929    iv = THD_3dmm_to_3dind ( im3d->anat_now , fv ) ;
11930    ii = iv.ijk[0] ; jj = iv.ijk[1] ; kk = iv.ijk[2] ;
11931 
11932    daxes = CURRENT_DAXES(im3d->anat_now) ;
11933    if( ii >= 0 && ii < daxes->nxx &&
11934        jj >= 0 && jj < daxes->nyy && kk >= 0 && kk < daxes->nzz ){
11935 
11936       AFNI_set_viewpoint( im3d , ii,jj,kk , REDISPLAY_ALL ) ; /* jump */
11937       RETURN(1) ;
11938    } else {
11939       BEEPIT ; WARNING_message("Jumpto DICOM failed -- bad coordinates?!") ;
11940       RETURN(-1) ;
11941    }
11942 }
11943 
11944 /*---------------------------------------------------------------------*/
11945 
11946 int AFNI_jump_and_seed( Three_D_View *im3d , float xx, float yy, float zz )
11947 {
11948    THD_dataxes  *daxes ;
11949    THD_fvec3 fv ; THD_ivec3 iv ;
11950    int ii,jj,kk,qq ;
11951    static int iil = -1, jjl = -1, kkl = -1;
11952 
11953 ENTRY("AFNI_jump_and_seed") ;
11954 
11955    LOAD_ANAT_VIEW(im3d) ;  /* 02 Nov 1996 */
11956 
11957    fv = THD_dicomm_to_3dmm( im3d->anat_now , TEMP_FVEC3(xx,yy,zz) ) ;
11958    iv = THD_3dmm_to_3dind ( im3d->anat_now , fv ) ;
11959    ii = iv.ijk[0] ; jj = iv.ijk[1] ; kk = iv.ijk[2] ;
11960 
11961    daxes = CURRENT_DAXES(im3d->anat_now) ;
11962    if( ii >= 0 && ii < daxes->nxx &&
11963        jj >= 0 && jj < daxes->nyy && kk >= 0 && kk < daxes->nzz ){
11964 
11965       /* Note that the locations of the last click should be set
11966          per im3d, perhaps within function AFNI_icor_setref_anatijk().
11967          This current static storage might fail whith multiple
11968          controllers.                                               */
11969       if (ii != iil || jj != jjl || kk != kkl) {
11970          DONT_TELL_SUMA;
11971          AFNI_set_viewpoint( im3d , ii,jj,kk , REDISPLAY_OPTIONAL ) ;
11972          TELL_SUMA;
11973          qq = AFNI_icor_setref_anatijk(im3d,ii,jj,kk) ;
11974          if( qq > 0 && im3d->giset == NULL ) AFNI_icor_setref_locked(im3d) ;
11975          iil = ii; jjl = jj; kkl = kk;
11976       }
11977       RETURN(1) ;
11978    } else {
11979       BEEPIT ;
11980       WARNING_message("AFNI_icor_seed_SUMA failed -- bad coordinates?!") ;
11981       RETURN(-1) ;
11982    }
11983 }
11984 
11985 /*---------------------------------------------------------------------*/
11986 
11987 int AFNI_creepto_dicom( Three_D_View *im3d , float xx, float yy, float zz )
11988 {
11989    float xc,yc,zc , dxx,dyy,dzz ; int ndd,qq,ii=0 ;
11990 
11991 ENTRY("AFNI_creepto_dicom") ;
11992 
11993    xc = im3d->vinfo->xi ; yc = im3d->vinfo->yj ; zc = im3d->vinfo->zk ;
11994 
11995    dxx = fabsf( (xx-xc) / DSET_DX(im3d->anat_now) ) ;
11996    dyy = fabsf( (yy-yc) / DSET_DY(im3d->anat_now) ) ;
11997    dzz = fabsf( (zz-zc) / DSET_DZ(im3d->anat_now) ) ;
11998    ndd = (int)sqrtf(dxx*dxx+dyy*dzz+dzz*dzz) ; ndd = MIN(ndd,32) ;
11999 
12000    SAVE_VPT(im3d) ;
12001    if( ndd < 2 ){ ii = AFNI_jumpto_dicom_OLD(im3d,xx,yy,zz) ; RETURN(ii) ; }
12002 
12003    dxx = (xx-xc) / ndd ; dyy = (yy-yc) / ndd ; dzz = (zz-zc) / ndd ;
12004 
12005    for( qq=ndd-1 ; qq >= 0  ; qq-- )
12006      ii = AFNI_jumpto_dicom_OLD( im3d , xx-dxx*qq , yy-dyy*qq , zz-dzz*qq ) ;
12007 
12008    RETURN(ii) ;
12009 }
12010 
12011 /*---------------------------------------------------------------------*/
12012 
12013 int AFNI_jumpto_dicom( Three_D_View *im3d , float xx, float yy, float zz )
12014 {
12015    int ii ;
12016    SAVE_VPT(im3d) ;
12017    if( AFNI_yesenv("AFNI_CREEPTO") )
12018      ii = AFNI_creepto_dicom(im3d,xx,yy,zz) ;
12019    else
12020      ii = AFNI_jumpto_dicom_OLD(im3d,xx,yy,zz) ;
12021    return ii ;
12022 }
12023 
12024 /*----------- the two functions below date to 19 Aug 1999 -------------*/
12025 
12026 int AFNI_jumpto_ijk( Three_D_View *im3d , int ii, int jj, int kk )
12027 {
12028    THD_dataxes *daxes ;
12029 
12030 ENTRY("AFNI_jumpto_ijk") ;
12031 
12032    LOAD_ANAT_VIEW(im3d) ;
12033 
12034    daxes = CURRENT_DAXES(im3d->anat_now) ;
12035    if( ii >= 0 && ii < daxes->nxx &&
12036        jj >= 0 && jj < daxes->nyy && kk >= 0 && kk < daxes->nzz ){
12037 
12038       SAVE_VPT(im3d) ;
12039       AFNI_set_viewpoint( im3d , ii,jj,kk , REDISPLAY_ALL ) ; /* jump */
12040       RETURN(1) ;
12041    } else {
12042       BEEPIT ; WARNING_message("Jumpto IJK failed -- bad input values?!") ;
12043                WARNING_message("  i range = 0 .. %d (inclusive)",daxes->nxx-1) ;
12044                WARNING_message("  j range = 0 .. %d (inclusive)",daxes->nyy-1) ;
12045                WARNING_message("  k range = 0 .. %d (inclusive)",daxes->nzz-1) ;
12046       RETURN(-1) ;
12047    }
12048 }
12049 
12050 /*---------------------------------------------------------------------*/
12051 
12052 void AFNI_jumpto_thminmax_CB( Widget w , XtPointer cd , XtPointer cb )
12053 {
12054    Three_D_View *im3d = (Three_D_View *)cd ;
12055    int ijk=-777, ii,jj,kk ;
12056    float xx,yy,zz ;
12057 
12058 ENTRY("AFNI_jumpto_thminmax_CB") ;
12059 
12060    if( !IM3D_OPEN(im3d) ) EXRETURN ;
12061 
12062         if( w == im3d->vwid->func->pbar_jumpto_thmax_pb )
12063           ijk = im3d->fim_thresh_max_ijk ;
12064    else if( w == im3d->vwid->func->pbar_jumpto_thmin_pb )
12065           ijk = im3d->fim_thresh_min_ijk ;
12066 
12067    if( ijk == -777 || im3d->fim_thrindex < 0 )  EXRETURN ;
12068    if( ijk < 0 ){ BEEPIT ; SENSITIZE(w,False) ; EXRETURN ; }
12069 
12070    ii = DSET_index_to_ix(im3d->fim_now,ijk) ;
12071    jj = DSET_index_to_jy(im3d->fim_now,ijk) ;
12072    kk = DSET_index_to_kz(im3d->fim_now,ijk) ;
12073 
12074    MAT44_VEC( im3d->fim_now->daxes->ijk_to_dicom , ii,jj,kk , xx,yy,zz ) ;
12075    (void)AFNI_jumpto_dicom( im3d , xx,yy,zz ) ;
12076 
12077    EXRETURN ;
12078 }
12079 
12080 /*---------------------------------------------------------------------*/
12081 /* Jump to ijk in Overlay [20 Apr 2016] */
12082 
12083 int AFNI_jumpto_ijk_olay( Three_D_View *im3d , int ii, int jj, int kk )
12084 {
12085    THD_dataxes *daxes ;
12086 
12087 ENTRY("AFNI_jumpto_ijk_olay") ;
12088 
12089    if( !ISVALID_DSET(im3d->fim_now) ){ BEEPIT; RETURN(-1); }
12090 
12091    daxes = im3d->fim_now->daxes ;
12092 
12093    if( ii >= 0 && ii < daxes->nxx &&
12094        jj >= 0 && jj < daxes->nyy && kk >= 0 && kk < daxes->nzz ){
12095 
12096       THD_fvec3 fv ;
12097       SAVE_VPT(im3d) ;
12098 
12099       fv = THD_3dind_to_dicomm_no_wod( im3d->fim_now , TEMP_IVEC3(ii,jj,kk) ) ;
12100       RETURN( AFNI_jumpto_dicom_OLD( im3d , fv.xyz[0], fv.xyz[1], fv.xyz[2] ) ) ;
12101    }
12102 
12103    BEEPIT ; WARNING_message("Jumpto IJK (OL) failed -- bad indexes?!") ;
12104    RETURN(-1) ;
12105 }
12106 
12107 /*---------------------------------------------------------------------*/
12108 
12109 void AFNI_jumpto_ijk_CB( Widget w , XtPointer cd , MCW_choose_cbs *cbs )
12110 {
12111    Three_D_View *im3d = (Three_D_View *) cd ;
12112    int ii=-1,jj=-1,kk=-1 ;
12113    int nn ;
12114    char dum1[32],dum2[32];
12115 
12116 ENTRY("AFNI_jumpto_ijk_CB") ;
12117 
12118    if( ! IM3D_OPEN(im3d) || im3d->type != AFNI_3DDATA_VIEW ) EXRETURN ;
12119    if( cbs->reason != mcwCR_string ) EXRETURN ;  /* error */
12120 
12121    if( last_jumpto_ijk_string != NULL ) free(last_jumpto_ijk_string) ;
12122    last_jumpto_ijk_string = strdup(cbs->cval) ;
12123 
12124    nn = sscanf( cbs->cval , "%d%[ ,]%d%[ ,]%d" , &ii,dum1,&jj,dum2,&kk ) ;
12125    if( nn > 0 && nn < 3 && ii >= 0 ){  /* 1D index jump [26 Jun 2009] */
12126      nn = ii ;
12127      ii = DSET_index_to_ix(im3d->anat_now,nn) ;
12128      jj = DSET_index_to_jy(im3d->anat_now,nn) ;
12129      kk = DSET_index_to_kz(im3d->anat_now,nn) ;
12130    } else if( nn != 5 ){
12131      BEEPIT; WARNING_message("Jumpto IJK failed -- bad entries?!"); EXRETURN;
12132    }
12133 
12134    nn = AFNI_jumpto_ijk( im3d , ii,jj,kk ) ;
12135    if( nn < 0 ) BEEPIT ;
12136 
12137    RESET_AFNI_QUIT(im3d) ;
12138    EXRETURN ;
12139 }
12140 
12141 /*---------------------------------------------------------------------*/
12142 
12143 void AFNI_jumpto_ijk_olay_CB( Widget w , XtPointer cd , MCW_choose_cbs *cbs )
12144 {
12145    Three_D_View *im3d = (Three_D_View *) cd ;
12146    int ii=-1,jj=-1,kk=-1 ;
12147    int nn ;
12148    char dum1[32],dum2[32];
12149 
12150 ENTRY("AFNI_jumpto_ijk_olay_CB") ;
12151 
12152    if( ! IM3D_OPEN(im3d) || im3d->type != AFNI_3DDATA_VIEW ) EXRETURN ;
12153    if( cbs->reason != mcwCR_string ) EXRETURN ;  /* error */
12154 
12155    if( last_jumpto_ijk_olay_string != NULL ) free(last_jumpto_ijk_olay_string) ;
12156    last_jumpto_ijk_olay_string = strdup(cbs->cval) ;
12157 
12158    nn = sscanf( cbs->cval , "%d%[ ,]%d%[ ,]%d" , &ii,dum1,&jj,dum2,&kk ) ;
12159    if( nn > 0 && nn < 3 && ii >= 0 ){
12160      nn = ii ;
12161      ii = DSET_index_to_ix(im3d->fim_now,nn) ;
12162      jj = DSET_index_to_jy(im3d->fim_now,nn) ;
12163      kk = DSET_index_to_kz(im3d->fim_now,nn) ;
12164    } else if( nn != 5 ){
12165      BEEPIT; WARNING_message("Jumpto IJK failed -- bad entries?!"); EXRETURN;
12166    }
12167 
12168    nn = AFNI_jumpto_ijk_olay( im3d , ii,jj,kk ) ;
12169    if( nn < 0 ) BEEPIT ;
12170 
12171    RESET_AFNI_QUIT(im3d) ;
12172    EXRETURN ;
12173 }
12174 
12175 /*---------------------------------------------------------------------
12176    called when the sumato chooser is set
12177 -----------------------------------------------------------------------*/
12178 
12179 void AFNI_sumato_CB( Widget w , XtPointer cd , MCW_choose_cbs *cbs )
12180 {
12181    Three_D_View *im3d = (Three_D_View *) cd ;
12182    int nn , ii ;
12183 
12184 ENTRY("AFNI_sumato_CB") ;
12185 
12186    if( !IM3D_OPEN(im3d) || im3d->type != AFNI_3DDATA_VIEW ) EXRETURN ;
12187    if( cbs->reason != mcwCR_string )                        EXRETURN ;
12188    if( !SESSION_HAS_SUMA(im3d->ss_now) )                    EXRETURN ;
12189 
12190    if( last_sumato_string != NULL ) free(last_sumato_string) ;
12191    last_sumato_string = strdup(cbs->cval) ;
12192 
12193    nn = -1 ;
12194    sscanf( cbs->cval , "%d" , &nn ) ;
12195    ii = SUMA_find_node_id( im3d->ss_now->su_surf[0] , nn ) ;
12196    if( ii < 0 ){ BEEPIT; WARNING_message("SUMA To fails -- bad entry?!"); EXRETURN; }
12197 
12198    (void) AFNI_jumpto_dicom( im3d ,
12199                              im3d->ss_now->su_surf[0]->ixyz[ii].x ,
12200                              im3d->ss_now->su_surf[0]->ixyz[ii].y ,
12201                              im3d->ss_now->su_surf[0]->ixyz[ii].z  ) ;
12202 
12203    RESET_AFNI_QUIT(im3d) ;
12204    EXRETURN ;
12205 }
12206 
12207 /*---------------------------------------------------------------------
12208    Transform current dataset based on the existing set of markers
12209 -----------------------------------------------------------------------*/
12210 
12211 #define BEEP_AND_RETURN { BEEPIT; EXRETURN; }
12212 
12213 void AFNI_marks_transform_CB( Widget w ,
12214                               XtPointer client_data , XtPointer call_data )
12215 {
12216    Three_D_View     *im3d = (Three_D_View *) client_data ;
12217    THD_marker_set   *markers ;
12218    THD_warp         *warp ;
12219    THD_3dim_dataset *new_dset ;
12220    THD_session      *ss ;
12221    int              vnew , vvv , sss , aaa , fff , id ;
12222    float            resam_size ;
12223    Widget           wmsg ;
12224 
12225 ENTRY("AFNI_marks_transform_CB") ;
12226 
12227    /*--- sanity checks ---*/
12228 
12229    if( ! IM3D_OPEN(im3d) ) EXRETURN ;
12230 
12231    markers = im3d->anat_now->markers ;
12232    if(markers == NULL || markers->aflags[1] != MARKACTION_WARP) BEEP_AND_RETURN ;
12233 
12234    vnew = WARPED_VIEW(im3d->vinfo->view_type) ; /* view index of new dataset */
12235    if( !ISVALID_VIEW(vnew) ) BEEP_AND_RETURN ;
12236 
12237    /*--- make warp ---*/
12238 
12239    warp = AFNI_make_warp( im3d ) ;
12240    if( warp == NULL ) BEEP_AND_RETURN ;
12241 
12242    /*--- create new dataset (empty at this point) ---*/
12243 
12244    resam_size = im3d->vinfo->resam_vox ;
12245    new_dset   = AFNI_init_warp( im3d , im3d->anat_now , warp , resam_size ) ;
12246    if( new_dset == NULL ) BEEP_AND_RETURN ;
12247 
12248    { char his[128] ;
12249      tross_Copy_History( im3d->anat_now , new_dset ) ;
12250      sprintf(his,"afni: transformed to %s",VIEW_typestr[vnew]) ;
12251      tross_Append_History( new_dset , his ) ;
12252    }
12253 
12254    /*----- This new dataset may replace a current dataset,
12255            and if so, THAT dataset may have a warp child,
12256            and so on.  Mark those datasets for destruction,
12257            mark their anatomy children for destruction, and destroy them -----*/
12258 
12259    vvv = vnew ;
12260    while( ISVALID_VIEW(vvv) && ISVALID_3DIM_DATASET(im3d->anat_dset[vvv]) ){
12261       DSET_MARK_FOR_DEATH( im3d->anat_dset[vvv] ) ;
12262       vvv = WARPED_VIEW(vvv) ;
12263    }
12264 
12265    AFNI_mark_for_death(GLOBAL_library.sslist ) ;        /* find descendants */
12266    AFNI_andersonville (GLOBAL_library.sslist , True ) ; /* kill (including files) */
12267 
12268    /*----- Can now place the new dataset into its rightful place -----*/
12269 
12270    sss = im3d->vinfo->sess_num ;
12271    aaa = im3d->vinfo->anat_num ;
12272    fff = im3d->vinfo->func_num ;
12273 
12274    SET_SESSION_DSET(new_dset, GLOBAL_library.sslist->ssar[sss], aaa, vnew);
12275 /*   GLOBAL_library.sslist->ssar[sss]->dsset_xform_table[aaa][vnew] = new_dset ;*/
12276 
12277    /* reload active datasets, to allow for destruction that may
12278       have occured (this code is copied from AFNI_initialize_view) */
12279 
12280    for( id=0 ; id <= LAST_VIEW_TYPE ; id++ ){
12281       im3d->anat_dset[id] = GET_SESSION_DSET(GLOBAL_library.sslist->ssar[sss], aaa, id) ;
12282       im3d->fim_dset[id]  = GET_SESSION_DSET(GLOBAL_library.sslist->ssar[sss], fff, id) ;
12283 /*      im3d->anat_dset[id] = GLOBAL_library.sslist->ssar[sss]->dsset_xform_table[aaa][id] ;
12284       im3d->fim_dset[id]  = GLOBAL_library.sslist->ssar[sss]->dsset_xform_table[fff][id] ;
12285 */
12286       if( ISVALID_3DIM_DATASET(im3d->anat_dset[id]) )
12287         SENSITIZE( im3d->vwid->view->view_bbox->wbut[id], True ) ;
12288       else
12289         SENSITIZE( im3d->vwid->view->view_bbox->wbut[id], False) ;
12290    }
12291 
12292 STATUS("writing new dataset") ;
12293 
12294    DSET_overwrite_header(new_dset) ;
12295 
12296    /*--- have transformed this anatomy dataset
12297          ==> if the input was the original view, then
12298              destroy any other marker sets in the original view
12299              and make their datasets anatomical children of this one ---*/
12300 
12301    if( im3d->vinfo->view_type == VIEW_ORIGINAL_TYPE ){
12302       int id ;
12303       THD_3dim_dataset *dss ;
12304 
12305       /* perform surgery on the anat datasets in this session */
12306 
12307 STATUS("re-anat_parenting anatomical datasets in this session") ;
12308 
12309       for( id=0 ; id < im3d->ss_now->num_dsset ; id++ ){
12310          dss = GET_SESSION_DSET(im3d->ss_now, id, 0) ;
12311 /*         dss = im3d->ss_now->dsset_xform_table[id][0] ;*/
12312 
12313          if( ! ISVALID_3DIM_DATASET(dss) || dss == im3d->anat_now ) continue ;
12314 
12315          if( dss->markers != NULL ) SINGLE_KILL(dss->kl,dss->markers) ;
12316          dss->markers = NULL ;
12317 
12318          if( dss->anat_parent == NULL ){
12319            dss->anat_parent = im3d->anat_now ;
12320            MCW_strncpy( dss->anat_parent_name ,
12321                         im3d->anat_now->self_name , THD_MAX_NAME ) ;
12322            dss->anat_parent_idcode = im3d->anat_now->idcode ;
12323          }
12324       }
12325    }
12326 
12327    /*--- now that we have a new potential parent (the warped dataset),
12328          and maybe some links to its warp_parent (done just above),
12329          try to make some descendants (followup warps) from it     ---*/
12330 
12331    AFNI_make_descendants( GLOBAL_library.sslist ) ;
12332 
12333    /*--- clean up some stuff ---*/
12334 
12335    if( GLOBAL_argopt.auto_purge == True ) AFNI_purge_unused_dsets() ;
12336 
12337    /* Jan 31, 1995: force adoption of any dataset
12338                     that was orphaned at Andersonville */
12339 
12340    for( sss=0 ; sss < GLOBAL_library.sslist->num_sess ; sss++ ){
12341       ss = GLOBAL_library.sslist->ssar[sss] ;
12342       if( ISVALID_SESSION(ss) ) AFNI_force_adoption( ss , GLOBAL_argopt.warp_4D ) ;
12343    }
12344 
12345    /*---  close marks panel and exit ---*/
12346 
12347 #if 0
12348    XtSetSensitive( im3d->vwid->top_shell , True ) ;
12349    SHOW_AFNI_READY ;
12350 #endif
12351 
12352    AFNI_marks_action_CB( NULL , (XtPointer) im3d , NULL ) ;
12353 
12354    MPROBE ;
12355    EXRETURN ;
12356 }
12357 
12358 /*-------------------------------------------------------------------
12359    Compute the warp.
12360 
12361    Notice the convention: the warp is always stored as Dicom-to-Dicom
12362    coordinates.  For actual use, it must be converted into the
12363    correct form for 3dmm-to-3dmm, or 3dfind-to-3dfind, etc.
12364 
12365    The reason for this convention is that anatomical warps will be
12366    applied to functional datasets, which will in general be oriented
12367    differently from the anatomical dataset that the warp was computed
12368    upon.  By keeping the warp in the generic Dicom system, this
12369    application of a warp to another dataset will be possible.
12370 ---------------------------------------------------------------------*/
12371 
12372 /* macro to extract the im-th marker vector into a THD_fvec3 structure */
12373 
12374 #define MVEC(im) \
12375  TEMP_FVEC3(markers->xyz[im][0],markers->xyz[im][1],markers->xyz[im][2])
12376 
12377 THD_warp * AFNI_make_warp( Three_D_View *im3d )
12378 {
12379    THD_3dim_dataset *anat    = im3d->anat_now ;
12380    THD_marker_set   *markers = im3d->anat_now->markers ;
12381    THD_warp         *warp ;
12382    RwcBoolean good ;
12383 
12384 ENTRY("AFNI_make_warp") ;
12385 
12386    /*--- check the markers for OK-osity ---*/
12387 
12388    good = AFNI_marks_quality_check( False , im3d ) ;
12389    if( !good ) RETURN(NULL) ;
12390 
12391    /*--- make a new warp, and then construct it,
12392          based on the type of marker set we have here ---*/
12393 
12394    warp = myXtNew( THD_warp ) ;
12395 
12396    switch( markers->type ){  /* type of marker set */
12397 
12398       default: RETURN(NULL) ;      /* something bad happened */
12399 
12400       /*--- bounding box markers set ---*/
12401 
12402       case MARKSET_BOUNDING:{
12403          THD_talairach_12_warp *twarp = (THD_talairach_12_warp *) warp ;
12404          THD_fvec3 mant,mpos,msup,minf,mrig,mlef , pcie ;
12405          float dist_sup , dist_inf , dist_ant , dist_med , dist_pos ,
12406                dist_lef , dist_rig ;
12407          float scale_S , scale_I , scale_A , scale_M , scale_P ,
12408                scale_L , scale_R , shift_P ;
12409          float bot_S   , bot_I   , bot_A   , bot_M   , bot_P ,
12410                bot_L   , bot_R ;
12411          float top_S   , top_I   , top_A   , top_M   , top_P ,
12412                top_L   , top_R ;
12413          THD_fvec3 bv_A , bv_M , bv_P , sv_A , sv_M , sv_P ;
12414 
12415          /* let the world know what kind of warp is being built */
12416 
12417          twarp->type = WARP_TALAIRACH_12_TYPE ;
12418 
12419          /* extract the marker vectors, put in Dicom coords */
12420 
12421          mant = THD_3dmm_to_dicomm( anat , MVEC(IMARK_MANT) ) ;
12422          mpos = THD_3dmm_to_dicomm( anat , MVEC(IMARK_MPOS) ) ;
12423          msup = THD_3dmm_to_dicomm( anat , MVEC(IMARK_MSUP) ) ;
12424          minf = THD_3dmm_to_dicomm( anat , MVEC(IMARK_MINF) ) ;
12425          mrig = THD_3dmm_to_dicomm( anat , MVEC(IMARK_MRIG) ) ;
12426          mlef = THD_3dmm_to_dicomm( anat , MVEC(IMARK_MLEF) ) ;
12427 
12428          /* convert Posterior Commissure from parent to current coords */
12429 
12430          LOAD_FVEC3( pcie ,
12431                      anat->warp_parent->markers->xyz[IMARK_PCIE][0] ,
12432                      anat->warp_parent->markers->xyz[IMARK_PCIE][1] ,
12433                      anat->warp_parent->markers->xyz[IMARK_PCIE][2]  ) ;
12434 
12435          pcie = THD_3dmm_to_dicomm( anat->warp_parent , pcie ) ;
12436          pcie = AFNI_transform_vector( anat->warp_parent , pcie , anat ) ;
12437 
12438          /* compute distances between points in various directions */
12439 
12440          dist_ant = -mant.xyz[1] ;
12441          dist_med =  pcie.xyz[1] ;
12442          dist_pos =  mpos.xyz[1] - pcie.xyz[1] ;
12443 
12444          dist_sup =  msup.xyz[2] ;
12445          dist_inf = -minf.xyz[2] ;
12446          dist_lef =  mlef.xyz[0] ;
12447          dist_rig = -mrig.xyz[0] ;
12448 
12449          /* from these, compute the scalings needed in each
12450             direction and the shift needed posterior to the PC */
12451 
12452          scale_A = ATLAS_FRONT_TO_AC / dist_ant ;
12453          scale_M = ATLAS_AC_TO_PC    / dist_med ;
12454          scale_P = ATLAS_PC_TO_BACK  / dist_pos ;
12455          scale_S = ATLAS_AC_TO_TOP   / dist_sup ;
12456          scale_I = ATLAS_BOT_TO_AC   / dist_inf ;
12457          scale_L = ATLAS_AC_TO_LAT   / dist_lef ;
12458          scale_R = ATLAS_AC_TO_LAT   / dist_rig ;
12459 
12460          shift_P = scale_P * dist_med - ATLAS_AC_TO_PC ;
12461 
12462          /* shift vectors in each direction, for each y cell (A,M,P) */
12463 
12464          LOAD_FVEC3( bv_A , 0,0,0 ) ; bv_M = sv_A = sv_M = bv_A ;
12465 
12466          LOAD_FVEC3( bv_P , 0 , shift_P , 0 ) ;
12467          LOAD_FVEC3( sv_P , 0 , -shift_P / scale_P , 0 ) ;
12468 
12469          /* bounds information for each direction, for each cell */
12470 
12471          bot_A = -9999.0        ; top_A = 0.0 ;
12472          bot_M =     0.0        ; top_M = ATLAS_AC_TO_PC ;
12473          bot_P = ATLAS_AC_TO_PC ; top_P = 9999.0 ;
12474 
12475          bot_R = -9999.0        ; top_R =    0.0 ;
12476          bot_L =     0.0        ; top_L = 9999.9 ;
12477 
12478          bot_I = -9999.0        ; top_I =    0.0 ;
12479          bot_S =     0.0        ; top_S = 9999.9 ;
12480 
12481          /* Compute the 12 linear maps:
12482                They are all linear scalings (diagonal matrices);
12483                posterior to the PC, they also contain shifts
12484                to align stuff to the nominal PC location.
12485             N.B.: these are maps from AC-PC aligned coordinates
12486                   to the Talairach system.  Maps from the
12487                   original data to the Talairach system
12488                   will be computed later (in AFNI_concatenate_warps). */
12489 
12490    /* ------- a macro to automate map making:
12491               xx = R or L , yy = A, M, or P , zz = I or S --------*/
12492 
12493 #define MAKE_MAP(xx,yy,zz) \
12494 (\
12495    LOAD_DIAG_MAT( twarp->warp[W_ ## xx ## yy ## zz].mfor ,      \
12496                   scale_ ## xx , scale_ ## yy , scale_ ## zz ) ,\
12497 \
12498    LOAD_DIAG_MAT( twarp->warp[W_ ## xx ## yy ## zz].mbac ,                 \
12499            1.0 / scale_ ## xx , 1.0 / scale_ ## yy , 1.0 / scale_ ## zz ) ,\
12500 \
12501    twarp->warp[W_ ## xx ## yy ## zz].bvec = bv_ ## yy , \
12502 \
12503    twarp->warp[W_ ## xx ## yy ## zz].svec = sv_ ## yy , \
12504 \
12505    LOAD_FVEC3( twarp->warp[W_ ## xx ## yy ## zz].bot ,   \
12506                bot_ ## xx , bot_ ## yy , bot_ ## zz   ) ,\
12507 \
12508    LOAD_FVEC3( twarp->warp[W_ ## xx ## yy ## zz].top ,   \
12509                top_ ## xx , top_ ## yy , top_ ## zz   )  \
12510 )
12511 
12512    /*------- end of MAKE_MAP macro --------*/
12513 
12514          MAKE_MAP(R,A,S) ;   /* right-anterior -superior */
12515          MAKE_MAP(L,A,S) ;   /* left -anterior -superior */
12516          MAKE_MAP(R,M,S) ;   /* right-medial   -superior */
12517          MAKE_MAP(L,M,S) ;   /* left -medial   -superior */
12518          MAKE_MAP(R,P,S) ;   /* right-posterior-superior */
12519          MAKE_MAP(L,P,S) ;   /* left -posterior-superior */
12520          MAKE_MAP(R,A,I) ;   /* right-anterior -inferior */
12521          MAKE_MAP(L,A,I) ;   /* left -anterior -inferior */
12522          MAKE_MAP(R,M,I) ;   /* right-medial   -inferior */
12523          MAKE_MAP(L,M,I) ;   /* left -medial   -inferior */
12524          MAKE_MAP(R,P,I) ;   /* right-posterior-inferior */
12525          MAKE_MAP(L,P,I) ;   /* left -posterior-inferior */
12526 
12527 #undef MAKE_MAP
12528 
12529       }
12530       break ; /* end of Bounding markers set */
12531 
12532       /*--- AC-PC alignment markers set ---*/
12533 
12534       case MARKSET_ALIGN:{
12535          THD_affine_warp *awarp = (THD_affine_warp *) warp ;
12536 
12537          THD_fvec3 acsup , acpos , pcinf , msag1 , msag2 ,
12538                    alpha1,alpha2,alpha,beta,gamma,rr1,rr2,rr , dif ;
12539          THD_mat33 to_al ;
12540          float size ;
12541 
12542          /* let the world know what kind of warp is being built */
12543 
12544          awarp->type = WARP_AFFINE_TYPE ;
12545 
12546          /* extract the marker vectors, put in Dicom coords */
12547 
12548          acsup = THD_3dmm_to_dicomm( anat , MVEC(IMARK_ACSE) ) ;
12549          acpos = THD_3dmm_to_dicomm( anat , MVEC(IMARK_ACPM) ) ;
12550          pcinf = THD_3dmm_to_dicomm( anat , MVEC(IMARK_PCIE) ) ;
12551          msag1 = THD_3dmm_to_dicomm( anat , MVEC(IMARK_MSA1) ) ;
12552          msag2 = THD_3dmm_to_dicomm( anat , MVEC(IMARK_MSA2) ) ;
12553 
12554          /*--- new y direction (beta) ---*/
12555 
12556          beta = SUB_FVEC3(pcinf,acsup) ;  beta = NORMALIZE_FVEC3(beta) ;
12557 
12558          /*--- new x direction (alpha) ---*/
12559 
12560          rr     = SUB_FVEC3(msag1,acsup) ;
12561          alpha1 = CROSS_FVEC3(beta,rr) ; alpha1 = NORMALIZE_FVEC3(alpha1) ;
12562 
12563          rr     = SUB_FVEC3(msag2,acsup) ;
12564          alpha2 = CROSS_FVEC3(beta,rr) ; alpha2 = NORMALIZE_FVEC3(alpha2) ;
12565 
12566          alpha  = SCLADD_FVEC3(0.5,alpha1,0.5,alpha2) ;
12567          alpha  = NORMALIZE_FVEC3(alpha) ;
12568 
12569          /*--- new z direction (gamma) ---*/
12570 
12571          gamma = CROSS_FVEC3(alpha,beta) ; gamma = NORMALIZE_FVEC3(gamma) ;
12572 
12573          /*--- origin of Talairach coordinates (rr) --*/
12574 
12575          dif  = SUB_FVEC3(acsup,acpos) ;
12576          size = DOT_FVEC3(dif,gamma) ;
12577          rr1  = SCLADD_FVEC3(1.0,acpos,size,gamma) ;
12578 
12579          size = DOT_FVEC3(dif,beta) ;
12580          rr2  = SCLADD_FVEC3(1.0,acsup,-size,beta) ;
12581 
12582          rr   = SCLADD_FVEC3(0.5,rr1,0.5,rr2) ;
12583 
12584          /*--- at this point, have:
12585                   new origin in rr ;
12586                   new axes directions in alpha,beta,gamma.
12587                Now construct the transformation between
12588                the Dicom coordinate systems ---------------------*/
12589 
12590          to_al.mat[0][0] = alpha.xyz[0] ;  /* first row is alpha */
12591          to_al.mat[0][1] = alpha.xyz[1] ;
12592          to_al.mat[0][2] = alpha.xyz[2] ;
12593 
12594          to_al.mat[1][0] = beta.xyz[0] ;   /* second row is beta */
12595          to_al.mat[1][1] = beta.xyz[1] ;
12596          to_al.mat[1][2] = beta.xyz[2] ;
12597 
12598          to_al.mat[2][0] = gamma.xyz[0] ;  /* third row is gamma */
12599          to_al.mat[2][1] = gamma.xyz[1] ;
12600          to_al.mat[2][2] = gamma.xyz[2] ;
12601 
12602          /*--- put into warp structure ---*/
12603 
12604          awarp->warp.type = MAPPING_LINEAR_TYPE ;
12605          awarp->warp.mfor = to_al ;
12606          awarp->warp.mbac = TRANSPOSE_MAT(to_al) ;  /* orthog^(-1) */
12607          awarp->warp.bvec = MATVEC(to_al,rr) ;
12608          awarp->warp.svec = rr ;  NEGATE_FVEC3(awarp->warp.svec) ;
12609 
12610          /* load bot & top with largest possible excursions from
12611             origin (the ALIGNBOX dimensions were added 3/25/95)  */
12612 
12613          {
12614             float zbot = ATLAS_ALIGNBOX_INF;
12615             float ztop = ATLAS_ALIGNBOX_SUP;
12616             float xtop = ATLAS_ALIGNBOX_LAT;
12617             float ytop = ATLAS_ALIGNBOX_POS;
12618             float ybot = ATLAS_ALIGNBOX_ANT;
12619             #define GETVAL(vvv,nnn) do{ char *eee = getenv(nnn) ;                            \
12620                             if( eee != NULL ){                                   \
12621                               float val=strtod(eee,NULL); if(val>0.0) vvv = val; \
12622                             } } while(0)
12623 
12624                      GETVAL(xtop,"AFNI_ACPC_BBOX_LAT") ;  /* ZSS: Apr 2007: get new bounding box */
12625                      GETVAL(ybot,"AFNI_ACPC_BBOX_ANT") ;  /* from environment variables, maybe */
12626                      GETVAL(ytop,"AFNI_ACPC_BBOX_POS") ;
12627                      GETVAL(zbot,"AFNI_ACPC_BBOX_INF") ;
12628                      GETVAL(ztop,"AFNI_ACPC_BBOX_SUP") ;
12629 
12630             #undef GETVAL
12631 
12632             LOAD_FVEC3(awarp->warp.bot,
12633                        -xtop, -ybot, -zbot);
12634             LOAD_FVEC3(awarp->warp.top,
12635                         xtop, ytop, ztop);
12636          }
12637 
12638 #ifdef AFNI_DEBUG
12639 STATUS("Original -> Aligned Map::") ;
12640 DUMP_LMAP(awarp->warp) ;
12641 #endif
12642 
12643       }  /* end of AC-PC alignment case */
12644       break ;
12645 
12646    } /* end of switch on marker set type */
12647 
12648    RETURN(warp) ;
12649 }
12650 
12651 /*---------------------------------------------------------------------*/
12652 
12653 #define ADD_ERROR(str)                                \
12654    { int ll = strlen(str) + strlen(error_list) + 16 ; \
12655      STATUS(str) ;                                    \
12656      error_list = (char*) XtRealloc( error_list , ll ) ;      \
12657      strcat( error_list , "*** ERROR:  ") ;           \
12658      strcat( error_list , str ) ; num_error++ ; }
12659 
12660 #define ADD_REPORT(str)                               \
12661    { int ll = strlen(str) + strlen(error_list) + 16 ; \
12662      STATUS(str) ;                                    \
12663      error_list = (char*)XtRealloc( error_list , ll ) ;      \
12664      strcat( error_list , str ) ; num_report++ ; }
12665 
12666 RwcBoolean AFNI_marks_quality_check( RwcBoolean make_report, Three_D_View *im3d )
12667 {
12668    THD_3dim_dataset *anat    = im3d->anat_now ;
12669    THD_marker_set   *markers = im3d->anat_now->markers ;
12670 
12671    char *error_list ;
12672    int   num_error , num_report ;
12673    char  msg[128] ;
12674    RwcBoolean good ;
12675 
12676 ENTRY("AFNI_marks_quality_check") ;
12677 
12678    /*--- for compiling a list of errors and/or reports ---*/
12679 
12680    if( markers == NULL ){ BEEPIT ; RETURN(False) ; }  /* should not happen */
12681 
12682    error_list = XtNewString(
12683                 "             *** MARKERS QUALITY REPORT ***           \n\n") ;
12684    num_error  = 0 ;
12685    num_report = 0 ;
12686 
12687    /*--- what we do depends on the kinds of markers we have ---*/
12688 
12689    switch( markers->type ){
12690 
12691       default: RETURN(False) ;      /* something bad happened */
12692 
12693       /*--- bounding box markers set ---*/
12694 
12695       case MARKSET_BOUNDING:{
12696          THD_fvec3 mant,mpos,msup,minf,mrig,mlef , pcie ;
12697          float dist_sup , dist_inf , dist_ant , dist_med , dist_pos ,
12698                dist_lef , dist_rig ;
12699 
12700          /* extract the marker vectors, put in Dicom coords */
12701 
12702          mant = THD_3dmm_to_dicomm( anat , MVEC(IMARK_MANT) ) ;
12703          mpos = THD_3dmm_to_dicomm( anat , MVEC(IMARK_MPOS) ) ;
12704          msup = THD_3dmm_to_dicomm( anat , MVEC(IMARK_MSUP) ) ;
12705          minf = THD_3dmm_to_dicomm( anat , MVEC(IMARK_MINF) ) ;
12706          mrig = THD_3dmm_to_dicomm( anat , MVEC(IMARK_MRIG) ) ;
12707          mlef = THD_3dmm_to_dicomm( anat , MVEC(IMARK_MLEF) ) ;
12708 
12709          /* convert Posterior Commissure from parent to current coords */
12710 
12711          LOAD_FVEC3( pcie ,
12712                      anat->warp_parent->markers->xyz[IMARK_PCIE][0] ,
12713                      anat->warp_parent->markers->xyz[IMARK_PCIE][1] ,
12714                      anat->warp_parent->markers->xyz[IMARK_PCIE][2]  ) ;
12715 
12716          pcie = THD_3dmm_to_dicomm( anat->warp_parent , pcie ) ;
12717          pcie = AFNI_transform_vector( anat->warp_parent , pcie , anat ) ;
12718 
12719          /* compute distances between points in various directions */
12720 
12721          dist_ant = -mant.xyz[1] ;
12722          dist_med =  pcie.xyz[1] ;
12723          dist_pos =  mpos.xyz[1] - pcie.xyz[1] ;
12724 
12725          dist_sup =  msup.xyz[2] ;
12726          dist_inf = -minf.xyz[2] ;
12727 
12728          dist_lef =  mlef.xyz[0] ;
12729          dist_rig = -mrig.xyz[0] ;
12730 
12731          /* check anterior distance and report it */
12732 
12733          if( dist_ant/ATLAS_FRONT_TO_AC < MIN_ALLOWED_DEVIATION ||
12734              dist_ant/ATLAS_FRONT_TO_AC > MAX_ALLOWED_DEVIATION   )
12735          ADD_ERROR("The following measurement is outside the allowed range!\n");
12736 
12737          sprintf(msg,"Front to Anterior commissure: %5.1f mm (Atlas:%5.1f)\n",
12738                  dist_ant,ATLAS_FRONT_TO_AC) ;
12739          ADD_REPORT(msg) ;
12740 
12741          /* medial */
12742 
12743 #if 0
12744          if( dist_med/ATLAS_AC_TO_PC < MIN_ALLOWED_DEVIATION ||
12745              dist_med/ATLAS_AC_TO_PC > MAX_ALLOWED_DEVIATION   )
12746          ADD_ERROR("The following measurement is outside the allowed range!\n");
12747 #endif
12748          sprintf(msg,"Intercommissural distance:    %5.1f mm (Atlas:%5.1f)\n",
12749                  dist_med,ATLAS_AC_TO_PC) ;
12750          ADD_REPORT(msg) ;
12751 
12752 
12753          /* posterior */
12754 
12755          if( dist_pos/ATLAS_PC_TO_BACK < MIN_ALLOWED_DEVIATION ||
12756              dist_pos/ATLAS_PC_TO_BACK > MAX_ALLOWED_DEVIATION   )
12757          ADD_ERROR("The following measurement is outside the allowed range!\n");
12758 
12759          sprintf(msg,"Posterior commissure to back: %5.1f mm (Atlas:%5.1f)\n",
12760                  dist_pos,ATLAS_PC_TO_BACK) ;
12761          ADD_REPORT(msg) ;
12762 
12763          /* inferior */
12764 
12765          if( dist_inf/ATLAS_BOT_TO_AC < MIN_ALLOWED_DEVIATION ||
12766              dist_inf/ATLAS_BOT_TO_AC > MAX_ALLOWED_DEVIATION   )
12767          ADD_ERROR("The following measurement is outside the allowed range!\n");
12768 
12769          sprintf(msg,"Bottom to Anterior commissure:%5.1f mm (Atlas:%5.1f)\n",
12770                  dist_inf,ATLAS_BOT_TO_AC) ;
12771          ADD_REPORT(msg) ;
12772 
12773          /* superior */
12774 
12775          if( dist_sup/ATLAS_AC_TO_TOP < MIN_ALLOWED_DEVIATION ||
12776              dist_sup/ATLAS_AC_TO_TOP > MAX_ALLOWED_DEVIATION   )
12777          ADD_ERROR("The following measurement is outside the allowed range!\n");
12778 
12779          sprintf(msg,"Anterior commissure to top:   %5.1f mm (Atlas:%5.1f)\n",
12780                  dist_sup,ATLAS_AC_TO_TOP) ;
12781          ADD_REPORT(msg) ;
12782 
12783          /* left */
12784 
12785          if( dist_lef/ATLAS_AC_TO_LAT < MIN_ALLOWED_DEVIATION ||
12786              dist_lef/ATLAS_AC_TO_LAT > MAX_ALLOWED_DEVIATION   )
12787          ADD_ERROR("The following measurement is outside the allowed range!\n");
12788 
12789          sprintf(msg,"Anterior commissure to left:  %5.1f mm (Atlas:%5.1f)\n",
12790                  dist_lef,ATLAS_AC_TO_LAT) ;
12791          ADD_REPORT(msg) ;
12792 
12793          /* right */
12794 
12795          if( dist_rig/ATLAS_AC_TO_LAT < MIN_ALLOWED_DEVIATION ||
12796              dist_rig/ATLAS_AC_TO_LAT > MAX_ALLOWED_DEVIATION   )
12797          ADD_ERROR("The following measurement is outside the allowed range!\n");
12798 
12799          sprintf(msg,"Anterior commissure to right: %5.1f mm (Atlas:%5.1f)\n",
12800                  dist_rig,ATLAS_AC_TO_LAT) ;
12801          ADD_REPORT(msg) ;
12802       }
12803       break ;  /* end of Boundings marker case */
12804 
12805       /*--- AC-PC alignment markers set ---*/
12806 
12807       case MARKSET_ALIGN:{
12808          THD_fvec3 acsup , acpos , pcinf , msag1 , msag2 ,
12809                    alpha1,alpha2,alpha,beta,gamma,rr1,rr2,rr , dif ;
12810          float size , slim ;
12811 
12812          /* extract the marker vectors, put in Dicom coords */
12813 
12814          acsup = THD_3dmm_to_dicomm( anat , MVEC(IMARK_ACSE) ) ;
12815          acpos = THD_3dmm_to_dicomm( anat , MVEC(IMARK_ACPM) ) ;
12816          pcinf = THD_3dmm_to_dicomm( anat , MVEC(IMARK_PCIE) ) ;
12817          msag1 = THD_3dmm_to_dicomm( anat , MVEC(IMARK_MSA1) ) ;
12818          msag2 = THD_3dmm_to_dicomm( anat , MVEC(IMARK_MSA2) ) ;
12819 
12820          /*-- check the points for proper distances between each other --*/
12821 
12822          rr = SUB_FVEC3(acsup,acpos) ; size = SIZE_FVEC3(rr) ;
12823          if( size > 4.0 )
12824          ADD_ERROR("The two AC points are more than 4 mm apart.\n") ;
12825 
12826          slim = MIN_ALLOWED_DEVIATION * ATLAS_AC_TO_PC ;
12827          rr = SUB_FVEC3(acsup,pcinf) ; size = SIZE_FVEC3(rr) ;
12828          if( size <= slim ){
12829             sprintf(msg, "The AC & PC points are separated by %5.2f mm\n"
12830                          "which is closer than the minimum %5.2f mm!\n" ,
12831                     size,slim ) ;
12832             ADD_ERROR(msg) ;
12833          }
12834 
12835          rr = SUB_FVEC3(acsup,msag1) ; size = SIZE_FVEC3(rr) ;
12836          if( size < 20.0 )
12837          ADD_ERROR("The AC and 1st mid-sag points are closer than 20 mm.\n");
12838 
12839          rr = SUB_FVEC3(acsup,msag2) ; size = SIZE_FVEC3(rr) ;
12840          if( size < 20.0 )
12841          ADD_ERROR("The AC and 2nd mid-sag points are closer than 20 mm.\n");
12842 
12843          rr = SUB_FVEC3(msag1,msag2) ; size = SIZE_FVEC3(rr) ;
12844          if( size < 20.0 )
12845          ADD_ERROR("The two mid-sag points are closer than 20 mm.\n");
12846 
12847          rr = SUB_FVEC3(pcinf,msag1) ; size = SIZE_FVEC3(rr) ;
12848          if( size < 20.0 )
12849          ADD_ERROR("The PC and 1st mid-sag points are closer than 20 mm.\n");
12850 
12851          rr = SUB_FVEC3(pcinf,msag2) ; size = SIZE_FVEC3(rr) ;
12852          if( size < 20.0 )
12853          ADD_ERROR("The PC and 2nd mid-sag points are closer than 20 mm.\n");
12854 
12855          /*--- compute the new y direction (beta) ---*/
12856 
12857          beta = SUB_FVEC3(pcinf,acsup) ;  beta = NORMALIZE_FVEC3(beta) ;
12858 
12859          /*--- compute the new x direction (alpha) ---*/
12860 
12861          rr     = SUB_FVEC3(msag1,acsup) ;
12862          alpha1 = CROSS_FVEC3(beta,rr) ; alpha1 = NORMALIZE_FVEC3(alpha1) ;
12863 
12864          rr     = SUB_FVEC3(msag2,acsup) ;
12865          alpha2 = CROSS_FVEC3(beta,rr) ; alpha2 = NORMALIZE_FVEC3(alpha2) ;
12866 
12867          size = DOT_FVEC3(alpha1,alpha2) ;  /* angle < 2 degrees ? */
12868          if( size < 0.99939 )               /* (size = cos(angle) */
12869          ADD_ERROR("The AC + PC + mid-sag pts do not form a good plane.\n");
12870 
12871          size = acos((double)size) * 180/3.14159265 ;  /* report angle */
12872          sprintf(msg,
12873          "Angular deviation between AC+PC+mid-sag pts: %6.2f degrees\n",size);
12874          ADD_REPORT(msg) ;
12875 
12876          alpha = SCLADD_FVEC3(0.5,alpha1,0.5,alpha2) ;
12877          alpha = NORMALIZE_FVEC3(alpha) ;
12878 
12879          /*--- compute the new z direction (gamma) ---*/
12880 
12881          gamma = CROSS_FVEC3(alpha,beta) ; gamma = NORMALIZE_FVEC3(gamma) ;
12882 
12883          /*--- now, consider the ray from the AC posterior margin (acpos)
12884                in the gamma direction, and the ray from the AC superior
12885                edge (acsup) in the beta direction.  Nominally, these rays
12886                should intersect.  Find their points of closest approach
12887                (rr1,rr2).  The average of these is the Talairach center
12888                of coordinates (rr). ------------------------------------*/
12889 
12890          dif  = SUB_FVEC3(acsup,acpos) ;
12891          size = DOT_FVEC3(dif,gamma) ;
12892          rr1  = SCLADD_FVEC3(1.0,acpos,size,gamma) ;
12893 
12894          size = DOT_FVEC3(dif,beta) ;
12895          rr2  = SCLADD_FVEC3(1.0,acsup,-size,beta) ;
12896 
12897          dif = SUB_FVEC3(rr1,rr2) ; size = SIZE_FVEC3(dif) ;
12898          if( size > 2.0 )
12899          ADD_ERROR("AC Talairach origin mismatch more than 2 mm!\n") ;
12900 
12901          sprintf(msg,
12902          "Mismatch between AC-PC line and Talairach origin: %6.2f mm\n",size);
12903          ADD_REPORT(msg) ;
12904 
12905          rr = SCLADD_FVEC3(0.5,rr1,0.5,rr2) ;
12906 
12907          /*-- Use the trace of the rotation matrix to find
12908               the total rotation angle [suggested by M. Klosek] --*/
12909 
12910          { float theta, costheta ;
12911 
12912             costheta = 0.5 * sqrt(1.0+alpha.xyz[0]+beta.xyz[1]+gamma.xyz[2]) ;
12913             theta    = 2.0 * acos(costheta) * 180/3.14159265 ;
12914             sprintf(msg,
12915             "Total rotation to align AC-PC and mid-sag:   %6.2f degrees\n",theta) ;
12916             ADD_REPORT(msg) ;
12917          }
12918 
12919 #ifdef AFNI_DEBUG
12920 STATUS("AC-PC alignment markers computation:") ;
12921 DUMP_FVEC3("   acsup ",acsup ) ;
12922 DUMP_FVEC3("   acpos ",acpos ) ;
12923 DUMP_FVEC3("   pcinf ",pcinf ) ;
12924 DUMP_FVEC3("   msag1 ",msag1 ) ;
12925 DUMP_FVEC3("   msag2 ",msag2 ) ;
12926 DUMP_FVEC3("   beta  ",beta  ) ;
12927 DUMP_FVEC3("   alpha1",alpha1) ;
12928 DUMP_FVEC3("   alpha2",alpha2) ;
12929 DUMP_FVEC3("   alpha ",alpha ) ;
12930 DUMP_FVEC3("   gamma ",gamma ) ;
12931 DUMP_FVEC3("   rr1   ",rr1   ) ;
12932 DUMP_FVEC3("   rr2   ",rr2   ) ;
12933 DUMP_FVEC3("   rr    ",rr    ) ;
12934 printf("\n") ;
12935 #endif
12936 
12937       }  /* end of AC-PC alignment case */
12938       break ;
12939 
12940    } /* end of switch on marker set type */
12941 
12942    if( num_error > 0 || (make_report && num_report > 0) ){
12943       (void) MCW_popup_message( im3d->vwid->marks->frame ,
12944                                 error_list ,
12945                                 MCW_USER_KILL | MCW_TIMER_KILL ) ;
12946    }
12947 
12948    myXtFree( error_list ) ;
12949 
12950    if( num_error > 0 && ! ELIDE_quality ) RETURN(False) ;
12951    RETURN(True) ;
12952 }
12953 
12954 /*------------------------------------------------------------------
12955   Create a new dataset that has the geometry specified as the
12956   warp from the parent.  The actual data will not be filled in yet.
12957 --------------------------------------------------------------------*/
12958 
12959 THD_3dim_dataset * AFNI_init_warp( Three_D_View *im3d ,
12960                                    THD_3dim_dataset *parent_dset ,
12961                                    THD_warp *warp_init , float resam_vox )
12962 {
12963    THD_3dim_dataset *adam_dset ;  /* the farthest ancestor */
12964    THD_warp         *warp_total ; /* the warp from that ancestor */
12965    THD_fvec3         xnew_bot , xnew_top ;
12966 
12967    THD_3dim_dataset *new_dset ;
12968    THD_datablock    *new_dblk  , *adam_dblk  , *parent_dblk ;
12969    THD_dataxes      *new_daxes , *adam_daxes , *parent_daxes ;
12970    THD_diskptr      *new_dkptr , *adam_dkptr , *parent_dkptr ;
12971    THD_marker_set   *new_markers ;
12972 
12973    int new_nx , new_ny , new_nz , ii ;
12974    THD_ivec3 ivbot , ivtop ;
12975 
12976 ENTRY("AFNI_init_warp") ;
12977 
12978    /*----- It is possible that this warp is one in a succession
12979            of warps.  In that case, the actual transformation is
12980            to be done directly from the "adam" dataset, rather
12981            than in succession from the parent.  The reason for
12982            this is to avoid repeated interpolation.  Thus, we
12983            first scan backward along the line of descent, and
12984            create the total warp from "adam" to the new dataset -----*/
12985 
12986    adam_dset   = parent_dset ;
12987    warp_total  = myXtNew( THD_warp ) ;  /* copy initial warp into final warp */
12988    *warp_total = *warp_init ;
12989 
12990    while( adam_dset->warp != NULL ){
12991       AFNI_concatenate_warp( warp_total , adam_dset->warp ) ;
12992       adam_dset = adam_dset->warp_parent ;
12993    }
12994 
12995    if( warp_total->type < FIRST_WARP_TYPE ||
12996        warp_total->type > LAST_WARP_TYPE    ) RETURN(NULL) ;  /* error! */
12997 
12998 #ifdef AFNI_DEBUG
12999 { char str[256] ;
13000   sprintf(str,"parent = %s ; adam = %s",
13001           parent_dset->self_name , adam_dset->self_name ) ;
13002   STATUS(str) ;
13003 
13004   STATUS("warp_total dump:") ;
13005   if( warp_total->type == WARP_AFFINE_TYPE ){
13006      DUMP_LMAP(warp_total->rig_bod.warp) ;
13007   } else {
13008      DUMP_T12_WARP(warp_total->tal_12) ;
13009   }
13010 }
13011 #endif
13012 
13013    adam_dblk  = adam_dset->dblk ;
13014    adam_daxes = adam_dset->daxes ;
13015    adam_dkptr = adam_dblk->diskptr ;
13016 
13017    parent_dblk  = parent_dset->dblk ;
13018    parent_daxes = parent_dset->daxes ;
13019    parent_dkptr = parent_dblk->diskptr ;
13020 
13021    /*----- We now determine the bounding box of the new dataset.
13022            This depends on the warp type:
13023               affine warps   --> use transformed bounding box of adam;
13024               Talairach warp --> use Talairach standard geometry;
13025            The results are in the vectors xnew_bot and xnew_top. -----*/
13026 
13027    switch( warp_total->type ){
13028 
13029       default:  RETURN(NULL) ;  /* something bad happened */
13030 
13031       /*--- 12 case Talairach mapping
13032             (sizes chosen to include borders of Atlas figures) ---*/
13033 
13034       case WARP_TALAIRACH_12_TYPE:{
13035          int   use_tlrc_big=MCW_val_bbox( im3d->vwid->marks->tlrc_big_bbox ) ;
13036          float xtop=ATLAS_BBOX_LAT ,
13037                ybot=ATLAS_BBOX_ANT ,
13038                ytop=ATLAS_BBOX_POS ,
13039                zbot=(use_tlrc_big) ? ATLAS_BBOX_INF_NEW : ATLAS_BBOX_INF ,
13040                ztop=ATLAS_BBOX_SUP ;
13041 
13042 #define GETVAL(vvv,nnn) do{ char *eee = getenv(nnn) ;                            \
13043                             if( eee != NULL ){                                   \
13044                               float val=strtod(eee,NULL); if(val>0.0) vvv = val; \
13045                             } } while(0)
13046 
13047          GETVAL(xtop,"AFNI_TLRC_BBOX_LAT") ;  /* 16 Apr 2002: get new bounding box */
13048          GETVAL(ybot,"AFNI_TLRC_BBOX_ANT") ;  /* from environment variables, maybe */
13049          GETVAL(ytop,"AFNI_TLRC_BBOX_POS") ;
13050          GETVAL(zbot,"AFNI_TLRC_BBOX_INF") ;
13051          GETVAL(ztop,"AFNI_TLRC_BBOX_SUP") ;
13052 
13053 #undef GETVAL
13054 
13055          LOAD_FVEC3( xnew_bot ,-xtop,-ybot,-zbot ) ;
13056          LOAD_FVEC3( xnew_top , xtop, ytop, ztop ) ;
13057       }
13058       break ;
13059 
13060       /*--- linear warp ---*/
13061 
13062       case WARP_AFFINE_TYPE:{
13063          THD_fvec3 corner , base , xnew , aff_bot , aff_top ;
13064          THD_mat33 to_new ;
13065 
13066          to_new  = warp_total->rig_bod.warp.mfor ;
13067          base    = warp_total->rig_bod.warp.bvec ;
13068 
13069          /*--- transform each of the 8 corner locations in
13070                the adam dataset to the aligned system, and
13071                determine the outer limits of the new datablock ---*/
13072 
13073          LOAD_FVEC3(corner,adam_daxes->xxmin,
13074                            adam_daxes->yymin,adam_daxes->zzmin) ;  /* 1 */
13075          corner   = THD_3dmm_to_dicomm( adam_dset , corner ) ;
13076          xnew_bot = xnew_top = MATVEC_SUB(to_new,corner,base) ;
13077 
13078          LOAD_FVEC3(corner,adam_daxes->xxmax,
13079                            adam_daxes->yymin,adam_daxes->zzmin) ;  /* 2 */
13080          corner   = THD_3dmm_to_dicomm( adam_dset , corner ) ;
13081          xnew     = MATVEC_SUB(to_new,corner,base) ;
13082          xnew_bot = MIN_FVEC3(xnew_bot,xnew) ;
13083          xnew_top = MAX_FVEC3(xnew_top ,xnew ) ;
13084 
13085          LOAD_FVEC3(corner,adam_daxes->xxmin,
13086                            adam_daxes->yymax,adam_daxes->zzmin) ;  /* 3 */
13087          corner   = THD_3dmm_to_dicomm( adam_dset , corner ) ;
13088          xnew     = MATVEC_SUB(to_new,corner,base) ;
13089          xnew_bot = MIN_FVEC3(xnew_bot,xnew) ;
13090          xnew_top = MAX_FVEC3(xnew_top ,xnew ) ;
13091 
13092          LOAD_FVEC3(corner,adam_daxes->xxmax,
13093                            adam_daxes->yymax,adam_daxes->zzmin) ;  /* 4 */
13094          corner   = THD_3dmm_to_dicomm( adam_dset , corner ) ;
13095          xnew     = MATVEC_SUB(to_new,corner,base) ;
13096          xnew_bot = MIN_FVEC3(xnew_bot,xnew) ;
13097          xnew_top = MAX_FVEC3(xnew_top ,xnew ) ;
13098 
13099          LOAD_FVEC3(corner,adam_daxes->xxmin,
13100                            adam_daxes->yymin,adam_daxes->zzmax) ;  /* 5 */
13101          corner   = THD_3dmm_to_dicomm( adam_dset , corner ) ;
13102          xnew     = MATVEC_SUB(to_new,corner,base) ;
13103          xnew_bot = MIN_FVEC3(xnew_bot,xnew) ;
13104          xnew_top = MAX_FVEC3(xnew_top ,xnew ) ;
13105 
13106          LOAD_FVEC3(corner,adam_daxes->xxmax,
13107                            adam_daxes->yymin,adam_daxes->zzmax) ;  /* 6 */
13108          corner   = THD_3dmm_to_dicomm( adam_dset , corner ) ;
13109          xnew     = MATVEC_SUB(to_new,corner,base) ;
13110          xnew_bot = MIN_FVEC3(xnew_bot,xnew) ;
13111          xnew_top = MAX_FVEC3(xnew_top ,xnew ) ;
13112 
13113          LOAD_FVEC3(corner,adam_daxes->xxmin,
13114                            adam_daxes->yymax,adam_daxes->zzmax) ;  /* 7 */
13115          corner   = THD_3dmm_to_dicomm( adam_dset , corner ) ;
13116          xnew     = MATVEC_SUB(to_new,corner,base) ;
13117          xnew_bot = MIN_FVEC3(xnew_bot,xnew) ;
13118          xnew_top = MAX_FVEC3(xnew_top ,xnew ) ;
13119 
13120          LOAD_FVEC3(corner,adam_daxes->xxmax,
13121                            adam_daxes->yymax,adam_daxes->zzmax) ;  /* 8 */
13122          corner   = THD_3dmm_to_dicomm( adam_dset , corner ) ;
13123          xnew     = MATVEC_SUB(to_new,corner,base) ;
13124          xnew_bot = MIN_FVEC3(xnew_bot,xnew) ;
13125          xnew_top = MAX_FVEC3(xnew_top ,xnew ) ;
13126 
13127          /* If the warp had any data in it about
13128             the region to map to, apply that data. */
13129 
13130          aff_bot = warp_total->rig_bod.warp.bot  ;
13131          aff_top = warp_total->rig_bod.warp.top  ;
13132 
13133          if( (aff_bot.xyz[0] < aff_top.xyz[0]) &&
13134              (aff_bot.xyz[1] < aff_top.xyz[1]) &&
13135              (aff_bot.xyz[2] < aff_top.xyz[2])   ){
13136 
13137    /* 3/25/95: use the bot & top INSTEAD of the corners
13138                (old version used in ADDITION to corners) */
13139 
13140 #if 0
13141             xnew_bot = MIN_FVEC3(xnew_bot,aff_bot) ;
13142             xnew_top = MAX_FVEC3(xnew_top,aff_top) ;
13143 #else
13144             xnew_bot = aff_bot ;
13145             xnew_top = aff_top ;
13146 #endif
13147          }
13148 
13149       }  /* end of affine warp case */
13150       break ;
13151 
13152    } /* end of xnew_bot & xnew_top computed from warp */
13153 
13154    /* force bounds to be integral multiples of resampling size */
13155 
13156 #define FLOOR(qq) ( ((qq) >= 0) ? ((int)(qq)) : (-1+(int)(qq)) )
13157 
13158    ivbot.ijk[0] = FLOOR( 0.01 + xnew_bot.xyz[0] / resam_vox ) ;
13159    ivbot.ijk[1] = FLOOR( 0.01 + xnew_bot.xyz[1] / resam_vox ) ;
13160    ivbot.ijk[2] = FLOOR( 0.01 + xnew_bot.xyz[2] / resam_vox ) ;
13161 
13162    ivtop.ijk[0] = FLOOR( 0.99 + xnew_top.xyz[0] / resam_vox ) ;
13163    ivtop.ijk[1] = FLOOR( 0.99 + xnew_top.xyz[1] / resam_vox ) ;
13164    ivtop.ijk[2] = FLOOR( 0.99 + xnew_top.xyz[2] / resam_vox ) ;
13165 
13166 #undef FLOOR
13167 
13168    xnew_bot.xyz[0] = ivbot.ijk[0] * resam_vox ;
13169    xnew_bot.xyz[1] = ivbot.ijk[1] * resam_vox ;
13170    xnew_bot.xyz[2] = ivbot.ijk[2] * resam_vox ;
13171 
13172    xnew_top.xyz[0] = ivtop.ijk[0] * resam_vox ;
13173    xnew_top.xyz[1] = ivtop.ijk[1] * resam_vox ;
13174    xnew_top.xyz[2] = ivtop.ijk[2] * resam_vox ;
13175 
13176    /* compute dimensions of the new brick */
13177 
13178    new_nx = (xnew_top.xyz[0] - xnew_bot.xyz[0])/resam_vox + 1.5 ;
13179    new_ny = (xnew_top.xyz[1] - xnew_bot.xyz[1])/resam_vox + 1.5 ;
13180    new_nz = (xnew_top.xyz[2] - xnew_bot.xyz[2])/resam_vox + 1.5 ;
13181 
13182    xnew_top.xyz[0] = xnew_bot.xyz[0] + (new_nx-1) * resam_vox ;
13183    xnew_top.xyz[1] = xnew_bot.xyz[1] + (new_ny-1) * resam_vox ;
13184    xnew_top.xyz[2] = xnew_bot.xyz[2] + (new_nz-1) * resam_vox ;
13185 
13186 #ifdef AFNI_DEBUG
13187 DUMP_FVEC3("  -- xnew_bot",xnew_bot) ;
13188 DUMP_FVEC3("  -- xnew_top",xnew_top) ;
13189 printf("  ==> new nx=%d ny=%d nz=%d\n",new_nx,new_ny,new_nz) ;
13190 #endif
13191 
13192    /*----- make a new 3D dataset !!! -----*/
13193 
13194    new_dset    =                     myXtNew( THD_3dim_dataset ) ;
13195    new_dblk    = new_dset->dblk    = myXtNew( THD_datablock ) ;
13196    new_daxes   = new_dset->daxes   = myXtNew( THD_dataxes ) ;
13197    new_markers = new_dset->markers = NULL ;                 /* later, dude */
13198    new_dkptr   = new_dblk->diskptr = myXtNew( THD_diskptr ) ;
13199    new_dset->Label_Dtable = NULL;                  /* ZSS Feb 26 2010 */
13200 
13201    INIT_KILL(new_dset->kl) ; INIT_KILL(new_dblk->kl) ;
13202 
13203    ADDTO_KILL(new_dset->kl,new_dblk)  ;
13204    ADDTO_KILL(new_dset->kl,new_daxes) ;
13205    ADDTO_KILL(new_dset->kl,new_dkptr) ;
13206 
13207    ADDTO_KILL(new_dset->kl,warp_total) ;
13208 
13209    new_dset->wod_daxes = NULL ;
13210    new_dset->wod_flag  = True ;
13211 
13212    new_dset->taxis = NULL ;
13213    new_dset->tagset = NULL ;  /* Oct 1998 */
13214 
13215    INIT_STAT_AUX( new_dset , MAX_STAT_AUX , parent_dset->stat_aux ) ;
13216 
13217 #define PARENT_MYSELF  /* 14 Dec 1999 */
13218 
13219    new_dset->idcode             = MCW_new_idcode() ;
13220    new_dset->warp_parent_idcode = adam_dset->idcode ;
13221 #ifndef PARENT_MYSELF
13222    ZERO_IDCODE(new_dset->anat_parent_idcode) ;
13223    new_dset->anat_parent = NULL ;
13224 #else
13225    new_dset->anat_parent_idcode = new_dset->idcode ; /* 14 Dec 1999 */
13226    new_dset->anat_parent        = new_dset ;         /* 14 Dec 1999 */
13227 #endif
13228 
13229    EMPTY_STRING(new_dset->anat_parent_name) ;
13230 
13231    /*------------ initialize dataset fields -------------*/
13232    /**** July 1997: be careful about adam and parent ****/
13233 
13234 STATUS("init new_dset") ;
13235 
13236    new_dset->type      = parent_dset->type;                    /* data types */
13237    new_dset->func_type = parent_dset->func_type;
13238    new_dset->view_type = WARPED_VIEW(parent_dset->view_type) ; /* view type */
13239 
13240    new_dset->warp      = warp_total ;                          /* warp info */
13241    new_dset->vox_warp  = NULL ;
13242    new_dset->self_warp = NULL ;    /* 26 Aug 2002 */
13243 
13244    new_dset->warp_parent = adam_dset ;
13245    MCW_strncpy( new_dset->warp_parent_name ,
13246                 adam_dset->self_name       , THD_MAX_NAME ) ;
13247 
13248    MCW_strncpy( new_dset->label1 , parent_dset->label1 , THD_MAX_LABEL ) ;
13249    MCW_strncpy( new_dset->label2 , parent_dset->label2 , THD_MAX_LABEL ) ;
13250 
13251    MCW_strncpy( new_dset->self_name  ,
13252                 parent_dset->self_name , THD_MAX_NAME ) ;  /* make up */
13253    ii = strlen( new_dset->self_name ) ;                    /* a new name */
13254    new_dset->self_name[ii++] = '+' ;
13255    MCW_strncpy( &(new_dset->self_name[ii]) ,
13256                 VIEW_typestr[new_dset->view_type] ,
13257                 THD_MAX_NAME-ii ) ;
13258 
13259    new_dset->death_mark  = 0 ;
13260    new_dset->tcat_list   = 0 ;
13261    new_dset->tcat_num    = 0 ;
13262    new_dset->tcat_len    = NULL ;
13263 
13264    /*--- initialize disk pointer fields ---*/
13265 
13266 STATUS("init new_dkptr") ;
13267 
13268    new_dkptr->type         = DISKPTR_TYPE ;
13269    new_dkptr->rank         = 3 ;
13270    new_dkptr->nvals        = adam_dkptr->nvals ;
13271    new_dkptr->dimsizes[0]  = new_nx ;
13272    new_dkptr->dimsizes[1]  = new_ny ;
13273    new_dkptr->dimsizes[2]  = new_nz ;
13274    new_dkptr->storage_mode = STORAGE_UNDEFINED ;
13275    new_dkptr->byte_order   = THD_get_write_order() ;  /* 25 April 1998 */
13276 
13277    THD_init_diskptr_names( new_dkptr ,
13278                            parent_dkptr->directory_name, NULL, parent_dkptr->prefix ,
13279                            new_dset->view_type , True ) ;
13280 
13281    /*--- initialize datablock fields ---*/
13282 
13283 STATUS("init new_dblk") ;
13284 
13285    new_dblk->type        = DATABLOCK_TYPE ;
13286    new_dblk->nvals       = adam_dblk->nvals ;
13287    new_dblk->malloc_type = DATABLOCK_MEM_UNDEFINED ;
13288    new_dblk->natr        = new_dblk->natr_alloc = 0 ;
13289    new_dblk->atr         = NULL ;
13290    new_dblk->parent      = (XtPointer) new_dset ;
13291 
13292    new_dblk->brick_fac   = NULL ;  /* THD_init_datablock_brick */
13293    new_dblk->brick_bytes = NULL ;  /* will initialize these arrays */
13294    new_dblk->brick       = NULL ;
13295    THD_init_datablock_brick( new_dblk , -1 , adam_dblk ) ;
13296 
13297    new_dblk->master_nvals = 0 ;     /* 11 Jan 1999 */
13298    new_dblk->master_ival  = NULL ;
13299    new_dblk->master_bytes = NULL ;
13300 
13301    new_dblk->vedim = NULL ;  /* 05 Sep 2006 */
13302 
13303    DSET_unlock(new_dset) ;
13304 
13305    THD_null_datablock_auxdata( new_dblk ) ;
13306    THD_copy_datablock_auxdata( adam_dblk , new_dblk ) ; /* 30 Nov 1997 */
13307 
13308    /*--- initialize data axes fields ---*/
13309 
13310 STATUS("init new_daxes") ;
13311 
13312    new_daxes->type     = DATAXES_TYPE ;
13313    new_daxes->nxx      = new_nx ;
13314    new_daxes->nyy      = new_ny ;
13315    new_daxes->nzz      = new_nz ;
13316    new_daxes->xxorg    = xnew_bot.xyz[0] ;
13317    new_daxes->yyorg    = xnew_bot.xyz[1] ;
13318    new_daxes->zzorg    = xnew_bot.xyz[2] ;
13319    new_daxes->xxdel    = resam_vox ;       /* cubical voxels */
13320    new_daxes->yydel    = resam_vox ;
13321    new_daxes->zzdel    = resam_vox ;
13322    new_daxes->xxmin    = xnew_bot.xyz[0] ; /* save new bounding box */
13323    new_daxes->yymin    = xnew_bot.xyz[1] ;
13324    new_daxes->zzmin    = xnew_bot.xyz[2] ;
13325    new_daxes->xxmax    = xnew_top.xyz[0] ;
13326    new_daxes->yymax    = xnew_top.xyz[1] ;
13327    new_daxes->zzmax    = xnew_top.xyz[2] ;
13328    new_daxes->parent   = (XtPointer) new_dset ;
13329 
13330    new_daxes->xxorient = ORI_R2L_TYPE ;    /* Dicom standard axes! */
13331    new_daxes->yyorient = ORI_A2P_TYPE ;
13332    new_daxes->zzorient = ORI_I2S_TYPE ;
13333    LOAD_DIAG_MAT(new_daxes->to_dicomm,1,1,1) ;  /* identity matrix */
13334 
13335    if( !ISVALID_MAT44(new_daxes->ijk_to_dicom) )  /* 15 Dec 2005 */
13336      THD_daxes_to_mat44( new_daxes ) ;
13337 
13338    /*--- if view type is appropriate, set new markers ---*/
13339 
13340    switch( new_dset->view_type ){
13341 
13342       default:
13343 STATUS("no new_markers") ;
13344       break ;   /* no markers */
13345 
13346       /*--- AC-PC aligned ==> can do the BOUNDING set of markers ---*/
13347 
13348       case VIEW_ACPCALIGNED_TYPE:
13349       if( new_dset->type == HEAD_ANAT_TYPE ){
13350          int ii , jj ;
13351 
13352 STATUS("init new_markers") ;
13353 
13354          new_markers = new_dset->markers = myXtNew( THD_marker_set ) ;
13355          ADDTO_KILL(new_dset->kl,new_markers) ;
13356 
13357          new_markers->numdef = NMARK_BOUNDING ;
13358          new_markers->numset = 0 ;                /* null data out */
13359          for( ii=0 ; ii < MARKS_MAXNUM ; ii++ ){
13360 
13361             new_markers->xyz[ii][0] =
13362               new_markers->xyz[ii][1] =
13363                 new_markers->xyz[ii][2] = -99999999.99 ;
13364 
13365             for( jj=0 ; jj < MARKS_MAXLAB ; jj++ )
13366                new_markers->label[ii][jj] = '\0' ;
13367 
13368             for( jj=0 ; jj < MARKS_MAXHELP ; jj++ )
13369                new_markers->help[ii][jj] = '\0' ;
13370 
13371             new_markers->valid[ii]   = False ;
13372             new_markers->ovcolor[ii] = -1 ;    /* not used yet */
13373          }
13374 
13375          for( ii=0 ; ii < NMARK_BOUNDING ; ii++ ){       /* copy strings in */
13376             MCW_strncpy( &(new_markers->label[ii][0]) ,
13377                          THD_bounding_label[ii] , MARKS_MAXLAB ) ;
13378             MCW_strncpy( &(new_markers->help[ii][0]) ,
13379                          THD_bounding_help[ii] , MARKS_MAXHELP ) ;
13380          }
13381 
13382          for( ii=0 ; ii < MARKS_MAXFLAG ; ii++ )     /* copy flags in */
13383             new_markers->aflags[ii] = THD_bounding_aflags[ii] ;
13384          new_markers->type = new_markers->aflags[0] ;
13385       }
13386       break ;  /* end of BOUNDING markers */
13387 
13388    }  /* end of marker creation */
13389 
13390    /*----- copy statistics, if any -----*/
13391 
13392    new_dset->stats = NULL ;
13393    AFNI_copy_statistics( adam_dset , new_dset ) ;
13394 
13395 #ifdef ALLOW_DATASET_VLIST
13396    new_dset->pts = NULL ;
13397 #endif
13398 
13399    /*----- dataset ready for warping -----*/
13400 
13401    PARENTIZE(new_dset,adam_dset->parent) ;
13402 
13403 STATUS("initialization complete") ;
13404 
13405    RETURN( new_dset ) ;
13406 }
13407 
13408 /*-----------------------------------------------------------------*/
13409 
13410 void AFNI_copy_statistics( THD_3dim_dataset *dsold , THD_3dim_dataset *dsnew )
13411 {
13412    int ibr , nvold , nvnew ;
13413    THD_statistics *stold , *stnew ;
13414 
13415 ENTRY("AFNI_copy_statistics") ;
13416 
13417    if( !ISVALID_3DIM_DATASET(dsold) || !ISVALID_3DIM_DATASET(dsnew) ) EXRETURN ;
13418 
13419    nvold = dsold->dblk->nvals ;
13420    nvnew = dsnew->dblk->nvals ;
13421    stold = dsold->stats ;
13422    stnew = dsnew->stats ;
13423    if( !ISVALID_STATISTIC(stold) ) EXRETURN ;
13424 
13425    if( stnew == NULL ){
13426       dsnew->stats  = stnew = myXtNew( THD_statistics ) ;
13427       stnew->type   = STATISTICS_TYPE ;
13428       stnew->nbstat = nvnew ;
13429       stnew->bstat  = (THD_brick_stats *)
13430                         XtMalloc( sizeof(THD_brick_stats) * nvnew ) ;
13431       ADDTO_KILL(dsnew->kl,stnew) ;
13432       stnew->parent = (XtPointer) dsnew ;
13433    } else {
13434       stnew->nbstat = nvnew ;
13435       stnew->bstat  = (THD_brick_stats *)
13436                         XtRealloc( (char *) stnew->bstat ,
13437                                    sizeof(THD_brick_stats) * nvnew ) ;
13438    }
13439 
13440    for( ibr=0 ; ibr < nvnew ; ibr++ ){
13441       if( ibr < nvold )
13442          stnew->bstat[ibr] = stold->bstat[ibr] ;
13443       else
13444          INVALIDATE_BSTAT(stnew->bstat[ibr]) ;
13445    }
13446 
13447    EXRETURN ;
13448 }
13449 
13450 /*-----------------------------------------------------------------*/
13451 
13452 void AFNI_set_cursor( int cursor_code )
13453 {
13454    Three_D_View *im3d ;
13455    int id ;
13456 
13457 ENTRY("AFNI_set_cursor") ;
13458 
13459    for( id=0 ; id < MAX_CONTROLLERS ; id++ ){
13460       im3d = GLOBAL_library.controllers[id] ;
13461       if( IM3D_OPEN(im3d) ){
13462          switch( cursor_code ){
13463 
13464             default:
13465             case AFNI_DEFAULT_CURSOR:
13466                NORMAL_cursorize( im3d->vwid->top_shell ) ;
13467 
13468                if( ISQ_REALZ(im3d->s123) )
13469                   NORMAL_cursorize( im3d->s123->wtop ) ;
13470 
13471                if( ISQ_REALZ(im3d->s231) )
13472                   NORMAL_cursorize( im3d->s231->wtop ) ;
13473 
13474                if( ISQ_REALZ(im3d->s312) )
13475                   NORMAL_cursorize( im3d->s312->wtop ) ;
13476 
13477                if( GRA_REALZ(im3d->g123) )
13478                   NORMAL_cursorize( im3d->g123->fdw_graph ) ;
13479 
13480                if( GRA_REALZ(im3d->g231) )
13481                   NORMAL_cursorize( im3d->g231->fdw_graph ) ;
13482 
13483                if( GRA_REALZ(im3d->g312) )
13484                   NORMAL_cursorize( im3d->g312->fdw_graph ) ;
13485 
13486                if( im3d->vinfo->inverted_pause ){
13487                   im3d->vinfo->inverted_pause = False ;
13488                   if( im3d->vwid->picture != NULL ){
13489                      if( !GLOBAL_argopt.keep_logo ) PICTURE_OFF(im3d) ;
13490                   } else
13491                      MCW_invert_widget( im3d->vwid->top_form ) ;
13492                }
13493 
13494                break ;
13495 
13496             case AFNI_WAITING_CURSOR:
13497                WATCH_cursorize( im3d->vwid->top_shell ) ;
13498 
13499                if( ISQ_REALZ(im3d->s123) )
13500                   WATCH_cursorize( im3d->s123->wtop ) ;
13501 
13502                if( ISQ_REALZ(im3d->s231) )
13503                   WATCH_cursorize( im3d->s231->wtop ) ;
13504 
13505                if( ISQ_REALZ(im3d->s312) )
13506                   WATCH_cursorize( im3d->s312->wtop ) ;
13507 
13508                if( GRA_REALZ(im3d->g123) )
13509                   WATCH_cursorize( im3d->g123->fdw_graph ) ;
13510 
13511                if( GRA_REALZ(im3d->g231) )
13512                   WATCH_cursorize( im3d->g231->fdw_graph ) ;
13513 
13514                if( GRA_REALZ(im3d->g312) )
13515                   WATCH_cursorize( im3d->g312->fdw_graph ) ;
13516 
13517                if( ! im3d->vinfo->inverted_pause ){
13518                   im3d->vinfo->inverted_pause = True ;
13519                   if( im3d->vwid->picture != NULL )
13520                      PICTURE_ON(im3d) ;
13521                   else
13522                      MCW_invert_widget( im3d->vwid->top_form ) ;
13523                }
13524 
13525                break ;
13526          }
13527 
13528          XSync( XtDisplay(im3d->vwid->top_shell) , False ) ;
13529          XmUpdateDisplay( im3d->vwid->top_shell ) ;
13530       }
13531    }
13532 
13533    EXRETURN ;
13534 }
13535 
13536 /****************************************************************/
13537 /***** June 1995: routine to load constants from X defaults *****/
13538 /***** June 1999: also allow loading from Unix environment  *****/
13539 
13540 #if 0
13541 # define NAME2INT(nnn,iii,bot,top)           \
13542   { xdef = XGetDefault(display,"AFNI",nnn) ; \
13543     if( xdef != NULL ){                      \
13544        ival = strtol( xdef , &cpt , 10 ) ;   \
13545        if( *cpt == '\0' && ival >= (bot) && ival <= (top) ) (iii) = ival ; } }
13546 
13547 # define NAME2FLOAT(nnn,fff,bot,top)         \
13548   { xdef = XGetDefault(display,"AFNI",nnn) ; \
13549     if( xdef != NULL ){                      \
13550        fval = strtod( xdef , &cpt ) ;        \
13551        if( *cpt == '\0' && fval >= (bot) && fval <= (top) ) (fff) = fval ; } }
13552 
13553 # define NAME2STRING(nnn,sss)                \
13554   { xdef = XGetDefault(display,"AFNI",nnn) ; \
13555     if( xdef != NULL ) sss  = XtNewString(xdef) ; }
13556 #else
13557 # define NAME2INT(nnn,iii,bot,top)           \
13558   { xdef = RWC_getname(display,nnn) ;        \
13559     if( xdef != NULL ){                      \
13560        ival = strtol( xdef , &cpt , 10 ) ;   \
13561        if( *cpt == '\0' && ival >= (bot) && ival <= (top) ) (iii) = ival ; } }
13562 
13563 # define NAME2FLOAT(nnn,fff,bot,top)         \
13564   { xdef = RWC_getname(display,nnn) ;        \
13565     if( xdef != NULL ){                      \
13566        fval = strtod( xdef , &cpt ) ;        \
13567        if( *cpt == '\0' && fval >= (bot) && fval <= (top) ) (fff) = fval ; } }
13568 
13569 # define NAME2STRING(nnn,sss)                \
13570   { xdef = RWC_getname(display,nnn) ;        \
13571     if( xdef != NULL ) sss  = XtNewString(xdef) ; }
13572 #endif
13573 
13574 #define BAD -999
13575 
13576 void AFNI_load_defaults( Widget w )
13577 {
13578    char    *xdef ;
13579    Display *display ;
13580    int      ival , ii,jj ;
13581    float    fval ;
13582    char    *cpt ;
13583    char     buf[64] ;
13584    float    pthr[NPANE_MAX+1] ;
13585    int      pov[NPANE_MAX+1] ;
13586 
13587 ENTRY("AFNI_load_defaults") ;
13588 
13589    if( w == NULL ){
13590      ERROR_message("\n** AFNI_load_defaults: NULL input widget") ;
13591      EXRETURN ;
13592    }
13593 
13594    display = XtDisplay( w ) ;
13595 
13596    /** initialize overlay color arrays from defaults **/
13597 
13598    for( ii=0 ; ii < DEFAULT_NCOLOVR ; ii++ ){
13599      INIT_colovr[ii] = XtNewString(INIT_def_colovr[ii]) ;
13600      INIT_labovr[ii] = XtNewString(INIT_def_labovr[ii]) ;
13601    }
13602    for( ; ii < MAX_NCOLOVR ; ii++ )
13603      INIT_colovr[ii] = INIT_labovr[ii] = NULL ;
13604 
13605    /** initialize display and overlay colors **/
13606 
13607    NAME2INT("ncolors",INIT_ngray,3,MAX_COLORS) ;
13608 
13609    NAME2INT("ncolovr",INIT_ncolovr,2,MAX_NCOLOVR) ;
13610 
13611    NAME2FLOAT("gamma",INIT_gamma,0.1,9.9) ;
13612 
13613    for( ii=0 ; ii < INIT_ncolovr ; ii++ ){
13614      sprintf( buf , "ovdef%02d" , ii+1 ) ;
13615      NAME2STRING(buf,INIT_colovr[ii] ) ;
13616 
13617      sprintf( buf , "ovlab%02d" , ii+1 ) ;
13618      NAME2STRING(buf,INIT_labovr[ii] ) ;
13619    }
13620 
13621    NAME2INT("ovcrosshair"      , INIT_crosshair_color,0,INIT_ncolovr) ;
13622    NAME2INT("ovmarksprimary"   , INIT_marks1_color   ,0,INIT_ncolovr) ;
13623    NAME2INT("ovmarkssecondary" , INIT_marks2_color   ,0,INIT_ncolovr) ;
13624    NAME2INT("markssize"        , INIT_marks_size     ,2,MAXOVSIZE   ) ;
13625    NAME2INT("marksgap"         , INIT_marks_gap      ,0,MAXOVSIZE-1 ) ;
13626    NAME2INT("crosshairgap"     , INIT_crosshair_gap  ,0,MAXOVSIZE   ) ;
13627    NAME2INT("bigscroll"        , INIT_bigscroll      ,1,MAXOVSIZE   ) ;
13628 
13629    NAME2INT("graph_boxes_color" ,INIT_GR_boxes_color ,BLUEST_COLOR,INIT_ncolovr) ;
13630    NAME2INT("graph_backg_color" ,INIT_GR_backg_color ,BLUEST_COLOR,INIT_ncolovr) ;
13631    NAME2INT("graph_grid_color"  ,INIT_GR_grid_color  ,BLUEST_COLOR,INIT_ncolovr) ;
13632    NAME2INT("graph_text_color"  ,INIT_GR_text_color  ,BLUEST_COLOR,INIT_ncolovr) ;
13633    NAME2INT("graph_data_color"  ,INIT_GR_data_color  ,BLUEST_COLOR,INIT_ncolovr) ;
13634    NAME2INT("graph_ideal_color" ,INIT_GR_ideal_color ,BLUEST_COLOR,INIT_ncolovr) ;
13635    NAME2INT("graph_ort_color"   ,INIT_GR_ort_color   ,BLUEST_COLOR,INIT_ncolovr) ;
13636    NAME2INT("graph_ignore_color",INIT_GR_ignore_color,BLUEST_COLOR,INIT_ncolovr) ;
13637    NAME2INT("graph_dplot_color" ,INIT_GR_dplot_color ,BLUEST_COLOR,INIT_ncolovr) ;
13638 
13639    NAME2INT("graph_boxes_thick" ,INIT_GR_boxes_thick ,0,1) ;
13640    NAME2INT("graph_grid_thick"  ,INIT_GR_grid_thick  ,0,1) ;
13641    NAME2INT("graph_data_thick"  ,INIT_GR_data_thick  ,0,1) ;
13642    NAME2INT("graph_ideal_thick" ,INIT_GR_ideal_thick ,0,1) ;
13643    NAME2INT("graph_ort_thick"   ,INIT_GR_ort_thick   ,0,1) ;
13644    NAME2INT("graph_dplot_thick" ,INIT_GR_dplot_thick ,0,1) ;
13645 
13646    NAME2INT("graph_ggap"        ,INIT_GR_ggap        ,0,19);         /* 27 May 1999 */
13647    NAME2INT("fim_polort"        ,INIT_fim_polort     ,0,MAX_POLORT); /* 30 May 1999 */
13648    NAME2INT("graph_matrix"      ,INIT_GR_gmat        ,1,MAT_MAX);    /* 10 Feb 2003 */
13649    NAME2INT("graph_gthick"      ,INIT_GR_gthick      ,2,10);         /* 06 Oct 2004 */
13650 
13651    /** initialize other junk **/
13652 
13653    cpt = NULL ;
13654    NAME2STRING( "tlrc_big" , cpt ) ;
13655    if( cpt != NULL ){
13656      INIT_tlrc_big = (strcmp(cpt,"True")==0) ? 1 : 0 ;
13657      XtFree(cpt) ;
13658    }
13659 
13660    cpt = NULL ;
13661    NAME2STRING( "montage_periodic" , cpt ) ;
13662    if( cpt != NULL ){
13663      INIT_montage_periodic = (strcmp(cpt,"True")==0) ? 1 : 0 ;
13664      XtFree(cpt) ;
13665    }
13666 
13667    NAME2INT("fim_ignore",INIT_ignore,0,999) ;
13668 
13669    cpt = NULL ;
13670    NAME2STRING( "purge" , cpt ) ;
13671    if( cpt != NULL ){
13672      INIT_purge = (strcmp(cpt,"True")==0) ? 1 : 0 ;
13673      myXtFree(cpt) ;
13674    }
13675 
13676    NAME2FLOAT("resam_vox",INIT_resam_vox,0.1,4.0) ;
13677    INIT_resam_vox = 0.1 * ( (int)(10*INIT_resam_vox) ) ;
13678 
13679    cpt = NULL ;
13680    NAME2STRING( "resam_anat" , cpt ) ;
13681    if( cpt != NULL ){
13682      for( ii=FIRST_RESAM_TYPE ; ii <= LAST_RESAM_TYPE ; ii++ )
13683        if( strcmp(cpt,RESAM_shortstr[ii]) == 0 ) break ;
13684 
13685      if( ii <= LAST_RESAM_TYPE ) INIT_resam_anat = ii ;
13686      myXtFree(cpt) ;
13687    }
13688 
13689    cpt = NULL ;
13690    NAME2STRING( "resam_func" , cpt ) ;
13691    if( cpt != NULL ){
13692      for( ii=FIRST_RESAM_TYPE ; ii <= LAST_RESAM_TYPE ; ii++ )
13693        if( strcmp(cpt,RESAM_shortstr[ii]) == 0 ) break ;
13694 
13695      if( ii <= LAST_RESAM_TYPE ) INIT_resam_func = ii ;
13696      (char*)myXtFree(cpt) ;
13697    }
13698 
13699    cpt = NULL ;
13700    NAME2STRING( "resam_thr" , cpt ) ;
13701    if( cpt != NULL ){
13702      for( ii=FIRST_RESAM_TYPE ; ii <= LAST_RESAM_TYPE ; ii++ )
13703        if( strcmp(cpt,RESAM_shortstr[ii]) == 0 ) break ;
13704 
13705      if( ii <= LAST_RESAM_TYPE ) INIT_resam_thr = ii ;
13706      myXtFree(cpt) ;
13707    }
13708 
13709    /** initialize pbar panes **/
13710 
13711    cpt = NULL ;
13712    NAME2STRING( "pbar_posfunc" , cpt ) ;
13713    if( cpt != NULL ){
13714      INIT_posfunc = (strcmp(cpt,"True")==0) ? 1 : 0 ;
13715      myXtFree(cpt) ;
13716    }
13717 
13718    cpt = NULL ;
13719    NAME2STRING( "pbar_hide" , cpt ) ;
13720    if( cpt != NULL ){
13721      INIT_panes_hide = (strcmp(cpt,"True")==0) ? 1 : 0 ;
13722      myXtFree(cpt) ;
13723    }
13724 
13725    NAME2INT("pbar_pos_pane_count" , INIT_panes_pos , NPANE_MIN , NPANE_MAX ) ;
13726    NAME2INT("pbar_sgn_pane_count" , INIT_panes_sgn , NPANE_MIN , NPANE_MAX ) ;
13727 
13728    /* start with positive panes */
13729 
13730    for( ii=NPANE_INIT+1 ; ii <= NPANE_MAX ; ii++ ){
13731      fval     = 1.0 / ii ;
13732      pthr[0]  = 1.0 ;
13733      pthr[ii] = 0.0 ;
13734      for( jj=1 ; jj < ii ; jj++ ) pthr[jj] = fval * (ii-jj) ;
13735      for( jj=0 ; jj < ii ; jj++ ) pov[jj]  = (jj % INIT_ncolovr) + 1 ;
13736 
13737      for( jj=0 ; jj <= ii ; jj++ ) INIT_pval_pos[ii][jj] = pthr[jj] ;
13738      for( jj=0 ; jj <  ii ; jj++ ) INIT_ovin_pos[ii][jj] = pov[jj] ;
13739    }
13740 
13741    for( ii=NPANE_MIN ; ii <= NPANE_MAX ; ii++ ){
13742 
13743      for( jj=0 ; jj <= ii ; jj++ ){
13744        sprintf( buf , "pbar_pos_pane%02d_thr%02d" , ii,jj ) ;
13745        pthr[jj] = BAD ;
13746        NAME2FLOAT(buf,pthr[jj],0.0,1.0) ;
13747      }
13748 
13749      for( jj=0 ; jj < ii ; jj++ ){
13750        sprintf( buf , "pbar_pos_pane%02d_ov%02d" , ii,jj ) ;
13751        pov[jj] = BAD ;
13752        NAME2INT(buf,pov[jj],0,INIT_ncolovr) ;
13753      }
13754 
13755      /* check pthr for OK-ness; if not good, skip to next pane count (ii) */
13756 
13757      if( pthr[0] != 1.0 || pthr[jj] != 0.0 ) continue ;
13758      for( jj=1 ; jj <= ii ; jj++ )
13759        if( pthr[jj] == BAD || pthr[jj] >= pthr[jj-1] ) break ;
13760      if( jj <= ii ) continue ;
13761 
13762      /* check pov for OK-ness */
13763 
13764      for( jj=0 ; jj < ii ; jj++ ) if( pov[jj] == BAD ) break ;
13765      if( jj < ii ) continue ;
13766 
13767      /* get to here --> load pthr and pov into arrays */
13768 
13769      for( jj=0 ; jj <= ii ; jj++ ) INIT_pval_pos[ii][jj] = pthr[jj] ;
13770      for( jj=0 ; jj <  ii ; jj++ ) INIT_ovin_pos[ii][jj] = pov[jj] ;
13771 
13772    }
13773 
13774    /** initialize signed pbar panes **/
13775 
13776    for( ii=NPANE_INIT+1 ; ii <= NPANE_MAX ; ii++ ){
13777      fval     =  1.0 / ii ;
13778      pthr[0]  =  1.0 ;
13779      pthr[ii] = -1.0 ;
13780      for( jj=1 ; jj < ii ; jj++ ) pthr[jj] = fval * (ii-2*jj) ;
13781      for( jj=0 ; jj < ii ; jj++ ) pov[jj]  = (jj % INIT_ncolovr) + 1 ;
13782 
13783      for( jj=0 ; jj <= ii ; jj++ ) INIT_pval_sgn[ii][jj] = pthr[jj] ;
13784      for( jj=0 ; jj <  ii ; jj++ ) INIT_ovin_sgn[ii][jj] = pov[jj] ;
13785    }
13786 
13787    for( ii=NPANE_MIN ; ii <= NPANE_MAX ; ii++ ){
13788 
13789      for( jj=0 ; jj <= ii ; jj++ ){
13790        sprintf( buf , "pbar_sgn_pane%02d_thr%02d" , ii,jj ) ;
13791        pthr[jj] = BAD ;
13792        NAME2FLOAT(buf,pthr[jj],-1.0,1.0) ; /* 14 Apr 1999: 0.0 changed to -1.0! */
13793      }
13794 
13795      for( jj=0 ; jj < ii ; jj++ ){
13796        sprintf( buf , "pbar_sgn_pane%02d_ov%02d" , ii,jj ) ;
13797        pov[jj] = BAD ;
13798        NAME2INT(buf,pov[jj],0,INIT_ncolovr) ;
13799      }
13800 
13801      /* check pthr for OK-ness; if not good, skip to next pane count (ii) */
13802 
13803      if( pthr[0] != 1.0 || pthr[jj] != -1.0 ) continue ;
13804      for( jj=1 ; jj <= ii ; jj++ )
13805        if( pthr[jj] == BAD || pthr[jj] >= pthr[jj-1] ) break ;
13806      if( jj <= ii ) continue ;
13807 
13808      /* check pov for OK-ness */
13809 
13810      for( jj=0 ; jj < ii ; jj++ ) if( pov[jj] == BAD ) break ;
13811      if( jj < ii ) continue ;
13812 
13813      /* get to here --> load pthr and pov into arrays */
13814 
13815      for( jj=0 ; jj <= ii ; jj++ ) INIT_pval_sgn[ii][jj] = pthr[jj] ;
13816      for( jj=0 ; jj <  ii ; jj++ ) INIT_ovin_sgn[ii][jj] = pov[jj] ;
13817 
13818    }
13819 
13820    /* 10 Jun 2002: put RGB cyclic maps in place */
13821 
13822 #if defined(RGBCYC_COUNT) && RGBCYC_COUNT <= NPANE_MAX
13823    ii = RGBCYC_COUNT ;
13824    for( jj=0 ; jj < ii ; jj++ ) INIT_ovin_pos[ii][jj] = RGBCYC_FIRST+jj+1 ;
13825    for( jj=0 ; jj < ii ; jj++ ) INIT_ovin_sgn[ii][jj] = RGBCYC_FIRST+jj+1 ;
13826 #endif
13827 
13828    EXRETURN ;
13829 }
13830 
13831 /********************************************************************/
13832 #ifdef USE_SONNETS
13833 
13834 void AFNI_popup_sonnet( Widget w , int ii )  /* 12 Dec 2001 */
13835 {
13836    char buf[3192] ; int jj=MCW_USER_KILL ;
13837 
13838    if( w == NULL ) return ;
13839 
13840    if( ii < 1 || ii > NUM_SONNETS ){
13841       ii  = (lrand48()%NUM_SONNETS) + 1 ;
13842       jj |= MCW_TIMER_KILL ;
13843    }
13844 
13845    sprintf( buf , "                    * %d *\n" , ii ) ;
13846    strcat( buf , sonnets[ii-1] ) ;
13847    (void) MCW_popup_message( w , buf , jj ) ;
13848    return ;
13849 }
13850 
13851 /*..................................................................*/
13852 
13853 void AFNI_sonnet_CB( Widget w , XtPointer client_data , XtPointer call_data )
13854 {
13855    Three_D_View *im3d = (Three_D_View *) client_data ;
13856    MCW_choose_cbs *cbs ;
13857 
13858    if( NO_frivolities || !IM3D_OPEN(im3d) ) return ;
13859 
13860    if( w == im3d->vwid->prog->hidden_sonnet_pb ){  /* start the process */
13861 
13862       MCW_choose_integer( im3d->vwid->picture ,
13863                           "Sonnet " ,
13864                           1 , NUM_SONNETS , sonnet_index+1 ,
13865                           AFNI_sonnet_CB , (XtPointer) im3d ) ;
13866       return ;
13867    }
13868 
13869    /** if get to here, finish the process **/
13870 
13871    cbs = (MCW_choose_cbs *) call_data ;
13872    if( cbs->reason != mcwCR_integer ){  /* error */
13873       BEEPIT ; return ;
13874    }
13875 
13876    AFNI_popup_sonnet( im3d->vwid->picture , cbs->ival ) ;
13877    return ;
13878 }
13879 #endif /* USE_SONNETS */
13880 /********************************************************************/
13881 
13882 /*----------------------------------------------------------------------*/
13883 /*! Put a function on the list of n-dimensional transformations
13884      - modified 03 Nov 1996 from just 0D transforms
13885      - modified 22 Apr 1997 to add int flags to each function
13886      - modified 31 Jan 2002 to add slice_proj for nd=-1
13887      - modified 21 Jul 2003 to add func_init
13888 ------------------------------------------------------------------------*/
13889 
13890 void AFNI_register_nD_function( int nd, char *name,
13891                                 generic_func *func, int flags )
13892 {
13893    MCW_function_list *rlist ;
13894    int num ;
13895 
13896    if( name == NULL || strlen(name) == 0 || func == NULL ) return ;
13897 
13898    switch( nd ){
13899       default: return ;
13900 
13901       case 0: rlist = &(GLOBAL_library.registered_0D) ; break ;
13902       case 1: rlist = &(GLOBAL_library.registered_1D) ; break ;
13903       case 2: rlist = &(GLOBAL_library.registered_2D) ; break ;
13904 
13905       case -1: rlist= &(GLOBAL_library.registered_slice_proj) ; break ;
13906    }
13907 
13908    num = rlist->num ;
13909 
13910    if( num == 0 ){
13911      rlist->flags=NULL; rlist->labels=NULL; rlist->funcs=NULL;
13912      rlist->func_data=NULL; rlist->func_code=NULL; rlist->func_init=NULL;
13913    }
13914 
13915    rlist->flags = (int *) XtRealloc( (char *)rlist->flags, sizeof(int)*(num+1) ) ;
13916 
13917    rlist->labels = (char **) XtRealloc( (char *)rlist->labels ,
13918                                         sizeof(char *)*(num+1) ) ;
13919 
13920    rlist->funcs = (generic_func **) XtRealloc( (char *)rlist->funcs ,
13921                                                sizeof(generic_func *)*(num+1) ) ;
13922 
13923    rlist->func_data = (void **) XtRealloc( (char *)rlist->func_data ,
13924                                            sizeof(void *)*(num+1) ) ;
13925 
13926    rlist->func_code = (int *) XtRealloc( (char *)rlist->func_code, sizeof(int)*(num+1) ) ;
13927 
13928    rlist->func_init = (generic_func **) XtRealloc( (char *)rlist->func_init ,
13929                                                    sizeof(generic_func *)*(num+1) ) ;
13930 
13931    rlist->flags[num]     = flags ;
13932    rlist->labels[num]    = XtNewString(name) ;
13933    rlist->funcs[num]     = func ;
13934    rlist->func_data[num] = NULL ;
13935    rlist->func_code[num] = nd ;
13936    rlist->func_init[num] = NULL ;
13937 
13938    rlist->num = num+1 ;
13939    return ;
13940 }
13941 
13942 /*-------------------------------------------------------------------------*/
13943 /*! Add init function to last registered function. This function
13944     should be called just after AFNI_register_nD_function(). [21 Jul 2003] */
13945 
13946 void AFNI_register_nD_func_init( int nd , generic_func *fin )
13947 {
13948    MCW_function_list *rlist ;
13949    int num ;
13950 
13951    if( fin == NULL ) return ;
13952 
13953    switch( nd ){
13954       default: return ;
13955 
13956       case 0: rlist = &(GLOBAL_library.registered_0D) ; break ;
13957       case 1: rlist = &(GLOBAL_library.registered_1D) ; break ;
13958       case 2: rlist = &(GLOBAL_library.registered_2D) ; break ;
13959 
13960       case -1: rlist= &(GLOBAL_library.registered_slice_proj) ; break ;
13961    }
13962 
13963    num = rlist->num ; if( num <= 0 ) return ;
13964    rlist->func_init[num-1] = fin ;
13965    return ;
13966 }
13967 
13968 #if 0
13969 /*---------- 18 May 2000: save/get dataset index for function calls -------*/
13970 
13971 static int dset_ijk=-1 , dset_tin=-1 ;
13972 
13973 void AFNI_store_dset_index( int ijk , int tin )
13974 {
13975    dset_ijk = ijk ; dset_tin = tin ; return ;
13976 }
13977 
13978 int AFNI_needs_dset_ijk(void){ return dset_ijk ; }
13979 int AFNI_needs_dset_tin(void){ return dset_tin ; }
13980 #endif
13981 
13982 /*-----------------------------------------------------------------------*/
13983 /*!  Add a timeseries to the global library.
13984 *//*---------------------------------------------------------------------*/
13985 
13986 void AFNI_add_timeseries( MRI_IMAGE *tsim )
13987 {
13988 ENTRY("AFNI_add_timeseries") ;
13989 
13990    if( tsim != NULL ){
13991       POPDOWN_timeseries_chooser ;
13992       ADDTO_IMARR(GLOBAL_library.timeseries,tsim) ;
13993    }
13994    EXRETURN ;
13995 }
13996 
13997 /*-----------------------------------------------------------------------*/
13998 /* N.B.: The input time series structure is destroyed!
13999          Never refer to it again, even to free() it!
14000 *//*---------------------------------------------------------------------*/
14001 
14002 void AFNI_replace_timeseries( MRI_IMAGE *tsim )
14003 {
14004    int its ; MRI_IMAGE *qsim ;
14005 
14006 ENTRY("AFNI_replace_timeseries") ;
14007 
14008    if( tsim == NULL ) EXRETURN ;
14009 
14010    its = AFNI_tsname_in_library( tsim->name ) ;
14011    if( its < 0 ){
14012     AFNI_add_timeseries(tsim); EXRETURN;
14013    }
14014 
14015    POPDOWN_timeseries_chooser ;
14016    qsim = IMARR_SUBIMAGE(GLOBAL_library.timeseries,its) ;
14017    mri_move_guts( qsim , tsim ) ;
14018    mri_free(tsim) ;
14019    EXRETURN ;
14020 }
14021 
14022 /*------------------------------------------------------------------------*/
14023 /*** New fix for scale size problem
14024      - via a timeout, to avoid excessive flashing of the scale widget
14025      - 03 Jun 2019 [RWC in Lucca]
14026      - 05 Jun 2019 - modified to a fixed timeout every so often
14027 ***/
14028 /*------------------------------------------------------------------------*/
14029 
14030 void AFNI_fix_scale_size_direct( Three_D_View *im3d )
14031 {
14032    int iqqq = AFNI_controller_index(im3d) ;
14033    int sel_height,sel_actual ;  XtPointer sel_ptr=NULL ;
14034    Dimension sel_aaa ;
14035 
14036    if( iqqq < 0 || ! IM3D_OPEN(im3d) ) return ; /* not valid */
14037 
14038    if( AFNI_yesenv("AFNI_DONT_FIX_SCALE_SIZE") ) return ; /* obey orders */
14039 
14040    /* check if height is correct */
14041 
14042    XtVaGetValues( im3d->vwid->func->thr_scale ,
14043                   XmNuserData , &sel_ptr , NULL ) ;
14044    sel_height = PTOI(sel_ptr) ; /* stored in a pointer, convert to int */
14045 
14046    XtVaGetValues( im3d->vwid->func->thr_scale ,
14047                   XmNheight , &sel_aaa , NULL ) ;
14048    sel_actual = (int)sel_aaa ;
14049 
14050    /**** INFO_message("actual = %d  nominal = %d",sel_actual,sel_height) ; ****/
14051 
14052    if( sel_actual == sel_height ) return ;  /* it's OK */
14053 
14054    /* do the work */
14055 
14056    XtUnmanageChild(im3d->vwid->func->thr_scale) ; AFNI_sleep(1) ;
14057 
14058    XtVaSetValues( im3d->vwid->func->thr_scale ,
14059                   XmNheight , sel_height , NULL ) ;
14060 
14061    XtManageChild(im3d->vwid->func->thr_scale) ;
14062 
14063    return ;
14064 }
14065 
14066 #undef  FIX_TIME
14067 #define FIX_TIME 1357  /* ms between calls */
14068 
14069 void AFNI_fix_scale_size_timer_CB( XtPointer client_data , XtIntervalId *id )
14070 {
14071    Three_D_View *im3d ;
14072    int iqqq ;
14073    int sel_height,sel_actual ;  XtPointer sel_ptr=NULL ;
14074 
14075    for( iqqq=0 ; iqqq < MAX_CONTROLLERS ; iqqq++ ){
14076      AFNI_fix_scale_size_direct(GLOBAL_library.controllers[iqqq]) ;
14077    }
14078 
14079    (void) XtAppAddTimeOut( MAIN_app , FIX_TIME ,
14080                            AFNI_fix_scale_size_timer_CB , NULL ) ;
14081 
14082    return ;
14083 }
14084 
14085 /* 04/06/2020 discoraj */
14086 int AFNI_find_session( char *dname ) {
14087 
14088     int ic ;
14089     /* find session name in list of sessions (sloppy compare) */
14090     for( ic=0 ; ic < GLOBAL_library.sslist->num_sess ; ic++ )
14091        if( strstr(GLOBAL_library.sslist->ssar[ic]->sessname,dname) != NULL )
14092         break;
14093 
14094     if( ic == GLOBAL_library.sslist->num_sess ) RETURN(-1) ;
14095 
14096     return ic ;
14097 }
14098