//The NODE and the WHEEL of NODES
//Written By Billy Stiltner COPYRIGHT 1996 Billy Stiltner
/*/
Copyright (C) 1995  Billy Stiltner

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation;

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
/*/
//#include<alloc.h>
//This is a very simple set of classes for a Node and List
///////////////////////////////////////////////////////////////////
unsigned long nexusconstructors;
unsigned long roticonstructors;
unsigned long nexusdestructors;
unsigned long rotidestructors;
class NEXUS;
typedef void (NEXUS::*pMF)();
//typedef class *pC;

class NEXUS
{
public:
//data members
NEXUS *next;
NEXUS *previous;
//member functions
NEXUS();
NEXUS *GET_NEXT();
NEXUS *operator ++();
NEXUS *operator --();
//NEXUS *operator +(int n);
//NEXUS *operator -(int n);
int IS_PRIMUS();
int IS_MAXIMUS();
int IS_INTERNEXUS();
int IS_UNUSNEXUS();
virtual ~NEXUS();
};
///////////////////////////////////////////////////////////////////     .


///////////////////////////////////////////////////////////////////////////
class ROTI : public NEXUS
{
public:
 //data members
 NEXUS *PRIMUS;
 NEXUS *MAXIMUS;
 NEXUS *PROXIMUS;
 NEXUS *BUFF;
 //member functions
 ROTI();
 void PUT_PRIMUS(NEXUS *p);
 void PUT_MAXIMUS(NEXUS *p);
 void PUT_BEFORE_PROXIMUS(NEXUS *p);
 void PUT_AFTER_PROXIMUS(NEXUS *p);
 void PUT_BEFORE_NEXUS(NEXUS *p,NEXUS *q);
 void PUT_AFTER_NEXUS(NEXUS *p,NEXUS *q);
 void XFER(NEXUS *n,ROTI *r);
 void DELETE_NEXUS(NEXUS *p);
 void FOR_EACH(pMF pFunc);
 void EXTRACT_NEXUS(NEXUS *p);
~ROTI();
};
/////////////////////////////////////////////////////////////////////


///////////////////////////////////////////////////////////////////////////
NEXUS::NEXUS()
{
//nexusconstructors++;
next=NULL;
previous=NULL;
}
///////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////
int NEXUS::IS_PRIMUS()
{
if((previous==NULL)&&(next!=NULL))
return(1);else return(0);
}
//////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////
int NEXUS::IS_MAXIMUS()
{
if((next==NULL)&&(previous!=NULL))
return(1);else return(0);
}
//////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////
int NEXUS::IS_INTERNEXUS()
{
if((previous!=NULL)&&(next!=NULL))
return(1);else return(0);
}
//////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////
int NEXUS::IS_UNUSNEXUS()
{
if((previous==NULL)&&(next==NULL))
return(1);else return(0);
}
//////////////////////////////////////////////////////////////////////////////


///////////////////////////////////////////////////////////////////////////
NEXUS *NEXUS::GET_NEXT()
{ // NEXUS *j;
//j=this->next;
return(next);
}
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
inline NEXUS *NEXUS::operator ++()
{ // NEXUS *j;
//j=this->next;
return(next);
}
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
inline NEXUS *NEXUS::operator --()
{
return(previous);
}
///////////////////////////////////////////////////////////////////////////

