aboutsummaryrefslogtreecommitdiff
path: root/Src/Wasabi/api/config
diff options
context:
space:
mode:
Diffstat (limited to 'Src/Wasabi/api/config')
-rw-r--r--Src/Wasabi/api/config/api_config.cpp12
-rw-r--r--Src/Wasabi/api/config/api_config.h149
-rw-r--r--Src/Wasabi/api/config/api_configi.cpp124
-rw-r--r--Src/Wasabi/api/config/api_configi.h46
-rw-r--r--Src/Wasabi/api/config/api_configx.cpp37
-rw-r--r--Src/Wasabi/api/config/api_configx.h44
-rw-r--r--Src/Wasabi/api/config/cfglist.cpp50
-rw-r--r--Src/Wasabi/api/config/cfglist.h23
-rw-r--r--Src/Wasabi/api/config/cfgscriptobj.cpp371
-rw-r--r--Src/Wasabi/api/config/cfgscriptobj.h198
-rw-r--r--Src/Wasabi/api/config/config.cpp329
-rw-r--r--Src/Wasabi/api/config/config.h43
-rw-r--r--Src/Wasabi/api/config/configapi.cpp95
-rw-r--r--Src/Wasabi/api/config/configapi.h32
-rw-r--r--Src/Wasabi/api/config/filetypes.cpp576
-rw-r--r--Src/Wasabi/api/config/filetypes.h46
-rw-r--r--Src/Wasabi/api/config/items/attrbool.h65
-rw-r--r--Src/Wasabi/api/config/items/attrcb.h127
-rw-r--r--Src/Wasabi/api/config/items/attrfloat.h52
-rw-r--r--Src/Wasabi/api/config/items/attrfn.h15
-rw-r--r--Src/Wasabi/api/config/items/attrhandler.h129
-rw-r--r--Src/Wasabi/api/config/items/attribs.h12
-rw-r--r--Src/Wasabi/api/config/items/attribute.cpp131
-rw-r--r--Src/Wasabi/api/config/items/attribute.h218
-rw-r--r--Src/Wasabi/api/config/items/attrint.h65
-rw-r--r--Src/Wasabi/api/config/items/attrstr.cpp14
-rw-r--r--Src/Wasabi/api/config/items/attrstr.h85
-rw-r--r--Src/Wasabi/api/config/items/cfgitem.h233
-rw-r--r--Src/Wasabi/api/config/items/cfgitemi.cpp274
-rw-r--r--Src/Wasabi/api/config/items/cfgitemi.h158
-rw-r--r--Src/Wasabi/api/config/items/cfgitemx.cpp27
-rw-r--r--Src/Wasabi/api/config/items/cfgitemx.h42
-rw-r--r--Src/Wasabi/api/config/items/intarray.cpp49
-rw-r--r--Src/Wasabi/api/config/items/intarray.h18
-rw-r--r--Src/Wasabi/api/config/options.cpp211
-rw-r--r--Src/Wasabi/api/config/options.h64
-rw-r--r--Src/Wasabi/api/config/uioptions.cpp109
-rw-r--r--Src/Wasabi/api/config/uioptions.h13
38 files changed, 4286 insertions, 0 deletions
diff --git a/Src/Wasabi/api/config/api_config.cpp b/Src/Wasabi/api/config/api_config.cpp
new file mode 100644
index 00000000..4cffc910
--- /dev/null
+++ b/Src/Wasabi/api/config/api_config.cpp
@@ -0,0 +1,12 @@
+// ----------------------------------------------------------------------------
+// Generated by InterfaceFactory [Thu May 15 21:06:24 2003]
+//
+// File : api_config.cpp
+// Class : api_config
+// class layer : Dispatchable Interface
+// ----------------------------------------------------------------------------
+
+#include <precomp.h>
+#include "api_config.h"
+
+
diff --git a/Src/Wasabi/api/config/api_config.h b/Src/Wasabi/api/config/api_config.h
new file mode 100644
index 00000000..ece231b5
--- /dev/null
+++ b/Src/Wasabi/api/config/api_config.h
@@ -0,0 +1,149 @@
+// ----------------------------------------------------------------------------
+// Generated by InterfaceFactory [Thu May 15 21:06:24 2003]
+//
+// File : api_config.h
+// Class : api_config
+// class layer : Dispatchable Interface
+// ----------------------------------------------------------------------------
+
+#ifndef __API_CONFIG_H
+#define __API_CONFIG_H
+
+#include <bfc/dispatch.h>
+#include <bfc/platform/types.h>
+
+class CfgItem;
+class ConfigFile;
+
+
+// ----------------------------------------------------------------------------
+
+class NOVTABLE api_config: public Dispatchable
+{
+ protected:
+ api_config() {}
+ ~api_config() {}
+ public:
+ void config_registerCfgItem(CfgItem *cfgitem);
+ void config_deregisterCfgItem(CfgItem *cfgitem);
+ int config_getNumCfgItems();
+ CfgItem *config_enumCfgItem(int n);
+ CfgItem *config_getCfgItemByGuid(GUID g);
+ void setIntPrivate(const wchar_t *name, int val);
+ int getIntPrivate(const wchar_t *name, int def_val);
+ void setIntArrayPrivate(const wchar_t *name, const int *val, int nval);
+ int getIntArrayPrivate(const wchar_t *name, int *val, int nval);
+ void setStringPrivate(const wchar_t *name, const wchar_t *str);
+ int getStringPrivate(const wchar_t *name, wchar_t *buf, int buf_len, const wchar_t *default_str);
+ int getStringPrivateLen(const wchar_t *name);
+ void setIntPublic(const wchar_t *name, int val);
+ int getIntPublic(const wchar_t *name, int def_val);
+ void setStringPublic(const wchar_t *name, const wchar_t *str);
+ int getStringPublic(const wchar_t *name, wchar_t *buf, int buf_len, const wchar_t *default_str);
+
+ protected:
+ enum {
+ API_CONFIG_CONFIG_REGISTERCFGITEM = 10,
+ API_CONFIG_CONFIG_DEREGISTERCFGITEM = 20,
+ API_CONFIG_CONFIG_GETNUMCFGITEMS = 30,
+ API_CONFIG_CONFIG_ENUMCFGITEM = 40,
+ API_CONFIG_CONFIG_GETCFGITEMBYGUID = 50,
+ API_CONFIG_SETINTPRIVATE = 60,
+ API_CONFIG_GETINTPRIVATE = 70,
+ API_CONFIG_SETINTARRAYPRIVATE = 80,
+ API_CONFIG_GETINTARRAYPRIVATE = 90,
+ API_CONFIG_SETSTRINGPRIVATE = 100,
+ API_CONFIG_GETSTRINGPRIVATE = 110,
+ API_CONFIG_GETSTRINGPRIVATELEN = 120,
+ API_CONFIG_SETINTPUBLIC = 130,
+ API_CONFIG_GETINTPUBLIC = 140,
+ API_CONFIG_SETSTRINGPUBLIC = 150,
+ API_CONFIG_GETSTRINGPUBLIC = 160,
+ };
+};
+
+// ----------------------------------------------------------------------------
+
+inline void api_config::config_registerCfgItem(CfgItem *cfgitem) {
+ _voidcall(API_CONFIG_CONFIG_REGISTERCFGITEM, cfgitem);
+}
+
+inline void api_config::config_deregisterCfgItem(CfgItem *cfgitem) {
+ _voidcall(API_CONFIG_CONFIG_DEREGISTERCFGITEM, cfgitem);
+}
+
+inline int api_config::config_getNumCfgItems() {
+ int __retval = _call(API_CONFIG_CONFIG_GETNUMCFGITEMS, (int)0);
+ return __retval;
+}
+
+inline CfgItem *api_config::config_enumCfgItem(int n) {
+ CfgItem *__retval = _call(API_CONFIG_CONFIG_ENUMCFGITEM, (CfgItem *)NULL, n);
+ return __retval;
+}
+
+inline CfgItem *api_config::config_getCfgItemByGuid(GUID g) {
+ CfgItem *__retval = _call(API_CONFIG_CONFIG_GETCFGITEMBYGUID, (CfgItem *)NULL, g);
+ return __retval;
+}
+
+inline void api_config::setIntPrivate(const wchar_t *name, int val) {
+ _voidcall(API_CONFIG_SETINTPRIVATE, name, val);
+}
+
+inline int api_config::getIntPrivate(const wchar_t *name, int def_val) {
+ int __retval = _call(API_CONFIG_GETINTPRIVATE, (int)0, name, def_val);
+ return __retval;
+}
+
+inline void api_config::setIntArrayPrivate(const wchar_t *name, const int *val, int nval) {
+ _voidcall(API_CONFIG_SETINTARRAYPRIVATE, name, val, nval);
+}
+
+inline int api_config::getIntArrayPrivate(const wchar_t *name, int *val, int nval) {
+ int __retval = _call(API_CONFIG_GETINTARRAYPRIVATE, (int)0, name, val, nval);
+ return __retval;
+}
+
+inline void api_config::setStringPrivate(const wchar_t *name, const wchar_t *str) {
+ _voidcall(API_CONFIG_SETSTRINGPRIVATE, name, str);
+}
+
+inline int api_config::getStringPrivate(const wchar_t *name, wchar_t *buf, int buf_len, const wchar_t *default_str) {
+ int __retval = _call(API_CONFIG_GETSTRINGPRIVATE, (int)0, name, buf, buf_len, default_str);
+ return __retval;
+}
+
+inline int api_config::getStringPrivateLen(const wchar_t *name) {
+ int __retval = _call(API_CONFIG_GETSTRINGPRIVATELEN, (int)0, name);
+ return __retval;
+}
+
+inline void api_config::setIntPublic(const wchar_t *name, int val) {
+ _voidcall(API_CONFIG_SETINTPUBLIC, name, val);
+}
+
+inline int api_config::getIntPublic(const wchar_t *name, int def_val) {
+ int __retval = _call(API_CONFIG_GETINTPUBLIC, (int)0, name, def_val);
+ return __retval;
+}
+
+inline void api_config::setStringPublic(const wchar_t *name, const wchar_t *str) {
+ _voidcall(API_CONFIG_SETSTRINGPUBLIC, name, str);
+}
+
+inline int api_config::getStringPublic(const wchar_t *name, wchar_t *buf, int buf_len, const wchar_t *default_str) {
+ int __retval = _call(API_CONFIG_GETSTRINGPUBLIC, (int)0, name, buf, buf_len, default_str);
+ return __retval;
+}
+
+// ----------------------------------------------------------------------------
+
+
+// {470B890C-4747-4113-ABA5-A8F8F4F8AB7E}
+static const GUID configApiServiceGuid =
+{ 0x470b890c, 0x4747, 0x4113, { 0xab, 0xa5, 0xa8, 0xf8, 0xf4, 0xf8, 0xab, 0x7e } };
+
+extern api_config *configApi;
+
+#endif // __API_CONFIG_H
diff --git a/Src/Wasabi/api/config/api_configi.cpp b/Src/Wasabi/api/config/api_configi.cpp
new file mode 100644
index 00000000..d6b62189
--- /dev/null
+++ b/Src/Wasabi/api/config/api_configi.cpp
@@ -0,0 +1,124 @@
+#include <precomp.h>
+//<?#include "<class data="implementationheader"/>"
+#include "api_configi.h"
+//?>
+
+#include <bfc/parse/pathparse.h>
+#include <api/config/cfglist.h>
+
+
+static CfgList cfglist;
+
+api_config *configApi = NULL;
+
+api_configI::api_configI()
+: public_config(StringPrintfW(INVALID_GUID), L"public data")
+{
+ public_config.initialize();
+}
+
+api_configI::~api_configI()
+{
+}
+
+void api_configI::config_registerCfgItem(CfgItem *cfgitem)
+{
+ cfglist.addItem(cfgitem);
+}
+
+void api_configI::config_deregisterCfgItem(CfgItem *cfgitem)
+{
+ cfglist.delItem(cfgitem);
+}
+
+int api_configI::config_getNumCfgItems()
+{
+ return cfglist.getNumItems();
+}
+
+CfgItem *api_configI::config_enumCfgItem(int n)
+{
+ return cfglist.enumItem(n);
+}
+
+CfgItem *api_configI::config_getCfgItemByGuid(GUID g)
+{
+ return cfglist.getByGuid(g);
+}
+
+// The private config functions are currently pointing at the public config item, this is because
+// only the monolithic api gets instantiated once per component and thus can know its GUID, this
+// version of the config api should eventually be instantiated once per component as well when
+// we start making them use the modular apis
+void api_configI::setIntPrivate(const wchar_t *name, int val)
+{
+ public_config.setInt(name, val);
+}
+
+int api_configI::getIntPrivate(const wchar_t *name, int def_val)
+{
+ int ret = public_config.getInt(name, def_val);
+ return ret;
+}
+
+void api_configI::setIntArrayPrivate(const wchar_t *name, const int *val, int nval)
+{
+ if (nval > 256) return;
+ wchar_t buf[12*256]=L"";
+ for (int i = 0; i < nval; i++)
+ {
+ wcscat(buf, StringPrintfW(L"%d", val[i]));
+ if (i != nval-1)
+ wcscat(buf, L",");
+ }
+ public_config.setString(name, buf);
+}
+
+int api_configI::getIntArrayPrivate(const wchar_t *name, int *val, int nval)
+{
+ wchar_t buf[12*256]=L"";
+ public_config.getString(name, buf, sizeof(buf)/sizeof(*buf), L"");
+ PathParserW pp(buf, L",");
+ if (pp.getNumStrings() != nval) return 0;
+ for (int i = 0; i < nval; i++) {
+ *val = WTOI(pp.enumString(i));
+ val ++;
+ }
+ return 1;
+}
+
+void api_configI::setStringPrivate(const wchar_t *name, const wchar_t *str)
+{
+ public_config.setString(name, str);
+}
+
+int api_configI::getStringPrivate(const wchar_t *name, wchar_t *buf, int buf_len, const wchar_t *default_str)
+{
+ int ret = public_config.getString(name, buf, buf_len, default_str);
+ return ret;
+}
+
+int api_configI::getStringPrivateLen(const wchar_t *name)
+{
+ return public_config.getStringLen(name);
+}
+
+void api_configI::setIntPublic(const wchar_t *name, int val)
+{
+ public_config.setInt(name, val);
+}
+
+int api_configI::getIntPublic(const wchar_t *name, int def_val)
+{
+ return public_config.getInt(name, def_val);
+}
+
+void api_configI::setStringPublic(const wchar_t *name, const wchar_t *str)
+{
+ public_config.setString(name, str);
+}
+
+int api_configI::getStringPublic(const wchar_t *name, wchar_t *buf, int buf_len, const wchar_t *default_str)
+{
+ return public_config.getString(name, buf, buf_len, default_str);
+}
diff --git a/Src/Wasabi/api/config/api_configi.h b/Src/Wasabi/api/config/api_configi.h
new file mode 100644
index 00000000..d0e5f755
--- /dev/null
+++ b/Src/Wasabi/api/config/api_configi.h
@@ -0,0 +1,46 @@
+#ifndef __API_CONFIG_IMPL_H
+#define __API_CONFIG_IMPL_H
+
+/*<?<autoheader/>*/
+#include "api_config.h"
+#include "api_configx.h"
+#include <api/config/config.h>
+
+class CfgItem;
+/*?>*/
+
+class api_configI : public api_configX
+{
+public:
+ api_configI();
+ virtual ~api_configI();
+
+ DISPATCH(10) virtual void config_registerCfgItem(CfgItem *cfgitem);
+ DISPATCH(20) virtual void config_deregisterCfgItem(CfgItem *cfgitem);
+ DISPATCH(30) virtual int config_getNumCfgItems();
+ DISPATCH(40) virtual CfgItem *config_enumCfgItem(int n);
+ DISPATCH(50) virtual CfgItem *config_getCfgItemByGuid(GUID g);
+ DISPATCH(60) virtual void setIntPrivate(const wchar_t *name, int val);
+ DISPATCH(70) virtual int getIntPrivate(const wchar_t *name, int def_val);
+ DISPATCH(80) virtual void setIntArrayPrivate(const wchar_t *name, const int *val, int nval);
+ DISPATCH(90) virtual int getIntArrayPrivate(const wchar_t *name, int *val, int nval);
+ DISPATCH(100) virtual void setStringPrivate(const wchar_t *name, const wchar_t *str);
+ DISPATCH(110) virtual int getStringPrivate(const wchar_t *name, wchar_t *buf, int buf_len, const wchar_t *default_str);
+ DISPATCH(120) virtual int getStringPrivateLen(const wchar_t *name);
+ DISPATCH(130) virtual void setIntPublic(const wchar_t *name, int val);
+ DISPATCH(140) virtual int getIntPublic(const wchar_t *name, int def_val);
+ DISPATCH(150) virtual void setStringPublic(const wchar_t *name, const wchar_t *str);
+ DISPATCH(160) virtual int getStringPublic(const wchar_t *name, wchar_t *buf, int buf_len, const wchar_t *default_str);
+private:
+ ConfigFile public_config;
+};
+
+/*[interface.footer.h]
+// {470B890C-4747-4113-ABA5-A8F8F4F8AB7E}
+static const GUID configApiServiceGuid =
+{ 0x470b890c, 0x4747, 0x4113, { 0xab, 0xa5, 0xa8, 0xf8, 0xf4, 0xf8, 0xab, 0x7e } };
+
+extern api_config *configApi;
+*/
+
+#endif // __API_CONFIG_IMPL_H
diff --git a/Src/Wasabi/api/config/api_configx.cpp b/Src/Wasabi/api/config/api_configx.cpp
new file mode 100644
index 00000000..8296023e
--- /dev/null
+++ b/Src/Wasabi/api/config/api_configx.cpp
@@ -0,0 +1,37 @@
+// ----------------------------------------------------------------------------
+// Generated by InterfaceFactory [Thu May 15 21:06:25 2003]
+//
+// File : api_configx.cpp
+// Class : api_config
+// class layer : Dispatchable Receiver
+// ----------------------------------------------------------------------------
+#include <precomp.h>
+
+#include "api_configx.h"
+#include "api_configi.h"
+
+#ifdef CBCLASS
+#undef CBCLASS
+#endif
+
+#define CBCLASS api_configX
+START_DISPATCH;
+ VCB(API_CONFIG_CONFIG_REGISTERCFGITEM, config_registerCfgItem);
+ VCB(API_CONFIG_CONFIG_DEREGISTERCFGITEM, config_deregisterCfgItem);
+ CB(API_CONFIG_CONFIG_GETNUMCFGITEMS, config_getNumCfgItems);
+ CB(API_CONFIG_CONFIG_ENUMCFGITEM, config_enumCfgItem);
+ CB(API_CONFIG_CONFIG_GETCFGITEMBYGUID, config_getCfgItemByGuid);
+ VCB(API_CONFIG_SETINTPRIVATE, setIntPrivate);
+ CB(API_CONFIG_GETINTPRIVATE, getIntPrivate);
+ VCB(API_CONFIG_SETINTARRAYPRIVATE, setIntArrayPrivate);
+ CB(API_CONFIG_GETINTARRAYPRIVATE, getIntArrayPrivate);
+ VCB(API_CONFIG_SETSTRINGPRIVATE, setStringPrivate);
+ CB(API_CONFIG_GETSTRINGPRIVATE, getStringPrivate);
+ CB(API_CONFIG_GETSTRINGPRIVATELEN, getStringPrivateLen);
+ VCB(API_CONFIG_SETINTPUBLIC, setIntPublic);
+ CB(API_CONFIG_GETINTPUBLIC, getIntPublic);
+ VCB(API_CONFIG_SETSTRINGPUBLIC, setStringPublic);
+ CB(API_CONFIG_GETSTRINGPUBLIC, getStringPublic);
+END_DISPATCH;
+#undef CBCLASS
+
diff --git a/Src/Wasabi/api/config/api_configx.h b/Src/Wasabi/api/config/api_configx.h
new file mode 100644
index 00000000..d8594b68
--- /dev/null
+++ b/Src/Wasabi/api/config/api_configx.h
@@ -0,0 +1,44 @@
+// ----------------------------------------------------------------------------
+// Generated by InterfaceFactory [Thu May 15 21:06:24 2003]
+//
+// File : api_configx.h
+// Class : api_config
+// class layer : Dispatchable Receiver
+// ----------------------------------------------------------------------------
+
+#ifndef __API_CONFIGX_H
+#define __API_CONFIGX_H
+
+#include "api_config.h"
+
+class CfgItem;
+class ConfigFile;
+
+// ----------------------------------------------------------------------------
+
+class api_configX : public api_config {
+ protected:
+ api_configX() {}
+ public:
+ virtual void config_registerCfgItem(CfgItem *cfgitem)=0;
+ virtual void config_deregisterCfgItem(CfgItem *cfgitem)=0;
+ virtual int config_getNumCfgItems()=0;
+ virtual CfgItem *config_enumCfgItem(int n)=0;
+ virtual CfgItem *config_getCfgItemByGuid(GUID g)=0;
+ virtual void setIntPrivate(const wchar_t *name, int val)=0;
+ virtual int getIntPrivate(const wchar_t *name, int def_val)=0;
+ virtual void setIntArrayPrivate(const wchar_t *name, const int *val, int nval)=0;
+ virtual int getIntArrayPrivate(const wchar_t *name, int *val, int nval)=0;
+ virtual void setStringPrivate(const wchar_t *name, const wchar_t *str)=0;
+ virtual int getStringPrivate(const wchar_t *name, wchar_t *buf, int buf_len, const wchar_t *default_str)=0;
+ virtual int getStringPrivateLen(const wchar_t *name)=0;
+ virtual void setIntPublic(const wchar_t *name, int val)=0;
+ virtual int getIntPublic(const wchar_t *name, int def_val)=0;
+ virtual void setStringPublic(const wchar_t *name, const wchar_t *str)=0;
+ virtual int getStringPublic(const wchar_t *name, wchar_t *buf, int buf_len, const wchar_t *default_str)=0;
+
+ protected:
+ RECVS_DISPATCH;
+};
+
+#endif // __API_CONFIGX_H
diff --git a/Src/Wasabi/api/config/cfglist.cpp b/Src/Wasabi/api/config/cfglist.cpp
new file mode 100644
index 00000000..b6baaab5
--- /dev/null
+++ b/Src/Wasabi/api/config/cfglist.cpp
@@ -0,0 +1,50 @@
+#include <precomp.h>
+
+#include "cfglist.h"
+#include <bfc/ptrlist.h>
+
+void CfgList::addItem(CfgItem *cfgitem)
+{
+ if (cfgitem == NULL ||
+ cfgitem->getGuid() == INVALID_GUID ||
+ list.haveItem(cfgitem)) return;
+ viewer_addViewItem(cfgitem);
+ list.addItem(cfgitem);
+
+ cfgitem->onRegister(); // recurses children
+}
+
+void CfgList::delItem(CfgItem *cfgitem)
+{
+ if (cfgitem == NULL || !list.haveItem(cfgitem)) return;
+
+ list.removeItem(cfgitem);
+ viewer_delViewItem(cfgitem);
+
+ cfgitem->onDeregister(); // recurses children
+}
+
+int CfgList::getNumItems()
+{
+ return list.getNumItems();
+}
+
+CfgItem *CfgList::enumItem(int n)
+{
+ return list[n];
+}
+
+CfgItem *CfgList::getByGuid(GUID g)
+{
+ if (g == INVALID_GUID) return NULL;
+ foreach(list)
+ if (list.getfor()->getGuid() == g) return list.getfor();
+ endfor
+ return NULL;
+}
+
+int CfgList::viewer_onItemDeleted(CfgItem *item)
+{
+ list.removeItem(item);
+ return 1;
+}
diff --git a/Src/Wasabi/api/config/cfglist.h b/Src/Wasabi/api/config/cfglist.h
new file mode 100644
index 00000000..cf456ccc
--- /dev/null
+++ b/Src/Wasabi/api/config/cfglist.h
@@ -0,0 +1,23 @@
+#ifndef _CFGLIST_H
+#define _CFGLIST_H
+
+#include <bfc/wasabi_std.h>
+#include <bfc/depview.h>
+#include <api/config/items/cfgitem.h>
+
+class CfgList : public DependentViewerTPtr<CfgItem> {
+public:
+ void addItem(CfgItem *cfgitem);
+ void delItem(CfgItem *cfgitem);
+
+ int getNumItems();
+ CfgItem *enumItem(int n);
+ CfgItem *getByGuid(GUID g);
+
+ virtual int viewer_onItemDeleted(CfgItem *item);
+
+private:
+ PtrList<CfgItem> list;
+};
+
+#endif
diff --git a/Src/Wasabi/api/config/cfgscriptobj.cpp b/Src/Wasabi/api/config/cfgscriptobj.cpp
new file mode 100644
index 00000000..6d220f02
--- /dev/null
+++ b/Src/Wasabi/api/config/cfgscriptobj.cpp
@@ -0,0 +1,371 @@
+#include <precomp.h>
+#include "cfgscriptobj.h"
+
+#include <api/config/items/cfgitemi.h>
+
+#ifndef _WASABIRUNTIME
+
+BEGIN_SERVICES(ConfigObject_Svc);
+DECLARE_SERVICE(ScriptObjectCreator<ConfigScriptObjectSvc>);
+END_SERVICES(ConfigObject_Svc, _ConfigObject_Svc);
+
+#ifdef _X86_
+extern "C" { int _link_ConfigObjectSvc; }
+#else
+extern "C" { int __link_ConfigObjectSvc; }
+#endif
+
+#endif
+
+static ConfigScriptObjectController _configController;
+ScriptObjectController *configController = &_configController;
+
+static ConfigItemScriptObjectController _configItemController;
+ScriptObjectController *configItemController = &_configItemController;
+
+static ConfigAttributeScriptObjectController _configAttributeController;
+ScriptObjectController *configAttributeController = &_configAttributeController;
+
+
+// -----------------------------------------------------------------------------------------------------
+// Service
+
+ScriptObjectController *ConfigScriptObjectSvc::getController(int n)
+{
+ switch (n) {
+ case 0:
+ return configController;
+ case 1:
+ return configItemController;
+ case 2:
+ return configAttributeController;
+ }
+ return NULL;
+}
+
+// -----------------------------------------------------------------------------------------------------
+// ConfigObject
+
+ConfigObject::ConfigObject() {
+ numobjects++;
+ getScriptObject()->vcpu_setInterface(CONFIG_SCRIPTOBJECT_GUID, (void *)static_cast<ConfigObject *>(this));
+ getScriptObject()->vcpu_setClassName(L"Config");
+ getScriptObject()->vcpu_setController(configController);
+}
+
+ConfigObject::~ConfigObject() {
+ numobjects--;
+ mylist.deleteAll();
+ if (numobjects == 0) {
+ foreach(ouraddeditems)
+ WASABI_API_CONFIG->config_deregisterCfgItem(ouraddeditems.getfor());
+ endfor
+ ouraddeditems.deleteAll();
+ }
+}
+
+PtrList<CfgItemI> ConfigObject::ouraddeditems;
+int ConfigObject::numobjects=0;
+
+
+function_descriptor_struct ConfigScriptObjectController::exportedFunction[] = {
+ {L"getItem", 1, (void*)ConfigObject::config_getItem},
+ {L"getItemByGuid", 1, (void*)ConfigObject::config_getItemByGuid},
+ {L"newItem", 2, (void*)ConfigObject::config_newItem},
+};
+
+int ConfigScriptObjectController::getNumFunctions() {
+ return sizeof(exportedFunction) / sizeof(function_descriptor_struct);
+}
+
+scriptVar ConfigObject::config_newItem(SCRIPT_FUNCTION_PARAMS, ScriptObject *o, scriptVar configitem_name, scriptVar configitem_guid)
+{
+ SCRIPT_FUNCTION_INIT
+ ConfigObject *co = static_cast<ConfigObject*>(o->vcpu_getInterface(CONFIG_SCRIPTOBJECT_GUID));
+ ConfigItemObject *ret=getItem(GET_SCRIPT_STRING(configitem_name), co);
+ if (!ret)
+ ret = getItem(GET_SCRIPT_STRING(configitem_guid), co);
+ if (ret)
+ return MAKE_SCRIPT_OBJECT(ret->getScriptObject());
+ CfgItemI *item = new CfgItemI(GET_SCRIPT_STRING(configitem_name), nsGUID::fromCharW(GET_SCRIPT_STRING(configitem_guid)));
+ ConfigObject::ouraddeditems.addItem(item);
+ WASABI_API_CONFIG->config_registerCfgItem(item);
+ ret = new ConfigItemObject(item);
+ co->mylist.addItem(ret);
+ return MAKE_SCRIPT_OBJECT(ret->getScriptObject());
+}
+
+ConfigItemObject *ConfigObject::getItem(const wchar_t *nameorguid, ConfigObject *co) {
+ int i=0;
+ ConfigItemObject *ret=NULL;
+ GUID g = nsGUID::fromCharW(nameorguid);
+ for (i=0;;i++) {
+ CfgItem *item = WASABI_API_CONFIG->config_enumCfgItem(i);
+ if (!item) break;
+ GUID ig = item->getGuid();
+ if (g == ig || WCSCASEEQLSAFE(nameorguid, item->getName()))
+ {
+ ret = new ConfigItemObject(item);
+ co->mylist.addItem(ret);
+ break;
+ }
+#if 0//CUT
+ for (int j=0;j<item->getNumChildren();j++) {
+ if (STRCASEEQL(nameorguid, item->enumChild(j)->getName())) {
+ ret = new ConfigItemObject(item->enumChild(j));
+ co->mylist.addItem(ret);
+ break;
+ }
+ }
+#endif
+ }
+ return ret;
+}
+
+scriptVar ConfigObject::config_getItem(SCRIPT_FUNCTION_PARAMS, ScriptObject *o, scriptVar cfgitem_name)
+{
+ SCRIPT_FUNCTION_INIT
+ ConfigObject *co = static_cast<ConfigObject*>(o->vcpu_getInterface(CONFIG_SCRIPTOBJECT_GUID));
+ ConfigItemObject *ret=getItem(GET_SCRIPT_STRING(cfgitem_name), co);
+ return MAKE_SCRIPT_OBJECT(ret ? ret->getScriptObject() : NULL);
+}
+
+scriptVar ConfigObject::config_getItemByGuid(SCRIPT_FUNCTION_PARAMS, ScriptObject *o, scriptVar cfgitem_guid)
+{
+ SCRIPT_FUNCTION_INIT
+// GUID g = nsGUID::fromChar(GET_SCRIPT_STRING(guid));
+// api->
+ int i=0;
+ ConfigItemObject *ret=NULL;
+ ConfigObject *co = static_cast<ConfigObject*>(o->vcpu_getInterface(CONFIG_SCRIPTOBJECT_GUID));
+
+ const wchar_t *p = GET_SCRIPT_STRING(cfgitem_guid);
+ if (p == NULL) {
+ RETURN_SCRIPT_ZERO;
+ }
+
+ GUID g = nsGUID::fromCharW(p);
+
+ for (i=0;;i++) {
+ CfgItem *item = WASABI_API_CONFIG->config_enumCfgItem(i);
+ if (!item) break;
+ if (g == item->getGuid()) {
+ ret = new ConfigItemObject(item);
+ co->mylist.addItem(ret);
+ break;
+ }
+#if 0//CUT
+ for (int j=0;j<item->getNumChildren();j++) {
+ if (g == item->enumChild(j)->getName()) {
+ ret = new ConfigItemObject(item->enumChild(j));
+ co->mylist.addItem(ret);
+ break;
+ }
+ }
+#endif
+ }
+ return MAKE_SCRIPT_OBJECT(ret ? ret->getScriptObject() : NULL);
+}
+
+ScriptObject *ConfigScriptObjectController::instantiate() {
+ ConfigObject *c = new ConfigObject;
+ if (!c) return NULL;
+ return c->getScriptObject();
+}
+
+void ConfigScriptObjectController::destroy(ScriptObject *o) {
+ ConfigObject *obj = static_cast<ConfigObject *>(o->vcpu_getInterface(CONFIG_SCRIPTOBJECT_GUID));
+ ASSERT(obj != NULL);
+ delete obj;
+}
+
+void *ConfigScriptObjectController::encapsulate(ScriptObject *o) {
+ return NULL; // no encapsulation for config
+}
+
+void ConfigScriptObjectController::deencapsulate(void *) {
+}
+
+// -----------------------------------------------------------------------------------------------------
+// ConfigItem
+
+function_descriptor_struct ConfigItemScriptObjectController::exportedFunction[] = {
+ {L"getAttribute", 1, (void*)ConfigItemObject::configItem_getAttribute},
+ {L"getGuid", 0, (void*)ConfigItemObject::configItem_getGuid},
+ {L"newAttribute", 2, (void*)ConfigItemObject::configItem_newAttribute},
+};
+
+int ConfigItemScriptObjectController::getNumFunctions() {
+ return sizeof(exportedFunction) / sizeof(function_descriptor_struct);
+}
+
+ConfigItemObject::ConfigItemObject(CfgItem *_item)
+{
+ getScriptObject()->vcpu_setInterface(CONFIGITEM_SCRIPTOBJECT_GUID, (void *)static_cast<ConfigItemObject *>(this));
+ getScriptObject()->vcpu_setClassName(L"ConfigItem");
+ getScriptObject()->vcpu_setController(configItemController);
+ wchar_t strguid[256];
+ nsGUID::toCharW(_item->getGuid(), strguid);
+ guid = strguid;
+ item = _item;
+}
+
+ConfigAttributeObject *ConfigItemObject::getAttribute(const wchar_t *name)
+{
+ if (!item) return NULL;
+ for (int i=0;i<item->getNumAttributes();i++)
+ {
+ if (!WCSICMP(item->enumAttribute(i), name))
+ {
+ ConfigAttributeObject *o = new ConfigAttributeObject(item, name, this);
+ mylist.addItem(o);
+ return o;
+ }
+ }
+ return NULL;
+}
+
+ConfigAttributeObject *ConfigItemObject::newAttribute(const wchar_t *name, const wchar_t *defaultvalue)
+{
+ if (!item) return NULL;
+ ConfigAttributeObject *o = getAttribute(name);
+ if (o != NULL) return o;
+
+ item->addAttribute(name, defaultvalue);
+
+ ConfigAttributeObject *cao = getAttribute(name);
+ cao->setAutoDelete();
+ return cao;
+}
+
+ConfigItemObject::~ConfigItemObject()
+{
+ mylist.deleteAll();
+}
+
+scriptVar ConfigItemObject::configItem_getAttribute(SCRIPT_FUNCTION_PARAMS, ScriptObject *o, scriptVar name)
+{
+ SCRIPT_FUNCTION_INIT
+ ConfigItemObject *cio = static_cast<ConfigItemObject *>(o->vcpu_getInterface(CONFIGITEM_SCRIPTOBJECT_GUID));
+ ConfigAttributeObject *cao = NULL;
+ if (cio)
+ cao = cio->getAttribute(GET_SCRIPT_STRING(name));
+ return MAKE_SCRIPT_OBJECT(cao ? cao->getScriptObject() : NULL);
+}
+
+scriptVar ConfigItemObject::configItem_getGuid(SCRIPT_FUNCTION_PARAMS, ScriptObject *o)
+{
+ SCRIPT_FUNCTION_INIT
+ ConfigItemObject *cio = static_cast<ConfigItemObject *>(o->vcpu_getInterface(CONFIGITEM_SCRIPTOBJECT_GUID));
+ if (cio) return MAKE_SCRIPT_STRING(cio->getGuid());
+ return MAKE_SCRIPT_STRING(L"");
+}
+
+scriptVar ConfigItemObject::configItem_newAttribute(SCRIPT_FUNCTION_PARAMS, ScriptObject *o, scriptVar name, scriptVar defval) {
+ SCRIPT_FUNCTION_INIT
+ ConfigItemObject *cio = static_cast<ConfigItemObject *>(o->vcpu_getInterface(CONFIGITEM_SCRIPTOBJECT_GUID));
+ ConfigAttributeObject *cao = NULL;
+ if (cio)
+ cao = cio->newAttribute(GET_SCRIPT_STRING(name), GET_SCRIPT_STRING(defval));
+ return MAKE_SCRIPT_OBJECT(cao ? cao->getScriptObject() : NULL);
+}
+
+// -----------------------------------------------------------------------------------------------------
+// ConfigAttribute
+
+function_descriptor_struct ConfigAttributeScriptObjectController::exportedFunction[] = {
+ {L"getData", 0, (void*)ConfigAttributeObject::configAttr_getData},
+ {L"setData", 1, (void*)ConfigAttributeObject::configAttr_setData},
+ {L"onDataChanged", 0, (void*)ConfigAttributeObject::configAttr_onDataChanged},
+ {L"getParentItem", 0, (void*)ConfigAttributeObject::configAttr_getParentItem},
+ {L"getAttributeName", 0, (void*)ConfigAttributeObject::configAttr_getAttributeName},
+};
+
+int ConfigAttributeScriptObjectController::getNumFunctions() {
+ return sizeof(exportedFunction) / sizeof(function_descriptor_struct);
+}
+
+void ConfigAttributeObject::setData(const wchar_t *data)
+{
+ if (!item || !attr) return;
+ item->setData(attr, data);
+}
+
+const wchar_t *ConfigAttributeObject::getData()
+{
+ if (!item || !attr) return NULL;
+ static wchar_t t[WA_MAX_PATH];
+ item->getData(attr, t, WA_MAX_PATH);
+ return t;
+}
+
+ConfigAttributeObject::ConfigAttributeObject(CfgItem *_item, const wchar_t *_attr, ConfigItemObject *_parent)
+{
+ getScriptObject()->vcpu_setInterface(CONFIGATTRIBUTE_SCRIPTOBJECT_GUID, (void *)static_cast<ConfigAttributeObject *>(this));
+ getScriptObject()->vcpu_setClassName(L"ConfigAttribute");
+ getScriptObject()->vcpu_setController(configAttributeController);
+ attr = _attr;
+ item = _item;
+ parent = _parent;
+ viewer_addViewItem(item);
+ autodelete = 0;
+}
+
+ConfigAttributeObject::~ConfigAttributeObject() {
+ if (autodelete) getParentItem()->getCfgItem()->delAttribute(attr);
+}
+
+int ConfigAttributeObject::viewer_onEvent(CfgItem *item, int event, intptr_t param, void *ptr, size_t ptrlen)
+{
+ if (event == CfgItem::Event_ATTRIBUTE_CHANGED)
+ {
+ const wchar_t *_attr = reinterpret_cast<const wchar_t *>(ptr);
+ if (!WCSICMP(attr, _attr))
+ configAttr_onDataChanged(SCRIPT_CALL, getScriptObject());
+ }
+ return 1;
+}
+
+scriptVar ConfigAttributeObject::configAttr_setData(SCRIPT_FUNCTION_PARAMS, ScriptObject *o, scriptVar val)
+{
+ SCRIPT_FUNCTION_INIT
+ ConfigAttributeObject *cao = static_cast<ConfigAttributeObject *>(o->vcpu_getInterface(CONFIGATTRIBUTE_SCRIPTOBJECT_GUID));
+ if (cao)
+ cao->setData(GET_SCRIPT_STRING(val));
+ RETURN_SCRIPT_VOID;
+}
+
+scriptVar ConfigAttributeObject::configAttr_getData(SCRIPT_FUNCTION_PARAMS, ScriptObject *o) {
+ SCRIPT_FUNCTION_INIT
+ ConfigAttributeObject *cao = static_cast<ConfigAttributeObject *>(o->vcpu_getInterface(CONFIGATTRIBUTE_SCRIPTOBJECT_GUID));
+ if (cao)
+ return MAKE_SCRIPT_STRING(cao->getData());
+ return MAKE_SCRIPT_STRING(L"");
+}
+
+scriptVar ConfigAttributeObject::configAttr_onDataChanged(SCRIPT_FUNCTION_PARAMS, ScriptObject *o) {
+ SCRIPT_FUNCTION_INIT
+ PROCESS_HOOKS0(o, configAttributeController);
+ SCRIPT_FUNCTION_CHECKABORTEVENT;
+ SCRIPT_EXEC_EVENT0(o);
+}
+
+scriptVar ConfigAttributeObject::configAttr_getParentItem(SCRIPT_FUNCTION_PARAMS, ScriptObject *o) {
+ SCRIPT_FUNCTION_INIT
+ ConfigAttributeObject *cao = static_cast<ConfigAttributeObject *>(o->vcpu_getInterface(CONFIGATTRIBUTE_SCRIPTOBJECT_GUID));
+ if (cao) return MAKE_SCRIPT_OBJECT(cao->getParentItem()->getScriptObject());
+ return MAKE_SCRIPT_OBJECT(NULL);
+}
+
+scriptVar ConfigAttributeObject::configAttr_getAttributeName(SCRIPT_FUNCTION_PARAMS, ScriptObject *o) {
+ SCRIPT_FUNCTION_INIT
+ ConfigAttributeObject *cao = static_cast<ConfigAttributeObject *>(o->vcpu_getInterface(CONFIGATTRIBUTE_SCRIPTOBJECT_GUID));
+
+ if (cao)
+ return MAKE_SCRIPT_STRING(cao->getAttributeName());
+
+ return MAKE_SCRIPT_STRING(L"");
+}
+
+
+
diff --git a/Src/Wasabi/api/config/cfgscriptobj.h b/Src/Wasabi/api/config/cfgscriptobj.h
new file mode 100644
index 00000000..e446b618
--- /dev/null
+++ b/Src/Wasabi/api/config/cfgscriptobj.h
@@ -0,0 +1,198 @@
+#ifndef __CFGSCRIPTOBJ_H
+#define __CFGSCRIPTOBJ_H
+
+#include <api/script/objects/rootobj.h>
+#include <api/script/objcontroller.h>
+#include <api/script/scriptobj.h>
+#include <bfc/depview.h>
+#include <api/service/svcs/svc_scriptobji.h>
+#include <api/config/items/attribs.h>
+
+class CfgItem;
+class ConfigObject;
+class ConfigItemObject;
+class ConfigAttributeObject;
+
+extern ScriptObjectController *configController;
+extern ScriptObjectController *configItemController;
+extern ScriptObjectController *configAttributeController;
+
+enum cfgtypes {
+ CFG_INT = 0,
+ CFG_BOOL = 1,
+ CFG_FLOAT = 2,
+ CFG_STRING = 3,
+};
+
+// -----------------------------------------------------------------------------------------------------
+// ScriptObject Provider Service
+
+class ConfigScriptObjectSvc : public svc_scriptObjectI {
+
+public:
+ ConfigScriptObjectSvc() {};
+ virtual ~ConfigScriptObjectSvc() {};
+
+ static const char *getServiceName() { return "Config maki object"; }
+ virtual ScriptObjectController *getController(int n);
+
+ static void addItemObject(ConfigItemObject *item);
+ static void addAttrObject(ConfigAttributeObject *attr);
+ static void removeItemObject(ConfigItemObject *item);
+ static void removeAttrObject(ConfigAttributeObject *attr);
+};
+
+// -----------------------------------------------------------------------------------------------------
+// Script classes GUIDS
+
+// {593DBA22-D077-4976-B952-F4713655400B}
+static const GUID CONFIG_SCRIPTOBJECT_GUID =
+{ 0x593dba22, 0xd077, 0x4976, { 0xb9, 0x52, 0xf4, 0x71, 0x36, 0x55, 0x40, 0xb } };
+
+// {D4030282-3AAB-4d87-878D-12326FADFCD5}
+static const GUID CONFIGITEM_SCRIPTOBJECT_GUID =
+{ 0xd4030282, 0x3aab, 0x4d87, { 0x87, 0x8d, 0x12, 0x32, 0x6f, 0xad, 0xfc, 0xd5 } };
+
+// {24DEC283-B76E-4a36-8CCC-9E24C46B6C73}
+static const GUID CONFIGATTRIBUTE_SCRIPTOBJECT_GUID =
+{ 0x24dec283, 0xb76e, 0x4a36, { 0x8c, 0xcc, 0x9e, 0x24, 0xc4, 0x6b, 0x6c, 0x73 } };
+
+// -----------------------------------------------------------------------------------------------------
+// ScriptObject Interfaces
+
+// Config
+class ConfigObject : public RootObjectInstance {
+
+ public:
+
+ ConfigObject();
+ virtual ~ConfigObject();
+
+ static scriptVar config_getItem(SCRIPT_FUNCTION_PARAMS, ScriptObject *o, scriptVar configitem_name);
+ static scriptVar config_getItemByGuid(SCRIPT_FUNCTION_PARAMS, ScriptObject *o, scriptVar configitem_name);
+ static scriptVar config_newItem(SCRIPT_FUNCTION_PARAMS, ScriptObject *o, scriptVar configitem_name, scriptVar guid);
+ private:
+ static ConfigItemObject *getItem(const wchar_t *nameorguid, ConfigObject *co);
+ PtrList<ConfigItemObject> mylist;
+ static PtrList<CfgItemI> ouraddeditems;
+ static int numobjects;
+};
+
+// ConfigItem
+class ConfigItemObject : public RootObjectInstance {
+
+ public:
+
+ ConfigItemObject(CfgItem *item);
+ virtual ~ConfigItemObject();
+
+ ConfigAttributeObject *getAttribute(const wchar_t *name);
+ const wchar_t *getGuid() { return guid; }
+ ConfigAttributeObject *newAttribute(const wchar_t *name, const wchar_t *defval);
+
+ CfgItem *getCfgItem() { return item; }
+
+ static scriptVar configItem_getAttribute(SCRIPT_FUNCTION_PARAMS, ScriptObject *o, scriptVar attr_name);
+ static scriptVar configItem_getGuid(SCRIPT_FUNCTION_PARAMS, ScriptObject *o);
+ static scriptVar configItem_newAttribute(SCRIPT_FUNCTION_PARAMS, ScriptObject *o, scriptVar attr_name, scriptVar defval);
+
+ private:
+ CfgItem *item;
+ StringW guid;
+ PtrList<ConfigAttributeObject> mylist;
+};
+
+// ConfigAttribute
+class ConfigAttributeObject : public RootObjectInstance, public DependentViewerTPtr<CfgItem> {
+
+ public:
+
+ ConfigAttributeObject(CfgItem *item, const wchar_t *attr, ConfigItemObject *parent);
+ virtual ~ConfigAttributeObject();
+
+ void setData(const wchar_t *data);
+ const wchar_t *getData();
+ ConfigItemObject *getParentItem() { return parent; }
+ const wchar_t *getAttributeName() { return attr; }
+ void setAutoDelete() { autodelete = 1; }
+
+ virtual int viewer_onEvent(CfgItem *item, int event, intptr_t param, void *ptr, size_t ptrlen);
+
+ static scriptVar configAttr_getData(SCRIPT_FUNCTION_PARAMS, ScriptObject *o);
+ static scriptVar configAttr_setData(SCRIPT_FUNCTION_PARAMS, ScriptObject *o, scriptVar val);
+ static scriptVar configAttr_onDataChanged(SCRIPT_FUNCTION_PARAMS, ScriptObject *o);
+ static scriptVar configAttr_getParentItem(SCRIPT_FUNCTION_PARAMS, ScriptObject *o);
+ static scriptVar configAttr_getAttributeName(SCRIPT_FUNCTION_PARAMS, ScriptObject *o);
+
+ private:
+ CfgItem *item;
+ StringW attr;
+ ConfigItemObject *parent;
+ int autodelete;
+};
+
+// -----------------------------------------------------------------------------------------------------
+// ScriptObjectControllers for our script classes
+
+// Config
+class ConfigScriptObjectController : public ScriptObjectControllerI {
+ public:
+ virtual const wchar_t *getClassName() { return L"Config"; }
+ virtual const wchar_t *getAncestorClassName() { return L"Object"; }
+ virtual ScriptObjectController *getAncestorController() { return NULL; }
+ virtual int getNumFunctions();
+ virtual const function_descriptor_struct *getExportedFunctions() { return exportedFunction; }
+ virtual GUID getClassGuid() { return CONFIG_SCRIPTOBJECT_GUID; }
+ virtual int getInstantiable() { return 0; }
+ virtual int getReferenceable() { return 0; }
+ virtual ScriptObject *instantiate();
+ virtual void destroy(ScriptObject *o);
+ virtual void *encapsulate(ScriptObject *o);
+ virtual void deencapsulate(void *o);
+
+ private:
+ static function_descriptor_struct exportedFunction[];
+};
+
+// ConfigItem
+class ConfigItemScriptObjectController : public ScriptObjectControllerI {
+ public:
+ virtual const wchar_t *getClassName() { return L"ConfigItem"; }
+ virtual const wchar_t *getAncestorClassName() { return L"Object"; }
+ virtual ScriptObjectController *getAncestorController() { return NULL; }
+ virtual int getNumFunctions();
+ virtual const function_descriptor_struct *getExportedFunctions() { return exportedFunction; }
+ virtual GUID getClassGuid() { return CONFIGITEM_SCRIPTOBJECT_GUID; }
+ virtual int getInstantiable() { return 0; }
+ virtual int getReferenceable() { return 1; }
+ virtual ScriptObject *instantiate() { return NULL; };
+ virtual void destroy(ScriptObject *o) { };
+ virtual void *encapsulate(ScriptObject *o) { return NULL; };
+ virtual void deencapsulate(void *o) { };
+
+ private:
+ static function_descriptor_struct exportedFunction[];
+};
+
+// ConfigAttribute
+class ConfigAttributeScriptObjectController : public ScriptObjectControllerI {
+ public:
+ virtual const wchar_t *getClassName() { return L"ConfigAttribute"; }
+ virtual const wchar_t *getAncestorClassName() { return L"Object"; }
+ virtual ScriptObjectController *getAncestorController() { return NULL; }
+ virtual int getNumFunctions();
+ virtual const function_descriptor_struct *getExportedFunctions() { return exportedFunction; }
+ virtual GUID getClassGuid() { return CONFIGATTRIBUTE_SCRIPTOBJECT_GUID; }
+ virtual int getInstantiable() { return 0; }
+ virtual int getReferenceable() { return 1; }
+ virtual ScriptObject *instantiate() { return NULL; };
+ virtual void destroy(ScriptObject *o) { };
+ virtual void *encapsulate(ScriptObject *o) { return NULL; };
+ virtual void deencapsulate(void *o) { };
+
+ private:
+ static function_descriptor_struct exportedFunction[];
+};
+
+#endif
+
diff --git a/Src/Wasabi/api/config/config.cpp b/Src/Wasabi/api/config/config.cpp
new file mode 100644
index 00000000..3b45d934
--- /dev/null
+++ b/Src/Wasabi/api/config/config.cpp
@@ -0,0 +1,329 @@
+#include <precomp.h>
+
+#include "config.h"
+#include <bfc/pair.h>
+#include <bfc/ptrlist.h>
+#include <bfc/parse/pathparse.h>
+#include <api/xml/xmlwrite.h>
+
+#include "../xml/ifc_xmlreadercallbackI.h"
+#include "../xml/obj_xml.h"
+#include <bfc/string/url.h>
+#include <api/service/waservicefactory.h>
+
+static StringW iniFile;
+#define XNFNAME L"studio.xnf"
+
+class StringPairCompare
+{
+public:
+ static int compareItem(StringPair *p1, StringPair *p2)
+ {
+ int r = wcscmp(p1->a.getValue(), p2->a.getValue());
+ if (r == 0)
+ return CMP3(p1, p2);
+ else
+ return r;
+ }
+ static int compareAttrib(const wchar_t *attrib, StringPair *item)
+ {
+ return wcscmp(attrib, item->a.getValue());
+ }
+};
+
+static PtrListQuickSorted<StringPair, StringPairCompare> strings;
+
+class Reader : public ifc_xmlreadercallbackI
+{
+public:
+ ~Reader();
+ void xmlReaderOnStartElementCallback(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params);
+ void xmlReaderOnEndElementCallback(const wchar_t *xmlpath, const wchar_t *xmltag);
+
+ void readem();
+
+private:
+ PtrList<StringW> sections;
+};
+
+Reader::~Reader()
+{
+ sections.deleteAll();
+}
+
+void Reader::xmlReaderOnStartElementCallback(const wchar_t *xmlpath, const wchar_t *xmltag, ifc_xmlreaderparams *params)
+{
+ if (!WCSICMP(xmltag, L"section"))
+ {
+ const wchar_t *name = params->getItemValue(L"name");
+ if (name == NULL)
+ return ;
+
+ StringW *strName = new StringW(name);
+ Url::decode(*strName);
+ sections.addItem(strName);
+ }
+ else if (!WCSICMP(xmltag, L"entry"))
+ {
+ const wchar_t *name = params->getItemValue(L"name");
+ const wchar_t *value = params->getItemValue(L"value");
+
+ // just in case
+ if (!WCSICMP(name, L"(null)")) name = NULL;
+ if (!WCSICMP(value, L"(null)")) value = NULL;
+
+ if (name == NULL /*| !*name */ || value == NULL /*|| !*value*/) return ;
+ StringW strName = name;
+ Url::decode(strName);
+
+ StringW strValue = value;
+ Url::decode(strValue);
+
+ StringW n;
+ for (int i = 0; i < sections.getNumItems(); i++)
+ {
+ n.catPostSeparator(*sections[i], '/');
+ }
+ n += strName;
+
+ StringPair *p = new StringPair(n, strValue);
+ strings.addItem(p);
+ }
+}
+
+void Reader::xmlReaderOnEndElementCallback(const wchar_t *xmlpath, const wchar_t *xmltag)
+{
+ if (!WCSICMP(xmltag, L"section"))
+ {
+ StringW *last = sections.getLast();
+ sections.removeLastItem();
+ delete last;
+ }
+}
+
+void LoadXmlFile(obj_xml *parser, const wchar_t *filename);
+
+void Reader::readem()
+{
+ strings.deleteAll();
+
+ if (iniFile.isempty())
+ {
+ iniFile = StringPathCombine(WASABI_API_APP->path_getUserSettingsPath(), XNFNAME);
+ }
+
+ waServiceFactory *parserFactory = WASABI_API_SVC->service_getServiceByGuid(obj_xmlGUID);
+ if (parserFactory)
+ {
+ obj_xml *parser = (obj_xml *)parserFactory->getInterface();
+
+ if (parser)
+ {
+
+ parser->xmlreader_registerCallback(L"WinampXML\fconfiguration\f*", this);
+ parser->xmlreader_registerCallback(L"WasabiXML\fconfiguration\f*", this);
+ parser->xmlreader_open();
+ LoadXmlFile(parser, iniFile);
+
+ parser->xmlreader_unregisterCallback(this);
+ parser->xmlreader_close();
+ parserFactory->releaseInterface(parser);
+ parser = 0;
+ }
+ }
+}
+
+StringPair *ConfigFile::getPair(const wchar_t *name)
+{
+ ASSERT(!sectionname.isempty());
+ StringW nname;
+ nname.catPostSeparator(sectionname.getValue(), '/');
+ nname.cat(name);
+ return strings.findItem(nname.getValue()); // cast to make PtrListSorted happy
+}
+
+StringPair *ConfigFile::makePair(const wchar_t *name, const wchar_t *value)
+{
+ StringPair *ret = getPair(name);
+ if (ret == NULL)
+ {
+ StringW nname;
+ nname.catPostSeparator(sectionname.getValue(), '/');
+ nname.cat(name);
+
+ ret = new StringPair(nname, value);
+ strings.addItem(ret);
+ }
+ else
+ {
+ ret->b.setValue(value);
+ }
+ return ret;
+}
+
+static int ninstances, inited;
+
+ConfigFile::ConfigFile(const wchar_t *section, const wchar_t *name)
+{
+ sectionname = section;
+ prettyname = name;
+ ninstances++;
+}
+
+void ConfigFile::initialize()
+{
+ Reader().readem();
+}
+
+ConfigFile::~ConfigFile()
+{
+ ninstances--;
+ if (ninstances == 0)
+ {
+ FILE *fp = _wfopen(iniFile, WF_WRITE_TEXT);
+ if (fp != NULL)
+ {
+ // write out the file
+ XMLWrite xml(fp, L"WasabiXML");
+ const wchar_t *app = WASABI_API_APP->main_getVersionString();
+ if (!app)
+ app = L"thousands of irascible butt monkeys";
+ xml.comment(StringPrintfW(L"Generated by: %s (%d)", app, WASABI_API_APP->main_getBuildNumber()));
+ xml.pushCategory(L"configuration");
+
+ PtrList<StringW> cats;
+
+ for (int i = 0; i < strings.getNumItems(); i++)
+ {
+ StringPair *p = strings[i];
+ PathParserW pp(p->a);
+
+ int climit = MIN(pp.getNumStrings() - 1, cats.getNumItems());
+ int j;
+ for (j = 0; j < climit; j++)
+ {
+ if (WCSICMP(*cats[j], pp.enumString(j)))
+ {
+ climit = j;
+ break;
+ }
+ }
+
+ while (cats.getNumItems() > climit)
+ {
+ StringW *s = cats.getLast();
+ xml.popCategory();
+ cats.removeLastItem();
+ delete s;
+ }
+ for (j = climit; j < pp.getNumStrings() - 1; j++)
+ {
+ StringW *s = cats.addItem(new StringW(pp.enumString(j)));
+ xml.pushCategoryAttrib(L"section");
+ StringW enc = *s;
+ Url::encode(enc, FALSE, URLENCODE_EXCLUDE_ABOVEEQ32);
+ xml.writeCategoryAttrib(L"name", enc);
+ xml.closeCategoryAttrib();
+ }
+
+ xml.pushCategoryAttrib(L"entry", TRUE);
+ StringW enc = pp.getLastString();
+ Url::encode(enc, FALSE, URLENCODE_EXCLUDE_ABOVEEQ32);
+ xml.writeCategoryAttrib(L"name", enc);
+ enc = p->b;
+ Url::encode(enc, FALSE, URLENCODE_EXCLUDE_ABOVEEQ32);
+ if (enc.iscaseequal(L"(null)") || enc.getValue() == NULL)
+ enc.setValue(L"");
+ xml.writeCategoryAttrib(L"value", enc);
+ xml.closeCategoryAttrib();
+ xml.popCategory();
+ }
+
+ while (xml.popCategory()) ;
+
+ strings.deleteAll();
+ fclose(fp);
+ } // fp != NULL
+ } // ninstances==0
+}
+
+int verifyName(const wchar_t *str)
+{
+ for (const wchar_t *p = str; *p; p++)
+ {
+ if (!ISALPHA(*p) &&
+ !ISDIGIT(*p) &&
+ !ISPUNCT(*p) &&
+ !ISSPACE(*p) &&
+ *p != '|' && *p != '_')
+ return 0;
+ }
+ return 1;
+}
+
+void ConfigFile::setInt(const wchar_t *name, int val)
+{
+ INCRITICALSECTION(cs);
+ if (name == NULL) return ;
+ if (!verifyName(name))
+ {
+ DebugStringW(L"illegal name given\n");
+ //__asm { int 3 };
+ return ;
+ }
+ makePair(name, StringPrintfW(val));
+}
+
+int ConfigFile::getInt(const wchar_t *name, int def_val)
+{
+ INCRITICALSECTION(cs);
+ if (name == NULL) return def_val;
+ StringPair *p = getPair(name);
+ if (p == NULL) return def_val;
+ return WTOI(p->b.getValue());
+}
+
+void ConfigFile::setString(const wchar_t *name, const wchar_t *str)
+{
+ INCRITICALSECTION(cs);
+ if (name == NULL) return ;
+ if (!verifyName(name))
+ {
+ DebugStringW(L"illegal name given\n");
+ return ;
+ }
+ if (str == NULL)
+ {
+ StringPair *p = getPair(name);
+ if (p != NULL)
+ {
+ strings.delItem(p);
+ delete p;
+ return ;
+ }
+ }
+ makePair(name, str);
+}
+
+int ConfigFile::getString(const wchar_t *name, wchar_t *buf, int buf_len, const wchar_t *def_str)
+{
+ INCRITICALSECTION(cs);
+ if (name == NULL || buf == NULL) return -1;
+ if (def_str == NULL)
+ def_str = L"";
+ StringPair *p = getPair(name);
+ if (p == NULL)
+ WCSCPYN(buf, def_str, buf_len);
+ else
+ WCSCPYN(buf, p->b.getValueSafe(), buf_len);
+ return 1;
+}
+
+int ConfigFile::getStringLen(const wchar_t *name)
+{
+ INCRITICALSECTION(cs);
+ if (name == NULL) return -1;
+ StringPair *p = getPair(name);
+ if (p == NULL) return -1;
+ return wcslen(p->b.getValue());
+}
diff --git a/Src/Wasabi/api/config/config.h b/Src/Wasabi/api/config/config.h
new file mode 100644
index 00000000..0f027b61
--- /dev/null
+++ b/Src/Wasabi/api/config/config.h
@@ -0,0 +1,43 @@
+#ifndef _CONFIG_H
+#define _CONFIG_H
+
+#include <bfc/string/bfcstring.h>
+#include <bfc/pair.h>
+#include <bfc/critsec.h>
+#include <bfc/string/StringW.h>
+
+class StringPair : public Pair<StringW, StringW>
+{
+public:
+ StringPair(StringW &_a, const wchar_t *_b)
+ {
+ b=_b;
+ a.swap(_a);
+ }
+};
+
+class ConfigFile
+{
+public:
+ ConfigFile(const wchar_t *section, const wchar_t *name);
+ ~ConfigFile();
+
+ static void initialize();
+
+ void setInt(const wchar_t *name, int val);
+ int getInt(const wchar_t *name, int default_val);
+
+ void setString(const wchar_t *name, const wchar_t *str);
+ int getString(const wchar_t *name, wchar_t *buf, int buf_len, const wchar_t *default_str);
+
+ int getStringLen(const wchar_t *name);
+
+private:
+ StringW sectionname;
+ StringW prettyname;
+ StringPair *getPair(const wchar_t *name);
+ StringPair *makePair(const wchar_t *name, const wchar_t *value);
+ CriticalSection cs;
+};
+
+#endif
diff --git a/Src/Wasabi/api/config/configapi.cpp b/Src/Wasabi/api/config/configapi.cpp
new file mode 100644
index 00000000..e66e00f8
--- /dev/null
+++ b/Src/Wasabi/api/config/configapi.cpp
@@ -0,0 +1,95 @@
+#include "precomp.h"
+#include "configapi.h"
+#include "../../studio/config.h"
+
+#include "../../studio/cfglist.h"
+
+config_api *configApi = NULL;
+
+static CfgList cfglist;
+
+void ConfigApi::config_registerCfgItem(CfgItem *cfgitem) {
+ cfglist.addItem(cfgitem);
+}
+
+void ConfigApi::config_deregisterCfgItem(CfgItem *cfgitem) {
+ cfglist.delItem(cfgitem);
+}
+
+int ConfigApi::config_getNumCfgItems() {
+ return cfglist.getNumItems();
+}
+
+CfgItem *ConfigApi::config_enumCfgItem(int n) {
+ return cfglist.enumItem(n);
+}
+
+CfgItem *ConfigApi::config_getCfgItemByGuid(GUID g) {
+ return NULL;//cfglist.getByGuid(g);
+}
+
+void ConfigApi::setIntPrivate(const char *name, int val) {
+ //config->setInt(name, val);
+}
+
+int ConfigApi::getIntPrivate(const char *name, int def_val) {
+/* int ret = config->getInt(name, def_val);
+ return ret;*/
+ return 0;
+}
+
+void ConfigApi::setIntArrayPrivate(const char *name, const int *val, int nval) {
+ /*if (nval > 256) return;
+ char buf[12*256]="";
+ for (int i = 0; i < nval; i++) {
+ STRCAT(buf, StringPrintf("%d", val[i]));
+ if (i != nval-1) STRCAT(buf, ",");
+ }
+ config->setString(name, buf);*/
+}
+
+int ConfigApi::getIntArrayPrivate(const char *name, int *val, int nval) {
+/* char buf[12*256]="";
+ config->getString(name, buf, sizeof(buf), "");
+ PathParser pp(buf, ",");
+ if (pp.getNumStrings() != nval) return 0;
+ for (int i = 0; i < nval; i++) {
+ *val = ATOI(pp.enumString(i));
+ val ++;
+ }
+ return 1;*/
+ return 1;
+}
+
+void ConfigApi::setStringPrivate(const char *name, const char *str) {
+ //config->setString(name, str);
+}
+
+int ConfigApi::getStringPrivate(const char *name, char *buf, int buf_len, const char *default_str) {
+/* int ret = config->getString(name, buf, buf_len, default_str);
+ return ret;*/
+ return 0;
+}
+
+int ConfigApi::getStringPrivateLen(const char *name) {
+ //return config->getStringLen(name);
+ return 0;
+}
+
+void ConfigApi::setIntPublic(const char *name, int val) {
+ //public_config->setInt(name, val);
+}
+
+int ConfigApi::getIntPublic(const char *name, int def_val) {
+ //return public_config->getInt(name, def_val);
+ return 0;
+}
+
+void ConfigApi::setStringPublic(const char *name, const char *str) {
+// public_config->setString(name, str);
+}
+int ConfigApi::getStringPublic(const char *name, char *buf, int buf_len, const char *default_str) {
+// return public_config->getString(name, buf, buf_len, default_str);
+ return 0;
+}
+
diff --git a/Src/Wasabi/api/config/configapi.h b/Src/Wasabi/api/config/configapi.h
new file mode 100644
index 00000000..2ea59f46
--- /dev/null
+++ b/Src/Wasabi/api/config/configapi.h
@@ -0,0 +1,32 @@
+#ifndef __CONFIG_API_H
+#define __CONFIG_API_H
+
+#include "../../bfc/api/api_configi.h"
+
+class ConfigApi : public config_apiI {
+ public:
+ ConfigApi() {}
+ virtual ~ConfigApi() {}
+
+ virtual void config_registerCfgItem(CfgItem *cfgitem);
+ virtual void config_deregisterCfgItem(CfgItem *cfgitem);
+ virtual int config_getNumCfgItems();
+ virtual CfgItem *config_enumCfgItem(int n);
+ virtual CfgItem *config_getCfgItemByGuid(GUID g);
+ virtual void setIntPrivate(const wchar_t *name, int val);
+ virtual int getIntPrivate(const wchar_t *name, int def_val);
+ virtual void setIntArrayPrivate(const wchar_t *name, const int *val, int nval);
+ virtual int getIntArrayPrivate(const wchar_t *name, int *val, int nval);
+ virtual void setStringPrivate(const wchar_t *name, const wchar_t *str);
+ virtual int getStringPrivate(const wchar_t *name, wchar_t *buf, int buf_len, const wchar_t *default_str);
+ virtual int getStringPrivateLen(const wchar_t *name);
+ virtual void setIntPublic(const wchar_t *name, int val);
+ virtual int getIntPublic(const wchar_t *name, int def_val);
+ virtual void setStringPublic(const wchar_t *name, const wchar_t *str);
+ virtual int getStringPublic(const wchar_t *name, wchar_t *buf, int buf_len, const wchar_t *default_str);
+
+ protected:
+};
+
+
+#endif
diff --git a/Src/Wasabi/api/config/filetypes.cpp b/Src/Wasabi/api/config/filetypes.cpp
new file mode 100644
index 00000000..20298b99
--- /dev/null
+++ b/Src/Wasabi/api/config/filetypes.cpp
@@ -0,0 +1,576 @@
+#include "precomp.h"
+#include "filetypes.h"
+#include "api.h"
+#include "main.h"
+#include "core.h"
+
+#include <bfc/attribs/attribs.h>
+#include <bfc/attribs/attrcb.h>
+
+#include "../common/locales.h"
+#include "../bfc/paramparser.h"
+
+// {DB26AA7F-0CF4-4e48-8AC8-49F9B9855A98}
+static const GUID winampa_guid =
+{ 0xdb26aa7f, 0xcf4, 0x4e48, { 0x8a, 0xc8, 0x49, 0xf9, 0xb9, 0x85, 0x5a, 0x98 } };
+
+class Filetypes;
+
+class ExtensionAttrCallback : public AttrCallback {
+public:
+ ExtensionAttrCallback(const char *extname, Filetypes *ft) : ext(extname), filetypes(ft) {}
+ virtual void onValueChange(Attribute *attr) {
+ Filetypes::registerExtension(ext, attr->getValueAsInt());
+ api->cmd_sendCommand(winampa_guid,"extchange",0,0,attr,sizeof(attr)); // CT> notifies winampa.wac of the change
+ // (dunno if there is a better method)
+ filetypes->updateKeepers();
+ }
+private:
+ String ext;
+ Filetypes *filetypes;
+};
+
+class KeepersCB : public AttrCallback {
+public:
+ KeepersCB(CfgItemI *_par) : par(_par) { }
+ virtual void onValueChange(Attribute *attr) {
+ //CT> This is REAL SLOW, for each attribute modified, you reregister them all, this needs to have
+ // an old list and just register/unregister what's new
+ char bufero[WA_MAX_PATH]="";
+ char data[WA_MAX_PATH]="";
+ attr->getData(bufero, WA_MAX_PATH-1);
+ ParamParser pp(bufero);
+ const char *ext=api->core_getSupportedExtensions();
+ const char *p=ext;
+ while(*p!=0 && *(p+1)!=0) {
+ if(*p) {
+ int v = !!pp.hasString(p);
+ int r = par->cfgitem_getData(StringPrintf("extension/%s", p), data, WA_MAX_PATH-1);
+ if (r == 0 || (!!ATOI(data) != v)) {
+ par->cfgitem_setData(StringPrintf("extension/%s", p), StringPrintf(v));
+ }
+ }
+ while(*p!=0) p++;
+ p++;
+ }
+ }
+private:
+ CfgItemI *par;
+};
+
+#ifdef WIN32
+static void DCM_cb(int v) {
+ if (v) {
+ HKEY mp3Key;
+ char programname[MAX_PATH];
+ GetModuleFileName(Main::gethInstance(),programname,sizeof(programname));
+ if (RegCreateKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Classes\\Directory\\shell\\Winamp3.Play",&mp3Key) == ERROR_SUCCESS) {
+ const char *str=_("&Play in Winamp");
+ RegSetValueEx(mp3Key, NULL,0,REG_SZ,(unsigned char*)str,strlen(str) + 1);
+ RegCloseKey(mp3Key);
+ }
+ if (RegCreateKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Classes\\Directory\\shell\\Winamp3.Play\\command",&mp3Key) == ERROR_SUCCESS) {
+ StringPrintf mstr("\"%s\" \"%%1\"", programname);
+ const char *blah = mstr;
+ const unsigned char *microsoft_sucks_ass = (const unsigned char*)blah;
+ RegSetValueEx(mp3Key, NULL,0,REG_SZ,microsoft_sucks_ass,mstr.len() + 1);
+ RegCloseKey(mp3Key);
+ }
+
+ if (RegCreateKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Classes\\Directory\\shell\\Winamp3.Enqueue",&mp3Key) == ERROR_SUCCESS) {
+ const char *str=_("&Enqueue in Winamp");
+ RegSetValueEx(mp3Key, NULL,0,REG_SZ,(unsigned char*)str,strlen(str) + 1);
+ RegCloseKey(mp3Key);
+ }
+ if (RegCreateKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\Classes\\Directory\\shell\\Winamp3.Enqueue\\command",&mp3Key) == ERROR_SUCCESS) {
+ StringPrintf mstr("\"%s\" /ADD \"%%1\"", programname);
+ const char *blah = mstr;
+ const unsigned char *microsoft_sucks_ass = (const unsigned char*)blah;
+ RegSetValueEx(mp3Key, NULL,0,REG_SZ,microsoft_sucks_ass,mstr.len() + 1);
+ RegCloseKey(mp3Key);
+ }
+ } else {
+ Filetypes::myRegDeleteKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Classes\\Directory\\shell\\Winamp3.Play");
+ Filetypes::myRegDeleteKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Classes\\Directory\\shell\\Winamp3.Enqueue");
+ }
+}
+#endif
+
+// {C30C97E6-77E6-4da4-9F4F-C7F848F8F641}
+const GUID filetypes_guid =
+{ 0xc30c97e6, 0x77e6, 0x4da4, { 0x9f, 0x4f, 0xc7, 0xf8, 0x48, 0xf8, 0xf6, 0x41 } };
+
+Filetypes::Filetypes() : CfgItemI("Filetypes", filetypes_guid) { }
+
+void Filetypes::registerAttributes() {
+ const char *ext=api->core_getSupportedExtensions();
+ if (ext == NULL) return; //BU
+
+ _bool *wantExtensions;
+ registerAttribute(wantExtensions = new _bool("Register associations on Winamp startup", TRUE));
+
+ const char *p=ext;
+ while(*p!=0 && *(p+1)!=0) {
+ if(*p) {
+ _bool *extenabled;
+ registerAttribute(extenabled = new _bool(StringPrintf("extension/%s", p), FALSE), new ExtensionAttrCallback(p, this));
+ if (*wantExtensions) registerExtension(p, *extenabled);
+ } while(*p!=0) p++;
+ p++;
+ }
+
+ registerAttribute(new _string("keepers"), new KeepersCB(this));
+
+#ifdef WIN32
+ registerAttribute(new _bool("Directory context menus", TRUE), new int_attrCB(DCM_cb));
+#endif
+
+ // Always steal the ".wal" extension.
+ CfgItem *cift=WASABI_API_CONFIG->config_getCfgItemByGuid(filetypes_guid);
+ if (cift) {
+ cift->setDataAsInt("extension/wal",1);
+ }
+
+ updateKeepers();
+}
+
+void Filetypes::updateKeepers() {
+ static int reentry=0;
+ if (reentry) return;
+ const char *ext=api->core_getSupportedExtensions();
+ if (ext == NULL) return; //BU
+
+ reentry = 1;
+ const char *p=ext;
+ String kstr;
+ while(*p!=0 && *(p+1)!=0) {
+ if(*p) {
+ _bool *extenabled = static_cast<_bool *>(getAttributeByName(StringPrintf("extension/%s", p)));
+ if (*extenabled) {
+ if (!kstr.isempty()) kstr += ";";
+ kstr += p;
+ }
+ } while(*p!=0) p++;
+ p++;
+ }
+ _string *k = static_cast<_string *>(getAttributeByName("keepers"));
+ k->setValue(kstr);
+ reentry = 0;
+}
+
+LONG Filetypes::myRegDeleteKeyEx(HKEY thiskey, LPCTSTR lpSubKey)
+{
+#ifdef WIN32
+ HKEY key;
+ int retval=RegOpenKey(thiskey,lpSubKey,&key);
+ if (retval==ERROR_SUCCESS)
+ {
+ char buffer[1024];
+ while (RegEnumKey(key,0,buffer,1024)==ERROR_SUCCESS)
+ if ((retval=myRegDeleteKeyEx(key,buffer)) != ERROR_SUCCESS) break;
+ RegCloseKey(key);
+ retval=RegDeleteKey(thiskey,lpSubKey);
+ }
+ return retval;
+#else
+ DebugString( "portme -- Filetypes::myRegDeleteKeyEx\n" );
+ return 0;
+#endif
+}
+
+int Filetypes::isRegistered(const char *ext) {
+ char b[256];
+ int rval=0;
+ unsigned long vt,s=sizeof(b);
+ HKEY key;
+ SPRINTF(b,".%s",ext);
+#ifdef WIN32
+ if (RegOpenKey(HKEY_CLASSES_ROOT,b,&key) != ERROR_SUCCESS) return 0;
+ if (RegQueryValueEx(key,NULL,0,&vt,b,&s) == ERROR_SUCCESS) {
+ if (vt != REG_SZ || (strcmp(b,"Winamp3.File") && strcmp(b,"Winamp3.PlayList") && strcmp(b,"Winamp3.SkinZip"))) rval=0;
+ else rval=1;
+ } else rval=0;
+ RegCloseKey(key);
+#else
+DebugString( "portme -- FileTypes::isRegistered\n" );
+#endif
+ return rval;
+}
+
+void Filetypes::regmimetype(const char *mtype, const char *programname, const char *ext, int nsonly) {
+#ifdef WIN32
+ HKEY mp3Key;
+ if (!nsonly) {
+ char s[MAX_PATH];
+ // Changed these to create rather than just open the mimetypes in the database.
+ if (RegCreateKey(HKEY_CLASSES_ROOT,ext,&mp3Key) == ERROR_SUCCESS) {
+ RegSetValueEx(mp3Key,"Content Type",0,REG_SZ,mtype,STRLEN(mtype) + 1);
+ RegCloseKey(mp3Key);
+ }
+ wsprintf(s,"MIME\\Database\\Content Type\\%s",mtype);
+ if (RegCreateKey(HKEY_CLASSES_ROOT,s,&mp3Key) == ERROR_SUCCESS) {
+ RegDeleteValue(mp3Key,"CLSID");
+ RegSetValueEx(mp3Key,"Extension",0,REG_SZ,ext,strlen(ext) + 1);
+ RegCloseKey(mp3Key);
+ }
+ }
+ if (RegOpenKey(HKEY_CURRENT_USER,"Software\\Netscape\\Netscape Navigator\\Viewers",&mp3Key) == ERROR_SUCCESS) {
+ int x;
+ RegSetValueEx(mp3Key, mtype,0,REG_SZ,programname,strlen(programname) + 1);
+ for (x = 0; x < 999; x ++) {
+ char st[100];
+ DWORD vt;
+ DWORD s=128;
+ char b[128];
+ wsprintf(st,"TYPE%d",x);
+ if (RegQueryValueEx(mp3Key,st,0,&vt,b,&s) == ERROR_SUCCESS) {
+ if (!strcmp(b,mtype)) break;
+ } else {
+ RegSetValueEx(mp3Key,st,0,REG_SZ,mtype,strlen(mtype)+1);
+ break;
+ }
+ }
+ RegCloseKey(mp3Key);
+ }
+#else
+DebugString( "portme -- Filetypes::regmimetype\n" );
+#endif
+}
+
+void Filetypes::registerExtension(const char *ext, int reg) {
+#ifdef WIN32
+ createWinampTypes();
+
+ char b[128];
+ HKEY mp3Key;
+ char *which_str="Winamp3.File";
+
+ if (!_stricmp(ext,"m3u") || !_stricmp(ext,"pls")) which_str="Winamp3.PlayList";
+ if (!_stricmp(ext,"wsz") || !_stricmp(ext,"wpz") || !_stricmp(ext,"wal"))
+ which_str="Winamp3.SkinZip";
+ wsprintf(b,".%s",ext);
+ if (reg && !_stricmp(ext,"pls")) {
+ char programname[MAX_PATH];
+ GetModuleFileName(Main::gethInstance(),programname,sizeof(programname));
+ regmimetype("audio/x-scpls", programname,".pls",1);
+ regmimetype("audio/scpls", programname,".pls",1);
+ }
+ if (reg && !_stricmp(ext,"wma")) {
+ char programname[MAX_PATH];
+ GetModuleFileName(Main::gethInstance(),programname,sizeof(programname));
+ regmimetype("audio/x-ms-wma", programname,".wma",1);
+ regmimetype("application/x-msdownload", programname,".wma",1);
+ }
+ if (reg && !_stricmp(ext,"m3u")) {
+ char programname[MAX_PATH];
+ GetModuleFileName(Main::gethInstance(),programname,sizeof(programname));
+ regmimetype("audio/x-mpegurl", programname,".m3u",1);
+ regmimetype("audio/mpegurl", programname,".m3u",1);
+ }
+ if (reg && !_stricmp(ext,"mp3")) {
+ char programname[MAX_PATH];
+ GetModuleFileName(Main::gethInstance(),programname,sizeof(programname));
+ regmimetype("audio/x-mpeg", programname,".mp3",1);
+ regmimetype("audio/x-mp3", programname,".mp3",1);
+ regmimetype("audio/x-mpg", programname,".mp3",1);
+ regmimetype("audio/mp3", programname,".mp3",1);
+ regmimetype("audio/mpg", programname,".mp3",1);
+ regmimetype("audio/mpeg", programname,".mp3",1);
+ }
+ if (RegCreateKey(HKEY_CLASSES_ROOT,b,&mp3Key) == ERROR_SUCCESS) {
+ if (reg) {
+ unsigned long s=sizeof(b);
+ if (RegQueryValueEx(mp3Key,NULL,0,NULL,b,&s) == ERROR_SUCCESS) {
+ if (strcmp(b,which_str)) {
+ RegSetValueEx(mp3Key,"Winamp_Back",0,REG_SZ,b,strlen(b)+1);
+ RegSetValueEx(mp3Key,NULL,0,REG_SZ,which_str,strlen(which_str)+1);
+ }
+ } else RegSetValueEx(mp3Key,NULL,0,REG_SZ,which_str,strlen(which_str)+1);
+ } else {
+ unsigned long s=sizeof(b);
+ if (RegQueryValueEx(mp3Key,NULL,0,NULL,b,&s) == ERROR_SUCCESS) {
+ if (!strcmp(b,which_str)) {
+ s=sizeof(b);
+ if (RegQueryValueEx(mp3Key,"Winamp_Back",0,NULL,b,&s) == ERROR_SUCCESS) {
+ if (RegSetValueEx(mp3Key, NULL,0,REG_SZ,b,strlen(b)+1) == ERROR_SUCCESS)
+ RegDeleteValue(mp3Key,"Winamp_Back");
+ } else {
+ RegDeleteValue(mp3Key,NULL);
+ RegCloseKey(mp3Key);
+ mp3Key=NULL;
+ wsprintf(b,".%s",ext);
+ myRegDeleteKeyEx(HKEY_CLASSES_ROOT,b);
+ }
+ }
+ }
+ }
+ if (mp3Key) RegCloseKey(mp3Key);
+ }
+#else
+DebugString( "portme -- Filetypes::registerExtensions\n" );
+#endif
+}
+
+void Filetypes::createWinampTypes() {
+#ifdef WIN32
+ HKEY mp3Key;
+ char programname[MAX_PATH];
+ char str[MAX_PATH+32];
+ char buf[128]="Winamp3.File";
+ char buf2[128]="Winamp3.PlayList";
+ char buf3[128]="Winamp3.SkinZip";
+ if (!GetModuleFileName(Main::gethInstance(),programname,sizeof(programname))) return;
+
+ if (RegCreateKey(HKEY_CLASSES_ROOT,"Winamp3.File",&mp3Key) == ERROR_SUCCESS) {
+ strcpy(str,"Winamp media file");
+ RegSetValueEx(mp3Key, NULL,0,REG_SZ,str,strlen(str)+1);
+ RegCloseKey(mp3Key);
+ }
+
+ if (RegCreateKey(HKEY_CLASSES_ROOT,"Winamp3.File\\DefaultIcon",&mp3Key) == ERROR_SUCCESS) {
+ wsprintf(str,"%s,%d",programname,whichicon);
+ RegSetValueEx(mp3Key, NULL,0,REG_SZ,str,strlen(str)+1);
+ RegCloseKey(mp3Key);
+ }
+ if (RegCreateKey(HKEY_CLASSES_ROOT,"Winamp3.File\\shell",&mp3Key) == ERROR_SUCCESS) {
+ if (addtolist)
+ RegSetValueEx(mp3Key, NULL,0,REG_SZ,"Enqueue",8);
+ else
+ RegSetValueEx(mp3Key, NULL,0,REG_SZ,"Play",5);
+ RegCloseKey(mp3Key);
+ }
+
+ if (RegCreateKey(HKEY_CLASSES_ROOT,"Winamp3.File\\shell\\Play",&mp3Key) == ERROR_SUCCESS) {
+ const char *str=_("&Play in Winamp");
+ RegSetValueEx(mp3Key, NULL,0,REG_SZ,str,strlen(str)+1);
+ RegCloseKey(mp3Key);
+ }
+ if (RegCreateKey(HKEY_CLASSES_ROOT,"Winamp3.File\\shell\\Play\\command",&mp3Key) == ERROR_SUCCESS) {
+ wsprintf(str,"\"%s\" \"%%1\"",programname);
+ RegSetValueEx(mp3Key, NULL,0,REG_SZ,str,strlen(str) + 1);
+ RegCloseKey(mp3Key);
+ }
+ if (RegCreateKey(HKEY_CLASSES_ROOT,"Winamp3.File\\shell\\open",&mp3Key) == ERROR_SUCCESS) {
+ RegSetValueEx(mp3Key, NULL,0,REG_SZ,"",1);
+ RegCloseKey(mp3Key);
+ }
+ if (RegCreateKey(HKEY_CLASSES_ROOT,"Winamp3.File\\shell\\open\\command",&mp3Key) == ERROR_SUCCESS) {
+ wsprintf(str,"\"%s\" \"%%1\"",programname);
+ RegSetValueEx(mp3Key, NULL,0,REG_SZ,str,strlen(str) + 1);
+ RegCloseKey(mp3Key);
+ }
+
+ if (RegCreateKey(HKEY_CLASSES_ROOT,"Winamp3.File\\shell\\Enqueue",&mp3Key) == ERROR_SUCCESS) {
+ const char *str=_("&Enqueue in Winamp");
+ RegSetValueEx(mp3Key, NULL,0,REG_SZ,str,strlen(str) + 1);
+ RegCloseKey(mp3Key);
+ }
+ if (RegCreateKey(HKEY_CLASSES_ROOT,"Winamp3.File\\shell\\Enqueue\\command",&mp3Key) == ERROR_SUCCESS) {
+ wsprintf(str,"\"%s\" /ADD \"%%1\"",programname);
+ RegSetValueEx(mp3Key, NULL,0,REG_SZ,str,strlen(str) + 1);
+ RegCloseKey(mp3Key);
+ }
+
+ if (RegCreateKey(HKEY_CLASSES_ROOT,"Winamp3.File\\shell\\ListBookmark",&mp3Key) == ERROR_SUCCESS) {
+ const char *str=_("Add to Winamp's &Bookmark list");
+ RegSetValueEx(mp3Key, NULL,0,REG_SZ,str,strlen(str) + 1);
+ RegCloseKey(mp3Key);
+ }
+ if (RegCreateKey(HKEY_CLASSES_ROOT,"Winamp3.File\\shell\\ListBookmark\\command",&mp3Key) == ERROR_SUCCESS) {
+ wsprintf(str,"\"%s\" /BOOKMARK \"%%1\"",programname);
+ RegSetValueEx(mp3Key, NULL,0,REG_SZ,str,strlen(str) + 1);
+ RegCloseKey(mp3Key);
+ }
+
+ if (RegCreateKey(HKEY_CLASSES_ROOT,"Winamp3.Playlist",&mp3Key) == ERROR_SUCCESS) {
+ strcpy(str,"Winamp playlist file");
+ RegSetValueEx(mp3Key, NULL,0,REG_SZ,str,strlen(str)+1);
+ str[0]=0;
+ str[1]=0;
+ str[2]=1;
+ str[3]=0;
+ RegSetValueEx(mp3Key, "EditFlags",0,REG_BINARY,str,4);
+ RegCloseKey(mp3Key);
+ }
+ if (RegCreateKey(HKEY_CLASSES_ROOT,"Winamp3.PlayList\\DefaultIcon",&mp3Key) == ERROR_SUCCESS) {
+ wsprintf(str,"%s,%d",programname,whichicon2);
+ RegSetValueEx(mp3Key, NULL,0,REG_SZ,str,strlen(str)+1);
+ RegCloseKey(mp3Key);
+ }
+ if (RegCreateKey(HKEY_CLASSES_ROOT,"Winamp3.PlayList\\shell",&mp3Key) == ERROR_SUCCESS) {
+ if (addtolist)
+ RegSetValueEx(mp3Key, NULL,0,REG_SZ,"Enqueue",8);
+ else
+ RegSetValueEx(mp3Key, NULL,0,REG_SZ,"Play",5);
+ RegCloseKey(mp3Key);
+ }
+ if (RegCreateKey(HKEY_CLASSES_ROOT,"Winamp3.PlayList\\shell\\Play",&mp3Key) == ERROR_SUCCESS) {
+ const char *str=_("&Play in Winamp");
+ RegSetValueEx(mp3Key, NULL,0,REG_SZ,str,strlen(str)+1);
+ RegCloseKey(mp3Key);
+ }
+ if (RegCreateKey(HKEY_CLASSES_ROOT,"Winamp3.PlayList\\shell\\Play\\command",&mp3Key) == ERROR_SUCCESS) {
+ wsprintf(str,"\"%s\" \"%%1\"",programname);
+ RegSetValueEx(mp3Key, NULL,0,REG_SZ,str,strlen(str) + 1);
+ RegCloseKey(mp3Key);
+ }
+ if (RegCreateKey(HKEY_CLASSES_ROOT,"Winamp3.PlayList\\shell\\open",&mp3Key) == ERROR_SUCCESS) {
+ RegSetValueEx(mp3Key, NULL,0,REG_SZ,"",1);
+ RegCloseKey(mp3Key);
+ }
+ if (RegCreateKey(HKEY_CLASSES_ROOT,"Winamp3.PlayList\\shell\\open\\command",&mp3Key) == ERROR_SUCCESS) {
+ wsprintf(str,"\"%s\" \"%%1\"",programname);
+ RegSetValueEx(mp3Key, NULL,0,REG_SZ,str,strlen(str) + 1);
+ RegCloseKey(mp3Key);
+ }
+ if (RegCreateKey(HKEY_CLASSES_ROOT,"Winamp3.PlayList\\shell\\Enqueue",&mp3Key) == ERROR_SUCCESS) {
+ const char *str=_("&Enqueue in Winamp");
+ RegSetValueEx(mp3Key, NULL,0,REG_SZ,str,strlen(str)+1);
+ RegCloseKey(mp3Key);
+ }
+ if (RegCreateKey(HKEY_CLASSES_ROOT,"Winamp3.PlayList\\shell\\Enqueue\\command",&mp3Key) == ERROR_SUCCESS) {
+ wsprintf(str,"\"%s\" /ADD \"%%1\"",programname);
+ RegSetValueEx(mp3Key, NULL,0,REG_SZ,str,strlen(str) + 1);
+ RegCloseKey(mp3Key);
+ }
+ if (RegCreateKey(HKEY_CLASSES_ROOT,"Winamp3.PlayList\\shell\\ListBookmark",&mp3Key) == ERROR_SUCCESS) {
+ const char *str=_("Add to Winamp's &Bookmark list");
+ RegSetValueEx(mp3Key, NULL,0,REG_SZ,str,strlen(str)+1);
+ RegCloseKey(mp3Key);
+ }
+ if (RegCreateKey(HKEY_CLASSES_ROOT,"Winamp3.PlayList\\shell\\ListBookmark\\command",&mp3Key) == ERROR_SUCCESS) {
+ wsprintf(str,"\"%s\" /BOOKMARK \"%%1\"",programname);
+ RegSetValueEx(mp3Key, NULL,0,REG_SZ,str,strlen(str) + 1);
+ RegCloseKey(mp3Key);
+ }
+
+ if (RegCreateKey(HKEY_CLASSES_ROOT,"Winamp3.SkinZip",&mp3Key) == ERROR_SUCCESS) {
+ strcpy(str,"Winamp3 skin file");
+ RegSetValueEx(mp3Key, NULL,0,REG_SZ,str,strlen(str)+1);
+ str[0]=0;
+ str[1]=0;
+ str[2]=1;
+ str[3]=0;
+ RegSetValueEx(mp3Key, "EditFlags",0,REG_BINARY,str,4);
+ RegCloseKey(mp3Key);
+ }
+ if (RegCreateKey(HKEY_CLASSES_ROOT,"Winamp3.SkinZip\\DefaultIcon",&mp3Key) == ERROR_SUCCESS) {
+ wsprintf(str,"%s,%d",programname,whichicon);
+ RegSetValueEx(mp3Key, NULL,0,REG_SZ,str,strlen(str)+1);
+ RegCloseKey(mp3Key);
+ }
+ if (RegCreateKey(HKEY_CLASSES_ROOT,"Winamp3.SkinZip\\shell",&mp3Key) == ERROR_SUCCESS) {
+ RegSetValueEx(mp3Key, NULL,0,REG_SZ,"Install and switch to",8);
+ RegCloseKey(mp3Key);
+ }
+ if (RegCreateKey(HKEY_CLASSES_ROOT,"Winamp3.SkinZip\\shell\\install",&mp3Key) == ERROR_SUCCESS) {
+ RegSetValueEx(mp3Key, NULL,0,REG_SZ,"",1);
+ RegCloseKey(mp3Key);
+ }
+ if (RegCreateKey(HKEY_CLASSES_ROOT,"Winamp3.SkinZip\\shell\\install\\command",&mp3Key) == ERROR_SUCCESS) {
+ wsprintf(str,"\"%s\" \"/installskin=%%1\"",programname);
+ RegSetValueEx(mp3Key, NULL,0,REG_SZ,str,strlen(str) + 1);
+ RegCloseKey(mp3Key);
+ }
+ if (RegCreateKey(HKEY_CLASSES_ROOT,"Winamp3.SkinZip\\shell\\open",&mp3Key) == ERROR_SUCCESS) {
+ RegSetValueEx(mp3Key, NULL,0,REG_SZ,"",1);
+ RegCloseKey(mp3Key);
+ }
+ if (RegCreateKey(HKEY_CLASSES_ROOT,"Winamp3.SkinZip\\shell\\open\\command",&mp3Key) == ERROR_SUCCESS) {
+ wsprintf(str,"\"%s\" \"/installskin=%%1\"",programname);
+ RegSetValueEx(mp3Key, NULL,0,REG_SZ,str,strlen(str) + 1);
+ RegCloseKey(mp3Key);
+ }
+
+ // Register the mimetypes to act like .wal files?
+
+// regmimetype("interface/x-winamp-skin", programname,".wsz",0);
+ regmimetype("interface/x-winamp-skin", programname,".wal",0);
+// regmimetype("interface/x-winamp3-skin", programname,".wsz",0);
+ regmimetype("interface/x-winamp3-skin", programname,".wal",0);
+// regmimetype("application/x-winamp-plugin", programname,"wpz",0);
+#else
+DebugString( "portme -- Filetypes::createWinampTypes\n" );
+#endif
+}
+
+int Filetypes::isCdPlayer() {
+ int r=0;
+#ifdef WIN32
+ unsigned long s;
+ HKEY mp3Key;
+ char buf[MAX_PATH],buf2[MAX_PATH]="\"";
+ if (!GetModuleFileName(Main::gethInstance(),buf2+1,sizeof(buf2)-8)) return 0;
+ if (RegOpenKey(HKEY_CLASSES_ROOT,"AudioCD\\shell\\play\\command",&mp3Key) != ERROR_SUCCESS) return 0;
+ strcat(buf2,"\" /CDA:%1");
+ s=sizeof(buf);
+ if (RegQueryValueEx(mp3Key,NULL,0,NULL,buf,&s) == ERROR_SUCCESS)
+ {
+ if (!lstrcmpi(buf,buf2)) r=1;
+ }
+ RegCloseKey(mp3Key);
+#else
+DebugString( "portme -- Filetypes::isCdPlayer\n" );
+#endif
+ return r;
+}
+
+void Filetypes::registerCdPlayer(int reg) {
+#ifdef WIN32
+ char b[MAX_PATH];
+ char buf2[MAX_PATH]="\"";
+ HKEY mp3Key;
+ if (!GetModuleFileName(Main::gethInstance(),buf2+1,sizeof(buf2)-8)) return;
+ strcat(buf2,"\" /CDA:%1");
+ if (RegOpenKey(HKEY_CLASSES_ROOT,"AudioCD\\shell\\play\\command",&mp3Key) == ERROR_SUCCESS)
+ {
+ if (reg)
+ {
+ unsigned long s=sizeof(b);
+ if (RegQueryValueEx(mp3Key,NULL,0,NULL,b,&s) == ERROR_SUCCESS)
+ {
+ if (_stricmp(b,buf2))
+ {
+ char buf3[MAX_PATH];
+ unsigned long st=sizeof(buf3);
+ if (RegQueryValueEx(mp3Key,"Winamp_Back",0,NULL,buf3,&st) != ERROR_SUCCESS ||
+ _stricmp(buf3,b))
+ {
+ RegSetValueEx(mp3Key,"Winamp_Back",0,REG_SZ,b,strlen(b)+1);
+ }
+ RegSetValueEx(mp3Key,NULL,0,REG_SZ,buf2,strlen(buf2)+1);
+ }
+ } else RegSetValueEx(mp3Key,NULL,0,REG_SZ,buf2,strlen(buf2)+1);
+ }
+ else
+ {
+ unsigned long s=sizeof(b);
+ if (RegQueryValueEx(mp3Key,NULL,0,NULL,b,&s) == ERROR_SUCCESS)
+ {
+ if (!strcmp(b,buf2))
+ {
+ s=sizeof(b);
+ if (RegQueryValueEx(mp3Key,"Winamp_Back",0,NULL,b,&s) == ERROR_SUCCESS)
+ {
+ if (!_stricmp(b,buf2)) b[0]=0;
+ if (RegSetValueEx(mp3Key, NULL,0,REG_SZ,b,strlen(b)+1) == ERROR_SUCCESS)
+ RegDeleteValue(mp3Key,"Winamp_Back");
+ }
+ else
+ {
+ buf2[0]=0;
+ RegSetValueEx(mp3Key,NULL,0,REG_SZ,buf2,strlen(buf2)+1);
+ }
+ }
+ }
+ }
+ RegCloseKey(mp3Key);
+ }
+#else
+DebugString( "portme -- Filetypes::isCdPlayer\n" );
+#endif
+}
+
+int Filetypes::whichicon=1;
+int Filetypes::whichicon2=1;
+int Filetypes::addtolist=0;
diff --git a/Src/Wasabi/api/config/filetypes.h b/Src/Wasabi/api/config/filetypes.h
new file mode 100644
index 00000000..4d7e6891
--- /dev/null
+++ b/Src/Wasabi/api/config/filetypes.h
@@ -0,0 +1,46 @@
+#ifndef _FILETYPES_H
+#define _FILETYPES_H
+
+#include <api/config/items/cfgitemi.h>
+
+#define FILETYPES_PARENT CfgItemI
+class Filetypes : public FILETYPES_PARENT {
+public:
+ Filetypes();
+ void registerAttributes();
+
+ static int isRegistered(const char *ext);
+ static void registerExtension(const char *ext, int reg);
+ static int isCdPlayer();
+ static void registerCdPlayer(int reg);
+
+ void updateKeepers();
+
+private:
+
+ static void createWinampTypes();
+ static void regmimetype(const char *mtype, const char *programname, const char *ext, int nsonly);
+
+ // workaround for (damn) c++ type checking
+ static LONG RegQueryValueEx(HKEY hKey, LPTSTR lpValueName, LPDWORD lpReserved, LPDWORD lpType, char *lpData, LPDWORD lpcbData) {
+#ifdef WIN32
+ return ::RegQueryValueEx(hKey, lpValueName, lpReserved, lpType, (unsigned char *)lpData, lpcbData);
+#endif
+ }
+ static LONG RegSetValueEx(HKEY hKey, LPCTSTR lpValueName, DWORD Reserved, DWORD dwType, char *lpData, DWORD cbData) {
+#ifdef WIN32
+ return ::RegSetValueEx(hKey, lpValueName, Reserved, dwType, (const unsigned char *)lpData, cbData);
+#endif
+ }
+ static LONG RegSetValueEx(HKEY hKey, LPCTSTR lpValueName, DWORD Reserved, DWORD dwType, const char *lpData, DWORD cbData) {
+#ifdef WIN32
+ return ::RegSetValueEx(hKey, lpValueName, Reserved, dwType, (const unsigned char *)lpData, cbData);
+#endif
+ }
+public:
+ static LONG myRegDeleteKeyEx(HKEY thiskey, LPCTSTR lpSubKey);
+
+ static int whichicon, whichicon2, addtolist;
+};
+
+#endif
diff --git a/Src/Wasabi/api/config/items/attrbool.h b/Src/Wasabi/api/config/items/attrbool.h
new file mode 100644
index 00000000..324a2e11
--- /dev/null
+++ b/Src/Wasabi/api/config/items/attrbool.h
@@ -0,0 +1,65 @@
+#ifndef _ATTRBOOL_H
+#define _ATTRBOOL_H
+
+#include "attribute.h"
+
+// inherit from this one, or just use it
+
+/**
+ Boolean configuration attributes have two values, true or false.
+ They can be used like any other config item.
+
+ @short Boolean configuration attribute.
+ @ver 1.0
+ @author Nullsoft
+ @see _int
+ @see _string
+ @see _float
+*/
+class _bool : public Attribute {
+public:
+ /**
+ Optionally set the name and default value of
+ your configuration attribute during construction.
+
+ @param name Name of the configuration attribute.
+ @param default_val Default value.
+ */
+ _bool(const wchar_t *name=NULL, int default_val=0) : Attribute(name) {
+ setValueAsInt(!!default_val, true);
+ }
+
+ // convenience operators
+ /**
+ Get the value of the attribute.
+ */
+ operator bool() { return !!getValueAsInt(); }
+
+ /**
+ Set the value of the attribute.
+ */
+ bool operator =(int newval) { setValueAsInt(!!newval); return *this; }
+
+ // from Attribute
+
+ /**
+ Get the attribute type. This will return
+ a constant representing the attribute type.
+
+ These constants can be: BOOL, FLOAT, STRING and INT.
+
+ @see AttributeType
+ @ret The attribute type.
+ */
+ virtual int getAttributeType() { return AttributeType::BOOL; }
+
+ /**
+ Get the configuration group to be used to represent
+ this attribute in the registry.
+
+ @ret Config group to be used.
+ */
+ virtual const wchar_t *getConfigGroup() { return L"studio.configgroup.bool"; }
+};
+
+#endif
diff --git a/Src/Wasabi/api/config/items/attrcb.h b/Src/Wasabi/api/config/items/attrcb.h
new file mode 100644
index 00000000..3aa0e41d
--- /dev/null
+++ b/Src/Wasabi/api/config/items/attrcb.h
@@ -0,0 +1,127 @@
+#ifndef _ATTRCB_H
+#define _ATTRCB_H
+
+#include "attribute.h"
+
+/**
+ Enables you to register callbacks on
+ a specific attribute to monitor if it's
+ value has been changed by the user or other.
+
+ This class is not meant to be used on it's own.
+ Please derive from it instead.
+
+ @short Attribute callback
+ @ver 1.0
+ @author Nullsoft
+ @see Attribute
+ @see int_attrCB
+ @see _int
+ @see _float
+ @see _string
+ @see _bool
+*/
+class AttrCallback {
+public:
+ /**
+ Does nothing.
+ */
+ virtual ~AttrCallback() {}
+
+ /**
+ Event triggered when the value of the attribute,
+ for which this callback has been registered, changes.
+
+ This is a pure virtual, please override to implement
+ your custom behavior.
+
+ @param attr Attribute for which the value has changed.
+ */
+ virtual void onValueChange(Attribute *attr)=0;
+};
+
+/**
+ Enables you to register callbacks on a specific
+ integer or boolean attribute to monitor if the
+ value has been changed by the user or other.
+
+ @short Integer or Boolean attribute Callback.
+ @ver 1.0
+ @author Nullsoft
+ @see Attribute
+ @see _int
+ @see _bool
+*/
+class int_attrCB : public AttrCallback {
+ typedef void (*fnPtrType)(int);
+public:
+ /**
+ Upon construction, you must specify which
+ function will be called when the value of
+ the attribute has indeed changed.
+
+ This is done using a pointer to the function.
+ The function must accept one parameter of type
+ int, like so: void myfunc(int val);
+
+ @param _fn Pointer to the function to use on value change.
+ */
+ int_attrCB(fnPtrType _fn) { fnptr = _fn; }
+
+ /**
+ Event triggered when the value of the attribute,
+ for which this callback has been registered, changes.
+
+ Override this to implement your own behavior.
+ The default is to send the new value of the attribute
+ to a function which you specify upon construction
+ of this object.
+
+ @param attr Attribute for which the value has changed.
+ */
+ virtual void onValueChange(Attribute *attr) {
+ ASSERT(attr->getAttributeType() == AttributeType::INT ||
+ attr->getAttributeType() == AttributeType::BOOL);
+ (*fnptr)(attr->getValueAsInt());
+ }
+private:
+ fnPtrType fnptr;
+};
+
+class string_attrCB : public AttrCallback {
+ typedef void (*fnPtrType)(const wchar_t *);
+public:
+ /**
+ Upon construction, you must specify which
+ function will be called when the value of
+ the attribute has indeed changed.
+
+ This is done using a pointer to the function.
+ The function must accept one parameter of type
+ int, like so: void myfunc(const char *val);
+
+ @param _fn Pointer to the function to use on value change.
+ */
+ string_attrCB(fnPtrType _fn) { fnptr = _fn; }
+
+ /**
+ Event triggered when the value of the attribute,
+ for which this callback has been registered, changes.
+
+ Override this to implement your own behavior.
+ The default is to send the name of the attribute
+ to a function which you specify upon construction
+ of this object.
+
+ @param attr Attribute for which the value has changed.
+ */
+ virtual void onValueChange(Attribute *attr)
+ {
+ ASSERT(attr->getAttributeType() == AttributeType::STRING);
+ (*fnptr)(attr->getAttributeName());
+ }
+private:
+ fnPtrType fnptr;
+};
+
+#endif
diff --git a/Src/Wasabi/api/config/items/attrfloat.h b/Src/Wasabi/api/config/items/attrfloat.h
new file mode 100644
index 00000000..056f0c46
--- /dev/null
+++ b/Src/Wasabi/api/config/items/attrfloat.h
@@ -0,0 +1,52 @@
+#ifndef _ATTRFLOAT_H
+#define _ATTRFLOAT_H
+
+#include "attribute.h"
+
+// actually it's a double :)
+
+class _float : public Attribute {
+public:
+ /**
+ Optionally set the name and default value of
+ your configuration attribute during construction.
+
+ @param name Name of the configuration attribute.
+ @param default_val Default value.
+ */
+ _float(const wchar_t *name=NULL, double default_val=0.f) : Attribute(name) {
+ setValueAsDouble(default_val, true);
+ }
+
+ /**
+ Get the attribute type. This will return
+ a constant representing the attribute type.
+
+ These constants can be: BOOL, FLOAT, STRING and INT.
+
+ @see AttributeType
+ @ret The attribute type.
+ */
+ virtual int getAttributeType() { return AttributeType::FLOAT; }
+
+ /**
+ Get the configuration group to be used to represent
+ this attribute in the registry.
+
+ @ret Config group to be used.
+ */
+ virtual const wchar_t *getConfigGroup() { return L"studio.configgroup.float"; }
+
+ // convenience operators
+ /**
+ Get the value of the attribute.
+ */
+ operator double() { return getValueAsDouble(); }
+
+ /**
+ Set the value of the attribute.
+ */
+ double operator =(double newval) { return setValueAsDouble(newval) ? newval : getValueAsDouble(); }
+};
+
+#endif
diff --git a/Src/Wasabi/api/config/items/attrfn.h b/Src/Wasabi/api/config/items/attrfn.h
new file mode 100644
index 00000000..54f46df0
--- /dev/null
+++ b/Src/Wasabi/api/config/items/attrfn.h
@@ -0,0 +1,15 @@
+#ifndef _ATTRFN_H
+#define _ATTRFN_H
+
+#include "attrstr.h"
+
+class _filename : public _string {
+public:
+ _filename(const wchar_t *name, const wchar_t *default_val=L"")
+ : _string(name, default_val) { }
+
+ virtual int getAttributeType() { return AttributeType::FILENAME; }
+ virtual const wchar_t *getConfigGroup() { return L"studio.configgroup.filename"; }
+};
+
+#endif
diff --git a/Src/Wasabi/api/config/items/attrhandler.h b/Src/Wasabi/api/config/items/attrhandler.h
new file mode 100644
index 00000000..c2624f46
--- /dev/null
+++ b/Src/Wasabi/api/config/items/attrhandler.h
@@ -0,0 +1,129 @@
+//!## An object to multiplex the callbacks of multiple attributes.
+#ifndef _ATTRHANDLER_H
+#define _ATTRHANDLER_H
+
+// This class is meant to be subclassed. The methods you must provide
+// are given as pure virtuals. See ExampleAttrib for more details, and
+// an example subclass that you can copy for your own use.
+
+#include "attrcb.h"
+#include "attribs.h"
+#include <bfc/map.h>
+
+//
+// Forward References
+class WAComponentClient;
+class Attribute;
+
+
+//
+// Class Definition
+template <class TCallback>
+class AttrHandler {
+protected:
+ // Heh, oops. Can't have one AttrCallback handle lots of different attribs, anymore. I fix.
+ class AttrHandlerChild : public AttrCallback {
+ public:
+ AttrHandlerChild(AttrHandler *_parent) : AttrCallback() {
+ ASSERT(_parent != NULL);
+ recursion = 0;
+ callback = NULL;
+ parent = _parent;
+ }
+
+ // Here is where we split out the different value types
+ virtual void onValueChange(Attribute *attr) {
+ if (!recursion) {
+ // protect our programmers from stack overflow, please.
+ recursion = 1;
+ if ((callback != NULL) && (parent != NULL)) {
+ int id;
+ // find the id from the map (friendly)
+ int success = parent->attribmap.getItem(attr,&id);
+ if (success) {
+ // and send it to the proper handling function (poorman's RTTI)
+ switch (attr->getAttributeType()) {
+ case AttributeType::INT:
+ callback->onIntChange(id,*static_cast<_int *>(attr));
+ break;
+ case AttributeType::BOOL:
+ callback->onBoolChange(id, *static_cast<_bool *>(attr));
+ break;
+ case AttributeType::FLOAT:
+ callback->onFloatChange(id, *static_cast<_float *>(attr));
+ break;
+ case AttributeType::STRING:
+ callback->onStringChange(id, *static_cast<_string *>(attr));
+ break;
+ }
+ }
+ }
+ recursion = 0;
+ }
+ }
+
+ virtual void bindCallbackObj(TCallback *callbackobj) {
+ // Be advised, this may be null. That's okay, we test for it above.
+ callback = callbackobj;
+ }
+ private:
+ int recursion;
+ TCallback *callback;
+ AttrHandler *parent;
+ };
+
+public:
+ AttrHandler() {
+ component = NULL;
+ callback = NULL;
+ }
+
+ // Call this method to bind your component (in your component's constructor)
+ virtual void bindComponent(WAComponentClient *parentcomponent) {
+ component = parentcomponent;
+ }
+
+ // Call this method to bind your callback object (usually your window in its constructor)
+ virtual void bindCallbackObj(TCallback *callbackobj) {
+ // Bind ourselves.
+ callback = callbackobj;
+
+ // Then go through and rebind any children.
+ int i, num = attrchildren.getNumItems();
+ for (i = 0; i < num; i++) {
+ AttrHandlerChild *child = attrchildren.enumItem(i);
+ child->bindCallbackObj(callback);
+ }
+ }
+
+ // Call this method to register each attribute.
+ virtual void registerAttribute(Attribute *attr, int id) {
+ ASSERTPR(component != NULL, "BIND YOUR COMPONENT before registering Attributes to a Handler.");
+ // register the attrib with a child object as its callback
+ AttrHandlerChild *child = new AttrHandlerChild(this);
+ attrchildren.addItem(child);
+ component->registerAttribute(attr, child);
+ // and save its id mapping
+ attribmap.addItem(attr, id);
+ }
+
+#if 0
+ // Your callback object (probably your primary window class) must implement
+ // its own versions of these methods here. They will be called by the
+ // switch statement below.
+ virtual void onIntChange(int id, int *attr);
+ virtual void onBoolChange(int id, bool *attr);
+ virtual void onFloatChange(int id, double *attr);
+ virtual void onStringChange(int id, const char *attr);
+#endif
+
+
+private:
+ friend AttrHandlerChild;
+ TCallback *callback;
+ WAComponentClient *component;
+ Map< Attribute *, int > attribmap;
+ PtrList<AttrHandlerChild> attrchildren;
+};
+
+#endif // _ATTRHANDLER_H
diff --git a/Src/Wasabi/api/config/items/attribs.h b/Src/Wasabi/api/config/items/attribs.h
new file mode 100644
index 00000000..1e35f78b
--- /dev/null
+++ b/Src/Wasabi/api/config/items/attribs.h
@@ -0,0 +1,12 @@
+#ifndef _ATTRIBS_H
+#define _ATTRIBS_H
+
+// a convenience header to get all the attrib types in one whack
+
+#include "attrbool.h"
+#include "attrfloat.h"
+#include "attrint.h"
+#include "attrstr.h"
+#include "attrfn.h"
+
+#endif
diff --git a/Src/Wasabi/api/config/items/attribute.cpp b/Src/Wasabi/api/config/items/attribute.cpp
new file mode 100644
index 00000000..27b519b6
--- /dev/null
+++ b/Src/Wasabi/api/config/items/attribute.cpp
@@ -0,0 +1,131 @@
+#include <precomp.h>
+
+#include "attribute.h"
+#include <api/config/items/cfgitemi.h>
+
+
+Attribute::Attribute(const wchar_t *newname, const wchar_t *_desc) :
+ NamedW(newname), desc(_desc), cfgitemi(NULL), private_storage(NULL) { }
+
+Attribute::~Attribute() {
+ delete private_storage;
+}
+
+const wchar_t *Attribute::getAttributeName() {
+ return NamedW::getName();
+}
+
+const wchar_t *Attribute::getAttributeDesc() {
+ return desc;
+}
+
+int Attribute::getValueAsInt()
+{
+ wchar_t buf[1024]=L"";
+ getData(buf, 1024);
+ return WTOI(buf);
+}
+
+int Attribute::setValueAsInt(int newval, bool def)
+{
+ return setData(StringPrintfW(newval), def);
+}
+
+double Attribute::getValueAsDouble()
+{
+ wchar_t buf[1024] = {0};
+ getData(buf, 1024);
+ return WTOF(buf);
+}
+
+double Attribute::setValueAsDouble(double newval, bool def)
+{
+ return setData(StringPrintfW(newval), def);
+}
+
+int Attribute::getDataLen() {
+ if (private_storage != NULL)
+ return (int)private_storage->len()+1;
+
+ ASSERTPR(WASABI_API_CONFIG != NULL, "getDataLen() before API");
+ int r = WASABI_API_CONFIG->getStringPrivateLen(mkTag());
+ if (r < 0) {
+ r = (int)default_val.len()+1;
+ }
+ return r;
+}
+
+int Attribute::getData(wchar_t *data, int data_len)
+{
+ if (data == NULL || data_len < 0)
+ return 0;
+ if (private_storage != NULL)
+ {
+ if (private_storage->isempty())
+ {
+ if (data_len >= 1) {
+ *data = 0;
+ return 1;
+ }
+ return 0;
+ }
+ WCSCPYN(data, private_storage->getValue(), data_len);
+ return MIN((int)private_storage->len(), data_len);
+ }
+ ASSERTPR(WASABI_API_CONFIG != NULL, "can't get without api");
+ if (WASABI_API_CONFIG == NULL) return 0;
+ int r = WASABI_API_CONFIG->getStringPrivate(mkTag(), data, data_len, default_val.isempty() ? L"" : default_val.getValue());
+ return r;
+}
+
+int Attribute::setData(const wchar_t *data, bool def)
+{
+ if (def) { // setting default value
+ default_val = data;
+ return 1;
+ }
+ ASSERTPR(WASABI_API_CONFIG != NULL, "can't set data before api");
+ if (WASABI_API_CONFIG == NULL) return 0;
+
+ int r = setDataNoCB(data);
+ if (r && cfgitemi != NULL) cfgitemi->cfgitem_onAttribSetValue(this);
+ return r;
+}
+
+int Attribute::setDataNoCB(const wchar_t *data)
+{
+ if (private_storage != NULL) {
+ private_storage->setValue(data);
+ } else {
+ WASABI_API_CONFIG->setStringPrivate(mkTag(), data);
+ }
+ dependent_sendEvent(Attribute::depend_getClassGuid(), Event_DATACHANGE);
+ return 1;
+}
+
+void Attribute::setCfgItem(CfgItemI *item)
+{
+ delete private_storage; private_storage = NULL;
+ ASSERT(cfgitemi == NULL || item == NULL);
+ cfgitemi = item;
+ if (cfgitemi != NULL)
+ {
+ if (cfgitemi->cfgitem_usePrivateStorage())
+ private_storage = new StringW;
+ }
+}
+
+StringW Attribute::mkTag()
+{
+ StringW ret;
+ if (cfgitemi)
+ {
+ ret = cfgitemi->cfgitem_getPrefix();
+ }
+ ret.cat(getName());
+ return ret;
+}
+
+void Attribute::disconnect() {
+ setCfgItem(NULL);
+}
diff --git a/Src/Wasabi/api/config/items/attribute.h b/Src/Wasabi/api/config/items/attribute.h
new file mode 100644
index 00000000..c91e8065
--- /dev/null
+++ b/Src/Wasabi/api/config/items/attribute.h
@@ -0,0 +1,218 @@
+#ifndef _ATTRIBUTE_H
+#define _ATTRIBUTE_H
+
+#include <bfc/depend.h>
+#include <bfc/named.h>
+#include <bfc/common.h>
+#include <bfc/string/StringW.h>
+
+class CfgItemI;
+
+// lowercase types are reserved for official Nullsoft use
+// uppercase are 3rd-party defined
+namespace AttributeType {
+ /**
+ Attribute types.
+ */
+ enum {
+ NONE = 0,
+ INT = MK3CC('i','n','t'), // attrint.h
+ STRING = MK3CC('s','t','r'), // attrstr.h
+ BOOL = MK4CC('b','o','o','l'), // attrbool.h
+ FLOAT = MK4CC('f','l','o','t'), // attrfloat.h
+ FILENAME = MK2CC('f','n'), // attrfn.h
+ };
+};
+
+/**
+ Generic configuration attribute.
+
+ Configuration attributes enable you to store
+ uniquely identifiable values that get pushed
+ to a configuration file automatically upon shutdown
+ of any Wasabi application.
+
+ You shouldn't normally use this on
+ it's own, look at the CfgItemI class
+ instead.
+
+ @short Generic configuration attribute.
+ @ver 1.0
+ @author Nullsoft
+ @see _float
+ @see _int
+ @see _bool
+ @see _string
+ @see CfgItemI
+*/
+class NOVTABLE Attribute : public DependentI, private NamedW
+{
+public:
+ static const GUID *depend_getClassGuid() {
+ // {5AB601D4-1628-4604-808A-7ED899849BEB}
+ static const GUID ret =
+ { 0x5ab601d4, 0x1628, 0x4604, { 0x80, 0x8a, 0x7e, 0xd8, 0x99, 0x84, 0x9b, 0xeb } };
+ return &ret;
+ }
+protected:
+
+ /**
+ Optionally set the name and default value of
+ your configuration attribute during construction.
+
+ @param name Name of the configuration attribute.
+ @param default_val Default value.
+ */
+ Attribute(const wchar_t *name=NULL, const wchar_t *desc=NULL);
+
+public:
+ virtual ~Attribute();
+
+ /**
+ Set the name of the configuration
+ attribute.
+
+ @param newname Name of the attribute.
+ */
+ void setName(const wchar_t *newname);
+
+ /**
+ Get the name of the configuration
+ attribute.
+
+ @ret Name of the attribute.
+ */
+ const wchar_t *getAttributeName();
+
+ /**
+ Get the attribute's description.
+
+ @ret Attribute's description.
+ */
+ const wchar_t *getAttributeDesc();
+
+ /**
+ Get the attribute type. Override
+ this for your custom attribute type.
+
+ @ret Attribute type.
+ */
+ virtual int getAttributeType()=0; // override me
+
+ /**
+ Get the configuration group to be used to represent
+ this attribute in the registry.
+
+ This is only called if the kernel doesn't have a default
+ config group set for your type already.
+
+ @ret Config group to be used.
+ */
+ virtual const wchar_t *getConfigGroup() { return NULL; } // override me
+
+ /**
+ Get the attribute's value as signed integer.
+
+ @ret Attribute value, as a signed integer.
+ */
+ int getValueAsInt();
+
+ /**
+ Set the attribute's value with a signed integer while
+ also being able to replace the default value previously
+ set.
+
+ @param newval Attribute's new value.
+ @param def true, replace the current default value; false, leave the default value unchanged;
+ */
+ int setValueAsInt(int newval, bool def=false);
+
+ /**
+ Get the attribute's value as signed double.
+
+ @ret Attribute value, as a signed double.
+ */
+ double getValueAsDouble();
+
+ /**
+ Set the attribute's value with a signed double while
+ also being able to replace the default value previously
+ set.
+
+ @param newval Attribute's new value.
+ @param def true, replace the current default value; false, leave the default value unchanged;
+ */
+ double setValueAsDouble(double newval, bool def=false);
+
+ /**
+ Get the length of the attribute's value (data)
+ in bytes.
+
+ @ret Attribute value (data) length, in bytes.
+ */
+ int getDataLen();
+
+ /**
+ Get the attribute's raw data.
+
+ This will return the data the attribute is storing
+ in a char buffer you hand to it.
+
+ @ret Attribute value, as a signed double.
+ @param data Pointer to a char buffer.
+ @param data_len The maximum amount of bytes the char buffer can hold.
+ */
+ int getData(wchar_t *data, int data_len);
+
+ /**
+ Set the attribute's value with a zero terminated string. Also
+ enables you to replace the default value previously
+ set.
+
+ @param newval Attribute's new value.
+ @param def true, replace the current default value; false, leave the default value unchanged;
+ */
+ int setData(const wchar_t *data, bool def=false);
+
+ void disconnect();
+
+ enum {
+ Event_DATACHANGE=100,
+ };
+protected:
+ friend class CfgItemI;
+
+ /**
+ Set the attribute's value without causing
+ a callback.
+
+ @ret 1.
+ @param data Attribute's new value.
+ */
+ int setDataNoCB(const wchar_t *data);
+
+ /**
+ Set the configuration item associated with this
+ attribute.
+ */
+ void setCfgItem(CfgItemI *item);
+
+ StringW mkTag();
+
+private:
+ StringW desc;
+ StringW default_val, *private_storage;
+ CfgItemI *cfgitemi;
+};
+
+#define ATTR_PERM_READ 1
+#define ATTR_PERM_WRITE 2
+
+#define ATTR_PERM_ALL (~0)
+
+// render hints for getRenderHint
+enum {
+ ATTR_RENDER_HINT_INT_CHECKMARK
+};
+
+#endif
diff --git a/Src/Wasabi/api/config/items/attrint.h b/Src/Wasabi/api/config/items/attrint.h
new file mode 100644
index 00000000..c63af8ce
--- /dev/null
+++ b/Src/Wasabi/api/config/items/attrint.h
@@ -0,0 +1,65 @@
+#ifndef _ATTRINT_H
+#define _ATTRINT_H
+
+#include "attribute.h"
+
+// inherit from this one, or just use it
+/**
+ Boolean configuration attributes have two values, true or false.
+ They can be used like any other config item.
+
+ @short Integer configuration attribute.
+ @ver 1.0
+ @author Nullsoft
+ @see CfgItemI
+ @see _bool
+ @see _string
+ @see _float
+*/
+class _int : public Attribute {
+public:
+ /**
+ Optionally set the name and default value of
+ your configuration attribute during construction.
+
+ @param name Name of the configuration attribute.
+ @param default_val Default value.
+ */
+ _int(const wchar_t *name=NULL, int default_val=0) : Attribute(name) {
+ setValueAsInt(default_val, true);
+ }
+
+ // from AttributeI
+ /**
+ Get the attribute type. This will return
+ a constant representing the attribute type.
+
+ These constants can be: BOOL, FLOAT, STRING and INT.
+
+ @see AttributeType
+ @ret The attribute type.
+ */
+ virtual int getAttributeType() { return AttributeType::INT; }
+
+ /**
+ Get the configuration group to be used to represent
+ this attribute in the registry.
+
+ @ret Config group to be used.
+ */
+ virtual const wchar_t *getConfigGroup() { return L"studio.configgroup.int"; }
+// virtual int getPermissions();
+
+ // convenience operators
+ /**
+ Get the value of the attribute.
+ */
+ operator int() { return getValueAsInt(); }
+
+ /**
+ Set the value of the attribute.
+ */
+ int operator =(int newval) { return setValueAsInt(newval) ? newval : getValueAsInt(); }
+};
+
+#endif
diff --git a/Src/Wasabi/api/config/items/attrstr.cpp b/Src/Wasabi/api/config/items/attrstr.cpp
new file mode 100644
index 00000000..1209e2f3
--- /dev/null
+++ b/Src/Wasabi/api/config/items/attrstr.cpp
@@ -0,0 +1,14 @@
+#include <precomp.h>
+#include "attrstr.h"
+
+#include <bfc/memblock.h>
+
+const wchar_t *_string::getValue()
+{
+ int l = getDataLen();
+ if (l <= 0) return L"";
+ MemBlock<wchar_t> mb(l+2);
+ getData(mb.getMemory(), l+2);
+ returnval = mb;
+ return returnval;
+}
diff --git a/Src/Wasabi/api/config/items/attrstr.h b/Src/Wasabi/api/config/items/attrstr.h
new file mode 100644
index 00000000..cde81a64
--- /dev/null
+++ b/Src/Wasabi/api/config/items/attrstr.h
@@ -0,0 +1,85 @@
+#ifndef _ATTRSTR_H
+#define _ATTRSTR_H
+
+#include "attribute.h"
+
+#include <bfc/string/bfcstring.h>
+#include <bfc/common.h>
+
+/**
+ String configuration attributes, can have any string value
+ of any length. They can be used like any other config item.
+
+ @short String configuration attribute.
+ @ver 1.0
+ @author Nullsoft
+ @see _int
+ @see _bool
+ @see _float
+*/
+class _string : public Attribute {
+public:
+ /**
+ Optionally set the name and default value of
+ your configuration attribute during construction.
+
+ @param name
+ @param default_val
+ */
+ _string(const wchar_t *name=NULL, const wchar_t *default_val=NULL)
+ : Attribute(name) {
+ setData(default_val, true);
+ }
+
+ /**
+ Get the attribute type. This will return
+ a constant representing the attribute type.
+
+ These constants can be: BOOL, FLOAT, STRING and INT.
+
+ @see AttributeType
+ @ret The attribute type.
+ */
+ virtual int getAttributeType() { return AttributeType::STRING; }
+
+ /**
+ Get the configuration group to be used to represent
+ this attribute in the registry.
+
+ @ret Config group to be used.
+ */
+ virtual const wchar_t *getConfigGroup() { return L"studio.configgroup.string"; }
+
+//CUT virtual int getPermissions() { return ATTR_PERM_ALL; }
+
+ /**
+ Get the value of the attribute.
+
+ @ret The value of the attribute
+ */
+ const wchar_t *getValue();
+
+ /**
+ Set the value of the attribute.
+
+ @param val The value you want to set.
+ @ret 1, success; 0, failure;
+ */
+ int setValue(const wchar_t *val) { return setData(val); }
+
+ // convenience operators
+ /**
+ Get the value of the attribute.
+ */
+ operator const wchar_t *() { return getValue(); }
+
+ /**
+ Set the value of the attribute.
+ */
+ const wchar_t *operator =(const wchar_t *newval) { return setValue(newval) ? newval : getValue(); }
+
+private:
+ StringW returnval;
+};
+
+#endif
diff --git a/Src/Wasabi/api/config/items/cfgitem.h b/Src/Wasabi/api/config/items/cfgitem.h
new file mode 100644
index 00000000..560198f0
--- /dev/null
+++ b/Src/Wasabi/api/config/items/cfgitem.h
@@ -0,0 +1,233 @@
+#ifndef _CFGITEM_H
+#define _CFGITEM_H
+
+#include <bfc/dispatch.h>
+#include <bfc/platform/types.h>
+#include <bfc/platform/guid.h>
+#include <bfc/wasabi_std.h>
+
+class ifc_dependent;
+class ifc_window;
+
+/* A CfgItem is a named, possibly unique (if GUID is set) interface to
+an object with 0 or more named attributes. If offers api_dependent-based callbacks
+when those attributes change.
+*/
+
+// abstract base class presented to the world
+/**
+
+
+ @short Base Config Item
+ @ver 1.0
+ @author Nullsoft
+ @see CfgItemI
+*/
+class NOVTABLE CfgItem : public Dispatchable
+{
+public:
+ /**
+ */
+ static const GUID *depend_getClassGuid() {
+ // {B4BE480E-2005-457c-A445-294F12387E74}
+ static const GUID ret =
+ { 0xb4be480e, 0x2005, 0x457c, { 0xa4, 0x45, 0x29, 0x4f, 0x12, 0x38, 0x7e, 0x74 } };
+ return &ret;
+ }
+
+ const wchar_t *getName();
+
+ /**
+ Get the GUID
+ */
+ GUID getGuid();
+
+ /**
+ Get the number of attributes
+ associated with this configuration
+ item.
+
+ @ret Number of attributes for this configuration item.
+ */
+ int getNumAttributes();
+
+ const wchar_t *enumAttribute(int n);
+
+ // so people can watch you for changes
+ ifc_dependent *getDependencyPtr();
+
+ // return * to your config xml if you want to specify it
+ const wchar_t *getConfigXML();
+ void onCfgGroupCreate(ifc_window *cfggroup, const wchar_t *attrname=NULL);
+ void onCfgGroupDelete(ifc_window *cfggroup);
+
+ // if you have child cfgitems, list them here
+ int getNumChildren();
+ CfgItem *enumChild(int n);
+ GUID getParentGuid();
+
+ void onRegister(); // kernel calls these
+ void onDeregister();
+
+ int getAttributeType(const wchar_t *name);
+ const wchar_t *getAttributeConfigGroup(const wchar_t *name);
+ int getDataLen(const wchar_t *name);
+ int getData(const wchar_t *name, wchar_t *data, int data_len);
+ int setData(const wchar_t *name, const wchar_t *data);
+
+ int getDataAsInt(const wchar_t *name, int def_val=0)
+ {
+ wchar_t buf[256];
+ if (getData(name, buf, sizeof(buf))==-1) return def_val;
+ return WTOI(buf);
+ }
+ void setDataAsInt(const wchar_t *name, int val) {
+ wchar_t buf[256];
+ WCSNPRINTF(buf, 256, L"%d", val); // this uses SPRINTF ON PURPOSE, motherfucker BU
+ setData(name, buf);
+ }
+
+ double getDataAsFloat(const wchar_t *name, double def_val=0) {
+ wchar_t buf[256];
+ if (getData(name, buf, sizeof(buf))==-1) return def_val;
+ return WTOF(buf);
+ }
+ void setDataAsFloat(const wchar_t *name, double val) {
+ wchar_t buf[256];
+ WCSNPRINTF(buf, 256, L"%f", val); // this uses SPRINTF ON PURPOSE, motherfucker BU
+ setData(name, buf);
+ }
+
+ int addAttribute(const wchar_t *name, const wchar_t *defval);
+ int delAttribute(const wchar_t *name);
+
+ enum {
+ Event_ATTRIBUTE_ADDED=100, // ptr is name of attrib
+ Event_ATTRIBUTE_REMOVED=200,// ptr is name of attrib
+ Event_ATTRIBUTE_CHANGED=300, // ptr is name of attrib
+ Event_NAMECHANGE=400,
+ };
+
+protected:
+ enum {
+ CFGITEM_GETNAME=100,
+ CFGITEM_GETGUID=110,
+ CFGITEM_GETNUMATTRIBUTES=200,
+ CFGITEM_ENUMATTRIBUTE=210,
+ CFGITEM_GETDEPENDENCYPTR=300,
+ CFGITEM_GETNUMCHILDREN=400,
+ CFGITEM_ENUMCHILD=410,
+ CFGITEM_GETPARENTGUID=420,
+ CFGITEM_ONREGISTER=500,
+ CFGITEM_ONDEREGISTER=510,
+ CFGITEM_GETCONFIGXML=600,
+ CFGITEM_ONCFGGROUPCREATE=610,
+ CFGITEM_ONCFGGROUPDELETE=620,
+ CFGITEM_GETATTRIBUTETYPE=700,
+ CFGITEM_GETATTRIBUTECONFIGGROUP=710,
+ CFGITEM_GETDATALEN=800,
+ CFGITEM_GETDATA=810,
+ CFGITEM_SETDATA=820,
+ CFGITEM_ADDATTRIB=830,
+ CFGITEM_DELATTRIB=840,
+ };
+};
+
+inline const wchar_t *CfgItem::getName() {
+ return _call(CFGITEM_GETNAME, L"");
+}
+
+inline GUID CfgItem::getGuid() {
+ return _call(CFGITEM_GETGUID, INVALID_GUID);
+}
+
+inline int CfgItem::getNumAttributes() {
+ return _call(CFGITEM_GETNUMATTRIBUTES, 0);
+}
+
+inline const wchar_t *CfgItem::enumAttribute(int n) {
+ return _call(CFGITEM_ENUMATTRIBUTE, (const wchar_t *)NULL, n);
+}
+
+inline ifc_dependent *CfgItem::getDependencyPtr() {
+ return _call(CFGITEM_GETDEPENDENCYPTR, (ifc_dependent*)NULL);
+}
+
+inline const wchar_t *CfgItem::getConfigXML() {
+ return _call(CFGITEM_GETCONFIGXML, (const wchar_t*)NULL);
+}
+
+inline void CfgItem::onCfgGroupCreate(ifc_window *cfggroup, const wchar_t *attrname) {
+ _voidcall(CFGITEM_ONCFGGROUPCREATE, cfggroup, attrname);
+}
+
+inline void CfgItem::onCfgGroupDelete(ifc_window *cfggroup) {
+ _voidcall(CFGITEM_ONCFGGROUPDELETE, cfggroup);
+}
+
+inline int CfgItem::getNumChildren() {
+ return _call(CFGITEM_GETNUMCHILDREN, 0);
+}
+
+inline CfgItem *CfgItem::enumChild(int n) {
+ return _call(CFGITEM_ENUMCHILD, (CfgItem*)NULL, n);
+}
+
+inline
+GUID CfgItem::getParentGuid() {
+ return _call(CFGITEM_GETPARENTGUID, INVALID_GUID);
+}
+
+inline void CfgItem::onRegister() { _voidcall(CFGITEM_ONREGISTER); }
+inline void CfgItem::onDeregister() { _voidcall(CFGITEM_ONDEREGISTER); }
+
+inline
+int CfgItem::getAttributeType(const wchar_t *name) {
+ return _call(CFGITEM_GETATTRIBUTETYPE, 0, name);
+}
+
+inline
+const wchar_t *CfgItem::getAttributeConfigGroup(const wchar_t *name) {
+ return _call(CFGITEM_GETATTRIBUTECONFIGGROUP, (const wchar_t *)NULL, name);
+}
+
+inline
+int CfgItem::getDataLen(const wchar_t *name) {
+ return _call(CFGITEM_GETDATALEN, -1, name);
+}
+
+inline
+int CfgItem::getData(const wchar_t *name, wchar_t *data, int data_len) {
+ return _call(CFGITEM_GETDATA, -1, name, data, data_len);
+}
+
+inline
+int CfgItem::setData(const wchar_t *name, const wchar_t *data) {
+ return _call(CFGITEM_SETDATA, -1, name, data);
+}
+
+inline
+int CfgItem::addAttribute(const wchar_t *name, const wchar_t *defval) {
+ return _call(CFGITEM_ADDATTRIB, 0, name, defval);
+}
+
+inline
+int CfgItem::delAttribute(const wchar_t *name) {
+ return _call(CFGITEM_DELATTRIB, 0, name);
+}
+
+inline int _intVal(CfgItem *cfgitem, const wchar_t *name, int def_val=0) {
+ if (cfgitem == NULL) return def_val;
+ return cfgitem->getDataAsInt(name, def_val);
+}
+
+#define _int_getValue _intVal
+
+//CUT kill these
+inline void _int_setValue(CfgItem *cfgitem, const wchar_t *name, int val) {
+ cfgitem->setDataAsInt(name, val);
+}
+// CfgItemI is in cfgitemi.h if you need it
+
+
+#endif
diff --git a/Src/Wasabi/api/config/items/cfgitemi.cpp b/Src/Wasabi/api/config/items/cfgitemi.cpp
new file mode 100644
index 00000000..b8734031
--- /dev/null
+++ b/Src/Wasabi/api/config/items/cfgitemi.cpp
@@ -0,0 +1,274 @@
+#include <precomp.h>
+
+#include "cfgitemi.h"
+#include <api/config/items/attrcb.h>
+#include <api/config/items/attribs.h>
+
+#include <bfc/wasabi_std.h>
+#include <bfc/memblock.h>
+
+CfgItemI::CfgItemI(const wchar_t *name, GUID guid)
+:NamedW(name), myguid(guid), parent_guid(INVALID_GUID) { }
+
+CfgItemI::~CfgItemI()
+{
+ deregisterAll();
+}
+
+const wchar_t *CfgItemI::cfgitem_getName()
+{
+ return NamedW::getName();
+}
+
+GUID CfgItemI::cfgitem_getGuid()
+{
+ return myguid;
+}
+
+void CfgItemI::cfgitem_setPrefix(const wchar_t *_prefix)
+{
+ prefix = _prefix;
+}
+
+const wchar_t *CfgItemI::cfgitem_getPrefix()
+{
+ return prefix.c_str();
+}
+
+int CfgItemI::cfgitem_getNumAttributes()
+{
+ return attributes.getNumItems();
+}
+
+const wchar_t *CfgItemI::cfgitem_enumAttribute(int n)
+{
+ Attribute *attr = attributes[n];
+ if (attr) return attr->getAttributeName();
+ return NULL;
+}
+
+const wchar_t *CfgItemI::cfgitem_getConfigXML()
+{
+ return cfgxml.c_str();
+}
+
+int CfgItemI::cfgitem_getNumChildren()
+{
+ return children.getNumItems();
+}
+
+CfgItem *CfgItemI::cfgitem_enumChild(int n)
+{
+ return children[n];
+}
+
+GUID CfgItemI::cfgitem_getParentGuid()
+{
+ return parent_guid;
+}
+
+void CfgItemI::cfgitem_onRegister()
+{
+ foreach(children)
+ WASABI_API_CONFIG->config_registerCfgItem(children.getfor());
+ endfor
+}
+void CfgItemI::cfgitem_onDeregister()
+{
+ foreach(children)
+ WASABI_API_CONFIG->config_deregisterCfgItem(children.getfor());
+ endfor
+}
+
+Attribute *CfgItemI::getAttributeByName(const wchar_t *name)
+{
+ Attribute *attr;
+ foreach(attributes)
+ attr = attributes.getfor();
+ if (!WCSICMP(name, attr->getAttributeName())) return attr;
+ endfor
+ return NULL;
+}
+
+int CfgItemI::cfgitem_getAttributeType(const wchar_t *name)
+{
+ Attribute *attr = getAttributeByName(name);
+ if (attr == NULL) return AttributeType::NONE;
+ return attr->getAttributeType();
+}
+
+const wchar_t *CfgItemI::cfgitem_getAttributeConfigGroup(const wchar_t *name)
+{
+ Attribute *attr = getAttributeByName(name);
+ if (attr == NULL) return NULL;
+ return attr->getConfigGroup();
+}
+
+int CfgItemI::cfgitem_getDataLen(const wchar_t *name)
+{
+ Attribute *attr = getAttributeByName(name);
+ if (attr == NULL) return -1;
+ return attr->getDataLen();
+}
+
+int CfgItemI::cfgitem_getData(const wchar_t *name, wchar_t *data, int data_len)
+{
+ Attribute *attr = getAttributeByName(name);
+ if (attr == NULL) return -1;
+ return attr->getData(data, data_len);
+}
+
+int CfgItemI::cfgitem_setData(const wchar_t *name, const wchar_t *data)
+{
+ Attribute *attr = getAttributeByName(name);
+ if (attr == NULL) return -1;
+ int ret = attr->setDataNoCB(data);
+ if (ret) cfgitem_onAttribSetValue(attr);
+ return ret;
+}
+
+int CfgItemI::cfgitem_onAttribSetValue(Attribute *attr)
+{
+ // notify dependency watchers that an attribute changed
+ dependent_sendEvent(CfgItem::depend_getClassGuid(), Event_ATTRIBUTE_CHANGED, 0, (void*)attr->getAttributeName());
+
+ //for (int i = 0; ; i++)
+ //{
+ // AttrCallback *acb;
+ // if (!callbacks.multiGetItem(attr, i, &acb))
+ // break;
+ //
+ // acb->onValueChange(attr);
+ //}
+ auto elements = callbacks.equal_range(attr);
+ for (auto& it = elements.first; it != elements.second; ++it)
+ {
+ AttrCallback* acb = it->second;
+ if (acb)
+ {
+ acb->onValueChange(attr);
+ }
+ }
+
+ return 0;
+}
+
+void CfgItemI::cfgitem_setGUID(GUID guid)
+{
+ myguid = guid;
+}
+
+int CfgItemI::setName(const wchar_t *name)
+{
+ NamedW::setName(name);
+ // notify dependency watchers that name changed?
+ dependent_sendEvent(CfgItem::depend_getClassGuid(), Event_NAMECHANGE);
+ return 1;
+}
+
+int CfgItemI::registerAttribute(Attribute *attr, AttrCallback *acb)
+{
+ if (attributes.haveItem(attr)) return 0;
+ int ret = attributes.addItem(attr) != NULL;
+ if (!ret) return ret;
+
+ attr->setCfgItem(this);
+
+ // set optional callback
+ if (acb != NULL)
+ {
+ addCallback(attr, acb);
+ }
+
+ // notify dependency watchers of new attribute
+ dependent_sendEvent(CfgItem::depend_getClassGuid(), Event_ATTRIBUTE_ADDED, 0, (void*)attr->getAttributeName());
+
+ return ret;
+}
+
+int CfgItemI::deregisterAttribute(Attribute *attr)
+{
+ if (!attributes.haveItem(attr)) return 0;
+ int ret = attributes.removeItem(attr);
+ // notify dependency watchers of attribute going away
+ dependent_sendEvent(CfgItem::depend_getClassGuid(), Event_ATTRIBUTE_REMOVED, 0, (void*)attr->getAttributeName());
+
+ // remove callbacks
+ //callbacks.multiDelAllForItem(attr, TRUE);
+ auto elements = callbacks.equal_range(attr);
+ for (auto& it = elements.first; it != elements.second; ++it)
+ {
+ AttrCallback* acb = it->second;
+ if (acb)
+ {
+ delete acb;
+ }
+ }
+ callbacks.erase(attr);
+
+
+ attr->disconnect();
+
+ return ret;
+}
+
+void CfgItemI::addCallback(Attribute *attr, AttrCallback *acb)
+{
+ ASSERT(attr != NULL);
+ ASSERT(acb != NULL);
+ //callbacks.multiAddItem(attr, acb);
+ callbacks.insert({ attr, acb });
+}
+
+void CfgItemI::deregisterAll()
+{
+ foreach(children)
+ children.getfor()->deregisterAll();
+ endfor
+ while (attributes.getNumItems()) deregisterAttribute(attributes[0]);
+}
+
+void CfgItemI::addChildItem(CfgItemI *child)
+{
+ ASSERT(child != NULL);
+ if (!children.haveItem(child))
+ {
+ children.addItem(child);
+ child->setParentGuid(myguid);
+ }
+}
+
+void CfgItemI::setCfgXml(const wchar_t *groupname)
+{
+ cfgxml = groupname;
+}
+
+void CfgItemI::setParentGuid(GUID guid)
+{
+ parent_guid = guid;
+}
+
+void *CfgItemI::dependent_getInterface(const GUID *classguid)
+{
+ HANDLEGETINTERFACE(CfgItem);
+ return NULL;
+}
+
+int CfgItemI::cfgitem_addAttribute(const wchar_t *name, const wchar_t *defval)
+{
+ if (getAttributeByName(name)) return 0;
+ registerAttribute(newattribs.addItem(new _string(name, defval)));
+ return 1;
+}
+
+int CfgItemI::cfgitem_delAttribute(const wchar_t *name)
+{
+ Attribute *attr = getAttributeByName(name);
+ if (!newattribs.haveItem(attr)) return 0;
+ deregisterAttribute(attr);
+ delete attr;
+ newattribs.removeItem(attr);
+ return 1;
+}
+
+
diff --git a/Src/Wasabi/api/config/items/cfgitemi.h b/Src/Wasabi/api/config/items/cfgitemi.h
new file mode 100644
index 00000000..7824abf5
--- /dev/null
+++ b/Src/Wasabi/api/config/items/cfgitemi.h
@@ -0,0 +1,158 @@
+#ifndef _CFGITEMI_H
+#define _CFGITEMI_H
+
+#include "cfgitemx.h"
+
+#include <bfc/named.h>
+#include <bfc/ptrlist.h>
+#include <bfc/depend.h>
+
+#include <map>
+#include <string>
+
+class AttrCallback;
+class Attribute;
+
+// this is the one you inherit from/use
+/**
+
+ @short Configuration Item
+ @ver 1.0
+ @author Nullsoft
+ @see Attribute
+ @see _bool
+ @see _int
+ @see _float
+ @see _string
+*/
+class CfgItemI : public CfgItemX, public DependentI, private NamedW
+{
+public:
+ /**
+ Optionally sets the name and the GUID of the
+ configuration item if they are specified
+ upon creation of the object.
+
+ @param name Name of the configuration item.
+ @param guid GUID of the configuration item.
+ */
+ CfgItemI(const wchar_t *name=NULL, GUID guid=INVALID_GUID);
+
+ /**
+ Does nothing.
+ */
+ virtual ~CfgItemI();
+
+ /**
+ Get the name of the configuration item.
+
+ @ret Name of the configuration item.
+ */
+ const wchar_t *cfgitem_getName();
+
+ /**
+ Get the GUID of the configuration item.
+
+ @ret GUID of the configuration item.
+ */
+ GUID cfgitem_getGuid();
+
+ /**
+ Sets the prefix to be prepended in the config file for all attributes
+ of this item.
+
+ @see cfgitem_getPrefix
+ @param prefix The prefix.
+ */
+ void cfgitem_setPrefix(const wchar_t *prefix);
+/**
+ Gets the config prefix, if any was set.
+
+ @see cfgitem_setPrefix
+ @ret Pointer to the config prefix.
+*/
+ const wchar_t *cfgitem_getPrefix();
+
+ /**
+ Get the number of attributes registered
+ to this configuration item.
+
+ @ret Number of attributes.
+ */
+ int cfgitem_getNumAttributes();
+
+ /**
+ Enumerate the attributes registered
+ with this configuration item.
+
+ @ret
+ */
+ const wchar_t *cfgitem_enumAttribute(int n);
+
+ const wchar_t *cfgitem_getConfigXML();
+ virtual void cfgitem_onCfgGroupCreate(ifc_window *cfggroup, const wchar_t *attrname) {}
+ virtual void cfgitem_onCfgGroupDelete(ifc_window *cfggroup) {}
+
+ virtual int cfgitem_getNumChildren();
+ virtual CfgItem *cfgitem_enumChild(int n);
+ virtual GUID cfgitem_getParentGuid();
+
+ virtual void cfgitem_onRegister();
+ virtual void cfgitem_onDeregister();
+
+ int cfgitem_getAttributeType(const wchar_t *name);
+ const wchar_t *cfgitem_getAttributeConfigGroup(const wchar_t *name);
+ int cfgitem_getDataLen(const wchar_t *name);
+ int cfgitem_getData(const wchar_t *name, wchar_t *data, int data_len);
+ int cfgitem_setData(const wchar_t *name, const wchar_t *data);
+
+ // override these to catch notifications from attribs, call down
+ virtual int cfgitem_onAttribSetValue(Attribute *attr);
+
+ virtual int cfgitem_usePrivateStorage() { return 0; } //override and return 1 to keep stuff out of system settings
+
+protected:
+ void cfgitem_setGUID(GUID guid);
+
+public:
+ int setName(const wchar_t *name);
+ int registerAttribute(Attribute *attr, AttrCallback *acb=NULL);
+ // does not call delete on the attribute
+ int deregisterAttribute(Attribute *attr);
+ void deregisterAll();
+
+ void addCallback(Attribute *attr, AttrCallback *acb);
+
+ int cfgitem_addAttribute(const wchar_t *name, const wchar_t *defval);
+ int cfgitem_delAttribute(const wchar_t *name);
+
+protected:
+
+ // derived classes can override this to catch name changes
+ virtual void cfgitem_onSetName() { }
+
+ Attribute *getAttributeByName(const wchar_t *name);
+
+ void addChildItem(CfgItemI *child);
+
+ void setCfgXml(const wchar_t *groupname);
+
+ void setParentGuid(GUID guid);
+
+private:
+ api_dependent *cfgitem_getDependencyPtr() { return this; };
+ virtual void *dependent_getInterface(const GUID *classguid);
+
+ // from Named
+ virtual void onSetName() { cfgitem_onSetName(); }
+
+ std::wstring prefix;
+ PtrList<Attribute> attributes;
+ std::multimap<Attribute*, AttrCallback*> callbacks; //CUT
+ PtrList<CfgItemI> children;
+ std::wstring cfgxml;
+ GUID myguid, parent_guid;
+ PtrList<Attribute> newattribs;
+};
+
+#endif
diff --git a/Src/Wasabi/api/config/items/cfgitemx.cpp b/Src/Wasabi/api/config/items/cfgitemx.cpp
new file mode 100644
index 00000000..b656dfc9
--- /dev/null
+++ b/Src/Wasabi/api/config/items/cfgitemx.cpp
@@ -0,0 +1,27 @@
+#include <precomp.h>
+#include "cfgitemx.h"
+
+#define CBCLASS CfgItemX
+START_DISPATCH
+ CB(CFGITEM_GETNAME, cfgitem_getName);
+ CB(CFGITEM_GETGUID, cfgitem_getGuid);
+ CB(CFGITEM_GETNUMATTRIBUTES, cfgitem_getNumAttributes);
+ CB(CFGITEM_ENUMATTRIBUTE, cfgitem_enumAttribute);
+ CB(CFGITEM_GETCONFIGXML, cfgitem_getConfigXML);
+ VCB(CFGITEM_ONCFGGROUPCREATE, cfgitem_onCfgGroupCreate);
+ VCB(CFGITEM_ONCFGGROUPDELETE, cfgitem_onCfgGroupDelete);
+ CB(CFGITEM_GETNUMCHILDREN, cfgitem_getNumChildren);
+ CB(CFGITEM_ENUMCHILD, cfgitem_enumChild);
+ CB(CFGITEM_GETPARENTGUID, cfgitem_getParentGuid);
+ VCB(CFGITEM_ONREGISTER, cfgitem_onRegister);
+ VCB(CFGITEM_ONDEREGISTER, cfgitem_onDeregister);
+ CB(CFGITEM_GETATTRIBUTETYPE, cfgitem_getAttributeType);
+ CB(CFGITEM_GETATTRIBUTECONFIGGROUP, cfgitem_getAttributeConfigGroup);
+ CB(CFGITEM_GETDATALEN, cfgitem_getDataLen);
+ CB(CFGITEM_GETDATA, cfgitem_getData);
+ CB(CFGITEM_SETDATA, cfgitem_setData);
+ CB(CFGITEM_GETDEPENDENCYPTR, cfgitem_getDependencyPtr);
+ CB(CFGITEM_ADDATTRIB, cfgitem_addAttribute);
+ CB(CFGITEM_DELATTRIB, cfgitem_delAttribute);
+END_DISPATCH
+#undef CBCLASS \ No newline at end of file
diff --git a/Src/Wasabi/api/config/items/cfgitemx.h b/Src/Wasabi/api/config/items/cfgitemx.h
new file mode 100644
index 00000000..6d5a9408
--- /dev/null
+++ b/Src/Wasabi/api/config/items/cfgitemx.h
@@ -0,0 +1,42 @@
+#ifndef NULLSOFT_WASABI_CFGITEMX_H
+#define NULLSOFT_WASABI_CFGITEMX_H
+
+#include "cfgitem.h"
+
+class CfgItemX : public CfgItem
+{
+public:
+ virtual ~CfgItemX() {}
+ virtual const wchar_t *cfgitem_getName()=0;
+ virtual GUID cfgitem_getGuid()=0;
+ virtual int cfgitem_getNumAttributes()=0;
+ virtual const wchar_t *cfgitem_enumAttribute(int n)=0;
+ virtual const wchar_t *cfgitem_getConfigXML()=0;
+ virtual void cfgitem_onCfgGroupCreate(ifc_window *cfggroup, const wchar_t *attrname)=0;
+ virtual void cfgitem_onCfgGroupDelete(ifc_window *cfggroup)=0;
+
+ virtual int cfgitem_getNumChildren()=0;
+ virtual CfgItem *cfgitem_enumChild(int n)=0;
+ virtual GUID cfgitem_getParentGuid()=0;
+
+ virtual void cfgitem_onRegister()=0;
+ virtual void cfgitem_onDeregister()=0;
+
+ virtual int cfgitem_getAttributeType(const wchar_t *name)=0;
+ virtual const wchar_t *cfgitem_getAttributeConfigGroup(const wchar_t *name)=0;
+
+ virtual int cfgitem_getDataLen(const wchar_t *name)=0;
+ virtual int cfgitem_getData(const wchar_t *name, wchar_t *data, int data_len)=0;
+ virtual int cfgitem_setData(const wchar_t *name, const wchar_t *data)=0;
+ virtual ifc_dependent *cfgitem_getDependencyPtr()=0;
+ virtual int cfgitem_delAttribute(const wchar_t *name)=0;
+ virtual int cfgitem_addAttribute(const wchar_t *name, const wchar_t *defval)=0;
+
+protected:
+ RECVS_DISPATCH;
+
+
+};
+
+
+#endif \ No newline at end of file
diff --git a/Src/Wasabi/api/config/items/intarray.cpp b/Src/Wasabi/api/config/items/intarray.cpp
new file mode 100644
index 00000000..c6ba4676
--- /dev/null
+++ b/Src/Wasabi/api/config/items/intarray.cpp
@@ -0,0 +1,49 @@
+#include <precomp.h>
+
+#include "intarray.h"
+
+
+enum { MAX_ARRAY=8 };
+
+int IntArray::read(const wchar_t *name, int *x1, int *x2, int *x3, int *x4, int *x5, int *x6, int *x7, int *x8) {
+ PtrList<int> list;
+ if (x1) { list.addItem(x1); }
+ if (x2) { list.addItem(x2); }
+ if (x3) { list.addItem(x3); }
+ if (x4) { list.addItem(x4); }
+ if (x5) { list.addItem(x5); }
+ if (x6) { list.addItem(x6); }
+ if (x7) { list.addItem(x7); }
+ if (x8) { list.addItem(x8); }
+ ASSERT(list.getNumItems() >= 1);
+
+ int array[MAX_ARRAY]; // gcc rules, msvc drools
+ for (int i = 0; i < list.getNumItems(); i++) {
+ if (list[i]) array[i] = *list[i];
+ }
+ if (!WASABI_API_CONFIG->getIntArrayPrivate(name, array, list.getNumItems())) return 0;
+ for (int j = 0; j < list.getNumItems(); j++) {
+ if (list[j]) *list[j] = array[j];
+ }
+ return 1;
+}
+
+void IntArray::write(const wchar_t *name, int x1) {
+ int array[] = { x1 };
+ WASABI_API_CONFIG->setIntArrayPrivate(name, array, sizeof(array)/sizeof(int));
+}
+
+void IntArray::write(const wchar_t *name, int x1, int x2) {
+ int array[] = { x1, x2 };
+ WASABI_API_CONFIG->setIntArrayPrivate(name, array, sizeof(array)/sizeof(int));
+}
+
+void IntArray::write(const wchar_t *name, int x1, int x2, int x3) {
+ int array[] = { x1, x2, x3 };
+ WASABI_API_CONFIG->setIntArrayPrivate(name, array, sizeof(array)/sizeof(int));
+}
+
+void IntArray::write(const wchar_t *name, int x1, int x2, int x3, int x4) {
+ int array[] = { x1, x2, x3, x4 };
+ WASABI_API_CONFIG->setIntArrayPrivate(name, array, sizeof(array)/sizeof(int));
+}
diff --git a/Src/Wasabi/api/config/items/intarray.h b/Src/Wasabi/api/config/items/intarray.h
new file mode 100644
index 00000000..edb26322
--- /dev/null
+++ b/Src/Wasabi/api/config/items/intarray.h
@@ -0,0 +1,18 @@
+#ifndef _INTARRAY_H
+#define _INTARRAY_H
+
+#include <bfc/common.h>
+#include <bfc/named.h>
+#include <bfc/ptrlist.h>
+
+class IntArray
+{
+public:
+ static int read(const wchar_t *name, int *x1, int *x2=NULL, int *x3=NULL, int *x4=NULL, int *x5=NULL, int *x6=NULL, int *x7=NULL, int *x8=NULL);
+ static void write(const wchar_t *name, int x1);
+ static void write(const wchar_t *name, int x1, int x2);
+ static void write(const wchar_t *name, int x1, int x2, int x3);
+ static void write(const wchar_t *name, int x1, int x2, int x3, int x4);
+};
+
+#endif
diff --git a/Src/Wasabi/api/config/options.cpp b/Src/Wasabi/api/config/options.cpp
new file mode 100644
index 00000000..e5c0d27a
--- /dev/null
+++ b/Src/Wasabi/api/config/options.cpp
@@ -0,0 +1,211 @@
+#include <precomp.h>
+
+#include "options.h"
+
+//#include <api/wac/main.h>//CUT!!
+#include <api/wnd/wndtrack.h>
+
+#include <bfc/util/inifile.h>
+#include <api/config/items/attribs.h>
+#include <api/config/items/attrcb.h>
+#include <bfc/wasabi_std_wnd.h>
+
+#include <api/locales/localesmgr.h>
+#include <api/font/font.h>
+
+#define ININAME "wasabi.ini"
+
+// {280876CF-48C0-40bc-8E86-73CE6BB462E5}
+const GUID options_guid =
+{ 0x280876cf, 0x48c0, 0x40bc, { 0x8e, 0x86, 0x73, 0xce, 0x6b, 0xb4, 0x62, 0xe5 } };
+
+#ifndef GEN_FF
+
+static void setMultipleInstance(int val)
+{
+ StringPrintf fn("%s%s%s", WASABI_API_APP->path_getAppPath(), DIRCHARSTR, ININAME);
+ IniFile(fn).setBool("Wasabi", "MultipleInstance", val);
+}
+
+_int forward_skip_time("Forward skip time", 5000);
+_int reverse_skip_time("Reverse skip time", 5000);
+#endif
+
+_bool cfg_options_altfonts(L"Alternate Fonts", FALSE);
+_bool cfg_options_allowbitmapfonts(L"Use bitmap fonts (no international support)", FALSE);
+_string cfg_options_defaultfont(L"Default font", WASABI_DEFAULT_FONTNAMEW L".ttf");
+_int cfg_options_defaultfontscale(L"Default font scale", 100);
+_string cfg_options_ttfoverridefont(L"TTF font override", WASABI_DEFAULT_FONTNAMEW L".ttf");
+_int cfg_options_ttfoverridescale(L"TTF Override Scale", 100);
+_bool cfg_options_no7bitsttfoverride(L"No 7-bit TTF override", TRUE);
+_bool cfg_options_noalt7bitsttfoverride(L"No 7-bit TTF AltFonts", TRUE);
+_bool cfg_options_usefontmapper(L"Enable Font Mapper", FALSE);
+
+#ifdef USEAPPBAR
+_bool cfg_options_appbarondrag(L"Dock Appbars on Window Drag", FALSE);
+_int cfg_options_appbardockingdistance(L"Appbars Docking Distance", 5);
+#endif
+
+void invalidateAll(int b) {
+#ifdef WASABI_COMPILE_WNDMGR
+ WASABI_API_WNDMGR->wndTrackInvalidateAll();
+#endif
+}
+
+void onDefaultFontChanged(const wchar_t *attribute) {
+ Font::uninstallAll(1);
+ Wasabi::Std::setDefaultFont(cfg_options_defaultfont.getValue());
+ invalidateAll(1);
+}
+
+void onOverrideFontChanged(const wchar_t *attribute) {
+ Font::uninstallAll(1);
+ invalidateAll(1);
+}
+
+void onDefaultFontScaleChanged(int scale) {
+ Wasabi::Std::setDefaultFontScale(scale);
+ invalidateAll(1);
+}
+
+void onOverrideFontScaleChanged(int scale) {
+ invalidateAll(1);
+}
+
+void onFontRendererChanged(const wchar_t *s) {
+ Font::uninstallAll(1);
+ invalidateAll(1);
+}
+
+void onFontMapperChanged(int b) {
+ Font::uninstallAll(1);
+ invalidateAll(1);
+}
+
+_bool cfg_audiooptions_crossfader(L"Enable crossfading", DEFAULT_CROSSFADE_ENABLED);
+_bool cfg_options_alwaysontop(L"Always on top", FALSE);
+_bool cfg_options_docking(L"Enable docking", TRUE);
+_int cfg_options_dockingdistance(L"Docking distance", DEFAULT_DOCK_DIST);
+_string cfg_options_fontrenderer(L"Font Renderer", WASABI_FONT_RENDERER);
+_int cfg_options_freetypecharmap(L"Character mapping", -1);
+
+Options::Options() : CfgItemI(L"Options", options_guid)
+{
+#ifdef _WASABIRUNTIME
+ registerAttribute(&cfg_options_alwaysontop, new int_attrCB(Main::setOnTop));
+#else
+ extern void setOnTop(int ontop);
+ registerAttribute(&cfg_options_alwaysontop, new int_attrCB(setOnTop));
+#endif
+ /* TODO: benski> move to wndmgr.w5s (or wherever it's final home is */
+ registerAttribute(&cfg_options_dockingdistance, new int_attrCB(WindowTracker::setDockDistance));
+ registerAttribute(&cfg_options_docking, new int_attrCB(WindowTracker::setEnableDocking));
+ /* --- END TO MOVE --- */
+ registerAttribute(new _bool(L"Find open rect", FALSE));
+ registerAttribute(new _bool(L"Animated rects", TRUE));
+ registerAttribute(&cfg_options_fontrenderer, new string_attrCB(onFontRendererChanged));
+ registerAttribute(&cfg_options_allowbitmapfonts, new int_attrCB(invalidateAll));
+ registerAttribute(&cfg_options_altfonts, new int_attrCB(invalidateAll));
+ registerAttribute(&cfg_options_defaultfont, new string_attrCB(onDefaultFontChanged));
+ registerAttribute(&cfg_options_ttfoverridefont, new string_attrCB(onOverrideFontChanged));
+ registerAttribute(&cfg_options_ttfoverridescale, new int_attrCB(onOverrideFontScaleChanged));
+ registerAttribute(&cfg_options_defaultfontscale, new int_attrCB(onDefaultFontScaleChanged));
+ registerAttribute(&cfg_options_freetypecharmap, new int_attrCB(invalidateAll));
+ registerAttribute(&cfg_options_no7bitsttfoverride, new int_attrCB(invalidateAll));
+ registerAttribute(&cfg_options_noalt7bitsttfoverride, new int_attrCB(invalidateAll));
+ registerAttribute(&cfg_options_usefontmapper, new int_attrCB(onFontMapperChanged));
+#ifdef USEAPPBAR
+ registerAttribute(&cfg_options_appbarondrag);
+ registerAttribute(&cfg_options_appbardockingdistance);
+#endif
+#ifdef _WASABIRUNTIME
+ registerAttribute(new _bool(L"Allow multiple instances", FALSE), new int_attrCB(setMultipleInstance));
+ registerAttribute(new _int(L"Icon mode", 1), new int_attrCB(Main::setIconMode));
+ registerAttribute(new _bool(L"Auto-play at startup", FALSE));
+ registerAttribute(new _string(L"Language", "English"), new LanguageCB(this));
+#ifdef WIN32
+ registerAttribute(new _bool("Associate with audio CDs", TRUE), new int_attrCB(Filetypes::registerCdPlayer));
+#endif
+ registerAttribute(new _string("Monitor aspect ratio", "4:3"));
+ registerAttribute(new _int("Internet connection",3)); //3==autodetect
+ registerAttribute(&forward_skip_time);
+ registerAttribute(&reverse_skip_time);
+#endif
+
+ //registerAttribute(new _bool("Use Mozilla instead of IE for minibrowser", FALSE)); // TODO:move into minibrowser component
+/* registerAttribute(new _bool("Force antialias on all TTF", FALSE));*/
+ addChildItem(&audio_options);
+ addChildItem(&ui_options);
+}
+
+void Options::checkCd() {
+#ifdef _WASABIRUNTIME
+#ifdef WIN32
+ if(getDataAsInt("Associate with audio CDs") && !Filetypes::isCdPlayer()) setDataAsInt("Associate with audio CDs",false);
+#endif
+#endif
+}
+
+// {FC3EAF78-C66E-4ed2-A0AA-1494DFCC13FF}
+static const GUID audio_options_guid =
+{ 0xfc3eaf78, 0xc66e, 0x4ed2, { 0xa0, 0xaa, 0x14, 0x94, 0xdf, 0xcc, 0x13, 0xff } };
+
+AudioOptions::AudioOptions() : CfgItemI(L"Audio options", audio_options_guid)
+{
+#ifdef GEN_FF
+#ifdef WASABI_COMPILE_MEDIACORE
+ extern void setCrossfader(int crossfade);
+ registerAttribute(&cfg_audiooptions_crossfader, new int_attrCB(setCrossfader));
+#endif
+#endif
+#ifdef _WASABIRUNTIME
+ registerAttribute(&cfg_audiooptions_crossfader);
+ int use_dsound=0;
+#ifdef WIN32
+ //check for Windows version for whether we make DSOUND default
+ DWORD dwVersion = GetVersion();
+ DWORD dwWindowsMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
+ if (dwVersion < 0x80000000) {
+ if(dwWindowsMajorVersion<=4) use_dsound=0; // no dsound on NT4/3.51
+ else use_dsound=1; // dsound yes on 2000/XP
+ } else
+ use_dsound=0; // no dsound by default on win9x (per PP)
+#endif
+ registerAttribute(new _bool("DirectSound output", use_dsound));
+#endif
+}
+
+#ifdef _WASABIRUNTIME
+
+// {C1BD5354-5EC4-406c-B5C0-549718D3AF45}
+static const GUID setup_guid =
+{ 0xc1bd5354, 0x5ec4, 0x406c, { 0xb5, 0xc0, 0x54, 0x97, 0x18, 0xd3, 0xaf, 0x45 } };
+
+SetupOptions::SetupOptions() : CfgItemI("Setup", setup_guid) {
+#ifdef WIN32
+ addChildItem(&filetypes);
+#endif
+}
+
+// {99CFD75C-1CA7-49e5-B8C0-7D78AA443C10}
+static const GUID installed_guid =
+{ 0x99cfd75c, 0x1ca7, 0x49e5, { 0xb8, 0xc0, 0x7d, 0x78, 0xaa, 0x44, 0x3c, 0x10 } };
+
+InstalledComponents::InstalledComponents() : CfgItemI("Installed components", installed_guid) {
+//CUT setCfgXml("config.components");
+}
+
+void LanguageCB::onValueChange(Attribute *attr) {
+ char bufero[WA_MAX_PATH]="";
+ attr->getData(bufero, WA_MAX_PATH-1);
+ const char *locname;
+ for(int i=0;locname=LocalesManager::enumLoadableLocales(i);i++) {
+ if (STRCASEEQLSAFE(bufero, locname)) {
+ LocalesManager::setNewLocaleNum(i);
+ return;
+ }
+ }
+ WASABI_API_WNDMGR->messageBox(StringPrintf("Internal problem switching to language %s, the language name couldn't be found in the list of loaded resources", bufero), "Error", 0, NULL, NULL);
+}
+
+#endif
diff --git a/Src/Wasabi/api/config/options.h b/Src/Wasabi/api/config/options.h
new file mode 100644
index 00000000..c86a7f3a
--- /dev/null
+++ b/Src/Wasabi/api/config/options.h
@@ -0,0 +1,64 @@
+#ifndef _OPTIONS_H
+#define _OPTIONS_H
+
+#include <api/config/items/cfgitemi.h>
+#include <api/config/items/attrcb.h>
+
+//#include <api/config/filetypes.h>
+#include <api/config/uioptions.h>
+
+class Options;
+
+class _string;
+class _int;
+class _bool;
+
+extern _string cfg_options_defaultfont;
+extern _int cfg_options_ttfoverridescale;
+extern _bool cfg_options_no7bitsttfoverride;
+extern _bool cfg_options_allowbitmapfonts;
+extern _string cfg_options_fontrenderer;
+
+#ifdef _WASABIRUNTIME
+
+class SetupOptions : public CfgItemI {
+public:
+ SetupOptions();
+
+ Filetypes filetypes;
+};
+
+class InstalledComponents : public CfgItemI {
+public:
+ InstalledComponents();
+};
+#endif
+
+class AudioOptions : public CfgItemI {
+public:
+ AudioOptions();
+};
+
+#define OPTIONS_PARENT CfgItemI
+class Options : public OPTIONS_PARENT {
+public:
+ Options();
+ void checkCd();
+
+ AudioOptions audio_options;
+ UIOptions ui_options;
+};
+
+#ifdef _WASABIRUNTIME
+
+class LanguageCB : public AttrCallback {
+public:
+ LanguageCB(CfgItemI *_par) : par(_par) { }
+ virtual void onValueChange(Attribute *attr);
+private:
+ CfgItemI *par;
+};
+
+#endif
+
+#endif
diff --git a/Src/Wasabi/api/config/uioptions.cpp b/Src/Wasabi/api/config/uioptions.cpp
new file mode 100644
index 00000000..0ccc33f7
--- /dev/null
+++ b/Src/Wasabi/api/config/uioptions.cpp
@@ -0,0 +1,109 @@
+#include <precomp.h>
+
+#include "uioptions.h"
+
+#include <api/wndmgr/layout.h>
+
+#include <api/config/items/attribs.h>
+#include <api/config/items/attrcb.h>
+
+#include <api/skin/skinparse.h>
+#include <api/wndmgr/alphamgr.h>
+
+// {9149C445-3C30-4e04-8433-5A518ED0FDDE}
+const GUID uioptions_guid =
+{ 0x9149c445, 0x3c30, 0x4e04, { 0x84, 0x33, 0x5a, 0x51, 0x8e, 0xd0, 0xfd, 0xde } };
+
+_bool cfg_uioptions_desktopalpha(L"Enable desktop alpha", DEFAULT_DESKTOPALPHA);
+_bool cfg_uioptions_linkratio(L"Link layouts scale", DEFAULT_LINKLAYOUTSCALE);
+_bool cfg_uioptions_linkalpha(L"Link layouts alpha", DEFAULT_LINKLAYOUTSALPHA);
+_bool cfg_uioptions_linkallalpha(L"Link All layouts alpha", DEFAULT_LINKALLALPHA);
+_bool cfg_uioptions_linkallratio(L"Link All layouts scale", DEFAULT_LINKALLRATIO);
+_int cfg_uioptions_linkedalpha(L"Linked layouts alpha", DEFAULT_LINKEDALPHA);
+_int cfg_uioptions_autoopacitytime(L"Auto Opacity hold time", DEFAULT_AUTOOPACITYTIME);
+_int cfg_uioptions_autoopacityfadein(L"Auto Opacity fade in time", DEFAULT_AUTOOPACITYFADEIN);
+_int cfg_uioptions_autoopacityfadeout(L"Auto Opacity fade out time", DEFAULT_AUTOOPACITYFADEOUT);
+_int cfg_uioptions_autoopacitylinked(L"Use Auto Opacity", DEFAULT_AUTOOPACITYTYPE);
+_int cfg_uioptions_extendautoopacity(L"Auto Opacity extend by", DEFAULT_EXTENDAUTOOPACITY);
+_bool cfg_uioptions_uselocks(L"Use layout scale locks", DEFAULT_USERATIOLOCKS);
+_int cfg_uioptions_timerresolution(L"Multiplexed timers resolution", DEFAULT_TIMERRESOLUTION);
+_bool cfg_uioptions_tooltips(L"Enable tooltips", DEFAULT_TOOLTIPS);
+_float cfg_uioptions_textspeed(L"Text Ticker Speed", DEFAULT_TEXTSPEED);
+_int cfg_uioptions_textincrement(L"Text Ticker Increment", DEFAULT_TEXTINCREMENT);
+_int cfg_uioptions_appbarshidetime(L"Appbar Hide Time", DEFAULT_APPBARHIDETIME);
+_int cfg_uioptions_appbarsshowtime(L"Appbar Show Time", DEFAULT_APPBARSHOWTIME);
+
+void onSetOpacityTime(int n) {
+ Layout *l = SkinParser::getMainLayout();
+ if (l) l->getAlphaMgr()->setHoldTime(n);
+}
+
+void onSetOpacityFadeIn(int n) {
+ Layout *l = SkinParser::getMainLayout();
+ if (l) l->getAlphaMgr()->setFadeInTime(n);
+}
+
+void onSetOpacityFadeOut(int n) {
+ Layout *l = SkinParser::getMainLayout();
+ if (l) l->getAlphaMgr()->setFadeOutTime(n);
+}
+
+void onSetAllRatio(int on) {
+ if (on) {
+ Layout *l = SkinParser::getMainLayout();
+ if (l) l->setRenderRatio(l->getRenderRatio());
+ }
+}
+
+void onSetAllAlpha(int on) {
+ Layout *l = SkinParser::getMainLayout();
+ if (l) l->getAlphaMgr()->setAllLinked(on);
+}
+
+void onSetLinkedAlpha(int a) {
+ Layout *l = SkinParser::getMainLayout();
+ if (l) l->getAlphaMgr()->setGlobalAlpha(a);
+}
+
+void onSetLinkedAuto100(int v) {
+ Layout *l = SkinParser::getMainLayout();
+ if (l) l->getAlphaMgr()->setAutoOpacify(v);
+}
+
+void onSetExtendAutoOpacity(int v) {
+ Layout *l = SkinParser::getMainLayout();
+ if (l) l->getAlphaMgr()->setExtendAutoOpacity(v);
+}
+
+UIOptions::UIOptions(const wchar_t *name) : CfgItemI(name ? name : L"Skins and UI Tweaks", uioptions_guid)
+{
+ registerAttribute(&cfg_uioptions_linkratio);
+ registerAttribute(&cfg_uioptions_linkalpha);
+ registerAttribute(&cfg_uioptions_uselocks);
+ registerAttribute(&cfg_uioptions_autoopacitylinked, new int_attrCB(onSetLinkedAuto100));
+ registerAttribute(&cfg_uioptions_linkallratio, new int_attrCB(onSetAllRatio));
+ registerAttribute(&cfg_uioptions_linkallalpha, new int_attrCB(onSetAllAlpha));
+ registerAttribute(&cfg_uioptions_desktopalpha, new int_attrCB(Layout::onGlobalEnableDesktopAlpha));
+ registerAttribute(&cfg_uioptions_linkedalpha, new int_attrCB(onSetLinkedAlpha));
+ registerAttribute(&cfg_uioptions_tooltips);
+ registerAttribute(&cfg_uioptions_timerresolution);
+ registerAttribute(&cfg_uioptions_textspeed);
+ registerAttribute(&cfg_uioptions_textincrement);
+ registerAttribute(&cfg_uioptions_appbarshidetime);
+ registerAttribute(&cfg_uioptions_appbarsshowtime);
+ registerAttribute(&cfg_uioptions_autoopacitytime, new int_attrCB(onSetOpacityTime));
+ registerAttribute(&cfg_uioptions_autoopacityfadein, new int_attrCB(onSetOpacityFadeIn));
+ registerAttribute(&cfg_uioptions_autoopacityfadeout, new int_attrCB(onSetOpacityFadeOut));
+ registerAttribute(&cfg_uioptions_extendautoopacity, new int_attrCB(onSetExtendAutoOpacity));
+ registerAttribute(new _int(L"Timer refresh rate", 30), new int_attrCB(onTimerRefreshRate));
+ registerAttribute(new _int(L"Popup menu alpha", 240));
+ registerAttribute(new _int(L"Spectrum analyzer mode",1));
+}
+
+void UIOptions::onTimerRefreshRate(int rate) {
+ if(rate==0 || rate<9 || rate>70) return;
+ int res=1000/rate;
+ CfgItem *ci=WASABI_API_CONFIG->config_getCfgItemByGuid(uioptions_guid);
+ if(!ci) return;
+ ci->setDataAsInt(L"Multiplexed timers resolution",res);
+}
diff --git a/Src/Wasabi/api/config/uioptions.h b/Src/Wasabi/api/config/uioptions.h
new file mode 100644
index 00000000..bf2cb963
--- /dev/null
+++ b/Src/Wasabi/api/config/uioptions.h
@@ -0,0 +1,13 @@
+#ifndef _UIOPTIONS_H
+#define _UIOPTIONS_H
+
+#include <api/config/items/cfgitemi.h>
+
+#define UIOPTIONS_PARENT CfgItemI
+class UIOptions : public UIOPTIONS_PARENT {
+public:
+ UIOptions(const wchar_t *name=NULL);
+ static void onTimerRefreshRate(int rate);
+};
+
+#endif