diff --git a/pub/lib/curve.cpp b/pub/lib/curve.cpp
index f5a8e0cf9e7183e4fbe713baf6b68f45951db409..a11be875f35b54343fcf7782ea5769e196424391 100644
--- a/pub/lib/curve.cpp
+++ b/pub/lib/curve.cpp
@@ -44,7 +44,7 @@ void NCurveFile::create_fitcurve()
     fc->curve_set_defaults();
 
     while( const COld *fd = fiter.nextD() ) {
-        POlc fout( fc->new_olc() );
+        POlc fout( fc->new_POlc() );
         vector<double> P( fout->nP, 1.0 );
         fout->name = string("fit_") + fd->name;
         fout->kd = fiter.k();
@@ -52,14 +52,14 @@ void NCurveFile::create_fitcurve()
         fout->yco = fd->yco;
         fout->ZCo = fd->ZCo;
         fout->RPar = fd->RPar;
-        fout->lDoc.push_back( "cc " + fc->expr + " # z from " + fd->name );
+        fout->log_action( "cc " + fc->expr + " # z from " + fd->name );
         fout->weighing = fd->has_nonzero_dy() ? COlc::_VAR : COlc::_LIN;
         for (int j=0; j<fd->nJ(); j++) {
             PCurve sout( new CCurve );
             sout->z = fd->VS(j)->z;
             sout->P = P;
             sout->ParAttr.resize( fout->nP, 'u' );
-            fout->V.push_back( sout );
+            fout->V.push_back( move(sout) );
         }
         NOlm::mem_store( fout );
     }
@@ -80,11 +80,11 @@ void NCurveFile::create_freecurve()
     fout->xco = CCoord( "x", "" );
     fout->yco = CCoord( "y", "" );
     fout->kd = -1;
-    fout->lDoc.push_back( "cca " + fout->expr );
+    fout->log_action( "cca " + fout->expr );
     PCurve sout( new CCurve );
     sout->P.resize    ( fout->nP, 1.0 );
     sout->ParAttr.resize( fout->nP, 'u' );
-    fout->V.push_back( sout );
+    fout->V.push_back( move(sout) );
     NOlm::mem_store( fout );
 }
 
@@ -108,7 +108,7 @@ void NCurveFile::change_expr()
         fc->expr = ftmp->expr;
         fc->T = ftmp->T;
         fc->nP = ftmp->nP;
-        fc->lDoc.push_back( "cm " + ftmp->expr );
+        fc->log_action( "cm " + ftmp->expr );
         fc->PCo.resize(fc->nP);
         for( int ip=nPold; ip<fc->nP; ip++ )
             fc->PCo[ip] = CCoord("p" + S(ip), "");
@@ -210,7 +210,7 @@ void NCurveFile::change_range()
 
     while( COlc *fc = fiter.nextC() ) {
         fc->range_expr = expr;
-        fc->lDoc.push_back( "cr " + expr );
+        fc->log_action( "cr " + expr );
         if( expr=="" ) {
             fc->range_T = nullptr;
             continue;
@@ -358,5 +358,5 @@ void NCurveFile::get_conv( const CSpec **sv, int *kv, int *jv, int k, int j )
     else
         throw "cannot convolute file " + S(k) + " with resolution " +
             S(*kv) + ": number of spectra does not match";
-    *sv = fv->VS(*jv).get();
+    *sv = fv->VS(*jv);
 }
diff --git a/pub/lib/edif.cpp b/pub/lib/edif.cpp
index 4380b905849734da9aeb36f2db98c6dbdbd9a081..4af704fd24f105ff9daa5d2a8bd5c0c631e9e87e 100644
--- a/pub/lib/edif.cpp
+++ b/pub/lib/edif.cpp
@@ -199,7 +199,7 @@ void NEdif::edit_fnam()
     while( COlo* f = fiter.next() ) {
         string fnam = wask( ("Rename " + f->name).c_str(), f->name );
         if ( fnam != f->name ){
-            f->lDoc.push_back( "ef " + fnam + " # < " + f->name );
+            f->log_action( "ef " + fnam + " # < " + f->name );
             f->name = fnam;
         }
     }
@@ -242,14 +242,14 @@ void NEdif::edit_coord( string which )
             in = sask( "Coordinate "+which+" for file "+S(fiter.k())+": name(unit)",
                        old_co.str_compact() );
             CCoord new_co(in);
-            fin->lDoc.push_back( "ec"+string(which)+" "+new_co.str_compact()+
+            fin->log_action( "ec"+string(which)+" "+new_co.str_compact()+
                                  " # old: " + old_co.str_compact() );
             fin->set_coord( genus, new_co );
         }
     } else {
         CCoord new_co(in);
         while ( fin = fiter.next() ) {
-            fin->lDoc.push_back( "ec"+string(which)+" "+new_co.str_compact()+
+            fin->log_action( "ec"+string(which)+" "+new_co.str_compact()+
                                  " # old: " + old_co.str_compact() );
             fin->set_coord( genus, new_co );
         }
@@ -302,7 +302,7 @@ void NEdif::edit_doc()
                 throw S("invalid change in ### line: wrong file name");
             f->lDoc.clear();
         } else {
-            f->lDoc.push_back( line );
+            f->log_action( line );
         }
     }
 
diff --git a/pub/lib/file_in.cpp b/pub/lib/file_in.cpp
index 98de9f8384c1b4d46ef04b3e986835391221c0de..1d05ccd5ef4995ff728a0c9e0f3a077e9969a06b 100644
--- a/pub/lib/file_in.cpp
+++ b/pub/lib/file_in.cpp
@@ -112,7 +112,7 @@ void NFileIn::Load_yda(std::ifstream& FS, string fnam)
         throw S("History is not of SEQUENCE type");
     for (int i = 0; i < doc["History"].size(); i++) {
         string s = doc["History"][i].as<string>();
-        fout->lDoc.push_back(s);
+        fout->log_action(s);
     }
 
     // read coord
@@ -244,7 +244,7 @@ void NFileIn::Load_yda(std::ifstream& FS, string fnam)
                     };
                 } else
                     throw "invalid xytag " + xytag;
-                fout->V.push_back( sout );
+                fout->V.push_back( move(sout) );
             } else {
                 PCurve cout( new CCurve );
                 cout->z = z;
@@ -257,7 +257,7 @@ void NFileIn::Load_yda(std::ifstream& FS, string fnam)
                     cout->P.push_back( num );
                     cout->ParAttr.push_back( 'u' );
                 }
-                fout->V.push_back( cout );
+                fout->V.push_back( move(cout) );
             }
         }
     } else {
@@ -306,7 +306,7 @@ void NFileIn::Load_yda(std::ifstream& FS, string fnam)
                     if( sout->dy.size() != sout->x.size() )
                         throw S("a dy entry differs in length from x");
                 }
-                fout->V.push_back( sout );
+                fout->V.push_back( move(sout) );
             } else {
                 PCurve cout( new CCurve );
                 cout->z = z;
@@ -332,7 +332,7 @@ void NFileIn::Load_yda(std::ifstream& FS, string fnam)
                 cout->fitChi2 = nodeSlic["fitChi2"].as<double>();
                 cout->fitR2 = nodeSlic["fitR2"].as<double>();
 
-                fout->V.push_back( cout );
+                fout->V.push_back( move(cout) );
             }
         }
     }
diff --git a/pub/lib/file_out.cpp b/pub/lib/file_out.cpp
index c244acaa9e1e19bf8504236c7c52466c21835f41..3bb2cde6f8429068cc104063f9e766d49ed0d5b9 100644
--- a/pub/lib/file_out.cpp
+++ b/pub/lib/file_out.cpp
@@ -46,7 +46,7 @@ void NFileOut::save( string fmt, bool allow_overwrite )
         f->name = outfnam;
         outfnam += "."+fmt;
         // document file save