/*///////////////////////////////////////////////////////////////////////////
inline NEXUS *NEXUS::operator +(int n)
{
 int c;
 NEXUS *np;
np=this;
if(np!=NULL)
{
 for(c=0;c<n;c++)
     {
      np=np->next;
      if(np==NULL)break;
      };
};
return(np);
};
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
inline NEXUS *NEXUS::operator -(int n)
{
 int c;
 NEXUS *np;
np=this;
if(np!=NULL)
{
 for(c=0;c<n;c++)
     {
      np=np->previous;
      if(np==NULL)break;
      };
};
return(np);
};
//*/////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
NEXUS::~NEXUS()
{
//nexusdestructors++;
//cout<<"IN NEXUS Destructor"<<"\n";
}
///////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////
ROTI::ROTI():NEXUS()
{
//roticonstructors++;
 PRIMUS=NULL;
 MAXIMUS=NULL;
 PROXIMUS=NULL;
 BUFF=NULL;
}
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////
void ROTI::PUT_PRIMUS(NEXUS *p)
{
 p->next = PRIMUS;
 p->previous = NULL;
 if(!p->IS_UNUSNEXUS()){
 p->next->previous = p;
 }else{
        MAXIMUS = p;
        };
 PRIMUS = p;
}
////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////
void ROTI::PUT_MAXIMUS(NEXUS *p)
{
 p->previous = MAXIMUS;
 p->next = NULL;
 if(!p->IS_UNUSNEXUS()){
 p->previous->next = p;
 }else{
        PRIMUS = p;
        };
 MAXIMUS = p;
}
///////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////
void ROTI::PUT_BEFORE_PROXIMUS(NEXUS *p)
{
if(PROXIMUS!=NULL)PUT_BEFORE_NEXUS(p,PROXIMUS);
}
////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////
void ROTI::PUT_AFTER_PROXIMUS(NEXUS *p)
{
if(PROXIMUS!=NULL)PUT_AFTER_NEXUS(p,PROXIMUS);
}
////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////
void ROTI::PUT_BEFORE_NEXUS(NEXUS *p,NEXUS *q)
{
if(q!=NULL)
  {
    if((q->IS_INTERNEXUS())||(q->IS_MAXIMUS()))
      {
        p->next=q;
        p->previous=q->previous;
        q->previous->next=p;
        q->previous=p;
      }else{
      if(q->IS_PRIMUS())PUT_PRIMUS(p);
      }
  }
}
////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////
void ROTI::PUT_AFTER_NEXUS(NEXUS *p,NEXUS *q)
{
if(q!=NULL)
  {
  if((q->IS_INTERNEXUS())||(q->IS_PRIMUS()))
     {
      p->previous=q;
      p->next=q->next;
      q->next->previous=p;
      q->next=p;
     }else{
      if(q->IS_MAXIMUS())PUT_MAXIMUS(p);
     }
  }
}
////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////
void ROTI::XFER(NEXUS *n,ROTI *r)
{
 //-+EXTRACT_NEXUS(n);
 r->PUT_MAXIMUS(n);
}
////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////
//REMOVES NEXUS FROM ROTI AND DELETES NEXUS
void ROTI::DELETE_NEXUS(NEXUS *p)
{
if((p->next!=NULL)&&(p->previous!=NULL)) //if p is between
{
 p->previous->next=p->next;//adjust previous
 p->next->previous=p->previous;//adjust next
 if(PROXIMUS==p)PROXIMUS=p->next; //if p was PROXIMUS make next PROXIMUS
 if(p!=NULL)delete p;//delete p
 return;
}
if(p->next==NULL)
{
 MAXIMUS=p->previous;
 p->previous->next=NULL;
 if(PROXIMUS==p)
 {
 if(p->previous==NULL){
    PROXIMUS=NULL;}else{PROXIMUS=p->previous;}
 }
    if(p!=NULL)delete p;
    return;
}

if(p->previous==NULL)
{
 PRIMUS=p->next;
 p->next->previous=NULL;
 if(PROXIMUS==NULL)
 {
  if(p->next==NULL){
         PROXIMUS=NULL;}else{PROXIMUS=p->next;}
 }
    if(p!=NULL)delete p;
 return;
}
//if(p->pPORTAL!=NULL)delete p->pPORTAL;
}
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
//EXTRACTS A NEXUS FROM LIST WITHOUT DELETING
void ROTI::EXTRACT_NEXUS(NEXUS *p)
{
 if(p->previous==NULL){
     PRIMUS=p->next;
     p->next->previous=NULL;
     }
 if(p->next==NULL){
     MAXIMUS=p->previous;
     p->previous->next=NULL;
     }
 if((p->next!=NULL)&&(p->previous!=NULL)){
 p->previous->next=p->next;
 p->next->previous=p->previous;
 }
}
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
void ROTI::FOR_EACH(pMF pFunc)
{
 if((PRIMUS!=NULL)&&(MAXIMUS!=NULL))//if not emptty
 for(NEXUS *current=PRIMUS;         //start on PRIMUS
      current!=NULL;                 //Stop after Maximus
      current=++(*current))          //increment current
 (current->*pFunc)();               //call current function


}
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
ROTI::~ROTI()
{
//rotidestructors++;
//cout<<"\n"<<"IN ROTI Destructor"<<"\n";
/*/
//roti can only be a base class and nexus can only be a base class
if(PRIMUS!=NULL)
 {
 NEXUS *NEXT;
  NEXUS* current = PRIMUS;
  for(;;)
      {
      NEXT=current->next;
        if(current!=NULL)delete current;
        if(current == NULL)break;
        current=NEXT;
      };
  };
 /*/
}
///////////////////////////////////////////////////////////////////

