/*****************************************************************************
   Major portions of this software are copyrighted by the Medical College
   of Wisconsin, 1994-2000, and are released under the Gnu General Public
   License, Version 2.  See the file README.Copyright for details.
******************************************************************************/

#include "mrilib.h"

/** Error messaging **/

#undef  EDERR
#define EDERR(str) \
 do{ ERROR_message("EDIT_dset_items[%d]: %s\n",ncall,str); errnum++; } while(0)

/*-----------------------------------------------------------------------*/
/*! Edit some internals of a dataset.  Notice that it is possible to
  create a dataset which is inconsistent.  Note also that some operations
  cannot be performed on a dataset containing actual data -- for example,
  you cannot change the types of sub-bricks if they already are attached
  to data arrays!

  This routine uses the <stdarg.h> variable argument interface.
  The first argument is a pointer to the dataset to edit.
  All succeeding arguments are pairs indicating which internal item
  to edit, and the new value for that item.  The first entry of a pair
  must be one of the ADN_ entries defined in editvol.h.  The type of the
  second entry of a pair depends on the particular item.
  [*** WARNING: due to C automatic 'type promotion', you cannot use
       float as the type to extract from the list -- you must use double!]

  Finally, the end of the argument list is found by the last argument
  being the special code ADN_none (0).

  The return value is the number of errors detected (hopefully, 0).
-------------------------------------------------------------------------*/