-        f->lDoc.push_back( "fs " + outfnam + " # " + triv::time2strg( time(0) ) );
+        f->log_action( "fs " + outfnam + " # " + triv::time2strg( time(0) ) );
         // prevent unintended overwriting
         if( !allow_overwrite ){
             FILE *file;
@@ -151,13 +151,13 @@ void NFileOut::save_yda( std::ofstream& ofs, const COlo *f )
         }
         out << YAML::EndSeq;
         if   ( fd ) {
-            const CSpec *sd = fd->VS(j).get();
+            const CSpec *sd = fd->VS(j);
             out << YAML::Key << "x" << YAML::Value << YAML::Flow << sd->x;
             out << YAML::Key << "y" << YAML::Value << YAML::Flow << sd->y;
             if( sd->has_dy() )
                 out << YAML::Key << "dy" << YAML::Value << YAML::Flow << sd->dy;
         } else {
-            const CCurve *sc = fc->VC(j).get();
+            const CCurve *sc = fc->VC(j);
             out << YAML::Key << "p" << YAML::Value << YAML::Flow << sc->P;
             out << YAML::Key << "attr" << YAML::Value << YAML::Flow << sc->ParAttr;
             out << YAML::Key << "fitOutcome" << YAML::Value << sc->fitOutcome;
@@ -222,7 +222,7 @@ void NFileOut::save_y08( FILE *file, const COlo *f )
                 fprintf( file, "    z%i: %s\n", i, s->z[i]->to_s().c_str() );
         }
         if   ( fd ) {
-            const CSpec *s = fd->VS(j).get();
+            const CSpec *s = fd->VS(j);
             if( s->dy.size() ) {
                 fprintf( file, "    xyd: |2 # %i entries\n", (int)s->size() );
                 for( int i=0; i<s->size(); i++ )
@@ -235,7 +235,7 @@ void NFileOut::save_y08( FILE *file, const COlo *f )
                              s->x[i], s->y[i] );
             }
         } else {
-            CCurve *s = fc->VC(j).get();
+            CCurve *s = fc->VC(j);
             for ( int i=0; i<fc->nP; i++ )
                 fprintf( file, "    p%i: %18.10g\n", i, s->P[i] );
         }
diff --git a/pub/lib/fit.cpp b/pub/lib/fit.cpp
index b054db787c3863e9f1d304a1697113d716935f66..6b9c36d091ee1e7232f1a7a3121b4118c7b67ad1 100644
--- a/pub/lib/fit.cpp
+++ b/pub/lib/fit.cpp
@@ -183,14 +183,14 @@ static void fit_evaluate( const double* par, int m_dat, const void *data,
         COlc *fc = mydata->fc;
         const COld *fd = mydata->fd;
         COlc::TWgt wt = fc->weighing;
-        PCurve c = fc->VC(mydata->j);
+        CCurve* c = fc->VC(mydata->j);
 
         int ip = 0;
         for( int i=0; i<fc->nP; ++i )
             if ( fc->VC(mydata->j)->ParAttr[i]!='x' )
                 c->P[i] = par[ip++];
 
-        const CSpec *s = fd->VS(mydata->j).get();
+        const CSpec *s = fd->VS(mydata->j);
         bool want_error = wt==COlc::_VAR || wt==COlc::_VARC;
 
         RObj cu = fc->eval_curve( s->x, mydata->k, mydata->j, want_error );
@@ -217,8 +217,8 @@ string NCurveFit::fit_one_spec( COlc *fc, const COld *fd, int k, int j,
                                 const lm_control_struct& control )
 {
     try {
-        PSpec D = fd->VS(j);
-        PCurve C = fc->VC(j);
+        CSpec* D = fd->VS(j);
+        CCurve* C = fc->VC(j);
         if ( C->frozen )
             throw S("frozen, no fit");
         FitDatTyp data;
@@ -347,7 +347,7 @@ static void fit_evaluate_glo( const double* par, int m_dat, const void *data,
                                                       mydata->k, mydata->J2J[_jj], want_error );
                             return compute_residues(
                                 fvec, mydata->Offset[_jj], mydata->J2J[_jj],
-                                fd->VS(mydata->J2J[_jj]).get(), cu, wt );
+                                fd->VS(mydata->J2J[_jj]), cu, wt );
                         }, jj
                         )
                     );
@@ -363,7 +363,7 @@ static void fit_evaluate_glo( const double* par, int m_dat, const void *data,
                 RObj cu = fc->eval_curve( fd->VS(mydata->J2J[jj])->x,
                                           mydata->k, mydata->J2J[jj], want_error );
                 if ( compute_residues( fvec, mydata->Offset[jj], mydata->J2J[jj],
-                                       fd->VS(mydata->J2J[jj]).get(), cu, wt ) ) {
+                                       fd->VS(mydata->J2J[jj]), cu, wt ) ) {
                     *userbreak = -1;
                     return;
                 }