I know Miller doesn't use c++,
I only use a limited subset of c++

here is the above code used in more code
I would like to know how do do this in c
about the only thing I used c++ for is
object oriented programming so that data of classes could have functions associated with them, the inheritance model i used might be a bit hard to follow then there is the problem of using borland style macros which simplifies defining member functions , it was something dreamed up in the development of borland's visual studio so that windows programs could be visually written, kind of how puredata is a visusual programming environment except the 2 approaches are very different.
What are the differences?

/*/
Impulse.h See below for description.
Copyright (C) 1995  Billy Stiltner

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License,

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
/*/

//The classes herein can be used together to provide a basis for a
//response mechanism.
//
//The impulse is a node based object.
//
//The Reactor is a list based object.
//
//The Coordinator is used as a wrapper in that it maintains two Reactors,
//an ACTIVE Reactor, and an INACTIVE Reactor so that responses can be
//loaded and unloaded hence DYNAMIC RESPONSE LOADING (DRL).
//
//The Coordinator can make reflexes and responses.
//
//The impulse is a dual natured class, it can be a reflex or a response.
//
//The reflex is created with a pointer to a variable uint *Var, a uint
//Condition, and a pMF pFunc. HOW IT WORKS: reflex's VAR is set to Var,
//CONDITION is set to Condition, and RESPOND is set to pFunc, if *VAR,
//wherever it may be, is equal to CONDITION, whatever it may be, RESPOND,
//whatever it does, is CALLED.
//
//The response is created with a uint Message and a pMF pFunc. HOW IT WORKS:
//response's CONDITION is set to Message and RESPOND is set to pFunc, *VAR
//must be provided at response time if *VAR = CONDITION then RESPOND is CALLED.
//
//The Reactor maintains reflexes and responses, it can only hold one
//type of impulse, but can hold as many as there is memory to put them.
//
//
//include files//////////////////////////////////////////////////////////////
//#include<objects.h>
//#include<nexus.h>
//#include"c:\program\svga\objects.h"
/////////////////////////////////////////////////////////////////////////////

//defines////////////////////////////////////////////////////////////////////
#define TORPID 0L
#define AWAKE 1L
/////////////////////////////////////////////////////////////////////////////

//variables//////////////////////////////////////////////////////////////////
unsigned long impulseconstructors;
unsigned long coordinatorconstructors;
unsigned long impulsedestructors;
unsigned long coordinatordestructors;
/////////////////////////////////////////////////////////////////////////////

//classes////////////////////////////////////////////////////////////////////
class impulse:  public NEXUS
{
 public://access modifier
//data members///////////////////////////////////////////////////////////////
 pMF RESPOND;                   //*function to call if message = CONDITION
 unsigned int *VAR;             //unsigned int pointer to a variable to check
 unsigned int CONDITION;        //value to compare condition with
//member functions///////////////////////////////////////////////////////////
 //impulse();                             //default constructor sets all to NULL
 impulse(impulse *i);                   //constructer using impulse *
 impulse(unsigned int Message,          //consructor to make a response
     pMF pFunc);
 impulse(unsigned int *Var,             //consructor to make a reflex
     unsigned int Condition,
     pMF pFunc);
 void makeresponse(unsigned int Message,//function to make a response
            pMF pFunc);
 void makereflex(unsigned int *Var,     //function to make a reflex
         unsigned int Condition,
         pMF pFunc);
 void respond(NEXUS *pN);               //function to call when responding

