[ncview] 12/31: Imported Upstream version 2.1.2
Sebastiaan Couwenberg
sebastic at moszumanska.debian.org
Sat Apr 18 00:43:41 UTC 2015
This is an automated email from the git hooks/post-receive script.
sebastic pushed a commit to branch master
in repository ncview.
commit 6954e14ed6ea728aead0a778cb636f6d68b12d63
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date: Sat Apr 18 01:40:38 2015 +0200
Imported Upstream version 2.1.2
---
src/Makefile.am | 2 +-
src/{Makefile.am => Makefile.am.orig} | 0
src/Makefile.in | 2 +-
src/do_buttons.c | 18 +-
src/file_netcdf.c | 548 ++++++++++++++++++++++++++++------
src/interface/{x_interface.c => '} | 184 +++++++++++-
src/interface/filesel.c | 12 +-
src/interface/x_interface.c | 170 +++++++++--
src/ncview.c | 50 +++-
src/ncview.defines.h | 10 +-
src/ncview.protos.h | 4 +-
src/util.c | 158 +++++++++-
src/view.c | 99 +++++-
x_interface.c | 0
14 files changed, 1091 insertions(+), 166 deletions(-)
diff --git a/src/Makefile.am b/src/Makefile.am
index f27ba2f..de8ca20 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -33,5 +33,5 @@ sources = ncview.c file.c util.c do_buttons.c \
stringlist.c handle_rc_file.c
AM_CPPFLAGS=-DNCVIEW_LIB_DIR=\"$(pkgdatadir)\" $(PNG_CPPFLAGS) $(UDUNITS2_CPPFLAGS) $(NETCDF_CPPFLAGS)
-AM_CFLAGS=-Wall $(X_CFLAGS)
+AM_CFLAGS=$(X_CFLAGS)
AM_LDFLAGS=$(PNG_LDFLAGS) $(UDUNITS2_LDFLAGS) $(NETCDF_LDFLAGS) $(X_PRE_LIBS) $(X_LIBS) $(X11_LIBS) $(X_EXTRA_LIBS) $(RPATH_FLAGS)
diff --git a/src/Makefile.am b/src/Makefile.am.orig
similarity index 100%
copy from src/Makefile.am
copy to src/Makefile.am.orig
diff --git a/src/Makefile.in b/src/Makefile.in
index bc95987..d1efbfd 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -227,7 +227,7 @@ sources = ncview.c file.c util.c do_buttons.c \
stringlist.c handle_rc_file.c
AM_CPPFLAGS = -DNCVIEW_LIB_DIR=\"$(pkgdatadir)\" $(PNG_CPPFLAGS) $(UDUNITS2_CPPFLAGS) $(NETCDF_CPPFLAGS)
-AM_CFLAGS = -Wall $(X_CFLAGS)
+AM_CFLAGS = $(X_CFLAGS)
AM_LDFLAGS = $(PNG_LDFLAGS) $(UDUNITS2_LDFLAGS) $(NETCDF_LDFLAGS) $(X_PRE_LIBS) $(X_LIBS) $(X11_LIBS) $(X_EXTRA_LIBS) $(RPATH_FLAGS)
all: all-am
diff --git a/src/do_buttons.c b/src/do_buttons.c
index ab7cdf6..219bf9d 100644
--- a/src/do_buttons.c
+++ b/src/do_buttons.c
@@ -92,7 +92,7 @@ do_rewind( int modifier )
in_timer_clear();
if( modifier == MOD_2 ) {
- change_view( -10, PERCENT );
+ change_view( -10, FRAMES );
in_timer_set( (XtTimerCallbackProc)do_rewind, (XtPointer)(MOD_2), delay_millisec );
}
else
@@ -157,7 +157,7 @@ do_fastforward( int modifier )
delay_millisec = (long)(DELAY_DELTA * options.frame_delay) + DELAY_OFFSET;
if( modifier == MOD_2 ) {
- if( change_view( 10, PERCENT ) == 0 )
+ if( change_view( 10, FRAMES ) == 0 )
in_timer_set( (XtTimerCallbackProc)do_fastforward, (XtPointer)(MOD_2), delay_millisec );
}
else
@@ -229,27 +229,29 @@ do_set_maximum( int modifier )
void
do_blowup( int modifier )
{
+ int view_var_is_valid = TRUE;
+
if( modifier == MOD_3 )
- view_change_blowup( -1, TRUE );
+ view_change_blowup( -1, TRUE, view_var_is_valid );
else if( modifier == MOD_2 ) {
/* Double the current blowup -- make image BIGGER */
if( options.blowup > 0 )
- view_change_blowup( options.blowup, TRUE );
+ view_change_blowup( options.blowup, TRUE, view_var_is_valid );
else
- view_change_blowup( -(options.blowup)/2, TRUE );
+ view_change_blowup( -(options.blowup)/2, TRUE, view_var_is_valid );
}
else if( modifier == MOD_4 ) {
/* Halve the current blowup -- make image SMALLER */
if( options.blowup > 0 )
- view_change_blowup( -(options.blowup/2), TRUE );
+ view_change_blowup( -(options.blowup/2), TRUE, view_var_is_valid );
else
- view_change_blowup( options.blowup, TRUE );
+ view_change_blowup( options.blowup, TRUE, view_var_is_valid );
}
else
- view_change_blowup( 1, TRUE );
+ view_change_blowup( 1, TRUE, view_var_is_valid );
/* If we are shrinking magnification, then try re-saving
* the frames because now there might be enough room.
diff --git a/src/file_netcdf.c b/src/file_netcdf.c
index 7b20ada..6c29ea4 100644
--- a/src/file_netcdf.c
+++ b/src/file_netcdf.c
@@ -40,6 +40,10 @@ void warn_about_char_dims();
int safe_ncdimid( int fileid, char *dim_name1 );
int netcdf_dimvar_id( int fileid, char *dim_name );
int netcdf_get_att_util( int id, int varid, char *var_name, char *att_name, int expected_len, void *value );
+int nc_inq_varid_grp( int ncid, char *varname, int *varid, int *groupid );
+void varname_no_groups( char *varname, char *varname_sans_groups );
+char *ncview_groupname( int gid );
+char *ncview_varname( int gid, int varid );
char *nc_type_to_string( nc_type type );
@@ -108,26 +112,62 @@ int netcdf_fi_recdim_id( int fileid )
err = nc_inq( fileid, &n_dims, &n_vars, &n_gatts, &rec_dim );
if( err != NC_NOERR ) {
- fprintf( stderr, "netcdf_fi_list_vars: error on nc_inq, cdfid=%d\n", fileid );
+ fprintf( stderr, "netcdf_fi_recdim_id: error on nc_inq, cdfid=%d\n", fileid );
exit( -1 );
}
return( rec_dim );
}
-/*******************************************************************************************/
-Stringlist *netcdf_fi_list_vars( int fileid )
+/*******************************************************************************************
+ * NOTE that netcdf returns names starting with slashes, while I do not. So, I strip
+ * the leading slash from returned names.
+ */
+void ncdf_fi_name_of_group( int ncid, char **name, int full_path )
{
- int n_vars, err, i, jj, n_dims, n_var_dims, eff_ndims;
- char *var_name;
- Stringlist *ret_val, *dimlist;
- int n_gatts, rec_dim;
- size_t *size, total_size;
+ int ierr;
+ size_t nchar, dummy;
+
+ ierr = nc_inq_grpname_len( ncid, &nchar ); /* According to docs, ALWAYS returns len of full path */
+ if( ierr != NC_NOERR ) {
+ fprintf( stderr, "Error getting grpname length from file for ncid=%d: %s\n",
+ ncid, nc_strerror(ierr) );
+ exit(-1);
+ }
- ret_val = NULL;
+ *name = (char *)malloc( sizeof(char) * (nchar+2) ); /* add space for trailing NULL */
- err = nc_inq( fileid, &n_dims, &n_vars, &n_gatts, &rec_dim );
+ if( full_path == 0 )
+ ierr = nc_inq_grpname( ncid, *name );
+ else
+ ierr = nc_inq_grpname_full( ncid, &dummy, *name );
+
+ /* Get rid of leading slash */
+ if( (*name)[0] == '/' )
+ (*name)++;
+
+ if( ierr != NC_NOERR ) {
+ fprintf( stderr, "Error getting grpname from file for ncid=%d: %s\n",
+ ncid, nc_strerror(ierr) );
+ exit(-1);
+ }
+}
+
+/*******************************************************************************************
+ * Returns list of ONLY displayable vars in the passed group. The list of displayable vars
+ * is appended to ret_val, which might already have some displayable vars from different
+ * groups in it.
+ */
+void netcdf_fi_list_vars_inner( Stringlist **ret_val, int gid, char *groupname )
+{
+ int n_vars, err, i, jj, kk, n_dims, n_var_dims, eff_ndims;
+ char *var_name, *grp_var_name;
+ Stringlist *dimlist;
+ int n_gatts, rec_dim, n_groups;
+ size_t *size, total_size;
+
+ err = nc_inq( gid, &n_dims, &n_vars, &n_gatts, &rec_dim );
if( err != NC_NOERR ) {
- fprintf( stderr, "netcdf_fi_list_vars: error on ncinqire, cdfid=%d\n", fileid );
+ fprintf( stderr, "netcdf_fi_list_vars: error on ncinqire, cdfid=%d\n", gid );
exit( -1 );
}
@@ -135,15 +175,31 @@ Stringlist *netcdf_fi_list_vars( int fileid )
* as a displayable variable. At present, we require: 1) that the
* variable have at least 1 scannable dimensions. 2) It shouldn't
* be a "dimension variable"; i.e., there should be no dimension
- * with the same name as this variable. 3) It's total size should
+ * with the same name as this variable. 3) Its total size should
* be > 1.
*/
for( i=0; i<n_vars; i++ ) {
- var_name = netcdf_varindex_to_name( fileid, i );
- if( netcdf_dim_name_to_id( fileid, var_name, var_name ) == -1 ){
+ var_name = netcdf_varindex_to_name( gid, i );
+
+ /* Prepend group name */
+ grp_var_name = (char *)malloc( sizeof(char) * (strlen(var_name) + strlen(groupname) + 10) );
+ grp_var_name[0] = '\0';
+ if( (strlen(groupname) == 0) || ((strlen(groupname) == 1) && (groupname[0] == '/' )))
+ strcpy( grp_var_name, var_name );
+ else
+ {
+ strcat( grp_var_name, groupname );
+ strcat( grp_var_name, "/" );
+ strcat( grp_var_name, var_name );
+ }
+
+ if( options.debug ) printf( "netcdf_fi_list_vars_inner: checking to see if a displayable var: >%s<\n",
+ grp_var_name );
+
+ if( netcdf_dim_name_to_id( gid, var_name, var_name ) == -1 ){
/* then it's NOT a dimension variable */
- size = netcdf_fi_var_size( fileid, var_name );
- n_var_dims = netcdf_fi_n_dims( fileid, var_name );
+ size = netcdf_fi_var_size( gid, var_name );
+ n_var_dims = netcdf_fi_n_dims( gid, var_name );
total_size = 1L;
eff_ndims = 0;
for(jj=0; jj<n_var_dims; jj++ ) {
@@ -151,45 +207,118 @@ Stringlist *netcdf_fi_list_vars( int fileid )
if( *(size+jj) > 1 )
eff_ndims++;
}
- dimlist = fi_scannable_dims( fileid, var_name );
- if( (total_size > 1L) && (stringlist_len( dimlist ) >= 1))
+ dimlist = fi_scannable_dims( gid, var_name );
+ if( (total_size > 1L) && (stringlist_len( dimlist ) >= 1)) {
/* Hack to make version 1.70+ emulate older versions
* that did not display 1-d vars.
*/
- if( ! (options.no_1d_vars && (eff_ndims == 1) ))
- stringlist_add_string( &ret_val, var_name, NULL, SLTYPE_NULL );
+ if( ! (options.no_1d_vars && (eff_ndims == 1) )) {
+ if( options.debug ) {
+ printf( "netcdf_fi_list_vars_inner: YES, is a displayable var: >%s< ndims=%d sizes=",
+ grp_var_name, n_var_dims );
+ for( kk=0; kk<n_var_dims; kk++ )
+ printf( "%ld ", size[kk] );
+ printf( "\n" );
+ }
+ stringlist_add_string( ret_val, grp_var_name, NULL, SLTYPE_NULL );
+ }
+ }
+ else
+ if( options.debug ) printf( "netcdf_fi_list_vars_inner: NO, is size 1 so not displayable: >%s<\n",
+ grp_var_name );
+
}
+ else
+ if( options.debug ) printf( "netcdf_fi_list_vars_inner: NO, is a dim so not displayable: >%s<\n",
+ grp_var_name );
}
-
- return( ret_val );
+}
+
+/*******************************************************************************************/
+void netcdf_fi_list_vars_v4( Stringlist **retval, int fileid )
+{
+ char *groupname;
+ int i, *grp_id, err, n_groups, full_path;
+
+
+ /* Get name of this group
+ */
+ full_path = 1;
+ ncdf_fi_name_of_group( fileid, &groupname, full_path );
+
+ netcdf_fi_list_vars_inner( retval, fileid, groupname );
+
+ /* Get number of groups in this group
+ */
+ err = nc_inq_grps( fileid, &n_groups, NULL);
+ if( err != NC_NOERR ) {
+ fprintf( stderr, "netcdf_fi_list_vars: error on nc_inq_grps, cdfid=%d: %s\n",
+ fileid, nc_strerror(err) );
+ exit( -1 );
+ }
+
+ /* Get group IDs
+ */
+ grp_id = (int *)malloc( sizeof(int) * n_groups );
+ err = nc_inq_grps( fileid, &n_groups, grp_id );
+ for( i=0; i<n_groups; i++ ) {
+ netcdf_fi_list_vars_v4( retval, grp_id[i] );
+ }
+
+ free( grp_id );
+
+}
+
+/*******************************************************************************************
+ * This provides the same interface for the requirements of groups introduced
+ * in netcdf library version 4
+ */
+Stringlist *netcdf_fi_list_vars( int fileid )
+{
+ Stringlist *retval = NULL;
+
+ if( options.debug ) printf( "netcdf_fi_list_vars: entering for file %d\n", fileid );
+
+ netcdf_fi_list_vars_v4( &retval, fileid );
+
+ if( options.debug ) {
+ printf( "netcdf_fi_list_vars: exiting with list of DISPLAYABLE vars in this file:\n" );
+ stringlist_dump( retval );
+ }
+
+ return( retval );
}
/*******************************************************************************************/
Stringlist *netcdf_scannable_dims( int fileid, char *var_name )
{
- int var_id, n_dims, i, err;
+ int var_id, n_dims, i, err, gid;
char *dim_name;
size_t dim_size;
Stringlist *dimlist = NULL;
int n_atts, dim[MAX_VAR_DIMS];
nc_type var_type;
+ char var_name_ng[MAX_NC_NAME];
dim_name = (char *)malloc( MAX_NC_NAME ); /* defined in netcdf.h */
- err = nc_inq_varid( fileid, var_name, &var_id );
+ err = nc_inq_varid_grp( fileid, var_name, &var_id, &gid );
if( err != NC_NOERR ) {
fprintf( stderr, "Error in netcdf_scannable_dims: could not find var named \"%s\" in file!\n",
var_name );
exit(-1);
}
- err = nc_inq_var( fileid, var_id, var_name, &var_type, &n_dims, dim, &n_atts );
+
+ varname_no_groups( var_name, var_name_ng );
+
+ err = nc_inq_var( gid, var_id, var_name_ng, &var_type, &n_dims, dim, &n_atts );
if( err != NC_NOERR ) {
fprintf( stderr, "netcdf_scannable_dims: Error on nc_inq_var call for var %s\n", var_name );
exit(-1);
}
for( i=0; i<n_dims; i++ ) {
- err = nc_inq_dim( fileid, *(dim+i), dim_name, &dim_size );
+ err = nc_inq_dim( gid, *(dim+i), dim_name, &dim_size );
if( err < 0 ) {
fprintf( stderr, "ncview: netcdf_scannable_dims: ");
fprintf( stderr, "error on nc_inq_dim call\n" );
@@ -212,20 +341,27 @@ Stringlist *netcdf_scannable_dims( int fileid, char *var_name )
return( dimlist );
}
-/*******************************************************************************************/
+/*******************************************************************************************
+ * On input, var_name might have prepended group names of the form "group0/group1/varname"
+ */
int netcdf_fi_n_dims( int fileid, char *var_name )
{
- int n_dims, err, varid;
+ int n_dims, err, varid, groupid;
int n_atts, dim[MAX_VAR_DIMS];
+ char var_name_nogroups[MAX_NC_NAME];
nc_type var_type;
- err = nc_inq_varid( fileid, var_name, &varid );
+ err = nc_inq_varid_grp( fileid, var_name, &varid, &groupid );
if( err != NC_NOERR ) {
fprintf( stderr, "Error in netcdf_fi_n_dims: could not find var named \"%s\" in file!\n",
var_name );
exit(-1);
}
- err = nc_inq_var( fileid, varid, var_name, &var_type, &n_dims, dim, &n_atts );
+
+ /* Strip off leading group names */
+ varname_no_groups( var_name, var_name_nogroups );
+
+ err = nc_inq_var( groupid, varid, var_name_nogroups, &var_type, &n_dims, dim, &n_atts );
if( err != NC_NOERR ) {
fprintf( stderr, "netcdf_fi_n_dims: error on nc_inq_var\n" );
fprintf( stderr, "netcdfid=%d, var_name=%s\n",
@@ -249,25 +385,35 @@ size_t netcdf_dim_size( fileid, dimid )
return( ret_val );
}
-/*******************************************************************************************/
+/*******************************************************************************************
+ * On input, var_name might have prepended group names of the form "group0/group1/varname"
+ */
size_t * netcdf_fi_var_size( int fileid, char *var_name )
{
- int n_dims, varid, err, i;
+ int n_dims, varid, err, i, groupid;
size_t *ret_val, dim_size;
- int n_atts, dim[MAX_VAR_DIMS];
+ int n_atts, dim[MAX_VAR_DIMS], debug;
+ char var_name_nogroups[MAX_NC_NAME];
nc_type var_type;
+ debug = 0;
+
+ if( debug==1 ) printf( "netcdf_fi_var_size: entering for fileid=%d varname=>%s<\n", fileid, var_name );
+
n_dims = netcdf_fi_n_dims( fileid, var_name );
ret_val = (size_t *)malloc( n_dims * sizeof(size_t) );
- err = nc_inq_varid( fileid, var_name, &varid );
+ err = nc_inq_varid_grp( fileid, var_name, &varid, &groupid );
if( err != NC_NOERR ) {
fprintf( stderr, "Error in netcdf_fi_var_size: could not find var named \"%s\" in file!\n",
var_name );
exit(-1);
}
- err = nc_inq_var( fileid, varid, var_name, &var_type, &n_dims, dim, &n_atts );
+ /* Strip off leading group names */
+ varname_no_groups( var_name, var_name_nogroups );
+
+ err = nc_inq_var( groupid, varid, var_name_nogroups, &var_type, &n_dims, dim, &n_atts );
if( err != NC_NOERR ) {
fprintf( stderr, "netcdf_fi_var_size: error on nc_inq_var\n" );
fprintf( stderr, "netcdfid=%d, var_name=%s\n",
@@ -275,9 +421,11 @@ size_t * netcdf_fi_var_size( int fileid, char *var_name )
exit( -1 );
}
+ if( debug==1 ) printf( "netcdf_fi_var_size: here are dim sizes:\n" );
for( i=0; i<n_dims; i++ ) {
- err = nc_inq_dimlen( fileid, *(dim+i), &dim_size );
+ err = nc_inq_dimlen( groupid, *(dim+i), &dim_size );
*(ret_val+i) = dim_size;
+ if( debug==1 ) printf( "dim=%d size=%ld\n", i, dim_size );
}
return( ret_val );
@@ -286,24 +434,27 @@ size_t * netcdf_fi_var_size( int fileid, char *var_name )
/*******************************************************************************************/
char *netcdf_dim_id_to_name( int fileid, char *var_name, int dim_id )
{
- int netcdf_dim_id, netcdf_var_id;
+ int netcdf_dim_id, netcdf_var_id, gid;
int n_dims, *dim, err, n_atts;
- char *dim_name;
+ char *dim_name, var_name_ng[MAX_NC_NAME];
nc_type var_type;
/* see notes under "netcdf_dim_name_to_id". "dim_id" is NOT
* the netCDF dimension ID, it is the entry into the size array
* for the passed variable.
*/
- err = nc_inq_varid( fileid, var_name, &netcdf_var_id );
+ err = nc_inq_varid_grp( fileid, var_name, &netcdf_var_id, &gid );
if( err != NC_NOERR ) {
fprintf( stderr, "Error in netcdf_dim_id_to_name: could not find var named \"%s\" in file!\n",
var_name );
exit(-1);
}
- n_dims = fi_n_dims( fileid, var_name );
- dim = (int *)malloc( n_dims * sizeof( int ));
- err = nc_inq_var( fileid, netcdf_var_id, var_name, &var_type,
+
+ varname_no_groups( var_name, var_name_ng );
+
+ n_dims = fi_n_dims( gid, var_name_ng );
+ dim = (int *)malloc( n_dims * sizeof( int ));
+ err = nc_inq_var( gid, netcdf_var_id, var_name_ng, &var_type,
&n_dims, dim, &n_atts );
if( err != NC_NOERR ) {
fprintf( stderr, "ncview: netcdf_dim_id_to_name: error on ");
@@ -313,7 +464,7 @@ char *netcdf_dim_id_to_name( int fileid, char *var_name, int dim_id )
netcdf_dim_id = *(dim+dim_id);
dim_name = (char *)malloc( MAX_NC_NAME ); /* defined in netcdf.h */
- err = nc_inq_dimname( fileid, netcdf_dim_id, dim_name );
+ err = nc_inq_dimname( gid, netcdf_dim_id, dim_name );
if( err != NC_NOERR ) {
fprintf( stderr, "ncview: netcdf_dim_id_to_name: error on ");
fprintf( stderr, "nc_inq_dimname call. Variable=%s\n", var_name );
@@ -322,11 +473,19 @@ char *netcdf_dim_id_to_name( int fileid, char *var_name, int dim_id )
return( dim_name );
}
-/*******************************************************************************************/
+/*******************************************************************************************
+ * On entry var_name could be something like "group0/group1/varname"
+ */
int netcdf_dim_name_to_id( int fileid, char *var_name, char *dim_name )
{
- int netcdf_dim_id, netcdf_var_id, n_dims, *dim, err, i, n_atts;
+ int netcdf_dim_id, netcdf_var_id, n_dims, *dim, err, i, n_atts, gid, debug;
nc_type var_type;
+ char var_name_ng[MAX_NC_NAME];
+
+ debug = 0;
+
+ if( debug == 1 ) printf( "netcdf_dim_name_to_id: entering with fileid=%d var_name=%s dim_name=%s\n",
+ fileid, var_name, dim_name );
/* It is important to note that this routine does NOT return
* the dimension ID of the passed dimension. That concept is
@@ -338,19 +497,37 @@ int netcdf_dim_name_to_id( int fileid, char *var_name, char *dim_name )
* in the requested variable.
*/
- netcdf_dim_id = safe_ncdimid( fileid, dim_name );
- if( netcdf_dim_id == -1 )
- return( -1 );
- err = nc_inq_varid( fileid, var_name, &netcdf_var_id );
+ err = nc_inq_varid_grp( fileid, var_name, &netcdf_var_id, &gid );
if( err != NC_NOERR ) {
fprintf( stderr, "Error in netcdf_dim_name_to_id: could not find var named \"%s\" in file!\n",
var_name );
exit(-1);
}
+ if( debug == 1 ) {
+ printf( "netcdf_dim_name_to_id: nc_inq_varid_grp reported that var >%s< of gid=%d (%s)",
+ var_name,
+ fileid,
+ ncview_groupname(fileid) );
+ printf( " is varid %d of gid=%d (%s), which ACTUALLY has name >%s<\n",
+ netcdf_var_id,
+ gid,
+ ncview_groupname(gid),
+ ncview_varname(gid, netcdf_var_id) );
+ }
+
+ varname_no_groups( var_name, var_name_ng );
+
+ if( debug == 1 ) printf( "netcdf_dim_name_to_id: group_id=%d var_name_no_groups=%s\n",
+ gid, var_name_ng );
+
+ netcdf_dim_id = safe_ncdimid( gid, dim_name );
+ if( debug == 1 ) printf( "netcdf_dim_name_to_id: netcdf_dim_id=%d\n", netcdf_dim_id );
+ if( netcdf_dim_id == -1 )
+ return( -1 );
- n_dims = fi_n_dims( fileid, var_name );
+ n_dims = fi_n_dims( gid, var_name_ng );
dim = (int *)malloc( n_dims * sizeof( int ));
- err = nc_inq_var( fileid, netcdf_var_id, var_name, &var_type,
+ err = nc_inq_var( gid, netcdf_var_id, var_name_ng, &var_type,
&n_dims, dim, &n_atts );
if( err != NC_NOERR ) {
fprintf( stderr, "ncview: netcdf_dim_name_to_id: error on ");
@@ -366,25 +543,39 @@ int netcdf_dim_name_to_id( int fileid, char *var_name, char *dim_name )
return( -1 );
}
-/*******************************************************************************************/
+/*******************************************************************************************
+ * On entry var_name could be something like "group0/group1/varname"
+ */
void netcdf_fi_get_data( int fileid, char *var_name, size_t *start_pos,
size_t *count, float *data, NetCDFOptions *aux_data )
{
- int i, err, varid;
+ int i, err, varid, gid, debug;
+ char var_name_ng[MAX_NC_NAME];
size_t tot_size, n_dims;
- tot_size = 1L;
- n_dims = netcdf_fi_n_dims( fileid, var_name );
- for( i=0; i<n_dims; i++ )
- tot_size *= *(count+i);
+ debug = 0;
- err = nc_inq_varid( fileid, var_name, &varid );
+ if( debug==1 ) printf( "netcdf_fi_get_data: entering for fileid=%d var_name=%s\n",
+ fileid, var_name );
+
+ err = nc_inq_varid_grp( fileid, var_name, &varid, &gid );
if( err != NC_NOERR ) {
fprintf( stderr, "Error in netcdf_fi_get_data: could not find var named \"%s\" in file!\n",
var_name );
exit(-1);
}
+ varname_no_groups( var_name, var_name_ng );
+
+ tot_size = 1L;
+ n_dims = netcdf_fi_n_dims( gid, var_name_ng );
+ if( debug==1 ) printf( "netcdf_fi_get_data: ndims=%ld\n", n_dims );
+ for( i=0; i<n_dims; i++ ) {
+ tot_size *= *(count+i);
+ if( debug==1 ) printf( "start[%d]=%ld count[%d]=%ld\n", i, start_pos[i], i, count[i] );
+ }
+
+
if( options.debug ) {
fprintf( stderr, "About to call nc_get_vara_float on variable %s\n",
var_name );
@@ -393,7 +584,7 @@ void netcdf_fi_get_data( int fileid, char *var_name, size_t *start_pos,
fprintf( stderr, "[%d]: %ld %ld\n", i, *(start_pos+i), *(count+i) );
}
- err = nc_get_vara_float( fileid, varid, start_pos, count, data );
+ err = nc_get_vara_float( gid, varid, start_pos, count, data );
if( err != NC_NOERR ) {
fprintf( stderr, "netcdf_fi_get_data: error on nc_get_vara_float call\n" );
fprintf( stderr, "cdfid=%d variable=%s\n", fileid, var_name );
@@ -478,6 +669,107 @@ void netcdf_fi_close( int fileid )
/* netCDF utility routines. Analogs are not required for each data file format. */
/****************************************************************************************/
+/*******************************************************************************************
+ * Given a varname string of format: groupname0/groupname1/groupnameN/varname
+ * this returns ONLY the trailing groupname
+ */
+void varname_no_groups( char *varname, char *varname_sans_groups )
+{
+ int i, i0, i1, idx_slash[MAX_NC_NAME], nslash;
+ char ts[MAX_NC_NAME];
+
+ /* Get indices of the slashes */
+ nslash = 0;
+ for( i=0; i<strlen(varname); i++ ) {
+ if( varname[i] == '/' ) {
+ idx_slash[nslash] = i;
+ nslash++;
+ }
+ }
+
+ if( nslash == 0 ) {
+ strcpy( varname_sans_groups, varname );
+ return;
+ }
+
+ strcpy( varname_sans_groups, varname+idx_slash[nslash-1]+1 );
+}
+
+/*******************************************************************************************
+ * A version of 'nc_inq_varid' that has been enhanced to return a groupid/varid pair
+ * given a var name of form "groupname/varname" (NOTE: *NO* leading slash!!)
+ */
+int nc_inq_varid_grp( int ncid, char *varname, int *varid, int *groupid )
+{
+ int ns, ig, gid, ierr, group_depth, cur_gid, debug, retval;
+ char groupname[MAX_NC_NAME], varname_sans_groups[MAX_NC_NAME], cur_gid_groupname[MAX_NC_NAME];
+
+ debug = 0;
+
+ if( debug ) printf( "nc_inq_varid_grp: entering with ncid=%d (%s) varname=>%s<\n",
+ ncid, ncview_groupname(ncid), varname );
+
+ if( varname[0] == '/' ) {
+ fprintf( stderr, "Internal error, called nc_inq_varid_grp with a varname that starts with a slash: >%s<\n",
+ varname );
+ exit(-1);
+ }
+
+ ns = count_nslashes( varname );
+ if( debug ) printf( "nc_inq_varid_grp: number of slashes in varname: %d\n", ns );
+
+ if( ns > 0 ) {
+ cur_gid = ncid;
+ group_depth = ns;
+
+ /* Traverse to the LAST group in the chain of groups, that's where
+ * we should find this var.
+ */
+ if( debug ) printf( "nc_inq_varid_grp: traversing to the LAST group of var >%s<\n", varname );
+ for( ig=0; ig<group_depth; ig++ ) {
+
+ ierr = nc_inq_grpname( cur_gid, cur_gid_groupname );
+ if( debug ) printf( "nc_inq_varid_grp: traversing group, cur depth=%d cur root name=>%s<\n",
+ ig, cur_gid_groupname );
+
+ ierr = unpack_groupname( varname, ig, groupname ); /* if ig==0, returns first groupname, etc */
+
+ if( debug ) printf( "nc_inq_varid_grp: looking for subgroup >%s< in root group >%s<\n",
+ groupname, cur_gid_groupname );
+
+ ierr = nc_inq_ncid( cur_gid, groupname, &gid );
+ if( ierr != NC_NOERR ) {
+ fprintf( stderr, "nc_inq_varid_grp: Error, did not find group named >%s< in base group >%s<\n",
+ groupname, cur_gid_groupname );
+ fprintf( stderr, "nc_inq_varid_grp was called with id=%d (%s) varname=>%s<\n", ncid, cur_gid_groupname, varname );
+ exit(-1);
+ return(-1);
+ }
+
+ if( debug ) printf( "nc_inq_varid_grp: group >%s< has groupid %d\n", groupname, gid );
+
+ cur_gid = gid;
+ }
+
+ *groupid = cur_gid;
+ if( debug ) printf( "nc_inq_varid_grp: should now be on the LAST group, here is groupname: >%s<\n", ncview_groupname( cur_gid ));
+
+ varname_no_groups( varname, varname_sans_groups );
+ if( debug ) printf( "nc_inq_varid_grp: calling regular nc_inq_varid with group %d (%s) and varname_sans_gruops >%s<\n",
+ cur_gid, ncview_groupname(cur_gid), varname_sans_groups );
+ retval = nc_inq_varid( cur_gid, varname_sans_groups, varid );
+
+ if( debug ) printf( "nc_inq_varid_grp: final returned gid=%d (%s) varid=%d (which is a var named >%s<)\n",
+ *groupid, ncview_groupname(*groupid), *varid, ncview_varname( *groupid, *varid ) );
+ return( retval );
+ }
+ else
+ {
+ *groupid = ncid;
+ return( nc_inq_varid( ncid, varname, varid ));
+ }
+}
+
/*******************************************************************************************/
/* How many dimensions does this variable have?
*/
@@ -642,25 +934,30 @@ char * netcdf_title( int fileid )
* As a special case, if the attribute exited, but the length of the
* attribute was zero, then it returns a pointer to a char string
* that is a single NULL.
+ *
+ * On input, var_name might be of the form "group0/group1/varname"
+ *
*/
char *netcdf_get_char_att( int fileid, char *var_name, char *att_name )
{
- int varid, err;
+ int varid, err, gid;
size_t name_length;
nc_type type;
- char *ret_val;
+ char *ret_val, var_name_ng[MAX_NC_NAME];
- err = nc_inq_varid( fileid, var_name, &varid );
+ err = nc_inq_varid_grp( fileid, var_name, &varid, &gid );
if( err != NC_NOERR ) {
fprintf( stderr, "Error in netcdf_get_char_att: could not find var named \"%s\" in file!\n",
var_name );
exit(-1);
}
- if( netcdf_att_id( fileid, varid, att_name ) < 0 )
+ varname_no_groups( var_name, var_name_ng );
+
+ if( netcdf_att_id( gid, varid, att_name ) < 0 )
return( NULL );
- err = nc_inq_att( fileid, varid, att_name, &type, &name_length );
+ err = nc_inq_att( gid, varid, att_name, &type, &name_length );
if( (err != NC_NOERR) || (type != NC_CHAR))
return( NULL );
@@ -671,7 +968,7 @@ char *netcdf_get_char_att( int fileid, char *var_name, char *att_name )
return( ret_val );
}
- err = nc_get_att_text( fileid, varid, att_name, ret_val );
+ err = nc_get_att_text( gid, varid, att_name, ret_val );
if( err != NC_NOERR )
return( NULL );
@@ -946,50 +1243,54 @@ nc_type netcdf_dim_value( int fileid, char *dim_name, size_t place,
return( ret_type );
}
-/*******************************************************************************************/
+/*******************************************************************************************
+ * On entry, var_name can be something like "group0/group1/varname"
+ */
void netcdf_fill_aux_data( int id, char *var_name, FDBlist *fdb )
{
- int err, varid, n_dims, dim[MAX_NC_DIMS], n_atts, unlimdimvar_id, recdim_id;
- char dummy_var_name[ MAX_NC_NAME ], unlimdim_name[MAX_NC_NAME];
+ int err, varid, n_dims, dim[MAX_NC_DIMS], n_atts, unlimdimvar_id, recdim_id, gid;
+ char dummy_var_name[ MAX_NC_NAME ], var_name_ng[MAX_NC_NAME], unlimdim_name[MAX_NC_NAME];
nc_type type;
NetCDFOptions *netcdf;
netcdf = (NetCDFOptions *)(fdb->aux_data);
- err = nc_inq_varid( id, var_name, &varid );
+ err = nc_inq_varid_grp( id, var_name, &varid, &gid );
if( err != NC_NOERR ) {
fprintf( stderr, "Error in netcdf_fill_aux_data: could not find var named \"%s\" in file!\n",
var_name );
exit(-1);
}
+ varname_no_groups( var_name, var_name_ng );
+
/* Record the recdim units in this file
*/
- recdim_id = netcdf_fi_recdim_id( id );
+ recdim_id = netcdf_fi_recdim_id( gid );
if( recdim_id == -1 ) {
fdb->recdim_units = NULL;
}
else
{
/* Get NAME of the record dimension */
- err = nc_inq_dimname( id, recdim_id, unlimdim_name );
+ err = nc_inq_dimname( gid, recdim_id, unlimdim_name );
if( err != 0 ) {
fprintf( stderr, "Error in netcdf_fill_aux_data: could not get recdim name\n%s\n",
nc_strerror( err ));
exit(-1);
}
/* See if there is a variable with the same name */
- err = nc_inq_varid( id, unlimdim_name, &unlimdimvar_id );
+ err = nc_inq_varid( gid, unlimdim_name, &unlimdimvar_id );
if( err != 0 )
fdb->recdim_units = NULL;
else
{
/* Get the units for the dimvar. Note: can be NULL */
- fdb->recdim_units = netcdf_var_units( id, unlimdim_name );
+ fdb->recdim_units = netcdf_var_units( gid, unlimdim_name );
}
}
- err = nc_inq_var( id, varid, dummy_var_name, &type, &n_dims, dim, &n_atts );
+ err = nc_inq_var( gid, varid, dummy_var_name, &type, &n_dims, dim, &n_atts );
if( err != NC_NOERR ) {
fprintf( stderr, "netcdf_fill_aux_data: failed on nc_inq_var call!\n" );
exit(-1);
@@ -999,15 +1300,15 @@ void netcdf_fill_aux_data( int id, char *var_name, FDBlist *fdb )
return;
netcdf->valid_range_set =
- netcdf_get_att_util( id, varid, var_name, "valid_range", 2, netcdf->valid_range );
+ netcdf_get_att_util( gid, varid, var_name_ng, "valid_range", 2, netcdf->valid_range );
netcdf->valid_min_set =
- netcdf_get_att_util( id, varid, var_name, "valid_min", 1, &(netcdf->valid_min) );
+ netcdf_get_att_util( gid, varid, var_name_ng, "valid_min", 1, &(netcdf->valid_min) );
netcdf->valid_max_set =
- netcdf_get_att_util( id, varid, var_name, "valid_max", 1, &(netcdf->valid_max) );
+ netcdf_get_att_util( gid, varid, var_name_ng, "valid_max", 1, &(netcdf->valid_max) );
netcdf->add_offset_set =
- netcdf_get_att_util( id, varid, var_name, "add_offset", 1, &(netcdf->add_offset) );
+ netcdf_get_att_util( gid, varid, var_name_ng, "add_offset", 1, &(netcdf->add_offset) );
netcdf->scale_factor_set =
- netcdf_get_att_util( id, varid, var_name, "scale_factor", 1, &(netcdf->scale_factor) );
+ netcdf_get_att_util( gid, varid, var_name_ng, "scale_factor", 1, &(netcdf->scale_factor) );
/* Special case: if we have add_offset and scale_factor attributes,
* then assume they apply to the valid range also. Q: is this
@@ -1246,31 +1547,36 @@ int netcdf_max_option_set( NCVar *var, float *ret_max )
return( max_set );
}
-/*******************************************************************************************/
+/*******************************************************************************************
+ * On entry var_name might be something like "group0/group1/varname"
+ */
void netcdf_fill_value( int file_id, char *var_name, float *v, NetCDFOptions *aux_data )
{
- int err, varid, foundit;
+ int err, varid, foundit, gid;
+ char var_name_ng[MAX_NC_NAME];
if( options.debug )
fprintf( stderr, "Checking %s for a missing value...\n",
var_name );
foundit = FALSE;
- err = nc_inq_varid( file_id, var_name, &varid );
+ err = nc_inq_varid_grp( file_id, var_name, &varid, &gid );
if( err != NC_NOERR ) {
fprintf( stderr, "Error in netcdf_fill_value: could not find var named \"%s\" in file!\n",
var_name );
exit(-1);
}
- if( netcdf_get_att_util( file_id, varid, var_name, "missing_value", 1, v ) ) {
+ varname_no_groups( var_name, var_name_ng );
+
+ if( netcdf_get_att_util( gid, varid, var_name_ng, "missing_value", 1, v ) ) {
if( options.debug )
fprintf( stderr, "found a \"missing_value\" attribute=%g\n",
*v );
foundit = TRUE;
}
- if( netcdf_get_att_util( file_id, varid, var_name, "_FillValue", 1, v ) ) {
+ if( netcdf_get_att_util( gid, varid, var_name_ng, "_FillValue", 1, v ) ) {
if( options.debug )
fprintf( stderr, "found a \"_FillValue\" attribute=%g\n",
*v );
@@ -1278,7 +1584,7 @@ void netcdf_fill_value( int file_id, char *var_name, float *v, NetCDFOptions *au
}
/* Is there a global missing value? */
- if( netcdf_get_att_util( file_id, NC_GLOBAL, var_name, "missing_value", 1, v ) ) {
+ if( netcdf_get_att_util( gid, NC_GLOBAL, var_name_ng, "missing_value", 1, v ) ) {
if( options.debug )
fprintf( stderr, "found a \"missing_value\" attribute=%g\n",
*v );
@@ -1345,23 +1651,53 @@ int safe_ncvarid( int fileid, char *varname )
*/
int safe_ncdimid( int fileid, char *dim_name1 )
{
- int n_vars, err, i, n_dims;
+ int n_vars, err, i, n_dims, *dimids, include_parents;
char dim_name2[MAX_NC_NAME];
- int n_gatts, rec_dim;
+ int n_gatts, rec_dim, debug;
size_t dim_size;
- err = nc_inq( fileid, &n_dims, &n_vars, &n_gatts, &rec_dim );
+ debug = 0;
+
+ if( debug == 1 ) printf( "safe_ncdimid: entering with fileid=%d (group %s) dim_name=%s\n",
+ fileid, ncview_groupname(fileid), dim_name1 );
+
+ /* Find how many dims there are available, make space
+ * for their dimids, read them in
+ */
+ include_parents = 1;
+ err = nc_inq_dimids( fileid, &n_dims, NULL, include_parents );
if( err != NC_NOERR ) {
- fprintf( stderr, "ncview: safe_ncdimid: error in nc_inq call\n" );
- exit( -1 );
+ fprintf( stderr, "safe_ncdimid: error on call to nc_inq_dimids (1): %s\n",
+ nc_strerror(err) );
+ exit(-1);
+ }
+ if( debug == 1 ) printf( "safe_ncdimid: n_dims=%d\n", n_dims );
+
+ dimids = (int *)malloc( sizeof(int) * n_dims );
+ err = nc_inq_dimids( fileid, &n_dims, dimids, include_parents );
+ if( err != NC_NOERR ) {
+ fprintf( stderr, "safe_ncdimid: error on call to nc_inq_dimids (2): %s\n",
+ nc_strerror(err) );
+ exit(-1);
}
for( i=0; i<n_dims; i++ ) {
- err = nc_inq_dim( fileid, i, dim_name2, &dim_size );
- if( strcmp( dim_name1, dim_name2 ) == 0 )
- return( i );
+ err = nc_inq_dim( fileid, dimids[i], dim_name2, &dim_size );
+ if( err != 0 ) {
+ fprintf( stderr, "safe_ncdimid: Error, call to nc_inq_dim returned: %s\n",
+ nc_strerror( err ));
+ fprintf( stderr, "Called with ncid=%d dimid=%d\n", fileid, i );
+ exit(-1);
+ }
+ if( debug == 1 ) printf( "safe_ncdimid: dim #%d (dimid %d) is named >%s<\n",
+ i, dimids[i], dim_name2 );
+ if( strcmp( dim_name1, dim_name2 ) == 0 ) {
+ if( debug==1 ) printf( "safe_ncdimid found match in dim %d: returning that value\n", dimids[i] );
+ return( dimids[i] );
+ }
}
+ if( debug==1 ) printf( "safe_ncdimid: no matches, returning -1\n" );
return( -1 );
}
@@ -1631,3 +1967,29 @@ int netcdf_dimvar_bounds_id( int fileid, char *dim_name, int *nvertices )
return( bounds_dimvar_id );
}
+/*****************************************************************************************************
+ * Returns a pointer to a static buffer with the group name; useful for debugging & info printouts
+ */
+char *ncview_groupname( int gid )
+{
+ static char buffer[MAX_NC_NAME];
+ int ierr;
+ size_t tlen;
+
+ ierr = nc_inq_grpname_full( gid, &tlen, buffer );
+ return( &(buffer[0]) );
+}
+
+/*****************************************************************************************************
+ * Returns a pointer to a static buffer with the var name; useful for debugging & info printouts
+ */
+char *ncview_varname( int gid, int varid )
+{
+ static char buffer[MAX_NC_NAME];
+ int ierr;
+ size_t tlen;
+
+ ierr = nc_inq_varname( gid, varid, buffer );
+ return( &(buffer[0]) );
+}
+
diff --git a/src/interface/x_interface.c b/src/interface/'
similarity index 95%
copy from src/interface/x_interface.c
copy to src/interface/'
index 5dcb0b2..7eeb35a 100644
--- a/src/interface/x_interface.c
+++ b/src/interface/'
@@ -192,6 +192,9 @@ static Widget
print_button_widget,
colorbar_form_widget,
colorbar_widget,
+ groupsel_form_widget,
+ grouplist_label_widget,
+ *grouplist_widget,
varsel_form_widget,
*var_selection_widget, /* the boxes with N vars per box */
varlist_label_widget,
@@ -440,6 +443,7 @@ void do_set_min_from_curdata(Widget w, XButtonEvent *e, String *p, Cardinal *n
void do_set_max_from_curdata(Widget w, XButtonEvent *e, String *p, Cardinal *n );
void expose_ccontour();
void expose_colorbar();
+void x_init_widgets_groupsel( Widget parent );
void testf(Widget w, XButtonEvent *e, String *p, Cardinal *n );
@@ -1501,6 +1505,143 @@ void x_init_widgets_varsel( Widget parent )
}
/*************************************************************************************************/
+void x_init_widgets_groupsel( Widget parent )
+{
+ int n_groups, n_groupsel_boxes, which_box, i, state;
+ NCVar *var;
+ char widget_name[128];
+ Widget w;
+ Pixel col2set;
+ Stringlist *group_list, *cursor;
+
+ /* Get list of known groups */
+ group_list = get_group_list( variables );
+
+ /* Arrange the groups in boxes, n_vars_per_row variables to a box */
+ n_groups = n_strings_in_list( group_list );
+ n_groupsel_boxes = n_groups / app_data.n_vars_per_row + 5;
+ group_selection_widget = (Widget *)malloc( n_groupsel_boxes*sizeof( Widget ));
+
+ /* Make an array of widgets for the variables; indicate the end of the
+ * array by a NULL value.
+ */
+ grouplist_widget = (Widget *)malloc( (n_groups+1)*sizeof(Widget));
+ if( grouplist_widget == NULL ) {
+ fprintf( stderr, "ncview: x_init_widgets: malloc ");
+ fprintf( stderr, "failed on grouplist_widget initializeation\n" );
+ exit( -1 );
+ }
+ *(grouplist_widget+n_groups) = NULL;
+
+ cursor = group_list;
+ which_box = 0;
+ while( cursor != NULL ) {
+ if( i == 0 ) {
+ /* The very first button box! */
+ snprintf( widget_name, 127, "groupselbox_%1d", which_box+1 );
+ *(group_selection_widget+which_box) = XtVaCreateManagedWidget(
+ widget_name,
+ boxWidgetClass,
+ parent,
+ XtNorientation, XtorientHorizontal,
+ XtNborderWidth, 0,
+ NULL);
+ snprintf( widget_name, 127, "grouplist_label_%1d", which_box+1 );
+ grouplist_label_widget = XtVaCreateManagedWidget(
+ widget_name,
+ labelWidgetClass,
+ *(group_selection_widget+which_box),
+ XtNwidth, app_data.button_width,
+ XtNlabel, "Group:",
+ XtNborderWidth, 0,
+ NULL );
+ which_box++;
+ }
+ else if( (i % app_data.n_vars_per_row) == 0 ) {
+ /* A new button box! */
+ snprintf( widget_name, 127, "box_%1d", which_box+1 );
+ *(var_selection_widget+which_box) = XtVaCreateManagedWidget(
+ widget_name,
+ boxWidgetClass,
+ parent,
+ XtNorientation, XtorientHorizontal,
+ XtNborderWidth, 0,
+ XtNfromVert, *(var_selection_widget + which_box - 1),
+ NULL);
+ snprintf( widget_name, 127, "varlist_label_%1d", which_box+1 );
+ varlist_label_widget = XtVaCreateManagedWidget(
+ widget_name,
+ labelWidgetClass,
+ *(var_selection_widget+which_box),
+ XtNwidth, app_data.button_width,
+ XtNborderWidth, 0,
+ XtNlabel, "",
+ NULL );
+ which_box++;
+ }
+
+ snprintf( widget_name, 127, "varsel_%s", var->name );
+ state = False;
+ if( i == 0 ) /* first variable button */
+ *(varlist_widget+i) = XtVaCreateManagedWidget(
+ widget_name,
+ toggleWidgetClass,
+ *(var_selection_widget+which_box-1),
+ XtNstate, state,
+ XtNlabel, var->name,
+ XtNsensitive, True,
+ XtNwidth, app_data.varlabel_width,
+ NULL );
+ else
+ *(varlist_widget+i) = XtVaCreateManagedWidget(
+ widget_name,
+ toggleWidgetClass,
+ *(var_selection_widget+which_box-1),
+ XtNradioGroup, *varlist_widget,
+ XtNstate, state,
+ XtNlabel, var->name,
+ XtNsensitive, True,
+ XtNwidth, app_data.varlabel_width,
+ NULL );
+ if( (n_vars > 1) && app_data.var_colors && options.color_by_ndims ) {
+ switch( var->effective_dimensionality ) {
+ case 1:
+ col2set = app_data.foreground1d;
+ break;
+ case 2:
+ col2set = app_data.foreground2d;
+ break;
+ case 3:
+ col2set = app_data.foreground3d;
+ break;
+ case 4:
+ col2set = app_data.foreground4d;
+ break;
+ case 5:
+ default:
+ col2set = app_data.foreground5d;
+ break;
+ }
+ XtVaSetValues( *(varlist_widget+i),
+ XtNforeground, col2set, NULL );
+ }
+ var = var->next;
+ }
+
+ /* In the degenerate case of only one variable, must make it a radio
+ * group by itself; can't do it above, because it needs to know its
+ * own widget number before it can be done.
+ */
+ if( n_vars == 1 )
+ XtVaSetValues( *varlist_widget, XtNradioGroup,
+ *varlist_widget, NULL );
+
+ i = 0;
+ while( (w = *(varlist_widget + i++)) != NULL )
+ XtAddCallback( w, XtNcallback, varlist_mod1, NULL );
+}
+
+/*************************************************************************************************/
void x_init_widgets_dimlabels( Widget parent )
{
labels_row_widget = XtVaCreateManagedWidget(
@@ -1626,12 +1767,43 @@ void x_init_widgets( Widget top )
XtAddEventHandler( colorbar_widget, ExposureMask, FALSE,
(XtEventHandler)expose_colorbar, NULL );
- varsel_form_widget = XtVaCreateManagedWidget(
- "varselectform",
- formWidgetClass,
- commandcanvas_widget,
- XtNfromVert, colorbar_form_widget,
- NULL);
+ if( options.enable_group_sel ) {
+ groupsel_form_widget = XtVaCreateManagedWidget(
+ "groupselectform",
+ formWidgetClass,
+ commandcanvas_widget,
+ XtNfromVert, colorbar_form_widget,
+ NULL);
+
+ grouplist_label_widget = XtVaCreateManagedWidget(
+ "grouplist_label_widget",
+ labelWidgetClass,
+ groupsel_form_widget,
+ XtNwidth, app_data.button_width,
+ XtNlabel, "Group:",
+ XtNborderWidth, 0,
+ NULL );
+
+ /* the widgets that allow the user to select the group to display */
+ x_init_widgets_groupsel( groupsel_form_widget );
+
+ /* Only diff between this and varsel_form_widget create call
+ * below is what widget this widget is vertically from
+ */
+ varsel_form_widget = XtVaCreateManagedWidget(
+ "varselectform",
+ formWidgetClass,
+ commandcanvas_widget,
+ XtNfromVert, groupsel_form_widget,
+ NULL);
+ }
+ else
+ varsel_form_widget = XtVaCreateManagedWidget(
+ "varselectform",
+ formWidgetClass,
+ commandcanvas_widget,
+ XtNfromVert, colorbar_form_widget,
+ NULL);
/* the widgets that allow the user to select the variable to display */
x_init_widgets_varsel( varsel_form_widget );
diff --git a/src/interface/filesel.c b/src/interface/filesel.c
index 2236591..936bb00 100644
--- a/src/interface/filesel.c
+++ b/src/interface/filesel.c
@@ -227,6 +227,7 @@ fs_double_click(Widget w, XButtonEvent *e, String *p, Cardinal *n )
{
XawListReturnStruct *highlited_entry;
Stringlist *files_and_dirs;
+ int ierr;
highlited_entry = XawListShowCurrent( w );
if( highlited_entry->list_index == XAW_LIST_NONE )
@@ -237,7 +238,7 @@ fs_double_click(Widget w, XButtonEvent *e, String *p, Cardinal *n )
* that we select this file.
*/
if( fs_is_a_directory( highlited_entry->string )) {
- chdir( highlited_entry->string );
+ ierr = chdir( highlited_entry->string );
fs_get_file_dir_list( &files_and_dirs );
XawListChange( fs_list_widget,
stringlist_to_Xawlist( files_and_dirs ),
@@ -272,7 +273,7 @@ fs_popup_callback( Widget widget, XtPointer client_data, XtPointer call_data)
int
file_select( char **filename, char *init_dir )
{
- int retval;
+ int retval, ierr;
Stringlist *files_and_dirs;
char *tstr, orig_dir[1024];
@@ -284,12 +285,12 @@ file_select( char **filename, char *init_dir )
return(MESSAGE_CANCEL);
}
- chdir( init_dir );
+ ierr = chdir( init_dir );
fs_get_file_dir_list( &files_and_dirs );
retval = fs_popup( files_and_dirs );
- chdir( orig_dir );
+ ierr = chdir( orig_dir );
/* Get the final selected filename if not MESSAGE_CANCEL */
if( retval != MESSAGE_CANCEL ) {
@@ -379,9 +380,10 @@ fs_is_a_directory( char *name )
static char *
fs_cwd()
{
+ char *s;
static char buf[2048];
- getcwd( buf, 2048 );
+ s = getcwd( buf, 2048 );
return( buf );
}
diff --git a/src/interface/x_interface.c b/src/interface/x_interface.c
index 5dcb0b2..73488f3 100644
--- a/src/interface/x_interface.c
+++ b/src/interface/x_interface.c
@@ -1252,15 +1252,22 @@ void x_sort_vars_by_ndims( NCVar *v, long **vl_1d, int *n_1d, long **vl_2d, int
/*************************************************************************************************/
void x_init_widgets_varsel_menu_inner( Widget parent, long *varlist, int nv, char *tag, Widget *var_menu_2use,
- Widget *list_of_sel_widgets )
+ Widget *list_of_sel_widgets, int discard_grpname )
{
char temp[1024], widget_name[1024], var_menu_name[1024];
NCVar *cursor;
int i_cursor, i;
- snprintf( temp, 1020, "(%d) %s vars", nv, tag );
+ strcpy( temp, tag );
snprintf( var_menu_name, 1020, "var_menu_%s", tag );
+ /* For some reason not clear to me, if a widget name has a period in it, the
+ * X windows system cannot find that widget ???
+ */
+ for( i=0; i<strlen(var_menu_name); i++ )
+ if( var_menu_name[i] == '.' )
+ var_menu_name[i] = '_';
+
varsel_menu_widget = XtVaCreateManagedWidget(
"varsel_menu",
menuButtonWidgetClass,
@@ -1282,7 +1289,10 @@ void x_init_widgets_varsel_menu_inner( Widget parent, long *varlist, int nv, cha
cursor = cursor->next;
i_cursor++;
}
- snprintf( widget_name, 1020, "%s", cursor->name );
+ if( discard_grpname )
+ unpack_groupname( cursor->name, -2, widget_name );
+ else
+ snprintf( widget_name, 1020, "%s", cursor->name );
list_of_sel_widgets[i] = XtVaCreateManagedWidget(
widget_name,
smeBSBObjectClass,
@@ -1292,6 +1302,89 @@ void x_init_widgets_varsel_menu_inner( Widget parent, long *varlist, int nv, cha
}
}
+/*****************************************************************************************************/
+void x_init_widgets_varsel_menu_grp( Widget menu_box, Widget *varsel_menu_widget_list )
+{
+ Stringlist *uniq_groups, *sl_cursor;
+ int discard_groupname, nvars, ngrps, *my_grp_num, i, igrp, nv_in_grp; /* Applies to each var on the global "variables" list; counting starts at zero */
+ long *varlist;
+ NCVar *var_cursor;
+ Widget *var_menu_grp;
+ char widget_name[2048];
+
+ nvars = n_vars_in_list( variables );
+
+ varlist = (long *)malloc( sizeof(long) * nvars );
+
+ /* Sort vars into lists based on their group */
+ uniq_groups = get_group_list( variables );
+ ngrps = stringlist_len( uniq_groups );
+
+ /* Get group number for each var. First group in list "uniq_groups" is
+ * assigned ID 0, etc.
+ */
+ my_grp_num = (int *)malloc( sizeof(int) * nvars );
+ var_cursor = variables;
+ for( i=0; i<nvars; i++ ) {
+ my_grp_num[i] = -1;
+ sl_cursor = uniq_groups;
+ for( igrp=0; igrp<ngrps; igrp++ ) {
+
+ /* Test for a var in the root group (in which case it has no slashes) matching
+ * the group named "/"
+ */
+ if( (count_nslashes( var_cursor->name )==0) && (strncmp( "/", sl_cursor->string, 1)==0)) {
+ my_grp_num[i] = igrp;
+ break;
+ }
+ /* Var has at least one slash in its name */
+ else if( strncmp( var_cursor->name, sl_cursor->string, strlen(sl_cursor->string) ) == 0 ) {
+ my_grp_num[i] = igrp;
+ break;
+ }
+
+ sl_cursor = sl_cursor->next;
+ }
+ if( my_grp_num[i] == -1 ) {
+ fprintf( stderr, "x_init_widgets_varsel_menu_grp: Error, did not find group for var named >%s< in the following list of unique groups:\n",
+ var_cursor->name );
+ stringlist_dump( uniq_groups );
+ exit(-1);
+ }
+
+ var_cursor = var_cursor->next;
+ }
+
+ /* Now go through the groups, and make a menu selection button for
+ * each group that generates a pop-up menu of all vars in that group
+ */
+ sl_cursor = uniq_groups;
+ for( igrp=0; igrp<ngrps; igrp++ ) {
+ /* The way the routine x_init_widgets_varsel_menu_inner is set up, it needs
+ * an array of longs that hold the entry number on the global "variables"
+ * list corresponding to each group
+ */
+ nv_in_grp = 0;
+ for( i=0; i<nvars; i++ ) {
+ if( my_grp_num[i] == igrp ) {
+ varlist[nv_in_grp] = i;
+ nv_in_grp++;
+ }
+ }
+ var_menu_grp = (Widget *)malloc( sizeof(Widget) );
+ discard_groupname = 1;
+ snprintf( widget_name, 2040, "%s (%d vars)", sl_cursor->string, nv_in_grp );
+ if( options.debug ) printf( "x_init_widgets_varsel_menu_grp: making menu for group selection named >%s< with %d vars\n",
+ widget_name, nv_in_grp );
+ x_init_widgets_varsel_menu_inner( menu_box, varlist, nv_in_grp, widget_name, var_menu_grp,
+ varsel_menu_widget_list, discard_groupname );
+
+ sl_cursor = sl_cursor->next;
+ }
+
+ free( varlist );
+}
+
/*************************************************************************************************
* The widget selection area can be in one of two different modes. In "menu" mode, there is one button
* for all the 1D variables, one button for all the 2D variables, ..., up to one button for all the
@@ -1303,9 +1396,10 @@ void x_init_widgets_varsel_menu_inner( Widget parent, long *varlist, int nv, cha
*/
void x_init_widgets_varsel_menu( Widget parent )
{
- long *vl_1d, *vl_2d, *vl_3d, *vl_4d, *vl_other;
- int n_1d, n_2d, n_3d, n_4d, n_other, n_tot;
+ long *vl_1d, *vl_2d, *vl_3d, *vl_4d, *vl_other; /* These have 0 if the var is NOT in the list, 1 if it is */
+ int discard_groupname, nvars, n_1d, n_2d, n_3d, n_4d, n_other;
Widget menu_box;
+ char widget_name[2048];
menu_box = XtVaCreateManagedWidget(
"varsel_menu_box",
@@ -1315,36 +1409,57 @@ void x_init_widgets_varsel_menu( Widget parent )
XtNborderWidth, 0,
NULL);
- n_tot = n_vars_in_list( variables );
+ nvars = n_vars_in_list( variables );
/* Allocate our "global" array that will store each menu selection widget, so we
* can later find them to set their sensitivities and otherwise manipulate them.
*/
- varsel_menu_widget_list = (Widget *)malloc( n_tot * sizeof(Widget) );
+ varsel_menu_widget_list = (Widget *)malloc( nvars * sizeof(Widget) );
+
+ /* If we are doing groups, we sort based on their group membership. If we
+ * are not doing groups, we sort based on the variable's number of dims
+ */
+ if( options.enable_group_sel )
+ x_init_widgets_varsel_menu_grp( menu_box, varsel_menu_widget_list );
+
+ else
+ {
+ discard_groupname = 0;
- /* Sort vars into lists based on their number of dimensions */
- x_sort_vars_by_ndims( variables, &vl_1d, &n_1d, &vl_2d, &n_2d, &vl_3d, &n_3d,
- &vl_4d, &n_4d, &vl_other, &n_other );
+ /* Sort vars into lists based on their number of dimensions */
+ x_sort_vars_by_ndims( variables, &vl_1d, &n_1d, &vl_2d, &n_2d, &vl_3d, &n_3d,
+ &vl_4d, &n_4d, &vl_other, &n_other );
- if( n_1d > 0 )
- x_init_widgets_varsel_menu_inner( menu_box, vl_1d, n_1d, "1d", &var_menu_1d,
- varsel_menu_widget_list );
+ if( n_1d > 0 ) {
+ snprintf( widget_name, 2040, "(%d) 1d vars", n_1d );
+ x_init_widgets_varsel_menu_inner( menu_box, vl_1d, n_1d, widget_name, &var_menu_1d,
+ varsel_menu_widget_list, discard_groupname );
+ }
- if( n_2d > 0 )
- x_init_widgets_varsel_menu_inner( menu_box, vl_2d, n_2d, "2d", &var_menu_2d,
- varsel_menu_widget_list+n_1d );
+ if( n_2d > 0 ) {
+ snprintf( widget_name, 2040, "(%d) 2d vars", n_2d );
+ x_init_widgets_varsel_menu_inner( menu_box, vl_2d, n_2d, widget_name, &var_menu_2d,
+ varsel_menu_widget_list+n_1d, discard_groupname );
+ }
- if( n_3d > 0 )
- x_init_widgets_varsel_menu_inner( menu_box, vl_3d, n_3d, "3d", &var_menu_3d,
- varsel_menu_widget_list+n_1d+n_2d );
+ if( n_3d > 0 ) {
+ snprintf( widget_name, 2040, "(%d) 3d vars", n_3d );
+ x_init_widgets_varsel_menu_inner( menu_box, vl_3d, n_3d, widget_name, &var_menu_3d,
+ varsel_menu_widget_list+n_1d+n_2d, discard_groupname );
+ }
- if( n_4d > 0 )
- x_init_widgets_varsel_menu_inner( menu_box, vl_4d, n_4d, "4d", &var_menu_4d,
- varsel_menu_widget_list+n_1d+n_2d+n_3d );
+ if( n_4d > 0 ) {
+ snprintf( widget_name, 2040, "(%d) 4d vars", n_4d );
+ x_init_widgets_varsel_menu_inner( menu_box, vl_4d, n_4d, widget_name, &var_menu_4d,
+ varsel_menu_widget_list+n_1d+n_2d+n_3d, discard_groupname );
+ }
- if( n_other > 0 )
- x_init_widgets_varsel_menu_inner( menu_box, vl_other, n_other, "5d", &var_menu_other,
- varsel_menu_widget_list+n_1d+n_2d+n_3d+n_4d );
+ if( n_other > 0 ) {
+ snprintf( widget_name, 2040, "(%d) 5d vars", n_other );
+ x_init_widgets_varsel_menu_inner( menu_box, vl_other, n_other, widget_name, &var_menu_other,
+ varsel_menu_widget_list+n_1d+n_2d+n_3d+n_4d, discard_groupname );
+ }
+ }
}
/*************************************************************************************************/
@@ -1489,6 +1604,11 @@ void x_init_widgets_varsel_list( Widget parent )
/*************************************************************************************************/
void x_init_widgets_varsel( Widget parent )
{
+ if( options.enable_group_sel && (options.varsel_style != VARSEL_MENU)) {
+ fprintf( stderr, "Internal error in x_init_widgets_varsel: if group selection is enambled, var selection must be done via menus\n" );
+ exit(-1);
+ }
+
if( options.varsel_style == VARSEL_LIST )
x_init_widgets_varsel_list( parent );
else if( options.varsel_style == VARSEL_MENU )
diff --git a/src/ncview.c b/src/ncview.c
index 1f3be77..ed974e4 100644
--- a/src/ncview.c
+++ b/src/ncview.c
@@ -110,9 +110,22 @@ main( int argc, char **argv )
exit( -1 );
}
+ /* If any vars are in groups, we build the interface differently.
+ * I pass this information through the global "options" struct.
+ */
+ if( any_var_in_group( variables )) {
+ options.enable_group_sel = TRUE;
+ options.varsel_style = VARSEL_MENU;
+ }
+ else
+ options.enable_group_sel = FALSE;
+
/* This initializes the colormaps, and then the X widows system */
+ if( options.debug ) printf( "Initializing display interface...\n" );
initialize_display_interface();
+ if( options.debug ) printf( "Initializing printing subsystem...\n" );
print_init();
+ if( options.debug ) printf( "Initializing overlays...\n" );
overlay_init();
/* If there is only one variable, make it the active one */
@@ -580,9 +593,12 @@ init_cmap_from_file( char *dir_name, char *file_name )
void
initialize_file_interface( Stringlist *input_files )
{
- int idim, nvars, nfiles;
+ int i, idim, nvars, nfiles;
NCVar *var;
+ if( options.debug )
+ fprintf( stderr, "Initializing file interface...\n" );
+
nfiles = stringlist_len( input_files );
while( input_files != NULL ) {
@@ -590,7 +606,7 @@ initialize_file_interface( Stringlist *input_files )
input_files = input_files->next;
}
if( options.debug )
- fprintf( stderr, "Calculating dim min & maxes...\n" );
+ fprintf( stderr, "...calculating dim min & maxes...\n" );
calc_dim_minmaxes();
/* Get the effective dimensionality of all the vars.
@@ -602,12 +618,18 @@ initialize_file_interface( Stringlist *input_files )
while( var != NULL ) {
nvars++;
var->effective_dimensionality = 0;
- for( idim=0; idim<var->n_dims; idim++ )
+ for( idim=0; idim<var->n_dims; idim++ ) {
if( *(var->size + idim) > 1 )
var->effective_dimensionality++;
- if( options.debug )
+ if( options.debug )
+ fprintf( stderr, "var %s has %d dims, dim %d: >%s< len %ld\n",
+ var->name, var->n_dims, idim,
+ var->dim[idim]->name, var->dim[idim]->size );
+ }
+ if( options.debug ) {
fprintf( stderr, "variable %s had effective_dimensionality of %d\n",
var->name, var->effective_dimensionality );
+ }
var = var->next;
}
@@ -619,6 +641,9 @@ initialize_file_interface( Stringlist *input_files )
if( nvars > options.listsel_max )
options.varsel_style = VARSEL_MENU;
+
+ if( options.debug )
+ fprintf( stderr, "Done initializing file interface...\n" );
}
/***********************************************************************************************/
@@ -632,7 +657,9 @@ initialize_display_interface()
*/
x_check_legal_colormap_loaded();
+ if( options.debug ) printf( "...initializing X interface\n" );
in_initialize();
+ if( options.debug ) printf( "...done with initializing X interface\n" );
}
/***********************************************************************************************/
@@ -679,6 +706,21 @@ create_default_colormap()
}
/***********************************************************************************************/
+int any_var_in_group( NCVar *var ) {
+
+ NCVar *cursor;
+
+ cursor = var;
+ while( cursor != NULL ) {
+ if( count_nslashes( cursor->name ) > 0 )
+ return( 1 );
+ cursor = cursor->next;
+ }
+
+ return( 0 );
+}
+
+/***********************************************************************************************/
void
useage()
{
diff --git a/src/ncview.defines.h b/src/ncview.defines.h
index d117c55..70bc97a 100644
--- a/src/ncview.defines.h
+++ b/src/ncview.defines.h
@@ -31,8 +31,8 @@
#include <udunits2.h>
#endif
-#define PROGRAM_ID "Ncview 2.1.1 David W. Pierce 1 Aug 2011"
-#define PROGRAM_VERSION_STRING "2.1.1"
+#define PROGRAM_ID "Ncview 2.1.2 David W. Pierce 24 Oct 2012"
+#define PROGRAM_VERSION_STRING "2.1.2"
#define APP_RES_VERSION 1.93
#ifndef TRUE
@@ -399,6 +399,10 @@ typedef struct {
* are global, rather than local to
* a file.
*/
+ int user_set_blowup; /* Initializes to -99999, then saves user-specified
+ * value of 'blowup' for this var so it can be
+ * used again if we leave this var & then come back
+ */
int auto_set_no_range; /* '1' if we autoset a range of -1,1 based
* on not having a valid range for this var
*/
@@ -532,6 +536,8 @@ typedef struct {
int save_frames; /* If true, try to save frames in core for faster display */
float frame_delay; /* Normalied to be between 0.0 and 1.0 */
+ int enable_group_sel; /* TRUE if we have some vars in groups, so interface must incl. grp selection */
+
OverlayOptions *overlay;
} Options;
diff --git a/src/ncview.protos.h b/src/ncview.protos.h
index 6fab2e0..8569552 100644
--- a/src/ncview.protos.h
+++ b/src/ncview.protos.h
@@ -141,6 +141,8 @@ void sl_cat ( Stringlist **dest, Stringlist **src );
void get_min_max_onestep( NCVar *var, size_t n_other, size_t tstep, float *data,
float *min, float *max, int verbose );
void cache_scalar_coord_info( NCVar *vars );
+int count_nslashes ( char *s );
+Stringlist *get_group_list ( NCVar *vars );
/******************************************************************************
* in interface.c
@@ -279,7 +281,7 @@ int view_draw ( int allow_saveframes_useage, int force_range_to_frame
void view_change_cur_dim ( char *dim_name, int modifier );
void view_forward ( void );
void view_backward ( void );
-void view_change_blowup ( int delta, int redraw_flag );
+void view_change_blowup ( int delta, int redraw_flag, int view_var_is_valid );
void init_saveframes ( void );
void redraw_dimension_info( void );
void redraw_ccontour ( void );
diff --git a/src/util.c b/src/util.c
index 5dc5488..4a6ff04 100644
--- a/src/util.c
+++ b/src/util.c
@@ -397,7 +397,7 @@ add_vars_to_list( Stringlist *var_list, int id, char *filename, int nfiles )
Stringlist *var;
if( options.debug )
- fprintf( stderr, "adding vars to list for file %s\n", filename );
+ fprintf( stderr, "add_vars_to_list: entering, adding vars to list for file %s\n", filename );
var = var_list;
while( var != NULL ) {
if( options.debug )
@@ -456,6 +456,7 @@ add_var_to_list( char *var_name, int file_id, char *filename, int nfiles )
new_var->global_max = 0.0;
new_var->user_min = 0.0;
new_var->user_max = 0.0;
+ new_var->user_set_blowup = -99999;
new_var->auto_set_no_range = 0;
new_var->have_set_range = FALSE;
new_var->size = fi_var_size( file_id, var_name );
@@ -509,9 +510,9 @@ add_var_to_list( char *var_name, int file_id, char *filename, int nfiles )
* Go through each variable, and if it has scalar coordinate information,
* read that in from each file that the var lives in.
*/
- void
- cache_scalar_coord_info( NCVar *vars )
- {
+ void
+cache_scalar_coord_info( NCVar *vars )
+{
NCVar *v;
FDBlist *tfile;
int nfiles, ifile, nsc, isc;
@@ -519,6 +520,8 @@ add_var_to_list( char *var_name, int file_id, char *filename, int nfiles )
float fval;
size_t zeros[MAX_NC_DIMS], ones[MAX_NC_DIMS], n_ts, ii, i_cursor, n_ts_this_file;
+ if( options.debug ) printf( "cache_scalar_coord_info: entering\n" );
+
/* Allocate space for the timestep_2_fdb array. This points
* to the file (FDBlist) associated with EACH TIMESTEP of
* the variable
@@ -624,6 +627,8 @@ add_var_to_list( char *var_name, int file_id, char *filename, int nfiles )
v = v->next;
}
+
+ if( options.debug ) printf( "cache_scalar_coord_info: finished\n" );
}
/******************************************************************************
@@ -1303,17 +1308,22 @@ handle_dim_mapping_2d( NCVar *v, char *coord_var_name, char *coord_att, size_t *
void
fill_dim_structs( NCVar *v )
{
- int i, fileid;
+ int i, fileid, debug;
NCDim *d;
char *dim_name, *tmp_units;
static int global_id = 0;
FDBlist *cursor;
+ debug = 0;
+
+ if( debug == 1 ) printf( "fill_dim_structs: entering for var %s, which has %d dims\n", v->name, v->n_dims );
+
fileid = v->first_file->id;
v->dim = (NCDim **)malloc( v->n_dims*sizeof( NCDim *));
for( i=0; i<v->n_dims; i++ ) {
+ dim_name = fi_dim_id_to_name( fileid, v->name, i );
+ if( debug == 1 ) printf( "fill_dim_structs: dim %d has name %s and length %ld\n", i, dim_name, v->size[i] );
if( is_scannable( v, i ) ) {
- dim_name = fi_dim_id_to_name( fileid, v->name, i );
*(v->dim + i) = (NCDim *)malloc( sizeof( NCDim ));
d = *(v->dim+i);
d->name = dim_name;
@@ -1333,7 +1343,8 @@ fill_dim_structs( NCVar *v )
/* Indicate non-scannable dimensions by a NULL */
*(v->dim + i) = NULL;
if( options.debug )
- fprintf( stderr, "adding non-scannable dim to var %s\n", v->name );
+ fprintf( stderr, "adding non-scannable dim to var %s: dim name: %s size: %ld\n",
+ v->name, fi_dim_id_to_name( fileid, v->name, i), *(v->size+i) );
}
}
@@ -1360,8 +1371,10 @@ fill_dim_structs( NCVar *v )
}
/******************************************************************************
- * Is this variable a "scannable" variable -- i.e., accessable by the taperecorder
- * style buttons?
+ * Is this a "scannable" dimension -- i.e., accessable by the taperecorder
+ * style buttons? Is scannable if:
+ * > is unlimited
+ * > or, is size > 1
*/
int
is_scannable( NCVar *v, int i )
@@ -2283,3 +2296,130 @@ int determine_lat_lon( char *s_in, int *is_lat, int *is_lon )
return(1); /* error return */
}
+/*******************************************************************************************
+ * Returns the number of forward slashes in a string
+ */
+int count_nslashes( char *s )
+{
+ int i, nslash;
+
+ nslash = 0;
+ for( i=0; i<strlen(s); i++ )
+ if( s[i] == '/' )
+ nslash++;
+
+ return( nslash );
+}
+
+/*******************************************************************************************
+ * Given a list of variables, this returns a stringlist of unique group names. If ANY var
+ * lives in the root group, then the return list includes "/". If no var lives in the root
+ * group, then the list does NOT include "/".
+ */
+Stringlist *get_group_list( NCVar *vars )
+{
+ Stringlist *retval = NULL, *tg;
+ NCVar *cursor;
+ char group_name[ MAX_NC_NAME*20 ]; /* Assume no more than 20 levels of groups */
+ int i, ierr, n_so_far, foundit;
+
+ cursor = vars;
+ while( cursor != NULL ) {
+
+ ierr = unpack_groupname( cursor->name, -1, group_name ); /* -1 means get full group name */
+
+ /* Only add to list if not already there */
+ n_so_far = stringlist_len( retval );
+ tg = retval;
+ foundit = 0;
+ while( tg != NULL ) {
+ if( strcmp( tg->string, group_name ) == 0 ) {
+ foundit = 1;
+ break;
+ }
+ tg = tg->next;
+ }
+ if( foundit == 0 )
+ ierr = stringlist_add_string( &retval, group_name, NULL, SLTYPE_NULL );
+
+ cursor = cursor->next;
+ }
+
+ return( retval );
+}
+
+/*******************************************************************************************
+ * Given a varname string of format: groupname0/groupname1/groupnameN/varname
+ *
+ * and an integer ig: 0...N this returns groupname correspoinding to the integer ig
+ * (NOTE: counting starts at 0, so if ig==0 then the first group name is returned)
+ *
+ * If ig == -1, then the full groupname without the varname is returned:
+ * I.e., "groupname0/groupname1/groupnameN". If the var does NOT have any
+ * forward slashes, it lives in the root group, and "/" is returned.
+ *
+ * If ig == -2, then ONLY the varname is returned. I.e., "varname"
+ *
+ * groupname must already be allocated upon entry
+ *
+ * Returns 0 on success, -1 on error
+ */
+int unpack_groupname( char *varname, int ig, char *groupname )
+{
+ int i, i0, i1, idx_slash[MAX_NC_NAME], nslash;
+ char ts[MAX_NC_NAME];
+
+ /* Get indices of the slashes */
+ nslash = 0;
+ for( i=0; i<strlen(varname); i++ ) {
+ if( varname[i] == '/' ) {
+ idx_slash[nslash] = i;
+ nslash++;
+ }
+ }
+
+ if( nslash == 0 ) {
+ if (ig == -2 ) {
+ /* Asked for varname only */
+ strcpy( groupname, varname );
+ return(0);
+ }
+ else
+ {
+ /* If no slashes in the var name, must live in root group */
+ strcpy( groupname, "/" );
+ return( 0 );
+ }
+ }
+
+ if( ig > (nslash+1) ) {
+ fprintf( stderr, "Error in unpack_groupname: varname: >%s< group to find (starting at 0)=%d invalid group to find (not this many groups in the varname)\n",
+ varname, ig );
+ exit(-1);
+ }
+
+ strcpy( ts, varname );
+
+ if( ig == -2 ) {
+ strcpy( groupname, ts+idx_slash[nslash-1]+1 );
+ return( 0 );
+ }
+
+ if( ig == -1 ) {
+ ts[ idx_slash[nslash-1] ] = '\0';
+ strcpy( groupname, ts );
+ return( 0 );
+ }
+
+ if( ig == 0 )
+ i0 = 0;
+ else
+ i0 = idx_slash[ig-1] + 1;
+ i1 = idx_slash[ig];
+ ts[i1] = '\0';
+
+ strcpy( groupname, ts+i0 );
+
+ return( 0 );
+}
+
diff --git a/src/view.c b/src/view.c
index 7ef0f2c..60d32f7 100644
--- a/src/view.c
+++ b/src/view.c
@@ -75,7 +75,7 @@ static void re_determine_scan_axes( View *new_view, NCVar *new_var, View *old_
static void set_scan_place( View *new_view, NCVar *var, View *old_view );
static void initial_set_scan_place( View *view, NCVar *var );
static void re_set_scan_place( View *new_view, NCVar *new_var, View *old_view );
-static void calculate_blowup( View *view, NCVar *var );
+static void calculate_blowup( View *view, NCVar *var, int val_to_set_to );
static void draw_file_info( NCVar *var );
static void label_dimensions( View *view );
static void show_current_dim_values( View *view );
@@ -111,8 +111,12 @@ set_scan_variable( NCVar *var )
float range_x, range_y;
NCDim *xdim, *ydim, *xdim_old, *xdim_new, *ydim_old, *ydim_new;
- if( options.debug )
+ if( options.debug ) {
fprintf( stderr, "\n\n******************************************\nentering set_scan_variable with var=%s\n", var->name );
+ fprintf( stderr, "var nims:%d\n", var->n_dims );
+ for( i=0; i<var->n_dims; i++ )
+ fprintf( stderr, "dim=%ld size=%ld\n", i, *(var->size + i) );
+ }
in_set_cursor_busy();
@@ -132,6 +136,9 @@ set_scan_variable( NCVar *var )
if( options.debug )
fprintf( stderr, "...determining scan axes (NEW)\n" );
determine_scan_axes( view, var, NULL );
+ if( options.debug )
+ fprintf( stderr, "...axes ids: scan=%d y=%d x=%d\n",
+ view->scan_axis_id, view->y_axis_id, view->x_axis_id );
if( var->effective_dimensionality == 1 ) {
start = (size_t *)malloc(view->variable->n_dims*sizeof(size_t));
count = (size_t *)malloc(view->variable->n_dims*sizeof(size_t));
@@ -162,7 +169,12 @@ set_scan_variable( NCVar *var )
/* How big should we initially make the picture? */
if( options.debug )
fprintf( stderr, "...calculating blowup (NEW)\n" );
- calculate_blowup( view, var );
+ calculate_blowup( view, var, -99999 ); /* last val is flag meaning to do automatic calculation */
+
+ /* Save the blowup we are using in the var structure so we can
+ * return to it later if we want
+ */
+ var->user_set_blowup = options.blowup;
if( options.debug )
fprintf( stderr, "... ... new blowup=%d\n", options.blowup );
}
@@ -226,7 +238,11 @@ set_scan_variable( NCVar *var )
if( options.debug )
fprintf( stderr, "...axis change, recalculating blowup; old, new X dim=%s, %s; old, new Y dim=%s, %s\n",
xdim_old->name, xdim_new->name, ydim_old->name, ydim_new->name );
- calculate_blowup( new_view, var );
+ calculate_blowup( new_view, var, var->user_set_blowup );
+ /* Save the blowup we are using in the var structure so we can
+ * return to it later if we want
+ */
+ var->user_set_blowup = options.blowup;
}
/* If the new var has a different shape than the old var,
@@ -425,7 +441,14 @@ change_view( int delta, int interpretation )
/* Delta is in percent of total size */
size = *(view->variable->size + view->scan_axis_id);
provisional_delta = (float)size * (float)delta/100.0;
- delta = (int)provisional_delta;
+ if( (int)provisional_delta == 0 ) {
+ if( delta < 0 )
+ delta = -1;
+ else
+ delta = 1;
+ }
+ else
+ delta = (int)provisional_delta;
}
place = *(view->var_place + view->scan_axis_id) + delta;
@@ -974,9 +997,16 @@ initial_determine_scan_axes( View *view, NCVar *var )
Stringlist *dimlist;
int n_dims;
+ if( options.debug ) fprintf( stderr, "initial_determine_scan_axes: entering for var %s\n", var->name );
+
/* Get a list of all possible scannable dimensions */
dimlist = fi_scannable_dims( var->first_file->id, var->name );
+ if( options.debug ) {
+ fprintf( stderr, "initial_determine_scan_axes: scannable dims:\n" );
+ stringlist_dump( dimlist );
+ }
+
/* For now, just pick the last two to be the Y and X axes.
*/
n_dims = stringlist_len( dimlist );
@@ -996,11 +1026,21 @@ initial_determine_scan_axes( View *view, NCVar *var )
var->first_file->id,
var->name,
dimlist->string );
+ if( view->y_axis_id == -1 ) {
+ fprintf( stderr, "initial_determine_scan_axes: internal error: dim >%s< was indicated by routine fi_scannable_dims to be a scannable dim for var >%s<, but routine fi_dim_name_to_id did not find that dim for the var\n",
+ dimlist->string, var->name );
+ exit(-1);
+ }
dimlist = dimlist->next;
view->x_axis_id = fi_dim_name_to_id(
var->first_file->id,
var->name,
dimlist->string );
+ if( view->x_axis_id == -1 ) {
+ fprintf( stderr, "initial_determine_scan_axes: internal error: dim >%s< was indicated by routine fi_scannable_dims to be a scannable dim for var >%s<, but routine fi_dim_name_to_id did not find that dim for the var\n",
+ dimlist->string, var->name );
+ exit(-1);
+ }
break;
default:
@@ -1012,6 +1052,11 @@ initial_determine_scan_axes( View *view, NCVar *var )
var->first_file->id,
var->name,
dimlist->string );
+ if( view->scan_axis_id == -1 ) {
+ fprintf( stderr, "initial_determine_scan_axes: internal error: dim >%s< was indicated by routine fi_scannable_dims to be a scannable dim for var >%s<, but routine fi_dim_name_to_id did not find that dim for the var\n",
+ dimlist->string, var->name );
+ exit(-1);
+ }
dimlist = dimlist->next;
/* Go to the second to the last entry */
@@ -1021,13 +1066,26 @@ initial_determine_scan_axes( View *view, NCVar *var )
var->first_file->id,
var->name,
dimlist->string );
+ if( view->y_axis_id == -1 ) {
+ fprintf( stderr, "initial_determine_scan_axes: internal error: dim >%s< was indicated by routine fi_scannable_dims to be a scannable dim for var >%s<, but routine fi_dim_name_to_id did not find that dim for the var\n",
+ dimlist->string, var->name );
+ exit(-1);
+ }
dimlist = dimlist->next;
view->x_axis_id = fi_dim_name_to_id(
var->first_file->id,
var->name,
dimlist->string );
+ if( view->x_axis_id == -1 ) {
+ fprintf( stderr, "initial_determine_scan_axes: internal error: dim >%s< was indicated by routine fi_scannable_dims to be a scannable dim for var >%s<, but routine fi_dim_name_to_id did not find that dim for the var\n",
+ dimlist->string, var->name );
+ exit(-1);
+ }
break;
}
+
+ if( options.debug ) fprintf( stderr, "initial_determine_scan_axes: exiting with axis_ids: scan=%d y=%d x=%d\n",
+ view->scan_axis_id, view->y_axis_id, view->x_axis_id );
}
/********************************************************************************
@@ -1053,7 +1111,7 @@ fill_view_data( View *v )
*(count+v->x_axis_id) = *(v->variable->size + v->x_axis_id);
*(count+v->y_axis_id) = *(v->variable->size + v->y_axis_id);
- if( options.show_sel ) {
+ if( options.debug || options.show_sel ) {
printf( "-var %s -start \\(", v->variable->name );
for( i=v->variable->n_dims-1; i >= 0; i-- ) {
printf( "%1ld", 1 + (*(v->var_place+i)) );
@@ -1079,7 +1137,7 @@ fill_view_data( View *v )
* Alter the amount by which we are blowing up pixels
*/
void
-view_change_blowup( int delta, int redraw_flag )
+view_change_blowup( int delta, int redraw_flag, int view_var_is_valid )
{
size_t x_size, y_size, scaled_x_size, scaled_y_size;
char blowup_label[32];
@@ -1112,6 +1170,10 @@ view_change_blowup( int delta, int redraw_flag )
in_set_label( LABEL_BLOWUP, blowup_label );
+ if( view_var_is_valid ) {
+ view->variable->user_set_blowup = options.blowup;
+ }
+
free( view->pixels );
x_size = *(view->variable->size + view->x_axis_id);
@@ -1824,22 +1886,37 @@ re_set_scan_place( View *new_view, NCVar *new_var, View *old_view )
}
/**************************************************************************************/
+/* If 'val_to_set_to' is -99999, then the blowup is calculated automatically,
+ * otherwise the blowup is set to val_to_set_to
+ */
static void
-calculate_blowup( View *view, NCVar *var )
+calculate_blowup( View *view, NCVar *var, int val_to_set_to )
{
size_t x_size, y_size;
float fbx, fby, f_x_size, f_y_size, f_blowup;
- int ifbx;
+ int ifbx, view_var_is_valid;
if( options.small )
return;
+ view_var_is_valid = 0;
+
+ if( val_to_set_to != -99999 ) {
+ while( options.blowup > val_to_set_to ) {
+ view_change_blowup( -1, FALSE, view_var_is_valid );
+ }
+ while( options.blowup < val_to_set_to ) {
+ view_change_blowup( 1, FALSE, view_var_is_valid );
+ }
+ return;
+ }
+
/* If the picture is too small, start out by blowing it up some */
x_size = *(var->size + view->x_axis_id);
y_size = *(var->size + view->y_axis_id);
while( (options.blowup*x_size < options.blowup_default_size) &&
(options.blowup*y_size < options.blowup_default_size) ) {
- view_change_blowup( 1, FALSE );
+ view_change_blowup( 1, FALSE, view_var_is_valid );
}
/* If picture is too big, reduce it some */
@@ -1851,7 +1928,7 @@ calculate_blowup( View *view, NCVar *var )
fbx = (fbx > fby) ? fbx : fby;
if( fbx > 3 ) {
ifbx = -(int)fbx;
- view_change_blowup(ifbx,FALSE);
+ view_change_blowup(ifbx,FALSE, view_var_is_valid);
}
}
diff --git a/x_interface.c b/x_interface.c
new file mode 100644
index 0000000..e69de29
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/ncview.git
More information about the Pkg-grass-devel
mailing list