int EDIT_dset_items( THD_3dim_dataset *dset , ... )
{
   va_list vararg_ptr ;
   int     flag_arg , errnum = 0 ;
   int     redo_bricks , redo_daxes , redo_taxis , ii ;
   void   *dummy ;
   int     iarg ;
   static int ncall=0 ;  /* 20 Dec 2005 */

   /**----- variables to flag and store presence of arguments -----**/

   int new_prefix        = 0; char *            prefix         = NULL ;
   int new_directory_name= 0; char *            directory_name = NULL ;
   int new_brick_fac     = 0; float *           brick_fac      = NULL ;
   int new_malloc_type   = 0; int               malloc_type    = ILLEGAL_TYPE;
   int new_datum_all     = 0; int               datum_all      = ILLEGAL_TYPE;
   int new_datum_array   = 0; int *             datum_array    = NULL ;
   int new_nvals         = 0; int               nvals          = 0 ;
   int new_nxyz          = 0; THD_ivec3         nxyz           ;
   int new_xyzdel        = 0; THD_fvec3         xyzdel         ;
   int new_xyzorg        = 0; THD_fvec3         xyzorg         ;
   int new_xyzorient     = 0; THD_ivec3         xyzorient      ;
   int new_to_dicomm     = 0; THD_mat33         to_dicomm      ;
   int new_ntt           = 0; int               ntt            = 0 ;
   int new_ttorg         = 0; float             ttorg          = 0.0 ;
   int new_ttdel         = 0; float             ttdel          = 0.0 ;
   int new_ttdur         = 0; float             ttdur          = 0.0 ;
   int new_nsl           = 0; int               nsl            = 0 ;
   int new_zorg_sl       = 0; float             zorg_sl        = 0.0 ;
   int new_dz_sl         = 0; float             dz_sl          = 0.0 ;
   int new_toff_sl       = 0; float *           toff_sl        = NULL ;
   int new_type          = 0; int               type           = ILLEGAL_TYPE;
   int new_view_type     = 0; int               view_type      = ILLEGAL_TYPE;
   int new_func_type     = 0; int               func_type      = ILLEGAL_TYPE;
   int new_label1        = 0; char *            label1         = NULL ;
   int new_label2        = 0; char *            label2         = NULL ;
   int new_self_name     = 0; char *            self_name      = NULL ;
   int new_warp_parent   = 0; THD_3dim_dataset *warp_parent    = NULL ;
   int new_anat_parent   = 0; THD_3dim_dataset *anat_parent    = NULL ;
   int new_stat_aux      = 0; float *           stat_aux       = NULL ;
   int new_warp          = 0; THD_warp *        warp           = NULL ;
   int new_tunits        = 0; int               tunits         = ILLEGAL_TYPE;
   int new_keywords      = 0; char *            keywords       = NULL ;

   /* 30 Nov 1997 */

   int new_brick_label_one = 0 ; char * brick_label_one    = NULL ;
                                 int    brick_label_one_iv = -1 ;

   int new_brick_fac_one = 0 ; float brick_fac_one    = 0.0 ;
                               int   brick_fac_one_iv = -1 ;

   int new_brick_stataux_one = 0 ; float * brick_stataux_one    = NULL ;
                                   int     brick_stataux_one_iv = -1 ;

   int new_brick_keywords_one = 0 ; char * brick_keywords_one    = NULL ;
                                    int    brick_keywords_one_iv = -1 ;

   /* 19 Dec 2005 */

   int new_ijk_to_dicom = 0; mat44 ijk_to_dicom ;

   /* 14 July 2006 */
   int cmode = COMPRESS_NOFILE;   /* check compression mode for NIFTI separately */


   /****---------------------- Sanity Check ----------------------****/

ENTRY("EDIT_dset_items") ;

   ncall++ ;  /* 20 Dec 2005: to keep track of number of calls for EDERR */

   if( ! ISVALID_3DIM_DATASET(dset) ){                /* bad data */
     EDERR("invalid input dataset"); RETURN(errnum);
   }

   /****----------- Scan input argument list;
                  - Load data into locals (va_arg);
                  - Check for legal values;
                  - Flag its presence (the new_ variables);
                  - Carry out simple processing that doesn't
                      depend on the presence of other arguments. ---------****/

   va_start( vararg_ptr , dset ) ;              /** Initialize arg reading **/
   iarg = 1 ;

   do{
      flag_arg = va_arg( vararg_ptr , int ) ;   /** Get next arg  **/
      if( flag_arg == ADN_none ) break ;        /** No more args! **/
#if 0
fprintf(stderr,"EDIT_dset_items: iarg=%d flag_arg=%d\n",iarg,flag_arg) ;
#endif
      iarg++ ;

      switch( flag_arg ){

         default:{
            int iv ;
            char str[128] ;

            /** 30 Nov 1997: check for special cases **/

            iv = flag_arg - ADN_brick_label_one ;
            if( iv >= 0 && iv < ADN_ONE_STEP ){
               brick_label_one_iv  = iv ;
               brick_label_one     = va_arg( vararg_ptr , char * ) ;
               if( brick_label_one != NULL ) new_brick_label_one = 1 ;
               break ; /* exit switch */
            }

            iv = flag_arg - ADN_brick_fac_one ;
            if( iv >= 0 && iv < ADN_ONE_STEP ){
               brick_fac_one_iv  = iv ;
               brick_fac_one     = va_arg( vararg_ptr , double ) ;
               new_brick_fac_one = 1 ;
               break ; /* exit switch */
            }

            iv = flag_arg - ADN_brick_stataux_one ;
            if( iv >= 0 && iv < ADN_ONE_STEP ){
               brick_stataux_one_iv = iv ;
               brick_stataux_one    = va_arg( vararg_ptr , float * ) ;
               if( brick_stataux_one != NULL ) new_brick_stataux_one = 1 ;
               break ; /* exit switch */
            }

            iv = flag_arg - ADN_brick_keywords_replace_one ;
            if( iv >= 0 && iv < ADN_ONE_STEP ){
               brick_keywords_one_iv  = iv ;
               brick_keywords_one     = va_arg( vararg_ptr , char * ) ;
               new_brick_keywords_one = 1 ;
               break ; /* exit switch */
            }

            iv = flag_arg - ADN_brick_keywords_append_one ;
            if( iv >= 0 && iv < ADN_ONE_STEP ){
               brick_keywords_one_iv  = iv ;
               brick_keywords_one     = va_arg( vararg_ptr , char * ) ;
               new_brick_keywords_one = 2 ;
               break ; /* exit switch */
            }

            /** not a special case? error! **/

            sprintf(str,"illegal opcode = %d at arg #%d",flag_arg,iarg) ;
            EDERR(str) ; if( errnum > 9 ) RETURN(errnum) ;
            dummy = va_arg( vararg_ptr , void * ) ;  /* skip next arg */
         }
         break ;

         /** these two commands affect the disk file names **/

         case ADN_prefix:  /* processed later */
            prefix = va_arg( vararg_ptr , char * ) ;
            if( prefix != NULL ) new_prefix = 1 ;
            else EDERR("illegal new prefix") ;
         break ;

         case ADN_directory_name:  /* processed later */
            directory_name = va_arg( vararg_ptr , char * ) ;
            if( directory_name != NULL ) new_directory_name = 1 ;
            else EDERR("illegal new directory_name") ;
         break ;

         /** change the memory allocation type (mmap or malloc) **/

         case ADN_malloc_type:  /* processed now */
            malloc_type = va_arg( vararg_ptr , int ) ;
            if( ISVALID_MEM_CODE(malloc_type) ){
               new_malloc_type = 1 ;
               THD_force_malloc_type( dset->dblk , malloc_type ) ;
            }
            else EDERR("illegal new malloc_type") ;
         break ;

         /** these commands affect the data in the bricks **/

         case ADN_brick_fac:  /* processed later */
            brick_fac = va_arg( vararg_ptr , float * ) ;
            new_brick_fac = 1 ;
         break ;

         case ADN_datum_all:  /* processed later */
            datum_all = va_arg( vararg_ptr , int ) ;
            if( AFNI_GOOD_DTYPE(datum_all) ) new_datum_all = 1 ;
            else EDERR("illegal new datum_all") ;
         break ;

         case ADN_datum_array:  /* processed later */
            datum_array = va_arg( vararg_ptr , int * ) ;
            if( datum_array != NULL ) new_datum_array = 1 ;
            else EDERR("illegal new datum_array") ;
         break ;

         case ADN_nvals:  /* processed later */
            nvals = va_arg( vararg_ptr , int ) ;
            if( nvals > 0 ) new_nvals = 1 ;
            else EDERR("illegal new nvals") ;
         break ;

         /** these commands affect the spatial axes,
             which may also influence size of the data bricks **/

         case ADN_ijk_to_dicom:  /* processed later [19 Dec 2005] */
           ijk_to_dicom = va_arg( vararg_ptr , mat44 ) ;
           if( ISVALID_MAT44(ijk_to_dicom) ) new_ijk_to_dicom = 1 ;
           else EDERR("illegal new ijk_to_dicom") ;
         break ;

         case ADN_nxyz:  /* processed later */
           nxyz = va_arg( vararg_ptr , THD_ivec3 ) ;
           if( nxyz.ijk[0] >= 1 && nxyz.ijk[1] >= 1 && nxyz.ijk[2] >= 1 )
             new_nxyz = 1 ;
             else EDERR("illegal new nxyz") ;
         break ;

         case ADN_xyzdel:  /* processed later */
           xyzdel = va_arg( vararg_ptr , THD_fvec3 ) ;
           if( xyzdel.xyz[0]!=0.0 && xyzdel.xyz[1]!=0.0 && xyzdel.xyz[2]!=0.0 )
             new_xyzdel = 1 ;
             else EDERR("illegal new xyzdel") ;
         break ;

         case ADN_xyzorg:  /* processed later */
           xyzorg = va_arg( vararg_ptr , THD_fvec3 ) ;
           new_xyzorg = 1 ;
         break ;

         case ADN_xyzorient:  /* processed later */
            xyzorient = va_arg( vararg_ptr , THD_ivec3 ) ;
            if( xyzorient.ijk[0] >= FIRST_ORIENT_TYPE &&
                xyzorient.ijk[0] <= LAST_ORIENT_TYPE  &&
                xyzorient.ijk[1] >= FIRST_ORIENT_TYPE &&
                xyzorient.ijk[1] <= LAST_ORIENT_TYPE  &&
                xyzorient.ijk[2] >= FIRST_ORIENT_TYPE &&
                xyzorient.ijk[2] <= LAST_ORIENT_TYPE  &&
                  ORIENT_xyzint[xyzorient.ijk[0]]
                + ORIENT_xyzint[xyzorient.ijk[1]]
                + ORIENT_xyzint[xyzorient.ijk[2]] == 6  )

               new_xyzorient = 1 ;
            else EDERR("illegal new xyzorient") ;
         break ;

         case ADN_to_dicomm:   /* illegal at this time */
            EDERR("to_dicomm not implemented") ;
         break ;

         /** these commands affect the time axis of the dataset **/

         case ADN_ntt:  /* processed later */
            ntt = va_arg( vararg_ptr , int ) ;
            if( ntt >= 0 ) new_ntt = 1 ;
            else EDERR("illegal new taxis ntt") ;
         break ;

         case ADN_tunits:  /* processed later */
            tunits = va_arg( vararg_ptr , int ) ;
            if( tunits >= 0 ) new_tunits = 1 ;
            else EDERR("illegal new taxis tunits") ;
         break ;

         case ADN_nsl:  /* processed later */
            nsl = va_arg( vararg_ptr , int ) ;
            if( nsl >= 0 ) new_nsl = 1 ;
            else EDERR("illegal new taxis nsl") ;
         break ;

         case ADN_ttorg:  /* processed later */
            ttorg = (float) va_arg( vararg_ptr , double ) ;
            new_ttorg = 1 ;
         break ;

         case ADN_ttdel:  /* processed later */
            ttdel = (float) va_arg( vararg_ptr , double ) ;
            new_ttdel = 1 ;
         break ;

         case ADN_ttdur:  /* processed later */
            ttdur = (float) va_arg( vararg_ptr , double ) ;
            new_ttdur = 1 ;
         break ;

         case ADN_zorg_sl:  /* processed later */
            zorg_sl = (float) va_arg( vararg_ptr , double ) ;
            new_zorg_sl = 1 ;
         break ;

         case ADN_dz_sl:  /* processed later */
            dz_sl = (float) va_arg( vararg_ptr , double ) ;
            if( dz_sl != 0.0 ) new_dz_sl = 1 ;
            else EDERR("illegal new taxis dz_sl") ;
         break ;

         case ADN_toff_sl:  /* processed later */
            toff_sl = va_arg( vararg_ptr , float * ) ;
            new_toff_sl = 1 ;
         break ;

         /** these commands affect the interpretation of the dataset
             (e.g., is it functional or anatomical, which view type, ...) **/

         case ADN_type:  /* processed later */
            type = va_arg( vararg_ptr , int ) ;
            if( type >= FIRST_3DIM_TYPE && type <= LAST_3DIM_TYPE )
               new_type = 1 ;
            else EDERR("illegal new type") ;
         break ;

         case ADN_view_type:  /* processed later */
            view_type = va_arg( vararg_ptr , int ) ;
            if( view_type >= FIRST_VIEW_TYPE && view_type <= LAST_VIEW_TYPE )
               new_view_type = 1 ;
            else EDERR("illegal new view_type") ;
         break ;

         case ADN_func_type:  /* processed later */
            func_type = va_arg( vararg_ptr , int ) ;
            if( func_type >= 0 ) new_func_type = 1 ;
            else EDERR("illegal new func_type") ;
         break ;

         /** auxiliary statistical data, for interpretation of functions **/

         case ADN_stat_aux:  /* processed now */
            stat_aux = va_arg( vararg_ptr , float * ) ;
            if( stat_aux != NULL ){
               new_stat_aux = 1 ;
               for( ii=0 ; ii < MAX_STAT_AUX ; ii++ )
                  dset->stat_aux[ii] = stat_aux[ii] ;
            } else EDERR("illegal new stat_aux") ;
         break ;

         /** dataset keywords **/

         case ADN_keywords_replace: /* processed now */
            keywords = va_arg( vararg_ptr , char * ) ;
            new_keywords = 1 ;
            THD_store_dataset_keywords( dset , keywords ) ;
         break ;

         case ADN_keywords_append: /* processed now */
            keywords = va_arg( vararg_ptr , char * ) ;
            new_keywords = 1 ;
            THD_append_dataset_keywords( dset , keywords ) ;
         break ;

         /** various labeling options **/

         case ADN_label1:  /* processed now */
            label1 = va_arg( vararg_ptr , char * ) ;
            if( label1 != NULL ){
               MCW_strncpy( dset->label1 , label1 , THD_MAX_LABEL ) ;
               new_label1 = 1 ;
            }
            else EDERR("illegal new label1") ;
         break ;

         case ADN_label2:  /* processed now */
            label2 = va_arg( vararg_ptr , char * ) ;
            if( label2 != NULL ){
               MCW_strncpy( dset->label2 , label2 , THD_MAX_LABEL ) ;
               new_label2 = 1 ;
            }
            else EDERR("illegal new label2") ;
         break ;

         case ADN_self_name:  /* processed now */
            self_name = va_arg( vararg_ptr , char * ) ;
            if( self_name != NULL ){
               MCW_strncpy( dset->self_name , self_name , THD_MAX_NAME ) ;
               new_self_name = 1 ;
            }
            else EDERR("illegal new self_name") ;
         break ;

         /** relationships to other datasets **/

         case ADN_warp_parent:  /* processed now */
            warp_parent = va_arg( vararg_ptr , THD_3dim_dataset * ) ;
            if( ISVALID_3DIM_DATASET(warp_parent) ){
               new_warp_parent = 1 ;
               dset->warp_parent = warp_parent ;
               MCW_strncpy(dset->warp_parent_name,warp_parent->self_name,THD_MAX_NAME) ;
               dset->warp_parent_idcode = warp_parent->idcode ;
            }
            else EDERR("illegal new warp_parent") ;
         break ;

         case ADN_warp:  /* processed now */
            warp = va_arg( vararg_ptr , THD_warp * ) ;
            if( ISVALID_WARP(warp) ){
               new_warp = 1 ;
               if( dset->warp == NULL ) dset->warp = myXtNew(THD_warp) ;
               *(dset->warp) =* warp ;
            } else EDERR("illegal new warp") ;
         break ;

         case ADN_anat_parent:  /* processed now */
            anat_parent = va_arg( vararg_ptr , THD_3dim_dataset * ) ;
            if( ISVALID_3DIM_DATASET(anat_parent) ){
               new_anat_parent = 1 ;
               dset->anat_parent = anat_parent ;
               MCW_strncpy(dset->anat_parent_name,anat_parent->self_name,THD_MAX_NAME) ;
               dset->anat_parent_idcode = anat_parent->idcode ;
            }
            else EDERR("illegal new anat_parent") ;
         break ;

         case ADN_anatpar_idcode:{ /* processed now [13 Dec 1999] */
            MCW_idcode * idc ;
            idc = va_arg( vararg_ptr , MCW_idcode * ) ;
            if( idc != NULL )
               dset->anat_parent_idcode = *idc ;
            else
               EDERR("illegal new anatpar_idcode") ;
         }
         break ;

      }  /*- end of switch on flag_arg -*/

      iarg++ ;
   } while( 1 ) ;  /* end of loop over arguments */
   va_end( vararg_ptr ) ;
   if( errnum > 0 ) RETURN(errnum) ;

   /**** carry out edits that were flagged above ****/

   /**---------- Need to reset the disk filename? ------------**/
   /** 22 Nov 2002: remove +orig etc. from prefix, if present **/

   if( new_prefix || new_directory_name || new_view_type ){
      char *nprefix = THD_deplus_prefix( prefix ) ;

      THD_init_diskptr_names( dset->dblk->diskptr ,
                              directory_name , NULL ,
                              nprefix , view_type , True ) ;

      if( DSET_IS_1D(dset) || DSET_IS_3D(dset) ){         /* 21 Mar 2003 */
        char *fname = dset->dblk->diskptr->brick_name ;
        int  ll = strlen(fname) ;
        fname[ll-10] = '\0' ;
        if( DSET_IS_1D(dset) || (DSET_NY(dset)==1 && DSET_NZ(dset)==1) )
          strcat(fname,".1D");
        else
          strcat(fname,".3D");
      }

      if( DSET_IS_NIML(dset) ){         /* 07 Jun 2006 [rickr] */
        char *fname = dset->dblk->diskptr->brick_name ;
        int  ll = strlen(fname) ;
        fname[ll-10] = '\0' ;
        if( !STRING_HAS_SUFFIX(fname,".niml") ) strcat(fname,".niml");
      }

      if( DSET_IS_NI_SURF_DSET(dset) ){ /* 28 Jun 2006 [rickr] */
        char *fname = dset->dblk->diskptr->brick_name ;
        int  ll = strlen(fname) ;
        fname[ll-10] = '\0' ;
        if( !STRING_HAS_SUFFIX(fname,".niml.dset") ) strcat(fname,".niml.dset");
      }
      /** output of NIfTI-1.1 dataset: 06 May 2005 **/
      /* if the prefix ends in .nii or .nii.gz, change filename in brick_name */
      if( nprefix != NULL && ( STRING_HAS_SUFFIX(nprefix,".nii") ||
                               STRING_HAS_SUFFIX(nprefix,".nii.gz") ) ){
        char *fname = dset->dblk->diskptr->brick_name ;
        int  ll = strlen(fname) ;
        fname[ll-10] = '\0' ;  /* taking off "+view.BRIK" */
	
        if( STRING_HAS_SUFFIX(nprefix,".nii") ) {  /* 22 Jun 2006 mod drg */
	   cmode = THD_get_write_compression() ; /* check env. variable for compression*/
	   if(cmode==0) { /* have to compress this NIFTI data, add .gz to prefix */
             sprintf(DSET_PREFIX(dset),"%s.gz",nprefix); /* add .gz on to prefix initialized in */
	                                          /* THD_init_diskptr_names just above */
             if(STRING_HAS_SUFFIX(fname,".nii")) {  /* if filename ends with .nii */
	       strcat(fname,".gz") ;   /* add the .gz extension */
	       }
             else {
	        if(!(STRING_HAS_SUFFIX(fname,".nii.gz"))) /* compressed NIFTI extension*/
       	        strcat(fname,".nii.gz") ;
	     }
	   }
	   else {
             if(!(STRING_HAS_SUFFIX(fname,".nii")))  /* if filename doesn't end with .nii */
	       strcat(fname,".nii") ;   /* add the .nii extension */
	    }
	  }
        else {
           if(!(STRING_HAS_SUFFIX(fname,".nii.gz"))) /* compressed NIFTI extension*/
   	      strcat(fname,".nii.gz") ;
	   }
      }
      
      if( nprefix != NULL ) free(nprefix) ;
   }

   /**----------- Need to reconfigure the spatial axes? -----------**/
   /**    Much of this code is from routine THD_3dim_from_block    **/

   redo_daxes = ( new_xyzorg || new_xyzdel || new_xyzorient ) ;

   redo_bricks = ( new_datum_all || new_datum_array ||
                   new_nvals     || new_nxyz          ) ;

   /*----- ye newe waye for ye axes change [19 Dec 2005] -----*/

   /* check for conflicts */

   if( new_xyzorg && new_ijk_to_dicom )
     EDERR("can't set ijk_to_dicom and xyzorg at same time");
   if( new_xyzdel && new_ijk_to_dicom )
     EDERR("can't set ijk_to_dicom and xyzdel at same time");
   if( new_xyzorient && new_ijk_to_dicom )
     EDERR("can't set ijk_to_dicom and xyzorient at same time");

   if( redo_bricks && THD_count_databricks(dset->dblk) > 0 )
     EDERR("cannot reconfigure bricks that already are full") ;

   if( errnum > 0 ) RETURN(errnum) ;

   /* set new data grid size now */

   if( new_nxyz ){
     THD_dataxes *daxes = dset->daxes ;
     THD_diskptr *dkptr = dset->dblk->diskptr ;

     daxes->nxx  = dkptr->dimsizes[0] = nxyz.ijk[0] ;
     daxes->nyy  = dkptr->dimsizes[1] = nxyz.ijk[1] ;
     daxes->nzz  = dkptr->dimsizes[2] = nxyz.ijk[2] ;

     if( !redo_daxes && !new_ijk_to_dicom ){
       THD_set_daxes_bbox(daxes) ;
       if( !ISVALID_MAT44(daxes->ijk_to_dicom) ) THD_daxes_to_mat44(daxes) ;
       else                                      THD_set_dicom_box (daxes) ;
     }
   }

   /* set the new matrix transform between index and space */

   if( new_ijk_to_dicom ){
     THD_dataxes *daxes = dset->daxes ;

     daxes->ijk_to_dicom = ijk_to_dicom ;
     daxes->dicom_to_ijk = nifti_mat44_inverse( ijk_to_dicom ) ;
     THD_set_dicom_box( daxes ) ;
     (void)THD_daxes_from_mat44( daxes ) ;  /* set the old stuff */
   }

   /*------ ye olde waye for ye axes change -----*/

   if( redo_daxes ){
     THD_dataxes *daxes = dset->daxes ;

     /** copy new stuff into the daxes structure **/

     if( new_xyzorg ){
       daxes->xxorg = xyzorg.xyz[0] ;
       daxes->yyorg = xyzorg.xyz[1] ;
       daxes->zzorg = xyzorg.xyz[2] ;
     }

     if( new_xyzdel ){
       daxes->xxdel = xyzdel.xyz[0] ;
       daxes->yydel = xyzdel.xyz[1] ;
       daxes->zzdel = xyzdel.xyz[2] ;
     }

     if( new_xyzorient ){
       daxes->xxorient = xyzorient.ijk[0] ;
       daxes->yyorient = xyzorient.ijk[1] ;
       daxes->zzorient = xyzorient.ijk[2] ;
     }

     /*-- set bounding box and to_dicomm matrix for this dataset --*/

     THD_set_daxes_bbox     ( daxes ) ; /* 20 Dec 2005 */
     THD_set_daxes_to_dicomm( daxes ) ; /* 20 Dec 2005 */
     THD_daxes_to_mat44     ( daxes ) ; /* 19 Dec 2005 */
   }

   /**---------- Need to reconfigure the sub-bricks? ----------**/

   if( new_datum_all && new_datum_array ){
     EDERR("datum_all and datum_array can't be used together") ;
     RETURN(errnum) ;
   }

   if( redo_bricks ){
      int old_nvals = dset->dblk->nvals ;
#if 0
fprintf(stderr,"EDIT_dset_items: about to redo_bricks\n") ;
#endif
      if( ! new_nvals ) nvals = old_nvals ;

      /** make an array of data types, if one not provided **/

      if( ! new_datum_array ){
         datum_array = (int *) XtMalloc( sizeof(int) * nvals ) ;

#if 0
fprintf(stderr,"EDIT_dset_items: about to make datum_array\n") ;
#endif
         for( ii=0 ; ii < nvals ; ii++ )
            datum_array[ii] =  (new_datum_all)  ? datum_all
                             : (ii < old_nvals) ? DSET_BRICK_TYPE(dset,ii)
                                                : DSET_BRICK_TYPE(dset,0) ;
      }                                           /* 06 Apr 2005 [rickr] */

      if( new_nvals ){
         if( dset->dblk->nvals != nvals )
            THD_copy_datablock_auxdata( NULL , dset->dblk ) ; /* 30 Nov 1997 */

         myXtFree( dset->dblk->brick_bytes ) ;
         myXtFree( dset->dblk->brick_fac   ) ;

         dset->dblk->nvals = dset->dblk->diskptr->nvals = nvals ;
      }

      THD_init_datablock_brick( dset->dblk , nvals , datum_array ) ;

      if( ! new_datum_array ) myXtFree(datum_array) ;
   }

   /**---------- Need to add new brick_fac values? ----------**/

   if( new_brick_fac ){
      if( brick_fac != NULL ){
         for( ii=0 ; ii < dset->dblk->nvals ; ii++ )
            dset->dblk->brick_fac[ii] = brick_fac[ii] ;
      } else {
         for( ii=0 ; ii < dset->dblk->nvals ; ii++ )
            dset->dblk->brick_fac[ii] = 0.0 ;
      }
   }

   /** 30 Nov 1997: do just one brick_fac value **/

   if( new_brick_fac_one ){
      if( brick_fac_one_iv < 0 || brick_fac_one_iv >= dset->dblk->nvals ){
         EDERR("illegal index for ADN_brick_fac_one") ;
         RETURN(errnum) ;
      }
      dset->dblk->brick_fac[ brick_fac_one_iv ] = brick_fac_one ;
   }

   /**--------- 30 Nov 1997: add a single brick label value --------**/

   if( new_brick_label_one ){
      if( brick_label_one_iv < 0 || brick_label_one_iv >= dset->dblk->nvals ){
         EDERR("illegal index for ADN_brick_label_one") ;
         RETURN(errnum) ;
      }

      THD_store_datablock_label( dset->dblk, brick_label_one_iv, brick_label_one ) ;
   }

   /*---- add a single brick keywords value ----*/

   if( new_brick_keywords_one ){
      if( brick_keywords_one_iv < 0 || brick_keywords_one_iv >= dset->dblk->nvals ){
         EDERR("illegal index for ADN_brick_keywords_one") ;
         RETURN(errnum) ;
      }

      if( new_brick_keywords_one == 1 )
         THD_store_datablock_keywords( dset->dblk, brick_keywords_one_iv,
                                                   brick_keywords_one    );
      else if( new_brick_keywords_one == 2 )
         THD_append_datablock_keywords( dset->dblk, brick_keywords_one_iv,
                                                    brick_keywords_one    );
   }

   /*---- Add a single brick stataux value.
          The input is a float array formatted like so:
            <statcode> <npar> <value> ... <value>
          where <statcode> is a FUNC_*_TYPE code
                <npar>     is the number of values to follow (may be 0);
                             normally is FUNC_need_stat_aux[<statcode>]
                <value>    is an auxiliary statistical parameter needed
                             for data of type <statcode>                ----*/

   if( new_brick_stataux_one ){
      int jv , npar , kv , iv ;

      iv = brick_stataux_one_iv ;

      if( iv < 0 || iv >= dset->dblk->nvals ){
         EDERR("illegal index for ADN_brick_stataux_one") ;
         RETURN(errnum) ;
      }

      jv = brick_stataux_one[0] ;  /* statcode */

      npar = brick_stataux_one[1] ;  /* # of values present */
      if( npar < 0 ){
         EDERR("illegal npar for ADN_brick_stataux_one") ;
         RETURN(errnum) ;
      }

      kv = FUNC_need_stat_aux[jv] ;  /* # of values needed */
      if( npar > kv ) npar = kv ;

      THD_store_datablock_stataux( dset->dblk ,
                                   iv , jv , npar , brick_stataux_one + 2 ) ;
   }

   /**---------- Need to reconfigure the time axis? ----------**/

   redo_taxis = ( new_ntt   || new_nsl     || new_ttorg || new_ttdel ||
                  new_ttdur || new_zorg_sl || new_dz_sl || new_toff_sl ) ;

   if( ! new_ntt ) ntt = ISVALID_TIMEAXIS(dset->taxis) ? dset->taxis->ntt : 0 ;

   if( ntt == 0 && dset->taxis != NULL ){
      myXtFree( dset->taxis->toff_sl ) ;
      myXtFree( dset->taxis ) ;
      dset->taxis = NULL ;
   }

   redo_taxis = ( redo_taxis && ntt > 0 ) ;

   if( (new_nsl && nsl > 0) && !new_toff_sl ){    /* if we have new slice count */
      EDERR("have new_nsl but not new_toff_sl") ; /* but no new slice offsets */
      RETURN(errnum) ;
   }

   if( redo_taxis ){
      THD_timeaxis * taxis = dset->taxis ;

      if( taxis == NULL ){
         taxis          = dset->taxis     = myXtNew( THD_timeaxis ) ;
         taxis->type    = TIMEAXIS_TYPE ;
         taxis->toff_sl = NULL ;
         taxis->nsl     = 0 ;
         taxis->ttorg   = taxis->ttdel = taxis->ttdur = 0.0 ;
         taxis->ntt     = ntt ;
      }

      if( new_ntt     ) taxis->ntt     = ntt ;
      if( new_ttorg   ) taxis->ttorg   = ttorg ;
      if( new_ttdel   ) taxis->ttdel   = ttdel ;
      if( new_ttdur   ) taxis->ttdur   = ttdur ;
      if( new_zorg_sl ) taxis->zorg_sl = zorg_sl ;
      if( new_dz_sl   ) taxis->dz_sl   = dz_sl ;

      if( new_nsl ){
         taxis->nsl = nsl ;
         if( nsl > 0 )
            taxis->toff_sl = (float *) XtRealloc( (char *) taxis->toff_sl ,
                                                  sizeof(float) * nsl      ) ;
         else
            myXtFree(taxis->toff_sl) ;
      }

      if( new_toff_sl )
         for( ii=0 ; ii < taxis->nsl ; ii++ ) taxis->toff_sl[ii] = toff_sl[ii] ;
   }

   if( new_tunits ){
      THD_timeaxis * taxis = dset->taxis ;

      if( taxis == NULL ){
         EDERR("have new_tunits but have no time axis") ;
         RETURN(errnum) ;
      }

      taxis->units_type = tunits ;
   }

   /**--------------- Need to redo dataset type codes? ------------**/
   /**  Note that changing the type codes by themselves won't fix  **/
   /**  nvals or other such stuff -- that must be done separately. **/

   if( new_type      ) dset->type      = type ;
   if( new_view_type ) dset->view_type = view_type ;

   if( new_func_type ){
      if( (ISANAT(dset) && func_type <= LAST_ANAT_TYPE) ||
          (ISFUNC(dset) && func_type <= LAST_FUNC_TYPE)   ){

         dset->func_type = func_type ;

      } else{
         EDERR("illegal new_func type combination") ; RETURN(errnum) ;
      }
   }

   /****--------------- hopefully, we are done! ---------------****/

   RETURN(errnum) ;
}


/*-------------------------------------------------------------------*/
/*! Remove any +???? suffix from a prefix, returning a new one.
    -- 22 Nov 2002 - RWCox
---------------------------------------------------------------------*/

char * THD_deplus_prefix( char *prefix )
{
   char *newprefix ;
   int nn ;

   if( prefix == NULL ) return NULL ;

   nn = strlen(prefix); newprefix = strdup(prefix);

   /* only remove the basic 3: +orig, +acpc +tlrc   17 May 2004 [rickr] */
   /* (blame Shruti) */
   if( nn > 4 &&   ( (strcmp(newprefix+nn-5,"+orig") == 0) ||
                     (strcmp(newprefix+nn-5,"+acpc") == 0) ||
                     (strcmp(newprefix+nn-5,"+tlrc") == 0)   ) )
      newprefix[nn-5] = '\0' ;

/* old check
       isalpha(newprefix[nn-4]) &&
       isalpha(newprefix[nn-3]) &&
       isalpha(newprefix[nn-2]) &&
       isalpha(newprefix[nn-1])   ) newprefix[nn-5] = '\0' ;
*/

   return newprefix ;
}


syntax highlighted by Code2HTML, v. 0.9.1