@@ -449,7 +449,7 @@ void NCurveFit::fit_global( COlc *fc, const COld *fd, int k, const lm_control_st
         fc->VC(j)->fitOutcome = (double) status.outcome;
 
         // compute deviation per spectrum:
-        const CSpec *s = fd->VS(j).get();
+        const CSpec *s = fd->VS(j);
         RObj cu = fc->eval_curve( s->x, k, j, want_error );
         int n = s->size();
         double *fvec = (double*) malloc( n*sizeof(double) );
@@ -528,9 +528,9 @@ void NCurveFit::fit( bool _allow_slow_conv )
             throw S("TODO: restore range evaluation");
             /*
             // overwrite fd with data that obye the range restriction:
-            POld fdr( fd->new_old() );
+            POld fdr( fd->new_POld() );
             for ( int j=0; j<fc->nJ(); j++ ) {
-                const CSpec *ein = fd->VS(j).get();
+                const CSpec *ein = fd->VS(j);
                 PSpec eout = PSpec( new CSpec );
                 eout->z = ein->z;
                 vector<double> range( ein->size() );
diff --git a/pub/lib/import.cpp b/pub/lib/import.cpp
index 50c67726768fbd2a4e27c75926efd2676076e21a..d124468f1c42aa6b355e6acf84499caec157a1c7 100644
--- a/pub/lib/import.cpp
+++ b/pub/lib/import.cpp
@@ -67,14 +67,14 @@ void NImport::read_tab( string qualif )
         cout << ".. reading from " << inFiles[iF] << "\n";
         POld fout( new COld );
         if( fromscript ) {
-            fout->lDoc.push_back( "ft"+qualif+" " + script );
+            fout->log_action( "ft"+qualif+" " + script );
             fout->name = script;
         } else {
             triv::fname_divide( inFiles[iF], &fdir, &fshort, &fext);
-            fout->lDoc.push_back( "ft"+qualif+" " + inFiles[iF] );
+            fout->log_action( "ft"+qualif+" " + inFiles[iF] );
             fout->name = fshort;
             if( choosecol ){
-                fout->lDoc.push_back( "y from column " + S(iycol) );
+                fout->log_action( "y from column " + S(iycol) );
                 fout->name += "_" + S(iycol);
             }
         }
@@ -113,7 +113,7 @@ void NImport::read_tab( string qualif )
 
             if( nline==-1 ) { // start of block
                 if( !horizontal && nblock!=0 && s && s->size()>0 )
-                    fout->V.push_back(s);
+                    fout->V.push_back( move(s) );
                 if ( multiblock ) {
                     if( !triv::str2vec(lin, &zdat, 0, false) )
                         throw "invalid header line [" + lin +
@@ -166,7 +166,7 @@ void NImport::read_tab( string qualif )
                 s->z[nz-1] = RObjInt( new CObjInt( nline ) );
                 for( int i=0; i<dat.size(); ++i )
                     s->push_xy( (double)i, dat[i] );
-                fout->V.push_back(s);
+                fout->V.push_back( move(s) );
             } else { // vertical
                 if( choosecol ){
                     if( iycol>=dat.size() )
@@ -193,7 +193,7 @@ void NImport::read_tab( string qualif )
         } // end of file input loop
 
         if( !horizontal && s && s->size()>0 )
-            fout->V.push_back(s);
+            fout->V.push_back( move(s) );
 
         if( !(fout->nJ()) )
             throw "no input lines";
@@ -227,7 +227,7 @@ void NImport::make_grid()
     if (nj>1) fnam += "x"+S(nj);
 
     fout->name = wask("Save as", fnam);
-    fout->lDoc.push_back( "fm " + S(ni) + " " + S(nj) );
+    fout->log_action( "fm " + S(ni) + " " + S(nj) );
 
     // *** set coordinates ***
     fout->xco = CCoord("x", "");
@@ -247,7 +247,7 @@ void NImport::make_grid()
 
         if (nj>1) s->z.push_back( RObjInt( new CObjInt(j) ) );
 
-        fout->V.push_back(s);
+        fout->V.push_back( move(s));
     }
 
     NOlm::mem_store( fout );
diff --git a/pub/lib/manip.cpp b/pub/lib/manip.cpp
index fd5b24aa59c1898f99159e81efa666e318e6b700..4e1fa26757912c718888bd85958e347b0136119d 100644
--- a/pub/lib/manip.cpp
+++ b/pub/lib/manip.cpp
@@ -53,7 +53,7 @@ void NManip::freeze_slices()
             throw S("not a valid index list");
         for ( int j=0; j<fio->nJ(); ++j )
             fio->V[j]->frozen = triv::contains( vsel->v, j );
-        fio->lDoc.push_back( "m/ " + sel );
+        fio->log_action( "m/ " + sel );
     }
 }
 
@@ -65,7 +65,7 @@ void NManip::unfreeze_all_slices()
     while ( COlo *fio = fiter.next() ) {
         for ( int j=0; j<fio->nJ(); ++j )
             fio->V[j]->frozen = false;
-        fio->lDoc.push_back( "m/-" );
+        fio->log_action( "m/-" );
     }
 }
 
@@ -86,10 +86,10 @@ void NManip::points_select( bool sel_del )
     RNode Tsel = user_xaxparse( sel.c_str() );
 
     while ( const COld *fin = fiter.nextD() ) {
-        POld fout( fin->new_old() );
-        fout->lDoc.push_back( "mp" + string( sel_del ? "d" : "r" ) + " " + sel );
+        POld fout( fin->new_POld() );
+        fout->log_action( "mp" + string( sel_del ? "d" : "r" ) + " " + sel );
         for ( int j=0; j<fin->nJ(); j++ ) {
-            const CSpec *sin = fin->VS(j).get();
+            const CSpec *sin = fin->VS(j);
             PSpec sout( new CSpec );
             sout->z = sin->z;
             RObjVecInt vsel = Tsel->to_index_list( sin->size() );
@@ -104,7 +104,7 @@ void NManip::points_select( bool sel_del )
                 }
             }
             if ( sout->size() )
-                fout->V.push_back( sout );
+                fout->V.push_back( move(sout) );
         }
         if ( !fout->V.size() )
             throw S("no data point left");
@@ -126,11 +126,11 @@ void NManip::points_rebin()
     RNode Tsel = user_xaxparse( sel.c_str() );
 
     while ( const COld *fin = fiter.nextD() ) {
-        POld fout( fin->new_old() );
-        fout->lDoc.push_back("mpa " + sel);
+        POld fout( fin->new_POld() );
+        fout->log_action("mpa " + sel);
 
         for ( int j=0; j<fin->nJ(); j++ ) {
-            const CSpec *sin = fin->VS(j).get();
+            const CSpec *sin = fin->VS(j);
             RObjVecInt vsel = Tsel->to_index_list( sin->size() );
             if (!vsel)
                 throw S("not a valid index list");
@@ -143,7 +143,7 @@ void NManip::points_rebin()
 
             PSpec sout = sin->binned( breaks );
 
-            fout->V.push_back(sout);
+            fout->V.push_back( move(sout) );
         }
         NOlm::mem_store( fout, fiter.k() );
     }
@@ -161,11 +161,11 @@ void NManip::points_rebin_by_factor()
         throw S("invalid choice");
 
     while ( const COld *fin = fiter.nextD() ) {
-        POld fout( fin->new_old() );
-        fout->lDoc.push_back( "mpaf " + S(ng) );
+        POld fout( fin->new_POld() );
+        fout->log_action( "mpaf " + S(ng) );
 
         for ( int j=0; j<fin->nJ(); j++ ) {
-            const CSpec* sin = fin->VS(j).get();
+            const CSpec* sin = fin->VS(j);
 
             int nout = sin->size() / ng;
             if ( nout<1 )
@@ -176,7 +176,7 @@ void NManip::points_rebin_by_factor()
 
             PSpec sout = sin->binned( breaks );
 
-            fout->V.push_back(sout);
+            fout->V.push_back( move(sout) );
         }
         NOlm::mem_store( fout, fiter.k() );
     }
@@ -200,10 +200,10 @@ void NManip::points_rebin_by_err( const string& subcmd )
     errbound = dask( "Keep error below", errbound );
 
     while ( const COld *fin = fiter.nextD() ) {
-        POld fout( fin->new_old() );
+        POld fout( fin->new_POld() );
         string groupinfo;
         for ( int j=0; j<fin->nJ(); j++ ) {
-            const CSpec *sin = fin->VS(j).get();
+            const CSpec *sin = fin->VS(j);
             PSpec sout( new CSpec() );
             sout->z = sin->z;
             if ( !sin->has_dy() )
@@ -228,12 +228,12 @@ void NManip::points_rebin_by_err( const string& subcmd )
                 }
             }
             if ( sout->size() )
-                fout->V.push_back(sout);
+                fout->V.push_back( move(sout) );
         }
         string docline = "mpae" + subcmd + " " + S(errbound);
         if ( fin->nJ()==1 )
             docline += " #=> groups " + groupinfo.substr(0,groupinfo.size()-1);
-        fout->lDoc.push_back( docline );
+        fout->log_action( docline );
         if ( fout->nJ() )
             NOlm::mem_store( fout, fiter.k() );
 
@@ -254,11 +254,11 @@ void NManip::points_sort()
 
     while ( const COld *fin = fiter.nextD() ) {
         int k = fiter.k();
-        POld fout( fin->new_old() );
-        fout->lDoc.push_back("mpo "+expr);
+        POld fout( fin->new_POld() );
+        fout->log_action("mpo "+expr);
 
         for ( int j=0; j<fin->nJ(); j++ ) {
-            const CSpec *sin = fin->VS(j).get();
+            const CSpec *sin = fin->VS(j);
             PSpec sout( new CSpec );
             sout->z = sin->z;
 
@@ -273,7 +273,7 @@ void NManip::points_sort()
                 if ( sin->has_dy() )
                     sout->dy[i] = sin->dy[P[i]];
             }
-            fout->V.push_back( sout );
+            fout->V.push_back( move(sout) );
         }
         NOlm::mem_store( fout, fiter.k() );
     }
@@ -287,11 +287,11 @@ void NManip::points_rebin_duplicates()
     FileIterator fiter(NSel::selD());
     COld fout;
     while ( const COld *fin = fiter.nextD() ) {
-        POld fout( fin->new_old() );
-        fout->lDoc.push_back("mpq # average points when x equal");
+        POld fout( fin->new_POld() );
+        fout->log_action("mpq # average points when x equal");
 
         for ( int j=0; j<fin->nJ(); j++ ) {
-            const CSpec *sin = fin->VS(j).get();
+            const CSpec *sin = fin->VS(j);
             PSpec sout( new CSpec );
             sout->z = sin->z;
 
@@ -316,7 +316,7 @@ void NManip::points_rebin_duplicates()
                 else
                     sout->push_xy(xg, yg/ng);
             }
-            fout->V.push_back( sout );
+            fout->V.push_back( move(sout) );
         }
         NOlm::mem_store( fout, fiter.k() );
     }
@@ -335,12 +335,12 @@ void NManip::points_symmetrize()
 
     while ( const COld *fin = fiter.nextD() ) {
         int k = fiter.k();
-        POld fout( fin->new_old() );
-        fout->lDoc.push_back("mpsym "+expr);
+        POld fout( fin->new_POld() );
+        fout->log_action("mpsym "+expr);
 
         for (int j=0; j<fin->nJ(); j++) {
             int n, i, il, ih, nl, nh;
-            const CSpec *sin = fin->VS(j).get();
+            const CSpec *sin = fin->VS(j);
             PSpec sout( new CSpec );
             sout->z = sin->z;
             if ( !triv::is_ascending( sin->x ) )
@@ -379,7 +379,7 @@ void NManip::points_symmetrize()
                         sout->push_xy( -sin->x[il-i], sin->y[il-i] );
             }
             sout->z = sin->z;
-            fout->V.push_back(sout);
+            fout->V.push_back( move(sout) );
         }
         NOlm::mem_store( fout, fiter.k() );
     }
@@ -391,15 +391,15 @@ void NManip::points_remove_err()
 {
     FileIterator fiter(NSel::selD());
     while ( const COld *fin = fiter.nextD() ) {
-        POld fout( fin->new_old() );
-        fout->lDoc.push_back("mpe-");
+        POld fout( fin->new_POld() );
+        fout->log_action("mpe-");
         for (int j=0; j<fin->nJ(); j++) {
-            const CSpec *sin = fin->VS(j).get();
+            const CSpec *sin = fin->VS(j);
             PSpec sout( new CSpec );
             sout->z = sin->z;
             sout->x = sin->x;
             sout->y = sin->y;
-            fout->V.push_back(sout);
+            fout->V.push_back( move(sout) );
         }
         NOlm::mem_store( fout, fiter.k() );
     }
@@ -444,13 +444,13 @@ void NManip::slices_select( bool sel_del )
 
     FileIterator fiter(NSel::sel());
     while ( const COlo *fin = fiter.next() ) {
-        POlo fout( fin->new_olo() );
+        POlo fout( fin->new_POlo() );
         // JSel.evaluate( 0, fin->nJ()-1 );
-        fout->lDoc.push_back( "ms" + string( sel_del ? "d" : "r" ) +
+        fout->log_action( "ms" + string( sel_del ? "d" : "r" ) +
                               " " + triv::indices_to_s(JSel) );
         for ( int j=0; j<fin->nJ(); ++j ) {
             if ( sel_del ^ triv::contains(JSel, j ) ) {
-                fout->V.push_back( fin->new_slice( j ) );
+                fout->V.push_back( fin->copy_slice( j ) );
             }
         }
         ScaRemoveConstantZ( fout.get() );
@@ -472,11 +472,11 @@ void NManip::slices_rebin()
             throw S("Only one slice in file");
         const COld *fd = dynamic_cast<const COld*>( fin );
         const COlc *fc = dynamic_cast<const COlc*>( fin );
-        POlo fout( fin->new_olo() );
+        POlo fout( fin->new_POlo() );
         // JSel.evaluate( 0, fin->nJ()-1 );
         if ( JSel.size()<1 || JSel[0]!=0 )
             throw S("spectrum selection must contain 0");
-        fout->lDoc.push_back("msa " + triv::indices_to_s(JSel));
+        fout->log_action("msa " + triv::indices_to_s(JSel));
         for ( int iv=0; iv<JSel.size(); iv++ ) {
             int ji = JSel[iv];
             int jf = iv<JSel.size()-1 ? JSel[iv+1] : fin->nJ();
@@ -548,7 +548,7 @@ void NManip::slices_rebin()
                 }
                 for ( int iz=0; iz<nz; ++iz )
                     sout->z.push_back( PObjDbl( new CObjDbl(zout[iz]) ) );
-                fout->V.push_back( sout );
+                fout->V.push_back( move(sout) );
             } else if ( fc ) {
                 PCurve cout( new CCurve );
                 int np = fc->nP;
@@ -566,7 +566,7 @@ void NManip::slices_rebin()
                 for ( int iz=0; iz<nz; ++iz )
                     cout->z.push_back( PObjDbl( new CObjDbl(zout[iz]) ) );
                 cout->ParAttr.resize( np, 'u' );
-                fout->V.push_back( cout );
+                fout->V.push_back( move(cout) );
             }
         }
         ScaRemoveConstantZ( fout.get() );
@@ -585,11 +585,11 @@ void NManip::slices_merge()
     JSelAsk( "Start groups at spectra", JSel );
 
     while ( const COld *fin = fiter.nextD() ) {
-        POld fout( fin->new_old() );
+        POld fout( fin->new_POld() );
         // JSel.evaluate( 0, fin->nJ()-1 );
         if (JSel.size()<1 || JSel[0]!=0)
             throw S("spectrum selection must contain 0");
-        fout->lDoc.push_back("msj " + triv::indices_to_s(JSel));
+        fout->log_action("msj " + triv::indices_to_s(JSel));
         cout << "WARNING: z just taken from first spectrum of each group\n";
         for ( int iv=0; iv<JSel.size(); iv++ ) {
             int ji, jf;
@@ -606,7 +606,7 @@ void NManip::slices_merge()
                     else
                         sout->push_xy( fin->VS(jj)->x[i], fin->VS(jj)->y[i] );
             }
-            fout->V.push_back(sout);
+            fout->V.push_back( move(sout) );
         }
         ScaRemoveConstantZ( fout.get() );
         NOlm::mem_store( fout, fiter.k() );
@@ -625,16 +625,16 @@ void NManip::slices_spawn()
     njj = njjIn;
 
     while ( const COlo *fin = fiter.next() ) {
-        POlo fout( fin->new_olo() );
-        fout->lDoc.push_back( "ms* " + S(njj) );
+        POlo fout( fin->new_POlo() );
+        fout->log_action( "ms* " + S(njj) );
 
         fout->ZCo.insert( fout->ZCo.begin(), CCoord("no-in-spawn", ""));
 
         for ( int jj=0; jj<njj; ++jj ) {
             for ( int j=0; j<fin->nJ(); j++ ) {
-                PSlice eout = fin->new_slice( j );
+                PSlice eout = fin->copy_slice( j );
                 eout->z.insert( eout->z.begin(), PObjInt( new CObjInt( jj ) ) );
-                fout->V.push_back( eout );
+                fout->V.push_back( move(eout) );
             }
         }
         NOlm::mem_store( fout, fiter.k() );
@@ -648,12 +648,11 @@ void NManip::exchange_x_z()
 {
     FileIterator fiter(NSel::selD());
     while ( const COld *fin = fiter.nextD() ) {
-        POld fout( fin->new_old() );
-
         int izco = fin->ZCo.size() - 1;
         if ( izco==(int)-1 )
             throw S("no input z coordinate");
-        fout->lDoc.push_back(
+        POld fout( fin->new_POld() );
+        fout->log_action(
             "msx # exchanging x=" + fin->xco.str_compact() +
             " with z" + S(izco) + "=" + fin->ZCo[izco].str_compact() );
         fout->xco = fin->ZCo[izco];
@@ -702,7 +701,7 @@ void NManip::exchange_x_z()
                     }
                 }
                 for ( int j=ji; j<jf; ++j ) {
-                    PSpec sin = fin->VS( j );
+                    const CSpec* sin = fin->VS( j );
                     if ( sin->x[ii]!=xcommon[i] ) { // guess failed
                         for (ii=0; ii<sin->size(); ++ii)
                             if ( sin->x[ii]==xcommon[i] )
@@ -715,7 +714,7 @@ void NManip::exchange_x_z()
                             sout->push_xy( sin->z[izco]->to_r(), sin->y[ii] );
                     }
                 }
-                fout->V.push_back( sout );
+                fout->V.push_back( move(sout) );
                 ++ii;
             }
             ji = jf;
@@ -735,8 +734,8 @@ void NManip::slices_sort()
     RNode T = user_xaxparse( expr.c_str() );
 
     while ( const COlo *fin = fiter.next() ) {
-        POlo fout( fin->new_olo() );
-        fout->lDoc.push_back( "mso "+expr );
+        POlo fout( fin->new_POlo() );
+        fout->log_action( "mso "+expr );
 
         int nj = fin->nJ();
         vector<double> v(nj);
@@ -745,7 +744,7 @@ void NManip::slices_sort()
 
         vector<size_t> P = triv::sorted_indices( v );
         for (int j=0; j<nj; j++)
-            fout->V.push_back( fin->new_slice( P[j] ) );
+            fout->V.push_back( fin->copy_slice( P[j] ) );
 
         NOlm::mem_store( fout, fiter.k() );
     }
@@ -758,9 +757,10 @@ void NManip::slices_sort_by_z()
 {
     FileIterator fiter(NSel::sel());
     while ( const COlo *fin = fiter.next() ) {
-        POlo fout( fin->new_olo() );
+        POlo fout( fin->new_POlo() );
+        fout->log_action( "msoz" );
         for (int j=0; j<fin->nJ(); j++)
-            fout->V.push_back( fin->new_slice( j ) );
+            fout->V.push_back( fin->copy_slice( j ) );
         sort( fout->V.begin(), fout->V.end(), []( const PSlice& E1, const PSlice& E2 ) {
                 if( E1->z.size()!=E2->z.size() )
                     throw S("BUG: inconsistent z.size in CompareZ");
@@ -833,10 +833,10 @@ void NManip::zcoords_reorder()
 
     fiter.reset();
     while ( const COlo *fin = fiter.next() ) {
-        POlo fout( fin->new_olo() );
-        fout->lDoc.push_back( com );
+        POlo fout( fin->new_POlo() );
+        fout->log_action( com );
         for (int j=0; j<fin->nJ(); j++)
-            fout->V.push_back( fin->new_slice( j ) );
+            fout->V.push_back( fin->copy_slice( j ) );
 
         int nz = fout->ZCo.size();
         if      ( nz<nzmin ) {
@@ -892,13 +892,13 @@ void NManip::zcoord_delete()
     RNode Tsel = user_xaxparse( sel.c_str() );
 
     while ( const COlo *fin = fiter.next() ) {
-        POlo fout( fin->new_olo() );
-        fout->lDoc.push_back( "mz- "+sel );
+        POlo fout( fin->new_POlo() );
+        fout->log_action( "mz- "+sel );
 
         if ( !fin->nJ() )
             throw S("BUG: no spectra");
         for ( int j=0; j<fin->nJ(); j++ )
-            fout->V.push_back( fin->new_slice( j ) );
+            fout->V.push_back( fin->copy_slice( j ) );
 
         RObjVecInt vsel = Tsel->to_index_list( fin->ZCo.size() );
         if (!vsel)
@@ -938,20 +938,21 @@ void NManip::slices_break()
         CCoord zco = fin->ZCo[0];
 
         // intermediate file, on which output files will be based:
-        POlo ftmp( fin->new_olo() );
+        POlo ftmp( fin->new_POlo() );
         ftmp->V.clear();
-        ftmp->lDoc.push_back( "msb # eliminating " + zco.str_compact() );
+        ftmp->log_action( "msb # eliminating " + zco.str_compact() );
         ftmp->ZCo.erase( ftmp->ZCo.begin() );
         int jout = 0;
 
         for ( int j=0; j<fin->nJ(); ) {
-            POlo fout( ftmp->new_olo() );
+            POlo fout( ftmp->new_POlo() );
+            fout->log_action( "msb" );
             double zval = ftmp->z(j,0)->to_r();
             fout->RPar.push_back( CParam( zco, zval ) );
             do {
-                PSlice eout( fin->new_slice(j) );
+                PSlice eout( fin->copy_slice(j) );
                 eout->z.erase( eout->z.begin() );
-                fout->V.push_back( eout );
+                fout->V.push_back( move(eout) );
             } while ( ++j<fin->nJ() && fin->z(j,0)->to_r()==zval );
             fout->name += "_" + S(jout++);
             NOlm::mem_store( fout );
@@ -1083,20 +1084,20 @@ void NManip::files_merge( const string& opts )
     fout->name = fnam;
 
     // doc lines:
-    fout->lDoc.push_back( "mfj # " + fnam + " is merger of:" );
+    fout->log_action( "mfj # " + fnam + " is merger of:" );
     fiter.reset();
     const COlo *f1 = fiter.next();
-    fout->lDoc.push_back("- " + f1->name);
+    fout->log_action("- " + f1->name);
     for ( int i=0; i<f1->lDoc.size(); ++i )
-        fout->lDoc.push_back("  " + f1->lDoc[i]);
+        fout->log_action("  " + f1->lDoc[i]);
     while ( (fin = fiter.next()) ) {
-        fout->lDoc.push_back("- " + fin->name);
+        fout->log_action("- " + fin->name);
         string line = "  ";
         for ( int i=0; i<fin->lDoc.size(); ++i ) {
             if ( i<f1->lDoc.size() && fin->lDoc[i]==f1->lDoc[i] ) {
                 line += "=";
             } else {
-                fout->lDoc.push_back( line + fin->lDoc[i] );
+                fout->log_action( line + fin->lDoc[i] );
                 line = "  ";
             }
         }
@@ -1106,14 +1107,14 @@ void NManip::files_merge( const string& opts )
     fiter.reset();
     while ( fin = fiter.next() ) {
         for ( int j=0; j<fin->nJ(); j++ ) {
-            PSlice eout( fin->new_slice(j) );
+            PSlice eout( fin->copy_slice(j) );
             auto zinsert=eout->z.begin();
             for ( int i=0; i<nR; ++i )
                 if ( RParDiff[i] )
                     eout->z.insert( zinsert++, PObjDbl( new CObjDbl( fin->RPar[i].val ) ) );
             if ( add_zk )
                 eout->z.insert( eout->z.begin(), PObjInt( new CObjInt( fiter.iteration() ) ) );
-            fout->V.push_back( eout );
+            fout->V.push_back( move(eout) );
         }
     }
 
@@ -1132,7 +1133,7 @@ void NManip::files_merge_pointwise()
     FileIterator fiter(NSel::selD());
     // Copy first input file:
     const COld *fin = fiter.nextD();
-    POld fout( fin->new_old() );
+    POld fout( fin->new_POld() );
     fout->copy_mainvec( fin );
 
     // Merge further input files:
@@ -1143,8 +1144,8 @@ void NManip::files_merge_pointwise()
             throw S("different x/y coordinates");
 
         for ( int j=0; j<fout->nJ(); ++j ) {
-            const CSpec *sin = fin->VS(j).get();
-            PSpec sout = fout->VS(j);
+            const CSpec *sin = fin->VS(j);
+            CSpec* sout = fout->VS(j);
             if ( sin->z.size() != sout->z.size() )
                 throw S("different # z entries");
             for ( int i=0; i<sout->z.size(); ++i )
@@ -1159,8 +1160,7 @@ void NManip::files_merge_pointwise()
                     sout->push_xy( sin->x[i], sin->y[i] );
             }
         }
-
-        fout->lDoc.push_back( "appended pointwise " + fin->name );
+        fout->log_action( "appended pointwise " + fin->name );
     }
 
     NOlm::mem_store( fout );
@@ -1183,19 +1183,18 @@ void NManip::interpolate()
     FileIterator fiter(NSel::selD());
     while ( const COld *fin = fiter.nextD() ) {
         int k = fiter.k();
-        POld fout( fin->new_old() );
-        fout->copy_mainvec( fin );
-
         CContext ctx( k );
         int k2 = T->tree_val_idx( ctx, "K" );
         COld *f2 = NOlm::mem_get_D( k2 );
 
-        fout->lDoc.push_back( "mi " + S(k2) );
+        POld fout( fin->new_POld() );
+        fout->copy_mainvec( fin );
+        fout->log_action( "mi " + S(k2) );
 
         for ( int j=0; j<fin->nJ(); j++ ) {
-            const CSpec *sin = fin ->VS(j).get();
-            PSpec s2  = f2  ->VS(j);
-            PSpec sout= fout->VS(j);
+            const CSpec *sin = fin ->VS(j);
+            CSpec* s2  = f2  ->VS(j);
+            CSpec* sout= fout->VS(j);
             int i2 = 0;
             if ( sin->y[0]<s2->x[0] )
                 throw "File "+S(k)+", spec "+S(j)+": y[0] not in reference";
@@ -1239,7 +1238,7 @@ void NManip::make_histogram()
     FileIterator fiter(NSel::selD());
     while ( const COld *fin = fiter.nextD() ) {
         for ( int j=0; j<fin->nJ(); j++ ) {
-            const CSpec *sin = fin ->VS(j).get();
+            const CSpec *sin = fin ->VS(j);
             for ( int i=0; i<sin->size(); i++ ) {
                 double x = sin->x[i];
                 if ( !npts ) {
@@ -1274,11 +1273,11 @@ void NManip::make_histogram()
     // Create and fill output histograms:
     fiter.reset();
     while ( const COld *fin = fiter.nextD() ) {
-        POld fout( fin->new_old() );
-        fout->lDoc.push_back("mhm " + S(nbin) );
+        POld fout( fin->new_POld() );
+        fout->log_action("mhm " + S(nbin) );
 
         for ( int j=0; j<fin->nJ(); j++ ) {
-            const CSpec *sin = fin->VS(j).get();
+            const CSpec *sin = fin->VS(j);
             PSpec sout( new CSpec() );
             sout->z = sin->z;
             sout->x = xout;
@@ -1289,7 +1288,7 @@ void NManip::make_histogram()
                     throw "BUG: invalid iout="+S(iout)+" for y="+S(sin->x[i]);
                 sout->y[iout] += sin->y[i];
             }
-            fout->V.push_back(sout);
+            fout->V.push_back( move(sout) );
         }
         NOlm::mem_store( fout, fiter.k() );
     }
diff --git a/pub/lib/mem.cpp b/pub/lib/mem.cpp
index 0744dfc4b9ad1f7f64a3dc86d430bc4e1796816e..bdf7454fdb1308d51ecdb71f277ca8fa4acc3fe4 100644
--- a/pub/lib/mem.cpp
+++ b/pub/lib/mem.cpp
@@ -119,7 +119,7 @@ namespace NOlm {
     {
         FileIterator fiter(NSel::sel());
         while ( const COlo *fin=fiter.next() ){
-            POlo fout( fin->new_olo( false ) );
+            POlo fout( fin->new_POlo() );
             fout->copy_mainvec( fin );
             mem_store( fout );
         }
@@ -143,7 +143,7 @@ namespace NOlm {
         BAK.clear();
         FileIterator fiter(NSel::sel());
         while ( const COlo *fin=fiter.next() ){
-            POlo fout( fin->new_olo( false ) );
+            POlo fout( fin->new_POlo() );
             fout->copy_mainvec( fin );
             BAK.push_back( POlo() );
             BAK.back().swap( fout ); // TODO: simplify!
diff --git a/pub/lib/node.cpp b/pub/lib/node.cpp
index 2f1505eedbfda9d3b1552d1ae2238a0f8ee27555..1ba2200b6f6dc5a66cf649d5bb9ab3c6cd25207f 100644
--- a/pub/lib/node.cpp
+++ b/pub/lib/node.cpp
@@ -844,7 +844,7 @@ RObj CNodeCurve::tree_val_scalar( const CContext& ctx ) const
     if ( !fc )
         throw f->type()+" file has no property "+tree_info();
     int j = PCAST<const CRef2>(ref)->get_j( ctx, f->nJ() );
-    return curve_val_scalar( fc->VC(j).get() );
+    return curve_val_scalar( fc->VC(j) );
 }
 
 
@@ -921,7 +921,7 @@ RObj CNodePoint::tree_val_point( const CContext& ctx, int i ) const
     if ( !fd )
         throw f->type()+" file has no property "+tree_info();
     int j = PCAST<const CRef2>(ref)->get_j( ctx, f->nJ() );
-    const CSpec *s = fd->VS(j).get();
+    const CSpec *s = fd->VS(j);
     if ( i<0 || i>= s->size() )
         throw "invalid data point index "+S(i)+", spectrum has length "+S(s->size());
     return spec_val_point( s, i, ctx.want_error );
@@ -937,7 +937,7 @@ RObj CNodePoint::tree_val_vector( const CContext& ctx ) const
     if ( !fd )
         throw f->type()+" file has no property "+tree_info();
     int j = PCAST<const CRef2>(ref)->get_j( ctx, f->nJ() );
-    const CSpec *s = fd->VS(j).get();
+    const CSpec *s = fd->VS(j);
     int n = ctx.nv;
     if ( n<0 ) // ctx.nv=-1 is used in integral operations
         n = s->size();
diff --git a/pub/lib/olf.cpp b/pub/lib/olf.cpp
index 4c4351d04561cf73f7dae5d05676d7cad37e217e..c500710883e784ea35d0ee163ed47cca960f93dd 100644
--- a/pub/lib/olf.cpp
+++ b/pub/lib/olf.cpp
@@ -36,6 +36,36 @@ using boost::format;
 //**************************************************************************************************
 
 
+//! Constructor.
+
+COlo::COlo() : as_on_disk(false) {}
+
+//! Destructor magic: makes dynamic_cast possible.
+
+COlo::~COlo() {}
+
+//! Copy meta data.
+
+void COlo::copy_meta_O_from_other( const COlo* other )
+{
+    lDoc = other->lDoc;
+    xco = other->xco;
+    yco = other->yco;
+    ZCo = other->ZCo;
+    RPar = other->RPar;
+    as_on_disk = other->as_on_disk;
+}
+
+
+//! Append a line to the log; set as_on_disk to false.
+
+void COlo::log_action( const string& line )
+{
+    lDoc.push_back( line );
+    as_on_disk = false;
+}
+
+
 //! Remove one z.
 
 void COlo::remove_z( int iz )
@@ -79,52 +109,85 @@ RObj COlo::z( int j, int iz ) const
 
 
 //**************************************************************************************************
-//*  trivially duplicated COld/COlc functions
+//*  COld/COlc (member functions that are similar for both classes)
 //**************************************************************************************************
 
+//! Copy meta data.
 
-//! Duplicate spectrum j, and return new shared pointer.
+void COld::copy_meta_D_from_other( const COld* other )
+{
+    copy_meta_O_from_other( other );
+}
 
-PSlice COld::new_slice( int j ) const
+
+//! Copy meta data.
+
+void COlc::copy_meta_C_from_other( const COlc* other )
+{
+    copy_meta_O_from_other( other );
+    expr = other->expr;
+    T = other->T;
+    nP = other->nP;
+    PCo = other->PCo;
+    kd = other->kd;
+    kconv = other->kconv;
+    weighing = other->weighing;
+    plot_to_grid = other->plot_to_grid;
+    range_expr = other->range_expr;
+    range_T = other->range_T;
+    chi2 = other->chi2;
+}
+
+
+//! Returns unique_ptr to new copy of spectrum j.
+
+PSlice COld::copy_slice( int j ) const
 {
     return PSlice( new CSpec( *(VS(j)) ) );
 }
 
 
-//! Duplicate curve j, and return new shared pointer.
+//! Returns unique_ptr to new copy of curve j.
 
-PSlice COlc::new_slice( int j ) const
+PSlice COlc::copy_slice( int j ) const
 {
     return PSlice( new CCurve( *(VC(j)) ) );
 }
 
 
-//! New shared pointer to copied online file (but without copying main vector).
+//! Returns pointer to new copy of this.
 
-POlo COld::new_olo( bool modified ) const
+POlo COld::new_POlo() const
 {
-    POlo ret( new COld( *this ) );
-    ret->V.clear(); // TODO: this is inefficient; don't copy then delete.
-    ret->as_on_disk = as_on_disk && !modified;
-    return ret;
+    return POlo( new_POld() );
 }
 
-POlo COlc::new_olo( bool modified ) const
+
+//! Returns pointer to new copy of this.
+
+POlo COlc::new_POlo() const
 {
-    POlo ret( new COlc( *this ) );
-    ret->V.clear();
-    ret->as_on_disk = as_on_disk && !modified;
-    return ret;
+    return POlo( new_POlc() );
 }
 
-POld COld::new_old( bool modified ) const // TODO improve this scandalous workaround
+
+//! Returns pointer to new copy of this.
+
+POld COld::new_POld() const
 {
-    return POld( dynamic_cast<COld*>(new_olo( modified ).release() ) );
+    COld *old = new COld();
+    old->copy_meta_D_from_other( this );
+    return POld( old );
 }
 
-POlc COlc::new_olc( bool modified ) const // TODO improve this scandalous workaround
+
+//! Returns pointer to new copy of this.
+
+POlc COlc::new_POlc() const
 {
-    return POlc( dynamic_cast<COlc*>(new_olo( modified ).release() ) );
+    COlc *olc = new COlc();
+    olc->copy_meta_C_from_other( this );
+    return POlc( olc );
 }
 
 
@@ -152,21 +215,21 @@ void COlc::copy_mainvec( const COlo *fin )
 
 //! Return pointer to selected main vector entry.
 
-PSpec COld::VS( int j ) const
+CSpec* COld::VS( int j ) const
 {
     if( j<0 || j>=V.size() )
         throw "VS call with j=" + S(j) + " though V.size=" + S(V.size());
-    PSpec s = std::dynamic_pointer_cast<class CSpec>( V[j] );
+    CSpec *s = dynamic_cast<class CSpec*>( V[j].get() );
     if ( !s )
         throw "BUG: file "+S(j)+" does not contain data";
     return s;
 }
 
-PCurve COlc::VC( int j ) const
+CCurve* COlc::VC( int j ) const
 {
     if( j<0 || j>=V.size() )
         throw "VC call with j=" + S(j) + " though V.size=" + S(V.size());
-    PCurve c = std::dynamic_pointer_cast<class CCurve>( V[j] );
+    CCurve *c = dynamic_cast<class CCurve*>( V[j].get() );
     if ( !c )
         throw "BUG: file "+S(j)+" does not contain curves";
     return c;
@@ -331,8 +394,10 @@ int COld::nPts() const
 
 bool COld::has_nonzero_dy() const
 {
-    return std::all_of( V.cbegin(), V.cend(),
-                        [](const PSlice& s){ return (PCAST<const CSpec>(s))->has_nonzero_dy(); } );
+    return std::all_of(
+        V.cbegin(), V.cend(),
+        [](const PSlice& s){ return dynamic_cast<const CSpec*>(s.get())->has_nonzero_dy(); }
+        );
 }
 
 //**************************************************************************************************
diff --git a/pub/lib/olf.hpp b/pub/lib/olf.hpp
index 26c8b16b442989644d491589ad0d4e53630a4247..c3acc79e4b7849456b3b9e304e6b8d23655394f7 100644
--- a/pub/lib/olf.hpp
+++ b/pub/lib/olf.hpp
@@ -16,20 +16,24 @@ class CGenus;
 
 class COlo {
  public:
-    // Data records:
-    vector<PSlice> V;
+    // Meta data:
     string name;
     vector<string> lDoc;
     CCoord xco, yco;
     vector<CCoord> ZCo;
     vector<CParam> RPar;
-
-    // Online state records:
     bool as_on_disk;
 
-    COlo() : as_on_disk(false) {}
-    virtual ~COlo() {} ///< magic: makes dynamic_cast possible
+    // Core data:
+    vector<PSlice> V;
 
+    COlo();
+    COlo& operator=( const COlo& ) = delete;
+    COlo(const COlo&) = delete;
+    virtual ~COlo(); ///< magic: makes dynamic_cast possible
+
+    void copy_meta_O_from_other( const COlo* from );
+    void log_action( const string& line );
     void remove_z( int iz );
     string info_line( int j ) const;
     void check_integrity() const;
@@ -39,8 +43,8 @@ class COlo {
     int nJ() const { return V.size(); }
     int nZ() const { return ZCo.size(); }
     RObj z( int j, int iz ) const;
-    virtual PSlice new_slice( int j ) const = 0;
-    virtual POlo new_olo( bool modified=true ) const = 0;
+    virtual PSlice copy_slice( int j ) const = 0;
+    virtual POlo new_POlo() const = 0;
     virtual CCoord coord( const CGenus& genus ) const = 0;
     virtual void set_coord( const CGenus& genus, CCoord& co ) = 0;
     virtual string type() const = 0;
@@ -54,11 +58,12 @@ class COld : public COlo {
     COld() : COlo() {}
     explicit COld( class COlc const* fc );
 
-    // Trivially duplicated functions:
-    PSpec VS( int j ) const;
-    PSlice new_slice( int j ) const;
-    POlo new_olo( bool modified=true ) const;
-    POld new_old( bool modified=true ) const;
+    // Functions that exist similarly for COld and COlc:
+    void copy_meta_D_from_other( const COld* other );
+    CSpec* VS( int j ) const;
+    PSlice copy_slice( int j ) const;
+    POlo new_POlo() const;
+    POld new_POld() const;
     void copy_mainvec( const COlo *fin );
 
     // Overloaded functions:
@@ -82,7 +87,7 @@ class COlc : public COlo {
     RObjVec eval_curve_expr( const vector<double>& vt, int k, int j, bool want_error ) const;
     RObjVec eval_curve_syscall( const vector<double>& vt, int k, int j, bool want_error ) const;
 
-public:
+ public:
     // Function:
     enum TEva    { _EXPR, _SCR, _SCR_INTP } evaMode; ///< How curve is defined
     enum TScrInp { _STDIN, _CMDLIN } scrInpMode; ///< Where pars are read from
@@ -109,11 +114,12 @@ public:
         COlo(), evaMode(_EXPR), scrInpMode(_STDIN), kd(-1), kconv(-1), weighing( _VAR ),
         plot_to_grid( false ), range_expr(""), chi2(0) {}
 
-    // Trivially duplicated functions:
-    PCurve VC( int j ) const;
-    PSlice new_slice( int j ) const;
-    POlo new_olo( bool modified=true ) const;
-    POlc new_olc( bool modified=true ) const;
+    // Functions that exist similarly for COld and COlc:
+    void copy_meta_C_from_other( const COlc* other );
+    CCurve* VC( int j ) const;
+    PSlice copy_slice( int j ) const;
+    POlo new_POlo() const;
+    POlc new_POlc() const;
     void copy_mainvec( const COlo *fin );
 
     // Overloaded functions:
diff --git a/pub/lib/opr.cpp b/pub/lib/opr.cpp
index 4e2a54b59f49de8b6e1dbcb6f74763b93c6aeaea..3fa32d3f058bcfd1cee9f209b3b277644b3d978f 100644
--- a/pub/lib/opr.cpp
+++ b/pub/lib/opr.cpp
@@ -65,7 +65,7 @@ void NOperate::show( const string& subcmd )
             outp = "";
 
             for( int j=0; j<fin->nJ(); j++ ){
-                const CSpec *s = fin->VS(j).get();
+                const CSpec *s = fin->VS(j);
                 if( i>= s->size() ) continue;
                 if ( ! T->tree_point_dbl( fiter.k(), j, i ) )
                     continue;
@@ -110,12 +110,12 @@ void NOperate::select( bool sel_del )
         const COld *fd = dynamic_cast<const COld*>( fin );
         const COlc *fc = dynamic_cast<const COlc*>( fin );
 
-        POlo fout( fin->new_olo() );
-        fout->lDoc.push_back((sel_del ? "md " : "mr ") + expr);
+        POlo fout( fin->new_POlo() );
+        fout->log_action((sel_del ? "md " : "mr ") + expr);
 
         for ( int j=0; j<fin->nJ(); j++ ) {
             if ( fd ) {
-                const CSpec *ein = fd->VS(j).get();
+                const CSpec *ein = fd->VS(j);
                 PSpec eout = PSpec( new CSpec );
                 eout->z = ein->z;
                 vector<double> lvec( ein->size() );
@@ -130,11 +130,11 @@ void NOperate::select( bool sel_del )
                     }
                 }
                 if ( eout->size() )
-                    fout->V.push_back( eout );
+                    fout->V.push_back( move(eout) );
             } else if ( fc ) {
                 PCurve eout = PCurve( new CCurve( *(fc->VC(j)) ) );
                 if ( sel_del ^ T->tree_point_val( fiter.k(), j )->to_b() )
-                    fout->V.push_back( eout );
+                    fout->V.push_back( move(eout) );
             }
         }
         if( !fout->nJ() )
@@ -170,10 +170,10 @@ void NOperate::Pointwise( string llabel )
         if( lref.categ==VCateg::CP && !fc )
             continue;
 
-        POlo fout( fin->new_olo() );
-
+        POlo fout( fin->new_POlo() );
         if( lref.categ!=VCateg::CP )
-            fout->lDoc.push_back( "o" + lref.genus_info() + " " + expr);
+            fout->log_action( "o" + lref.genus_info() + " " + expr);
+        fout->as_on_disk = false;
 
         CCoord co = T->node_coord( k );
         if        ( lref.categ==VCateg::X ) {
@@ -213,7 +213,7 @@ void NOperate::Pointwise( string llabel )
         } else {
             fout->V.resize( fin->nJ() );
             for( int j=0; j<fin->nJ(); j++ ){
-                fout->V[j] = fin->new_slice( j );
+                fout->V[j] = fin->copy_slice( j );
                 if ( fin->V[j]->frozen )
                     continue;
                 if ( lref.pointwise() ) {
@@ -282,8 +282,8 @@ void NOperate::Integral()
             if      ( const COlc *fc = dynamic_cast<const COlc*>(fin) )
                 fout = POld( new COld( fc ) );
             else
-                fout = POld( (dynamic_cast<const COld*>(fin))->new_old() );
-            fout->lDoc.push_back( "oi " +expr );
+                fout = POld( (dynamic_cast<const COld*>(fin))->new_POld() );
+            fout->log_action( "oi " +expr );
             fout->ZCo.pop_back();
             fout->xco = fin->ZCo.back();
             fout->yco = T->node_coord( k );
@@ -306,7 +306,7 @@ void NOperate::Integral()
             if (nz>=2) { // new spectrum if jump in other z values
                 double zval = fin->V[j]->z[nz-2]->to_r();
                 if ( j+1 < fin->nJ() && fin->V[j+1]->z[nz-2]->to_r() != zval ) {
-                    fout->V.push_back( sout );
+                    fout->V.push_back( move(sout) );
                     sout = PSpec( new CSpec );
                     sout->z = fin->V[j+1]->z;
                     sout->z.pop_back();
@@ -315,7 +315,7 @@ void NOperate::Integral()
         }
         if ( savable ) {
             fout->purge_dy();
-            fout->V.push_back( sout );
+            fout->V.push_back( move(sout) );
             NOlm::mem_store( fout, fiter.k() );
         }
 //      if ( !savable )
@@ -354,11 +354,11 @@ void NOperate::IntXY( string mode )
     while( const COld *fin = fiter.nextD() ) {
         int nz = fin->ZCo.size();
 
-        POld fout( fin->new_old() );
+        POld fout( fin->new_POld() );
         string lin = S("oi") + mode + " " + S(icolx) + " " + S(icoly);
         if ( with_d )
             lin += " " + S(icold);
-        fout->lDoc.push_back( lin );
+        fout->log_action( lin );
 
         fout->xco = xco;
         fout->yco = yco;
@@ -379,12 +379,12 @@ void NOperate::IntXY( string mode )
             sout->z = fin->VS(j)->z;
             if ( nz ) { // new spectrum if jump in any z values
                 if ( j+1 < fin->nJ() && fin->V[j+1]->z != fin->V[j]->z ) {
-                    fout->V.push_back( sout );
+                    fout->V.push_back( move(sout) );
                     sout = PSpec( new CSpec );
                 }
             }
         }
-        fout->V.push_back( sout );
+        fout->V.push_back( move(sout) );
         NOlm::mem_store( fout, fiter.k() );
     }
 }
@@ -400,8 +400,8 @@ void NOperate::Functional( const string& subcmd )
 {
     FileIterator fiter(NSel::selD());
     while ( const COld *fin = fiter.nextD() ) {
-        POld fout( fin->new_old() );
-        fout->lDoc.push_back( "of"+subcmd );
+        POld fout( fin->new_POld() );
+        fout->log_action( "of"+subcmd );
 
         if        ( subcmd=="i" ) { // integrate
             fout->yco.name = "Int d" + fin->xco.name + " " + fin->yco.name;
@@ -420,7 +420,7 @@ void NOperate::Functional( const string& subcmd )
         }
 
         for ( int j=0; j<fin->nJ(); j++ ) {
-            PSpec sin = fin->VS(j);
+            const CSpec *sin = fin->VS(j);
             PSpec sout( new CSpec );
             sout->z = sin->z;
             int n = sin->size();
@@ -449,7 +449,7 @@ void NOperate::Functional( const string& subcmd )
             } else if ( subcmd=="ac" ) { // autocorrelate
                 throw "currently disabled, old code in old/src-fragm/opr-func-ac.cpp";
             }
-            fout->V.push_back( sout );
+            fout->V.push_back( move(sout) );
         }
         NOlm::mem_store( fout, fiter.k() );
     }
diff --git a/pub/lib/plot.cpp b/pub/lib/plot.cpp
index b114136ab8f5a257c190e135ab4aa5d198e8fec9..56010aed9be5da60d93a5bfdfe1046471576528f 100644
--- a/pub/lib/plot.cpp
+++ b/pub/lib/plot.cpp
@@ -79,7 +79,7 @@ void determine_Yrange( CPlot* plot, vector<int>& JSel )
             int j = JSel[iv];
             PSpec s;
             if ( fd ){
-                s = fd->VS(j);
+                s = PSpec( fd->VS(j) );
             } else {
                 s = PSpec( new CSpec );
                 plot->X.set_xgrid( s->x, 97 );
@@ -113,7 +113,7 @@ void determine_Yrange( CPlot* plot, vector<int>& JSel )
 
 int plot_data( CPlot* plot, const COld *fd, int k, int j, int pstyle )
 {
-    const CSpec *s = fd->VS(j).get();
+    const CSpec *s = fd->VS(j);
     int n=s->x.size();
     if ( n!=s->y.size() )
         throw S("BUG: plot: x.size<>y.size");
diff --git a/pub/lib/ptr.hpp b/pub/lib/ptr.hpp
index 0095d29131afdc24c81e10696062f4eae9958b7c..0be917c61647d1d76d9cd18fb0c46ee4825c2427 100644
--- a/pub/lib/ptr.hpp
+++ b/pub/lib/ptr.hpp
@@ -33,9 +33,9 @@ DEF_PTR( CObjVecEnu, PObjVecEnu, RObjVecEnu );
 using POlo   = std::unique_ptr<class COlo>;
 using POld   = std::unique_ptr<class COld>;
 using POlc   = std::unique_ptr<class COlc>;
-using PSlice = std::shared_ptr<class CSlice>;
-using PSpec  = std::shared_ptr<class CSpec>;
-using PCurve = std::shared_ptr<class CCurve>;
+using PSlice = std::unique_ptr<class CSlice>;
+using PSpec  = std::unique_ptr<class CSpec>;
+using PCurve = std::unique_ptr<class CCurve>;
 
 using RNode  = std::shared_ptr<const class CNode>;
 using RRef   = std::shared_ptr<const class CRef1>;
diff --git a/pub/lib/rssm.cpp b/pub/lib/rssm.cpp
index 643ec66fc8b6051181fc4ab73c23c9ad3cccecd5..06c6437b4d461e96035dca5e3868a1141df03e18 100644
--- a/pub/lib/rssm.cpp
+++ b/pub/lib/rssm.cpp
@@ -259,21 +259,21 @@ void NRSSM::read_spec( int flag )
     olf[6]->name = name;
     olf[7]->name = name+"open";
     string doc = "ry" + (flag==0 ? "" : S(flag+1)) + " " + file_f;
-    olf[0]->lDoc.push_back( doc + " # refl, left halfspace" );
-    olf[1]->lDoc.push_back( doc + " # refl, right halfspace" );
-    olf[2]->lDoc.push_back( doc + " # open, left halfspace" );
-    olf[3]->lDoc.push_back( doc + " # open, right halfspace" );
-    olf[4]->lDoc.push_back( doc + " # elastic" );
-    olf[5]->lDoc.push_back( doc + " # inelastic" );
-    olf[6]->lDoc.push_back( doc + " # refl" );
-    olf[7]->lDoc.push_back( doc + " # open" );
+    olf[0]->log_action( doc + " # refl, left halfspace" );
+    olf[1]->log_action( doc + " # refl, right halfspace" );
+    olf[2]->log_action( doc + " # open, left halfspace" );
+    olf[3]->log_action( doc + " # open, right halfspace" );
+    olf[4]->log_action( doc + " # elastic" );
+    olf[5]->log_action( doc + " # inelastic" );
+    olf[6]->log_action( doc + " # refl" );
+    olf[7]->log_action( doc + " # open" );
 
     for( iolf=0; iolf<8; ++iolf ){
         for( int j=0; j<ndet; ++j ){
             PSpec s( new CSpec );
             s->z.resize( 1 );
             s->z[0] = PObjInt( new CObjInt( j ) );
-            olf[iolf]->V.push_back(s);
+            olf[iolf]->V.push_back( move(s) );
         }
     }
 
@@ -440,7 +440,7 @@ void NRSSM::read_series( int flag )
     int j, nE;
 
     for( iolf=0; iolf<2; ++iolf ){
-        olf[iolf]->lDoc.push_back( "acquire data from series"+fser );
+        olf[iolf]->log_action( "acquire data from series"+fser );
         olf[iolf]->xco = CCoord( "E", "ueV" );
         olf[iolf]->yco = CCoord( "cts", "sec-1" );
         olf[iolf]->ZCo.push_back( CCoord( "#sub", "") );
@@ -449,8 +449,8 @@ void NRSSM::read_series( int flag )
     triv::fname_divide( fser, 0, &name, 0 );
     olf[0]->name = name;
     olf[1]->name = name+"open";
-    olf[0]->lDoc.push_back( "refl, average over both halfspaces" );
-    olf[1]->lDoc.push_back( "open, average over both halfspaces" );
+    olf[0]->log_action( "refl, average over both halfspaces" );
+    olf[1]->log_action( "open, average over both halfspaces" );
 
 
     for( isub=0; isub<nsub; ++isub ){
@@ -461,7 +461,7 @@ void NRSSM::read_series( int flag )
             s->z[0] = PObjInt( new CObjInt (isub) );
             s->z[1] = PObjInt( new CObjInt (j) );
             for( iolf=0; iolf<2; ++iolf )
-                olf[iolf]->V.push_back( s );
+                olf[iolf]->V.push_back( move(s) );
         }
     }
 
diff --git a/pub/lib/special.cpp b/pub/lib/special.cpp
index 334c7ebba45763dc7443b5a98c8b3ca5f72f090e..81422089d5df5a796078fd77f5e446ae06706525 100644
--- a/pub/lib/special.cpp
+++ b/pub/lib/special.cpp
@@ -37,8 +37,8 @@ void NSpecial::FourierCosine()
 
     FileIterator fiter(NSel::selD());
     while( const COld *fin = fiter.nextD() ) {
-        POld fout( fin->new_old() );
-        fout->lDoc.push_back("Fourier Cosine");
+        POld fout( fin->new_POld() );
+        fout->log_action("Fourier Cosine");
 
         cout << "WARNING: coordinates not changed\n";
         cout << "WARNING: x not changed\n";
@@ -48,7 +48,7 @@ void NSpecial::FourierCosine()
 //                olf.yco = CCoord("B_dim", "B-unit");
 
         for ( int j=0; j<fin->nJ(); j++ ) {
-            PSpec sin = fin->VS(j);
+            CSpec* sin = fin->VS(j);
             PSpec sout( new CSpec( *sin ) );
 
             n = sin->size();
@@ -63,7 +63,7 @@ void NSpecial::FourierCosine()
                 sout->y[i] /= sqrt(2.*n);
             }
 
-            fout->V.push_back(sout);
+            fout->V.push_back( move(sout) );
         }
         NOlm::mem_store( fout );
     }
@@ -113,7 +113,7 @@ void NSpecial::Test()
         for( int n=0; n<N; ++n )
             s->y[n] /= sqrt(nor);
 
-        fout->V.push_back(s);
+        fout->V.push_back( move(s) );
     }
     NOlm::mem_store( fout );
 }