Skip to content

AFNI/NIfTI Server

Sections
Personal tools
You are here: Home » AFNI » Documentation

Doxygen Source Code Documentation


Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Search  

xutil.c

Go to the documentation of this file.
00001 /*****************************************************************************
00002    Major portions of this software are copyrighted by the Medical College
00003    of Wisconsin, 1994-2000, and are released under the Gnu General Public
00004    License, Version 2.  See the file README.Copyright for details.
00005 ******************************************************************************/
00006 
00007 #include "xutil.h"
00008 #include "afni_environ.h"
00009 #include "debugtrace.h"    /* 12 Mar 2001 */
00010 
00011 #include "Amalloc.h"
00012 extern char * THD_find_executable( char * ) ;
00013 
00014 /*--------------------------------------------------------------------
00015   force an immediate expose for the widget
00016 ----------------------------------------------------------------------*/
00017 
00018 /****************************************
00019   requires the following line somewhere
00020 
00021 #include <X11/IntrinsicP.h>
00022 
00023 *****************************************/
00024 
00025 void MCW_expose_widget( Widget w )
00026 {
00027    XExposeEvent xev;
00028    Dimension ww , hh ;
00029 
00030                                if( ! XtIsRealized(w)           ) return ;
00031                                if( ! XtIsManaged(w)            ) return ;
00032    xev.window  = XtWindow(w) ; if( xev.window == (Window) NULL ) return ;
00033    xev.type    = Expose ;
00034    xev.display = XtDisplay(w) ;
00035    xev.x       = xev.y = 0 ;
00036    XtVaGetValues( w, XmNwidth, &ww, XmNheight, &hh, NULL ) ;
00037    if( ww <= 0 || hh <= 0 ) return ;
00038    xev.width   = ww ; xev.height  = hh ;
00039    (XtClass (w))->core_class.expose( w, (XEvent *)&xev, NULL ) ;
00040    XFlush( XtDisplay(w) ) ;
00041    return ;
00042 }
00043 
00044 /*--------------------------------------------------------------------
00045   Get the Colormap for a widget -- 01 Sep 1998
00046 ----------------------------------------------------------------------*/
00047 
00048 Colormap MCW_get_colormap( Widget w )
00049 {
00050    Colormap cmap = (Colormap) 0 ;
00051 
00052    if( w == NULL || ! XtIsWidget(w) ) return (Colormap) 0 ;
00053 
00054    XtVaGetValues( w , XmNcolormap  , &cmap , NULL ) ;
00055    return cmap ;
00056 }
00057 
00058 /*--------------------------------------------------------------------*/
00059 
00060 int MCW_get_depth( Widget w )  /* 14 Sep 1998 */
00061 {
00062    int depth = 0 ;
00063 
00064    if( w == NULL || ! XtIsWidget(w) ) return 0 ;
00065    XtVaGetValues( w , XmNdepth  , &depth , NULL ) ;
00066    return depth  ;
00067 }
00068 
00069 /*--------------------------------------------------------------------*/
00070 
00071 Visual * MCW_get_visual( Widget w )  /* 14 Sep 1998 */
00072 {
00073    Visual * visual = NULL ;
00074    Widget wpar = w ;
00075 
00076    if( w == NULL || ! XtIsWidget(w) ) return NULL ;
00077 
00078    while( XtParent(wpar) != NULL ) wpar = XtParent(wpar) ;  /* find top */
00079 
00080    XtVaGetValues( wpar , XmNvisual , &visual , NULL ) ;
00081    return visual ;
00082 }
00083 
00084 /*--------------------------------------------------------------------
00085   Set the Colormap for a widget -- 14 Sep 1998
00086   (Will only work if widget is not yet realized)
00087 ----------------------------------------------------------------------*/
00088 
00089 void MCW_set_colormap( Widget w , Colormap cmap )
00090 {
00091    if( w == NULL || ! XtIsWidget(w) ) return ;
00092    XtVaSetValues( w , XmNcolormap  , cmap , NULL ) ;
00093    return ;
00094 }
00095 
00096 /*--------------------------------------------------------------------
00097    swap the fg and bg colors of a widget
00098    (the shadow colors are altered to fit the new bg)
00099 ----------------------------------------------------------------------*/
00100 
00101 void MCW_invert_widget( Widget w )
00102 {
00103    Pixel bg_pix , topsh_pix , botsh_pix , fg_pix , sel_pix ;
00104    Colormap cmap ;
00105 
00106    if( ! XtIsWidget(w) ) return ;
00107 
00108    XtVaGetValues( w , XmNforeground , &bg_pix ,  /* foreground -> bg */
00109                       XmNbackground , &fg_pix ,  /* background -> fg */
00110                       XmNcolormap   , &cmap ,
00111                   NULL ) ;
00112 
00113    XmGetColors( XtScreen(w) , cmap , bg_pix ,
00114                 NULL , &topsh_pix , &botsh_pix , &sel_pix ) ;
00115 
00116    XtVaSetValues( w ,
00117                     XmNtopShadowColor    , topsh_pix ,
00118                     XmNbottomShadowColor , botsh_pix ,
00119                     XmNselectColor       , sel_pix   ,
00120                     XmNarmColor          , sel_pix   ,
00121                     XmNborderColor       , fg_pix    ,
00122                     XmNforeground        , fg_pix    ,
00123                     XmNbackground        , bg_pix    ,
00124                   NULL ) ;
00125 
00126    XSync( XtDisplay(w) , False ) ;  /* make it happen NOW */
00127    XmUpdateDisplay( w ) ;
00128    return ;
00129 }
00130 
00131 /*---------------------------------------------------------------------
00132    set the background color of a widget; the other colors are
00133    altered to match, a la Motif;
00134      cname = character specification of color
00135      pix   = if cname == NULL, use this pixel value
00136 -----------------------------------------------------------------------*/
00137 
00138 void MCW_set_widget_bg( Widget w , char * cname , Pixel pix )
00139 {
00140    Pixel bg_pix , topsh_pix , botsh_pix , fg_pix , sel_pix ;
00141    Colormap cmap ;
00142 
00143 #if 1
00144    if( ! XtIsWidget(w) ) return ;
00145 #else
00146    if( ! XtIsObject(w) ) return ;
00147 #endif
00148 
00149 
00150    if( cname != NULL && strlen(cname) > 0 ){
00151       XtVaSetValues( w ,
00152                      XtVaTypedArg , XmNbackground , XmRString ,
00153                                     cname , strlen(cname)+1 ,
00154                      NULL ) ;
00155 
00156       XtVaGetValues( w , XmNbackground , &bg_pix , NULL ) ;
00157    } else {
00158       bg_pix = pix ;
00159    }
00160 
00161 #if 0
00162    XtVaGetValues( w , XmNcolormap , &cmap , NULL ) ;
00163    XmGetColors( XtScreen(w) , cmap , bg_pix ,
00164                 &fg_pix , &topsh_pix , &botsh_pix , &sel_pix ) ;
00165    XtVaSetValues( w ,
00166                     XmNtopShadowColor    , topsh_pix ,
00167                     XmNbottomShadowColor , botsh_pix ,
00168                     XmNselectColor       , sel_pix   ,
00169                     XmNarmColor          , sel_pix   ,
00170                     XmNborderColor       , fg_pix    ,
00171                     XmNforeground        , fg_pix    ,
00172                     XmNbackground        , bg_pix    ,
00173                   NULL ) ;
00174    XFlush( XtDisplay(w) ) ;
00175 #else
00176    XmChangeColor( w , bg_pix ) ;
00177 #endif
00178 
00179    return ;
00180 }
00181 
00182 /*-------------------------------------------------------------------*/
00183 
00184 void MCW_set_widget_label( Widget w , char * str )
00185 {
00186    XmString xstr ;
00187    xstr = XmStringCreateLtoR( str , XmFONTLIST_DEFAULT_TAG ) ;
00188    XtVaSetValues( w , XmNlabelString , xstr , NULL ) ;
00189    XmStringFree( xstr ) ;
00190    MCW_expose_widget( w ) ;
00191 }
00192 
00193 /*-----------------------------------------------------------------------*/
00194 
00195 void MCW_widget_geom( Widget w, int *wout, int *hout, int *xout, int *yout )
00196 {
00197    Dimension nx , ny ;  /* don't try to make these ints! */
00198    Position  xx , yy ;
00199 
00200    if( w == NULL ) return ;
00201 
00202    if( XtIsRealized(w) ){
00203       XtVaGetValues( w , XmNwidth  , &nx , XmNheight , &ny ,
00204                          XmNx      , &xx , XmNy      , &yy , NULL ) ;
00205    } else {
00206       XtWidgetGeometry wg ;
00207       (void) XtQueryGeometry( w , NULL , &wg ) ;   /* works! */
00208       nx = wg.width ; ny = wg.height ;
00209       xx = wg.x     ; yy = wg.y      ;
00210    }
00211 
00212 #define ASSIF(p,v) if( p!= NULL ) *p = v
00213 
00214    ASSIF(wout,nx) ; ASSIF(hout,ny) ;
00215    ASSIF(xout,xx) ; ASSIF(yout,yy) ;
00216 
00217    return ;
00218 }
00219 
00220 /*--------------------------------------------------------------------------*/
00221 
00222 void MCW_discard_events( Widget w , int ev_mask )
00223 {
00224    XEvent evjunk ;
00225 
00226    if( w == NULL || XtWindow(w) == (Window) NULL ) return ;
00227 
00228    XSync( XtDisplay(w) , False ) ;
00229    while( XCheckWindowEvent( XtDisplay(w), XtWindow(w) , ev_mask , &evjunk ) ) ;
00230    return ;
00231 }
00232 
00233 /*--------------------------------------------------------------------------*/
00234 
00235 char * MCW_hotcolor(Widget w)
00236 {
00237    static char *redcolor = NULL ;
00238 
00239    if( redcolor == NULL ){
00240      char *xdef = RWC_getname( (w!=NULL) ? XtDisplay(w) : NULL, "hotcolor" ) ;
00241 
00242      redcolor = (xdef != NULL) ? (xdef) : ("red4") ;
00243    }
00244    return redcolor ;
00245 }
00246 
00247 /*--------------------------------------------------------------------------
00248    24 Apr 2001: manage array of widgets, some of which may be NULL
00249 ----------------------------------------------------------------------------*/
00250 
00251 void MCW_manage_widgets( Widget * war , int nar )
00252 {
00253    int ii ;
00254    if( war == NULL ) return ;
00255    for( ii=0 ; ii < nar ; ii++ )
00256       if( war[ii] != (Widget) 0 ) XtManageChild( war[ii] ) ;
00257    return ;
00258 }
00259 
00260 void MCW_unmanage_widgets( Widget * war , int nar )
00261 {
00262    int ii ;
00263    if( war == NULL ) return ;
00264    for( ii=0 ; ii < nar ; ii++ )
00265       if( war[ii] != (Widget) 0 ) XtUnmanageChild( war[ii] ) ;
00266    return ;
00267 }
00268 
00269 /*--------------------------------------------------------------------------*/
00270 
00271 #define TIG 25
00272 
00273 Widget MCW_action_area( Widget parent, MCW_action_item * action, int num_act )
00274 {
00275    Widget act_area , ww ;
00276    int ii ;
00277 
00278    act_area = XtVaCreateWidget( "action_area" , xmFormWidgetClass , parent ,
00279                                     XmNfractionBase , TIG*num_act - 1,
00280 
00281                                     XmNinitialResourcesPersistent , False ,
00282                                 NULL ) ;
00283 
00284    for( ii=0 ; ii < num_act ; ii++ ){
00285 
00286       ww = XtVaCreateManagedWidget(
00287                action[ii].label , xmPushButtonWidgetClass , act_area ,
00288 
00289                   XmNleftAttachment   ,
00290                        (ii) ? XmATTACH_POSITION : XmATTACH_FORM ,
00291                   XmNleftPosition     , ii*TIG ,
00292                   XmNtopAttachment    , XmATTACH_FORM ,
00293                   XmNbottomAttachment , XmATTACH_FORM ,
00294                   XmNrightAttachment  ,
00295                      (ii==num_act-1) ? XmATTACH_FORM : XmATTACH_POSITION ,
00296 
00297                   XmNrightPosition    , ii*TIG + (TIG-1) ,
00298 
00299                   XmNrecomputeSize , False ,
00300                   XmNtraversalOn   , False ,
00301                   XmNinitialResourcesPersistent , False ,
00302                NULL ) ;
00303 
00304       XtAddCallback( ww , XmNactivateCallback ,
00305                      action[ii].func_CB , action[ii].data ) ;
00306 
00307       action[ii].data = (XtPointer) ww ;  /* Feb 1998: save widget */
00308 
00309       if( action[ii].help_text != NULL )
00310          MCW_register_help( ww , action[ii].help_text ) ;
00311 
00312       if( action[ii].hint_text != NULL )
00313          MCW_register_hint( ww , action[ii].hint_text ) ;
00314 
00315       if( action[ii].make_red > 0 )                  /* for some fun */
00316          MCW_set_widget_bg( ww , MCW_hotcolor(ww) , 0 ) ;
00317       else if( action[ii].make_red < 0 )             /* for no fun at all */
00318          XtSetSensitive( ww , False ) ;
00319 
00320    }
00321 
00322    XtManageChild( act_area ) ;
00323    return act_area ;
00324 }
00325 
00326 /*------------------------------------------------------------------
00327    Popup a window with a message;  return the Widget.
00328    The message can be of two types, signified by the 3rd argument:
00329       msg_type = MCW_CALLER_KILL means the caller has to kill the
00330                  widget for the window to go away.
00331 
00332                = MCW_USER_KILL means that the user can click in
00333                   the widget to kill it.
00334 
00335       msg_type may also be OR-ed with MCW_TIMER_KILL to have the
00336       message automatically killed after 30 seconds.
00337 --------------------------------------------------------------------*/
00338 
00339 Widget MCW_popup_message( Widget wparent , char *msg , int msg_type )
00340 {
00341    Widget wmsg , wlab ;
00342    int wx,hy,xx,yy , xp,yp , scr_width,scr_height , xr,yr , xpr,ypr ;
00343    Screen *scr ;
00344    XEvent ev ;
00345 
00346 ENTRY("MCW_popup_message") ;
00347 
00348    if( ! XtIsRealized( wparent ) ||
00349        msg == NULL               || strlen(msg) == 0 ) RETURN(NULL) ;
00350 
00351    /* set position for message box based on parent and screen geometry */
00352 
00353    MCW_widget_geom( wparent , &wx,&hy,&xx,&yy ) ;  /* geometry of parent */
00354 
00355 #if 1
00356    { Position xroot , yroot ;
00357      XtTranslateCoords( wparent, 0,0, &xroot,&yroot ) ; /* root coords */
00358      xr = (int) xroot ; yr = (int) yroot ;
00359    }
00360 #else
00361      xr = xx ; yr = yy ;  /* the old code, essentially */
00362 #endif
00363 
00364    scr        = XtScreen( wparent ) ;
00365    scr_width  = WidthOfScreen( scr ) ;
00366    scr_height = HeightOfScreen( scr ) ;
00367 
00368    xp = xx+8 ;  xpr = xr+8 ;
00369         if( xpr+50 > scr_width ){ xp -= 100 ; xpr -= 100 ; } /* too right */
00370    else if( xpr+10 < 0 )        { xpr = xp = 1 ; }           /* too left  */
00371 
00372    yp = yy+hy+8 ;  ypr = yr+hy+8 ;
00373         if( ypr+50 > scr_height ){ yp = yy-8 ; ypr = yr-100 ;} /* too down */
00374    else if( ypr+10 < 0 )         { ypr = yp = 1 ;            } /* too up   */
00375 
00376    /* create a popup shell with a label */
00377 
00378    wmsg = XtVaCreatePopupShell(
00379              "help" , xmDialogShellWidgetClass , wparent ,
00380                 XmNx , xpr ,
00381                 XmNy , ypr ,
00382                 XmNinitialResourcesPersistent , False ,
00383              NULL ) ;
00384 
00385    if( MCW_isitmwm( wparent ) ){
00386       XtVaSetValues( wmsg ,
00387                         XmNmwmDecorations , MWM_DECOR_BORDER ,
00388                         XmNmwmFunctions   , MWM_FUNC_MOVE ,
00389                      NULL ) ;
00390    }
00391 
00392    switch( msg_type & (MCW_CALLER_KILL | MCW_USER_KILL) ){
00393 
00394       case MCW_CALLER_KILL:
00395 
00396          wlab = XtVaCreateManagedWidget(
00397                   "help" , xmLabelWidgetClass , wmsg ,
00398                      XtVaTypedArg,XmNlabelString,XmRString,msg,strlen(msg)+1,
00399                      XmNalignment , XmALIGNMENT_BEGINNING ,
00400                      XmNinitialResourcesPersistent , False ,
00401                   NULL ) ;
00402       break ;
00403 
00404       default:
00405       case MCW_USER_KILL:{
00406          static int first=1 ; char *mmsg = msg ;     /* 'first' stuff  */
00407          if( first ){                                /* on 06 Apr 2004 */
00408            if( !AFNI_noenv("AFNI_CLICK_MESSAGE") ){
00409              mmsg = (char *) malloc(strlen(msg)+99) ;
00410              strcpy(mmsg,msg) ;
00411              strcat(mmsg,"\n [---------------] "
00412                          "\n [ Click in Text ] "
00413                          "\n [ to Pop Down!! ]\n" ) ;
00414            }
00415          }
00416 
00417          wlab = XtVaCreateManagedWidget(
00418                   "help" , xmPushButtonWidgetClass , wmsg ,
00419                      XtVaTypedArg,XmNlabelString,XmRString,mmsg,strlen(msg)+1,
00420                      XmNalignment , XmALIGNMENT_BEGINNING ,
00421                      XmNinitialResourcesPersistent , False ,
00422                   NULL ) ;
00423 
00424          if( mmsg != msg ){ free((void *)mmsg); first = 0; }
00425 
00426          XtAddCallback( wlab , XmNactivateCallback , MCW_message_CB , NULL ) ;
00427       }
00428       break ;
00429    }
00430 
00431    SAVEUNDERIZE(wmsg) ;           /* 27 Feb 2001 */
00432    XtPopup( wmsg , XtGrabNone ) ;
00433 
00434    /* now wait until the label is exposed, and make sure it appears;
00435       the reason for this stuff is that this routine is likely to be
00436       called by a long computation that won't return control to Xt   */
00437 
00438    WAIT_for_window(wlab) ;
00439    XSync( XtDisplay(wlab) , False ) ;
00440 #if 0
00441    XMaskEvent( XtDisplay(wlab) , ExposureMask , &ev ) ;/* wait for expose  */
00442 #else
00443    XWindowEvent( XtDisplay(wlab) , XtWindow(wlab) , ExposureMask , &ev ) ;
00444 #endif
00445    XPutBackEvent( XtDisplay(wlab) , &ev ) ;            /* put expose back  */
00446    XSync( XtDisplay(wlab) , False ) ;
00447    XmUpdateDisplay( wlab ) ;                           /* show it for sure */
00448 
00449    /* now add the timer kill, if wanted */
00450 
00451 #define ALLOW_TIMER_KILL
00452 #ifdef ALLOW_TIMER_KILL
00453    if( (msg_type & MCW_TIMER_KILL) != 0 ){
00454       XtIntervalId tid ;
00455 
00456       tid = XtAppAddTimeOut( XtWidgetToApplicationContext( wmsg ) ,
00457                              33333 , MCW_message_timer_CB , wmsg   ) ;
00458 
00459       XtVaSetValues( wlab , XmNuserData ,  tid , NULL );/* put tid on wlab; */
00460    } else {                                             /* shells don't */
00461       XtVaSetValues( wlab , XmNuserData , 0 , NULL ) ;  /* have XmNuserData */
00462    }
00463 #endif
00464 
00465    RWC_visibilize(wmsg) ;  /* 27 Sep 2000 */
00466    NORMAL_cursorize(wmsg) ;
00467    RETURN(wmsg) ;
00468 }
00469 
00470 /*-------------------------------------------------------------------------
00471   Alter the text in the popup message - 10 Jul 2001
00472 ---------------------------------------------------------------------------*/
00473 
00474 void MCW_message_alter( Widget wmsg , char *msg )
00475 {
00476    Widget wlab ;
00477    Widget *children=NULL ;
00478    int  num_children=0 ;
00479    XmString xstr ;
00480 
00481 ENTRY("MCW_message_alter") ;
00482 
00483    if( wmsg == NULL || msg == NULL || msg[0] == '\0' ) EXRETURN ;
00484 
00485    XtVaGetValues( wmsg , XmNchildren    , &children ,
00486                          XmNnumChildren , &num_children , NULL ) ;
00487    if( num_children < 1 ) EXRETURN ;
00488 
00489    MCW_set_widget_label( children[0] , msg ) ;
00490    EXRETURN ;
00491 }
00492 
00493 /*-------------------------------------------------------------------------
00494     callback when the popup message created above is a PushButton
00495     (Note that w is the PushButton widget, so its parent is to be killed)
00496 ---------------------------------------------------------------------------*/
00497 
00498 void MCW_message_CB( Widget w , XtPointer cd , XtPointer cbs )
00499 {
00500 #ifdef ALLOW_TIMER_KILL
00501    XtIntervalId tid ;
00502 
00503    XtVaGetValues( w , XmNuserData , &tid , NULL ) ;  /* get timer id */
00504    XtDestroyWidget( XtParent(w) ) ;
00505 
00506    if( tid > 0 ) XtRemoveTimeOut( tid ) ;  /* if a timer exists, kill it */
00507 #else
00508    XtDestroyWidget( XtParent(w) ) ;
00509 #endif
00510 }
00511 
00512 /*----------------------------------------------------*/
00513 /*--- callback when timer expires on popup message ---*/
00514 /*----------------------------------------------------*/
00515 
00516 void MCW_message_timer_CB( XtPointer client_data , XtIntervalId * id )
00517 {
00518    XtDestroyWidget( (Widget) client_data ) ;
00519 }
00520 
00521 /*------------------------------------------------------------------
00522    routines to change Widget cursors
00523      cur argument:  = 0 --> None
00524                     > 0 --> is a Cursor already allocated
00525                     < 0 --> -cur is a cursorfont index
00526 --------------------------------------------------------------------*/
00527 
00528 void MCW_set_widget_cursor( Widget w , int cur )
00529 {
00530    MCW_alter_widget_cursor( w , cur , NULL,NULL ) ;
00531    return ;
00532 }
00533 
00534 /*--------------------------------------------------------------------*/
00535 
00536 void MCW_alter_widget_cursor( Widget w, int cur, char * fgname, char * bgname )
00537 {
00538    XColor fg , bg ;
00539    Cursor ccc ;
00540    Colormap cmap ;
00541    Display  * dis ;
00542    Boolean  good ;
00543    int ii ;
00544 
00545    static Cursor  cur_font[XC_num_glyphs] ;
00546    static Boolean first = True ;
00547 
00548    if( AFNI_yesenv("AFNI_DISABLE_CURSORS") ) return ; /* 21 Mar 2004 */
00549 
00550    if( first ){
00551       for( ii=0 ; ii < XC_num_glyphs ; ii++ ) cur_font[ii] = None ;
00552       first = False ;
00553    }
00554 
00555    if( !XtIsRealized(w) || XtWindow(w) == (Window) NULL ) return ;
00556 
00557    dis = XtDisplay(w) ;
00558 
00559    if( cur == 0 || cur <= -XC_num_glyphs ){    /* define cursor */
00560       ccc = None ;
00561    } else if( cur > 0 ){
00562       ccc = cur ;
00563    } else {
00564       ii = -cur ;
00565       if( cur_font[ii] == None ) cur_font[ii] = XCreateFontCursor( dis , ii ) ;
00566       ccc = cur_font[ii] ;
00567    }
00568 
00569    XDefineCursor( dis , XtWindow(w) , ccc ) ;
00570 
00571    if( fgname != NULL && bgname != NULL ){
00572 
00573       cmap = DefaultColormap( dis , DefaultScreen(dis) ) ;
00574 
00575       good =    XParseColor( dis , cmap , fgname , &fg )
00576              && XParseColor( dis , cmap , bgname , &bg ) ;
00577 
00578       if( good ) XRecolorCursor( dis , ccc , &fg , &bg ) ;
00579    }
00580    return ;
00581 }
00582 
00583 /*------------------------------------------------------------------------
00584    widget help routines (for "button help" buttons)
00585 --------------------------------------------------------------------------*/
00586 
00587 void MCW_click_help_CB( Widget w, XtPointer client_data, XtPointer call_data )
00588 {
00589    Widget whelp ;
00590    XmAnyCallbackStruct cbs ;
00591    XEvent ev ;
00592    static Cursor cur = 0 ;
00593    Display * dis = XtDisplay(w) ;
00594 
00595    if( cur == 0 ){
00596       cur = XCreateFontCursor( dis , XC_hand2 ) ;
00597    }
00598 
00599 #ifdef USE_LOCATE  /* old version */
00600    whelp = XmTrackingLocate( w , cur , False ) ; /* wait for user to click */
00601 #else
00602    cbs.event = &ev ;
00603    whelp = XmTrackingEvent( w , cur , False , cbs.event ) ;
00604 #endif
00605 
00606    if( whelp != NULL &&
00607        XtHasCallbacks(whelp,XmNhelpCallback) == XtCallbackHasSome ){
00608 
00609       cbs.reason = XmCR_HELP ;
00610       XtCallCallbacks( whelp , XmNhelpCallback , &cbs ) ;  /* call for help */
00611    } else {
00612       XBell( dis , 100 ) ;
00613    }
00614    return ;
00615 }
00616 
00617 /*------------------------------------------------------------------------*/
00618 /*------------------------------------------------------------------------*/
00619 
00620 static int disable_helps = 0 ;                     /* 02 Aug 1999 */
00621 void MCW_disable_help(void){ disable_helps = 1 ; }
00622 void MCW_enable_help (void){ disable_helps = 0 ; }
00623 
00624 #ifdef DONT_USE_HINTS
00625 void MCW_register_hint( Widget w , char * msg ) { return ; }
00626 void MCW_reghint_children( Widget w , char * msg ) { return ; }
00627 void MCW_hint_toggle(void){ return ; }
00628 void MCW_unregister_hint( Widget w ){ return ; }
00629 #else
00630 
00631 #include "LiteClue.h"
00632 
00633 static Widget liteClue = NULL ;
00634 static int clueless    = -1 ;
00635 
00636 void MCW_hint_toggle(void)
00637 {
00638 #define PBIG 999999
00639    int period ;
00640    char * pdef ;
00641 
00642    if( liteClue == NULL ) return ;
00643 
00644    XtVaGetValues( liteClue , XgcNwaitPeriod , &period , NULL ) ;
00645    if( period < PBIG ){
00646       period = PBIG ;
00647    } else {
00648 #if 0
00649       pdef = XGetDefault(XtDisplay(liteClue),"AFNI","waitperiod") ;
00650 #else
00651       pdef = RWC_getname(XtDisplay(liteClue),"waitperiod") ;
00652 #endif
00653       if( pdef == NULL ){
00654          period = 1066 ;
00655       } else {
00656          period = strtol( pdef , NULL , 10 ) ;
00657          if( period < 100 ) period = 1066 ;
00658       }
00659    }
00660    XtVaSetValues( liteClue , XgcNwaitPeriod , period , NULL ) ;
00661    return ;
00662 }
00663 
00664 /*--------------------------------------------------------------------*/
00665 
00666 void MCW_unregister_hint( Widget w )    /* 11 Jul 2001 */
00667 {
00668    if( liteClue != NULL && w != NULL )
00669       XcgLiteClueDeleteWidget( liteClue , w ) ;
00670    return ;
00671 }
00672 
00673 /*--------------------------------------------------------------------*/
00674 
00675 #define RES_CONVERT( res_name, res_value) \
00676        XtVaTypedArg, (res_name), XmRString, (res_value), strlen(res_value) + 1
00677 
00678 void MCW_register_hint( Widget w , char * msg )
00679 {
00680    if( disable_helps ) return ;
00681    if( w == NULL || msg == NULL || clueless == 1 || !XtIsWidget(w) ) return ;
00682 
00683    if( clueless == -1 ){
00684       char * hh = my_getenv("AFNI_HINTS") ;
00685       if( hh != NULL && ( strncmp(hh,"KILL",4)==0 ||
00686                           strncmp(hh,"kill",4)==0 ||
00687                           strncmp(hh,"Kill",4)==0 ) ){
00688          clueless = 1 ;
00689          return ;
00690       } else {
00691          clueless = 0 ;
00692       }
00693    }
00694 
00695    /*-- Do we have to make the hint-displaying widget? --*/
00696 
00697    if( liteClue == NULL ){
00698       Widget wpar = w ;
00699       char * cfont ;
00700 
00701       while( XtParent(wpar) != NULL ) wpar = XtParent(wpar) ;  /* find top */
00702 
00703       cfont = XGetDefault(XtDisplay(wpar),"AFNI","cluefont") ;
00704       if( cfont != NULL ){
00705          liteClue = XtVaCreatePopupShell( "help", xcgLiteClueWidgetClass, wpar,
00706                                              RES_CONVERT(XtNfontSet,cfont) ,
00707                                           NULL);
00708       } else {
00709          liteClue = XtVaCreatePopupShell( "help", xcgLiteClueWidgetClass, wpar,
00710                                           NULL);
00711       }
00712       if( liteClue == NULL ) return ;
00713 
00714       XtVaSetValues( liteClue , XmNsaveUnder , True , NULL ) ;  /* 22 Jan 1999 */
00715    }
00716 
00717    /*-- attach the hint to the widget, if it is a widget --*/
00718 
00719    if( XtIsWidget(w) ) XcgLiteClueAddWidget( liteClue, w, msg, 0,0 ) ;
00720 
00721    return ;
00722 }
00723 
00724 /*--------------------------------------------------------------------*/
00725 
00726 void MCW_reghint_children( Widget w , char * msg )
00727 {
00728    Widget * children=NULL ;
00729    int  num_children=0 , ic ;
00730 
00731    if( disable_helps ) return ;
00732    if( w == NULL || msg == NULL || clueless == 1 || !XtIsWidget(w) ) return ;
00733 
00734    XtVaGetValues( w , XmNchildren    , &children ,
00735                       XmNnumChildren , &num_children , NULL ) ;
00736 
00737    MCW_register_hint( w , msg ) ;
00738    if( children == NULL || num_children == 0 ) return ;
00739 
00740    for( ic=0 ; ic < num_children ; ic++ )
00741       MCW_register_hint( children[ic] , msg ) ;
00742 
00743    return ;
00744 }
00745 #endif /* DONT_USE_HINTS */
00746 /*------------------------------------------------------------------------*/
00747 /*------------------------------------------------------------------------*/
00748 
00749 void MCW_unregister_help( Widget w ) /* 24 Apr 2001 */
00750 {
00751    XtCallbackList hc=NULL ;
00752 
00753    XtVaGetValues( w , XmNhelpCallback , &hc , NULL ) ;
00754 
00755    if( hc != NULL )
00756       XtRemoveCallbacks( w , XmNhelpCallback , hc ) ;
00757 }
00758 
00759 /*------------------------------------------------------------------------*/
00760 
00761 void MCW_register_help( Widget w , char * msg )
00762 {
00763    if( disable_helps ) return ;
00764    if( w == NULL || msg == NULL ) return ;
00765    XtAddCallback( w , XmNhelpCallback , MCW_help_CB , msg ) ;
00766    return ;
00767 }
00768 
00769 /*--------------------------------------------------------------------*/
00770 
00771 void MCW_reghelp_children( Widget w , char * msg )
00772 {
00773    Widget * children ;
00774    int  num_children , ic ;
00775 
00776    if( disable_helps ) return ;
00777    if( w == NULL || msg == NULL ) return ;
00778 
00779    XtVaGetValues( w , XmNchildren    , &children ,
00780                       XmNnumChildren , &num_children , NULL ) ;
00781 
00782    XtAddCallback( w , XmNhelpCallback , MCW_help_CB , msg ) ;
00783 
00784    for( ic=0 ; ic < num_children ; ic++ )
00785       XtAddCallback( children[ic] , XmNhelpCallback , MCW_help_CB , msg ) ;
00786    return ;
00787 }
00788 
00789 /*------------------------------------------------------------------------*/
00790 
00791 void MCW_help_CB( Widget w , XtPointer client_data , XtPointer call_data )
00792 {
00793    char * msg         = (char *) client_data ;
00794    static Widget wpop = NULL , wbut ;
00795    Position xx,yy ;
00796    XmString xstr ;
00797    int ww,hh , sw,sh ;
00798    char * def ;
00799 
00800 #ifndef USE_LOCATE
00801    XmAnyCallbackStruct * cbs = (XmAnyCallbackStruct *) call_data ;
00802 #endif
00803 
00804    if( w == NULL ){
00805       if( wpop != NULL ) XtUnmapWidget(wpop) ;
00806       return ;
00807    }
00808 
00809    if( wpop == NULL || ! XtIsWidget(wpop) ){
00810 
00811       Widget wpar = w ;
00812 
00813       while( XtParent(wpar) != NULL ) wpar = XtParent(wpar) ;  /* find top */
00814 
00815       wpop = XtVaCreatePopupShell(
00816               "help" , xmDialogShellWidgetClass , wpar ,
00817                  XmNmappedWhenManaged , False ,
00818                  XmNallowShellResize , True ,
00819                  XmNdeleteResponse , XmDO_NOTHING ,
00820                  XmNinitialResourcesPersistent , False ,
00821               NULL ) ;
00822 
00823 #if 0
00824       def = XGetDefault(XtDisplay(wpar),"AFNI","helpborder") ;
00825 #else
00826       def = RWC_getname(XtDisplay(wpar),"helpborder") ;
00827 #endif
00828       if( def != NULL && strcmp(def,"False") == 0 ){
00829          XtVaSetValues( wpop ,
00830                            XmNoverrideRedirect , True ,
00831                         NULL ) ;
00832       } else if( MCW_isitmwm(wpar) ){
00833          XtVaSetValues( wpop ,
00834                            XmNmwmDecorations , MWM_DECOR_BORDER ,
00835                            XmNmwmFunctions   , MWM_FUNC_MOVE ,
00836                         NULL ) ;
00837       }
00838 
00839       wbut = XtVaCreateManagedWidget(
00840                 "help" , xmPushButtonWidgetClass , wpop ,
00841                    XmNalignment , XmALIGNMENT_BEGINNING ,
00842                    XmNinitialResourcesPersistent , False ,
00843                 NULL ) ;
00844 
00845       XtAddCallback( wbut , XmNactivateCallback , MCW_unhelp_CB , wpop ) ;
00846 
00847       XmUpdateDisplay( wpar ) ;
00848       RWC_XtPopdown( wpop ) ;
00849 
00850       XmAddWMProtocolCallback(
00851            wpop ,
00852            XmInternAtom( XtDisplay(wpop) , "WM_DELETE_WINDOW" , False ) ,
00853            MCW_unhelp_CB , wpop ) ;
00854 
00855       if( ! XtIsRealized(wpar) ) return ;
00856    }
00857 
00858    if( msg == NULL || strlen(msg) == 0 ) return ; /* no popup if no message */
00859 
00860    xstr = XmStringCreateLtoR( msg , XmFONTLIST_DEFAULT_TAG ) ;
00861    XtVaSetValues( wbut , XmNlabelString , xstr , NULL ) ;
00862    XmStringFree( xstr ) ;
00863 
00864 #ifndef USE_LOCATE
00865    if( cbs != NULL && cbs->event != NULL
00866                    && cbs->event->type == ButtonRelease ){
00867       XButtonEvent * xev = (XButtonEvent *) cbs->event ;
00868       xx = xev->x_root ;
00869       yy = xev->y_root ;
00870    } else
00871 #endif
00872    XtTranslateCoords( w , 15,15 , &xx , &yy ) ;    /* coordinates on root */
00873 
00874    MCW_widget_geom( wpop , &ww,&hh , NULL,NULL ) ; /* widget width and height */
00875    sw = WidthOfScreen (XtScreen(wpop)) ;           /* screen width and height */
00876    sh = HeightOfScreen(XtScreen(wpop)) ;
00877 
00878    if( xx+ww+3 >= sw && ww <= sw ) xx = sw-ww ;    /* make sure is on screen */
00879    if( yy+hh+3 >= sh && hh <= sh ) yy = sh-hh ;
00880 
00881    XtVaSetValues( wpop , XmNx , (int) xx , XmNy , (int) yy , NULL ) ;
00882    XtPopup( wpop , XtGrabNone ) ;
00883    RWC_visibilize(wpop) ;  /* 27 Sep 2000 */
00884    NORMAL_cursorize(wpop) ;
00885    return ;
00886 }
00887 
00888 /*---------------------------------------------------------------------*/
00889 
00890 void MCW_unhelp_CB( Widget w , XtPointer client_data , XtPointer call_data )
00891 {
00892    Widget wpop = (Widget) client_data ;
00893 
00894    RWC_XtPopdown(wpop) ;
00895    return ;
00896 }
00897 
00898 /*---------------------------------------------------------------------*/
00899 
00900 int MCW_filetype( char * fname )
00901 {
00902    FILE * fff ;
00903 
00904    if( fname == NULL || strlen(fname) == 0 ) return MCW_nofile ;
00905 
00906    fff = fopen( fname , "r+" ) ;  /* open for read-update */
00907    fclose( fff ) ;
00908 
00909    if( fff != NULL ) return MCW_readwrite ;
00910 
00911    fff = fopen( fname , "r" ) ;   /* open for read-only */
00912    fclose(fff) ;
00913 
00914    if( fff != NULL ) return MCW_readonly ;
00915 
00916    return MCW_nofile ;
00917 }
00918 
00919 /*-------------------------------------------------------------------*/
00920 
00921 #if 0
00922 Boolean MCW_isitmwm( Widget w )
00923 {
00924    Widget wsh ;
00925 
00926    if( w == NULL || ! XtIsWidget(w) ) return False ;
00927 
00928    wsh = w ;
00929 
00930    while( ! XtIsShell(wsh) ){
00931       wsh = XtParent(wsh) ;
00932       if( wsh == NULL ) return False ;
00933    }
00934 
00935 #if 1
00936    return XmIsMotifWMRunning(wsh) ;
00937 #else
00938    { int immm = -73 ;
00939      XtVaGetValues( wsh , XmNmwmDecorations , &immm , NULL ) ;
00940      if( immm == -73 ) return False ;
00941      else              return True ;
00942    }
00943 #endif
00944 }
00945 #endif
00946 
00947 /*------------------------------------------------------------------
00948    Popup a scale that will serve as a progress meter.
00949    The meter is set initially to 0, and can later be set to any
00950    value from 0 to 100 using MCW_set_meter().
00951 
00952    wparent is the widget the meter will be attached to
00953    position is one of
00954      METER_TOP      = meter on top of wparent, default width
00955      METER_TOP_WIDE = meter on top of parent, width of parent
00956      METER_BOT      = similar, but on bottom of parent
00957      METER_BOT_WIDE
00958 --------------------------------------------------------------------*/
00959 
00960 #define METER_HEIGHT 10
00961 #define METER_WIDTH  200
00962 
00963 Widget MCW_popup_meter( Widget wparent , int position )
00964 {
00965    Widget wmsg , wscal ;
00966    int wx,hy,xx,yy , xp,yp , scr_width,scr_height , xr,yr , xpr,ypr , wid ;
00967    Screen * scr ;
00968    XEvent ev ;
00969    Position xroot , yroot ;
00970 
00971 ENTRY("MCW_popup_meter") ;
00972 
00973    if( wparent == NULL || ! XtIsRealized( wparent ) ) RETURN(NULL) ;
00974 
00975    /* set position parent and screen geometry */
00976 
00977    MCW_widget_geom( wparent , &wx,&hy,&xx,&yy ) ;     /* geometry of parent */
00978    XtTranslateCoords( wparent, 0,0, &xroot,&yroot ) ; /* root coords of parent */
00979    xr = (int) xroot ; yr = (int) yroot ;
00980 
00981    scr        = XtScreen( wparent ) ;
00982    scr_width  = WidthOfScreen( scr ) ;
00983    scr_height = HeightOfScreen( scr ) ;
00984 
00985    switch( position ){
00986 
00987       default:
00988       case METER_TOP:
00989       case METER_TOP_WIDE:
00990          xpr = xr ;
00991          ypr = yr - METER_HEIGHT-2 ;
00992          wid = (position==METER_TOP_WIDE) ? wx : METER_WIDTH ;
00993          if( ypr < 0 ) ypr = yr+hy+1 ;
00994       break ;
00995 
00996       case METER_BOT:
00997       case METER_BOT_WIDE:
00998          xpr = xr ;
00999          ypr = yr+hy+1 ;
01000          wid = (position==METER_BOT_WIDE) ? wx : METER_WIDTH ;
01001          if( ypr+METER_HEIGHT > scr_height ) ypr = yr - METER_HEIGHT-2 ;
01002       break ;
01003    }
01004 
01005    /* create a popup shell with a scale */
01006 
01007    wmsg = XtVaCreatePopupShell(
01008              "menu" , xmDialogShellWidgetClass , wparent ,
01009                 XmNx , xpr ,
01010                 XmNy , ypr ,
01011                 XmNborderWidth , 0 ,
01012                 XmNoverrideRedirect , True ,
01013                 XmNinitialResourcesPersistent , False ,
01014              NULL ) ;
01015 
01016 #if 0
01017    if( MCW_isitmwm( wparent ) ){
01018       XtVaSetValues( wmsg ,
01019                         XmNmwmDecorations , MWM_DECOR_BORDER ,
01020                         XmNmwmFunctions   , MWM_FUNC_MOVE ,
01021                      NULL ) ;
01022    }
01023 #endif
01024 
01025    wscal = XtVaCreateManagedWidget(
01026             "menu" , xmScaleWidgetClass , wmsg ,
01027                XmNminimum , 0 ,
01028                XmNmaximum , 100 ,
01029                XmNshowValue , False ,
01030                XmNvalue , 0 ,
01031                XmNorientation , XmHORIZONTAL ,
01032                XmNscaleWidth , wid ,
01033                XmNscaleHeight , METER_HEIGHT ,
01034                XmNborderWidth , 0 ,
01035                XmNhighlightThickness , 0 ,
01036                XmNshadowThickness , 0 ,
01037                XmNtraversalOn , False ,
01038                XmNinitialResourcesPersistent , False ,
01039             NULL ) ;
01040 
01041    XtPopup( wmsg , XtGrabNone ) ;
01042 
01043    RETURN(wscal) ;
01044 }
01045 
01046 /*--------------------------------------------------------------------*/
01047 
01048 void MCW_popdown_meter( Widget wscal )
01049 {
01050    if( wscal == NULL ) return ;
01051    XtDestroyWidget( XtParent(wscal) ) ;
01052    return ;
01053 }
01054 
01055 /*--------------------------------------------------------------------*/
01056 
01057 void MCW_set_meter( Widget wscal , int percent )
01058 {
01059    int val , old ;
01060 
01061 #undef  NCOL
01062 #define NCOL 30
01063 #ifdef NCOL
01064    static int icol=0 ;
01065    static char *cname[] = {
01066       "#0000ff", "#3300ff", "#6600ff", "#9900ff", "#cc00ff",
01067       "#ff00ff", "#ff00cc", "#ff0099", "#ff0066", "#ff0033",
01068       "#ff0000", "#ff3300", "#ff6600", "#ff9900", "#ffcc00",
01069       "#ffff00", "#ccff00", "#99ff00", "#66ff00", "#33ff00",
01070       "#00ff00", "#00ff33", "#00ff66", "#00ff99", "#00ffcc",
01071       "#00ffff", "#00ccff", "#0099ff", "#0066ff", "#0033ff"
01072     } ;
01073 #endif
01074 
01075    val = percent ;
01076    if( wscal == NULL || val < 0 || val > 100 ) return ;
01077 
01078    XmScaleGetValue( wscal , &old ) ; if( val == old ) return ;
01079 
01080    XtVaSetValues( wscal , XmNvalue , val , NULL ) ;
01081 
01082 #ifdef NCOL
01083    { Widget ws = XtNameToWidget(wscal,"Scrollbar") ;
01084      if( ws != NULL )
01085      XtVaSetValues( ws ,
01086                      XtVaTypedArg , XmNtroughColor , XmRString ,
01087                                     cname[icol] , strlen(cname[icol])+1 ,
01088                    NULL ) ;
01089      icol = (icol+1) % NCOL ;
01090    }
01091 #endif
01092 
01093    XmUpdateDisplay(wscal) ;
01094    return ;
01095 }
01096 
01097 /*-----------------------------------------------------------------------*/
01098 
01099 #define RONLY_NUM 1
01100 #define EDIT_NUM  2
01101 
01102 static MCW_action_item TWIN_act[] = {
01103  { "Quit" , MCW_textwin_CB , NULL , NULL , "Close window" , 0 } ,
01104  { "Set"  , MCW_textwin_CB , NULL , NULL , "Apply choice and close window" , 0 }
01105 } ;
01106 
01107 MCW_textwin * new_MCW_textwin( Widget wpar, char * msg, int type )
01108 {
01109    return new_MCW_textwin_2001( wpar,msg,type , NULL,NULL ) ;
01110 }
01111 
01112 /*-----------------------------------------------------------------------
01113    Modified 10 Jul 2001 to include killing callback
01114 -------------------------------------------------------------------------*/
01115 
01116 MCW_textwin * new_MCW_textwin_2001( Widget wpar, char * msg, int type,
01117                                     void_func * kill_func , XtPointer kill_data )
01118 {
01119    MCW_textwin * tw ;
01120    int wx,hy,xx,yy , xp,yp , scr_width,scr_height , xr,yr , xpr,ypr , ii,nact ;
01121    int swid , shi ;
01122    Position xroot , yroot ;
01123    Screen * scr ;
01124    Boolean editable ;
01125    Arg wa[64] ; int na ;
01126 
01127 ENTRY("new_MCW_textwin_2001") ;
01128 
01129    /*-- sanity check --*/
01130 
01131    if( ! XtIsRealized(wpar) ) RETURN(NULL) ;
01132 
01133    /* set position based on parent and screen geometry */
01134 
01135    MCW_widget_geom( wpar , &wx,&hy,&xx,&yy ) ;     /* geometry of parent */
01136    XtTranslateCoords( wpar, 0,0, &xroot,&yroot ) ; /* root coords */
01137    xr = (int) xroot ; yr = (int) yroot ;
01138 
01139    scr        = XtScreen(wpar) ;
01140    scr_width  = WidthOfScreen(scr) ;
01141    scr_height = HeightOfScreen(scr) ;
01142 
01143    xp = xx+8 ;  xpr = xr+8 ;
01144         if( xpr+50 > scr_width ){ xp -= 100 ; xpr -= 100 ; } /* too right */
01145    else if( xpr+10 < 0 )        { xpr = xp = 1 ; }           /* too left  */
01146 
01147    yp = yy+hy+8 ;  ypr = yr+hy+8 ;
01148         if( ypr+50 > scr_height ){ yp = yy-8 ; ypr = yr-100 ;} /* too down */
01149    else if( ypr+10 < 0 )         { ypr = yp = 1 ;            } /* too up   */
01150 
01151    /* create a popup shell */
01152 
01153    tw = myXtNew(MCW_textwin) ;
01154 
01155    tw->kill_func = kill_func ;  /* 10 Jul 2001 */
01156    tw->kill_data = kill_data ;
01157 
01158    tw->wshell = XtVaCreatePopupShell(
01159                  "menu" , xmDialogShellWidgetClass , wpar ,
01160                     XmNx , xpr ,
01161                     XmNy , ypr ,
01162                     XmNborderWidth , 0 ,
01163                     XmNborderColor , 0 ,
01164                     XmNinitialResourcesPersistent , False ,
01165                  NULL ) ;
01166 
01167    XmAddWMProtocolCallback(
01168         tw->wshell ,
01169         XmInternAtom( XtDisplay(tw->wshell) , "WM_DELETE_WINDOW" , False ) ,
01170         MCW_textwinkill_CB , (XtPointer) tw ) ;
01171 
01172    /* create a form to hold everything else */
01173 
01174    tw->wtop = XtVaCreateWidget(
01175                 "menu" , xmFormWidgetClass , tw->wshell ,
01176                   XmNborderWidth , 0 ,
01177                   XmNborderColor , 0 ,
01178                   XmNtraversalOn , False ,
01179                   XmNinitialResourcesPersistent , False ,
01180                 NULL ) ;
01181 
01182    /* create action area */
01183 
01184    editable = (Boolean) (type == TEXT_EDITABLE) ;
01185 
01186    nact = (editable) ? EDIT_NUM : RONLY_NUM ;
01187    for( ii=0 ; ii < nact ; ii++ ){
01188      TWIN_act[ii].data     = (XtPointer) tw ;
01189      TWIN_act[ii].make_red = 0 ;
01190    }
01191    TWIN_act[nact-1].make_red = 1 ;
01192 
01193    tw->wactar = MCW_action_area( tw->wtop , TWIN_act , nact ) ;
01194 
01195    /* create text area */
01196 
01197    tw->wscroll = XtVaCreateManagedWidget(
01198                     "menu" , xmScrolledWindowWidgetClass , tw->wtop ,
01199                        XmNscrollingPolicy        , XmAUTOMATIC ,
01200                        XmNvisualPolicy           , XmVARIABLE ,
01201                        XmNscrollBarDisplayPolicy , XmAS_NEEDED ,
01202 
01203                        XmNleftAttachment  , XmATTACH_FORM ,
01204                        XmNrightAttachment , XmATTACH_FORM ,
01205                        XmNbottomAttachment, XmATTACH_FORM ,
01206                        XmNtopAttachment   , XmATTACH_WIDGET ,
01207                        XmNtopWidget       , tw->wactar ,
01208                        XmNtopOffset       , 7 ,
01209 
01210                        XmNinitialResourcesPersistent , False ,
01211                     NULL ) ;
01212 
01213    XtVaSetValues( tw->wactar ,
01214                      XmNleftAttachment , XmATTACH_FORM ,
01215                      XmNrightAttachment, XmATTACH_FORM ,
01216                      XmNtopAttachment  , XmATTACH_FORM ,
01217                      XmNtopOffset      , 7 ,
01218                   NULL ) ;
01219 
01220    tw->wtext = XtVaCreateManagedWidget(
01221                     "menu" , xmTextWidgetClass , tw->wscroll ,
01222                        XmNeditMode               , XmMULTI_LINE_EDIT ,
01223                        XmNautoShowCursorPosition , editable ,
01224                        XmNeditable               , editable ,
01225                        XmNcursorPositionVisible  , editable ,
01226                     NULL ) ;
01227 
01228    if( msg == NULL ) msg = "\0" ;  /* 27 Sep 2000 */
01229 
01230    if( msg != NULL ){
01231       int cmax = 20 , ll , nlin ;
01232       char * cpt , *cold , cbuf[128] ;
01233       XmString xstr ;
01234       XmFontList xflist ;
01235 
01236       XtVaSetValues( tw->wtext , XmNvalue , msg , NULL ) ;
01237       XtVaGetValues( tw->wtext , XmNfontList , &xflist , NULL ) ;
01238 
01239       cmax = 20 ; nlin = 1 ;
01240       for( cpt=msg,cold=msg ; *cpt != '\0' ; cpt++ ){
01241          if( *cpt == '\n' ){
01242             ll = cpt - cold - 1 ; if( cmax < ll ) cmax = ll ;
01243             cold = cpt ; nlin++ ;
01244          }
01245       }
01246       ll = cpt - cold - 1 ; if( cmax < ll ) cmax = ll ;
01247       if( cmax > 100 ) cmax = 100 ;
01248       cmax+=3 ;
01249       for( ll=0 ; ll < cmax ; ll++ ) cbuf[ll] = 'x' ;
01250       cbuf[cmax] = '\0' ;
01251 
01252       xstr = XmStringCreateLtoR( cbuf , XmFONTLIST_DEFAULT_TAG ) ;
01253       swid = XmStringWidth ( xflist , xstr ) + 44 ;
01254       shi  = XmStringHeight( xflist , xstr ) * nlin + 66 ;
01255       XmStringFree( xstr ) ;
01256 
01257       cmax = WidthOfScreen(XtScreen(wpar)) - 128 ;
01258       if( swid > cmax ) swid = cmax ;
01259 
01260       cmax = HeightOfScreen(XtScreen(wpar)) - 128 ;
01261       if( shi > cmax ) shi = cmax ;
01262    } else {
01263       swid = shi = 100 ;
01264    }
01265 
01266    XtManageChild( tw->wtop ) ;
01267 
01268    XtVaSetValues( tw->wshell , XmNwidth,swid , XmNheight,shi , NULL ) ;
01269 
01270    XtPopup( tw->wshell , XtGrabNone ) ;
01271 
01272    RWC_visibilize_widget( tw->wshell ) ;  /* 09 Nov 1999 */
01273 
01274    RWC_xineramize( XtDisplay(tw->wshell) ,
01275                    xpr,ypr,swid,shi , &xpr,&ypr ); /* 27 Sep 2000 */
01276 
01277    XtVaSetValues( tw->wshell, XmNx,xpr , XmNy,ypr , NULL ) ;
01278 
01279    tw->shell_width = swid ; tw->shell_height = shi ; /* 10 Jul 2001 */
01280 
01281    NORMAL_cursorize( tw->wshell ) ;
01282    RETURN(tw) ;
01283 }
01284 
01285 /*--------------------------------------------------------------------*/
01286 
01287 void MCW_textwin_alter( MCW_textwin * tw , char * mmm ) /* 10 Jul 2001 */
01288 {
01289    int swid , shi ;
01290    char * msg = mmm ;
01291    int cmax = 20 , ll , nlin ;
01292    char * cpt , *cold , cbuf[128] ;
01293    XmString xstr ;
01294    XmFontList xflist ;
01295 
01296 ENTRY("MCW_textwin_alter") ;
01297 
01298    if( tw == NULL ) EXRETURN ;     /* bad */
01299 
01300    if( msg == NULL ) msg = " " ; /* don't let user be so stupid */
01301 
01302 #if 0
01303    /*-- compute size of text window with new message in it --*/
01304 
01305    XtVaGetValues( tw->wtext , XmNfontList , &xflist , NULL ) ;
01306 
01307    /* find longest line in msg */
01308 
01309    cmax = 20 ; nlin = 1 ;
01310    for( cpt=msg,cold=msg ; *cpt != '\0' ; cpt++ ){
01311       if( *cpt == '\n' ){
01312          ll = cpt - cold - 1 ; if( cmax < ll ) cmax = ll ;
01313          cold = cpt ; nlin++ ;
01314       }
01315    }
01316    ll = cpt - cold - 1 ; if( cmax < ll ) cmax = ll ;
01317    if( cmax > 100 ) cmax = 100 ;
01318 
01319    /* fill a dummy string of that length, plus a bit */
01320 
01321    cmax+=3 ;
01322    for( ll=0 ; ll < cmax ; ll++ ) cbuf[ll] = 'x' ;
01323    cbuf[cmax] = '\0' ;
01324 
01325    /* find width, height of the dummy string */
01326 
01327    xstr = XmStringCreateLtoR( cbuf , XmFONTLIST_DEFAULT_TAG ) ;
01328    swid = XmStringWidth ( xflist , xstr ) + 44 ;
01329    shi  = XmStringHeight( xflist , xstr ) * nlin + 66 ;
01330    XmStringFree( xstr ) ;
01331 
01332    /* find width, height of screen */
01333 
01334    cmax = WidthOfScreen(XtScreen(tw->wshell)) - 128 ;
01335    if( swid > cmax ) swid = cmax ;
01336 
01337    cmax = HeightOfScreen(XtScreen(tw->wshell)) - 128 ;
01338    if( shi > cmax ) shi = cmax ;
01339 #endif
01340 
01341    /*-- actually set new text --*/
01342 
01343    XtVaSetValues( tw->wtext , XmNvalue , msg , NULL ) ;
01344 
01345 #if 1
01346    MCW_widget_geom( tw->wtext , &swid , &shi , NULL,NULL ) ;
01347    XtVaSetValues( tw->wshell , XmNwidth,swid+29 , XmNheight,shi+59 , NULL ) ;
01348    tw->shell_width = swid+29 ; tw->shell_height = shi+59 ;
01349 #endif
01350 
01351 #if 0
01352    /*-- maybe set new window size --*/
01353 
01354    if( swid > tw->shell_width || shi > tw->shell_height ){
01355       tw->shell_width  = swid = MAX( swid , tw->shell_width ) ;
01356       tw->shell_height = shi  = MAX( shi  , tw->shell_height ) ;
01357       XtVaSetValues( tw->wshell , XmNwidth,swid , XmNheight,shi , NULL ) ;
01358    }
01359 #endif
01360 
01361    EXRETURN ;
01362 }
01363 
01364 /*--------------------------------------------------------------------*/
01365 
01366 void MCW_textwin_CB( Widget w , XtPointer client_data , XtPointer call_data )
01367 {
01368    MCW_textwin * tw = (MCW_textwin *) client_data ;
01369    char * wname     = XtName(w) ;
01370 
01371    if( client_data == NULL ) return ;
01372 
01373    if( strcmp(wname,"Quit") == 0 ){
01374       if( tw->kill_func != NULL )
01375 #if 0
01376         tw->kill_func(tw->kill_data); /* 10 Jul 2001 */
01377 #else
01378         AFNI_CALL_VOID_1ARG( tw->kill_func , XtPointer , tw->kill_data ) ;
01379 #endif
01380       XtDestroyWidget( tw->wshell ) ;
01381       myXtFree( tw ) ;
01382       return ;
01383    }
01384 
01385    XBell( XtDisplay(w) , 100 ) ;
01386    return ;
01387 }
01388 
01389 /*--------------------------------------------------------------------*/
01390 
01391 void MCW_textwinkill_CB( Widget w , XtPointer client_data , XtPointer call_data )
01392 {
01393    MCW_textwin * tw = (MCW_textwin *) client_data ;
01394 
01395    if( tw->kill_func != NULL )
01396 #if 0
01397      tw->kill_func(tw->kill_data); /* 10 Jul 2001 */
01398 #else
01399      AFNI_CALL_VOID_1ARG( tw->kill_func , XtPointer , tw->kill_data ) ;
01400 #endif
01401    XtDestroyWidget( tw->wshell ) ;
01402    myXtFree( tw ) ;
01403    return ;
01404 }
01405 
01406 /*-----------------------------------------------------------------------
01407    03 Jan 1999: Check if a widget is potentially visible
01408                 -- return 0 if not, 1 if yes.
01409 -------------------------------------------------------------------------*/
01410 
01411 int MCW_widget_visible( Widget w )
01412 {
01413    Window ww ;
01414    XWindowAttributes wa ;
01415 
01416    if( w == (Widget) NULL ) return 0 ;
01417    ww = XtWindow(w) ;
01418    if( ww == (Window) NULL ) return 0 ;
01419 
01420    XGetWindowAttributes( XtDisplay(w) , ww , &wa ) ;
01421 
01422    return ( (wa.map_state == IsViewable) ? 1 : 0 ) ;
01423 }
01424 
01425 /*------------------------------------------------------------------
01426  June 1999: routine to get string constants either from X defaults
01427             or from Unix environment variables.  Returns a pointer
01428             to static storage -- do not free()!
01429 --------------------------------------------------------------------*/
01430 
01431 #include <ctype.h>
01432 
01433 char * RWC_getname( Display * display , char * name )
01434 {
01435    char * cval , qqq[256] ;
01436    int nn , ii ;
01437 
01438    if( name == NULL || name[0] == '\0' ) return NULL ;
01439 
01440    /* try X11 */
01441 
01442    if( display != NULL ){
01443      cval = XGetDefault(display,"AFNI",name) ;
01444      if( cval != NULL ) return cval ;
01445    }
01446 
01447    /* try AFNI_name */
01448 
01449    strcpy(qqq,"AFNI_") ; strcat(qqq,name) ;
01450    cval = my_getenv(qqq) ;
01451    if( cval != NULL ) return cval ;
01452 
01453    /* try AFNI_NAME (uppercase it) */
01454 
01455    strcpy(qqq,"AFNI_") ; nn = strlen(name) ;
01456    for( ii=0 ; ii < nn && ii < 250 ; ii++ ) qqq[ii+5] = toupper(name[ii]) ;
01457    qqq[ii+5] = '\0' ;
01458    cval = my_getenv(qqq) ;
01459    return cval ;
01460 }
01461 
01462 /*-------------------------------------------------------------------
01463   09 Nov 1999: move a widget to make sure it is visible
01464 ---------------------------------------------------------------------*/
01465 
01466 void RWC_visibilize_widget( Widget w )
01467 {
01468    Position xroot , yroot ;
01469    int wx,hy,xx,yy , scr_width,scr_height , xo,yo ;
01470    Screen *scr ;
01471 
01472 ENTRY("RWC_visibilize_widget") ;
01473 
01474    if( w == NULL || !XtIsWidget(w) ) EXRETURN ;
01475 
01476    MCW_widget_geom( w , &wx,&hy,&xx,&yy ) ;     /* geometry of widget */
01477 
01478    scr        = XtScreen( w ) ;
01479    scr_width  = WidthOfScreen( scr ) ;
01480    scr_height = HeightOfScreen( scr ) ;
01481 
01482    xo = xx ; yo = yy ;                          /* save original position */
01483 
01484    if( xx+wx > scr_width ) xx = scr_width - wx ;
01485    if( xx    < 0         ) xx = 0              ;
01486 
01487    if( yy+hy > scr_height ) yy = scr_height - hy ;
01488    if( yy    < 0          ) yy = 0               ;
01489 
01490    RWC_xineramize( XtDisplay(w) , xx,yy,wx,hy , &xx,&yy ); /* 27 Sep 2000 */
01491 
01492    if( xx != xo || yy != yo )
01493       XtVaSetValues( w , XmNx , xx , XmNy , yy , NULL ) ;
01494 
01495    EXRETURN ;
01496 }
01497 
01498 /*----------------------------------------------------------------------
01499   A callback version of the above (for use when menus are mapped, say)
01500 ------------------------------------------------------------------------*/
01501 
01502 static void RWC_visibilize_timeout_CB( XtPointer cd , XtIntervalId * id )
01503 {
01504    Widget w = (Widget) cd ;
01505 ENTRY("RWC_visibilize_timeout_CB") ;
01506    RWC_visibilize_widget(w) ; EXRETURN ;
01507 }
01508 
01509 /*--------------------------------------------------------------------*/
01510 
01511 void RWC_visibilize_CB( Widget w , XtPointer cd , XtPointer cb )
01512 {
01513    Widget wpar = w ;
01514 ENTRY("RWC_visibilize_CB") ;
01515 
01516    if( AFNI_yesenv("AFNI_DONT_MOVE_MENUS") ) return ;  /* 08 Aug 2001 */
01517 
01518    while( !XtIsShell(wpar) ){ wpar = XtParent(w); } /* find 1st shell parent */
01519 
01520    /* must wait for the thing to actually appear, dammit */
01521 
01522    (void) XtAppAddTimeOut( XtWidgetToApplicationContext(wpar) ,
01523                            1 , RWC_visibilize_timeout_CB , wpar ) ;
01524    EXRETURN ;
01525 }
01526 
01527 /*----------------------------------------------------------------------
01528    Given a rectangle (xx..xx+ww,yy..yy+hh), return the new origin
01529    (xn,yn) so that the rectangle (xn..xn+ww,yn..yn+hh) fits onto
01530    a single Xinerama sub-screen.  If the AFNI.xinerama X11 resource is
01531    not found, then this routine uses the display size.
01532    -- RWCox -- 27 Sep 2000
01533 ------------------------------------------------------------------------*/
01534 
01535 #define BUF 5  /* buffer around the rectangle */
01536 
01537 void RWC_xineramize( Display * dpy,
01538                      int xx, int yy, int ww, int hh, int *xn, int *yn )
01539 {
01540    static int first=1 ;
01541    static int nxsi=0 , *xbot,*ybot,*xtop,*ytop ;
01542    int ii , ss ;
01543 
01544 ENTRY("RWC_xineramize") ;
01545 
01546    if( dpy==NULL || xn==NULL || yn==NULL || ww<0 || hh<0 ) EXRETURN; /* ERROR */
01547 
01548    /*--- first time in: check AFNI.xinerama X resource
01549                         load boundaries of sub-screens from resource ---*/
01550 
01551    if( first ){
01552       char * xdef , * xp ;
01553       int nn,xorg,yorg,wide,high ;
01554 
01555       first = 0 ;                         /* never again */
01556       xdef  = getenv( "AFNI_XINERAMA" ) ;
01557 
01558       if( xdef != NULL && (xdef[0] == 'N' || xdef[0] == 'n') ){ /* skip Xinerama */
01559          nxsi = 0 ;
01560          STATUS("AFNI_XINERAMA is NO") ;
01561       } else {
01562          xdef = XGetDefault(dpy,"AFNI","xinerama") ; /* get resource */
01563          if( xdef == NULL ) xdef = getenv("AFNI_xinerama") ;  /* 27 Oct 2003 */
01564          if( xdef != NULL ){
01565             char *qdef = strdup(xdef) ;
01566             for( nn=0 ; qdef[nn] != '\0' ; nn++ )
01567               if( qdef[nn] == '_' || qdef[nn] == ':' ) qdef[nn] = ' ' ;
01568 
01569             nn = 0 ; sscanf(qdef,"%d%n",&nxsi,&nn) ;  /* number of sub-screens */
01570             if( nn <= 0 || nxsi <= 1 ){               /* ERROR */
01571                nxsi = 0 ;
01572             } else {
01573                xbot = (int *) malloc(sizeof(int)*nxsi) ; /* make arrays to */
01574                ybot = (int *) malloc(sizeof(int)*nxsi) ; /* store sub-screen */
01575                xtop = (int *) malloc(sizeof(int)*nxsi) ; /* coordinate ranges */
01576                ytop = (int *) malloc(sizeof(int)*nxsi) ;
01577                xp = qdef + nn ;
01578                for( ii=0 ; ii < nxsi ; ii++ ){    /* scan for sub-screen info */
01579                   nn = 0 ;
01580                   sscanf(xp,"%d%d%d%d%d%n",&ss,&xorg,&yorg,&wide,&high,&nn) ;
01581                   if( nn <= 0 ) break ;           /* ERROR */
01582                   xbot[ii] = xorg ; xtop[ii] = xorg+wide ;
01583                   ybot[ii] = yorg ; ytop[ii] = yorg+high ;
01584                   xp += nn ;
01585 
01586                   if(PRINT_TRACING){
01587                     char str[256] ;
01588                     sprintf(str," Screen %d: xbot=%4d ybot=%4d xtop=%4d ytop=%4d",
01589                                   ii,xbot[ii],ybot[ii],xtop[ii],ytop[ii] ) ;
01590                     STATUS(str) ;
01591                   }
01592                }
01593 
01594                nxsi = ii ;  /* in case the scan aborted */
01595             }
01596          }
01597       }
01598 
01599       /* if nothing found yet, use the display size */
01600 
01601       if( nxsi <= 0 ){
01602          nxsi = 1 ;
01603          xbot = (int *) malloc(sizeof(int)*nxsi) ;
01604          ybot = (int *) malloc(sizeof(int)*nxsi) ;
01605          xtop = (int *) malloc(sizeof(int)*nxsi) ;
01606          ytop = (int *) malloc(sizeof(int)*nxsi) ;
01607          xbot[0] = ybot[0] = 0 ;
01608          xtop[0] = WidthOfScreen(DefaultScreenOfDisplay(dpy)) ;
01609          ytop[0] = HeightOfScreen(DefaultScreenOfDisplay(dpy)) ;
01610       }
01611    }
01612 
01613 #if 0                                           /* doesn't occur anymore */
01614    if( nxsi == 0 ){ *xn=xx; *yn=yy; EXRETURN; } /* not setup? change nothing */
01615 #endif
01616 
01617    /*--- find the Xinerama sub-screen that (xx,yy) is on (if any) ---*/
01618 
01619    if( nxsi > 1 ){
01620       for( ss=0 ; ss < nxsi ; ss++ ){
01621          if( xx >= xbot[ss] && xx < xtop[ss] &&
01622              yy >= ybot[ss] && yy < ytop[ss]   ) break ;
01623       }
01624    } else {
01625       ss = 0 ;  /* must use #0 - what else is there? */
01626    }
01627 
01628    if(PRINT_TRACING){
01629       char str[256] ;
01630       sprintf(str,"Rect: xx=%d yy=%d ww=%d hh=%d; On ss=%d",xx,yy,ww,hh,ss); STATUS(str);
01631    }
01632 
01633    /*--- if not inside any screen, find one it is closest to ---*/
01634 
01635    if( ss >= nxsi ){
01636       int dleft,dright,dtop,dbot,dd , dmin , xdif,ydif ;
01637       dmin = 123456789 ; ss = 0 ;
01638       for( ii=0 ; ii < nxsi; ii++ ){
01639          xdif = (xx < xbot[ii]) ? (xbot[ii]-xx)       /* x dist to    */
01640                :(xx > xtop[ii]) ? (xx-xtop[ii]) : 0 ; /* [xbot..xtop] */
01641 
01642          ydif = (yy < ybot[ii]) ? (ybot[ii]-yy)
01643                :(yy > ytop[ii]) ? (yy-ytop[ii]) : 0 ;
01644 
01645          dleft  = abs(xx-xbot[ii]) + ydif ;  /* L1 dist to left edge */
01646          dright = abs(xx-xtop[ii]) + ydif ;
01647          dbot   = abs(yy-ybot[ii]) + xdif ;
01648          dtop   = abs(yy-ytop[ii]) + xdif ;
01649 
01650                            dd = dleft ;      /* find smallest dist */
01651          if( dright < dd ) dd = dright ;
01652          if( dbot   < dd ) dd = dbot ;
01653          if( dtop   < dd ) dd = dtop ;
01654 
01655          if( dd < dmin ){ dmin = dd; ss = ii; } /* smallest so far? */
01656       }
01657 
01658       if(PRINT_TRACING){
01659          char str[256] ; sprintf(str,"New ss=%d",ss) ; STATUS(str) ;
01660       }
01661    }
01662 
01663    /*--- now adjust position so all of rectangle
01664          (xx..xx+ww,yy..yy+hh) fits on that screen (if possible) ---*/
01665 
01666    if( xx+ww+BUF >= xtop[ss] ){ xx = xtop[ss]-ww-1-2*BUF; } /* move left */
01667    if( yy+hh+BUF >= ytop[ss] ){ yy = ytop[ss]-hh-1-2*BUF; } /* move up  */
01668    if( xx    < xbot[ss]+BUF  ){ xx = xbot[ss]+BUF; }        /* move right */
01669    if( yy    < ybot[ss]+BUF  ){ yy = ybot[ss]+BUF; }        /* move down */
01670 
01671 
01672    if(PRINT_TRACING){
01673       char str[256] ; sprintf(str,"New xx=%d yy=%d",xx,yy) ; STATUS(str) ;
01674    }
01675 
01676    *xn = xx ; *yn = yy ; EXRETURN ;
01677 }
01678 
01679 /*----------------------------------------------------------------------
01680   NULL out a pointer when a widget is destroyed -- 31 Jul 2001 - RWCox
01681 ------------------------------------------------------------------------*/
01682 
01683 void RWC_destroy_nullify_CB( Widget w, XtPointer xp, XtPointer cd )
01684 {
01685    void ** p = (void **) xp ;
01686 ENTRY("RWC_destroy_nullify_CB") ;
01687    if( p != NULL ) *p = NULL ;
01688    EXRETURN ;
01689 }
01690 
01691 void RWC_destroy_nullify( Widget w, void **p )
01692 {
01693    if( p != NULL && w != NULL )
01694      XtAddCallback( w, XmNdestroyCallback, RWC_destroy_nullify_CB, p ) ;
01695    return ;
01696 }
01697 
01698 void RWC_destroy_nullify_cancel( Widget w, void **p )
01699 {
01700    if( w != NULL )
01701      XtRemoveCallback( w, XmNdestroyCallback, RWC_destroy_nullify_CB, p ) ;
01702    return ;
01703 }
01704 
01705 /*---------------------------------------------------------------------------*/
01706 
01707 static RWC_draw_rect( Display *dis, Window win, GC gc,
01708                       int x1, int y1, int x2, int y2  )
01709 {
01710   int xb,yb , xt,yt ;
01711   unsigned int short w,h ;
01712 
01713   if( x1 < x2 ){ xb=x1; xt=x2; } else { xb=x2; xt=x1; }
01714   if( y1 < y2 ){ yb=y1; yt=y2; } else { yb=y2; yt=y1; }
01715   w = xt-xb ; h = yt-yb ;
01716   if( w || h )
01717     XDrawRectangle( dis,win,gc , xb,yb,w,h ) ;
01718   else
01719     XDrawPoint( dis,win,gc , xb,yb ) ;
01720 }
01721 
01722 /*---------------------------------------------------------------------------*/
01723 
01724 static Cursor cur = None ;  /* 17 Jun 2002 */
01725 
01726 static void RWC_drag_cursor( Display *dis )
01727 {
01728    XColor fg , bg ;
01729    Colormap cmap ;
01730    Boolean  good ;
01731 
01732    if( cur == None ){
01733      cur  = XCreateFontCursor( dis , XC_arrow ) ;
01734      cmap = DefaultColormap( dis , DefaultScreen(dis) ) ;
01735      good =   XParseColor( dis, cmap, "yellow" , &fg )
01736            && XParseColor( dis, cmap, "red"    , &bg )  ;
01737      if( good ) XRecolorCursor( dis , cur , &fg , &bg ) ;
01738    }
01739 }
01740 
01741 void RWC_drag_rectangle( Widget w, int x1, int y1, int *x2, int *y2 )
01742 {
01743    Display *dis ;
01744    Window win , rW,cW ;
01745    int grab , xold,yold , x,y, rx,ry , first=1 ;
01746    unsigned int mask ;                                      /* which buttons */
01747    unsigned int bmask=Button1Mask|Button2Mask|Button3Mask ; /* all buttons  */
01748    XGCValues  gcv;
01749    GC         myGC ;
01750 
01751 
01752 ENTRY("RWC_drag_rectangle") ;
01753 
01754    /** make a GC for invert drawing **/
01755 
01756    gcv.function = GXinvert ;
01757    myGC         = XtGetGC( w , GCFunction , &gcv ) ;
01758 
01759    /** grab the pointer (so no one else gets events from it),
01760        and confine it to the window in question              **/
01761 
01762    dis = XtDisplay(w) ; win = XtWindow(w) ;
01763 
01764    RWC_drag_cursor(dis) ;
01765 
01766    grab = !XGrabPointer(dis, win, False, 0, GrabModeAsync,
01767                         GrabModeAsync, win, cur , (Time)CurrentTime);
01768 
01769    /* grab fails => exit */
01770 
01771    if( !grab ){ XBell(dis,100); *x2=x1; *y2=y1; EXRETURN; }
01772 
01773    xold = x1 ; yold = y1 ;  /* current location of pointer */
01774 
01775    /** loop and find out where the pointer is (while button is down) **/
01776 
01777    while( XQueryPointer(dis,win,&rW,&cW,&rx,&ry,&x,&y,&mask) ){
01778 
01779      /* check if all buttons are released */
01780 
01781      if( !(mask & bmask) ) break ;  /* no button down => done! */
01782 
01783      /* pointer now at (x,y) in the window */
01784 
01785      /* if it has moved, redraw rectangle */
01786 
01787      if( x != xold || y != yold ){
01788 
01789        if( !first )  /* undraw old rectangle */
01790          RWC_draw_rect( dis,win,myGC , x1,y1 , xold,yold ) ;
01791 
01792        /* draw new rectangle */
01793 
01794        xold = x ; yold = y ; first = 0 ;
01795        RWC_draw_rect( dis,win,myGC , x1,y1 , xold,yold ) ;
01796 
01797      } /* end of new (x,y) position */
01798 
01799    } /* end of loop while button is pressed */
01800 
01801    if( !first )  /* undraw old rectangle */
01802      RWC_draw_rect( dis,win,myGC , x1,y1 , xold,yold ) ;
01803 
01804    /* clean up */
01805 
01806    XtReleaseGC( w , myGC ) ;
01807    if (grab) XUngrabPointer(dis, (Time)CurrentTime) ;
01808 
01809    *x2 = xold ; *y2 = yold ;  /* output values */
01810    EXRETURN ;
01811 }
01812 
01813 /*---------------------------------------------------------------------------*/
01814 
01815 static RWC_draw_circle( Display *dis, Window win, GC gc, int xc, int yc, int rad )
01816 {
01817    int xb,yb ;
01818    unsigned int ww ;
01819 
01820    if( rad < 0 ) rad = 0 ;
01821    xb = xc-rad ; yb = yc-rad ; ww = 2*rad ;
01822    XDrawArc( dis,win,gc , xb,yb , ww,ww , 0,360*64 ) ;
01823 }
01824 
01825 /*---------------------------------------------------------------------------*/
01826 
01827 void RWC_drag_circle( Widget w, int x1, int y1, int *radius )
01828 {
01829    Display *dis ;
01830    Window win , rW,cW ;
01831    int grab , xold,yold , x,y, rx,ry , first=1 , rrr=0 ;
01832    unsigned int mask ;                                      /* which buttons */
01833    unsigned int bmask=Button1Mask|Button2Mask|Button3Mask ; /* all buttons  */
01834    XGCValues  gcv;
01835    GC         myGC ;
01836 
01837 ENTRY("RWC_drag_circle") ;
01838 
01839    /** make a GC for invert drawing **/
01840 
01841    gcv.function = GXinvert ;
01842    myGC         = XtGetGC( w , GCFunction , &gcv ) ;
01843 
01844    /** grab the pointer (so no one else gets events from it),
01845        and confine it to the window in question              **/
01846 
01847    dis = XtDisplay(w) ; win = XtWindow(w) ;
01848 
01849    RWC_drag_cursor(dis) ;
01850 
01851    grab = !XGrabPointer(dis, win, False, 0, GrabModeAsync,
01852                         GrabModeAsync, win, cur , (Time)CurrentTime);
01853 
01854    /* grab fails => exit */
01855 
01856    if( !grab ){ XBell(dis,100); *radius=0; EXRETURN; }
01857 
01858    xold = x1 ; yold = y1 ;  /* current location of pointer */
01859 
01860    /** loop and find out where the pointer is (while button is down) **/
01861 
01862    while( XQueryPointer(dis,win,&rW,&cW,&rx,&ry,&x,&y,&mask) ){
01863 
01864      /* check if all buttons are released */
01865 
01866      if( !(mask & bmask) ) break ;  /* no button down => done! */
01867 
01868      /* pointer now at (x,y) in the window */
01869 
01870      /* if it has moved, redraw rectangle */
01871 
01872      if( x != xold || y != yold ){
01873 
01874        if( !first )  /* undraw old circle */
01875          RWC_draw_circle( dis,win,myGC , x1,y1 , rrr ) ;
01876 
01877        /* draw new circle */
01878 
01879        xold = x ; yold = y ; first = 0 ;
01880        rrr = (int)rint(sqrt( (x-x1)*(x-x1) + (y-y1)*(y-y1) )) ;
01881        RWC_draw_circle( dis,win,myGC , x1,y1 , rrr ) ;
01882 
01883      } /* end of new (x,y) position */
01884 
01885    } /* end of loop while button is pressed */
01886 
01887    if( !first )  /* undraw old circle */
01888      RWC_draw_circle( dis,win,myGC , x1,y1 , rrr ) ;
01889 
01890    /* clean up */
01891 
01892    XtReleaseGC( w , myGC ) ;
01893    if (grab) XUngrabPointer(dis, (Time)CurrentTime) ;
01894 
01895    *radius = rrr ;
01896    EXRETURN ;
01897 }
01898 
01899 /*-------------------------------------------------------------------*/
01900 /*!  Sleep a given # of milliseconds (uses the Unix select routine).
01901 ---------------------------------------------------------------------*/
01902 
01903 #include <sys/time.h>
01904 #include <sys/types.h>
01905 #include <unistd.h>
01906 
01907 void RWC_sleep( int msec )
01908 {
01909    struct timeval tv ;
01910    if( msec <= 0 ) return ;             /* can't wait into the past */
01911    tv.tv_sec  = msec/1000 ;
01912    tv.tv_usec = (msec%1000)*1000 ;
01913    select( 1 , NULL,NULL,NULL , &tv ) ;
01914    return ;
01915 }
01916 
01917 /*-----------------------------------------------------------------*/
01918 /*! Popdown a widget that may not be a shell. [30 Jun 2003]
01919 -------------------------------------------------------------------*/
01920 
01921 void RWC_XtPopdown( Widget w )
01922 {
01923    Widget wpar = w ;
01924 
01925    if( wpar == NULL ) return ;
01926    while( XtIsShell(wpar) == 0 && XtParent(wpar) != NULL ) wpar = XtParent(wpar);
01927    XtPopdown(wpar) ;
01928    return ;
01929 }
01930 
01931 /*-----------------------------------------------------------------*/
01932 /******************** Speech stuff (for Mac OS X) ******************/
01933 
01934 #if !defined(NO_FRIVOLITIES) && defined(DARWIN)
01935 
01936 #include <unistd.h>
01937 #include <string.h>
01938 #include <stdlib.h>
01939 #include <ctype.h>
01940 #include <sys/wait.h>
01941 #include <sys/types.h>
01942 
01943 static int have_say = -1 ;
01944 static char voice[128] = "Cellos" ;
01945 
01946 /*-----------------------------------------------------------------*/
01947 /*! Set the voice for the Apple speech synthesizer. */
01948 
01949 void AFNI_speak_setvoice( char *vvv )
01950 {
01951    int ll ;
01952    if( vvv == NULL || *vvv == '\0' ) return ;
01953    ll = strlen(vvv) ; if( ll > 100 ) return ;
01954    strcpy(voice,vvv) ;               return ;
01955 }
01956 
01957 
01958 /*-----------------------------------------------------------------*/
01959 /*! Speak a string using Apple's say command:
01960     - string = Apple text-to-speech code
01961     - nofork = 1 if you want to wait for the speech to finish;
01962              = 0 if you want the function to return immediately,
01963                  before speech finishes (or perhaps even starts). */
01964 
01965 void AFNI_speak( char *string , int nofork )
01966 {
01967    char *buf ; pid_t ppp ;
01968 
01969    /* bad input ==> quit */
01970 
01971    if( string == NULL || *string == '\0' ) return ;
01972 
01973    /* user says "don't talk" ==> quit */
01974 
01975    buf = getenv("AFNI_SPEECH") ;
01976 #if 1
01977    if( buf == NULL || toupper(*buf) != 'Y' ) return ;   /* 02 Apr 2004 */
01978 #else
01979    if( buf != NULL && toupper(*buf) == 'N' ) return ;
01980 #endif
01981 
01982    /* don't have "say" program ==> quit */
01983 
01984    if( have_say == -1 ) have_say = (THD_find_executable("say") != NULL) ;
01985    if( have_say == 0 ) return ;
01986 
01987    /* if want speech to run in a separate process ... */
01988 
01989    if( !nofork ){
01990      ppp = fork() ;
01991      if( ppp < 0 ) return ; /* fork failed */
01992 
01993      /* parent: wait for child to exit (happens almost instantly) */
01994 
01995      if( ppp > 0 ){ waitpid(ppp,NULL,0); return; }
01996 
01997      /* child: fork again immediately, then this child exits;
01998         this is to prevent zombie processes from hanging around */
01999 
02000      ppp = fork() ; if( ppp != 0 ) _exit(0) ; /* child exits now */
02001 
02002      /* grandchild continues on to actually do something */
02003    }
02004 
02005    /* Run the say program using system() */
02006 
02007    buf = (char *)malloc(strlen(string)+32) ;
02008    sprintf(buf,"say -v%s '%s'",voice,string) ;
02009    system(buf) ; free(buf) ;
02010 
02011    if( !nofork ) _exit(0) ;  /* grandchild exits */
02012    return ;                  /* no forking ==> return to caller */
02013 }
02014 
02015 #else
02016 
02017 void AFNI_speak( char *string , int nofork ){ return; }  /* dummy function */
02018 void AFNI_speak_setvoice( char *vvv ){ return; }
02019 
02020 #endif
 

Powered by Plone

This site conforms to the following standards: