00001 
00002 
00003 
00004 
00005 
00006    
00007 #include "afni.h"
00008 
00009 #ifndef ALLOW_PLUGINS
00010 #  error "Plugins not properly set up -- see machdep.h"
00011 #endif
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 char * NOTES_main( PLUGIN_interface * ) ;
00022 
00023 static void NOTES_make_widgets(void) ;
00024 
00025 static void NOTES_done_CB   ( Widget , XtPointer , XtPointer ) ;
00026 static void NOTES_help_CB   ( Widget , XtPointer , XtPointer ) ;
00027 static void NOTES_quit_CB   ( Widget , XtPointer , XtPointer ) ;
00028 static void NOTES_save_CB   ( Widget , XtPointer , XtPointer ) ;
00029 static void NOTES_choose_CB ( Widget , XtPointer , XtPointer ) ;
00030 static void NOTES_add_CB    ( Widget , XtPointer , XtPointer ) ;
00031 static void NOTES_delete_CB ( Widget , XtPointer , XtPointer ) ;
00032 static void NOTES_restore_CB( Widget , XtPointer , XtPointer ) ;
00033 static void NOTES_refit_CB  ( Widget , XtPointer , XtPointer ) ;
00034 
00035 static void NOTES_finalize_dset_CB( Widget , XtPointer , MCW_choose_cbs * ) ;
00036 
00037 static PLUGIN_interface * plint = NULL ;
00038 
00039 #define TWIDTH 75
00040 #define newstring(str) strcpy(malloc(strlen(str)+1),str)
00041 static int line_count( char * ) ;
00042 
00043 #define THEIGHT 9
00044 static int max_tlines = 0 ;
00045 
00046 
00047 
00048 
00049 
00050 
00051 
00052 
00053 
00054 DEFINE_PLUGIN_PROTOTYPE
00055 
00056 PLUGIN_interface * PLUGIN_init( int ncall )
00057 {
00058 
00059    if( ncall > 0 ) return NULL ;  
00060 
00061    plint = PLUTO_new_interface( "Dataset NOTES" , NULL , NULL ,
00062                                 PLUGIN_CALL_IMMEDIATELY , NOTES_main ) ;
00063 
00064    PLUTO_add_hint( plint , "Edit/View Notes attached to dataset" ) ;
00065 
00066    PLUTO_set_sequence( plint , "A:olddset:notes" ) ;
00067 
00068    return plint ;
00069 }
00070 
00071 
00072 
00073 
00074 
00075 
00076 
00077 typedef struct {
00078    Widget frame, vert_rc , horz_rc , note_label ,
00079           delete_pb , restore_pb , scrollw , textw ;
00080 
00081    char * note_orig , * date_orig ;
00082 } NOTE_wind ;
00083 
00084 static NOTE_wind * NOTES_make_note(void) ;
00085 
00086 static Widget shell=NULL , topman , info_lab , choose_pb ;
00087 static Widget done_pb , help_pb , quit_pb , save_pb , add_pb ;
00088 static Widget notesw , noterc , refit_pb ;
00089 
00090 static int text_width = 0 ;
00091 static int text_height = 0 ;
00092 
00093 static NOTE_wind ** notar = NULL ;
00094 static int          notar_num = 0 ;
00095 static int          num_notes = 0 ;
00096 
00097 static MCW_DC * dc ;                 
00098 static Three_D_View * im3d ;         
00099 static THD_3dim_dataset * dset ;     
00100 static MCW_idcode         dset_idc ; 
00101 
00102 static int editor_open  = 0 ;
00103 
00104 #define NUM_DH 10
00105 static char * default_history[NUM_DH] = {
00106 
00107    "The mind is its own place, and in itself\n"
00108    "Can make a Heaven of Hell, a Hell of Heaven.\n"
00109    "-- John Milton (Paradise Lost)\n" ,
00110 
00111    "Those who cannot remember the past are condemned to repeat it.\n"
00112    "-- George Santayana" ,
00113 
00114    "Chanter of Personality, outlining what is yet to be,\n"
00115    "I project the history of the future.\n"
00116    "-- Walt Whitman" ,
00117 
00118    "I shall cheerfully bear the reproach of having descended below the\n"
00119    "dignity of history.\n"
00120    "-- Thomas Macaulay" ,
00121 
00122    "There was a time - we see it in the marvellous dawn of Hellenic life -\n"
00123    "when history was distinguished neither from poetry, from mythology,\n"
00124    "nor from the first dim beginnings of science.\n"
00125    "-- Theodore Roosevelt" ,
00126 
00127    "You cannot escape the responsibility of tomorrow by evading it today.\n"
00128    "-- Abraham Lincoln" ,
00129 
00130    "Once you get into this great stream of history, you can't get out.\n"
00131    "-- Richard Nixon" ,
00132 
00133    "History is the version of past events that people have decided to\n"
00134    "agree upon.\n"
00135    "--Napoleon" ,
00136 
00137    "Ever returning Spring, trinity sure to me you bring:\n"
00138    "Lilac blooming perennial, and drooping star in the West,\n"
00139    "And thought of him I love.\n"
00140    "-- Walt Whitman" ,
00141 
00142    "What has occurred in this case, must ever recur in similar cases.\n"
00143    "Human nature will not change. In any future great national trial,\n"
00144    "compared with the men of this, we shall have as weak, and as strong;\n"
00145    "as silly and as wise; as bad and good. Let us, therefore, study the\n"
00146    "incidents of this, as philosophy to learn wisdom from, and none of\n"
00147    "them as wrongs to be revenged.\n"
00148    "-- Abraham Lincoln"
00149 
00150 } ;
00151 
00152 static char * empty_note = "-- Empty Note Text --" ;
00153 static char * no_date    = "no date" ;
00154 
00155 static void scroll_topbot( Widget , int ) ;
00156 
00157 char * NOTES_main( PLUGIN_interface * plint )
00158 {
00159    XmString xstr ;
00160    int ii ;
00161 
00162    
00163 
00164    if( ! IM3D_OPEN(plint->im3d) ) return "AFNI Controller\nnot opened?!" ;
00165 
00166    if( editor_open ){
00167       XtMapWidget(shell) ;
00168       XRaiseWindow( XtDisplay(shell) , XtWindow(shell) ) ;
00169       return NULL ;
00170    }
00171 
00172    im3d = plint->im3d ;  
00173 
00174    
00175 
00176    if( shell == NULL ){
00177       dc = im3d->dc ;        
00178       NOTES_make_widgets() ;
00179       PLUTO_set_topshell( plint , shell ) ;  
00180       RWC_visibilize_widget( shell ) ;       
00181    }
00182 
00183    
00184 
00185    XtUnmanageChild( notesw ) ;
00186    XtUnmanageChild( noterc ) ;
00187    for( ii=0 ; ii < notar_num ; ii++ )
00188       XtUnmanageChild( notar[ii]->frame ) ;
00189 
00190    
00191 
00192    { char ttl[32] ;
00193      sprintf( ttl , "AFNI Notes %s" , AFNI_controller_label(im3d) ) ;
00194      XtVaSetValues( shell , XmNtitle , ttl , NULL ) ;
00195    }
00196 
00197    
00198 
00199    xstr = XmStringCreateLtoR( "[No dataset]" ,
00200                               XmFONTLIST_DEFAULT_TAG ) ;
00201    XtVaSetValues( info_lab , XmNlabelString , xstr , NULL ) ;
00202    XmStringFree(xstr) ;
00203 
00204    
00205 
00206    XtMapWidget(shell) ;
00207    PLUTO_cursorize(shell) ;
00208 
00209    
00210 
00211    dset         = NULL ;   
00212    editor_open  = 1 ;      
00213    num_notes    = 0 ;      
00214 
00215    return NULL ;
00216 }
00217 
00218 
00219 
00220 
00221 
00222 
00223 
00224 #define NACT 6  
00225 
00226 static MCW_action_item NOTES_actor[NACT] = {
00227  {"Quit",NOTES_quit_CB,NULL,
00228   "Discard edits since last\nSave and close Editor" ,
00229    "Discard edits and close",0} ,
00230 
00231  {"Help",NOTES_help_CB,NULL,
00232   "Displays more help" , "Displays more help",0} ,
00233 
00234  {"Add",NOTES_add_CB,NULL,
00235   "Add a new Note to the\nlist (at the end)", "Add a new Note" , 0 } ,
00236 
00237  {"Refit",NOTES_refit_CB,NULL,
00238   "Resize the Notes' sub-windows\nto fit the Notes' texts." ,
00239   "Resize Notes sub-windows" , 0 } ,
00240 
00241  {"Save",NOTES_save_CB,NULL,
00242   "Save edits to disk\nand continue" , "Save to disk; continue",0} ,
00243 
00244  {"Done",NOTES_done_CB,NULL,
00245   "Save edits to disk\nand close Editor" , "Save and Quit",1}
00246 } ;
00247 
00248 static void NOTES_make_widgets(void)
00249 {
00250    XmString xstr ;
00251    Widget twid , tsep ;
00252 
00253    
00254 
00255    if( max_tlines < 1 ){
00256       char * cc = my_getenv("AFNI_NOTES_DLINES") ;
00257       if( cc != NULL ) max_tlines = strtol( cc , NULL , 10 ) ;
00258 
00259            if( max_tlines <  1 ) max_tlines = THEIGHT ;
00260       else if( max_tlines > 99 ) max_tlines = 99 ;     
00261    }
00262 
00263    
00264 
00265    shell =
00266       XtVaAppCreateShell(
00267            "AFNI" , "AFNI" , topLevelShellWidgetClass , dc->display ,
00268 
00269            XmNtitle             , "Notes Editor" , 
00270            XmNiconName          , "Notes"        , 
00271            XmNdeleteResponse    , XmDO_NOTHING   , 
00272            XmNallowShellResize  , True ,           
00273            XmNmappedWhenManaged , False ,          
00274       NULL ) ;
00275 
00276    DC_yokify( shell , dc ) ;
00277 
00278    if( afni48_good )             
00279       XtVaSetValues( shell ,
00280                         XmNiconPixmap , afni48_pixmap ,
00281                      NULL ) ;
00282 
00283    XmAddWMProtocolCallback(      
00284            shell ,
00285            XmInternAtom( dc->display , "WM_DELETE_WINDOW" , False ) ,
00286            NOTES_quit_CB , (XtPointer) plint ) ;
00287 
00288    
00289 
00290    topman = XtVaCreateWidget(
00291                 "AFNI" , xmFormWidgetClass , shell ,
00292                   XmNborderWidth , 0 ,
00293                   XmNborderColor , 0 ,
00294                   XmNtraversalOn , False ,
00295                 NULL ) ;
00296 
00297    
00298 
00299    twid = XtVaCreateWidget(
00300              "AFNI" , xmRowColumnWidgetClass , topman ,
00301                 XmNpacking     , XmPACK_TIGHT ,
00302                 XmNorientation , XmHORIZONTAL ,
00303                 XmNtraversalOn , False ,
00304                 XmNleftAttachment , XmATTACH_FORM ,
00305                 XmNrightAttachment, XmATTACH_FORM ,
00306                 XmNtopAttachment  , XmATTACH_FORM ,
00307                 XmNtopOffset      , 1 ,
00308              NULL ) ;
00309 
00310    
00311 
00312    xstr = XmStringCreateLtoR( "Choose Dataset" , XmFONTLIST_DEFAULT_TAG ) ;
00313    choose_pb = XtVaCreateManagedWidget(
00314                   "AFNI" , xmPushButtonWidgetClass , twid ,
00315                      XmNlabelString , xstr ,
00316                      XmNtraversalOn , False ,
00317                   NULL ) ;
00318    XmStringFree(xstr) ;
00319    XtAddCallback( choose_pb, XmNactivateCallback, NOTES_choose_CB, NULL ) ;
00320    MCW_register_help( choose_pb ,
00321                       "Use this to popup a\n"
00322                       "'chooser' that lets\n"
00323                       "you select which\n"
00324                       "dataset to edit."
00325                     ) ;
00326    MCW_register_hint( choose_pb , "Popup a dataset chooser" ) ;
00327 
00328    
00329 
00330    xstr = XmStringCreateLtoR( "[No dataset]" , XmFONTLIST_DEFAULT_TAG ) ;
00331    info_lab = XtVaCreateManagedWidget(
00332                  "AFNI" , xmLabelWidgetClass , twid ,
00333                     XmNlabelString , xstr ,
00334                  NULL ) ;
00335    XmStringFree(xstr) ;
00336    MCW_register_help( info_lab , "Shows dataset being edited" ) ;
00337    MCW_register_hint( info_lab , "Dataset being edited" ) ;
00338 
00339    XtManageChild(twid) ;  
00340 
00341    
00342 
00343    tsep   = XtVaCreateManagedWidget(
00344              "AFNI" , xmSeparatorWidgetClass , topman ,
00345                 XmNseparatorType , XmSINGLE_LINE ,
00346                 XmNleftAttachment  , XmATTACH_FORM ,
00347                 XmNrightAttachment , XmATTACH_FORM ,
00348                 XmNtopAttachment   , XmATTACH_WIDGET ,
00349                 XmNtopWidget       , info_lab ,
00350                 XmNtopOffset       , 1 ,
00351              NULL ) ;
00352 
00353    
00354 
00355    twid = MCW_action_area( topman , NOTES_actor , NACT ) ;
00356 
00357    XtVaSetValues( twid ,
00358                      XmNleftAttachment , XmATTACH_FORM ,
00359                      XmNrightAttachment, XmATTACH_FORM ,
00360                      XmNtopAttachment  , XmATTACH_WIDGET ,
00361                      XmNtopWidget      , tsep   ,
00362                      XmNtopOffset      , 1 ,
00363                   NULL ) ;
00364 
00365    quit_pb  = (Widget) NOTES_actor[0].data ;
00366    help_pb  = (Widget) NOTES_actor[1].data ;
00367    add_pb   = (Widget) NOTES_actor[2].data ;
00368    refit_pb = (Widget) NOTES_actor[3].data ;
00369    save_pb  = (Widget) NOTES_actor[4].data ;
00370    done_pb  = (Widget) NOTES_actor[5].data ;
00371 
00372    
00373 
00374    tsep   = XtVaCreateManagedWidget(
00375               "AFNI" , xmSeparatorWidgetClass , topman ,
00376                  XmNseparatorType , XmSINGLE_LINE ,
00377                  XmNleftAttachment  , XmATTACH_FORM ,
00378                  XmNrightAttachment , XmATTACH_FORM ,
00379                  XmNtopAttachment   , XmATTACH_WIDGET ,
00380                  XmNtopWidget       , twid ,
00381                  XmNtopOffset       , 1 ,
00382               NULL ) ;
00383 
00384    
00385 
00386    notesw = XtVaCreateWidget(
00387                     "AFNI" , xmScrolledWindowWidgetClass , topman ,
00388                        XmNscrollingPolicy        , XmAUTOMATIC ,
00389                        XmNvisualPolicy           , XmCONSTANT ,
00390                        XmNshadowThickness        , 0 ,
00391                        XmNscrollBarDisplayPolicy , XmAS_NEEDED ,
00392                        XmNscrollBarPlacement     , XmTOP_LEFT ,
00393                        XmNleftAttachment  , XmATTACH_FORM ,
00394                        XmNrightAttachment , XmATTACH_FORM ,
00395                        XmNbottomAttachment, XmATTACH_FORM ,
00396                        XmNtopAttachment   , XmATTACH_WIDGET ,
00397                        XmNtopWidget       , tsep   ,
00398                        XmNtopOffset       , 1 ,
00399                     NULL ) ;
00400 
00401    noterc = XtVaCreateWidget(
00402              "AFNI" , xmRowColumnWidgetClass , notesw ,
00403                 XmNpacking     , XmPACK_TIGHT ,
00404                 XmNorientation , XmVERTICAL ,
00405                 XmNmarginHeight, 0 ,
00406                 XmNmarginWidth , 0 ,
00407                 XmNtraversalOn , False ,
00408              NULL ) ;
00409 
00410    
00411 
00412 
00413    notar     = (NOTE_wind **) malloc( sizeof(NOTE_wind *) ) ;
00414    notar[0]  = NOTES_make_note() ;
00415    notar_num = 1 ;
00416 
00417    XtUnmanageChild( notar[0]->delete_pb  ) ;  
00418    XtUnmanageChild( notar[0]->restore_pb ) ;  
00419    XtVaSetValues( notar[0]->textw ,
00420                     XmNautoShowCursorPosition , False ,
00421                     XmNeditable               , False ,
00422                     XmNcursorPositionVisible  , False ,
00423                   NULL ) ;
00424    xstr = XmStringCreateLtoR( "----- History -----" , XmFONTLIST_DEFAULT_TAG ) ;
00425    XtVaSetValues( notar[0]->note_label , XmNlabelString , xstr , NULL ) ;
00426    MCW_register_hint( notar[0]->textw , "Dataset History; or Edifying Text" ) ;
00427 
00428    
00429 
00430    { char cbuf[TWIDTH+8] ; int ii ;
00431      XmFontList xflist ;
00432 
00433      for( ii=0; ii < TWIDTH+3; ii++ ) cbuf[ii] = 'x' ; cbuf[ii] = '\0' ;
00434      xstr = XmStringCreateLtoR( cbuf , XmFONTLIST_DEFAULT_TAG ) ;
00435      XtVaGetValues( notar[0]->textw , XmNfontList , &xflist , NULL ) ;
00436      text_width  = XmStringWidth ( xflist , xstr ) + 14 ;
00437      text_height = XmStringHeight( xflist , xstr ) ;
00438      XmStringFree( xstr ) ;
00439      ii = WidthOfScreen(XtScreen(shell)) - 128 ;
00440      if( text_width > ii ) text_width = ii ;
00441    }
00442 
00443    
00444 
00445    XtManageChild(topman) ;
00446    XtRealizeWidget(shell) ;  
00447 
00448    return ;
00449 }
00450 
00451 
00452 
00453 
00454 
00455 static NOTE_wind * NOTES_make_note( void )
00456 {
00457    NOTE_wind * nw ;
00458    XmString xstr ;
00459 
00460    nw = (NOTE_wind *) calloc( 1 , sizeof(NOTE_wind) ) ;
00461 
00462    nw->frame = XtVaCreateWidget(
00463                   "AFNI" , xmFrameWidgetClass , noterc ,
00464                   XmNshadowType , XmSHADOW_IN ,
00465                   XmNshadowThickness , 1 ,
00466                   XmNtraversalOn , False ,
00467                NULL ) ;
00468 
00469    nw->vert_rc = XtVaCreateWidget(
00470                     "AFNI" , xmRowColumnWidgetClass , nw->frame ,
00471                        XmNpacking     , XmPACK_TIGHT ,
00472                        XmNorientation , XmVERTICAL ,
00473                        XmNtraversalOn , False ,
00474                        XmNmarginHeight, 0 ,
00475                        XmNmarginWidth , 0 ,
00476                     NULL ) ;
00477 
00478    nw->horz_rc = XtVaCreateWidget(
00479                     "AFNI" , xmRowColumnWidgetClass , nw->vert_rc ,
00480                        XmNpacking     , XmPACK_TIGHT ,
00481                        XmNorientation , XmHORIZONTAL ,
00482                        XmNtraversalOn , False ,
00483                        XmNmarginHeight, 0 ,
00484                        XmNmarginWidth , 0 ,
00485                     NULL ) ;
00486 
00487    nw->note_label = XtVaCreateManagedWidget(
00488                        "AFNI" , xmLabelWidgetClass , nw->horz_rc ,
00489                        XmNmarginHeight, 0 ,
00490                        XmNmarginWidth , 0 ,
00491                        NULL ) ;
00492 
00493    xstr = XmStringCreateLtoR( "Delete" , XmFONTLIST_DEFAULT_TAG ) ;
00494    nw->delete_pb = XtVaCreateManagedWidget(
00495                       "AFNI" , xmPushButtonWidgetClass , nw->horz_rc ,
00496                          XmNlabelString , xstr ,
00497                          XmNtraversalOn , False ,
00498                          XmNmarginHeight, 0 ,
00499                          XmNmarginWidth , 0 ,
00500                       NULL ) ;
00501    XmStringFree(xstr) ;
00502    XtAddCallback( nw->delete_pb, XmNactivateCallback, NOTES_delete_CB, NULL ) ;
00503    MCW_register_help( nw->delete_pb ,
00504                       "Use this button to delete\n"
00505                       "this Note from the dataset."
00506                     ) ;
00507    MCW_register_hint( nw->delete_pb , "Delete this Note" ) ;
00508 
00509    xstr = XmStringCreateLtoR( "Restore" , XmFONTLIST_DEFAULT_TAG ) ;
00510    nw->restore_pb = XtVaCreateManagedWidget(
00511                       "AFNI" , xmPushButtonWidgetClass , nw->horz_rc ,
00512                          XmNlabelString , xstr ,
00513                          XmNtraversalOn , False ,
00514                          XmNmarginHeight, 0 ,
00515                          XmNmarginWidth , 0 ,
00516                       NULL ) ;
00517    XmStringFree(xstr) ;
00518    XtAddCallback( nw->restore_pb, XmNactivateCallback, NOTES_restore_CB, NULL ) ;
00519    MCW_register_help( nw->restore_pb ,
00520                       "Use this button to restore\n"
00521                       "this Note to its original\n"
00522                       "value (i.e., as it currently\n"
00523                       "stored on in the HEAD file)."
00524                     ) ;
00525    MCW_register_hint( nw->restore_pb , "Restore Note from disk" ) ;
00526 
00527    XtManageChild(nw->horz_rc) ;
00528 
00529    (void) XtVaCreateManagedWidget(
00530              "AFNI" , xmSeparatorWidgetClass , nw->vert_rc ,
00531                 XmNseparatorType , XmSINGLE_LINE ,
00532              NULL ) ;
00533 
00534    nw->scrollw = XtVaCreateManagedWidget(
00535                     "AFNI" , xmScrolledWindowWidgetClass , nw->vert_rc ,
00536                        XmNscrollingPolicy        , XmAPPLICATION_DEFINED ,
00537                        XmNvisualPolicy           , XmVARIABLE ,
00538                        XmNshadowThickness        , 0 ,
00539                     NULL ) ;
00540 
00541    nw->textw = XtVaCreateManagedWidget(
00542                     "AFNI" , xmTextWidgetClass , nw->scrollw ,
00543                        XmNeditMode               , XmMULTI_LINE_EDIT ,
00544                        XmNautoShowCursorPosition , True ,
00545                        XmNeditable               , True ,
00546                        XmNcursorPositionVisible  , True ,
00547                        XmNcolumns                , TWIDTH ,
00548                        XmNrows                   , 1    ,
00549                        XmNwordWrap               , True ,
00550                     NULL ) ;
00551 
00552    XtManageChild(nw->vert_rc) ;  
00553 
00554    nw->note_orig = nw->date_orig = NULL ;
00555    return nw ;
00556 }
00557 
00558 
00559 
00560 static int line_count( char * msg )
00561 {
00562    char * cpt ; int nlin ;
00563    if( msg == NULL ) return 0 ;
00564    for( nlin=1,cpt=msg ; *cpt != '\0' ; cpt++ ) if( *cpt == '\n' ) nlin++ ;
00565    return nlin ;
00566 }
00567 
00568 
00569 
00570 
00571 
00572 static void NOTES_done_CB( Widget w, XtPointer client_data, XtPointer call_data )
00573 {
00574    if( dset != NULL && num_notes > 0 ) NOTES_save_CB(NULL,NULL,NULL) ;
00575    NOTES_quit_CB(NULL,NULL,NULL) ;
00576    return ;
00577 }
00578 
00579 
00580 
00581 
00582 
00583 static void NOTES_quit_CB( Widget w, XtPointer client_data, XtPointer call_data )
00584 {
00585    int ii ;
00586 
00587    XtUnmapWidget( shell ) ; editor_open = 0 ; dset = NULL ;
00588 
00589    XtUnmanageChild( notesw ) ;
00590    XtUnmanageChild( noterc ) ;
00591    for( ii=0 ; ii < notar_num ; ii++ ){
00592       XtUnmanageChild( notar[ii]->frame ) ;
00593 
00594       if( notar[ii]->note_orig != NULL ){
00595           free(notar[ii]->note_orig) ; notar[ii]->note_orig = NULL ;
00596       }
00597 
00598       if( notar[ii]->date_orig != NULL ){
00599           free(notar[ii]->date_orig) ; notar[ii]->date_orig = NULL ;
00600       }
00601 
00602       XmTextSetString( notar[ii]->textw , "\0" ) ;  
00603    }
00604 
00605    return ;
00606 }
00607 
00608 
00609 
00610 
00611 
00612 static void NOTES_save_CB( Widget w, XtPointer client_data, XtPointer call_data )
00613 {
00614    int ii , nnew ;
00615    char * nstr , str[256] ;
00616    XmString xstr ;
00617 
00618    if( dset == NULL || num_notes == 0 ){ XBell(dc->display,100); return; }
00619 
00620    MCW_invert_widget(save_pb) ;
00621 
00622    
00623 
00624    for( nnew=0,ii=1 ; ii <= num_notes ; ii++ ){
00625       nstr = XmTextGetString( notar[ii]->textw ) ;  
00626       if( strcmp(nstr,notar[ii]->note_orig) != 0 ){ 
00627 
00628          tross_Store_Note( dset , ii , nstr ) ; nnew++ ;  
00629          free( notar[ii]->note_orig ) ;                   
00630          notar[ii]->note_orig = newstring(nstr) ;
00631          free( notar[ii]->date_orig ) ;                   
00632          notar[ii]->date_orig = tross_Get_Notedate( dset , ii ) ;
00633 
00634          sprintf(str,"----- NOTE %d [%s] -----",ii,notar[ii]->date_orig) ;
00635          xstr = XmStringCreateLtoR( str , XmFONTLIST_DEFAULT_TAG ) ;
00636          XtVaSetValues( notar[ii]->note_label , XmNlabelString , xstr , NULL ) ;
00637          XmStringFree(xstr) ;
00638       }
00639       XtFree(nstr) ;
00640    }
00641 
00642    
00643 
00644    if( nnew > 0 )
00645       DSET_write_header(dset) ;
00646    else if( w != NULL )
00647       (void) MCW_popup_message( save_pb ,
00648                                 " \n Nothing has changed! \n " ,
00649                                 MCW_USER_KILL | MCW_TIMER_KILL ) ;
00650 
00651    MCW_invert_widget(save_pb) ;
00652    return ;
00653 }
00654 
00655 
00656 
00657 
00658 
00659 static void NOTES_help_CB( Widget w, XtPointer client_data, XtPointer call_data )
00660 {
00661    (void ) new_MCW_textwin( choose_pb ,
00662 
00663    " \n"
00664    "This plugin is used to view and edit the Notes attached to a dataset.\n"
00665    "---------------------------------------------------------------------\n"
00666    "The buttons at the top perform the following functions:\n"
00667    "\n"
00668    "  Choose Dataset: Use this to select a dataset to deal with.\n"
00669    "\n"
00670    "  Quit:           Exit the plugin without saving any edits to Notes\n"
00671    "                  made since the last 'Save' button press.\n"
00672    "\n"
00673    "  Help:           I hope you already got the idea for this widget.\n"
00674    "\n"
00675    "  Add:            Add a new Note at the end of the existing notes.\n"
00676    "\n"
00677    "  Refit:          Resize all Notes' sub-windows to fit the number of\n"
00678    "                  lines of text in each Note.  The maximum line count\n"
00679    "                  for each sub-window is set by the Unix environment\n"
00680    "                  variable AFNI_NOTES_DLINES; if this is not defined,\n"
00681    "                  the default maximum is 9.\n"
00682    "\n"
00683    "  Save:           Save the current Notes to the dataset .HEAD file.\n"
00684    "\n"
00685    "  Done:           Save then Quit.\n"
00686    "-------------------------------------------------------------------------- \n"
00687    "Below these buttons are the Notes sub-windows.\n"
00688    "\n"
00689    "The first Note sub-window shows the dataset History Note.  This Note can't\n"
00690    "be edited by the user - it is created by each AFNI program as a record of\n"
00691    "the actions that led to this dataset. If no History Note is present in the\n"
00692    "dataset .HEAD file, some edifying text will be shown here instead.\n"
00693    "\n"
00694    "Each other Note sub-window shows the Note number, the date of the Note's\n"
00695    "creation (or last change), and the Note itself.  These windows are\n"
00696    "editable.  If you want to remove a Note from the dataset, use the\n"
00697    "Delete button for that Note.  (This operation is NOT reversible - using\n"
00698    "the Quit button will not get a deleted Note back!)  If you edit a note\n"
00699    "badly and want to restore it to the value saved in the dataset header,\n"
00700    "use the Restore button.\n"
00701    "\n"
00702    "Notes can also be viewed with the program 3dinfo, and with the Info\n"
00703    "buttons from the Datamode/Misc menu.  The command line program 3dNotes\n"
00704    "lets you create dataset Notes in a batch script file.\n"
00705    "\n"
00706    "--- Bob Cox - September 1999\n"
00707    "    (Based on ideas and some code from Tom Ross of MCW)\n"
00708 
00709     , TEXT_READONLY ) ;
00710 
00711    return ;
00712 }
00713 
00714 
00715 
00716 
00717 
00718 
00719 
00720 static int                  ndsl = 0 ;
00721 static PLUGIN_dataset_link * dsl = NULL ;
00722 
00723 static void NOTES_choose_CB( Widget w, XtPointer client_data, XtPointer call_data )
00724 {
00725    THD_session * ss  = im3d->ss_now ;           
00726    int           vv  = im3d->vinfo->view_type ; 
00727    THD_3dim_dataset * qset ;
00728    int id , ltop , llen ;
00729    char qnam[THD_MAX_NAME] , label[THD_MAX_NAME] ;
00730    static char ** strlist = NULL ;
00731 
00732    
00733 
00734    ndsl = 0 ;
00735 
00736    
00737 
00738    for( id=0 ; id < ss->num_dsset ; id++ ){
00739       qset = ss->dsset[id][vv] ;
00740 
00741       if( ! ISVALID_DSET (qset) ) continue ;  
00742 
00743       ndsl++ ;
00744       dsl = (PLUGIN_dataset_link *)
00745               XtRealloc( (char *) dsl , sizeof(PLUGIN_dataset_link)*ndsl ) ;
00746 
00747       make_PLUGIN_dataset_link( qset , dsl + (ndsl-1) ) ;
00748    }
00749 
00750    
00751 
00752    if( ndsl < 1 ){
00753       (void) MCW_popup_message( choose_pb ,
00754                                    "Didn't find any\ndatasets to edit!" ,
00755                                 MCW_USER_KILL | MCW_TIMER_KILL ) ;
00756       XBell( dc->display , 100 ) ;
00757       return ;
00758    }
00759 
00760    
00761 
00762 
00763    ltop = 4 ;
00764    for( id=0 ; id < ndsl ; id++ ){
00765       llen = strlen(dsl[id].title) ;
00766       ltop = MAX(ltop,llen) ;
00767    }
00768 
00769    for( id=0 ; id < ndsl ; id++ ){
00770       qset = PLUTO_find_dset( &(dsl[id].idcode) ) ;
00771       if( ! ISVALID_DSET(qset) ) continue ;
00772       if( ISANAT(qset) ){
00773          if( ISANATBUCKET(qset) )         
00774             sprintf(qnam,"%-*s [%s:%d]" ,
00775                     ltop,dsl[id].title ,
00776                     ANAT_prefixstr[qset->func_type] , DSET_NVALS(qset) ) ;
00777 
00778          else if( DSET_NUM_TIMES(qset) == 1 )
00779             sprintf(qnam,"%-*s [%s]" ,
00780                     ltop,dsl[id].title ,
00781                     ANAT_prefixstr[qset->func_type] ) ;
00782 
00783          else
00784             sprintf(qnam,"%-*s [%s:3D+t:%d]" ,
00785                     ltop,dsl[id].title ,
00786                     ANAT_prefixstr[qset->func_type] , DSET_NUM_TIMES(qset) ) ;
00787 
00788       } else {
00789          if( ISFUNCBUCKET(qset) )         
00790             sprintf(qnam,"%-*s [%s:%d]" ,
00791                     ltop,dsl[id].title ,
00792                     FUNC_prefixstr[qset->func_type] , DSET_NVALS(qset) ) ;
00793 
00794          else if( DSET_NUM_TIMES(qset) == 1 )
00795             sprintf(qnam,"%-*s [%s]" ,
00796                     ltop,dsl[id].title ,
00797                     FUNC_prefixstr[qset->func_type] ) ;
00798 
00799          else
00800             sprintf(qnam,"%-*s [%s:3D+t:%d]" ,
00801                     ltop,dsl[id].title ,
00802                     FUNC_prefixstr[qset->func_type] , DSET_NVALS(qset) ) ;
00803       }
00804 
00805       if( DSET_COMPRESSED(qset) ) strcat(qnam,"z") ;
00806 
00807       strcpy( dsl[id].title , qnam ) ;
00808    }
00809 
00810    
00811 
00812    POPDOWN_strlist_chooser ;
00813 
00814    strlist = (char **) XtRealloc( (char *)strlist , sizeof(char *)*ndsl ) ;
00815    for( id=0 ; id < ndsl ; id++ ) strlist[id] = dsl[id].title ;
00816 
00817    sprintf( label , "AFNI Dataset from\nthe %s" , VIEW_typestr[vv] ) ;
00818 
00819    MCW_choose_strlist( w , label , ndsl , -1 , strlist ,
00820                        NOTES_finalize_dset_CB , NULL     ) ;
00821 
00822    return ;
00823 }
00824 
00825 
00826 
00827 static void NOTES_finalize_dset_CB( Widget w, XtPointer fd, MCW_choose_cbs * cbs )
00828 {
00829    int id = cbs->ival ;
00830    THD_3dim_dataset * qset ;
00831    XmString xstr ;
00832    char str[256] , * his ;
00833    int ii , nl , nltot , ww,hh,qh ;
00834 
00835    
00836 
00837    if( ! editor_open ){ POPDOWN_strlist_chooser; XBell(dc->display,100); return; }
00838 
00839    if( id < 0 || id >= ndsl ){ XBell(dc->display,100) ; return ; }
00840 
00841    qset = PLUTO_find_dset( &(dsl[id].idcode) ) ;  
00842 
00843    if( qset == NULL ){ XBell(dc->display,100) ; return ; }
00844 
00845    
00846 
00847    dset     = qset ;
00848    dset_idc = qset->idcode ;   
00849 
00850    
00851 
00852    strcpy(str,dsl[id].title) ;
00853    xstr = XmStringCreateLtoR( str , XmFONTLIST_DEFAULT_TAG ) ;
00854    XtVaSetValues( info_lab , XmNlabelString , xstr , NULL ) ;
00855    XmStringFree(xstr) ;
00856 
00857    
00858 
00859    XtUnmanageChild( notesw ) ;
00860    XtUnmanageChild( noterc ) ;
00861    for( ii=0 ; ii < notar_num ; ii++ ){
00862       XtUnmanageChild( notar[ii]->frame ) ;
00863 
00864       if( notar[ii]->note_orig != NULL ){
00865           free(notar[ii]->note_orig) ; notar[ii]->note_orig = NULL ;
00866       }
00867 
00868       if( notar[ii]->date_orig != NULL ){
00869           free(notar[ii]->date_orig) ; notar[ii]->date_orig = NULL ;
00870       }
00871    }
00872 
00873    
00874 
00875    num_notes = tross_Get_Notecount( dset ) ;
00876 
00877    if( notar_num < num_notes + 1 ){
00878       notar = (NOTE_wind **) realloc( notar, sizeof(NOTE_wind *)*(num_notes+1) ) ;
00879       for( ii=notar_num ; ii <= num_notes ; ii++ )
00880          notar[ii]  = NOTES_make_note() ;
00881       notar_num = num_notes + 1 ;
00882    }
00883 
00884    
00885 
00886    his = tross_Get_History( dset ) ;
00887    if( his == NULL ){
00888       ii = ( lrand48() >> 8) % NUM_DH ;
00889       notar[0]->note_orig = newstring(default_history[ii]) ;
00890       xstr = XmStringCreateLtoR( "----- EDIFYING TEXT -----" , XmFONTLIST_DEFAULT_TAG ) ;
00891    } else {
00892       notar[0]->note_orig = tross_breakup_string( his , 2*TWIDTH/3 , TWIDTH-1 ) ;
00893       free(his) ;
00894       xstr = XmStringCreateLtoR( "----- HISTORY -----" , XmFONTLIST_DEFAULT_TAG ) ;
00895    }
00896    notar[0]->date_orig = NULL ;
00897 
00898    XtVaSetValues( notar[0]->note_label , XmNlabelString , xstr , NULL ) ;
00899    XmStringFree(xstr) ;
00900    XmTextSetString( notar[0]->textw , notar[0]->note_orig ) ;
00901 
00902    nl = line_count( notar[0]->note_orig ) ;
00903    if( nl > max_tlines ) nl = max_tlines ;
00904    XtVaSetValues( notar[0]->textw , XmNrows , nl , NULL ) ;
00905    nltot = nl ;
00906 
00907    XtManageChild( notar[0]->frame ) ;
00908 
00909    for( ii=1 ; ii <= num_notes ; ii++ ){
00910       notar[ii]->note_orig = tross_Get_Note    ( dset , ii ) ;
00911       notar[ii]->date_orig = tross_Get_Notedate( dset , ii ) ;
00912 
00913       if( notar[ii]->note_orig == NULL )
00914          notar[ii]->note_orig = newstring( empty_note ) ;
00915 
00916       if( notar[ii]->date_orig == NULL )
00917          notar[ii]->date_orig = newstring( no_date ) ;
00918 
00919       sprintf(str,"----- NOTE %d [%s] -----",ii,notar[ii]->date_orig) ;
00920       xstr = XmStringCreateLtoR( str , XmFONTLIST_DEFAULT_TAG ) ;
00921       XtVaSetValues( notar[ii]->note_label , XmNlabelString , xstr , NULL ) ;
00922       XmStringFree(xstr) ;
00923       XmTextSetString( notar[ii]->textw , notar[ii]->note_orig ) ;
00924 
00925       nl = line_count( notar[ii]->note_orig ) ;
00926       if( nl > max_tlines ) nl = max_tlines ;
00927       XtVaSetValues( notar[ii]->textw , XmNrows , nl , NULL ) ;
00928       nltot += nl ;
00929 
00930       XtManageChild( notar[ii]->frame ) ;
00931    }
00932 
00933    XtVaSetValues( notar[0]->scrollw , XmNwidth , text_width , NULL ) ;
00934 
00935    XtManageChild( noterc ) ;
00936    XtManageChild( notesw ) ;
00937 
00938    
00939 
00940    MCW_widget_geom( noterc , &ww,&hh , NULL,NULL ) ;
00941    ww += 4 ; hh += 4 ; qh = hh ;
00942    if( ww > dc->width - 128 ) ww = dc->width - 128 ;
00943    if( hh > dc->height- 128 ) hh = dc->height- 128 ;
00944 
00945    XtVaSetValues( notesw , XmNwidth,ww , XmNheight,hh , NULL ) ;
00946 
00947    if( qh > hh ) scroll_topbot( notesw , 0 ) ;
00948    return ;
00949 }
00950 
00951 
00952 
00953 static void NOTES_add_CB( Widget w, XtPointer client_data, XtPointer call_data )
00954 {
00955    int nl , hh , ii , qh ;
00956    char str[256] ;
00957    XmString xstr ;
00958 
00959    if( dset == NULL ){ XBell(dc->display,100) ; return ; }
00960 
00961    if( num_notes >= MAX_DSET_NOTES ){
00962       (void) MCW_popup_message( add_pb ,
00963                                 " \n"
00964                                 " Max number of notes\n"
00965                                 " would be exceeded!\n " ,
00966                                 MCW_USER_KILL | MCW_TIMER_KILL ) ;
00967       XBell(dc->display,100) ; return ;
00968    }
00969 
00970    tross_Add_Note( dset , empty_note ) ;
00971 
00972    num_notes ++ ;
00973 
00974    if( notar_num < num_notes + 1 ){
00975       notar = (NOTE_wind **) realloc( notar, sizeof(NOTE_wind *)*(num_notes+1) ) ;
00976       for( ii=notar_num ; ii <= num_notes ; ii++ )
00977          notar[ii]  = NOTES_make_note() ;
00978       notar_num = num_notes + 1 ;
00979    }
00980 
00981    notar[num_notes]->note_orig = tross_Get_Note    ( dset , num_notes ) ;
00982    notar[num_notes]->date_orig = tross_Get_Notedate( dset , num_notes ) ;
00983 
00984    if( notar[num_notes]->note_orig == NULL )
00985       notar[num_notes]->note_orig = newstring( empty_note ) ;
00986 
00987    if( notar[num_notes]->date_orig == NULL )
00988       notar[num_notes]->date_orig = newstring( no_date ) ;
00989 
00990    sprintf(str,"----- NOTE %d [%s] -----",num_notes,notar[num_notes]->date_orig) ;
00991    xstr = XmStringCreateLtoR( str , XmFONTLIST_DEFAULT_TAG ) ;
00992    XtVaSetValues( notar[num_notes]->note_label , XmNlabelString , xstr , NULL ) ;
00993    XmStringFree(xstr) ;
00994    XmTextSetString( notar[num_notes]->textw , notar[num_notes]->note_orig ) ;
00995 
00996    nl = line_count( notar[num_notes]->note_orig ) ;
00997    if( nl > max_tlines ) nl = max_tlines ;
00998    XtVaSetValues( notar[num_notes]->textw , XmNrows , nl , NULL ) ;
00999 
01000    XtManageChild( notar[num_notes]->frame ) ;
01001 
01002    
01003 
01004    MCW_widget_geom( noterc , NULL,&hh , NULL,NULL ) ; hh +=4 ; qh = hh ;
01005    if( hh > dc->height- 128 ) hh = dc->height- 128 ;
01006 
01007    XtVaSetValues( notesw , XmNheight,hh , NULL ) ;
01008 
01009    if( qh > hh ) scroll_topbot( notesw , 1 ) ;
01010    return ;
01011 }
01012 
01013 
01014 
01015 static void NOTES_refit_CB( Widget w, XtPointer client_data, XtPointer call_data )
01016 {
01017    int ii , hh , nl , qh ;
01018    char * ts ;
01019 
01020    if( dset == NULL ){ XBell(dc->display,100) ; return ; }
01021 
01022    for( ii=0 ; ii <= num_notes ; ii++ ){
01023       ts =  XmTextGetString( notar[ii]->textw ) ;  
01024       nl = line_count( ts ) ; XtFree( ts ) ;       
01025       if( nl > max_tlines ) nl = max_tlines ;
01026       XtVaSetValues( notar[ii]->textw , XmNrows , nl , NULL ) ;
01027    }
01028 
01029    
01030 
01031    MCW_widget_geom( noterc , NULL,&hh , NULL,NULL ) ; hh += 4 ; qh = hh ;
01032    if( hh > dc->height- 128 ) hh = dc->height- 128 ;
01033 
01034    XtVaSetValues( notesw , XmNheight,hh , NULL ) ;
01035    return ;
01036 }
01037 
01038 
01039 
01040 static void NOTES_delete_CB( Widget w, XtPointer client_data, XtPointer call_data )
01041 {
01042    int ii , kk , hh , nl ;
01043    char str[256] , * ts ;
01044    XmString xstr ;
01045 
01046    if( dset == NULL ) return ;    
01047 
01048    for( kk=1 ; kk <= num_notes ; kk++ )
01049       if( w == notar[kk]->delete_pb ) break ;
01050 
01051    if( kk > num_notes ) return ;  
01052 
01053    tross_Delete_Note( dset , kk ) ;  
01054 
01055    
01056 
01057    free( notar[kk]->note_orig ) ;  
01058    free( notar[kk]->date_orig ) ;
01059 
01060    
01061 
01062    for( ii=kk+1 ; ii <= num_notes ; ii++ ){
01063       notar[ii-1]->note_orig = notar[ii]->note_orig ;  
01064       notar[ii-1]->date_orig = notar[ii]->date_orig ;  
01065 
01066       ts = XmTextGetString( notar[ii]->textw ) ;       
01067       XmTextSetString( notar[ii-1]->textw , ts ) ;     
01068       nl = line_count( ts ) ;
01069       if( nl > max_tlines ) nl = max_tlines ;
01070       XtVaSetValues( notar[ii-1]->textw , XmNrows , nl , NULL ) ;
01071       XtFree(ts) ;
01072 
01073       sprintf(str,"----- NOTE %d [%s] -----",ii-1,notar[ii-1]->date_orig) ;
01074       xstr = XmStringCreateLtoR( str , XmFONTLIST_DEFAULT_TAG ) ;
01075       XtVaSetValues( notar[ii-1]->note_label , XmNlabelString , xstr , NULL ) ;
01076       XmStringFree(xstr) ;
01077    }
01078 
01079    notar[num_notes]->note_orig = NULL ;
01080    notar[num_notes]->date_orig = NULL ;
01081    XmTextSetString( notar[num_notes]->textw , "\0" ) ;
01082    XtUnmanageChild( notar[num_notes]->frame ) ;
01083    num_notes-- ;
01084 
01085    MCW_widget_geom( noterc , NULL,&hh , NULL,NULL ) ;
01086    if( hh > dc->height- 128 ) hh = dc->height- 128 ;
01087    XtVaSetValues( notesw , XmNheight,hh , NULL ) ;
01088 
01089    return ;
01090 }
01091 
01092 
01093 
01094 static void NOTES_restore_CB( Widget w, XtPointer client_data, XtPointer call_data )
01095 {
01096    int kk ;
01097 
01098    if( dset == NULL ) return ;    
01099 
01100    for( kk=1 ; kk <= num_notes ; kk++ )
01101       if( w == notar[kk]->restore_pb ) break ;
01102 
01103    if( kk > num_notes ) return ;  
01104 
01105    XmTextSetString( notar[kk]->textw , notar[kk]->note_orig ) ;
01106    return ;
01107 }
01108 
01109 
01110 
01111 static void scroll_topbot( Widget sw , int where )
01112 {
01113    Widget sb=NULL ;
01114    int val,siz,inc,pag , smin,smax ;
01115 
01116    if( sw == NULL ) return ;
01117 
01118    XtVaGetValues( sw ,
01119                      XmNverticalScrollBar , &sb ,
01120                      XmNmaximum           , &smax ,
01121                      XmNminimum           , &smin ,
01122                   NULL ) ;
01123    if( sb == NULL ) return ;
01124 
01125    XmScrollBarGetValues( sb , &val,&siz,&inc,&pag ) ;
01126 
01127    if( where == 0 ) val = smin ;  
01128    else             val = smax ;  
01129 
01130    XmScrollBarSetValues( sb , val,siz,inc,pag , True ) ;
01131    return ;
01132 }