 ~impulse();                   //destructor
};
/////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
class Reactor : public ROTI
{
public:
 //data members
 //member functions
 Reactor();
 //void DefineResponse(impulse *im);
  impulse *DefineReflex(unsigned int *Var,
             unsigned int Condition,
             pMF pFunc);
  impulse *DefineResponse(unsigned int Message,
              pMF pFunc);
  virtual void Reflex(NEXUS *pN);
  virtual void Respond(MSG *Msg,NEXUS *pN);
  ~Reactor();
};
////////////////////////////////////////////////////////////////////////////


/////////////////////////////////////////////////////////////////////
class Coordinator
{
public:
Reactor *ACTIVE;
Reactor *INACTIVE;
Coordinator();
impulse *MakeReflex(unsigned int *Var,
             unsigned int Condition,
             pMF pFunc);
impulse *MakeResponse(unsigned int Message,
              pMF pFunc);
void Activate(impulse *i);
void Deactivate(impulse *i);
virtual void Reflex(NEXUS *pN);
virtual void Respond(MSG *Msg,NEXUS *pN);
~Coordinator();
};
////////////////////////////////////////////////////////////////////

//SUGGESTION:
//make a member of class x

// x::MakeResponseTable()
// {
// DEFINE_RESPONSE(x,MessageId,NameOfFunctionCalledInResponseToMessageId);
// etc...
// }
////////////////////////////////////////////////////////////////////////
#define DEFINE_RESPONSE(classname,\
            imessage,\
            ifunctionname)\
    DefineResponse(imessage,\
                 (pMF)&classname::ifunctionname);
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
#define DEFINE_REFLEX(classname,\
                nvar,\
                ncondittion,\
                nfunctionname)\
    DefineReflex(nvar,\
              ncondittion,\
              (pMF)&classname::nfunctionname);
//////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////
#define MAKE_RESPONSE(classname,\
            imessage,\
            ifunctionname)\
    MakeResponse(imessage,\
                 (pMF)&classname::ifunctionname);
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
#define MAKE_REFLEX(classname,\
                nvar,\
                ncondittion,\
                nfunctionname)\
    MakeReflex(nvar,\
              ncondittion,\
              (pMF)&classname::nfunctionname);
//////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////
impulse::impulse(unsigned int Message,pMF pFunc) : NEXUS()
{  // void (impulse::*pFunc)()):NEXUS()
impulseconstructors++;
CONDITION=Message;
RESPOND=pFunc;
}
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
impulse::impulse(impulse *i):NEXUS()
{
impulseconstructors++;
RESPOND=i->RESPOND;
VAR=i->VAR;
CONDITION=i->CONDITION;
}
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
//impulse::impulse():NEXUS()
//{
//impulseconstructors++;
//VAR=NULL;
//CONDITION=NULL;
//RESPOND=NULL;
//};
///////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////
impulse::impulse(unsigned int *Var,
             unsigned int Condition,
             pMF pFunc):NEXUS()
{
impulseconstructors++;
VAR=Var;
CONDITION=Condition;
RESPOND=pFunc;
}
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
void impulse::makeresponse(unsigned int Message, pMF pFunc)
{
CONDITION=Message;
RESPOND=pFunc;
VAR=NULL;
}
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
void impulse::respond(NEXUS *pN)
{
 (pN->*RESPOND)();//This works but all RESPOND functions must be NEXUS
 //(this->*RESPOND)();
 //RESPOND();
 //return(RESPOND);
}
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
impulse::~impulse()
{
impulsedestructors++;
//cout<<"\n"<<"IN impulse Destructor"<<"\n";
}
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
void impulse::makereflex(unsigned int *Var,
              unsigned int Condition,
              pMF pFunc)
{
VAR=Var;
CONDITION=Condition;
RESPOND=pFunc;
}
///////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////
Reactor::Reactor():ROTI()
{
coordinatorconstructors++;
}
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////
impulse * Reactor::DefineResponse(unsigned int Message,
                 pMF pFunc)
{
 impulse* newimpulse = new impulse(Message,pFunc);
 PUT_MAXIMUS(newimpulse);
 return(newimpulse);
}
///////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////

