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 "xutil.h"
8 #include "afni_environ.h"
9 #include "debugtrace.h" /* 12 Mar 2001 */
10 #include <time.h>
11
12 #undef SYNC
13 #define SYNC(w) XSync(XtDisplay(w),False)
14
15 #include "Amalloc.h"
16 extern char * THD_find_executable( char * ) ;
17
18 /*--------------------------------------------------------------------
19 force an immediate expose for the widget
20 ----------------------------------------------------------------------*/
21
22 /****************************************
23 requires the following line somewhere
24
25 #include <X11/IntrinsicP.h>
26
27 *****************************************/
28
MCW_expose_widget(Widget w)29 void MCW_expose_widget( Widget w )
30 {
31 XExposeEvent xev;
32 Dimension ww=0 , hh=0 ;
33
34 memset(&xev, 0, sizeof(xev));
35
36 if( w == NULL ) return ;
37 if( ! XtIsRealized(w) ) return ;
38 if( ! XtIsManaged(w) ) return ;
39 if( ! XtIsWidget(w) ) return ;
40 xev.window = XtWindow(w) ; if( xev.window == (Window) NULL ) return ;
41 xev.type = Expose ;
42 xev.display = XtDisplay(w) ;
43 xev.x = xev.y = 0 ; SYNC(w) ;
44 XtVaGetValues( w, XmNwidth, &ww, XmNheight, &hh, NULL ) ;
45 if( ww <= 0 || hh <= 0 ) return ;
46 xev.width = ww ; xev.height = hh ;
47 (XtClass (w))->core_class.expose( w, (XEvent *)&xev, NULL ) ;
48 XFlush( XtDisplay(w) ) ;
49 return ;
50 }
51
52 /*--------------------------------------------------------------------
53 Get the Colormap for a widget -- 01 Sep 1998
54 ----------------------------------------------------------------------*/
55
MCW_get_colormap(Widget w)56 Colormap MCW_get_colormap( Widget w )
57 {
58 Colormap cmap = (Colormap) 0 ;
59
60 if( w == NULL || ! XtIsWidget(w) ) return (Colormap) 0 ;
61
62 SYNC(w) ;
63 XtVaGetValues( w , XmNcolormap , &cmap , NULL ) ;
64 return cmap ;
65 }
66
67 /*--------------------------------------------------------------------*/
68
MCW_get_depth(Widget w)69 int MCW_get_depth( Widget w ) /* 14 Sep 1998 */
70 {
71 int depth = 0 ;
72
73 if( w == NULL || ! XtIsWidget(w) ) return 0 ;
74 SYNC(w) ;
75 XtVaGetValues( w , XmNdepth , &depth , NULL ) ;
76 return depth ;
77 }
78
79 /*--------------------------------------------------------------------*/
80
MCW_get_visual(Widget w)81 Visual * MCW_get_visual( Widget w ) /* 14 Sep 1998 */
82 {
83 Visual *visual = NULL ;
84 Widget wpar = w ;
85
86 if( w == NULL || ! XtIsWidget(w) ) return NULL ;
87 SYNC(w) ;
88
89 while( XtParent(wpar) != NULL ) wpar = XtParent(wpar) ; /* find top */
90
91 XtVaGetValues( wpar , XmNvisual , &visual , NULL ) ;
92 return visual ;
93 }
94
95 /*--------------------------------------------------------------------
96 Set the Colormap for a widget -- 14 Sep 1998
97 (Will only work if widget is not yet realized)
98 ----------------------------------------------------------------------*/
99
MCW_set_colormap(Widget w,Colormap cmap)100 void MCW_set_colormap( Widget w , Colormap cmap )
101 {
102 if( w == NULL || ! XtIsWidget(w) ) return ;
103 SYNC(w) ;
104 XtVaSetValues( w , XmNcolormap , cmap , NULL ) ;
105 return ;
106 }
107
108 /*--------------------------------------------------------------------
109 swap the fg and bg colors of a widget
110 (the shadow colors are altered to fit the new bg)
111 ----------------------------------------------------------------------*/
MCW_invert_widget(Widget w)112 void MCW_invert_widget( Widget w ) { return(MCW_invert_widget_sync(w,1)); }
113
MCW_invert_widget_sync(Widget w,int sync)114 void MCW_invert_widget_sync( Widget w , int sync)
115 {
116 Pixel bg_pix=0 , topsh_pix=0 , botsh_pix=0 , fg_pix=0 , sel_pix=0 ;
117 Colormap cmap ;
118
119 memset(&cmap, 0, sizeof(cmap));
120
121 if( ! XtIsWidget(w) ) return ;
122 if (sync) { SYNC(w) ; }
123
124 XtVaGetValues( w , XmNforeground , &bg_pix , /* foreground -> bg */
125 XmNbackground , &fg_pix , /* background -> fg */
126 XmNcolormap , &cmap ,
127 NULL ) ;
128
129 XmGetColors( XtScreen(w) , cmap , bg_pix ,
130 NULL , &topsh_pix , &botsh_pix , &sel_pix ) ;
131
132 XtVaSetValues( w ,
133 XmNtopShadowColor , topsh_pix ,
134 XmNbottomShadowColor , botsh_pix ,
135 XmNselectColor , sel_pix ,
136 XmNarmColor , sel_pix ,
137 XmNborderColor , fg_pix ,
138 XmNforeground , fg_pix ,
139 XmNbackground , bg_pix ,
140 NULL ) ;
141
142 if (sync) {
143 XSync( XtDisplay(w) , False ) ; /* make it happen NOW */
144 XmUpdateDisplay( w ) ;
145 }
146 return ;
147 }
148
149 /*---------------------------------------------------------------------*/
150
MCW_flash_widget(int ntime,Widget w)151 void MCW_flash_widget( int ntime , Widget w ) /* 12 Feb 2010 */
152 {
153 int ii ;
154
155 if( ! XtIsWidget(w) ) return ;
156 if( ntime < 1 ) ntime = 1 ;
157
158 for( ii=0 ; ii < ntime ; ii++ ){
159 MCW_invert_widget(w) ; RWC_sleep(100) ;
160 MCW_invert_widget(w) ; RWC_sleep(100) ;
161 }
162
163 return ;
164 }
165
166 /*---------------------------------------------------------------------*/
167
MCW_flash_widget_list(int ntime,...)168 void MCW_flash_widget_list( int ntime , ... )
169 {
170 int ii,kk , nwid=0 ; Widget w , *war=NULL ;
171 va_list vararg_ptr ;
172
173 if( ntime < 1 ) ntime = 1 ;
174
175 va_start( vararg_ptr , ntime ) ;
176
177 while(1){
178 w = va_arg( vararg_ptr , Widget ) ;
179 if( w == (Widget)NULL ) break ;
180 war = (Widget *)realloc(war,sizeof(Widget)*(nwid+1)) ;
181 war[nwid++] = w ;
182 }
183 va_end( vararg_ptr ) ;
184 if( nwid < 1 ) return ;
185
186 for( ii=0 ; ii < ntime ; ii++ ){
187 for( kk=0 ; kk < nwid ; kk++ ) MCW_invert_widget(war[kk]) ;
188 RWC_sleep(100) ;
189 for( kk=0 ; kk < nwid ; kk++ ) MCW_invert_widget(war[kk]) ;
190 RWC_sleep(100) ;
191 }
192
193 free(war) ; return ;
194 }
195
196 /*---------------------------------------------------------------------
197 set the background color of a widget; the other colors are
198 altered to match, a la Motif;
199 cname = character specification of color
200 pix = if cname == NULL, use this pixel value
201 -----------------------------------------------------------------------*/
202
MCW_set_widget_bg(Widget w,char * cname,Pixel pix)203 void MCW_set_widget_bg( Widget w , char *cname , Pixel pix )
204 {
205 Pixel bg_pix=0 , topsh_pix=0 , botsh_pix=0 , fg_pix=0 , sel_pix=0 ;
206 Colormap cmap ;
207
208 memset(&cmap, 0, sizeof(cmap));
209
210 #if 1
211 if( ! XtIsWidget(w) ) return ;
212 #else
213 if( ! XtIsObject(w) ) return ;
214 #endif
215
216 SYNC(w) ;
217
218 if( cname != NULL && strlen(cname) > 0 ){
219 XtVaSetValues( w ,
220 XtVaTypedArg , XmNbackground , XmRString ,
221 cname , strlen(cname)+1 ,
222 NULL ) ;
223
224 XtVaGetValues( w , XmNbackground , &bg_pix , NULL ) ;
225 } else {
226 bg_pix = pix ;
227 }
228
229 #if 0
230 XtVaGetValues( w , XmNcolormap , &cmap , NULL ) ;
231 XmGetColors( XtScreen(w) , cmap , bg_pix ,
232 &fg_pix , &topsh_pix , &botsh_pix , &sel_pix ) ;
233 XtVaSetValues( w ,
234 XmNtopShadowColor , topsh_pix ,
235 XmNbottomShadowColor , botsh_pix ,
236 XmNselectColor , sel_pix ,
237 XmNarmColor , sel_pix ,
238 XmNborderColor , fg_pix ,
239 XmNforeground , fg_pix ,
240 XmNbackground , bg_pix ,
241 NULL ) ;
242 XFlush( XtDisplay(w) ) ;
243 #else
244 XmChangeColor( w , bg_pix ) ;
245 #endif
246
247 if( XmIsToggleButton(w) ){ /* 18 Sep 2009 */
248 Pixel fg_pix=0 ;
249 XtVaGetValues( w , XmNforeground , &fg_pix , NULL ) ;
250 XtVaSetValues( w , XmNselectColor, fg_pix , NULL ) ;
251 }
252
253 return ;
254 }
255
256 /*-------------------------------------------------------------------*/
257
MCW_scale_widget_bg(Widget w,float fac,MCW_DC * dc)258 void MCW_scale_widget_bg( Widget w , float fac , MCW_DC *dc )
259 {
260 Pixel bg_pix=0 ; byte rr,gg,bb ;
261 unsigned int nr,ng,nb ;
262 float aa , fr,fg,fb , ff ;
263
264 if( !XtIsWidget(w) || dc == NULL || fac < 0.0f || fac > 2.0f ) return ;
265
266
267 XtVaGetValues( w , XmNbackground , &bg_pix , NULL ) ;
268 DC_pixel_to_rgb( dc , bg_pix , &rr,&gg,&bb ) ;
269 aa = (fac > 1.0f) ? 1.0f : 0.0f ;
270 nr = aa+fac*rr ; ng = aa+fac*gg ; nb = aa+fac*bb ;
271 fr = fg = fb = fac ;
272 if( nr > 255 ){ nr = 255 ; fr = 255.0f/rr ; }
273 if( ng > 255 ){ ng = 255 ; fg = 255.0f/gg ; }
274 if( nb > 255 ){ nb = 255 ; fb = 255.0f/bb ; }
275 ff = MIN(fr,fac) ; ff = MIN(fg,ff) ; ff = MIN(fb,ff) ;
276 if( ff < fac ){ nr = aa+ff*rr ; ng = aa+ff*gg ; nb = aa+ff*bb ; }
277 if( nr > 255 ) nr = 255 ; else if( nr == 0 ) nr = lrand48()%32 ;
278 if( ng > 255 ) ng = 255 ; else if( ng == 0 ) ng = lrand48()%16 ;
279 if( nb > 255 ) nb = 255 ; else if( nb == 0 ) nb = lrand48()%24 ;
280 #if 0
281 INFO_message("scale_bg: %u %u %u ==> %u %u %u",
282 (unsigned int)rr, (unsigned int)gg, (unsigned int)bb, nr,ng,nb ) ;
283 #endif
284 rr = (byte)nr ; gg = (byte)ng ; bb = (byte)nb ;
285 bg_pix = DC_rgb_to_pixel( dc , rr,gg,bb ) ;
286 MCW_set_widget_bg( w , NULL , bg_pix ) ;
287 return ;
288 }
289
290 /*-------------------------------------------------------------------*/
291
MCW_set_widget_fg(Widget w,char * cname)292 void MCW_set_widget_fg( Widget w , char *cname )
293 {
294 Pixel bg_pix , topsh_pix , botsh_pix , fg_pix , sel_pix ;
295 Colormap cmap ;
296
297 if( !XtIsWidget(w) || cname == NULL || *cname == '\0' ) return ;
298
299 SYNC(w) ;
300
301 XtVaSetValues( w , XtVaTypedArg , XmNforeground , XmRString ,
302 cname , strlen(cname)+1 , NULL ) ;
303 return ;
304 }
305
306 /*-------------------------------------------------------------------*/
307
MCW_set_widget_label(Widget w,char * str)308 void MCW_set_widget_label( Widget w , char *str )
309 {
310 XmString xstr ;
311 if( w == NULL || str == NULL ) return ;
312 xstr = XmStringCreateLtoR( str , XmFONTLIST_DEFAULT_TAG ) ;
313 XtVaSetValues( w , XmNlabelString , xstr , NULL ) ;
314 XmStringFree( xstr ) ;
315 MCW_expose_widget( w ) ;
316 return ;
317 }
318
319 #if 0
320 void MCW_set_widget_label_tagged( Widget w , char *str , char *tag )
321 {
322 XmString xstr ;
323 if( w == NULL || str == NULL ) return ;
324 xstr = XmStringCreateLtoR( str , tag ) ;
325 XtVaSetValues( w , XmNlabelString , xstr , NULL ) ;
326 XmStringFree( xstr ) ;
327 MCW_expose_widget( w ) ;
328 return ;
329 }
330 #endif
331
332 /*-----------------------------------------------------------------------*/
333
MCW_widget_geom(Widget w,int * wout,int * hout,int * xout,int * yout)334 void MCW_widget_geom( Widget w, int *wout, int *hout, int *xout, int *yout )
335 {
336 Dimension nx=0 , ny=0 ; /* don't try to make these ints! */
337 Position xx=0 , yy=0 ;
338
339 if( w == NULL ) return ; /* user == loser */
340 SYNC(w) ; RWC_sleep(1) ;
341
342 if( XtIsRealized(w) ){
343 XtVaGetValues( w , XmNwidth , &nx , XmNheight , &ny ,
344 XmNx , &xx , XmNy , &yy , NULL ) ;
345 } else {
346 XtWidgetGeometry wg ;
347 memset(&wg, 0, sizeof(wg)); /* probably doesn't matter, but be safe */
348 (void) XtQueryGeometry( w , NULL , &wg ) ; /* works! */
349 nx = wg.width ; ny = wg.height ;
350 xx = wg.x ; yy = wg.y ;
351 }
352
353 #define ASSIF(p,v) if( p!= NULL ) *p = v
354
355 ASSIF(wout,nx) ; ASSIF(hout,ny) ;
356 ASSIF(xout,xx) ; ASSIF(yout,yy) ;
357
358 return ;
359 }
360
361 /*--------------------------------------------------------------------------*/
362
MCW_discard_events(Widget w,int ev_mask)363 void MCW_discard_events( Widget w , int ev_mask )
364 {
365 XEvent evjunk ;
366
367 if( w == NULL || XtWindow(w) == (Window) NULL ) return ;
368
369 XSync( XtDisplay(w) , False ) ;
370 while( XCheckWindowEvent( XtDisplay(w), XtWindow(w) , ev_mask , &evjunk ) ) ;
371 return ;
372 }
373
374 /*--------------------------------------------------------------------------*/
375
MCW_discard_events_all(Widget w,int ev_mask)376 void MCW_discard_events_all( Widget w , int ev_mask )
377 {
378 XEvent evjunk ;
379
380 if( w == NULL || XtWindow(w) == (Window) NULL ) return ;
381
382 XSync( XtDisplay(w) , False ) ;
383 while( XCheckMaskEvent( XtDisplay(w), ev_mask , &evjunk ) ) ;
384 return ;
385 }
386
387 /*--------------------------------------------------------------------------*/
388
MCW_hotcolor(Widget w)389 char * MCW_hotcolor(Widget w)
390 {
391 static char *redcolor = NULL ;
392
393 if( redcolor == NULL ){
394 char *xdef = RWC_getname( (w!=NULL) ? XtDisplay(w) : NULL, "hotcolor" ) ;
395
396 redcolor = (xdef != NULL) ? (xdef) : ("red4") ;
397 }
398 return redcolor ;
399 }
400
401 /*--------------------------------------------------------------------------*/
402
MCW_buthighlight(Widget w)403 char * MCW_buthighlight(Widget w)
404 {
405 static char *buthighlight = NULL ;
406
407 if( buthighlight == NULL ){
408 char *xdef = RWC_getname( (w!=NULL) ? XtDisplay(w) : NULL,
409 "buthighlight" ) ;
410
411 buthighlight = (xdef != NULL) ? (xdef) : ("blue2") ;
412 }
413 return buthighlight ;
414 }
415
416 /*--------------------------------------------------------------------------
417 24 Apr 2001: manage array of widgets, some of which may be NULL
418 ----------------------------------------------------------------------------*/
419
MCW_manage_widgets(Widget * war,int nar)420 void MCW_manage_widgets( Widget *war , int nar )
421 {
422 int ii ;
423 if( war == NULL ) return ;
424 for( ii=0 ; ii < nar ; ii++ )
425 if( war[ii] != (Widget) 0 ) XtManageChild( war[ii] ) ;
426 return ;
427 }
428
MCW_unmanage_widgets(Widget * war,int nar)429 void MCW_unmanage_widgets( Widget *war , int nar )
430 {
431 int ii ;
432 if( war == NULL ) return ;
433 for( ii=0 ; ii < nar ; ii++ )
434 if( war[ii] != (Widget) 0 ) XtUnmanageChild( war[ii] ) ;
435 return ;
436 }
437
438 /*--------------------------------------------------------------------------*/
439
440 #define TIG 25
441
MCW_action_area(Widget parent,MCW_action_item * action,int num_act)442 Widget MCW_action_area( Widget parent, MCW_action_item *action, int num_act )
443 {
444 Widget act_area , ww ;
445 int ii ;
446
447 if( parent == NULL ) return NULL ; /* should not happen */
448
449 act_area = XtVaCreateWidget( "action_area" , xmFormWidgetClass , parent ,
450 XmNfractionBase , TIG*num_act - 1,
451
452 XmNinitialResourcesPersistent , False ,
453 NULL ) ;
454
455 for( ii=0 ; ii < num_act ; ii++ ){
456
457 ww = XtVaCreateManagedWidget(
458 action[ii].label , xmPushButtonWidgetClass , act_area ,
459
460 XmNleftAttachment ,
461 (ii) ? XmATTACH_POSITION : XmATTACH_FORM ,
462 XmNleftPosition , ii*TIG ,
463 XmNtopAttachment , XmATTACH_FORM ,
464 XmNbottomAttachment , XmATTACH_FORM ,
465 XmNrightAttachment ,
466 (ii==num_act-1) ? XmATTACH_FORM : XmATTACH_POSITION ,
467
468 XmNrightPosition , ii*TIG + (TIG-1) ,
469
470 XmNrecomputeSize , False ,
471 XmNtraversalOn , True ,
472 XmNinitialResourcesPersistent , False ,
473 NULL ) ;
474
475 XtAddCallback( ww , XmNactivateCallback ,
476 action[ii].func_CB , action[ii].data ) ;
477
478 action[ii].data = (XtPointer) ww ; /* Feb 1998: save widget */
479
480 if( action[ii].help_text != NULL )
481 MCW_register_help( ww , action[ii].help_text ) ;
482
483 if( action[ii].hint_text != NULL )
484 MCW_register_hint( ww , action[ii].hint_text ) ;
485
486 if( action[ii].make_red > 0 ) /* for some fun */
487 MCW_set_widget_bg( ww , MCW_hotcolor(ww) , 0 ) ;
488 else if( action[ii].make_red < 0 ) /* for no fun at all */
489 XtSetSensitive( ww , False ) ;
490
491 }
492
493 XtManageChild( act_area ) ;
494 return act_area ;
495 }
496
497 /*------------------------------------------------------------------
498 Popup a window with a message; return the Widget.
499 The message can be of two types, signified by the 3rd argument:
500 msg_type = MCW_CALLER_KILL means the caller has to kill the
501 widget for the window to go away.
502
503 = MCW_USER_KILL means that the user can click in
504 the widget to kill it.
505
506 msg_type may also be OR-ed with MCW_TIMER_KILL to have the
507 message automatically killed after 22 seconds --
508 OR with MCW_QUICK_KILL to be auto-killed after 7 seconds.
509 --------------------------------------------------------------------*/
510
MCW_popup_message(Widget wparent,char * msg,int msg_type)511 Widget MCW_popup_message( Widget wparent , char *msg , int msg_type )
512 {
513 Widget wmsg , wlab ;
514 int wx,hy,xx,yy , xp,yp , scr_width,scr_height , xr,yr , xpr,ypr , lm ;
515 Screen *scr ;
516 XEvent ev ;
517
518 ENTRY("MCW_popup_message") ;
519
520 if( msg == NULL || (lm=strlen(msg)) == 0 ) RETURN(NULL) ;
521
522 if( wparent == NULL || !XtIsRealized(wparent) ){ /* 21 Aug 2007 */
523 fprintf(stderr,"%s\n",msg) ; RETURN(NULL) ;
524 }
525
526 /* set position for message box based on parent and screen geometry */
527
528 MCW_widget_geom( wparent , &wx,&hy,&xx,&yy ) ; /* geometry of parent */
529
530 #if 1
531 { Position xroot , yroot ;
532 XtTranslateCoords( wparent, 0,0, &xroot,&yroot ) ; /* root coords */
533 xr = (int) xroot ; yr = (int) yroot ;
534 }
535 #else
536 xr = xx ; yr = yy ; /* the old code, essentially */
537 #endif
538
539 scr = XtScreen( wparent ) ;
540 scr_width = WidthOfScreen( scr ) ;
541 scr_height = HeightOfScreen( scr ) ;
542
543 xp = xx+8 ; xpr = xr+8 ;
544 if( xpr+50 > scr_width ){ xp -= 100 ; xpr -= 100 ; } /* too right */
545 else if( xpr+10 < 0 ) { xpr = xp = 1 ; } /* too left */
546
547 yp = yy+hy+8 ; ypr = yr+hy+8 ;
548 if( ypr+50 > scr_height ){ yp = yy-8 ; ypr = yr-100 ;} /* too down */
549 else if( ypr+10 < 0 ) { ypr = yp = 1 ; } /* too up */
550
551 /* create a popup shell with a label */
552
553 wmsg = XtVaCreatePopupShell(
554 "help" , xmDialogShellWidgetClass , wparent ,
555 XmNx , xpr ,
556 XmNy , ypr ,
557 XmNinitialResourcesPersistent , False ,
558 NULL ) ;
559
560 if( MCW_isitmwm( wparent ) ){
561 XtVaSetValues( wmsg ,
562 XmNmwmDecorations , MWM_DECOR_BORDER ,
563 XmNmwmFunctions , MWM_FUNC_MOVE ,
564 NULL ) ;
565 }
566
567 switch( msg_type & (MCW_CALLER_KILL | MCW_USER_KILL) ){
568
569 case MCW_CALLER_KILL:
570
571 wlab = XtVaCreateManagedWidget(
572 "help" , xmLabelWidgetClass , wmsg ,
573 XtVaTypedArg,XmNlabelString,XmRString,msg,lm+1,
574 XmNalignment , XmALIGNMENT_BEGINNING ,
575 XmNinitialResourcesPersistent , False ,
576 NULL ) ;
577 break ;
578
579 default:
580 case MCW_USER_KILL:{
581 static int first=1 ; char *mmsg = msg ; /* 'first' stuff */
582 if( first ){ /* on 06 Apr 2004 */
583 if( !AFNI_noenv("AFNI_CLICK_MESSAGE") ){
584 mmsg = (char *) malloc(lm+99) ;
585 strcpy(mmsg,msg) ;
586 strcat(mmsg,"\n [---------------] "
587 "\n [ Click in Text ] "
588 "\n [ to Pop Down!! ]\n" ) ;
589 }
590 }
591
592 wlab = XtVaCreateManagedWidget(
593 "help" , xmPushButtonWidgetClass , wmsg ,
594 XtVaTypedArg,XmNlabelString,XmRString,mmsg,lm+1,
595 XmNalignment , XmALIGNMENT_BEGINNING ,
596 XmNinitialResourcesPersistent , False ,
597 NULL ) ;
598
599 if( mmsg != msg ){ free((void *)mmsg); first = 0; }
600
601 XtAddCallback( wlab , XmNactivateCallback , MCW_message_CB , NULL ) ;
602 }
603 break ;
604 }
605
606 SAVEUNDERIZE(wmsg) ; /* 27 Feb 2001 */
607 XtPopup( wmsg , XtGrabNone ) ; RWC_sleep(1);
608
609 /* now wait until the label is exposed, and make sure it appears;
610 the reason for this stuff is that this routine is likely to be
611 called by a long computation that won't return control to Xt */
612
613 WAIT_for_window(wlab) ;
614 XSync( XtDisplay(wlab) , False ) ;
615 #if 0
616 XMaskEvent( XtDisplay(wlab) , ExposureMask , &ev ) ;/* wait for expose */
617 #else
618 XWindowEvent( XtDisplay(wlab) , XtWindow(wlab) , ExposureMask , &ev ) ;
619 #endif
620 XPutBackEvent( XtDisplay(wlab) , &ev ) ; /* put expose back */
621 XSync( XtDisplay(wlab) , False ) ;
622 XmUpdateDisplay( wlab ) ; /* show it for sure */
623
624 /* now add the timer kill, if wanted */
625
626 #define ALLOW_TIMER_KILL
627 #ifdef ALLOW_TIMER_KILL
628 if( (msg_type & (MCW_TIMER_KILL|MCW_QUICK_KILL)) ){
629 XtIntervalId tid ;
630 unsigned long dtime = (msg_type & MCW_TIMER_KILL) ? 22111 : 7111 ;
631
632 tid = XtAppAddTimeOut( XtWidgetToApplicationContext( wmsg ) ,
633 dtime , MCW_message_timer_CB , wmsg ) ;
634
635 XtVaSetValues( wlab , XmNuserData , tid , NULL ); /* put tid on wlab, */
636 } else { /* since shells don't */
637 XtVaSetValues( wlab , XmNuserData , 0 , NULL ) ; /* have XmNuserData */
638 }
639 #endif
640
641 RWC_visibilize(wmsg) ; /* 27 Sep 2000 */
642 NORMAL_cursorize(wmsg) ;
643 MCW_flash_widget(1,wlab) ; /* 25 Jul 2014 */
644 RETURN(wmsg) ;
645 }
646
647 /*-------------------------------------------------------------------------
648 Alter the text in the popup message - 10 Jul 2001
649 ---------------------------------------------------------------------------*/
650
MCW_message_alter(Widget wmsg,char * msg)651 void MCW_message_alter( Widget wmsg , char *msg )
652 {
653 Widget wlab ;
654 Widget *children=NULL ;
655 int num_children=0 ;
656 XmString xstr ;
657
658 ENTRY("MCW_message_alter") ;
659
660 if( wmsg == NULL || msg == NULL || msg[0] == '\0' ) EXRETURN ;
661
662 XtVaGetValues( wmsg , XmNchildren , &children ,
663 XmNnumChildren , &num_children , NULL ) ;
664 if( num_children < 1 ) EXRETURN ;
665
666 MCW_set_widget_label( children[0] , msg ) ;
667 EXRETURN ;
668 }
669
670 /*-------------------------------------------------------------------------
671 callback when the popup message created above is a PushButton
672 (Note that w is the PushButton widget, so its parent is to be killed)
673 ---------------------------------------------------------------------------*/
674
MCW_message_CB(Widget w,XtPointer cd,XtPointer cbs)675 void MCW_message_CB( Widget w , XtPointer cd , XtPointer cbs )
676 {
677 #ifdef ALLOW_TIMER_KILL
678 XtIntervalId tid=0 ;
679
680 XtVaGetValues( w , XmNuserData , &tid , NULL ) ; /* get timer id */
681 XtDestroyWidget( XtParent(w) ) ;
682
683 if( tid > 0 ) XtRemoveTimeOut( tid ) ; /* if a timer exists, kill it */
684 RWC_sleep(1) ;
685 #else
686 XtDestroyWidget( XtParent(w) ) ;
687 #endif
688 }
689
690 /*----------------------------------------------------*/
691 /*--- callback when timer expires on popup message ---*/
692 /*----------------------------------------------------*/
693
MCW_message_timer_CB(XtPointer client_data,XtIntervalId * id)694 void MCW_message_timer_CB( XtPointer client_data , XtIntervalId *id )
695 {
696 XtDestroyWidget( (Widget) client_data ) ;
697 RWC_sleep(1) ;
698 }
699
700 /*------------------------------------------------------------------------------*/
701 /* This function is intended to popup the given message only once
702 (for each user). The 'w' and 'msg' arguments are self-explanatory, I hope.
703
704 'expiry', if not NULL, is a data after which the message should not be shown.
705
706 'codestring' is a short string to encode that the message has been seen,
707 in the ${HOME)/.afni.recordings file -- if codestring is NULL, then the
708 MD5 hashstring of the message will be used for this hideous purpose.
709
710 Example:
711 MCW_popup_message_once( w, "Hi, this is Bob", "01 Jan 2099", "Bob#001" ) ;
712 *//*----------------------------------------------------------------------------*/
713
MCW_popup_message_once(Widget w,char * msg,char * expiry,char * codestring)714 void MCW_popup_message_once( Widget w, char *msg, char *expiry, char *codestring )
715 {
716 char *home = getenv("HOME") , mname[1024]="file:" ;
717 NI_stream ns ; NI_element *nel ;
718 int seen=0 ;
719
720 time_t tt=time(NULL) ; struct tm *lt=localtime(&tt) ;
721
722 static char *monthlist[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
723 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" } ;
724
725 if( w == (Widget)NULL ) return ;
726 if( msg == NULL || *msg == '\0' ) return ;
727 if( AFNI_yesenv("AFNI_SKIP_ONETIME_POPUPS") ) return ;
728
729 /* check expiry date vs today */
730
731 if( expiry != NULL && *expiry != '\0' ){
732 char da[16],db[16],dc[16] ; int emon=-1,eday=-1,eyear=-1 , ii ;
733 da[0] = db[0] = dc[0] = '\0' ;
734 sscanf( expiry , "%5s%5s%5s" , da,db,dc ) ;
735 if( da[0] != '\0' && db[0] != '\0' && dc != '\0' ){ /* got 3 sub-strings */
736 if( isalpha(da[0]) ){ /* month is first */
737 for( ii=0; ii < 12 && strcasecmp(da,monthlist[ii]); ii++ ) ; /*nada*/
738 emon = ii ;
739 eday = (int)strtol(db,NULL,10) ;
740 } else if( isalpha(db[0]) ){ /* month is second */
741 for( ii=0; ii < 12 && strcasecmp(db,monthlist[ii]); ii++ ) ; /*nada*/
742 emon = ii ;
743 eday = (int)strtol(da,NULL,10) ;
744 }
745 eyear = (int)strtol(dc,NULL,10)-1900 ;
746 if( emon >= 0 && emon < 12 && eday > 0 && eday < 32 && eyear > 0 ){
747 if( lt->tm_year > eyear ) return ; /* past the expiry year == DONE */
748 if( lt->tm_year == eyear ){ /* in expiry year */
749 if( lt->tm_mon > emon ) return ; /* past expiry month == DONE */
750 if( lt->tm_mon == emon ){ /* in expiry month */
751 if( lt->tm_mday >= eday ) return ; /* past expiry day == DONE */
752 }
753 }
754 }
755 }
756 }
757
758 if( codestring == NULL ||
759 codestring[0] == '\0' || strlen(codestring) > 66 ) /* backup for luser */
760 codestring = MD5_static_string(msg) ;
761
762 if( home != NULL ) strcat(mname,home) ;
763 else strcat(mname,"." ) ;
764 strcat(mname,"/.afni.recordings") ;
765
766 /* check if we saw this already */
767
768 ns = NI_stream_open(mname,"r") ;
769 if( ns != NULL ){
770 while( !seen ){
771 nel = NI_read_element_header(ns,11) ;
772 if( nel == NULL ) break ;
773 if( strcmp(nel->name,"AFNI_saw_message") == 0 ){
774 char *rhs = NI_get_attribute(nel,"codestring") ;
775 if( rhs != NULL && strcmp(rhs,codestring) == 0 ) seen = 1 ;
776 }
777 NI_free_element(nel) ;
778 }
779 NI_stream_close(ns) ;
780 }
781 if( seen ) return ; /* it was recorded! */
782
783 /* popup the actual message now */
784
785 (void)MCW_popup_message( w , msg , MCW_USER_KILL ) ;
786
787 /* recordation of seeing */
788
789 ns = NI_stream_open(mname,"a") ;
790 if( ns != NULL ){
791 char rhs[32] ;
792 nel = NI_new_data_element("AFNI_saw_message",0) ;
793 NI_set_attribute(nel,"codestring",codestring) ;
794 sprintf(rhs,"%02d %s %4d",lt->tm_mday,monthlist[lt->tm_mon],lt->tm_year+1900) ;
795 NI_set_attribute(nel,"seendate",rhs) ;
796 NI_write_element(ns,nel,NI_TEXT_MODE) ;
797 NI_free_element(nel) ;
798 NI_stream_close(ns) ;
799 }
800
801 return ;
802 }
803
804 /*------------------------------------------------------------------
805 routines to change Widget cursors
806 cur argument: = 0 --> None
807 > 0 --> is a Cursor already allocated
808 < 0 --> -cur is a cursorfont index
809 --------------------------------------------------------------------*/
810
MCW_set_widget_cursor(Widget w,int cur)811 void MCW_set_widget_cursor( Widget w , int cur )
812 {
813 MCW_alter_widget_cursor( w , cur , NULL,NULL ) ;
814 return ;
815 }
816
817 /*--------------------------------------------------------------------*/
818
MCW_alter_widget_cursor(Widget w,int cur,char * fgname,char * bgname)819 void MCW_alter_widget_cursor( Widget w, int cur, char *fgname, char *bgname )
820 {
821 XColor fg , bg ;
822 Cursor ccc ;
823 Colormap cmap ;
824 Display *dis ;
825 RwcBoolean good ;
826 int ii ;
827
828 static Cursor cur_font[XC_num_glyphs] ;
829 static RwcBoolean first = True ;
830
831 if( AFNI_yesenv("AFNI_DISABLE_CURSORS") ) return ; /* 21 Mar 2004 */
832
833 if( first ){
834 for( ii=0 ; ii < XC_num_glyphs ; ii++ ) cur_font[ii] = None ;
835 first = False ;
836 }
837
838 if( w == NULL || !XtIsRealized(w) || XtWindow(w) == (Window)NULL ) return ;
839 RWC_sleep(1) ;
840
841 dis = XtDisplay(w) ;
842
843 if( cur == 0 || cur <= -XC_num_glyphs ){ /* define cursor */
844 ccc = None ;
845 } else if( cur > 0 ){
846 ccc = cur ;
847 } else {
848 ii = -cur ;
849 if( cur_font[ii] == None ) cur_font[ii] = XCreateFontCursor( dis , ii ) ;
850 ccc = cur_font[ii] ;
851 }
852
853 XDefineCursor( dis , XtWindow(w) , ccc ) ;
854
855 if( fgname != NULL && bgname != NULL ){
856
857 cmap = DefaultColormap( dis , DefaultScreen(dis) ) ;
858
859 good = XParseColor( dis , cmap , fgname , &fg )
860 && XParseColor( dis , cmap , bgname , &bg ) ;
861
862 if( good ) XRecolorCursor( dis , ccc , &fg , &bg ) ;
863 }
864 return ;
865 }
866
867 /*------------------------------------------------------------------------
868 widget help routines (for "button help" buttons)
869 --------------------------------------------------------------------------*/
870
MCW_click_help_CB(Widget w,XtPointer client_data,XtPointer call_data)871 void MCW_click_help_CB( Widget w, XtPointer client_data, XtPointer call_data )
872 {
873 Widget whelp ;
874 XmAnyCallbackStruct cbs ;
875 XEvent ev ;
876 static Cursor cur = 0 ;
877 Display *dis = XtDisplay(w) ;
878
879 if( cur == 0 ) cur = XCreateFontCursor( dis , XC_hand2 ) ;
880
881 #ifdef USE_LOCATE /* old version */
882 whelp = XmTrackingLocate( w , cur , False ) ; /* wait for user to click */
883 #else
884 cbs.event = &ev ;
885 whelp = XmTrackingEvent( w , cur , False , cbs.event ) ;
886 #endif
887
888 if( whelp != NULL &&
889 XtHasCallbacks(whelp,XmNhelpCallback) == XtCallbackHasSome ){
890
891 cbs.reason = XmCR_HELP ;
892 XtCallCallbacks( whelp , XmNhelpCallback , &cbs ) ; /* call for help */
893 } else {
894 XBell( dis , 100 ) ;
895 }
896 return ;
897 }
898
899 /*------------------------------------------------------------------------*/
900 /*------------------------------------------------------------------------*/
901
902 static int disable_helps = 0 ; /* 02 Aug 1999 */
MCW_disable_help(void)903 void MCW_disable_help(void){ disable_helps = 1 ; }
MCW_enable_help(void)904 void MCW_enable_help (void){ disable_helps = 0 ; }
905
906 #ifdef DONT_USE_HINTS
MCW_register_hint(Widget w,char * msg)907 void MCW_register_hint( Widget w , char *msg ) { return ; }
MCW_reghint_children(Widget w,char * msg)908 void MCW_reghint_children( Widget w , char *msg ) { return ; }
MCW_hint_toggle(void)909 void MCW_hint_toggle(void){ return ; }
MCW_unregister_hint(Widget w)910 void MCW_unregister_hint( Widget w ){ return ; }
911 #else
912
913 #include "LiteClue.h"
914
915 static Widget liteClue = NULL ;
916 static int clueless = -1 ;
917
MCW_hint_toggle(void)918 void MCW_hint_toggle(void)
919 {
920 #define PBIG 999999
921 int period=0 ;
922 char *pdef=NULL ;
923
924 if( liteClue == NULL ) return ;
925
926 XtVaGetValues( liteClue , XgcNwaitPeriod , &period , NULL ) ;
927 if( period < PBIG ){
928 period = PBIG ;
929 } else {
930 #if 0
931 pdef = XGetDefault(XtDisplay(liteClue),"AFNI","waitperiod") ;
932 #else
933 pdef = RWC_getname(XtDisplay(liteClue),"waitperiod") ;
934 #endif
935 if( pdef == NULL ){
936 period = 1066 ;
937 } else {
938 period = strtol( pdef , NULL , 10 ) ;
939 if( period < 100 ) period = 1066 ;
940 }
941 }
942 XtVaSetValues( liteClue , XgcNwaitPeriod , period , NULL ) ;
943 return ;
944 }
945
946 /*--------------------------------------------------------------------*/
947
MCW_unregister_hint(Widget w)948 void MCW_unregister_hint( Widget w ) /* 11 Jul 2001 */
949 {
950 if( liteClue != NULL && w != NULL )
951 XcgLiteClueDeleteWidget( liteClue , w ) ;
952 return ;
953 }
954
955 /*--------------------------------------------------------------------*/
956
957 #define RES_CONVERT( res_name, res_value) \
958 XtVaTypedArg, (res_name), XmRString, (res_value), strlen(res_value) + 1
959
MCW_register_hint(Widget w,char * msg)960 void MCW_register_hint( Widget w , char *msg )
961 {
962 if( disable_helps ) return ;
963 if( w == NULL || msg == NULL || clueless == 1 || !XtIsWidget(w) ) return ;
964
965 if( clueless == -1 ){
966 char *hh = my_getenv("AFNI_HINTS") ;
967 if( hh != NULL && ( strncmp(hh,"KILL",4)==0 ||
968 strncmp(hh,"kill",4)==0 ||
969 strncmp(hh,"Kill",4)==0 ) ){
970 clueless = 1 ;
971 return ;
972 } else {
973 clueless = 0 ;
974 }
975 }
976
977 /*-- Do we have to make the hint-displaying widget? --*/
978
979 if( liteClue == NULL ){
980 Widget wpar = w ;
981 char *cfont ;
982
983 while( XtParent(wpar) != NULL ) wpar = XtParent(wpar) ; /* find top */
984
985 cfont = XGetDefault(XtDisplay(wpar),"AFNI","cluefont") ;
986 if( cfont == NULL ) cfont = "10x20" ; /* 08 Jan 2021 */
987 liteClue = XtVaCreatePopupShell( "help", xcgLiteClueWidgetClass, wpar,
988 RES_CONVERT(XtNfontSet,cfont) ,
989 NULL);
990 if( !RWC_liteclue_has_fontset(liteClue) ){ /* Failed :( */
991 INFO_message("\n") ;
992 INFO_message("\n Hints disabled: X11 failure to create LiteClue window") ;
993 INFO_message("\n") ;
994 clueless = 1 ;
995 return ;
996 }
997
998 XtVaSetValues( liteClue , XmNsaveUnder , True , NULL ) ; /* 22 Jan 1999 */
999 }
1000
1001 /*-- attach the hint to the widget, if it is a widget --*/
1002
1003 if( XtIsWidget(w) ) XcgLiteClueAddWidget( liteClue, w, msg, 0,0 ) ;
1004
1005 return ;
1006 }
1007
1008 /*--------------------------------------------------------------------*/
1009
MCW_reghint_children(Widget w,char * msg)1010 void MCW_reghint_children( Widget w , char *msg )
1011 {
1012 Widget *children=NULL ;
1013 int num_children=0 , ic ;
1014
1015 if( disable_helps ) return ;
1016 if( w == NULL || msg == NULL || clueless == 1 || !XtIsWidget(w) ) return ;
1017
1018 XtVaGetValues( w , XmNchildren , &children ,
1019 XmNnumChildren , &num_children , NULL ) ;
1020
1021 MCW_register_hint( w , msg ) ;
1022 if( children == NULL || num_children == 0 ) return ;
1023
1024 for( ic=0 ; ic < num_children ; ic++ )
1025 MCW_register_hint( children[ic] , msg ) ;
1026
1027 return ;
1028 }
1029 #endif /* DONT_USE_HINTS */
1030 /*------------------------------------------------------------------------*/
1031 /*------------------------------------------------------------------------*/
1032
MCW_unregister_help(Widget w)1033 void MCW_unregister_help( Widget w ) /* 24 Apr 2001 */
1034 {
1035 XtCallbackList hc=NULL ;
1036
1037 if( w == NULL ) return ;
1038 XtVaGetValues( w , XmNhelpCallback , &hc , NULL ) ;
1039 if( hc != NULL ) XtRemoveCallbacks( w , XmNhelpCallback , hc ) ;
1040 }
1041
1042 /*------------------------------------------------------------------------*/
1043
MCW_register_help(Widget w,char * msg)1044 void MCW_register_help( Widget w , char *msg )
1045 {
1046 if( disable_helps ) return ;
1047 if( w == NULL || msg == NULL ) return ;
1048 XtAddCallback( w , XmNhelpCallback , MCW_help_CB , msg ) ;
1049 return ;
1050 }
1051
1052 /*--------------------------------------------------------------------*/
1053
MCW_reghelp_children(Widget w,char * msg)1054 void MCW_reghelp_children( Widget w , char *msg )
1055 {
1056 Widget *children=NULL ;
1057 int num_children=0 , ic ;
1058
1059 if( disable_helps ) return ;
1060 if( w == NULL || msg == NULL ) return ;
1061
1062 XtVaGetValues( w , XmNchildren , &children ,
1063 XmNnumChildren , &num_children , NULL ) ;
1064
1065 XtAddCallback( w , XmNhelpCallback , MCW_help_CB , msg ) ;
1066
1067 for( ic=0 ; ic < num_children ; ic++ )
1068 XtAddCallback( children[ic] , XmNhelpCallback , MCW_help_CB , msg ) ;
1069 return ;
1070 }
1071
1072 /*------------------------------------------------------------------------*/
1073
MCW_help_CB(Widget w,XtPointer client_data,XtPointer call_data)1074 void MCW_help_CB( Widget w , XtPointer client_data , XtPointer call_data )
1075 {
1076 char *msg = (char *) client_data ;
1077 static Widget wpop = NULL , wbut = NULL ;
1078 Position xx,yy ;
1079 XmString xstr ;
1080 int ww,hh , sw,sh ;
1081 char *def ;
1082
1083 ENTRY("MCW_help_CB") ;
1084
1085 #ifndef USE_LOCATE
1086 XmAnyCallbackStruct *cbs = (XmAnyCallbackStruct *) call_data ;
1087 #endif
1088
1089 if( w == NULL ){
1090 STATUS("popdown call") ;
1091 if( wpop != NULL ) XtUnmapWidget(wpop) ;
1092 EXRETURN ;
1093 }
1094
1095 if( wpop == NULL || ! XtIsWidget(wpop) ){
1096
1097 Widget wpar = w ;
1098
1099 STATUS("create help widget") ;
1100
1101 while( XtParent(wpar) != NULL ) wpar = XtParent(wpar) ; /* find top */
1102
1103 STATUS(" create wpop") ;
1104
1105 wpop = XtVaCreatePopupShell(
1106 "help" , xmDialogShellWidgetClass , wpar ,
1107 XmNmappedWhenManaged , False ,
1108 XmNallowShellResize , True ,
1109 XmNdeleteResponse , XmDO_NOTHING ,
1110 XmNinitialResourcesPersistent , False ,
1111 NULL ) ;
1112
1113 if( wpop == NULL ){ ERROR_message("can't create help popup!"); EXRETURN; }
1114
1115 #if 0
1116 def = XGetDefault(XtDisplay(wpar),"AFNI","helpborder") ;
1117 #else
1118 def = RWC_getname(XtDisplay(wpar),"helpborder") ;
1119 #endif
1120 if( def != NULL && strcmp(def,"False") == 0 ){
1121 XtVaSetValues( wpop ,
1122 XmNoverrideRedirect , True ,
1123 NULL ) ;
1124 } else if( MCW_isitmwm(wpar) ){
1125 XtVaSetValues( wpop ,
1126 XmNmwmDecorations , MWM_DECOR_BORDER ,
1127 XmNmwmFunctions , MWM_FUNC_MOVE ,
1128 NULL ) ;
1129 }
1130
1131 STATUS(" create wbut") ;
1132
1133 wbut = XtVaCreateManagedWidget(
1134 "help" , xmPushButtonWidgetClass , wpop ,
1135 XmNalignment , XmALIGNMENT_BEGINNING ,
1136 XmNinitialResourcesPersistent , False ,
1137 NULL ) ;
1138
1139 STATUS(" add unhelp_CB") ;
1140
1141 XtAddCallback( wbut , XmNactivateCallback , MCW_unhelp_CB , wpop ) ;
1142
1143 STATUS(" update display") ;
1144
1145 XmUpdateDisplay( wpar ) ;
1146
1147 STATUS(" popdown wpop") ;
1148
1149 RWC_XtPopdown( wpop ) ;
1150
1151 STATUS(" add kill protocol") ;
1152
1153 XmAddWMProtocolCallback(
1154 wpop ,
1155 XmInternAtom( XtDisplay(wpop) , "WM_DELETE_WINDOW" , False ) ,
1156 MCW_unhelp_CB , wpop ) ;
1157
1158 if( ! XtIsRealized(wpar) ) EXRETURN ;
1159 }
1160
1161 if( msg == NULL || strlen(msg) == 0 ) EXRETURN ; /* no popup if no message */
1162
1163 xstr = XmStringCreateLtoR( msg , XmFONTLIST_DEFAULT_TAG ) ;
1164 XtVaSetValues( wbut , XmNlabelString , xstr , NULL ) ;
1165 XmStringFree( xstr ) ;
1166
1167 #ifndef USE_LOCATE
1168 if( cbs != NULL && cbs->event != NULL
1169 && cbs->event->type == ButtonRelease ){
1170 XButtonEvent *xev = (XButtonEvent *) cbs->event ;
1171 xx = xev->x_root ;
1172 yy = xev->y_root ;
1173 } else
1174 #endif
1175 XtTranslateCoords( w , 15,15 , &xx , &yy ) ; /* coordinates on root */
1176
1177 MCW_widget_geom( wpop , &ww,&hh , NULL,NULL ) ; /* widget width and height */
1178 sw = WidthOfScreen (XtScreen(wpop)) ; /* screen width and height */
1179 sh = HeightOfScreen(XtScreen(wpop)) ;
1180
1181 if( xx+ww+3 >= sw && ww <= sw ) xx = sw-ww ; /* make sure is on screen */
1182 if( yy+hh+3 >= sh && hh <= sh ) yy = sh-hh ;
1183
1184 XtVaSetValues( wpop , XmNx , (int) xx , XmNy , (int) yy , NULL ) ;
1185 XtPopup( wpop , XtGrabNone ) ; RWC_sleep(1);
1186 RWC_visibilize(wpop) ; /* 27 Sep 2000 */
1187 NORMAL_cursorize(wpop) ;
1188 EXRETURN ;
1189 }
1190
1191 /*---------------------------------------------------------------------*/
1192
MCW_unhelp_CB(Widget w,XtPointer client_data,XtPointer call_data)1193 void MCW_unhelp_CB( Widget w , XtPointer client_data , XtPointer call_data )
1194 {
1195 Widget wpop = (Widget) client_data ;
1196
1197 RWC_XtPopdown(wpop) ;
1198 return ;
1199 }
1200
1201 /*---------------------------------------------------------------------*/
1202
MCW_filetype(char * fname)1203 int MCW_filetype( char *fname )
1204 {
1205 FILE *fff ;
1206
1207 if( fname == NULL || strlen(fname) == 0 ) return MCW_nofile ;
1208
1209 fff = fopen( fname , "r+" ) ; /* open for read-update */
1210 fclose( fff ) ;
1211
1212 if( fff != NULL ) return MCW_readwrite ;
1213
1214 fff = fopen( fname , "r" ) ; /* open for read-only */
1215 fclose(fff) ;
1216
1217 if( fff != NULL ) return MCW_readonly ;
1218
1219 return MCW_nofile ;
1220 }
1221
1222 /*-------------------------------------------------------------------*/
1223
1224 #if 0
1225 RwcBoolean MCW_isitmwm( Widget w )
1226 {
1227 Widget wsh ;
1228
1229 if( w == NULL || ! XtIsWidget(w) ) return False ;
1230
1231 wsh = w ;
1232
1233 while( ! XtIsShell(wsh) ){
1234 wsh = XtParent(wsh) ;
1235 if( wsh == NULL ) return False ;
1236 }
1237
1238 #if 1
1239 return XmIsMotifWMRunning(wsh) ;
1240 #else
1241 { int immm = -73 ;
1242 XtVaGetValues( wsh , XmNmwmDecorations , &immm , NULL ) ;
1243 if( immm == -73 ) return False ;
1244 else return True ;
1245 }
1246 #endif
1247 }
1248 #endif
1249
1250 /*------------------------------------------------------------------
1251 Popup a scale that will serve as a progress meter.
1252 The meter is set initially to 0, and can later be set to any
1253 value from 0 to 100 using MCW_set_meter().
1254
1255 wparent is the widget the meter will be attached to
1256 position is one of
1257 METER_TOP = meter on top of wparent, default width
1258 METER_TOP_WIDE = meter on top of parent, width of parent
1259 METER_BOT = similar, but on bottom of parent
1260 METER_BOT_WIDE
1261 --------------------------------------------------------------------*/
1262
1263 #define METER_HEIGHT 10
1264 #define METER_WIDTH 200
1265
MCW_popup_meter(Widget wparent,int position)1266 Widget MCW_popup_meter( Widget wparent , int position )
1267 {
1268 Widget wmsg , wscal ;
1269 int wx,hy,xx,yy , xp,yp , scr_width,scr_height , xr,yr , xpr,ypr , wid ;
1270 Screen *scr ;
1271 XEvent ev ;
1272 Position xroot , yroot ;
1273
1274 ENTRY("MCW_popup_meter") ;
1275
1276 if( wparent == NULL || ! XtIsRealized(wparent) ) RETURN(NULL) ;
1277
1278 /* set position parent and screen geometry */
1279
1280 MCW_widget_geom( wparent , &wx,&hy,&xx,&yy ) ; /* geometry of parent */
1281 XtTranslateCoords( wparent, 0,0, &xroot,&yroot ) ; /* root coords of parent */
1282 xr = (int) xroot ; yr = (int) yroot ;
1283
1284 scr = XtScreen( wparent ) ;
1285 scr_width = WidthOfScreen( scr ) ;
1286 scr_height = HeightOfScreen( scr ) ;
1287
1288 switch( position ){
1289
1290 default:
1291 case METER_TOP:
1292 case METER_TOP_WIDE:
1293 xpr = xr ;
1294 ypr = yr - METER_HEIGHT-2 ;
1295 wid = (position==METER_TOP_WIDE) ? wx : METER_WIDTH ;
1296 if( ypr < 0 ) ypr = yr+hy+1 ;
1297 break ;
1298
1299 case METER_BOT:
1300 case METER_BOT_WIDE:
1301 xpr = xr ;
1302 ypr = yr+hy+1 ;
1303 wid = (position==METER_BOT_WIDE) ? wx : METER_WIDTH ;
1304 if( ypr+METER_HEIGHT > scr_height ) ypr = yr - METER_HEIGHT-2 ;
1305 break ;
1306 }
1307
1308 /* create a popup shell with a scale */
1309
1310 wmsg = XtVaCreatePopupShell(
1311 "menu" , xmDialogShellWidgetClass , wparent ,
1312 XmNx , xpr ,
1313 XmNy , ypr ,
1314 XmNborderWidth , 0 ,
1315 XmNoverrideRedirect , True ,
1316 XmNinitialResourcesPersistent , False ,
1317 NULL ) ;
1318
1319 #if 0
1320 if( MCW_isitmwm( wparent ) ){
1321 XtVaSetValues( wmsg ,
1322 XmNmwmDecorations , MWM_DECOR_BORDER ,
1323 XmNmwmFunctions , MWM_FUNC_MOVE ,
1324 NULL ) ;
1325 }
1326 #endif
1327
1328 wscal = XtVaCreateManagedWidget(
1329 "menu" , xmScaleWidgetClass , wmsg ,
1330 XmNminimum , 0 ,
1331 XmNmaximum , 100 ,
1332 XmNshowValue , False ,
1333 XmNvalue , 0 ,
1334 XmNorientation , XmHORIZONTAL ,
1335 XmNscaleWidth , wid ,
1336 XmNscaleHeight , METER_HEIGHT ,
1337 XmNborderWidth , 0 ,
1338 XmNhighlightThickness , 0 ,
1339 XmNshadowThickness , 0 ,
1340 XmNtraversalOn , True ,
1341 XmNinitialResourcesPersistent , False ,
1342 NULL ) ;
1343
1344 XtPopup( wmsg , XtGrabNone ) ; RWC_sleep(1);
1345
1346 RETURN(wscal) ;
1347 }
1348
1349 /*--------------------------------------------------------------------*/
1350
MCW_popdown_meter(Widget wscal)1351 void MCW_popdown_meter( Widget wscal )
1352 {
1353 if( wscal == NULL ) return ;
1354 XtDestroyWidget( XtParent(wscal) ) ;
1355 return ;
1356 }
1357
1358 /*--------------------------------------------------------------------*/
1359
MCW_set_meter(Widget wscal,int percent)1360 void MCW_set_meter( Widget wscal , int percent )
1361 {
1362 int val , old ;
1363
1364 #undef NCOL
1365 #define NCOL 30
1366 #ifdef NCOL
1367 static int icol=0 ;
1368 static char *cname[] = {
1369 "#0000ff", "#3300ff", "#6600ff", "#9900ff", "#cc00ff",
1370 "#ff00ff", "#ff00cc", "#ff0099", "#ff0066", "#ff0033",
1371 "#ff0000", "#ff3300", "#ff6600", "#ff9900", "#ffcc00",
1372 "#ffff00", "#ccff00", "#99ff00", "#66ff00", "#33ff00",
1373 "#00ff00", "#00ff33", "#00ff66", "#00ff99", "#00ffcc",
1374 "#00ffff", "#00ccff", "#0099ff", "#0066ff", "#0033ff"
1375 } ;
1376 #endif
1377
1378 val = percent ;
1379 if( wscal == NULL || val < 0 || val > 100 ) return ;
1380
1381 XmScaleGetValue( wscal , &old ) ; if( val == old ) return ;
1382
1383 XtVaSetValues( wscal , XmNvalue , val , NULL ) ;
1384
1385 #ifdef NCOL
1386 { Widget ws = XtNameToWidget(wscal,"Scrollbar") ;
1387 if( ws != NULL )
1388 XtVaSetValues( ws ,
1389 XtVaTypedArg , XmNtroughColor , XmRString ,
1390 cname[icol] , strlen(cname[icol])+1 ,
1391 NULL ) ;
1392 icol = (icol+1) % NCOL ;
1393 }
1394 #endif
1395
1396 XmUpdateDisplay(wscal) ;
1397 return ;
1398 }
1399
1400 /*------------------------------------------------------------------------*/
1401
1402 #if 0
1403 static void MCW_textwin_timer_CB( XtPointer client_data , XtIntervalId *id )
1404 {
1405 Widget ws = (Widget)client_data ;
1406 XtVaSetValues( ws , XmNincrement , 1 ,
1407 XmNpageIncrement , 1 ,
1408 XmNmaximum , 100 , NULL ) ;
1409 }
1410 #endif
1411
1412 /*-----------------------------------------------------------------------*/
1413
1414 #define RONLY_NUM 1
1415 #define EDIT_NUM 2
1416
1417 static MCW_action_item TWIN_act[] = {
1418 { "Quit" , MCW_textwin_CB , NULL , NULL , "Close window" , 0 } ,
1419 { "Set" , MCW_textwin_CB , NULL , NULL , "Apply choice and close window" , 0 }
1420 } ;
1421
new_MCW_textwin(Widget wpar,char * msg,int type)1422 MCW_textwin * new_MCW_textwin( Widget wpar, char *msg, int type )
1423 {
1424 return new_MCW_textwin_2001( wpar,msg,type , NULL,NULL ) ;
1425 }
1426
1427 static int bigtext = 0 ;
MCW_textwin_setbig(int b)1428 void MCW_textwin_setbig( int b ){ bigtext = b ; } /* 29 Apr 2009 */
1429
1430 /*-----------------------------------------------------------------------
1431 Modified 10 Jul 2001 to include killing callback
1432 -------------------------------------------------------------------------*/
1433
new_MCW_textwin_2001(Widget wpar,char * msg,int type,void_func * kill_func,XtPointer kill_data)1434 MCW_textwin * new_MCW_textwin_2001( Widget wpar, char *msg, int type,
1435 void_func *kill_func , XtPointer kill_data )
1436 {
1437 MCW_textwin *tw ;
1438 int wx,hy,xx,yy , xp,yp , scr_width,scr_height , xr,yr , xpr,ypr , ii,nact ;
1439 int swid , shi ;
1440 Position xroot , yroot ;
1441 Screen *scr ;
1442 RwcBoolean editable , cursorable ;
1443 Arg wa[64] ; int na ; Widget ws ;
1444 char *wtype = "menu" ;
1445
1446 ENTRY("new_MCW_textwin_2001") ;
1447
1448 /*-- sanity check --*/
1449
1450 if( wpar == NULL || !XtIsRealized(wpar) ) RETURN(NULL) ;
1451
1452 if( bigtext > 0 ) wtype = "bigtext" ; /* 29 Apr 2009 */
1453 else if( bigtext < 0 ) wtype = "font8" ;
1454 bigtext = 0 ;
1455
1456 /* set position based on parent and screen geometry */
1457
1458 MCW_widget_geom( wpar , &wx,&hy,&xx,&yy ) ; /* geometry of parent */
1459 XtTranslateCoords( wpar, 0,0, &xroot,&yroot ) ; /* root coords */
1460 xr = (int) xroot ; yr = (int) yroot ;
1461
1462 scr = XtScreen(wpar) ;
1463 scr_width = WidthOfScreen(scr) ;
1464 scr_height = HeightOfScreen(scr) ;
1465
1466 xp = xx+8 ; xpr = xr+8 ;
1467 if( xpr+50 > scr_width ){ xp -= 100 ; xpr -= 100 ; } /* too right */
1468 else if( xpr+10 < 0 ) { xpr = xp = 1 ; } /* too left */
1469
1470 yp = yy+hy+8 ; ypr = yr+hy+8 ;
1471 if( ypr+50 > scr_height ){ yp = yy-8 ; ypr = yr-100 ;} /* too down */
1472 else if( ypr+10 < 0 ) { ypr = yp = 1 ; } /* too up */
1473
1474 /* create a popup shell */
1475
1476 tw = myXtNew(MCW_textwin) ;
1477
1478 tw->kill_func = kill_func ; /* 10 Jul 2001 */
1479 tw->kill_data = kill_data ;
1480
1481 tw->wshell = XtVaCreatePopupShell(
1482 wtype , xmDialogShellWidgetClass , wpar ,
1483 XmNx , xpr ,
1484 XmNy , ypr ,
1485 XmNborderWidth , 0 ,
1486 XmNborderColor , 0 ,
1487 XmNinitialResourcesPersistent , False ,
1488 NULL ) ;
1489
1490 XmAddWMProtocolCallback(
1491 tw->wshell ,
1492 XmInternAtom( XtDisplay(tw->wshell) , "WM_DELETE_WINDOW" , False ) ,
1493 MCW_textwinkill_CB , (XtPointer) tw ) ;
1494
1495 /* create a form to hold everything else */
1496
1497 tw->wtop = XtVaCreateWidget(
1498 wtype , xmFormWidgetClass , tw->wshell ,
1499 XmNborderWidth , 0 ,
1500 XmNborderColor , 0 ,
1501 XmNtraversalOn , True ,
1502 XmNinitialResourcesPersistent , False ,
1503 NULL ) ;
1504
1505 /* create action area */
1506
1507 editable = (RwcBoolean) (type == TEXT_EDITABLE) ;
1508 cursorable = True ; /* 26 Feb 2007 */
1509
1510 nact = (editable) ? EDIT_NUM : RONLY_NUM ;
1511 for( ii=0 ; ii < nact ; ii++ ){
1512 TWIN_act[ii].data = (XtPointer) tw ;
1513 TWIN_act[ii].make_red = 0 ;
1514 }
1515 TWIN_act[nact-1].make_red = 1 ;
1516
1517 tw->wactar = MCW_action_area( tw->wtop , TWIN_act , nact ) ;
1518
1519 /* create text area */
1520
1521 tw->wscroll = XtVaCreateManagedWidget(
1522 wtype , xmScrolledWindowWidgetClass , tw->wtop ,
1523 XmNscrollingPolicy , XmAUTOMATIC ,
1524 XmNvisualPolicy , XmVARIABLE ,
1525 XmNscrollBarDisplayPolicy , XmAS_NEEDED ,
1526
1527 XmNleftAttachment , XmATTACH_FORM ,
1528 XmNrightAttachment , XmATTACH_FORM ,
1529 XmNbottomAttachment, XmATTACH_FORM ,
1530 XmNtopAttachment , XmATTACH_WIDGET ,
1531 XmNtopWidget , tw->wactar ,
1532 XmNtopOffset , 7 ,
1533
1534 XmNinitialResourcesPersistent , False ,
1535 NULL ) ;
1536
1537 XtVaSetValues( tw->wactar ,
1538 XmNleftAttachment , XmATTACH_FORM ,
1539 XmNrightAttachment, XmATTACH_FORM ,
1540 XmNtopAttachment , XmATTACH_FORM ,
1541 XmNtopOffset , 7 ,
1542 NULL ) ;
1543
1544 tw->wtext = XtVaCreateManagedWidget(
1545 wtype , xmTextWidgetClass , tw->wscroll ,
1546 XmNeditMode , XmMULTI_LINE_EDIT ,
1547 XmNautoShowCursorPosition , cursorable ,
1548 XmNeditable , editable ,
1549 XmNcursorPositionVisible , cursorable ,
1550 NULL ) ;
1551
1552 if( msg == NULL ) msg = "\0" ; /* 27 Sep 2000 */
1553
1554 if( msg != NULL ){
1555 int cmax = 20 , ll , nlin ;
1556 char *cpt , *cold , cbuf[128] ;
1557 XmString xstr=NULL ;
1558 XmFontList xflist=NULL ;
1559
1560 /* In lesstif, the text length is limited by the XmTextGetMaxLength
1561 * resource, however setting it via XmTextSetMaxLength does not work.
1562 * The string lengths seems to be limited to perhaps 100, even though
1563 * XmTextGetMaxLength might return 256.
1564 *
1565 * The solution is to use XmTextSetString(w, str) to set the text.
1566 * After that, XmTextGetMaxLength returns an updated value.
1567 *
1568 * 31 Dec, 2008 [lesstif patrol] */
1569 #ifdef USING_LESSTIF
1570 XmTextSetString( tw->wtext , msg ) ;
1571 #else
1572 XtVaSetValues( tw->wtext , XmNvalue , msg , NULL ) ;
1573 #endif
1574
1575 XtVaGetValues( tw->wtext , XmNfontList , &xflist , NULL ) ;
1576
1577 cmax = 20 ; nlin = 1 ;
1578 for( cpt=msg,cold=msg ; *cpt != '\0' ; cpt++ ){
1579 if( *cpt == '\n' ){
1580 ll = cpt - cold - 1 ; if( cmax < ll ) cmax = ll ;
1581 cold = cpt ; nlin++ ;
1582 }
1583 }
1584 ll = cpt - cold - 1 ; if( cmax < ll ) cmax = ll ;
1585 if( cmax > 100 ) cmax = 100 ;
1586 cmax +=3 ;
1587 for( ll=0 ; ll < cmax ; ll++ ) cbuf[ll] = 'x' ;
1588 cbuf[cmax] = '\0' ;
1589
1590 xstr = XmStringCreateLtoR( cbuf , XmFONTLIST_DEFAULT_TAG ) ;
1591 swid = XmStringWidth ( xflist , xstr ) + 44 ;
1592 shi = XmStringHeight( xflist , xstr ) * nlin + 66 ;
1593 XmStringFree( xstr ) ;
1594
1595 cmax = WidthOfScreen(XtScreen(wpar)) - 128 ;
1596 if( swid > cmax ) swid = cmax ;
1597
1598 cmax = HeightOfScreen(XtScreen(wpar)) - 128 ;
1599 if( shi > cmax ) shi = cmax ;
1600 } else {
1601 swid = shi = 100 ;
1602 }
1603
1604 XtManageChild( tw->wtop ) ;
1605
1606 XtVaSetValues( tw->wshell , XmNwidth,swid , XmNheight,shi , NULL ) ;
1607
1608 XtPopup( tw->wshell , XtGrabNone ) ; RWC_sleep(1);
1609
1610 RWC_visibilize_widget( tw->wshell ) ; /* 09 Nov 1999 */
1611
1612 RWC_xineramize( XtDisplay(tw->wshell) ,
1613 xpr,ypr,swid,shi , &xpr,&ypr ); /* 27 Sep 2000 */
1614
1615 XtVaSetValues( tw->wshell, XmNx,xpr , XmNy,ypr , NULL ) ;
1616
1617 tw->shell_width = swid ; tw->shell_height = shi ; /* 10 Jul 2001 */
1618
1619 NORMAL_cursorize( tw->wshell ) ;
1620
1621 ws = XtNameToWidget(tw->wscroll,"VertScrollBar") ;
1622 if( ws != NULL ){
1623 #ifdef DARWIN
1624 XtVaSetValues( ws , XmNshowArrows , XmMIN_SIDE , NULL ) ;
1625 #endif
1626 (void)XmProcessTraversal( ws , XmTRAVERSE_CURRENT ) ;
1627 #if 0
1628 (void)XtAppAddTimeOut( XtWidgetToApplicationContext(ws) ,
1629 66 , MCW_textwin_timer_CB , ws ) ;
1630 #endif
1631 }
1632 #ifdef DARWIN
1633 ws = XtNameToWidget(tw->wscroll,"HorScrollBar") ;
1634 if( ws != NULL )
1635 XtVaSetValues( ws , XmNshowArrows , XmMIN_SIDE , NULL ) ;
1636 #endif
1637
1638 RETURN(tw) ;
1639 }
1640
1641 /*--------------------------------------------------------------------*/
1642
MCW_textwin_alter(MCW_textwin * tw,char * mmm)1643 void MCW_textwin_alter( MCW_textwin *tw , char *mmm ) /* 10 Jul 2001 */
1644 {
1645 int swid , shi ;
1646 char *msg = mmm ;
1647 int cmax = 20 , ll , nlin ;
1648 char *cpt , *cold , cbuf[128] ;
1649 XmString xstr ;
1650 XmFontList xflist=(XmFontList)NULL ;
1651
1652 ENTRY("MCW_textwin_alter") ;
1653
1654 if( tw == NULL ) EXRETURN ; /* bad */
1655
1656 if( msg == NULL ) msg = " " ; /* don't let user be so stupid */
1657
1658 #if 0
1659 /*-- compute size of text window with new message in it --*/
1660
1661 XtVaGetValues( tw->wtext , XmNfontList , &xflist , NULL ) ;
1662
1663 /* find longest line in msg */
1664
1665 cmax = 20 ; nlin = 1 ;
1666 for( cpt=msg,cold=msg ; *cpt != '\0' ; cpt++ ){
1667 if( *cpt == '\n' ){
1668 ll = cpt - cold - 1 ; if( cmax < ll ) cmax = ll ;
1669 cold = cpt ; nlin++ ;
1670 }
1671 }
1672 ll = cpt - cold - 1 ; if( cmax < ll ) cmax = ll ;
1673 if( cmax > 100 ) cmax = 100 ;
1674
1675 /* fill a dummy string of that length, plus a bit */
1676
1677 cmax+=3 ;
1678 for( ll=0 ; ll < cmax ; ll++ ) cbuf[ll] = 'x' ;
1679 cbuf[cmax] = '\0' ;
1680
1681 /* find width, height of the dummy string */
1682
1683 xstr = XmStringCreateLtoR( cbuf , XmFONTLIST_DEFAULT_TAG ) ;
1684 swid = XmStringWidth ( xflist , xstr ) + 44 ;
1685 shi = XmStringHeight( xflist , xstr ) * nlin + 66 ;
1686 XmStringFree( xstr ) ;
1687
1688 /* find width, height of screen */
1689
1690 cmax = WidthOfScreen(XtScreen(tw->wshell)) - 128 ;
1691 if( swid > cmax ) swid = cmax ;
1692
1693 cmax = HeightOfScreen(XtScreen(tw->wshell)) - 128 ;
1694 if( shi > cmax ) shi = cmax ;
1695 #endif
1696
1697 /*-- actually set new text --*/
1698
1699 XtVaSetValues( tw->wtext , XmNvalue , msg , NULL ) ;
1700
1701 #if 1
1702 MCW_widget_geom( tw->wtext , &swid , &shi , NULL,NULL ) ;
1703 XtVaSetValues( tw->wshell , XmNwidth,swid+29 , XmNheight,shi+59 , NULL ) ;
1704 tw->shell_width = swid+29 ; tw->shell_height = shi+59 ;
1705 #endif
1706
1707 #if 0
1708 /*-- maybe set new window size --*/
1709
1710 if( swid > tw->shell_width || shi > tw->shell_height ){
1711 tw->shell_width = swid = MAX( swid , tw->shell_width ) ;
1712 tw->shell_height = shi = MAX( shi , tw->shell_height ) ;
1713 XtVaSetValues( tw->wshell , XmNwidth,swid , XmNheight,shi , NULL ) ;
1714 }
1715 #endif
1716
1717 EXRETURN ;
1718 }
1719
1720 /*--------------------------------------------------------------------*/
1721
MCW_textwin_CB(Widget w,XtPointer client_data,XtPointer call_data)1722 void MCW_textwin_CB( Widget w , XtPointer client_data , XtPointer call_data )
1723 {
1724 MCW_textwin *tw = (MCW_textwin *) client_data ;
1725 char *wname = XtName(w) ;
1726
1727 if( client_data == NULL ) return ;
1728
1729 if( strcmp(wname,"Quit") == 0 ){
1730 if( tw->kill_func != NULL )
1731 #if 0
1732 tw->kill_func(tw->kill_data); /* 10 Jul 2001 */
1733 #else
1734 AFNI_CALL_VOID_1ARG( tw->kill_func , XtPointer , tw->kill_data ) ;
1735 #endif
1736 XtDestroyWidget( tw->wshell ) ;
1737 myXtFree( tw ) ;
1738 return ;
1739 }
1740
1741 XBell( XtDisplay(w) , 100 ) ;
1742 return ;
1743 }
1744
1745 /*--------------------------------------------------------------------*/
1746
MCW_textwinkill_CB(Widget w,XtPointer client_data,XtPointer call_data)1747 void MCW_textwinkill_CB( Widget w , XtPointer client_data , XtPointer call_data )
1748 {
1749 MCW_textwin *tw = (MCW_textwin *) client_data ;
1750
1751 if( tw->kill_func != NULL )
1752 #if 0
1753 tw->kill_func(tw->kill_data); /* 10 Jul 2001 */
1754 #else
1755 AFNI_CALL_VOID_1ARG( tw->kill_func , XtPointer , tw->kill_data ) ;
1756 #endif
1757 XtDestroyWidget( tw->wshell ) ;
1758 myXtFree( tw ) ;
1759 return ;
1760 }
1761
1762 /*-----------------------------------------------------------------------
1763 03 Jan 1999: Check if a widget is potentially visible
1764 -- return 0 if not, 1 if yes.
1765 -------------------------------------------------------------------------*/
1766
MCW_widget_visible(Widget w)1767 int MCW_widget_visible( Widget w )
1768 {
1769 Window ww ;
1770 XWindowAttributes wa ;
1771
1772 if( w == (Widget)NULL ) return 0 ;
1773 ww = XtWindow(w) ;
1774 if( ww == (Window)NULL ) return 0 ;
1775
1776 XGetWindowAttributes( XtDisplay(w) , ww , &wa ) ;
1777
1778 return ( (wa.map_state == IsViewable) ? 1 : 0 ) ;
1779 }
1780
1781 /*------------------------------------------------------------------
1782 June 1999: routine to get string constants either from X defaults
1783 or from Unix environment variables. Returns a pointer
1784 to static storage -- do not free()!
1785 --------------------------------------------------------------------*/
1786
1787 #include <ctype.h>
1788
RWC_getname(Display * display,char * name)1789 char * RWC_getname( Display *display , char *name )
1790 {
1791 char *cval , qqq[256] ;
1792 int nn , ii ;
1793
1794 if( name == NULL || name[0] == '\0' ) return NULL ;
1795
1796 /* try X11 */
1797
1798 if( display != NULL ){
1799 cval = XGetDefault(display,"AFNI",name) ;
1800 if( cval != NULL ) return cval ;
1801 }
1802
1803 /* try AFNI_name */
1804
1805 strcpy(qqq,"AFNI_") ; strcat(qqq,name) ;
1806 cval = my_getenv(qqq) ;
1807 if( cval != NULL ) return cval ;
1808
1809 /* try AFNI_NAME (uppercase it) */
1810
1811 strcpy(qqq,"AFNI_") ; nn = strlen(name) ;
1812 for( ii=0 ; ii < nn && ii < 250 ; ii++ ) qqq[ii+5] = toupper(name[ii]) ;
1813 qqq[ii+5] = '\0' ;
1814 cval = my_getenv(qqq) ;
1815 return cval ;
1816 }
1817
1818 /*-------------------------------------------------------------------
1819 09 Nov 1999: move a widget to make sure it is visible
1820 ---------------------------------------------------------------------*/
1821
RWC_visibilize_widget(Widget w)1822 void RWC_visibilize_widget( Widget w )
1823 {
1824 Position xroot , yroot ;
1825 int wx,hy,xx,yy , scr_width,scr_height , xo,yo ;
1826 Screen *scr ;
1827
1828 ENTRY("RWC_visibilize_widget") ;
1829
1830 if( w == NULL || !XtIsWidget(w) ) EXRETURN ;
1831
1832 MCW_widget_geom( w , &wx,&hy,&xx,&yy ) ; /* geometry of widget */
1833
1834 scr = XtScreen( w ) ;
1835 scr_width = WidthOfScreen( scr ) ;
1836 scr_height = HeightOfScreen( scr ) ;
1837
1838 xo = xx ; yo = yy ; /* save original position */
1839
1840 if( xx+wx > scr_width ) xx = scr_width - wx ;
1841 if( xx < 0 ) xx = 0 ;
1842
1843 if( yy+hy > scr_height ) yy = scr_height - hy ;
1844 if( yy < 0 ) yy = 0 ;
1845
1846 RWC_xineramize( XtDisplay(w) , xx,yy,wx,hy , &xx,&yy ); /* 27 Sep 2000 */
1847
1848 if( xx != xo || yy != yo )
1849 XtVaSetValues( w , XmNx , xx , XmNy , yy , NULL ) ;
1850
1851 RWC_sleep(1) ; MCW_expose_widget(w) ; /* 09 Nov 2007 */
1852
1853 EXRETURN ;
1854 }
1855
1856 /*----------------------------------------------------------------------
1857 A callback version of the above (for use when menus are mapped, say)
1858 ------------------------------------------------------------------------*/
1859
RWC_visibilize_timeout_CB(XtPointer cd,XtIntervalId * id)1860 static void RWC_visibilize_timeout_CB( XtPointer cd , XtIntervalId *id )
1861 {
1862 Widget w = (Widget) cd ;
1863 ENTRY("RWC_visibilize_timeout_CB") ;
1864 RWC_visibilize_widget(w) ; EXRETURN ;
1865 }
1866
1867 /*--------------------------------------------------------------------*/
1868
RWC_visibilize_CB(Widget w,XtPointer cd,XtPointer cb)1869 void RWC_visibilize_CB( Widget w , XtPointer cd , XtPointer cb )
1870 {
1871 Widget wpar = w ;
1872 ENTRY("RWC_visibilize_CB") ;
1873
1874 if( AFNI_yesenv("AFNI_DONT_MOVE_MENUS") ) return ; /* 08 Aug 2001 */
1875
1876 while( !XtIsShell(wpar) ){ wpar = XtParent(w); } /* find 1st shell parent */
1877
1878 /* must wait for the thing to actually appear, dammit */
1879
1880 (void) XtAppAddTimeOut( XtWidgetToApplicationContext(wpar) ,
1881 3 , RWC_visibilize_timeout_CB , wpar ) ;
1882 EXRETURN ;
1883 }
1884
1885 /*----------------------------------------------------------------------
1886 Given a rectangle (xx..xx+ww,yy..yy+hh), return the new origin
1887 (xn,yn) so that the rectangle (xn..xn+ww,yn..yn+hh) fits onto
1888 a single Xinerama sub-screen. If the AFNI.xinerama X11 resource is
1889 not found, then this routine uses the display size.
1890 -- RWCox -- 27 Sep 2000
1891 ------------------------------------------------------------------------*/
1892
1893 #define BUF 5 /* buffer around the rectangle */
1894
RWC_xineramize(Display * dpy,int xx,int yy,int ww,int hh,int * xn,int * yn)1895 void RWC_xineramize( Display *dpy,
1896 int xx, int yy, int ww, int hh, int *xn, int *yn )
1897 {
1898 static int first=1 ;
1899 static int nxsi=0 , *xbot,*ybot,*xtop,*ytop ;
1900 int ii , ss ;
1901
1902 ENTRY("RWC_xineramize") ;
1903
1904 if( dpy==NULL || xn==NULL || yn==NULL || ww<0 || hh<0 ) EXRETURN; /* ERROR */
1905
1906 /*--- first time in: check AFNI.xinerama X resource
1907 load boundaries of sub-screens from resource ---*/
1908
1909 if( first ){
1910 char *xdef , *xp ;
1911 int nn,xorg,yorg,wide,high ;
1912
1913 first = 0 ; /* never again */
1914 xdef = getenv( "AFNI_XINERAMA" ) ;
1915
1916 if( xdef != NULL && (xdef[0] == 'N' || xdef[0] == 'n') ){ /* skip Xinerama */
1917 nxsi = 0 ;
1918 STATUS("AFNI_XINERAMA is NO") ;
1919 } else {
1920 xdef = XGetDefault(dpy,"AFNI","xinerama") ; /* get resource */
1921 if( xdef == NULL ) xdef = getenv("AFNI_xinerama") ; /* 27 Oct 2003 */
1922 if( xdef != NULL ){
1923 char *qdef = strdup(xdef) ;
1924 for( nn=0 ; qdef[nn] != '\0' ; nn++ )
1925 if( qdef[nn] == '_' || qdef[nn] == ':' ||
1926 qdef[nn] == ';' || qdef[nn] == ',' ) qdef[nn] = ' ' ;
1927
1928 nn = 0 ; sscanf(qdef,"%d%n",&nxsi,&nn) ; /* number of sub-screens */
1929 if( nn <= 0 || nxsi <= 1 ){ /* ERROR */
1930 nxsi = 0 ;
1931 } else {
1932 xbot = (int *) malloc(sizeof(int)*nxsi) ; /* make arrays to */
1933 ybot = (int *) malloc(sizeof(int)*nxsi) ; /* store sub-screen */
1934 xtop = (int *) malloc(sizeof(int)*nxsi) ; /* coordinate ranges */
1935 ytop = (int *) malloc(sizeof(int)*nxsi) ;
1936 xp = qdef + nn ;
1937 for( ii=0 ; ii < nxsi ; ii++ ){ /* scan for sub-screen info */
1938 nn = 0 ;
1939 sscanf(xp,"%d%d%d%d%d%n",&ss,&xorg,&yorg,&wide,&high,&nn) ;
1940 if( nn <= 0 ) break ; /* ERROR */
1941 xbot[ii] = xorg ; xtop[ii] = xorg+wide ;
1942 ybot[ii] = yorg ; ytop[ii] = yorg+high ;
1943 xp += nn ;
1944
1945 if(PRINT_TRACING){
1946 char str[256] ;
1947 sprintf(str," Screen %d: xbot=%4d ybot=%4d xtop=%4d ytop=%4d",
1948 ii,xbot[ii],ybot[ii],xtop[ii],ytop[ii] ) ;
1949 STATUS(str) ;
1950 }
1951 }
1952
1953 nxsi = ii ; /* in case the scan aborted */
1954 }
1955 }
1956 }
1957
1958 /* if nothing found yet, use the display size */
1959
1960 if( nxsi <= 0 ){
1961 nxsi = 1 ;
1962 xbot = (int *) malloc(sizeof(int)*nxsi) ;
1963 ybot = (int *) malloc(sizeof(int)*nxsi) ;
1964 xtop = (int *) malloc(sizeof(int)*nxsi) ;
1965 ytop = (int *) malloc(sizeof(int)*nxsi) ;
1966 xbot[0] = ybot[0] = 0 ;
1967 xtop[0] = WidthOfScreen(DefaultScreenOfDisplay(dpy)) ;
1968 ytop[0] = HeightOfScreen(DefaultScreenOfDisplay(dpy)) ;
1969 }
1970 }
1971
1972 #if 0 /* doesn't occur anymore */
1973 if( nxsi == 0 ){ *xn=xx; *yn=yy; EXRETURN; } /* not setup? change nothing */
1974 #endif
1975
1976 /*--- find the Xinerama sub-screen that (xx,yy) is on (if any) ---*/
1977
1978 if( nxsi > 1 ){
1979 for( ss=0 ; ss < nxsi ; ss++ ){
1980 if( xx >= xbot[ss] && xx < xtop[ss] &&
1981 yy >= ybot[ss] && yy < ytop[ss] ) break ;
1982 }
1983 } else {
1984 ss = 0 ; /* must use #0 - what else is there? */
1985 }
1986
1987 if(PRINT_TRACING){
1988 char str[256] ;
1989 sprintf(str,"Rect: xx=%d yy=%d ww=%d hh=%d; On ss=%d",xx,yy,ww,hh,ss); STATUS(str);
1990 }
1991
1992 /*--- if not inside any screen, find one it is closest to ---*/
1993
1994 if( ss >= nxsi ){
1995 int dleft,dright,dtop,dbot,dd , dmin , xdif,ydif ;
1996 dmin = 123456789 ; ss = 0 ;
1997 for( ii=0 ; ii < nxsi; ii++ ){
1998 xdif = (xx < xbot[ii]) ? (xbot[ii]-xx) /* x dist to */
1999 :(xx > xtop[ii]) ? (xx-xtop[ii]) : 0 ; /* [xbot..xtop] */
2000
2001 ydif = (yy < ybot[ii]) ? (ybot[ii]-yy)
2002 :(yy > ytop[ii]) ? (yy-ytop[ii]) : 0 ;
2003
2004 dleft = abs(xx-xbot[ii]) + ydif ; /* L1 dist to left edge */
2005 dright = abs(xx-xtop[ii]) + ydif ;
2006 dbot = abs(yy-ybot[ii]) + xdif ;
2007 dtop = abs(yy-ytop[ii]) + xdif ;
2008
2009 dd = dleft ; /* find smallest dist */
2010 if( dright < dd ) dd = dright ;
2011 if( dbot < dd ) dd = dbot ;
2012 if( dtop < dd ) dd = dtop ;
2013
2014 if( dd < dmin ){ dmin = dd; ss = ii; } /* smallest so far? */
2015 }
2016
2017 if(PRINT_TRACING){
2018 char str[256] ; sprintf(str,"New ss=%d",ss) ; STATUS(str) ;
2019 }
2020 }
2021
2022 /*--- now adjust position so all of rectangle
2023 (xx..xx+ww,yy..yy+hh) fits on that screen (if possible) ---*/
2024
2025 if( xx+ww+BUF >= xtop[ss] ){ xx = xtop[ss]-ww-1-2*BUF; } /* move left */
2026 if( yy+hh+BUF >= ytop[ss] ){ yy = ytop[ss]-hh-1-2*BUF; } /* move up */
2027 if( xx < xbot[ss]+BUF ){ xx = xbot[ss]+BUF; } /* move right */
2028 if( yy < ybot[ss]+BUF ){ yy = ybot[ss]+BUF; } /* move down */
2029
2030
2031 if(PRINT_TRACING){
2032 char str[256] ; sprintf(str,"New xx=%d yy=%d",xx,yy) ; STATUS(str) ;
2033 }
2034
2035 *xn = xx ; *yn = yy ; EXRETURN ;
2036 }
2037
2038 /*----------------------------------------------------------------------
2039 NULL out a pointer when a widget is destroyed -- 31 Jul 2001 - RWCox
2040 ------------------------------------------------------------------------*/
2041
RWC_destroy_nullify_CB(Widget w,XtPointer xp,XtPointer cd)2042 void RWC_destroy_nullify_CB( Widget w, XtPointer xp, XtPointer cd )
2043 {
2044 void ** p = (void **) xp ;
2045 ENTRY("RWC_destroy_nullify_CB") ;
2046 if( p != NULL ) *p = NULL ;
2047 EXRETURN ;
2048 }
2049
RWC_destroy_nullify(Widget w,void ** p)2050 void RWC_destroy_nullify( Widget w, void **p )
2051 {
2052 if( p != NULL && w != NULL )
2053 XtAddCallback( w, XmNdestroyCallback, RWC_destroy_nullify_CB, p ) ;
2054 return ;
2055 }
2056
RWC_destroy_nullify_cancel(Widget w,void ** p)2057 void RWC_destroy_nullify_cancel( Widget w, void **p )
2058 {
2059 if( w != NULL )
2060 XtRemoveCallback( w, XmNdestroyCallback, RWC_destroy_nullify_CB, p ) ;
2061 return ;
2062 }
2063
2064 /*---------------------------------------------------------------------------*/
2065
RWC_draw_rect(Display * dis,Window win,GC gc,int x1,int y1,int x2,int y2)2066 static void RWC_draw_rect( Display *dis, Window win, GC gc,
2067 int x1, int y1, int x2, int y2 )
2068 {
2069 int xb,yb , xt,yt ;
2070 unsigned int short w,h ;
2071
2072 if( x1 < x2 ){ xb=x1; xt=x2; } else { xb=x2; xt=x1; }
2073 if( y1 < y2 ){ yb=y1; yt=y2; } else { yb=y2; yt=y1; }
2074 w = xt-xb ; h = yt-yb ;
2075 if( w || h )
2076 XDrawRectangle( dis,win,gc , xb,yb,w,h ) ;
2077 else
2078 XDrawPoint( dis,win,gc , xb,yb ) ;
2079 }
2080
2081 /*---------------------------------------------------------------------------*/
2082
2083 static Cursor cur = None ; /* 17 Jun 2002 */
2084
RWC_drag_cursor(Display * dis)2085 static void RWC_drag_cursor( Display *dis )
2086 {
2087 XColor fg , bg ;
2088 Colormap cmap ;
2089 RwcBoolean good ;
2090
2091 if( cur == None ){
2092 cur = XCreateFontCursor( dis , XC_arrow ) ;
2093 cmap = DefaultColormap( dis , DefaultScreen(dis) ) ;
2094 good = XParseColor( dis, cmap, "yellow" , &fg )
2095 && XParseColor( dis, cmap, "red" , &bg ) ;
2096 if( good ) XRecolorCursor( dis , cur , &fg , &bg ) ;
2097 }
2098 }
2099
RWC_drag_rectangle(Widget w,int x1,int y1,int * x2,int * y2)2100 void RWC_drag_rectangle( Widget w, int x1, int y1, int *x2, int *y2 )
2101 {
2102 Display *dis ;
2103 Window win , rW,cW ;
2104 int grab , xold,yold , x,y, rx,ry , first=1 ;
2105 unsigned int mask ; /* which buttons */
2106 unsigned int bmask=Button1Mask|Button2Mask|Button3Mask ; /* all buttons */
2107 XGCValues gcv;
2108 GC myGC ;
2109
2110 ENTRY("RWC_drag_rectangle") ;
2111
2112 /** make a GC for invert drawing **/
2113
2114 gcv.function = GXinvert ;
2115 myGC = XtGetGC( w , GCFunction , &gcv ) ;
2116
2117 /** grab the pointer (so no one else gets events from it),
2118 and confine it to the window in question **/
2119
2120 dis = XtDisplay(w) ; win = XtWindow(w) ;
2121
2122 RWC_drag_cursor(dis) ;
2123
2124 grab = !XGrabPointer(dis, win, False, 0, GrabModeAsync,
2125 GrabModeAsync, win, cur , (Time)CurrentTime);
2126
2127 /* grab fails => exit */
2128
2129 if( !grab ){ XBell(dis,100); *x2=x1; *y2=y1; EXRETURN; }
2130
2131 xold = x1 ; yold = y1 ; /* current location of pointer */
2132
2133 /** loop and find out where the pointer is (while button is down) **/
2134
2135 while( XQueryPointer(dis,win,&rW,&cW,&rx,&ry,&x,&y,&mask) ){
2136
2137 /* check if all buttons are released */
2138
2139 if( !(mask & bmask) ) break ; /* no button down => done! */
2140
2141 /* pointer now at (x,y) in the window */
2142
2143 /* if it has moved, redraw rectangle */
2144
2145 if( x != xold || y != yold ){
2146
2147 if( !first ) /* undraw old rectangle */
2148 RWC_draw_rect( dis,win,myGC , x1,y1 , xold,yold ) ;
2149
2150 /* draw new rectangle */
2151
2152 xold = x ; yold = y ; first = 0 ;
2153 RWC_draw_rect( dis,win,myGC , x1,y1 , xold,yold ) ;
2154
2155 } /* end of new (x,y) position */
2156
2157 } /* end of loop while button is pressed */
2158
2159 if( !first ) /* undraw old rectangle */
2160 RWC_draw_rect( dis,win,myGC , x1,y1 , xold,yold ) ;
2161
2162 /* clean up */
2163
2164 XtReleaseGC( w , myGC ) ;
2165 if (grab) XUngrabPointer(dis, (Time)CurrentTime) ;
2166
2167 *x2 = xold ; *y2 = yold ; /* output values */
2168 EXRETURN ;
2169 }
2170
2171 /*---------------------------------------------------------------------------*/
2172
RWC_draw_circle(Display * dis,Window win,GC gc,int xc,int yc,int rad)2173 static void RWC_draw_circle( Display *dis, Window win, GC gc, int xc, int yc, int rad )
2174 {
2175 int xb,yb ;
2176 unsigned int ww ;
2177
2178 if( rad < 0 ) rad = 0 ;
2179 xb = xc-rad ; yb = yc-rad ; ww = 2*rad ;
2180 XDrawArc( dis,win,gc , xb,yb , ww,ww , 0,360*64 ) ;
2181 }
2182
2183 /*---------------------------------------------------------------------------*/
2184
RWC_drag_circle(Widget w,int x1,int y1,int * radius)2185 void RWC_drag_circle( Widget w, int x1, int y1, int *radius )
2186 {
2187 Display *dis ;
2188 Window win , rW,cW ;
2189 int grab , xold,yold , x,y, rx,ry , first=1 , rrr=0 ;
2190 unsigned int mask ; /* which buttons */
2191 unsigned int bmask=Button1Mask|Button2Mask|Button3Mask ; /* all buttons */
2192 XGCValues gcv;
2193 GC myGC ;
2194
2195 ENTRY("RWC_drag_circle") ;
2196
2197 /** make a GC for invert drawing **/
2198
2199 gcv.function = GXinvert ;
2200 myGC = XtGetGC( w , GCFunction , &gcv ) ;
2201
2202 /** grab the pointer (so no one else gets events from it),
2203 and confine it to the window in question **/
2204
2205 dis = XtDisplay(w) ; win = XtWindow(w) ;
2206
2207 RWC_drag_cursor(dis) ;
2208
2209 grab = !XGrabPointer(dis, win, False, 0, GrabModeAsync,
2210 GrabModeAsync, win, cur , (Time)CurrentTime);
2211
2212 /* grab fails => exit */
2213
2214 if( !grab ){ XBell(dis,100); *radius=0; EXRETURN; }
2215
2216 xold = x1 ; yold = y1 ; /* current location of pointer */
2217
2218 /** loop and find out where the pointer is (while button is down) **/
2219
2220 while( XQueryPointer(dis,win,&rW,&cW,&rx,&ry,&x,&y,&mask) ){
2221
2222 /* check if all buttons are released */
2223
2224 if( !(mask & bmask) ) break ; /* no button down => done! */
2225
2226 /* pointer now at (x,y) in the window */
2227
2228 /* if it has moved, redraw rectangle */
2229
2230 if( x != xold || y != yold ){
2231
2232 if( !first ) /* undraw old circle */
2233 RWC_draw_circle( dis,win,myGC , x1,y1 , rrr ) ;
2234
2235 /* draw new circle */
2236
2237 xold = x ; yold = y ; first = 0 ;
2238 rrr = (int)rint(sqrt( (x-x1)*(x-x1) + (y-y1)*(y-y1) )) ;
2239 RWC_draw_circle( dis,win,myGC , x1,y1 , rrr ) ;
2240
2241 } /* end of new (x,y) position */
2242
2243 } /* end of loop while button is pressed */
2244
2245 if( !first ) /* undraw old circle */
2246 RWC_draw_circle( dis,win,myGC , x1,y1 , rrr ) ;
2247
2248 /* clean up */
2249
2250 XtReleaseGC( w , myGC ) ;
2251 if (grab) XUngrabPointer(dis, (Time)CurrentTime) ;
2252
2253 *radius = rrr ;
2254 EXRETURN ;
2255 }
2256
2257 /*-------------------------------------------------------------------*/
2258 /*! Sleep a given # of milliseconds (uses the Unix select routine).
2259 ---------------------------------------------------------------------*/
2260
2261 #include <sys/time.h>
2262 #include <sys/types.h>
2263 #include <unistd.h>
2264
RWC_sleep(int msec)2265 void RWC_sleep( int msec )
2266 {
2267 struct timeval tv ;
2268 if( msec <= 0 ) return ; /* can't wait into the past */
2269 tv.tv_sec = msec/1000 ;
2270 tv.tv_usec = (msec%1000)*1000 ;
2271 select( 1 , NULL,NULL,NULL , &tv ) ;
2272 return ;
2273 }
2274
2275 /*-----------------------------------------------------------------*/
2276 /*! Popdown a widget that may not be a shell. [30 Jun 2003]
2277 -------------------------------------------------------------------*/
2278
RWC_XtPopdown(Widget w)2279 void RWC_XtPopdown( Widget w )
2280 {
2281 Widget wpar = w ;
2282
2283 ENTRY("RWC_XtPopdown") ;
2284
2285 if( wpar == NULL ) EXRETURN ;
2286 RWC_sleep(1) ;
2287 while( XtIsShell(wpar)==0 && XtParent(wpar)!=NULL ) wpar = XtParent(wpar);
2288 XtPopdown(wpar) ; RWC_sleep(1) ;
2289 EXRETURN ;
2290 }
2291
2292 /*-----------------------------------------------------------------*/
2293 /******************** Speech stuff (for Mac OS X) ******************/
2294
2295 #if !defined(NO_FRIVOLITIES) && defined(DARWIN)
2296
2297 #include <unistd.h>
2298 #include <string.h>
2299 #include <stdlib.h>
2300 #include <ctype.h>
2301 #include <sys/wait.h>
2302 #include <sys/types.h>
2303
2304 static int have_say = -1 ;
2305 static char voice[128] = "Cellos" ;
2306
2307 /*-----------------------------------------------------------------*/
2308 /*! Set the voice for the Apple speech synthesizer. */
2309
AFNI_speak_setvoice(char * vvv)2310 void AFNI_speak_setvoice( char *vvv )
2311 {
2312 int ll ;
2313 if( vvv == NULL || *vvv == '\0' ) return ;
2314 ll = strlen(vvv) ; if( ll > 100 ) return ;
2315 strcpy(voice,vvv) ; return ;
2316 }
2317
2318
2319 /*-----------------------------------------------------------------*/
2320 /*! Speak a string using Apple's say command:
2321 - string = Apple text-to-speech code
2322 - nofork = 1 if you want to wait for the speech to finish;
2323 = 0 if you want the function to return immediately,
2324 before speech finishes (or perhaps even starts). */
2325
AFNI_speak(char * string,int nofork)2326 void AFNI_speak( char *string , int nofork )
2327 {
2328 char *buf ; pid_t ppp ;
2329
2330 /* bad input ==> quit */
2331
2332 if( string == NULL || *string == '\0' ) return ;
2333
2334 /* user says "don't talk" ==> quit */
2335
2336 buf = getenv("AFNI_SPEECH") ;
2337 #if 1
2338 if( buf == NULL || toupper(*buf) != 'Y' ) return ; /* 02 Apr 2004 */
2339 #else
2340 if( buf != NULL && toupper(*buf) == 'N' ) return ;
2341 #endif
2342
2343 /* don't have "say" program ==> quit */
2344
2345 if( have_say == -1 ) have_say = (THD_find_executable("say") != NULL) ;
2346 if( have_say == 0 ) return ;
2347
2348 /* if want speech to run in a separate process ... */
2349
2350 if( !nofork ){
2351 ppp = fork() ;
2352 if( ppp < 0 ) return ; /* fork failed */
2353
2354 /* parent: wait for child to exit (happens almost instantly) */
2355
2356 if( ppp > 0 ){ waitpid(ppp,NULL,0); return; }
2357
2358 /* child: fork again immediately, then this child exits;
2359 this is to prevent zombie processes from hanging around */
2360
2361 ppp = fork() ; if( ppp != 0 ) _exit(0) ; /* child exits now */
2362
2363 /* grandchild continues on to actually do something */
2364 }
2365
2366 /* Run the say program using system() */
2367
2368 buf = (char *)malloc(strlen(string)+32) ;
2369 sprintf(buf,"say -v%s '%s'",voice,string) ;
2370 system(buf) ; free(buf) ;
2371
2372 if( !nofork ) _exit(0) ; /* grandchild exits */
2373 return ; /* no forking ==> return to caller */
2374 }
2375
2376 #else
2377
AFNI_speak(char * string,int nofork)2378 void AFNI_speak( char *string , int nofork ){ return; } /* dummy function */
AFNI_speak_setvoice(char * vvv)2379 void AFNI_speak_setvoice( char *vvv ){ return; }
2380
2381 #endif
2382
2383 /****************************************************************************/
2384
AFNI_startup_sound(int nnn)2385 void AFNI_startup_sound(int nnn)
2386 {
2387 #ifndef NO_FRIVOLITIES
2388 static int have_sox=-1 ; int ii ;
2389
2390 if( have_sox < 0 ) have_sox = ( THD_find_executable("sox") != NULL ) ;
2391 if( have_sox == 0 ) return ;
2392
2393 for( ii=0 ; ii < nnn ; ii++ ){
2394 if( ii%2 == 0 )
2395 system("sox -n -d synth 0.5 pluck E3 pluck F3 gain -h -27 delay 0.2 0 fade t 0.05 &> /dev/null") ;
2396 else
2397 system("sox -n -d synth 0.5 pluck F3 pluck E3 gain -h -27 delay 0.2 0 fade t 0.05 &> /dev/null") ;
2398 }
2399 #endif
2400 return ;
2401 }
2402
2403 /****************************************************************************/
2404
2405 #ifdef DARWIN
get_XQuartz_version(void)2406 char * get_XQuartz_version(void){
2407 char *vers , *info , *cpt , *dpt ; int len , ii ;
2408
2409 info = AFNI_suck_file("/Applications/Utilities/XQuartz.app/Contents/Info.plist") ;
2410 if( info == NULL ) return NULL ;
2411
2412 cpt = strcasestr(info,"CFBundleShortVersionString") ;
2413 if( cpt == NULL ) cpt = strcasestr(info,"CFBundleVersion") ;
2414 if( cpt == NULL ){ free(info); return NULL; }
2415 dpt = strcasestr(cpt+15,"<string>") ;
2416 if( dpt == NULL ){ free(info); return NULL; }
2417 dpt += 8 ; /* 8 = strlen("<string>") */
2418 cpt = strstr(dpt,"<") ;
2419 if( cpt == NULL || cpt == dpt ) { free(info); return NULL; }
2420 len = cpt - dpt ; if( len > 32 ){ free(info); return NULL; }
2421 vers = (char *)malloc(sizeof(char)*(len+1)) ;
2422 for( ii=0 ; ii < len ; ii++ ) vers[ii] = dpt[ii] ;
2423 vers[len] = '\0' ;
2424 free(info) ; return vers ;
2425 }
2426 #else
2427
get_XQuartz_version(void)2428 char * get_XQuartz_version(void){ return NULL; }
2429
2430 #endif
2431
2432 /****************************************************************************/
2433 #define MIN_SIZE 4
2434 #define MAX_SIZE 26
2435 #define MIN_DIST 4
2436 #define MIN_WIDTH 8
2437 #define WIDTH_ADD 8
2438 #define FINISHED 50
2439 #define rnd(x) (lrand48() % (x))
2440
2441 /*--------------------------------------------------------------------------*/
2442
calc_xloc(int width,int twid)2443 static int calc_xloc(int width , int twid )
2444 {
2445 int xloc = rnd(twid+MIN_WIDTH) - MIN_WIDTH;
2446 if ((xloc + width) >= twid ) xloc = twid - width-1;
2447 else if (xloc < 0 ) xloc = 0;
2448 return xloc;
2449 }
2450
MCW_melt_widget(Widget w)2451 void MCW_melt_widget( Widget w )
2452 {
2453 Display *dpy;
2454 Window win , rin ;
2455 GC copygc, fillgc;
2456 int screen , rww,rhh,planes ;
2457 unsigned long vmask;
2458 XSetWindowAttributes xswat;
2459 XGCValues gcvals;
2460 int finished=0;
2461 int width, xloc, yloc, dist, size, i , slow ;
2462 short *heights;
2463
2464 if( w == NULL ) return ;
2465 if( ! XtIsRealized(w) ) return ;
2466 if( ! XtIsManaged(w) ) return ;
2467 if( ! XtIsWidget(w) ) return ;
2468 rin = XtWindow(w) ; if( rin == (Window)NULL ) return ;
2469
2470 MCW_widget_geom( w , &rww , &rhh , NULL,NULL ) ;
2471 if( rww < MIN_WIDTH+FINISHED || rhh < 2*MIN_SIZE ) return ;
2472
2473 dpy = XtDisplay(w) ; screen = DefaultScreen(dpy);
2474
2475 planes = DefaultDepthOfScreen( XtScreen(w) ) ;
2476
2477 xswat.override_redirect = True;
2478 xswat.do_not_propagate_mask = KeyPressMask | KeyReleaseMask |
2479 ButtonPressMask | ButtonReleaseMask ;
2480 vmask = CWOverrideRedirect | CWDontPropagate;
2481 win = XCreateWindow( dpy, rin , 0, 0, rww , rhh ,
2482 0, CopyFromParent, CopyFromParent, CopyFromParent,
2483 vmask, &xswat);
2484 XMapWindow(dpy, win);
2485
2486 gcvals.graphics_exposures = False;
2487 gcvals.foreground = 1;
2488 gcvals.background = 0;
2489 copygc = XCreateGC(dpy, win,
2490 GCForeground | GCBackground | GCGraphicsExposures,
2491 &gcvals);
2492
2493 gcvals.foreground = (lrand48()%2==0) ? BlackPixel(dpy,screen)
2494 : WhitePixel(dpy,screen) ;
2495
2496 fillgc = XCreateGC(dpy, win, GCForeground, &gcvals);
2497
2498 slow = (rww*rhh) / 34567 ; /* larger ==> faster */
2499
2500 XSync(dpy,0); if( slow < 0 ) slow = -slow ;
2501
2502 heights = (short *) calloc(sizeof(short), rww+1 );
2503
2504 while (1){
2505 width = rnd(MIN_WIDTH) + WIDTH_ADD;
2506
2507 xloc = calc_xloc(width,rww); yloc = rhh ;
2508 for (i = xloc; i < (xloc + width); i++) yloc = MIN(yloc, heights[i]);
2509 if (yloc == rhh) continue;
2510
2511 dist = rnd(yloc/8 + MIN_DIST);
2512 size = rnd(MAX(yloc/4 + MIN_SIZE, MAX_SIZE));
2513
2514 XCopyArea(dpy, win, win, copygc,
2515 xloc, yloc, width, size, xloc, yloc + dist);
2516 XFillRectangle(dpy, win, fillgc,
2517 xloc, yloc, width, dist);
2518 if( slow > 0 && rnd(slow)==0 ) RWC_sleep(1);
2519 if( rnd(33) == 0 ) XSync(dpy,0) ;
2520 yloc += dist;
2521 for (i = xloc; i < (xloc + width); i++){
2522 if( (heights[i] < (rhh - MIN_SIZE)) && (yloc >= (rhh - MIN_SIZE)) )
2523 finished++;
2524 heights[i] = MAX(heights[i], yloc);
2525 }
2526 if (finished >= (rww - FINISHED)){
2527 XDestroyWindow(dpy,win); XFreeGC(dpy,copygc); XFreeGC(dpy,fillgc);
2528 XSync(dpy,0); RWC_sleep(200); free(heights); return;
2529 }
2530 #if 1
2531 if( lrand48()%47 == 0 ){
2532 gcvals.foreground = (lrand48()%3) ? BlackPixel(dpy,screen) : WhitePixel(dpy,screen) ;
2533 XChangeGC(dpy, fillgc , GCForeground, &gcvals);
2534 }
2535 #endif
2536 }
2537 }
2538