diff --git a/pub/lib/node.cpp b/pub/lib/node.cpp
index 5ab67b73c9f12f965fdcb2c1921af5583238441b..54ba463e81b151f052b88651907f4cd75a13c240 100644
--- a/pub/lib/node.cpp
+++ b/pub/lib/node.cpp
@@ -711,7 +711,7 @@ string CNodeVal::tree_info() const
 
 void CNodeIva::npar_exec( int *np ) const
 {
-    if ( var->typ == CVar::_CP )
+    if ( var->categ == VCateg::CP )
         *np = std::max( *np, var->num+1 );
 }
 
@@ -720,7 +720,7 @@ void CNodeIva::npar_exec( int *np ) const
 const RObj CNodeIva::tree_val( const CContext& ctx ) const
 {
     try {
-        if ( (var->typ == CVar::_I || var->typ == CVar::_J || var->typ == CVar::_K) &&
+        if ( (var->categ == VCateg::I || var->categ == VCateg::J || var->categ == VCateg::K) &&
              ( ref->ti || ref->tj || ref->tk ) )
             throw S("invalid cross reference: index cannot be indexed");
 
@@ -728,29 +728,29 @@ const RObj CNodeIva::tree_val( const CContext& ctx ) const
         int k = ref->get_k( ctx );
 
         // Return k-dependent reference (unless already done above):
-        if ( var->typ == CVar::_K ) {
+        if ( var->categ == VCateg::K ) {
             return RObjInt( new CObjInt( k ) );
         }
 
         // Proceed with file reference f[k]:
         POlo f = NOlm::mem_get(k);
 
-        if        ( var->typ == CVar::_NK ) {
+        if        ( var->categ == VCateg::NK ) {
             return RObjInt( new CObjInt( NOlm::mem_size() ) );
-        } else if ( var->typ == CVar::_NJ ) {
+        } else if ( var->categ == VCateg::NJ ) {
             return RObjInt( new CObjInt( f->nJ() ) );
-        } else if ( var->typ == CVar::_R ) {
+        } else if ( var->categ == VCateg::R ) {
             if ( var->num>= f->RPar.size() )
                 throw "invalid reference " + var->var_info();
             return RObjDbl( new CObjDbl( f->RPar[var->num].val ) ); // TODO: RPar -> Enu? Obj?
         }
 
         // Return k-j-dependent reference (unless done above):
-        if        ( var->typ == CVar::_J ) {
+        if        ( var->categ == VCateg::J ) {
             if ( ref->ti )
                 throw S("J does not require 3 indices");
             return RObjInt( new CObjInt( ctx.j ) );
-        } else if ( var->typ == CVar::_Z ) {
+        } else if ( var->categ == VCateg::Z ) {
             if ( ref->ti )
                 throw S("Z does not require 3 indices");
             if ( var->num>= f->nZ() )
@@ -790,16 +790,16 @@ const RObj CNodeIva::tree_val( const CContext& ctx ) const
                     }
                     if( i>= sj->size() )
                         throw "i="+S(i)+" while there are only ni="+S(sj->size())+" points";
-                    if       ( var->typ == CVar::_I ) {
+                    if       ( var->categ == VCateg::I ) {
                         return RObjInt( new CObjInt( i ) );
-                    } else if ( var->typ == CVar::_X ) {
+                    } else if ( var->categ == VCateg::X ) {
                         return RObjDbl( new CObjDbl( sj->x[i] ) );
-                    } else if ( var->typ == CVar::_Y ) {
+                    } else if ( var->categ == VCateg::Y ) {
                         if ( ctx.want_error && sj->has_dy() )
                             return RObjEnu( new CObjEnu( sj->y[i], sj->dy[i] ) );
                         else
                             return RObjDbl( new CObjDbl( sj->y[i] ) );
-                    } else if ( var->typ == CVar::_DY ) {
+                    } else if ( var->categ == VCateg::DY ) {
                         return RObjDbl( new CObjDbl( sj->dy[i] ) );
                     } else
                         throw S("BUG: unexpected case");
@@ -808,7 +808,7 @@ const RObj CNodeIva::tree_val( const CContext& ctx ) const
                     if ( ref->ti ) {
                         CContext myctx = ctx;
                         myctx.dim = CContext::_1;
-                        if        ( var->typ == CVar::_I ) {
+                        if        ( var->categ == VCateg::I ) {
                             PObjVecInt pret( new CObjVecInt( ctx.nv ) );
                             for ( int ii=0; ii<ctx.nv; ++ii ) {
                                 myctx.i = ii;
@@ -816,7 +816,7 @@ const RObj CNodeIva::tree_val( const CContext& ctx ) const
                                 pret->v[ii] = i;
                             }
                             return pret;
-                        } else if ( var->typ == CVar::_Y ) {
+                        } else if ( var->categ == VCateg::Y ) {
                             if ( ctx.want_error ) {
                                 PObjVecEnu pret( new CObjVecEnu( ctx.nv ) );
                                 for ( int ii=0; ii<ctx.nv; ++ii ) {
@@ -847,7 +847,7 @@ const RObj CNodeIva::tree_val( const CContext& ctx ) const
                                 pret2->v[ii] = sj->y[i];
                             }
                             return pret2;
-                        } else if ( var->typ == CVar::_X ) {
+                        } else if ( var->categ == VCateg::X ) {
                             PObjVecDbl pret( new CObjVecDbl( ctx.nv ) );
                             for ( int ii=0; ii<ctx.nv; ++ii ) {
                                 myctx.i = ii;
@@ -860,7 +860,7 @@ const RObj CNodeIva::tree_val( const CContext& ctx ) const
                                 pret->v[ii] = sj->x[i];
                             }
                             return pret;
-                        } else if ( var->typ == CVar::_DY ) {
+                        } else if ( var->categ == VCateg::DY ) {
                             PObjVecDbl pret( new CObjVecDbl( ctx.nv ) );
                             for ( int ii=0; ii<ctx.nv; ++ii ) {
                                 myctx.i = ii;
@@ -885,19 +885,19 @@ const RObj CNodeIva::tree_val( const CContext& ctx ) const
                         } else if ( nv != sj->size() )
                             throw "ref_val "+var->var_info()+": requested vec("+S(ctx.nv)+
                                 "), found vec("+S( sj->size() );
-                        if        ( var->typ == CVar::_I ) {
+                        if        ( var->categ == VCateg::I ) {
                             PObjVecInt pret( new CObjVecInt( nv ) );
                             for( int i=0; i<nv; ++i )
                                 pret->v[i] = i;
                             return pret;
-                        } else if ( var->typ == CVar::_X ) {
+                        } else if ( var->categ == VCateg::X ) {
                             return RObjVecDbl( new CObjVecDbl( sj->x ) );
-                        } else if ( var->typ == CVar::_Y ) {
+                        } else if ( var->categ == VCateg::Y ) {
                             if ( ctx.want_error && sj->has_dy() )
                                 return RObjVecEnu( new CObjVecEnu( sj->y, sj->dy ) );
                             else
                                 return RObjVecDbl( new CObjVecDbl( sj->y ) );
-                        } else if ( var->typ == CVar::_DY ) {
+                        } else if ( var->categ == VCateg::DY ) {
                             return RObjVecDbl( new CObjVecDbl( sj->dy ) );
                         }
                         throw S("BUG: unexpected case");
@@ -905,7 +905,7 @@ const RObj CNodeIva::tree_val( const CContext& ctx ) const
                 }
                 throw S("BUG: invalid context::dim");
 
-            } else if ( var->typ == CVar::_NI ) {
+            } else if ( var->categ == VCateg::NI ) {
                 int j = ref->get_j( ctx, f->nJ() );
                 PSpec sj = fd->VS(j);
                 return PObjInt( new CObjInt( sj->size() ) );
@@ -932,13 +932,13 @@ const RObj CNodeIva::tree_val( const CContext& ctx ) const
 
 void CNodeIva::set_coord( CCoord& ret, int k_in ) const
 {
-    if        ( var->typ == CVar::_K ) {
+    if        ( var->categ == VCateg::K ) {
         ret = CCoord("k","");
         return;
-    } else if ( var->typ == CVar::_J ) {
+    } else if ( var->categ == VCateg::J ) {
         ret = CCoord("j","");
         return;
-    } else if ( var->typ == CVar::_I ) {
+    } else if ( var->categ == VCateg::I ) {
         ret = CCoord("i","");
         return;
     }
@@ -953,43 +953,43 @@ void CNodeIva::set_coord( CCoord& ret, int k_in ) const
     }
     POlo f = NOlm::mem_get(k);
 
-    if  ( var->typ == CVar::_Z ) {
+    if  ( var->categ == VCateg::Z ) {
         if (var->num>=f->ZCo.size())
             throw "set_coord: z" + S(var->num) + " undefined";
         ret = f->ZCo[var->num];
-    } else if  ( var->typ == CVar::_R ) {
+    } else if  ( var->categ == VCateg::R ) {
         if (var->num>=f->RPar.size())
             throw "set_coord: r" + S(var->num) + " undefined";
         ret = f->RPar[var->num].Co;
-    } else if ( var->typ == CVar::_NJ ) {
+    } else if ( var->categ == VCateg::NJ ) {
         ret = CCoord("#spectra", "");
     } else {
         POld fd = P2D( f );
         POlc fc = P2C( f );
         if         ( fd ) {
-            if       ( var->typ == CVar::_X )
+            if       ( var->categ == VCateg::X )
                 ret = fd->xco;
-            else if  ( var->typ == CVar::_Y )
+            else if  ( var->categ == VCateg::Y )
                 ret = fd->yco;
-            else if  ( var->typ == CVar::_DY )
+            else if  ( var->categ == VCateg::DY )
                 ret = CCoord( "d"+fd->yco.name, fd->yco.unit );
-            else if  ( var->typ == CVar::_NI )
+            else if  ( var->categ == VCateg::NI )
                 ret = CCoord("#points", "");
             else
                 throw "data file has no " + var->var_info();
         } else if ( fc ) {
-            if     ( var->typ == CVar::_CP ) {
+            if     ( var->categ == VCateg::CP ) {
                 if( var->num>=fc->nP )
                     throw "invalid reference p" + S(var->num);
                 ret = fc->PCo[var->num];
             }
-            else if ( var->typ == CVar::_COUTCOME )
+            else if ( var->categ == VCateg::COUTCOME )
                 ret = CCoord("fit_outcome", "");
-            else if ( var->typ == CVar::_CCHI2 )
+            else if ( var->categ == VCateg::CCHI2 )
                 ret = CCoord("chi2", "");
-            else if ( var->typ == CVar::_CR2 )
+            else if ( var->categ == VCateg::CR2 )
                 ret = CCoord("R2", "");
-            else if ( var->typ == CVar::_C )
+            else if ( var->categ == VCateg::C )
                 ret = CCoord(fc->expr,"");
             else
                 throw "curve file has no " + var->var_info();
diff --git a/pub/lib/olf.cpp b/pub/lib/olf.cpp
index 70bb1fc077729e02823f9b0e2472a1aca394a693..bae382f62b81be3711fe3f8cef204a84fe08379f 100644
--- a/pub/lib/olf.cpp
+++ b/pub/lib/olf.cpp
@@ -166,15 +166,15 @@ PCurve COlc::VC( int j ) const
 
 CCoord COld::coord( CVar* var ) const
 {
-    if        ( var->typ==CVar::_X ) {
+    if        ( var->categ==VCateg::X ) {
         return xco;
-    } else if ( var->typ==CVar::_Y ) {
+    } else if ( var->categ==VCateg::Y ) {
         return yco;
-    } else if ( var->typ==CVar::_Z ) {
+    } else if ( var->categ==VCateg::Z ) {
         if( var->num >= nZ() )
             throw "coordinate " + var->var_info() + " not defined";
         return ZCo[var->num];
-    } else if ( var->typ==CVar::_R ) {
+    } else if ( var->categ==VCateg::R ) {
         if( var->num >= RPar.size() )
             throw "coordinate " + var->var_info() + " not defined";
         return RPar[var->num].Co;
@@ -188,19 +188,19 @@ CCoord COld::coord( CVar* var ) const
 
 CCoord COlc::coord( CVar* var ) const
 {
-    if        ( var->typ==CVar::_X ) {
+    if        ( var->categ==VCateg::X ) {
         return xco;
-    } else if ( var->typ==CVar::_Y ) {
+    } else if ( var->categ==VCateg::Y ) {
         return yco;
-    } else if ( var->typ==CVar::_Z ) {
+    } else if ( var->categ==VCateg::Z ) {
         if( var->num >= nZ() )
             throw "coordinate " + var->var_info() + " not defined";
         return ZCo[var->num];
-    } else if ( var->typ==CVar::_CP ) {
+    } else if ( var->categ==VCateg::CP ) {
         if( var->num >= nP )
             throw "coordinate " + var->var_info() + " not defined";
         return PCo[var->num];
-    } else if ( var->typ==CVar::_R ) {
+    } else if ( var->categ==VCateg::R ) {
         if( var->num >= RPar.size() )
             throw "coordinate " + var->var_info() + " not defined";
         return RPar[var->num].Co;
@@ -214,15 +214,15 @@ CCoord COlc::coord( CVar* var ) const
 
 void COld::set_coord( CVar* var, CCoord& co )
 {
-    if        ( var->typ==CVar::_X ) {
+    if        ( var->categ==VCateg::X ) {
         xco = co;
-    } else if ( var->typ==CVar::_Y ) {
+    } else if ( var->categ==VCateg::Y ) {
         yco = co;
-    } else if ( var->typ==CVar::_Z ) {
+    } else if ( var->categ==VCateg::Z ) {
         if( var->num >= nZ() )
             throw "coordinate " + var->var_info() + " not defined";
         ZCo[var->num] = co;
-    } else if ( var->typ==CVar::_R ) {
+    } else if ( var->categ==VCateg::R ) {
         if( var->num >= RPar.size() )
             throw "coordinate " + var->var_info() + " not defined";
         RPar[var->num].Co = co;
@@ -236,19 +236,19 @@ void COld::set_coord( CVar* var, CCoord& co )
 
 void COlc::set_coord( CVar* var, CCoord& co )
 {
-    if        ( var->typ==CVar::_X ) {
+    if        ( var->categ==VCateg::X ) {
         xco = co;
-    } else if ( var->typ==CVar::_Y ) {
+    } else if ( var->categ==VCateg::Y ) {
         yco = co;
-    } else if ( var->typ==CVar::_Z ) {
+    } else if ( var->categ==VCateg::Z ) {
         if( var->num >= nZ() )
             throw "coordinate " + var->var_info() + " not defined";
         ZCo[var->num] = co;
-    } else if ( var->typ==CVar::_CP ) {
+    } else if ( var->categ==VCateg::CP ) {
         if( var->num >= nP )
             throw "coordinate " + var->var_info() + " not defined";
         PCo[var->num] = co;
-    } else if ( var->typ==CVar::_R ) {
+    } else if ( var->categ==VCateg::R ) {
         if( var->num >= RPar.size() )
             throw "coordinate " + var->var_info() + " not defined";
         RPar[var->num] = co;
diff --git a/pub/lib/opr.cpp b/pub/lib/opr.cpp
index 096de9162624b0ca3e7393cf463be38f793fdca9..a3d476046ab14d2f53b6ed3397294f9fdf17bcd8 100644
--- a/pub/lib/opr.cpp
+++ b/pub/lib/opr.cpp
@@ -165,35 +165,35 @@ void NOperate::Pointwise( string llabel )
 
         if ( lref.pointwise() && !fd )
             throw S("no pointwise operation on curve");
-        if( lref.typ==CVar::_CP && !fc )
+        if( lref.categ==VCateg::CP && !fc )
             continue;
 
         POlo fout( fin->new_olo() );
 
-        if( lref.typ!=CVar::_CP )
+        if( lref.categ!=VCateg::CP )
             fout->lDoc.push_back( "o" + lref.var_info() + " " + expr);
 
         CCoord co;
         T->set_coord( co, k );
-        if        ( lref.typ==CVar::_X ) {
+        if        ( lref.categ==VCateg::X ) {
             fout->xco = co;
-        } else if ( lref.typ==CVar::_Y ) {
+        } else if ( lref.categ==VCateg::Y ) {
             fout->yco = co;
-        } else if ( lref.typ==CVar::_Z ) {
+        } else if ( lref.categ==VCateg::Z ) {
             if( lref.num==-1 )
                 fout->ZCo.push_back( co );
             else if( lref.num >= fin->ZCo.size() )
                 throw S("no such z coordinate to operate on");
             else
                 fout->ZCo[lref.num] = co;
-        } else if ( lref.typ==CVar::_R ) {
+        } else if ( lref.categ==VCateg::R ) {
             if( lref.num==-1 )
                 fout->RPar.push_back( CParam( co ) );
             else if( lref.num >= fin->RPar.size() )
                 throw S("no such real par to operate on");
             else
                 fout->RPar[lref.num].Co = co;
-        } else if ( lref.typ==CVar::_CP ) {
+        } else if ( lref.categ==VCateg::CP ) {
             if( !fc )
                 continue; // just ignore op operations on data files
             if( lref.num>=fc->nP )
@@ -202,7 +202,7 @@ void NOperate::Pointwise( string llabel )
             P2C(fout)->clear_fits_outcome();
         }
 
-        if ( lref.typ==CVar::_R ) {
+        if ( lref.categ==VCateg::R ) {
             fout->copy_mainvec( fin );
             double val = T->tree_point_val( k, 0 )->to_r();
             if( lref.num==-1 )
@@ -218,15 +218,15 @@ void NOperate::Pointwise( string llabel )
                 if ( lref.pointwise() ) {
                     PSpec eout( new CSpec( *(fd->VS(j)) ) );
                     vector<double> vout( fd->nPts(j) );
-                    if ( lref.typ==CVar::_X || lref.typ==CVar::_DY ) {
+                    if ( lref.categ==VCateg::X || lref.categ==VCateg::DY ) {
                         T->tree_vec_val( &vout, 0, k, j );
-                        if      ( lref.typ==CVar::_X )
+                        if      ( lref.categ==VCateg::X )
                             (P2D(fout))->VS(j)->x = vout;
-                        else if ( lref.typ==CVar::_DY )
+                        else if ( lref.categ==VCateg::DY )
                             (P2D(fout))->VS(j)->dy = vout;
                         else
                             throw S("BUG: unexpected lref");
-                    } else if ( lref.typ==CVar::_Y ) {
+                    } else if ( lref.categ==VCateg::Y ) {
                         vector<double> dvout( fd->nPts(j) );
                         T->tree_vec_val( &vout, &dvout, k, j );
                         (P2D(fout))->VS(j)->y = vout;
@@ -236,13 +236,13 @@ void NOperate::Pointwise( string llabel )
                             (P2D(fout))->VS(j)->dy.clear();
                     } else
                         throw S("BUG: unexpected lref");
-                } else if ( lref.typ==CVar::_Z ) {
+                } else if ( lref.categ==VCateg::Z ) {
                     RObj pret = T->tree_point_val( k, j );
                     if ( lref.num==-1 )
                         fout->V[j]->z.push_back( pret );
                     else
                         fout->V[j]->z[lref.num] = pret;
-                } else if ( lref.typ==CVar::_CP ) {
+                } else if ( lref.categ==VCateg::CP ) {
                     (P2C(fout))->VC(j)->P[lref.num] = T->tree_point_val( k, j )->to_r();
                 } else {
                     throw S("BUG: invalid oxy");
diff --git a/pub/lib/slice.cpp b/pub/lib/slice.cpp
index 09c81f0aca646274518ff5339c430ba3ff8e1e58..be7d39ca5e2f2c1fb4952cfaa04d3c0787cbc1d1 100644
--- a/pub/lib/slice.cpp
+++ b/pub/lib/slice.cpp
@@ -379,18 +379,18 @@ string CCurve::info_line() const
 
 RObj CCurve::get_var( const RVar& var ) const
 {
-    if       ( var->typ == CVar::_CP ) {
+    if       ( var->categ == VCateg::CP ) {
         if ( var->num >= P.size() )
             throw "invalid p ref("+var->var_info()+") in curve file";
         return RObjDbl( new CObjDbl( P[var->num] ) );
 
-    } else if ( var->typ == CVar::_COUTCOME ) {
+    } else if ( var->categ == VCateg::COUTCOME ) {
         return RObjInt( new CObjInt( fitOutcome ) );
 
-    } else if ( var->typ == CVar::_CCHI2 ) {
+    } else if ( var->categ == VCateg::CCHI2 ) {
         return RObjDbl( new CObjDbl( fitChi2 ) );
 
-    } else if ( var->typ == CVar::_CR2 ) {
+    } else if ( var->categ == VCateg::CR2 ) {
         return RObjDbl( new CObjDbl( fitR2 ) );
 
     }
diff --git a/pub/lib/var.cpp b/pub/lib/var.cpp
index 7cad350edccb1e20f9a1a641517497158fbc1b04..f0e4468817c393eb8ba142b069c35dc094070843 100644
--- a/pub/lib/var.cpp
+++ b/pub/lib/var.cpp
@@ -16,8 +16,6 @@
 //*  class CVar
 //**************************************************************************************************
 
-// Variables may be unnumbered (x,y,i,j,k,f,...) or numbered (z0,p0,...).
-
 
 //! Returns number contained in parameter label s, starting at index pos.
 
@@ -42,46 +40,45 @@ CVar::CVar( string s )
 
     if ( s[0]=='p' ) {        // curve parameter
         num = request_num( s, 1 );
-        typ = _CP;
+        categ = VCateg::CP;
     } else if ( s=="z+" ) {          // new z value
-        typ = _Z;
+        categ = VCateg::Z;
     } else if ( s[0]=='z' ) {        // existing z value
         num = request_num( s, 1 );
-        typ = _Z;
+        categ = VCateg::Z;
     } else if ( s=="r+" ) {          // new real par
-        typ = _R;
+        categ = VCateg::R;
     } else if ( s[0]=='r' ) { // existing real par
         num = request_num( s, 1 );
-        typ = _R;
+        categ = VCateg::R;
     } else if ( s=="nk" ) {
-        typ = _NK;
+        categ = VCateg::NK;
     } else if ( s=="nj" ) {
-        typ = _NJ;
+        categ = VCateg::NJ;
     } else if ( s=="ni" ) {
-        typ = _NI;
+        categ = VCateg::NI;
     } else if ( s=="x" ) {
-        typ = _X;
+        categ = VCateg::X;
     } else if ( s=="y" ) {
-        typ = _Y;
+        categ = VCateg::Y;
     } else if ( s=="dy" ) {
-        typ = _DY;
+        categ = VCateg::DY;
     } else if ( s=="c" ) {
-        typ = _C;
+        categ = VCateg::C;
     } else if ( s=="outcome" ) {
-        typ = _COUTCOME;
+        categ = VCateg::COUTCOME;
     } else if ( s=="chi2" ) {
-        typ = _CCHI2;
+        categ = VCateg::CCHI2;
     } else if ( s=="R2" ) {
-        typ = _CR2;
+        categ = VCateg::CR2;
     } else if ( s=="k" ) {
-        typ = _K;
+        categ = VCateg::K;
     } else if ( s=="j" ) {
-        typ = _J;
+        categ = VCateg::J;
     } else if ( s=="i" ) {
-        typ = _I;
+        categ = VCateg::I;
     } else {
         throw "Invalid variable '" + s + "'";
-        // typ = _NOREF;
     }
 }
 
@@ -91,25 +88,25 @@ CVar::CVar( string s )
 string CVar::var_info() const
 {
     string ret;
-    switch (typ) {
-    case _X:  ret = "x";  break;
-    case _Y:  ret = "y";  break;
-    case _DY: ret = "dy";  break;
-    case _C:  ret = "c";  break;
-    case _Z:  ret = "z";  break;
-    case _R:  ret = "r";  break;
-    case _CP: ret = "p";  break;
-    case _COUTCOME: ret = "fit_outcome"; break;
-    case _CCHI2: ret = "chi2"; break;
-    case _CR2: ret = "R2"; break;
-    case _K:  ret = "k";  break;
-    case _J:  ret = "j";  break;
-    case _I:  ret = "i";  break;
-    case _NK: ret = "nk"; break;
-    case _NJ: ret = "nj"; break;
-    case _NI: ret = "ni"; break;
+    switch (categ) {
+    case VCateg::X:  ret = "x";  break;
+    case VCateg::Y:  ret = "y";  break;
+    case VCateg::DY: ret = "dy";  break;
+    case VCateg::C:  ret = "c";  break;
+    case VCateg::Z:  ret = "z";  break;
+    case VCateg::R:  ret = "r";  break;
+    case VCateg::CP: ret = "p";  break;
+    case VCateg::COUTCOME: ret = "outcome_code"; break;
+    case VCateg::CCHI2: ret = "chi2"; break;
+    case VCateg::CR2: ret = "R2"; break;
+    case VCateg::K:  ret = "k";  break;
+    case VCateg::J:  ret = "j";  break;
+    case VCateg::I:  ret = "i";  break;
+    case VCateg::NK: ret = "nk"; break;
+    case VCateg::NJ: ret = "nj"; break;
+    case VCateg::NI: ret = "ni"; break;
     default:
-        throw S("BUG: no info available for unexpected variable typ");
+        throw S("BUG: no info available for unexpected variable category");
     }
     if ( numbered() ) {
         if( num==-1 )
diff --git a/pub/lib/var.hpp b/pub/lib/var.hpp
index ea1ef61382a57cb91079adab59cc1cf189597783..c171feae41074c3988255c17d34613925d0df284 100644
--- a/pub/lib/var.hpp
+++ b/pub/lib/var.hpp
@@ -8,29 +8,58 @@
 //! \brief Variable reference CVar.
 
 
-//! Variable type (and number, if applicable).
+//! Variable category.
+
+enum class VCateg : char {
+    X, Y, Z, R, // data
+    DY,            // associated error
+    C, CP,        // curve, curve parameters
+    COUTCOME, CCHI2, CR2, // fit outcome
+    K, J, I,     // indices for file, spectrum, point
+    NK, NJ, NI,  // number of files, of spectra in file, of points in spectrum
+    _LAST_
+};
+
+
+//! Variable reference, composed of a category and a number, if applicable.
 
 class CVar {
-    // Variables may be unnumbered (x,y,i,j,k,c,...) or numbered (z0,p0,r0)
  public:
-    enum TTyp {
-        _NOREF=0,
-        _X, _Y, _Z, _R, // data
-        _DY,            // associated error
-        _C, _CP,        // curve, curve parameters
-        _COUTCOME, _CCHI2, _CR2, // fit outcome
-        _K, _J, _I,     // indices for file, spectrum, point
-        _NK, _NJ, _NI   // number of files, of spectra in file, of points in spectrum
-    };
-    TTyp typ;
+    VCateg categ;
     int num;
 
-    CVar( TTyp _typ=_NOREF, int _num=0 ) : typ(_typ), num(_num) {};
+    CVar( VCateg categ, int num=0 ) : categ(categ), num(num) {}
     CVar( const string s );
 
-    bool is_errvar() const { return typ==_DY; }
-    bool pointwise() const { return typ==_X || typ==_Y || typ==_DY || typ==_I; };
-    bool numbered() const { return typ==_CP || typ==_Z; };
+    bool is_errvar() const { return
+            categ==VCateg::DY; }
+    bool fitoutcome() const { return
+            categ==VCateg::COUTCOME ||
+            categ==VCateg::CCHI2 ||
+            categ==VCateg::CR2; }
+    bool pointwise() const { return
+            categ==VCateg::X ||
+            categ==VCateg::Y ||
+            categ==VCateg::DY ||
+            categ==VCateg::I; }
+    bool curvewise() const { return
+            categ==VCateg::C ||
+            categ==VCateg::CP ||
+            fitoutcome(); }
+    bool slicewise() const { return
+            curvewise() ||
+            categ==VCateg::J ||
+            categ==VCateg::NI; }
+    bool filewise() const { return
+            categ==VCateg::R ||
+            categ==VCateg::K ||
+            categ==VCateg::NJ; }
+    bool sessionwise() const { return
+            categ==VCateg::NK; }
+    bool numbered() const { return
+            categ==VCateg::CP ||
+            categ==VCateg::R ||
+            categ==VCateg::Z; }
 
     string var_info() const;