impulse * Reactor::DefineReflex(unsigned int *Var,
                unsigned int Condition,
                pMF pFunc)
{
 impulse* newnatural = new impulse(Var,Condition,pFunc);
 PUT_MAXIMUS(newnatural);
 return(newnatural);
}
///////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
void Reactor::Respond(MSG *Msg,NEXUS *pN)
{
if(PRIMUS!=NULL)
 {
  impulse* current = (impulse *)PRIMUS;
  for(;;)
      {
        if(current->CONDITION==Msg->message){
        current->respond(pN);
        break;
        }
        if(current->next == NULL)break;
        current=(impulse *)current->next;
      }
  }
}
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
void Reactor::Reflex(NEXUS *pN)
{
if(PRIMUS!=NULL)
 {
  impulse* current =(impulse *) PRIMUS;
  for(;;)
      {
        if(current->CONDITION==*(current->VAR)){
        current->respond(pN);
        }
        if(current->next == NULL)break;
        current=(impulse *)current->next;
      }
  }
}
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
Reactor::~Reactor()
{
coordinatordestructors++;

if((PRIMUS!=NULL)&&(MAXIMUS!=NULL))//if not emptty
for(NEXUS *current=PRIMUS;         //start on PRIMUS
     current!=NULL;                 //Stop after Maximus
     current=++(*current))          //increment current
delete current;
//cout<<"\n"<<"IN Reactor Destructor"<<"\n";
//NEXUS* NEXT;
//NEXUS* current = PRIMUS;//IDLE->PRIMUS;
//if(PRIMUS!=NULL)//IDLE->PRIMUS!=NULL)
 //{
  //for(;;)
     // {
     // NEXT=current->next;
     //    if(current!=NULL)delete current;
      //    if(current == NULL)break;
      //    current=NEXT;
      //    }
  //}
}
///////////////////////////////////////////////////////////////////

Coordinator::Coordinator()
{
ACTIVE=new Reactor();
INACTIVE=new Reactor();
}
///////////////////////////////////////////////////////////////////
impulse * Coordinator::MakeResponse(unsigned int Message,
                 pMF pFunc)
{
 impulse* newimpulse = ACTIVE->DefineResponse(Message,pFunc);
 return(newimpulse);
}
///////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////
impulse * Coordinator::MakeReflex(unsigned int *Var,
                unsigned int Condition,
                pMF pFunc)
{
 impulse *newreflex;
 newreflex=ACTIVE->DefineReflex(Var,Condition,pFunc);
 return(newreflex);
}
/////////////////////////////////////////////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////
void Coordinator::Activate(impulse *i)
{
//this method of activation is slower than another type that would take
//up more memory so this type takes up less memory
//so this is the small slow version
//1 see if i is inactive
//2 see if i is already active
impulse *current;
//iterate through the inactive list
for(current=(impulse *)INACTIVE->PRIMUS;
     current!=NULL;
     current=(impulse *)current->next)
//see if i is in here
if(i==current)
{
//if so iterate through the active list
for(current=(impulse *)ACTIVE->PRIMUS;
     current!=NULL;
     current=(impulse *)current->next)
     if(i==current)return;//get out if i is already in the active  list
     //if we made it here i aint already active
INACTIVE->EXTRACT_NEXUS(i);//if not active get i out of inactive list
ACTIVE->PUT_MAXIMUS(i);//and put i in active list
break;
}
}
/////////////////////////////////////////////////////////////////////////////


