You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kvirc/src/kvirc/kvs/kvi_kvs_object_class.cpp

235 lines
7.0 KiB

//=============================================================================
//
// File : kvi_kvs_objectclass.cpp
// Created on Sat 23 Apr 2005 20:31:32 by Szymon Stefanek
//
// This file is part of the KVIrc IRC client distribution
// Copyright (C) 2005 Szymon Stefanek <pragma at kvirc dot net>
//
// 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, or (at your opinion) any later version.
//
// 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. ,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
//=============================================================================
#define __KVIRC__
#include "kvi_kvs_object_class.h"
#include "kvi_kvs_object_controller.h"
#include "kvi_kvs_object.h"
#include "kvi_kvs_kernel.h"
#include "kvi_kvs_object_functionhandlerimpl.h"
#include "kvi_kvs_object_functioncall.h"
#include "kvi_kvs_runtimecontext.h"
#include "kvi_kvs_variantlist.h"
#include "kvi_kvs_script.h"
#include "kvi_fileutils.h"
#include "kvi_window.h"
#include "kvi_cmdformatter.h"
KviKvsObjectClass::KviKvsObjectClass(
KviKvsObjectClass * pParent,
const TQString &szName,
KviKvsObjectAllocateInstanceProc pProc,
bool bBuiltin)
{
m_pParentClass = pParent;
if(m_pParentClass)
m_pParentClass->registerChildClass(this);
m_szName = szName;
m_bBuiltin = bBuiltin;
m_bDirty = !bBuiltin;
m_pFunctionHandlers = new KviPointerHashTable<TQString,KviKvsObjectFunctionHandler>(17,false);
m_pFunctionHandlers->setAutoDelete(true);
m_pChildClasses = new KviPointerList<KviKvsObjectClass>;
m_pChildClasses->setAutoDelete(false);
m_allocProc = pProc ? pProc : pParent->m_allocProc;
// inherit everything from the class above
if(pParent)
{
KviPointerHashTableIterator<TQString,KviKvsObjectFunctionHandler> it(*(pParent->functionHandlers()));
while(KviKvsObjectFunctionHandler * fh = it.current())
{
m_pFunctionHandlers->insert(it.currentKey(),fh->clone());
++it;
}
}
// "object" class is automatically registered in the controller constructor
KviKvsKernel::instance()->objectController()->registerClass(this);
}
KviKvsObjectClass::~KviKvsObjectClass()
{
// order here is critical
// first of all kill our child classes
while(m_pChildClasses->first())delete m_pChildClasses->first();
// then kill all objects that belong to our class
KviKvsKernel::instance()->objectController()->killAllObjectsWithClass(this);
// now we're quite clean: should have no object depending on us alive
// unregister from the parent, if any
if(m_pParentClass)m_pParentClass->unregisterChildClass(this);
// unregister from the object controller
KviKvsKernel::instance()->objectController()->unregisterClass(this);
// and start effectively dying
delete m_pFunctionHandlers;
// this is empty now
delete m_pChildClasses;
}
void KviKvsObjectClass::registerFunctionHandler(const TQString & szFunctionName,KviKvsObjectFunctionHandlerProc pProc,unsigned int uFlags)
{
m_pFunctionHandlers->replace(szFunctionName,new KviKvsObjectCoreCallFunctionHandler(pProc,uFlags));
}
void KviKvsObjectClass::registerFunctionHandler(const TQString & szFunctionName,const TQString &szBuffer,unsigned int uFlags)
{
TQString szContext = m_szName;
szContext += "::";
szContext += szFunctionName;
m_pFunctionHandlers->replace(szFunctionName,new KviKvsObjectScriptFunctionHandler(szContext,szBuffer,uFlags));
}
void KviKvsObjectClass::registerStandardNothingReturnFunctionHandler(const TQString &szFunctionName)
{
m_pFunctionHandlers->replace(szFunctionName,new KviKvsObjectStandardNothingReturnFunctionHandler());
}
void KviKvsObjectClass::registerStandardTrueReturnFunctionHandler(const TQString &szFunctionName)
{
m_pFunctionHandlers->replace(szFunctionName,new KviKvsObjectStandardTrueReturnFunctionHandler());
}
void KviKvsObjectClass::registerStandardFalseReturnFunctionHandler(const TQString &szFunctionName)
{
m_pFunctionHandlers->replace(szFunctionName,new KviKvsObjectStandardFalseReturnFunctionHandler());
}
KviKvsObject * KviKvsObjectClass::allocateInstance(KviKvsObject * pParent,const TQString &szName,KviKvsRunTimeContext * pContext,KviKvsVariantList * pParams)
{
if(!m_allocProc)return 0;
KviKvsObject * pObject = m_allocProc(this,pParent,szName);
if(!pObject)return 0;
KviKvsVariant * v=pParams->first(); // FIXME: what the hell is this ?
if(!pObject->init(pContext,pParams))
{
// internal init failure : abort
delete pObject;
return 0;
}
KviKvsVariant ret;
KviKvsVariantList copy;
copy.setAutoDelete(false);
while(v)
{
copy.append(v);
v = pParams->next();
}
if(!pObject->callFunction(pObject,"constructor",TQString(),pContext,&ret,&copy))
{
// ops...constructor failed (script error!)
delete pObject;
return 0;
} else {
if(ret.isInteger())
{
if(ret.integer() == 0)
{
// implementation failure...
delete pObject;
return 0;
}
} else if(ret.isHObject())
{
if(ret.hobject() == (kvs_hobject_t)0)
{
// implementation failure...
delete pObject;
return 0;
}
}
}
return pObject;
}
void KviKvsObjectClass::registerChildClass(KviKvsObjectClass *pClass)
{
m_pChildClasses->append(pClass);
}
void KviKvsObjectClass::unregisterChildClass(KviKvsObjectClass *pClass)
{
m_pChildClasses->removeRef(pClass);
}
bool KviKvsObjectClass::save(const TQString &szFileName)
{
if(!m_pParentClass)return false;
if(isBuiltin())return false;
TQString szBuffer;
TQString szParentName = m_pParentClass->name();
KviTQString::sprintf(szBuffer,
"# Automatically generated KVS class dump\n\n" \
"class(\"%Q\",\"%Q\")\n" \
"{\n",
&m_szName,&szParentName);
KviPointerHashTableIterator<TQString,KviKvsObjectFunctionHandler> it(*m_pFunctionHandlers);
while(KviKvsObjectFunctionHandler * h = it.current())
{
if(h->isScriptHandler())
{
szBuffer += " ";
if(h->flags() & KviKvsObjectFunctionHandler::Internal)
szBuffer += "internal ";
szBuffer += "function ";
szBuffer += it.currentKey();
szBuffer += "()\n";
TQString szCode = h->scriptHandlerCode();
KviCommandFormatter::blockFromBuffer(szCode);
KviCommandFormatter::indent(szCode);
szBuffer += szCode;
szBuffer += "\n";
}
++it;
}
szBuffer += "}\n";
return KviFileUtils::writeFile(szFileName,szBuffer);
}
void KviKvsObjectClass::getFunctionCode(TQString &szCode,KviKvsObjectFunctionHandler &h)
{
szCode=h.scriptHandlerCode();
}
bool KviKvsObjectClass::load(const TQString &szFileName)
{
TQString szBuffer;
if(!KviFileUtils::readFile(szFileName,szBuffer,0xffffff))return false;
return KviKvsScript::run(szBuffer,g_pActiveWindow);
}