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 #include "bbox.h"
8 #include "xim.h"
9
10 static Widget wtemp ;
11
12 static char *wsubtype = NULL ;
BBOX_set_wsubtype(char * wt)13 void BBOX_set_wsubtype( char *wt ){ wsubtype = wt ; }
14
15 #undef DIALOG
16 #define DIALOG ( (wsubtype==NULL) ? "dialog" : wsubtype )
17
18 #undef MENU
19 #define MENU ( (wsubtype==NULL) ? "menu" : wsubtype )
20
21 static Widget old_wpar=NULL ; /* Apr 2013 -- for Allison */
22 static int old_xx=-666,old_yy=-666;
23
24 /* macro to relocate popup w.r.t. parent [12 Oct 2017] */
25
26 #undef RELOCATE
27 #define RELOCATE(wwpar,wwpop,dd) \
28 do{ int www=0 , hhh=0 ; Position qx=0,qy=0 ; \
29 MCW_widget_geom( wwpar , &www , &hhh , NULL,NULL ) ; \
30 www /= dd ; if( www < 19 ) www = 19 ; \
31 hhh /= dd ; if( hhh < 10 ) hhh = 10 ; \
32 XtTranslateCoords( wwpar , www,hhh , &qx , &qy ) ; \
33 XtVaSetValues( wwpop, XmNx,(int)qx, XmNy,(int)qy, NULL ) ; \
34 } while(0) ;
35
36 /*------------------------------------------------------------------------*/
37 /*
38 This function was meant to find the top parent of a widget and later
39 test if that parent was one that allowed rowcolumns. This was function
40 was to be called from new_MCW_bbox. However, none of the tests shown
41 below identified such forbidding widgets.
42 Code is left here for documentation purposes.
43
44 Lesstif patrol Jan 09
45 */
top_parent(Widget w)46 Widget top_parent( Widget w)
47 {
48 Widget pa = w;
49 int iw = 0;
50 char str[500]={""}, strb[500]={""};
51
52 ENTRY("top_parent");
53
54 while (pa) {
55 str[iw] = '-'; str[iw+1]='\0';
56 strb[iw] = ' '; strb[iw+1]='\0';
57 fprintf( stderr,
58 "%sWidget name %s ancestor(%d)\n",
59 str, XtName(pa), iw);
60 if (XtIsTransientShell(pa)) {
61 fprintf(stderr,"%sTransient (%d)!!!\n",strb, iw);
62 } else {
63 /*fprintf(stderr,"%sNOOOT Transient (%d)!!!\n",strb, iw);*/
64 }
65 if (XtIsTopLevelShell(pa)) {
66 fprintf(stderr,"%sTopLevel (%d)!!!\n", strb, iw);
67 } else {
68 /*fprintf(stderr,"%sNOOOT TopLevel (%d)!!!\n", strb, iw);*/
69 }
70 if (XtIsSubclass(pa, xmCascadeButtonWidgetClass)) {
71 fprintf(stderr,"%sCascadeButtonWidget (%d)!!!\n", strb, iw);
72 } else {
73 /*fprintf(stderr,"%sNOOOT CascadeButtonWidget (%d)!!!\n", strb, iw);*/
74
75 }
76 if (XtIsShell(pa)) {
77 fprintf(stderr,"%sShell (%d)!!!\n", strb, iw);
78 } else {
79 /*fprintf(stderr,"%sNOOOT Shell (%d)!!!\n", strb, iw);*/
80 }
81 w = pa;
82 pa = XtParent(w);
83 ++iw;
84 }
85 RETURN(w);
86 }
87 /*------------------------------------------------------------------------*/
88 /*
89 A simple way to determine if a widget has a popup_menu for a parent.
90
91 Lesstif Partol, Jan 09
92 */
is_daddy_popup(Widget w)93 int is_daddy_popup(Widget w)
94 {
95 Widget pa = w;
96 int iw = 0;
97 char str[500]={""}, strb[500]={""};
98
99 ENTRY("is_daddy_popup");
100
101 while (pa) {
102 str[iw] = '-'; str[iw+1]='\0';
103 strb[iw] = ' '; strb[iw+1]='\0';
104 if (!strcmp(XtName(pa), "popup_menu")) RETURN(1);
105 w = pa;
106 pa = XtParent(w);
107 ++iw;
108 }
109 RETURN(0);
110 }
111
112 /*
113 A structure to hold widget and callback information
114 for the callback wrapper used by new_MCW_bbox
115
116 Lesstif Patrol, Jan 09
117 */
118
119 typedef struct {
120 MCW_bbox *bb;
121 XtCallbackProc cb;
122 XtPointer cb_data;
123 XtPointer client_data;
124 Widget parent;
125 int is_popup;
126 int bb_type;
127 } cb_wrap_struct;
128
129 /*------------------------------------------------------------------------*/
130 /* set all buttons in a button box, given that button ikeep
131 has been pressed on */
MCW_enforce_radio_bbox(MCW_bbox * bb,int ikeep)132 void MCW_enforce_radio_bbox( MCW_bbox *bb, int ikeep )
133 {
134 int ib;
135 RwcBoolean oset ;
136
137 ENTRY("MCW_enforce_radio_bbox") ;
138
139 if( bb == NULL ) EXRETURN ; /* 01 Feb 2000 */
140 for( ib=0 ; ib < bb->nbut ; ib++ ){
141 if (ib != ikeep) {
142 oset = XmToggleButtonGetState( bb->wbut[ib] ) ;
143 if( XtIsSensitive(bb->wbut[ib]) && oset){
144 XmToggleButtonSetState( bb->wbut[ib] , !oset , False ) ;
145 XmUpdateDisplay( bb->wbut[ib] ) ;
146 }
147 }
148 }
149 bb->value = MCW_val_bbox(bb) ;
150 EXRETURN ;
151 }
152
153
154 /*------------------------------------------------------------------------*/
155 /*
156 Manually handle radio buttons where rowcolumn widgets are not allowed
157
158 See new_MCW_bbox for help
159
160 Lesstif Patrol, Jan 2009
161 */
new_MCW_bbox_cbwrap(Widget w,XtPointer client_data,XtPointer call_data)162 void new_MCW_bbox_cbwrap ( Widget w, XtPointer client_data, XtPointer call_data )
163 {
164 int ib=0, icaller = -1;
165 RwcBoolean oset = False;
166 cb_wrap_struct *cbws = (cb_wrap_struct *)client_data;
167 XmAnyCallbackStruct *cbs = (XmAnyCallbackStruct *) call_data ;
168 int dbg = 0;
169
170 ENTRY("new_MCW_bbox_cbwrap") ;
171
172 if (cbws->is_popup) {
173 if (dbg) { /* some debugging */
174 fprintf(stderr,"Potential for work\n");
175 /* For some reason, when a button other than button
176 0 is pressed, there are two callback calls made.
177 The first comes from widget 0 with a NULL event,
178 and the second from the widget pressed. */
179 for (ib=0; ib<cbws->bb->nbut; ++ib) {
180 if (cbws->bb->wbut[ib] == w) {
181 fprintf(stderr,
182 "A call from widget (%p) %s at ib = %d, reason: %d\n",
183 cbws->bb->wbut[ib], XtName(w), ib, cbs->reason);
184 if (cbs->event) {
185 fprintf(stderr,
186 " event->type = %d\n", cbs->event->type);
187 } else {
188 fprintf(stderr,
189 " event is NULL\n");
190 }
191 }
192 }
193 }
194
195 if (cbs->event) {
196 if( cbws->bb_type != MCW_BB_check ){ /* 05 May 2020 */
197 for (ib=0; ib<cbws->bb->nbut && icaller < 0; ++ib) {
198 if (cbws->bb->wbut[ib] == w) icaller = ib;
199 }
200
201 /* what --was-- the state the calling widget? */
202 oset = !XmToggleButtonGetState( cbws->bb->wbut[icaller] );
203 if (oset && cbws->bb_type == MCW_BB_radio_one) {
204 /* widget was already set, and we're in radio one mode
205 turn it back on and vamoose */
206 XmToggleButtonSetState(cbws->bb->wbut[icaller], oset, False);
207 EXRETURN;
208 }
209
210 /* flip everything but the calling widget */
211 MCW_enforce_radio_bbox(cbws->bb, icaller);
212 }
213 } else {
214 /* ignore the initial call */
215 /* for some reason, if you press on widgets other than 0, you get
216 two calls, one from widget 0 with a NULL event and another from
217 the proper widget with a proper event */
218 }
219 } else {
220 /* This is not a popup menu case, rowcolumns are allowed.
221 No need to do anything */
222 if (dbg) { /* some debugging */
223 fprintf(stderr,"I thought this caused no trouble, but check anyway\n");
224 /* For some reason, when a button other than button
225 0 is pressed, there are two callback calls made.
226 The first comes from widget 0 with a NULL event,
227 and the second from the widget pressed. */
228 for (ib=0; ib<cbws->bb->nbut; ++ib) {
229 if (cbws->bb->wbut[ib] == w) {
230 fprintf(stderr,
231 "A call from widget (%p) %s at ib = %d, reason: %d\n",
232 cbws->bb->wbut[ib], XtName(w), ib, cbs->reason);
233 if (cbs->event) {
234 fprintf(stderr,
235 " event->type = %d\n", cbs->event->type);
236 } else {
237 fprintf(stderr,
238 " event is NULL\n");
239 }
240 }
241 }
242 }
243
244 }
245
246 /* Now call the intended callback */
247 if( cbws->cb != NULL )
248 (cbws->cb)(w, cbws->cb_data, call_data);
249
250 EXRETURN;
251 }
252
253 /*-------------------------------------------------------------------------
254 create a new MCW_bbox:
255 parent = parent Widget
256 num_but = number of buttons (from 1 to MCW_MAX_BB)
257 label_but = array of strings of button labels
258 bb_type = MCW_BB_check -> check box (any may be on)
259 MCW_BB_radio_one -> radio box, exactly one will be on
260 MCW_BB_radio_zero -> radio box, zero or one will be on
261 bb_frame = MCW_BB_noframe -> no frame around box
262 = MCW_BB_frame -> put frame around box
263 cb = Callback procedure for Disarm (NULL for none)
264 cb_data = data to pass to Callback procedure (NULL for none)
265
266 Lesstif Patrol, Jan 13, 2009
267 ----------------------------
268 Rowcolumn widgets are not allowed in popup menus. Motif allowed them
269 to work, in most cases, but Lesstif does not. To fix this, new_MCW_bbox
270 was modified to check whether MCW_bbox has a popup parent. The check is
271 done with function 'is_daddy_popup'. If the parent is a popup, then
272 a rowcolumn widget is NOT created and the widget wtop is set to the
273 parent Widget. For MCW_bbox with a popup parent, allowing 'frame' to
274 be wtop if a frame is requested is bad news.
275 With this modification however, radio buttons must be managed manually.
276 To do so, new_MCW_bbox always calls a wrapper callback named
277 new_MCW_bbox_cbwrap. This callback will perform radio button management
278 if necessary and then call the button's intended callbacks.
279 ---------------------------------------------------------------------------*/
280
new_MCW_bbox(Widget parent,int num_but,char * label_but[],int bb_type,int bb_frame,XtCallbackProc cb,XtPointer cb_data)281 MCW_bbox * new_MCW_bbox( Widget parent ,
282 int num_but , char *label_but[] ,
283 int bb_type , int bb_frame ,
284 XtCallbackProc cb , XtPointer cb_data )
285 {
286 MCW_bbox *bb ;
287 int ib , initial_value ;
288 Widget rc_parent, gp;
289 Arg wa[30] ; int na ;
290 Pixel fg_pix=0 ;
291 int is_popup=0;
292 cb_wrap_struct *cbws=NULL;
293 int dbg = 0;
294
295 ENTRY("new_MCW_bbox") ;
296
297 if( num_but <= 0 || num_but >= 32 ){
298 fprintf(stderr,"\n*** illegal new_MCW_bbox has %d buttons\n",num_but) ;
299 EXIT(1) ;
300 }
301
302 /* study the parent Lesstif Patrol*/
303
304 /* finding out if a parent was 'transient' failed.
305 the function that was to do that is called
306 gp = top_parent(parent); and is left here for documentation
307 purposes. */
308
309 /* this simpler approach worked fine */
310 is_popup = is_daddy_popup(parent);
311 if (dbg) {
312 if (is_popup) {
313 for( ib=0 ; ib < num_but ; ib++ ){
314 fprintf(stderr," Popping for button %s\n", label_but[ib]);
315 }
316 } else {
317 for( ib=0 ; ib < num_but ; ib++ ){
318 fprintf(stderr," Not popping for button %s\n", label_but[ib]);
319 }
320 }
321 }
322
323 bb = (MCW_bbox *) XtMalloc( sizeof(MCW_bbox) ) ;
324 memset(bb, 0, sizeof(MCW_bbox)) ; /* 12 Feb 2009 [lesstif patrol] */
325
326 bb->nbut = num_but ;
327 initial_value = 0 ;
328
329 /***--- create Frame, if desired ---***/
330
331 switch( bb_frame ){
332
333 case MCW_BB_frame:
334 STATUS("create frame") ;
335 rc_parent = bb->wtop = bb->wframe =
336 XtVaCreateManagedWidget(
337 "frame" , xmFrameWidgetClass , parent ,
338 XmNshadowType , XmSHADOW_ETCHED_IN ,
339 XmNtraversalOn , True ,
340 XmNinitialResourcesPersistent , False ,
341 NULL ) ;
342 break ;
343
344 case MCW_BB_noframe:
345 default:
346 rc_parent = parent ;
347 bb->wframe = NULL ;
348 break ;
349 }
350
351 /***--- create RowColumn to hold the buttons ---***/
352
353 if (!is_popup) {
354 #define MAX_PER_COL 8
355
356 na = 0 ;
357
358 #ifdef BBOX_COL
359 XtSetArg( wa[na] , XmNpacking , XmPACK_COLUMN ) ; na++ ;
360 XtSetArg( wa[na] , XmNnumColumns , 1 + (num_but-1)/MAX_PER_COL ) ; na++ ;
361 #else
362 XtSetArg( wa[na] , XmNpacking , XmPACK_TIGHT ) ; na++ ;
363 #endif
364
365 XtSetArg( wa[na] , XmNmarginHeight , 0 ) ; na++ ; /* squash things in */
366 XtSetArg( wa[na] , XmNmarginWidth , 0 ) ; na++ ;
367 XtSetArg( wa[na] , XmNspacing , 1 ) ; na++ ;
368
369 XtSetArg( wa[na] , XmNtraversalOn , True ) ; na++ ;
370 XtSetArg( wa[na] , XmNinitialResourcesPersistent , False ) ; na++ ;
371
372 if( bb_type == MCW_BB_radio_zero || bb_type == MCW_BB_radio_one ){
373
374 XtSetArg( wa[na] , XmNradioBehavior , True ) ; na++ ;
375
376 if( bb_type == MCW_BB_radio_one ){
377 XtSetArg( wa[na] , XmNradioAlwaysOne , True ) ; na++ ;
378 } else {
379 XtSetArg( wa[na] , XmNradioAlwaysOne , False ) ; na++ ;
380 }
381 } else {
382 XtSetArg( wa[na] , XmNradioBehavior , False ) ; na++ ; /* 05 May 2020 */
383 }
384
385 STATUS("create rowcol") ;
386 bb->wrowcol = XtCreateWidget(
387 DIALOG , xmRowColumnWidgetClass , rc_parent ,
388 wa , na ) ;
389 if( bb->wframe == NULL ) bb->wtop = bb->wrowcol ; /* topmost widget */
390 } else {
391 bb->wrowcol = NULL;
392 /* You cannot use:
393 if( bb->wframe == NULL ) bb->wtop = parent;
394 If you do so, the recorder window does not respond to mouse
395 input */
396
397 bb->wtop = parent;
398 }
399 if( bb_type == MCW_BB_radio_one ){
400 initial_value = 1 ;
401 }
402
403 XtVaGetValues( bb->wtop , XmNforeground , &fg_pix , NULL ) ;
404
405 /***--- create the buttons ---***/
406
407 STATUS("create toggle buttons") ;
408 for( ib=0 ; ib < num_but ; ib++ ){
409 bb->wbut[ib] = XtVaCreateManagedWidget(
410 DIALOG , xmToggleButtonWidgetClass ,
411 is_popup ? parent : bb->wrowcol ,
412 LABEL_ARG(label_but[ib]) ,
413 XmNmarginHeight , 0 ,
414 XmNmarginWidth , 0 ,
415 XmNselectColor , fg_pix , /* 04 Nov 1996 */
416 XmNrecomputeSize , False ,
417 XmNtraversalOn , True ,
418 XmNinitialResourcesPersistent , False ,
419 NULL ) ;
420
421 if( cb != NULL ) {
422 cbws = (cb_wrap_struct *)calloc(1, sizeof(cb_wrap_struct));
423 cbws->bb = bb;
424 cbws->cb = cb;
425 cbws->cb_data = cb_data;
426 cbws->parent = parent;
427 cbws->is_popup = is_popup;
428 cbws->bb_type = bb_type;
429 if (dbg) fprintf(stderr,
430 "Registering callback for\n"
431 " widget (%p) %s at ib = %d, labeled %s\n",
432 bb->wbut[ib], XtName(bb->wbut[ib]), ib, label_but[ib]);
433 XtAddCallback( bb->wbut[ib] ,
434 XmNdisarmCallback ,
435 new_MCW_bbox_cbwrap, (XtPointer)cbws);
436 }
437 }
438 for( ib=num_but ; ib < MCW_MAX_BB ; ib++ ) bb->wbut[ib] = NULL ;
439
440 MCW_set_bbox( bb , initial_value ) ;
441 STATUS("manage button box") ;
442 if (bb->wrowcol) XtManageChild( bb->wrowcol ) ;
443
444 bb->parent = bb->aux = NULL ;
445 RETURN(bb) ;
446 }
447
448 /*------------------------------------------------------------------------*/
449
MCW_bbox_hints(MCW_bbox * bb,int nh,char ** hh)450 void MCW_bbox_hints( MCW_bbox *bb , int nh , char **hh )
451 {
452 int ib ;
453
454 if( bb == NULL || nh == 0 || hh == NULL ) return ;
455 if( nh > bb->nbut ) nh = bb->nbut ;
456 for( ib=0 ; ib < nh ; ib++ )
457 MCW_register_hint( bb->wbut[ib] , hh[ib] ) ;
458 return ;
459 }
460
461 /*------------------------------------------------------------------------*/
462
MCW_set_bbox(MCW_bbox * bb,int val)463 void MCW_set_bbox( MCW_bbox *bb , int val )
464 {
465 int ib ;
466 RwcBoolean nset , oset ;
467
468 ENTRY("MCW_set_bbox") ;
469
470 if( bb == NULL ) EXRETURN ; /* 01 Feb 2000 */
471 bb->value = val ;
472 for( ib=0 ; ib < bb->nbut ; ib++ ){
473 nset = ( val & (1<<ib) ) ? (True) : (False) ;
474 oset = XmToggleButtonGetState( bb->wbut[ib] ) ;
475 if( nset != oset && XtIsSensitive(bb->wbut[ib]) ){
476 XmToggleButtonSetState( bb->wbut[ib] , nset , False ) ;
477 XmUpdateDisplay( bb->wbut[ib] ) ;
478 }
479 }
480 EXRETURN ;
481 }
482
483 /*------------------------------------------------------------------------*/
484
MCW_val_bbox(MCW_bbox * bb)485 int MCW_val_bbox( MCW_bbox *bb )
486 {
487 int ib , val ;
488 RwcBoolean set ;
489
490 if( bb == NULL ) return 0 ; /* 01 Feb 2000 */
491 val = 0 ;
492 for( ib=0 ; ib < bb->nbut ; ib++ ){
493 set = XmToggleButtonGetState( bb->wbut[ib] ) ;
494 if( set ) val |= (1<<ib) ;
495 }
496 bb->value = val ;
497 return val ;
498 }
499
500 /*----------------------------------------------------------------------
501 Create a new MCW_arrowval: [label] [v][^] [value]
502 parent = parent Widget
503 label = string to put to left of arrows (NULL means none)
504 direc = MCW_AV_downup for down and up arrows
505 MCW_AV_leftright for left and right arrows
506 MCW_AV_updown for up and down arrows
507 MCW_AV_optmenu for option menu (completely different style!)
508 minval = smallest value allowed } value is like in Scales:
509 maxval = largest value allowed } an integer
510 inival = initial value }
511 textype = MCW_AV_notext to turn display of value off
512 MCW_AV_editext to allow user to edit the text
513 MCW_AV_noactext like above, but no "activation" when the
514 cursor leaves the window
515 MCW_AV_readtext to make the text display readonly
516 decim = # of decimals to shift to left for display of value
517 (like Scales)
518
519 delta_value = pointer to a function that will be called when the value
520 changes (due to arrows or text edit); not used if NULL
521 delta_data = pointer to data to be passed to delta_value;
522 delta_value( av , delta_data ) ;
523 where av is a pointer to the MCW_arrowval that changed.
524 (N.B.: the old value is available as av->old_ival
525 or av->old_fval)
526
527 text_proc = pointer to a function that returns the text to display
528 in the value window; if non-NULL, then textype is
529 forced to be MCW_AV_readtext; the routine is called by
530
531 string = text_proc( av , text_data )
532
533 text_data = pointer to data to be passed to text_proc
534 ---------------------------------------------------------------------------*/
535
new_MCW_arrowval(Widget parent,char * label,int direc,int minval,int maxval,int inival,int textype,int decim,gen_func * delta_value,XtPointer delta_data,str_func * text_proc,XtPointer text_data)536 MCW_arrowval * new_MCW_arrowval( Widget parent ,
537 char *label ,
538 int direc ,
539 int minval , int maxval , int inival ,
540 int textype , int decim ,
541 gen_func *delta_value, XtPointer delta_data,
542 str_func *text_proc , XtPointer text_data
543 )
544 {
545 MCW_arrowval *av = NULL ;
546 int asizx = 20 , asizy = 15 ; /* arrow sizes */
547 int aup , adown ;
548
549 ENTRY("new_MCW_arrowval") ;
550
551 /** July 1996: optmenu capability as a dropin for arrowval **/
552
553 if( direc == MCW_AV_optmenu ){
554 av = new_MCW_optmenu( parent , label , minval,maxval,inival , decim ,
555 delta_value , delta_data , text_proc , text_data ) ;
556 RETURN(av) ;
557 }
558
559 av = myXtNew( MCW_arrowval ) ;
560 STATUS("creating wrowcol") ;
561 av->wrowcol = XtVaCreateWidget(
562 DIALOG , xmRowColumnWidgetClass , parent ,
563
564 XmNpacking , XmPACK_TIGHT ,
565 XmNorientation , XmHORIZONTAL ,
566 XmNmarginHeight , 0 ,
567 XmNmarginWidth , 0 ,
568 XmNspacing , 0 ,
569 #if 0
570 XmNresizeHeight , False ,
571 XmNresizeWidth , False ,
572 #endif
573 XmNinitialResourcesPersistent , False ,
574 XmNtraversalOn , True ,
575 NULL ) ;
576
577 if( label != NULL && strlen(label) > 0 ){
578 XmString xstr = XmStringCreateLtoR( label , XmFONTLIST_DEFAULT_TAG );
579 XmFontList xflist = (XmFontList)NULL ;
580
581 STATUS("creating wlabel") ;
582 av->wlabel = XtVaCreateManagedWidget(
583 DIALOG , xmLabelWidgetClass , av->wrowcol ,
584 XmNlabelString , xstr ,
585 XmNrecomputeSize , False ,
586 XmNmarginWidth , 0 ,
587 XmNinitialResourcesPersistent , False ,
588 NULL ) ;
589 LABELIZE(av->wlabel) ;
590 XtVaGetValues( av->wlabel , XmNfontList , &xflist , NULL ) ;
591
592 STATUS("getting label height") ;
593 if( xflist != (XmFontList)NULL ){
594 asizy = XmStringHeight( xflist , xstr ) ;
595 } else {
596 static int first = 1 ;
597 if( first ){ ERROR_message("Can't get font list?"); first=0; }
598 }
599 STATUS("freeing xstr") ;
600 XmStringFree( xstr ) ;
601
602 } else {
603 av->wlabel = NULL ;
604 }
605
606 if( asizx < asizy ) asizx = asizy ;
607 else asizy = asizx ;
608
609 STATUS("creating item labels") ;
610
611 adown = (direc==MCW_AV_leftright) ? XmARROW_LEFT
612 :(direc==MCW_AV_downup ) ? XmARROW_DOWN : XmARROW_UP ;
613
614 aup = (direc==MCW_AV_leftright) ? XmARROW_RIGHT
615 :(direc==MCW_AV_downup ) ? XmARROW_UP : XmARROW_DOWN ;
616
617 av->wdown = XtVaCreateManagedWidget(
618 "arrow" , xmArrowButtonWidgetClass , av->wrowcol ,
619
620 XmNarrowDirection , adown ,
621
622 XmNheight , asizy , XmNwidth , asizx ,
623 XmNborderWidth , 0 ,
624
625 XmNinitialResourcesPersistent , False ,
626 XmNtraversalOn , True ,
627 NULL ) ;
628
629 av->wup = XtVaCreateManagedWidget(
630 "arrow" , xmArrowButtonWidgetClass , av->wrowcol ,
631
632 XmNarrowDirection , aup ,
633
634 XmNheight , asizy , XmNwidth , asizx ,
635 XmNborderWidth , 0 ,
636
637 XmNinitialResourcesPersistent , False ,
638 XmNtraversalOn , True ,
639 NULL ) ;
640
641 XtAddCallback( av->wdown , XmNarmCallback , AV_press_CB , av ) ;
642 XtAddCallback( av->wdown , XmNdisarmCallback , AV_press_CB , av ) ;
643 XtAddCallback( av->wup , XmNarmCallback , AV_press_CB , av ) ;
644 XtAddCallback( av->wup , XmNdisarmCallback , AV_press_CB , av ) ;
645
646 if( text_proc != NULL && textype != MCW_AV_notext )
647 textype = MCW_AV_readtext ;
648
649 switch( textype ){
650
651 default:
652 case MCW_AV_notext:
653 av->wtext = NULL ;
654 av->text_CB = NULL ;
655 av->text_data = NULL ;
656 break ;
657
658 /* Note hardwire of 9 columns of text, here and in AV_fval_to_char;
659 this CANNOT be changed just by changing AV_NCOL below, you must
660 also edit the sprintf formats in AV_fval_to_char.
661
662 If text_proc is not NULL, then av->wtext could have its dimensions
663 changed later to handle the user supplied string. My point above
664 is that the default text_proc is hardwired to 9 characters wide.
665 */
666
667 #ifndef AV_NCOL
668 #define AV_NCOL 9
669 #endif
670
671 case MCW_AV_readtext:
672 STATUS("creating wtext1") ;
673 av->wtext = XtVaCreateManagedWidget(
674 DIALOG , TEXT_CLASS , av->wrowcol ,
675
676 XmNcolumns , AV_NCOL ,
677 XmNeditable , False ,
678 XmNmaxLength , AV_NCOL ,
679 XmNresizeWidth , False ,
680 XmNshadowThickness , 0 ,
681 #if 0
682 XmNsensitive , False , /* looks bad */
683 #endif
684 XmNmarginHeight , 1 ,
685 XmNmarginWidth , 1 ,
686
687 XmNcursorPositionVisible , False ,
688
689 XmNinitialResourcesPersistent , False ,
690 XmNtraversalOn , True ,
691 NULL ) ;
692
693 av->text_CB = (text_proc != NULL ) ? (text_proc)
694 : (AV_default_text_CB) ;
695 av->text_data = text_data ;
696 break ;
697
698 case MCW_AV_noactext: /* noactext added 08 Feb 1999 */
699 case MCW_AV_editext:{
700 Widget wf ; int maxlen ;
701
702 if( textype == MCW_AV_noactext ){
703 STATUS("creating frame") ;
704 wf = XtVaCreateWidget( DIALOG , xmFrameWidgetClass , av->wrowcol ,
705 XmNshadowType , XmSHADOW_OUT ,
706 XmNshadowThickness , 1 ,
707 XmNtraversalOn , True ,
708 XmNinitialResourcesPersistent , False ,
709 NULL ) ;
710 maxlen = AV_MAXLEN ;
711 } else {
712 wf = av->wrowcol ;
713 maxlen = AV_NCOL ;
714 }
715
716 STATUS("creating wtext2") ;
717 av->wtext = XtVaCreateManagedWidget(
718 DIALOG , TEXT_CLASS , wf ,
719
720 XmNcolumns , AV_NCOL ,
721 XmNeditable , True ,
722 XmNmaxLength , maxlen ,
723 XmNresizeWidth , False ,
724
725 XmNmarginHeight , 1 ,
726 XmNmarginWidth , 1 ,
727
728 XmNcursorPositionVisible , True ,
729 XmNblinkRate , 0 ,
730 XmNautoShowCursorPosition , True ,
731
732 XmNinitialResourcesPersistent , False ,
733 XmNtraversalOn , True ,
734 NULL ) ;
735
736 if( textype == MCW_AV_noactext ) XtManageChild(wf) ;
737
738 if( textype == MCW_AV_editext ){
739 XtAddCallback( av->wtext , XmNactivateCallback ,
740 AV_textact_CB , av ) ; /* return key */
741
742 XtAddCallback( av->wtext , XmNlosingFocusCallback ,
743 AV_textact_CB , av ) ; /* tab key */
744
745 XtInsertEventHandler( av->wtext , /* notify when */
746 LeaveWindowMask , /* pointer leaves */
747 FALSE , /* this window */
748 AV_leave_EV ,
749 (XtPointer) av ,
750 XtListTail ) ; /* last in queue */
751 }
752
753 av->text_CB = AV_default_text_CB ;
754 av->text_data = NULL ;
755 }
756 break ;
757
758 }
759
760 av->wname = NULL ;
761
762 XtManageChild( av->wrowcol ) ;
763
764 if( minval < maxval ){
765 av->fmin = av->imin = minval ; AV_SHIFT_VAL(decim,av->fmin) ;
766 av->fmax = av->imax = maxval ; AV_SHIFT_VAL(decim,av->fmax) ;
767 } else {
768 av->fmin = av->imin = -9999999 ; AV_SHIFT_VAL(decim,av->fmin) ;
769 av->fmax = av->imax = 9999999 ; AV_SHIFT_VAL(decim,av->fmax) ;
770 }
771 av->decimals = decim ;
772 av->timer_id = 0 ;
773 av->fastdelay = MCW_AV_shortdelay ; /* default delay on 2nd call */
774
775 av->fval = av->ival = inival ; AV_SHIFT_VAL(decim,av->fval) ;
776
777 av->sval = av->old_sval = NULL ; /* string values */
778
779 av->block_assign_actions = 0 ; /* don't block these actions */
780 av->wmenu = NULL ; /* signal that this is NOT an optmenu */
781 av->optmenu_call_if_unchanged = 0 ; /* 10 Oct 2007 */
782
783 AV_assign_ival( av , inival ) ;
784
785 av->dval_CB = delta_value ;
786 av->dval_data = delta_data ;
787
788 av->allow_wrap = 0 ;
789
790 av->parent = av->aux = NULL ;
791 av->fstep = 0.0 ; /* 16 Feb 1999 */
792 RETURN(av) ;
793 }
794
795 /*-----------------------------------------------------------------------*/
796
AV_colsize()797 int AV_colsize() /* 11 Dec 2001 */
798 {
799 int cc=20 ; char *ee ;
800 ee = getenv("AFNI_MENU_COLSIZE") ;
801 if( ee != NULL ){
802 cc = (int) strtol(ee,NULL,10) ;
803 if( cc < 9 ) cc = 10 ;
804 }
805 return cc ;
806 }
807
808 /*-----------------------------------------------------------------------
809 This can be used as a "drop in" replacement for a arrowval with a
810 small fixed number of elements. The textype argument is missing because
811 the only one that makes sense is MCW_AV_readtext (readonly text as button
812 labels). The direc argument is missing because that choice has already
813 been made.
814 -------------------------------------------------------------------------*/
815
816 #define COLSIZE AV_colsize() /* 11 Dec 2001: redefined from a constant */
817
818 static void optmenu_EV( Widget,XtPointer,XEvent *,RwcBoolean *) ; /* prototype */
819
820 static volatile int allow_optmenu_EV = 1 ;
821
allow_MCW_optmenu_popup(int ii)822 void allow_MCW_optmenu_popup( int ii ){ allow_optmenu_EV = ii ; }
823
824 #undef USE_FIXUP
825 #ifdef USE_FIXUP
826 static void optmenu_EV_fixup( Widget ww ) ;
827 #endif
828
829
830 /*
831 This is the only fix we could come up with to keep
832 AFNI from crashing when users open a pulldown menu
833 and select from a menu within:
834
835 graph-->click Opt AND drag to Tran 0D = BOOM
836
837 Doing:
838 graph-->click Opt, RELEASE -->click Tran 0D = Hazah!
839
840 The problem is either in Lesstif or Xt.
841
842 What we do is capture the button release over such
843 menus and dispatch a button press immediately. So
844 every time there is a button release atop such menus,
845 there is an additional button press call done.
846
847 That seems to do the trick, we hope.
848
849 Feb 13 2009, [LPatrol]
850 */
text_EV(int v)851 const char *text_EV(int v)
852 {
853 switch (v) {
854 case EnterNotify:
855 return("enter");
856 case LeaveNotify:
857 return("leave");
858 case ButtonPress:
859 return("press");
860 case ButtonRelease:
861 return("release");
862 default:
863 return("dunno");
864 }
865 return("weird");
866 }
enter_EV(Widget w,XtPointer client_data,XEvent * ev,RwcBoolean * continue_to_dispatch)867 void enter_EV( Widget w , XtPointer client_data ,
868 XEvent * ev , RwcBoolean * continue_to_dispatch )
869 {
870 XLeaveWindowEvent * lev = (XLeaveWindowEvent *) ev ;
871 XButtonEvent *bev = (XButtonEvent *)ev;
872 MCW_arrowval *av = (MCW_arrowval *)client_data;
873 int is_popup = 0;
874 static Widget widlist[10000];
875 int N_widlist=0;
876 int dbg =0;
877
878 #ifdef USING_LESSTIF
879 if (CPU_IS_64_BIT() ){
880 is_popup = is_daddy_popup(w);
881 if (dbg > 1) {
882 fprintf(stderr,
883 "\n"
884 "ispopup=%d\n"
885 "%s bev->button = %d\n"
886 "av->wdown=%p, av->wlabel=%p\n"
887 "w =%p, w =%p\n"
888 "av->wrowcol=%p\n"
889 "ev->type %d (realized: %d) \n"
890 " Queued %d, QAF %d, QAR %d\n"
891 "E%d,L%d,P%d,R%d\n"
892 "\n",
893 is_popup, text_EV(lev->type), bev->button,
894 av->wdown, av->wlabel, w, w, av->wrowcol,
895 lev->type,
896 XtIsRealized(w),
897 XEventsQueued(XtDisplay(w), QueuedAlready ),
898 XEventsQueued(XtDisplay(w), QueuedAfterFlush ),
899 XEventsQueued(XtDisplay(w), QueuedAfterReading ),
900 EnterNotify, LeaveNotify, ButtonPress, ButtonRelease);
901 } else if (dbg) {
902 fprintf(stderr,
903 "\n"
904 "%s widget %p, button = %d\n""\n",
905 text_EV(lev->type), w, bev->button);
906
907 }
908
909 /* NOTICE: This last ditch fix only for an option menu inside a pulldown
910 window. */
911 if (is_popup && bev->button == 1 && ev->type == ButtonRelease) {
912 /* Button release over menu button: DUCK! */
913 if (dbg) fprintf(stderr,"Holy Toledo!\n");
914 ev->type = ButtonPress; /* Make that be a button press first */
915 XtDispatchEvent(ev); /* pray real hard now */
916 /* DO NOT reset ev->type to ButtonRelease; don't ask. */
917 }
918 }
919 #endif
920 }
921
922 /* create a chooser list of text strings */
923 /* label - title string to the left of the chooser dropdown
924 minval - minimum value of index (usually 0)
925 maxval - maximum value of index (usually the number of strings - 1
926 inival - initial value of index (to get default string shown)
927 decim - number of decimal places to shift a number in a string (I haven't used this yet)
928 delta_value - callback function when item is changed (use void function)
929 delta_data - ?
930 text_proc - function to use as the chooser list is filled
931 (usually MCW_av_substring_CB)
932 text_data - list of strings to fill chooser list (char **)
933 (probably should not freed (static may be good too) )
934 */
new_MCW_optmenu(Widget parent,char * label,int minval,int maxval,int inival,int decim,gen_func * delta_value,XtPointer delta_data,str_func * text_proc,XtPointer text_data)935 MCW_arrowval * new_MCW_optmenu( Widget parent ,
936 char *label ,
937 int minval , int maxval , int inival ,
938 int decim ,
939 gen_func *delta_value, XtPointer delta_data,
940 str_func *text_proc , XtPointer text_data
941 )
942 {
943 ENTRY("new_MCW_optmenu") ;
944
945 #ifdef USING_LESSTIF_NOT_DOING_THIS_CRAP
946 if (CPU_IS_64_BIT() ){
947 RETURN(new_MCW_optmenu_64fix(
948 parent , label ,
949 minval , maxval , inival ,
950 decim ,
951 delta_value, delta_data,
952 text_proc , text_data));
953 }
954 #endif
955
956 RETURN(new_MCW_optmenu_orig(
957 parent , label ,
958 minval , maxval , inival ,
959 decim ,
960 delta_value, delta_data,
961 text_proc , text_data));
962 }
963
new_MCW_optmenu_orig(Widget parent,char * label,int minval,int maxval,int inival,int decim,gen_func * delta_value,XtPointer delta_data,str_func * text_proc,XtPointer text_data)964 MCW_arrowval * new_MCW_optmenu_orig( Widget parent ,
965 char *label ,
966 int minval , int maxval , int inival ,
967 int decim ,
968 gen_func *delta_value, XtPointer delta_data,
969 str_func *text_proc , XtPointer text_data
970 )
971 {
972 MCW_arrowval *av = myXtNew( MCW_arrowval ) ;
973 Widget wmenu , wbut ;
974 Arg args[5] ;
975 int nargs , ival ;
976 XmString xstr ;
977 char *butlabel , *blab ;
978 int dbg = 0;
979
980 ENTRY("new_MCW_optmenu_orig") ;
981
982 /** create the menu window **/
983
984 STATUS("creating menu window") ;
985 av->wmenu = wmenu = XmCreatePulldownMenu( parent , MENU , NULL , 0 ) ;
986 av->optmenu_call_if_unchanged = 0 ; /* 10 Oct 2007 */
987
988 VISIBILIZE_WHEN_MAPPED(wmenu) ;
989 #if 0 /* doesn't work well if optmenu is inside a popup! */
990 if( !AFNI_yesenv("AFNI_DISABLE_TEAROFF") ) TEAROFFIZE(wmenu) ;
991 #endif
992
993 /** create the button that pops down the menu **/
994
995 nargs = 0 ;
996 XtSetArg( args[nargs] , XmNsubMenuId , wmenu ) ; nargs++ ;
997 XtSetArg( args[nargs] , XmNtraversalOn, True ) ; nargs++ ;
998
999 if( label == NULL ) label = " " ; /* 24 Sep 2001 */
1000
1001 xstr = XmStringCreateLtoR( label , XmFONTLIST_DEFAULT_TAG ) ;
1002 XtSetArg( args[nargs] , XmNlabelString , xstr ) ; nargs++ ;
1003
1004 STATUS("creating option menu") ;
1005 av->wrowcol = XmCreateOptionMenu( parent , DIALOG , args , nargs ) ;
1006 XmStringFree(xstr) ;
1007 XtVaSetValues( av->wrowcol ,
1008 XmNmarginWidth , 0 ,
1009 XmNmarginHeight , 0 ,
1010 XmNspacing , 2 ,
1011 XmNtraversalOn , True ,
1012 NULL ) ;
1013
1014 av->wlabel = XmOptionLabelGadget (av->wrowcol) ;
1015 av->wdown = XmOptionButtonGadget(av->wrowcol) ;
1016 av->wup = NULL ;
1017 av->wtext = NULL ; /* signal that this is NOT really an arrowval */
1018 av->wname = NULL ;
1019
1020 XtVaSetValues( av->wlabel , /* label next to menu button */
1021 XmNmarginWidth , 0 ,
1022 XmNmarginHeight , 0 ,
1023 XmNmarginBottom , 0 ,
1024 XmNmarginTop , 0 ,
1025 XmNmarginRight , 0 ,
1026 XmNmarginLeft , 0 ,
1027 NULL ) ;
1028
1029 if( label == NULL || strlen(label) == 0 ){
1030 XtVaSetValues( av->wlabel , XmNwidth , 0 , NULL ) ;
1031 XtVaSetValues( av->wrowcol , XmNspacing , 2 , NULL ) ;
1032 }
1033
1034 XtVaSetValues( av->wdown , /* menu button */
1035 XmNmarginWidth , 0 ,
1036 XmNmarginHeight , 0 ,
1037 XmNmarginBottom , 0 ,
1038 XmNmarginTop , 0 ,
1039 XmNmarginRight , 0 ,
1040 XmNmarginLeft , 0 ,
1041 XmNtraversalOn , True ,
1042 XmNhighlightThickness , 0 ,
1043 NULL ) ;
1044
1045 av->text_CB = (text_proc != NULL ) ? (text_proc)
1046 : (AV_default_text_CB) ;
1047 av->text_data = text_data ;
1048 av->decimals = decim ;
1049 av->fmin = av->imin = minval ; AV_SHIFT_VAL(decim,av->fmin) ;
1050 av->fmax = av->imax = maxval ; AV_SHIFT_VAL(decim,av->fmax) ;
1051 av->sval = av->old_sval = NULL ;
1052
1053 av->block_assign_actions = 1 ; /* temporarily block these actions */
1054
1055 /** create the buttons on the menu window **/
1056
1057 for( ival=minval ; ival <= maxval ; ival++ ){
1058
1059 AV_assign_ival( av , ival ) ; /* just to create label */
1060
1061 blab = butlabel = XtNewString( av->sval ) ;
1062 if( av->text_CB==AV_default_text_CB && butlabel[0]==' ' && minval >= 0 ){
1063 blab += 1 ; /* deal with leading blanks in default routine */
1064 }
1065
1066 xstr = XmStringCreateLtoR( blab , XmFONTLIST_DEFAULT_TAG ) ;
1067
1068 wbut = XtVaCreateManagedWidget(
1069 DIALOG , xmPushButtonWidgetClass , wmenu ,
1070 XmNlabelString , xstr ,
1071 XmNmarginWidth , 0 ,
1072 XmNmarginHeight , 0 ,
1073 XmNmarginBottom , 0 ,
1074 XmNmarginTop , 0 ,
1075 XmNmarginRight , 0 ,
1076 XmNmarginLeft , 0 ,
1077 XmNuserData , (XtPointer)ITOP(ival) , /* Who am I? */
1078 XmNtraversalOn , True ,
1079 XmNinitialResourcesPersistent , False ,
1080 NULL ) ;
1081
1082 XmStringFree(xstr) ; myXtFree(butlabel) ;
1083
1084 XtAddCallback( wbut , XmNactivateCallback , AVOPT_press_CB , av ) ;
1085
1086 if( ival == inival )
1087 XtVaSetValues( av->wrowcol , XmNmenuHistory , wbut , NULL ) ;
1088 }
1089
1090 XtManageChild( av->wrowcol ) ;
1091
1092 av->timer_id = 0 ; /* won't be used for this type of arrowval! */
1093 av->fastdelay = 0 ;
1094
1095 av->block_assign_actions = 0 ; /* unblock these actions */
1096
1097 AV_assign_ival( av , inival ) ; /* actual initial assignment */
1098
1099 av->dval_CB = delta_value ;
1100 av->dval_data = delta_data ;
1101
1102 av->allow_wrap = 0 ;
1103
1104 av->parent = av->aux = NULL ;
1105 av->fstep = 0.0 ; /* 16 Feb 1999 */
1106
1107 /* 11 Dec 2001: allow user to choose via Button-3 popup */
1108
1109 if( allow_optmenu_EV ){
1110 XtInsertEventHandler( av->wrowcol , /* handle events in optmenu */
1111 ButtonPressMask , /* button presses */
1112 FALSE , /* nonmaskable events? */
1113 optmenu_EV , /* handler */
1114 (XtPointer) av , /* client data */
1115 XtListTail ) ; /* last in queue */
1116 #ifdef USE_FIXUP
1117 optmenu_EV_fixup( av->wrowcol ) ;
1118 #endif
1119 }
1120
1121 RETURN(av) ;
1122 }
1123
1124
new_MCW_optmenu_64fix(Widget parent,char * label,int minval,int maxval,int inival,int decim,gen_func * delta_value,XtPointer delta_data,str_func * text_proc,XtPointer text_data)1125 MCW_arrowval * new_MCW_optmenu_64fix( Widget parent ,
1126 char *label ,
1127 int minval , int maxval , int inival ,
1128 int decim ,
1129 gen_func *delta_value, XtPointer delta_data,
1130 str_func *text_proc , XtPointer text_data
1131 )
1132 {
1133 MCW_arrowval *av = myXtNew( MCW_arrowval ) ;
1134 Widget wmenu , wbut, rcholder , lb, rcparent;
1135 Arg args[5] ;
1136 int nargs , ival ;
1137 XmString xstr ;
1138 char *butlabel , *blab ;
1139 int dbg = 0;
1140
1141 ENTRY("new_MCW_optmenu_64fix") ;
1142
1143 rcparent = XtVaCreateWidget ("rowcolumn",
1144 xmRowColumnWidgetClass, parent,
1145 XmNpacking, XmPACK_TIGHT,
1146 XmNorientation , XmHORIZONTAL ,
1147 XmNmarginHeight, 0 ,
1148 XmNmarginWidth , 0 ,
1149 NULL); /** create the menu window **/
1150
1151 av->wmenu = wmenu = XmCreatePulldownMenu( rcparent , MENU , NULL , 0 ) ;
1152 av->optmenu_call_if_unchanged = 0 ; /* 10 Oct 2007 */
1153
1154 VISIBILIZE_WHEN_MAPPED(wmenu) ;
1155 #if 0 /* doesn't work well if optmenu is inside a popup! */
1156 if( !AFNI_yesenv("AFNI_DISABLE_TEAROFF") ) TEAROFFIZE(wmenu) ;
1157 #endif
1158
1159 /** create the button that pops down the menu **/
1160
1161 nargs = 0 ;
1162 XtSetArg( args[nargs] , XmNsubMenuId , wmenu ) ; nargs++ ;
1163 XtSetArg( args[nargs] , XmNtraversalOn, True ) ; nargs++ ;
1164
1165 if( label == NULL ) label = " " ; /* 24 Sep 2001 */
1166
1167 rcholder = XtVaCreateWidget ("rowcolumn",
1168 xmRowColumnWidgetClass, rcparent,
1169 XmNpacking, XmPACK_TIGHT,
1170 XmNorientation , XmHORIZONTAL ,
1171 XmNmarginWidth , 0 ,
1172 XmNmarginHeight , 0 ,
1173 XmNmarginBottom , 0 ,
1174 XmNmarginTop , 0 ,
1175 XmNmarginRight , 0 ,
1176 XmNmarginLeft , 0 ,
1177 XmNspacing , 0 ,
1178 NULL);
1179 lb = XtVaCreateManagedWidget (label,
1180 xmLabelWidgetClass, rcholder,
1181 XmNmarginHeight, 0 ,
1182 XmNmarginWidth , 0 ,
1183 XmNmarginWidth , 0 ,
1184 XmNmarginHeight , 0 ,
1185 XmNmarginBottom , 0 ,
1186 XmNmarginTop , 0 ,
1187 XmNmarginRight , 0 ,
1188 XmNmarginLeft , 0 ,
1189 NULL) ;
1190 LABELIZE(lb) ;
1191
1192 xstr = XmStringCreateLtoR( "" , XmFONTLIST_DEFAULT_TAG ) ;
1193 XtSetArg( args[nargs] , XmNlabelString , xstr ) ; nargs++ ;
1194 av->wrowcol = XmCreateOptionMenu( rcholder , DIALOG , args , nargs ) ;
1195 XmStringFree(xstr) ;
1196 XtVaSetValues( av->wrowcol ,
1197 XmNmarginWidth , 0 ,
1198 XmNmarginHeight , 0 ,
1199 XmNspacing , 2 ,
1200 XmNtraversalOn , True ,
1201 NULL ) ;
1202
1203 #ifdef USING_LESSTIF
1204 if (CPU_IS_64_BIT() ){
1205 XtInsertEventHandler( av->wrowcol ,
1206 ButtonReleaseMask ,
1207 FALSE ,
1208 enter_EV,
1209 (XtPointer) av,
1210 XtListHead) ;
1211 /*
1212 XtInsertEventHandler( av->wrowcol ,
1213 ButtonPressMask ,
1214 FALSE ,
1215 enter_EV,
1216 (XtPointer) av ,
1217 XtListHead) ;
1218 XtInsertEventHandler( av->wrowcol ,
1219 EnterWindowMask ,
1220 FALSE ,
1221 enter_EV,
1222 (XtPointer) av,
1223 XtListHead) ;
1224
1225 XtInsertEventHandler( av->wrowcol ,
1226 LeaveWindowMask ,
1227 FALSE ,
1228 enter_EV,
1229 (XtPointer) av,
1230 XtListHead) ;
1231 */
1232 }
1233 #endif
1234 av->wlabel = lb ;
1235 av->wdown = XmOptionButtonGadget(av->wrowcol) ;
1236 av->wup = NULL ;
1237 av->wtext = NULL ; /* signal that this is NOT really an arrowval */
1238
1239 XtVaSetValues( av->wlabel , /* label next to menu button */
1240 XmNmarginWidth , 0 ,
1241 XmNmarginHeight , 0 ,
1242 XmNmarginBottom , 0 ,
1243 XmNmarginTop , 0 ,
1244 XmNmarginRight , 0 ,
1245 XmNmarginLeft , 0 ,
1246 NULL ) ;
1247
1248 if( label == NULL || strlen(label) == 0 ){
1249 XtVaSetValues( av->wlabel , XmNwidth , 0 , NULL ) ;
1250 XtVaSetValues( av->wrowcol , XmNspacing , 2 , NULL ) ;
1251 }
1252
1253 XtVaSetValues( av->wdown , /* menu button */
1254 XmNmarginWidth , 0 ,
1255 XmNmarginHeight , 0 ,
1256 XmNmarginBottom , 0 ,
1257 XmNmarginTop , 0 ,
1258 XmNmarginRight , 0 ,
1259 XmNmarginLeft , 0 ,
1260 XmNtraversalOn , True ,
1261 XmNhighlightThickness , 0 ,
1262 NULL ) ;
1263
1264 av->text_CB = (text_proc != NULL ) ? (text_proc)
1265 : (AV_default_text_CB) ;
1266 av->text_data = text_data ;
1267 av->decimals = decim ;
1268 av->fmin = av->imin = minval ; AV_SHIFT_VAL(decim,av->fmin) ;
1269 av->fmax = av->imax = maxval ; AV_SHIFT_VAL(decim,av->fmax) ;
1270 av->sval = av->old_sval = NULL ;
1271
1272 av->block_assign_actions = 1 ; /* temporarily block these actions */
1273
1274 /** create the buttons on the menu window **/
1275
1276 for( ival=minval ; ival <= maxval ; ival++ ){
1277
1278 AV_assign_ival( av , ival ) ; /* just to create label */
1279
1280 blab = butlabel = XtNewString( av->sval ) ;
1281 if( av->text_CB==AV_default_text_CB && butlabel[0]==' ' && minval >= 0 ){
1282 blab += 1 ; /* deal with leading blanks in default routine */
1283 }
1284
1285 xstr = XmStringCreateLtoR( blab , XmFONTLIST_DEFAULT_TAG ) ;
1286
1287 wbut = XtVaCreateManagedWidget(
1288 DIALOG , xmPushButtonWidgetClass , wmenu ,
1289 XmNlabelString , xstr ,
1290 XmNmarginWidth , 0 ,
1291 XmNmarginHeight , 0 ,
1292 XmNmarginBottom , 0 ,
1293 XmNmarginTop , 0 ,
1294 XmNmarginRight , 0 ,
1295 XmNmarginLeft , 0 ,
1296 XmNuserData , (XtPointer)ITOP(ival) , /* Who am I? */
1297 XmNtraversalOn , True ,
1298 XmNinitialResourcesPersistent , False ,
1299 NULL ) ;
1300
1301 XmStringFree(xstr) ; myXtFree(butlabel) ;
1302
1303 XtAddCallback( wbut , XmNactivateCallback , AVOPT_press_CB , av ) ;
1304
1305 if( ival == inival )
1306 XtVaSetValues( av->wrowcol , XmNmenuHistory , wbut , NULL ) ;
1307 }
1308
1309 XtManageChild( av->wrowcol ) ;
1310
1311 av->timer_id = 0 ; /* won't be used for this type of arrowval! */
1312 av->fastdelay = 0 ;
1313
1314 av->block_assign_actions = 0 ; /* unblock these actions */
1315
1316 AV_assign_ival( av , inival ) ; /* actual initial assignment */
1317
1318 av->dval_CB = delta_value ;
1319 av->dval_data = delta_data ;
1320
1321 av->allow_wrap = 0 ;
1322
1323 av->parent = av->aux = NULL ;
1324 av->fstep = 0.0 ; /* 16 Feb 1999 */
1325
1326 /* 11 Dec 2001: allow user to choose via Button-3 popup */
1327
1328 if( allow_optmenu_EV ){
1329 XtInsertEventHandler( av->wlabel , /* handle events in optmenu */
1330 ButtonPressMask , /* button presses */
1331 FALSE , /* nonmaskable events? */
1332 optmenu_EV , /* handler */
1333 (XtPointer) av , /* client data */
1334 XtListTail ) ; /* last in queue */
1335 #ifdef USE_FIXUP
1336 optmenu_EV_fixup( av->wlabel ) ;
1337 #endif
1338 }
1339 XtManageChild( rcholder);
1340 XtManageChild( rcparent);
1341 RETURN(av) ;
1342 }
1343
1344 /*----------------------------------------------------------------------------
1345 Relabels all the buttons on an optmenu, adding or unmanaging as needed.
1346 The label and action callback remain the same.
1347 ------------------------------------------------------------------------------*/
1348
refit_MCW_optmenu(MCW_arrowval * av,int minval,int maxval,int inival,int decim,str_func * text_proc,XtPointer text_data)1349 void refit_MCW_optmenu( MCW_arrowval *av ,
1350 int minval , int maxval , int inival , int decim ,
1351 str_func *text_proc , XtPointer text_data )
1352 {
1353 Widget *children=NULL , wbut , wmenu ;
1354 int num_children=0 , ic , ival ;
1355 char *butlabel , *blab ;
1356 XmString xstr ;
1357 int maxbut ; /* 23 Aug 2003 */
1358 static int iwarn=0;
1359
1360 ENTRY("refit_MCW_optmenu") ;
1361
1362 /** sanity check **/
1363
1364 if( av == NULL || av->wmenu == NULL ) EXRETURN ;
1365 wmenu = av->wmenu ;
1366
1367 /** get all the existing children **/
1368
1369 #if 0
1370 XtUnmanageChild( av->wrowcol ) ; XtUnmanageChild( wmenu ) ;
1371 #endif
1372
1373 XtVaGetValues( wmenu ,
1374 XmNchildren , &children ,
1375 XmNnumChildren , &num_children ,
1376 NULL ) ;
1377
1378 /* 23 Aug 2003: replace hard limit of 255 buttons
1379 with maxbut from environment variable */
1380
1381 maxbut = AFNI_numenv( "AFNI_MAX_OPTMENU" ) ;
1382 if( maxbut <= 0 ) maxbut = 1024 ; /* up from 255 ZSS Aug. 4 2011 */
1383 else if( maxbut < 99 ) maxbut = 99 ;
1384 if( maxval > minval+maxbut ) {
1385 if (!iwarn % 15) { /* ZSS June 2011 */
1386 INFO_message(
1387 "\n"
1388 "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"
1389 "The number of sub-bricks in one of your datasets exceeds \n"
1390 " the current maximum of %d. Some menus like Ulay/Olay/Thr \n"
1391 " will not allow you to select sub-bricks beyond #%d.\n"
1392 "To access all sub-bricks from such menus, increase the value of \n"
1393 " environment variable 'AFNI_MAX_OPTMENU'. You can do so for this \n"
1394 " AFNI session via the 'Edit Environment' plugin. For a more lasting \n"
1395 " fix, add the line:\n"
1396 " AFNI_MAX_OPTMENU = XXX \n"
1397 " under the '***ENVIRONMENT' section of your .afnirc file with XXX \n"
1398 " being a suitably large number. \n"
1399 " For details, search for 'AFNI_MAX_OPTMENU' in AFNI's README.environment.\n"
1400 "You can still use the 'Index' widget in the main AFNI controller\n"
1401 " to access all sub-bricks in such large datasets.\n"
1402 "\n"
1403 "This message is shown intermittently. This message is only\n"
1404 "a WARNING and does not mean that anything is seriously wrong!\n"
1405 "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"
1406 , maxbut, maxbut);
1407 }
1408 ++iwarn;
1409 maxval = minval+maxbut ; /* 23 Mar 2003 */
1410 }
1411 /** reset some internal parameters **/
1412
1413 av->text_CB = (text_proc != NULL ) ? (text_proc)
1414 : (AV_default_text_CB) ;
1415 av->text_data = text_data ;
1416 av->decimals = decim ;
1417 av->fmin = av->imin = minval ; AV_SHIFT_VAL(decim,av->fmin) ;
1418 av->fmax = av->imax = maxval ; AV_SHIFT_VAL(decim,av->fmax) ;
1419
1420 myXtFree(av->sval) ; myXtFree(av->old_sval) ; /* 09 Mar 1999 */
1421
1422 av->block_assign_actions = 1 ; /* temporarily block these actions */
1423
1424 /** create buttons anew **/
1425
1426 STATUS("create buttons anew") ;
1427 for( ival=minval ; ival <= maxval ; ival++ ){
1428
1429 ic = ival - minval ; /* index into widget list */
1430
1431 AV_assign_ival( av , ival ) ; /* just to create label */
1432
1433 blab = butlabel = XtNewString( av->sval ) ;
1434 if( av->text_CB==AV_default_text_CB && butlabel[0]==' ' && minval >= 0 ){
1435 blab += 1 ; /* deal with leading blanks in default routine */
1436 }
1437
1438 xstr = XmStringCreateLtoR( blab , XmFONTLIST_DEFAULT_TAG ) ;
1439
1440 /** re-use old button if possible, otherwise add a new one **/
1441
1442 if( ic < num_children ){
1443 XtPointer user_old=NULL ;
1444 int ival_old ;
1445 XmString xstr_old=NULL ;
1446
1447 wbut = children[ic] ;
1448 XtVaGetValues( wbut ,
1449 XmNlabelString , &xstr_old ,
1450 XmNuserData , &user_old ,
1451 NULL ) ;
1452 ival_old = PTOI(user_old) ;
1453
1454 if( ival_old != ival || XmStringCompare(xstr_old,xstr) != True ){
1455 STATUS("setting label in recycled button") ;
1456 XtVaSetValues( wbut ,
1457 XmNlabelString, xstr, /* change label */
1458 XmNuserData , (XtPointer)ITOP(ival), /* Who am I? */
1459 NULL ) ;
1460 }
1461 #if 1
1462 STATUS("freeing xstr_old") ;
1463 XmStringFree( xstr_old ) ;
1464 #endif
1465 STATUS("managing child") ;
1466 XtManageChild( wbut ) ; /* if not now managed */
1467 } else {
1468 STATUS("setting up new button") ;
1469 wbut = XtVaCreateManagedWidget(
1470 DIALOG , xmPushButtonWidgetClass , wmenu ,
1471 XmNlabelString , xstr ,
1472 XmNmarginWidth , 0 ,
1473 XmNmarginHeight , 0 ,
1474 XmNmarginBottom , 0 ,
1475 XmNmarginTop , 0 ,
1476 XmNmarginRight , 0 ,
1477 XmNmarginLeft , 0 ,
1478 XmNuserData , (XtPointer)ITOP(ival) , /* Who am I? */
1479 XmNtraversalOn , True ,
1480 XmNinitialResourcesPersistent , False ,
1481 NULL ) ;
1482 XtAddCallback( wbut , XmNactivateCallback , AVOPT_press_CB , av ) ;
1483 }
1484
1485 STATUS("freeing xstr") ;
1486 XmStringFree(xstr) ; myXtFree(butlabel) ;
1487
1488 if( ival == inival ){
1489 STATUS("setting menu history") ;
1490 XtVaSetValues( av->wrowcol , XmNmenuHistory , wbut , NULL ) ;
1491 }
1492 }
1493
1494 /** Unmanage extra children from an old incarnation **/
1495
1496 ic = maxval-minval+1 ; /* first child after those used above */
1497
1498 if( ic < num_children ){
1499 STATUS("unmanaging unused children") ;
1500 XtUnmanageChildren( children + ic , num_children - ic ) ;
1501 }
1502
1503 /** set number of columns to see **/
1504
1505 STATUS("set number of columns") ;
1506 AVOPT_columnize( av , 1+(maxval-minval)/COLSIZE ) ;
1507
1508 #if 0
1509 XtManageChild( wmenu ) ;
1510 XtManageChild( av->wrowcol ) ;
1511 #endif
1512
1513 #if 0
1514 RWC_XtPopdown( XtParent(wmenu) ) ; /* 28 Apr 1997 */
1515 #endif
1516
1517 av->block_assign_actions = 0 ; /* unblock these actions */
1518 AV_assign_ival( av , inival ) ; /* actual initial assignment */
1519
1520 EXRETURN ;
1521 }
1522
1523 /*--------------------------------------------------------------------------
1524 11 Dec 2001: Provide a Button 3 list to choose from for an optmenu
1525 ----------------------------------------------------------------------------*/
1526
optmenu_finalize(Widget w,XtPointer cd,MCW_choose_cbs * cbs)1527 static void optmenu_finalize( Widget w, XtPointer cd, MCW_choose_cbs *cbs )
1528 {
1529 MCW_arrowval *av = (MCW_arrowval *) cd ;
1530 int ival ;
1531
1532 ENTRY("optmenu_finalize") ;
1533
1534 if( av == NULL || av->wmenu == NULL ) EXRETURN ;
1535
1536 ival = cbs->ival + av->imin ;
1537 AV_assign_ival( av , ival ) ;
1538
1539 /* call user callback, if present */
1540
1541 if( av->dval_CB != NULL &&
1542 (av->optmenu_call_if_unchanged || av->fval != av->old_fval) )
1543 #if 0
1544 av->dval_CB( av , av->dval_data ) ;
1545 #else
1546 AFNI_CALL_VOID_2ARG( av->dval_CB ,
1547 MCW_arrowval * , av ,
1548 XtPointer , av->dval_data ) ;
1549 #endif
1550
1551 EXRETURN ;
1552 }
1553
1554 /*--------------------------------------------------------------------------*/
1555 /* 15 Mar 2004: fix the cursors on the optmenus with popups */
1556
1557 #ifdef USE_FIXUP
1558 static volatile int nwid = 0 ;
1559 static volatile Widget *wid = NULL ;
1560
1561 /*- called if an optmenu is destroyed, to remove it from the fixup list -*/
1562
optmenu_EV_fixup_CB(Widget ww,XtPointer xp,XtPointer cd)1563 static void optmenu_EV_fixup_CB( Widget ww , XtPointer xp, XtPointer cd )
1564 {
1565 int ii ;
1566 ENTRY("optmenu_EV_fixup_CB") ;
1567 for( ii=0 ; ii < nwid ; ii++ )
1568 if( wid[ii] == ww ) wid[ii] = (Widget)NULL ;
1569 EXRETURN ; ;
1570 }
1571
1572 /*- called occasionally to see if anyone can be fixed yet -*/
1573
1574 static volatile XtIntervalId timer_id = (XtIntervalId)0 ;
1575 static volatile XtAppContext timer_cx = (XtAppContext)NULL ;
1576
optmenu_EV_fixup_timer_CB(XtPointer cd,XtIntervalId * id)1577 static void optmenu_EV_fixup_timer_CB( XtPointer cd , XtIntervalId *id )
1578 {
1579 ENTRY("optmenu_EV_fixup_timer_CB") ;
1580 optmenu_EV_fixup((Widget)NULL) ;
1581 timer_id = XtAppAddTimeOut( timer_cx, 3033, optmenu_EV_fixup_timer_CB, NULL ) ;
1582 EXRETURN ;
1583 }
1584
1585 /*- called with NULL to fix anything on the current list;
1586 called with a Widget to put it on the to-be-fixed-up list -*/
1587
optmenu_EV_fixup(Widget ww)1588 static void optmenu_EV_fixup( Widget ww ) /* 15 Mar 2004 - RWCox */
1589 {
1590 int ii , jj ;
1591 Widget *qwid ;
1592
1593 ENTRY("optmenu_EV_fixup") ;
1594
1595 if( ww == (Widget)NULL ){ /* try to fix what's on the list */
1596 if( nwid == 0 ) EXRETURN ; /* that was easy */
1597 if(PRINT_TRACING){ char str[256]; sprintf(str,"scanning %d widgets for fixing",nwid); STATUS(str); }
1598 for( ii=jj=0 ; ii < nwid ; ii++ ){
1599 if( wid[ii] != (Widget)NULL && XtIsRealized(wid[ii]) &&
1600 XtIsManaged(wid[ii]) && MCW_widget_visible(wid[ii]) ){
1601 if(PRINT_TRACING){ char str[256]; sprintf(str," about to fix ii=%d",ii); STATUS(str); }
1602 POPUP_cursorize(wid[ii]) ;
1603 XtRemoveCallback( wid[ii], XmNdestroyCallback, optmenu_EV_fixup_CB, NULL ) ;
1604 wid[ii] = NULL ; jj++ ;
1605 if(PRINT_TRACING){ char str[256]; sprintf(str," #%d cursor fixed",ii); STATUS(str); }
1606 }
1607 else if(PRINT_TRACING){ char str[256]; sprintf(str," #%d not fixable",ii); STATUS(str); }
1608 }
1609 if( jj == 0 ){ STATUS("nothing to fix"); EXRETURN; }
1610 if( jj >= nwid ){ STATUS("fixed them all"); free(wid); wid = NULL; nwid = 0; EXRETURN; }
1611 qwid = (Widget *) calloc( nwid , sizeof(Widget) ) ;
1612 for( ii=jj=0 ; ii < nwid ; ii++ )
1613 if( wid[ii] != (Widget)NULL ) qwid[jj++] = wid[ii] ;
1614 nwid = jj ;
1615 for( ii=0 ; ii < nwid ; ii++ ) wid[ii] = qwid[ii] ;
1616 free(qwid) ;
1617 if(PRINT_TRACING){ char str[256]; sprintf(str," %d left to fix later",nwid); STATUS(str); }
1618
1619 } else { /* add to the list */
1620 wid = (Widget *)realloc( (void *)wid , sizeof(Widget)*(nwid+1) ) ;
1621 wid[nwid++] = ww ;
1622 XtAddCallback( ww, XmNdestroyCallback, optmenu_EV_fixup_CB, NULL ) ;
1623 if( timer_cx == (XtAppContext)NULL ){
1624 STATUS(" starting first timer callback") ;
1625 timer_cx = XtWidgetToApplicationContext(ww) ;
1626 timer_id = XtAppAddTimeOut( timer_cx, 5055, optmenu_EV_fixup_timer_CB, NULL ) ;
1627 }
1628 if(PRINT_TRACING){ char str[256]; sprintf(str," now have %d to fix",nwid); STATUS(str); }
1629 }
1630 EXRETURN ;
1631 }
1632 #endif /* USE_FIXUP */
1633
1634 /*--------------------------------------------------------------------------*/
1635
optmenu_EV(Widget w,XtPointer cd,XEvent * ev,RwcBoolean * continue_to_dispatch)1636 static void optmenu_EV( Widget w , XtPointer cd ,
1637 XEvent *ev , RwcBoolean *continue_to_dispatch )
1638 {
1639 MCW_arrowval *av = (MCW_arrowval *) cd ;
1640 int ic , ival , sval , nstr ;
1641 XButtonEvent *bev = (XButtonEvent *) ev ;
1642 Dimension lw=0 ;
1643 static char **strlist=NULL ;
1644 static int nstrlist=0 ; /* 06 Aug 2002 */
1645 char *slab=NULL ;
1646 XmString xstr=NULL ;
1647
1648 /*-- Attempt to fix a Motif problem with Button 2
1649 when the optmenu is itself in a popup menu.
1650 The pointer grab is never released, so the
1651 X server is effectively frozen forever (or
1652 until the afni process is SIGTERM-ed). Here,
1653 if we see Button 2, then we manually ungrab
1654 the pointer. This has the side-effect of
1655 popping down the popup menu. If the optmenu
1656 is NOT in a popup menu, it has no side effect. --*/
1657
1658 #ifdef USE_FIXUP
1659 optmenu_EV_fixup(NULL) ;
1660 #endif
1661
1662 if( bev->button == Button2 ){
1663 XUngrabPointer( bev->display , CurrentTime ) ; return ;
1664 }
1665
1666 /*-- start of actual work --*/
1667
1668 ENTRY("optmenu_EV") ;
1669
1670 /** sanity checks **/
1671
1672 if( w == NULL || av == NULL || av->wmenu == NULL ) EXRETURN ;
1673
1674 if( bev->button != Button3 ) EXRETURN ;
1675 if( av->imin >= av->imax ) EXRETURN ; /* 15 Oct 2007: nugation */
1676
1677 XtVaGetValues( av->wlabel , XmNwidth,&lw , NULL ) ;
1678 if( bev->x > lw ) EXRETURN ;
1679
1680 /** get ready to popup a new list chooser **/
1681
1682 POPDOWN_strlist_chooser ;
1683
1684 av->block_assign_actions = 1 ; /* temporarily block actions */
1685 sval = av->ival ;
1686
1687 /* 06 Aug 2002: free list of old strings, if any */
1688
1689 for( ic=0 ; ic < nstrlist ; ic++ ) free(strlist[ic]) ;
1690
1691 /** make a list of strings **/
1692
1693 nstrlist = nstr = av->imax - av->imin + 1 ;
1694 strlist = (char **) realloc( strlist , sizeof(char *)*nstr ) ;
1695
1696 for( ival=av->imin ; ival <= av->imax ; ival++ ){
1697 AV_assign_ival( av , ival ) ; /* just to create label */
1698 ic = ival - av->imin ; /* index into widget list */
1699 strlist[ic] = strdup( av->sval ) ; /* copy label */
1700 }
1701
1702 AV_assign_ival( av , sval ) ;
1703 av->block_assign_actions = 0 ; /* back to normal */
1704
1705 /** actually choose something **/
1706
1707 XtVaGetValues( av->wlabel , XmNlabelString , &xstr , NULL ) ;
1708 XmStringGetLtoR( xstr , XmFONTLIST_DEFAULT_TAG , &slab ) ;
1709 XmStringFree(xstr) ;
1710
1711 MCW_choose_strlist( w , slab , nstr ,
1712 sval - av->imin , strlist ,
1713 optmenu_finalize , cd ) ;
1714 EXRETURN ;
1715 }
1716
1717 /*--------------------------------------------------------------------------
1718 Create a colormenu -- an optmenu with buttons colorized
1719 ----------------------------------------------------------------------------*/
1720
new_MCW_colormenu(Widget parent,char * label,MCW_DC * dc,int min_col,int max_col,int ini_col,gen_func * delta_value,XtPointer delta_data)1721 MCW_arrowval * new_MCW_colormenu( Widget parent , char *label , MCW_DC *dc ,
1722 int min_col , int max_col , int ini_col ,
1723 gen_func *delta_value, XtPointer delta_data
1724 )
1725 {
1726 MCW_arrowval *av ;
1727 Widget *children=NULL ;
1728 int num_children=0 , ic , icol ;
1729
1730 ENTRY("new_MCW_colormenu") ;
1731
1732 av = new_MCW_optmenu( parent , label ,
1733 min_col , max_col , ini_col , 0 ,
1734 delta_value , delta_data ,
1735 MCW_DC_ovcolor_text , (XtPointer)dc ) ;
1736
1737 XtVaGetValues( av->wmenu , XmNchildren , &children ,
1738 XmNnumChildren , &num_children , NULL ) ;
1739 for( ic=0 ; ic < num_children ; ic++ ){
1740 icol = min_col + ic ;
1741 if( icol > 0 ) MCW_set_widget_bg( children[ic] , 0 , dc->ovc->pix_ov[icol] ) ;
1742 else MCW_set_widget_bg( children[ic] , "gray40" , 0 ) ;
1743 }
1744
1745 if( max_col > COLSIZE ) AVOPT_columnize( av , 1+(max_col-1)/COLSIZE ) ;
1746
1747 RETURN(av) ;
1748 }
1749
1750 /*-----------------------------------------------------------------------*/
1751
colorize_MCW_optmenu(MCW_arrowval * av,char * cname,int ibut)1752 void colorize_MCW_optmenu( MCW_arrowval *av , char *cname , int ibut )
1753 {
1754 Widget *children=NULL ;
1755 int num_children=0 , ic,ibot,itop ;
1756
1757 ENTRY("colorize_MCW_optmenu") ;
1758
1759 if( av == NULL || av->wmenu == NULL ) EXRETURN ;
1760 if( cname == NULL || *cname == '\0' ) cname = "gray40" ;
1761
1762 XtVaGetValues( av->wmenu , XmNchildren , &children ,
1763 XmNnumChildren , &num_children , NULL ) ;
1764 if( children == NULL || num_children <= 0 || ibut >= num_children ) EXRETURN ;
1765
1766 if( ibut < 0 ){ ibot = 0 ; itop = num_children-1 ; }
1767 else { ibot = itop = ibut ; }
1768
1769 for( ic=ibot ; ic <= itop ; ic++ )
1770 MCW_set_widget_bg( children[ic] , cname , 0 ) ;
1771
1772 EXRETURN ;
1773 }
1774
1775 /*-----------------------------------------------------------------------*/
1776
MCW_av_substring_CB(MCW_arrowval * av,XtPointer cd)1777 char * MCW_av_substring_CB( MCW_arrowval *av , XtPointer cd )
1778 {
1779 char **str = (char **) cd ;
1780 return str[av->ival] ;
1781 }
1782
1783 /*-----------------------------------------------------------------------*/
1784
AVOPT_press_CB(Widget wbut,XtPointer client_data,XtPointer call_data)1785 void AVOPT_press_CB( Widget wbut, XtPointer client_data, XtPointer call_data )
1786 {
1787 MCW_arrowval *av = (MCW_arrowval *) client_data ;
1788 int newval ;
1789 XtPointer xval=NULL ;
1790
1791 ENTRY("AVOPT_press_CB");
1792
1793 XtVaGetValues( wbut , XmNuserData , &xval , NULL ) ;
1794 newval = PTOI(xval) ;
1795
1796 AV_assign_ival( av , newval ) ; /* assign */
1797
1798 /* call user callback, if present */
1799
1800 if( av->dval_CB != NULL &&
1801 (av->optmenu_call_if_unchanged || av->fval != av->old_fval) )
1802 #if 0
1803 av->dval_CB( av , av->dval_data ) ;
1804 #else
1805 AFNI_CALL_VOID_2ARG( av->dval_CB ,
1806 MCW_arrowval * , av ,
1807 XtPointer , av->dval_data ) ;
1808 #endif
1809
1810 EXRETURN ;
1811 }
1812
1813 /*-----------------------------------------------------------------------*/
1814
AV_press_CB(Widget warrow,XtPointer client_data,XtPointer call_data)1815 void AV_press_CB( Widget warrow, XtPointer client_data, XtPointer call_data )
1816 {
1817 MCW_arrowval *av = (MCW_arrowval *) client_data ;
1818 XmArrowButtonCallbackStruct *cbs =
1819 (XmArrowButtonCallbackStruct *) call_data ;
1820
1821 XtIntervalId fake_id = 0 ;
1822
1823 /* release of button */
1824
1825 switch( cbs->reason ){
1826
1827 default:
1828 case XmCR_DISARM:
1829 if( av->timer_id != 0 ) XtRemoveTimeOut( av->timer_id ) ; /* stop */
1830 av->timer_id = 0 ;
1831 break ;
1832
1833 case XmCR_ARM:
1834 if( warrow == av->wup ) av->incr = 1 ; /* go up */
1835 else if( warrow == av->wdown ) av->incr = -1 ; /* down */
1836 else return ;
1837
1838 if( cbs->event->type == ButtonPress ) av->delay = MCW_AV_longdelay ;
1839 else av->delay = 0 ;
1840
1841 av->xev = *(cbs->event) ; /* copy event for user's info */
1842
1843 AV_timer_CB( av , &fake_id ) ; /* do the work */
1844 }
1845 return;
1846 }
1847
1848 /*------------------------------------------------------------------------*/
1849
AV_timer_CB(XtPointer client_data,XtIntervalId * id)1850 void AV_timer_CB( XtPointer client_data , XtIntervalId *id )
1851 {
1852 MCW_arrowval *av = (MCW_arrowval *) client_data ;
1853 int newval ;
1854 double sval ;
1855
1856 if( av->fstep == 0.0 ){ /* 16 Feb 1999: this is the old way */
1857
1858 sval = av->fval ; AV_SHIFT_VAL( -av->decimals , sval ) ;
1859
1860 if( av->incr < 0 ){
1861 newval = (int) floor( 0.99 + sval + av->incr ) ;
1862 } else {
1863 newval = (int) ceil(-0.99 + sval + av->incr ) ;
1864 }
1865
1866 if( newval > av->imax && av->allow_wrap ){ /* out of range? wrap. */
1867 newval = av->imin ;
1868 } else if( newval < av->imin && av->allow_wrap ){
1869 newval = av->imax ;
1870
1871 } else if( newval > av->imax || newval < av->imin ){ /* out of range? stop. */
1872 av->timer_id = 0 ;
1873 return ;
1874 }
1875
1876 AV_assign_ival( av , newval ) ; /* assign */
1877
1878 } else { /* 16 Feb 1999: this is the new way, if user sets fstep */
1879
1880 if( av->incr > 0 )
1881 sval = av->fval + av->fstep ;
1882 else
1883 sval = av->fval - av->fstep ;
1884
1885 if( sval > av->fmax || sval < av->fmin ){ /* out of range? stop. */
1886 av->timer_id = 0 ;
1887 return ;
1888 }
1889
1890 AV_assign_fval( av , sval ) ;
1891 }
1892
1893 /* call user callback, if present */
1894
1895 if( av->dval_CB != NULL && av->fval != av->old_fval )
1896 #if 0
1897 av->dval_CB( av , av->dval_data ) ;
1898 #else
1899 AFNI_CALL_VOID_2ARG( av->dval_CB ,
1900 MCW_arrowval * , av ,
1901 XtPointer , av->dval_data ) ;
1902 #endif
1903
1904 /* delay and then call again, if desired */
1905
1906 if( av->delay <= 0 ) return ;
1907
1908 av->timer_id = XtAppAddTimeOut(
1909 XtWidgetToApplicationContext( av->wrowcol ) ,
1910 av->delay , AV_timer_CB , av ) ;
1911
1912 if( av->delay == MCW_AV_longdelay ){
1913 if( av->fastdelay > 0 ) av->delay = av->fastdelay ;
1914 else av->delay = MCW_AV_shortdelay ;
1915 }
1916
1917 return ;
1918 }
1919
1920 /*------------------------------------------------------------------------*/
1921 /* Assign the integer value, but do not call the callback */
1922
AV_assign_ival(MCW_arrowval * av,int nval)1923 void AV_assign_ival( MCW_arrowval *av , int nval )
1924 {
1925 int newival = nval ;
1926 char *cval = NULL ;
1927
1928 ENTRY("AV_assign_ival") ;
1929
1930 if( av == NULL ) EXRETURN ; /* 01 Feb 2000 */
1931
1932 if( newival > av->imax ) newival = av->imax ;
1933 if( newival < av->imin ) newival = av->imin ;
1934
1935 /* assign */
1936
1937 av->old_ival = av->ival ;
1938 av->old_fval = av->fval ;
1939
1940 av->fval = av->ival = newival ;
1941
1942 /* adjust decimal point */
1943
1944 AV_SHIFT_VAL( av->decimals , av->fval ) ;
1945
1946 /* change text display, if present */
1947
1948 if( av->text_CB != NULL ){
1949 STATUS("adjust text") ;
1950 #if 0
1951 cval = av->text_CB( av , av->text_data ) ; /* save */
1952 #else
1953 AFNI_CALL_VALU_2ARG( av->text_CB , char * , cval ,
1954 MCW_arrowval * , av ,
1955 XtPointer , av->text_data ) ;
1956 #endif
1957 myXtFree( av->old_sval ) ; av->old_sval = av->sval ; /* string */
1958 av->sval = XtNewString( cval ) ; /* values */
1959
1960 if( av->wtext != NULL && ! av->block_assign_actions )
1961 TEXT_SET( av->wtext , cval ) ;
1962 }
1963
1964 /* if an option menu, change display */
1965
1966 if( av->wmenu != NULL && ! av->block_assign_actions ){
1967
1968 Widget *children=NULL , wbut=NULL ;
1969 int num_children=0 , ic ;
1970 STATUS("adjust optmenu history") ;
1971 XtVaGetValues( av->wmenu ,
1972 XmNchildren , &children ,
1973 XmNnumChildren , &num_children ,
1974 NULL ) ;
1975
1976 XtVaGetValues( av->wrowcol , XmNmenuHistory , &wbut , NULL ) ;
1977
1978 ic = newival - av->imin ;
1979
1980 if( ic >= 0 && ic < num_children && wbut != children[ic] )
1981 XtVaSetValues( av->wrowcol , XmNmenuHistory , children[ic] , NULL ) ;
1982 }
1983
1984 EXRETURN ;
1985 }
1986
1987 /*-------------------------------------------------------------------------
1988 format a floating value for output
1989 ---------------------------------------------------------------------------*/
1990
AV_default_text_CB(MCW_arrowval * av,XtPointer junk)1991 char * AV_default_text_CB( MCW_arrowval *av , XtPointer junk )
1992 {
1993 static char buf[32] ;
1994
1995 if( av == NULL ) buf[0] = '\0' ;
1996 else AV_fval_to_char( av->fval , buf ) ;
1997 return &(buf[0]) ;
1998 }
1999
2000 /*------------------------------------------------------------------------*/
2001
AV_fval_to_char(float qval,char * buf)2002 void AV_fval_to_char( float qval , char *buf )
2003 {
2004 float aval = fabs(qval) ;
2005 int lv ;
2006 char lbuf[16] ;
2007 int il ;
2008
2009 /* special case if the value is an integer */
2010
2011 lv = (fabs(qval) < 9999999.0) ? (int)qval : 10000001 ;
2012
2013 if( qval == lv && abs(lv) < 10000000 ){
2014 if( lv >= 0 ) sprintf( buf , " %d" , lv ) ;
2015 else sprintf( buf , "%d" , lv ) ;
2016 return ;
2017 }
2018
2019 /* macro to strip trailing zeros from output */
2020
2021 #define BSTRIP \
2022 for( il=AV_NCOL-1 ; il>1 && lbuf[il]=='0' ; il-- ) lbuf[il] = '\0'
2023
2024 /* noninteger: choose floating format based on magnitude */
2025
2026 lv = (int) (10.0001 + log10(aval)) ;
2027
2028 switch( lv ){
2029
2030 default:
2031 if( qval > 0.0 ) sprintf( lbuf , "%9.3e" , qval ) ;
2032 else sprintf( lbuf , "%9.2e" , qval ) ;
2033 break ;
2034
2035 case 6: /* 0.0001-0.001 */
2036 case 7: /* 0.001 -0.01 */
2037 case 8: /* 0.01 -0.1 */
2038 case 9: /* 0.1 -1 */
2039 case 10: /* 1 -9.99 */
2040 sprintf( lbuf , "%9.6f" , qval ) ; BSTRIP ; break ;
2041
2042 case 11: /* 10-99.9 */
2043 sprintf( lbuf , "%9.5f" , qval ) ; BSTRIP ; break ;
2044
2045 case 12: /* 100-999.9 */
2046 sprintf( lbuf , "%9.4f" , qval ) ; BSTRIP ; break ;
2047
2048 case 13: /* 1000-9999.9 */
2049 sprintf( lbuf , "%9.3f" , qval ) ; BSTRIP ; break ;
2050
2051 case 14: /* 10000-99999.9 */
2052 sprintf( lbuf , "%9.2f" , qval ) ; BSTRIP ; break ;
2053
2054 case 15: /* 100000-999999.9 */
2055 sprintf( lbuf , "%9.1f" , qval ) ; BSTRIP ; break ;
2056
2057 case 16: /* 1000000-9999999.9 */
2058 sprintf( lbuf , "%9.0f" , qval ) ; break ;
2059 }
2060
2061 lv = strlen(lbuf) ; /* length of result at this stage */
2062
2063 if( lv <= AV_NCOL ){ /* length OK */
2064 strcpy(buf,lbuf) ;
2065 } else { /* too long (should not occur!) */
2066 sprintf( lbuf , "%%%d.%dg" , AV_NCOL , AV_NCOL-7 ) ;
2067 sprintf( buf , lbuf , qval ) ;
2068 }
2069 return ;
2070 }
2071
2072 /*------------------------------------------------------------------------*/
2073
AV_format_fval(float fval)2074 char * AV_format_fval( float fval )
2075 {
2076 static char buf[32] ;
2077 AV_fval_to_char( fval , buf ) ;
2078 return buf ;
2079 }
2080
2081 /*------------------------------------------------------------------------*/
2082
AV_uformat_fval(float fval)2083 char * AV_uformat_fval( float fval )
2084 {
2085 static char buf[32] ;
2086 AV_fval_to_char( fval , buf ) ;
2087 if( buf[0] == ' ' ) return (buf+1) ;
2088 return buf ;
2089 }
2090
2091 /*------------------------------------------------------------------------*/
2092
AV_assign_fval(MCW_arrowval * av,float qval)2093 void AV_assign_fval( MCW_arrowval *av , float qval )
2094 {
2095 double newfval = qval ;
2096 char *cval ;
2097
2098 if( av == NULL ) return ; /* 01 Feb 2000 */
2099
2100 if( newfval > av->fmax ) newfval = av->fmax ;
2101 if( newfval < av->fmin ) newfval = av->fmin ;
2102
2103 /* assign */
2104
2105 av->old_ival = av->ival ;
2106 av->old_fval = av->fval ;
2107
2108 av->fval = newfval ;
2109
2110 /* adjust decimal point */
2111
2112 AV_SHIFT_VAL( -av->decimals , newfval ) ;
2113
2114 av->ival = (int) floor(newfval) ;
2115
2116 /* change text display, if present */
2117
2118 if( av->text_CB != NULL ){
2119 #if 0
2120 cval = av->text_CB( av , av->text_data ) ; /* save */
2121 #else
2122 AFNI_CALL_VALU_2ARG( av->text_CB , char * , cval ,
2123 MCW_arrowval * , av ,
2124 XtPointer , av->text_data ) ;
2125 #endif
2126 myXtFree( av->old_sval ) ; av->old_sval = av->sval ; /* string */
2127 av->sval = XtNewString( cval ) ; /* values */
2128
2129 if( av->wtext != NULL && ! av->block_assign_actions )
2130 TEXT_SET( av->wtext , cval ) ;
2131 }
2132
2133 return ;
2134 }
2135
2136 /*----------------------------------------------------------------------*/
2137
AV_leave_EV(Widget w,XtPointer client_data,XEvent * ev,RwcBoolean * continue_to_dispatch)2138 void AV_leave_EV( Widget w , XtPointer client_data ,
2139 XEvent *ev , RwcBoolean *continue_to_dispatch )
2140 {
2141 MCW_arrowval *av = (MCW_arrowval *) client_data ;
2142 XLeaveWindowEvent *lev = (XLeaveWindowEvent *) ev ;
2143 XmAnyCallbackStruct cbs ;
2144
2145 if( lev->type != LeaveNotify || av == NULL ) return ;
2146
2147 cbs.reason = XmCR_ACTIVATE ; /* simulate a return press */
2148 AV_textact_CB( av->wtext , (XtPointer) av , &cbs ) ;
2149 }
2150
2151 /*----------------------------------------------------------------------*/
2152
AV_textact_CB(Widget wtex,XtPointer client_data,XtPointer call_data)2153 void AV_textact_CB( Widget wtex, XtPointer client_data, XtPointer call_data )
2154 {
2155 MCW_arrowval *av = (MCW_arrowval *) client_data ;
2156 XmAnyCallbackStruct *cbs = (XmAnyCallbackStruct *) call_data ;
2157
2158 float sval ;
2159 int ii ;
2160 char *str ;
2161
2162 ENTRY("AV_textact_CB") ;
2163
2164 if( (cbs->reason != XmCR_ACTIVATE && cbs->reason != XmCR_LOSING_FOCUS )
2165 || wtex != av->wtext ){
2166 fprintf(stderr,"\n*** Illegal call to AV_textact_CB ***\n") ;
2167 EXRETURN ;
2168 }
2169
2170 str = TEXT_GET( wtex ) ; /* get the new text */
2171
2172 /* check if new text is any different from last value */
2173
2174 if( av->sval != NULL && strcmp( av->sval , str ) == 0 ){
2175 myXtFree(str) ; EXRETURN ;
2176 }
2177
2178 MCW_invert_widget( wtex ) ; /* start flash */
2179
2180 ii = sscanf( str , "%f" , &sval ) ; /* convert to float in sval */
2181
2182 if( ii == 0 ) sval = av->fval ; /* bad float conversion */
2183
2184 AV_assign_fval( av , sval ) ; /* will alter ival,fval,sval in av */
2185
2186 if( av->dval_CB != NULL && av->fval != av->old_fval ) /* value changed */
2187 #if 0
2188 av->dval_CB( av , av->dval_data ) ;
2189 #else
2190 AFNI_CALL_VOID_2ARG( av->dval_CB ,
2191 MCW_arrowval * , av ,
2192 XtPointer , av->dval_data ) ;
2193 #endif
2194
2195 myXtFree(str) ; /* give it back */
2196
2197 MCW_invert_widget( wtex ) ; /* end flash */
2198 EXRETURN ;
2199 }
2200
2201 /*----------------------------------------------------------------------
2202 NULL out the pointer to a popup widget when the widget is destroyed
2203 ------------------------------------------------------------------------*/
2204
MCW_destroy_chooser_CB(Widget wpop,XtPointer client_data,XtPointer call_data)2205 void MCW_destroy_chooser_CB( Widget wpop ,
2206 XtPointer client_data, XtPointer call_data )
2207 {
2208 Widget *wpointer = (Widget *) client_data ;
2209 ENTRY("MCW_destroy_chooser_CB") ;
2210 MCW_widget_geom( wpop , NULL,NULL , &old_xx,&old_yy ) ; /* Apr 2013 */
2211 *wpointer = NULL ;
2212 EXRETURN ;
2213 }
2214
MCW_kill_chooser_CB(Widget w,XtPointer client_data,XtPointer call_data)2215 void MCW_kill_chooser_CB( Widget w ,
2216 XtPointer client_data, XtPointer call_data )
2217 {
2218 Widget wpop = (Widget) client_data ;
2219 ENTRY("MCW_kill_chooser_CB") ;
2220 MCW_widget_geom( wpop , NULL,NULL , &old_xx,&old_yy ) ; /* Apr 2013 */
2221 XtDestroyWidget(wpop) ;
2222 EXRETURN ;
2223 }
2224
2225 /*-----------------------------------------------------------------------*/
2226
2227 #undef RECOLOR_OPTMENU
2228
MCW_DC_ovcolor_text(MCW_arrowval * av,MCW_DC * dc)2229 char * MCW_DC_ovcolor_text( MCW_arrowval *av , MCW_DC *dc )
2230 {
2231 int ii = av->ival ;
2232 Widget wfix ;
2233
2234 if( ii < 0 ) ii = 0 ;
2235 else if( ii > dc->ovc->ncol_ov - 1 ) ii = dc->ovc->ncol_ov - 1 ;
2236
2237 wfix = av->wtext ;
2238
2239 if( wfix != NULL ){
2240 if( ii > 0 ) MCW_set_widget_bg( wfix , 0 , dc->ovc->pix_ov[ii] ) ;
2241 else MCW_set_widget_bg( wfix , "gray40" , 0 ) ;
2242 }
2243
2244 #ifdef RECOLOR_OPTMENU
2245 /** make the option menu cascade button gadget be outlined in color **/
2246
2247 else if( av->wmenu != NULL && XtIsRealized(av->wrowcol) ){
2248 Pixel ptop=0 , pbot=0 ;
2249 wfix = av->wrowcol ;
2250 if( ii > 0 ) pbot = ptop = dc->ovc->pix_ov[ii] ;
2251 else XtVaGetValues( XtParent(wfix) ,
2252 XmNtopShadowColor , &ptop ,
2253 XmNbottomShadowColor , &pbot ,
2254 NULL ) ;
2255 XtVaSetValues( wfix ,
2256 XmNtopShadowColor , ptop ,
2257 XmNbottomShadowColor , pbot ,
2258 NULL ) ;
2259 }
2260 #endif
2261
2262 return dc->ovc->label_ov[ii] ;
2263 }
2264
2265 /*------------------------------------------------------------------------
2266 Get a table index for a DC overlay color:
2267 pops up a shell to let the user make the selection
2268
2269 wpar = parent widget (where to popup)
2270 dc = display context to choose colors from
2271 ovc_init = initial overlay color index
2272
2273 func = routine to call when a selection is made:
2274 void func( Widget wpar,XtPointer func_data,MCW_choose_cbs *cbs )
2275 func_data = data to pass to func
2276
2277 The "ival" stored in the MCW_choose_cbs will be the index into the
2278 DC overlay color table. The pixel value is thus dc->ovc->pix_ov[cbs->ival].
2279 The color name is dc->ovc->name_ov[cbs->ival]. Etc.
2280
2281 Note that cbs->ival = 0 means that the user choose the "None" color.
2282
2283 This routine is coded in such a way that only one color chooser will be
2284 active at a time (per application). This is a deliberate choice.
2285 --------------------------------------------------------------------------*/
2286
2287 #define OVC_quit_label "Quit"
2288 #define OVC_apply_label "Apply"
2289 #define OVC_done_label "Set"
2290 #define OVC_clear_label "Clear"
2291
2292 #define OVC_quit_help "Press to close\nthis `chooser'"
2293 #define OVC_apply_help "Press to apply\nthis choice and\nkeep this `chooser'"
2294 #define OVC_done_help "Press to apply\nthis choice and\nclose this `chooser'"
2295 #define OVC_clear_help "Press to clear\nthe entry"
2296
2297 #define OVC_av_help "Use arrows to\nsee what choices\nare available"
2298 #define OVC_opt_help "Click this button\nto pop up a menu\nof overlay colors"
2299
2300 #define OVC_list_help_1 "Click Button 1 on the\n" \
2301 "item of your choice,\n" \
2302 "then press one of the\n" \
2303 "control buttons below.\n" \
2304 " ** OR **\n" \
2305 "Double-click Button 1\n" \
2306 "on an item to choose it."
2307
2308 #define OVC_list_help_2 "Multiple Mode:\n" \
2309 " Click Button 1 on items to\n" \
2310 " select or de-select them.\n" \
2311 "\n" \
2312 "Extended Mode:\n" \
2313 "+ Click and drag Button 1 to\n" \
2314 " select ranges of items.\n" \
2315 "+ Press Ctrl (on keyboard)\n" \
2316 " at same time to avoid\n" \
2317 " de-selecting items that\n" \
2318 " were selected previously."
2319
2320 #define NUM_OVC_ACT 3
2321 #define NUM_CLR_ACT 4
2322
2323 static MCW_action_item OVC_act[] = {
2324 { OVC_quit_label , MCW_choose_CB, NULL, OVC_quit_help ,"Close window" ,0 },
2325 { OVC_apply_label, MCW_choose_CB, NULL, OVC_apply_help,"Apply choice and keep window" ,0 },
2326 { OVC_done_label , MCW_choose_CB, NULL, OVC_done_help ,"Apply choice and close window",1 },
2327 { OVC_clear_label, MCW_choose_CB, NULL, OVC_clear_help,"Clear entry" ,0 }
2328 } ;
2329
2330 #define NUM_LIST_MODES 2
2331 static char *list_modes[NUM_LIST_MODES] = { "Multiple" , "Extended" } ;
2332
MCW_choose_ovcolor(Widget wpar,MCW_DC * dc,int ovc_init,gen_func * func,XtPointer func_data)2333 void MCW_choose_ovcolor( Widget wpar , MCW_DC *dc , int ovc_init ,
2334 gen_func *func , XtPointer func_data )
2335 {
2336 static Widget wpop = NULL , wrc ;
2337 static MCW_arrowval * av = NULL ;
2338 static MCW_choose_data cd ;
2339 Position xx,yy ;
2340 int ib ;
2341
2342 ENTRY("MCW_choose_ovcolor") ;
2343
2344 /** destructor callback **/
2345
2346 if( wpar == NULL ){
2347 if( wpop != NULL ){
2348 XtUnmapWidget( wpop ) ;
2349 XtRemoveCallback( wpop, XmNdestroyCallback, MCW_destroy_chooser_CB, &wpop ) ;
2350 XtDestroyWidget( wpop ) ;
2351 }
2352 wpop = NULL ; EXRETURN ;
2353 }
2354
2355 if( ! XtIsRealized(wpar) || dc->ovc->ncol_ov < 2 ){ /* illegal call */
2356 fprintf(stderr,"\n*** illegal call to MCW_choose_ovcolor: %s %d\n",
2357 XtName(wpar) , dc->ovc->ncol_ov ) ;
2358 EXRETURN ;
2359 }
2360
2361 if( ovc_init < 0 || ovc_init >= dc->ovc->ncol_ov ) ovc_init = 1 ;
2362
2363 /*--- if popup widget already exists, destroy it ---*/
2364
2365 if( wpop != NULL ){
2366 XtRemoveCallback( wpop, XmNdestroyCallback, MCW_destroy_chooser_CB, &wpop ) ;
2367 XtDestroyWidget( wpop ) ;
2368 }
2369
2370 if( av != NULL ){
2371 myXtFree( av ) ; av = NULL ;
2372 }
2373
2374 /*--- create popup widget ---*/
2375
2376 wpop = XtVaCreatePopupShell( /* Popup Shell */
2377 MENU , xmDialogShellWidgetClass , wpar ,
2378 XmNtraversalOn , True ,
2379 XmNinitialResourcesPersistent , False ,
2380 XmNkeyboardFocusPolicy , XmEXPLICIT ,
2381 NULL ) ;
2382
2383 if( MCW_isitmwm(wpar) ){
2384 XtVaSetValues( wpop ,
2385 XmNmwmDecorations , MWM_DECOR_BORDER ,
2386 XmNmwmFunctions , MWM_FUNC_MOVE ,
2387 NULL ) ;
2388 }
2389
2390 XtAddCallback( wpop , XmNdestroyCallback , MCW_destroy_chooser_CB , &wpop ) ;
2391
2392 XmAddWMProtocolCallback(
2393 wpop ,
2394 XmInternAtom( XtDisplay(wpop) , "WM_DELETE_WINDOW" , False ) ,
2395 MCW_kill_chooser_CB , wpop ) ;
2396
2397 wrc = XtVaCreateWidget( /* RowColumn to hold all */
2398 MENU , xmRowColumnWidgetClass , wpop ,
2399 XmNpacking , XmPACK_TIGHT ,
2400 XmNorientation , XmVERTICAL ,
2401 XmNtraversalOn , True ,
2402 XmNinitialResourcesPersistent , False ,
2403 NULL ) ;
2404
2405 av = new_MCW_colormenu( wrc , "Color " , dc ,
2406 0 , dc->ovc->ncol_ov - 1 , ovc_init , NULL,NULL ) ;
2407 MCW_reghelp_children( av->wrowcol , OVC_opt_help ) ;
2408 MCW_reghint_children( av->wrowcol , "Overlay colors" ) ;
2409
2410 cd.dc = dc ; /* data to be passed to pushbutton callback */
2411 cd.wpop = wpop ;
2412 cd.wcaller = wpar ;
2413 cd.av = av ;
2414 cd.sel_CB = func ;
2415 cd.sel_cd = func_data ;
2416 cd.ctype = mcwCT_ovcolor ;
2417
2418 for( ib=0 ; ib < NUM_OVC_ACT ; ib++ ) OVC_act[ib].data = &cd ;
2419
2420 (void) MCW_action_area( wrc , OVC_act , NUM_OVC_ACT ) ;
2421
2422 RELOCATE(wpar,wpop,5) ; /* 12 Oct 2017 */
2423
2424 XtManageChild( wrc ) ;
2425 XtPopup( wpop , XtGrabNone ) ; RWC_sleep(1);
2426
2427 if( av->wtext != NULL )
2428 MCW_set_widget_bg( av->wtext , NULL , dc->ovc->pix_ov[ovc_init] ) ; /* after popup */
2429
2430 RWC_visibilize_widget( wpop ) ; /* 09 Nov 1999 */
2431 NORMAL_cursorize( wpop ) ;
2432
2433 EXRETURN ;
2434 }
2435
2436 /*-------------------------------------------------------------------------*/
2437 /* Get a bunch of values [19 Mar 2004].
2438 Change initvec from int to float. [21 Sep 2007].
2439 ---------------------------------------------------------------------------*/
2440
2441 static int vec_nav = 0 ;
2442 static MCW_arrowval **vec_av = NULL ;
2443
2444 /** this function gives access to the array of arrowvals used
2445 in MCW_choose_vector(), in order to let the caller change
2446 the ranges of values allowed from the stupid defaults. **/
2447
MCW_choose_vector_avarray(int * nav)2448 MCW_arrowval ** MCW_choose_vector_avarray( int *nav ) /* 03 Aug 2010 */
2449 {
2450 if( nav != NULL ) *nav = vec_nav ;
2451 return vec_av ;
2452 }
2453
MCW_choose_vector(Widget wpar,char * label,int nvec,char ** labvec,float * initvec,gen_func * func,XtPointer func_data)2454 void MCW_choose_vector( Widget wpar , char *label ,
2455 int nvec , char **labvec , float *initvec ,
2456 gen_func *func , XtPointer func_data )
2457 {
2458 static Widget wpop = NULL , wrc ;
2459 static MCW_choose_data cd ;
2460 Position xx,yy ;
2461 int ib , iv ;
2462
2463 ENTRY("MCW_choose_vector") ;
2464
2465 /** destructor callback **/
2466
2467 if( wpar == NULL || nvec <= 0 ){
2468 if( wpop != NULL ){
2469 XtUnmapWidget( wpop ) ;
2470 XtRemoveCallback( wpop, XmNdestroyCallback, MCW_destroy_chooser_CB, &wpop ) ;
2471 XtDestroyWidget( wpop ) ;
2472 }
2473 wpop = NULL ; EXRETURN ;
2474 }
2475
2476 if( ! XtIsRealized(wpar) ){ /* illegal call */
2477 fprintf(stderr,"\n*** illegal call to MCW_choose_vector: %s\n",
2478 XtName(wpar) ) ;
2479 EXRETURN ;
2480 }
2481
2482 /*--- if popup widget already exists, destroy it ---*/
2483
2484 if( wpop != NULL ){
2485 XtRemoveCallback( wpop, XmNdestroyCallback, MCW_destroy_chooser_CB, &wpop ) ;
2486 XtDestroyWidget( wpop ) ;
2487 }
2488
2489 if( vec_nav > 0 && vec_av != NULL ){
2490 for( iv=0 ; iv < vec_nav ; iv++ ) myXtFree( vec_av[iv] ) ;
2491 myXtFree(vec_av) ; vec_av = NULL ; vec_nav = 0 ;
2492 }
2493
2494 /*--- create popup widget ---*/
2495
2496 wpop = XtVaCreatePopupShell( /* Popup Shell */
2497 MENU , xmDialogShellWidgetClass , wpar ,
2498 XmNtraversalOn , True ,
2499 XmNinitialResourcesPersistent , False ,
2500 XmNkeyboardFocusPolicy , XmEXPLICIT ,
2501 NULL ) ;
2502
2503 if( MCW_isitmwm(wpar) ){
2504 XtVaSetValues( wpop ,
2505 XmNmwmDecorations , MWM_DECOR_BORDER ,
2506 XmNmwmFunctions , MWM_FUNC_MOVE ,
2507 NULL ) ;
2508 }
2509
2510 XtAddCallback( wpop , XmNdestroyCallback , MCW_destroy_chooser_CB , &wpop ) ;
2511
2512 XmAddWMProtocolCallback(
2513 wpop ,
2514 XmInternAtom( XtDisplay(wpop) , "WM_DELETE_WINDOW" , False ) ,
2515 MCW_kill_chooser_CB , wpop ) ;
2516
2517 wrc = XtVaCreateWidget( /* RowColumn to hold all */
2518 MENU , xmRowColumnWidgetClass , wpop ,
2519 XmNpacking , XmPACK_TIGHT ,
2520 XmNorientation , XmVERTICAL ,
2521 XmNtraversalOn , True ,
2522 XmNinitialResourcesPersistent , False ,
2523 NULL ) ;
2524
2525 if( label != NULL ){
2526 wtemp = XtVaCreateManagedWidget(
2527 MENU , xmLabelWidgetClass , wrc ,
2528 LABEL_ARG(label) ,
2529 XmNinitialResourcesPersistent , False ,
2530 NULL ) ; LABELIZE(wtemp) ;
2531 (void) XtVaCreateManagedWidget(
2532 MENU , xmSeparatorWidgetClass , wrc ,
2533 XmNseparatorType , XmSHADOW_ETCHED_IN ,
2534 XmNinitialResourcesPersistent , False ,
2535 NULL ) ;
2536 }
2537
2538 vec_av = (MCW_arrowval **) XtMalloc( sizeof(MCW_arrowval *) * nvec ) ;
2539 vec_nav = nvec ;
2540 for( iv=0 ; iv < nvec ; iv++ ){
2541 vec_av[iv] = new_MCW_arrowval( wrc ,
2542 (labvec!=NULL) ? labvec[iv] : NULL ,
2543 MCW_AV_downup ,
2544 -99999,99999,
2545 0 ,
2546 MCW_AV_edittext , 0 ,
2547 NULL , NULL , NULL , NULL ) ;
2548 }
2549
2550 cd.wpop = wpop ; /* data to be passed to pushbutton callback */
2551 cd.wcaller = wpar ;
2552 cd.av = (MCW_arrowval *)vec_av ; /* hack hack hack */
2553 cd.sel_CB = func ;
2554 cd.sel_cd = func_data ;
2555 cd.ctype = mcwCT_vector ;
2556 cd.nvec = nvec ;
2557
2558 for( ib=0 ; ib < NUM_OVC_ACT ; ib++ ) OVC_act[ib].data = &cd ;
2559
2560 (void) MCW_action_area( wrc , OVC_act , NUM_OVC_ACT ) ;
2561
2562 RELOCATE(wpar,wpop,5) ; /* 12 Oct 2017 */
2563
2564 XtManageChild( wrc ) ;
2565 XtPopup( wpop , XtGrabNone ) ; RWC_sleep(1);
2566
2567 RWC_visibilize_widget( wpop ) ;
2568 NORMAL_cursorize( wpop ) ;
2569
2570 if( initvec != NULL ){
2571 for( iv=0 ; iv < nvec ; iv++ ) AV_assign_fval(vec_av[iv],initvec[iv]) ;
2572 }
2573
2574 EXRETURN ;
2575 }
2576
2577 /*-------------------------------------------------------------------------
2578 Get an integer:
2579 pops up a shell to let the user make the selection
2580
2581 wpar = parent widget (where to popup)
2582 label = label for chooser
2583 bot,top,init = integers defining range and initial value
2584 func = routine to call when a selection is made:
2585 void func( Widget wpar,XtPointer func_data,MCW_choose_cbs *cbs )
2586 func_data = data to pass to func
2587
2588 The "ival" stored in the MCW_choose_cbs will be the desired result.
2589
2590 This routine is coded in such a way that only one chooser will be
2591 active at a time (per application). This is a deliberate choice.
2592 ---------------------------------------------------------------------------*/
2593
MCW_choose_integer(Widget wpar,char * label,int bot,int top,int init,gen_func * func,XtPointer func_data)2594 void MCW_choose_integer( Widget wpar , char *label ,
2595 int bot , int top , int init ,
2596 gen_func *func , XtPointer func_data )
2597 {
2598 static Widget wpop = NULL , wrc ;
2599 static MCW_arrowval * av = NULL ;
2600 static MCW_choose_data cd ;
2601 Position xx,yy ;
2602 int ib ;
2603
2604 ENTRY("MCW_choose_integer") ;
2605
2606 /** destructor callback **/
2607
2608 if( wpar == NULL ){
2609 if( wpop != NULL ){
2610 XtUnmapWidget( wpop ) ;
2611 XtRemoveCallback( wpop, XmNdestroyCallback, MCW_destroy_chooser_CB, &wpop ) ;
2612 XtDestroyWidget( wpop ) ;
2613 }
2614 wpop = NULL ; EXRETURN ;
2615 }
2616
2617 if( ! XtIsRealized(wpar) ){ /* illegal call */
2618 fprintf(stderr,"\n*** illegal call to MCW_choose_integer: %s\n",
2619 XtName(wpar) ) ;
2620 EXRETURN ;
2621 }
2622
2623 /*--- if popup widget already exists, destroy it ---*/
2624
2625 if( wpop != NULL ){
2626 XtRemoveCallback( wpop, XmNdestroyCallback, MCW_destroy_chooser_CB, &wpop ) ;
2627 XtDestroyWidget( wpop ) ;
2628 }
2629
2630 if( av != NULL ){
2631 myXtFree( av ) ; av = NULL ;
2632 }
2633
2634 /*--- create popup widget ---*/
2635
2636 wpop = XtVaCreatePopupShell( /* Popup Shell */
2637 MENU , xmDialogShellWidgetClass , wpar ,
2638 XmNtraversalOn , True ,
2639 XmNinitialResourcesPersistent , False ,
2640 XmNkeyboardFocusPolicy , XmEXPLICIT ,
2641 NULL ) ;
2642
2643 if( MCW_isitmwm(wpar) ){
2644 XtVaSetValues( wpop ,
2645 XmNmwmDecorations , MWM_DECOR_BORDER ,
2646 XmNmwmFunctions , MWM_FUNC_MOVE ,
2647 NULL ) ;
2648 }
2649
2650 XtAddCallback( wpop , XmNdestroyCallback , MCW_destroy_chooser_CB , &wpop ) ;
2651
2652 XmAddWMProtocolCallback(
2653 wpop ,
2654 XmInternAtom( XtDisplay(wpop) , "WM_DELETE_WINDOW" , False ) ,
2655 MCW_kill_chooser_CB , wpop ) ;
2656
2657 wrc = XtVaCreateWidget( /* RowColumn to hold all */
2658 MENU , xmRowColumnWidgetClass , wpop ,
2659 XmNpacking , XmPACK_TIGHT ,
2660 XmNorientation , XmVERTICAL ,
2661 XmNtraversalOn , True ,
2662 XmNinitialResourcesPersistent , False ,
2663 NULL ) ;
2664
2665 av = new_MCW_arrowval( wrc ,
2666 label , MCW_AV_downup , /* selection */
2667 bot,top,init ,
2668 MCW_AV_edittext , 0 ,
2669 NULL , NULL , NULL , NULL ) ;
2670
2671 av->allow_wrap = 1 ;
2672
2673 MCW_reghelp_children( av->wrowcol , OVC_av_help ) ;
2674 MCW_reghint_children( av->wrowcol , "Pick value" ) ;
2675
2676 cd.wpop = wpop ; /* data to be passed to pushbutton callback */
2677 cd.wcaller = wpar ;
2678 cd.av = av ;
2679 cd.sel_CB = func ;
2680 cd.sel_cd = func_data ;
2681 cd.ctype = mcwCT_integer ;
2682
2683 for( ib=0 ; ib < NUM_OVC_ACT ; ib++ ) OVC_act[ib].data = &cd ;
2684
2685 (void) MCW_action_area( wrc , OVC_act , NUM_OVC_ACT ) ;
2686
2687 RELOCATE(wpar,wpop,5) ; /* 12 Oct 2017 */
2688
2689 XtManageChild( wrc ) ;
2690 XtPopup( wpop , XtGrabNone ) ; RWC_sleep(1);
2691
2692 RWC_visibilize_widget( wpop ) ; /* 09 Nov 1999 */
2693 NORMAL_cursorize( wpop ) ;
2694
2695 EXRETURN ;
2696 }
2697
2698 /*-------------------------------------------------------------------------
2699 ^
2700 Create a new MCW_arrowpad: < O >
2701 v
2702 parent = parent Widget
2703
2704 press_func = pointer to a function that will be called when an arrow or
2705 the button at the center is pressed
2706 press_data = pointer to data to be passed to press_func;
2707 press_func( apad , press_data ) ;
2708 where apad is a pointer to the MCW_arrowpad that was hit.
2709
2710 If press_func is NULL, no callback occurs. You may create the arrowpad and
2711 later set the callback by apad->action_CB = press_func.
2712 ---------------------------------------------------------------------------*/
2713
new_MCW_arrowpad(Widget parent,gen_func * press_func,XtPointer press_data)2714 MCW_arrowpad * new_MCW_arrowpad( Widget parent ,
2715 gen_func *press_func, XtPointer press_data
2716 )
2717 {
2718 MCW_arrowpad *apad ;
2719 int asizx = 20 , asizy = 20 ; /* arrow sizes */
2720 int iar ;
2721
2722 ENTRY("new_MCW_arrowpad") ;
2723
2724 apad = myXtNew( MCW_arrowpad ) ;
2725
2726 /*--- form to hold the stuff: everything is tied to rubber positions ---*/
2727
2728 apad->wform = XtVaCreateWidget(
2729 DIALOG , xmFormWidgetClass , parent ,
2730 XmNfractionBase , AP_FBASE ,
2731 XmNinitialResourcesPersistent , False ,
2732 XmNtraversalOn , True ,
2733 NULL ) ;
2734
2735 /*--- create the arrowbuttons ---*/
2736
2737 for( iar = 0 ; iar < 4 ; iar++ ){
2738 apad->wbut[iar] =
2739 XtVaCreateManagedWidget(
2740 "arrow" , xmArrowButtonWidgetClass , apad->wform ,
2741
2742 XmNtopAttachment , XmATTACH_POSITION ,
2743 XmNbottomAttachment , XmATTACH_POSITION ,
2744 XmNleftAttachment , XmATTACH_POSITION ,
2745 XmNrightAttachment , XmATTACH_POSITION ,
2746
2747 XmNarrowDirection , AP_but_def[iar].atype ,
2748 XmNtopPosition , AP_but_def[iar].atop ,
2749 XmNbottomPosition , AP_but_def[iar].abottom ,
2750 XmNleftPosition , AP_but_def[iar].aleft ,
2751 XmNrightPosition , AP_but_def[iar].aright ,
2752
2753 XmNheight , asizy ,
2754 XmNwidth , asizx ,
2755 XmNborderWidth , 0 ,
2756
2757 XmNinitialResourcesPersistent , False ,
2758 XmNtraversalOn , True ,
2759 NULL ) ;
2760
2761
2762 XtAddCallback( apad->wbut[iar], XmNarmCallback , AP_press_CB, apad ) ;
2763 XtAddCallback( apad->wbut[iar], XmNdisarmCallback, AP_press_CB, apad ) ;
2764 }
2765
2766 /*--- create the pushbutton in the middle ---*/
2767
2768 apad->wbut[4] = XtVaCreateManagedWidget(
2769 "arrow" , xmPushButtonWidgetClass , apad->wform ,
2770
2771 XmNtopAttachment , XmATTACH_POSITION ,
2772 XmNbottomAttachment , XmATTACH_POSITION ,
2773 XmNleftAttachment , XmATTACH_POSITION ,
2774 XmNrightAttachment , XmATTACH_POSITION ,
2775
2776 XmNtopPosition , AP_but_def[4].atop ,
2777 XmNbottomPosition , AP_but_def[4].abottom ,
2778 XmNleftPosition , AP_but_def[4].aleft ,
2779 XmNrightPosition , AP_but_def[4].aright ,
2780
2781 XtVaTypedArg , XmNlabelString , XmRString , " " , 2 ,
2782
2783 XmNheight , asizy ,
2784 XmNwidth , asizx ,
2785 XmNborderWidth , 0 ,
2786 XmNrecomputeSize , False ,
2787
2788 XmNinitialResourcesPersistent , False ,
2789 XmNtraversalOn , True ,
2790 NULL ) ;
2791
2792 XtAddCallback( apad->wbut[4] , XmNactivateCallback , AP_press_CB , apad ) ;
2793
2794 XtManageChild( apad->wform ) ;
2795
2796 apad->action_CB = press_func ;
2797 apad->action_data = press_data ;
2798 apad->fastdelay = MCW_AV_shortdelay ; /* default delay on 2nd call */
2799 apad->count = 0 ;
2800
2801 apad->parent = apad->aux = NULL ;
2802 RETURN(apad) ;
2803 }
2804
2805 /*-------------------------------------------------------------------------*/
2806
AP_press_CB(Widget wbut,XtPointer client_data,XtPointer call_data)2807 void AP_press_CB( Widget wbut , XtPointer client_data , XtPointer call_data )
2808 {
2809 MCW_arrowpad *apad = (MCW_arrowpad *) client_data ;
2810 XmArrowButtonCallbackStruct *cbs =
2811 (XmArrowButtonCallbackStruct *) call_data ;
2812
2813 XtIntervalId fake_id = 0 ;
2814
2815 switch( cbs->reason ){
2816
2817 /*--- release of button (will only happen for arrows) ---*/
2818
2819 default:
2820 case XmCR_DISARM: /* time to stop */
2821 if( apad->timer_id != 0 ) XtRemoveTimeOut( apad->timer_id ) ;
2822 apad->timer_id = 0 ;
2823 break ;
2824
2825 /*--- press of button ---*/
2826
2827 case XmCR_ARM: /* arrow press */
2828 case XmCR_ACTIVATE:{ /* button press */
2829 int iar ;
2830
2831 for( iar=0 ; iar < 5 ; iar++ )
2832 if( wbut == apad->wbut[iar] ) break ;
2833
2834 if( iar > 4 ) return ; /* something wrong, exit */
2835
2836 apad->which_pressed = iar ;
2837 apad->count = 0 ;
2838
2839 if( cbs->reason == XmCR_ARM &&
2840 cbs->event->type == ButtonPress ) apad->delay = MCW_AV_longdelay;
2841 else apad->delay = 0 ;
2842
2843 apad->xev = *(cbs->event) ; /* copy event for user's info */
2844
2845 AP_timer_CB( apad , &fake_id ) ; /* do the work */
2846 }
2847 }
2848 return;
2849 }
2850
2851 /*-------------------------------------------------------------------------*/
2852
AP_timer_CB(XtPointer client_data,XtIntervalId * id)2853 void AP_timer_CB( XtPointer client_data , XtIntervalId *id )
2854 {
2855 MCW_arrowpad *apad = (MCW_arrowpad *) client_data ;
2856
2857 /* call user callback */
2858
2859 if( apad->action_CB != NULL )
2860 #if 0
2861 apad->action_CB( apad , apad->action_data ) ;
2862 #else
2863 AFNI_CALL_VOID_2ARG( apad->action_CB ,
2864 MCW_arrowpad * , apad ,
2865 XtPointer , apad->action_data ) ;
2866 #endif
2867
2868 /* delay and then call again, if desired */
2869
2870 if( apad->delay <= 0 ) return ;
2871
2872 (apad->count)++ ;
2873 if( apad->count > AP_MAXCOUNT ){
2874 apad->count = 0 ;
2875 return ;
2876 }
2877
2878 apad->timer_id = XtAppAddTimeOut(
2879 XtWidgetToApplicationContext( apad->wform ) ,
2880 apad->delay , AP_timer_CB , apad ) ;
2881
2882 if( apad->delay == MCW_AV_longdelay ){
2883 if( apad->fastdelay > 0 ) apad->delay = apad->fastdelay ;
2884 else apad->delay = MCW_AV_shortdelay ;
2885 }
2886
2887 return ;
2888 }
2889
2890 /*-------------------------------------------------------------------------
2891 Get a string:
2892 pops up a shell to let the user make the selection
2893
2894 wpar = parent widget (where to popup)
2895 label = label for chooser
2896 default_string = initial value
2897 func = routine to call when a selection is made:
2898 void func( Widget wpar,XtPointer func_data,MCW_choose_cbs *cbs )
2899 func_data = data to pass to func
2900
2901 The "cval" stored in the MCW_choose_cbs will be the desired result.
2902
2903 This routine is coded in such a way that only one chooser will be
2904 active at a time (per application). This is a deliberate choice.
2905 ---------------------------------------------------------------------------*/
2906
MCW_choose_string(Widget wpar,char * label,char * default_string,gen_func * func,XtPointer func_data)2907 void MCW_choose_string( Widget wpar , char *label ,
2908 char *default_string ,
2909 gen_func *func , XtPointer func_data )
2910 {
2911 static Widget wpop = NULL , wrc , wtf , wlab ;
2912 static MCW_choose_data cd ;
2913 Position xx,yy ;
2914 int ib , ncol=0 ;
2915
2916 ENTRY("MCW_choose_string") ;
2917
2918 /** destructor callback **/
2919
2920 if( wpar == NULL ){
2921 if( wpop != NULL ){
2922 XtUnmapWidget( wpop ) ;
2923 XtRemoveCallback( wpop,XmNdestroyCallback,MCW_destroy_chooser_CB,&wpop );
2924 XtDestroyWidget( wpop ) ;
2925 }
2926 wpop = NULL ; EXRETURN ;
2927 }
2928
2929 if( ! XtIsWidget(wpar) ) EXRETURN ;
2930
2931 if( ! XtIsRealized(wpar) ){ /* illegal call */
2932 fprintf(stderr,"\n*** illegal call to MCW_choose_string: %s\n",
2933 XtName(wpar) ) ;
2934 EXRETURN ;
2935 }
2936
2937 /*--- if popup widget already exists, destroy it ---*/
2938
2939 if( wpop != NULL ){
2940 XtRemoveCallback( wpop,XmNdestroyCallback,MCW_destroy_chooser_CB,&wpop );
2941 XtDestroyWidget( wpop ) ;
2942 }
2943
2944 /*--- create popup widget ---*/
2945
2946 wpop = XtVaCreatePopupShell( /* Popup Shell */
2947 MENU , xmDialogShellWidgetClass , wpar ,
2948 XmNtraversalOn , True ,
2949 XmNinitialResourcesPersistent , False ,
2950 XmNkeyboardFocusPolicy , XmEXPLICIT ,
2951 NULL ) ;
2952
2953 if( MCW_isitmwm(wpar) ){
2954 XtVaSetValues( wpop ,
2955 XmNmwmDecorations , MWM_DECOR_BORDER ,
2956 XmNmwmFunctions , MWM_FUNC_MOVE ,
2957 NULL ) ;
2958 }
2959
2960 XtAddCallback( wpop , XmNdestroyCallback , MCW_destroy_chooser_CB , &wpop ) ;
2961
2962 XmAddWMProtocolCallback(
2963 wpop ,
2964 XmInternAtom( XtDisplay(wpop) , "WM_DELETE_WINDOW" , False ) ,
2965 MCW_kill_chooser_CB , wpop ) ;
2966
2967 wrc = XtVaCreateWidget( /* RowColumn to hold all */
2968 MENU , xmRowColumnWidgetClass , wpop ,
2969 XmNpacking , XmPACK_TIGHT ,
2970 XmNorientation , XmVERTICAL ,
2971 XmNtraversalOn , True ,
2972 XmNinitialResourcesPersistent , False ,
2973 NULL ) ;
2974
2975 if( label != NULL && (ncol=strlen(label)) > 0 ){
2976 char *cpt ;
2977 wlab = XtVaCreateManagedWidget(
2978 MENU , xmLabelWidgetClass , wrc ,
2979 LABEL_ARG(label) ,
2980 XmNinitialResourcesPersistent , False ,
2981 NULL ) ;
2982 LABELIZE(wlab) ;
2983
2984 cpt = strstr(label,"\n") ;
2985 if( cpt != NULL ) ncol = cpt-label ; /* 01 Nov 2001 */
2986 }
2987
2988 if( default_string != NULL && default_string[0] != '\0' ){
2989 int qq = strlen(default_string) ;
2990 if( qq > ncol ) ncol = qq ;
2991 }
2992 if( ncol < AV_NCOL ) ncol = AV_NCOL ;
2993
2994 wtf = XtVaCreateManagedWidget(
2995 MENU , TEXT_CLASS , wrc ,
2996
2997 XmNcolumns , ncol ,
2998 XmNeditable , True ,
2999 XmNmaxLength , ncol+64 ,
3000 XmNresizeWidth , False ,
3001
3002 XmNmarginHeight , 1 ,
3003 XmNmarginWidth , 1 ,
3004
3005 XmNcursorPositionVisible , True ,
3006 XmNblinkRate , 0 ,
3007 XmNautoShowCursorPosition , True ,
3008
3009 XmNinitialResourcesPersistent , False ,
3010 XmNtraversalOn , True ,
3011 NULL ) ;
3012
3013 if( default_string != NULL && default_string[0] != '\0' ){
3014 int qq = strlen(default_string) , ii ;
3015 for( ii=0 ; ii < qq ; ii++ ) if( default_string[ii] != ' ' ) break ;
3016 if( ii < qq ) TEXT_SET( wtf , default_string ) ;
3017 }
3018
3019 cd.wpop = wpop ; /* data to be passed to pushbutton callback */
3020 cd.wcaller = wpar ;
3021 cd.wchoice = wtf ;
3022 cd.sel_CB = func ;
3023 cd.sel_cd = func_data ;
3024 cd.ctype = mcwCT_string ;
3025
3026 XtAddCallback( wtf,XmNactivateCallback,MCW_choose_CB,&cd ) ; /* return key */
3027
3028 for( ib=0 ; ib < NUM_CLR_ACT ; ib++ ) OVC_act[ib].data = &cd ;
3029
3030 (void) MCW_action_area( wrc , OVC_act , NUM_CLR_ACT ) ;
3031
3032 RELOCATE(wpar,wpop,5) ; /* 12 Oct 2017 */
3033
3034 XtManageChild( wrc ) ;
3035 XtPopup( wpop , XtGrabNone ) ; RWC_sleep(1);
3036
3037 RWC_visibilize_widget( wpop ) ; /* 09 Nov 1999 */
3038 NORMAL_cursorize( wpop ) ;
3039
3040 EXRETURN ;
3041 }
3042
3043 /*-------------------------------------------------------------------------*/
3044
3045 static int browse_select = 0 , bcs = 0 , blocked = 0 ;
MCW_set_browse_select(int i)3046 void MCW_set_browse_select(int i){ browse_select = i ; } /* 21 Feb 2007 */
3047
3048 /*-------------------------------------------------------------------------*/
3049
3050 static int list_max = -1 , list_maxmax ;
3051
MCW_set_listmax(Widget wpar)3052 static void MCW_set_listmax( Widget wpar )
3053 {
3054 if( list_max < 0 ){
3055 #if 0
3056 char *xdef = XGetDefault( XtDisplay(wpar) , "AFNI" , "chooser_listmax" ) ;
3057 #else
3058 char *xdef = RWC_getname( XtDisplay(wpar) , "chooser_listmax" ) ;
3059 #endif
3060 if( xdef == NULL ) xdef = getenv("AFNI_MENU_COLSIZE") ; /* 11 Dec 2001 */
3061 if( xdef != NULL ) list_max = strtol( xdef , NULL , 10 ) ;
3062 if( list_max <= 4 ) list_max = LIST_MAX ;
3063 list_maxmax = list_max + 5 ;
3064 }
3065 return ;
3066 }
3067
3068 /*-------------------------------------------------------------------------
3069 Get an integer, as an index to an array of strings:
3070 pops up a shell to let the user make the selection, cycling through
3071 the string array
3072
3073 wpar = parent widget (where to popup)
3074 label = label for chooser
3075 num_str = number of strings
3076 init = index of initial string
3077 strlist = array of char *, pointing to strings
3078 func = routine to call when a selection is made:
3079 void func( Widget wpar,XtPointer func_data,MCW_choose_cbs *cbs )
3080 func_data = data to pass to func
3081
3082 The "ival" stored in the MCW_choose_cbs will be the desired result
3083 (from 0 to num_str-1).
3084
3085 This routine is coded in such a way that only one chooser will be
3086 active at a time (per application). This is a deliberate choice.
3087 ---------------------------------------------------------------------------*/
3088
MCW_choose_strlist(Widget wpar,char * label,int num_str,int init,char * strlist[],gen_func * func,XtPointer func_data)3089 void MCW_choose_strlist( Widget wpar , char *label ,
3090 int num_str , int init , char *strlist[] ,
3091 gen_func *func , XtPointer func_data )
3092 {
3093 int initar[2] ;
3094 initar[0] = init ;
3095 initar[1] = -666 ;
3096
3097 MCW_choose_multi_strlist( wpar , label , mcwCT_single_mode ,
3098 num_str , initar , strlist , func , func_data ) ;
3099 return ;
3100 }
3101
3102 /*-------------------------------------------------------------------------*/
3103
MCW_choose_binary(Widget wpar,char * label,int init,char * str0,char * str1,gen_func * func,XtPointer func_data)3104 void MCW_choose_binary( Widget wpar , char *label , /* 10 Feb 2012 */
3105 int init , char *str0 , char *str1 ,
3106 gen_func *func , XtPointer func_data )
3107 {
3108 char *strlist[2] ;
3109 strlist[0] = (str0 == NULL || *str0 == '\0' ) ? "Off" : str0 ;
3110 strlist[1] = (str1 == NULL || *str1 == '\0' ) ? "On" : str1 ;
3111 MCW_choose_strlist( wpar, label, 2, (init!=0), strlist, func,func_data ) ;
3112 return ;
3113 }
3114
3115 /*-------------------------------------------------------------------------*/
3116
3117 static Widget str_wlist = NULL ; /* 12 Oct 2007 */
3118 static int str_wlist_num = 0 ;
3119 static MCW_arrowval *str_wlist_av = NULL ;
3120
MCW_strlist_av_CB(MCW_arrowval * av,XtPointer cd)3121 static void MCW_strlist_av_CB( MCW_arrowval *av , XtPointer cd )
3122 {
3123 int init=1+av->ival , itop=0,nvis=0 ;
3124
3125 if( str_wlist == NULL || !XtIsRealized(str_wlist) ||
3126 init <= 0 || init > str_wlist_num ) return ;
3127
3128 XmListSelectPos( str_wlist , init , False ) ;
3129 XtVaGetValues( str_wlist ,
3130 XmNtopItemPosition ,&itop ,
3131 XmNvisibleItemCount,&nvis ,
3132 NULL ) ;
3133 if( init < itop ) XmListSetPos ( str_wlist , init ) ;
3134 else if( init >= itop+nvis ) XmListSetBottomPos( str_wlist , init ) ;
3135
3136 if( bcs && !blocked ){
3137 blocked = 1 ;
3138 XtCallCallbacks( str_wlist , XmNbrowseSelectionCallback , NULL ) ;
3139 blocked = 0 ;
3140 }
3141 }
3142
3143 /*-------------------------------------------------------------------------*/
3144
MCW_strlist_select_CB(Widget w,XtPointer cd,XtPointer cb)3145 static void MCW_strlist_select_CB( Widget w, XtPointer cd, XtPointer cb )
3146 {
3147 int ns=0 ; unsigned int *sp=NULL ;
3148
3149 if( str_wlist == NULL || !XtIsRealized(str_wlist) ) return ;
3150
3151 XtVaGetValues( str_wlist ,
3152 XmNselectedPositionCount , &ns ,
3153 XmNselectedPositions , &sp ,
3154 NULL ) ;
3155 if( ns <= 0 || sp == NULL ) return ;
3156 AV_assign_ival( str_wlist_av , (int)(sp[0])-1 ) ;
3157 blocked = 1 ;
3158 MCW_strlist_av_CB( str_wlist_av , NULL ) ;
3159 blocked = 0 ;
3160 }
3161
3162 /*-------------------------------------------------------------------------*/
3163
MCW_choose_multi_strlist(Widget wpar,char * label,int mode,int num_str,int * init,char * strlist[],gen_func * func,XtPointer func_data)3164 void MCW_choose_multi_strlist( Widget wpar , char *label , int mode ,
3165 int num_str , int *init , char *strlist[] ,
3166 gen_func *func , XtPointer func_data )
3167 {
3168 static Widget wpop=NULL , wrc ;
3169 static MCW_choose_data cd ;
3170 Position xx,yy ;
3171 int ib , ll , ltop ;
3172 Widget wlist=NULL , wlab ;
3173 XmStringTable xmstr ;
3174 XmString xms ;
3175 char *lbuf ;
3176 int nvisible ;
3177 MCW_arrowval *wav ; /* 12 Oct 2007 */
3178
3179 ENTRY("MCW_choose_multi_strlist") ;
3180
3181 /** destructor callback **/
3182
3183 bcs = browse_select ; /* 21 Feb 2007 */
3184 browse_select = 0 ; /* 21 Feb 2007 */
3185 str_wlist = NULL ; /* 12 Oct 2007 */
3186
3187 if( wpop != NULL && old_wpar != NULL ){ /* Apr 2013: save current location */
3188 MCW_widget_geom( wpop , NULL,NULL , &old_xx,&old_yy ) ;
3189 }
3190
3191 if( wpar == NULL ){
3192 if( wpop != NULL ){
3193 STATUS("destroying chooser") ;
3194 XtUnmapWidget( wpop ) ;
3195 XtRemoveCallback( wpop, XmNdestroyCallback, MCW_destroy_chooser_CB, &wpop ) ;
3196 XtDestroyWidget( wpop ) ;
3197 wpop = NULL ;
3198 }
3199 EXRETURN ;
3200 }
3201
3202 if( ! XtIsRealized(wpar) ){ /* illegal call */
3203 fprintf(stderr,"\n*** illegal call to MCW_choose_strlist %s\n",
3204 XtName(wpar) ) ;
3205 EXRETURN ;
3206 }
3207
3208 MCW_set_listmax( wpar ) ;
3209
3210 /*--- if popup widget already exists, destroy it ---*/
3211
3212 if( wpop != NULL ){
3213 XtRemoveCallback( wpop, XmNdestroyCallback, MCW_destroy_chooser_CB, &wpop ) ;
3214 XtDestroyWidget( wpop ) ;
3215 }
3216
3217 wlist = NULL ;
3218
3219 /*--- create popup widget ---*/
3220
3221 wpop = XtVaCreatePopupShell( /* Popup Shell */
3222 MENU , xmDialogShellWidgetClass , wpar ,
3223 XmNtraversalOn , True ,
3224 XmNinitialResourcesPersistent , False ,
3225 XmNkeyboardFocusPolicy , XmEXPLICIT ,
3226 NULL ) ;
3227
3228 if( MCW_isitmwm(wpar) ){
3229 XtVaSetValues( wpop ,
3230 XmNmwmDecorations , MWM_DECOR_BORDER ,
3231 XmNmwmFunctions , MWM_FUNC_MOVE
3232 | MWM_FUNC_CLOSE ,
3233 NULL ) ;
3234 }
3235
3236 XtAddCallback( wpop , XmNdestroyCallback , MCW_destroy_chooser_CB , &wpop ) ;
3237
3238 XmAddWMProtocolCallback(
3239 wpop ,
3240 XmInternAtom( XtDisplay(wpop) , "WM_DELETE_WINDOW" , False ) ,
3241 MCW_kill_chooser_CB , wpop ) ;
3242
3243 wrc = XtVaCreateWidget( /* RowColumn to hold all */
3244 MENU , xmRowColumnWidgetClass , wpop ,
3245 XmNpacking , XmPACK_TIGHT ,
3246 XmNorientation , XmVERTICAL ,
3247 XmNtraversalOn , True ,
3248 XmNinitialResourcesPersistent , False ,
3249 NULL ) ;
3250
3251 if( label != NULL && label[0] != '\0' ){
3252 lbuf = (char*)XtMalloc( strlen(label) + 32 ) ;
3253 sprintf( lbuf , "----Choose %s----\n%s" ,
3254 (mode == mcwCT_single_mode) ? "One" : "One or More" , label ) ;
3255 } else {
3256 lbuf = (char*)XtMalloc( 32 ) ;
3257 sprintf( lbuf , "----Choose %s----",
3258 (mode == mcwCT_single_mode) ? "One" : "One or More" ) ;
3259 }
3260 xms = XmStringCreateLtoR( lbuf , XmFONTLIST_DEFAULT_TAG ) ;
3261 wlab = XtVaCreateManagedWidget(
3262 MENU , xmLabelWidgetClass , wrc ,
3263 XmNlabelString , xms ,
3264 XmNalignment , XmALIGNMENT_CENTER ,
3265 XmNinitialResourcesPersistent , False ,
3266 NULL ) ;
3267 myXtFree(lbuf) ; XmStringFree(xms) ; LABELIZE(wlab) ;
3268
3269 (void) XtVaCreateManagedWidget(
3270 MENU , xmSeparatorWidgetClass , wrc ,
3271 XmNseparatorType , XmSHADOW_ETCHED_IN ,
3272 XmNinitialResourcesPersistent , False ,
3273 NULL ) ;
3274
3275 xmstr = (XmStringTable) XtMalloc( num_str * sizeof(XmString *) ) ;
3276 for( ib=0 ; ib < num_str ; ib++ )
3277 xmstr[ib] = XmStringCreateSimple(strlist[ib]) ;
3278
3279 wlist = XmCreateScrolledList( wrc , MENU , NULL , 0 ) ;
3280
3281 nvisible = (num_str < list_maxmax ) ? num_str : list_max ;
3282
3283 str_wlist = wlist ; /* 12 Oct 2007 */
3284 str_wlist_num = num_str ;
3285
3286 XtVaSetValues( wlist ,
3287 XmNitems , xmstr ,
3288 XmNitemCount , num_str ,
3289 XmNvisibleItemCount , nvisible ,
3290 XmNtraversalOn , True ,
3291 XmNselectionPolicy , (mode == mcwCT_single_mode)
3292 ? XmBROWSE_SELECT : XmMULTIPLE_SELECT ,
3293 NULL ) ;
3294
3295 if( init != NULL ){
3296 for( ib=0 ; init[ib] >= 0 && init[ib] < num_str ; ib++ )
3297 XmListSelectPos( wlist , init[ib]+1 , False ) ;
3298 if( ib > 0 && init[ib-1] > nvisible )
3299 XmListSetBottomPos( wlist , init[ib-1]+1 ) ;
3300 }
3301
3302 XtManageChild(wlist) ;
3303
3304 if( mode == mcwCT_multi_mode ){ /* multiple selections allowed at a time */
3305 MCW_register_help( wlist , OVC_list_help_2 ) ;
3306 MCW_register_help( wlab , OVC_list_help_2 ) ;
3307 } else { /* single selection allowed at a time */
3308 MCW_register_help( wlist , OVC_list_help_1 ) ;
3309 MCW_register_help( wlab , OVC_list_help_1 ) ;
3310 XtAddCallback( wlist , XmNdefaultActionCallback , MCW_choose_CB , &cd ) ;
3311 if( bcs ) /* 21 Feb 2007 */
3312 XtAddCallback( wlist, XmNbrowseSelectionCallback,MCW_choose_CB, &cd ) ;
3313 }
3314
3315 cd.wchoice = wlist ;
3316 cd.av = NULL ; /* this is NULL --> will use the list widget */
3317
3318 for( ib=0 ; ib < num_str ; ib++ ) XmStringFree(xmstr[ib]) ;
3319 myXtFree(xmstr) ;
3320
3321 cd.wpop = wpop ; /* data to be passed to pushbutton callback */
3322 cd.wcaller = wpar ;
3323 cd.sel_CB = func ;
3324 cd.sel_cd = func_data ;
3325 cd.ctype = mcwCT_integer ;
3326
3327 for( ib=0 ; ib < NUM_OVC_ACT ; ib++ ) OVC_act[ib].data = &cd ;
3328
3329 (void) MCW_action_area( wrc , OVC_act , NUM_OVC_ACT ) ;
3330
3331 if( mode == mcwCT_multi_mode ){
3332 (void) XtVaCreateManagedWidget(
3333 MENU , xmSeparatorWidgetClass , wrc ,
3334 XmNseparatorType , XmSINGLE_LINE ,
3335 XmNinitialResourcesPersistent , False ,
3336 NULL ) ;
3337
3338 wav = new_MCW_optmenu( wrc , "Selection Mode" , 0,NUM_LIST_MODES-1,0,0 ,
3339 MCW_list_mode_CB , wlist ,
3340 MCW_av_substring_CB , list_modes ) ;
3341
3342 MCW_reghelp_children( wav->wrowcol , OVC_list_help_2 ) ;
3343 MCW_reghint_children( wav->wrowcol , "How list selections work" ) ;
3344
3345 } else if( mode == mcwCT_single_mode &&
3346 !AFNI_noenv("AFNI_STRLIST_INDEX") &&
3347 num_str > 1 ){ /* 12 Oct 2007 */
3348 int ival = 0 ;
3349
3350 (void) XtVaCreateManagedWidget(
3351 MENU , xmSeparatorWidgetClass , wrc ,
3352 XmNseparatorType , XmSINGLE_LINE ,
3353 XmNinitialResourcesPersistent , False ,
3354 NULL ) ;
3355
3356 if( init != NULL && init[0] > 0 && init[0] < num_str ) ival = init[0] ;
3357
3358 str_wlist_av = new_MCW_arrowval( wrc , "Index" , MCW_AV_updown ,
3359 0 , num_str-1 , ival , MCW_AV_editext , 0 ,
3360 MCW_strlist_av_CB , NULL , NULL , NULL ) ;
3361
3362 XtAddCallback(wlist,XmNbrowseSelectionCallback,MCW_strlist_select_CB,NULL);
3363 }
3364
3365 if( old_xx < 0 || old_yy < 0 || old_wpar != wpar ){
3366 RELOCATE(wpar,wpop,2) ; /* 12 Oct 2017 */
3367 } else {
3368 #ifdef DARWIN
3369 # define YDEL 20
3370 #else
3371 # define YDEL 0
3372 #endif
3373 XtVaSetValues( wpop , XmNx , old_xx , XmNy , old_yy-YDEL , NULL ) ; /* Apr 2013 */
3374 }
3375
3376 XtManageChild( wrc ) ;
3377 XtPopup( wpop , XtGrabNone ) ; RWC_sleep(1);
3378
3379 RWC_visibilize_widget( wpop ) ; /* 09 Nov 1999 */
3380 NORMAL_cursorize( wpop ) ;
3381
3382 old_wpar = wpar ; /* Apr 2013 */
3383
3384 EXRETURN ;
3385 }
3386
3387 /*--------------------------------------------------------------------*/
3388
MCW_list_mode_CB(MCW_arrowval * av,XtPointer cd)3389 void MCW_list_mode_CB( MCW_arrowval *av , XtPointer cd )
3390 {
3391 Widget wlist = (Widget) cd ;
3392
3393 if( av == NULL || wlist == NULL ) return ;
3394
3395 XtVaSetValues( wlist ,
3396 XmNselectionPolicy ,
3397 (av->ival == 0) ? XmMULTIPLE_SELECT
3398 : XmEXTENDED_SELECT ,
3399 NULL ) ;
3400 }
3401
3402 /*==================================================================================*/
3403
3404 #define TSC_quit_label "Quit"
3405 #define TSC_plot_label "Plot"
3406 #define TSC_apply_label "Apply"
3407 #define TSC_done_label "Set"
3408
3409 #define TSC_quit_help "Press to close\nthis `chooser'"
3410 #define TSC_plot_help "Press to popup\na graph of the\nselected time series"
3411 #define TSC_apply_help "Press to apply\nthis choice and\nkeep this `chooser'"
3412 #define TSC_done_help "Press to apply\nthis choice and\nclose this `chooser'"
3413
3414 #define TSC_list_help_1 OVC_list_help_1
3415
3416 #define NUM_TSC_ACT 4
3417
3418 #undef DONT_USE_COXPLOT /* for the long-delayed Plot option */
3419
3420 #undef PCODE
3421 #ifdef DONT_USE_COXPLOT
3422 # define PCODE -1
3423 #else
3424 # define PCODE 0
3425 # include "coxplot.h"
3426 #endif
3427
3428 static MCW_action_item TSC_act[] = {
3429 { TSC_quit_label , MCW_choose_CB, NULL, TSC_quit_help ,"Close window" , 0 },
3430 { TSC_plot_label , MCW_choose_CB, NULL, TSC_plot_help ,"Plot data" , PCODE },
3431 { TSC_apply_label, MCW_choose_CB, NULL, TSC_apply_help,"Apply choice, keep window" , 0 },
3432 { TSC_done_label , MCW_choose_CB, NULL, TSC_done_help ,"Apply choice, close window", 1 }
3433 } ;
3434
3435 #undef PCODE
3436
3437 /*-------------------------------------------------------------------------
3438 Get a time series (1D MRI_IMAGE *) from an array of such things:
3439 pops up a shell to let the user make the selection, with a list
3440 of time series name
3441
3442 wpar = parent widget (where to popup)
3443 label = label for chooser
3444 tsarr = array of time series (1D images)
3445 init = index of initial time series to select
3446 func = routine to call when choice is made
3447 void func( Widget wpar,XtPointer func_data,MCW_choose_cbs *cbs )
3448 func_data = data to pass to func
3449
3450 The "ival" stored in the MCW_choose_cbs will the index of the
3451 chosen timeseries in tsarr. The "imval" be the pointer to the
3452 chosen timeseries itself. Do NOT mri_free this, since it will just be a
3453 pointer to the correct entry in tsarr (which should not be modified
3454 by any other code during the lifetime of this popup!).
3455
3456 This routine is coded in such a way that only one chooser will be
3457 active at a time (per application). This is a deliberate choice.
3458 ---------------------------------------------------------------------------*/
3459
MCW_choose_timeseries(Widget wpar,char * label,MRI_IMARR * tsarr,int init,gen_func * func,XtPointer func_data)3460 void MCW_choose_timeseries( Widget wpar , char *label ,
3461 MRI_IMARR *tsarr , int init ,
3462 gen_func *func , XtPointer func_data )
3463 {
3464 static Widget wpop = NULL , wrc ;
3465 static MCW_choose_data cd ;
3466 Position xx,yy ;
3467 int ib , ll , ltop , num_ts , nvisible , xd,yd ;
3468 Widget wlist = NULL , wlab ;
3469 XmStringTable xmstr ;
3470 XmString xms ;
3471 char *lbuf ;
3472 char pbuf[256] , qbuf[512] ;
3473 MRI_IMAGE *tsim ;
3474
3475 ENTRY("MCW_choose_timeseries") ;
3476
3477 /** destructor callback **/
3478
3479 if( wpar == NULL ){
3480 if( wpop != NULL ){
3481 STATUS("popdown call") ;
3482 XtUnmapWidget( wpop ) ;
3483 XtRemoveCallback( wpop, XmNdestroyCallback, MCW_destroy_chooser_CB, &wpop ) ;
3484 XtDestroyWidget( wpop ) ;
3485 }
3486 wpop = NULL ; EXRETURN ;
3487 }
3488
3489 if( ! XtIsRealized(wpar) ){ /* illegal call */
3490 fprintf(stderr,"\n*** illegal call to MCW_choose_timeseries %s\n",
3491 XtName(wpar) ) ;
3492 EXRETURN ;
3493 }
3494
3495 MCW_set_listmax( wpar ) ;
3496
3497 /*--- if popup widget already exists, destroy it ---*/
3498
3499 if( wpop != NULL ){
3500 STATUS("destroying old widget") ;
3501 XtRemoveCallback( wpop, XmNdestroyCallback, MCW_destroy_chooser_CB, &wpop ) ;
3502 XtDestroyWidget( wpop ) ;
3503 }
3504
3505 wlist = NULL ;
3506
3507 /*--- sanity checks ---*/
3508
3509 if( tsarr == NULL || tsarr->num == 0 ) EXRETURN ;
3510 num_ts = tsarr->num ;
3511
3512 if(PRINT_TRACING){
3513 char str[256]; sprintf(str,"creation with %d choices",num_ts); STATUS(str);
3514 }
3515
3516 /*--- create popup widget ---*/
3517
3518 wpop = XtVaCreatePopupShell( /* Popup Shell */
3519 MENU , xmDialogShellWidgetClass , wpar ,
3520 XmNtraversalOn , True ,
3521 XmNinitialResourcesPersistent , False ,
3522 XmNkeyboardFocusPolicy , XmEXPLICIT ,
3523 NULL ) ;
3524
3525 if( MCW_isitmwm(wpar) ){
3526 XtVaSetValues( wpop ,
3527 XmNmwmDecorations , MWM_DECOR_BORDER ,
3528 XmNmwmFunctions , MWM_FUNC_MOVE
3529 | MWM_FUNC_CLOSE ,
3530 NULL ) ;
3531 }
3532
3533 XtAddCallback( wpop , XmNdestroyCallback , MCW_destroy_chooser_CB , &wpop ) ;
3534
3535 XmAddWMProtocolCallback(
3536 wpop ,
3537 XmInternAtom( XtDisplay(wpop) , "WM_DELETE_WINDOW" , False ) ,
3538 MCW_kill_chooser_CB , wpop ) ;
3539
3540 wrc = XtVaCreateWidget( /* RowColumn to hold all */
3541 MENU , xmRowColumnWidgetClass , wpop ,
3542 XmNpacking , XmPACK_TIGHT ,
3543 XmNorientation , XmVERTICAL ,
3544 XmNtraversalOn , True ,
3545 XmNinitialResourcesPersistent , False ,
3546 NULL ) ;
3547
3548 if( label != NULL ){
3549 lbuf = (char*)XtMalloc( strlen(label) + 32 ) ;
3550 sprintf( lbuf , "----Choose One----\n%s" , label ) ;
3551 } else {
3552 lbuf = (char*)XtMalloc( 32 ) ;
3553 sprintf( lbuf , "----Choose One----" ) ;
3554 }
3555 xms = XmStringCreateLtoR( lbuf , XmFONTLIST_DEFAULT_TAG ) ;
3556 wlab = XtVaCreateManagedWidget(
3557 MENU , xmLabelWidgetClass , wrc ,
3558 XmNlabelString , xms ,
3559 XmNalignment , XmALIGNMENT_CENTER ,
3560 XmNinitialResourcesPersistent , False ,
3561 NULL ) ;
3562 myXtFree(lbuf) ; XmStringFree(xms) ; LABELIZE(wlab) ;
3563
3564 (void) XtVaCreateManagedWidget(
3565 MENU , xmSeparatorWidgetClass , wrc ,
3566 XmNseparatorType , XmSHADOW_ETCHED_IN ,
3567 XmNinitialResourcesPersistent , False ,
3568 NULL ) ;
3569
3570 xmstr = (XmStringTable) XtMalloc( num_ts * sizeof(XmString *) ) ;
3571
3572 xd = yd = ltop = 1 ;
3573 for( ib=0 ; ib < num_ts ; ib++ ){
3574 tsim = IMARR_SUBIMAGE(tsarr,ib) ;
3575 if( tsim == NULL ){
3576 strcpy(pbuf,"** NULL series ??") ;
3577 } else {
3578 if( tsim->name != NULL )
3579 MCW_strncpy(pbuf,IMARR_SUBIMAGE(tsarr,ib)->name,254) ;
3580 else
3581 strcpy(pbuf,"** NO NAME ??") ;
3582
3583 sprintf(qbuf,"%d",tsim->nx) ; ll = strlen(qbuf) ; xd = MAX(xd,ll) ;
3584 sprintf(qbuf,"%d",tsim->ny) ; ll = strlen(qbuf) ; yd = MAX(yd,ll) ;
3585 }
3586 ll = strlen(pbuf) ; ltop = MAX(ltop,ll) ;
3587 }
3588
3589 for( ib=0 ; ib < num_ts ; ib++ ){
3590 tsim = IMARR_SUBIMAGE(tsarr,ib) ;
3591 if( tsim == NULL ){
3592 strcpy(qbuf,"** NULL series ??") ;
3593 } else {
3594 if( tsim->name != NULL )
3595 MCW_strncpy(pbuf,IMARR_SUBIMAGE(tsarr,ib)->name,254) ;
3596 else
3597 strcpy(pbuf,"** NO NAME ??") ;
3598
3599 sprintf(qbuf,"%-*s [%*d x %*d]", ltop,pbuf , xd,tsim->nx , yd,tsim->ny ) ;
3600 }
3601 xmstr[ib] = XmStringCreateSimple( qbuf ) ;
3602 }
3603
3604 wlist = XmCreateScrolledList( wrc , MENU , NULL , 0 ) ;
3605
3606 nvisible = (num_ts < list_maxmax ) ? num_ts : list_max ;
3607 XtVaSetValues( wlist ,
3608 XmNitems , xmstr ,
3609 XmNitemCount , num_ts ,
3610 XmNvisibleItemCount , nvisible ,
3611 XmNtraversalOn , True ,
3612 XmNselectionPolicy , XmBROWSE_SELECT ,
3613 NULL ) ;
3614 if( init >= 0 && init < num_ts ){
3615 XmListSelectPos( wlist , init+1 , False ) ;
3616 if( init+1 > nvisible ) XmListSetBottomPos( wlist , init+1 ) ;
3617 }
3618 XtManageChild(wlist) ;
3619
3620 XtAddCallback( wlist , XmNdefaultActionCallback , MCW_choose_CB , &cd ) ;
3621
3622 MCW_register_help( wlist , TSC_list_help_1 ) ;
3623 MCW_register_help( wlab , TSC_list_help_1 ) ;
3624
3625 cd.tsarr = tsarr ;
3626 cd.wchoice = wlist ;
3627 cd.av = NULL ;
3628
3629 #if 1
3630 for( ib=0 ; ib < num_ts ; ib++ ) XmStringFree(xmstr[ib]) ;
3631 myXtFree(xmstr) ;
3632 #endif
3633
3634 cd.wpop = wpop ; /* data to be passed to pushbutton callback */
3635 cd.wcaller = wpar ;
3636 cd.sel_CB = func ;
3637 cd.sel_cd = func_data ;
3638 cd.ctype = mcwCT_timeseries ;
3639
3640 for( ib=0 ; ib < NUM_TSC_ACT ; ib++ ) TSC_act[ib].data = &cd ;
3641
3642 (void) MCW_action_area( wrc , TSC_act , NUM_TSC_ACT ) ;
3643
3644 RELOCATE(wpar,wpop,5) ; /* 12 Oct 2017 */
3645
3646 XtManageChild( wrc ) ;
3647 XtPopup( wpop , XtGrabNone ) ; RWC_sleep(1);
3648
3649 RWC_visibilize_widget( wpop ) ; /* 09 Nov 1999 */
3650 NORMAL_cursorize( wpop ) ;
3651
3652 EXRETURN ;
3653 }
3654
3655 /*==================================================================================*/
3656
3657 #define TCV_quit_label "Quit"
3658 #define TCV_view_label "View"
3659 #define TCV_apply_label "Apply"
3660 #define TCV_done_label "Set"
3661
3662 #define TCV_quit_help "Press to close\nthis `chooser'"
3663 #define TCV_view_help "Press to popup\na view of this\nfile's top"
3664 #define TCV_apply_help "Press to apply\nthis choice and\nkeep this `chooser'"
3665 #define TCV_done_help "Press to apply\nthis choice and\nclose this `chooser'"
3666
3667 #define TCV_list_help_1 OVC_list_help_1
3668
3669 #define NUM_TCV_ACT 4
3670
3671 static MCW_action_item TCV_act[] = {
3672 { TCV_quit_label , MCW_choose_CB, NULL, TCV_quit_help ,"Close this window" , 0 },
3673 { TCV_view_label , MCW_choose_CB, NULL, TCV_view_help ,"View top few lines of data", 0 },
3674 { TCV_apply_label, MCW_choose_CB, NULL, TCV_apply_help,"Apply choice, keep window" , 0 },
3675 { TCV_done_label , MCW_choose_CB, NULL, TCV_done_help ,"Apply choice, close window", 1 }
3676 } ;
3677
3678 /*-------------------------------------------------------------------------
3679 Get a NI_element from a *.[tc]sv file, from an array of such things:
3680 pops up a shell to let the user make the selection, with a list
3681 of filenames:
3682
3683 wpar = parent widget (where to popup)
3684 label = label for chooser
3685 elarr = array of NI_elements
3686 init = index of initial element to select
3687 func = routine to call when choice is made
3688 void func( Widget wpar,XtPointer func_data,MCW_choose_cbs *cbs )
3689 func_data = data to pass to func
3690
3691 The "ival" stored in the MCW_choose_cbs will the index of the
3692 chosen element in elarr. The "imval" be the pointer to the
3693 chosen NI_element itself (which will have to be cast to the
3694 correct type). Do NOT NI_free_element this, since it will just be a
3695 pointer to the correct entry in elarr (which should not be modified
3696 by any other code during the lifetime of this popup!).
3697
3698 This routine is coded in such a way that only one chooser will be
3699 active at a time (per application). This is a deliberate choice.
3700 ---------------------------------------------------------------------------*/
3701
MCW_choose_tcsv(Widget wpar,char * label,NI_ELARR * elarr,int init,gen_func * func,XtPointer func_data)3702 void MCW_choose_tcsv( Widget wpar , char *label ,
3703 NI_ELARR *elarr , int init ,
3704 gen_func *func , XtPointer func_data )
3705 {
3706 static Widget wpop = NULL , wrc ;
3707 static MCW_choose_data cd ;
3708 Position xx,yy ;
3709 int ib , ll , ltop , num_el , nvisible , xd,yd ;
3710 Widget wlist = NULL , wlab ;
3711 XmStringTable xmstr ;
3712 XmString xms ;
3713 char *lbuf ;
3714 char pbuf[256] , qbuf[512] ;
3715 NI_element *nel ;
3716
3717 ENTRY("MCW_choose_tcsv") ;
3718
3719 /** destructor callback **/
3720
3721 if( wpar == NULL ){
3722 if( wpop != NULL ){
3723 STATUS("popdown call") ;
3724 XtUnmapWidget( wpop ) ;
3725 XtRemoveCallback( wpop, XmNdestroyCallback, MCW_destroy_chooser_CB, &wpop ) ;
3726 XtDestroyWidget( wpop ) ;
3727 }
3728 wpop = NULL ; EXRETURN ;
3729 }
3730
3731 if( ! XtIsRealized(wpar) ){ /* illegal call */
3732 fprintf(stderr,"\n*** illegal call to MCW_choose_tcsv %s\n",
3733 XtName(wpar) ) ;
3734 EXRETURN ;
3735 }
3736
3737 MCW_set_listmax( wpar ) ;
3738
3739 /*--- if popup widget already exists, destroy it ---*/
3740
3741 if( wpop != NULL ){
3742 STATUS("destroying old widget") ;
3743 XtRemoveCallback( wpop, XmNdestroyCallback, MCW_destroy_chooser_CB, &wpop ) ;
3744 XtDestroyWidget( wpop ) ;
3745 }
3746
3747 wlist = NULL ;
3748
3749 /*--- sanity checks ---*/
3750
3751 if( elarr == NULL || elarr->num == 0 ) EXRETURN ;
3752 num_el = elarr->num ;
3753
3754 if(PRINT_TRACING){
3755 char str[256]; sprintf(str,"creation with %d choices",num_el); STATUS(str);
3756 }
3757
3758 /*--- create popup widget ---*/
3759
3760 wpop = XtVaCreatePopupShell( /* Popup Shell */
3761 MENU , xmDialogShellWidgetClass , wpar ,
3762 XmNtraversalOn , True ,
3763 XmNinitialResourcesPersistent , False ,
3764 XmNkeyboardFocusPolicy , XmEXPLICIT ,
3765 NULL ) ;
3766
3767 if( MCW_isitmwm(wpar) ){ /* decorate for Motif Window Manager */
3768 XtVaSetValues( wpop ,
3769 XmNmwmDecorations , MWM_DECOR_BORDER ,
3770 XmNmwmFunctions , MWM_FUNC_MOVE
3771 | MWM_FUNC_CLOSE ,
3772 NULL ) ;
3773 }
3774
3775 /* what to do when widget is destroyed cruelly */
3776
3777 XtAddCallback( wpop , XmNdestroyCallback , MCW_destroy_chooser_CB , &wpop ) ;
3778
3779 /* what to do when window manager shoots widget in the head */
3780
3781 XmAddWMProtocolCallback(
3782 wpop ,
3783 XmInternAtom( XtDisplay(wpop) , "WM_DELETE_WINDOW" , False ) ,
3784 MCW_kill_chooser_CB , wpop ) ;
3785
3786 /* start creating widgets inside the shell */
3787
3788 wrc = XtVaCreateWidget( /* RowColumn to hold all */
3789 MENU , xmRowColumnWidgetClass , wpop ,
3790 XmNpacking , XmPACK_TIGHT ,
3791 XmNorientation , XmVERTICAL ,
3792 XmNtraversalOn , True ,
3793 XmNinitialResourcesPersistent , False ,
3794 NULL ) ;
3795
3796 /* top level label describing what's going on */
3797
3798 if( label != NULL ){
3799 lbuf = (char*)XtMalloc( strlen(label) + 32 ) ;
3800 sprintf( lbuf , "----Choose One----\n%s" , label ) ;
3801 } else {
3802 lbuf = (char*)XtMalloc( 32 ) ;
3803 sprintf( lbuf , "----Choose One----" ) ;
3804 }
3805 xms = XmStringCreateLtoR( lbuf , XmFONTLIST_DEFAULT_TAG ) ;
3806 wlab = XtVaCreateManagedWidget(
3807 MENU , xmLabelWidgetClass , wrc ,
3808 XmNlabelString , xms ,
3809 XmNalignment , XmALIGNMENT_CENTER ,
3810 XmNinitialResourcesPersistent , False ,
3811 NULL ) ;
3812 myXtFree(lbuf) ; XmStringFree(xms) ; LABELIZE(wlab) ;
3813
3814 /* separator, for beauty */
3815
3816 (void) XtVaCreateManagedWidget(
3817 MENU , xmSeparatorWidgetClass , wrc ,
3818 XmNseparatorType , XmSHADOW_ETCHED_IN ,
3819 XmNinitialResourcesPersistent , False ,
3820 NULL ) ;
3821
3822 /* table of strings from which to choose */
3823
3824 xmstr = (XmStringTable) XtMalloc( num_el * sizeof(XmString *) ) ;
3825
3826 /* scan and find max string sizes for element descriptions */
3827
3828 xd = yd = ltop = 1 ;
3829 for( ib=0 ; ib < num_el ; ib++ ){
3830 nel = ELARR_SUBEL(elarr,ib) ;
3831
3832 if( nel == NULL ){ /* should not happen */
3833 strcpy(pbuf,"** NULL file ??") ;
3834 } else {
3835 if( nel->filename != NULL )
3836 MCW_strncpy(pbuf,nel->filename,254) ; /* filename label */
3837 else
3838 strcpy(pbuf,"** NO NAME ??") ; /* should not happen */
3839
3840 /* labels for size of data in file (column length, num of columns) */
3841
3842 sprintf(qbuf,"%d",nel->vec_len) ; ll = strlen(qbuf) ; xd = MAX(xd,ll) ;
3843 sprintf(qbuf,"%d",nel->vec_num) ; ll = strlen(qbuf) ; yd = MAX(yd,ll) ;
3844 }
3845 ll = strlen(pbuf) ; ltop = MAX(ltop,ll) ;
3846 }
3847
3848 /* repeat above loop to actually make the strings, nicely spaced */
3849
3850 for( ib=0 ; ib < num_el ; ib++ ){
3851 nel = ELARR_SUBEL(elarr,ib) ;
3852
3853 if( nel == NULL ){
3854 strcpy(qbuf,"** NULL file ??") ;
3855 } else {
3856 if( nel->filename != NULL )
3857 MCW_strncpy(pbuf,nel->filename,254) ;
3858 else
3859 strcpy(pbuf,"** NO NAME ??") ;
3860
3861 sprintf(qbuf,"%-*s [%*d x %*d]", ltop,pbuf , xd,nel->vec_len, yd,nel->vec_num ) ;
3862 }
3863 xmstr[ib] = XmStringCreateSimple( qbuf ) ;
3864 }
3865
3866 /* this is the scrollable list of filenames the user chooses from */
3867
3868 wlist = XmCreateScrolledList( wrc , MENU , NULL , 0 ) ;
3869
3870 /* set how many items are visible at once, etc */
3871
3872 nvisible = (num_el < list_maxmax ) ? num_el : list_max ;
3873 XtVaSetValues( wlist ,
3874 XmNitems , xmstr ,
3875 XmNitemCount , num_el ,
3876 XmNvisibleItemCount , nvisible ,
3877 XmNtraversalOn , True ,
3878 XmNselectionPolicy , XmBROWSE_SELECT ,
3879 NULL ) ;
3880
3881 /* set initial highlighted selection */
3882
3883 if( init >= 0 && init < num_el ){
3884 XmListSelectPos( wlist , init+1 , False ) ;
3885 if( init+1 > nvisible ) XmListSetBottomPos( wlist , init+1 ) ;
3886 }
3887 XtManageChild(wlist) ;
3888
3889 /* what to do when user actually makes the choice */
3890
3891 XtAddCallback( wlist , XmNdefaultActionCallback , MCW_choose_CB , &cd ) ;
3892
3893 /* who the hell needs help? */
3894
3895 MCW_register_help( wlist , TCV_list_help_1 ) ;
3896 MCW_register_help( wlab , TCV_list_help_1 ) ;
3897
3898 cd.tsarr = (MRI_IMARR *)elarr ; /* cast to image array for fun */
3899 cd.wchoice = wlist ;
3900 cd.av = NULL ;
3901
3902 for( ib=0 ; ib < num_el ; ib++ ) XmStringFree(xmstr[ib]) ;
3903 myXtFree(xmstr) ;
3904
3905 cd.wpop = wpop ; /* data to be passed to pushbutton callback */
3906 cd.wcaller = wpar ;
3907 cd.sel_CB = func ;
3908 cd.sel_cd = func_data ;
3909 cd.ctype = mcwCT_tcsv ;
3910
3911 for( ib=0 ; ib < NUM_TCV_ACT ; ib++ ) TCV_act[ib].data = &cd ;
3912
3913 (void) MCW_action_area( wrc , TCV_act , NUM_TCV_ACT ) ;
3914
3915 RELOCATE(wpar,wpop,5) ; /* 12 Oct 2017 */
3916
3917 XtManageChild( wrc ) ;
3918 XtPopup( wpop , XtGrabNone ) ; RWC_sleep(1);
3919
3920 RWC_visibilize_widget( wpop ) ; /* 09 Nov 1999 */
3921 NORMAL_cursorize( wpop ) ;
3922
3923 EXRETURN ;
3924 }
3925
3926 /*==================================================================================*/
3927
3928 /*-------------------------------------------------------------------------
3929 Get an integer, as an index to an array of strings:
3930 * pops up a shell to let the user make the selection, cycling through
3931 the string array
3932 * allows the user to add to the string array
3933
3934 wpar = parent widget (where to popup)
3935 label = label for chooser
3936 sar = array of initial strings (see 3ddata.h)
3937 [may be changed by the user during operations]
3938 init = index of initial string
3939 func = routine to call when a selection is made:
3940 void func( Widget wpar,XtPointer func_data,MCW_choose_cbs *cbs )
3941 func_data = data to pass to func
3942
3943 The "ival" stored in the MCW_choose_cbs will be the desired result.
3944
3945 This routine is coded in such a way that only one chooser will be
3946 active at a time (per application). This is a deliberate choice.
3947 ---------------------------------------------------------------------------*/
3948
MCW_choose_editable_strlist(Widget wpar,char * label,THD_string_array * sar,int init,gen_func * func,XtPointer func_data)3949 void MCW_choose_editable_strlist( Widget wpar , char *label ,
3950 THD_string_array *sar ,
3951 int init , gen_func *func , XtPointer func_data )
3952 {
3953 int initar[2] ;
3954 initar[0] = init ;
3955 initar[1] = -666 ;
3956
3957 MCW_choose_multi_editable_strlist( wpar , label , mcwCT_single_mode ,
3958 sar , initar , func , func_data ) ;
3959 return ;
3960 }
3961
MCW_choose_multi_editable_strlist(Widget wpar,char * label,int mode,THD_string_array * sar,int * init,gen_func * func,XtPointer func_data)3962 void MCW_choose_multi_editable_strlist( Widget wpar , char *label , int mode ,
3963 THD_string_array *sar ,
3964 int *init ,
3965 gen_func *func , XtPointer func_data )
3966 {
3967 static Widget wpop = NULL , wrc , wrc2 ;
3968 static MCW_choose_data cd ;
3969 Position xx,yy ;
3970 int ib , ll , ltop , num_str ;
3971 Widget wlist = NULL , wlab , wtf , wadd ;
3972 XmStringTable xmstr ;
3973 XmString xms ;
3974 char *lbuf ;
3975 int nvisible ;
3976
3977 ENTRY("MCW_choose_multi_editable_strlist") ;
3978
3979 /** destructor callback **/
3980
3981 if( wpar == NULL ){
3982 if( wpop != NULL ){
3983 XtUnmapWidget( wpop ) ;
3984 XtRemoveCallback( wpop, XmNdestroyCallback, MCW_destroy_chooser_CB, &wpop ) ;
3985 XtDestroyWidget( wpop ) ;
3986 }
3987 wpop = NULL ; EXRETURN ;
3988 }
3989
3990 if( ! XtIsRealized(wpar) ){ /* illegal call */
3991 fprintf(stderr,"\n*** illegal call to MCW_choose_strlist %s\n",
3992 XtName(wpar) ) ;
3993 EXRETURN ;
3994 }
3995
3996 MCW_set_listmax( wpar ) ;
3997
3998 /*--- if popup widget already exists, destroy it ---*/
3999
4000 if( wpop != NULL ){
4001 XtRemoveCallback( wpop, XmNdestroyCallback, MCW_destroy_chooser_CB, &wpop ) ;
4002 XtDestroyWidget( wpop ) ;
4003 }
4004
4005 wlist = NULL ;
4006
4007 /*--- create popup widget ---*/
4008
4009 wpop = XtVaCreatePopupShell( /* Popup Shell */
4010 MENU , xmDialogShellWidgetClass , wpar ,
4011 XmNallowShellResize , True ,
4012 XmNtraversalOn , True ,
4013 XmNinitialResourcesPersistent , False ,
4014 XmNkeyboardFocusPolicy , XmEXPLICIT ,
4015 NULL ) ;
4016
4017 if( MCW_isitmwm(wpar) ){
4018 XtVaSetValues( wpop ,
4019 XmNmwmDecorations , MWM_DECOR_BORDER ,
4020 XmNmwmFunctions , MWM_FUNC_MOVE
4021 | MWM_FUNC_CLOSE ,
4022 NULL ) ;
4023 }
4024
4025 XtAddCallback( wpop , XmNdestroyCallback , MCW_destroy_chooser_CB , &wpop ) ;
4026
4027 XmAddWMProtocolCallback(
4028 wpop ,
4029 XmInternAtom( XtDisplay(wpop) , "WM_DELETE_WINDOW" , False ) ,
4030 MCW_kill_chooser_CB , wpop ) ;
4031
4032 /* RowColumn to hold all */
4033
4034 wrc = XtVaCreateWidget(
4035 MENU , xmRowColumnWidgetClass , wpop ,
4036 XmNpacking , XmPACK_TIGHT ,
4037 XmNorientation , XmVERTICAL ,
4038 XmNtraversalOn , True ,
4039 XmNinitialResourcesPersistent , False ,
4040 NULL ) ;
4041
4042 /* Label at the top */
4043
4044 if( label != NULL ){
4045 lbuf = (char*)XtMalloc( strlen(label) + 32 ) ;
4046 sprintf( lbuf , "----Choose %s----\n%s" ,
4047 (mode == mcwCT_single_mode) ? "One" : "One or More" , label ) ;
4048 } else {
4049 lbuf = (char*)XtMalloc( 32 ) ;
4050 sprintf( lbuf , "----Choose %s----",
4051 (mode == mcwCT_single_mode) ? "One" : "One or More" ) ;
4052 }
4053 xms = XmStringCreateLtoR( lbuf , XmFONTLIST_DEFAULT_TAG ) ;
4054 wlab = XtVaCreateManagedWidget(
4055 MENU , xmLabelWidgetClass , wrc ,
4056 XmNlabelString , xms ,
4057 XmNalignment , XmALIGNMENT_CENTER ,
4058 XmNinitialResourcesPersistent , False ,
4059 NULL ) ;
4060 myXtFree(lbuf) ; XmStringFree(xms) ; LABELIZE(wlab) ;
4061
4062 /* Separator line */
4063
4064 (void) XtVaCreateManagedWidget(
4065 MENU , xmSeparatorWidgetClass , wrc ,
4066 XmNseparatorType , XmSHADOW_ETCHED_IN ,
4067 XmNinitialResourcesPersistent , False ,
4068 NULL ) ;
4069
4070 /* List to choose from */
4071
4072 wlist = XmCreateScrolledList( wrc , MENU , NULL , 0 ) ;
4073 XtVaSetValues( wlist ,
4074 XmNtraversalOn , True ,
4075 XmNselectionPolicy , (mode == mcwCT_single_mode)
4076 ? XmBROWSE_SELECT : XmMULTIPLE_SELECT ,
4077 NULL ) ;
4078
4079 num_str = SARR_NUM(sar) ;
4080
4081 if( num_str > 0 ){
4082 xmstr = (XmStringTable) XtMalloc( num_str * sizeof(XmString *) ) ;
4083 for( ib=0 ; ib < num_str ; ib++ )
4084 xmstr[ib] = XmStringCreateSimple( SARR_STRING(sar,ib) ) ;
4085
4086 nvisible = (num_str < list_maxmax ) ? num_str : list_max ;
4087 XtVaSetValues( wlist ,
4088 XmNitems , xmstr ,
4089 XmNitemCount , num_str ,
4090 XmNvisibleItemCount , nvisible ,
4091 NULL ) ;
4092
4093 if( init != NULL ){
4094 for( ib=0 ; init[ib] >= 0 && init[ib] < num_str ; ib++ )
4095 XmListSelectPos( wlist , init[ib]+1 , False ) ;
4096 if( ib > 0 && init[ib-1] > nvisible )
4097 XmListSetBottomPos( wlist , init[ib-1]+1 ) ;
4098 }
4099
4100 for( ib=0 ; ib < num_str ; ib++ ) XmStringFree(xmstr[ib]) ;
4101 myXtFree(xmstr) ;
4102 }
4103
4104 XtManageChild(wlist) ;
4105
4106 /* Some help? */
4107
4108 if( mode == mcwCT_multi_mode ){
4109 MCW_register_help( wlist , OVC_list_help_2 ) ;
4110 MCW_register_help( wlab , OVC_list_help_2 ) ;
4111 } else {
4112 MCW_register_help( wlist , OVC_list_help_1 ) ;
4113 MCW_register_help( wlab , OVC_list_help_1 ) ;
4114 XtAddCallback( wlist , XmNdefaultActionCallback , MCW_choose_CB , &cd ) ;
4115 }
4116
4117 cd.wchoice = wlist ;
4118 cd.av = NULL ; /* this is NULL --> will use the list widget */
4119
4120 cd.wpop = wpop ; /* data to be passed to pushbutton callback */
4121 cd.wcaller = wpar ;
4122 cd.sel_CB = func ;
4123 cd.sel_cd = func_data ;
4124 cd.ctype = mcwCT_integer ;
4125 cd.sar = sar ;
4126
4127 /* action buttons */
4128
4129 for( ib=0 ; ib < NUM_OVC_ACT ; ib++ ) OVC_act[ib].data = &cd ;
4130
4131 (void) MCW_action_area( wrc , OVC_act , NUM_OVC_ACT ) ;
4132
4133 /* choosing mode, for multiple selections */
4134
4135 if( mode == mcwCT_multi_mode ){
4136 MCW_arrowval *av ;
4137
4138 (void) XtVaCreateManagedWidget(
4139 MENU , xmSeparatorWidgetClass , wrc ,
4140 XmNseparatorType , XmSHADOW_ETCHED_IN ,
4141 XmNinitialResourcesPersistent , False ,
4142 NULL ) ;
4143
4144 av = new_MCW_optmenu( wrc , "Selection Mode" , 0,NUM_LIST_MODES-1,0,0 ,
4145 MCW_list_mode_CB , wlist ,
4146 MCW_av_substring_CB , list_modes ) ;
4147
4148 MCW_reghelp_children( av->wrowcol , OVC_list_help_2 ) ;
4149 MCW_reghint_children( av->wrowcol , "How list selections work" ) ;
4150 }
4151
4152 /* Separator line */
4153
4154 (void) XtVaCreateManagedWidget(
4155 MENU , xmSeparatorWidgetClass , wrc ,
4156 XmNseparatorType , XmSINGLE_LINE ,
4157 XmNinitialResourcesPersistent , False ,
4158 NULL ) ;
4159
4160 /*-- Stuff to string array --*/
4161
4162 wrc2 = XtVaCreateWidget( /* Rowcol for stuff */
4163 MENU , xmRowColumnWidgetClass , wrc ,
4164 XmNpacking , XmPACK_TIGHT ,
4165 XmNorientation , XmHORIZONTAL ,
4166 XmNtraversalOn , True ,
4167 XmNinitialResourcesPersistent , False ,
4168 NULL ) ;
4169
4170 wtf = XtVaCreateManagedWidget( /* String to add */
4171 MENU , TEXT_CLASS , wrc2 ,
4172
4173 XmNcolumns , 24 ,
4174 XmNeditable , True ,
4175 XmNmaxLength , 128 ,
4176 XmNresizeWidth , False ,
4177
4178 XmNmarginHeight , 1 ,
4179 XmNmarginWidth , 1 ,
4180
4181 XmNcursorPositionVisible , True ,
4182 XmNblinkRate , 0 ,
4183 XmNautoShowCursorPosition , True ,
4184
4185 XmNinitialResourcesPersistent , False ,
4186 XmNtraversalOn , True ,
4187 NULL ) ;
4188
4189 xms = XmStringCreateLtoR( "Add" , XmFONTLIST_DEFAULT_TAG ) ;
4190
4191 wadd = XtVaCreateManagedWidget( /* Button to add it */
4192 MENU , xmPushButtonWidgetClass , wrc2 ,
4193 XmNlabelString , xms ,
4194 XmNtraversalOn , True ,
4195 XmNinitialResourcesPersistent , False ,
4196 NULL ) ;
4197
4198 XmStringFree(xms) ;
4199
4200 MCW_set_widget_bg( wadd , MCW_hotcolor(wadd) , 0 ) ;
4201
4202 XtAddCallback( wadd, XmNactivateCallback, MCW_stradd_CB, &cd ) ;
4203 XtAddCallback( wtf , XmNactivateCallback, MCW_stradd_CB, &cd ) ;
4204 cd.wtf = wtf ;
4205
4206 MCW_reghelp_children( wrc2 , "Type an entry and press Add\n"
4207 "or hit Enter to make a new\n"
4208 "entry in the chooser list." ) ;
4209
4210 MCW_reghint_children( wrc2 , "Enter new item into chooser list" ) ;
4211
4212 XtManageChild( wrc2 ) ;
4213
4214 /* make it appear, like magic! */
4215
4216 RELOCATE(wpar,wpop,5) ; /* 12 Oct 2017 */
4217
4218 XtManageChild( wrc ) ;
4219 XtPopup( wpop , XtGrabNone ) ; RWC_sleep(1);
4220
4221 RWC_visibilize_widget( wpop ) ; /* 09 Nov 1999 */
4222 NORMAL_cursorize( wpop ) ;
4223
4224 EXRETURN ;
4225 }
4226
4227 /*--------------------------------------------------------------------------*/
4228
MCW_stradd_CB(Widget w,XtPointer client_data,XtPointer call_data)4229 void MCW_stradd_CB( Widget w, XtPointer client_data, XtPointer call_data )
4230 {
4231 MCW_choose_data *cd = (MCW_choose_data *) client_data ;
4232 char *nstr = TEXT_GET( cd->wtf ) ;
4233 int id , nvisible , num_str ;
4234 XmString xms ;
4235
4236 ENTRY("MCW_stradd_CB") ;
4237
4238 if( nstr == NULL || strlen(nstr) == 0 ){
4239 myXtFree(nstr); XBell(XtDisplay(w),100); EXRETURN;
4240 }
4241
4242 /* see if new string is already in the list */
4243
4244 for( id=0 ; id < SARR_NUM(cd->sar) ; id++ )
4245 if( strcmp(nstr,SARR_STRING(cd->sar,id)) == 0 ) break ;
4246
4247 if( id < SARR_NUM(cd->sar) ){ /* found it, so just jump to it in the list */
4248
4249 XmListSetBottomPos( cd->wchoice , id+1 ) ; /* put on bottom */
4250 XmListSelectPos( cd->wchoice , id+1 , False ) ; /* select it */
4251
4252 } else { /* is a new string, so add it to the list */
4253
4254 ADDTO_SARR( cd->sar , nstr ) ; /* add to internal list */
4255
4256 xms = XmStringCreateSimple( nstr ) ;
4257 XmListAddItem( cd->wchoice , xms , 0 ) ; /* add to List widget */
4258 XmStringFree(xms) ;
4259
4260 num_str = SARR_NUM(cd->sar) ;
4261 nvisible = (num_str < list_maxmax) ? num_str : list_max ;
4262 XtVaSetValues( cd->wchoice ,
4263 XmNvisibleItemCount , nvisible ,
4264 NULL ) ;
4265
4266 XmListSetBottomPos( cd->wchoice , 0 ) ; /* make sure it is visible */
4267 XmListSelectPos( cd->wchoice , 0 , False ) ; /* select it */
4268 }
4269
4270 myXtFree(nstr) ; EXRETURN ;
4271 }
4272
4273 /*--------------------------------------------------------------------------*/
4274
4275 #define LIST_DBCLICK_UNKNOWN -1
4276 #define LIST_DBCLICK_APPLY 1
4277 #define LIST_DBCLICK_DONE 2
4278
MCW_choose_CB(Widget w,XtPointer client_data,XtPointer call_data)4279 void MCW_choose_CB( Widget w , XtPointer client_data , XtPointer call_data )
4280 {
4281 MCW_choose_data *cd = (MCW_choose_data *) client_data ;
4282 char *wname = XtName(w) ;
4283 XmAnyCallbackStruct *icbs = (XmAnyCallbackStruct *) call_data ;
4284
4285 static MCW_choose_cbs cbs ; /* to be passed back to user */
4286 static int list_dbclick_use = LIST_DBCLICK_UNKNOWN ;
4287 RwcBoolean clear ;
4288 XEvent *cbev = (icbs != NULL) ? icbs->event : NULL ; /* 03 Jun 2009 */
4289
4290 ENTRY("MCW_choose_CB") ;
4291
4292 /*--- set up what to do for list double clicks ---*/
4293
4294 if( list_dbclick_use == LIST_DBCLICK_UNKNOWN ){
4295 #if 0
4296 char *xdef = XGetDefault( XtDisplay(w) , "AFNI" , "chooser_doubleclick" ) ;
4297 #else
4298 char *xdef = RWC_getname( XtDisplay(w) , "chooser_doubleclick" ) ;
4299 #endif
4300 if( xdef != NULL && strcasecmp(xdef,OVC_done_label) != 0 )
4301 list_dbclick_use = LIST_DBCLICK_DONE ;
4302 else
4303 list_dbclick_use = LIST_DBCLICK_APPLY ;
4304 }
4305
4306 /*--- branch on type of chooser that called this ---*/
4307
4308 clear = (strcmp(wname,OVC_clear_label) == 0) ;
4309
4310 if( clear && cd->ctype != mcwCT_string ){ /* bad */
4311 XBell( XtDisplay(cd->wpop) , 100 ) ;
4312 RWC_XtPopdown( cd->wpop ) ;
4313 EXRETURN ;
4314 }
4315
4316 switch( cd->ctype ){
4317
4318 default: /* error! */
4319 XBell( XtDisplay(w) , 100 ) ;
4320 fprintf(stderr,
4321 "\n*** unknown choose type=%d from %s\n", cd->ctype, wname ) ;
4322 EXRETURN ;
4323
4324 /*.....................*/
4325
4326 case mcwCT_vector:{ /* vector chooser [19 Mar 2004] */
4327 RwcBoolean done,call ;
4328 int iv ; float *vec ;
4329 MCW_arrowval **aav = (MCW_arrowval **)cd->av ;
4330
4331 done = strcmp(wname,OVC_apply_label) != 0 ;
4332 call = strcmp(wname,OVC_quit_label) != 0 ;
4333
4334 if( done ) RWC_XtPopdown( cd->wpop ) ;
4335
4336 if( call && cd->sel_CB != NULL ){
4337 cbs.reason = mcwCR_vector ; /* set structure for call to user */
4338 cbs.event = cbev ;
4339 cbs.ival = cd->nvec ;
4340 vec = (float *)malloc(sizeof(float)*cd->nvec) ;
4341 cbs.cval = (char *)vec ;
4342 for( iv=0 ; iv < cd->nvec ; iv++ ) vec[iv] = aav[iv]->fval ;
4343
4344 if( !done ) MCW_invert_widget(w) ; /* flash */
4345 #if 0
4346 cd->sel_CB( cd->wcaller , cd->sel_cd , &cbs ) ; /* call user */
4347 #else
4348 AFNI_CALL_VOID_3ARG( cd->sel_CB ,
4349 Widget , cd->wcaller ,
4350 XtPointer , cd->sel_cd ,
4351 MCW_choose_cbs * , &cbs ) ;
4352 #endif
4353 free((void *)vec) ; cbs.cval = NULL ;
4354 if( !done ) MCW_invert_widget(w) ; /* flash */
4355 }
4356 EXRETURN ;
4357 }
4358
4359 /*.....................*/
4360
4361 case mcwCT_ovcolor:{ /* color chooser */
4362 RwcBoolean done , call ;
4363
4364 done = strcmp(wname,OVC_apply_label) != 0 ;
4365 call = strcmp(wname,OVC_quit_label) != 0 ;
4366
4367 if( done ) RWC_XtPopdown( cd->wpop ) ;
4368
4369 if( call && cd->sel_CB != NULL ){
4370 cbs.reason = mcwCR_ovcolor ; /* set structure for call to user */
4371 cbs.event = cbev ;
4372 cbs.ival = cd->av->ival ;
4373
4374 if( !done ) MCW_invert_widget(w) ; /* flash */
4375 #if 0
4376 cd->sel_CB( cd->wcaller , cd->sel_cd , &cbs ) ; /* call user */
4377 #else
4378 AFNI_CALL_VOID_3ARG( cd->sel_CB ,
4379 Widget , cd->wcaller ,
4380 XtPointer , cd->sel_cd ,
4381 MCW_choose_cbs * , &cbs ) ;
4382 #endif
4383 if( !done ) MCW_invert_widget(w) ; /* flash */
4384 }
4385 EXRETURN ;
4386 }
4387
4388 /*.....................*/
4389
4390 case mcwCT_integer:{ /* integer chooser */
4391 RwcBoolean done , call , flash ;
4392
4393 done = strcmp(wname,OVC_apply_label) != 0 ; /* done unless just "Apply" */
4394 flash = ! done ; /* flash if not done */
4395 call = strcmp(wname,OVC_quit_label) != 0 ; /* call unless just "Quit" */
4396 if( w == cd->wchoice ){ /* Double click in List */
4397 done = (list_dbclick_use == LIST_DBCLICK_DONE) ;
4398 flash = False ;
4399 call = True ;
4400 }
4401
4402 if( done ) RWC_XtPopdown( cd->wpop ) ;
4403
4404 if( call && cd->sel_CB != NULL ){
4405 int pos_count=0 , *pos_list=NULL , ib ;
4406 RwcBoolean any ;
4407
4408 cbs.reason = mcwCR_integer ; /* set structure for call to user */
4409 cbs.event = cbev ;
4410
4411 if( cd->av != NULL ){ /* chooser was an arrowval */
4412 cbs.ival = cd->av->ival ;
4413 cbs.fval = cd->av->fval ; /* 21 Jan 1997 */
4414 cbs.nilist = 1 ;
4415 cbs.ilist = &(cbs.ival) ;
4416
4417 } else { /* chooser was a List widget */
4418 any = XmListGetSelectedPos( cd->wchoice, &pos_list, &pos_count ) ;
4419 if( any ){
4420 for( ib=0 ; ib < pos_count ; ib++ ) /* List indexes */
4421 pos_list[ib]-- ; /* start at 1. */
4422
4423 cbs.ival = pos_list[0] ; /* holds the first choice */
4424 cbs.fval = cbs.ival ; /* 21 Jan 1997 */
4425 cbs.nilist = pos_count ; /* number of choices */
4426 cbs.ilist = pos_list ; /* holds all choices */
4427 } else {
4428 EXRETURN ; /* no choice made */
4429 }
4430 }
4431
4432 if( flash ) MCW_invert_widget(w) ; /* flash */
4433 #if 0
4434 cd->sel_CB( cd->wcaller , cd->sel_cd , &cbs ) ; /* call user */
4435 #else
4436 AFNI_CALL_VOID_3ARG( cd->sel_CB ,
4437 Widget , cd->wcaller ,
4438 XtPointer , cd->sel_cd ,
4439 MCW_choose_cbs * , &cbs ) ;
4440 #endif
4441 if( flash ) MCW_invert_widget(w) ; /* flash */
4442
4443 myXtFree(pos_list) ;
4444 }
4445 EXRETURN ;
4446 }
4447
4448 /*.....................*/
4449
4450 case mcwCT_string:{ /* string chooser */
4451 RwcBoolean done , call , istextf ;
4452
4453 /* special action: "Clear" button */
4454
4455 if( clear ){ TEXT_SET( cd->wchoice , "" ) ; EXRETURN ; }
4456
4457 /* find out if called by the text field itself */
4458
4459 istextf = XtIsSubclass( w , TEXT_CLASS ) ;
4460
4461 if( istextf == False ){ /* check button names */
4462 done = strcmp(wname,OVC_apply_label) != 0 ; /* to decide upon */
4463 call = strcmp(wname,OVC_quit_label) != 0 ; /* correct actions */
4464 } else {
4465 done = False ; /* input from textfield == press "Apply" */
4466 call = True ;
4467 }
4468
4469 if( done ) RWC_XtPopdown( cd->wpop ) ;
4470
4471 if( call && cd->sel_CB != NULL ){
4472 cbs.reason = mcwCR_string ; /* set structure for call to user */
4473 cbs.event = cbev ;
4474 cbs.cval = TEXT_GET( cd->wchoice ) ;
4475
4476 if( !done ) MCW_invert_widget(w) ; /* flash */
4477 #if 0
4478 cd->sel_CB( cd->wcaller , cd->sel_cd , &cbs ) ; /* call user */
4479 #else
4480 AFNI_CALL_VOID_3ARG( cd->sel_CB ,
4481 Widget , cd->wcaller ,
4482 XtPointer , cd->sel_cd ,
4483 MCW_choose_cbs * , &cbs ) ;
4484 #endif
4485 if( !done ) MCW_invert_widget(w) ; /* flash */
4486
4487 myXtFree( cbs.cval ) ; cbs.cval = NULL ;
4488 }
4489 EXRETURN ;
4490 }
4491
4492 /*.....................*/
4493
4494 case mcwCT_timeseries:{ /* timeseries chooser */
4495 RwcBoolean done , call , flash , any , plot ;
4496 int pos_count , *pos_list ;
4497
4498 #ifdef AFNI_DEBUG
4499 printf("MCW_choose_CB: timeseries choice made\n") ;
4500 #endif
4501
4502 if( w == cd->wchoice ){ /* choice is from double click in List widget */
4503 done = (list_dbclick_use == LIST_DBCLICK_DONE) ;
4504 flash = False ;
4505 plot = False ;
4506 call = True ;
4507 } else { /* choice is from control buttons */
4508
4509 done = (strcmp(wname,TSC_quit_label) == 0) || /* are we done with */
4510 (strcmp(wname,TSC_done_label) == 0) ; /* this popup widget? */
4511
4512 flash = ! done ; /* flash if not done */
4513
4514 call = (strcmp(wname,TSC_apply_label) == 0) || /* do we call the */
4515 (strcmp(wname,TSC_done_label) == 0) ; /* user's routine? */
4516
4517 plot = (strcmp(wname,TSC_plot_label) == 0) ; /* do we plot a graph? */
4518 }
4519
4520 #ifdef BBOX_DEBUG
4521 printf("MCW_choose_CB: done=%d call=%d plot=%d flash=%d\n",
4522 (int)done , (int)call , (int)plot , (int)flash ) ;
4523 #endif
4524
4525 if( done ) RWC_XtPopdown( cd->wpop ) ;
4526
4527 if( call || plot ){ /* must find out what is selected */
4528 int pos_count , *pos_list , first ;
4529 MRI_IMAGE *fim ;
4530
4531 #ifdef BBOX_DEBUG
4532 printf("MCW_choose_CB: querying list for choice\n") ;
4533 #endif
4534
4535 any = XmListGetSelectedPos( cd->wchoice , &pos_list , &pos_count ) ;
4536
4537 #ifdef BBOX_DEBUG
4538 printf("MCW_choose_CB: queryed list for choice\n") ;
4539 #endif
4540
4541 if( any ){
4542 first = pos_list[0] - 1 ; /* XmList index starts at 1 */
4543 fim = IMARR_SUBIMAGE(cd->tsarr,first) ;
4544 myXtFree(pos_list) ;
4545 } else { /* no choice made --> nothing to do! */
4546 if( plot ) XBell( XtDisplay(w) , 100 ) ;
4547 EXRETURN ;
4548 }
4549
4550 #ifdef BBOX_DEBUG
4551 printf("MCW_choose_CB: choice index = %d\n",first) ;
4552 #endif
4553
4554 if( call && cd->sel_CB != NULL ){
4555 cbs.reason = mcwCR_timeseries ; /* set structure for call to user */
4556 cbs.event = cbev ;
4557 cbs.ival = first ;
4558 cbs.imval = fim ;
4559
4560 #ifdef BBOX_DEBUG
4561 printf("MCW_choose_CB: calling user supplied routine\n") ;
4562 #endif
4563
4564 if( flash ) MCW_invert_widget(w) ; /* flash */
4565 #if 0
4566 cd->sel_CB( cd->wcaller , cd->sel_cd , &cbs ) ; /* call user */
4567 #else
4568 AFNI_CALL_VOID_3ARG( cd->sel_CB ,
4569 Widget , cd->wcaller ,
4570 XtPointer , cd->sel_cd ,
4571 MCW_choose_cbs * , &cbs ) ;
4572 #endif
4573 if( flash ) MCW_invert_widget(w) ; /* flash */
4574 EXRETURN ;
4575 }
4576
4577 if( plot ){
4578
4579 #ifdef BBOX_DEBUG
4580 printf("MCW_choose_CB: plotting selected timeseries\n") ;
4581 #endif
4582
4583 /*-- 17 Aug 1998: plotting code (at last!) --*/
4584
4585 #ifdef DONT_USE_COXPLOT
4586 (void) MCW_popup_message( w , "Plot not yet\nimplemented." ,
4587 MCW_USER_KILL | MCW_TIMER_KILL ) ;
4588 EXRETURN ;
4589 #else
4590 if( fim->kind != MRI_float ){
4591 (void) MCW_popup_message( w , "Can't plot\nnon-float data!" ,
4592 MCW_USER_KILL | MCW_TIMER_KILL ) ;
4593 EXRETURN ;
4594 } else {
4595 float **yar , *far = MRI_FLOAT_PTR(fim) ;
4596 char **nar=NULL ;
4597 int jj ;
4598
4599 #undef USE_NAR /* use labels for each column? (just to test the code) */
4600
4601 yar = (float **) malloc( sizeof(float *) * fim->ny ) ;
4602 for( jj=0 ; jj < fim->ny ; jj++ )
4603 yar[jj] = far + jj * fim->nx ;
4604
4605 #ifdef USE_NAR
4606 nar = (char **) malloc( sizeof(char * ) * fim->ny ) ;
4607 for( jj=0 ; jj < fim->ny ; jj++ ){
4608 nar[jj] = (char *) malloc( sizeof(char) * 32 ) ;
4609 sprintf(nar[jj],"column %d",jj+1) ;
4610 }
4611 #endif
4612 X11_SET_NEW_PLOT ;
4613 plot_ts_lab( XtDisplay(w) ,
4614 fim->nx , NULL , fim->ny , yar ,
4615 "index" , NULL , fim->name , nar , NULL ) ;
4616
4617 if( nar != NULL ){
4618 for( jj=0 ; jj < fim->ny ; jj++ ) free(nar[jj]) ;
4619 free(nar) ;
4620 }
4621 free(yar) ;
4622 EXRETURN ;
4623 }
4624 #endif /* DONT_USE_COXPLOT */
4625 }
4626
4627 }
4628 EXRETURN ;
4629 }
4630
4631 /*.....................*/
4632
4633 case mcwCT_tcsv:{ /* *.[tc]sv chooser [19 Jun 2020] */
4634 RwcBoolean done=FALSE , call=FALSE , flash=FALSE , any=FALSE , view=FALSE ;
4635
4636 #ifdef AFNI_DEBUG
4637 printf("MCW_choose_CB: tcsv choice made\n") ;
4638 #endif
4639
4640 if( w == cd->wchoice ){ /* choice is from double click in List widget */
4641 done = (list_dbclick_use == LIST_DBCLICK_DONE) ;
4642 flash = False ;
4643 view = False ;
4644 call = True ;
4645 } else { /* choice is from control buttons */
4646
4647 done = (strcmp(wname,TCV_quit_label) == 0) || /* are we done with */
4648 (strcmp(wname,TCV_done_label) == 0) ; /* this popup widget? */
4649
4650 flash = ! done ; /* flash if not done */
4651
4652 call = (strcmp(wname,TCV_apply_label) == 0) || /* do we call the */
4653 (strcmp(wname,TCV_done_label) == 0) ; /* user's routine? */
4654
4655 view = (strcmp(wname,TCV_view_label) == 0) ; /* do we view data? */
4656 }
4657
4658 #ifdef BBOX_DEBUG
4659 printf("MCW_choose_CB: done=%d call=%d view=%d flash=%d\n",
4660 (int)done , (int)call , (int)view , (int)flash ) ;
4661 #endif
4662
4663 if( done ) RWC_XtPopdown( cd->wpop ) ;
4664
4665 if( call || view ){ /* must find out what item is selected */
4666 int pos_count=0 , *pos_list=NULL , first=0 ;
4667 NI_element *nel=NULL ; NI_ELARR *elarr = (NI_ELARR *)cd->tsarr ;
4668
4669 #ifdef BBOX_DEBUG
4670 printf("MCW_choose_CB: querying list for choice\n") ;
4671 #endif
4672
4673 any = XmListGetSelectedPos( cd->wchoice , &pos_list , &pos_count ) ;
4674
4675 #ifdef BBOX_DEBUG
4676 printf("MCW_choose_CB: queryed list for choice\n") ;
4677 #endif
4678
4679 if( any && pos_list != NULL ){
4680 first = pos_list[0] - 1 ; /* XmList index starts at 1 */
4681 nel = ELARR_SUBEL(elarr,first) ;
4682 myXtFree(pos_list) ;
4683 } else { /* no choice made --> nothing to do! */
4684 if( view ) XBell( XtDisplay(w) , 100 ) ;
4685 EXRETURN ;
4686 }
4687
4688 #ifdef BBOX_DEBUG
4689 printf("MCW_choose_CB: choice index = %d\n",first) ;
4690 #endif
4691
4692 /** call the user function to do something with the choice **/
4693
4694 if( call && cd->sel_CB != NULL ){
4695 cbs.reason = mcwCR_tcsv ; /* set structure for call to user */
4696 cbs.event = cbev ;
4697 cbs.ival = first ;
4698 cbs.imval = (MRI_IMAGE *)nel ;
4699
4700 #ifdef BBOX_DEBUG
4701 printf("MCW_choose_CB: calling user supplied routine\n") ;
4702 #endif
4703
4704 if( flash ) MCW_invert_widget(w) ; /* flash */
4705 #if 0
4706 cd->sel_CB( cd->wcaller , cd->sel_cd , &cbs ) ; /* call user */
4707 #else
4708 AFNI_CALL_VOID_3ARG( cd->sel_CB ,
4709 Widget , cd->wcaller ,
4710 XtPointer , cd->sel_cd ,
4711 MCW_choose_cbs * , &cbs ) ;
4712 #endif
4713 if( flash ) MCW_invert_widget(w) ; /* flash */
4714 EXRETURN ;
4715 }
4716
4717 /** popup a text viewer for the first few lines of the file **/
4718
4719 #define NVIEW_TCSV 4
4720 if( view && nel != NULL ){
4721 int ii , jj , qq , nview ;
4722 char *qpt,*zpt , *vstring ;
4723
4724 nview = AFNI_numenv("AFNI_TCSV_VIEWNUM") ;
4725 if( nview < 1 ) nview = NVIEW_TCSV ;
4726 vstring = NI_preview_string( nel , nview , NULL ) ;
4727
4728 /* popup the "view" window */
4729 if( vstring != NULL ){
4730 (void) MCW_popup_message( w , vstring , MCW_USER_KILL ) ;
4731 free( vstring ) ;
4732 }
4733 }
4734 }
4735 EXRETURN ;
4736 }
4737
4738 } /* end of switch on ctype */
4739
4740 EXRETURN ; /* unreachable */
4741 }
4742
4743 /*----------------------------------------------------------------------------*/
4744 /*----------------------------------------------------------------------------*/
4745
4746 #define MSTUF_tofree(ic) \
4747 ( (ic) == MSTUF_INT || (ic) == MSTUF_STRLIST || (ic) == MSTUF_YESNO )
4748
4749 static int CS_nsav = 0 ;
4750 static void ** CS_sav = NULL ;
4751 static int * CS_scod = NULL ;
4752
4753 static gen_func *CS_func = NULL ;
4754 static XtPointer CS_func_data = NULL ;
4755 static Widget CS_wpop = NULL ;
4756 static Widget CS_wpar = NULL ;
4757
4758 #define NUM_CSO_ACT 3
4759 static MCW_action_item CSO_act[] = {
4760 { OVC_quit_label , MCW_stuff_CB, NULL, OVC_quit_help ,"Close window" ,0 },
4761 { OVC_apply_label, MCW_stuff_CB, NULL, OVC_apply_help,"Apply choice and keep window" ,0 },
4762 { OVC_done_label , MCW_stuff_CB, NULL, OVC_done_help ,"Apply choice and close window",1 },
4763 } ;
4764
4765 /*----------------------------------------------------------------------------*/
4766
MCW_stuff_CB(Widget w,XtPointer client_data,XtPointer call_data)4767 void MCW_stuff_CB( Widget w , XtPointer client_data , XtPointer call_data )
4768 {
4769 char *wname = XtName(w) ;
4770 XmAnyCallbackStruct *icbs = (XmAnyCallbackStruct *)call_data ;
4771 XEvent *cbev = (icbs != NULL) ? icbs->event : NULL ;
4772 void **outval ; int iss, done,call ;
4773
4774 ENTRY("MCW_stuff_CB") ;
4775
4776 if( CS_wpop == NULL || CS_nsav == 0 ) EXRETURN ; /* should not happen */
4777
4778 done = (strcmp(wname,OVC_apply_label) != 0) ;
4779 call = (strcmp(wname,OVC_quit_label) != 0) ;
4780 if( done ) RWC_XtPopdown(CS_wpop) ;
4781 if( !call ) EXRETURN ;
4782
4783 outval = (void **)calloc(CS_nsav,sizeof(void *)) ;
4784
4785 for( iss=0 ; iss < CS_nsav ; iss++ ){
4786 switch( CS_scod[iss] ){
4787 case MSTUF_INT:{
4788 MCW_arrowval *av = (MCW_arrowval *)CS_sav[iss] ;
4789 outval[iss] = (void *)(intptr_t)(av->ival) ;
4790 }
4791 break ;
4792
4793 case MSTUF_STRING:{
4794 Widget wtf = (Widget)CS_sav[iss] ;
4795 outval[iss] = (void *)TEXT_GET(wtf) ;
4796 }
4797 break ;
4798
4799 case MSTUF_STRLIST:{
4800 MCW_arrowval *av = (MCW_arrowval *)CS_sav[iss] ;
4801 outval[iss] = (void *)(av->sval) ;
4802 }
4803
4804 case MSTUF_YESNO:{
4805 MCW_arrowval *av = (MCW_arrowval *)CS_sav[iss] ;
4806 outval[iss] = (void *)(av->sval) ;
4807 }
4808 break ;
4809 }
4810 }
4811
4812 AFNI_CALL_VOID_4ARG( CS_func ,
4813 Widget , CS_wpar ,
4814 XtPointer , CS_func_data ,
4815 int , CS_nsav ,
4816 void ** , outval ) ;
4817
4818 free(outval) ; EXRETURN ;
4819 }
4820
4821 /*----------------------------------------------------------------------------*/
4822 /* Call this multi-item chooser like
4823 MCW_choose_stuff( parent_widget , "Top Label" ,
4824 call_func , call_func_data ,
4825 ITEM ,
4826 ITEM , ...
4827 MSTUF_END ) ;
4828 where ITEM is one of the following lists specifying something to choose:
4829 MSTUF_INT , label , bot , top , init
4830 MSTUF_STRING , label
4831 MSTUF_STRLIST, label, nstring , init_index , string_array
4832 MSTUF_YESNO , label [like STRLIST with {"No","Yes"} as input array]
4833
4834 The call_func is called like so
4835
4836 void call_func( Widget wpar, XtPointer call_func_data, int nval, void **val );
4837
4838 This function must know what the types to which to cast each val[] result.
4839 *//*--------------------------------------------------------------------------*/
4840
MCW_choose_stuff(Widget wpar,char * mainlabel,gen_func * func,XtPointer func_data,...)4841 void MCW_choose_stuff( Widget wpar , char *mainlabel ,
4842 gen_func *func , XtPointer func_data , ... )
4843 {
4844 Widget wrc ;
4845 va_list vararg_ptr ;
4846 Position xx,yy ;
4847 int iss , scode ;
4848
4849 ENTRY("MCW_choose_stuff") ;
4850
4851 /** destructor callback **/
4852
4853 if( wpar == NULL ){
4854 if( CS_wpop != NULL ){
4855 XtUnmapWidget( CS_wpop ) ;
4856 XtRemoveCallback( CS_wpop, XmNdestroyCallback, MCW_destroy_chooser_CB, &CS_wpop ) ;
4857 XtDestroyWidget( CS_wpop ) ;
4858 }
4859 CS_wpop = NULL ; CS_wpar = NULL ; EXRETURN ;
4860 }
4861
4862 if( ! XtIsRealized(wpar) ){ /* illegal call */
4863 fprintf(stderr,"\n*** illegal call to MCW_choose_stuff: %s\n",XtName(wpar)) ;
4864 EXRETURN ;
4865 }
4866
4867 /*--- if popup widget already exists, destroy it ---*/
4868
4869 if( CS_wpop != NULL ){
4870 XtRemoveCallback( CS_wpop, XmNdestroyCallback, MCW_destroy_chooser_CB, &CS_wpop ) ;
4871 XtDestroyWidget( CS_wpop ) ;
4872 }
4873 if( CS_nsav > 0 ){
4874 for( iss=0 ; iss < CS_nsav ; iss++ ){
4875 if( MSTUF_tofree(CS_scod[iss]) ) myXtFree(CS_sav[iss]) ;
4876 }
4877 free(CS_sav) ; free(CS_scod) ;
4878 }
4879 CS_sav = NULL ; CS_scod = NULL ; CS_nsav = 0 ;
4880
4881 /*--- create popup widget ---*/
4882
4883 CS_wpop = XtVaCreatePopupShell( /* Popup Shell */
4884 MENU , xmDialogShellWidgetClass , wpar ,
4885 XmNtraversalOn , True ,
4886 XmNinitialResourcesPersistent , False ,
4887 XmNkeyboardFocusPolicy , XmEXPLICIT ,
4888 NULL ) ;
4889
4890 CS_wpar = wpar ; CS_func = func ; CS_func_data = func_data ;
4891
4892 if( MCW_isitmwm(CS_wpar) ){
4893 XtVaSetValues( CS_wpop ,
4894 XmNmwmDecorations , MWM_DECOR_BORDER ,
4895 XmNmwmFunctions , MWM_FUNC_MOVE ,
4896 NULL ) ;
4897 }
4898
4899 XtAddCallback( CS_wpop, XmNdestroyCallback, MCW_destroy_chooser_CB, &CS_wpop ) ;
4900
4901 XmAddWMProtocolCallback(
4902 CS_wpop ,
4903 XmInternAtom( XtDisplay(CS_wpop) , "WM_DELETE_WINDOW" , False ) ,
4904 MCW_kill_chooser_CB , CS_wpop ) ;
4905
4906 wrc = XtVaCreateWidget( /* RowColumn to hold all */
4907 MENU , xmRowColumnWidgetClass , CS_wpop ,
4908 XmNpacking , XmPACK_TIGHT ,
4909 XmNorientation , XmVERTICAL ,
4910 XmNtraversalOn , True ,
4911 XmNinitialResourcesPersistent , False ,
4912 NULL ) ;
4913
4914 if( mainlabel != NULL && *mainlabel != '\0' ){
4915 Widget wlab ;
4916 wlab = XtVaCreateManagedWidget(
4917 MENU , xmLabelWidgetClass , wrc ,
4918 LABEL_ARG(mainlabel) ,
4919 XmNinitialResourcesPersistent , False ,
4920 NULL ) ;
4921 LABELIZE(wlab) ;
4922 (void) XtVaCreateManagedWidget(
4923 MENU , xmSeparatorWidgetClass , wrc ,
4924 XmNseparatorType , XmSHADOW_ETCHED_IN ,
4925 XmNinitialResourcesPersistent , False ,
4926 NULL ) ;
4927 }
4928
4929 /* now loop over variable arguments to create selectors */
4930
4931 va_start( vararg_ptr , func_data ) ;
4932
4933 do{
4934 scode = va_arg( vararg_ptr , int ) ; /** get next arg **/
4935 if( scode <= 0 ) break ; /** no more args **/
4936
4937 switch( scode ){
4938
4939 default: ERROR_message("Illegal code %d in MCW_choose_stuff()",scode) ;
4940 EXRETURN ;
4941
4942 case MSTUF_INT:{ /* label, bot, top, init */
4943 int bot, top, init ; char *lab ; MCW_arrowval *av ;
4944 lab = va_arg( vararg_ptr , char * ) ;
4945 bot = va_arg( vararg_ptr , int ) ;
4946 top = va_arg( vararg_ptr , int ) ;
4947 init = va_arg( vararg_ptr , int ) ;
4948 if( bot >= top ) top = bot+1 ;
4949 if( init < bot ) init = bot ; else if( init > top ) init = top ;
4950 av = new_MCW_arrowval( wrc ,
4951 lab , MCW_AV_downup , /* selection */
4952 bot,top,init ,
4953 MCW_AV_edittext , 0 ,
4954 NULL , NULL , NULL , NULL ) ;
4955 av->allow_wrap = 1 ;
4956 CS_sav = (void **)realloc( CS_sav , sizeof(void *)*(CS_nsav+1) ) ;
4957 CS_sav[CS_nsav] = (void *)av ;
4958 CS_scod = (int *)realloc( CS_scod , sizeof(int)*(CS_nsav+1) ) ;
4959 CS_scod[CS_nsav] = scode ;
4960 CS_nsav++ ;
4961 }
4962 break ;
4963
4964 case MSTUF_STRING:{ /* label */
4965 char *lab ; Widget hrc, wlab, wtf ; int ncol=16 ;
4966 hrc = XtVaCreateWidget( /* RowColumn to hold all */
4967 MENU , xmRowColumnWidgetClass , wrc ,
4968 XmNpacking , XmPACK_TIGHT ,
4969 XmNorientation , XmHORIZONTAL ,
4970 XmNtraversalOn , True ,
4971 XmNinitialResourcesPersistent , False ,
4972 NULL ) ;
4973 lab = va_arg( vararg_ptr , char * ) ;
4974 wlab = XtVaCreateManagedWidget(
4975 MENU , xmLabelWidgetClass , hrc ,
4976 LABEL_ARG(lab) ,
4977 XmNinitialResourcesPersistent , False ,
4978 NULL ) ;
4979 LABELIZE(wlab) ;
4980 wtf = XtVaCreateManagedWidget(
4981 MENU , TEXT_CLASS , hrc ,
4982 XmNcolumns , ncol ,
4983 XmNeditable , True ,
4984 XmNmaxLength , 31 ,
4985 XmNresizeWidth , False ,
4986 XmNmarginHeight , 1 ,
4987 XmNmarginWidth , 1 ,
4988 XmNcursorPositionVisible , True ,
4989 XmNblinkRate , 0 ,
4990 XmNautoShowCursorPosition , True ,
4991 XmNinitialResourcesPersistent , False ,
4992 XmNtraversalOn , True ,
4993 NULL ) ;
4994 XtAddCallback( wtf,XmNactivateCallback,MCW_stuff_CB,NULL ) ; /* return key */
4995 XtManageChild(hrc) ;
4996 CS_sav = (void **)realloc( CS_sav , sizeof(void *)*(CS_nsav+1) ) ;
4997 CS_sav[CS_nsav] = (void *)wtf ;
4998 CS_scod = (int *)realloc( CS_scod , sizeof(int)*(CS_nsav+1) ) ;
4999 CS_scod[CS_nsav] = scode ;
5000 CS_nsav++ ;
5001 }
5002 break ;
5003
5004 case MSTUF_STRLIST:{ /* label, nstring , init_index , string_array */
5005 char *lab ; char **strlist ; MCW_arrowval *av ; int nstr , init ;
5006 lab = va_arg( vararg_ptr , char * ) ; if( lab == NULL ) break ;
5007 nstr = va_arg( vararg_ptr , int ) ; if( nstr <= 1 ) break ;
5008 init = va_arg( vararg_ptr , int ) ;
5009 strlist = va_arg( vararg_ptr , char ** ) ; if( strlist == NULL ) break ;
5010
5011 av = new_MCW_optmenu( wrc , lab ,
5012 0 , nstr-1 , init , 0 ,
5013 NULL , NULL ,
5014 MCW_av_substring_CB , strlist ) ;
5015
5016 CS_sav = (void **)realloc( CS_sav , sizeof(void *)*(CS_nsav+1) ) ;
5017 CS_sav[CS_nsav] = (void *)av ;
5018 CS_scod = (int *)realloc( CS_scod , sizeof(int)*(CS_nsav+1) ) ;
5019 CS_scod[CS_nsav] = scode ;
5020 CS_nsav++ ;
5021 }
5022 break ;
5023
5024 case MSTUF_YESNO:{ /* label */
5025 static char *strlist[2] = { "No" , "Yes" } ;
5026 char *lab ; MCW_arrowval *av ;
5027 lab = va_arg( vararg_ptr , char * ) ; if( lab == NULL ) break ;
5028
5029 av = new_MCW_optmenu( wrc , lab ,
5030 0 , 1 , 0 , 0 ,
5031 NULL , NULL ,
5032 MCW_av_substring_CB , strlist ) ;
5033
5034 CS_sav = (void **)realloc( CS_sav , sizeof(void *)*(CS_nsav+1) ) ;
5035 CS_sav[CS_nsav] = (void *)av ;
5036 CS_scod = (int *)realloc( CS_scod , sizeof(int)*(CS_nsav+1) ) ;
5037 CS_scod[CS_nsav] = scode ;
5038 CS_nsav++ ;
5039 }
5040 break ;
5041
5042 }
5043 }while(1) ;
5044 va_end( vararg_ptr ) ;
5045
5046 for( iss=0 ; iss < NUM_CSO_ACT ; iss++ ) CSO_act[iss].data = NULL ;
5047 (void) MCW_action_area( wrc , CSO_act , NUM_CSO_ACT ) ;
5048
5049 RELOCATE(CS_wpar,CS_wpop,2) ; /* 12 Oct 2017 */
5050 XtManageChild( wrc ) ;
5051 XtPopup( CS_wpop , XtGrabNone ) ; RWC_sleep(1);
5052 RWC_visibilize_widget( CS_wpop ) ;
5053 NORMAL_cursorize( CS_wpop ) ;
5054
5055 EXRETURN ;
5056 }
5057