/////////////////////////////////////////////////////////////////////////////
void Coordinator::Deactivate(impulse *i)
{
//1 see if i is active
//2 see if i is already inactive
impulse *current;
for(current=(impulse *)ACTIVE->PRIMUS;
     current!=NULL;
     current=(impulse *)current->next)
if(i==current)
{
for(current=(impulse *)INACTIVE->PRIMUS;
     current!=NULL;
     current=(impulse *)current->next)if(i==current)return;
ACTIVE->EXTRACT_NEXUS(i);
INACTIVE->PUT_MAXIMUS(i);
break;
}
}


///////////////////////////////////////////////////////////////////////////
void Coordinator::Respond(MSG *Msg,NEXUS *pN)
{
 ACTIVE->Respond(Msg,pN);
};
///////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////
void Coordinator::Reflex(NEXUS *pN)
{
 ACTIVE->Reflex(pN);
}
///////////////////////////////////////////////////////////////////////////


Coordinator::~Coordinator()
{
if(ACTIVE!=NULL)delete ACTIVE;
if(INACTIVE!=NULL)delete INACTIVE;
}


On Fri, Mar 31, 2017 at 8:44 AM, Billy Stiltner <billy.stiltner@gmail.com> wrote:
i dont like tree structures at the moment
but here ya go
void Spider(xTreeItem CurrentItem)
{
    int s;
    CString spaces;
    CString xStr;
    //There Could Probably Be More Vars Here To Save Space
    //Down There...  There Also Needs To Be Some Space
    //Generating Loop Code Put Into A Function

    //CurrentItem Is Either A Branch Or A Leaf
    //The Processing Of CurrentItem Will Be Different
    //For Each State Of CurrentItem
    if(CurrentItem.IsBranch())
    {
        CString currentpath;
        CString currenturl;
       
        //Set Up All The Path Variables And File Names
        //And Levels
        CurrentLevel ++;
        currentpath = BasePath;
        currenturl = BaseURL;   
        CurrentItem.FileName = "index.txt";
        CurrentItem.Level = CurrentLevel;           
        DirectoryL[CurrentLevel] = CurrentItem.Directory;
       
        for(int l = 1; l <= CurrentLevel; l ++)
        {
            currentpath += "\\" + DirectoryL[l];
            currenturl += "/" + DirectoryL[l];     
        }

        CurrentItem.LocalHtmlPath=currentpath + "\\index.html";
        CurrentItem.Url = currenturl + "/index.html";
        currentpath += "\\index.txt";
       
        //Add This Branch Item To The Flat List
        xTreeItems.Add(xTreeItem(CurrentItem));

        spaces = MakeSpace(CurrentLevel);
        TocFile.WriteString(spaces);//Toc File Was Opened For Append Each
                                 //Write To Eat Bugs
       
        //Start A New Division
        TocFile.WriteString("<UL>\n<LI>\n");
        TocFile.WriteString(CurrentItem.MakeSiteMapObject());
       
        //This Is A New Branch So Keep Spidering
        InputIndexFile[CurrentLevel].Open(currentpath,
                            CFile::modeRead |
                            CFile::typeText);
        HtmlOutputFile[CurrentLevel].Open(CurrentItem.LocalHtmlPath,
                            CFile::modeCreate |
                            CFile::modeWrite | CFile::typeText );
        //Start A Fresh Html Page
        HtmlOutputFile[CurrentLevel].WriteString("<HTML>\n<Body>\n");
       
        //Create A Link From The Entry
        HrefL[CurrentLevel] = CurrentItem.MakeHref();

        //Make A Line Hrefs That Link To The Parent Level(s)
        CString DirectoryBar;
        DirectoryBar="";
        for(int h = 1; h < CurrentLevel; h++)
        {
            DirectoryBar += HrefL[h] + " / ";
        }

        //Put The DirectoryBar On The Page
        HtmlOutputFile[CurrentLevel].WriteString(DirectoryBar +
                                            CurrentItem.Name +
                                            "<BR><BR>\n");
       
        //If This Is Not The Root
        if(CurrentLevel > 1)
        {
            //Then Put A Link To This Page
            //On This Item's Parent's Page
            HtmlOutputFile[CurrentLevel - 1].WriteString(
                                            CurrentItem.MakeHref() +
                                             "<BR>\n");
        }
       
       
        for(;;)
        {
            //If We Don't Hit EOF Spider Recursively   
            if(InputIndexFile[CurrentLevel].ReadString(xStr))
            {
                xTreeItem NewTreeItem;
                NewTreeItem.InitFromTxtEntry(xStr);
                Spider(NewTreeItem);   
            }
            //If We Do Hit EOF
            else
            {       
                //Close This Division
                TocFile.WriteString("</UL>\n");

                //Close This Input File
                InputIndexFile[CurrentLevel].Close();

                //This Could Be A (Nifty Page Ground)
                //HtmlOutputFile[CurrentLevel].WriteString(themeFooter);

                //Close The Html And Body Tags And The File
                HtmlOutputFile[CurrentLevel].WriteString(
                                            "</Body>\n</Html>\n");
                HtmlOutputFile[CurrentLevel].Close();

                //Decrement The CurrentLevel And Break Out Of The Loop
                //So We Can Return To Whence We Came Which Was
                //Probably Up There Where It Says Spider(NewTreeItem);
                CurrentLevel --;
                break;
                //Maybe This Is Where The Recursive Action Ends Hmmm...
                //All Those pMFs Pushed On The Stack Get Popped Right
                //Back On To IP... OH Wait The Class This Function Used
                //To Belong To Has Probably Been Removed For The Sake
                //Of Simpleness So pFs If So
            }
        }   
    }
    //Here Is Where The Leaf Gets Processed
    else
    {
        //First We Need To Make Sure CurrentItem Has A URL   
        if(CurrentItem.Url)
        {
            xTreeItem LeafTreeItem;
            LeafTreeItem.copy(CurrentItem);
           
            //The Leaf Is As Far As The Spider Will Crawl
            //So There's No Need To Increment The CurrentLevel
            //Just Set The LeafTreeItem's Level To CurrentLevel + 1
            LeafTreeItem.Level = CurrentLevel + 1;
           
            //Ah Add The Item To The Flat List
            xTreeItems.Add(xTreeItem(LeafTreeItem));   
           
            //Nothing Done With Spaces Yet Here
            //Need To Standardize And Functionize The TocFile Writes
            spaces = MakeSpace(CurentLevel + 1);
           
            //Start A New Division I The Toc And Put This Item
            //In As The Head Of The Division
            TocFile.WriteString("<UL>\n<LI>\n");
            TocFile.WriteString(LeafTreeItem.MakeSiteMapObject());

           
            //Throw It In It's Parent's List Of Links
            HtmlOutputFile[CurrentLevel].WriteString(LeafTreeItem.MakeHref() +
                                                 "<BR>\n");
           
            //Loop Through The Rest Of The File
            //Here Is Where It's Assumed That All
            //Items That Follow Are Leaves
            //This Is Fine For Our DirectoryTree Spider
            //Where All The Links In The Deepest Folder
            //Are Outside Of The Crawler's Space
            //But Not For A Web Crawler
            for(;;)
            {
               
                if(InputIndexFile[CurrentLevel].ReadString(xStr))
                {
                    //Again As Above
                    LeafTreeItem.InitFromTxtEntry(xStr);
                    LeafTreeItem.Level = CurrentLevel + 1;
                   
                    xTreeItems.Add(xTreeItem(LeafTreeItem));       

                    //Those Spaces Again
                    spaces = MakeSpace(CurrentLevel + 1);
                   
                    //We Are Allready In A Division So Just
                    //Make A New Entry
                    TocFile.WriteString("<LI>\n");       
                    TocFile.WriteString(LeafTreeItem.MakeSiteMapObject());
                   
                    //Throw It In It's Parent's List Of Links
                    HtmlOutputFile[CurrentLevel].WriteString(
                                  LeafTreeItem.MakeHref() + "<BR>\n");
                }
                else
                {
                    //Close The Division... We Ran Out Of File                   
                    TocFile.WriteString("</UL>\n");

                    //Get Out Of The Loop And Return To Next Line Of Caller
                    //Which Was Probably This Very Function               
                    break;

                    //This Could Be Where The Recursive Action Ends
                    //Nah I Think It's Up There At The Branch Break
                    //Cause You Have To Start The Spider On A Branch
                    //Unless The Spider Drops From Another Tree And
                    //Lands On A Leaf
                }
               
            }
        }       
    }
}

