aboutsummaryrefslogtreecommitdiff
path: root/externals/grill/pool
diff options
context:
space:
mode:
Diffstat (limited to 'externals/grill/pool')
-rw-r--r--externals/grill/pool/main.cpp905
-rw-r--r--externals/grill/pool/pool.cpp645
-rwxr-xr-xexternals/grill/pool/pool.cwbin0 -> 58761 bytes
-rw-r--r--externals/grill/pool/pool.dsp103
-rw-r--r--externals/grill/pool/pool.h124
-rwxr-xr-xexternals/grill/pool/pool.helpbin0 -> 5345 bytes
-rw-r--r--externals/grill/pool/pool.pd201
7 files changed, 1978 insertions, 0 deletions
diff --git a/externals/grill/pool/main.cpp b/externals/grill/pool/main.cpp
new file mode 100644
index 00000000..5d0cef10
--- /dev/null
+++ b/externals/grill/pool/main.cpp
@@ -0,0 +1,905 @@
+/*
+
+pool - hierarchical storage object for PD and Max/MSP
+
+Copyright (c) 2002 Thomas Grill (xovo@gmx.net)
+For information on usage and redistribution, and for a DISCLAIMER OF ALL
+WARRANTIES, see the file, "license.txt," in this distribution.
+
+*/
+
+#include "pool.h"
+
+class pool:
+ public flext_base
+{
+ FLEXT_HEADER_S(pool,flext_base,setup)
+
+public:
+ pool(I argc,const A *argv);
+ ~pool();
+
+ static V setup(t_class *);
+
+ pooldata *Pool() { return pl; }
+
+protected:
+
+ // switch to other pool
+ V m_pool(I argc,const A *argv);
+
+ // clear all data in pool
+ V m_reset();
+
+ // output absolute directory paths?
+ V m_absdir(BL abs) { absdir = abs; }
+ // always output current directory
+ V m_echodir(BL e) { echo = e; }
+
+ // handle directories
+ V m_getdir();
+
+ V m_mkdir(I argc,const A *argv,BL abs = true); // make and change to dir
+ V m_chdir(I argc,const A *argv,BL abs = true); // change to dir
+ V m_rmdir(I argc,const A *argv,BL abs = true); // remove dir
+ V m_updir(I argc,const A *argv); // one or more levels up
+
+ V m_mksub(I argc,const A *argv) { m_mkdir(argc,argv,false); }
+ V m_chsub(I argc,const A *argv) { m_chdir(argc,argv,false); }
+ V m_rmsub(I argc,const A *argv) { m_rmdir(argc,argv,false); }
+
+ // handle data
+ V m_set(I argc,const A *argv) { set(MakeSymbol("set"),argc,argv,true); }
+ V m_add(I argc,const A *argv) { set(MakeSymbol("add"),argc,argv,false); }
+ V m_clr(I argc,const A *argv);
+ V m_clrall(); // only values
+ V m_clrrec(); // also subdirectories
+ V m_clrsub(); // only subdirectories
+ V m_get(I argc,const A *argv);
+ V m_getall(); // only values
+ V m_getrec(I argc,const A *argv); // also subdirectories
+ V m_getsub(I argc,const A *argv); // only subdirectories
+ V m_cntall(); // only values
+ V m_cntrec(I argc,const A *argv); // also subdirectories
+ V m_cntsub(I argc,const A *argv); // only subdirectories
+
+ // cut/copy/paste
+ V m_paste(I argc,const A *argv) { paste(MakeSymbol("paste"),argc,argv,true); } // paste contents of clipboard
+ V m_pasteadd(I argc,const A *argv) { paste(MakeSymbol("pasteadd"),argc,argv,false); } // paste but don't replace
+ V m_clrclip(); // clear clipboard
+ V m_cut(I argc,const A *argv) { copy(MakeSymbol("cut"),argc,argv,true); } // cut value into clipboard
+ V m_copy(I argc,const A *argv) { copy(MakeSymbol("copy"),argc,argv,false); } // copy value into clipboard
+ V m_cutall() { copyall(MakeSymbol("cutall"),true,0); } // cut all values in current directory into clipboard
+ V m_copyall() { copyall(MakeSymbol("copyall"),false,0); } // copy all values in current directory into clipboard
+ V m_cutrec(I argc,const A *argv) { copyrec(MakeSymbol("cutrec"),argc,argv,true); } // cut directory (and subdirs) into clipboard
+ V m_copyrec(I argc,const A *argv) { copyrec(MakeSymbol("copyrec"),argc,argv,false); } // cut directory (and subdirs) into clipboard
+
+ // load/save from/to file
+ V m_load(I argc,const A *argv);
+ V m_save(I argc,const A *argv);
+
+ // load directories
+ V m_lddir(I argc,const A *argv); // load values into current dir
+ V m_ldrec(I argc,const A *argv); // load values recursively
+
+ // save directories
+ V m_svdir(I argc,const A *argv); // save values in current dir
+ V m_svrec(I argc,const A *argv); // save values recursively
+
+private:
+ static BL KeyChk(const A &a);
+ static BL ValChk(I argc,const A *argv);
+ static BL ValChk(const AtomList &l) { return ValChk(l.Count(),l.Atoms()); }
+ V ToOutAtom(I ix,const A &a);
+
+ V set(const S *tag,I argc,const A *argv,BL over);
+ V getdir(const S *tag);
+ I getrec(const S *tag,I level,BL cntonly = false,const AtomList &rdir = AtomList());
+ I getsub(const S *tag,I level,BL cntonly = false,const AtomList &rdir = AtomList());
+
+ V paste(const S *tag,I argc,const A *argv,BL repl);
+ V copy(const S *tag,I argc,const A *argv,BL cut);
+ V copyall(const S *tag,BL cut,I lvls);
+ V copyrec(const S *tag,I argc,const A *argv,BL cut);
+
+ V echodir() { if(echo) getdir(MakeSymbol("echo")); }
+
+ BL priv,absdir,echo;
+ pooldata *pl;
+ AtomList curdir;
+ pooldir *clip;
+
+ static pooldata *head,*tail;
+
+ V SetPool(const S *s);
+ V FreePool();
+
+ static pooldata *GetPool(const S *s);
+ static V RmvPool(pooldata *p);
+
+ FLEXT_CALLBACK_V(m_pool)
+ FLEXT_CALLBACK(m_reset)
+ FLEXT_CALLBACK_B(m_absdir)
+ FLEXT_CALLBACK_B(m_echodir)
+ FLEXT_CALLBACK(m_getdir)
+ FLEXT_CALLBACK_V(m_mkdir)
+ FLEXT_CALLBACK_V(m_chdir)
+ FLEXT_CALLBACK_V(m_updir)
+ FLEXT_CALLBACK_V(m_rmdir)
+ FLEXT_CALLBACK_V(m_mksub)
+ FLEXT_CALLBACK_V(m_chsub)
+ FLEXT_CALLBACK_V(m_rmsub)
+
+ FLEXT_CALLBACK_V(m_set)
+ FLEXT_CALLBACK_V(m_add)
+ FLEXT_CALLBACK_V(m_clr)
+ FLEXT_CALLBACK(m_clrall)
+ FLEXT_CALLBACK(m_clrrec)
+ FLEXT_CALLBACK(m_clrsub)
+ FLEXT_CALLBACK_V(m_get)
+ FLEXT_CALLBACK(m_getall)
+ FLEXT_CALLBACK_V(m_getrec)
+ FLEXT_CALLBACK_V(m_getsub)
+ FLEXT_CALLBACK(m_cntall)
+ FLEXT_CALLBACK_V(m_cntrec)
+ FLEXT_CALLBACK_V(m_cntsub)
+
+ FLEXT_CALLBACK_V(m_paste)
+ FLEXT_CALLBACK_V(m_pasteadd)
+ FLEXT_CALLBACK(m_clrclip)
+ FLEXT_CALLBACK_V(m_copy)
+ FLEXT_CALLBACK_V(m_cut)
+ FLEXT_CALLBACK(m_copyall)
+ FLEXT_CALLBACK(m_cutall)
+ FLEXT_CALLBACK_V(m_copyrec)
+ FLEXT_CALLBACK_V(m_cutrec)
+
+ FLEXT_CALLBACK_V(m_load)
+ FLEXT_CALLBACK_V(m_save)
+ FLEXT_CALLBACK_V(m_lddir)
+ FLEXT_CALLBACK_V(m_ldrec)
+ FLEXT_CALLBACK_V(m_svdir)
+ FLEXT_CALLBACK_V(m_svrec)
+};
+
+FLEXT_NEW_V("pool",pool);
+
+
+pooldata *pool::head,*pool::tail;
+
+
+V pool::setup(t_class *)
+{
+ post("");
+ post("pool %s - hierarchical storage object, (C)2002 Thomas Grill",POOL_VERSION);
+ post("");
+
+ head = tail = NULL;
+}
+
+pool::pool(I argc,const A *argv):
+ absdir(true),echo(false),pl(NULL),
+ clip(NULL)
+{
+ SetPool(argc >= 1 && IsSymbol(argv[0])?GetSymbol(argv[0]):NULL);
+
+ AddInAnything();
+ AddOutList();
+ AddOutAnything();
+ AddOutList();
+ AddOutAnything();
+
+ FLEXT_ADDMETHOD_(0,"set",m_set);
+ FLEXT_ADDMETHOD_(0,"add",m_add);
+ FLEXT_ADDMETHOD_(0,"reset",m_reset);
+ FLEXT_ADDMETHOD_(0,"absdir",m_absdir);
+ FLEXT_ADDMETHOD_(0,"echodir",m_echodir);
+ FLEXT_ADDMETHOD_(0,"getdir",m_getdir);
+ FLEXT_ADDMETHOD_(0,"mkdir",m_mkdir);
+ FLEXT_ADDMETHOD_(0,"chdir",m_chdir);
+ FLEXT_ADDMETHOD_(0,"rmdir",m_rmdir);
+ FLEXT_ADDMETHOD_(0,"updir",m_updir);
+ FLEXT_ADDMETHOD_(0,"mksub",m_mksub);
+ FLEXT_ADDMETHOD_(0,"chsub",m_chsub);
+ FLEXT_ADDMETHOD_(0,"rmsub",m_rmsub);
+
+ FLEXT_ADDMETHOD_(0,"set",m_set);
+ FLEXT_ADDMETHOD_(0,"clr",m_clr);
+ FLEXT_ADDMETHOD_(0,"clrall",m_clrall);
+ FLEXT_ADDMETHOD_(0,"clrrec",m_clrrec);
+ FLEXT_ADDMETHOD_(0,"clrsub",m_clrsub);
+ FLEXT_ADDMETHOD_(0,"get",m_get);
+ FLEXT_ADDMETHOD_(0,"getall",m_getall);
+ FLEXT_ADDMETHOD_(0,"getrec",m_getrec);
+ FLEXT_ADDMETHOD_(0,"getsub",m_getsub);
+ FLEXT_ADDMETHOD_(0,"cntall",m_cntall);
+ FLEXT_ADDMETHOD_(0,"cntrec",m_cntrec);
+ FLEXT_ADDMETHOD_(0,"cntsub",m_cntsub);
+
+ FLEXT_ADDMETHOD_(0,"paste",m_paste);
+ FLEXT_ADDMETHOD_(0,"pasteadd",m_pasteadd);
+ FLEXT_ADDMETHOD_(0,"clrclip",m_clrclip);
+ FLEXT_ADDMETHOD_(0,"cut",m_cut);
+ FLEXT_ADDMETHOD_(0,"copy",m_copy);
+ FLEXT_ADDMETHOD_(0,"cutall",m_cutall);
+ FLEXT_ADDMETHOD_(0,"copyall",m_copyall);
+ FLEXT_ADDMETHOD_(0,"cutrec",m_cutrec);
+ FLEXT_ADDMETHOD_(0,"copyrec",m_copyrec);
+
+ FLEXT_ADDMETHOD_(0,"load",m_load);
+ FLEXT_ADDMETHOD_(0,"save",m_save);
+ FLEXT_ADDMETHOD_(0,"lddir",m_lddir);
+ FLEXT_ADDMETHOD_(0,"ldrec",m_ldrec);
+ FLEXT_ADDMETHOD_(0,"svdir",m_svdir);
+ FLEXT_ADDMETHOD_(0,"svrec",m_svrec);
+}
+
+pool::~pool()
+{
+ FreePool();
+}
+
+V pool::SetPool(const S *s)
+{
+ if(pl) FreePool();
+
+ if(s) {
+ priv = false;
+ pl = GetPool(s);
+ }
+ else {
+ priv = true;
+ pl = new pooldata;
+ }
+}
+
+V pool::FreePool()
+{
+ curdir(); // reset current directory
+
+ if(pl) {
+ if(!priv)
+ RmvPool(pl);
+ else
+ delete pl;
+ pl = NULL;
+ }
+
+ if(clip) { delete clip; clip = NULL; }
+}
+
+V pool::m_pool(I argc,const A *argv)
+{
+ const S *s = NULL;
+ if(argc > 0) {
+ if(argc > 1) post("%s - pool: superfluous arguments ignored",thisName());
+ s = GetASymbol(argv[0]);
+ if(!s) post("%s - pool: invalid pool name, pool set to private",thisName());
+ }
+
+ SetPool(s);
+}
+
+V pool::m_reset()
+{
+ pl->Reset();
+}
+
+
+V pool::getdir(const S *tag)
+{
+ ToOutAnything(3,tag,0,NULL);
+ ToOutList(2,curdir);
+}
+
+V pool::m_getdir() { getdir(MakeSymbol("getdir")); }
+
+V pool::m_mkdir(I argc,const A *argv,BL abs)
+{
+ if(!ValChk(argc,argv))
+ post("%s - mkdir: invalid directory name",thisName());
+ else {
+ AtomList ndir;
+ if(abs) ndir(argc,argv);
+ else (ndir = curdir).Append(argc,argv);
+ if(!pl->MkDir(ndir)) {
+ post("%s - mkdir: directory couldn't be created",thisName());
+ }
+ }
+
+ echodir();
+}
+
+V pool::m_chdir(I argc,const A *argv,BL abs)
+{
+ if(!ValChk(argc,argv))
+ post("%s - chdir: invalid directory name",thisName());
+ else {
+ AtomList prv(curdir);
+ if(abs) curdir(argc,argv);
+ else curdir.Append(argc,argv);
+ if(!pl->ChkDir(curdir)) {
+ post("%s - chdir: directory couldn't be changed",thisName());
+ curdir = prv;
+ }
+ }
+
+ echodir();
+}
+
+V pool::m_updir(I argc,const A *argv)
+{
+ I lvls = 1;
+ if(argc > 0) {
+ if(CanbeInt(argv[0])) {
+ if(argc > 1)
+ post("%s - updir: superfluous arguments ignored",thisName());
+ lvls = GetAInt(argv[0]);
+ if(lvls < 0)
+ post("%s - updir: invalid level specification - set to 1",thisName());
+ }
+ else
+ post("%s - updir: invalid level specification - set to 1",thisName());
+ }
+
+ AtomList prv(curdir);
+
+ if(lvls > curdir.Count()) {
+ post("%s - updir: level exceeds directory depth - corrected",thisName());
+ curdir();
+ }
+ else
+ curdir.Part(0,curdir.Count()-lvls);
+
+ if(!pl->ChkDir(curdir)) {
+ post("%s - updir: directory couldn't be changed",thisName());
+ curdir = prv;
+ }
+
+ echodir();
+}
+
+V pool::m_rmdir(I argc,const A *argv,BL abs)
+{
+ if(abs) curdir(argc,argv);
+ else curdir.Append(argc,argv);
+
+ if(!pl->RmDir(curdir))
+ post("%s - rmdir: directory couldn't be removed",thisName());
+ curdir();
+
+ echodir();
+}
+
+V pool::set(const S *tag,I argc,const A *argv,BL over)
+{
+ if(!argc || !KeyChk(argv[0]))
+ post("%s - %s: invalid key",thisName(),GetString(tag));
+ else if(!ValChk(argc-1,argv+1)) {
+ post("%s - %s: invalid data values",thisName(),GetString(tag));
+ }
+ else
+ if(!pl->Set(curdir,argv[0],new AtomList(argc-1,argv+1),over))
+ post("%s - %s: value couldn't be set",thisName(),GetString(tag));
+
+ echodir();
+}
+
+V pool::m_clr(I argc,const A *argv)
+{
+ if(!argc || !KeyChk(argv[0]))
+ post("%s - clr: invalid key",thisName());
+ else {
+ if(argc > 1)
+ post("%s - clr: superfluous arguments ignored",thisName());
+
+ if(!pl->Clr(curdir,argv[0]))
+ post("%s - clr: value couldn't be cleared",thisName());
+ }
+
+ echodir();
+}
+
+V pool::m_clrall()
+{
+ if(!pl->ClrAll(curdir,false))
+ post("%s - clrall: values couldn't be cleared",thisName());
+
+ echodir();
+}
+
+V pool::m_clrrec()
+{
+ if(!pl->ClrAll(curdir,true))
+ post("%s - clrrec: values couldn't be cleared",thisName());
+
+ echodir();
+}
+
+V pool::m_clrsub()
+{
+ if(!pl->ClrAll(curdir,true,true))
+ post("%s - clrsub: directories couldn't be cleared",thisName());
+
+ echodir();
+}
+
+V pool::m_get(I argc,const A *argv)
+{
+ if(!argc || !KeyChk(argv[0]))
+ post("%s - get: invalid key",thisName());
+ else {
+ if(argc > 1)
+ post("%s - get: superfluous arguments ignored",thisName());
+
+ AtomList *r = pl->Get(curdir,argv[0]);
+
+ ToOutAnything(3,MakeSymbol("get"),0,NULL);
+ if(absdir)
+ ToOutList(2,curdir);
+ else
+ ToOutList(2,0,NULL);
+ ToOutAtom(1,argv[0]);
+ if(r) {
+ ToOutList(0,*r);
+ delete r;
+ }
+ else
+ ToOutBang(0);
+ }
+
+ echodir();
+}
+
+I pool::getrec(const S *tag,I level,BL cntonly,const AtomList &rdir)
+{
+ AtomList gldir(curdir);
+ gldir.Append(rdir);
+
+ I ret = 0;
+
+ if(cntonly)
+ ret = pl->CntAll(gldir);
+ else {
+ A *k;
+ AtomList *r;
+ I cnt = pl->GetAll(gldir,k,r);
+ if(!k)
+ post("%s - %s: error retrieving values",thisName(),GetString(tag));
+ else {
+ for(I i = 0; i < cnt; ++i) {
+ ToOutAnything(3,tag,0,NULL);
+ ToOutList(2,absdir?gldir:rdir);
+ ToOutAtom(1,k[i]);
+ ToOutList(0,r[i]);
+ }
+ delete[] k;
+ delete[] r;
+ }
+ ret = cnt;
+ }
+
+ if(level != 0) {
+ const A **r;
+ I cnt = pl->GetSub(gldir,r);
+ if(!r)
+ post("%s - %s: error retrieving directories",thisName(),GetString(tag));
+ else {
+ I lv = level > 0?level-1:-1;
+ for(I i = 0; i < cnt; ++i) {
+ ret += getrec(tag,lv,cntonly,AtomList(rdir).Append(*r[i]));
+ }
+ delete[] r;
+ }
+ }
+
+ return ret;
+}
+
+V pool::m_getall()
+{
+ getrec(MakeSymbol("getall"),0);
+ ToOutBang(3);
+
+ echodir();
+}
+
+V pool::m_getrec(I argc,const A *argv)
+{
+ I lvls = -1;
+ if(argc > 0) {
+ if(CanbeInt(argv[0])) {
+ if(argc > 1)
+ post("%s - getrec: superfluous arguments ignored",thisName());
+ lvls = GetAInt(argv[0]);
+ }
+ else
+ post("%s - getrec: invalid level specification - set to infinite",thisName());
+ }
+ getrec(MakeSymbol("getrec"),lvls);
+ ToOutBang(3);
+
+ echodir();
+}
+
+
+I pool::getsub(const S *tag,I level,BL cntonly,const AtomList &rdir)
+{
+ AtomList gldir(curdir);
+ gldir.Append(rdir);
+
+ I ret = 0;
+
+ const A **r;
+ I cnt = pl->GetSub(gldir,r);
+ if(!r)
+ post("%s - %s: error retrieving directories",thisName(),GetString(tag));
+ else {
+ I lv = level > 0?level-1:-1;
+ for(I i = 0; i < cnt; ++i) {
+ AtomList ndir(absdir?gldir:rdir);
+ ndir.Append(*r[i]);
+
+ if(!cntonly) {
+ ToOutAnything(3,tag,0,NULL);
+ ToOutList(2,curdir);
+ ToOutList(1,ndir);
+ }
+
+ if(level != 0)
+ ret += getsub(tag,lv,cntonly,AtomList(rdir).Append(*r[i]));
+ }
+ delete[] r;
+ }
+
+ return ret;
+}
+
+V pool::m_getsub(I argc,const A *argv)
+{
+ I lvls = 0;
+ if(argc > 0) {
+ if(CanbeInt(argv[0])) {
+ if(argc > 1)
+ post("%s - getsub: superfluous arguments ignored",thisName());
+ lvls = GetAInt(argv[0]);
+ }
+ else
+ post("%s - getsub: invalid level specification - set to 0",thisName());
+ }
+
+ getsub(MakeSymbol("getsub"),lvls);
+ ToOutBang(3);
+
+ echodir();
+}
+
+
+V pool::m_cntall()
+{
+ const S *tag = MakeSymbol("cntall");
+ I cnt = getrec(tag,0,true);
+ ToOutSymbol(3,tag);
+ ToOutBang(2);
+ ToOutBang(1);
+ ToOutInt(0,cnt);
+
+ echodir();
+}
+
+V pool::m_cntrec(I argc,const A *argv)
+{
+ const S *tag = MakeSymbol("cntrec");
+
+ I lvls = -1;
+ if(argc > 0) {
+ if(CanbeInt(argv[0])) {
+ if(argc > 1)
+ post("%s - %s: superfluous arguments ignored",thisName(),GetString(tag));
+ lvls = GetAInt(argv[0]);
+ }
+ else
+ post("%s - %s: invalid level specification - set to infinite",thisName(),GetString(tag));
+ }
+
+ I cnt = getrec(tag,lvls,true);
+ ToOutSymbol(3,tag);
+ ToOutBang(2);
+ ToOutBang(1);
+ ToOutInt(0,cnt);
+
+ echodir();
+}
+
+
+V pool::m_cntsub(I argc,const A *argv)
+{
+ const S *tag = MakeSymbol("cntsub");
+
+ I lvls = 0;
+ if(argc > 0) {
+ if(CanbeInt(argv[0])) {
+ if(argc > 1)
+ post("%s - %s: superfluous arguments ignored",thisName(),GetString(tag));
+ lvls = GetAInt(argv[0]);
+ }
+ else
+ post("%s - %s: invalid level specification - set to 0",thisName(),GetString(tag));
+ }
+
+ I cnt = getsub(tag,lvls,true);
+ ToOutSymbol(3,tag);
+ ToOutBang(2);
+ ToOutBang(1);
+ ToOutInt(0,cnt);
+
+ echodir();
+}
+
+
+V pool::paste(const S *tag,I argc,const A *argv,BL repl)
+{
+ if(clip) {
+ BL mkdir = true;
+ I depth = -1;
+
+ if(argc >= 1) {
+ if(CanbeInt(argv[0])) depth = GetAInt(argv[1]);
+ else
+ post("%s - %s: invalid depth argument - set to -1",thisName(),GetString(tag));
+
+ if(argc >= 2) {
+ if(CanbeBool(argv[1])) mkdir = GetABool(argv[1]);
+ else
+ post("%s - %s: invalid mkdir argument - set to true",thisName(),GetString(tag));
+
+ if(argc > 2) post("%s - %s: superfluous arguments ignored",thisName(),GetString(tag));
+ }
+ }
+
+ pl->Paste(curdir,clip,depth,repl,mkdir);
+ }
+ else
+ post("%s - %s: clipboard is empty",thisName(),GetString(tag));
+
+ echodir();
+}
+
+
+V pool::m_clrclip()
+{
+ if(clip) { delete clip; clip = NULL; }
+}
+
+
+V pool::copy(const S *tag,I argc,const A *argv,BL cut)
+{
+ if(!argc || !KeyChk(argv[0]))
+ post("%s - %s: invalid key",thisName(),GetString(tag));
+ else {
+ if(argc > 1)
+ post("%s - %s: superfluous arguments ignored",thisName(),GetString(tag));
+
+ m_clrclip();
+ clip = pl->Copy(curdir,argv[0],cut);
+
+ if(!clip)
+ post("%s - %s: Copying into clipboard failed",thisName(),GetString(tag));
+ }
+
+ echodir();
+}
+
+
+V pool::copyall(const S *tag,BL cut,I depth)
+{
+ m_clrclip();
+ clip = pl->CopyAll(curdir,depth,cut);
+
+ if(!clip)
+ post("%s - %s: Copying into clipboard failed",thisName(),GetString(tag));
+
+ echodir();
+}
+
+
+V pool::copyrec(const S *tag,I argc,const A *argv,BL cut)
+{
+ I lvls = -1;
+ if(argc > 0) {
+ if(CanbeInt(argv[0])) {
+ if(argc > 1)
+ post("%s - %s: superfluous arguments ignored",thisName(),GetString(tag));
+ lvls = GetAInt(argv[0]);
+ }
+ else
+ post("%s - %s: invalid level specification - set to infinite",thisName(),GetString(tag));
+ }
+
+ copyall(tag,cut,lvls);
+}
+
+V pool::m_load(I argc,const A *argv)
+{
+ const C *flnm = NULL;
+ if(argc > 0) {
+ if(argc > 1) post("%s - load: superfluous arguments ignored",thisName());
+ if(IsString(argv[0])) flnm = GetString(argv[0]);
+ }
+
+ if(!flnm)
+ post("%s - load: no filename given",thisName());
+ else if(!pl->Load(flnm))
+ post("%s - load: error loading data",thisName());
+
+ echodir();
+}
+
+V pool::m_save(I argc,const A *argv)
+{
+ const C *flnm = NULL;
+ if(argc > 0) {
+ if(argc > 1) post("%s - save: superfluous arguments ignored",thisName());
+ if(IsString(argv[0])) flnm = GetString(argv[0]);
+ }
+
+ if(!flnm)
+ post("%s - save: no filename given",thisName());
+ else if(!pl->Save(flnm))
+ post("%s - save: error saving data",thisName());
+
+ echodir();
+}
+
+V pool::m_lddir(I argc,const A *argv)
+{
+ const C *flnm = NULL;
+ if(argc > 0) {
+ if(argc > 1) post("%s - lddir: superfluous arguments ignored",thisName());
+ if(IsString(argv[0])) flnm = GetString(argv[0]);
+ }
+
+ if(!flnm)
+ post("%s - lddir: invalid filename",thisName());
+ else {
+ if(!pl->LdDir(curdir,flnm,0))
+ post("%s - lddir: directory couldn't be loaded",thisName());
+ }
+
+ echodir();
+}
+
+V pool::m_ldrec(I argc,const A *argv)
+{
+ const C *flnm = NULL;
+ I depth = -1;
+ BL mkdir = true;
+ if(argc >= 1) {
+ if(IsString(argv[0])) flnm = GetString(argv[0]);
+
+ if(argc >= 2) {
+ if(CanbeInt(argv[1])) depth = GetAInt(argv[1]);
+ else
+ post("%s - ldrec: invalid depth argument - set to -1",thisName());
+
+ if(argc >= 3) {
+ if(CanbeBool(argv[2])) mkdir = GetABool(argv[2]);
+ else
+ post("%s - ldrec: invalid mkdir argument - set to true",thisName());
+
+ if(argc > 3) post("%s - ldrec: superfluous arguments ignored",thisName());
+ }
+ }
+ }
+
+ if(!flnm)
+ post("%s - ldrec: invalid filename",thisName());
+ else {
+ if(!pl->LdDir(curdir,flnm,depth,mkdir))
+ post("%s - ldrec: directory couldn't be saved",thisName());
+ }
+
+ echodir();
+}
+
+V pool::m_svdir(I argc,const A *argv)
+{
+ const C *flnm = NULL;
+ if(argc > 0) {
+ if(argc > 1) post("%s - svdir: superfluous arguments ignored",thisName());
+ if(IsString(argv[0])) flnm = GetString(argv[0]);
+ }
+
+ if(!flnm)
+ post("%s - svdir: invalid filename",thisName());
+ else {
+ if(!pl->SvDir(curdir,flnm,0,absdir))
+ post("%s - svdir: directory couldn't be saved",thisName());
+ }
+
+ echodir();
+}
+
+V pool::m_svrec(I argc,const A *argv)
+{
+ const C *flnm = NULL;
+ if(argc > 0) {
+ if(argc > 1) post("%s - svrec: superfluous arguments ignored",thisName());
+ if(IsString(argv[0])) flnm = GetString(argv[0]);
+ }
+
+ if(!flnm)
+ post("%s - svrec: invalid filename",thisName());
+ else {
+ if(!pl->SvDir(curdir,flnm,-1,absdir))
+ post("%s - svrec: directory couldn't be saved",thisName());
+ }
+
+ echodir();
+}
+
+
+
+BL pool::KeyChk(const t_atom &a)
+{
+ return IsSymbol(a) || IsFloat(a) || IsInt(a);
+}
+
+BL pool::ValChk(I argc,const t_atom *argv)
+{
+ for(I i = 0; i < argc; ++i) {
+ const t_atom &a = argv[i];
+ if(!IsSymbol(a) && !IsFloat(a) && !IsInt(a)) return false;
+ }
+ return true;
+}
+
+V pool::ToOutAtom(I ix,const t_atom &a)
+{
+ if(IsSymbol(a))
+ ToOutSymbol(ix,GetSymbol(a));
+ else if(IsFloat(a))
+ ToOutFloat(ix,GetFloat(a));
+ else if(IsInt(a))
+ ToOutInt(ix,GetInt(a));
+ else
+ post("%s - output atom: type not supported!",thisName());
+}
+
+
+
+pooldata *pool::GetPool(const S *s)
+{
+ pooldata *pi = head;
+ for(; pi && pi->sym != s; pi = pi->nxt) (V)0;
+
+ if(pi) {
+ pi->Push();
+ return pi;
+ }
+ else {
+ pooldata *p = new pooldata(s);
+ p->Push();
+
+ // now add to chain
+ if(head) head->nxt = p;
+ else head = p;
+ tail = p;
+ return p;
+ }
+}
+
+V pool::RmvPool(pooldata *p)
+{
+ pooldata *prv = NULL,*pi = head;
+ for(; pi && pi != p; prv = pi,pi = pi->nxt) (V)0;
+
+ if(pi && !pi->Pop()) {
+ if(prv) prv->nxt = pi->nxt;
+ else head = pi->nxt;
+ if(!pi->nxt) tail = pi;
+
+ delete pi;
+ }
+}
+
diff --git a/externals/grill/pool/pool.cpp b/externals/grill/pool/pool.cpp
new file mode 100644
index 00000000..629ab7fb
--- /dev/null
+++ b/externals/grill/pool/pool.cpp
@@ -0,0 +1,645 @@
+/*
+
+pool - hierarchical storage object for PD and Max/MSP
+
+Copyright (c) 2002 Thomas Grill (xovo@gmx.net)
+For information on usage and redistribution, and for a DISCLAIMER OF ALL
+WARRANTIES, see the file, "license.txt," in this distribution.
+
+*/
+
+#include "pool.h"
+
+#include <string.h>
+#include <fstream.h>
+#include <ctype.h>
+#include <stdlib.h>
+
+
+inline I compare(I a,I b) { return a == b?0:(a < b?-1:1); }
+inline I compare(F a,F b) { return a == b?0:(a < b?-1:1); }
+
+static I compare(const S *a,const S *b)
+{
+ if(a == b)
+ return 0;
+ else
+ return strcmp(flext::GetString(a),flext::GetString(b));
+}
+
+static I compare(const A &a,const A &b)
+{
+ if(a.a_type == b.a_type) {
+ switch(a.a_type) {
+ case A_FLOAT:
+ return compare(a.a_w.w_float,b.a_w.w_float);
+#ifdef MAXMSP
+ case A_LONG:
+ return compare((I)a.a_w.w_long,(I)b.a_w.w_long);
+#endif
+ case A_SYMBOL:
+ return compare(a.a_w.w_symbol,b.a_w.w_symbol);
+#ifdef PD
+ case A_POINTER:
+ return a.a_w.w_gpointer == b.a_w.w_gpointer?0:(a.a_w.w_gpointer < b.a_w.w_gpointer?-1:1);
+#endif
+ default:
+ LOG("pool - atom comparison: type not handled");
+ return -1;
+ }
+ }
+ else
+ return a.a_type < b.a_type?-1:1;
+}
+
+
+poolval::poolval(const A &k,AtomList *d):
+ data(d),nxt(NULL)
+{
+ SetAtom(key,k);
+}
+
+poolval::~poolval()
+{
+ if(data) delete data;
+ if(nxt) delete nxt;
+}
+
+poolval &poolval::Set(AtomList *d)
+{
+ if(data) delete data;
+ data = d;
+ return *this;
+}
+
+poolval *poolval::Dup() const
+{
+ return new poolval(key,data?new AtomList(*data):NULL);
+}
+
+
+pooldir::pooldir(const A &d):
+ dirs(NULL),vals(NULL),nxt(NULL)
+{
+ CopyAtom(&dir,&d);
+}
+
+pooldir::~pooldir()
+{
+ Clear(true);
+ if(nxt) delete nxt;
+}
+
+V pooldir::Clear(BL rec,BL dironly)
+{
+ if(rec && dirs) { delete dirs; dirs = NULL; }
+ if(!dironly && vals) { delete vals; vals = NULL; }
+}
+
+pooldir *pooldir::AddDir(I argc,const A *argv)
+{
+ if(!argc) return this;
+
+ I c = 1;
+ pooldir *prv = NULL,*ix = dirs;
+ for(; ix; prv = ix,ix = ix->nxt) {
+ c = compare(argv[0],ix->dir);
+ if(c <= 0) break;
+ }
+
+ if(c || !ix) {
+ pooldir *nd = new pooldir(argv[0]);
+ nd->nxt = ix;
+
+ if(prv) prv->nxt = nd;
+ else dirs = nd;
+ ix = nd;
+ }
+
+ return ix->AddDir(argc-1,argv+1);
+}
+
+pooldir *pooldir::GetDir(I argc,const A *argv,BL rmv)
+{
+ if(!argc) return this;
+
+ I c = 1;
+ pooldir *prv = NULL,*ix = dirs;
+ for(; ix; prv = ix,ix = ix->nxt) {
+ c = compare(argv[0],ix->dir);
+ if(c <= 0) break;
+ }
+
+ if(c || !ix)
+ return NULL;
+ else {
+ if(argc > 1)
+ return ix->GetDir(argc-1,argv+1,rmv);
+ else if(rmv) {
+ pooldir *nd = ix->nxt;
+ if(prv) prv->nxt = nd;
+ else dirs = nd;
+ ix->nxt = NULL;
+ return ix;
+ }
+ else
+ return ix;
+ }
+}
+
+BL pooldir::DelDir(const AtomList &d)
+{
+ pooldir *pd = GetDir(d,true);
+ if(pd && pd != this) {
+ delete pd;
+ return true;
+ }
+ else
+ return false;
+}
+
+V pooldir::SetVal(const A &key,AtomList *data,BL over)
+{
+ I c = 1;
+ poolval *prv = NULL,*ix = vals;
+ for(; ix; prv = ix,ix = ix->nxt) {
+ c = compare(key,ix->key);
+ if(c <= 0) break;
+ }
+
+ if(c || !ix) {
+ // no existing data found
+
+ if(data) {
+ poolval *nv = new poolval(key,data);
+ nv->nxt = ix;
+
+ if(prv) prv->nxt = nv;
+ else vals = nv;
+ }
+ }
+ else if(over) {
+ // data exists... only set if overwriting enabled
+
+ if(data)
+ ix->Set(data);
+ else {
+ poolval *nv = ix->nxt;
+ if(prv) prv->nxt = nv;
+ else vals = nv;
+ ix->nxt = NULL;
+ delete ix;
+ }
+ }
+}
+
+flext::AtomList *pooldir::GetVal(const A &key,BL cut)
+{
+ I c = 1;
+ poolval *prv = NULL,*ix = vals;
+ for(; ix; prv = ix,ix = ix->nxt) {
+ c = compare(key,ix->key);
+ if(c <= 0) break;
+ }
+
+ if(c || !ix)
+ return NULL;
+ else {
+ AtomList *ret;
+ if(cut) {
+ poolval *nv = ix->nxt;
+ if(prv) prv->nxt = nv;
+ else vals = nv;
+ ix->nxt = NULL;
+ ret = ix->data; ix->data = NULL;
+ delete ix;
+ }
+ else
+ ret = new AtomList(*ix->data);
+ return ret;
+ }
+}
+
+I pooldir::CntAll()
+{
+ I cnt = 0;
+ poolval *ix = vals;
+ for(; ix; ix = ix->nxt,++cnt) {}
+ return cnt;
+}
+
+I pooldir::GetAll(A *&keys,AtomList *&lst,BL cut)
+{
+ I cnt = CntAll();
+ keys = new A[cnt];
+ lst = new AtomList[cnt];
+
+ poolval *ix = vals;
+ for(I i = 0; ix; ++i) {
+ SetAtom(keys[i],ix->key);
+ lst[i] = *ix->data;
+
+ if(cut) {
+ poolval *t = ix;
+ vals = ix = ix->nxt;
+ t->nxt = NULL; delete t;
+ }
+ else
+ ix = ix->nxt;
+ }
+
+ return cnt;
+}
+
+I pooldir::GetSub(const A **&lst)
+{
+ I cnt = 0;
+ pooldir *ix = dirs;
+ for(; ix; ix = ix->nxt,++cnt) {}
+ lst = new const A *[cnt];
+
+ ix = dirs;
+ for(I i = 0; ix; ix = ix->nxt,++i) {
+ lst[i] = &ix->dir;
+ }
+
+ return cnt;
+}
+
+
+BL pooldir::Paste(const pooldir *p,I depth,BL repl,BL mkdir)
+{
+ BL ok = true;
+
+ for(poolval *ix = p->vals; ix; ix = ix->nxt) {
+ SetVal(ix->key,new AtomList(*ix->data),repl);
+ }
+
+ if(ok && depth) {
+ for(pooldir *dix = p->dirs; ok && dix; dix = dix->nxt) {
+ pooldir *ndir = mkdir?AddDir(1,&dix->dir):GetDir(1,&dix->dir);
+ if(ndir) {
+ ok = ndir->Paste(dix,depth > 0?depth-1:depth,repl,mkdir);
+ }
+ }
+ }
+
+ return ok;
+}
+
+BL pooldir::Copy(pooldir *p,I depth,BL cut)
+{
+ BL ok = true;
+
+ if(cut) {
+ if(p->vals)
+ ok = false;
+ else
+ p->vals = vals, vals = NULL;
+ }
+ else {
+ // inefficient!! p->SetVal has to search through list unnecessarily!!
+ for(poolval *ix = vals; ix; ix = ix->nxt) {
+ p->SetVal(ix->key,new AtomList(*ix->data));
+ }
+ }
+
+ if(ok && depth) {
+ // also quite inefficient for cut
+ for(pooldir *dix = dirs; ok && dix; dix = dix->nxt) {
+ pooldir *ndir = p->AddDir(1,&dix->dir);
+ if(ndir)
+ ok = ndir->Copy(dix,depth > 0?depth-1:depth,cut);
+ else
+ ok = false;
+ }
+ }
+
+ return ok;
+}
+
+
+static C *ReadAtom(C *c,A *a)
+{
+ // skip whitespace
+ while(*c && isspace(*c)) ++c;
+ if(!*c) return NULL;
+
+ const C *m = c; // remember position
+
+ // check for word type (s = 0,1,2 ... int,float,symbol)
+ I s = 0;
+ for(; *c && !isspace(*c); ++c) {
+ if(!isdigit(*c))
+ s = (*c != '.' || s == 1)?2:1;
+ }
+
+ if(a) {
+ switch(s) {
+ case 0: // integer
+#ifdef MAXMSP
+ a->a_type = A_LONG;
+ a->a_w.w_long = atol(m);
+ break;
+#endif
+ case 1: // float
+ a->a_type = A_FLOAT;
+ a->a_w.w_float = (F)atof(m);
+ break;
+ default: { // anything else is a symbol
+ C t = *c; *c = 0;
+ a->a_type = A_SYMBOL;
+ a->a_w.w_symbol = (S *)flext::MakeSymbol(m);
+ *c = t;
+ break;
+ }
+ }
+ }
+
+ return c;
+}
+
+static BL ReadAtoms(istream &is,flext::AtomList &l,C del)
+{
+ C tmp[1024];
+ is.getline(tmp,sizeof tmp,del);
+ if(is.eof() || !is.good()) return false;
+
+ I i,cnt;
+ C *t = tmp;
+ for(cnt = 0; ; ++cnt) {
+ t = ReadAtom(t,NULL);
+ if(!t) break;
+ }
+
+ l(cnt);
+ if(cnt) {
+ for(i = 0,t = tmp; i < cnt; ++i)
+ t = ReadAtom(t,&l[i]);
+ }
+ return true;
+}
+
+static V WriteAtom(ostream &os,const A &a)
+{
+ switch(a.a_type) {
+ case A_FLOAT:
+ os << a.a_w.w_float;
+ break;
+#ifdef MAXMSP
+ case A_LONG:
+ os << a.a_w.w_long;
+ break;
+#endif
+ case A_SYMBOL:
+ os << flext::GetString(a.a_w.w_symbol);
+ break;
+ }
+}
+
+static V WriteAtoms(ostream &os,const flext::AtomList &l)
+{
+ for(I i = 0; i < l.Count(); ++i) {
+ WriteAtom(os,l[i]);
+ os << ' ';
+ }
+}
+
+BL pooldir::LdDir(istream &is,I depth,BL mkdir)
+{
+ BL r;
+ for(I i = 1; !is.eof(); ++i) {
+ AtomList d,k,*v = new AtomList;
+ r = ReadAtoms(is,d,',');
+ r = r && ReadAtoms(is,k,',') && k.Count() == 1;
+ r = r && ReadAtoms(is,*v,'\n') && v->Count();
+
+ if(r) {
+ if(depth < 0 || d.Count() <= depth) {
+ pooldir *nd = mkdir?AddDir(d):GetDir(d);
+ if(nd) {
+ nd->SetVal(k[0],v); v = NULL;
+ }
+ #ifdef _DEBUG
+ else
+ post("pool - directory was not found",i);
+ #endif
+ }
+ }
+ else if(!is.eof())
+ post("pool - format mismatch encountered, skipped line %i",i);
+
+ if(v) delete v;
+ }
+ return true;
+}
+
+BL pooldir::SvDir(ostream &os,I depth,const AtomList &dir)
+{
+ {
+ for(poolval *ix = vals; ix; ix = ix->nxt) {
+ WriteAtoms(os,dir);
+ os << ", ";
+ WriteAtom(os,ix->key);
+ os << " , ";
+ WriteAtoms(os,*ix->data);
+ os << endl;
+ }
+ }
+ if(depth) {
+ I nd = depth > 0?depth-1:-1;
+ for(pooldir *ix = dirs; ix; ix = ix->nxt) {
+ ix->SvDir(os,nd,AtomList(dir).Append(ix->dir));
+ }
+ }
+ return true;
+}
+
+
+
+
+pooldata::pooldata(const S *s):
+ sym(s),nxt(NULL),refs(0),
+ root(nullatom)
+{
+ LOG1("new pool %s",sym?flext_base::GetString(sym):"<private>");
+}
+
+pooldata::~pooldata()
+{
+ LOG1("free pool %s",sym?flext_base::GetString(sym):"<private>");
+}
+
+t_atom pooldata::nullatom = { A_NULL };
+
+
+V pooldata::Reset()
+{
+ root.Clear(true);
+}
+
+BL pooldata::MkDir(const AtomList &d)
+{
+ root.AddDir(d);
+ return true;
+}
+
+BL pooldata::ChkDir(const AtomList &d)
+{
+ return root.GetDir(d) != NULL;
+}
+
+BL pooldata::RmDir(const AtomList &d)
+{
+ return root.DelDir(d);
+}
+
+BL pooldata::Set(const AtomList &d,const A &key,AtomList *data,BL over)
+{
+ pooldir *pd = root.GetDir(d);
+ if(!pd) return false;
+ pd->SetVal(key,data,over);
+ return true;
+}
+
+BL pooldata::Clr(const AtomList &d,const A &key)
+{
+ pooldir *pd = root.GetDir(d);
+ if(!pd) return false;
+ pd->ClrVal(key);
+ return true;
+}
+
+BL pooldata::ClrAll(const AtomList &d,BL rec,BL dironly)
+{
+ pooldir *pd = root.GetDir(d);
+ if(!pd) return false;
+ pd->Clear(rec,dironly);
+ return true;
+}
+
+flext::AtomList *pooldata::Get(const AtomList &d,const A &key)
+{
+ pooldir *pd = root.GetDir(d);
+ return pd?pd->GetVal(key):NULL;
+}
+
+I pooldata::CntAll(const AtomList &d)
+{
+ pooldir *pd = root.GetDir(d);
+ return pd?pd->CntAll():0;
+}
+
+I pooldata::GetAll(const AtomList &d,A *&keys,AtomList *&lst)
+{
+ pooldir *pd = root.GetDir(d);
+ if(pd)
+ return pd->GetAll(keys,lst);
+ else {
+ keys = NULL; lst = NULL;
+ return 0;
+ }
+}
+
+I pooldata::GetSub(const AtomList &d,const t_atom **&dirs)
+{
+ pooldir *pd = root.GetDir(d);
+ if(pd)
+ return pd->GetSub(dirs);
+ else {
+ dirs = NULL;
+ return 0;
+ }
+}
+
+
+BL pooldata::Paste(const AtomList &d,const pooldir *clip,I depth,BL repl,BL mkdir)
+{
+ pooldir *pd = root.GetDir(d);
+ if(pd)
+ return pd->Paste(clip,depth,repl,mkdir);
+ else
+ return false;
+}
+
+pooldir *pooldata::Copy(const AtomList &d,const A &key,BL cut)
+{
+ pooldir *pd = root.GetDir(d);
+ if(pd) {
+ AtomList *val = pd->GetVal(key,cut);
+ if(val) {
+ pooldir *ret = new pooldir(nullatom);
+ ret->SetVal(key,val);
+ return ret;
+ }
+ else
+ return NULL;
+ }
+ else
+ return NULL;
+}
+
+pooldir *pooldata::CopyAll(const AtomList &d,I depth,BL cut)
+{
+ pooldir *pd = root.GetDir(d);
+ if(pd) {
+ pooldir *ret = new pooldir(nullatom);
+ if(pd->Copy(ret,depth,cut))
+ return ret;
+ else {
+ delete ret;
+ return NULL;
+ }
+ }
+ else
+ return NULL;
+}
+
+
+static const C *CnvFlnm(C *dst,const C *src,I sz)
+{
+#if defined(PD) && defined(NT)
+ I cnt = strlen(src);
+ if(cnt >= sz-1) return NULL;
+ for(I i = 0; i < cnt; ++i)
+ dst[i] = src[i] != '/'?src[i]:'\\';
+ dst[i] = 0;
+ return dst;
+#else
+ return src;
+#endif
+}
+
+BL pooldata::LdDir(const AtomList &d,const C *flnm,I depth,BL mkdir)
+{
+ pooldir *pd = root.GetDir(d);
+ if(pd) {
+ C tmp[1024];
+ const C *t = CnvFlnm(tmp,flnm,sizeof tmp);
+ if(t) {
+ ifstream fl(t);
+ return fl.good() && pd->LdDir(fl,depth,mkdir);
+ }
+ else return false;
+ }
+ else
+ return false;
+}
+
+BL pooldata::SvDir(const AtomList &d,const C *flnm,I depth,BL absdir)
+{
+ pooldir *pd = root.GetDir(d);
+ if(pd) {
+ C tmp[1024];
+ const C *t = CnvFlnm(tmp,flnm,sizeof tmp);
+ if(t) {
+ ofstream fl(t);
+ return fl.good() && pd->SvDir(fl,depth,absdir?d:AtomList());
+ }
+ else return false;
+ }
+ else
+ return false;
+}
+
+
diff --git a/externals/grill/pool/pool.cw b/externals/grill/pool/pool.cw
new file mode 100755
index 00000000..66e93306
--- /dev/null
+++ b/externals/grill/pool/pool.cw
Binary files differ
diff --git a/externals/grill/pool/pool.dsp b/externals/grill/pool/pool.dsp
new file mode 100644
index 00000000..dbe09386
--- /dev/null
+++ b/externals/grill/pool/pool.dsp
@@ -0,0 +1,103 @@
+# Microsoft Developer Studio Project File - Name="pool" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** NICHT BEARBEITEN **
+
+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
+
+CFG=pool - Win32 Debug
+!MESSAGE Dies ist kein gültiges Makefile. Zum Erstellen dieses Projekts mit NMAKE
+!MESSAGE verwenden Sie den Befehl "Makefile exportieren" und führen Sie den Befehl
+!MESSAGE
+!MESSAGE NMAKE /f "pool.mak".
+!MESSAGE
+!MESSAGE Sie können beim Ausführen von NMAKE eine Konfiguration angeben
+!MESSAGE durch Definieren des Makros CFG in der Befehlszeile. Zum Beispiel:
+!MESSAGE
+!MESSAGE NMAKE /f "pool.mak" CFG="pool - Win32 Debug"
+!MESSAGE
+!MESSAGE Für die Konfiguration stehen zur Auswahl:
+!MESSAGE
+!MESSAGE "pool - Win32 Release" (basierend auf "Win32 (x86) Dynamic-Link Library")
+!MESSAGE "pool - Win32 Debug" (basierend auf "Win32 (x86) Dynamic-Link Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName "max/pool"
+# PROP Scc_LocalPath "."
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "pool - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "pd-msvc/r"
+# PROP Intermediate_Dir "pd-msvc/r"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "POOL_EXPORTS" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "c:\programme\audio\pd\src" /I "f:\prog\max\flext\source" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "NT" /D "PD" /YX /FD /c
+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0xc07 /d "NDEBUG"
+# ADD RSC /l 0xc07 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+# ADD LINK32 kernel32.lib user32.lib pd.lib flext-pdwin.lib /nologo /dll /machine:I386 /libpath:"c:\programme\audio\pd\bin" /libpath:"f:\prog\max\flext\pd-msvc"
+
+!ELSEIF "$(CFG)" == "pool - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "pd-msvc/d"
+# PROP Intermediate_Dir "pd-msvc/d"
+# PROP Ignore_Export_Lib 0
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "POOL_EXPORTS" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "c:\programme\audio\pd\src" /I "f:\prog\max\flext\source" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "NT" /D "PD" /FR /YX /FD /GZ /c
+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
+# ADD BASE RSC /l 0xc07 /d "_DEBUG"
+# ADD RSC /l 0xc07 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib pd.lib flext_d-pdwin.lib /nologo /dll /debug /machine:I386 /pdbtype:sept /libpath:"c:\programme\audio\pd\bin" /libpath:"f:\prog\max\flext\pd-msvc"
+
+!ENDIF
+
+# Begin Target
+
+# Name "pool - Win32 Release"
+# Name "pool - Win32 Debug"
+# Begin Source File
+
+SOURCE=.\main.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\pool.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\pool.h
+# End Source File
+# End Target
+# End Project
diff --git a/externals/grill/pool/pool.h b/externals/grill/pool/pool.h
new file mode 100644
index 00000000..21fe4eb3
--- /dev/null
+++ b/externals/grill/pool/pool.h
@@ -0,0 +1,124 @@
+/*
+
+pool - hierarchical storage object for PD and Max/MSP
+
+Copyright (c) 2002 Thomas Grill (xovo@gmx.net)
+For information on usage and redistribution, and for a DISCLAIMER OF ALL
+WARRANTIES, see the file, "license.txt," in this distribution.
+
+*/
+
+#ifndef __POOL_H
+#define __POOL_H
+
+#include <flext.h>
+
+#if !defined(FLEXT_VERSION) || (FLEXT_VERSION < 400)
+#error You need at least flext version 0.4.0
+#endif
+
+#define POOL_VERSION "0.0.5"
+
+#include <iostream.h>
+
+typedef void V;
+typedef int I;
+typedef float F;
+typedef char C;
+typedef bool BL;
+typedef t_atom A;
+typedef t_symbol S;
+
+class poolval:
+ public flext
+{
+public:
+ poolval(const A &key,AtomList *data);
+ ~poolval();
+
+ poolval &Set(AtomList *data);
+ poolval *Dup() const;
+
+ A key;
+ AtomList *data;
+ poolval *nxt;
+};
+
+ class pooldir:
+ public flext
+{
+public:
+ pooldir(const A &dir);
+ ~pooldir();
+
+ V Clear(BL rec,BL dironly = false);
+
+ pooldir *GetDir(I argc,const A *argv,BL cut = false);
+ pooldir *GetDir(const AtomList &d,BL cut = false) { return GetDir(d.Count(),d.Atoms(),cut); }
+ BL DelDir(const AtomList &d);
+ pooldir *AddDir(I argc,const A *argv);
+ pooldir *AddDir(const AtomList &d) { return AddDir(d.Count(),d.Atoms()); }
+
+ V SetVal(const A &key,AtomList *data,BL over = true);
+ V ClrVal(const A &key) { SetVal(key,NULL); }
+ AtomList *GetVal(const A &key,BL cut = false);
+ I CntAll();
+ I GetAll(A *&keys,AtomList *&lst,BL cut = false);
+ I GetSub(const t_atom **&dirs);
+
+ BL Paste(const pooldir *p,I depth,BL repl,BL mkdir);
+ BL Copy(pooldir *p,I depth,BL cur);
+
+ BL LdDir(istream &is,I depth,BL mkdir);
+ BL SvDir(ostream &os,I depth,const AtomList &dir = AtomList());
+
+ A dir;
+ pooldir *nxt;
+
+ pooldir *dirs;
+ poolval *vals;
+};
+
+ class pooldata:
+ public flext
+{
+public:
+ pooldata(const S *s = NULL);
+ ~pooldata();
+
+ V Push() { ++refs; }
+ BL Pop() { return --refs > 0; }
+
+ V Reset();
+ BL MkDir(const AtomList &d);
+ BL ChkDir(const AtomList &d);
+ BL RmDir(const AtomList &d);
+
+ BL Set(const AtomList &d,const A &key,AtomList *data,BL over = true);
+ BL Clr(const AtomList &d,const A &key);
+ BL ClrAll(const AtomList &d,BL rec,BL dironly = false);
+ AtomList *Get(const AtomList &d,const A &key);
+ I CntAll(const AtomList &d);
+ I GetAll(const AtomList &d,A *&keys,AtomList *&lst);
+ I GetSub(const AtomList &d,const t_atom **&dirs);
+
+ BL Paste(const AtomList &d,const pooldir *clip,I depth = -1,BL repl = true,BL mkdir = true);
+ pooldir *Copy(const AtomList &d,const A &key,BL cut);
+ pooldir *CopyAll(const AtomList &d,I depth,BL cut);
+
+ BL LdDir(const AtomList &d,const C *flnm,I depth,BL mkdir = true);
+ BL SvDir(const AtomList &d,const C *flnm,I depth,BL absdir);
+ BL Load(const C *flnm) { return LdDir(AtomList(),flnm,-1); }
+ BL Save(const C *flnm) { return SvDir(AtomList(),flnm,-1,true); }
+
+ I refs;
+ const S *sym;
+ pooldata *nxt;
+
+ pooldir root;
+
+private:
+ static t_atom nullatom;
+};
+
+#endif
diff --git a/externals/grill/pool/pool.help b/externals/grill/pool/pool.help
new file mode 100755
index 00000000..24d189b7
--- /dev/null
+++ b/externals/grill/pool/pool.help
Binary files differ
diff --git a/externals/grill/pool/pool.pd b/externals/grill/pool/pool.pd
new file mode 100644
index 00000000..ffd49615
--- /dev/null
+++ b/externals/grill/pool/pool.pd
@@ -0,0 +1,201 @@
+#N canvas 25 23 966 669 12;
+#X obj 273 441 pool;
+#X msg 236 52 set 1 2 3;
+#X obj 272 563 print K;
+#X msg 602 156 getall;
+#X msg 236 81 set A k g;
+#X obj 251 594 print V;
+#X obj 290 532 print D;
+#X msg 236 111 set A l m;
+#X msg 239 140 set 2 34;
+#X msg 238 171 set 3 17;
+#X msg 423 50 clr A;
+#X msg 427 126 get A;
+#X msg 427 158 get 2;
+#X msg 20 79 echodir \$1;
+#X obj 20 58 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1
+;
+#X obj 20 160 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1
+;
+#X msg 20 181 absdir \$1;
+#X text 422 30 clear value;
+#X text 423 104 get value;
+#X obj 309 505 print C;
+#X text 375 504 command;
+#X text 357 531 directory (abs or rel to current);
+#X text 320 594 data value;
+#X text 338 562 data key;
+#X msg 26 279 pool pool1;
+#X msg 27 308 pool;
+#X text 69 308 set to private;
+#X msg 27 370 reset;
+#X text 26 349 clear all pool data;
+#X msg 608 56 clrall;
+#X text 599 34 clear all values in dir;
+#X text 602 135 get all values in dir;
+#X text 314 442 pool name can be given as argument;
+#X text 598 81 clear all values and dirs;
+#X msg 606 103 clrrec;
+#X msg 600 203 getrec;
+#X text 600 181 get all values in dir and subdirs;
+#X text 652 232 bang at EOL;
+#X text 661 150 bang at EOL;
+#X text 655 202 depth may be given;
+#X text 22 258 data is shared among pool objects;
+#X text 23 237 set pool name;
+#X text 20 36 at each command;
+#X text 20 20 echo current dir;
+#X text 233 27 set values;
+#X text 15 141 (default on);
+#X text 7 125 report absolute dirs;
+#X msg 28 417 help;
+#X text 70 418 get some info;
+#X text 658 219 default=-1 (= infinite);
+#X msg 604 283 cntall;
+#X text 663 281 count all values in dir;
+#X msg 604 309 cntrec;
+#X text 665 307 ... and subdirs;
+#X text 661 321 (depth may be given);
+#X msg 237 226 add 3 14;
+#X text 235 205 set but don't replace;
+#N canvas 0 0 421 528 dirs 0;
+#X msg 109 27 mkdir fld1;
+#X msg 111 122 chdir;
+#X msg 110 217 updir;
+#X msg 111 354 getsub -1;
+#X text 110 7 make absolute dir;
+#X text 109 51 make relative dir;
+#X msg 110 72 mksub fld2;
+#X text 109 104 change to absolute dir;
+#X msg 110 165 chsub fld2;
+#X text 108 146 change to relative dir;
+#X text 106 198 change to upper dir;
+#X text 107 250 remove absolute dir;
+#X msg 108 269 rmdir fld1;
+#X msg 110 308 rmsub fld2;
+#X text 109 289 remove relative dir;
+#X text 109 336 get subdirs;
+#X text 239 379 -1 ... infinite;
+#X text 161 213 depth may be given;
+#X text 162 229 default=1;
+#X text 192 348 depth may be given;
+#X text 192 365 default=1;
+#X text 108 377 count subdirs;
+#X msg 111 398 cntsub -1;
+#X obj 11 239 outlet;
+#X msg 111 458 getdir;
+#X text 110 438 get current dir;
+#X text 172 457 always absolute;
+#X connect 0 0 23 0;
+#X connect 1 0 23 0;
+#X connect 2 0 23 0;
+#X connect 3 0 23 0;
+#X connect 6 0 23 0;
+#X connect 8 0 23 0;
+#X connect 12 0 23 0;
+#X connect 13 0 23 0;
+#X connect 22 0 23 0;
+#X connect 24 0 23 0;
+#X restore 713 494 pd dirs;
+#X text 710 468 directory operations;
+#N canvas 0 0 467 434 file 0;
+#X text 117 207 save dir and subdirs;
+#X text 117 165 save data in current dir;
+#X msg 117 184 svdir c:/temp/pool.dat;
+#X msg 117 226 svrec c:/temp/pool.dat;
+#X msg 116 272 lddir c:/temp/pool.dat;
+#X msg 116 319 ldrec c:/temp/pool.dat;
+#X text 117 253 load data into current dir;
+#X text 115 300 load data into current dir and below;
+#X text 132 340 depth (default -1) and;
+#X text 134 356 mkdir flag (default 1) can be given;
+#X obj 22 188 outlet;
+#X text 117 37 save all;
+#X text 117 81 load all (add to existing data);
+#X msg 118 100 load c:/temp/pool.dat;
+#X msg 120 54 save c:/temp/pool.dat;
+#X text 22 12 file operations;
+#X connect 2 0 10 0;
+#X connect 3 0 10 0;
+#X connect 4 0 10 0;
+#X connect 5 0 10 0;
+#X connect 13 0 10 0;
+#X connect 14 0 10 0;
+#X restore 714 549 pd file;
+#X text 712 526 file operations;
+#X text 712 583 clipboard operations;
+#N canvas 0 0 529 577 clip 0;
+#X obj 17 183 outlet;
+#X text 97 56 copy value associated to key into clipboard;
+#X msg 100 77 copy A;
+#X msg 98 119 cut B;
+#X text 96 101 cut value associated to key into clipboard;
+#X msg 96 401 paste;
+#X msg 98 179 copyall;
+#X text 95 158 copy all values in current dir into clipboard;
+#X msg 97 221 cutall;
+#X text 95 201 cut all values in current dir into clipboard;
+#X text 94 263 copy all values in current dir into clipboard;
+#X text 94 306 cut all values in current dir into clipboard;
+#X msg 97 284 copyrec;
+#X text 194 285 depth may be given (default=-1);
+#X text 193 326 depth may be given (default=-1);
+#X msg 96 326 cutrec 1;
+#X text 194 345 1..only with first level subdirs;
+#X text 96 379 paste clipboard contents into current directory;
+#X text 167 397 depth (default -1) and;
+#X text 169 413 mkdir flag (default 1) can be given;
+#X text 171 448 depth (default -1) and;
+#X text 173 466 mkdir flag (default 1) can be given;
+#X msg 95 453 pasteadd;
+#X text 95 431 paste but don't replace;
+#X msg 94 521 clrclip;
+#X text 160 523 clear clipboard (free memory);
+#X text 22 12 clipboard operations (this is an internal clipboard...)
+;
+#X connect 2 0 0 0;
+#X connect 3 0 0 0;
+#X connect 5 0 0 0;
+#X connect 6 0 0 0;
+#X connect 8 0 0 0;
+#X connect 12 0 0 0;
+#X connect 15 0 0 0;
+#X connect 22 0 0 0;
+#X connect 24 0 0 0;
+#X restore 714 606 pd clip;
+#X text 712 437 more commands:;
+#X obj 780 494 s \$0-pool;
+#X obj 778 549 s \$0-pool;
+#X obj 778 606 s \$0-pool;
+#X obj 349 392 r \$0-pool;
+#X connect 0 0 5 0;
+#X connect 0 1 2 0;
+#X connect 0 2 6 0;
+#X connect 0 3 19 0;
+#X connect 1 0 0 0;
+#X connect 3 0 0 0;
+#X connect 4 0 0 0;
+#X connect 7 0 0 0;
+#X connect 8 0 0 0;
+#X connect 9 0 0 0;
+#X connect 10 0 0 0;
+#X connect 11 0 0 0;
+#X connect 12 0 0 0;
+#X connect 13 0 0 0;
+#X connect 14 0 13 0;
+#X connect 15 0 16 0;
+#X connect 16 0 0 0;
+#X connect 24 0 0 0;
+#X connect 25 0 0 0;
+#X connect 27 0 0 0;
+#X connect 29 0 0 0;
+#X connect 34 0 0 0;
+#X connect 35 0 0 0;
+#X connect 47 0 0 0;
+#X connect 50 0 0 0;
+#X connect 52 0 0 0;
+#X connect 55 0 0 0;
+#X connect 57 0 64 0;
+#X connect 59 0 65 0;
+#X connect 62 0 66 0;
+#X connect 67 0 0 0;