1 /*****************************************************************************
2 Major portions of this software are copyrighted by the Medical College
3 of Wisconsin, 1994-2000, and are released under the Gnu General Public
4 License, Version 2. See the file README.Copyright for details.
5 ******************************************************************************/
6
7 #undef MAIN
8 #include "afni.h"
9
10 #include "mcw_graf.h"
11 #include "parser.h"
12 #include "whats_my_exepath.h"
13 /*========================================================================*/
14 /*==== Compile this only if plugins are properly enabled in machdep.h ====*/
15
16 #ifdef ALLOW_PLUGINS
17
18 #define EMPTY_STRING "\0"
19
20 #define COLSIZE AV_colsize()
21
22 static Widget wtemp ;
23
24 /***************************************************************************
25 Routines to open and initialize plugins. These should only
26 be called at the very end of AFNI initialization, since they
27 will call each plugin's internal initializer function, which
28 may make requests to get AFNI data structures.
29 ****************************************************************************/
30
31 /*================ dynamic loading of plugins is allowed ==================*/
32 #ifndef NO_DYNAMIC_LOADING
33
34 /*-------------------------------------------------------------------------
35 Routine to read in all plugins found in a given directory
36 ---------------------------------------------------------------------------*/
37
PLUG_get_all_plugins(char * dname)38 AFNI_plugin_array * PLUG_get_all_plugins( char * dname )
39 {
40 THD_string_array * flist , * rlist ;
41 int ir , ii ;
42 char * fname , * suff ;
43 AFNI_plugin_array * outar ;
44 AFNI_plugin * plin ;
45
46 /*----- sanity check and initialize -----*/
47
48 ENTRY("PLUG_get_all_plugins") ;
49
50 if( dname == NULL || strlen(dname) == 0 ) RETURN(NULL) ;
51 if( ! THD_is_directory(dname) ) RETURN(NULL) ;
52
53 INIT_PLUGIN_ARRAY( outar ) ;
54
55 if(PRINT_TRACING)
56 { char str[256] ; sprintf(str,"scanning directory %s",dname) ; STATUS(str) ; }
57
58 /*----- find all filenames -----*/
59
60 flist = THD_get_all_filenames( dname ) ;
61 if( flist == NULL || flist->num <= 0 ){
62 DESTROY_SARR(flist) ;
63 DESTROY_PLUGIN_ARRAY(outar) ;
64 RETURN(NULL) ;
65 }
66
67 rlist = THD_extract_regular_files( flist ) ;
68 DESTROY_SARR(flist) ;
69 if( rlist == NULL || rlist->num <= 0 ){
70 DESTROY_SARR(rlist) ;
71 DESTROY_PLUGIN_ARRAY(outar) ;
72 RETURN(NULL) ;
73 }
74
75 if(PRINT_TRACING)
76 { char str[256] ; sprintf(str,"%d files to scan",rlist->num) ; STATUS(str) ; }
77
78 /*----- scan thru and find all filenames ending in DYNAMIC_suffix -----*/
79
80 for( ir=0 ; ir < rlist->num ; ir++ ){
81 fname = rlist->ar[ir] ; if( fname == NULL ) continue ;
82 if( strstr(fname,"plug") == NULL ) continue ;
83 if( strstr(fname,"plug_nlfit.") != NULL ) continue ; /* 13 Jul 2020 */
84
85 suff = strstr(fname,DYNAMIC_suffix) ;
86 if( suff != NULL && strlen(suff) == strlen(DYNAMIC_suffix) ){
87 plin = PLUG_read_plugin( fname ) ;
88 if( plin != NULL ) ADDTO_PLUGIN_ARRAY( outar , plin ) ;
89 }
90 }
91
92 if(PRINT_TRACING)
93 { char str[256] ;
94 sprintf(str,"directory %s has %d plugins",dname,outar->num) ; STATUS(str) ; }
95
96 DESTROY_SARR(rlist) ;
97 if( outar->num == 0 ) DESTROY_PLUGIN_ARRAY(outar) ;
98
99 /* 06 Aug 1999: sort array by seqcodes */
100
101 if( outar != NULL && outar->num > 1 ){
102 int iid , qq ; AFNI_plugin * plin ;
103 do{ qq = 0 ;
104 for( iid=1 ; iid < outar->num ; iid++ )
105 if( strcmp(outar->plar[iid-1]->seqcode,
106 outar->plar[iid ]->seqcode ) > 0 ){
107
108 plin = outar->plar[iid-1] ;
109 outar->plar[iid-1] = outar->plar[iid] ;
110 outar->plar[iid] = plin ;
111 qq++ ;
112 }
113 } while( qq > 0 ) ;
114 }
115
116 RETURN(outar) ;
117 }
118
119 /*----------------------------------------------------------------------
120 Routine to open and initialize a single plugin
121 ------------------------------------------------------------------------*/
122
PLUG_read_plugin(char * fname)123 AFNI_plugin * PLUG_read_plugin( char *fname )
124 {
125 AFNI_plugin *plin ;
126 PLUGIN_interface *plint=NULL ;
127 int nin ;
128 static int firsterr=1 ;
129
130 /*----- sanity checks -----*/
131
132 ENTRY("PLUG_read_plugin") ;
133
134 if( fname == NULL || strlen(fname) == 0 ) RETURN(NULL) ;
135 if( ! THD_is_file(fname) ) RETURN(NULL) ;
136
137 /*----- make space for new plugin -----*/
138
139 plin = (AFNI_plugin *) XtMalloc( sizeof(AFNI_plugin) ) ;
140 memset(plin, 0, sizeof(AFNI_plugin)) ; /* 11 Feb 2009 [lesstif patrol] */
141 plin->type = AFNI_PLUGIN_TYPE ;
142
143 /*----- copy name into plin structure -----*/
144
145 MCW_strncpy( plin->libname , fname , MAX_PLUGIN_NAME ) ;
146
147 /*----- open the library (we hope) -----*/
148
149 if(PRINT_TRACING)
150 { char str[256] ;
151 sprintf(str,"opening plugin %s" , fname ) ; STATUS(str) ; }
152
153 DYNAMIC_OPEN( fname , plin->libhandle ) ;
154
155 STATUS("returned from DYNAMIC_OPEN()") ;
156
157 if( ! ISVALID_DYNAMIC_handle( plin->libhandle ) ){ /* open failed */
158
159 /* 24 May 2001: always print if there is an error */
160
161 char *er ;
162 if( firsterr ){fprintf(stderr,"\n"); firsterr=0; }
163 fprintf(stderr,"Failed to open plugin %s",fname) ;
164 er = (char *)DYNAMIC_ERROR_STRING ;
165 if( er != NULL ) fprintf(stderr," -- %s\n",er) ;
166 else fprintf(stderr,"\n") ;
167
168 myXtFree(plin) ; RETURN(NULL) ;
169 }
170
171 /* open was good */
172
173 if(PRINT_TRACING)
174 { char str[256] ;
175 sprintf(str,"opened library %s with handle %p" , fname,plin->libhandle ) ;
176 STATUS(str) ; }
177
178 /*----- find the required symbol -----*/
179 /*..... 13 Sep 2001: add _ for stupid Darwin .....*/
180 /*..... 30 Oct 2003: remove for OS X 10.3 .....*/
181
182 #ifndef NEED_UNDERSCORE
183 DYNAMIC_SYMBOL(plin->libhandle, "PLUGIN_init" , plin->libinit_func );
184 #else
185 DYNAMIC_SYMBOL(plin->libhandle,"_PLUGIN_init" , plin->libinit_func );
186 #endif
187
188 /*----- if symbol not found, complain and kill this plugin -----*/
189
190 if( plin->libinit_func == (vptr_func *) NULL ){
191 char *er = (char *)DYNAMIC_ERROR_STRING ;
192 if( firsterr ){fprintf(stderr,"\n"); firsterr=0; }
193 fprintf(stderr,"plugin %s lacks PLUGIN_init() function\n",fname) ;
194 if( er != NULL ) fprintf(stderr," -- %s\n",er) ;
195 DYNAMIC_CLOSE( plin->libhandle ) ;
196 myXtFree(plin) ;
197 RETURN(NULL) ;
198 }
199
200 /*----- create interface(s) by calling initialization function -----*/
201
202 plin->interface_count = nin = 0 ;
203 plin->interface = NULL ;
204
205 #ifdef AFNI_DEBUG
206 MCHECK ;
207 #else
208 MPROBE ;
209 #endif
210
211 do {
212 #if 0
213 plint = (PLUGIN_interface *) plin->libinit_func( nin ) ;
214 #else
215 AFNI_CALL_VALU_1ARG(plin->libinit_func ,
216 PLUGIN_interface *,plint , int,nin ) ;
217 #endif
218 if( plint == NULL ) break ;
219
220 plin->interface = (PLUGIN_interface **)
221 XtRealloc( (char *) plin->interface ,
222 sizeof(PLUGIN_interface *) * (nin+1) ) ;
223
224 plin->interface[nin] = plint ;
225 if( nin == 0 ) strcpy( plin->seqcode , plint->seqcode ) ; /* 06 Aug 1999 */
226 nin++ ;
227 } while( plint != NULL ) ;
228
229 plin->interface_count = nin ;
230
231 #if 1
232 if( nin > 0 ){ /* 01 Nov 1999 */
233 char * bcol , benv[256] ;
234 int ii = strlen(DYNAMIC_suffix) , jj ;
235
236 strcpy(benv,"AFNI_") ; strcat(benv,THD_trailname(fname,0)) ; /* make */
237 jj = strlen(benv) ; benv[jj-ii] = '\0' ; /* name */
238 strcat(benv,"_butcolor") ;
239 bcol = my_getenv(benv) ; /* find name */
240 if( bcol != NULL ){ /* if have name: */
241 for( ii=0 ; ii < nin ; ii++ ){
242 plint = plin->interface[ii] ;
243 if( plint->butcolor[0] == '\0' ) /* set color if */
244 PLUTO_set_butcolor( plint , bcol ) ; /* not defined */
245 }
246 }
247 }
248 #endif
249
250 if(PRINT_TRACING)
251 { char str[256] ;
252 sprintf(str,"library %s created %d interfaces",fname,nin) ; STATUS(str) ; }
253
254 /*----- done -----*/
255
256 RETURN(plin) ;
257 }
258
259 /*--------------------------------------------------------------------
260 Routine to read in all plugins in the desired list of directories
261 29 Mar 2001: pname = argv[0] = potential program name
262 ----------------------------------------------------------------------*/
263
264 #ifdef DARWIN
265 #include <mach-o/dyld.h>
266 /* extern unsigned long _dyld_present(void); */
267 #endif
268
PLUG_get_many_plugins(char * pname)269 AFNI_plugin_array * PLUG_get_many_plugins(char *pname)
270 {
271 char * epath , * elocal , * eee ;
272 char ename[THD_MAX_NAME] ;
273 AFNI_plugin_array * outar , * tmpar ;
274 int epos , ll , ii , id ;
275 THD_string_array *qlist ; /* 02 Feb 2002 */
276 #ifdef DARWIN
277 int size = PATH_MAX;
278 #else
279 int size = THD_MAX_NAME;
280 #endif
281 char *exe_path=NULL, *exe_dir=NULL, *lib_dir=NULL;
282
283
284 /*----- sanity checks -----*/
285
286 ENTRY("PLUG_get_many_plugins") ;
287
288 /**
289 #if defined(DARWIN) && !defined(c_plusplus) && !defined(__cplusplus)
290 **/
291 #if 0 /* formerly ifdef DARWIN */
292 if( _dyld_present() == 0 ) RETURN(NULL) ; /* 05 Sep 2001: Mac OSX */
293 #endif
294
295 epath = getenv("AFNI_PLUGINPATH") ; /* get the path list to read from */
296
297 if( epath == NULL )
298 epath = getenv("AFNI_PLUGIN_PATH") ; /* try another name? */
299
300 if( epath == NULL ) {
301 exe_path = (char *)malloc(sizeof(char)*size);
302 if( whats_my_exepath(exe_path, size) ) {
303 fprintf(stderr,"** failure\n");
304 RETURN(NULL);
305 }
306 exe_dir = strdup(dirname(exe_path)) ;
307 /* contents of exe_path not guaranteed */
308 free(exe_path) ;
309
310 /* get possible lib directory for alternative installation pattern */
311 lib_dir = malloc(strlen(exe_dir)+64) ;
312 strcpy(lib_dir,exe_dir) ; strcat(lib_dir,"/../lib") ;
313
314 /* use putative bin and lib dirs to search for plugins */
315 epath = (char *)malloc(size) ;
316 strcpy(epath,exe_dir) ;
317 free(exe_dir) ;
318
319 strcat(strcat(epath," "),lib_dir) ;
320 free(lib_dir) ;
321 }
322
323 if( epath == NULL && pname != NULL && strchr(pname,'/') != NULL ){ /* 29 Mar 2001 */
324 char *ep = strdup(pname) ; /* get path */
325 char *tp = THD_trailname(ep,0) ; /* to program */
326 *tp = '\0' ;
327 if( strlen(ep) > 0 ) epath = ep ; /* got some path */
328 else free(ep) ; /* got zipperoni */
329 }
330
331 if( epath == NULL ) /* abandon plugin search */
332 RETURN(NULL) ;
333
334 INIT_SARR(qlist) ; /* 02 Feb 2002: list of checked directories */
335
336 /*----- copy path list into local memory -----*/
337
338 ll = strlen(epath) ;
339 elocal = (char *) XtMalloc( sizeof(char) * (ll+2) ) ;
340
341 /*----- put a blank at the end -----*/
342
343 strcpy( elocal , epath ) ; elocal[ll] = ' ' ; elocal[ll+1] = '\0' ;
344
345 /*----- replace colons with blanks -----*/
346
347 for( ii=0 ; ii < ll ; ii++ )
348 if( elocal[ii] == ':' ) elocal[ii] = ' ' ;
349
350 printf("\nPath(s) to be searched for plugins: \n%s\n",elocal) ;
351 fflush(stdout) ;
352
353 /*----- extract blank delimited strings;
354 use as directory names to get libraries -----*/
355
356 INIT_PLUGIN_ARRAY( outar ) ;
357 epos = 0 ;
358
359 do{
360 ii = sscanf( elocal+epos , "%s%n" , ename , &id ) ; /* next substring */
361 if( ii < 1 || id < 1 ) break ; /* none --> end of work */
362 epos += id ; /* char after last scanned */
363
364 if( !THD_is_directory(ename) ) continue ; /* 21 May 2002 -rcr */
365
366 /* 02 Feb 2002: did we check this one already? */
367
368 for( ii=0 ; ii < qlist->num ; ii++ )
369 if( THD_equiv_files(qlist->ar[ii],ename) ) break ;
370 if( ii < qlist->num ) continue ;
371 ADDTO_SARR(qlist,ename) ;
372
373 ii = strlen(ename) ; /* make sure name has */
374 if( ename[ii-1] != '/' ){ /* a trailing '/' on it */
375 ename[ii] = '/' ; ename[ii+1] = '\0' ;
376 }
377
378 tmpar = PLUG_get_all_plugins( ename ) ; /* read this directory */
379 if( tmpar != NULL ){
380 for( ii=0 ; ii < tmpar->num ; ii++ ) /* move results to output */
381 ADDTO_PLUGIN_ARRAY( outar , tmpar->plar[ii] ) ;
382
383 FREE_PLUGIN_ARRAY(tmpar) ; /* toss temp array */
384 }
385 } while( epos < ll ) ; /* scan until 'epos' is after end of epath */
386
387 myXtFree(elocal) ;
388
389 if(PRINT_TRACING)
390 { char str[256] ; sprintf(str,"found %d plugins",outar->num) ; STATUS(str) ; }
391
392 if( outar->num == 0 ) DESTROY_PLUGIN_ARRAY(outar) ;
393 DESTROY_SARR(qlist) ; /* 02 Feb 2002 */
394 RETURN(outar) ;
395 }
396
397 /*=================== Plugins are statically linked into AFNI ===================*/
398
399 #else /* NO_DYNAMIC_LOADING is defined (e.g., CYGWIN) */
400
401 /* get the list of fixed (compiled-in) plugins */
402
403 #include "fixed_plugins.h"
404
405 /*-------------------------------------------------------------------------------*/
406 /*! Function to load one fixed plugin (for CYGWIN) */
407
PLUG_load_fixed_plugin(FIXED_plugin pin)408 AFNI_plugin * PLUG_load_fixed_plugin( FIXED_plugin pin )
409 {
410 AFNI_plugin * plin ;
411 PLUGIN_interface * plint ;
412 int nin ;
413
414 /*----- sanity checks -----*/
415
416 ENTRY("PLUG_load_plugin") ;
417
418 if( pin.pfunc == NULL ) RETURN(NULL) ;
419
420 /*----- make space for new plugin -----*/
421
422 plin = (AFNI_plugin *) XtMalloc( sizeof(AFNI_plugin) ) ;
423 memset(plin, 0, sizeof(AFNI_plugin)) ; /* 11 Feb 2009 [lesstif patrol] */
424 plin->type = AFNI_PLUGIN_TYPE ;
425
426 /*----- copy name into plin structure -----*/
427
428 MCW_strncpy( plin->libname , pin.pname , MAX_PLUGIN_NAME ) ;
429 plin->libinit_func = pin.pfunc ;
430
431 /*----- create interface(s) by calling initialization function -----*/
432
433 plin->interface_count = nin = 0 ;
434 plin->interface = NULL ;
435
436 do {
437 plint = (PLUGIN_interface *) plin->libinit_func( nin ) ;
438 if( plint == NULL ) break ;
439
440 plin->interface = (PLUGIN_interface **)
441 XtRealloc( (char *) plin->interface ,
442 sizeof(PLUGIN_interface *) * (nin+1) ) ;
443
444 plin->interface[nin] = plint ;
445 if( nin == 0 ) strcpy( plin->seqcode , plint->seqcode ) ; /* 06 Aug 1999 */
446 nin++ ;
447 } while( plint != NULL ) ;
448
449 plin->interface_count = nin ;
450
451 /*----- done -----*/
452
453 RETURN(plin) ;
454 }
455
456 /*------------------------------------------------------------------------*/
457 /*! Function to load all fixed plugins (for CYGWIN). pname is ignored. */
458
PLUG_get_many_plugins(char * pname)459 AFNI_plugin_array * PLUG_get_many_plugins(char *pname)
460 {
461 int ir ;
462 AFNI_plugin_array * outar ;
463 AFNI_plugin * plin ;
464
465 /*----- sanity check and initialize -----*/
466
467 ENTRY("PLUG_get_many_plugins") ;
468
469 INIT_PLUGIN_ARRAY( outar ) ;
470
471 /*----- scan thru and create plugins from the fixed list -----*/
472
473 for( ir=0 ; ir < NUM_FIXED_plugin_funcs ; ir++ ){
474 plin = PLUG_load_fixed_plugin( FIXED_plugin_funcs[ir] ) ;
475 if( plin != NULL ) ADDTO_PLUGIN_ARRAY( outar , plin ) ;
476 }
477
478 RETURN(outar) ;
479 }
480
481 #endif /* NO_DYNAMIC_LOADING */
482
483 /*==============================================================================*/
484
485 /****************************************************************************
486 Routines to create interface descriptions for new plugins. Usage:
487 1) Use "new_PLUGIN_interface" to create the initial data structure.
488 2) Use "add_option_to_PLUGIN_interface" to create an option line in the
489 AFNI interface menu. There is no built-in limit to the number
490 of option lines that may be added to an AFNI interface menu.
491 2(abcdef)
492 Use "add_number_to_PLUGIN_interface" , and
493 "add_string_to_PLUGIN_interface" , and
494 "add_dataset_to_PLUGIN_interface" , et cetera,
495 to add control parameter choosers to the most recently created
496 option line. Up to 6 choosers may be added to an option line.
497 3) When done, return the new "PLUGIN_interface *" to AFNI.
498 *****************************************************************************/
499
500 /*--------------------------------------------------------------------------
501 Create a new plugin interface.
502
503 label = C string to go on the button that activates this interface
504 (will be truncated to 15 characters)
505
506 description = C string to go on the interface control panel popped-up
507 when the button above is pressed -- this has no
508 meaning for call_type = PLUGIN_CALL_IMMEDIATELY
509
510 help = C string to be popped up if the user presses "Help" on
511 the interface control panel -- this has no
512 meaning for call_type = PLUGIN_CALL_IMMEDIATELY.
513 If this is NULL, then there will be no help available.
514
515 call_type = int that describes how the plugin is to be called from AFNI:
516 PLUGIN_CALL_IMMEDIATELY means to call APL_main as soon
517 as the activating button is pressed;
518 PLUGIN_CALL_VIA_MENU means to have AFNI popup a menu
519 to control the input parameters passed to APL_main.
520
521 call_func = routine that AFNI should call when the user activates
522 this plugin. The routine will be passed the the
523 pointer "PLUGIN_interface *" created herein, which
524 can be interrogated with the get_*_from_PLUGIN_interface
525 routines. The call_func should return a "char *", which
526 is NULL if everything is OK, and points to an error
527 message that AFNI will display if something bad happened.
528
529 The value returned is the pointer to the new interface struct.
530
531 Note that the three input strings are copied by AFNI, and so could
532 be freed after this routine returns.
533 ----------------------------------------------------------------------------*/
534
new_PLUGIN_interface(char * label,char * description,char * help,int call_type,cptr_func * call_func)535 PLUGIN_interface * new_PLUGIN_interface( char * label , char * description ,
536 char * help ,
537 int call_type , cptr_func * call_func )
538 {
539 PLUGIN_interface * plint ;
540
541 ENTRY("new_PLUGIN_interface") ;
542
543 plint = new_PLUGIN_interface_1999( label , description , help ,
544 call_type , call_func , NULL ) ;
545 RETURN(plint) ;
546 }
547
548 /**** 15 Jun 1999: modified to crosscheck compilation dates ****/
549
550 #include <time.h>
551
new_PLUGIN_interface_1999(char * label,char * description,char * help,int call_type,cptr_func * call_func,char * compile_date)552 PLUGIN_interface * new_PLUGIN_interface_1999( char * label , char * description ,
553 char * help ,
554 int call_type , cptr_func * call_func ,
555 char * compile_date )
556 {
557 PLUGIN_interface * plint ;
558 static int num_date_err = 0 ;
559
560 /*-- sanity check --*/
561
562 ENTRY("new_PLUGIN_interface_1999") ;
563
564 if( label == NULL || strlen(label) == 0 ) RETURN(NULL) ;
565
566 if( !( (call_type == PLUGIN_CALL_IMMEDIATELY) ||
567 (call_type == PLUGIN_CALL_VIA_MENU )
568 ) ) RETURN(NULL) ;
569
570 if( call_func == (cptr_func *) NULL ) RETURN(NULL) ;
571
572 /*-- create new interface --*/
573
574 plint = (PLUGIN_interface *) XtMalloc(sizeof(PLUGIN_interface)) ;
575 if( plint == NULL ) RETURN(NULL) ;
576 memset(plint, 0, sizeof(PLUGIN_interface)) ; /* 11 Feb 2009 [LPatrol] */
577
578 plint->flags = 0 ; /* 29 Mar 2002 */
579
580 MCW_strncpy( plint->label , label , PLUGIN_LABEL_SIZE ) ;
581
582 if( description != NULL )
583 MCW_strncpy( plint->description , description , PLUGIN_STRING_SIZE ) ;
584 else
585 MCW_strncpy( plint->description , label , PLUGIN_STRING_SIZE ) ;
586
587 plint->call_method = call_type ;
588 plint->call_func = call_func ;
589 plint->option_count = 0 ;
590 plint->option = NULL ;
591 plint->wid = NULL ;
592 plint->im3d = NULL ;
593 plint->hint = NULL ;
594 plint->toplabel[0] = '\0' ; /* 13 May 2010 */
595
596 if( help == NULL || strlen(help) == 0 )
597 plint->helpstring = NULL ;
598 else
599 plint->helpstring = XtNewString( help ) ;
600
601 strcpy( plint->seqcode , "zzzzzzz" ) ; /* 06 Aug 1999 */
602 strcpy( plint->butcolor, "\0" ) ; /* 01 Nov 1999 */
603
604 /** 15 Jun 1999 stuff for date checking **/
605
606 #ifndef DONT_USE_STRPTIME
607 if( compile_date == NULL ){
608
609 if( num_date_err == 0 ) fprintf(stderr,"\n") ;
610 fprintf(stderr,
611 "*** Warning: Plugin %-15s was compiled with an earlier version of AFNI\n",
612 label ) ;
613 num_date_err++ ;
614
615 #if 0
616 # define AFNI_DATE "Jun 17 1999" /* for testing purposes */
617 #else
618 # define AFNI_DATE __DATE__
619 #endif
620
621 } else {
622 struct tm compile_tm ={0} , date_tm={0} ;
623 time_t compile_time , date_time ;
624 double date_minus_compile ;
625
626 strptime( compile_date , "%b %d %Y" , &compile_tm ) ; compile_time = mktime( &compile_tm ) ;
627 strptime( AFNI_DATE , "%b %d %Y" , &date_tm ) ; date_time = mktime( &date_tm ) ;
628 date_minus_compile = difftime( date_time , compile_time ) ;
629
630 if( date_minus_compile > 3600.0 ){
631 if( num_date_err == 0 ) fprintf(stderr,"\n") ;
632 fprintf(stderr,
633 "\n*** Warning: Plugin %-15s compile date=%s predates AFNI=%s",
634 label , compile_date , AFNI_DATE ) ;
635 num_date_err++ ;
636 } else if( PRINT_TRACING ){
637 char str[256] ;
638 sprintf(str,"Plugin %-15s compile date=%s AFNI date=%s difftime=%g\n",
639 label , compile_date , AFNI_DATE , date_minus_compile ) ;
640 STATUS(str) ;
641 }
642 }
643 #endif
644
645 plint->run_label[0] = '\0' ; /* 04 Nov 2003 */
646 plint->doit_label[0] = '\0' ;
647
648 plint->wid = NULL ;
649
650 RETURN(plint) ;
651 }
652
653 /*------------------------------------------------------------------------*/
654 /*! Set the "Run+Keep" and "Run+Close" labels for a plugin. [04 Nov 2003] */
655 /*------------------------------------------------------------------------*/
656
PLUTO_set_runlabels(PLUGIN_interface * plint,char * rlab,char * dlab)657 void PLUTO_set_runlabels( PLUGIN_interface *plint , char *rlab , char *dlab )
658 {
659 if( plint == NULL ) return ;
660 if( rlab != NULL ) MCW_strncpy( plint->run_label , rlab, PLUGIN_LABEL_SIZE );
661 if( dlab != NULL ) MCW_strncpy( plint->doit_label, dlab, PLUGIN_LABEL_SIZE );
662 return ;
663 }
664
665 /*----------------------------------------------------------------------
666 Set the seqcode in a plugin, for sorting in the interface.
667 [06 Aug 1999]
668 ------------------------------------------------------------------------*/
669
PLUTO_set_sequence(PLUGIN_interface * plint,char * sq)670 void PLUTO_set_sequence( PLUGIN_interface * plint , char * sq )
671 {
672 ENTRY("PLUTO_set_sequence") ;
673 if( plint == NULL || sq == NULL || sq[0] == '\0' ) EXRETURN ;
674 MCW_strncpy( plint->seqcode , sq , PLUGIN_STRING_SIZE ) ;
675 EXRETURN ;
676 }
677
678 /*----------------------------------------------------------------------
679 Set the button color in a plugin [01 Nov 1999]
680 ------------------------------------------------------------------------*/
681
PLUTO_set_butcolor(PLUGIN_interface * plint,char * sq)682 void PLUTO_set_butcolor( PLUGIN_interface * plint , char * sq )
683 {
684 ENTRY("PLUTO_set_butcolor") ;
685 if( plint == NULL || sq == NULL || sq[0] == '\0' ) EXRETURN ;
686 if( strncmp(sq,"hot",3) == 0 ) sq = MCW_hotcolor(NULL) ;
687 MCW_strncpy( plint->butcolor , sq , PLUGIN_STRING_SIZE ) ;
688 EXRETURN ;
689 }
690
691 /*----------------------------------------------------------------------
692 Change the top level label in a plugin [13 May 2010]
693 ------------------------------------------------------------------------*/
694
PLUTO_set_toplabel(PLUGIN_interface * plint,char * lab)695 void PLUTO_set_toplabel( PLUGIN_interface *plint , char *lab )
696 {
697 ENTRY("PLUTO_set_toplabel") ;
698 if( plint != NULL ){
699 if( plint->wid != NULL )
700 MCW_set_widget_label( plint->wid->label , lab ) ;
701 MCW_strncpy( plint->toplabel , lab , PLUGIN_STRING_SIZE ) ;
702 }
703 EXRETURN ;
704 }
705
706 /*---------------------------------------------------------------------------
707 Routine to add a new option line to a plugin interface menu.
708
709 plint = PLUGIN_interface * which will have the option added
710 label = C string to be displayed in the menu describing this option
711 tag = C string to be passed to the plugin when this option is used
712 mandatory = TRUE (1) if this option is always passed to the plugin
713 FALSE (0) if the user may or may not select this option
714 MAYBE (-1) if it is to be turned on, but it can be turned off
715 -----------------------------------------------------------------------------*/
716
add_option_to_PLUGIN_interface(PLUGIN_interface * plint,char * label,char * tag,int mandatory)717 void add_option_to_PLUGIN_interface( PLUGIN_interface * plint ,
718 char * label , char * tag , int mandatory )
719 {
720 int nopt , isv ;
721 PLUGIN_option * opt ;
722
723 ENTRY("add_option_to_PLUGIN_interface") ;
724
725 /*-- sanity check --*/
726
727 if( plint == NULL ) EXRETURN ;
728 if( plint->call_method == PLUGIN_CALL_IMMEDIATELY ) EXRETURN ;
729
730 if( label == NULL ) label = EMPTY_STRING ;
731 if( tag == NULL ) tag = EMPTY_STRING ;
732
733 /*-- create space for new option --*/
734
735 nopt = plint->option_count ;
736 plint->option = (PLUGIN_option **)
737 XtRealloc( (char *) plint->option ,
738 sizeof(PLUGIN_option *) * (nopt+1) ) ;
739
740 plint->option[nopt] = opt = (PLUGIN_option *)XtMalloc(sizeof(PLUGIN_option));
741 memset(opt, 0, sizeof(PLUGIN_option)) ; /* 11 Feb 2009 [lesstif patrol] */
742
743 /*-- put values in new option --*/
744
745 PLUGIN_LABEL_strcpy( opt->label , label ) ;
746 MCW_strncpy( opt->tag , tag , PLUGIN_STRING_SIZE ) ;
747
748 opt->mandatory = mandatory ;
749 opt->subvalue_count = 0 ;
750
751 opt->hint = NULL ;
752 for( isv=0 ; isv < PLUGIN_MAX_SUBVALUES ; isv++ )
753 opt->subvalue[isv].hint = NULL ;
754
755 (plint->option_count)++ ; /* one more option */
756
757 #if 0
758 {int qq; fprintf(stderr,"Option tags thus far:\n");
759 for(qq=0;qq<plint->option_count;qq++)
760 fprintf(stderr," %s",plint->option[qq]->tag) ;
761 fprintf(stderr,"\n"); }
762 #endif
763
764 EXRETURN ;
765 }
766
767 /*-------------------------------------------------------------------------
768 Add a hint to the most recently created interface item
769 ---------------------------------------------------------------------------*/
770
PLUTO_add_hint(PLUGIN_interface * plint,char * hh)771 void PLUTO_add_hint( PLUGIN_interface * plint , char * hh )
772 {
773 int nopt , nsv ;
774 PLUGIN_option * opt ;
775 PLUGIN_subvalue * sv ;
776
777 ENTRY("PLUTO_add_hint") ;
778
779 if( plint == NULL || hh == NULL ) EXRETURN ;
780
781 nopt = plint->option_count - 1 ;
782 if( nopt < 0 ){ /* no options yet, so hint is global */
783 myXtFree(plint->hint) ;
784 plint->hint = XtNewString(hh) ;
785 EXRETURN ;
786 }
787
788 opt = plint->option[nopt] ; /* latest option line */
789 nsv = opt->subvalue_count ; /* number of subvalues on it */
790
791 if( nsv == 0 ){ /* no subvalues yet */
792 myXtFree(opt->hint) ; /* so put hint on the option line */
793 opt->hint = XtNewString(hh) ;
794 } else { /* add hint to last subvalue */
795 sv = &(opt->subvalue[nsv-1]) ;
796 myXtFree(sv->hint) ;
797 sv->hint = XtNewString(hh) ;
798
799 #if 0
800 if(PRINT_TRACING)
801 { char str[256] ; sprintf(str,"%s: %s hint=%s",
802 plint->label,sv->label,sv->hint) ; STATUS(str) ; }
803 #endif
804
805 }
806
807 EXRETURN ;
808 }
809
810 /*-------------------------------------------------------------------------
811 Routine to add a number-type "chooser" to the most recently created
812 option within a plugin interface. "Numbers" are always passed to
813 the plugin in float format, but are specified here using an
814 integer range with a decimal shift, sort of like the Motif Scale Widget.
815
816 label = C string to go in the menu, next to the "chooser" for
817 the integer.
818
819 bot, top, = Smallest and largest integer values allowed in the chooser.
820 decim = Number of decimals to shift to left for display of value.
821 For example, bot=1 top=100 with decim=2 will actually
822 specify a range of 0.01 to 1.00. One function of decim
823 is simply to set the increments between values in the
824 chooser. With decim=2, the increment is 0.01.
825
826 defval = Integer value for the default. For example, if decim=2,
827 and defval=43, then the floating point default value
828 (as it appears to the user) is actually 0.43.
829
830 editable = TRUE (1) if the user will be allowed to type in any
831 value in the chooser. For example, this would allow
832 the input of 0.43721.
833 FALSE (0) if the user is restricted to the range of
834 values given by bot/10**decim to top/10**decim,
835 in steps of 1/10**decim.
836 ---------------------------------------------------------------------------*/
837
add_number_to_PLUGIN_interface(PLUGIN_interface * plint,char * label,int bot,int top,int decim,int defval,int editable)838 void add_number_to_PLUGIN_interface( PLUGIN_interface * plint ,
839 char * label ,
840 int bot , int top , int decim ,
841 int defval , int editable )
842 {
843 int nopt , nsv ;
844 PLUGIN_option * opt ;
845 PLUGIN_subvalue * sv ;
846
847 /*-- sanity check --*/
848
849 ENTRY("add_number_to_PLUGIN_interface") ;
850
851 if( plint == NULL || plint->option_count == 0 ) EXRETURN ;
852
853 if( label == NULL ) label = EMPTY_STRING ;
854
855 nopt = plint->option_count - 1 ;
856 opt = plint->option[nopt] ;
857
858 nsv = opt->subvalue_count ;
859 if( nsv == PLUGIN_MAX_SUBVALUES ){
860 fprintf(stderr,"*** Warning: maximum plugin subvalue count exceeded!\n");
861 EXRETURN ;
862 }
863
864 /*-- load values into next subvalue --*/
865
866 sv = &(opt->subvalue[nsv]) ;
867
868 sv->data_type = PLUGIN_NUMBER_TYPE ;
869 PLUGIN_LABEL_strcpy( sv->label , label ) ;
870
871 sv->int_range_bot = bot ;
872 sv->int_range_top = top ;
873 sv->int_range_decim = decim ;
874 sv->value_default = defval ;
875 sv->editable = editable ;
876
877 (opt->subvalue_count)++ ;
878 EXRETURN ;
879 }
880
881 /*-------------------------------------------------------------------
882 Routine to add a string-type "chooser" to the most recently created
883 option within a plugin interface.
884
885 label = C string to go in the menu, next to the "chooser" for
886 the string.
887
888 num_str = Count of the number of strings provided in strlist.
889 strlist = strlist[i] is a pointer to the i'th string value
890 that the user is to choose from, for i=0...num_str-1.
891
892 defval = If num_str > 0:
893 Integer from 0...num_str-1 indicating which string
894 in strlist is the default value.
895 If num_str == 0:
896 Gives width of field supplied for string input.
897
898 Note that if num_str is <= 0, then instead of being presented with
899 a menu of fixed strings, the user will have to type in a string.
900 ---------------------------------------------------------------------*/
901
add_string_to_PLUGIN_interface(PLUGIN_interface * plint,char * label,int num_str,char ** strlist,int defval)902 void add_string_to_PLUGIN_interface( PLUGIN_interface * plint ,
903 char * label ,
904 int num_str , char ** strlist ,
905 int defval )
906 {
907 int nopt , nsv , ii ;
908 PLUGIN_option * opt ;
909 PLUGIN_subvalue * sv ;
910
911 ENTRY("add_string_to_PLUGIN_interface") ;
912
913 if( plint == NULL || plint->option_count == 0 ) EXRETURN ;
914
915 if( label == NULL ) label = EMPTY_STRING ;
916
917 nopt = plint->option_count - 1 ;
918 opt = plint->option[nopt] ;
919
920 nsv = opt->subvalue_count ;
921 if( nsv == PLUGIN_MAX_SUBVALUES ){
922 fprintf(stderr,"*** Warning: maximum plugin subvalue count exceeded!\n");
923 EXRETURN ;
924 }
925
926 /*-- load values into next subvalue --*/
927
928 sv = &(opt->subvalue[nsv]) ;
929
930 sv->data_type = PLUGIN_STRING_TYPE ;
931 PLUGIN_LABEL_strcpy( sv->label , label ) ;
932
933 if( num_str > 0 ){
934 sv->string_range_count = num_str ;
935 if( num_str > PLUGIN_MAX_STRING_RANGE )
936 ERROR_message("num_str=%d > %d :(",num_str,PLUGIN_MAX_STRING_RANGE) ;
937 for( ii=0 ; ii < num_str ; ii++ ){
938 sv->string_range[ii] = (char*)XtMalloc( PLUGIN_STRING_SIZE ) ;
939 MCW_strncpy( sv->string_range[ii] , strlist[ii] , PLUGIN_STRING_SIZE ) ;
940 }
941 sv->value_default = defval ;
942 sv->editable = FALSE ;
943 } else {
944 sv->string_range_count = 0 ;
945 sv->editable = TRUE ;
946 sv->value_default = defval ;
947
948 if( strlist != NULL && strlist[0] != NULL ){ /* 19 Jun 2000 */
949 sv->string_range_count = -1 ;
950 sv->string_range[0] = (char*)XtMalloc( PLUGIN_STRING_SIZE ) ;
951 MCW_strncpy( sv->string_range[0], strlist[0], PLUGIN_STRING_SIZE ) ;
952 }
953 }
954
955 (opt->subvalue_count)++ ;
956 EXRETURN ;
957 }
958
959 /*-----------------------------------------------------------------------
960 Routine to add a dataset "chooser" to the most recently created
961 option within a plugin interface.
962
963 label = C string to go in the menu, next to the "chooser" for
964 the dataset.
965
966 The _mask inputs are bitwise ORs (|) of dataset type masks.
967 These are used to specify the types of datasets that can be
968 passed to the plugin. The first two _mask inputs below cannot both
969 be zero (for then no dataset would be allowed into the plugin!).
970
971 anat_mask = Chosen from the list in 3ddata.h, which is currently
972 ANAT_SPGR_MASK ANAT_FSE_MASK ANAT_EPI_MASK
973 ANAT_MRAN_MASK ANAT_CT_MASK ANAT_SPECT_MASK
974 ANAT_PET_MASK ANAT_MRA_MASK ANAT_BMAP_MASK
975 ANAT_DIFF_MASK ANAT_OMRI_MASK
976 and ANAT_ALL_MASK, which will allow any anatomical
977 dataset. Entering 0 for this mask will mean that
978 no anatomical datasets will be choosable.
979
980 func_mask = Similar mask for functional dataset types, chosen from
981 FUNC_FIM_MASK FUNC_THR_MASK
982 FUNC_COR_MASK FUNC_TT_MASK
983 and FUNC_ALL_MASK, which will allow any functional
984 dataset. Entering 0 for this mask will mean that
985 no functional datasets will be choosable.
986
987 ctrl_mask = An additional mask to specify further exactly which
988 datasets should be choosable. Mask options are:
989
990 SESSION_ALL_MASK = If this is set, then the choice of
991 datasets will be drawn from all
992 sessions now loaded into AFNI.
993 * By default, only the "current"
994 session will be included.
995
996 DIMEN_3D_MASK = Masks that define whether 3D and/or
997 DIMEN_4D_MASK 3D+time (4D) datasets are allowable.
998 DIMEN_ALL_MASK
999
1000 WARP_ON_DEMAND_MASK = If this is set, then datasets that may
1001 not have a BRIK file will be included
1002 in the list of datasets to choose from.
1003 In this case, the plugin must be ready
1004 to deal with the warp-on-demand routines
1005 that return one slice at a time.
1006 * By default, only datasets with actual
1007 BRIKs will be included.
1008
1009 BRICK_BYTE_MASK = Masks that define what type of data
1010 BRICK_SHORT_MASK should be stored in the sub-bricks
1011 BRICK_FLOAT_MASK of the allowable datasets.
1012 BRICK_COMPLEX_MASK
1013 BRICK_RGB_MASK
1014 BRICK_ALLTYPE_MASK
1015 BRICK_ALLREAL_MASK
1016
1017 * Note that entering 0 for ctrl_mask means that no *
1018 * datasets will be choosable. At the least, one of *
1019 * the DIMEN_ masks must be chosen, and one of the *
1020 * BRICK_ masks must be chosen. *
1021 -------------------------------------------------------------------------*/
1022
add_dataset_to_PLUGIN_interface(PLUGIN_interface * plint,char * label,int anat_mask,int func_mask,int ctrl_mask)1023 void add_dataset_to_PLUGIN_interface( PLUGIN_interface * plint ,
1024 char * label ,
1025 int anat_mask , int func_mask , int ctrl_mask )
1026 {
1027 int nopt , nsv , ii ;
1028 PLUGIN_option * opt ;
1029 PLUGIN_subvalue * sv ;
1030
1031 ENTRY("add_dataset_to_PLUGIN_interface") ;
1032
1033 /*-- sanity checks --*/
1034
1035 if( plint == NULL || plint->option_count == 0 ) EXRETURN ;
1036 if( anat_mask == 0 && func_mask == 0 ) EXRETURN ;
1037
1038 if( label == NULL ) label = EMPTY_STRING ;
1039
1040 if( (ctrl_mask & BRICK_ALLTYPE_MASK)==0 ||
1041 (ctrl_mask & DIMEN_ALL_MASK) ==0 ) EXRETURN ;
1042
1043 nopt = plint->option_count - 1 ;
1044 opt = plint->option[nopt] ;
1045
1046 nsv = opt->subvalue_count ;
1047 if( nsv == PLUGIN_MAX_SUBVALUES ){
1048 fprintf(stderr,"*** Warning: maximum plugin subvalue count exceeded!\n");
1049 EXRETURN ;
1050 }
1051
1052 /*-- load values into next subvalue --*/
1053
1054 sv = &(opt->subvalue[nsv]) ;
1055
1056 sv->data_type = PLUGIN_DATASET_TYPE ;
1057 PLUGIN_LABEL_strcpy( sv->label , label ) ;
1058
1059 sv->dset_anat_mask = anat_mask ;
1060 sv->dset_func_mask = func_mask ;
1061 sv->dset_ctrl_mask = ctrl_mask ;
1062
1063 (opt->subvalue_count)++ ;
1064 EXRETURN ;
1065 }
1066
add_dataset_list_to_PLUGIN_interface(PLUGIN_interface * plint,char * label,int anat_mask,int func_mask,int ctrl_mask)1067 void add_dataset_list_to_PLUGIN_interface( PLUGIN_interface * plint ,
1068 char * label ,
1069 int anat_mask , int func_mask , int ctrl_mask )
1070 {
1071 int nopt , nsv , ii ;
1072 PLUGIN_option * opt ;
1073 PLUGIN_subvalue * sv ;
1074
1075 ENTRY("add_dataset_list_to_PLUGIN_interface") ;
1076
1077 /*-- sanity checks --*/
1078
1079 if( plint == NULL || plint->option_count == 0 ) EXRETURN ;
1080 if( anat_mask == 0 && func_mask == 0 ) EXRETURN ;
1081
1082 if( label == NULL ) label = EMPTY_STRING ;
1083
1084 if( (ctrl_mask & BRICK_ALLTYPE_MASK)==0 ||
1085 (ctrl_mask & DIMEN_ALL_MASK) ==0 ) EXRETURN ;
1086
1087 nopt = plint->option_count - 1 ;
1088 opt = plint->option[nopt] ;
1089
1090 nsv = opt->subvalue_count ;
1091 if( nsv == PLUGIN_MAX_SUBVALUES ){
1092 fprintf(stderr,"*** Warning: maximum plugin subvalue count exceeded!\n");
1093 EXRETURN ;
1094 }
1095
1096 /*-- load values into next subvalue --*/
1097
1098 sv = &(opt->subvalue[nsv]) ;
1099
1100 sv->data_type = PLUGIN_DATASET_LIST_TYPE ;
1101 PLUGIN_LABEL_strcpy( sv->label , label ) ;
1102
1103 sv->dset_anat_mask = anat_mask ;
1104 sv->dset_func_mask = func_mask ;
1105 sv->dset_ctrl_mask = ctrl_mask ;
1106
1107 (opt->subvalue_count)++ ;
1108 EXRETURN ;
1109 }
1110
1111 /*-----------------------------------------------------------------------
1112 Routine to add a timeseries "chooser" to the most recently created
1113 option within a plugin interface.
1114
1115 label = C string to go in the menu, next to the "chooser" for
1116 the dataset.
1117 -------------------------------------------------------------------------*/
1118
add_timeseries_to_PLUGIN_interface(PLUGIN_interface * plint,char * label)1119 void add_timeseries_to_PLUGIN_interface( PLUGIN_interface * plint, char * label )
1120 {
1121 int nopt , nsv , ii ;
1122 PLUGIN_option * opt ;
1123 PLUGIN_subvalue * sv ;
1124
1125 ENTRY("add_timeseries_to_PLUGIN_interface") ;
1126
1127 /*-- sanity checks --*/
1128
1129 if( plint == NULL || plint->option_count == 0 ) EXRETURN ;
1130
1131 if( label == NULL ) label = EMPTY_STRING ;
1132
1133 nopt = plint->option_count - 1 ;
1134 opt = plint->option[nopt] ;
1135
1136 nsv = opt->subvalue_count ;
1137 if( nsv == PLUGIN_MAX_SUBVALUES ){
1138 fprintf(stderr,"*** Warning: maximum plugin subvalue count exceeded!\n");
1139 EXRETURN ;
1140 }
1141
1142 /*-- load values into next subvalue --*/
1143
1144 sv = &(opt->subvalue[nsv]) ;
1145
1146 sv->data_type = PLUGIN_TIMESERIES_TYPE ;
1147 PLUGIN_LABEL_strcpy( sv->label , label ) ;
1148
1149 (opt->subvalue_count)++ ;
1150 EXRETURN ;
1151 }
1152
1153 /*-----------------------------------------------------------------------
1154 Routine to add a *.[tc]sv "chooser" to the most recently created
1155 option within a plugin interface.
1156
1157 label = C string to go in the menu, next to the "chooser" for
1158 the dataset.
1159 -------------------------------------------------------------------------*/
1160
add_tcsv_to_PLUGIN_interface(PLUGIN_interface * plint,char * label)1161 void add_tcsv_to_PLUGIN_interface( PLUGIN_interface * plint, char * label )
1162 {
1163 int nopt , nsv , ii ;
1164 PLUGIN_option * opt ;
1165 PLUGIN_subvalue * sv ;
1166
1167 ENTRY("add_tcsv_to_PLUGIN_interface") ;
1168
1169 /*-- sanity checks --*/
1170
1171 if( plint == NULL || plint->option_count == 0 ) EXRETURN ;
1172
1173 if( label == NULL ) label = EMPTY_STRING ;
1174
1175 nopt = plint->option_count - 1 ;
1176 opt = plint->option[nopt] ;
1177
1178 nsv = opt->subvalue_count ;
1179 if( nsv == PLUGIN_MAX_SUBVALUES ){
1180 fprintf(stderr,"*** Warning: maximum plugin subvalue count exceeded!\n");
1181 EXRETURN ;
1182 }
1183
1184 /*-- load values into next subvalue --*/
1185
1186 sv = &(opt->subvalue[nsv]) ;
1187
1188 sv->data_type = PLUGIN_TCSV_TYPE ;
1189 PLUGIN_LABEL_strcpy( sv->label , label ) ;
1190
1191 (opt->subvalue_count)++ ;
1192 EXRETURN ;
1193 }
1194
1195 /*-----------------------------------------------------------------------*/
1196
1197 static int initcolorindex=1 ;
PLUTO_set_initcolorindex(int i)1198 void PLUTO_set_initcolorindex( int i ){ initcolorindex = i; } /* 10 Oct 2007 */
1199
1200 /*-----------------------------------------------------------------------
1201 Routine to add a color overlay "chooser" to the most recently
1202 created option within a plugin interface -- 11 Jul 2001 - RWCox.
1203
1204 label = C string to go in the menu, next to the "chooser" for
1205 the color.
1206 -------------------------------------------------------------------------*/
1207
add_overlaycolor_to_PLUGIN_interface(PLUGIN_interface * plint,char * label)1208 void add_overlaycolor_to_PLUGIN_interface( PLUGIN_interface *plint, char *label )
1209 {
1210 int nopt , nsv , ii ;
1211 PLUGIN_option *opt ;
1212 PLUGIN_subvalue *sv ;
1213
1214 ENTRY("add_overlaycolor_to_PLUGIN_interface") ;
1215
1216 /*-- sanity checks --*/
1217
1218 if( plint == NULL || plint->option_count == 0 ) EXRETURN ;
1219
1220 if( label == NULL ) label = EMPTY_STRING ;
1221
1222 nopt = plint->option_count - 1 ;
1223 opt = plint->option[nopt] ;
1224
1225 nsv = opt->subvalue_count ;
1226 if( nsv == PLUGIN_MAX_SUBVALUES ){
1227 WARNING_message("maximum plugin subvalue count exceeded - overlaycolor");
1228 EXRETURN ;
1229 }
1230
1231 /*-- load values into next subvalue --*/
1232
1233 sv = &(opt->subvalue[nsv]) ;
1234
1235 sv->data_type = PLUGIN_OVERLAY_COLOR_TYPE ;
1236 PLUGIN_LABEL_strcpy( sv->label , label ) ;
1237 sv->value_default = initcolorindex ;
1238
1239 (opt->subvalue_count)++ ;
1240 EXRETURN ;
1241 }
1242
1243 /*--------------------------------------------------------------------------*/
1244
PLUG_nonblank_len(char * str)1245 int PLUG_nonblank_len( char *str )
1246 {
1247 int ii , ll ;
1248
1249 if( str == NULL || *str == '\0' ) return 0 ;
1250 ll = strlen(str) ;
1251
1252 for( ii=ll-1 ; ii >= 0 ; ii-- ) if( !isspace(str[ii]) ) break ;
1253
1254 return (ii+1) ;
1255 }
1256
1257 /*--------------------------------------------------------------------------
1258 Decide if a dataset prefix is OK. The string itself is checked for
1259 legality, then the list of all datasets is checked for duplicates.
1260 ----------------------------------------------------------------------------*/
1261
PLUTO_prefix_ok(char * str)1262 int PLUTO_prefix_ok( char *str )
1263 {
1264 int ll , ii ;
1265 THD_slist_find find ;
1266
1267 ENTRY("PLUTO_prefix_ok") ;
1268
1269 /*--- check the string itself for OK-osity ---*/
1270
1271 if( str == NULL ) RETURN(0) ;
1272 ll = strlen( str ) ; if( ll == 0 ) RETURN(0) ;
1273
1274 for( ii=0 ; ii < ll ; ii++ )
1275 if( iscntrl(str[ii]) || isspace(str[ii]) ||
1276 str[ii] == '/' || str[ii] == ';' ||
1277 str[ii] == '*' || str[ii] == '?' ||
1278 str[ii] == '&' || str[ii] == '|' ||
1279 str[ii] == '"' || str[ii] == '>' ||
1280 str[ii] == '<' || str[ii] == '\'' ||
1281 str[ii] == '[' || str[ii] == ']' ) RETURN(0) ;
1282
1283 /*--- now see if the prefix already exists in AFNI ---*/
1284
1285 find = THD_dset_in_sessionlist( FIND_PREFIX , str ,
1286 GLOBAL_library.sslist , -1 ) ;
1287
1288 RETURN(find.dset == NULL) ;
1289 }
1290
1291 /*------------------------------------------------------------------------------
1292 Routine to create (but not map) the widgets for a plugin interface.
1293 --------------------------------------------------------------------------------*/
1294
1295 /***** definitions for the action area controls *****/
1296
1297 #define PLUG_quit_label "Quit"
1298 #define PLUG_run_label "Run+Keep"
1299 #define PLUG_doit_label "Run+Close"
1300 #define PLUG_help_label "Help"
1301
1302 #define PLUG_quit_help "Press to close\nthis panel without\nrunning program."
1303 #define PLUG_run_help "Press to run\nthe program\nand keep panel open."
1304 #define PLUG_doit_help "Press to run\nthe program\nand close this panel."
1305 #define PLUG_help_help "Press to get\nthe help for\nthis program."
1306
1307 #define NUM_PLUG_ACT 4
1308
1309 static MCW_action_item PLUG_act[] = {
1310 { PLUG_quit_label, PLUG_action_CB, NULL, PLUG_quit_help,"Close window" , 0 },
1311 { PLUG_run_label , PLUG_action_CB, NULL, PLUG_run_help ,"Run plugin and keep window" , 0 },
1312 { PLUG_doit_label, PLUG_action_CB, NULL, PLUG_doit_help,"Run plugin and close window", 1 },
1313 { PLUG_help_label, PLUG_action_CB, NULL, PLUG_help_help,"Get help for plugin" , 0 }
1314 } ;
1315
PLUG_setup_widgets(PLUGIN_interface * plint,MCW_DC * dc)1316 void PLUG_setup_widgets( PLUGIN_interface * plint , MCW_DC * dc )
1317 {
1318 int iopt , ib , max_nsv , ww,hh , shh , toff , zlen ;
1319 XmString xstr ;
1320 char str[256] ;
1321 PLUGIN_widgets * wid ;
1322 PLUGIN_option_widgets ** opwid ;
1323 PLUGIN_option_widgets * ow ;
1324 PLUGIN_option * opt ;
1325 PLUGIN_subvalue * sv ;
1326 Widget actar , wframe , separator = NULL ;
1327 int opt_lwid , sv_lwid[PLUGIN_MAX_SUBVALUES] ;
1328 Widget widest_chooser[PLUGIN_MAX_SUBVALUES] ;
1329 int widest_width[PLUGIN_MAX_SUBVALUES] ;
1330 Pixel fg_pix=0 ;
1331
1332 ENTRY("PLUG_setup_widgets") ;
1333
1334 /**** sanity checks ****/
1335
1336 STATUS("check plint") ;
1337 if( plint == NULL ) EXRETURN ;
1338 STATUS("check plint->wid") ;
1339 if( plint->wid != NULL ) EXRETURN ;
1340 STATUS("check plint->call_method") ;
1341 if( plint->call_method == PLUGIN_CALL_IMMEDIATELY ) EXRETURN ;
1342
1343 /**** create widgets structure ****/
1344
1345 STATUS("create widget structure") ;
1346 plint->wid = wid = myXtNew(PLUGIN_widgets) ;
1347
1348 /**** create Shell that can be opened up later ****/
1349 /* 'LessTif Widormous'
1350 With 64bit LessTif, some widgets get created with
1351 enormous sizes. To complicate matters, the problem
1352 occurred randomly so tracking it is a frustrating
1353 exercise. It looks like adding a few, harmless,
1354 XmNheight and XmNwidth parameters at widget creation
1355 fixed the problem. Those parameters have no effect
1356 on the final plugin's look so we won't bother to find
1357 out which of them was necessary for fixing the problem.
1358 12 Feb 2009 9Lesstif patrol]
1359 */
1360 STATUS("create shell") ;
1361 wid->shell =
1362 XtVaAppCreateShell(
1363 "AFNI" , "AFNI" , topLevelShellWidgetClass , dc->display ,
1364
1365 XmNtitle , plint->label , /* top of window */
1366 XmNiconName , plint->label , /* label on icon */
1367 XmNmappedWhenManaged , False , /* must map it manually */
1368 XmNdeleteResponse , XmDO_NOTHING , /* deletion handled below */
1369 XmNallowShellResize , False , /* let code resize shell? */
1370 XmNinitialResourcesPersistent , False ,
1371 XmNheight, 207, /* See 'LessTif Widormous' comment above */
1372 XmNwidth, 206, /* 12 Feb 2009 9Lesstif patrol] */
1373 XmNkeyboardFocusPolicy , XmEXPLICIT ,
1374 NULL ) ;
1375
1376 DC_yokify( wid->shell , dc ) ; /* 14 Sep 1998 */
1377
1378 if( afni48_good )
1379 XtVaSetValues( wid->shell ,
1380 XmNiconPixmap , afni48_pixmap ,
1381 NULL ) ;
1382
1383 if( MCW_isitmwm(wid->shell) )
1384 XtVaSetValues( wid->shell ,
1385 XmNmwmDecorations , MWM_DECOR_ALL | MWM_DECOR_MAXIMIZE ,
1386 NULL ) ;
1387
1388 XmAddWMProtocolCallback( /* make "Close" window menu work */
1389 wid->shell ,
1390 XmInternAtom( dc->display , "WM_DELETE_WINDOW" , False ) ,
1391 PLUG_delete_window_CB , (XtPointer) plint ) ;
1392
1393 /**** create Form to hold all widgets ****/
1394
1395 STATUS("create Form") ;
1396 wid->form = XtVaCreateWidget(
1397 "AFNI" , xmFormWidgetClass , wid->shell ,
1398 XmNborderWidth , 0 ,
1399 XmNborderColor , 0 ,
1400 XmNwidth, 70,/* See 'LessTif Widormous' comment above */
1401 XmNheight, 100,/* 12 Feb 2009 9Lesstif patrol] */
1402 XmNtraversalOn , True ,
1403 XmNinitialResourcesPersistent , False ,
1404 NULL ) ;
1405
1406 /**** create Label at top to hold description of this program ****/
1407
1408 if( plint->toplabel[0] == '\0' )
1409 sprintf( str , "AFNI Plugin: %s" , plint->description ) ;
1410 else
1411 strcpy( str , plint->toplabel ) ; /* 13 May 2010 */
1412
1413 STATUS("Create Label") ;
1414 xstr = XmStringCreateLtoR( str , XmFONTLIST_DEFAULT_TAG ) ;
1415 wid->label =
1416 XtVaCreateManagedWidget(
1417 "AFNI" , xmLabelWidgetClass , wid->form ,
1418 XmNlabelString , xstr ,
1419 XmNalignment , XmALIGNMENT_CENTER ,
1420
1421 XmNleftAttachment , XmATTACH_FORM ,
1422 XmNrightAttachment, XmATTACH_FORM ,
1423 XmNtopAttachment , XmATTACH_FORM ,
1424 XmNtopOffset , 5 ,
1425 XmNheight, 20, /* See 'LessTif Widormous' comment above */
1426 XmNwidth, 20, /* 12 Feb 2009 9Lesstif patrol] */
1427 XmNinitialResourcesPersistent , False ,
1428 NULL ) ;
1429 XmStringFree( xstr ) ; LABELIZE(wid->label) ;
1430
1431 /* now that we have the label,
1432 find its sizes and make sure the shell doesn't get too small */
1433
1434 MCW_widget_geom( wid->label , &ww , &hh , NULL , NULL ) ;
1435 XtVaSetValues( wid->shell ,
1436 XmNminWidth , ww+3*hh ,
1437 XmNminHeight , (plint->option_count == 0) ? 5*hh : 7*hh ,
1438 NULL ) ;
1439
1440 /**** create an action area beneath to hold user control buttons ****/
1441
1442 for( ib=0 ; ib < NUM_PLUG_ACT ; ib++ )
1443 PLUG_act[ib].data = (XtPointer) plint ;
1444
1445 /* 04 Nov 2003: allow for change of Run+Close and Run+Keep labels */
1446
1447 if( plint->run_label[0] == '\0' ) strcpy(plint->run_label ,PLUG_run_label );
1448 if( plint->doit_label[0] == '\0' ) strcpy(plint->doit_label,PLUG_doit_label);
1449 PLUG_act[1].label = plint->run_label ;
1450 PLUG_act[2].label = plint->doit_label;
1451
1452 actar = MCW_action_area( wid->form , PLUG_act ,
1453 (plint->helpstring!=NULL) ? NUM_PLUG_ACT
1454 : NUM_PLUG_ACT-1 ) ;
1455
1456 XtVaSetValues( actar ,
1457 XmNleftAttachment , XmATTACH_FORM ,
1458 XmNrightAttachment, XmATTACH_FORM ,
1459 XmNtopAttachment , XmATTACH_WIDGET ,
1460 XmNtopWidget , wid->label ,
1461 XmNtopOffset , 7 ,
1462 NULL ) ;
1463
1464 /**** create a Scrolled Window and Form to hold
1465 the user input option widgets, if they will be needed ****/
1466
1467 if( plint->option_count > 0 ){
1468 STATUS("create ScrolledWindow") ;
1469 wid->scrollw =
1470 XtVaCreateWidget(
1471 "AFNI" , xmScrolledWindowWidgetClass , wid->form ,
1472 XmNscrollingPolicy , XmAUTOMATIC ,
1473 XmNwidth , ww+2*hh ,
1474 XmNheight , 3*hh ,
1475 XmNleftAttachment , XmATTACH_FORM ,
1476 XmNrightAttachment , XmATTACH_FORM ,
1477 XmNtopAttachment , XmATTACH_WIDGET ,
1478 XmNbottomAttachment, XmATTACH_FORM ,
1479 XmNtopWidget , actar ,
1480 XmNtopOffset , 7 ,
1481 XmNtraversalOn , True ,
1482 XmNinitialResourcesPersistent , False ,
1483 NULL ) ;
1484
1485 wframe =
1486 XtVaCreateWidget(
1487 "AFNI" , xmFrameWidgetClass , wid->scrollw ,
1488 XmNshadowType , XmSHADOW_ETCHED_IN ,
1489 XmNshadowThickness , 5 ,
1490 XmNtraversalOn , True ,
1491 XmNinitialResourcesPersistent , False ,
1492 NULL ) ;
1493
1494 wid->workwin =
1495 XtVaCreateWidget(
1496 "AFNI" , xmFormWidgetClass , wframe ,
1497 XmNborderWidth , 0 ,
1498 XmNborderColor , 0 ,
1499 XmNtraversalOn , True ,
1500 XmNinitialResourcesPersistent , False ,
1501 NULL ) ;
1502
1503 wid->opwid = opwid =
1504 (PLUGIN_option_widgets **)
1505 XtMalloc(sizeof(PLUGIN_option_widgets *) * plint->option_count) ;
1506
1507 /** setup widest widgets for each column of the Form **/
1508
1509 for( ib=0 ; ib < PLUGIN_MAX_SUBVALUES ; ib++ ){
1510 widest_chooser[ib] = NULL ;
1511 widest_width[ib] = 0 ;
1512 }
1513
1514 XtVaGetValues( wframe , XmNforeground , &fg_pix , NULL ) ;
1515
1516 } else {
1517 wframe = wid->scrollw = wid->workwin = NULL ;
1518 opwid = NULL ;
1519 }
1520
1521 /**** for each column within each option, find the max string width ****/
1522
1523 opt_lwid = 1 ;
1524 for( ib=0 ; ib < PLUGIN_MAX_SUBVALUES ; ib++ ) sv_lwid[ib] = 1 ;
1525
1526 for( iopt=0 ; iopt < plint->option_count ; iopt++ ){
1527 opt = plint->option[iopt] ;
1528 if( opt == NULL ) continue ; /* bad? */
1529
1530 opt_lwid = MAX( opt_lwid , PLUG_nonblank_len(opt->label) ) ;
1531 for( ib=0 ; ib < opt->subvalue_count ; ib++ ){
1532 sv = &(opt->subvalue[ib]) ;
1533 sv_lwid[ib] = MAX( sv_lwid[ib] , PLUG_nonblank_len(sv->label) ) ;
1534 }
1535 }
1536
1537 /**** now clip each label string to its column's width ****/
1538
1539 for( iopt=0 ; iopt < plint->option_count ; iopt++ ){
1540 opt = plint->option[iopt] ;
1541 if( opt == NULL ) continue ; /* bad? */
1542
1543 #define LPAD 0 /* 29 Mar 2002: used to be 1 */
1544
1545 opt->label[ opt_lwid + LPAD ] = '\0' ;
1546 for( ib=0 ; ib < opt->subvalue_count ; ib++ ){
1547 sv = &(opt->subvalue[ib]) ;
1548 sv->label[ sv_lwid[ib] + LPAD ] = '\0' ;
1549 }
1550 }
1551
1552 /**** create a row of Widgets for each option ****/
1553
1554 for( iopt=0 ; iopt < plint->option_count ; iopt++ ){
1555 opt = plint->option[iopt] ;
1556 if( opt == NULL ) continue ; /* bad? */
1557
1558 ow = opwid[iopt] = myXtNew(PLUGIN_option_widgets) ;
1559
1560 for( ib=0 ; ib < PLUGIN_MAX_SUBVALUES ; ib++ ){ /* initialize */
1561 ow->chooser[ib] = NULL ; /* all subvalue */
1562 ow->chtop[ib] = NULL ; /* stuff */
1563 ow->chooser_type[ib] = OP_CHOOSER_NONE ;
1564 opt->callvalue[ib] = NULL ;
1565 }
1566
1567 /** create ToggleButton to indicate whether this is used **/
1568
1569 STATUS("create ToggleButton for row") ;
1570 ow->toggle =
1571 XtVaCreateManagedWidget(
1572 "AFNI" , xmToggleButtonWidgetClass , wid->workwin ,
1573 XmNleftAttachment , XmATTACH_FORM ,
1574 XmNtopAttachment , (iopt==0) ? XmATTACH_FORM /* first row */
1575 : XmATTACH_WIDGET , /* 2nd+ row */
1576 XmNtopOffset , 1 ,
1577 XmNleftOffset , 1 ,
1578 XmNtopWidget , separator , /* 2nd+ row */
1579
1580 XmNlabelType , XmPIXMAP , /* No label attached */
1581 XmNlabelPixmap , XmUNSPECIFIED_PIXMAP , /* Just the toggle! */
1582
1583 XmNset , (opt->mandatory != FALSE) ? True : False ,
1584 XmNsensitive , (opt->mandatory == TRUE ) ? False : True ,
1585
1586 XmNindicatorSize , hh-1 ,
1587 XmNmarginHeight , 0 ,
1588 XmNmarginWidth , 0 ,
1589 XmNselectColor , fg_pix , /* fill with foreground when set */
1590 XmNheight, 20,
1591 XmNwidth, 20,
1592 XmNtraversalOn , True ,
1593 XmNinitialResourcesPersistent , False ,
1594 NULL ) ;
1595
1596 MCW_register_help( ow->toggle ,
1597 "When pressed in and filled,\n"
1598 "this button denotes that this\n"
1599 "line of input will be passed\n"
1600 "to the plugin. If the plugin\n"
1601 "has specified that this line\n"
1602 "is required, then you cannot\n"
1603 "toggle this button off."
1604 ) ;
1605
1606 if( opt->mandatory == TRUE )
1607 MCW_register_hint( ow->toggle ,
1608 "This input line is mandatory" ) ;
1609 else
1610 MCW_register_hint( ow->toggle ,
1611 "IN: this input line sent to plugin" ) ;
1612
1613 /* this callback will change the appearance of the
1614 option's row of widgets when the toggle button is pressed */
1615
1616 if( opt->mandatory != TRUE )
1617 XtAddCallback( ow->toggle , XmNvalueChangedCallback ,
1618 PLUG_optional_toggle_CB , (XtPointer) ow ) ;
1619
1620 /** create Label to describe this option **/
1621
1622 #if 0
1623 fprintf(stderr,"Option setup %s\n",opt->label) ;
1624 #endif
1625
1626 STATUS("create Label for row") ;
1627 zlen = (PLUG_nonblank_len(opt->label) == 0) ;
1628 xstr = XmStringCreateLtoR( opt->label , XmFONTLIST_DEFAULT_TAG ) ;
1629 ow->label =
1630 XtVaCreateManagedWidget(
1631 "AFNI" , xmLabelWidgetClass , wid->workwin ,
1632 XmNleftAttachment , XmATTACH_WIDGET ,
1633 XmNtopAttachment , (iopt==0) ? XmATTACH_FORM /* 1st row */
1634 : XmATTACH_WIDGET , /* 2nd+ row */
1635 XmNtopOffset , 6 ,
1636 XmNleftOffset , 0 ,
1637 XmNleftWidget , ow->toggle ,
1638 XmNtopWidget , separator , /* 2nd+ row */
1639
1640 XmNmarginHeight , 0 ,
1641 XmNmarginWidth , 0 ,
1642
1643 XmNlabelString , xstr ,
1644 XmNuserData , (XtPointer)ITOP(zlen) ,
1645 XmNinitialResourcesPersistent , False ,
1646 NULL ) ;
1647 XmStringFree( xstr ) ;
1648 if( opt->mandatory == TRUE && !zlen ){
1649 MCW_invert_widget( ow->label ) ;
1650 MCW_register_help( ow->label ,
1651 "This label is inverted as a\n"
1652 "signal that this line of inputs\n"
1653 "is required by the plugin, and\n"
1654 "can't be toggled off."
1655 ) ;
1656 }
1657 if( opt->hint != NULL )
1658 MCW_register_hint( ow->label , opt->hint ) ;
1659
1660 /** for each subvalue, create a chooser to select it **/
1661
1662 for( ib=0 ; ib < opt->subvalue_count ; ib++ ){
1663 sv = &(opt->subvalue[ib]) ;
1664 toff = 4 ; /* default top offset */
1665
1666 switch( sv->data_type ){
1667
1668 /** type I can't handle yet, so just put some label there **/
1669 default:
1670 WARNING_message("Plugin: unknown subvalue type %d", sv->data_type);
1671 xstr = XmStringCreateLtoR( "** N/A **" , XmFONTLIST_DEFAULT_TAG ) ;
1672 ow->chtop[ib] =
1673 XtVaCreateManagedWidget(
1674 "AFNI" , xmLabelWidgetClass , wid->workwin ,
1675 XmNlabelString , xstr ,
1676 XmNinitialResourcesPersistent , False ,
1677 NULL ) ;
1678 XmStringFree( xstr ) ;
1679 ow->chooser_type[ib] = OP_CHOOSER_NONE ;
1680 ow->chooser[ib] = NULL ;
1681 break ;
1682
1683 /** overlay color type -- 11 Jul 2001 **/
1684
1685 case PLUGIN_OVERLAY_COLOR_TYPE:{
1686 MCW_arrowval *av ; int iv=sv->value_default ;
1687 STATUS("create PLUGIN_OVERLAY_COLOR_TYPE") ;
1688 #if 0
1689 fprintf(stderr,"colormenu setup %s; opt->tag=%s.\n",sv->label,opt->tag) ;
1690 #endif
1691 if( iv < 0 || iv > dc->ovc->ncol_ov-1 ) iv = 1 ;
1692
1693 av = new_MCW_colormenu(
1694 wid->workwin , /* parent */
1695 sv->label , /* label */
1696 dc , /* display context */
1697 1 , /* first color */
1698 dc->ovc->ncol_ov - 1 , /* last color */
1699 iv , /* initial color */
1700 NULL,NULL /* callback func,data */
1701 ) ;
1702
1703 ow->chooser[ib] = (void *) av ;
1704 ow->chtop[ib] = av->wrowcol ; /* get the top widget */
1705 #ifdef USING_LESSTIF_NOT_DOING_THIS
1706 if (CPU_IS_64_BIT() ){
1707 ow->chtop[ib] = XtParent(XtParent(av->wrowcol));
1708 /* get the very top rowcol holding the
1709 optmenu rowcol, see function
1710 new_MCW_optmenu_64fix [LPatrol Feb 19 2009] */
1711 }
1712 #endif
1713
1714 ow->chooser_type[ib] = OP_CHOOSER_COLORMENU ;
1715 }
1716 break ;
1717
1718 /** number type: make an arrowval or an option menu **/
1719
1720 case PLUGIN_NUMBER_TYPE:{
1721 int num_choice , use_optmenu ;
1722 MCW_arrowval * av ;
1723
1724 STATUS("create PLUGIN_NUMBER_TYPE") ;
1725 num_choice = abs(sv->int_range_top - sv->int_range_bot) + 1 ;
1726 use_optmenu = (num_choice < OP_OPTMENU_LIMIT) && !sv->editable ;
1727
1728 av = new_MCW_arrowval(
1729 wid->workwin , /* parent */
1730 sv->label , /* label */
1731 (use_optmenu) ? MCW_AV_optmenu /* type */
1732 : MCW_AV_downup ,
1733 sv->int_range_bot , /* min */
1734 sv->int_range_top , /* max */
1735 sv->value_default , /* initial */
1736 (sv->editable) ? MCW_AV_editext /* type */
1737 : MCW_AV_readtext ,
1738 sv->int_range_decim , /* decimals? */
1739 NULL , NULL , NULL , NULL
1740 ) ;
1741
1742 if( use_optmenu && num_choice > COLSIZE )
1743 AVOPT_columnize(av, 1+(num_choice-1)/COLSIZE) ;
1744
1745 ow->chooser[ib] = (void *) av ;
1746 ow->chtop[ib] = av->wrowcol ; /* get the top widget */
1747 #ifdef USING_LESSTIF_NOT_DOING_THIS
1748 if (CPU_IS_64_BIT() && use_optmenu){
1749 ow->chtop[ib] = XtParent(XtParent(av->wrowcol));
1750 /* get the very top rowcol holding the
1751 optmenu rowcol, see function
1752 new_MCW_optmenu_64fix [LPatrol Feb 19 2009]*/
1753 }
1754 #endif
1755 ow->chooser_type[ib] = (use_optmenu) ? OP_CHOOSER_OPTMENU
1756 : OP_CHOOSER_NUMBER ;
1757
1758 if( !use_optmenu ) av->allow_wrap = 1 ;
1759 if( use_optmenu ) toff-- ;
1760
1761 if( !use_optmenu && (plint->flags & SHORT_NUMBER_FLAG) )
1762 XtVaSetValues( av->wtext , XmNcolumns , 6 , NULL ) ;
1763 }
1764 break ;
1765
1766 /** string type:
1767 make an arrowval if a finite number of choices,
1768 or a label+textfield if the user can type in anything **/
1769
1770 case PLUGIN_STRING_TYPE:{
1771 if( sv->string_range_count > 0 ){ /* finite number of choices */
1772 int num_choice , use_optmenu ;
1773 MCW_arrowval * av ;
1774
1775 STATUS("create PLUGIN_STRING_TYPE (fixed)") ;
1776 num_choice = sv->string_range_count ;
1777 use_optmenu = (num_choice < OP_OPTMENU_LIMIT) ;
1778
1779 av = new_MCW_arrowval(
1780 wid->workwin , /* parent */
1781 sv->label , /* label */
1782 (use_optmenu) ? MCW_AV_optmenu /* type */
1783 : MCW_AV_downup ,
1784 0 , /* min */
1785 num_choice-1 , /* max */
1786 sv->value_default , /* initial */
1787 MCW_AV_readtext , /* type */
1788 0 , /* decimals? */
1789 NULL , NULL , /* callbacks */
1790 MCW_av_substring_CB , /* text routine */
1791 sv->string_range /* text data */
1792 ) ;
1793
1794 if( !use_optmenu ){ /* 11 Jul 2001 */
1795 int ss , ll , mm=9 ; /* increase */
1796 for( ss=0 ; ss < num_choice ; ss++ ){ /* width of */
1797 if( sv->string_range[ss] != NULL ){ /* widget, */
1798 ll = strlen(sv->string_range[ss]); /* if needed */
1799 if( ll > mm ) mm = ll ;
1800 }
1801 }
1802 if( mm > 9 )
1803 XtVaSetValues( av->wtext ,
1804 XmNmaxLength,mm , XmNcolumns,mm ,
1805 NULL ) ;
1806 }
1807
1808 if( use_optmenu && num_choice > COLSIZE )
1809 AVOPT_columnize(av, 1+(num_choice-1)/COLSIZE) ;
1810
1811 ow->chooser[ib] = (void *) av ;
1812 ow->chtop[ib] = av->wrowcol ; /* get the top widget */
1813 #ifdef USING_LESSTIF_NOT_DOING_THIS
1814 if (CPU_IS_64_BIT() && use_optmenu ){
1815 ow->chtop[ib] = XtParent(XtParent(av->wrowcol));
1816 /* get the very top rowcol holding the
1817 optmenu rowcol, see function
1818 new_MCW_optmenu_64fix [LPatrol Feb 19 2009]*/
1819 }
1820 #endif
1821 ow->chooser_type[ib] = (use_optmenu) ? OP_CHOOSER_OPTMENU
1822 : OP_CHOOSER_STRING ;
1823
1824 if( !use_optmenu ) av->allow_wrap = 1 ;
1825 if( use_optmenu ) toff-- ;
1826
1827 } else { /* arbitrary string input allowed */
1828
1829 PLUGIN_strval * av = myXtNew(PLUGIN_strval) ;
1830
1831 STATUS("create PLUGIN_STRING_TYPE (free)") ;
1832 av->rowcol =
1833 XtVaCreateWidget(
1834 "AFNI" , xmRowColumnWidgetClass , wid->workwin ,
1835 XmNpacking , XmPACK_TIGHT ,
1836 XmNorientation , XmHORIZONTAL ,
1837 XmNmarginHeight, 0 ,
1838 XmNmarginWidth , 0 ,
1839 XmNspacing , 0 ,
1840 XmNtraversalOn , True ,
1841 XmNinitialResourcesPersistent , False ,
1842 NULL ) ;
1843
1844 xstr = XmStringCreateLtoR( sv->label , XmFONTLIST_DEFAULT_TAG ) ;
1845 av->label =
1846 XtVaCreateManagedWidget(
1847 "AFNI" , xmLabelWidgetClass , av->rowcol ,
1848 XmNlabelString , xstr ,
1849 XmNmarginWidth , 0 ,
1850 XmNinitialResourcesPersistent , False ,
1851 NULL ) ;
1852 XmStringFree( xstr ) ;
1853
1854 av->textf =
1855 XtVaCreateManagedWidget(
1856 "AFNI" , xmTextFieldWidgetClass , av->rowcol ,
1857 XmNcolumns , (sv->value_default > 1)
1858 ? sv->value_default : 9 ,
1859 XmNeditable , True ,
1860 XmNmaxLength , PLUGIN_STRING_SIZE ,
1861 XmNresizeWidth , False ,
1862 XmNmarginHeight , 1 ,
1863 XmNmarginWidth , 1 ,
1864 XmNcursorPositionVisible , True ,
1865 XmNblinkRate , 0 ,
1866 XmNautoShowCursorPosition , True ,
1867 XmNtraversalOn , True ,
1868 XmNinitialResourcesPersistent , False ,
1869 NULL ) ;
1870
1871 if( sv->string_range_count == -1 )
1872 XmTextFieldSetString( av->textf , sv->string_range[0] ) ;
1873
1874 XtManageChild( av->rowcol ) ;
1875
1876 ow->chooser[ib] = (void *) av ;
1877 ow->chtop[ib] = av->rowcol ; /* get the top widget */
1878
1879 ow->chooser_type[ib] = OP_CHOOSER_STRING ;
1880 }
1881 }
1882 break ;
1883
1884 /** single dataset type: make a pushbutton to popup a chooser **/
1885 /** 24 Nov 1996: adapt to include dataset list type as well **/
1886
1887 case PLUGIN_DATASET_LIST_TYPE:
1888 case PLUGIN_DATASET_TYPE:{
1889 PLUGIN_dsetval * av = myXtNew(PLUGIN_dsetval) ;
1890
1891 STATUS("create PLUGIN_DATASET_TYPE") ;
1892
1893 av->sv = sv ; /* what this is linked to */
1894
1895 av->dset_count = 0 ; /* will be array of datasets */
1896 av->dset_link = NULL ; /* we can choose amongst */
1897
1898 av->dset_choice = -1 ; /* will be index of our choice */
1899
1900 /* 24 Nov 1996 */
1901
1902 av->multi = (sv->data_type == PLUGIN_DATASET_LIST_TYPE) ;
1903 av->nchosen = 0 ;
1904 av->chosen = NULL ;
1905 av->current = 0 ;
1906 av->idclist = NULL ;
1907
1908 av->rowcol =
1909 XtVaCreateWidget(
1910 "AFNI" , xmRowColumnWidgetClass , wid->workwin ,
1911 XmNpacking , XmPACK_TIGHT ,
1912 XmNorientation , XmHORIZONTAL ,
1913 XmNmarginHeight, 0 ,
1914 XmNmarginWidth , 0 ,
1915 XmNspacing , 0 ,
1916 XmNtraversalOn , True ,
1917 XmNinitialResourcesPersistent , False ,
1918 NULL ) ;
1919
1920 xstr = XmStringCreateLtoR( sv->label , XmFONTLIST_DEFAULT_TAG ) ;
1921 av->label =
1922 XtVaCreateManagedWidget(
1923 "AFNI" , xmLabelWidgetClass , av->rowcol ,
1924 XmNlabelString , xstr ,
1925 XmNmarginWidth , 0 ,
1926 XmNinitialResourcesPersistent , False ,
1927 NULL ) ;
1928 XmStringFree( xstr ) ;
1929
1930 if( plint->flags & SHORT_CHOOSE_FLAG )
1931 xstr = XmStringCreateLtoR(
1932 (av->multi) ? "* Datasets *"
1933 : "- Dataset -" ,
1934 XmFONTLIST_DEFAULT_TAG ) ;
1935 else
1936 xstr = XmStringCreateLtoR(
1937 (av->multi) ? "** Choose Datasets *"
1938 : "-- Choose Dataset --" ,
1939 XmFONTLIST_DEFAULT_TAG ) ;
1940
1941 av->pb = XtVaCreateManagedWidget(
1942 "AFNI" , xmPushButtonWidgetClass , av->rowcol ,
1943 XmNlabelString , xstr ,
1944 XmNmarginHeight , 0 ,
1945 XmNmarginWidth , 0 ,
1946 XmNrecomputeSize , False ,
1947 XmNtraversalOn , True ,
1948 XmNuserData , (XtPointer) av ,
1949 XmNinitialResourcesPersistent , False ,
1950 NULL ) ;
1951
1952 XtAddCallback( av->pb , XmNactivateCallback ,
1953 PLUG_choose_dataset_CB , (XtPointer) plint ) ;
1954
1955 XtManageChild( av->rowcol ) ;
1956
1957 ow->chooser[ib] = (void *) av ;
1958 ow->chtop[ib] = av->rowcol ; /* get the top widget */
1959
1960 ow->chooser_type[ib] = OP_CHOOSER_DSET ;
1961 toff-- ;
1962 }
1963 break ;
1964
1965 /** single timeseries type (similiar to dataset above) **/
1966
1967 case PLUGIN_TIMESERIES_TYPE:{
1968 PLUGIN_tsval * av = myXtNew(PLUGIN_tsval) ;
1969
1970 STATUS("create PLUGIN_TIMESERIES_TYPE") ;
1971
1972 av->sv = sv ; /* a friend in need */
1973 av->tsimar = GLOBAL_library.timeseries ; /* to choose amongst */
1974 av->ts_choice = -1 ; /* no initial choice */
1975 av->tsim = NULL ;
1976
1977 av->rowcol =
1978 XtVaCreateWidget(
1979 "AFNI" , xmRowColumnWidgetClass , wid->workwin ,
1980 XmNpacking , XmPACK_TIGHT ,
1981 XmNorientation , XmHORIZONTAL ,
1982 XmNmarginHeight, 0 ,
1983 XmNmarginWidth , 0 ,
1984 XmNspacing , 0 ,
1985 XmNtraversalOn , True ,
1986 XmNheight, 20,
1987 XmNwidth, 30,
1988 XmNinitialResourcesPersistent , False ,
1989 NULL ) ;
1990
1991 xstr = XmStringCreateLtoR( sv->label , XmFONTLIST_DEFAULT_TAG ) ;
1992 av->label =
1993 XtVaCreateManagedWidget(
1994 "AFNI" , xmLabelWidgetClass , av->rowcol ,
1995 XmNlabelString , xstr ,
1996 XmNmarginWidth , 0 ,
1997 XmNinitialResourcesPersistent , False ,
1998 NULL ) ;
1999 XmStringFree( xstr ) ;
2000
2001 if( plint->flags & SHORT_CHOOSE_FLAG )
2002 xstr = XmStringCreateLtoR( "-Timeseries-",XmFONTLIST_DEFAULT_TAG ) ;
2003 else
2004 xstr = XmStringCreateLtoR( "-Choose Timeseries- ",XmFONTLIST_DEFAULT_TAG ) ;
2005
2006 av->pb = XtVaCreateManagedWidget(
2007 "AFNI" , xmPushButtonWidgetClass , av->rowcol ,
2008 XmNlabelString , xstr ,
2009 XmNmarginHeight , 0 ,
2010 XmNmarginWidth , 0 ,
2011 XmNrecomputeSize , False ,
2012 XmNtraversalOn , True ,
2013 XmNuserData , (XtPointer) av ,
2014 XmNinitialResourcesPersistent , False ,
2015 NULL ) ;
2016
2017 XtAddCallback( av->pb , XmNactivateCallback ,
2018 PLUG_choose_timeseries_CB , (XtPointer) plint ) ;
2019
2020 XtManageChild( av->rowcol ) ;
2021
2022 ow->chooser[ib] = (void *) av ;
2023 ow->chtop[ib] = av->rowcol ; /* get the top widget */
2024
2025 ow->chooser_type[ib] = OP_CHOOSER_TIMESERIES ;
2026 toff-- ;
2027 }
2028 break ;
2029
2030 /** single tcsv type (similiar to timeseries above) **/
2031
2032 case PLUGIN_TCSV_TYPE:{
2033 PLUGIN_tcsvval * av = myXtNew(PLUGIN_tcsvval) ;
2034
2035 STATUS("create PLUGIN_TCSV_TYPE") ;
2036
2037 av->sv = sv ; /* a friend in need */
2038 av->elarr = GLOBAL_library.tcsv_data ; /* to choose amongst */
2039 av->tcsv_choice = -1 ; /* no initial choice */
2040 av->tcsv_el = NULL ;
2041
2042 av->rowcol =
2043 XtVaCreateWidget(
2044 "AFNI" , xmRowColumnWidgetClass , wid->workwin ,
2045 XmNpacking , XmPACK_TIGHT ,
2046 XmNorientation , XmHORIZONTAL ,
2047 XmNmarginHeight, 0 ,
2048 XmNmarginWidth , 0 ,
2049 XmNspacing , 0 ,
2050 XmNtraversalOn , True ,
2051 XmNheight, 20,
2052 XmNwidth, 30,
2053 XmNinitialResourcesPersistent , False ,
2054 NULL ) ;
2055
2056 xstr = XmStringCreateLtoR( sv->label , XmFONTLIST_DEFAULT_TAG ) ;
2057 av->label =
2058 XtVaCreateManagedWidget(
2059 "AFNI" , xmLabelWidgetClass , av->rowcol ,
2060 XmNlabelString , xstr ,
2061 XmNmarginWidth , 0 ,
2062 XmNinitialResourcesPersistent , False ,
2063 NULL ) ;
2064 XmStringFree( xstr ) ;
2065
2066 if( plint->flags & SHORT_CHOOSE_FLAG )
2067 xstr = XmStringCreateLtoR( "-*.[tc]sv-",XmFONTLIST_DEFAULT_TAG ) ;
2068 else
2069 xstr = XmStringCreateLtoR( "-Choose *.[tc]sv -",XmFONTLIST_DEFAULT_TAG ) ;
2070
2071 av->pb = XtVaCreateManagedWidget(
2072 "AFNI" , xmPushButtonWidgetClass , av->rowcol ,
2073 XmNlabelString , xstr ,
2074 XmNmarginHeight , 0 ,
2075 XmNmarginWidth , 0 ,
2076 XmNrecomputeSize , False ,
2077 XmNtraversalOn , True ,
2078 XmNuserData , (XtPointer) av ,
2079 XmNinitialResourcesPersistent , False ,
2080 NULL ) ;
2081
2082 XtAddCallback( av->pb , XmNactivateCallback ,
2083 PLUG_choose_tcsv_CB , (XtPointer) plint ) ;
2084
2085 XtManageChild( av->rowcol ) ;
2086
2087 ow->chooser[ib] = (void *) av ;
2088 ow->chtop[ib] = av->rowcol ; /* get the top widget */
2089
2090 ow->chooser_type[ib] = OP_CHOOSER_TCSV ;
2091 toff-- ;
2092 }
2093 break ;
2094
2095 } /* end of switch on subvalue type */
2096
2097 /** set initial attachments for the topmost chooser widget **/
2098
2099 XtVaSetValues(
2100 ow->chtop[ib] ,
2101 XmNleftAttachment , (ib==0) ? XmATTACH_WIDGET /* First column */
2102 : XmATTACH_NONE , /* of widgets */
2103 XmNleftOffset , (ib==0) ? 6 /* is attached */
2104 : 0 , /* to the label. */
2105 XmNleftWidget , (ib==0) ? ow->label /* Later columns */
2106 : NULL , /* fixed below. */
2107
2108 XmNtopAttachment , (iopt==0) ? XmATTACH_FORM /* 1st row */
2109 : XmATTACH_WIDGET , /* 2nd+ row */
2110 XmNtopOffset , toff ,
2111 XmNtopWidget , separator ,
2112 NULL ) ;
2113
2114 if( opt->mandatory == FALSE ) XtSetSensitive( ow->chtop[ib] , False ) ;
2115
2116 if( sv->hint != NULL )
2117 MCW_reghint_children( ow->chtop[ib] , sv->hint ) ;
2118
2119 /** find out if this is the widest one in its column so far **/
2120
2121 MCW_widget_geom( ow->chtop[ib] , &ww , NULL,NULL,NULL ) ;
2122
2123 if( ww > widest_width[ib] ){
2124 widest_width[ib] = ww ;
2125 widest_chooser[ib] = ow->chtop[ib] ;
2126 }
2127
2128 } /* end of loop over subvalues */
2129
2130 /** separator between option rows **/
2131
2132 STATUS("create row Separator") ;
2133 separator = XtVaCreateManagedWidget(
2134 "AFNI" , xmSeparatorWidgetClass , wid->workwin ,
2135 XmNseparatorType , XmSHADOW_ETCHED_OUT ,
2136 XmNshadowThickness, 5 ,
2137 XmNleftAttachment , XmATTACH_FORM ,
2138 XmNrightAttachment, XmATTACH_FORM ,
2139 XmNtopAttachment , XmATTACH_WIDGET ,
2140 XmNtopWidget , ow->toggle ,
2141 XmNtopOffset , 7 ,
2142 NULL ) ;
2143
2144 } /* end of loop over options */
2145
2146 #if 0
2147 fprintf(stderr,"Widget attachments\n") ;
2148 #endif
2149
2150 /**** Now that we've created all the rows,
2151 and have found all the widest widgets in each column,
2152 go back and attach each column to the widest one to its left. ****/
2153
2154 for( iopt=0 ; iopt < plint->option_count ; iopt++ ){
2155 opt = plint->option[iopt] ;
2156 if( opt == NULL ) continue ; /* bad? */
2157
2158 ow = opwid[iopt] ;
2159 for( ib=1 ; ib < opt->subvalue_count ; ib++ ){
2160 XtVaSetValues( ow->chtop[ib] ,
2161 XmNleftAttachment , XmATTACH_WIDGET ,
2162 XmNleftWidget , widest_chooser[ib-1] ,
2163 XmNleftOffset , 6 ,
2164 NULL ) ;
2165 }
2166 }
2167
2168 #if 0
2169 fprintf(stderr,"Widget separators\n") ;
2170 #endif
2171
2172 /**** Create a vertical separator to the left of each column ****/
2173
2174 if( plint->option_count > 0 ){
2175 STATUS("create vertical Separators") ;
2176 for( ib=0 ; ib < PLUGIN_MAX_SUBVALUES && widest_width[ib] > 0 ; ib++ ){
2177 separator = XtVaCreateManagedWidget(
2178 "AFNI" , xmSeparatorWidgetClass , wid->workwin ,
2179 XmNseparatorType , XmSHADOW_ETCHED_OUT ,
2180 XmNorientation , XmVERTICAL ,
2181 XmNtopAttachment , XmATTACH_FORM ,
2182 XmNbottomAttachment, XmATTACH_FORM ,
2183 XmNrightAttachment , XmATTACH_WIDGET ,
2184 XmNrightWidget , widest_chooser[ib] ,
2185 XmNrightOffset , 2 ,
2186 NULL ) ;
2187
2188 }
2189 }
2190
2191 #if 0
2192 fprintf(stderr,"Widget management\n") ;
2193 #endif
2194
2195 /**** Manage the managers, and go home ****/
2196
2197 if( plint->option_count > 0 ){
2198 STATUS("management") ;
2199 XtManageChild( wid->workwin ) ;
2200 XtManageChild( wframe ) ;
2201 XtManageChild( wid->scrollw ) ;
2202 }
2203 XtManageChild( wid->form ) ;
2204
2205 #if 0
2206 fprintf(stderr,"Widget realization\n") ;
2207 #endif
2208
2209 STATUS("realization") ;
2210 XtRealizeWidget( wid->shell ) ; /* will not be mapped */
2211 NI_sleep(1) ;
2212
2213 /** set its width after it is mapped **/
2214
2215 #define OPC_MAX 8
2216 #define OPC_MAXMAX 10
2217 #define LUCK 5
2218
2219 if( wframe != NULL ){
2220 Widget bar=NULL ;
2221 int fww , fhh , fyy , bww ;
2222
2223 #if 0
2224 fprintf(stderr,"Widget geometrization\n") ;
2225 #endif
2226
2227 STATUS("geometrization") ;
2228 MCW_widget_geom( wid->label , &ww , &hh , NULL, NULL ) ; /* get dimensions */
2229 MCW_widget_geom( wframe , &fww, &fhh, NULL, NULL ) ; /* of various */
2230 MCW_widget_geom( wid->scrollw , NULL, NULL, NULL, &fyy ) ; /* pieces-parts */
2231
2232 fww = MAX( fww+LUCK , ww ) ; /* extra pixels for luck */
2233
2234 ib = plint->option_count ; /* too many options --> will use vertical scrollbar */
2235 if( ib > OPC_MAXMAX ){
2236 fhh = (OPC_MAX * fhh) / ib ; /* set height to allow for OPC_MAX options visible */
2237
2238 if( fww > ww ){ /* set width to allow for vertical scrollbar */
2239 XtVaGetValues( wid->scrollw , XmNverticalScrollBar , &bar , NULL ) ;
2240 MCW_widget_geom( bar , &bww , NULL,NULL,NULL ) ;
2241 fww += bww+LUCK+LUCK ; /* need more luck here, I guess */
2242 }
2243 }
2244 fhh += fyy+LUCK ; /* set height to allow for stuff above options */
2245
2246 XtVaSetValues( wid->shell , XmNwidth , fww , XmNheight , fhh , NULL ) ;
2247 }
2248
2249 /** set the popup meter to be nothing at all right now **/
2250
2251 wid->meter = NULL ;
2252
2253 #if 0
2254 fprintf(stderr,"Widgets done!\n") ;
2255 #endif
2256
2257 EXRETURN ;
2258 }
2259
2260 /*-----------------------------------------------------------------------
2261 21 Feb 2001: routine to turn off optional inputs
2262 -------------------------------------------------------------------------*/
2263
PLUTO_turnoff_options(PLUGIN_interface * plint)2264 void PLUTO_turnoff_options( PLUGIN_interface * plint )
2265 {
2266 int kk ;
2267
2268 ENTRY("PLUTO_turnoff_options") ;
2269
2270 /**** sanity checks ****/
2271
2272 if( plint == NULL || plint->wid == NULL ||
2273 plint->call_method == PLUGIN_CALL_IMMEDIATELY ) EXRETURN ;
2274
2275 /**** loop over options */
2276
2277 for( kk=0 ; kk < plint->option_count ; kk++ ){
2278 if( plint->option[kk]->mandatory != TRUE )
2279 XmToggleButtonSetState( plint->wid->opwid[kk]->toggle, False,True ) ;
2280 }
2281
2282 EXRETURN ;
2283 }
2284
2285 /*-----------------------------------------------------------------------
2286 What happens when a plugin interface action button is pressed
2287 -------------------------------------------------------------------------*/
2288
PLUG_action_CB(Widget w,XtPointer cd,XtPointer cbs)2289 void PLUG_action_CB( Widget w , XtPointer cd , XtPointer cbs )
2290 {
2291 PLUGIN_interface *plint = (PLUGIN_interface *) cd ;
2292 char *wname = XtName(w) ;
2293 char *mesg=NULL ;
2294 int close , run , badrun=0 , help ;
2295
2296 ENTRY("PLUG_action_CB") ;
2297
2298 run = (strcmp(wname,plint->doit_label)==0) || (strcmp(wname,plint->run_label)==0);
2299 close = (strcmp(wname,plint->doit_label)==0) || (strcmp(wname,PLUG_quit_label) ==0);
2300 help = (strcmp(wname,PLUG_help_label)==0) ;
2301
2302 if( run ){
2303 PLUG_fillin_values( plint ) ; /* load callvalues */
2304 plint->opnum = plint->svnum = -1 ; /* initialize get_ */
2305
2306 /***** CALL THE PLUGIN !!!! *****/
2307
2308 MPROBE ;
2309
2310 SHOW_AFNI_PAUSE ;
2311 #if 0
2312 mesg = plint->call_func( plint ) ;
2313 #else
2314 AFNI_CALL_VALU_1ARG( plint->call_func ,
2315 char *,mesg , PLUGIN_interface *,plint ) ;
2316 #endif
2317 SHOW_AFNI_READY ;
2318
2319 PLUTO_popdown_meter( plint ) ; /* if the user forgets */
2320
2321 MPROBE ;
2322
2323 /********************************/
2324
2325 badrun = (mesg != NULL) ;
2326 if( badrun ){
2327 if( w != NULL ){
2328 (void) MCW_popup_message( w , mesg , MCW_USER_KILL ) ;
2329 BEEPIT ;
2330 } else {
2331 fprintf(stderr,"\n%s\a\n",mesg) ;
2332 }
2333 }
2334 }
2335
2336 if( close && !badrun ) PLUG_delete_window_CB( w , cd , cbs ) ;
2337
2338 /* 28 Dec 1997: use a scrolling text window if help too big */
2339
2340 if( help ){
2341 int nl = THD_linecount( plint->helpstring ) ;
2342 if( nl < 10 ) MCW_popup_message( plint->wid->label ,
2343 plint->helpstring , MCW_USER_KILL ) ;
2344 else new_MCW_textwin ( plint->wid->label ,
2345 plint->helpstring , TEXT_READONLY ) ;
2346 }
2347
2348 EXRETURN ;
2349 }
2350
2351 /*------------------------------------------------------------------------
2352 What happens when the user selects "Close" from the window
2353 menu in a plugin interface menu window.
2354 --------------------------------------------------------------------------*/
2355
PLUG_delete_window_CB(Widget w,XtPointer cd,XtPointer cbs)2356 void PLUG_delete_window_CB( Widget w , XtPointer cd , XtPointer cbs )
2357 {
2358 PLUGIN_interface * plint = (PLUGIN_interface *) cd ;
2359
2360 ENTRY("PLUG_delete_window_CB") ;
2361
2362 if( plint != NULL && plint->wid != NULL ){
2363 XtUnmapWidget(plint->wid->shell) ;
2364 XmUpdateDisplay(plint->wid->shell) ;
2365 }
2366 EXRETURN ;
2367 }
2368
2369 /*------------------------------------------------------------------------
2370 What happens when the user toggles an option's toggle button.
2371 --------------------------------------------------------------------------*/
2372
PLUG_optional_toggle_CB(Widget w,XtPointer cd,XtPointer cbs)2373 void PLUG_optional_toggle_CB( Widget w , XtPointer cd , XtPointer cbs )
2374 {
2375 PLUGIN_option_widgets * ow = (PLUGIN_option_widgets *) cd ;
2376 int ib , zlen ;
2377 XtPointer xptr=NULL ;
2378
2379 ENTRY("PLUG_optional_toggle_CB") ;
2380
2381 /** invert label widget, and switch sensitivity of subvalue widgets **/
2382
2383 if( ow != NULL ){
2384 #if 0
2385 if( ow->label != NULL ){
2386 XtVaGetValues( ow->label , XmNuserData , &xptr , NULL ) ;
2387 zlen = (int) xptr ;
2388 if( !zlen ) MCW_invert_widget( ow->label ) ;
2389 }
2390 #endif
2391
2392 for( ib=0 ; ib < PLUGIN_MAX_SUBVALUES ; ib++ )
2393 if( ow->chtop[ib] != NULL )
2394 XtSetSensitive( ow->chtop[ib] , !XtIsSensitive(ow->chtop[ib]) ) ;
2395 }
2396 EXRETURN ;
2397 }
2398
2399 /*--------------------------------------------------------------------------
2400 Routine to take the interface widgets and put their values into
2401 place, so that the plugin can get them out again.
2402 ----------------------------------------------------------------------------*/
2403
PLUG_fillin_values(PLUGIN_interface * plint)2404 void PLUG_fillin_values( PLUGIN_interface * plint )
2405 {
2406 int iopt , ib ;
2407 PLUGIN_option_widgets ** opwid , * ow ;
2408 PLUGIN_option * opt ;
2409 PLUGIN_subvalue * sv ;
2410
2411 ENTRY("PLUG_fillin_values") ;
2412
2413 /*--- check if there is anything to do ---*/
2414
2415 if( plint == NULL || plint->option_count == 0 ) EXRETURN ;
2416
2417 /*--- scan thru options ---*/
2418
2419 opwid = plint->wid->opwid ;
2420
2421 for( iopt=0 ; iopt < plint->option_count ; iopt++){
2422
2423 opt = plint->option[iopt] ; /* option to deal with */
2424 if( opt == NULL ) continue ; /* bad? */
2425
2426 ow = opwid[iopt] ; /* row of widgets to deal with */
2427
2428 /*-- find if this option is chosen by the user --*/
2429
2430 opt->chosen = (int) XmToggleButtonGetState( ow->toggle ) ;
2431
2432 /*-- scan thru subvalues, and load callvalue.
2433 note that we do this even for unchosen options. --*/
2434
2435 for( ib=0 ; ib < opt->subvalue_count ; ib++ ){
2436
2437 myXtFree( opt->callvalue[ib] ) ; /* free any old value here */
2438 sv = &(opt->subvalue[ib]) ; /* subvalue to deal with */
2439
2440 /*-- deal with each type of subvalue --*/
2441
2442 switch( sv->data_type ){
2443
2444 /** some type I don't know, so just put NULL in **/
2445
2446 default:
2447 opt->callvalue[ib] = NULL ;
2448 break ;
2449
2450 /** 11 Jul 2001: overlay color type; send in the color index **/
2451
2452 case PLUGIN_OVERLAY_COLOR_TYPE:{
2453 MCW_arrowval *av = (MCW_arrowval *)ow->chooser[ib] ;
2454 int *iptr ;
2455
2456 iptr = (int *)XtMalloc( sizeof(int) ) ;
2457 *iptr = av->ival ;
2458 opt->callvalue[ib] = (void *) iptr ;
2459 }
2460 break ;
2461
2462 /** number type: uses arrowval interface;
2463 send in the float value **/
2464
2465 case PLUGIN_NUMBER_TYPE:{
2466 MCW_arrowval *av = (MCW_arrowval *) ow->chooser[ib] ;
2467 float *fptr ;
2468
2469 fptr = (float *) XtMalloc( sizeof(float) ) ;
2470 *fptr = av->fval ;
2471 opt->callvalue[ib] = (void *) fptr ;
2472 }
2473 break ;
2474
2475 /** string type: may be an arrowval or a strval **/
2476
2477 case PLUGIN_STRING_TYPE:{
2478 if( sv->string_range_count > 0 ){
2479 MCW_arrowval * av = (MCW_arrowval *) ow->chooser[ib] ;
2480 char * cptr ;
2481
2482 cptr = XtNewString( av->sval ) ;
2483 opt->callvalue[ib] = (void *) cptr ;
2484 } else {
2485 PLUGIN_strval * av = (PLUGIN_strval *) ow->chooser[ib] ;
2486 char * cptr ;
2487
2488 cptr = XmTextFieldGetString( av->textf ) ;
2489 opt->callvalue[ib] = (void *) cptr ;
2490 }
2491 }
2492 break ;
2493
2494 /** dataset type **/
2495
2496 case PLUGIN_DATASET_TYPE:{
2497 PLUGIN_dsetval * av = (PLUGIN_dsetval *) ow->chooser[ib] ;
2498 MCW_idcode * idc ;
2499
2500 idc = myXtNew( MCW_idcode ) ;
2501 if( av->dset_choice < 0 )
2502 ZERO_IDCODE(*idc) ;
2503 else
2504 *idc = av->dset_link[av->dset_choice].idcode ;
2505
2506 opt->callvalue[ib] = (void *) idc ;
2507 }
2508 break ;
2509
2510 /** 25 Nov 1996: list of datasets **/
2511
2512 case PLUGIN_DATASET_LIST_TYPE:{
2513 PLUGIN_dsetval * av = (PLUGIN_dsetval *) ow->chooser[ib] ;
2514 MCW_idclist ** llist ;
2515 int id ;
2516
2517 llist = myXtNew(MCW_idclist *) ; *llist = av ;
2518
2519 av->current = 0 ;
2520 if( av->nchosen <= 0 ){
2521 myXtFree(av->idclist) ;
2522 } else {
2523 av->idclist = (MCW_idcode *)
2524 XtRealloc( (char *) av->idclist ,
2525 sizeof(MCW_idcode) * av->nchosen ) ;
2526 for( id=0 ; id < av->nchosen ; id++ )
2527 av->idclist[id] = av->dset_link[av->chosen[id]].idcode ;
2528 }
2529
2530 opt->callvalue[ib] = (void *) llist ;
2531 }
2532 break ;
2533
2534 /** timeseries type **/
2535
2536 case PLUGIN_TIMESERIES_TYPE:{
2537 PLUGIN_tsval * av = (PLUGIN_tsval *) ow->chooser[ib] ;
2538 MRI_IMAGE ** imp ;
2539
2540 imp = myXtNew(MRI_IMAGE *) ;
2541 *imp = av->tsim ;
2542
2543 opt->callvalue[ib] = (void *) imp ;
2544 }
2545 break ;
2546
2547 /** tcsv type **/
2548
2549 case PLUGIN_TCSV_TYPE:{
2550 PLUGIN_tcsvval * av = (PLUGIN_tcsvval *) ow->chooser[ib] ;
2551 NI_element ** imp ;
2552
2553 imp = myXtNew(NI_element *) ;
2554 *imp = av->tcsv_el ;
2555
2556 opt->callvalue[ib] = (void *) imp ;
2557 }
2558 break ;
2559
2560 } /* end of switch over subvalue type */
2561 } /* end of scan thru subvalues */
2562 } /* end of scan thru options */
2563
2564 EXRETURN ;
2565 }
2566
2567 /*--------------------------------------------------------------------------
2568 Routine to take the interface widgets and clear their callvalues to NULL.
2569 ----------------------------------------------------------------------------*/
2570
PLUG_freeup_values(PLUGIN_interface * plint)2571 void PLUG_freeup_values( PLUGIN_interface * plint )
2572 {
2573 int iopt , ib ;
2574 PLUGIN_option * opt ;
2575
2576 ENTRY("PLUG_freeup_values") ;
2577
2578 /*--- check if there is anything to do ---*/
2579
2580 if( plint == NULL || plint->option_count == 0 ) EXRETURN ;
2581
2582 /*--- scan thru options ---*/
2583
2584 for( iopt=0 ; iopt < plint->option_count ; iopt++){
2585
2586 opt = plint->option[iopt] ; /* option to deal with */
2587 if( opt == NULL ) continue ; /* bad? */
2588
2589 /*-- scan thru subvalues, and free all callvalues --*/
2590
2591 for( ib=0 ; ib < opt->subvalue_count ; ib++ ){
2592 XtFree( opt->callvalue[ib] ) ; /* free any old value here */
2593 opt->callvalue[ib] = NULL ;
2594 }
2595
2596 } /* end of scan thru options */
2597
2598 EXRETURN ;
2599 }
2600
2601 /*-----------------------------------------------------------------------
2602 Routines to get values from a plugin interface, when passed
2603 to a plugin.
2604 -------------------------------------------------------------------------*/
2605
get_label_from_PLUGIN_interface(PLUGIN_interface * plint)2606 char * get_label_from_PLUGIN_interface( PLUGIN_interface * plint )
2607 {
2608 ENTRY("get_label_from_PLUGIN_interface") ;
2609 if( plint == NULL ) RETURN(NULL) ;
2610 else RETURN(plint->label) ;
2611 }
2612
2613 /*-----------------------------------------------------------------------*/
2614
get_description_from_PLUGIN_interface(PLUGIN_interface * plint)2615 char * get_description_from_PLUGIN_interface( PLUGIN_interface * plint )
2616 {
2617 ENTRY("get_description_from_PLUGIN_interface") ;
2618 if( plint == NULL ) RETURN(NULL) ;
2619 else RETURN(plint->description) ;
2620 }
2621
2622 /*-----------------------------------------------------------------------
2623 Get the next chosen option, and return its string "tag".
2624 If there is no "next chosen option", return NULL.
2625 -------------------------------------------------------------------------*/
2626
get_optiontag_from_PLUGIN_interface(PLUGIN_interface * plint)2627 char * get_optiontag_from_PLUGIN_interface( PLUGIN_interface * plint )
2628 {
2629 int iopt ;
2630 PLUGIN_option * opt ;
2631
2632 ENTRY("get_optiontag_from_PLUGIN_interface") ;
2633
2634 if( plint == NULL ) RETURN(NULL) ;
2635
2636 iopt = plint->opnum + 1 ;
2637 while( iopt < plint->option_count ){
2638
2639 opt = plint->option[iopt++] ;
2640 if( opt == NULL ) continue ; /* bad? */
2641 if( ! opt->chosen ) continue ; /* not used this time */
2642
2643 plint->opnum = iopt-1 ; /* keep track of which option */
2644 plint->svnum = 0 ; /* start at 1st subvalue */
2645 RETURN(opt->tag) ;
2646 }
2647
2648 plint->opnum = plint->option_count ;
2649 RETURN(NULL) ;
2650 }
2651
2652 /*-----------------------------------------------------------------------
2653 Return a string encaspulating information about how the plugin
2654 was called. This string is created with malloc() and should be
2655 free()-ed when it is used up. If NULL is returned, an error
2656 occurred (and you should be ashamed of yourself).
2657 -- 31 Aug 1999 -- RWCox
2658 -------------------------------------------------------------------------*/
2659
2660 #include <stdarg.h>
2661
blanktrim(char * ch)2662 static void blanktrim( char * ch )
2663 {
2664 int ii , ll ;
2665 if( ch == NULL ) return ;
2666 ll = strlen(ch) ; if( ll < 2 ) return ;
2667 for( ii=ll-1 ; ii > 0 ; ii-- )
2668 if( isspace(ch[ii]) ) ch[ii] = '\0' ; else break ;
2669 return ;
2670 }
2671
2672 #undef BUFIT
2673 #define BUFIT(s) do{ strcpy(buf,s); blanktrim(buf); } while(0)
2674
PLUTO_commandstring(PLUGIN_interface * plint)2675 char * PLUTO_commandstring( PLUGIN_interface * plint )
2676 {
2677 char * outbuf = NULL ;
2678 PLUGIN_option * opt ;
2679 PLUGIN_subvalue * sv ;
2680 int iopt , jsv ;
2681 char buf[256] ;
2682
2683 ENTRY("PLUTO_commandstring") ;
2684
2685 if( plint == NULL ) RETURN(outbuf) ;
2686
2687 BUFIT(plint->label) ;
2688 outbuf = THD_zzprintf( outbuf , "%s " , buf ) ; /* start with name */
2689
2690 if( plint->call_method != PLUGIN_CALL_VIA_MENU ||
2691 plint->option_count == 0 ||
2692 plint->option == NULL ) RETURN(outbuf) ;
2693
2694 /* loop over each option for the plugin */
2695
2696 for( iopt=0 ; iopt < plint->option_count ; iopt++ ){
2697 opt = plint->option[iopt] ;
2698 if( opt == NULL ) continue ; /* bad? */
2699 if( ! opt->chosen ) continue ; /* not used this time */
2700
2701 BUFIT(opt->label) ;
2702 outbuf = THD_zzprintf( outbuf , "{%s: " , buf ) ;
2703
2704 /* if this option is used, put a list of its subvalues in the string */
2705
2706 for( jsv=0 ; jsv < opt->subvalue_count ; jsv++ ){
2707 sv = &(opt->subvalue[jsv]) ;
2708 BUFIT(sv->label) ;
2709 outbuf = THD_zzprintf( outbuf , "%s=" , buf ) ;
2710 switch( sv->data_type ){
2711
2712 default:
2713 outbuf = THD_zzprintf( outbuf,"?" ) ; break ;
2714
2715 case PLUGIN_OVERLAY_COLOR_TYPE:{
2716 int *val = (int *) opt->callvalue[jsv] ;
2717 MCW_DC *dc = plint->im3d->dc ;
2718 if( val != NULL && *val >= 0 )
2719 outbuf = THD_zzprintf( outbuf,"%s",dc->ovc->label_ov[*val] );
2720 else
2721 outbuf = THD_zzprintf( outbuf,"?" ) ;
2722 }
2723 break ;
2724
2725 case PLUGIN_NUMBER_TYPE:{
2726 float * val = (float *) opt->callvalue[jsv] ;
2727 if( val != NULL ) outbuf = THD_zzprintf( outbuf,"%g",*val) ;
2728 else outbuf = THD_zzprintf( outbuf,"?" ) ;
2729 }
2730 break ;
2731
2732 case PLUGIN_STRING_TYPE:{
2733 char * val = (char *) opt->callvalue[jsv] ;
2734 if( val != NULL ){ BUFIT(val); outbuf = THD_zzprintf( outbuf,"%s",buf); }
2735 else outbuf = THD_zzprintf( outbuf,"?" ) ;
2736 }
2737 break ;
2738
2739 case PLUGIN_DATASET_LIST_TYPE:{
2740 MCW_idclist ** llist = (MCW_idclist **) opt->callvalue[jsv] ;
2741 int nd = PLUTO_idclist_count(*llist) ;
2742 outbuf = THD_zzprintf( outbuf , "[%d dsets]" , nd ) ;
2743 }
2744 break ;
2745
2746 case PLUGIN_DATASET_TYPE:{
2747 MCW_idcode * idc = (MCW_idcode *) opt->callvalue[jsv] ;
2748 THD_3dim_dataset * dset ;
2749
2750 dset = PLUTO_find_dset( idc ) ;
2751 if( dset != NULL ){
2752 char * qb = THD_trailname(DSET_HEADNAME(dset),SESSTRAIL+1) ;
2753 outbuf = THD_zzprintf( outbuf,"%s",qb) ;
2754 } else
2755 outbuf = THD_zzprintf( outbuf,"?" ) ;
2756 }
2757 break ;
2758
2759 case PLUGIN_TIMESERIES_TYPE:{
2760 MRI_IMAGE ** imp = (MRI_IMAGE **) opt->callvalue[jsv] ;
2761
2762 if( imp != NULL && *imp != NULL && (*imp)->name != NULL )
2763 outbuf = THD_zzprintf( outbuf,"%s",(*imp)->name ) ;
2764 else
2765 outbuf = THD_zzprintf( outbuf,"?" ) ;
2766 }
2767 break ;
2768
2769 } /* end of switch on subvalue type */
2770
2771 if( jsv < opt->subvalue_count - 1 )
2772 outbuf = THD_zzprintf( outbuf,"; ") ;
2773
2774 } /* end of loop on subvalues */
2775
2776 outbuf = THD_zzprintf( outbuf , "} " ) ; /* end of this option */
2777
2778 } /* end of loop on options */
2779
2780 RETURN(outbuf) ;
2781 }
2782
2783 /*-------------------------------------------------------------------------
2784 Find out what the next chosen option is, without actually retrieving it.
2785 ---------------------------------------------------------------------------*/
2786
peek_optiontag_from_PLUGIN_interface(PLUGIN_interface * plint)2787 char * peek_optiontag_from_PLUGIN_interface( PLUGIN_interface * plint )
2788 {
2789 int iopt ;
2790 PLUGIN_option * opt ;
2791
2792 ENTRY("peek_optiontag_from_PLUGIN_interface") ;
2793
2794 if( plint == NULL ) RETURN(NULL) ;
2795
2796 iopt = plint->opnum + 1 ;
2797 while( iopt < plint->option_count ){
2798 opt = plint->option[iopt++] ;
2799 if( opt == NULL ) continue ; /* bad? */
2800 if( opt->chosen ) RETURN(opt->tag) ;
2801 }
2802 RETURN(NULL) ;
2803 }
2804
2805 /*-------------------------------------------------------------------------
2806 Find out what the next subvalue type is, without actually retrieving it.
2807 This will be one of the PLUGIN_*_TYPE codes. If something is wrong,
2808 the return value will be ILLEGAL_TYPE. This can be used to detect that
2809 no more subvalues are present in the option currently being processed.
2810 ---------------------------------------------------------------------------*/
2811
peek_callvalue_type_from_PLUGIN_interface(PLUGIN_interface * plint)2812 int peek_callvalue_type_from_PLUGIN_interface( PLUGIN_interface * plint )
2813 {
2814 int isv ;
2815 PLUGIN_option * opt ;
2816
2817 ENTRY("peek_callvalue_type_from_PLUGIN_interface") ;
2818
2819 if( plint == NULL ) RETURN(ILLEGAL_TYPE) ;
2820 if( plint->opnum >= plint->option_count ) RETURN(ILLEGAL_TYPE) ;
2821
2822 opt = plint->option[ plint->opnum ] ;
2823 if( opt == NULL ) RETURN(ILLEGAL_TYPE) ;
2824
2825 isv = plint->svnum ;
2826 if( isv >= opt->subvalue_count ) RETURN(ILLEGAL_TYPE) ;
2827
2828 RETURN(opt->subvalue[isv].data_type) ;
2829 }
2830
2831 /*-------------------------------------------------------------------------
2832 Get the next subvalue, which should be of the type given by
2833 "type". If it is not, return NULL, otherwise return a "void *",
2834 which must be properly de-referenced to get the true value:
2835
2836 type output is really
2837 ------------------ ----------------
2838 PLUGIN_NUMBER_TYPE float * points to number
2839 PLUGIN_STRING_TYPE char * duh
2840 PLUGIN_DATASET_TYPE MCW_idcode * duh
2841 PLUGIN_TIMESERIES_TYPE MRI_IMAGE ** duh
2842 PLUGIN_OVERLAY_COLOR_TYPE int * points to overlay index
2843
2844 Following this are convenience routines to do similar work on specific
2845 data types.
2846 ---------------------------------------------------------------------------*/
2847
get_callvalue_from_PLUGIN_interface(PLUGIN_interface * plint,int type)2848 void * get_callvalue_from_PLUGIN_interface( PLUGIN_interface * plint , int type )
2849 {
2850 int isv ;
2851 PLUGIN_option * opt ;
2852
2853 ENTRY("get_callvalue_from_PLUGIN_interface") ;
2854
2855 if( plint == NULL ) RETURN( NULL );
2856
2857 opt = plint->option[ plint->opnum ] ;
2858 if( opt == NULL ) RETURN( NULL );
2859
2860 isv = plint->svnum ;
2861 if( isv >= opt->subvalue_count ) RETURN( NULL );
2862
2863 if( opt->subvalue[isv].data_type != type ) RETURN( NULL );
2864
2865 plint->svnum ++ ;
2866 RETURN( opt->callvalue[isv] );
2867 }
2868
2869 /*----------------------------------------------------------------------------*/
2870
get_timeseries_from_PLUGIN_interface(PLUGIN_interface * plint)2871 MRI_IMAGE * get_timeseries_from_PLUGIN_interface( PLUGIN_interface * plint )
2872 {
2873 MRI_IMAGE ** imp ;
2874
2875 ENTRY("get_timeseries_from_PLUGIN_interface") ;
2876
2877 imp = (MRI_IMAGE **)
2878 get_callvalue_from_PLUGIN_interface(plint,PLUGIN_TIMESERIES_TYPE) ;
2879
2880 if( imp == NULL ) RETURN(NULL) ;
2881 RETURN(*imp) ;
2882 }
2883
2884 /*----------------------------------------------------------------------------*/
2885
get_tcsv_from_PLUGIN_interface(PLUGIN_interface * plint)2886 NI_element * get_tcsv_from_PLUGIN_interface( PLUGIN_interface * plint )
2887 {
2888 NI_element ** imp ;
2889
2890 ENTRY("get_tcsv_from_PLUGIN_interface") ;
2891
2892 imp = (NI_element **)
2893 get_callvalue_from_PLUGIN_interface(plint,PLUGIN_TCSV_TYPE) ;
2894
2895 if( imp == NULL ) RETURN(NULL) ;
2896 RETURN(*imp) ;
2897 }
2898
2899 /*----------------------------------------------------------------------------*/
2900
get_number_from_PLUGIN_interface(PLUGIN_interface * plint)2901 float get_number_from_PLUGIN_interface( PLUGIN_interface * plint )
2902 {
2903 float * fp ;
2904 ENTRY("get_number_from_PLUGIN_interface") ;
2905 fp = (float *)get_callvalue_from_PLUGIN_interface(plint,PLUGIN_NUMBER_TYPE) ;
2906 if( fp == NULL ) RETURN(BAD_NUMBER) ;
2907 RETURN(*fp) ;
2908 }
2909
2910 /*----------------------------------------------------------------------------*/
2911
get_overlaycolor_from_PLUGIN_interface(PLUGIN_interface * plint)2912 int get_overlaycolor_from_PLUGIN_interface( PLUGIN_interface * plint )
2913 {
2914 int * ip ;
2915 ENTRY("get_overlaycolor_from_PLUGIN_interface") ;
2916 ip = (int *)get_callvalue_from_PLUGIN_interface(plint,PLUGIN_OVERLAY_COLOR_TYPE) ;
2917 if( ip == NULL ) RETURN(-1) ;
2918 RETURN(*ip) ;
2919 }
2920
2921 /*----------------------------------------------------------------------------*/
2922
get_string_from_PLUGIN_interface(PLUGIN_interface * plint)2923 char * get_string_from_PLUGIN_interface( PLUGIN_interface * plint )
2924 {
2925 ENTRY("get_string_from_PLUGIN_interface") ;
2926 RETURN(
2927 (char *) get_callvalue_from_PLUGIN_interface(plint,PLUGIN_STRING_TYPE) );
2928 }
2929
2930 /*----------------------------------------------------------------------------*/
2931
get_idcode_from_PLUGIN_interface(PLUGIN_interface * plint)2932 MCW_idcode * get_idcode_from_PLUGIN_interface( PLUGIN_interface * plint )
2933 {
2934 ENTRY("get_idcode_from_PLUGIN_interface") ;
2935 RETURN(
2936 (MCW_idcode *)get_callvalue_from_PLUGIN_interface(plint,PLUGIN_DATASET_TYPE) );
2937 }
2938
2939 /*----------------------------------------------------------------------------*/
2940
get_idclist_from_PLUGIN_interface(PLUGIN_interface * plint)2941 MCW_idclist * get_idclist_from_PLUGIN_interface( PLUGIN_interface * plint )
2942 {
2943 MCW_idclist ** llist ;
2944
2945 ENTRY("get_idclist_from_PLUGIN_interface") ;
2946
2947 llist = (MCW_idclist **)
2948 get_callvalue_from_PLUGIN_interface(plint,PLUGIN_DATASET_LIST_TYPE) ;
2949
2950 if( llist != NULL ) RETURN(*llist) ;
2951 RETURN(NULL) ;
2952 }
2953
2954 /*------------------------------------------------------------------------
2955 What happens when a dataset chooser button is pressed:
2956 1) Retrieve the pointers to the data structures associated
2957 with the button.
2958 2) Select the datasets that are allowable and make a list of
2959 their names and idcodes.
2960 3) Popup a strlist chooser to let the user make the choice.
2961
2962 24 Nov 1996: add the option for multiple choices, flagged by av->multi.
2963 --------------------------------------------------------------------------*/
2964
PLUG_choose_dataset_CB(Widget w,XtPointer cd,XtPointer cbs)2965 void PLUG_choose_dataset_CB( Widget w , XtPointer cd , XtPointer cbs )
2966 {
2967 PLUGIN_interface * plint = (PLUGIN_interface *) cd ;
2968 PLUGIN_dsetval * av = NULL ;
2969 PLUGIN_subvalue * sv = NULL ;
2970 Three_D_View * im3d ;
2971
2972 THD_session * ss ;
2973 THD_3dim_dataset * dset ;
2974 int iss_bot , iss_top , iss , vv ;
2975 int id , num_dset , qd ;
2976 MCW_idcode old_idcode ;
2977 static char ** strlist = NULL ;
2978 char label[64] ;
2979 int llen , ltop ;
2980 char qnam[THD_MAX_NAME+2048] ;
2981
2982 int num_old = 0 , qold ; /* multi-choice stuff */
2983 MCW_idcode * old_chosen = NULL ;
2984 int * indold = NULL ;
2985
2986 ENTRY("PLUG_choose_dataset_CB") ;
2987
2988 /** find the stuff that is associated with this button **/
2989
2990 XtVaGetValues( w , XmNuserData , &av , NULL ) ;
2991
2992 if( plint == NULL || av == NULL ) EXRETURN ;
2993 sv = av->sv ;
2994 if( sv == NULL ) EXRETURN ;
2995 im3d = plint->im3d ;
2996
2997 /** Select the datasets **/
2998
2999 if( ! IM3D_VALID(im3d) || (sv->dset_ctrl_mask & SESSION_ALL_MASK) != 0 ){
3000 iss_bot = 0 ;
3001 iss_top = GLOBAL_library.sslist->num_sess - 1 ;
3002 } else {
3003 iss_bot = iss_top = im3d->vinfo->sess_num ;
3004 }
3005
3006 if( im3d != NULL ) vv = im3d->vinfo->view_type ; /* select view type */
3007 else vv = VIEW_ORIGINAL_TYPE ;
3008
3009 /** Save the current selection, if any **/
3010
3011 if( ! av->multi ){
3012 if( av->dset_choice >= 0 && av->dset_choice < av->dset_count )
3013 old_idcode = av->dset_link[av->dset_choice].idcode ;
3014 else
3015 ZERO_IDCODE(old_idcode) ;
3016 } else {
3017 for( id=0 ; id < av->nchosen ; id++ ){
3018 if( av->chosen[id] >= 0 && av->chosen[id] < av->dset_count ){
3019 num_old++ ;
3020 old_chosen = (MCW_idcode *) XtRealloc((char *)old_chosen,
3021 sizeof(MCW_idcode)*num_old) ;
3022 old_chosen[num_old-1] = av->dset_link[av->chosen[id]].idcode ;
3023 }
3024 }
3025 }
3026
3027 /** Scan sessions **/
3028
3029 num_dset = 0 ;
3030 for( iss=iss_bot ; iss <= iss_top ; iss++ ){
3031 ss = GLOBAL_library.sslist->ssar[iss] ;
3032
3033 /* check datasets in this session */
3034
3035 for( id=0 ; id < ss->num_dsset ; id++ ){
3036 dset = GET_SESSION_DSET(ss, id, vv);
3037 /* dset = ss->dsset_xform_table[id][vv] ; */
3038 if( dset == NULL ) continue ;
3039
3040 if( sv->dset_anat_mask != 0 && ISANAT(dset) )
3041 if( ! PLUGIN_dset_check( sv->dset_anat_mask ,
3042 sv->dset_ctrl_mask , dset ) ) continue ;
3043
3044 if( sv->dset_func_mask != 0 && ISFUNC(dset) )
3045 if( ! PLUGIN_dset_check( sv->dset_func_mask ,
3046 sv->dset_ctrl_mask , dset ) ) continue ;
3047
3048 /* if we get here, then this dataset is OK to choose! */
3049
3050 num_dset++ ;
3051 av->dset_link = (PLUGIN_dataset_link *)
3052 XtRealloc( (char *) av->dset_link ,
3053 sizeof(PLUGIN_dataset_link)*num_dset ) ;
3054
3055 make_PLUGIN_dataset_link( dset , av->dset_link + (num_dset-1) ) ;
3056 }
3057
3058 } /* end of loop over sessions */
3059
3060 /*--- if nothing was found that fits, then nothing further can happen ---*/
3061
3062 if( num_dset == 0 ){
3063 av->dset_count = 0 ;
3064 av->dset_choice = -1 ;
3065 myXtFree(old_chosen) ;
3066 BEEPIT ;
3067 EXRETURN ;
3068 }
3069
3070 /*--- 23 Nov 1996: loop over dataset links and patch their titles
3071 to include an indicator of the dataset type ---*/
3072
3073 ltop = 4 ;
3074 for( id=0 ; id < num_dset ; id++ ){
3075 llen = strlen(av->dset_link[id].title) ;
3076 ltop = MAX(ltop,llen) ;
3077 }
3078
3079 for( id=0 ; id < num_dset ; id++ ){
3080 dset = PLUTO_find_dset( &(av->dset_link[id].idcode) ) ;
3081 if( ! ISVALID_3DIM_DATASET(dset) ) continue ;
3082 if( ISANAT(dset) ){
3083 if( ISANATBUCKET(dset) ) /* 30 Nov 1997 */
3084 sprintf(qnam,"%-*s [%s:%d]" ,
3085 ltop,av->dset_link[id].title ,
3086 ANAT_prefixstr[dset->func_type] , DSET_NVALS(dset) ) ;
3087
3088 else if( DSET_NUM_TIMES(dset) == 1 )
3089 sprintf(qnam,"%-*s [%s]" ,
3090 ltop,av->dset_link[id].title ,
3091 ANAT_prefixstr[dset->func_type] ) ;
3092
3093 else
3094 sprintf(qnam,"%-*s [%s:3D+t:%d]" ,
3095 ltop,av->dset_link[id].title ,
3096 ANAT_prefixstr[dset->func_type] , DSET_NUM_TIMES(dset) ) ;
3097
3098 } else {
3099 if( ISFUNCBUCKET(dset) ) /* 30 Nov 1997 */
3100 sprintf(qnam,"%-*s [%s:%d]" ,
3101 ltop,av->dset_link[id].title ,
3102 FUNC_prefixstr[dset->func_type] , DSET_NVALS(dset) ) ;
3103
3104 else if( DSET_NUM_TIMES(dset) == 1 )
3105 sprintf(qnam,"%-*s [%s]" ,
3106 ltop,av->dset_link[id].title ,
3107 FUNC_prefixstr[dset->func_type] ) ;
3108
3109 else
3110 sprintf(qnam,"%-*s [%s:3D+t:%d]" ,
3111 ltop,av->dset_link[id].title ,
3112 FUNC_prefixstr[dset->func_type] , DSET_NVALS(dset) ) ;
3113 }
3114
3115 if( DSET_COMPRESSED(dset) ) strcat(qnam,"z") ;
3116
3117 strcpy( av->dset_link[id].title , qnam ) ;
3118 }
3119
3120 /*--- find the old choice in the current list, if any ---*/
3121
3122 av->dset_count = num_dset ;
3123
3124 if( ! av->multi ){
3125 if( !ISZERO_IDCODE(old_idcode) ){
3126 for( id=0 ; id < num_dset ; id++ )
3127 if( EQUIV_IDCODES(old_idcode,av->dset_link[id].idcode) ) break ;
3128
3129 if( id < num_dset ) av->dset_choice = id ;
3130 else av->dset_choice = -1 ;
3131 }
3132 } else {
3133 qold = 0 ;
3134 for( qd=0 ; qd < num_old ; qd++ ){
3135 if( !ISZERO_IDCODE(old_chosen[qd]) ){
3136 for( id=0 ; id < num_dset ; id++ )
3137 if( EQUIV_IDCODES(old_chosen[qd],av->dset_link[id].idcode) ) break ;
3138
3139 if( id < num_dset ){
3140 qold++ ;
3141 indold = (int *) XtRealloc((char *)indold , sizeof(int)*qold) ;
3142 indold[qold-1] = id ;
3143 av->chosen[qold-1] = id ;
3144 }
3145 }
3146 }
3147 av->nchosen = qold ;
3148 if( qold > 0 ){
3149 qold++ ;
3150 indold = (int *) XtRealloc((char *)indold , sizeof(int)*qold) ;
3151 indold[qold-1] = -666 ;
3152 }
3153 }
3154
3155 /*--- make a popup chooser for the user to browse ---*/
3156
3157 POPDOWN_strlist_chooser ;
3158
3159 strlist = (char **) XtRealloc( (char *)strlist , sizeof(char *)*num_dset ) ;
3160 for( id=0 ; id < num_dset ; id++ ) strlist[id] = av->dset_link[id].title ;
3161
3162 sprintf( label , "AFNI Dataset from\nthe %s" , VIEW_typestr[vv] ) ;
3163
3164 if( av->multi ){
3165 MCW_choose_multi_strlist( w , label , mcwCT_multi_mode ,
3166 num_dset , indold , strlist ,
3167 PLUG_finalize_dataset_CB , (XtPointer) plint ) ;
3168 } else {
3169 MCW_choose_strlist( w , label ,
3170 num_dset , av->dset_choice , strlist ,
3171 PLUG_finalize_dataset_CB , (XtPointer) plint ) ;
3172 }
3173
3174 myXtFree(indold) ; myXtFree(old_chosen) ;
3175 EXRETURN ;
3176 }
3177
3178 /*-----------------------------------------------------------------------
3179 Called when the user actually selects a dataset from the chooser.
3180 This routine just changes the original pushbutton label, and
3181 notes the index of the choice in the right place, for later retrieval.
3182 -------------------------------------------------------------------------*/
3183
PLUG_finalize_dataset_CB(Widget w,XtPointer fd,MCW_choose_cbs * cbs)3184 void PLUG_finalize_dataset_CB( Widget w, XtPointer fd, MCW_choose_cbs * cbs )
3185 {
3186 PLUGIN_interface * plint = (PLUGIN_interface *) fd ;
3187 PLUGIN_dsetval * av = NULL ;
3188 XmString xstr ;
3189 int id ;
3190 char str[THD_MAX_NAME], *shrtit=NULL;
3191
3192 ENTRY("PLUG_finalize_dataset_CB") ;
3193
3194 /** find the stuff that is associated with this button **/
3195
3196 XtVaGetValues( w , XmNuserData , &av , NULL ) ;
3197 if( plint == NULL || av == NULL ) EXRETURN ;
3198
3199 shrtit = TrimString(av->dset_link[cbs->ival].title, 20); /* ZSS Jan 2012*/
3200 if( ! av->multi ){
3201 xstr = XmStringCreateLtoR( shrtit ,
3202 XmFONTLIST_DEFAULT_TAG ) ;
3203 } else {
3204 sprintf( str , "[%d]%s" , cbs->nilist , shrtit ) ;
3205 xstr = XmStringCreateLtoR( str , XmFONTLIST_DEFAULT_TAG ) ;
3206 }
3207 XtVaSetValues( w , XmNlabelString , xstr , NULL ) ;
3208 XmStringFree( xstr ) ;
3209
3210 if( ! av->multi ){
3211 av->dset_choice = cbs->ival ;
3212 } else {
3213 av->nchosen = cbs->nilist ;
3214 av->chosen = (int *) XtRealloc( (char *) av->chosen ,
3215 sizeof(int) * av->nchosen ) ;
3216 for( id=0 ; id < av->nchosen ; id++ ) av->chosen[id] = cbs->ilist[id] ;
3217 }
3218
3219 EXRETURN ;
3220 }
3221
3222 /*-----------------------------------------------------------------------
3223 Fill in a PLUGIN_dataset_link
3224 -------------------------------------------------------------------------*/
3225
make_PLUGIN_dataset_link(THD_3dim_dataset * dset,PLUGIN_dataset_link * dsl)3226 void make_PLUGIN_dataset_link( THD_3dim_dataset * dset ,
3227 PLUGIN_dataset_link * dsl )
3228 {
3229 char nam[THD_MAX_NAME+2048] ;
3230 char * tnam ;
3231
3232 ENTRY("make_PLUGIN_dataset_link") ;
3233
3234 /*-- sanity checks --*/
3235
3236 if( dsl == NULL ) EXRETURN ;
3237
3238 if( ! ISVALID_3DIM_DATASET(dset) ){ /* should not happen */
3239 strcpy( dsl->title , "* garbage :( *" ) ;
3240 ZERO_IDCODE( dsl->idcode ) ;
3241 EXRETURN ;
3242 }
3243
3244 /*-- make title (cf. AFNI_set_window_titles) --*/
3245
3246 strcpy( nam , dset->dblk->diskptr->directory_name ) ;
3247 strcat( nam , dset->dblk->diskptr->filecode ) ;
3248 tnam = THD_trailname(nam,SESSTRAIL+1) ;
3249 MCW_strncpy( dsl->title , tnam , PLUGIN_STRING_SIZE ) ;
3250
3251 /*-- copy idcode --*/
3252
3253 dsl->idcode = dset->idcode ;
3254
3255 EXRETURN ;
3256 }
3257
3258 /*-----------------------------------------------------------------------
3259 Determine if a dataset passes the type_mask and ctrl_mask
3260 criteria for acceptability.
3261 -------------------------------------------------------------------------*/
3262
PLUTO_dset_check(int anat_mask,int func_mask,int ctrl_mask,THD_3dim_dataset * dset)3263 int PLUTO_dset_check( int anat_mask, int func_mask,
3264 int ctrl_mask, THD_3dim_dataset * dset )
3265 {
3266 int iv=0 ;
3267
3268 if( ISANAT(dset) )
3269 iv = PLUGIN_dset_check( anat_mask , ctrl_mask , dset ) ;
3270 else if( ISFUNC(dset) )
3271 iv = PLUGIN_dset_check( func_mask , ctrl_mask , dset ) ;
3272
3273 return iv ;
3274 }
3275
PLUGIN_dset_check(int type_mask,int ctrl_mask,THD_3dim_dataset * dset)3276 int PLUGIN_dset_check( int type_mask , int ctrl_mask , THD_3dim_dataset * dset )
3277 {
3278 int itmp ;
3279
3280 ENTRY("PLUGIN_dset_check") ;
3281
3282 if( ! ISVALID_3DIM_DATASET(dset) ) RETURN(0) ;
3283
3284 if( ((1 << dset->func_type) & type_mask) == 0 ) RETURN(0) ;
3285
3286 itmp = (DSET_NVALS(dset) > 1) ? DIMEN_4D_MASK : DIMEN_3D_MASK ;
3287 if( (itmp & ctrl_mask) == 0 ) RETURN(0) ;
3288
3289 if( !DSET_INMEMORY(dset) && (ctrl_mask & WARP_ON_DEMAND_MASK) == 0 ) RETURN(0) ;
3290
3291 itmp = DSET_PRINCIPAL_VALUE(dset) ; /* get the type of */
3292 itmp = DSET_BRICK_TYPE(dset,itmp) ; /* the "principal" brick */
3293
3294 if( itmp == MRI_byte && (ctrl_mask & BRICK_BYTE_MASK) == 0 ) RETURN(0) ;
3295 if( itmp == MRI_short && (ctrl_mask & BRICK_SHORT_MASK) == 0 ) RETURN(0) ;
3296 if( itmp == MRI_float && (ctrl_mask & BRICK_FLOAT_MASK) == 0 ) RETURN(0) ;
3297 if( itmp == MRI_complex && (ctrl_mask & BRICK_COMPLEX_MASK) == 0 ) RETURN(0) ;
3298 if( itmp == MRI_rgb && (ctrl_mask & BRICK_RGB_MASK) == 0 ) RETURN(0) ;
3299
3300 RETURN(1) ;
3301 }
3302
3303 /*-------------------------------------------------------------------------
3304 Loop over a bunch of dataset links and patch their
3305 titles to include an indicator of the dataset type, etc.
3306 23 October 1998 -- RWCox
3307 ---------------------------------------------------------------------------*/
3308
patch_PLUGIN_dataset_links(int ndsl,PLUGIN_dataset_link * dsl)3309 void patch_PLUGIN_dataset_links( int ndsl , PLUGIN_dataset_link * dsl )
3310 {
3311 int id , ltop , llen ;
3312 char qnam[THD_MAX_NAME] ;
3313 THD_3dim_dataset * dset ;
3314
3315 ENTRY("patch_PLUGIN_dataset_links") ;
3316
3317 if( ndsl < 1 || dsl == NULL ) EXRETURN ;
3318
3319 ltop = 4 ;
3320 for( id=0 ; id < ndsl ; id++ ){ /* find longest string */
3321 llen = strlen(dsl[id].title) ;
3322 ltop = MAX(ltop,llen) ;
3323 }
3324
3325 /* patch each title string */
3326
3327 for( id=0 ; id < ndsl ; id++ ){
3328 dset = PLUTO_find_dset( &(dsl[id].idcode) ) ; /* get the dataset */
3329 if( ! ISVALID_3DIM_DATASET(dset) ) continue ; /* bad news for Bozo */
3330
3331 if( ISANAT(dset) ){
3332 if( ISANATBUCKET(dset) ) /* 30 Nov 1997 */
3333 sprintf(qnam,"%-*s [%s:%d]" ,
3334 ltop,dsl[id].title ,
3335 ANAT_prefixstr[dset->func_type] , DSET_NVALS(dset) ) ;
3336
3337 else if( DSET_NUM_TIMES(dset) == 1 )
3338 sprintf(qnam,"%-*s [%s]" ,
3339 ltop,dsl[id].title ,
3340 ANAT_prefixstr[dset->func_type] ) ;
3341
3342 else
3343 sprintf(qnam,"%-*s [%s:3D+t:%d]" ,
3344 ltop,dsl[id].title ,
3345 ANAT_prefixstr[dset->func_type] , DSET_NUM_TIMES(dset) ) ;
3346
3347 } else {
3348 if( ISFUNCBUCKET(dset) ) /* 30 Nov 1997 */
3349 sprintf(qnam,"%-*s [%s:%d]" ,
3350 ltop,dsl[id].title ,
3351 FUNC_prefixstr[dset->func_type] , DSET_NVALS(dset) ) ;
3352
3353 else if( DSET_NUM_TIMES(dset) == 1 )
3354 sprintf(qnam,"%-*s [%s]" ,
3355 ltop,dsl[id].title ,
3356 FUNC_prefixstr[dset->func_type] ) ;
3357
3358 else
3359 sprintf(qnam,"%-*s [%s:3D+t:%d]" ,
3360 ltop,dsl[id].title ,
3361 FUNC_prefixstr[dset->func_type] , DSET_NVALS(dset) ) ;
3362 }
3363
3364 if( DSET_COMPRESSED(dset) ) strcat(qnam,"z") ;
3365
3366 strcpy( dsl[id].title , qnam ) ;
3367 }
3368
3369 EXRETURN ;
3370 }
3371
3372 /*------------------------------------------------------------------------
3373 Popup a chooser list of datasets that meet some criteria.
3374 Note that only one such chooser will be popped up at any given time.
3375 This routine is for use in user-written plugins with custom interfaces.
3376 23 October 1998 -- RWCox
3377
3378 w = widget to popup near
3379
3380 vv = view type of datasets (cf. VIEW_*_TYPE from 3ddata.h)
3381 [one way to select this is plint->im3d->vinfo->view_type]
3382
3383 multi = 1 to allow selection of multiple datasets
3384 = 0 to allow selection of only 1 dataset at a time
3385
3386 chk_func = int function( THD_3dim_dataset * dset, void * cd ) ;
3387 If this function pointer is not NULL, it will be called to
3388 check if each dataset should be allowed in. A zero return
3389 value means don't allow; any other return value means dset
3390 will be in the displayed list. If chk_func is NULL, then
3391 all datasets known to AFNI will be allowed. [The function
3392 PLUTO_dset_check() may be useful inside chk_func.]
3393
3394 cb_func = void function( int num, THD_3dim_dataset ** dslist, void * cd ) ;
3395 This function pointer must not be NULL. It will be called
3396 when the user makes a choice on the popup chooser.
3397 The value num will be the number of datasets chosen.
3398 dslist[i] will be a pointer to the i-th dataset, for
3399 i=0..num-1. If multi was 0, then num will be 1 and the
3400 single selected dataset will be pointed to by dlist[0].
3401
3402 cd = A pointer to anything the user likes. It will be passed to
3403 chk_func and cb_func, as described above. (Can be NULL.)
3404 --------------------------------------------------------------------------*/
3405
3406 static int num_user_dset = 0 ;
3407 static PLUGIN_dataset_link * user_dset_link = NULL ;
3408 static char ** user_dset_strlist = NULL ;
3409 static int user_dset_numds = 0 ;
3410 static THD_3dim_dataset ** user_dset_dslist = NULL ;
3411 static void_func * user_dset_cb_func = NULL ;
3412 static void * user_dset_cb_data = NULL ;
3413
PLUTO_popup_dset_chooser(Widget w,int vv,int multi,int_func * chk_func,void_func * cb_func,void * cd)3414 void PLUTO_popup_dset_chooser( Widget w , int vv , int multi ,
3415 int_func * chk_func ,
3416 void_func * cb_func , void * cd )
3417 {
3418 THD_session * ss ;
3419 THD_3dim_dataset * dset ;
3420 int iss_bot , iss_top , iss ;
3421 int id ;
3422 char label[64] ;
3423
3424 ENTRY("PLUTO_popup_dset_chooser") ;
3425
3426 if( w == NULL || cb_func == NULL ||
3427 vv < FIRST_VIEW_TYPE || vv > LAST_VIEW_TYPE ) EXRETURN ;
3428
3429 /** Scan sessions **/
3430
3431 iss_bot = 0 ;
3432 iss_top = GLOBAL_library.sslist->num_sess - 1 ;
3433 num_user_dset = 0 ;
3434
3435 for( iss=iss_bot ; iss <= iss_top ; iss++ ){
3436 ss = GLOBAL_library.sslist->ssar[iss] ;
3437
3438 /* check datasets from this session */
3439
3440 for( id=0 ; id < ss->num_dsset ; id++ ){
3441 dset = GET_SESSION_DSET(ss, id, vv);
3442 /* dset = ss->dsset_xform_table[id][vv] ; */
3443 if( dset == NULL ) continue ;
3444 #if 0
3445 if( chk_func != NULL && chk_func(dset,cd) == 0 ) continue ; /* skip */
3446 #else
3447 { int cval=1 ;
3448 AFNI_CALL_VALU_2ARG( chk_func ,
3449 int,cval , THD_3dim_dataset *,dset, void *,cd ) ;
3450 if( cval == 0 ) continue ;
3451 }
3452 #endif
3453
3454 num_user_dset++ ;
3455 user_dset_link = (PLUGIN_dataset_link *)
3456 XtRealloc( (char *) user_dset_link ,
3457 sizeof(PLUGIN_dataset_link)*num_user_dset ) ;
3458
3459 make_PLUGIN_dataset_link( dset , user_dset_link + (num_user_dset-1) ) ;
3460
3461 } /* end of loop over datasets */
3462
3463 } /* end of loop over sessions */
3464
3465 /*--- if nothing was found that fits, then nothing further can happen ---*/
3466
3467 if( num_user_dset == 0 ){
3468 myXtFree(user_dset_link) ; BEEPIT ;
3469 MCW_popup_message( w ,
3470 "No datasets that meet this\ncriterion are available!" ,
3471 MCW_USER_KILL|MCW_TIMER_KILL ) ;
3472 EXRETURN ;
3473 }
3474
3475 /*--- make a popup chooser for the user to browse ---*/
3476
3477 POPDOWN_strlist_chooser ; /* death to the old regime */
3478
3479 /* fix the dataset titles to be more fun */
3480
3481 patch_PLUGIN_dataset_links( num_user_dset , user_dset_link ) ;
3482
3483 /* make an array of pointers to all the titles */
3484
3485 user_dset_strlist = (char **) XtRealloc( (char *) user_dset_strlist ,
3486 sizeof(char *) * num_user_dset ) ;
3487 for( id=0 ; id < num_user_dset ; id++ )
3488 user_dset_strlist[id] = user_dset_link[id].title ;
3489
3490 /* label for the top of the chooser */
3491
3492 sprintf( label , "AFNI Dataset from\nthe %s" , VIEW_typestr[vv] ) ;
3493
3494 /* and take it away, Goldie */
3495
3496 user_dset_cb_func = cb_func ;
3497 user_dset_cb_data = cd ;
3498
3499 if( multi ){
3500 MCW_choose_multi_strlist( w , label , mcwCT_multi_mode ,
3501 num_user_dset , NULL , user_dset_strlist ,
3502 PLUG_finalize_user_dset_CB , NULL ) ;
3503 } else {
3504 MCW_choose_strlist( w , label ,
3505 num_user_dset , -1 , user_dset_strlist ,
3506 PLUG_finalize_user_dset_CB , NULL ) ;
3507 }
3508
3509 EXRETURN ;
3510 }
3511
3512 /*-----------------------------------------------------------------------
3513 Called when the user actually selects a dataset from the chooser.
3514 Will call the user's pitiful and loathsome routine.
3515 23 October 1998 -- RWCox
3516 -------------------------------------------------------------------------*/
3517
PLUG_finalize_user_dset_CB(Widget w,XtPointer fd,MCW_choose_cbs * cbs)3518 void PLUG_finalize_user_dset_CB( Widget w, XtPointer fd, MCW_choose_cbs * cbs )
3519 {
3520 int id , jd , num ;
3521
3522 ENTRY("PLUG_finalize_user_dset_CB") ;
3523
3524 if( cbs == NULL || cbs->nilist < 1 ) EXRETURN ;
3525
3526 user_dset_numds = num = cbs->nilist ;
3527
3528 user_dset_dslist = (THD_3dim_dataset **)
3529 XtRealloc( (char *) user_dset_dslist ,
3530 sizeof(THD_3dim_dataset *) * num ) ;
3531
3532 for( id=0 ; id < num ; id++ ){
3533 jd = cbs->ilist[id] ;
3534 user_dset_dslist[id] = PLUTO_find_dset( &(user_dset_link[jd].idcode) ) ;
3535 }
3536
3537 #if 0
3538 user_dset_cb_func( num , user_dset_dslist , user_dset_cb_data ) ;
3539 #else
3540 AFNI_CALL_VOID_3ARG( user_dset_cb_func ,
3541 int,num , THD_3dim_dataset **,user_dset_dslist ,
3542 void *,user_dset_cb_data ) ;
3543 #endif
3544
3545 EXRETURN ;
3546 }
3547
3548 /*----------------------------------------------------------------------
3549 What happens when a timeseries chooser button is pressed:
3550 Popup a timeseries chooser window.
3551 ------------------------------------------------------------------------*/
3552
PLUG_choose_timeseries_CB(Widget w,XtPointer cd,XtPointer cbs)3553 void PLUG_choose_timeseries_CB( Widget w , XtPointer cd , XtPointer cbs )
3554 {
3555 PLUGIN_interface * plint = (PLUGIN_interface *) cd ;
3556 PLUGIN_tsval * av = NULL ;
3557 PLUGIN_subvalue * sv = NULL ;
3558 Three_D_View * im3d ;
3559 int init_ts ;
3560
3561 ENTRY("PLUG_choose_timeseries_CB") ;
3562
3563 /** find the stuff that is associated with this button **/
3564
3565 XtVaGetValues( w , XmNuserData , &av , NULL ) ;
3566
3567 if( plint == NULL || av == NULL ) EXRETURN ;
3568 sv = av->sv ;
3569 if( sv == NULL ) EXRETURN ;
3570 im3d = plint->im3d ;
3571
3572 av->tsimar = GLOBAL_library.timeseries ; /* to choose amongst */
3573 if( av->tsimar==NULL || IMARR_COUNT(av->tsimar)==0 ){
3574 av->ts_choice = -1 ;
3575 av->tsim = NULL ;
3576 BEEPIT ; EXRETURN ;
3577 }
3578
3579 init_ts = AFNI_ts_in_library( av->tsim ) ;
3580
3581 MCW_choose_timeseries( w , "Choose Timeseries" ,
3582 av->tsimar , init_ts ,
3583 PLUG_finalize_timeseries_CB , (XtPointer) plint ) ;
3584
3585 EXRETURN ;
3586 }
3587
3588 /*----------------------------------------------------------------------
3589 What happens when a tcsv chooser button is pressed:
3590 Popup a tcsv chooser window.
3591 ------------------------------------------------------------------------*/
3592
PLUG_choose_tcsv_CB(Widget w,XtPointer cd,XtPointer cbs)3593 void PLUG_choose_tcsv_CB( Widget w , XtPointer cd , XtPointer cbs )
3594 {
3595 PLUGIN_interface * plint = (PLUGIN_interface *) cd ;
3596 PLUGIN_tcsvval * av = NULL ;
3597 PLUGIN_subvalue * sv = NULL ;
3598 Three_D_View * im3d ;
3599 int init_ts ;
3600
3601 ENTRY("PLUG_choose_tcsv_CB") ;
3602
3603 /** find the stuff that is associated with this button **/
3604
3605 XtVaGetValues( w , XmNuserData , &av , NULL ) ;
3606
3607 if( plint == NULL || av == NULL ) EXRETURN ;
3608 sv = av->sv ;
3609 if( sv == NULL ) EXRETURN ;
3610 im3d = plint->im3d ;
3611
3612 av->elarr = GLOBAL_library.tcsv_data ; /* to choose amongst */
3613 if( av->elarr==NULL || ELARR_COUNT(av->elarr)==0 ){
3614 av->tcsv_choice = -1 ;
3615 av->tcsv_el = NULL ;
3616 BEEPIT ; EXRETURN ;
3617 }
3618
3619 #if 0
3620 init_ts = AFNI_ts_in_library( av->tsim ) ;
3621 #else
3622 init_ts = -1 ;
3623 #endif
3624
3625 MCW_choose_tcsv( w , "Choose Timeseries" ,
3626 av->elarr , init_ts ,
3627 PLUG_finalize_tcsv_CB , (XtPointer) plint ) ;
3628
3629 EXRETURN ;
3630 }
3631
3632 /*-----------------------------------------------------------------------
3633 Called when the user actually selects a timeseries from the chooser.
3634 This routine just changes the original pushbutton label, and
3635 notes the index of the choice in the right place, for later retrieval.
3636 -------------------------------------------------------------------------*/
3637
PLUG_finalize_timeseries_CB(Widget w,XtPointer fd,MCW_choose_cbs * cbs)3638 void PLUG_finalize_timeseries_CB( Widget w, XtPointer fd, MCW_choose_cbs * cbs )
3639 {
3640 PLUGIN_interface * plint = (PLUGIN_interface *) fd ;
3641 PLUGIN_tsval * av = NULL ;
3642 XmString xstr ;
3643 int its ;
3644
3645 ENTRY("PLUG_finalize_timeseries_CB") ;
3646
3647 /** find the stuff that is associated with this button **/
3648
3649 XtVaGetValues( w , XmNuserData , &av , NULL ) ;
3650 if( plint == NULL || av == NULL || av->tsimar == NULL ) EXRETURN ;
3651 if( cbs->reason != mcwCR_timeseries ) EXRETURN ; /* error */
3652
3653 /** store the choice, and change the widget label **/
3654
3655 its = cbs->ival ;
3656 if( its >= 0 && its < IMARR_COUNT(av->tsimar) ){
3657 av->tsim = IMARR_SUBIMAGE(av->tsimar,its) ;
3658 av->ts_choice = its ;
3659
3660 xstr = XmStringCreateLtoR( av->tsim->name , XmFONTLIST_DEFAULT_TAG ) ;
3661 XtVaSetValues( w , XmNlabelString , xstr , NULL ) ;
3662 XmStringFree( xstr ) ;
3663 }
3664
3665 EXRETURN ;
3666 }
3667
3668 /*-----------------------------------------------------------------------
3669 Called when the user actually selects a tcsv from the chooser.
3670 This routine just changes the original pushbutton label, and
3671 notes the index of the choice in the right place, for later retrieval.
3672 -------------------------------------------------------------------------*/
3673
PLUG_finalize_tcsv_CB(Widget w,XtPointer fd,MCW_choose_cbs * cbs)3674 void PLUG_finalize_tcsv_CB( Widget w, XtPointer fd, MCW_choose_cbs * cbs )
3675 {
3676 PLUGIN_interface * plint = (PLUGIN_interface *) fd ;
3677 PLUGIN_tcsvval * av = NULL ;
3678 XmString xstr ;
3679 int its ;
3680
3681 ENTRY("PLUG_finalize_tcsv_CB") ;
3682
3683 /** find the stuff that is associated with this button **/
3684
3685 XtVaGetValues( w , XmNuserData , &av , NULL ) ;
3686 if( plint == NULL || av == NULL || av->elarr == NULL ) EXRETURN ;
3687 if( cbs->reason != mcwCR_tcsv ) EXRETURN ; /* error */
3688
3689 /** store the choice, and change the widget label **/
3690
3691 its = cbs->ival ;
3692 if( its >= 0 && its < ELARR_COUNT(av->elarr) ){
3693 av->tcsv_el = ELARR_SUBEL(av->elarr,its) ;
3694 av->tcsv_choice = its ;
3695
3696 xstr = XmStringCreateLtoR( av->tcsv_el->filename , XmFONTLIST_DEFAULT_TAG ) ;
3697 XtVaSetValues( w , XmNlabelString , xstr , NULL ) ;
3698 XmStringFree( xstr ) ;
3699 }
3700
3701 EXRETURN ;
3702 }
3703
3704 /********************************************************************************
3705 Routine to interface to AFNI, after plugins are read in.
3706 *********************************************************************************/
3707
AFNI_plugin_button(Three_D_View * im3d)3708 void AFNI_plugin_button( Three_D_View * im3d )
3709 {
3710 AFNI_plugin_array * exten = GLOBAL_library.plugins ;
3711 AFNI_plugin * plug ;
3712 int pp , ipl , nbut , npbut , kpl ;
3713 Widget rc , mbar , menu , cbut , pbut , wpar , sep ;
3714 XmString xstr ;
3715 PLUGIN_interface ** plintar ; /* 28 Nov 2000 */
3716
3717 ENTRY("AFNI_plugin_button") ;
3718
3719 /*-- check inputs for legality --*/
3720
3721 if( exten == NULL ||
3722 ! IM3D_VALID(im3d) || im3d->type != AFNI_3DDATA_VIEW ) EXRETURN ;
3723
3724 /*-- 23 Sep 2000: count number of buttons that will be made --*/
3725
3726 npbut = 0 ;
3727 for( pp=0 ; pp < exten->num ; pp++ ){
3728 plug = exten->plar[pp] ;
3729 for( ipl=0 ; ipl < plug->interface_count ; ipl++ ){
3730 npbut++ ;
3731 }
3732 }
3733
3734 /*-- make arrays to hold the plugin buttons (etc.),
3735 so that plugins can be started from layouts (in afni_splash.c) --*/
3736
3737 /* from malloc 12 Feb 2009 [lesstif patrol] */
3738 im3d->vwid->nplugbut = npbut ;
3739 im3d->vwid->plugbut = (Widget *) calloc(1, sizeof(Widget) *npbut) ;
3740 im3d->vwid->pluglab = (char **) calloc(1, sizeof(char *) *npbut) ;
3741 im3d->vwid->plugint = (PLUGIN_interface **) calloc(1, sizeof(PLUGIN_interface *)*npbut) ;
3742
3743 /*-- create menu bar --*/
3744
3745 wpar = im3d->vwid->dmode->mbar_rowcol ;
3746
3747 rc = XtVaCreateWidget(
3748 "dialog" , xmRowColumnWidgetClass , wpar ,
3749 XmNorientation , XmHORIZONTAL ,
3750 XmNpacking , XmPACK_TIGHT ,
3751 XmNtraversalOn , True ,
3752 XmNinitialResourcesPersistent , False ,
3753 NULL ) ;
3754
3755 mbar = XmCreateMenuBar( rc , "dialog" , NULL,0 ) ;
3756 XtVaSetValues( mbar ,
3757 XmNmarginWidth , 0 ,
3758 XmNmarginHeight , 0 ,
3759 XmNspacing , 3 ,
3760 XmNborderWidth , 0 ,
3761 XmNborderColor , 0 ,
3762 XmNtraversalOn , True ,
3763 XmNbackground , im3d->dc->ovc->pixov_brightest ,
3764 NULL ) ;
3765 XtManageChild( mbar ) ;
3766
3767 menu = XmCreatePulldownMenu( mbar , "menu" , NULL,0 ) ;
3768
3769 VISIBILIZE_WHEN_MAPPED(menu) ;
3770 #if 0
3771 if( !AFNI_yesenv("AFNI_DISABLE_TEAROFF") ) TEAROFFIZE(menu) ;
3772 #endif
3773
3774 xstr = XmStringCreateLtoR( "Plugins" , XmFONTLIST_DEFAULT_TAG ) ;
3775 cbut = XtVaCreateManagedWidget(
3776 "dialog" , xmCascadeButtonWidgetClass , mbar ,
3777 XmNlabelString , xstr ,
3778 XmNsubMenuId , menu ,
3779 XmNmarginWidth , 0 ,
3780 XmNmarginHeight , 0 ,
3781 XmNmarginBottom , 0 ,
3782 XmNmarginTop , 0 ,
3783 XmNmarginRight , 0 ,
3784 XmNmarginLeft , 0 ,
3785 XmNtraversalOn , True ,
3786 XmNinitialResourcesPersistent , False ,
3787 NULL ) ;
3788 XmStringFree( xstr ) ;
3789
3790 MCW_register_help( cbut , "Pressing this drops down\n"
3791 "the menu of the plugin\n"
3792 "programs loaded when\n"
3793 "AFNI started."
3794 ) ;
3795 MCW_register_hint( cbut , "Plugins menu" ) ;
3796
3797 /* macro to create a new menu button */
3798
3799 #define MENU_BUT(pl) \
3800 do{ \
3801 xstr = XmStringCreateLtoR( (pl)->label , XmFONTLIST_DEFAULT_TAG ) ; \
3802 pbut = XtVaCreateManagedWidget( \
3803 "dialog" , xmPushButtonWidgetClass , menu , \
3804 XmNlabelString , xstr , \
3805 XmNmarginHeight , 0 , \
3806 XmNuserData , (XtPointer) im3d , \
3807 XmNtraversalOn , True , \
3808 XmNinitialResourcesPersistent , False , \
3809 NULL ) ; \
3810 im3d->vwid->plugbut[npbut] = pbut ; /* 23 Sep 2000 */ \
3811 im3d->vwid->plugint[npbut] = (pl) ; \
3812 im3d->vwid->pluglab[npbut] = XtNewString((pl)->label) ; \
3813 XtAddCallback( pbut , XmNactivateCallback , \
3814 PLUG_startup_plugin_CB , (XtPointer)(pl) ) ; \
3815 XmStringFree(xstr) ; \
3816 if( (pl)->hint != NULL ) MCW_register_hint( pbut , (pl)->hint ) ; \
3817 if( (pl)->butcolor[0] != '\0' ) \
3818 MCW_set_widget_bg( pbut , (pl)->butcolor , 0 ) ; \
3819 } while(0)
3820
3821 /*** top of menu = a label to click on that does nothing at all ***/
3822
3823 xstr = XmStringCreateLtoR( "-- Cancel --" , XmFONTLIST_DEFAULT_TAG ) ;
3824 wtemp = XtVaCreateManagedWidget(
3825 "dialog" , xmLabelWidgetClass , menu ,
3826 XmNlabelString , xstr ,
3827 XmNrecomputeSize , False ,
3828 XmNinitialResourcesPersistent , False ,
3829 NULL ) ;
3830 XmStringFree(xstr) ; LABELIZE(wtemp) ;
3831
3832 sep = XtVaCreateManagedWidget(
3833 "dialog" , xmSeparatorWidgetClass , menu ,
3834 XmNseparatorType , XmSINGLE_LINE ,
3835 NULL ) ;
3836
3837 /*-- 28 Nov 2000: allow user to specify that
3838 button should be alphabetized --*/
3839
3840 /* make single array of all plugin interfaces */
3841
3842 plintar = (PLUGIN_interface **) malloc(sizeof(PLUGIN_interface *)*npbut) ;
3843 for( kpl=pp=0 ; pp < exten->num ; pp++ ){
3844 plug = exten->plar[pp] ;
3845 for( ipl=0 ; ipl < plug->interface_count ; ipl++ ){
3846 plintar[kpl++] = plug->interface[ipl] ;
3847 }
3848 }
3849
3850 /* sort this array, if desired */
3851
3852 if( !AFNI_noenv("AFNI_PLUGINS_ALPHABETIZE") ){
3853 int qq , ss ;
3854 PLUGIN_interface * tpl ;
3855
3856 do{ /* bubble sort */
3857 for( ss=qq=0 ; qq < npbut-1 ; qq++ ){
3858 if( strcasecmp(plintar[qq]->label,plintar[qq+1]->label) > 0 ){
3859 tpl = plintar[qq+1] ;
3860 plintar[qq+1] = plintar[qq] ;
3861 plintar[qq] = tpl ;
3862 ss++ ;
3863 }
3864 }
3865 } while( ss ) ;
3866 }
3867
3868 /*-- prepare to make the actual buttons --*/
3869
3870 nbut = 2 ; /* allow for the Cancel label and separator */
3871 npbut = 0 ; /* actual number of buttons */
3872
3873 /*** make buttons for each interface ***/
3874
3875 for( kpl=pp=0 ; pp < exten->num ; pp++ ){
3876 plug = exten->plar[pp] ;
3877 for( ipl=0 ; ipl < plug->interface_count ; ipl++ ){
3878 MENU_BUT( plintar[kpl] ) ; /* uses npbut */
3879 nbut++ ; npbut++ ; kpl++ ;
3880 }
3881 }
3882
3883 free(plintar) ; /* don't need no more */
3884
3885 if( nbut > COLSIZE ){
3886 int ncol = (nbut-2)/COLSIZE + 1 ;
3887 XtDestroyWidget(sep) ;
3888 XtVaSetValues( menu ,
3889 XmNpacking , XmPACK_COLUMN ,
3890 XmNnumColumns , ncol ,
3891 NULL ) ;
3892 }
3893
3894 XtManageChild( rc ) ;
3895 EXRETURN ;
3896 }
3897
3898 /*------------------------------------------------------------------------
3899 Routine that actually starts up a plugin when the user makes
3900 his or her choice from the menu created above.
3901 --------------------------------------------------------------------------*/
3902
PLUG_startup_plugin_CB(Widget w,XtPointer cd,XtPointer cbd)3903 void PLUG_startup_plugin_CB( Widget w , XtPointer cd , XtPointer cbd )
3904 {
3905 PLUGIN_interface *plint = (PLUGIN_interface *) cd ;
3906 XmAnyCallbackStruct *cbs = (XmAnyCallbackStruct *) cbd ;
3907 char *mesg=NULL ;
3908 Widget wpop ;
3909 Three_D_View *im3d = NULL ;
3910
3911 ENTRY("PLUG_startup_plugin_CB") ;
3912
3913 if( plint == NULL ) EXRETURN ; /* error? */
3914
3915 if( w != NULL ){
3916 XtVaGetValues( w , XmNuserData , &im3d , NULL ) ; /* set controller from */
3917 plint->im3d = im3d ; /* data on menu button */
3918 } else if( cbs != NULL ){ /* 21 Jul 2003 */
3919 plint->im3d = (Three_D_View *) cbs ;
3920 cbs = NULL ;
3921 }
3922 if( plint->im3d == NULL ) plint->im3d = AFNI_find_open_controller() ;
3923
3924 /*-- if no interface is needed, just call it --*/
3925
3926 if( plint->call_method == PLUGIN_CALL_IMMEDIATELY ){
3927
3928 STATUS("calling plugin") ;
3929
3930 MPROBE ;
3931
3932 SHOW_AFNI_PAUSE ;
3933 #if 0
3934 mesg = plint->call_func( plint ) ;
3935 #else
3936 AFNI_CALL_VALU_1ARG( plint->call_func ,
3937 char *,mesg , PLUGIN_interface *,plint ) ;
3938 #endif
3939 SHOW_AFNI_READY ;
3940
3941 MPROBE ;
3942
3943 if( mesg != NULL ){
3944 if( w != NULL ){
3945 (void) MCW_popup_message( w , mesg , MCW_USER_KILL ) ;
3946 BEEPIT ;
3947 } else {
3948 fprintf(stderr,"\n%s\a\n",mesg) ;
3949 }
3950 }
3951 EXRETURN ;
3952 }
3953
3954 /*-- if widgets not created yet, create them now --*/
3955
3956 if( plint->wid == NULL )
3957 PLUG_setup_widgets( plint , GLOBAL_library.dc ) ;
3958
3959 /*-- set labels to go on shell widget and icon;
3960 include the [] controller window index, if possible --*/
3961
3962 { char ttl[PLUGIN_STRING_SIZE] ;
3963
3964 sprintf(ttl , "%s%s" , AFNI_controller_label(plint->im3d) , plint->label ) ;
3965
3966 XtVaSetValues( plint->wid->shell ,
3967 XmNtitle , ttl , /* top of window */
3968 XmNiconName , ttl , /* label on icon */
3969 NULL ) ;
3970 }
3971
3972 /*-- if possible, find where this popup should go --*/
3973
3974 wpop = plint->wid->shell ;
3975
3976 if( cbs != NULL && cbs->event != NULL
3977 && cbs->event->type == ButtonRelease ){
3978
3979 XButtonEvent * xev = (XButtonEvent *) cbs->event ;
3980 int xx = (int)xev->x_root , yy = (int)xev->y_root ;
3981 int ww,hh , sw,sh ;
3982
3983 STATUS("trying to position popup") ;
3984
3985 MCW_widget_geom( wpop , &ww,&hh , NULL,NULL ) ; /* widget width and height */
3986 sw = WidthOfScreen (XtScreen(wpop)) ; /* screen width and height */
3987 sh = HeightOfScreen(XtScreen(wpop)) ;
3988
3989 if( xx+ww+3 >= sw && ww <= sw ) xx = sw-ww ; /* make sure is on screen */
3990 if( yy+hh+3 >= sh && hh <= sh ) yy = sh-hh ;
3991
3992 XtVaSetValues( wpop , XmNx , xx , XmNy , yy , NULL ) ;
3993 }
3994
3995 /*-- popup the widgets that control this plugin --*/
3996
3997 STATUS("popping up interface") ;
3998
3999 XtMapWidget( wpop ) ;
4000 RWC_visibilize_widget( wpop ) ; /* 27 Sep 2000 */
4001 PLUTO_cursorize( plint->wid->shell ) ;
4002 EXRETURN ;
4003 }
4004
4005 /*---------------------------------------------------------------------------
4006 Routine to add a dataset to the AFNI global collection.
4007 Return value is 0 if all is OK, 1 if bad things happened.
4008 "action_flag" is the OR (|) of various possibilities:
4009 DSET_ACTION_NONE == do nothing
4010 DSET_ACTION_MAKE_CURRENT == make this the currently viewed dataset
4011 -----------------------------------------------------------------------------*/
4012
PLUTO_add_dset(PLUGIN_interface * plint,THD_3dim_dataset * dset,int action_flag)4013 int PLUTO_add_dset( PLUGIN_interface *plint ,
4014 THD_3dim_dataset *dset , int action_flag )
4015 {
4016 Three_D_View *im3d ;
4017 THD_session *sess ;
4018 int iss , vv , id ;
4019 int make_current = (action_flag & DSET_ACTION_MAKE_CURRENT) ;
4020
4021 ENTRY("PLUTO_add_dset") ;
4022
4023 /** sanity check **/
4024
4025 if( plint == NULL || ! ISVALID_3DIM_DATASET(dset) ) RETURN(1) ;
4026
4027 /** find some indices **/
4028
4029 im3d = plint->im3d ;
4030 iss = IM3D_VALID(im3d) ? im3d->vinfo->sess_num : 0 ;
4031 sess = GLOBAL_library.sslist->ssar[iss] ;
4032 vv = dset->view_type ;
4033
4034 /** add the dataset to the session **/
4035
4036 id = sess->num_dsset ;
4037 if( id >= THD_MAX_SESSION_SIZE ){
4038 fprintf(stderr,"*** Overflow session dataset limit ***\n") ;
4039 RETURN(1) ;
4040 }
4041 SET_SESSION_DSET(dset, sess, id, vv);
4042
4043 /* sess->dsset_xform_table[id][vv] = dset ; */
4044 sess->num_dsset ++ ;
4045
4046 /** make sure the dataset is properly fit into the situation **/
4047
4048 POPDOWN_strlist_chooser ; /* added dataset --> old choosers are invalid */
4049
4050 #if 0
4051 THD_load_statistics( dset ) ;
4052 THD_write_3dim_dataset( NULL,NULL , dset , True ) ;
4053 #else
4054 DSET_overwrite(dset) ;
4055 #endif
4056
4057 if( dset->anat_parent == NULL ) /* if() added 14 Dec 1999 */
4058 AFNI_force_adoption( sess , GLOBAL_argopt.warp_4D ) ;
4059
4060 AFNI_make_descendants( GLOBAL_library.sslist ) ;
4061
4062 /** if desired, jump to this puppy in the viewer **/
4063
4064 if( make_current && IM3D_VALID(im3d) ){
4065 if( ISANAT(dset) )
4066 im3d->vinfo->anat_num = sess->num_dsset - 1 ;
4067 else
4068 im3d->vinfo->func_num = sess->num_dsset - 1 ;
4069
4070 AFNI_initialize_view( im3d->anat_now , im3d ) ;
4071 }
4072
4073 THD_force_malloc_type( dset->dblk , DATABLOCK_MEM_ANY ) ;
4074 RETURN(0) ;
4075 }
4076
4077 /*---------------------------------------------------------------------
4078 Routine to make a copy of a dataset, with data attached.
4079 [Moved into edt_fullcopy.c -- RWCox, 07 Oct 1998]
4080 -----------------------------------------------------------------------*/
4081
PLUTO_copy_dset(THD_3dim_dataset * dset,char * new_prefix)4082 THD_3dim_dataset * PLUTO_copy_dset( THD_3dim_dataset * dset , char * new_prefix )
4083 {
4084 THD_3dim_dataset * new_dset ;
4085 int ival , ityp , nbytes , nvals ;
4086 void * new_brick , * old_brick ;
4087
4088 ENTRY("PLUTO_copy_dset") ;
4089
4090 new_dset = EDIT_full_copy( dset , new_prefix ) ;
4091 RETURN(new_dset) ;
4092 }
4093
4094 /*----------------------------------------------------------------------
4095 Routine to force AFNI to redisplay controllers that are attached
4096 to a given dataset. (Feb 1998)
4097 ------------------------------------------------------------------------*/
4098
PLUTO_dset_redisplay(THD_3dim_dataset * dset)4099 void PLUTO_dset_redisplay( THD_3dim_dataset *dset )
4100 {
4101 PLUTO_dset_redisplay_mode( dset , REDISPLAY_OPTIONAL ) ;
4102 }
4103
4104 /*---- 23 Oct 1998: superseded above routine with this one; RWCox -----*/
4105
PLUTO_dset_redisplay_mode(THD_3dim_dataset * dset,int mode)4106 void PLUTO_dset_redisplay_mode( THD_3dim_dataset *dset , int mode )
4107 {
4108 Three_D_View * im3d ;
4109 int ii , amode , fmode ;
4110
4111 ENTRY("PLUTO_dset_redisplay_mode") ;
4112
4113 if( mode == REDISPLAY_OPTIONAL ){
4114 amode = REDISPLAY_ALL ;
4115 fmode = REDISPLAY_OVERLAY ;
4116 } else {
4117 amode = fmode = mode ;
4118 }
4119
4120 for( ii=0 ; ii < MAX_CONTROLLERS ; ii++ ){
4121 im3d = GLOBAL_library.controllers[ii] ;
4122 if( ! IM3D_OPEN(im3d) ) continue ;
4123 IM3D_CLEAR_TMASK(im3d) ;
4124 IM3D_CLEAR_THRSTAT(im3d) ; /* 12 Jun 2014 */
4125
4126 if( ! ISVALID_DSET(dset) ){
4127 im3d->anat_voxwarp->type = ILLEGAL_TYPE ;
4128 im3d->fim_voxwarp->type = ILLEGAL_TYPE ;
4129 AFNI_reset_func_range( im3d ) ;
4130 IM3D_VEDIT_FORCE(im3d) ; /* 01 Feb 2008 */
4131 AFNI_set_viewpoint( im3d , -1,-1,-1 , REDISPLAY_ALL ) ;
4132 } else if( im3d->anat_now == dset ){
4133 im3d->anat_voxwarp->type = ILLEGAL_TYPE ;
4134 AFNI_reset_func_range( im3d ) ;
4135 AFNI_imseq_clearstat( im3d ) ;
4136 IM3D_VEDIT_FORCE(im3d) ; /* 01 Feb 2008 */
4137 AFNI_set_viewpoint( im3d , -1,-1,-1 , amode ) ;
4138 } else if( im3d->fim_now == dset ){
4139 im3d->fim_voxwarp->type = ILLEGAL_TYPE ;
4140 AFNI_reset_func_range( im3d ) ;
4141 AFNI_imseq_clearstat( im3d ) ;
4142 IM3D_VEDIT_FORCE(im3d) ; /* 01 Feb 2008 */
4143 AFNI_redisplay_func( im3d ) ;
4144 }
4145 }
4146 EXRETURN ;
4147 }
4148
4149 /*----------------------------------------------------------------------
4150 Routine to inform AFNI that some dataset names are now different,
4151 so stuff should be done about it.
4152 ------------------------------------------------------------------------*/
4153
PLUTO_fixup_names(void)4154 void PLUTO_fixup_names(void)
4155 {
4156 Three_D_View * im3d ;
4157 int ii ;
4158
4159 ENTRY("PLUTO_fixup_names") ;
4160
4161 POPDOWN_strlist_chooser ; /* get rid of any dataset chooser that is open */
4162
4163 for( ii=0 ; ii < MAX_CONTROLLERS ; ii++ ){
4164 im3d = GLOBAL_library.controllers[ii] ;
4165 if( IM3D_OPEN(im3d) )
4166 AFNI_set_window_titles( im3d ) ;
4167 }
4168 EXRETURN ;
4169 }
4170
4171 /*-----------------------------------------------------------------------
4172 Let the user popup a message
4173 -------------------------------------------------------------------------*/
4174
PLUTO_popup_worker(PLUGIN_interface * plint,char * mesg,int flag)4175 void PLUTO_popup_worker( PLUGIN_interface * plint , char * mesg , int flag )
4176 {
4177 Widget w = NULL ;
4178 Three_D_View * im3d ;
4179 int ii ;
4180
4181 ENTRY("PLUTO_popup_worker") ;
4182
4183 if( mesg == NULL || strlen(mesg) == 0 ) EXRETURN ;
4184
4185 /* find a widget to popup next to */
4186
4187 if( plint->wid != NULL && plint->wid->label != NULL ){
4188 w = plint->wid->label ;
4189 } else {
4190 im3d = plint->im3d ;
4191 if( !IM3D_OPEN(im3d) ) im3d = AFNI_find_open_controller() ;
4192 w = im3d->vwid->top_shell ;
4193 }
4194
4195 if( w != NULL ){
4196 if( flag >= 0 )
4197 (void) MCW_popup_message( w , mesg , flag ) ;
4198 else
4199 (void) new_MCW_textwin( w , mesg , TEXT_READONLY ) ;
4200 } else {
4201 fprintf(stderr,"\n%s\a\n",mesg) ;
4202 }
4203
4204 EXRETURN ;
4205 }
4206
4207 /*------------------------------------------------------------------*/
4208
PLUTO_beep(void)4209 void PLUTO_beep(void)
4210 {
4211 BEEPIT ; return ;
4212 }
4213
4214 /*------------------------------------------------------------------*/
4215
4216 #include <ctype.h>
4217
PLUTO_strncmp(char * aa,char * bb,int nn)4218 static int PLUTO_strncmp( char * aa , char * bb , int nn ) /* 09 Oct 2000 */
4219 {
4220 int ii ;
4221
4222 if( aa == bb ) return 0 ; /* special cases */
4223 if( aa == NULL || bb == NULL ) return 1 ;
4224
4225 for( ii=0 ; ii < nn ; ii++,aa++,bb++ ){
4226 if( *aa == '\0' && *bb == '\0' ) return 0 ; /* got to end all same! */
4227 if( *aa == '\0' || *bb == '\0' ) return 1 ; /* premature end of one */
4228 if( isspace(*aa) || isspace(*bb) ) continue ; /* don't compare blanks */
4229 if( toupper(*aa) != toupper(*bb) ) return 1 ; /* case insensitive */
4230 }
4231
4232 return 0 ; /* finished max # chars */
4233 }
4234
4235 /*------------------------------------------------------------------*/
4236
PLUTO_string_index(char * target,int num,char * source[])4237 int PLUTO_string_index( char * target , int num , char * source[] )
4238 {
4239 int ii ;
4240
4241 if( num <= 0 || source == NULL || target == NULL ) return -1 ;
4242
4243 for( ii=0 ; ii < num ; ii++ )
4244 if( PLUTO_strncmp(target,source[ii],PLUGIN_STRING_SIZE) == 0 ) return ii ;
4245
4246 return -1 ;
4247 }
4248
4249 /*-----------------------------------------------------------------------
4250 Function to let an IMMEDIATE mode plugin let AFNI know where its
4251 toplevel shell is -- 22 Sep 2000 -- RWCox.
4252 -------------------------------------------------------------------------*/
4253
PLUTO_set_topshell(PLUGIN_interface * plint,Widget ts)4254 void PLUTO_set_topshell( PLUGIN_interface * plint , Widget ts )
4255 {
4256 ENTRY("PLUTO_set_topshell") ;
4257
4258 if( plint == NULL ||
4259 plint->wid != NULL ||
4260 ts == (Widget) 0 ||
4261 plint->call_method != PLUGIN_CALL_IMMEDIATELY ) EXRETURN ;
4262
4263 plint->wid = myXtNew(PLUGIN_widgets) ;
4264 plint->wid->shell = ts ;
4265 plint->wid->meter = NULL ;
4266 EXRETURN ;
4267 }
4268
4269 /*-----------------------------------------------------------------------
4270 Routines to put a progress meter on the top of the interface shell
4271 -------------------------------------------------------------------------*/
4272
PLUTO_popup_meter(PLUGIN_interface * plint)4273 void PLUTO_popup_meter( PLUGIN_interface * plint )
4274 {
4275 ENTRY("PLUTO_popup_meter") ;
4276
4277 if( plint == NULL || plint->wid == NULL ||
4278 plint->wid->shell == NULL || plint->wid->meter != NULL ) EXRETURN ;
4279
4280 plint->wid->meter = MCW_popup_meter( plint->wid->shell , METER_TOP_WIDE ) ;
4281 EXRETURN ;
4282 }
4283
PLUTO_popdown_meter(PLUGIN_interface * plint)4284 void PLUTO_popdown_meter( PLUGIN_interface * plint )
4285 {
4286 ENTRY("PLUTO_popdown_meter") ;
4287
4288 if( plint == NULL || plint->wid == NULL ||
4289 plint->wid->shell == NULL || plint->wid->meter == NULL ) EXRETURN ;
4290
4291 MCW_popdown_meter( plint->wid->meter ) ;
4292 plint->wid->meter = NULL ;
4293 EXRETURN ;
4294 }
4295
PLUTO_set_meter(PLUGIN_interface * plint,int percent)4296 void PLUTO_set_meter( PLUGIN_interface * plint , int percent )
4297 {
4298 ENTRY("PLUTO_set_meter") ;
4299
4300 if( plint == NULL || plint->wid == NULL ||
4301 plint->wid->shell == NULL || plint->wid->meter == NULL ) EXRETURN ;
4302
4303 MCW_set_meter( plint->wid->meter , percent ) ;
4304 EXRETURN ;
4305 }
4306
4307 /*-----------------------------------------------------------------------
4308 Routine to popup an image.
4309 Inputs:
4310 handle = (a) value returned from previous call to this routine
4311 (b) or NULL to start a new image display window
4312 im = pointer to MRI_IMAGE structure
4313 (a) NULL to popdown the image display window
4314 (b) non-NULL to display this image in the window
4315
4316 Output is a "handle" that can be used to control the next usage
4317 of this routine (whether to send an image to a new window or
4318 replace it in an old one).
4319 -------------------------------------------------------------------------*/
4320
PLUTO_popup_image(void * handle,MRI_IMAGE * im)4321 void * PLUTO_popup_image( void * handle , MRI_IMAGE * im )
4322 {
4323 PLUGIN_impopper * imp = (PLUGIN_impopper *) handle ;
4324
4325 ENTRY("PLUTO_popup_image") ;
4326
4327 /*-- input image is NULL ==> popdown, if applicable --*/
4328
4329 if( im == NULL ){
4330 if( imp != NULL )
4331 drive_MCW_imseq( imp->seq , isqDR_destroy , NULL ) ;
4332
4333 RETURN((void *) imp) ;
4334 }
4335
4336 /*-- input = no popper handle ==> create one --*/
4337
4338 if( imp == NULL ){
4339 imp = myXtNew(PLUGIN_impopper) ;
4340 imp->seq = NULL ; imp->im = NULL ;
4341 }
4342
4343 /*-- input = non-null image ==> replace image --*/
4344
4345 mri_free( imp->im ) ; /* toss old copy */
4346 imp->im = mri_copy( im ) ; /* make new copy */
4347
4348 /*-- input = inactive popper handle ==> activate it --*/
4349
4350 if( imp->seq == NULL ){
4351 imp->seq = open_MCW_imseq( GLOBAL_library.dc ,
4352 PLUGIN_imseq_getim , (XtPointer) imp ) ;
4353
4354 drive_MCW_imseq( imp->seq , isqDR_realize, NULL ) ;
4355 drive_MCW_imseq( imp->seq , isqDR_onoffwid , (XtPointer) isqDR_offwid ) ;
4356
4357 drive_MCW_imseq( imp->seq , isqDR_opacitybut , (XtPointer) 0 ) ; /* 07 Mar 2001 */
4358 drive_MCW_imseq( imp->seq , isqDR_zoombut , (XtPointer) 0 ) ; /* 12 Mar 2002 */
4359 drive_MCW_imseq( imp->seq , isqDR_penbbox , (XtPointer) 0 ) ; /* 18 Jul 2003 */
4360 }
4361
4362 /*-- display image at last --*/
4363
4364 if( im->name != NULL && strlen(im->name) > 0 )
4365 drive_MCW_imseq( imp->seq , isqDR_title, im->name ) ;
4366
4367 drive_MCW_imseq( imp->seq , isqDR_clearstat , NULL ) ;
4368 drive_MCW_imseq( imp->seq , isqDR_reimage , (XtPointer) 0 ) ;
4369
4370 RETURN((void *) imp) ;
4371 }
4372
4373 /*------------------------------------------------------------------
4374 Routine to provide data to the imseq for PLUGIN_popup_image.
4375 Just returns the control information, or the given image.
4376 --------------------------------------------------------------------*/
4377
PLUGIN_imseq_getim(int n,int type,XtPointer handle)4378 XtPointer PLUGIN_imseq_getim( int n , int type , XtPointer handle )
4379 {
4380 PLUGIN_impopper * imp = (PLUGIN_impopper *) handle ;
4381
4382 ENTRY("PLUGIN_imseq_getim") ;
4383
4384 if( imp == NULL ) RETURN(NULL) ;
4385
4386 /*--- control info ---*/
4387
4388 if( type == isqCR_getstatus ){
4389 MCW_imseq_status * stat = myXtNew( MCW_imseq_status ) ;
4390 stat->num_total = 1 ;
4391 stat->num_series = 1 ;
4392 stat->send_CB = PLUGIN_seq_send_CB ;
4393 stat->parent = (XtPointer) imp ;
4394 stat->aux = NULL ;
4395
4396 stat->transforms0D = & (GLOBAL_library.registered_0D) ;
4397 stat->transforms2D = & (GLOBAL_library.registered_2D) ;
4398 stat->slice_proj = NULL ;
4399
4400 RETURN((XtPointer) stat) ;
4401 }
4402
4403 /*--- no overlay ---*/
4404
4405 if( type == isqCR_getoverlay ) RETURN(NULL) ;
4406
4407 /*--- return a copy of the image
4408 (since the imseq will delete it when it is done) ---*/
4409
4410 if( type == isqCR_getimage || type == isqCR_getqimage ){
4411 MRI_IMAGE * im = NULL ;
4412 if( imp->im != NULL ) im = mri_copy( imp->im ) ;
4413 RETURN((XtPointer) im) ;
4414 }
4415
4416 RETURN(NULL) ; /* should not occur, but who knows? */
4417 }
4418
4419 /*---------------------------------------------------------------------------
4420 Routine called when the imseq wants to send a message.
4421 In this case, all we need to handle is the destroy message,
4422 so that we can free some memory.
4423 -----------------------------------------------------------------------------*/
4424
PLUGIN_seq_send_CB(MCW_imseq * seq,XtPointer handle,ISQ_cbs * cbs)4425 void PLUGIN_seq_send_CB( MCW_imseq * seq , XtPointer handle , ISQ_cbs * cbs )
4426 {
4427 PLUGIN_impopper * imp = (PLUGIN_impopper *) handle ;
4428
4429 ENTRY("PLUGIN_seq_send_CB") ;
4430
4431 if( imp == NULL ) EXRETURN ;
4432
4433 switch( cbs->reason ){
4434
4435 case isqCR_destroy:{
4436 XtFree((char*)imp->seq->status) ;
4437 XtFree((char*)imp->seq) ; imp->seq = NULL ;
4438 mri_free( imp->im ) ; imp->im = NULL ;
4439 }
4440 break ;
4441
4442 #ifndef NO_FRIVOLITIES
4443 case isqCR_buttonpress:{
4444 XButtonEvent *xev = (XButtonEvent *) cbs->event ;
4445 #define NBIRN 11
4446 static int nold=0 ;
4447 static char *birn[NBIRN] = {
4448 " \n** Don't DO That! **\n " ,
4449 " \n** Stop it, Rasmus! **\n " ,
4450 " \n** Do NOT read this message! **\n " ,
4451 " \n** Having fun yet? **\n " ,
4452 " \n** What do you want NOW? **\n " ,
4453 " \n** Too much time on your hands? **\n " ,
4454 " \n** Why are you bothering me? **\n " ,
4455 " \n** Danger! Danger, Will Robinson! **\n " ,
4456 " \n** WARNING: Planetary meltdown imminent! **\n " ,
4457
4458 " \n"
4459 " God of our fathers, known of old,\n"
4460 " Lord of our far-flung battle-line,\n"
4461 " Beneath whose awful hand we hold\n"
4462 " Dominion over palm and pine -\n"
4463 " Lord God of Hosts, be with us yet,\n"
4464 " Lest we forget - lest we forget!\n"
4465 " \n"
4466 " The tumult and the shouting dies;\n"
4467 " The captains and the kings depart:\n"
4468 " Still stands Thine ancient sacrifice,\n"
4469 " An humble and a contrite heart.\n"
4470 " Lord God of Hosts, be with us yet,\n"
4471 " Lest we forget - lest we forget!\n"
4472 " \n"
4473 " Far-called, our navies melt away;\n"
4474 " On dune and headland sinks the fire:\n"
4475 " Lo, all our pomp of yesterday\n"
4476 " Is one with Nineveh and Tyre!\n"
4477 " Judge of the Nations, spare us yet.\n"
4478 " Lest we forget - lest we forget!\n"
4479 " \n"
4480 " If, drunk with sight of power, we loose\n"
4481 " Wild tongues that have not Thee in awe,\n"
4482 " Such boastings as the Gentiles use,\n"
4483 " Or lesser breeds without the Law -\n"
4484 " Lord God of Hosts, be with us yet,\n"
4485 " Lest we forget - lest we forget!\n"
4486 " \n"
4487 " For heathen heart that puts her trust\n"
4488 " In reeking tube and iron shard,\n"
4489 " All valiant dust that builds on dust,\n"
4490 " And, guarding, calls not Thee to guard,\n"
4491 " For frantic boast and foolish word -\n"
4492 " The Mercy on Thy People, Lord!\n" ,
4493
4494 "*\n"
4495 " That's all there is, there ain't no more \n"
4496 "*"
4497 } ;
4498
4499 #define NKLING 5
4500 static int nkl=0 ;
4501 static char *kling[NKLING] = {
4502 " \n What is this talk of 'release'?\n"
4503 " Klingons do not make software 'releases'.\n"
4504 " Our software 'escapes', leaving a bloody trail of\n"
4505 " designers and 'Quality Assurance' people in its wake.\n" ,
4506
4507 " \n Debugging? Klingons do not debug.\n"
4508 " Our software does not coddle the weak.\n" ,
4509
4510 " \n Klingon software does NOT have BUGS.\n"
4511 " It has FEATURES, and those features are too\n"
4512 " sophisticated for a Romulan pig like you to understand.\n" ,
4513
4514 " \n Our users will know fear and cower before our software!\n"
4515 " Ship it! Ship it and let them flee like the dogs they are!\n" ,
4516
4517 " \n You question the worthiness of my code?\n"
4518 " I should kill you where you stand!\n"
4519 } ;
4520
4521 /* button 1 = Birn strings */
4522 if( xev == NULL || xev->button == Button1 ){
4523 if( !NO_frivolities && nold < NBIRN ){
4524 if( strstr(birn[nold],"Rasmus") != NULL )
4525 AFNI_speak("Stop it, Rasmus", 0 ) ;
4526 MCW_popup_message( seq->wimage , birn[nold] ,
4527 (nold+1 < NBIRN) ? MCW_QUICK_KILL : MCW_USER_KILL ) ;
4528 nold++ ;
4529 } else {
4530 PLUTO_beep() ;
4531 if( nold == NBIRN ){ AFNI_speak("Stop it",0); nold++; }
4532 }
4533 /* button 3 = Klingon strings */
4534 } else if( xev->button == Button3 ){
4535 if( !NO_frivolities && nkl < NKLING ){
4536 MCW_popup_message( seq->wimage , kling[nkl++] , MCW_QUICK_KILL ) ;
4537 } else {
4538 PLUTO_beep() ;
4539 if( nkl == NKLING ){ AFNI_speak("Deesist at once",0); nkl++; }
4540 }
4541 }
4542 }
4543 break ;
4544
4545 /*--------------------------------------*/
4546
4547 case isqCR_keypress:{ /* 12 Sep 2002 */
4548 static char *nash[] = {
4549 " \n"
4550 "The ant has made himself illustrious\n"
4551 "Through constant industry industrious.\n"
4552 "So what?\n"
4553 "Would you be calm and placid\n"
4554 "If you were full of formic acid?\n"
4555 ,
4556 " \n"
4557 "Celery, raw\n"
4558 "Develops the jaw,\n"
4559 "But celery, stewed,\n"
4560 "Is more quietly chewed.\n"
4561 ,
4562 " \n"
4563 "I objurgate the centipede,\n"
4564 "A bug we do not really need.\n"
4565 "At sleepy-time he beats a path\n"
4566 "Straight to the bedroom or the bath.\n"
4567 "You always wallop where he's not,\n"
4568 "Or, if he is, he makes a spot. \n"
4569 ,
4570 " \n"
4571 "The cow is of the bovine ilk;\n"
4572 "One end is moo, the other, milk.\n"
4573 ,
4574 " \n"
4575 "This is my dream,\n"
4576 "It is my own dream,\n"
4577 "I dreamt it.\n"
4578 "I dreamt that my hair was kempt.\n"
4579 "Then I dreamt that my true love unkempt it.\n"
4580 ,
4581 " \n"
4582 "I find it very difficult to enthuse\n"
4583 "Over the current news.\n"
4584 "Just when you think that at least the outlook\n"
4585 " is so black that it can grow no blacker, it worsens,\n"
4586 "And that is why I do not like the news, because there\n"
4587 " has never been an era when so many things were going\n"
4588 " so right for so many of the wrong persons. \n"
4589 ,
4590 " \n"
4591 "I test my bath before I sit,\n"
4592 "And I'm always moved to wonderment\n"
4593 "That what chills the finger not a bit\n"
4594 "Is so frigid upon the fundament.\n"
4595 ,
4596 " \n"
4597 "The turtle lives 'twixt plated decks\n"
4598 "Which practically conceal its sex.\n"
4599 "I think it clever of the turtle\n"
4600 "In such a fix to be so fertile.\n"
4601 ,
4602 " \n"
4603 "Candy\n"
4604 "Is Dandy\n"
4605 "But liquor\n"
4606 "Is quicker.\n"
4607 ,
4608 " \n"
4609 "I've never seen an abominable snowman,\n"
4610 "I'm hoping not to see one,\n"
4611 "I'm also hoping, if I do,\n"
4612 "That it will be a wee one. \n"
4613 ,
4614 " \n"
4615 "Children aren't happy without\n"
4616 "something to ignore, and that's\n"
4617 "what parents were created for. \n"
4618 ,
4619 " \n"
4620 "Middle age is when you've met so\n"
4621 "many people that every new person\n"
4622 "you meet reminds you of someone else.\n"
4623 } ;
4624 #define NUM_NASH (sizeof(nash)/sizeof(char *)) ;
4625
4626 static int iold=-1 ; int ii ;
4627 do{ ii=lrand48()%NUM_NASH; } while( ii==iold ) ; iold = ii ;
4628 MCW_popup_message( seq->wimage , nash[ii] ,
4629 (strlen(nash[ii]) < 111) ? MCW_QUICK_KILL : MCW_TIMER_KILL ) ;
4630 }
4631 break ;
4632 #endif /* NO_FRIVOLITIES */
4633
4634 }
4635 EXRETURN ;
4636 }
4637
4638 /*-----------------------------------------------------------------------
4639 28 April 2000: Open an image sequence display window.
4640 The input image(s) are copied, so they can be destroyed after
4641 these calls.
4642 PLUTO_imseq_popim(im,kfunc,kdata)
4643 starts the image window off with a single image;
4644 return value is a "handle" that is used in other calls;
4645 if kfunc is not NULL, it is a function that will be called
4646 with argument kdata when the imseq window is closed
4647 (e.g., this can be used to set the saved handle to NULL)
4648 PLUTO_imseq_popup(imar,kfunc,kdata)
4649 starts the window off with an array of images
4650 PLUTO_imseq_retitle(handle,string)
4651 changes the window manager title
4652 PLUTO_imseq_rekill(handle,kfunc,kdata)
4653 changes the kill function/data to kfunc/kdata;
4654 PLUTO_imseq_addto(handle,im)
4655 adds the single image "im" to the display
4656 PLUTO_imseq_setim(handle,n)
4657 sets the image index to 'n'
4658 PLUTO_imseq_destroy(handle)
4659 pops down the image viewer;
4660 destroys the internal copies of the images;
4661 calls kfunc(kdata) if kfunc is not NULL
4662 (so do PLUTO_imseq_rekill(handle,NULL,NULL); before
4663 PLUTO_imseq_destroy(handle);
4664 if you don't want the kfunc to be called)
4665 -------------------------------------------------------------------------*/
4666
PLUTO_imseq_popim(MRI_IMAGE * im,generic_func * kfunc,void * kdata)4667 void * PLUTO_imseq_popim( MRI_IMAGE * im, generic_func * kfunc, void * kdata )
4668 {
4669 MRI_IMARR * imar ;
4670 void * handle ;
4671
4672 if( im == NULL ) return NULL ;
4673 INIT_IMARR(imar) ;
4674 ADDTO_IMARR(imar,im) ;
4675 handle = PLUTO_imseq_popup( imar,kfunc,kdata ) ;
4676 FREE_IMARR(imar) ; /* not DESTROY_IMARR: we don't 'own' im */
4677 return handle ;
4678 }
4679
PLUTO_imseq_popup(MRI_IMARR * imar,generic_func * kfunc,void * kdata)4680 void * PLUTO_imseq_popup( MRI_IMARR * imar, generic_func * kfunc, void * kdata )
4681 {
4682 int ntot , ii ;
4683 MRI_IMAGE * im=NULL , * cim=NULL ;
4684 PLUGIN_imseq * psq=NULL ;
4685
4686 if( imar == NULL || IMARR_COUNT(imar) == 0 ) return NULL ;
4687
4688 ntot = IMARR_COUNT(imar) ;
4689
4690 psq = (PLUGIN_imseq *) calloc(1,sizeof(PLUGIN_imseq)) ;
4691 if( psq == NULL ) return NULL ;
4692
4693 INIT_IMARR(psq->imar) ;
4694 psq->kill_func = kfunc ;
4695 psq->kill_data = kdata ;
4696 psq->rgb_count = 0 ;
4697
4698 for( ii=0 ; ii < ntot ; ii++ ){
4699 im = IMARR_SUBIMAGE(imar,ii) ;
4700 if( im != NULL ){
4701 cim = mri_copy( im ) ;
4702 ADDTO_IMARR(psq->imar,cim) ;
4703 if( cim->kind == MRI_rgb ) psq->rgb_count++ ;
4704 }
4705 }
4706 ntot = IMARR_COUNT(psq->imar) ;
4707 if( ntot == 0 ){
4708 DESTROY_IMARR(psq->imar) ; free(psq) ; return NULL ;
4709 }
4710
4711 psq->seq = open_MCW_imseq( GLOBAL_library.dc , PLUTO_imseq_getim , psq ) ;
4712
4713 drive_MCW_imseq( psq->seq , isqDR_clearstat , NULL ) ;
4714
4715 { ISQ_options opt ; /* change some options from the defaults */
4716
4717 memset(&opt, 0, sizeof(opt));
4718 ISQ_DEFAULT_OPT(opt) ;
4719 opt.save_one = False ; /* change to Save:bkg */
4720 opt.save_pnm = False ;
4721 drive_MCW_imseq( psq->seq , isqDR_options , (XtPointer) &opt ) ;
4722 drive_MCW_imseq( psq->seq , isqDR_periodicmont , (XtPointer) 0 ) ;
4723 }
4724
4725 /* make it popup */
4726
4727 drive_MCW_imseq( psq->seq , isqDR_realize, NULL ) ;
4728 drive_MCW_imseq( psq->seq , isqDR_title, "Images" ) ;
4729
4730 if( ntot == 1 )
4731 drive_MCW_imseq( psq->seq , isqDR_onoffwid , (XtPointer) isqDR_offwid ) ;
4732 else {
4733 drive_MCW_imseq( psq->seq , isqDR_onoffwid , (XtPointer) isqDR_onwid ) ;
4734 drive_MCW_imseq( psq->seq , isqDR_opacitybut , (XtPointer) 0 ) ; /* 07 Mar 2001 */
4735 drive_MCW_imseq( psq->seq , isqDR_zoombut , (XtPointer) 0 ) ; /* 12 Mar 2002 */
4736 drive_MCW_imseq( psq->seq , isqDR_penbbox , (XtPointer) 0 ) ; /* 18 Jul 2003 */
4737 }
4738
4739 return (void *) psq ;
4740 }
4741
4742 /*-----------------------------------------------------------------------*/
4743
PLUTO_imseq_retitle(void * handle,char * title)4744 void PLUTO_imseq_retitle( void * handle , char * title )
4745 {
4746 PLUGIN_imseq * psq = (PLUGIN_imseq *) handle ;
4747
4748 if( psq == NULL || psq->seq == NULL || title == NULL ) return ;
4749 drive_MCW_imseq( psq->seq , isqDR_title, title ) ;
4750 return ;
4751 }
4752
4753 /*-----------------------------------------------------------------------*/
4754
PLUTO_imseq_rekill(void * handle,generic_func * kfunc,void * kdata)4755 void PLUTO_imseq_rekill( void * handle, generic_func * kfunc, void * kdata )
4756 {
4757 PLUGIN_imseq * psq = (PLUGIN_imseq *) handle ;
4758
4759 if( psq == NULL ) return ;
4760 psq->kill_func = kfunc ;
4761 psq->kill_data = kdata ;
4762 return ;
4763 }
4764
4765 /*-----------------------------------------------------------------------*/
4766
PLUTO_imseq_addto(void * handle,MRI_IMAGE * im)4767 void PLUTO_imseq_addto( void * handle , MRI_IMAGE * im )
4768 {
4769 PLUGIN_imseq * psq = (PLUGIN_imseq *) handle ;
4770 int ntot , ii ;
4771 MRI_IMAGE * cim ;
4772
4773 if( psq == NULL || psq->seq == NULL || im == NULL ) return ;
4774
4775 ntot = IMARR_COUNT(psq->imar) ;
4776 cim = mri_copy(im) ;
4777 if( cim->kind == MRI_rgb ) psq->rgb_count++ ;
4778 ADDTO_IMARR(psq->imar,cim) ;
4779
4780 drive_MCW_imseq( psq->seq , isqDR_newseq , psq ) ;
4781
4782 if( ntot == 1 )
4783 drive_MCW_imseq( psq->seq , isqDR_onoffwid , (XtPointer) isqDR_offwid ) ;
4784 else {
4785 drive_MCW_imseq( psq->seq , isqDR_onoffwid , (XtPointer) isqDR_onwid ) ;
4786 drive_MCW_imseq( psq->seq , isqDR_opacitybut , (XtPointer) 0 ) ; /* 07 Mar 2001 */
4787 drive_MCW_imseq( psq->seq , isqDR_zoombut , (XtPointer) 0 ) ; /* 12 Mar 2002 */
4788 }
4789
4790 drive_MCW_imseq( psq->seq , isqDR_reimage , (XtPointer)ITOP(ntot) ) ;
4791
4792 return ;
4793 }
4794
4795 /*-----------------------------------------------------------------------*/
4796
PLUTO_imseq_setim(void * handle,int n)4797 void PLUTO_imseq_setim( void *handle , int n ) /* 17 Dec 2004 */
4798 {
4799 PLUGIN_imseq *psq = (PLUGIN_imseq *)handle ;
4800
4801 if( psq == NULL || psq->seq == NULL ||
4802 n < 0 || n >= IMARR_COUNT(psq->imar) ) return ;
4803
4804 drive_MCW_imseq( psq->seq , isqDR_reimage , (XtPointer)ITOP(n) ) ;
4805 return ;
4806 }
4807
4808 /*-----------------------------------------------------------------------*/
4809
PLUTO_imseq_destroy(void * handle)4810 void PLUTO_imseq_destroy( void * handle )
4811 {
4812 PLUGIN_imseq * psq = (PLUGIN_imseq *) handle ;
4813
4814 if( psq == NULL ) return ;
4815 drive_MCW_imseq( psq->seq , isqDR_destroy , NULL ) ;
4816 return ;
4817 }
4818
4819 /*------------------------------------------------------------------
4820 Routine to provide data to the imseq.
4821 Just returns the control information, or the selected image.
4822 --------------------------------------------------------------------*/
4823
PLUTO_imseq_getim(int n,int type,XtPointer handle)4824 XtPointer PLUTO_imseq_getim( int n , int type , XtPointer handle )
4825 {
4826 PLUGIN_imseq * psq = (PLUGIN_imseq *) handle ;
4827
4828 int ntot = 0 ;
4829
4830 if( psq->imar != NULL ) ntot = IMARR_COUNT(psq->imar) ;
4831 if( ntot < 1 ) ntot = 1 ;
4832
4833 /*--- send control info ---*/
4834
4835 if( type == isqCR_getstatus ){
4836 MCW_imseq_status * stat = myXtNew( MCW_imseq_status ) ; /* will be free-d */
4837 /* when imseq is */
4838 /* destroyed */
4839 stat->num_total = ntot ;
4840 stat->num_series = ntot ;
4841 stat->send_CB = PLUTO_imseq_send_CB ;
4842 stat->parent = NULL ;
4843 stat->aux = NULL ;
4844
4845 stat->transforms0D = &(GLOBAL_library.registered_0D) ;
4846 stat->transforms2D = &(GLOBAL_library.registered_2D) ;
4847 stat->slice_proj = NULL ;
4848
4849 return (XtPointer) stat ;
4850 }
4851
4852 /*--- no overlay, never ---*/
4853
4854 if( type == isqCR_getoverlay ) return NULL ;
4855
4856 /*--- return a copy of an image
4857 (since the imseq will delete it when it is done) ---*/
4858
4859 if( type == isqCR_getimage || type == isqCR_getqimage ){
4860 MRI_IMAGE * im = NULL , * rim ;
4861
4862 if( psq->imar != NULL ){
4863 if( n < 0 ) n = 0 ; else if( n >= ntot ) n = ntot-1 ;
4864 rim = IMARR_SUBIMAGE(psq->imar,n) ;
4865 if( psq->rgb_count > 0 )
4866 im = mri_to_rgb( rim ) ;
4867 else
4868 im = mri_copy( rim ) ;
4869 }
4870 return (XtPointer) im ;
4871 }
4872
4873 return NULL ; /* should not occur, but who knows? */
4874 }
4875
4876 /*---------------------------------------------------------------------------
4877 Routine called when the imseq wants to send a message.
4878 In this case, all we need to handle is the destroy message,
4879 so that we can free some memory.
4880 -----------------------------------------------------------------------------*/
4881
PLUTO_imseq_send_CB(MCW_imseq * seq,XtPointer handle,ISQ_cbs * cbs)4882 void PLUTO_imseq_send_CB( MCW_imseq * seq , XtPointer handle , ISQ_cbs * cbs )
4883 {
4884 PLUGIN_imseq * psq = (PLUGIN_imseq *) handle ;
4885
4886 switch( cbs->reason ){
4887 case isqCR_destroy:{
4888 myXtFree(psq->seq) ;
4889 DESTROY_IMARR( psq->imar ) ;
4890
4891 if( psq->kill_func != NULL )
4892 #if 0
4893 psq->kill_func( psq->kill_data ) ;
4894 #else
4895 AFNI_CALL_VOID_1ARG( psq->kill_func , void *,psq->kill_data ) ;
4896 #endif
4897
4898 free(psq) ;
4899 }
4900 break ;
4901 }
4902 return ;
4903 }
4904
4905 /*-------------------------------------------------------------------------*/
4906
4907 /*-- 13 Dec 1997: moved guts into thd_make*.c --*/
4908
PLUTO_4D_to_typed_fim(THD_3dim_dataset * old_dset,char * new_prefix,int new_datum,int ignore,int detrend,generic_func * user_func,void * user_data)4909 THD_3dim_dataset * PLUTO_4D_to_typed_fim( THD_3dim_dataset * old_dset ,
4910 char * new_prefix , int new_datum ,
4911 int ignore , int detrend ,
4912 generic_func * user_func ,
4913 void * user_data )
4914 {
4915 THD_3dim_dataset * new_dset ; /* output dataset */
4916
4917 ENTRY("PLUTO_4D_to_typed_fim") ;
4918
4919 if( ! PLUTO_prefix_ok(new_prefix) ) RETURN(NULL) ;
4920
4921 new_dset = MAKER_4D_to_typed_fim( old_dset , new_prefix , new_datum ,
4922 ignore , detrend , user_func , user_data ) ;
4923
4924 RETURN(new_dset) ;
4925 }
4926
4927 /*-------------------------------------------------------------------------*/
4928
PLUTO_4D_to_typed_fith(THD_3dim_dataset * old_dset,char * new_prefix,int new_datum,int ignore,int detrend,generic_func * user_func,void * user_data)4929 THD_3dim_dataset * PLUTO_4D_to_typed_fith( THD_3dim_dataset * old_dset ,
4930 char * new_prefix , int new_datum ,
4931 int ignore , int detrend ,
4932 generic_func * user_func ,
4933 void * user_data )
4934 {
4935 THD_3dim_dataset * new_dset ; /* output dataset */
4936
4937 ENTRY("PLUTO_4D_to_typed_fith") ;
4938
4939 if( ! PLUTO_prefix_ok(new_prefix) ) RETURN(NULL) ;
4940
4941 new_dset = MAKER_4D_to_typed_fith( old_dset , new_prefix , new_datum ,
4942 ignore , detrend , user_func , user_data ) ;
4943
4944 RETURN(new_dset) ;
4945 }
4946
4947 /*-------------------------------------------------------------------------*/
4948
PLUTO_4D_to_typed_fbuc(THD_3dim_dataset * old_dset,char * new_prefix,int new_datum,int ignore,int detrend,int nbrik,generic_func * user_func,void * user_data)4949 THD_3dim_dataset * PLUTO_4D_to_typed_fbuc( THD_3dim_dataset * old_dset ,
4950 char * new_prefix , int new_datum ,
4951 int ignore , int detrend ,
4952 int nbrik ,
4953 generic_func * user_func ,
4954 void * user_data )
4955 {
4956 THD_3dim_dataset * new_dset ; /* output dataset */
4957
4958 ENTRY("PLUTO_4D_to_typed_fbuc") ;
4959
4960 if( ! PLUTO_prefix_ok(new_prefix) ) RETURN(NULL) ;
4961
4962 new_dset = MAKER_4D_to_typed_fbuc( old_dset , new_prefix , new_datum ,
4963 ignore , detrend , nbrik , user_func ,
4964 user_data, NULL, 0 ) ;
4965
4966 RETURN(new_dset) ;
4967 }
4968
4969 /*----------------------------------------------------------------------------*/
4970
PLUTO_report(PLUGIN_interface * plint,char * str)4971 void PLUTO_report( PLUGIN_interface *plint , char *str )
4972 {
4973 if( plint == NULL || str == NULL || !AFNI_VERBOSE ) return ;
4974 printf("\n%15.15s= %s" , plint->label , str ) ; fflush(stdout) ;
4975 return ;
4976 }
4977
4978 /*----------------------------------------------------------------------------
4979 Routines to add a text entry box.
4980 ------------------------------------------------------------------------------*/
4981
new_PLUGIN_strval(Widget wpar,char * str)4982 PLUGIN_strval * new_PLUGIN_strval( Widget wpar , char * str )
4983 {
4984 PLUGIN_strval * av ;
4985 XmString xstr ;
4986
4987 ENTRY("new_PLUGIN_strval") ;
4988
4989 if( wpar == (Widget) NULL ) RETURN(NULL) ;
4990
4991 av = myXtNew(PLUGIN_strval) ;
4992
4993 av->rowcol = XtVaCreateWidget(
4994 "AFNI" , xmRowColumnWidgetClass , wpar ,
4995 XmNpacking , XmPACK_TIGHT ,
4996 XmNorientation , XmHORIZONTAL ,
4997 XmNmarginHeight, 0 ,
4998 XmNmarginWidth , 0 ,
4999 XmNspacing , 0 ,
5000 XmNtraversalOn , True ,
5001 XmNinitialResourcesPersistent , False ,
5002 NULL ) ;
5003
5004 xstr = XmStringCreateLtoR( str , XmFONTLIST_DEFAULT_TAG ) ;
5005 av->label = XtVaCreateManagedWidget(
5006 "AFNI" , xmLabelWidgetClass , av->rowcol ,
5007 XmNlabelString , xstr ,
5008 XmNmarginWidth , 0 ,
5009 XmNinitialResourcesPersistent , False ,
5010 NULL ) ;
5011 XmStringFree( xstr ) ;
5012
5013 av->textf = XtVaCreateManagedWidget(
5014 "AFNI" , xmTextFieldWidgetClass , av->rowcol ,
5015 XmNcolumns , 9 ,
5016 XmNeditable , True ,
5017 XmNmaxLength , PLUGIN_STRING_SIZE ,
5018 XmNresizeWidth , False ,
5019 XmNmarginHeight , 1 ,
5020 XmNmarginWidth , 1 ,
5021 XmNcursorPositionVisible , True ,
5022 XmNblinkRate , 0 ,
5023 XmNautoShowCursorPosition , True ,
5024 XmNtraversalOn , True ,
5025 XmNinitialResourcesPersistent , False ,
5026 NULL ) ;
5027
5028 XtManageChild( av->rowcol ) ;
5029 RETURN(av) ;
5030 }
5031
5032 /*----------------------------------------------------------------------------*/
5033
destroy_PLUGIN_strval(PLUGIN_strval * av)5034 void destroy_PLUGIN_strval( PLUGIN_strval * av )
5035 {
5036 if( av != NULL ){
5037 XtDestroyWidget( av->rowcol ) ;
5038 myXtFree(av) ;
5039 }
5040 return ;
5041 }
5042
5043 /*----------------------------------------------------------------------------*/
5044
alter_PLUGIN_strval_width(PLUGIN_strval * av,int nchar)5045 void alter_PLUGIN_strval_width( PLUGIN_strval * av , int nchar )
5046 {
5047 if( av != NULL && nchar > 0 )
5048 XtVaSetValues( av->textf , XmNcolumns , nchar , NULL ) ;
5049 return ;
5050 }
5051
5052 /*----------------------------------------------------------------------------*/
5053
set_PLUGIN_strval(PLUGIN_strval * av,char * str)5054 void set_PLUGIN_strval( PLUGIN_strval * av , char * str )
5055 {
5056 if( av != NULL && str != NULL )
5057 XmTextFieldSetString( av->textf , str ) ;
5058 return ;
5059 }
5060
5061 /*----------------------------------------------------------------------------*/
5062
get_PLUGIN_strval(PLUGIN_strval * av)5063 char * get_PLUGIN_strval( PLUGIN_strval * av ) /* must be XtFree-d */
5064 {
5065 if( av == NULL ) return NULL ;
5066 return XmTextFieldGetString( av->textf ) ;
5067 }
5068
5069 /*----------------------------------------------------------------------------*/
5070
5071 /* Set the addresses of the main vol2surf globals. Note that the
5072 * plugin options pointer is stored as (void *) so that vol2surf.h
5073 * will not need to percolate up to afni.h. 09 Sep 2004 [rickr]
5074 */
5075 #include "vol2surf.h"
PLUTO_set_v2s_addrs(void ** vopt,char *** maps,char ** hist)5076 int PLUTO_set_v2s_addrs(void ** vopt, char *** maps, char ** hist)
5077 {
5078 if ( !vopt || !maps || !hist ) return -1;
5079
5080 *vopt = (void *)&gv2s_plug_opts;
5081 *maps = gv2s_map_names;
5082 *hist = gv2s_history;
5083
5084 return 0;
5085 }
5086
5087 /**************************************************************************/
5088 /*========================================================================*/
5089 /*============ These must remain the last lines of this file! ============*/
5090
5091 /** put library routines here that must be loaded **/
5092
5093 #include "cox_render.h" /* 14 Feb 2002 */
5094
5095 #ifndef MATRIX_INCLUDED /* matrix.h is now included and matrix_initialize
5096 prototype conflicts with this one. ZSS Nov. 21 2014 */
5097 extern void matrix_initialize(void *); /* 30 Jul 2007 */
5098 #endif
5099
5100 static vptr_func * forced_loads[] = {
5101 #ifndef NO_DYNAMIC_LOADING
5102 (vptr_func *) startup_lsqfit ,
5103 (vptr_func *) delayed_lsqfit ,
5104 (vptr_func *) mri_align_dfspace ,
5105 (vptr_func *) EDIT_one_dataset ,
5106 (vptr_func *) EDIT_add_brick ,
5107 (vptr_func *) mri_2dalign_setup ,
5108 (vptr_func *) mri_3dalign_setup ,
5109 (vptr_func *) qsort_floatint ,
5110 (vptr_func *) qsort_floatfloat ,
5111 (vptr_func *) symeig_double ,
5112 (vptr_func *) new_MCW_graf ,
5113 (vptr_func *) THD_makemask ,
5114 (vptr_func *) mri_copy ,
5115 (vptr_func *) beta_t2p ,
5116 (vptr_func *) get_laguerre_table ,
5117 (vptr_func *) mri_fix_data_pointer ,
5118 (vptr_func *) THD_zeropad ,
5119 (vptr_func *) THD_axcode ,
5120 (vptr_func *) THD_dataset_rowfillin ,
5121 (vptr_func *) mri_histobyte , /* 25 Jul 2001 */
5122 (vptr_func *) sphere_voronoi_vectors , /* 18 Oct 2001 */
5123 (vptr_func *) new_CREN_renderer , /* 14 Feb 2002 */
5124 (vptr_func *) THD_average_timeseries , /* 03 Apr 2002 */
5125 (vptr_func *) cl1_solve , /* 07 Aug 2002 */
5126 (vptr_func *) new_Dtable , /* 20 Oct 2003 */
5127 (vptr_func *) powell_newuoa , /* 24 Jul 2006 */
5128 (vptr_func *) matrix_initialize , /* 30 Jul 2007 */
5129 (vptr_func *) r_new_resam_dset , /* 31 Jul 2007 */
5130 (vptr_func *) r_hex_str_to_long , /* 31 Jul 2007 */
5131 (vptr_func *) r_idisp_vec3f , /* 31 Jul 2007 */
5132 (vptr_func *) THD_dataset_mismatch , /* 04 Sep 2009 */
5133 (vptr_func *) legendre , /* 16 Jul 2010 */
5134 (vptr_func *) AFNI_needs_dset_ijk , /* 13 Jan 2020 */
5135 #endif
5136 NULL } ;
5137
MCW_onen_i_estel_edain(void * n)5138 vptr_func * MCW_onen_i_estel_edain(void *n){
5139 THD_3dim_dataset *ds = (THD_3dim_dataset *)n ;
5140 double x = (double)(ds->dblk->total_bytes) ;
5141 return forced_loads[(int)x] ;
5142 }
5143
5144 #else /* not ALLOW_PLUGINS */
5145
MCW_onen_i_estel_edain(void * n)5146 void * MCW_onen_i_estel_edain(void *n){} ; /* dummy routine */
5147
5148 #endif /* ALLOW_PLUGINS */
5149
5150 /***********************************************************************
5151 Routines that are always compiled, since they are used in
5152 a few places in AFNI that are not plugin-specific.
5153 ************************************************************************/
5154
PLUTO_register_timeseries(char * cname,MRI_IMAGE * tsim)5155 void PLUTO_register_timeseries( char *cname , MRI_IMAGE *tsim )
5156 {
5157 MRI_IMAGE *qim ;
5158
5159 ENTRY("PLUTO_register_timeseries") ;
5160
5161 if( tsim != NULL ){
5162 qim = mri_to_float( tsim ) ; /* a copy */
5163 mri_add_name( cname , qim ) ; /* the name */
5164 AFNI_add_timeseries( qim ) ; /* give it to AFNI */
5165 }
5166 EXRETURN ;
5167 }
5168
5169 /*----------------------------------------------------------------------------
5170 Find a dataset, given its idcode string. [02 Mar 2002]
5171 ------------------------------------------------------------------------------*/
5172
PLUTO_find_dset_idc(char * idc)5173 THD_3dim_dataset * PLUTO_find_dset_idc( char *idc )
5174 {
5175 MCW_idcode idcode ;
5176 if( idc == NULL ) return NULL ;
5177 MCW_strncpy( idcode.str , idc , MCW_IDSIZE ) ;
5178 return PLUTO_find_dset( &idcode ) ;
5179 }
5180
5181 /*----------------------------------------------------------------------------
5182 Routine to find a dataset in the global sessionlist, given its idcode.
5183 If this returns NULL, then you are SOL.
5184 ------------------------------------------------------------------------------*/
5185
PLUTO_find_dset(MCW_idcode * idcode)5186 THD_3dim_dataset * PLUTO_find_dset( MCW_idcode *idcode )
5187 {
5188 THD_slist_find find ;
5189
5190 ENTRY("PLUTO_find_dset") ;
5191
5192 if( idcode == NULL || ISZERO_IDCODE(*idcode) ) RETURN(NULL) ;
5193
5194 find = THD_dset_in_sessionlist( FIND_IDCODE , idcode ,
5195 GLOBAL_library.sslist , -1 ) ;
5196
5197 RETURN(find.dset) ;
5198 }
5199
5200 /*-----------------------------------------------------------------*/
5201
PLUTO_dset_finder(char * idc)5202 THD_slist_find PLUTO_dset_finder( char *idc )
5203 {
5204 MCW_idcode idcode ;
5205 THD_slist_find find ;
5206
5207 BADFIND(find) ; if( idc == NULL || *idc == '\0' ) return find ;
5208
5209 MCW_strncpy( idcode.str , idc , MCW_IDSIZE ) ;
5210 find = THD_dset_in_sessionlist( FIND_IDCODE , &idcode ,
5211 GLOBAL_library.sslist , -1 ) ;
5212 if( find.dset != NULL ) return find ;
5213
5214 find = THD_dset_in_sessionlist( FIND_PREFIX , idc ,
5215 GLOBAL_library.sslist , -1 ) ;
5216 if( find.dset != NULL ) return find ;
5217
5218 find = THD_dset_in_sessionlist( FIND_NAME , idc ,
5219 GLOBAL_library.sslist , -1 ) ;
5220 return find ;
5221 }
5222
5223 /*----------------------------------------------------------------------*/
5224 /*!
5225 Look for a dataset by name and append it to session in question
5226 Search if needed for exact name matches under paths from find_afni_file()
5227 and then try get_atlas()
5228
5229 Returns a 0 only when a dataset was found.
5230 Non-zero indicates stupidity, error, etc.
5231 ZSS Oct. 2013
5232 ------------------------------------------------------------------------*/
AFNI_append_dset_to_session(char * fname,int sss)5233 int AFNI_append_dset_to_session( char *fname, int sss )
5234 {
5235 THD_3dim_dataset *new_dset=NULL;
5236 THD_session * this_ss ;
5237 THD_slist_find find;
5238
5239 ENTRY("AFNI_append_dset_to_session");
5240
5241 if( GLOBAL_library.have_dummy_dataset ){ RETURN(1); }
5242 if (!fname) { RETURN(2); }
5243 if( sss < 0 || sss >= GLOBAL_library.sslist->num_sess ){ RETURN(2); }
5244
5245 this_ss = GLOBAL_library.sslist->ssar[sss] ;
5246 if( ! ISVALID_SESSION(this_ss) ){ RETURN(3); }
5247
5248 /* not sure what to do with GLOBAL_library session yet.
5249 why not add to it too? Also, why not add to global
5250 if sss == -1 ? For now, return merrily */
5251 if( this_ss == GLOBAL_library.session ) RETURN(4);
5252
5253 if( this_ss->num_dsset < THD_MAX_SESSION_SIZE ){
5254 if (!(new_dset = THD_open_dataset( fname ))) {
5255 /* now try looking for it */
5256 new_dset = THD_open_dataset(find_afni_file(fname, 0, NULL));
5257 }
5258 if (!new_dset) { /* try again, this works better if name
5259 is not complete */
5260 new_dset = get_atlas(NULL, fname);
5261 }
5262 if( ISVALID_DSET(new_dset) ){
5263 /* make sure it is not in the session already */
5264 find = THD_dset_in_session( FIND_IDCODE, &(new_dset->idcode), this_ss );
5265 if( find.dset == NULL ){
5266 find = THD_dset_in_session(FIND_PREFIX,
5267 DSET_PREFIX(new_dset),this_ss);
5268 if( find.dset != NULL &&
5269 find.dset->view_type != new_dset->view_type ) find.dset = NULL ;
5270 }
5271 if (!find.dset) {
5272 SET_SESSION_DSET(new_dset, this_ss,
5273 this_ss->num_dsset, new_dset->view_type);
5274 this_ss->num_dsset ++ ;
5275 AFNI_inconstancy_check(NULL,new_dset) ;
5276 RETURN(0);
5277 }
5278 }
5279 }
5280
5281 RETURN(5);
5282 }
5283
5284 /*-----------------------------------------------------------------
5285 Plot a histogram; input might be from mri_histogram():
5286 nbin = # of bins in hist[]
5287 bot = bottom of hist[0] bin } bin size is
5288 top = top of hist[nbin-1] bin } (top-bot)/nbin
5289 hist = array of counts in each bin
5290 xlab } labels for x-axis,
5291 ylab } y-axis
5292 tlab } and top of graph (NULL => skip this label)
5293
5294 njist = number of extra histograms [can be 0]
5295 jist = "extra" histograms to plot atop hist
5296 (if jist == NULL, this plot is skipped)
5297 Graph is popped up and then "forgotten" -- RWCox - 30 Sep 1999.
5298 -------------------------------------------------------------------*/
5299
PLUTO_histoplot_f(int nbin,float bot,float top,float * hist,char * xlab,char * ylab,char * tlab,int njist,float ** jist)5300 void PLUTO_histoplot_f( int nbin, float bot, float top, float *hist ,
5301 char *xlab , char *ylab , char *tlab ,
5302 int njist , float **jist )
5303 {
5304 int ii , nx , ny,jj ;
5305 float *xar , *yar , *zar=NULL , **yzar ;
5306 float dx ;
5307 int cumu = AFNI_yesenv("AFNI_HISTOG_CUMULATIVE") ||
5308 AFNI_yesenv("AFNI_HISTOPLOT_CUMULATIVE") ;
5309
5310 ENTRY("PLUTO_histoplot_f") ;
5311
5312 if( nbin < 2 || hist == NULL ) EXRETURN ;
5313 if( bot >= top ){ bot = 0.0f ; top = nbin ; }
5314
5315 nx = 2*(nbin+1) ;
5316 dx = (top-bot)/nbin ;
5317 xar = (float *) malloc(sizeof(float)*nx) ;
5318 yar = (float *) malloc(sizeof(float)*nx) ;
5319
5320 if( jist == NULL || njist < 0 ) njist = 0 ;
5321 ny = njist + 1 ;
5322
5323 yzar = (float **) calloc(sizeof(float *),ny) ;
5324 yzar[0] = yar ;
5325 for( jj=0 ; jj < njist ; jj++ )
5326 yzar[jj+1] = (float *) calloc(sizeof(float),nx) ;
5327
5328 xar[0] = bot ; yar[0] = 0.0f ;
5329 for( ii=0 ; ii < nbin ; ii++ ){
5330 xar[2*ii+1] = bot+ii*dx ; yar[2*ii+1] = hist[ii] ;
5331 xar[2*ii+2] = bot+(ii+1)*dx ; yar[2*ii+2] = hist[ii] ;
5332
5333 for( jj=0 ; jj < njist ; jj++ )
5334 yzar[jj+1][2*ii+1] = yzar[jj+1][2*ii+2] = jist[jj][ii] ;
5335 }
5336 xar[2*nbin+1] = top ; yar[2*nbin+1] = 0.0f ;
5337 for( jj=0 ; jj < njist ; jj++ )
5338 yzar[jj+1][0] = yzar[jj+1][2*nbin+1] = 0.0f ;
5339
5340 if( cumu ){
5341 int nyy=2*ny ; float sum , ytop=0.0f , yfac ;
5342 for( jj=0 ; jj < ny ; jj++ ){
5343 for( ii=0 ; ii < nx ; ii++ ) if( yzar[jj][ii] > ytop ) ytop = yzar[jj][ii] ;
5344 }
5345 yzar = (float **)realloc(yzar,sizeof(float *)*nyy) ;
5346 for( jj=0 ; jj < ny ; jj++ ){
5347 yzar[ny+jj] = (float *)calloc(sizeof(float),nx) ;
5348 yzar[ny+jj][0] = sum = 0.0f ;
5349 for( ii=0 ; ii < nbin ; ii++ ){
5350 sum += yzar[jj][2*ii+1] ;
5351 yzar[ny+jj][2*ii+1] = yzar[ny+jj][2*ii+2] = sum ;
5352 }
5353 yzar[ny+jj][2*nbin+1] = sum ;
5354 yfac = ytop / sum ;
5355 for( ii=0 ; ii < nx ; ii++ ) yzar[ny+jj][ii] *= yfac ;
5356 }
5357 plot_ts_setthik_12( ny , nyy , 0.002f ) ;
5358 ny = nyy ;
5359 }
5360
5361 X11_SET_NEW_PLOT ;
5362 plot_ts_lab( GLOBAL_library.dc->display ,
5363 nx , xar , ny , yzar ,
5364 xlab,ylab,tlab , NULL , NULL ) ;
5365
5366 for( jj=0 ; jj < ny ; jj++ ) free(yzar[jj]) ;
5367 free(yzar) ; free(xar) ;
5368 plot_ts_setthik_12( -555,-666,0.0f ) ;
5369 EXRETURN ;
5370 }
5371
5372 /*----------------------------------------------------------------------*/
5373
PLUTO_histoplot(int nbin,float bot,float top,int * hist,char * xlab,char * ylab,char * tlab,int njist,int ** jist)5374 void PLUTO_histoplot( int nbin, float bot, float top, int *hist ,
5375 char *xlab , char *ylab , char *tlab ,
5376 int njist , int **jist )
5377 {
5378 float *hist_f , **jist_f ;
5379 int ii,jj ;
5380
5381 ENTRY("PLUTO_histoplot") ;
5382
5383 if( nbin < 2 || hist == NULL ) EXRETURN ;
5384
5385 hist_f = (float *)malloc(sizeof(float)*nbin) ;
5386 for( ii=0 ; ii < nbin ; ii++ ) hist_f[ii] = (float)hist[ii] ;
5387
5388 if( njist <= 0 || jist == NULL ){
5389 PLUTO_histoplot_f( nbin, bot,top , hist_f , xlab,ylab,tlab , 0,NULL ) ;
5390 free((void *)hist_f) ;
5391 EXRETURN ;
5392 }
5393
5394 jist_f = (float **)malloc(sizeof(float *)*njist) ;
5395 for( jj=0 ; jj < njist ; jj++ ){
5396 jist_f[jj] = (float *)malloc(sizeof(float)*nbin) ;
5397 for( ii=0 ; ii < nbin ; ii++ ) jist_f[jj][ii] = (float)jist[jj][ii] ;
5398 }
5399 PLUTO_histoplot_f( nbin,bot,top , hist_f , xlab,ylab,tlab , njist,jist_f );
5400 for( jj=0 ; jj < njist ; jj++ ) free((void *)jist_f[jj]) ;
5401 free((void *)jist_f) ; free((void *)hist_f) ;
5402 EXRETURN ;
5403 }
5404
5405 /*----------------------------------------------------------------------
5406 Return p10 as a power of 10 such that
5407 p10 <= fabs(x) < 10*p10
5408 unless x == 0, in which case return 0.
5409 ------------------------------------------------------------------------*/
5410
p10(float x)5411 static float p10( float x )
5412 {
5413 double y ;
5414 if( x == 0.0 ) return 0.0 ;
5415 if( x < 0.0 ) x = -x ;
5416 y = floor(log10(x)+0.000001) ; y = pow( 10.0 , y ) ;
5417 return (float) y ;
5418 }
5419
5420 #define STGOOD(s) ( (s) != NULL && (s)[0] != '\0' )
5421
5422 static int xpush=1 , ypush=1 ;
PLUTO_set_xypush(int a,int b)5423 void PLUTO_set_xypush( int a, int b ){ xpush=a; ypush=b; }
5424
5425 /*-----------------------------------------------------------------
5426 Plot a scatterplot.
5427 npt = # of points in x[] and y[]
5428 x = x-axis values array
5429 y = y-axis values array
5430 xlab } labels for x-axis,
5431 ylab } y-axis
5432 tlab } and top of graph (NULL => skip this label)
5433 nlin = number of straight lines to plot
5434 alin,blin,clin = slope, intercept, color of lines
5435 Graph is popped up and then "forgotten" -- RWCox - 13 Jan 2000
5436 -------------------------------------------------------------------*/
5437
PLUTO_scatterplot_NEW(int npt,float * x,float * y,char * xlab,char * ylab,char * tlab,int nlin,float * alin,float * blin,float_triple * clin)5438 void PLUTO_scatterplot_NEW( int npt , float *x , float *y ,
5439 char *xlab , char *ylab , char *tlab ,
5440 int nlin , float *alin , float *blin , float_triple *clin )
5441 {
5442 int ii , np , nnax,mmax , nnay,mmay , ll ;
5443 float xbot,xtop , ybot,ytop , pbot,ptop ,
5444 xobot,xotop,yobot,yotop , xa,xb,ya,yb , dx,dy ;
5445 float *xar , *yar , *zar=NULL , **yzar ;
5446 float dsq , rx,ry , a,b ;
5447 char str[32] ;
5448 MEM_plotdata *mp ;
5449
5450 ENTRY("PLUTO_scatterplot_NEW") ;
5451
5452 if( npt < 2 || x == NULL || y == NULL ) EXRETURN ;
5453
5454 /* find range of data */
5455
5456 xbot = xtop = x[0] ; ybot = ytop = y[0] ;
5457 for( ii=1 ; ii < npt ; ii++ ){
5458 if( x[ii] < xbot ) xbot = x[ii] ;
5459 else if( x[ii] > xtop ) xtop = x[ii] ;
5460
5461 if( y[ii] < ybot ) ybot = y[ii] ;
5462 else if( y[ii] > ytop ) ytop = y[ii] ;
5463 }
5464 if( xbot >= xtop || ybot >= ytop ){
5465 ERROR_message("Data has no range in PLUTO_scatterplot!\a") ;
5466 EXRETURN ;
5467 }
5468
5469 /*-- push range of x outwards --*/
5470
5471 pbot = p10(xbot) ; ptop = p10(xtop) ; if( ptop < pbot ) ptop = pbot ;
5472 if( ptop != 0.0 && xpush > 0 ){
5473 np = (xtop-xbot) / ptop + 0.5 ;
5474 switch( np ){
5475 case 1: ptop *= 0.1 ; break ;
5476 case 2: ptop *= 0.2 ; break ;
5477 case 3: ptop *= 0.25 ; break ;
5478 case 4:
5479 case 5: ptop *= 0.5 ; break ;
5480 }
5481 xbot = floor( xbot/ptop ) * ptop ;
5482 xtop = ceil( xtop/ptop ) * ptop ;
5483 nnax = floor( (xtop-xbot) / ptop + 0.5 ) ;
5484 mmax = (nnax < 3) ? 10
5485 : (nnax < 6) ? 5 : 2 ;
5486 } else {
5487 nnax = 1 ; mmax = 10 ;
5488 dx = 0.02*(xtop-xbot) ;
5489 if( xtop-floorf(xtop) > 0.001f ) xtop += dx ;
5490 if( xbot-floorf(xbot) > 0.001f ) xbot -= dx ;
5491 }
5492
5493 /*-- push range of y outwards --*/
5494
5495 pbot = p10(ybot) ; ptop = p10(ytop) ; if( ptop < pbot ) ptop = pbot ;
5496 if( ptop != 0.0 && ypush > 0 ){
5497 np = (ytop-ybot) / ptop + 0.5 ;
5498 switch( np ){
5499 case 1: ptop *= 0.1 ; break ;
5500 case 2: ptop *= 0.2 ; break ;
5501 case 3: ptop *= 0.25 ; break ;
5502 case 4:
5503 case 5: ptop *= 0.5 ; break ;
5504 }
5505 ybot = floor( ybot/ptop ) * ptop ;
5506 ytop = ceil( ytop/ptop ) * ptop ;
5507 nnay = floor( (ytop-ybot) / ptop + 0.5 ) ;
5508 mmay = (nnay < 3) ? 10
5509 : (nnay < 6) ? 5 : 2 ;
5510 } else {
5511 nnay = 1 ; mmay = 10 ;
5512 dy = 0.02*(ytop-ybot) ;
5513 if( ytop-floorf(ytop) > 0.001f ) ytop += dy ;
5514 if( ybot-floorf(ybot) > 0.001f ) ybot -= dy ;
5515 }
5516
5517 /*-- setup to plot --*/
5518
5519 create_memplot_surely( "ScatPlot" , 1.3 ) ;
5520
5521 /*-- plot labels, if any --*/
5522
5523 xobot = 0.15 ; xotop = 1.27 ; /* set objective size of plot */
5524 yobot = 0.1 ; yotop = 0.95 ;
5525
5526 if( STGOOD(tlab) ){ yotop -= 0.02 ; yobot -= 0.01 ; }
5527
5528 /* x-axis label? */
5529
5530 set_color_memplot( 0.0 , 0.0 , 0.0 ) ; set_thick_memplot( 0.002f ) ;
5531 if( STGOOD(xlab) )
5532 plotpak_pwritf( 0.5*(xobot+xotop) , yobot-0.06 , xlab , 16 , 0 , 0 ) ;
5533
5534 /* y-axis label? */
5535
5536 if( STGOOD(ylab) )
5537 plotpak_pwritf( xobot-0.12 , 0.5*(yobot+yotop) , ylab , 16 , 90 , 0 ) ;
5538
5539 /* label at top? */
5540
5541 if( STGOOD(tlab) )
5542 plotpak_pwritf( xobot+0.01 , yotop+0.01 , tlab , 18 , 0 , -2 ) ;
5543
5544 /* plot axes */
5545
5546 set_thick_memplot( 0.001f ) ;
5547 plotpak_set( xobot,xotop , yobot,yotop , xbot,xtop , ybot,ytop , 1 ) ;
5548 plotpak_periml( nnax,mmax , nnay,mmay ) ;
5549
5550 /* plot data */
5551
5552 #define DSQ 0.0011111
5553
5554 set_thick_memplot( 0.0f ) ;
5555 set_color_memplot( 0.0 , 0.0 , 0.4 ) ; /* 28 Feb 2011 */
5556 dsq = AFNI_numenv( "AFNI_SCATPLOT_FRAC" ) ; /* 15 Feb 2005 */
5557 if( dsq <= 0.0 || dsq >= 0.01 ){
5558 dsq = 64.0f*DSQ / sqrtf((float)npt) ;
5559 if ( dsq < 0.5f*DSQ ) dsq = 0.5f*DSQ ;
5560 else if( dsq > 5.0f*DSQ ){ dsq = 5.0f*DSQ ; set_thick_memplot(0.002f) ; }
5561 }
5562
5563 dx = dsq*(xtop-xbot) ;
5564 dy = dsq*(ytop-ybot) * (xotop-xobot)/(yotop-yobot) ;
5565 for( ii=0 ; ii < npt ; ii++ ){
5566
5567 #if 0
5568 rx = (drand48()-0.5)*dx ;
5569 ry = (drand48()-0.5)*dy ;
5570 #else
5571 rx = ry = 0.0 ;
5572 #endif
5573 xa = x[ii]+rx - dx ; xb = x[ii]+rx + dx ;
5574 ya = y[ii]+ry - dy ; yb = y[ii]+ry + dy ;
5575
5576 plotpak_line( xa,ya , xa,yb ) ;
5577 plotpak_line( xa,yb , xb,yb ) ;
5578 plotpak_line( xb,yb , xb,ya ) ;
5579 plotpak_line( xb,ya , xa,ya ) ;
5580 }
5581
5582
5583 /* draw lines (showing the linear fit of y to x) */
5584
5585 set_thick_memplot(0.003456789f) ; /* thick-ish lines */
5586 plotpak_setlin(2) ; /* and dashed line mode */
5587 for( ll=0 ; ll < nlin ; ll++ ){
5588 a = alin[ll] ; b = blin[ll] ;
5589 if( a != 0.0f || b != 0.0f ){
5590
5591 /* endpoints of line passing from left edge to right edge */
5592
5593 xa = xbot ; ya = a*xa+b ; xb = xtop ; yb = a*xb+b ;
5594
5595 /* clip line at left end */
5596
5597 if( ya < ybot && a > 0.0f ){ xa = (ybot-b)/a ; ya = ybot ; }
5598 else if( ya > ytop && a < 0.0f ){ xa = (ytop-b)/a ; ya = ytop ; }
5599
5600 /* clip line at right end */
5601
5602 if( yb < ybot && a < 0.0f ){ xb = (ybot-b)/a ; yb = ybot ; }
5603 else if( yb > ytop && a > 0.0f ){ xb = (ytop-b)/a ; yb = ytop ; }
5604
5605 set_color_memplot(clin[ll].a,clin[ll].b,clin[ll].c) ;
5606 plotpak_line( xa,ya , xb,yb ) ; /* draw it */
5607 }
5608 }
5609 plotpak_setlin(1) ; /* back to solid line mode */
5610 set_thick_memplot(0.0f) ; /* and thin lines */
5611
5612 mp = get_active_memplot() ;
5613
5614 X11_SET_NEW_PLOT ;
5615 (void) memplot_to_topshell( GLOBAL_library.dc->display , mp , NULL ) ;
5616
5617 EXRETURN ;
5618 }
5619
5620 /*----------------------------------------------------------------------*/
5621 /* The old interface, with 1 red line */
5622
PLUTO_scatterplot(int npt,float * x,float * y,char * xlab,char * ylab,char * tlab,float a,float b)5623 void PLUTO_scatterplot( int npt , float *x , float *y ,
5624 char *xlab , char *ylab , char *tlab ,
5625 float a , float b )
5626 {
5627 float alin , blin ; float_triple clin ;
5628
5629 alin = a ; blin = b ; clin.a = 0.7f ; clin.b = 0.0f ; clin.c = 0.0f ;
5630
5631 PLUTO_scatterplot_NEW( npt,x,y , xlab,ylab,tlab , 1,&alin,&blin,&clin ) ;
5632 return ;
5633 }
5634
5635 /*----------------------------------------------------------------------
5636 Routine to force AFNI to redisplay images in all open controllers.
5637 ------------------------------------------------------------------------*/
5638
PLUTO_force_redisplay(void)5639 void PLUTO_force_redisplay(void)
5640 {
5641 Three_D_View * im3d ;
5642 int ii ;
5643
5644 ENTRY("PLUTO_force_redisplay") ;
5645
5646 for( ii=0 ; ii < MAX_CONTROLLERS ; ii++ ){
5647 im3d = GLOBAL_library.controllers[ii] ;
5648 if( IM3D_OPEN(im3d) ){
5649 im3d->anat_voxwarp->type = /* 11 Jul 1997 */
5650 im3d->fim_voxwarp->type = ILLEGAL_TYPE ;
5651 IM3D_CLEAR_TMASK(im3d) ;
5652 IM3D_CLEAR_THRSTAT(im3d) ; /* 12 Jun 2014 */
5653 AFNI_set_viewpoint( im3d , -1,-1,-1 , REDISPLAY_ALL ) ;
5654 }
5655 }
5656 EXRETURN ;
5657 }
5658
5659 /*----------------------------------------------------------------------
5660 Force the redisplay of the color bars in all image windows.
5661 23 Aug 1998 -- RWCox.
5662 ------------------------------------------------------------------------*/
5663
PLUTO_force_rebar(void)5664 void PLUTO_force_rebar(void)
5665 {
5666 Three_D_View * im3d ;
5667 int ii ;
5668
5669 ENTRY("PLUTO_force_rebar") ;
5670
5671 for( ii=0 ; ii < MAX_CONTROLLERS ; ii++ ){
5672 im3d = GLOBAL_library.controllers[ii] ;
5673 if( IM3D_OPEN(im3d) ){
5674 drive_MCW_imseq( im3d->s123 , isqDR_rebar , NULL ) ;
5675 drive_MCW_imseq( im3d->s231 , isqDR_rebar , NULL ) ;
5676 drive_MCW_imseq( im3d->s312 , isqDR_rebar , NULL ) ;
5677 }
5678 }
5679 EXRETURN ;
5680 }
5681
5682 /*----------------------------------------------------------------------
5683 Force the change of opacity in all open image viewers
5684 06 Jun 2019 -- RWCox.
5685 ------------------------------------------------------------------------*/
5686
PLUTO_force_opacity_change(void)5687 void PLUTO_force_opacity_change(void)
5688 {
5689 Three_D_View *im3d ;
5690 int ii , opval=GLOBAL_library.opacity_setting ;
5691
5692 ENTRY("PLUTO_force_opacity_change") ;
5693
5694 for( ii=0 ; ii < MAX_CONTROLLERS ; ii++ ){
5695 im3d = GLOBAL_library.controllers[ii] ;
5696 if( IM3D_OPEN(im3d) ){
5697 drive_MCW_imseq( im3d->s123, isqDR_setopacity, (XtPointer)ITOP(opval) );
5698 drive_MCW_imseq( im3d->s231, isqDR_setopacity, (XtPointer)ITOP(opval) );
5699 drive_MCW_imseq( im3d->s312, isqDR_setopacity, (XtPointer)ITOP(opval) );
5700 }
5701 }
5702 EXRETURN ;
5703 }
5704
5705 /*------------------------------------------------------------------------*/
5706 static int num_workp = 0 ;
5707 static XtWorkProc * workp = NULL ;
5708 static XtPointer * datap = NULL ;
5709 static XtWorkProcId wpid ;
5710
5711 #undef WPDEBUG
5712
PLUTO_register_workproc(XtWorkProc func,XtPointer data)5713 void PLUTO_register_workproc( XtWorkProc func , XtPointer data )
5714 {
5715 ENTRY("PLUTO_register_workproc") ;
5716
5717 if( func == NULL ){
5718 fprintf(stderr,"PLUTO_register_workproc: func=NULL on entry!\n") ;
5719 EXRETURN ;
5720 }
5721
5722 if( num_workp == 0 ){
5723 workp = (XtWorkProc *) malloc( sizeof(XtWorkProc) ) ;
5724 datap = (XtPointer *) malloc( sizeof(XtPointer) ) ;
5725 wpid = XtAppAddWorkProc( PLUTO_Xt_appcontext, PLUG_workprocess, NULL ) ;
5726 #ifdef WPDEBUG
5727 fprintf(stderr,"PLUTO_register_workproc: wpid = %x\n",(int)wpid) ;
5728 #endif
5729 } else {
5730 workp = (XtWorkProc *) realloc( workp, sizeof(XtWorkProc)*(num_workp+1) ) ;
5731 datap = (XtPointer*) realloc( datap, sizeof(XtPointer) *(num_workp+1) ) ;
5732 }
5733
5734 workp[num_workp] = func ;
5735 datap[num_workp] = data ;
5736 num_workp++ ;
5737
5738 #ifdef WPDEBUG
5739 fprintf(stderr,"PLUTO_register_workproc: have %d workprocs\n",num_workp) ;
5740 #endif
5741
5742 EXRETURN ;
5743 }
5744
5745 /*----------------------------------------------------------------------------*/
5746
PLUTO_remove_workproc(XtWorkProc func)5747 void PLUTO_remove_workproc( XtWorkProc func )
5748 {
5749 int ii , ngood ;
5750
5751 ENTRY("PLUTO_remove_workproc") ;
5752
5753 if( func == NULL || num_workp == 0 ){
5754 fprintf(stderr,"*** PLUTO_remove_workproc: illegal parameters!\n") ;
5755 EXRETURN ;
5756 }
5757
5758 for( ii=0 ; ii < num_workp ; ii++ ){
5759 if( func == workp[ii] ) workp[ii] = NULL ;
5760 }
5761
5762 for( ii=0,ngood=0 ; ii < num_workp ; ii++ )
5763 if( workp[ii] != NULL ) ngood++ ;
5764
5765 if( ngood == 0 ){
5766 #ifdef WPDEBUG
5767 fprintf(stderr,"PLUTO_remove_workproc: No workprocs left\n") ;
5768 #endif
5769 XtRemoveWorkProc( wpid ) ;
5770 free(workp) ; workp = NULL ; free(datap) ; datap = NULL ;
5771 num_workp = 0 ;
5772 } else {
5773 #ifdef WPDEBUG
5774 fprintf(stderr,"PLUTO_remove_workproc: %d workprocs left\n",ngood) ;
5775 #endif
5776 }
5777
5778 EXRETURN ;
5779 }
5780
5781 /*----------------------------------------------------------------------------*/
5782
PLUG_workprocess(XtPointer fred)5783 RwcBoolean PLUG_workprocess( XtPointer fred )
5784 {
5785 int ii , ngood ;
5786 RwcBoolean done ;
5787
5788 #ifdef WPDEBUG
5789 { static int ncall=0 ;
5790 if( (ncall++) % 1000 == 0 )
5791 fprintf(stderr,"PLUG_workprocess: entry %d\n",ncall) ; }
5792 #endif
5793
5794 if( num_workp == 0 ) return True ;
5795
5796 for( ii=0,ngood=0 ; ii < num_workp ; ii++ ){
5797 if( workp[ii] != NULL ){
5798 done = workp[ii]( datap[ii] ) ;
5799 if( done == True ) workp[ii] = NULL ;
5800 else ngood++ ;
5801 }
5802 }
5803
5804 if( ngood == 0 ){
5805 #ifdef WPDEBUG
5806 fprintf(stderr,"Found no workprocs left\n") ;
5807 #endif
5808 free(workp) ; workp = NULL ; free(datap) ; datap = NULL ;
5809 num_workp = 0 ;
5810 return True ;
5811 }
5812 return False ;
5813 }
5814
5815 /*---------------------------------------------------------------*/
5816
5817 typedef struct {
5818 generic_func * func ;
5819 XtPointer cd ;
5820 } mytimeout ;
5821
PLUG_dotimeout_CB(XtPointer cd,XtIntervalId * id)5822 static void PLUG_dotimeout_CB( XtPointer cd , XtIntervalId * id )
5823 {
5824 mytimeout * myt = (mytimeout *) cd ;
5825
5826 ENTRY("PLUTO_dotimeout_CB") ;
5827
5828 if( myt == NULL ) EXRETURN ; /* bad news */
5829
5830 STATUS("calling user timeout function") ;
5831
5832 #if 0
5833 myt->func( myt->cd ) ;
5834 #else
5835 AFNI_CALL_VOID_1ARG( myt->func , XtPointer,myt->cd ) ;
5836 #endif
5837
5838 myXtFree(myt) ; EXRETURN ;
5839 }
5840
5841 /*----------------------------------------------------------------------------*/
5842
PLUTO_register_timeout(int msec,generic_func * func,XtPointer cd)5843 void PLUTO_register_timeout( int msec, generic_func * func, XtPointer cd )
5844 {
5845 mytimeout * myt ;
5846
5847 ENTRY("PLUTO_register_timeout") ;
5848
5849 if( func == NULL ){
5850 fprintf(stderr,"PLUTO_register_timeout: func=NULL on entry!\n") ;
5851 EXRETURN ;
5852 }
5853
5854 if( msec < 0 ) msec = 0 ;
5855
5856 myt = myXtNew(mytimeout) ;
5857 myt->func = func ;
5858 myt->cd = cd ;
5859
5860 (void) XtAppAddTimeOut( PLUTO_Xt_appcontext , msec ,
5861 PLUG_dotimeout_CB , (XtPointer) myt ) ;
5862
5863 EXRETURN ;
5864 }
5865
5866 /*---------------------------------------------------------------*/
5867
PLUTO_elapsed_time(void)5868 double PLUTO_elapsed_time(void) /* in seconds */
5869 {
5870 struct timeval new_tval ;
5871 struct timezone tzone ;
5872 static struct timeval old_tval ;
5873 static int first = 1 ;
5874
5875 gettimeofday( &new_tval , &tzone ) ;
5876
5877 if( first ){
5878 old_tval = new_tval ;
5879 first = 0 ;
5880 return 0.0 ;
5881 }
5882
5883 if( old_tval.tv_usec > new_tval.tv_usec ){
5884 new_tval.tv_usec += 1000000 ;
5885 new_tval.tv_sec -- ;
5886 }
5887
5888 return (double)( (new_tval.tv_sec - old_tval.tv_sec )
5889 +(new_tval.tv_usec - old_tval.tv_usec)*1.0e-6 ) ;
5890 }
5891
5892 /*----------------------------------------------------------------------------*/
5893
PLUTO_cpu_time(void)5894 double PLUTO_cpu_time(void) /* in seconds */
5895 {
5896 #ifdef CLK_TCK
5897 struct tms ttt ;
5898
5899 (void) times( &ttt ) ;
5900 return ( (double) (ttt.tms_utime
5901 /* + ttt.tms_stime */
5902 )
5903 / (double) CLK_TCK ) ;
5904 #else
5905 return 0.0 ;
5906 #endif
5907 }
5908