more on the spider later
http://geocities.ws/billy_stiltner/code/OSOS-3_25_am_06_06_02.zip

On Thu, Mar 30, 2017 at 9:28 AM, Christof Ressi <christof.ressi@gmx.at> wrote:
> If it was possible to have an array of pointers,

I get your idea. You can already have [list]s of pointers but this is rather cumbersome. Sometimes I've wished that pointers could be fields in structs (don't know why that's not possible...). Together with a mechanism to compare pointers (right now you can only route them by their type) these could indeed add some new possibilities.

Gesendet: Mittwoch, 29. März 2017 um 15:37 Uhr
Von: "José de Abreu" <abreubacelar@gmail.com>
An: "Derek Kwan" <derek.x.kwan@gmail.com>, "Christof Ressi" <christof.ressi@gmx.at>, pd-list@lists.iem.at
Betreff: Re: [PD] [text define] functionality for text in structs?
Hello, this is my first e-mail on the list, and i don't understand the code of pd or anything like that, but I have an idea. Plus, sorry for bad english.
If it was possible to have an array of pointers, maintained by the user, we could jump to some scalar in the list, say I have 1000 scalars, and an array with pointers to 100th, 200th, 300th, or any combination. This would improve the search.
Maybe this would be a list/array of pointers inside another scalar? What do you think?
Using this design, the user itself can create his own structures with pointers, creating trees,  graphs with the scalars themself.
It make sense?
 

