00001 #include "coxplot.h"
00002 #include <Xm/XmAll.h>
00003 #include <ctype.h>
00004 #include "Amalloc.h"
00005 
00006 
00007 
00008 
00009 
00010 
00011 static char print_command[256] = "\0" ;
00012 static char * redcolor = NULL ;
00013 
00014 #ifndef LABEL_ARG
00015 #define LABEL_ARG(str) \
00016   XtVaTypedArg , XmNlabelString , XmRString , (str) , strlen(str)+1
00017 #endif
00018 
00019 #ifndef BGCOLOR_ARG
00020 #define BGCOLOR_ARG(str) \
00021   XtVaTypedArg , XmNbackground , XmRString , (str) , strlen(str)+1
00022 #endif
00023 
00024 #ifndef HOTCOLOR
00025 #define HOTCOLOR(ww,ss)                                                        \
00026   { char * xdef = XGetDefault(XtDisplay(ww),"AFNI","hotcolor") ;               \
00027     if( xdef == NULL ) xdef = getenv("AFNI_hotcolor") ;                        \
00028     if( xdef == NULL ) xdef = getenv("AFNI_HOTCOLOR") ;                        \
00029     if( xdef == NULL ) xdef = XGetDefault(XtDisplay(ww),"AFNI","background") ; \
00030     (ss) = (xdef != NULL) ? (xdef) : ("gray40") ; }
00031 #endif
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 static void beep_CB( Widget w , XtPointer cd , XtPointer cb )
00040 {
00041    char * str = (char *) cd ;
00042 
00043    if( w != NULL ) XBell(XtDisplay(w),100) ;
00044    if( str != NULL && str[0] != '\0' ) fprintf(stderr,"%s\a\n",str) ;
00045    return ;
00046 }
00047 
00048 
00049 
00050 
00051 
00052 
00053 
00054 static void pscancel_CB( Widget w , XtPointer cd , XtPointer cb )
00055 {
00056    MEM_topshell_data * mpcb = (MEM_topshell_data *) cd ;
00057 
00058    if( mpcb == NULL || ! MTD_VALID(mpcb) ) return ;
00059 
00060    if( mpcb->dial != NULL ) XtDestroyWidget( mpcb->dial ) ;
00061    mpcb->dial = mpcb->wtf = NULL ;
00062    return ;
00063 }
00064 
00065 
00066 
00067 static void psfinalize_CB( Widget w , XtPointer cd , XtPointer cb )
00068 {
00069    MEM_topshell_data * mpcb = (MEM_topshell_data *) cd ;
00070    char * text , fname[64] ;
00071    int ii , ll ;
00072 
00073    if( mpcb == NULL || ! MTD_VALID(mpcb) ) return ;
00074 
00075    if( mpcb->dial == NULL ){ XBell(XtDisplay(w),100) ; return ; }
00076 
00077    text = XmTextFieldGetString( mpcb->wtf ) ;
00078    if( text == NULL || text[0] == '\0' ){ XBell(XtDisplay(w),100) ; return ; }
00079 
00080    ll = strlen(text) ;
00081    for( ii=0 ; ii < ll ; ii++ ){
00082       if( iscntrl(text[ii]) || isspace(text[ii]) ||
00083           text[ii] == '/'   || text[ii] == ';'   ||
00084           text[ii] == '*'   || text[ii] == '?'   ||
00085           text[ii] == '&'   || text[ii] == '|'   ||
00086           text[ii] == '"'   || text[ii] == '>'   ||
00087           text[ii] == '<'   || text[ii] == '\''  ||
00088           text[ii] == '['   || text[ii] == ']'     ){
00089 
00090         XBell(XtDisplay(w),100) ; return ;
00091       }
00092    }
00093 
00094    strcpy(fname,text) ;
00095    if( !(ll > 2 && text[ll-2] == 'p' && text[ll-1] == 's' ) )
00096       strcat(fname,".ps") ;
00097 
00098    memplot_to_postscript( fname , mpcb->mp ) ;
00099 
00100    XtDestroyWidget( mpcb->dial ) ;
00101    mpcb->dial = mpcb->wtf = NULL ;
00102    return ;
00103 }
00104 
00105 
00106 
00107 static void psfile_CB( Widget w , XtPointer cd , XtPointer cb )
00108 {
00109    MEM_topshell_data * mpcb = (MEM_topshell_data *) cd ;
00110    Widget wpop , wrc , wlab , wtf , form , but0 , but1 ;
00111    int ibut = 0 ;
00112    Position xx,yy ;
00113 
00114    if( mpcb == NULL || ! MTD_VALID(mpcb) ) return ;
00115 
00116    if( mpcb->dial != NULL ){ XBell(XtDisplay(w),100) ; return ; }
00117 
00118    mpcb->dial = wpop = XtVaCreatePopupShell(
00119              "AFNI" , xmDialogShellWidgetClass , mpcb->top ,
00120                 XmNtraversalOn , False ,
00121                 XmNinitialResourcesPersistent , False ,
00122              NULL ) ;
00123 
00124    XtVaSetValues( wpop ,
00125                      XmNmwmDecorations , MWM_DECOR_BORDER ,
00126                      XmNmwmFunctions   ,  MWM_FUNC_MOVE ,
00127                   NULL ) ;
00128 
00129    wrc  = XtVaCreateWidget(
00130              "menu" , xmRowColumnWidgetClass , wpop ,
00131                 XmNpacking      , XmPACK_TIGHT ,
00132                 XmNorientation  , XmVERTICAL ,
00133                 XmNtraversalOn , False ,
00134                 XmNinitialResourcesPersistent , False ,
00135              NULL ) ;
00136 
00137    wlab = XtVaCreateManagedWidget(
00138              "menu" , xmLabelWidgetClass , wrc ,
00139                 LABEL_ARG("PostScript filename:") ,
00140                 XmNinitialResourcesPersistent , False ,
00141              NULL ) ;
00142 
00143    mpcb->wtf = wtf = XtVaCreateManagedWidget(
00144              "menu" , xmTextFieldWidgetClass , wrc ,
00145                  XmNcolumns         , 20 ,
00146                  XmNeditable        , True ,
00147                  XmNmaxLength       , 32 ,
00148                  XmNresizeWidth     , False ,
00149                  XmNmarginHeight    , 1 ,
00150                  XmNmarginWidth     , 1 ,
00151                  XmNcursorPositionVisible , True ,
00152                  XmNblinkRate , 0 ,
00153                  XmNautoShowCursorPosition , True ,
00154                  XmNinitialResourcesPersistent , False ,
00155                  XmNtraversalOn , False ,
00156               NULL ) ;
00157    XtAddCallback( wtf, XmNactivateCallback, psfinalize_CB, cd ) ; 
00158 
00159 #undef TIG
00160 #undef NBUT
00161 #define TIG  20
00162 #define NBUT 2
00163 
00164    form = XtVaCreateWidget( "menu" , xmFormWidgetClass , wrc ,
00165                                XmNborderWidth , 0 ,
00166                                XmNfractionBase , TIG*NBUT - 1 ,
00167                                XmNinitialResourcesPersistent , False ,
00168                             NULL ) ;
00169 
00170    ibut = 0 ;
00171    but0 = XtVaCreateManagedWidget(
00172                  "menu" , xmPushButtonWidgetClass , form ,
00173                     LABEL_ARG("Cancel") ,
00174                     XmNtopAttachment  , XmATTACH_FORM ,
00175 
00176                     XmNleftAttachment   ,
00177                         (ibut!=0) ? XmATTACH_POSITION : XmATTACH_FORM ,
00178                     XmNleftPosition , ibut*TIG ,
00179 
00180                     XmNrightAttachment  ,
00181                      (ibut==NBUT-1) ? XmATTACH_FORM : XmATTACH_POSITION ,
00182                     XmNrightPosition , ibut*TIG + (TIG-1) ,
00183 
00184                     XmNrecomputeSize , False ,
00185                     XmNtraversalOn   , False ,
00186                     XmNinitialResourcesPersistent , False ,
00187                  NULL ) ;
00188    XtAddCallback( but0 , XmNactivateCallback , pscancel_CB , cd ) ;
00189 
00190 
00191    if( redcolor == NULL ){ HOTCOLOR(form,redcolor) ; }
00192    ibut++ ;
00193    but1 = XtVaCreateManagedWidget(
00194                  "menu" , xmPushButtonWidgetClass , form ,
00195                     LABEL_ARG("Save") ,
00196 #if 1
00197                     BGCOLOR_ARG(redcolor) ,
00198 #endif
00199 
00200                     XmNtopAttachment  , XmATTACH_FORM ,
00201 
00202                     XmNleftAttachment   ,
00203                         (ibut!=0) ? XmATTACH_POSITION : XmATTACH_FORM ,
00204                     XmNleftPosition , ibut*TIG ,
00205 
00206                     XmNrightAttachment  ,
00207                      (ibut==NBUT-1) ? XmATTACH_FORM : XmATTACH_POSITION ,
00208                     XmNrightPosition , ibut*TIG + (TIG-1) ,
00209 
00210                     XmNrecomputeSize , False ,
00211                     XmNtraversalOn   , False ,
00212                     XmNinitialResourcesPersistent , False ,
00213                  NULL ) ;
00214    XtAddCallback( but1 , XmNactivateCallback , psfinalize_CB , cd ) ;
00215 
00216    XtTranslateCoords( mpcb->top , 15,15 , &xx , &yy ) ;
00217    XtVaSetValues( wpop , XmNx , (int) xx , XmNy , (int) yy , NULL ) ;
00218 
00219    XtManageChild( form ) ;
00220    XtManageChild( wrc ) ;
00221    XtPopup( wpop , XtGrabNone ) ;
00222    return ;
00223 }
00224 
00225 
00226 
00227 
00228 
00229 static void psprint_CB( Widget w , XtPointer cd , XtPointer cb )
00230 {
00231    MEM_topshell_data * mpcb = (MEM_topshell_data *) cd ;
00232    MEM_plotdata * mp ;
00233 
00234    if( mpcb == NULL ) return ;
00235    mp = mpcb->mp ; if( mp == NULL ) return ;
00236    memplot_to_postscript( print_command , mp ) ;
00237    return ;
00238 }
00239 
00240 
00241 
00242 
00243 
00244 static void donebut_CB( Widget w , XtPointer cd , XtPointer cb )
00245 {
00246    MEM_topshell_data * mpcb = (MEM_topshell_data *) cd ;
00247 
00248    if( mpcb == NULL || ! MTD_VALID(mpcb) ) return ;
00249 
00250    mpcb->valid = 0 ;
00251 
00252    if( mpcb->killfunc != NULL )
00253 #if 0
00254      mpcb->killfunc( mpcb ) ;
00255 #else
00256      AFNI_CALL_VOID_1ARG( mpcb->killfunc , MEM_topshell_data * , mpcb ) ;
00257 #endif
00258 
00259    if( mpcb->dial != NULL ) XtDestroyWidget( mpcb->dial ) ;
00260 #ifdef HAVE_XDBE
00261    if( mpcb->have_xdbe )
00262       XdbeDeallocateBackBufferName( XtDisplay(mpcb->top) , mpcb->buf_xdbe ) ;
00263 #endif
00264    XtDestroyWidget( mpcb->top ) ;
00265    delete_memplot( mpcb->mp ) ;
00266    free(mpcb) ;
00267 
00268    return ;
00269 }
00270 
00271 
00272 
00273 
00274 
00275 static void expose_CB( Widget w , XtPointer cd , XtPointer cb )
00276 {
00277    XmDrawingAreaCallbackStruct * cbs = (XmDrawingAreaCallbackStruct *) cb ;
00278    MEM_topshell_data * mpcb = (MEM_topshell_data *) cd ;
00279    MEM_plotdata * mp ;
00280    XEvent evjunk ;
00281    Display * dpy = XtDisplay(w) ;
00282    Window  win   = XtWindow(w) ;
00283    Drawable dw   = win ;                               
00284 
00285    if( win == (Window) 0 ) return ;  
00286    if( mpcb == NULL ) return ;
00287    mp = mpcb->mp ; if( mp == NULL ) return ;
00288 
00289    if( cbs != NULL ){
00290       XExposeEvent * ev = (XExposeEvent *) cbs->event ;
00291       if( ev->count > 0 ) return ;
00292    }
00293 
00294 #ifdef HAVE_XDBE
00295    if( use_xdbe > 0 && mpcb->have_xdbe == 0 ){
00296       XdbeSwapInfo info_xdbe ;
00297 
00298       mpcb->buf_xdbe  = XdbeAllocateBackBufferName( dpy,win,XdbeBackground );
00299       mpcb->have_xdbe = 1 ;
00300 
00301       set_X11_background( dpy , win , 255,255,255 ) ;
00302       info_xdbe.swap_window = win ;
00303       info_xdbe.swap_action = XdbeBackground ;
00304       XdbeSwapBuffers( dpy , &info_xdbe , 1 ) ;
00305    }
00306 
00307    if( mpcb->have_xdbe ) dw = mpcb->buf_xdbe ;         
00308 #endif
00309 
00310    set_X11_background( dpy , win , 255,255,255 ) ;
00311    if( dw == win ) XClearWindow( dpy , win ) ;
00312    memplot_to_X11_sef( dpy , dw , mp , 0,0,MEMPLOT_FREE_ASPECT ) ;
00313 
00314 #ifdef HAVE_XDBE
00315    if( mpcb->have_xdbe ){
00316       XdbeSwapInfo info_xdbe ;
00317       info_xdbe.swap_window = win ;
00318       info_xdbe.swap_action = XdbeBackground ;
00319       XdbeSwapBuffers( dpy , &info_xdbe , 1 ) ;
00320     }
00321 #endif
00322 
00323    while( XCheckWindowEvent(dpy, win ,
00324                             ExposureMask|StructureNotifyMask,&evjunk) ) ;
00325    return ;
00326 }
00327 
00328 void redraw_topshell( MEM_topshell_data * mpcb )
00329 {
00330    if( mpcb == NULL ) return ;
00331    expose_CB( mpcb->drawing , mpcb , NULL ) ;
00332    return ;
00333 }
00334 
00335 
00336 
00337 
00338 
00339 static void resize_CB( Widget w , XtPointer cd , XtPointer cb )
00340 {
00341    expose_CB( w , cd , NULL ) ;
00342    return ;
00343 }
00344 
00345 
00346 
00347 
00348 
00349 static void input_CB( Widget w , XtPointer cd , XtPointer cb )
00350 {
00351    MEM_topshell_data * mpcb = (MEM_topshell_data *) cd ;
00352    XmDrawingAreaCallbackStruct * cbs = (XmDrawingAreaCallbackStruct *) cb ;
00353 
00354    if( mpcb == NULL || ! MTD_VALID(mpcb)         ) return ;  
00355    if( cbs  == NULL || cbs->reason != XmCR_INPUT ) return ;  
00356 
00357    switch( cbs->event->type ){
00358 
00359       default: break ;
00360 
00361       
00362 
00363       case KeyPress:{
00364          XKeyEvent * event = (XKeyEvent *) cbs->event ;
00365          char           buf[32] ;
00366          KeySym         ks ;
00367 
00368          buf[0] = '\0' ;
00369          XLookupString( event , buf , 32 , &ks , NULL ) ;
00370 
00371          switch( buf[0] ){
00372             default: break ;
00373 
00374             case 'Q':
00375             case 'q':
00376                donebut_CB( NULL , (XtPointer) mpcb , NULL ) ;
00377                break ;
00378          }
00379          break ;
00380       }
00381       break ;
00382    }
00383 
00384    return ;
00385 }
00386 
00387 
00388 
00389 
00390 
00391 void plotkill_topshell( MEM_topshell_data * mpcb )
00392 {
00393    if( mpcb == NULL || ! MTD_VALID(mpcb) ) return ;
00394 
00395    donebut_CB( NULL , (XtPointer) mpcb , NULL ) ;
00396    return ;
00397 }
00398 
00399 
00400 
00401 static void decode_geom( char * geom , int *ww, int *hh , int *xx, int *yy )
00402 {
00403    int has_x , has_plus ;
00404 
00405    *ww = *hh = *xx = *yy = -1 ;
00406    if( geom == NULL || geom[0] == '\0' ) return ;
00407 
00408    has_x    = strstr(geom,"x") != NULL ;
00409    has_plus = strstr(geom,"+") != NULL ;
00410 
00411    if( has_x && has_plus )
00412       sscanf(geom,"%dx%d+%d+%d",ww,hh,xx,yy) ;
00413    else if( has_x )
00414       sscanf(geom,"%dx%d",ww,hh) ;
00415    else if( has_plus )
00416       sscanf(geom,"+%d+%d",xx,yy) ;
00417 
00418    return ;
00419 }
00420 
00421 
00422 
00423 
00424 
00425 
00426 
00427 
00428 
00429 
00430 
00431 
00432 
00433 
00434 
00435 
00436 
00437 MEM_topshell_data * memplot_to_topshell( Display * dpy,
00438                                          MEM_plotdata * mp, void_func * kfun )
00439 {
00440    Widget topshell , drawing , donebut , form , psfilebut , psprintbut ;
00441    MEM_topshell_data * mpcb ;
00442    int hmin=400 , wmin , ibut=0 , hh,ww,xx,yy ;
00443    char * prc , * ept ;
00444 
00445    
00446 
00447    if( dpy == NULL || mp == NULL ) return NULL ;
00448 
00449    mpcb = (MEM_topshell_data *) malloc( sizeof(MEM_topshell_data) ) ;
00450    mpcb->valid = 0 ;
00451 
00452 #ifdef HAVE_XDBE
00453    init_XDBE(dpy) ; mpcb->have_xdbe = 0 ;
00454 #endif
00455 
00456    wmin = MEMPLOT_ASPECT(mp) * hmin ;
00457 
00458    
00459 
00460    decode_geom( getenv("AFNI_tsplotgeom") , &ww,&hh,&xx,&yy ) ;
00461    if( ww < wmin ) ww = wmin ;
00462    if( hh < hmin ) hh = hmin ;
00463 
00464    
00465 
00466    topshell = XtVaAppCreateShell(
00467                  "AFNI" , "AFNI" , topLevelShellWidgetClass , dpy ,
00468                    XmNborderWidth ,   0  ,
00469                    XmNminHeight   , hmin , XmNheight , hh ,
00470                    XmNminWidth    , wmin , XmNwidth  , ww ,
00471                    XmNallowShellResize , False ,
00472                    XmNinitialResourcesPersistent , False ,
00473                    XmNdeleteResponse   , XmDO_NOTHING ,   
00474                  NULL ) ;
00475 
00476    XmAddWMProtocolCallback(
00477         topshell , XmInternAtom(dpy,"WM_DELETE_WINDOW",False) ,
00478         donebut_CB , (XtPointer) mpcb ) ;
00479 
00480    mpcb->top = topshell ;
00481    mpcb->mp  = mp ;
00482    mpcb->dial= NULL ;
00483    mpcb->wtf = NULL ;
00484 
00485    mpcb->killfunc = kfun ;
00486 
00487    
00488 
00489 #undef TIG
00490 #undef NBUT
00491 #define TIG  20
00492 #define NBUT 3
00493 
00494    mpcb->form = form =
00495         XtVaCreateWidget( "dialog" , xmFormWidgetClass , topshell ,
00496                              XmNborderWidth , 0 ,
00497                              XmNfractionBase , TIG*NBUT - 1 ,
00498                              XmNinitialResourcesPersistent , False ,
00499                           NULL ) ;
00500 
00501    
00502 
00503    if( redcolor == NULL ){ HOTCOLOR(form,redcolor) ; }
00504 
00505    ibut = 0 ;
00506    psfilebut = XtVaCreateManagedWidget(
00507                  "dialog" , xmPushButtonWidgetClass , form ,
00508                     LABEL_ARG("PS->file") ,
00509                     XmNtopAttachment  , XmATTACH_FORM ,
00510 
00511                     XmNleftAttachment   ,
00512                         (ibut!=0) ? XmATTACH_POSITION : XmATTACH_FORM ,
00513                     XmNleftPosition , ibut*TIG ,
00514 
00515                     XmNrightAttachment  ,
00516                      (ibut==NBUT-1) ? XmATTACH_FORM : XmATTACH_POSITION ,
00517                     XmNrightPosition , ibut*TIG + (TIG-1) ,
00518 
00519                     XmNrecomputeSize , False ,
00520                     XmNtraversalOn   , False ,
00521                     XmNinitialResourcesPersistent , False ,
00522                  NULL ) ;
00523    XtAddCallback( psfilebut , XmNactivateCallback , psfile_CB , (XtPointer) mpcb ) ;
00524 
00525    ibut++ ;
00526    psprintbut = XtVaCreateManagedWidget(
00527                  "dialog" , xmPushButtonWidgetClass , form ,
00528                     LABEL_ARG("->printer") ,
00529                     XmNtopAttachment  , XmATTACH_FORM ,
00530 
00531                     XmNleftAttachment   ,
00532                         (ibut!=0) ? XmATTACH_POSITION : XmATTACH_FORM ,
00533                     XmNleftPosition , ibut*TIG ,
00534 
00535                     XmNrightAttachment  ,
00536                      (ibut==NBUT-1) ? XmATTACH_FORM : XmATTACH_POSITION ,
00537                     XmNrightPosition , ibut*TIG + (TIG-1) ,
00538 
00539                     XmNrecomputeSize , False ,
00540                     XmNtraversalOn   , False ,
00541                     XmNinitialResourcesPersistent , False ,
00542                  NULL ) ;
00543    prc = getenv( "AFNI_PSPRINT" ) ;
00544    if( prc != NULL ){
00545       sprintf( print_command , "|%.250s" , prc ) ;
00546       XtAddCallback( psprintbut , XmNactivateCallback , psprint_CB , (XtPointer) mpcb ) ;
00547    } else {
00548 #if 0
00549       XtAddCallback( psprintbut , XmNactivateCallback , beep_CB ,
00550                      (XtPointer) "*** AFNI_PSPRINT not defined - see README.environment" ) ;
00551 #else
00552       XtSetSensitive( psprintbut , False ) ;  
00553 #endif
00554    }
00555 
00556    ibut++ ;
00557    donebut = XtVaCreateManagedWidget(
00558                  "dialog" , xmPushButtonWidgetClass , form ,
00559                     LABEL_ARG("Done") ,
00560 #if 1
00561                     BGCOLOR_ARG(redcolor) ,
00562 #endif
00563 
00564                     XmNtopAttachment  , XmATTACH_FORM ,
00565 
00566                     XmNleftAttachment   ,
00567                         (ibut!=0) ? XmATTACH_POSITION : XmATTACH_FORM ,
00568                     XmNleftPosition , ibut*TIG ,
00569 
00570                     XmNrightAttachment  ,
00571                      (ibut==NBUT-1) ? XmATTACH_FORM : XmATTACH_POSITION ,
00572                     XmNrightPosition , ibut*TIG + (TIG-1) ,
00573 
00574                     XmNrecomputeSize , False ,
00575                     XmNtraversalOn   , False ,
00576                     XmNinitialResourcesPersistent , False ,
00577                  NULL ) ;
00578    XtAddCallback( donebut , XmNactivateCallback , donebut_CB , (XtPointer) mpcb ) ;
00579 
00580    
00581 
00582    drawing = XtVaCreateManagedWidget( "dialog" , xmDrawingAreaWidgetClass , form ,
00583                                           XmNtopAttachment    , XmATTACH_WIDGET ,
00584                                           XmNtopWidget        , donebut ,
00585                                           XmNleftAttachment   , XmATTACH_FORM ,
00586                                           XmNrightAttachment  , XmATTACH_FORM ,
00587                                           XmNbottomAttachment , XmATTACH_FORM ,
00588                                           XmNinitialResourcesPersistent , False ,
00589                                         NULL ) ;
00590 
00591    XtAddCallback( drawing , XmNexposeCallback , expose_CB , (XtPointer) mpcb ) ;
00592    XtAddCallback( drawing , XmNresizeCallback , resize_CB , (XtPointer) mpcb ) ;
00593    XtAddCallback( drawing , XmNinputCallback  , input_CB  , (XtPointer) mpcb ) ;
00594 
00595    
00596 
00597    XtVaSetValues( form , BGCOLOR_ARG("white") , NULL ) ;
00598 
00599    if( xx >= 0 && yy >= 0 )
00600       XtVaSetValues( topshell , XmNx,xx , XmNy,yy , NULL ) ;
00601 
00602    XtManageChild(form) ;
00603    XtRealizeWidget(topshell);
00604 
00605    mpcb->valid = 1 ; mpcb->userdata = NULL ; mpcb->drawing = drawing ;
00606    return mpcb ;
00607 }