Em Qua, 29 de mar de 2017 08:47, Derek Kwan <derek.x.kwan@gmail.com[mailto:derek.x.kwan@gmail.com]> escreveu:"Christof Ressi" <christof.ressi@gmx.at[mailto:christof.ressi@gmx.at]> writes:


> I have - and traversing large lists of scalars by pointer can be veeeery slow.
>
yeahhhh, i figured that could be the case =P

> you could hide the fact that it's a linked list from the user but I
> don't know if that's a good thing to do. It doesn't seem transparent
> to me ("why is accessing the 1000th elements slower than the 1st
> element?").

I suppose you could tell the user via documentation, but then you'd have
go into what a linked list is and why linked list indexing is
O(n) versus array O(1) to explain the speed difference and yeah,
I see your point haha. And it's probably not good either to have a layer
of abstraction that isn't totally necessary either.

>
> if you don't use the graphical representation, you can just as well
> work with data structure arrays and get fast random access. there is
> one little but unfortunate drawback compared to using lists of
> scalars: drawn instances of array elements don't respond to mouse
> events, making them more or less useless as UI elements. if you
> click/select an element, you only get a pointer to the array, not to
> the element(s). if you click on the canvas, you get pointers to the
> array + all array elements (for whatever reason).
> The right behaviour IMHO would be that clicking/selecting array
> elements gives you pointers to the array *and* the clicked/selected
> element(s). clicking on the empty canvas shouldn't trigger any mouse
> events!
>
> Apart from that, data structure arrays are quite easy to handle and
> much more efficient than linked lists of scalars

ah, that's interesting. admittedly, i haven't used pd structs that much
in my pd work as of yet but the stuff i want to do seems to be
increasingly lending itself to that (or a similar) sort of paradigm so
i'll keep that in mind!

Derek

--
Derek Kwan
www.derekxkwan.com[http://www.derekxkwan.com]

_______________________________________________
Pd-list@lists.iem.at[mailto:Pd-list@lists.iem.at] mailing list
UNSUBSCRIBE and account-management -> https://lists.puredata.info/listinfo/pd-list[https://lists.puredata.info/listinfo/pd-list]

_______________________________________________
Pd-list@lists.iem.at mailing list
UNSUBSCRIBE and account-management -> https://lists.puredata.info/listinfo/pd-list