summaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
authorKirill Volinsky <mataes2007@gmail.com>2012-07-10 18:37:21 +0000
committerKirill Volinsky <mataes2007@gmail.com>2012-07-10 18:37:21 +0000
commit9242a80a84fa5c96dbadec9594177875aeeec1ac (patch)
tree05140dc253f5c73bc5a96624ffed8d1eff9a48e7 /plugins
parent6f8361aaf17045ff81149eeb22ed0a15b4d4ad94 (diff)
only added MyDetails and Skins. not adopted yet
git-svn-id: http://svn.miranda-ng.org/main/trunk@892 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins')
-rw-r--r--plugins/ExternalAPI/m_skins.h142
-rw-r--r--plugins/ExternalAPI/m_skins_cpp.h210
-rw-r--r--plugins/MyDetails/Docs/Skins/Default/MyDetails.msk399
-rw-r--r--plugins/MyDetails/Docs/Skins/Pidgin/MyDetails.msk59
-rw-r--r--plugins/MyDetails/Docs/langpack_MyDetails.txt85
-rw-r--r--plugins/MyDetails/Docs/mydetails.gifbin0 -> 80764 bytes
-rw-r--r--plugins/MyDetails/Docs/mydetails_changelog.txt228
-rw-r--r--plugins/MyDetails/Docs/mydetails_readme.txt41
-rw-r--r--plugins/MyDetails/Docs/mydetails_version.txt1
-rw-r--r--plugins/MyDetails/commons.h148
-rw-r--r--plugins/MyDetails/data.cpp1063
-rw-r--r--plugins/MyDetails/data.h183
-rw-r--r--plugins/MyDetails/frame.cpp2428
-rw-r--r--plugins/MyDetails/frame.h38
-rw-r--r--plugins/MyDetails/mydetails.cpp992
-rw-r--r--plugins/MyDetails/mydetails.h42
-rw-r--r--plugins/MyDetails/mydetails.vcproj642
-rw-r--r--plugins/MyDetails/options.cpp189
-rw-r--r--plugins/MyDetails/options.h83
-rw-r--r--plugins/MyDetails/res/leftarrow.icobin0 -> 2550 bytes
-rw-r--r--plugins/MyDetails/res/listening_to.icobin0 -> 2038 bytes
-rw-r--r--plugins/MyDetails/res/mail.icobin0 -> 2550 bytes
-rw-r--r--plugins/MyDetails/res/rightarrow.icobin0 -> 2550 bytes
-rw-r--r--plugins/MyDetails/resource.h72
-rw-r--r--plugins/MyDetails/resource.rc326
-rw-r--r--plugins/Skins/Docs/langpack_skins.txt2
-rw-r--r--plugins/Skins/Docs/skins_changelog.txt25
-rw-r--r--plugins/Skins/Docs/skins_readme.txt31
-rw-r--r--plugins/Skins/Docs/skins_version.txt1
-rw-r--r--plugins/Skins/MirandaField.h14
-rw-r--r--plugins/Skins/MirandaFont.cpp87
-rw-r--r--plugins/Skins/MirandaFont.h28
-rw-r--r--plugins/Skins/MirandaIconField.cpp19
-rw-r--r--plugins/Skins/MirandaIconField.h21
-rw-r--r--plugins/Skins/MirandaImageField.cpp19
-rw-r--r--plugins/Skins/MirandaImageField.h21
-rw-r--r--plugins/Skins/MirandaSkinnedDialog.cpp252
-rw-r--r--plugins/Skins/MirandaSkinnedDialog.h64
-rw-r--r--plugins/Skins/MirandaTextField.cpp27
-rw-r--r--plugins/Skins/MirandaTextField.h27
-rw-r--r--plugins/Skins/SkinLib/BorderState.cpp61
-rw-r--r--plugins/Skins/SkinLib/BorderState.h28
-rw-r--r--plugins/Skins/SkinLib/BorderState_v8_wrapper.cpp160
-rw-r--r--plugins/Skins/SkinLib/BorderState_v8_wrapper.h10
-rw-r--r--plugins/Skins/SkinLib/ButtonField.cpp22
-rw-r--r--plugins/Skins/SkinLib/ButtonField.h19
-rw-r--r--plugins/Skins/SkinLib/ButtonFieldState.cpp30
-rw-r--r--plugins/Skins/SkinLib/ButtonFieldState.h23
-rw-r--r--plugins/Skins/SkinLib/ButtonFieldState_v8_wrapper.cpp20
-rw-r--r--plugins/Skins/SkinLib/ButtonFieldState_v8_wrapper.h10
-rw-r--r--plugins/Skins/SkinLib/ControlField.cpp123
-rw-r--r--plugins/Skins/SkinLib/ControlField.h37
-rw-r--r--plugins/Skins/SkinLib/ControlFieldState.cpp86
-rw-r--r--plugins/Skins/SkinLib/ControlFieldState.h39
-rw-r--r--plugins/Skins/SkinLib/ControlFieldState_v8_wrapper.cpp59
-rw-r--r--plugins/Skins/SkinLib/ControlFieldState_v8_wrapper.h10
-rw-r--r--plugins/Skins/SkinLib/Dialog.cpp100
-rw-r--r--plugins/Skins/SkinLib/Dialog.h41
-rw-r--r--plugins/Skins/SkinLib/DialogInfo.cpp190
-rw-r--r--plugins/Skins/SkinLib/DialogInfo.h50
-rw-r--r--plugins/Skins/SkinLib/DialogState.cpp132
-rw-r--r--plugins/Skins/SkinLib/DialogState.h59
-rw-r--r--plugins/Skins/SkinLib/DialogState_v8_wrapper.cpp233
-rw-r--r--plugins/Skins/SkinLib/DialogState_v8_wrapper.h10
-rw-r--r--plugins/Skins/SkinLib/EditField.cpp23
-rw-r--r--plugins/Skins/SkinLib/EditField.h19
-rw-r--r--plugins/Skins/SkinLib/EditFieldState.cpp58
-rw-r--r--plugins/Skins/SkinLib/EditFieldState.h24
-rw-r--r--plugins/Skins/SkinLib/EditFieldState_v8_wrapper.cpp20
-rw-r--r--plugins/Skins/SkinLib/EditFieldState_v8_wrapper.h10
-rw-r--r--plugins/Skins/SkinLib/Field.cpp56
-rw-r--r--plugins/Skins/SkinLib/Field.h66
-rw-r--r--plugins/Skins/SkinLib/FieldState.cpp303
-rw-r--r--plugins/Skins/SkinLib/FieldState.h108
-rw-r--r--plugins/Skins/SkinLib/FieldState.rec89
-rw-r--r--plugins/Skins/SkinLib/FieldState_v8_wrapper.cpp539
-rw-r--r--plugins/Skins/SkinLib/FieldState_v8_wrapper.h10
-rw-r--r--plugins/Skins/SkinLib/FontState.cpp186
-rw-r--r--plugins/Skins/SkinLib/FontState.h57
-rw-r--r--plugins/Skins/SkinLib/FontState_v8_wrapper.cpp269
-rw-r--r--plugins/Skins/SkinLib/FontState_v8_wrapper.h10
-rw-r--r--plugins/Skins/SkinLib/IconField.cpp38
-rw-r--r--plugins/Skins/SkinLib/IconField.h27
-rw-r--r--plugins/Skins/SkinLib/IconFieldState.cpp37
-rw-r--r--plugins/Skins/SkinLib/IconFieldState.h28
-rw-r--r--plugins/Skins/SkinLib/IconFieldState_v8_wrapper.cpp20
-rw-r--r--plugins/Skins/SkinLib/IconFieldState_v8_wrapper.h10
-rw-r--r--plugins/Skins/SkinLib/ImageField.cpp38
-rw-r--r--plugins/Skins/SkinLib/ImageField.h26
-rw-r--r--plugins/Skins/SkinLib/ImageFieldState.cpp37
-rw-r--r--plugins/Skins/SkinLib/ImageFieldState.h28
-rw-r--r--plugins/Skins/SkinLib/ImageFieldState_v8_wrapper.cpp20
-rw-r--r--plugins/Skins/SkinLib/ImageFieldState_v8_wrapper.h10
-rw-r--r--plugins/Skins/SkinLib/LabelField.cpp23
-rw-r--r--plugins/Skins/SkinLib/LabelField.h20
-rw-r--r--plugins/Skins/SkinLib/LabelFieldState.cpp35
-rw-r--r--plugins/Skins/SkinLib/LabelFieldState.h25
-rw-r--r--plugins/Skins/SkinLib/LabelFieldState_v8_wrapper.cpp20
-rw-r--r--plugins/Skins/SkinLib/LabelFieldState_v8_wrapper.h10
-rw-r--r--plugins/Skins/SkinLib/Position.cpp9
-rw-r--r--plugins/Skins/SkinLib/Position.h16
-rw-r--r--plugins/Skins/SkinLib/Size.cpp84
-rw-r--r--plugins/Skins/SkinLib/Size.h27
-rw-r--r--plugins/Skins/SkinLib/SkinOption.h1
-rw-r--r--plugins/Skins/SkinLib/SkinOption_v8_wrapper.cpp179
-rw-r--r--plugins/Skins/SkinLib/SkinOption_v8_wrapper.h10
-rw-r--r--plugins/Skins/SkinLib/SkinOptions.cpp216
-rw-r--r--plugins/Skins/SkinLib/SkinOptions.h98
-rw-r--r--plugins/Skins/SkinLib/SkinnedDialog.cpp235
-rw-r--r--plugins/Skins/SkinLib/SkinnedDialog.h89
-rw-r--r--plugins/Skins/SkinLib/TextField.cpp78
-rw-r--r--plugins/Skins/SkinLib/TextField.h35
-rw-r--r--plugins/Skins/SkinLib/TextFieldState.cpp65
-rw-r--r--plugins/Skins/SkinLib/TextFieldState.h38
-rw-r--r--plugins/Skins/SkinLib/TextFieldState_v8_wrapper.cpp59
-rw-r--r--plugins/Skins/SkinLib/TextFieldState_v8_wrapper.h10
-rw-r--r--plugins/Skins/SkinLib/V8Script.cpp236
-rw-r--r--plugins/Skins/SkinLib/V8Script.h46
-rw-r--r--plugins/Skins/SkinLib/V8Templates.cpp475
-rw-r--r--plugins/Skins/SkinLib/V8Templates.h114
-rw-r--r--plugins/Skins/SkinLib/V8Wrappers.cpp385
-rw-r--r--plugins/Skins/SkinLib/V8Wrappers.h35
-rw-r--r--plugins/Skins/SkinLib/globals.h20
-rw-r--r--plugins/Skins/SkinLib/scope.h37
-rw-r--r--plugins/Skins/SkinLib/tstring.h13
-rw-r--r--plugins/Skins/commons.h119
-rw-r--r--plugins/Skins/libs/v8-debug.h384
-rw-r--r--plugins/Skins/libs/v8.h3686
-rw-r--r--plugins/Skins/libs/v8.libbin0 -> 34627500 bytes
-rw-r--r--plugins/Skins/libs/v8_g.libbin0 -> 40003716 bytes
-rw-r--r--plugins/Skins/options.cpp487
-rw-r--r--plugins/Skins/options.h47
-rw-r--r--plugins/Skins/resource.h22
-rw-r--r--plugins/Skins/resource.rc111
-rw-r--r--plugins/Skins/skins.cpp968
-rw-r--r--plugins/Skins/skins.vcproj1066
136 files changed, 21360 insertions, 0 deletions
diff --git a/plugins/ExternalAPI/m_skins.h b/plugins/ExternalAPI/m_skins.h
new file mode 100644
index 0000000000..da01064c64
--- /dev/null
+++ b/plugins/ExternalAPI/m_skins.h
@@ -0,0 +1,142 @@
+/*
+Copyright (C) 2008 Ricardo Pescuma Domenecci
+
+This is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this file; see the file license.txt. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef __M_SKINS_H__
+# define __M_SKINS_H__
+
+#include <windows.h>
+
+#define MIID_SKINS { 0x917db7a4, 0xd0fe, 0x4b1c, { 0x8c, 0xa3, 0x6d, 0xc1, 0x44, 0x80, 0xf5, 0xcc } }
+
+
+typedef void * SKINNED_DIALOG;
+typedef void * SKINNED_FIELD;
+typedef void * SKINNED_DIALOG_STATE;
+typedef void * SKINNED_FIELD_STATE;
+
+typedef void (*SkinOptionsChangedCallback)(void *param, SKINNED_DIALOG dlg);
+
+
+#define SKN_HALIGN_LEFT 1
+#define SKN_HALIGN_CENTER 2
+#define SKN_HALIGN_RIGHT 3
+
+#define SKN_VALIGN_TOP 1
+#define SKN_VALIGN_CENTER 2
+#define SKN_VALIGN_BOTTOM 3
+
+
+/// Some common parameters:
+/// - name : internal name and name used inside skin file
+/// - description : name shown to the user
+/// - module : the module name where the settings will be stored
+/// Do not translate any parameters.
+struct SKIN_INTERFACE
+{
+ int cbSize;
+
+ // Global methods
+ SKINNED_DIALOG (*RegisterDialog)(const char *name, const char *description, const char *module);
+ void (*DeleteDialog)(SKINNED_DIALOG dlg);
+ void (*SetSkinChangedCallback)(SKINNED_DIALOG dlg, SkinOptionsChangedCallback cb, void *param);
+ void (*FinishedConfiguring)(SKINNED_DIALOG dlg);
+
+ // Dialog methods
+ SKINNED_FIELD (*AddTextField)(SKINNED_DIALOG dlg, const char *name, const char *description);
+ SKINNED_FIELD (*AddIconField)(SKINNED_DIALOG dlg, const char *name, const char *description);
+ SKINNED_FIELD (*AddImageField)(SKINNED_DIALOG dlg, const char *name, const char *description);
+ SKINNED_FIELD (*GetField)(SKINNED_DIALOG dlg, const char *name);
+ void (*SetDialogSize)(SKINNED_DIALOG dlg, int width, int height);
+ void (*SetInfoInt)(SKINNED_DIALOG dlg, const char *name, int value);
+ void (*SetInfoDouble)(SKINNED_DIALOG dlg, const char *name, double value);
+ void (*SetInfoBool)(SKINNED_DIALOG dlg, const char *name, BOOL value);
+ void (*SetInfoString)(SKINNED_DIALOG dlg, const char *name, const TCHAR *value);
+ void (*RemoveInfo)(SKINNED_DIALOG dlg, const char *name);
+
+ // Field methods
+ void (*SetEnabled)(SKINNED_FIELD field, BOOL enabled);
+ void (*SetToolTipA)(SKINNED_FIELD field, const char *tooltip);
+ void (*SetToolTipW)(SKINNED_FIELD field, const WCHAR *tooltip);
+
+ // TextField methods
+ void (*SetTextA)(SKINNED_FIELD field, const char *text);
+ void (*SetTextW)(SKINNED_FIELD field, const WCHAR *text);
+
+ // IconField methods
+ void (*SetIcon)(SKINNED_FIELD field, HICON hIcon);
+
+ // ImageField methods
+ void (*SetImage)(SKINNED_FIELD field, HBITMAP hBmp);
+
+ // Run the skin and get an state from it
+ SKINNED_DIALOG_STATE (*Run)(SKINNED_DIALOG dialog);
+
+ // Dialog State methods
+ SKINNED_FIELD_STATE (*GetFieldState)(SKINNED_DIALOG_STATE dlg, const char *name);
+ RECT (*GetDialogBorders)(SKINNED_DIALOG_STATE dlg);
+
+ // Field State methods
+ RECT (*GetRect)(SKINNED_FIELD_STATE field); // With borders
+ RECT (*GetInsideRect)(SKINNED_FIELD_STATE field); // Without borders
+ RECT (*GetRawRect)(SKINNED_FIELD_STATE field); // With borders, without processing to assert inside window
+ RECT (*GetRawInsideRect)(SKINNED_FIELD_STATE field); // Without borders, without processing to assert inside window
+ RECT (*GetBorders)(SKINNED_FIELD_STATE field);
+ BOOL (*IsVisible)(SKINNED_FIELD_STATE field);
+ char * (*GetToolTipA)(SKINNED_FIELD field); // You have to free the result
+ WCHAR * (*GetToolTipW)(SKINNED_FIELD field); // You have to free the result
+ int (*GetHorizontalAlign)(SKINNED_FIELD_STATE field); // one of SKN_HALIGN_*
+ int (*GetVerticalAlign)(SKINNED_FIELD_STATE field); // one of SKN_VALIGN_*
+
+ // TextField State methods
+ char * (*GetTextA)(SKINNED_FIELD_STATE field); // You have to free the result
+ WCHAR * (*GetTextW)(SKINNED_FIELD_STATE field); // You have to free the result
+ HFONT (*GetFont)(SKINNED_FIELD_STATE field);
+ COLORREF (*GetFontColor)(SKINNED_FIELD_STATE field);
+
+ // IconField State methods
+ HICON (*GetIcon)(SKINNED_FIELD_STATE field);
+
+ // ImageField State methods
+ HBITMAP (*GetImage)(SKINNED_FIELD_STATE field);
+};
+
+
+
+/*
+Skins/GetInterface service
+Fill the function pointers for a SKIN_INTERFACE struct
+
+wparam = 0
+lparam = (SKIN_INTERFACE *) struct to be filled
+returns: 0 on success
+*/
+#define MS_SKINS_GETINTERFACE "Skins/GetInterface"
+
+
+
+
+static int mir_skins_getInterface(struct SKIN_INTERFACE *dest)
+{
+ dest->cbSize = sizeof(SKIN_INTERFACE);
+ return CallService(MS_SKINS_GETINTERFACE, 0, (LPARAM) dest);
+}
+
+
+#endif // __M_SKINS_H__
diff --git a/plugins/ExternalAPI/m_skins_cpp.h b/plugins/ExternalAPI/m_skins_cpp.h
new file mode 100644
index 0000000000..bdc7337419
--- /dev/null
+++ b/plugins/ExternalAPI/m_skins_cpp.h
@@ -0,0 +1,210 @@
+/*
+Copyright (C) 2008 Ricardo Pescuma Domenecci
+
+This is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this file; see the file license.txt. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef __M_SKINS_CPP_H__
+# define __M_SKINS_CPP_H__
+
+#include "m_skins.h"
+
+extern struct SKIN_INTERFACE mski;
+
+
+class SkinFieldState
+{
+public:
+ SkinFieldState(SKINNED_FIELD_STATE field) : tooltip(NULL) { this->field = field; }
+ virtual ~SkinFieldState() { if (tooltip != NULL) mir_free(tooltip); }
+
+ bool isValid() { return field != NULL; }
+
+ RECT getRect(bool raw = false) { return raw ? mski.GetRawRect(field) : mski.GetRect(field); }
+ RECT getInsideRect(bool raw = false) { return raw ? mski.GetRawInsideRect(field) : mski.GetInsideRect(field); }
+ RECT getBorders() { return mski.GetBorders(field); }
+ bool isVisible() { return mski.IsVisible(field) != FALSE; }
+ int getHorizontalAlign() { return mski.GetHorizontalAlign(field); } // one of SKN_HALIGN_*
+ int getVerticalAlign() { return mski.GetVerticalAlign(field); } // one of SKN_VALIGN_*
+
+ const TCHAR * getToolTip() {
+ if (tooltip != NULL)
+ mir_free(tooltip);
+
+#ifdef UNICODE
+ tooltip = mski.GetToolTipW(field);
+#else
+ tooltip = mski.GetToolTipA(field);
+#endif
+ return tooltip;
+ }
+
+protected:
+ SKINNED_FIELD_STATE field;
+ TCHAR *tooltip;
+};
+
+class SkinTextFieldState : public SkinFieldState
+{
+public:
+ SkinTextFieldState(SKINNED_FIELD_STATE field) : SkinFieldState(field), text(NULL) {}
+ virtual ~SkinTextFieldState() { if (text != NULL) mir_free(text); }
+
+ const TCHAR * getText() {
+ if (text != NULL)
+ mir_free(text);
+
+#ifdef UNICODE
+ text = mski.GetTextW(field);
+#else
+ text = mski.GetTextA(field);
+#endif
+ return text;
+ }
+
+ HFONT getFont() { return mski.GetFont(field); }
+ COLORREF getFontColor() { return mski.GetFontColor(field); }
+
+private:
+ TCHAR *text;
+};
+
+class SkinIconFieldState : public SkinFieldState
+{
+public:
+ SkinIconFieldState(SKINNED_FIELD_STATE field) : SkinFieldState(field) {}
+
+ HICON getIcon() { return mski.GetIcon(field); }
+};
+
+class SkinImageFieldState : public SkinFieldState
+{
+public:
+ SkinImageFieldState(SKINNED_FIELD_STATE field) : SkinFieldState(field) {}
+
+ HBITMAP getImage() { return mski.GetImage(field); }
+};
+
+
+class SkinDialogState
+{
+public:
+ SkinDialogState(SKINNED_DIALOG_STATE dlg) { this->dlg = dlg; }
+
+ bool isValid() { return dlg != NULL; }
+
+ RECT getBorders() { return mski.GetDialogBorders(dlg); }
+
+ SkinFieldState getField(const char *name) { return SkinFieldState( mski.GetFieldState(dlg, name) ); }
+ SkinTextFieldState getTextField(const char *name) { return SkinTextFieldState( mski.GetFieldState(dlg, name) ); }
+ SkinIconFieldState getIconField(const char *name) { return SkinIconFieldState( mski.GetFieldState(dlg, name) ); }
+ SkinImageFieldState getImageField(const char *name) { return SkinImageFieldState( mski.GetFieldState(dlg, name) ); }
+
+private:
+ SKINNED_DIALOG_STATE dlg;
+};
+
+
+class SkinField
+{
+public:
+ SkinField(SKINNED_FIELD field) { this->field = field; }
+
+ bool isValid() { return field != NULL; }
+
+ void setEnabled(bool enabled) { mski.SetEnabled(field, enabled); }
+
+ void setToolTip(const TCHAR *tooltip) {
+#ifdef UNICODE
+ mski.SetToolTipW(field, tooltip);
+#else
+ mski.SetToolTipA(field, tooltip);
+#endif
+ }
+
+protected:
+ SKINNED_FIELD field;
+};
+
+class SkinTextField : public SkinField
+{
+public:
+ SkinTextField(SKINNED_FIELD field) : SkinField(field) {}
+
+ void setText(const TCHAR *text) {
+#ifdef UNICODE
+ mski.SetTextW(field, text);
+#else
+ mski.SetTextA(field, text);
+#endif
+ }
+};
+
+class SkinIconField : public SkinField
+{
+public:
+ SkinIconField(SKINNED_FIELD field) : SkinField(field) {}
+
+ void setIcon(HICON hIcon) { mski.SetIcon(field, hIcon); }
+};
+
+class SkinImageField : public SkinField
+{
+public:
+ SkinImageField(SKINNED_FIELD field) : SkinField(field) {}
+
+ void setImage(HBITMAP hBmp) { mski.SetImage(field, hBmp); }
+};
+
+
+class SkinDialog
+{
+public:
+ SkinDialog(const char *name, const char *description, const char *module) { dlg = mski.RegisterDialog(name, description, module); }
+ ~SkinDialog() { mski.DeleteDialog(dlg); dlg = NULL; }
+
+ bool isValid() { return dlg != NULL; }
+
+ void setSkinChangedCallback(SkinOptionsChangedCallback cb, void *param) { mski.SetSkinChangedCallback(dlg, cb, param); }
+
+ void finishedConfiguring() { mski.FinishedConfiguring(dlg); }
+
+ void setSize(int width, int height) { mski.SetDialogSize(dlg, width, height); }
+
+ SkinTextField addTextField(const char *name, const char *description) { return SkinTextField( mski.AddTextField(dlg, name, description) ); }
+ SkinIconField addIconField(const char *name, const char *description) { return SkinIconField( mski.AddIconField(dlg, name, description) ); }
+ SkinImageField addImageField(const char *name, const char *description) { return SkinImageField( mski.AddImageField(dlg, name, description) ); }
+
+ SkinField getField(const char *name) { return SkinField( mski.GetField(dlg, name) ); }
+ SkinTextField getTextField(const char *name) { return SkinTextField( mski.GetField(dlg, name) ); }
+ SkinIconField getIconField(const char *name) { return SkinIconField( mski.GetField(dlg, name) ); }
+ SkinImageField getImageField(const char *name) { return SkinImageField( mski.GetField(dlg, name) ); }
+
+ void setInfoInt(const char *name, int value) { mski.SetInfoInt(dlg, name, value); }
+ void setInfoDouble(const char *name, double value) { mski.SetInfoDouble(dlg, name, value); }
+ void setInfoBool(const char *name, bool value) { mski.SetInfoBool(dlg, name, value); }
+ void setInfoString(const char *name, const TCHAR *value) { mski.SetInfoString(dlg, name, value); }
+ void removeInfo(const char *name) { mski.RemoveInfo(dlg, name); }
+
+ SkinDialogState run() { return SkinDialogState( mski.Run(dlg) ); }
+
+private:
+ SKINNED_DIALOG dlg;
+};
+
+
+#endif // __M_SKINS_CPP_H__ \ No newline at end of file
diff --git a/plugins/MyDetails/Docs/Skins/Default/MyDetails.msk b/plugins/MyDetails/Docs/Skins/Default/MyDetails.msk
new file mode 100644
index 0000000000..93c46b457a
--- /dev/null
+++ b/plugins/MyDetails/Docs/Skins/Default/MyDetails.msk
@@ -0,0 +1,399 @@
+function configure()
+{
+ // Options for this skin
+
+ opts.align_right.description = "Align to right"
+ opts.align_right.type = CHECKBOX
+ opts.align_right.value = false
+
+ opts.show_avatar.description = "Show avatar"
+ opts.show_avatar.type = CHECKBOX
+ opts.show_avatar.value = true
+
+ opts.avatar_allow_grow.description = "Allow avatar to grow (be bigger than original image)"
+ opts.avatar_allow_grow.type = CHECKBOX
+ opts.avatar_allow_grow.value = false
+
+ opts.avatar_use_fixed_size.description = "Use fixed size avatar"
+ opts.avatar_use_fixed_size.type = CHECKBOX
+ opts.avatar_use_fixed_size.value = false
+
+ opts.avatar_fixed_size.description = "Avatar fixed size (pixels)"
+ opts.avatar_fixed_size.type = NUMBER
+ opts.avatar_fixed_size.value = 30
+ opts.avatar_fixed_size.min = 1
+ opts.avatar_fixed_size.max = 255
+
+ opts.show_protocol.description = "Show protocol"
+ opts.show_protocol.type = CHECKBOX
+ opts.show_protocol.value = true
+
+ opts.show_email.description = "Show unread mail count"
+ opts.show_email.type = CHECKBOX
+ opts.show_email.value = true
+
+ opts.show_status.description = "Show status"
+ opts.show_status.type = CHECKBOX
+ opts.show_status.value = true
+
+ opts.show_status_msg.description = "Show status message"
+ opts.show_status_msg.type = CHECKBOX
+ opts.show_status_msg.value = true
+
+ opts.show_listening.description = "Show listening to"
+ opts.show_listening.type = CHECKBOX
+ opts.show_listening.value = true
+
+ opts.show_protocol_cycle.description = "Show protocol cycle buttons"
+ opts.show_protocol_cycle.type = CHECKBOX
+ opts.show_protocol_cycle.value = false
+
+ opts.use_under_avatar.description = "Use free space (under avatar) to other texts"
+ opts.use_under_avatar.type = CHECKBOX
+ opts.use_under_avatar.value = true
+
+ opts.border_left.description = "Left border"
+ opts.border_left.type = NUMBER
+ opts.border_left.value = 8
+ opts.border_left.min = 0
+ opts.border_left.max = 100
+
+ opts.border_top.description = "Top border"
+ opts.border_top.type = NUMBER
+ opts.border_top.value = 8
+ opts.border_top.min = 0
+ opts.border_top.max = 100
+
+ opts.border_right.description = "Right border"
+ opts.border_right.type = NUMBER
+ opts.border_right.value = 8
+ opts.border_right.min = 0
+ opts.border_right.max = 100
+
+ opts.border_bottom.description = "Bottom border"
+ opts.border_bottom.type = NUMBER
+ opts.border_bottom.value = 8
+ opts.border_bottom.min = 0
+ opts.border_bottom.max = 100
+
+ // Default fonts
+
+ nickname.font.face = "Tahoma"
+ nickname.font.size = 13
+ nickname.font.bold = true
+ nickname.font.color = RGB(0,0,0)
+
+ protocol.font.face = "Tahoma"
+ protocol.font.size = 8
+ protocol.font.color = RGB(0,0,0)
+
+ email.font.face = "Tahoma"
+ email.font.size = 8
+ email.font.color = RGB(0,0,0)
+
+ status_name.font.face = "Tahoma"
+ status_name.font.size = 8
+ status_name.font.color = RGB(0,0,0)
+
+ status_msg.font.face = "Tahoma"
+ status_msg.font.size = 8
+ status_msg.font.italic = true
+ status_msg.font.color = RGB(150,150,150)
+
+ listening.font.face = "Tahoma"
+ listening.font.size = 8
+ listening.font.italic = true
+ listening.font.color = RGB(150,150,150)
+}
+
+function valign_center(top)
+{
+ var height = 0
+ for(var i = 1; i < arguments.length; i++)
+ height = Math.max(height, arguments[i].height)
+ for(var i = 1; i < arguments.length; i++)
+ arguments[i].top = top + (height - arguments[i].height)/2
+ return top + height
+}
+
+// Resize a field, keeping its aspect ratio
+function resize(field, maxWidth, maxHeight, allowGrow)
+{
+ if (allowGrow == null)
+ allowGrow = true
+
+ var factor = Math.min(maxWidth / field.width, maxHeight / field.height)
+ if (!allowGrow && factor >= 1)
+ return
+
+ field.width *= factor
+ field.height *= factor
+}
+
+function draw()
+{
+ // Default texts
+ if (nickname.enabled && nickname.text == "")
+ nickname.text = "<no nickname>"
+ if (status_msg.enabled && status_msg.text == "")
+ status_msg.text = "<no status message>"
+ if (listening.enabled && listening.text == "")
+ listening.text = "<nothing playing>"
+
+ if (info.protocol.locked)
+ status_name.text += " (locked)"
+
+
+ // ToolTips
+ nickname.toolTip = nickname.text
+ protocol.toolTip = protocol.text
+ status_icon.toolTip = status_name.toolTip = status_name.text
+ status_msg.toolTip = status_msg.text
+ listening_icon.toolTip = listening.toolTip = listening.text
+ next_proto.toolTip = "Show next protocol"
+ prev_proto.toolTip = "Show previous protocol"
+ email_icon.toolTip = email.toolTip = "Unread Email Count: " + email.text
+
+
+ // Borders
+ window.borders.left = opts.border_left
+ window.borders.top = opts.border_top
+ window.borders.right = opts.border_right
+ window.borders.bottom = opts.border_bottom
+
+
+ // Visible
+ nickname.visible = true
+ prev_proto.visible = next_proto.visible = opts.show_protocol_cycle && !IsEmpty(next_proto, prev_proto)
+ avatar.visible = opts.show_avatar && avatar.enabled && !IsEmpty(avatar)
+ protocol.visible = opts.show_protocol && protocol.enabled
+ status_icon.visible = status_name.visible = opts.show_status && status_name.enabled
+ status_msg.visible = opts.show_status_msg && !IsEmpty(status_msg)
+ listening_icon.visible = listening.visible = opts.show_listening && !IsEmpty(listening_icon, listening)
+ email_icon.visible = email.visible = opts.show_email && email.enabled && !IsEmpty(email_icon, email) && email.text > 0
+
+
+ // Space to draw the frame around
+ var BORDER_SPACE = 2
+ nickname.borders = BORDER_SPACE
+ protocol.borders = BORDER_SPACE
+ status_icon.borders = BORDER_SPACE
+ status_name.borders = BORDER_SPACE
+ status_msg.borders = BORDER_SPACE
+ listening_icon.borders = BORDER_SPACE
+ listening.borders = BORDER_SPACE
+ email_icon.borders = BORDER_SPACE
+ email.borders = BORDER_SPACE
+
+
+ if (avatar.visible)
+ {
+ if (opts.avatar_use_fixed_size)
+ resize(avatar, opts.avatar_fixed_size, opts.avatar_fixed_size, opts.avatar_allow_grow)
+ else
+ resize(avatar, window.width/2.5, window.height - (!info.resize_frame && prev_proto.visible ? prev_proto.height : 0), opts.avatar_allow_grow)
+ }
+
+ if (!info.resize_frame && prev_proto.visible)
+ {
+ prev_proto.left = 0
+ prev_proto.bottom = window.height
+
+ next_proto.right = window.width
+ next_proto.bottom = window.height
+ }
+
+ var avatar_bottom = avatar.bottom
+ if (opts.show_avatar && opts.avatar_use_fixed_size)
+ avatar_bottom = opts.avatar_fixed_size
+
+ var top = 0
+
+ if (opts.align_right)
+ {
+ // Align
+ nickname.hAlign = RIGHT
+ protocol.hAlign = RIGHT
+ status_name.hAlign = RIGHT
+ status_msg.hAlign = RIGHT
+ listening.hAlign = RIGHT
+
+
+ var right = window.right
+
+ function updateTopRight(val)
+ {
+ top = val
+ if (opts.use_under_avatar && top > avatar_bottom)
+ right = window.right
+ }
+
+ if (avatar.visible)
+ {
+ avatar.right = window.right
+ avatar.top = 0
+
+ right = avatar.left - 6
+ }
+
+ if (opts.show_avatar && opts.avatar_use_fixed_size)
+ right = window.right - opts.avatar_fixed_size - 6
+
+ nickname.right = right
+ nickname.top = top
+
+ updateTopRight(nickname.bottom)
+
+ if (protocol.visible)
+ {
+ protocol.right = right
+ protocol.top = top
+
+ if (email.visible)
+ {
+ email_icon.right = protocol.left - 10
+ email.right = email_icon.left
+
+ var bottom = valign_center(top, protocol, email_icon, email)
+ updateTopRight(bottom)
+ }
+ else
+ updateTopRight(protocol.bottom)
+ }
+ else if (email.visible)
+ {
+ email_icon.borders.left = 0
+ email_icon.right = right
+
+ email.right = email_icon.left
+
+ var bottom = valign_center(top, email_icon, email)
+ updateTopRight(bottom)
+ }
+
+ if (status_name.visible)
+ {
+ status_icon.right = right
+ status_name.right = status_icon.left
+
+ var bottom = valign_center(top, status_icon, status_name)
+ updateTopRight(bottom)
+ }
+
+ if (status_msg.visible)
+ {
+ status_msg.right = right
+ status_msg.top = top
+
+ updateTopRight(status_msg.bottom)
+ }
+
+ if (listening.visible)
+ {
+ listening_icon.borders.left = 0
+ listening_icon.right = right
+
+ listening.right = listening_icon.left
+
+ var bottom = valign_center(top, listening_icon, listening)
+ updateTopRight(bottom)
+ }
+ }
+ else
+ {
+ var left = 0
+
+ function updateTopLeft(val)
+ {
+ top = val
+ if (opts.use_under_avatar && top > avatar_bottom)
+ left = 0
+ }
+
+ if (avatar.visible)
+ {
+ avatar.left = 0
+ avatar.top = 0
+
+ left = avatar.right + 6
+ }
+
+ if (opts.show_avatar && opts.avatar_use_fixed_size)
+ left = opts.avatar_fixed_size + 6
+
+ nickname.left = left
+ nickname.top = top
+
+ updateTopLeft(nickname.bottom)
+
+ if (protocol.visible)
+ {
+ protocol.left = left
+ protocol.top = top
+
+ if (email.visible)
+ {
+ email_icon.left = protocol.right + 10
+ email.left = email_icon.right
+
+ var bottom = valign_center(top, protocol, email_icon, email)
+ updateTopLeft(bottom)
+ }
+ else
+ updateTopLeft(protocol.bottom)
+ }
+ else if (email.visible)
+ {
+ email_icon.borders.right = 0
+ email_icon.left = left
+
+ email.left = email_icon.right
+
+ var bottom = valign_center(top, email_icon, email)
+ updateTopLeft(bottom)
+ }
+
+ if (status_name.visible)
+ {
+ status_icon.left = left
+ status_name.left = status_icon.right
+
+ var bottom = valign_center(top, status_icon, status_name)
+ updateTopLeft(bottom)
+ }
+
+ if (status_msg.visible)
+ {
+ status_msg.left = left
+ status_msg.top = top
+
+ updateTopLeft(status_msg.bottom)
+ }
+
+ if (listening.visible)
+ {
+ listening_icon.borders.right = 0
+ listening_icon.left = left
+
+ listening.borders.left = 0
+ listening.left = listening_icon.right
+
+ var bottom = valign_center(top, listening_icon, listening)
+ updateTopLeft(bottom)
+ }
+ }
+
+ if (info.resize_frame)
+ {
+ if (prev_proto.visible)
+ {
+ top = Math.max(avatar.bottom, top)
+
+ prev_proto.left = 0
+ prev_proto.top = top
+
+ next_proto.right = window.width
+ next_proto.top = top
+ }
+ }
+} \ No newline at end of file
diff --git a/plugins/MyDetails/Docs/Skins/Pidgin/MyDetails.msk b/plugins/MyDetails/Docs/Skins/Pidgin/MyDetails.msk
new file mode 100644
index 0000000000..89295899f8
--- /dev/null
+++ b/plugins/MyDetails/Docs/Skins/Pidgin/MyDetails.msk
@@ -0,0 +1,59 @@
+function configure()
+{
+ // Default fonts
+
+ status_msg.font.face = "Tahoma"
+ status_msg.font.size = 8
+ status_msg.font.color = RGB(0,0,0)
+}
+
+function draw()
+{
+ if (status_msg.text == "")
+ status_msg.text = status_name.text
+
+ // ToolTips
+ status_icon.toolTip = protocol.text + " : " + status_name.text
+ if (info.protocol.locked)
+ status_icon.toolTip += " (locked)"
+ if (email.text > 0)
+ status_icon.toolTip += " [" + email.text + " emails]"
+
+ status_msg.toolTip = status_msg.text
+
+ // Borders
+ window.borders = 10
+
+ // Visible
+ status_msg.visible = true
+ avatar.visible = true
+ status_icon.visible = true
+
+ status_name.visible = false
+ protocol.visible = false
+ nickname.visible = false
+ prev_proto.visible = next_proto.visible = false
+ listening_icon.visible = listening.visible = false
+ email_icon.visible = email.visible = false
+
+ // Space to draw the frame around
+ var BORDER_SPACE = 2
+ status_icon.borders = BORDER_SPACE
+ status_msg.borders = BORDER_SPACE
+ status_name.borders = BORDER_SPACE
+
+ // Positions
+ var HEIGHT = 45
+
+ avatar.right = window.right
+ avatar.top = 0
+ avatar.width = HEIGHT
+ avatar.height = HEIGHT
+
+ status_icon.left = 0
+ status_icon.top = (HEIGHT - status_icon.height) / 2
+
+ status_msg.left = status_icon.right + 5
+ status_msg.top = (HEIGHT - status_msg.height) / 2
+ status_msg.right = avatar.left - 5
+}
diff --git a/plugins/MyDetails/Docs/langpack_MyDetails.txt b/plugins/MyDetails/Docs/langpack_MyDetails.txt
new file mode 100644
index 0000000000..01c61de1b4
--- /dev/null
+++ b/plugins/MyDetails/Docs/langpack_MyDetails.txt
@@ -0,0 +1,85 @@
+; My Details
+; Author: Pescuma
+; http://forums.miranda-im.org/showthread.php?t=5643
+
+[My Details]
+
+; Group in options
+[Customize]
+
+; Options
+
+[ General ]
+[Cycle through protocols every:]
+[seconds]
+[RTL]
+[Auto-resize frame]
+[Replace Smileys]
+[Align text to right]
+[Use contact lest smileys]
+[Resize Smileys]
+[Global on avatar]
+[Global on nickname]
+[Global on status]
+[Global on status message]
+
+[ Frame Options ]
+[Top:]
+[Bottom:]
+[Left:]
+[Right:]
+[Background Color:]
+
+[ Avatar ]
+[Custom size:]
+[pixels]
+[Allow it to grow]
+[Draw border on avatar]
+[Border Color:]
+[Round corners of avatars]
+[Custom corner size:]
+[Use free space (under avatar) to other texts]
+
+[ Protocol ]
+[Show protocol name]
+[Show protocol cycle button]
+
+
+; Default values
+[<no nickname>]
+[<no status name>]
+
+
+; Without multiwindows
+[Show My Details]
+[Hide My Details]
+
+
+; Menus
+[Set My Avatar...]
+[Set My Nickname...]
+[Set My Status Message...]
+[Set My Avatar for %s...]
+[Set My Nickname for %s...]
+[Set My Status Message for %s...]
+[Show next protocol]
+[Show previous protocol]
+[Cycle through protocols]
+[Don't cycle through protocols]
+
+
+; Dialogs
+[Set My Nickname]
+[Set My Nickname for %s]
+[Nickname:]
+
+[Set My Status Message for All Status]
+[Set My Status Message for %s]
+[Status Message:]
+
+[OK]
+[Cancel]
+
+; Clist Modern BAckground
+[Main Window/Backgrnd]
+[MyDetails/Backgrnd]
diff --git a/plugins/MyDetails/Docs/mydetails.gif b/plugins/MyDetails/Docs/mydetails.gif
new file mode 100644
index 0000000000..8e4d04e583
--- /dev/null
+++ b/plugins/MyDetails/Docs/mydetails.gif
Binary files differ
diff --git a/plugins/MyDetails/Docs/mydetails_changelog.txt b/plugins/MyDetails/Docs/mydetails_changelog.txt
new file mode 100644
index 0000000000..011a1c63b3
--- /dev/null
+++ b/plugins/MyDetails/Docs/mydetails_changelog.txt
@@ -0,0 +1,228 @@
+My Details
+
+Changelog:
+
+. 0.0.2.6
+ + Added support for clist modern skin engine
+ + Added pidgin style skin
+ * Fix for last shown protocol
+ * Updated updater to use googlecode
+
+. 0.0.2.5
+ + Use account name and ordering
+ * Better handling status messages
+ * Fix for jabber status names
+ * Bug fixes
+
+. 0.0.2.3
+ * Moved background color to font service settings
+ + Better simple away support
+
+. 0.0.2.2
+ * Fix for email count
+ * Better handling of hover
+ * Better handling of small sizes
+ * If fixed avatar size is set, use it even if no avatar present
+ + If windows uses RTL, it is selected by default
+
+. 0.0.2.1
+ + Show lock icon over status
+ + Show unread mail count
+ * Resize frame is working again
+ * Still work in progress
+
+. 0.0.2.0
+ + Now uses skins plugin to position elements (work in progress)
+
+. 0.0.1.11
+ * Fix for arrows: always draw then at right side
+
+. 0.0.1.10
+ + Added arrows to change protocols (Drugwash patch)
+ * Use icolib to show icons (uses listening to icon from contact list)
+
+. 0.0.1.9
+ + Created 2 services: MyDetails/HideFrame and MyDetails/ShowFrame
+ * MyDetails/ShowHideMyDetails changed to work with frames too (it toggles the frame)
+
+. 0.0.1.8
+ * Fix for crash when using main menu options
+
+. 0.0.1.7
+ * Fix for crash when no protocol found
+ + Added 2 keys to allow themes to show/hide frame: MyDetails\ForceHideFrame and MyDetails\ForceShowFrame (BYTE). Both are deleted after use.
+
+. 0.0.1.6
+ + Added uid for 0.8
+
+. 0.0.1.5:
+ + Added option to set status message per protocol
+
+. 0.0.1.4
+ * Fixed crash on protocol connection
+ + Support for new version of ersatz
+
+. 0.0.1.3
+ + Support for ersatz plugin by TioDuke. When it is finished, status message will be shown correctly always :)
+
+. 0.0.1.2
+ + Added listening to info
+
+. 0.0.1.1
+ * Fix for crash on exit (thanks ghazan)
+ - Removed clist modern mod support
+
+. 0.0.1.0
+ * Fix in call to NAS service
+ + Ready to FL
+
+. 0.0.0.42
+ * Fixed code to open only one dialog
+ + CTRL-Enter on status message dialog
+
+. 0.0.0.41
+ + Added support to new NAS services
+ + Open only one dialog (for dialogs that t handles - does not include NAS / avs)
+ * Bigger buffer for status messages
+ + First release build (dll is 200k smaller)
+
+. 0.0.0.40
+ * Changed text [Top: ] to [Top:]
+ + Added langpack_MyDetails.txt
+
+. 0.0.0.39
+ * Reverted to show menus on key up
+ + Using miranda lists now. This version only works with newer versions of miranda
+ * Fixed call to NAS with parsed variables
+
+. 0.0.0.38
+ * Fix for international languages
+ + Translateble options dialog
+ + Show some menus on key down (but it still not work as desired, i'll have to figure it)
+
+. 0.0.0.37
+ * Bugfix in status menu
+ + Better support for updater
+
+. 0.0.0.36
+ + Change to better support NAS
+ + Change to know when info changed (may flick a little less the screen and the tooltip, but may be losing changes)
+
+. 0.0.0.35
+ + Try to discover the default nick
+ + Global on avatar
+ * Fixed order of fields in options dialog
+
+. 0.0.0.34
+ * Fixed issue with mTooltip
+ + Changed tooltip timeout to 10h (is it long enougth? :P )
+
+. 0.0.0.33
+ + Added timer to refresh status messages. It isnt in options dialog, but can be changed at DB, in key MyDetails\RefreshStatusMessageTimer (0 disables it, default to 12 s)
+ * Fixed input box in set my nickname
+
+. 0.0.0.32
+ * Fix for crash on startup
+ * Fix for drawing function
+
+. 0.0.0.31
+ * Fix for status message with NAS
+
+. 0.0.0.30
+ * Try to fix bug when setting name (Again)
+ * Fix for multi line in status message and nickname
+ + Setting to call global functions on left click
+ + Calling service to get max nickname length from protocol (no proto support it right now)
+
+. 0.0.0.29
+ * Fix in status message code
+
+. 0.0.0.28
+ + Multiline popup
+ + More options in context menu
+ * Try to fix bug when setting name
+
+. 0.0.0.27
+ + Better support for core away system (it set the message in the DB, inside SRAway module)
+
+. 0.0.0.26
+ + Added tooltips
+ + Added background collor
+ + Added XStatus support
+ + Added in the zip: avatar service (unicode and non-unicode) and folder service
+
+. 0.0.0.25
+ + Added support to set avatars (needs modified version of avatar service - is inside zip)
+ + Added in the zip: avatar service and folder service
+
+. 0.0.0.23
+ * Bugfix in new status menu code
+
+. 0.0.0.22
+ + Using clist status menus when possible (this should add support to all away system always)
+ + Show global status menu on right click
+ * Fixed space in status
+
+. 0.0.0.21
+ * Bugfixes
+
+. 0.0.0.20
+ + Compatibility with KeepStatus -> code is too ugly :'(
+ + Show status messages only for supported statuses
+ + Show SimpleAway dialog only to supported protocols
+
+. 0.0.0.19
+ + Better support to SimpleAway
+ + Set what protocol to show by clicking in proto name
+ * Bug fixes
+
+. 0.0.0.18
+ + Set status message after status change (should work with gadu-gadu, but it isn't the best solution at all)
+
+. 0.0.0.17
+ + Popups with more actions
+ + Option to grow avatar
+ + An attempt to set status messages withou NAS
+
+. 0.0.0.16
+ * Fixed leak of GDI objects
+ * Fixed resizing of avatar
+
+. 0.0.0.15
+ * Bug fixes
+
+. 0.0.0.14
+ + Resize frame
+ + Use space bellow avatar
+
+. 0.0.0.13
+ - Change to try to get more updates from status message changes
+ * Fix in avatar refresh
+
+. 0.0.0.12
+ * Updater works
+ * Fix drawing protocol name
+
+. 0.0.0.11
+ * Fixed bug on drawing status name
+ + Added custom avatar size
+ + Will not cicle when changing status
+
+. 0.0.0.9
+ * Fixed crash on Set My Nickname from status menu
+ + Added cache to data (should draw faster, but have to see if the data shown is correct)
+ + Added visual things
+ + Option to set status
+ - Changed to set things with left click of mouse
+
+. 0.0.0.7
+ * Fix in NAS fetching code (again)
+
+. 0.0.0.6
+ * Fix in NAS fetching code
+ + RTL
+ + Smileys
+
+. 0.0.0.5
+ + Added option dialog
+ + Added option to not cicle throught protocols \ No newline at end of file
diff --git a/plugins/MyDetails/Docs/mydetails_readme.txt b/plugins/MyDetails/Docs/mydetails_readme.txt
new file mode 100644
index 0000000000..c9e58d0136
--- /dev/null
+++ b/plugins/MyDetails/Docs/mydetails_readme.txt
@@ -0,0 +1,41 @@
+My Details plugin
+-----------------
+
+What it does:
+- Show your current configuration, per protocol, for avatar, nickname, status and away message
+- It shows each protocol at a time, cicling throught then
+- Allows to set nickname (per protocol or for all protocols) and away messages (per protocol or for all protocols - need NewAwaySystem, SimpleAway or core module)
+
+Some comments:
+1. SimpleAway does not show a dialog to set a message for all protocols. Someones it does not show the dialog (I requested it in the thread http://forums.miranda-im.org/showthread.php?p=47157).
+2. For core away system, only some protocols works (probabily the same as SimpleAway). But for the ones that it works, the message in the frame is the old message. I know, it sucks... But if you use ersatz plugin this problem doesn't happen: http://pescuma.mirandaim.ru/miranda/ersatz.zip
+
+To request support to other away system: If someone wants to use another away system, please request in its thread to add support for 2 services:
+1. Get current status message for a protocol, given its name
+2. Set current status message for a protocol, given its name and the message
+
+
+To use skin engine of clist modern: the following glyphs are used:
+- MyDetails,ID=Background : background of frame
+- MyDetails,ID=MouseOver : base mouse over background (for all fields)
+- MyDetails,ID=MouseOverNick : base mouse over background for nick (drawn over the base one)
+- MyDetails,ID=MouseOverProto : base mouse over background for protocol (drawn over the base one)
+- MyDetails,ID=MouseOverStatus : base mouse over status name/icon for nick (drawn over the base one)
+- MyDetails,ID=MouseOverStatusMsg : base mouse over background for status message (drawn over the base one)
+- MyDetails,ID=MouseOverListening : base mouse over background for listening info (drawn over the base one)
+
+To report bugs/make suggestions, go to the forum thread: http://forums.miranda-im.org/showthread.php?t=5643
+
+Dependencies:
+- If you want integration with clist, an frame enabled clist, such as clist_modern or clist_nicer+
+- Away systens supported: Core, NewAwaySystem or SimpleAway
+
+Todo:
+- Global page
+- Add custom presets
+- Resize on mouse hover
+- clist_modern_layered integration -> try this: http://forums.miranda-im.org/showthread.php?t=6597
+- New drawing code (please, do not request things like order of items or spacing, it is in TODO list, but will take time to be made)
+- Options to XStatus setup
+- Icons instead of ... on mouse over
+- Options to show/hide itens
diff --git a/plugins/MyDetails/Docs/mydetails_version.txt b/plugins/MyDetails/Docs/mydetails_version.txt
new file mode 100644
index 0000000000..e078af1e48
--- /dev/null
+++ b/plugins/MyDetails/Docs/mydetails_version.txt
@@ -0,0 +1 @@
+My Details 0.0.2.6 \ No newline at end of file
diff --git a/plugins/MyDetails/commons.h b/plugins/MyDetails/commons.h
new file mode 100644
index 0000000000..ca1849c826
--- /dev/null
+++ b/plugins/MyDetails/commons.h
@@ -0,0 +1,148 @@
+/*
+Copyright (C) 2005 Ricardo Pescuma Domenecci
+
+This is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this file; see the file license.txt. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef __COMMONS_H__
+# define __COMMONS_H__
+
+
+#define _WIN32_WINNT 0x0501
+#include <windows.h>
+#include <win2k.h>
+#include <commctrl.h>
+#include <stdio.h>
+#include <vector>
+
+#define MIRANDA_VER 0x800
+#include <newpluginapi.h>
+#include <m_clist.h>
+#include <m_skin.h>
+#include <m_system.h>
+#include <m_protocols.h>
+#include <m_protosvc.h>
+#include <m_database.h>
+#include <m_utils.h>
+#include <m_langpack.h>
+#include <m_awaymsg.h>
+#include <m_contacts.h>
+#include <m_options.h>
+#include <m_clui.h>
+#include <m_clc.h>
+#include <m_proto_listeningto.h>
+#include <m_listeningto.h>
+
+#include <m_NewAwaySys.h>
+#include <m_updater.h>
+#include <m_fontservice.h>
+#include <m_variables.h>
+#include <m_avatars.h>
+#include <m_statusplugins.h>
+#include <m_ersatz.h>
+#include <m_icq.h>
+#include <m_icolib.h>
+#include "m_cluiframes.h"
+#include "m_simpleaway.h"
+
+#include <richedit.h>
+#include <m_smileyadd.h>
+
+#include <io.h>
+
+#include "../skins/m_skins_cpp.h"
+
+#include "resource.h"
+
+
+#define MODULE_NAME "MyDetails"
+
+#define SETTING_FRAME_VISIBLE "FrameVisible"
+#define SETTING_DEFAULT_NICK "DefaultNick"
+
+
+extern HINSTANCE hInst;
+extern PLUGINLINK *pluginLink;
+
+extern long nickname_dialog_open;
+extern long status_msg_dialog_open;
+
+extern SkinDialog *dialog;
+
+
+#include "m_mydetails.h"
+#include "data.h"
+#include "options.h"
+#include "frame.h"
+#include "../utils/mir_smileys.h"
+#include "../utils/mir_memory.h"
+#include "../utils/mir_options.h"
+#include "../utils/mir_icons.h"
+#include "../utils/tstring.h"
+
+
+#define PS_SETMYAVATAR "/SetMyAvatar"
+#define PS_GETMYAVATAR "/GetMyAvatar"
+#define PS_GETMYAVATARMAXSIZE "/GetMyAvatarMaxSize"
+#define PS_GETUNREADEMAILCOUNT "/GetUnreadEmailCount"
+
+#define PS_SETMYNICKNAME "/SetNickname"
+
+#define PS_GETMYNICKNAMEMAXLENGTH "/GetMyNicknameMaxLength"
+
+#define WAYD_UNICODE 1 // return Unicode texts
+#if defined( _UNICODE )
+ #define WAYD_TCHAR WAYD_UNICODE
+#else
+ #define WAYD_TCHAR 0
+#endif
+
+// Get the max length that a WAYD message can have
+// wParam=(WPARAM)0
+// lParam=(LPARAM)0
+// Returns the max length
+#define PS_GET_MY_WAYD_MAXLENGTH "/GetMyWAYDMaxLength"
+
+// Get the WAYD message for the user
+// wParam=(WPARAM)WAYD_xxx
+// lParam=(LPARAM)0
+// Returns the text or NULL if there is none. Remember to mir_free the return value.
+#define PS_GET_MY_WAYD "/GetMyWAYD"
+
+// Sets the WAYD message for the user
+// wParam=(WPARAM)WAYD_xxx
+// lParam=(LPARAM)(WCHAR * or char *)The text to set
+// Returns 0 on success, nonzero on failure
+#define PS_SET_MY_WAYD "/SetMyWAYD"
+
+#define MAX_REGS(_A_) ( sizeof(_A_) / sizeof(_A_[0]) )
+
+
+// See if a protocol service exists
+__inline static int ProtoServiceExists(const char *szModule,const char *szService)
+{
+ char str[MAXMODULELABELLENGTH];
+ strcpy(str,szModule);
+ strcat(str,szService);
+ return ServiceExists(str);
+}
+
+
+
+
+
+#endif // __COMMONS_H__
diff --git a/plugins/MyDetails/data.cpp b/plugins/MyDetails/data.cpp
new file mode 100644
index 0000000000..eccd72e0e7
--- /dev/null
+++ b/plugins/MyDetails/data.cpp
@@ -0,0 +1,1063 @@
+/*
+Copyright (C) 2005 Ricardo Pescuma Domenecci
+
+This is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this file; see the file license.txt. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+*/
+
+
+#include "commons.h"
+#include "data.h"
+#include <algorithm>
+
+
+static char *StatusModeToDbSetting(int status,const char *suffix);
+
+
+static bool IsValid(const char *proto)
+{
+ if (proto == NULL || proto[0] == 0)
+ return false;
+
+ int caps = CallProtoService(proto, PS_GETCAPS, PFLAGNUM_1, 0);
+ return (caps & PF1_IM) == PF1_IM && strcmp(proto, "MetaContacts") != 0;
+}
+
+static bool AccOrderComp(PROTOACCOUNT *p1, PROTOACCOUNT *p2)
+{
+ return p1->iOrder < p2->iOrder;
+}
+
+static void GetAccounts(std::vector<PROTOACCOUNT *> *result)
+{
+ int count;
+ PROTOACCOUNT **protos;
+ ProtoEnumAccounts(&count, &protos);
+
+ for (int i = 0; i < count; i++)
+ {
+ if (protos[i]->type != PROTOTYPE_PROTOCOL)
+ continue;
+
+ if (!IsAccountEnabled(protos[i]))
+ continue;
+
+ if (!IsValid(protos[i]->szModuleName))
+ continue;
+
+ result->push_back(protos[i]);
+ }
+
+ std::sort(result->begin(), result->begin(), AccOrderComp);
+}
+
+
+void GetProtocols(std::vector<Protocol> *result)
+{
+ std::vector<PROTOACCOUNT *> accs;
+ GetAccounts(&accs);
+
+ unsigned int accsSize = accs.size();
+ for (unsigned int i = 0; i < accsSize ; ++i)
+ result->push_back(Protocol(accs[i]->szModuleName));
+}
+
+
+int GetProtocolIndexByName(const char *moduleName)
+{
+ std::vector<PROTOACCOUNT *> protos;
+ GetAccounts(&protos);
+
+ int protosSize = (int) protos.size();
+ for(int i = 0; i < protosSize; ++i)
+ {
+ if (strcmp(protos[i]->szModuleName, moduleName) == 0)
+ return i;
+ }
+
+ return -1;
+}
+
+
+int GetNumProtocols()
+{
+ std::vector<PROTOACCOUNT *> protos;
+ GetAccounts(&protos);
+ return protos.size();
+}
+
+
+struct ProtoCache
+{
+ Protocol *proto;
+ int index;
+
+ void Free()
+ {
+ delete proto;
+ proto = NULL;
+ index = -1;
+ }
+};
+
+static ProtoCache current = { NULL, -1 };
+
+
+void SetCurrentProtocol(int index)
+{
+ current.Free();
+
+ int protosSize = GetNumProtocols();
+ if (protosSize > 0)
+ current.index = (index % protosSize + protosSize) % protosSize;
+
+ DBWriteContactSettingWord(NULL, "MyDetails", "ProtocolNumber", current.index);
+}
+
+Protocol * GetCurrentProtocol(bool createIfDontExist)
+{
+ if (createIfDontExist && current.index >= 0 && current.proto == NULL)
+ {
+ std::vector<PROTOACCOUNT *> protos;
+ GetAccounts(&protos);
+
+ int protosSize = protos.size();
+ if (current.index >= protosSize)
+ {
+ current.index = -1;
+ return NULL;
+ }
+
+ current.proto = new Protocol(protos[current.index]->szModuleName);
+ }
+
+ return current.proto;
+}
+
+int GetCurrentProtocolIndex()
+{
+ return current.index;
+}
+
+
+Protocol GetProtocolByIndex(int index)
+{
+ std::vector<PROTOACCOUNT *> protos;
+ GetAccounts(&protos);
+ int protosSize = protos.size();
+
+ if (protosSize < 1)
+ return Protocol(NULL);
+
+ index = (index % protosSize + protosSize) % protosSize;
+ return Protocol(protos[index]->szModuleName);
+}
+
+
+Protocol GetProtocolByName(const char *moduleName)
+{
+ std::vector<PROTOACCOUNT *> protos;
+ GetAccounts(&protos);
+
+ int protosSize = (int) protos.size();
+ for(int i = 0; i < protosSize; ++i)
+ {
+ if (strcmp(protos[i]->szModuleName, moduleName) == 0)
+ return Protocol(protos[i]->szModuleName);
+ }
+
+ return Protocol(NULL);
+}
+
+
+ProtocolArray *protocols = NULL;
+
+
+void InitProtocolData()
+{
+ protocols = new ProtocolArray();
+}
+
+
+void DeInitProtocolData()
+{
+ current.Free();
+
+ delete protocols;
+ protocols = NULL;
+}
+
+
+// Protocol Class ///////////////////////////////////////////////////////////////////////////////////////////
+
+
+Protocol::Protocol(const char *aName)
+{
+ if (aName)
+ name = aName;
+
+ avatar_bmp = NULL;
+ status = 0;
+ custom_status = 0;
+ locked = false;
+ emails = 0;
+
+ // Initial value
+ UpdateAll();
+}
+
+Protocol::~Protocol()
+{
+}
+
+
+bool Protocol::IsValid()
+{
+ return !name.empty();
+}
+
+
+Protocol::operator bool ()
+{
+ return IsValid();
+}
+
+
+void Protocol::UpdateAll()
+{
+ status_initialized = false;
+ status_message_initialized = false;
+ nickname_initialized = false;
+ avatar_initialized = false;
+ locked_initialized = false;
+ emails_initialized = false;
+ listening_to_initialized = false;
+}
+
+
+int Protocol::Call(const char *service, WPARAM wParam, LPARAM lParam)
+{
+ return CallProtoService(name.c_str(), service, wParam, lParam);
+}
+
+
+bool Protocol::CanCall(const char *service)
+{
+ return ProtoServiceExists(name.c_str(), service) != 0;
+}
+
+
+std::string Protocol::GetDBSettingString(const char *key, const char *def)
+{
+ std::string result = def;
+
+ DBVARIANT dbv;
+ if (!DBGetContactSettingTString(0, name.c_str(), key, &dbv))
+ {
+ if (dbv.ptszVal != NULL && dbv.ptszVal[0] != 0)
+ result = dbv.ptszVal;
+
+ DBFreeVariant(&dbv);
+ }
+
+ return result;
+}
+
+
+const char * Protocol::GetName()
+{
+ return name.c_str();
+}
+
+
+const char * Protocol::GetDescription()
+{
+ if (description.empty())
+ {
+ PROTOACCOUNT *acc = ProtoGetAccount(name.c_str());
+
+ if (acc == NULL || acc->tszAccountName == NULL || acc->tszAccountName[0] == 0)
+ {
+ char tmp[1024];
+ Call(PS_GETNAME, sizeof(tmp), (LPARAM) tmp);
+ description = tmp;
+ }
+ else
+ {
+ if (mir_is_unicode())
+ {
+ char *tmp = mir_u2a((const wchar_t *) acc->tszAccountName);
+ description = tmp;
+ mir_free(tmp);
+ }
+ else
+ {
+ description = acc->tszAccountName;
+ }
+ }
+ }
+
+ return description.c_str();
+}
+
+void Protocol::UpdateStatus()
+{
+ status_initialized = true;
+
+ status = Call(PS_GETSTATUS);
+
+ if (status > ID_STATUS_OFFLINE && CanCall(PS_ICQ_GETCUSTOMSTATUS))
+ {
+ char *name_key = NULL;
+ char *message_key = NULL;
+
+ custom_status = Call(PS_ICQ_GETCUSTOMSTATUS, (WPARAM) &name_key, (LPARAM) &message_key);
+
+ // Fix fo jabber, that returns 0xbaadf00d here
+ if (custom_status < 0)
+ custom_status = 0;
+
+ custom_status_name_key = (name_key ? name_key : "");
+ custom_status_message_key = (message_key ? message_key : "");
+ }
+ else
+ {
+ custom_status = 0;
+ custom_status_name_key = "";
+ custom_status_message_key = "";
+ }
+
+ if (custom_status == 0)
+ {
+ status_name = (char *) CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, status, GCMDF_TCHAR);
+ }
+ else
+ {
+ status_name = "";
+
+ if (!custom_status_name_key.empty())
+ status_name = GetDBSettingString(custom_status_name_key.c_str());
+
+ if (!custom_status_message_key.empty())
+ {
+ std::string tmp = GetDBSettingString(custom_status_message_key.c_str());
+ if (!tmp.empty())
+ {
+ status_name += ": ";
+ status_name += tmp;
+ }
+ }
+ }
+
+ if (status_name.empty())
+ status_name = TranslateTS("<no status name>");
+}
+
+const char * Protocol::GetStatusName()
+{
+ if (!status_initialized)
+ UpdateStatus();
+
+ return status_name.c_str();
+}
+
+const char * Protocol::GetCustomStatusNameKey()
+{
+ if (!status_initialized)
+ UpdateStatus();
+
+ return custom_status_name_key.c_str();
+}
+
+const char * Protocol::GetCustomStatusMessageKey()
+{
+ if (!status_initialized)
+ UpdateStatus();
+
+ return custom_status_message_key.c_str();
+}
+
+int Protocol::GetStatus()
+{
+ if (!status_initialized)
+ UpdateStatus();
+
+ return status;
+}
+
+int Protocol::GetCustomStatus()
+{
+ if (!status_initialized)
+ UpdateStatus();
+
+ return custom_status;
+}
+
+
+void Protocol::SetStatus(int aStatus)
+{
+ char status_msg[256];
+
+ if (ServiceExists(MS_CS_SETSTATUSEX))
+ {
+ // :'(
+
+ // BEGIN From commomstatus.cpp (KeepStatus)
+ int i, count, pCount;
+ PROTOCOLDESCRIPTOR **protos;
+
+ pCount = 0;
+ CallService(MS_PROTO_ENUMPROTOCOLS,(WPARAM)&count,(LPARAM)&protos);
+ for(i=0;i<count;i++) {
+ if(protos[i]->type!=PROTOTYPE_PROTOCOL || CallProtoService(protos[i]->szName,PS_GETCAPS,PFLAGNUM_2,0)==0) continue;
+ pCount += 1;
+ }
+ // END From commomstatus.cpp (KeepStatus)
+
+
+ PROTOCOLSETTINGEX **pse = (PROTOCOLSETTINGEX **) mir_alloc0(pCount * sizeof(PROTOCOLSETTINGEX *));
+
+ for(i = 0; i < pCount; i++)
+ {
+ pse[i] = (PROTOCOLSETTINGEX *) mir_alloc0(sizeof(PROTOCOLSETTINGEX));
+ pse[i]->szName = "";
+ }
+
+ pse[0]->cbSize = sizeof(PROTOCOLSETTINGEX);
+ pse[0]->status = aStatus;
+ pse[0]->szName = (char *) name.c_str();
+
+ GetStatusMsg(aStatus, status_msg, sizeof(status_msg));
+ pse[0]->szMsg = status_msg;
+
+ CallService(MS_CS_SETSTATUSEX, (WPARAM) &pse, 0);
+
+ for(i = 0; i < pCount; i++)
+ mir_free(pse[i]);
+ mir_free(pse);
+ }
+ else
+ {
+ Call(PS_SETSTATUS, aStatus);
+
+ if (CanSetStatusMsg(aStatus))
+ {
+ char status_msg[MS_MYDETAILS_GETMYSTATUSMESSAGE_BUFFER_SIZE];
+ GetStatusMsg(aStatus, status_msg, sizeof(status_msg));
+ SetStatusMsg(aStatus, status_msg);
+ }
+ }
+}
+
+
+bool Protocol::CanGetStatusMsg()
+{
+ return CanGetStatusMsg(GetStatus());
+}
+
+bool Protocol::CanGetStatusMsg(int aStatus)
+{
+ return (Call(PS_GETCAPS, PFLAGNUM_1) & PF1_MODEMSGSEND) != 0
+ && (Call(PS_GETCAPS, (WPARAM)PFLAGNUM_3) & Proto_Status2Flag(aStatus));
+}
+
+
+bool Protocol::CanSetStatusMsg()
+{
+ return CanSetStatusMsg(GetStatus()) // <- Simple away handled by this one
+ || ServiceExists(MS_NAS_INVOKESTATUSWINDOW);
+
+}
+
+bool Protocol::CanSetStatusMsg(int aStatus)
+{
+ return CanGetStatusMsg(aStatus);
+}
+
+void Protocol::GetStatusMsg(int aStatus, char *msg, size_t msg_size)
+{
+ if (!CanGetStatusMsg())
+ {
+ lstrcpyn(msg, "", msg_size);
+ return;
+ }
+
+ bool isCurrentStatus = (aStatus == GetStatus());
+
+ if (isCurrentStatus && CanCall(PS_GETMYAWAYMSG))
+ {
+ char *tmp = (char *) Call(PS_GETMYAWAYMSG);
+ lstrcpyn(msg, tmp == NULL ? "" : tmp, msg_size);
+ }
+ else if (isCurrentStatus && ServiceExists(MS_SA_ISSARUNNING) && CallService(MS_SA_ISSARUNNING, 0, 0))
+ {
+ char *tmp = (char *) CallService(MS_AWAYMSG_GETSTATUSMSG, (WPARAM) ID_STATUS_CURRENT, (LPARAM) name.c_str());
+
+ if (tmp != NULL)
+ {
+ lstrcpyn(msg, tmp, msg_size);
+ mir_free(tmp);
+ }
+ else lstrcpyn(msg, "", msg_size);
+
+ }
+ else if (ServiceExists(MS_NAS_GETSTATE))
+ {
+ NAS_PROTOINFO pi;
+
+ ZeroMemory(&pi, sizeof(pi));
+ pi.cbSize = sizeof(NAS_PROTOINFO);
+ pi.szProto = (char *) name.c_str();
+ pi.status = (isCurrentStatus ? 0 : aStatus);
+ pi.szMsg = NULL;
+
+ if (CallService(MS_NAS_GETSTATE, (WPARAM) &pi, 1) == 0)
+ {
+ if (pi.szMsg == NULL)
+ {
+ pi.szProto = NULL;
+
+ if (CallService(MS_NAS_GETSTATE, (WPARAM) &pi, 1) == 0)
+ {
+ if (pi.szMsg != NULL)
+ {
+ lstrcpyn(msg, pi.szMsg, msg_size);
+ mir_free(pi.szMsg);
+ }
+ else lstrcpyn(msg, "", msg_size);
+ }
+ else lstrcpyn(msg, "", msg_size);
+ }
+ else // if (pi.szMsg != NULL)
+ {
+ lstrcpyn(msg, pi.szMsg, msg_size);
+ mir_free(pi.szMsg);
+ }
+ }
+ else lstrcpyn(msg, "", msg_size);
+
+ if (ServiceExists(MS_VARS_FORMATSTRING))
+ {
+ char *tmp = variables_parse(msg, NULL, NULL);
+ lstrcpyn(msg, tmp, msg_size);
+ variables_free(tmp);
+ }
+ }
+ // TODO: Remove when removing old NAS services support
+ else if (ServiceExists("NewAwaySystem/GetState"))
+ {
+ NAS_PROTOINFO pi, *pii;
+
+ ZeroMemory(&pi, sizeof(pi));
+ pi.cbSize = sizeof(NAS_PROTOINFO);
+ pi.szProto = (char *) name.c_str();
+ pi.status = (isCurrentStatus ? 0 : aStatus);
+ pi.szMsg = NULL;
+
+ pii = &pi;
+
+ if (CallService("NewAwaySystem/GetState", (WPARAM) &pii, 1) == 0)
+ {
+ if (pi.szMsg == NULL)
+ {
+ pi.szProto = NULL;
+
+ if (CallService("NewAwaySystem/GetState", (WPARAM) &pii, 1) == 0)
+ {
+ if (pi.szMsg != NULL)
+ {
+ lstrcpyn(msg, pi.szMsg, msg_size);
+ mir_free(pi.szMsg);
+ }
+ else lstrcpyn(msg, "", msg_size);
+ }
+ else lstrcpyn(msg, "", msg_size);
+ }
+ else // if (pi.szMsg != NULL)
+ {
+ lstrcpyn(msg, pi.szMsg, msg_size);
+ mir_free(pi.szMsg);
+ }
+ }
+ else lstrcpyn(msg, "", msg_size);
+
+ if (ServiceExists(MS_VARS_FORMATSTRING))
+ {
+ char *tmp = variables_parse(msg, NULL, NULL);
+ lstrcpyn(msg, tmp, msg_size);
+ variables_free(tmp);
+ }
+ }
+ else if (ServiceExists(MS_AWAYMSG_GETSTATUSMSG))
+ {
+ char *tmp = (char *) CallService(MS_AWAYMSG_GETSTATUSMSG, (WPARAM)aStatus, 0);
+
+ if (tmp != NULL)
+ {
+ lstrcpyn(msg, tmp, msg_size);
+ mir_free(tmp);
+ }
+ else lstrcpyn(msg, "", msg_size);
+ }
+}
+
+void Protocol::UpdateStatusMsg()
+{
+ status_message_initialized = true;
+
+ TCHAR tmp[1024];
+ GetStatusMsg(GetStatus(), tmp, sizeof(tmp));
+
+ status_message = tmp;
+}
+
+const char * Protocol::GetStatusMsg()
+{
+ if (!status_message_initialized)
+ UpdateStatusMsg();
+
+ return status_message.c_str();
+}
+
+void Protocol::SetStatusMsg(const char *message)
+{
+ SetStatusMsg(GetStatus(), message);
+}
+
+void Protocol::SetStatusMsg(int aStatus, const char *message)
+{
+ if (!CanSetStatusMsg(aStatus))
+ return;
+
+ if (ServiceExists(MS_NAS_SETSTATE))
+ {
+ NAS_PROTOINFO pi = {0}, *pii;
+
+ pi.cbSize = sizeof(pi);
+ pi.szProto = (char *) name.c_str();
+ pi.szMsg = mir_strdup(message);
+ pi.status = aStatus;
+
+ pii = &pi;
+
+ CallService(MS_NAS_SETSTATE, (WPARAM) &pii, 1);
+ }
+ else
+ {
+ Call(PS_SETAWAYMSG, (WPARAM) aStatus, (LPARAM) message);
+ }
+}
+
+bool Protocol::HasAvatar()
+{
+ if (!avatar_initialized)
+ UpdateAvatar();
+
+ return avatar_bmp != NULL;
+}
+
+bool Protocol::CanGetAvatar()
+{
+ int caps = Call(PS_GETCAPS, PFLAGNUM_4);
+
+ if ((caps & PF4_AVATARS) == 0)
+ return false;
+
+ if (!ServiceExists(MS_AV_GETMYAVATAR))
+ return false;
+
+ return true;
+}
+
+void Protocol::UpdateAvatar()
+{
+ avatar_initialized = true;
+ avatar_file = "";
+ avatar_bmp = NULL;
+
+ // See if can get one
+ if (!CanGetAvatar())
+ return;
+
+ // Get HBITMAP from cache
+ AVATARCACHEENTRY *ace = (avatarCacheEntry *) CallService(MS_AV_GETMYAVATAR, 0, (LPARAM) name.c_str());
+ if (ace != NULL)
+ {
+ avatar_file = ace->szFilename;
+ avatar_bmp = ace->hbmPic;
+ }
+}
+
+const char * Protocol::GetAvatarFile()
+{
+ if (!avatar_initialized)
+ UpdateAvatar();
+
+ return avatar_file.c_str();
+}
+
+HBITMAP Protocol::GetAvatarImage()
+{
+ if (!avatar_initialized)
+ UpdateAvatar();
+
+ return avatar_bmp;
+}
+
+
+bool Protocol::CanGetNick()
+{
+ return ServiceExists(MS_CONTACT_GETCONTACTINFO) != FALSE;
+}
+
+int Protocol::GetNickMaxLength()
+{
+ if (CanCall(PS_GETMYNICKNAMEMAXLENGTH))
+ {
+ int ret = Call(PS_GETMYNICKNAMEMAXLENGTH);
+ if (ret <= 0)
+ ret = MS_MYDETAILS_GETMYNICKNAME_BUFFER_SIZE;
+ return ret;
+ }
+ else
+ return MS_MYDETAILS_GETMYNICKNAME_BUFFER_SIZE;
+}
+
+void Protocol::UpdateNick()
+{
+ nickname_initialized = true;
+ nickname = "";
+
+ // See if can get one
+ if (!CanGetNick())
+ return;
+
+ // Get it
+ CONTACTINFO ci;
+ ZeroMemory(&ci, sizeof(ci));
+ ci.cbSize = sizeof(ci);
+ ci.hContact = NULL;
+ ci.szProto = (char *) name.c_str();
+ ci.dwFlag = CNF_DISPLAY;
+
+#ifdef UNICODE
+ ci.dwFlag |= CNF_UNICODE;
+#endif
+
+ if (!CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM) & ci))
+ {
+ // CNF_DISPLAY always returns a string type
+ nickname = ci.pszVal;
+ mir_free(ci.pszVal);
+ }
+}
+
+const char * Protocol::GetNick()
+{
+ if (!nickname_initialized)
+ UpdateNick();
+
+ return nickname.c_str();
+}
+
+
+bool Protocol::CanSetNick()
+{
+ return CanCall(PS_SETMYNICKNAME) != 0;
+}
+
+
+void Protocol::SetNick(const char *nick)
+{
+ // See if can get one
+ if (!CanSetNick())
+ return;
+
+ if (nick == NULL)
+ return;
+
+ // Get it
+ Call(PS_SETMYNICKNAME, NULL, (LPARAM) nick);
+}
+
+
+bool Protocol::CanSetAvatar()
+{
+ return ServiceExists(MS_AV_SETMYAVATAR) != FALSE && ServiceExists(MS_AV_CANSETMYAVATAR) != FALSE &&
+ CallService(MS_AV_CANSETMYAVATAR, (WPARAM) name.c_str(), 0);
+}
+
+void Protocol::SetAvatar(const char *file_name)
+{
+ if (!CanSetAvatar())
+ return;
+
+ CallService(MS_AV_SETMYAVATAR, (WPARAM) name.c_str(), (LPARAM) file_name);
+}
+
+bool Protocol::CanGetListeningTo()
+{
+ return CanCall(PS_SET_LISTENINGTO) != 0;
+}
+
+bool Protocol::CanSetListeningTo()
+{
+ return CanGetListeningTo() && ServiceExists(MS_LISTENINGTO_ENABLE);
+}
+
+bool Protocol::ListeningToEnabled()
+{
+ return CanSetListeningTo() && CallService(MS_LISTENINGTO_ENABLED, (WPARAM) name.c_str(), 0) != 0;
+}
+
+void Protocol::UpdateListeningTo()
+{
+ listening_to_initialized = true;
+ listening_to = "";
+
+ if (!CanGetListeningTo())
+ return;
+
+ listening_to = GetDBSettingString("ListeningTo");
+}
+
+const char * Protocol::GetListeningTo()
+{
+ if (!listening_to_initialized)
+ UpdateListeningTo();
+
+ return listening_to.c_str();
+}
+
+void Protocol::UpdateLocked()
+{
+ locked_initialized = true;
+
+ locked = (DBGetContactSettingByte(NULL, name.c_str(), "LockMainStatus", 0) != 0);
+}
+
+bool Protocol::IsLocked()
+{
+ if (!locked_initialized)
+ UpdateLocked();
+
+ return locked;
+}
+
+bool Protocol::CanGetEmailCount()
+{
+ return CanCall(PS_GETUNREADEMAILCOUNT) != 0
+ && GetStatus() > ID_STATUS_OFFLINE;
+}
+
+void Protocol::UpdateEmailCount()
+{
+ emails_initialized = true;
+
+ if (!CanGetEmailCount())
+ emails = 0;
+ else
+ emails = max(0, Call(PS_GETUNREADEMAILCOUNT));
+}
+
+int Protocol::GetEmailCount()
+{
+ if (!emails_initialized)
+ UpdateEmailCount();
+
+ return emails;
+}
+
+
+// ProtocolDataArray Class /////////////////////////////////////////////////////////////////////////////
+
+
+ProtocolArray::ProtocolArray()
+{
+ GetDefaultNick();
+ GetDefaultAvatar();
+}
+
+int ProtocolArray::GetGlobalStatus()
+{
+ int status = CallService(MS_CLIST_GETSTATUSMODE, 0, 0);
+ if (status == ID_STATUS_CONNECTING)
+ status = ID_STATUS_OFFLINE;
+
+ return status;
+}
+
+bool ProtocolArray::CanSetAvatars()
+{
+ return ServiceExists(MS_AV_SETMYAVATAR) != FALSE;
+}
+
+void ProtocolArray::SetAvatars(const char *file_name)
+{
+ if (!CanSetAvatars())
+ return;
+
+ CallService(MS_AV_SETMYAVATAR, NULL, (WPARAM) file_name);
+}
+
+
+void ProtocolArray::SetNicks(const char *nick)
+{
+ if (nick == NULL || nick[0] == '\0')
+ return;
+
+ lstrcpyn(default_nick, nick, sizeof(default_nick));
+
+ DBWriteContactSettingString(0, MODULE_NAME, SETTING_DEFAULT_NICK, nick);
+
+ std::vector<Protocol> protos;
+ GetProtocols(&protos);
+
+ unsigned int protosSize = protos.size();
+ for (int i = 0; i < protosSize; ++i)
+ protos[i].SetNick(default_nick);
+}
+
+
+void ProtocolArray::SetStatus(int aStatus)
+{
+ CallService(MS_CLIST_SETSTATUSMODE, aStatus, 0);
+}
+
+void ProtocolArray::SetStatusMsgs(const char *message)
+{
+ for (int i = ID_STATUS_OFFLINE ; i <= ID_STATUS_IDLE; i++)
+ {
+ SetStatusMsgs(i, message);
+ }
+}
+
+void ProtocolArray::SetStatusMsgs(int status, const char *message)
+{
+ DBWriteContactSettingString(NULL,"SRAway",StatusModeToDbSetting(status,"Msg"),message);
+ if (!DBGetContactSettingByte(NULL,"SRAway",StatusModeToDbSetting(status,"UsePrev"),0))
+ {
+ // Save default also
+ DBWriteContactSettingString(NULL,"SRAway",StatusModeToDbSetting(status,"Default"),message);
+ }
+
+ std::vector<Protocol> protos;
+ GetProtocols(&protos);
+
+ unsigned int protosSize = protos.size();
+ for (int i = 0; i < protosSize; ++i)
+ {
+ if (protos[i].GetStatus() == status)
+ protos[i].SetStatusMsg(status, message);
+ }
+}
+
+
+void ProtocolArray::GetDefaultNick()
+{
+ DBVARIANT dbv;
+
+ if (!DBGetContactSettingTString(0, MODULE_NAME, SETTING_DEFAULT_NICK, &dbv))
+ {
+ lstrcpyn(default_nick, dbv.pszVal, sizeof(default_nick));
+ DBFreeVariant(&dbv);
+ }
+ else
+ {
+ default_nick[0] = '\0';
+ }
+}
+
+void ProtocolArray::GetDefaultAvatar()
+{
+ DBVARIANT dbv;
+
+ if (!DBGetContactSettingTString(0, "ContactPhoto", "File", &dbv))
+ {
+ lstrcpyn(default_avatar_file, dbv.pszVal, sizeof(default_avatar_file));
+ DBFreeVariant(&dbv);
+ }
+ else
+ {
+ default_avatar_file[0] = '\0';
+ }
+}
+
+char * ProtocolArray::GetDefaultStatusMsg()
+{
+ return GetDefaultStatusMsg(CallService(MS_CLIST_GETSTATUSMODE, 0, 0));
+}
+
+char * ProtocolArray::GetDefaultStatusMsg(int status)
+{
+ default_status_message[0] = '\0';
+
+ if (ServiceExists(MS_AWAYMSG_GETSTATUSMSG))
+ {
+ if (status == ID_STATUS_CONNECTING)
+ {
+ status = ID_STATUS_OFFLINE;
+ }
+
+ char *tmp = (char *) CallService(MS_AWAYMSG_GETSTATUSMSG, (WPARAM)status, 0);
+
+ if (tmp != NULL)
+ {
+ lstrcpyn(default_status_message, tmp, sizeof(default_status_message));
+ mir_free(tmp);
+ }
+ }
+
+ return default_status_message;
+}
+
+bool ProtocolArray::CanSetListeningTo()
+{
+ return ServiceExists(MS_LISTENINGTO_ENABLE) != 0;
+}
+
+bool ProtocolArray::ListeningToEnabled()
+{
+ return CanSetListeningTo() && CallService(MS_LISTENINGTO_ENABLED, 0, 0) != 0;
+}
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////////
+// Helper functions
+
+static char *StatusModeToDbSetting(int status,const char *suffix)
+{
+ char *prefix;
+ static char str[64];
+
+ switch(status) {
+ case ID_STATUS_AWAY: prefix="Away"; break;
+ case ID_STATUS_NA: prefix="Na"; break;
+ case ID_STATUS_DND: prefix="Dnd"; break;
+ case ID_STATUS_OCCUPIED: prefix="Occupied"; break;
+ case ID_STATUS_FREECHAT: prefix="FreeChat"; break;
+ case ID_STATUS_ONLINE: prefix="On"; break;
+ case ID_STATUS_OFFLINE: prefix="Off"; break;
+ case ID_STATUS_INVISIBLE: prefix="Inv"; break;
+ case ID_STATUS_ONTHEPHONE: prefix="Otp"; break;
+ case ID_STATUS_OUTTOLUNCH: prefix="Otl"; break;
+ case ID_STATUS_IDLE: prefix="Idl"; break;
+ default: return NULL;
+ }
+ lstrcpyA(str,prefix); lstrcatA(str,suffix);
+ return str;
+}
+
+
diff --git a/plugins/MyDetails/data.h b/plugins/MyDetails/data.h
new file mode 100644
index 0000000000..9c458b50dd
--- /dev/null
+++ b/plugins/MyDetails/data.h
@@ -0,0 +1,183 @@
+/*
+Copyright (C) 2005 Ricardo Pescuma Domenecci
+
+This is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this file; see the file license.txt. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef __DATA_H__
+# define __DATA_H__
+
+
+//#include "protocol_config.h"
+
+class Protocol
+{
+ // Attributes ////////////
+ std::string name;
+
+ std::string description;
+
+ bool avatar_initialized;
+ std::string avatar_file;
+ HBITMAP avatar_bmp;
+
+ bool status_message_initialized;
+ std::string status_message;
+
+ bool nickname_initialized;
+ std::string nickname;
+
+ bool locked_initialized;
+ bool locked;
+
+ bool emails_initialized;
+ int emails;
+
+ bool listening_to_initialized;
+ std::string listening_to;
+
+ bool status_initialized;
+ std::string status_name;
+ std::string custom_status_name_key;
+ std::string custom_status_message_key;
+ int status;
+ int custom_status;
+
+public:
+ Protocol(const char *name);
+ ~Protocol();
+
+ bool IsValid();
+ operator bool ();
+
+ void UpdateAll();
+
+ const char * GetName();
+ const char * GetDescription();
+
+ const char * GetStatusName();
+ const char * GetCustomStatusNameKey();
+ const char * GetCustomStatusMessageKey();
+ int GetStatus();
+ int GetCustomStatus();
+ void SetStatus(int aStatus);
+
+ bool HasAvatar();
+ bool CanGetAvatar();
+ const char * GetAvatarFile();
+ HBITMAP GetAvatarImage();
+
+ bool CanSetAvatar();
+ void SetAvatar(const TCHAR *file_name);
+
+ bool CanGetNick();
+ const char * GetNick();
+ int GetNickMaxLength();
+ bool CanSetNick();
+ void SetNick(const TCHAR *nick);
+
+ bool CanGetListeningTo();
+ bool CanSetListeningTo();
+ bool ListeningToEnabled();
+ const char * GetListeningTo();
+
+ bool CanGetStatusMsg();
+ bool CanGetStatusMsg(int aStatus);
+ void GetStatusMsg(int aStatus, TCHAR *msg, size_t msg_size);
+ const char * GetStatusMsg();
+
+ bool CanSetStatusMsg();
+ bool CanSetStatusMsg(int aStatus);
+ void SetStatusMsg(const TCHAR *message);
+ void SetStatusMsg(int aStatus, const TCHAR *message);
+
+ bool IsLocked();
+
+ bool CanGetEmailCount();
+ int GetEmailCount();
+
+ int Call(const char *service, WPARAM wParam = 0, LPARAM lParam = 0);
+ bool CanCall(const char *service);
+
+ std::string GetDBSettingString(const char *key, const char *def = "");
+
+private:
+ void UpdateStatus();
+ void UpdateAvatar();
+ void UpdateNick();
+ void UpdateListeningTo();
+ void UpdateStatusMsg();
+ void UpdateLocked();
+ void UpdateEmailCount();
+};
+
+
+
+class ProtocolArray
+{
+public:
+ TCHAR default_nick[256];
+ TCHAR default_avatar_file[256];
+ TCHAR default_status_message[256];
+
+ // Methods ///////////////
+
+ ProtocolArray();
+
+ bool CanSetAvatars();
+ void SetAvatars(const TCHAR *file);
+
+ void SetNicks(const TCHAR *nick);
+
+ void SetStatus(int aStatus);
+
+ void SetStatusMsgs(const TCHAR *message);
+ void SetStatusMsgs(int status, const TCHAR *message);
+
+ int GetGlobalStatus();
+
+ void GetDefaultNick(); // Copy to cache
+ void GetDefaultAvatar(); // Copy to cache
+ TCHAR * GetDefaultStatusMsg(); // Copy to cache
+ TCHAR * GetDefaultStatusMsg(int status);
+
+ bool CanSetListeningTo();
+ bool ListeningToEnabled();
+};
+
+extern ProtocolArray *protocols;
+
+
+void SetCurrentProtocol(int index);
+Protocol * GetCurrentProtocol(bool createIfDontExist = true);
+int GetCurrentProtocolIndex();
+
+void GetProtocols(std::vector<Protocol> *result);
+int GetProtocolIndexByName(const char *moduleName);
+int GetNumProtocols();
+Protocol GetProtocolByIndex(int index);
+Protocol GetProtocolByName(const char *proto);
+
+void InitProtocolData();
+void DeInitProtocolData();
+
+
+
+
+
+
+#endif // __DATA_H__
diff --git a/plugins/MyDetails/frame.cpp b/plugins/MyDetails/frame.cpp
new file mode 100644
index 0000000000..d5b609a4e9
--- /dev/null
+++ b/plugins/MyDetails/frame.cpp
@@ -0,0 +1,2428 @@
+/*
+Copyright (C) 2005 Ricardo Pescuma Domenecci
+
+This is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this file; see the file license.txt. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+*/
+
+
+#include "commons.h"
+#include "frame.h"
+#include "wingdi.h"
+#include "winuser.h"
+#include <m_skin_eng.h>
+
+
+// Prototypes /////////////////////////////////////////////////////////////////////////////////////
+
+
+#define WINDOW_NAME_PREFIX "mydetails_window"
+#define WINDOW_CLASS_NAME "MyDetailsFrame"
+#define CONTAINER_CLASS_NAME "MyDetailsFrameContainer"
+
+#define ID_FRAME_TIMER 1011
+#define ID_RECALC_TIMER 1012
+#define ID_STATUSMESSAGE_TIMER 1013
+
+#define RECALC_TIME 500
+
+#define IDC_HAND MAKEINTRESOURCE(32649)
+
+
+// Messages
+#define MWM_REFRESH (WM_USER+10)
+#define MWM_REFRESH_DATA (WM_USER+18)
+
+
+HWND hwnd_frame = NULL;
+HWND hwnd_container = NULL;
+
+int frame_id = -1;
+
+HANDLE hMenuShowHideFrame = 0;
+
+int CreateFrame();
+void FixMainMenu();
+void UpdateFrameData();
+void RedrawFrame();
+
+
+// used when no multiwindow functionality available
+BOOL MyDetailsFrameVisible();
+void SetMyDetailsFrameVisible(BOOL visible);
+int ShowHideMenuFunc(WPARAM wParam, LPARAM lParam);
+int ShowFrameFunc(WPARAM wParam, LPARAM lParam);
+int HideFrameFunc(WPARAM wParam, LPARAM lParam);
+int ShowHideFrameFunc(WPARAM wParam, LPARAM lParam);
+
+
+
+LRESULT CALLBACK FrameContainerWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+LRESULT CALLBACK FrameWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+void SetCycleTime();
+void SetCycleTime(HWND hwnd);
+void SetStatusMessageRefreshTime();
+void SetStatusMessageRefreshTime(HWND hwnd);
+int SettingsChangedHook(WPARAM wParam, LPARAM lParam);
+int AvatarChangedHook(WPARAM wParam, LPARAM lParam);
+int ProtoAckHook(WPARAM wParam, LPARAM lParam);
+int SmileyAddOptionsChangedHook(WPARAM wParam,LPARAM lParam);
+int ListeningtoEnableStateChangedHook(WPARAM wParam,LPARAM lParam);
+int AccListChanged(WPARAM wParam, LPARAM lParam);
+
+
+void ExternalRect(RECT &ret, const RECT r1, const RECT r2);
+bool InsideRect(const POINT &p, const RECT &r);
+
+
+int operator==(const RECT& left, const RECT& right)
+{
+ return left.left == right.left && left.right == right.right
+ && left.top == right.top && left.bottom == right.bottom;
+}
+
+class ToolTipArea
+{
+public:
+ ToolTipArea() : hwndTT(0), hwndParent(0) { memset(&rc, 0, sizeof(rc)); }
+ ~ToolTipArea() { removeTooltip(); }
+
+ void createTooltip(HWND hwnd, const RECT &rc, const TCHAR *text)
+ {
+ if (text == NULL || text[0] == 0)
+ {
+ removeTooltip();
+ return;
+ }
+
+ this->text = text;
+
+ if (this->rc == rc && hwndParent == hwnd && hwndTT != NULL)
+ return;
+
+ removeTooltip();
+
+ this->rc = rc;
+ this->hwndParent = hwnd;
+ this->hwndTT = CreateTooltip(this->hwndParent, this->rc);
+ }
+
+ void removeTooltip()
+ {
+ if (hwndTT == NULL)
+ return;
+
+ DestroyWindow(hwndTT);
+ hwndTT = NULL;
+ hwndParent = NULL;
+ }
+
+ const TCHAR * getTextFor(HWND hwndFrom)
+ {
+ if (hwndTT == NULL || hwndTT != hwndFrom)
+ return NULL;
+ return text.c_str();
+ }
+
+
+private:
+
+ HWND hwndTT;
+ RECT rc;
+ HWND hwndParent;
+ std::tstring text;
+
+ HWND CreateTooltip(HWND hwnd, RECT &rect)
+ {
+ // struct specifying control classes to register
+ INITCOMMONCONTROLSEX iccex;
+ HWND hwndTT; // handle to the ToolTip control
+ // struct specifying info about tool in ToolTip control
+ TOOLINFO ti;
+ unsigned int uid = 0; // for ti initialization
+
+ // Load the ToolTip class from the DLL.
+ iccex.dwSize = sizeof(iccex);
+ iccex.dwICC = ICC_BAR_CLASSES;
+
+ if(!InitCommonControlsEx(&iccex))
+ return NULL;
+
+ /* CREATE A TOOLTIP WINDOW */
+ hwndTT = CreateWindowEx(WS_EX_TOPMOST,
+ TOOLTIPS_CLASS,
+ NULL,
+ WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ CW_USEDEFAULT,
+ hwnd,
+ NULL,
+ hInst,
+ NULL
+ );
+
+ /* Gives problem with mToolTip
+ SetWindowPos(hwndTT,
+ HWND_TOPMOST,
+ 0,
+ 0,
+ 0,
+ 0,
+ SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
+ */
+
+ /* INITIALIZE MEMBERS OF THE TOOLINFO STRUCTURE */
+ ti.cbSize = sizeof(TOOLINFO);
+ ti.uFlags = TTF_SUBCLASS;
+ ti.hwnd = hwnd;
+ ti.hinst = hInst;
+ ti.uId = uid;
+ ti.lpszText = LPSTR_TEXTCALLBACK;
+ // ToolTip control will cover the whole window
+ ti.rect.left = rect.left;
+ ti.rect.top = rect.top;
+ ti.rect.right = rect.right;
+ ti.rect.bottom = rect.bottom;
+
+ /* SEND AN ADDTOOL MESSAGE TO THE TOOLTIP CONTROL WINDOW */
+ SendMessage(hwndTT, TTM_ADDTOOL, 0, (LPARAM) (LPTOOLINFO) &ti);
+ SendMessage(hwndTT, TTM_SETDELAYTIME, (WPARAM) (DWORD) TTDT_AUTOPOP, (LPARAM) MAKELONG(24 * 60 * 60 * 1000, 0));
+
+ return hwndTT;
+ }
+};
+
+
+struct SimpleItem
+{
+ RECT rc;
+ bool draw;
+ bool mouseOver;
+ ToolTipArea tt;
+ bool alignRight;
+
+ SimpleItem() : draw(FALSE), mouseOver(FALSE), alignRight(FALSE)
+ {
+ memset(&rc, 0, sizeof(rc));
+ }
+ virtual ~SimpleItem() {}
+
+ virtual void hide()
+ {
+ draw = false;
+ mouseOver = false;
+ tt.removeTooltip();
+ }
+
+ virtual void update(HWND hwnd, SkinFieldState *item)
+ {
+ draw = item->isVisible();
+ alignRight = ( item->getHorizontalAlign() == SKN_HALIGN_RIGHT );
+
+ if (draw)
+ {
+ rc = item->getRect();
+ tt.createTooltip(hwnd, rc, item->getToolTip());
+ }
+ else
+ {
+ tt.removeTooltip();
+ }
+ }
+
+ virtual bool hitTest(const POINT &p)
+ {
+ return draw && InsideRect(p, rc);
+ }
+
+ virtual const TCHAR * getToolTipFor(HWND hwndFrom)
+ {
+ return tt.getTextFor(hwndFrom);
+ }
+
+ bool setMouseOver(POINT *mousePos)
+ {
+ bool over = (mousePos != NULL && hitTest(*mousePos));
+
+ if (mouseOver == over)
+ return FALSE;
+
+ mouseOver = over;
+ return TRUE;
+ }
+
+};
+
+struct IconAndItem : public SimpleItem
+{
+ RECT rcIcon;
+ RECT rcItem;
+ BOOL drawIcon;
+ BOOL drawItem;
+ ToolTipArea ttIcon;
+
+ IconAndItem() : drawIcon(FALSE), drawItem(FALSE)
+ {
+ memset(&rcIcon, 0, sizeof(rcIcon));
+ memset(&rcItem, 0, sizeof(rcItem));
+ }
+ virtual ~IconAndItem() {}
+
+ virtual void hide()
+ {
+ SimpleItem::hide();
+ drawIcon = FALSE;
+ drawItem = FALSE;
+ }
+
+ virtual void update(HWND hwnd, SkinIconFieldState *icon, SkinTextFieldState *item)
+ {
+ drawIcon = icon->isVisible();
+ drawItem = item->isVisible();
+ alignRight = ( item->getHorizontalAlign() == SKN_HALIGN_RIGHT );
+
+ draw = drawIcon || drawItem;
+ if (draw)
+ {
+ if (drawIcon)
+ rcIcon = icon->getRect();
+ if (drawItem)
+ rcItem = item->getRect();
+
+ if (drawIcon && drawItem)
+ ExternalRect(rc, rcIcon, rcItem);
+ else if (drawIcon)
+ rc = rcIcon;
+ else // if (drawItem)
+ rc = rcItem;
+ }
+
+ if (drawItem)
+ tt.createTooltip(hwnd, rcItem, item->getToolTip());
+ else
+ tt.removeTooltip();
+
+ if (drawIcon)
+ ttIcon.createTooltip(hwnd, rcIcon, icon->getToolTip());
+ else
+ ttIcon.removeTooltip();
+ }
+
+ virtual const TCHAR * getToolTipFor(HWND hwndFrom)
+ {
+ const TCHAR * ret = tt.getTextFor(hwndFrom);
+
+ if (ret == NULL)
+ ret = ttIcon.getTextFor(hwndFrom);
+
+ return ret;
+ }
+};
+
+
+struct MyDetailsFrameData
+{
+ std::vector<SimpleItem*> items;
+ SimpleItem proto;
+ SimpleItem proto_cycle_next;
+ SimpleItem proto_cycle_prev;
+ SimpleItem avatar;
+ SimpleItem nick;
+ IconAndItem status;
+ SimpleItem away_msg;
+ IconAndItem listening_to;
+ IconAndItem email;
+
+ bool showing_menu;
+
+ bool tracking_exit;
+
+ MyDetailsFrameData()
+ : showing_menu(false)
+ , tracking_exit(false)
+ {
+ items.push_back(&proto);
+ items.push_back(&proto_cycle_next);
+ items.push_back(&proto_cycle_prev);
+ items.push_back(&avatar);
+ items.push_back(&nick);
+ items.push_back(&status);
+ items.push_back(&away_msg);
+ items.push_back(&listening_to);
+ items.push_back(&email);
+ }
+};
+
+
+
+// Functions //////////////////////////////////////////////////////////////////////////////////////
+
+void InitFrames()
+{
+ InitContactListSmileys();
+
+ CreateFrame();
+
+ HookEvent(ME_DB_CONTACT_SETTINGCHANGED, SettingsChangedHook);
+ HookEvent(ME_AV_MYAVATARCHANGED, AvatarChangedHook);
+ HookEvent(ME_PROTO_ACK, ProtoAckHook);
+ HookEvent(ME_SMILEYADD_OPTIONSCHANGED,SmileyAddOptionsChangedHook);
+ HookEvent(ME_LISTENINGTO_ENABLE_STATE_CHANGED,ListeningtoEnableStateChangedHook);
+ HookEvent(ME_PROTO_ACCLISTCHANGED, AccListChanged);
+}
+
+
+void DeInitFrames()
+{
+ if(ServiceExists(MS_CLIST_FRAMES_REMOVEFRAME) && frame_id != -1)
+ {
+ CallService(MS_CLIST_FRAMES_REMOVEFRAME, (WPARAM)frame_id, 0);
+ }
+
+ if (hwnd_frame != NULL) DestroyWindow(hwnd_frame);
+ if (hwnd_container != NULL) DestroyWindow(hwnd_container);
+}
+
+int SmileyAddOptionsChangedHook(WPARAM wParam,LPARAM lParam)
+{
+ UpdateFrameData();
+ return 0;
+}
+
+int SkinEngineDrawCallback(HWND hWnd, HDC hDC, RECT * rcPaint, HRGN rgn, DWORD dFlags, void * CallBackData);
+
+int CreateFrame()
+{
+ WNDCLASS wndclass;
+ wndclass.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW; //CS_PARENTDC | CS_HREDRAW | CS_VREDRAW;
+ wndclass.lpfnWndProc = FrameWindowProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = 0;
+ wndclass.hInstance = hInst;
+ wndclass.hIcon = NULL;
+ wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
+ wndclass.hbrBackground = 0; //(HBRUSH)(COLOR_3DFACE+1);
+ wndclass.lpszMenuName = NULL;
+ wndclass.lpszClassName = WINDOW_CLASS_NAME;
+ RegisterClass(&wndclass);
+
+ if (ServiceExists(MS_CLIST_FRAMES_ADDFRAME))
+ {
+ hwnd_frame = CreateWindow(WINDOW_CLASS_NAME, Translate("My Details"),
+ WS_CHILD | WS_VISIBLE,
+ 0,0,10,10, (HWND)CallService(MS_CLUI_GETHWND, 0, 0), NULL, hInst, NULL);
+
+ CLISTFrame Frame = {0};
+
+ Frame.cbSize = sizeof(Frame);
+ Frame.name = "My Details";
+ Frame.TBname = Translate("My Details");
+ Frame.hWnd = hwnd_frame;
+ Frame.align = alTop;
+ Frame.Flags = F_VISIBLE | F_SHOWTB | F_SHOWTBTIP | F_NOBORDER | F_NO_SUBCONTAINER;
+ Frame.height = 100;
+
+ frame_id = CallService(MS_CLIST_FRAMES_ADDFRAME, (WPARAM)&Frame, 0);
+
+ if (ServiceExists(MS_SKINENG_REGISTERPAINTSUB))
+ {
+ CallService(MS_BACKGROUNDCONFIG_REGISTER,(WPARAM)"My Details Background/MyDetails", 0);
+ CallService(MS_SKINENG_REGISTERPAINTSUB, (WPARAM) Frame.hWnd, (LPARAM) SkinEngineDrawCallback);
+ }
+
+ if (DBGetContactSettingByte(NULL, "MyDetails", "ForceHideFrame", 0))
+ {
+ int flags = CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS, MAKEWPARAM(FO_FLAGS, frame_id), 0);
+ if(flags & F_VISIBLE)
+ CallService(MS_CLIST_FRAMES_SHFRAME, frame_id, 0);
+
+ DBDeleteContactSetting(NULL, "MyDetails", "ForceHideFrame");
+ }
+
+ if (DBGetContactSettingByte(NULL, "MyDetails", "ForceShowFrame", 0))
+ {
+ int flags = CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS, MAKEWPARAM(FO_FLAGS, frame_id), 0);
+ if(!(flags & F_VISIBLE))
+ CallService(MS_CLIST_FRAMES_SHFRAME, frame_id, 0);
+
+ DBDeleteContactSetting(NULL, "MyDetails", "ForceShowFrame");
+ }
+ }
+ else
+ {
+ wndclass.style = CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW;//CS_HREDRAW | CS_VREDRAW;
+ wndclass.lpfnWndProc = FrameContainerWindowProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = 0;
+ wndclass.hInstance = hInst;
+ wndclass.hIcon = NULL;
+ wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
+ wndclass.hbrBackground = 0; //(HBRUSH)(COLOR_3DFACE+1);
+ wndclass.lpszMenuName = NULL;
+ wndclass.lpszClassName = CONTAINER_CLASS_NAME;
+ RegisterClass(&wndclass);
+
+ hwnd_container = CreateWindowEx(WS_EX_TOOLWINDOW, CONTAINER_CLASS_NAME, Translate("My Details"),
+ (WS_THICKFRAME | WS_CAPTION | WS_SYSMENU) & ~WS_VISIBLE,
+ 0,0,200,130, (HWND)CallService(MS_CLUI_GETHWND, 0, 0), NULL, hInst, NULL);
+
+ hwnd_frame = CreateWindow(WINDOW_CLASS_NAME, Translate("My Details"),
+ WS_CHILD | WS_VISIBLE,
+ 0,0,10,10, hwnd_container, NULL, hInst, NULL);
+
+ SetWindowLong(hwnd_container, GWL_USERDATA, (LONG)hwnd_frame);
+ SendMessage(hwnd_container, WM_SIZE, 0, 0);
+
+ // Create menu item
+
+ CLISTMENUITEM menu = {0};
+
+ menu.cbSize=sizeof(menu);
+ menu.flags = CMIM_ALL;
+ menu.popupPosition = -0x7FFFFFFF;
+ menu.pszPopupName = Translate("My Details");
+ menu.position = 1; // 500010000
+ menu.hIcon = LoadSkinnedIcon(SKINICON_OTHER_MIRANDA);
+ menu.pszName = Translate("Show My Details");
+ menu.pszService= MODULE_NAME "/ShowHideMyDetails";
+ hMenuShowHideFrame = (HANDLE)CallService(MS_CLIST_ADDMAINMENUITEM, 0, (LPARAM)&menu);
+
+ if(DBGetContactSettingByte(0, MODULE_NAME, SETTING_FRAME_VISIBLE, 1) == 1)
+ {
+ ShowWindow(hwnd_container, SW_SHOW);
+ FixMainMenu();
+ }
+ }
+
+ CreateServiceFunction(MS_MYDETAILS_SHOWFRAME, ShowFrameFunc);
+ CreateServiceFunction(MS_MYDETAILS_HIDEFRAME, HideFrameFunc);
+ CreateServiceFunction(MS_MYDETAILS_SHOWHIDEFRAME, ShowHideFrameFunc);
+
+ return 0;
+}
+
+
+BOOL FrameIsFloating()
+{
+ if (frame_id == -1)
+ {
+ return true; // no frames, always floating
+ }
+
+ return (CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS, MAKEWPARAM(FO_FLOATING, frame_id), 0) != 0);
+}
+
+
+LRESULT CALLBACK FrameContainerWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
+ switch(msg)
+ {
+ case WM_SHOWWINDOW:
+ {
+ if ((BOOL)wParam)
+ Utils_RestoreWindowPosition(hwnd, 0, MODULE_NAME, WINDOW_NAME_PREFIX);
+ else
+ Utils_SaveWindowPosition(hwnd, 0, MODULE_NAME, WINDOW_NAME_PREFIX);
+ break;
+ }
+
+ case WM_ERASEBKGND:
+ {
+ HWND child = (HWND)GetWindowLong(hwnd, GWL_USERDATA);
+
+ SendMessage(child, WM_ERASEBKGND, wParam, lParam);
+ break;
+ }
+
+ case WM_SIZE:
+ {
+ HWND child = (HWND)GetWindowLong(hwnd, GWL_USERDATA);
+ RECT r;
+ GetClientRect(hwnd, &r);
+
+ SetWindowPos(child, 0, r.left, r.top, r.right - r.left, r.bottom - r.top, SWP_NOZORDER | SWP_NOACTIVATE);
+ InvalidateRect(child, NULL, TRUE);
+
+ return TRUE;
+ }
+
+ case WM_CLOSE:
+ {
+ DBWriteContactSettingByte(0, MODULE_NAME, SETTING_FRAME_VISIBLE, 0);
+ ShowWindow(hwnd, SW_HIDE);
+ FixMainMenu();
+ return TRUE;
+ }
+ }
+
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+}
+
+
+
+BOOL ScreenToClient(HWND hWnd, LPRECT lpRect)
+{
+ BOOL ret;
+
+ POINT pt;
+
+ pt.x = lpRect->left;
+ pt.y = lpRect->top;
+
+ ret = ScreenToClient(hWnd, &pt);
+
+ if (!ret) return ret;
+
+ lpRect->left = pt.x;
+ lpRect->top = pt.y;
+
+
+ pt.x = lpRect->right;
+ pt.y = lpRect->bottom;
+
+ ret = ScreenToClient(hWnd, &pt);
+
+ lpRect->right = pt.x;
+ lpRect->bottom = pt.y;
+
+ return ret;
+}
+
+
+BOOL MoveWindow(HWND hWnd, const RECT &rect, BOOL bRepaint)
+{
+ return MoveWindow(hWnd, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, bRepaint);
+}
+
+
+RECT GetInnerRect(const RECT &rc, const RECT &clipping)
+{
+ RECT rc_ret = rc;
+
+ rc_ret.left = max(rc.left, clipping.left);
+ rc_ret.top = max(rc.top, clipping.top);
+ rc_ret.right = min(rc.right, clipping.right);
+ rc_ret.bottom = min(rc.bottom, clipping.bottom);
+
+ return rc_ret;
+}
+
+
+
+
+
+void ExternalRect(RECT &ret, const RECT r1, const RECT r2)
+{
+ ret.left = min(r1.left, r2.left);
+ ret.right = max(r1.right, r2.right);
+ ret.top = min(r1.top, r2.top);
+ ret.bottom = max(r1.bottom, r2.bottom);
+}
+
+
+HBITMAP CreateBitmap32(int cx, int cy)
+{
+ BITMAPINFO RGB32BitsBITMAPINFO;
+ UINT * ptPixels;
+ HBITMAP DirectBitmap;
+
+ ZeroMemory(&RGB32BitsBITMAPINFO,sizeof(BITMAPINFO));
+ RGB32BitsBITMAPINFO.bmiHeader.biSize=sizeof(BITMAPINFOHEADER);
+ RGB32BitsBITMAPINFO.bmiHeader.biWidth=cx;//bm.bmWidth;
+ RGB32BitsBITMAPINFO.bmiHeader.biHeight=cy;//bm.bmHeight;
+ RGB32BitsBITMAPINFO.bmiHeader.biPlanes=1;
+ RGB32BitsBITMAPINFO.bmiHeader.biBitCount=32;
+
+ DirectBitmap = CreateDIBSection(NULL,
+ (BITMAPINFO *)&RGB32BitsBITMAPINFO,
+ DIB_RGB_COLORS,
+ (void **)&ptPixels,
+ NULL, 0);
+ return DirectBitmap;
+}
+
+
+BOOL UseLayeredMode()
+{
+ return isLayeredEnabled() && !FrameIsFloating();
+}
+
+
+void EraseBackground(HWND hwnd, HDC hdc)
+{
+ RECT r;
+ GetClientRect(hwnd, &r);
+
+ if (isSkinEngineEnabled())
+ {
+ if (FrameIsFloating())
+ {
+ HBRUSH hB = CreateSolidBrush(opts.bkg_color);
+ FillRect(hdc, &r, hB);
+ DeleteObject(hB);
+ }
+ else
+ {
+ SkinDrawWindowBack(hwnd, hdc, &r, "Main,ID=Background");
+ }
+
+ SkinDrawGlyph(hdc, &r, &r,"MyDetails,ID=Background");
+ }
+ else
+ {
+ HBRUSH hB = CreateSolidBrush(opts.bkg_color);
+ FillRect(hdc, &r, hB);
+ DeleteObject(hB);
+ }
+}
+
+static int Width(const RECT &rc)
+{
+ return rc.right - rc.left;
+}
+
+static int Height(const RECT &rc)
+{
+ return rc.bottom - rc.top;
+}
+
+static HICON CreateOverlayedIcon(HICON icon, HICON overlay)
+{
+ HIMAGELIST il = ImageList_Create(
+ GetSystemMetrics(SM_CXICON),
+ GetSystemMetrics(SM_CYICON),
+ ILC_COLOR32|ILC_MASK, 2, 2);
+ ImageList_AddIcon(il, icon);
+ ImageList_AddIcon(il, overlay);
+ HIMAGELIST newImage = ImageList_Merge(il,0,il,1,0,0);
+ ImageList_Destroy(il);
+ HICON hIcon = ImageList_GetIcon(newImage, 0, 0);
+ ImageList_Destroy(newImage);
+ return hIcon; // the result should be destroyed by DestroyIcon()
+}
+
+void Draw(HDC hdc, SkinIconFieldState &state)
+{
+ if (!state.isVisible())
+ return;
+
+ RECT rc = state.getInsideRect();
+ HRGN rgn = CreateRectRgnIndirect(&rc);
+ SelectClipRgn(hdc, rgn);
+
+ rc = state.getInsideRect(true);
+
+ skin_DrawIconEx(hdc, rc.left, rc.top, state.getIcon(), Width(rc), Height(rc), 0, NULL, DI_NORMAL);
+
+ SelectClipRgn(hdc, NULL);
+ DeleteObject(rgn);
+}
+
+void Draw(HDC hdc, SkinTextFieldState &state, BOOL replace_smileys = FALSE, const char *protocol = NULL)
+{
+ if (!state.isVisible())
+ return;
+
+ RECT rc = state.getInsideRect();
+ HRGN rgn = CreateRectRgnIndirect(&rc);
+ SelectClipRgn(hdc, rgn);
+
+ HGDIOBJ oldFont = SelectObject(hdc, state.getFont());
+ COLORREF oldColor = SetTextColor(hdc, state.getFontColor());
+
+ UINT uFormat = DT_NOPREFIX | DT_END_ELLIPSIS | (opts.draw_text_rtl ? DT_RTLREADING : 0);
+
+ switch(state.getHorizontalAlign())
+ {
+ case SKN_HALIGN_RIGHT:
+ uFormat |= DT_RIGHT;
+ break;
+ case SKN_HALIGN_CENTER:
+ uFormat |= DT_CENTER;
+ break;
+ case SKN_HALIGN_LEFT:
+ uFormat |= DT_LEFT;
+ break;
+ }
+
+ if (replace_smileys && opts.replace_smileys)
+ {
+ uFormat |= DT_SINGLELINE;
+
+ // Draw only first line of text
+ char *tmp = strdup(state.getText());
+ char *pos = strchr(tmp, '\r');
+ if (pos != NULL)
+ pos[0] = '\0';
+ pos = strchr(tmp, '\n');
+ if (pos != NULL)
+ pos[0] = '\0';
+
+ Smileys_DrawText(hdc, tmp, -1, &rc, uFormat | (opts.resize_smileys ? DT_RESIZE_SMILEYS : 0),
+ opts.use_contact_list_smileys ? "clist" : protocol, NULL);
+ }
+ else
+ {
+ skin_DrawText(hdc, state.getText(), -1, &rc, uFormat);
+ }
+
+
+ SelectObject(hdc, oldFont);
+ SetTextColor(hdc, oldColor);
+
+ SelectClipRgn(hdc, NULL);
+ DeleteObject(rgn);
+}
+
+
+void DrawMouseOver(HDC hdc, RECT *lprc, const char *place)
+{
+ if (isSkinEngineEnabled())
+ {
+ SkinDrawGlyph(hdc, lprc, lprc, "MyDetails,ID=MouseOver");
+
+ char glyph[1024];
+ mir_snprintf(glyph, MAX_REGS(glyph), "MyDetails,ID=MouseOver%s", place);
+ SkinDrawGlyph(hdc, lprc, lprc, glyph);
+ }
+ else
+ {
+ FrameRect(hdc, lprc, (HBRUSH) GetStockObject(GRAY_BRUSH));
+ }
+}
+
+
+void Draw(HWND hwnd, HDC hdc_orig)
+{
+ MyDetailsFrameData *data = (MyDetailsFrameData *) GetWindowLong(hwnd, GWL_USERDATA);
+
+ Protocol *proto = GetCurrentProtocol();
+ if (proto == NULL)
+ {
+ EraseBackground(hwnd, hdc_orig);
+ return;
+ }
+
+ if (ServiceExists(MS_CLIST_FRAMES_SETFRAMEOPTIONS) && frame_id != -1)
+ {
+ int flags = CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS, MAKEWPARAM(FO_FLAGS, frame_id), 0);
+ if(flags & F_UNCOLLAPSED)
+ {
+ RECT rf;
+ GetClientRect(hwnd, &rf);
+
+ if (rf.bottom - rf.top != 0)
+ {
+ if (FrameIsFloating())
+ {
+ HWND parent = GetParent(hwnd);
+
+ if (parent != NULL)
+ {
+ RECT rp_client, rp_window, r_window;
+ GetClientRect(parent, &rp_client);
+ GetWindowRect(parent, &rp_window);
+ GetWindowRect(hwnd, &r_window);
+ int diff = (rp_window.bottom - rp_window.top) - (rp_client.bottom - rp_client.top);
+ if(ServiceExists(MS_CLIST_FRAMES_ADDFRAME))
+ diff += (r_window.top - rp_window.top);
+
+ SetWindowPos(parent, 0, 0, 0, rp_window.right - rp_window.left, diff, SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
+ }
+ }
+ }
+
+ for (size_t i = 0; i < data->items.size(); ++i)
+ data->items[i]->hide();
+
+ return;
+ }
+ }
+
+
+ RECT r_full;
+ GetClientRect(hwnd, &r_full);
+
+ HDC hdc;
+ HBITMAP hBmp;
+ BOOL useLayeredMode = UseLayeredMode();
+ if (useLayeredMode)
+ {
+ hdc = hdc_orig;
+ hBmp = NULL;
+ }
+ else
+ {
+ hdc = CreateCompatibleDC(hdc_orig);
+ hBmp = CreateBitmap32(Width(r_full), Height(r_full));
+ SelectObject(hdc, hBmp);
+ }
+
+ int old_bk_mode = SetBkMode(hdc, TRANSPARENT);
+ HFONT old_font = (HFONT) GetCurrentObject(hdc, OBJ_FONT);
+ COLORREF old_color = GetTextColor(hdc);
+ SetStretchBltMode(hdc, HALFTONE);
+
+
+ HICON hStatusIcon;
+ bool freeStatusIcon = false;
+ if (proto->GetCustomStatus() != 0 && proto->CanCall(PS_ICQ_GETCUSTOMSTATUSICON))
+ hStatusIcon = (HICON) proto->Call(PS_ICQ_GETCUSTOMSTATUSICON, proto->GetCustomStatus(), LR_SHARED);
+ else
+ hStatusIcon = LoadSkinnedProtoIcon(proto->GetName(), proto->GetStatus());
+
+ if (proto->IsLocked())
+ {
+ HICON hLockOverlay = LoadSkinnedIcon(SKINICON_OTHER_STATUS_LOCKED);
+ if (hLockOverlay != NULL)
+ {
+ freeStatusIcon = true;
+ hStatusIcon = CreateOverlayedIcon(hStatusIcon, hLockOverlay);
+ }
+ }
+
+
+ HICON hListeningIcon = IcoLib_LoadIcon("LISTENING_TO_ICON");
+ HICON hEmailIcon = IcoLib_LoadIcon("MYDETAILS_EMAIL");
+ HICON hNextIcon = IcoLib_LoadIcon("MYDETAILS_NEXT_PROTOCOL");
+ HICON hPrevIcon = IcoLib_LoadIcon("MYDETAILS_PREV_PROTOCOL");
+
+ {
+ dialog->setInfoBool("resize_frame", opts.resize_frame);
+ dialog->setInfoBool("protocol.locked", proto->IsLocked());
+
+
+ if (opts.resize_frame)
+ dialog->setSize(Width(r_full), 0x1FFFFFFF);
+ else
+ dialog->setSize(Width(r_full), Height(r_full));
+
+
+
+ SkinImageField avatar = dialog->getImageField("avatar");
+ if (proto->CanGetAvatar() && proto->GetAvatarImage() != NULL)
+ {
+ avatar.setEnabled(TRUE);
+ avatar.setImage(proto->GetAvatarImage());
+ }
+ else
+ {
+ avatar.setEnabled(FALSE);
+ avatar.setImage(NULL);
+ }
+
+ SkinTextField nickname = dialog->getTextField("nickname");
+ nickname.setText(proto->GetNick());
+
+ SkinTextField protocol = dialog->getTextField("protocol");
+ protocol.setText(proto->GetDescription());
+
+ SkinIconField status_icon = dialog->getIconField("status_icon");
+ status_icon.setIcon(hStatusIcon);
+
+ SkinTextField status_name = dialog->getTextField("status_name");
+ status_name.setText(proto->GetStatusName());
+
+ SkinTextField status_msg = dialog->getTextField("status_msg");
+ if (proto->CanGetStatusMsg())
+ {
+ status_msg.setEnabled(TRUE);
+ status_msg.setText(proto->GetStatusMsg());
+ }
+ else
+ {
+ status_msg.setEnabled(FALSE);
+ status_msg.setText(_T(""));
+ }
+
+ SkinIconField listening_icon = dialog->getIconField("listening_icon");
+ SkinTextField listening = dialog->getTextField("listening");
+ if (proto->ListeningToEnabled() && proto->GetStatus() > ID_STATUS_OFFLINE
+ && proto->GetListeningTo()[0] != 0)
+ {
+ listening_icon.setEnabled(TRUE);
+ listening.setEnabled(TRUE);
+ listening_icon.setIcon(hListeningIcon);
+ listening.setText(proto->GetListeningTo());
+ }
+ else
+ {
+ listening_icon.setEnabled(FALSE);
+ listening.setEnabled(FALSE);
+ listening_icon.setIcon(NULL);
+ listening.setText(_T(""));
+ }
+
+ SkinIconField email_icon = dialog->getIconField("email_icon");
+ SkinTextField email = dialog->getTextField("email");
+ if (proto->CanGetEmailCount())
+ {
+ email_icon.setEnabled(TRUE);
+ email.setEnabled(TRUE);
+ email_icon.setIcon(hEmailIcon);
+
+ TCHAR tmp[64];
+ _sntprintf(tmp, MAX_REGS(tmp), _T("%d"), proto->GetEmailCount());
+ email.setText(tmp);
+ }
+ else
+ {
+ email_icon.setEnabled(FALSE);
+ email.setEnabled(FALSE);
+ email_icon.setIcon(NULL);
+ email.setText(_T(""));
+ }
+
+ SkinIconField next_proto = dialog->getIconField("next_proto");
+ SkinIconField prev_proto = dialog->getIconField("prev_proto");
+ prev_proto.setIcon(hPrevIcon);
+ next_proto.setIcon(hNextIcon);
+ }
+
+ SkinDialogState state = dialog->run();
+ SkinImageFieldState avatar = state.getImageField("avatar");
+ SkinTextFieldState nickname = state.getTextField("nickname");
+ SkinTextFieldState protocol = state.getTextField("protocol");
+ SkinIconFieldState status_icon = state.getIconField("status_icon");
+ SkinTextFieldState status_name = state.getTextField("status_name");
+ SkinTextFieldState status_msg = state.getTextField("status_msg");
+ SkinIconFieldState listening_icon = state.getIconField("listening_icon");
+ SkinTextFieldState listening = state.getTextField("listening");
+ SkinIconFieldState email_icon = state.getIconField("email_icon");
+ SkinTextFieldState email = state.getTextField("email");
+ SkinIconFieldState next_proto = state.getIconField("next_proto");
+ SkinIconFieldState prev_proto = state.getIconField("prev_proto");
+
+
+ {
+ data->proto.update(hwnd, &protocol);
+ data->proto_cycle_next.update(hwnd, &next_proto);
+ data->proto_cycle_prev.update(hwnd, &prev_proto);
+ data->avatar.update(hwnd, &avatar);
+ data->nick.update(hwnd, &nickname);
+ data->status.update(hwnd, &status_icon, &status_name);
+ data->away_msg.update(hwnd, &status_msg);
+ data->listening_to.update(hwnd, &listening_icon, &listening);
+ data->email.update(hwnd, &email_icon, &email);
+
+
+ POINT p = {0};
+ GetCursorPos(&p);
+ ScreenToClient(hwnd, &p);
+
+ for(size_t i = 0; i < data->items.size(); ++i)
+ data->items[i]->setMouseOver(&p);
+ }
+
+ // Erase
+ EraseBackground(hwnd, hdc);
+
+ // Draw items
+
+ UINT uFormat = DT_SINGLELINE | DT_NOPREFIX | DT_END_ELLIPSIS
+ | (opts.draw_text_rtl ? DT_RTLREADING : 0);
+
+ // Image
+ if (avatar.isVisible() && proto->CanGetAvatar() && proto->GetAvatarImage() != NULL)
+ {
+ RECT rc = avatar.getInsideRect();
+ HRGN rgn = CreateRectRgnIndirect(&rc);
+ SelectClipRgn(hdc, rgn);
+
+ rc = avatar.getInsideRect(true);
+
+ int width = Width(rc);
+ int height = Height(rc);
+
+ int round_radius;
+ if (opts.draw_avatar_round_corner)
+ {
+ if (opts.draw_avatar_use_custom_corner_size)
+ round_radius = opts.draw_avatar_custom_corner_size;
+ else
+ round_radius = min(width, height) / 6;
+ }
+ else
+ {
+ round_radius = 0;
+ }
+
+
+ AVATARDRAWREQUEST adr = {0};
+
+ adr.cbSize = sizeof(AVATARDRAWREQUEST);
+ adr.hTargetDC = hdc;
+ adr.rcDraw = rc;
+
+ adr.dwFlags = AVDRQ_OWNPIC | AVDRQ_HIDEBORDERONTRANSPARENCY |
+ (opts.draw_avatar_border ? AVDRQ_DRAWBORDER : 0 ) |
+ (opts.draw_avatar_round_corner ? AVDRQ_ROUNDEDCORNER : 0 );
+
+ if (useLayeredMode)
+ adr.dwFlags |= AVDRQ_AERO;
+
+ adr.clrBorder = opts.draw_avatar_border_color;
+ adr.radius = round_radius;
+ adr.alpha = 255;
+ adr.szProto = (char *) proto->GetName();
+
+ CallService(MS_AV_DRAWAVATAR, 0, (LPARAM) &adr);
+
+ // Clipping rgn
+ SelectClipRgn(hdc, NULL);
+ DeleteObject(rgn);
+ }
+
+ // Nick
+ if (data->nick.draw && data->nick.mouseOver && proto->CanSetNick())
+ DrawMouseOver(hdc, &nickname.getRect(), "Nick");
+
+ Draw(hdc, nickname, TRUE, proto->GetName());
+
+
+ // Protocol
+ if (data->proto.draw && data->proto.mouseOver)
+ DrawMouseOver(hdc, &data->proto.rc, "Proto");
+
+ Draw(hdc, protocol);
+
+
+ // Status
+ if (data->status.draw && data->status.mouseOver)
+ DrawMouseOver(hdc, &data->status.rc, "Status");
+
+ Draw(hdc, status_icon);
+ Draw(hdc, status_name);
+
+
+ // Away message
+ if (data->away_msg.draw && data->away_msg.mouseOver && proto->CanSetStatusMsg())
+ DrawMouseOver(hdc, &data->away_msg.rc, "StatusMsg");
+
+ Draw(hdc, status_msg, TRUE, proto->GetName());
+
+
+ // Listening to
+ Draw(hdc, listening_icon);
+ Draw(hdc, listening);
+
+ if (data->listening_to.draw && data->listening_to.mouseOver && protocols->CanSetListeningTo())
+ DrawMouseOver(hdc, &data->listening_to.rc, "Listening");
+
+
+ // Unread email count
+ Draw(hdc, email_icon);
+ Draw(hdc, email);
+
+ // Protocol cycle icon
+ Draw(hdc, next_proto);
+ Draw(hdc, prev_proto);
+
+
+ SelectObject(hdc, old_font);
+ SetTextColor(hdc, old_color);
+ SetBkMode(hdc, old_bk_mode);
+
+ if (!useLayeredMode)
+ {
+ BitBlt(hdc_orig, r_full.left, r_full.top, r_full.right - r_full.left,
+ r_full.bottom - r_full.top, hdc, r_full.left, r_full.top, SRCCOPY);
+ DeleteDC(hdc);
+ DeleteObject(hBmp);
+ }
+
+ if (freeStatusIcon)
+ DestroyIcon(hStatusIcon);
+ IcoLib_ReleaseIcon(hListeningIcon);
+ IcoLib_ReleaseIcon(hEmailIcon);
+ IcoLib_ReleaseIcon(hPrevIcon);
+ IcoLib_ReleaseIcon(hNextIcon);
+
+ if (opts.resize_frame && ServiceExists(MS_CLIST_FRAMES_SETFRAMEOPTIONS) && frame_id != -1)
+ {
+ RECT rf;
+ GetClientRect(hwnd, &rf);
+
+ int currentSize = Height(r_full);
+
+ int expectedSize = 0;
+ for(size_t i = 0; i < data->items.size(); ++i)
+ {
+ SimpleItem *item = data->items[i];
+ if (!item->draw)
+ continue;
+
+ expectedSize = max(expectedSize, item->rc.bottom);
+ }
+ expectedSize += state.getBorders().bottom;
+
+ if (expectedSize != currentSize)
+ {
+ if (FrameIsFloating())
+ {
+ HWND parent = GetParent(hwnd);
+
+ if (parent != NULL)
+ {
+ RECT rp_client, rp_window, r_window;
+ GetClientRect(parent, &rp_client);
+ GetWindowRect(parent, &rp_window);
+ GetWindowRect(hwnd, &r_window);
+ int diff = (rp_window.bottom - rp_window.top) - (rp_client.bottom - rp_client.top);
+ if(ServiceExists(MS_CLIST_FRAMES_ADDFRAME))
+ diff += (r_window.top - rp_window.top);
+
+ SetWindowPos(parent, 0, 0, 0, rp_window.right - rp_window.left, expectedSize + diff, SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
+ }
+ }
+ else if (IsWindowVisible(hwnd) && ServiceExists(MS_CLIST_FRAMES_ADDFRAME))
+ {
+ int flags = CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS, MAKEWPARAM(FO_FLAGS, frame_id), 0);
+ if(flags & F_VISIBLE)
+ {
+ CallService(MS_CLIST_FRAMES_SETFRAMEOPTIONS, MAKEWPARAM(FO_HEIGHT, frame_id), (LPARAM) expectedSize);
+ CallService(MS_CLIST_FRAMES_UPDATEFRAME, (WPARAM)frame_id, (LPARAM)(FU_TBREDRAW | FU_FMREDRAW | FU_FMPOS));
+ }
+ }
+ }
+ }
+}
+
+int SkinEngineDrawCallback(HWND hWnd, HDC hDC, RECT * rcPaint, HRGN rgn, DWORD dFlags, void * CallBackData)
+{
+ Draw(hWnd, hDC);
+ return 0;
+}
+
+bool InsideRect(const POINT &p, const RECT &r)
+{
+ return p.x >= r.left && p.x < r.right && p.y >= r.top && p.y < r.bottom;
+}
+
+int ShowPopupMenu(HWND hwnd, HMENU submenu, SimpleItem &item)
+{
+ POINT p;
+ if (item.alignRight)
+ p.x = item.rc.right;
+ else
+ p.x = item.rc.left;
+ p.y = item.rc.bottom+1;
+ ClientToScreen(hwnd, &p);
+
+ return TrackPopupMenu(submenu, TPM_TOPALIGN|TPM_RIGHTBUTTON|TPM_RETURNCMD
+ | (item.alignRight ? TPM_RIGHTALIGN : TPM_LEFTALIGN), p.x, p.y, 0, hwnd, NULL);
+}
+
+
+void ShowGlobalStatusMenu(HWND hwnd, MyDetailsFrameData *data, Protocol *proto, POINT &p)
+{
+ HMENU submenu = (HMENU) CallService(MS_CLIST_MENUGETSTATUS,0,0);
+
+ int ret = ShowPopupMenu(hwnd, submenu, data->status);
+ if(ret)
+ CallService(MS_CLIST_MENUPROCESSCOMMAND, MAKEWPARAM(LOWORD(ret),MPCF_MAINMENU),(LPARAM)NULL);
+}
+
+void ShowProtocolStatusMenu(HWND hwnd, MyDetailsFrameData *data, Protocol *proto, POINT &p)
+{
+ HMENU menu = (HMENU) CallService(MS_CLIST_MENUGETSTATUS,0,0);
+ HMENU submenu = NULL;
+
+ if (menu != NULL)
+ {
+ // Find the correct menu item
+ int count = GetMenuItemCount(menu);
+ for (int i = 0 ; i < count && submenu == NULL; i++)
+ {
+ MENUITEMINFO mii = {0};
+
+ mii.cbSize = sizeof(mii);
+
+ if(!IsWinVer98Plus())
+ {
+ mii.fMask = MIIM_TYPE;
+ }
+ else
+ {
+ mii.fMask = MIIM_STRING;
+ }
+
+ GetMenuItemInfo(menu, i, TRUE, &mii);
+
+ if (mii.cch != 0)
+ {
+ mii.cch++;
+ mii.dwTypeData = (char *)malloc(sizeof(char) * mii.cch);
+ GetMenuItemInfo(menu, i, TRUE, &mii);
+
+ if (strcmp(mii.dwTypeData, proto->GetDescription()) == 0)
+ {
+ submenu = GetSubMenu(menu, i);
+ }
+
+ free(mii.dwTypeData);
+ }
+ }
+
+ if (submenu == NULL && GetNumProtocols() == 1)
+ {
+ submenu = menu;
+ }
+ }
+
+ if (submenu != NULL)
+ {
+ int ret = ShowPopupMenu(hwnd, submenu, data->status);
+ if(ret)
+ CallService(MS_CLIST_MENUPROCESSCOMMAND, MAKEWPARAM(LOWORD(ret),MPCF_MAINMENU),(LPARAM)NULL);
+ }
+ else
+ {
+ // Well, lets do it by hand
+ static int statusModePf2List[]={0xFFFFFFFF,PF2_ONLINE,PF2_SHORTAWAY,PF2_LONGAWAY,PF2_LIGHTDND,PF2_HEAVYDND,PF2_FREECHAT,PF2_INVISIBLE,PF2_ONTHEPHONE,PF2_OUTTOLUNCH};
+
+ menu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_MENU1));
+ submenu = GetSubMenu(menu, 0);
+ CallService(MS_LANGPACK_TRANSLATEMENU,(WPARAM)submenu,0);
+
+ DWORD flags = proto->Call(PS_GETCAPS, PFLAGNUM_2);
+ for ( int i = GetMenuItemCount(submenu) -1 ; i >= 0 ; i-- )
+ {
+ if (!(flags & statusModePf2List[i]))
+ {
+ // Hide menu
+ RemoveMenu(submenu, i, MF_BYPOSITION);
+ }
+ }
+
+ int ret = ShowPopupMenu(hwnd, submenu, data->status);
+ DestroyMenu(menu);
+
+ if(ret)
+ proto->SetStatus(ret);
+ }
+}
+
+void ShowListeningToMenu(HWND hwnd, MyDetailsFrameData *data, Protocol *proto, POINT &p)
+{
+ HMENU menu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_MENU1));
+ HMENU submenu = GetSubMenu(menu, 5);
+ CallService(MS_LANGPACK_TRANSLATEMENU,(WPARAM)submenu,0);
+
+ // Add this proto to menu
+ char tmp[128];
+ mir_snprintf(tmp, sizeof(tmp), Translate("Enable Listening To for %s"), proto->GetDescription());
+
+ MENUITEMINFO mii = {0};
+ mii.cbSize = sizeof(mii);
+ mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
+ mii.fType = MFT_STRING;
+ mii.fState = proto->ListeningToEnabled() ? MFS_CHECKED : 0;
+ mii.dwTypeData = tmp;
+ mii.cch = strlen(tmp);
+ mii.wID = 1;
+
+ if (!proto->CanSetListeningTo())
+ {
+ mii.fState |= MFS_DISABLED;
+ }
+
+ InsertMenuItem(submenu, 0, TRUE, &mii);
+
+ ZeroMemory(&mii, sizeof(mii));
+ mii.cbSize = sizeof(mii);
+ mii.fMask = MIIM_STATE;
+ mii.fState = protocols->ListeningToEnabled() ? MFS_CHECKED : 0;
+
+ if (!protocols->CanSetListeningTo())
+ {
+ mii.fState |= MFS_DISABLED;
+ }
+
+ SetMenuItemInfo(submenu, ID_LISTENINGTOPOPUP_SENDLISTENINGTO, FALSE, &mii);
+
+ int ret = ShowPopupMenu(hwnd, submenu, data->listening_to);
+
+ DestroyMenu(menu);
+
+ switch(ret)
+ {
+ case 1:
+ {
+ CallService(MS_LISTENINGTO_ENABLE, (LPARAM) proto->GetName(), !proto->ListeningToEnabled());
+ break;
+ }
+ case ID_LISTENINGTOPOPUP_SENDLISTENINGTO:
+ {
+ CallService(MS_LISTENINGTO_ENABLE, 0, !protocols->ListeningToEnabled());
+ break;
+ }
+ }
+
+}
+
+
+LRESULT CALLBACK FrameWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch(msg)
+ {
+ case WM_CREATE:
+ {
+ MyDetailsFrameData *data = new MyDetailsFrameData();
+ SetWindowLong(hwnd, GWL_USERDATA, (LONG) data);
+
+ SetCurrentProtocol(DBGetContactSettingWord(NULL, "MyDetails", "ProtocolNumber", 0));
+
+ SetCycleTime(hwnd);
+
+ SetStatusMessageRefreshTime(hwnd);
+
+ return TRUE;
+ }
+
+
+ case WM_ERASEBKGND:
+ {
+ //EraseBackground(hwnd, (HDC)wParam);
+ //Draw(hwnd, (HDC)wParam);
+ return TRUE;
+ }
+
+ /*
+ case WM_PRINTCLIENT:
+ {
+ Draw(hwnd, (HDC)wParam);
+ return TRUE;
+ }
+ */
+
+ case WM_PAINT:
+ {
+ if (UseLayeredMode())
+ {
+ CallService(MS_SKINENG_INVALIDATEFRAMEIMAGE, (WPARAM) hwnd, 0);
+ ValidateRect(hwnd, NULL);
+ }
+ else
+ {
+ RECT r;
+ if(GetUpdateRect(hwnd, &r, FALSE))
+ {
+ PAINTSTRUCT ps;
+
+ HDC hdc = BeginPaint(hwnd, &ps);
+ Draw(hwnd, hdc);
+ EndPaint(hwnd, &ps);
+ }
+ }
+
+ return TRUE;
+ }
+
+ case WM_SIZE:
+ {
+ //InvalidateRect(hwnd, NULL, FALSE);
+ MyDetailsFrameData *data = (MyDetailsFrameData *)GetWindowLong(hwnd, GWL_USERDATA);
+ RedrawFrame();
+ break;
+ }
+
+ case WM_TIMER:
+ {
+ MyDetailsFrameData *data = (MyDetailsFrameData *)GetWindowLong(hwnd, GWL_USERDATA);
+
+ if (wParam == ID_FRAME_TIMER)
+ {
+ if (!data->showing_menu)
+ CallService(MS_MYDETAILS_SHOWNEXTPROTOCOL, 0, 0);
+ }
+ else if (wParam == ID_RECALC_TIMER)
+ {
+ KillTimer(hwnd, ID_RECALC_TIMER);
+
+ PostMessage(hwnd, MWM_REFRESH_DATA, 0, 0);
+ }
+ else if (wParam == ID_STATUSMESSAGE_TIMER)
+ {
+ SetStatusMessageRefreshTime(hwnd);
+
+ PostMessage(hwnd, MWM_REFRESH_DATA, 0, 0);
+ }
+
+ return TRUE;
+ }
+
+ case WM_LBUTTONUP:
+ {
+ MyDetailsFrameData *data = (MyDetailsFrameData *)GetWindowLong(hwnd, GWL_USERDATA);
+ Protocol *proto = GetCurrentProtocol();
+ if (proto == NULL)
+ break;
+
+ POINT p;
+ p.x = LOWORD(lParam);
+ p.y = HIWORD(lParam);
+
+ // In proto cycle button?
+ if (data->proto_cycle_next.hitTest(p))
+ {
+ CallService(MS_MYDETAILS_SHOWNEXTPROTOCOL, 0, 0);
+ }
+ else if (data->proto_cycle_prev.hitTest(p))
+ {
+ CallService(MS_MYDETAILS_SHOWPREVIOUSPROTOCOL, 0, 0);
+ }
+ // In image?
+ else if (data->avatar.hitTest(p) && proto->CanSetAvatar())
+ {
+ if (opts.global_on_avatar)
+ CallService(MS_MYDETAILS_SETMYAVATARUI, 0, 0);
+ else
+ CallService(MS_MYDETAILS_SETMYAVATARUI, 0, (LPARAM) proto->GetName());
+ }
+ // In nick?
+ else if (data->nick.hitTest(p) && proto->CanSetNick())
+ {
+ if (opts.global_on_nickname)
+ CallService(MS_MYDETAILS_SETMYNICKNAMEUI, 0, 0);
+ else
+ CallService(MS_MYDETAILS_SETMYNICKNAMEUI, 0, (LPARAM) proto->GetName());
+ }
+ // In status message?
+ else if (data->away_msg.hitTest(p) && proto->CanSetStatusMsg())
+ {
+ if (opts.global_on_status_message)
+ CallService(MS_MYDETAILS_SETMYSTATUSMESSAGEUI, 0, 0);
+ else
+ CallService(MS_MYDETAILS_SETMYSTATUSMESSAGEUI, 0, (LPARAM) proto->GetName());
+ }
+ // In status?
+ else if (data->status.hitTest(p))
+ {
+ data->showing_menu = true;
+
+ if (opts.global_on_status)
+ ShowGlobalStatusMenu(hwnd, data, proto, p);
+ else
+ ShowProtocolStatusMenu(hwnd, data, proto, p);
+
+ data->showing_menu = false;
+ }
+ // In listening to?
+ else if (data->listening_to.hitTest(p) && protocols->CanSetListeningTo())
+ {
+ ShowListeningToMenu(hwnd, data, proto, p);
+ }
+ // In protocol?
+ else if (data->proto.hitTest(p))
+ {
+ data->showing_menu = true;
+
+ HMENU menu = CreatePopupMenu();
+
+ std::vector<Protocol> protos;
+ GetProtocols(&protos);
+
+ int current = GetCurrentProtocolIndex();
+
+ int protosSize = (int) protos.size();
+ for (int i = protosSize - 1 ; i >= 0 ; i--)
+ {
+ Protocol &proto = protos[i];
+
+ MENUITEMINFO mii = {0};
+ mii.cbSize = sizeof(mii);
+ mii.fMask = MIIM_ID | MIIM_TYPE;
+ mii.fType = MFT_STRING;
+ mii.dwTypeData = (char *) proto.GetDescription();
+ mii.cch = strlen(mii.dwTypeData);
+ mii.wID = i + 1;
+
+ if (i == current)
+ {
+ mii.fMask |= MIIM_STATE;
+ mii.fState = MFS_DISABLED;
+ }
+
+ InsertMenuItem(menu, 0, TRUE, &mii);
+ }
+
+ int ret = ShowPopupMenu(hwnd, menu, data->proto);
+
+ DestroyMenu(menu);
+
+ if (ret != 0)
+ PluginCommand_ShowProtocol(NULL, (WPARAM) GetProtocolByIndex(ret - 1).GetName());
+
+ data->showing_menu = false;
+ }
+
+ break;
+ }
+
+ case WM_MEASUREITEM:
+ {
+ return CallService(MS_CLIST_MENUMEASUREITEM,wParam,lParam);
+ }
+ case WM_DRAWITEM:
+ {
+ return CallService(MS_CLIST_MENUDRAWITEM,wParam,lParam);
+ }
+
+ case WM_CONTEXTMENU:
+ {
+ MyDetailsFrameData *data = (MyDetailsFrameData *)GetWindowLong(hwnd, GWL_USERDATA);
+ Protocol *proto = GetCurrentProtocol();
+ if (proto == NULL)
+ break;
+
+ POINT p;
+ p.x = LOWORD(lParam);
+ p.y = HIWORD(lParam);
+
+ ScreenToClient(hwnd, &p);
+
+ data->showing_menu = true;
+
+ // In proto cycle button?
+ if (data->proto_cycle_next.hitTest(p))
+ {
+ CallService(MS_MYDETAILS_SHOWPREVIOUSPROTOCOL, 0, 0);
+ }
+ else if (data->proto_cycle_prev.hitTest(p))
+ {
+ CallService(MS_MYDETAILS_SHOWNEXTPROTOCOL, 0, 0);
+ }
+ // In image?
+ else if (data->avatar.hitTest(p))
+ {
+ HMENU menu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_MENU1));
+ HMENU submenu = GetSubMenu(menu, 4);
+ CallService(MS_LANGPACK_TRANSLATEMENU,(WPARAM)submenu,0);
+
+ // Add this proto to menu
+ char tmp[128];
+ mir_snprintf(tmp, sizeof(tmp), Translate("Set My Avatar for %s..."), proto->GetDescription());
+
+ MENUITEMINFO mii = {0};
+ mii.cbSize = sizeof(mii);
+ mii.fMask = MIIM_ID | MIIM_TYPE;
+ mii.fType = MFT_STRING;
+ mii.dwTypeData = tmp;
+ mii.cch = strlen(tmp);
+ mii.wID = 1;
+
+ if (!proto->CanSetAvatar())
+ {
+ mii.fMask |= MIIM_STATE;
+ mii.fState = MFS_DISABLED;
+ }
+
+ InsertMenuItem(submenu, 0, TRUE, &mii);
+
+ ClientToScreen(hwnd, &p);
+
+ int ret = TrackPopupMenu(submenu, TPM_TOPALIGN|TPM_LEFTALIGN|TPM_RIGHTBUTTON|TPM_RETURNCMD, p.x, p.y, 0, hwnd, NULL);
+ DestroyMenu(menu);
+
+ switch(ret)
+ {
+ case 1:
+ {
+ CallService(MS_MYDETAILS_SETMYAVATARUI, 0, (LPARAM) proto->GetName());
+ break;
+ }
+ case ID_AVATARPOPUP_SETMYAVATAR:
+ {
+ CallService(MS_MYDETAILS_SETMYAVATARUI, 0, 0);
+ break;
+ }
+ }
+ }
+ // In nick?
+ else if (data->nick.hitTest(p))
+ {
+ HMENU menu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_MENU1));
+ HMENU submenu = GetSubMenu(menu, 2);
+ CallService(MS_LANGPACK_TRANSLATEMENU,(WPARAM)submenu,0);
+
+ // Add this proto to menu
+ char tmp[128];
+ mir_snprintf(tmp, sizeof(tmp), Translate("Set My Nickname for %s..."), proto->GetDescription());
+
+ MENUITEMINFO mii = {0};
+ mii.cbSize = sizeof(mii);
+ mii.fMask = MIIM_ID | MIIM_TYPE;
+ mii.fType = MFT_STRING;
+ mii.dwTypeData = tmp;
+ mii.cch = strlen(tmp);
+ mii.wID = 1;
+
+ if (!proto->CanSetNick())
+ {
+ mii.fMask |= MIIM_STATE;
+ mii.fState = MFS_DISABLED;
+ }
+
+ InsertMenuItem(submenu, 0, TRUE, &mii);
+
+ ClientToScreen(hwnd, &p);
+
+ int ret = TrackPopupMenu(submenu, TPM_TOPALIGN|TPM_LEFTALIGN|TPM_RIGHTBUTTON|TPM_RETURNCMD, p.x, p.y, 0, hwnd, NULL);
+ DestroyMenu(menu);
+
+ switch(ret)
+ {
+ case 1:
+ {
+ CallService(MS_MYDETAILS_SETMYNICKNAMEUI, 0, (LPARAM) proto->GetName());
+ break;
+ }
+ case ID_NICKPOPUP_SETMYNICKNAME:
+ {
+ CallService(MS_MYDETAILS_SETMYNICKNAMEUI, 0, 0);
+ break;
+ }
+ }
+ }
+ // In status message?
+ else if (data->away_msg.hitTest(p))
+ {
+ char tmp[128];
+
+ HMENU menu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_MENU1));
+ HMENU submenu = GetSubMenu(menu, 3);
+ CallService(MS_LANGPACK_TRANSLATEMENU,(WPARAM)submenu,0);
+
+ // Add this proto to menu
+ mir_snprintf(tmp, sizeof(tmp), Translate("Set My Status Message for %s..."),
+ proto->GetDescription());
+
+ MENUITEMINFO mii = {0};
+ mii.cbSize = sizeof(mii);
+ mii.fMask = MIIM_ID | MIIM_TYPE;
+ mii.fType = MFT_STRING;
+ mii.dwTypeData = tmp;
+ mii.cch = strlen(tmp);
+ mii.wID = 1;
+
+ if (!proto->CanSetStatusMsg())
+ {
+ mii.fMask |= MIIM_STATE;
+ mii.fState = MFS_DISABLED;
+ }
+
+ InsertMenuItem(submenu, 0, TRUE, &mii);
+
+ {
+ // Add this to menu
+ mir_snprintf(tmp, sizeof(tmp), Translate("Set My Status Message for %s..."),
+ CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, proto->GetStatus(), 0));
+
+ MENUITEMINFO mii = {0};
+ mii.cbSize = sizeof(mii);
+ mii.fMask = MIIM_ID | MIIM_TYPE;
+ mii.fType = MFT_STRING;
+ mii.dwTypeData = tmp;
+ mii.cch = strlen(tmp);
+ mii.wID = 2;
+
+ if (proto->GetStatus() == ID_STATUS_OFFLINE)
+ {
+ mii.fMask |= MIIM_STATE;
+ mii.fState = MFS_DISABLED;
+ }
+
+ InsertMenuItem(submenu, 0, TRUE, &mii);
+ }
+
+ ClientToScreen(hwnd, &p);
+
+ int ret = TrackPopupMenu(submenu, TPM_TOPALIGN|TPM_LEFTALIGN|TPM_RIGHTBUTTON|TPM_RETURNCMD, p.x, p.y, 0, hwnd, NULL);
+ DestroyMenu(menu);
+
+ switch(ret)
+ {
+ case 1:
+ {
+ CallService(MS_MYDETAILS_SETMYSTATUSMESSAGEUI, 0, (LPARAM) proto->GetName());
+ break;
+ }
+ case 2:
+ {
+ CallService(MS_MYDETAILS_SETMYSTATUSMESSAGEUI, (WPARAM) proto->GetStatus(), 0);
+ break;
+ }
+ case ID_STATUSMESSAGEPOPUP_SETMYSTATUSMESSAGE:
+ {
+ CallService(MS_MYDETAILS_SETMYSTATUSMESSAGEUI, 0, 0);
+ break;
+ }
+ }
+ }
+ // In status?
+ else if (data->status.hitTest(p))
+ {
+ if (opts.global_on_status)
+ ShowProtocolStatusMenu(hwnd, data, proto, p);
+ else
+ ShowGlobalStatusMenu(hwnd, data, proto, p);
+ }
+ // In listening to?
+ else if (data->listening_to.hitTest(p) && protocols->CanSetListeningTo())
+ {
+ ShowListeningToMenu(hwnd, data, proto, p);
+ }
+ // In protocol?
+ else if (data->proto.hitTest(p))
+ {
+ }
+ // Default context menu
+ else
+ {
+ HMENU menu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_MENU1));
+ HMENU submenu = GetSubMenu(menu, 1);
+ CallService(MS_LANGPACK_TRANSLATEMENU,(WPARAM)submenu,0);
+
+ if (opts.cycle_through_protocols)
+ RemoveMenu(submenu, ID_CYCLE_THROUGH_PROTOS, MF_BYCOMMAND);
+ else
+ RemoveMenu(submenu, ID_DONT_CYCLE_THROUGH_PROTOS, MF_BYCOMMAND);
+
+ // Add this proto to menu
+ char tmp[128];
+ MENUITEMINFO mii = {0};
+
+ mir_snprintf(tmp, sizeof(tmp), Translate("Enable Listening To for %s"), proto->GetDescription());
+
+ ZeroMemory(&mii, sizeof(mii));
+ mii.cbSize = sizeof(mii);
+ mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
+ mii.fType = MFT_STRING;
+ mii.fState = proto->ListeningToEnabled() ? MFS_CHECKED : 0;
+ mii.dwTypeData = tmp;
+ mii.cch = strlen(tmp);
+ mii.wID = 5;
+
+ if (!proto->CanSetListeningTo())
+ {
+ mii.fState |= MFS_DISABLED;
+ }
+
+ InsertMenuItem(submenu, 0, TRUE, &mii);
+
+ // Add this to menu
+ mir_snprintf(tmp, sizeof(tmp), Translate("Set My Status Message for %s..."),
+ CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, proto->GetStatus(), 0));
+
+ ZeroMemory(&mii, sizeof(mii));
+ mii.cbSize = sizeof(mii);
+ mii.fMask = MIIM_ID | MIIM_TYPE;
+ mii.fType = MFT_STRING;
+ mii.dwTypeData = tmp;
+ mii.cch = strlen(tmp);
+ mii.wID = 4;
+
+ if (proto->GetStatus() == ID_STATUS_OFFLINE)
+ {
+ mii.fMask |= MIIM_STATE;
+ mii.fState = MFS_DISABLED;
+ }
+
+ InsertMenuItem(submenu, 0, TRUE, &mii);
+
+ // Add this proto to menu
+ mir_snprintf(tmp, sizeof(tmp), Translate("Set My Status Message for %s..."), proto->GetDescription());
+
+ ZeroMemory(&mii, sizeof(mii));
+ mii.cbSize = sizeof(mii);
+ mii.fMask = MIIM_ID | MIIM_TYPE;
+ mii.fType = MFT_STRING;
+ mii.dwTypeData = tmp;
+ mii.cch = strlen(tmp);
+ mii.wID = 3;
+
+ if (!proto->CanSetStatusMsg())
+ {
+ mii.fMask |= MIIM_STATE;
+ mii.fState = MFS_DISABLED;
+ }
+
+ InsertMenuItem(submenu, 0, TRUE, &mii);
+
+ mir_snprintf(tmp, sizeof(tmp), Translate("Set My Nickname for %s..."), proto->GetDescription());
+
+ ZeroMemory(&mii, sizeof(mii));
+ mii.cbSize = sizeof(mii);
+ mii.fMask = MIIM_ID | MIIM_TYPE;
+ mii.fType = MFT_STRING;
+ mii.dwTypeData = tmp;
+ mii.cch = strlen(tmp);
+ mii.wID = 2;
+
+ if (!proto->CanSetNick())
+ {
+ mii.fMask |= MIIM_STATE;
+ mii.fState = MFS_DISABLED;
+ }
+
+ InsertMenuItem(submenu, 0, TRUE, &mii);
+
+ mir_snprintf(tmp, sizeof(tmp), Translate("Set My Avatar for %s..."), proto->GetDescription());
+
+ ZeroMemory(&mii, sizeof(mii));
+ mii.cbSize = sizeof(mii);
+ mii.fMask = MIIM_ID | MIIM_TYPE;
+ mii.fType = MFT_STRING;
+ mii.dwTypeData = tmp;
+ mii.cch = strlen(tmp);
+ mii.wID = 1;
+
+ if (!proto->CanSetAvatar())
+ {
+ mii.fMask |= MIIM_STATE;
+ mii.fState = MFS_DISABLED;
+ }
+
+ InsertMenuItem(submenu, 0, TRUE, &mii);
+
+ ZeroMemory(&mii, sizeof(mii));
+ mii.cbSize = sizeof(mii);
+ mii.fMask = MIIM_STATE;
+ mii.fState = protocols->ListeningToEnabled() ? MFS_CHECKED : 0;
+
+ if (!protocols->CanSetListeningTo())
+ {
+ mii.fState |= MFS_DISABLED;
+ }
+
+ SetMenuItemInfo(submenu, ID_CONTEXTPOPUP_ENABLELISTENINGTO, FALSE, &mii);
+
+ ClientToScreen(hwnd, &p);
+
+ int ret = TrackPopupMenu(submenu, TPM_TOPALIGN|TPM_LEFTALIGN|TPM_RIGHTBUTTON|TPM_RETURNCMD, p.x, p.y, 0, hwnd, NULL);
+ DestroyMenu(menu);
+
+ switch(ret)
+ {
+ case 1:
+ {
+ CallService(MS_MYDETAILS_SETMYAVATARUI, 0, (LPARAM) proto->GetName());
+ break;
+ }
+ case ID_AVATARPOPUP_SETMYAVATAR:
+ {
+ CallService(MS_MYDETAILS_SETMYAVATARUI, 0, 0);
+ break;
+ }
+ case 2:
+ {
+ CallService(MS_MYDETAILS_SETMYNICKNAMEUI, 0, (LPARAM) proto->GetName());
+ break;
+ }
+ case ID_NICKPOPUP_SETMYNICKNAME:
+ {
+ CallService(MS_MYDETAILS_SETMYNICKNAMEUI, 0, 0);
+ break;
+ }
+ case 3:
+ {
+ CallService(MS_MYDETAILS_SETMYSTATUSMESSAGEUI, 0, (LPARAM) proto->GetName());
+ break;
+ }
+ case 4:
+ {
+ CallService(MS_MYDETAILS_SETMYSTATUSMESSAGEUI, (WPARAM) proto->GetStatus(), 0);
+ break;
+ }
+ case ID_STATUSMESSAGEPOPUP_SETMYSTATUSMESSAGE:
+ {
+ CallService(MS_MYDETAILS_SETMYSTATUSMESSAGEUI, 0, 0);
+ break;
+ }
+ case 5:
+ {
+ CallService(MS_LISTENINGTO_ENABLE, (LPARAM) proto->GetName(), !proto->ListeningToEnabled());
+ break;
+ }
+ case ID_CONTEXTPOPUP_ENABLELISTENINGTO:
+ {
+ CallService(MS_LISTENINGTO_ENABLE, 0, !protocols->ListeningToEnabled());
+ break;
+ }
+ case ID_SHOW_NEXT_PROTO:
+ {
+ CallService(MS_MYDETAILS_SHOWNEXTPROTOCOL, 0, 0);
+ break;
+ }
+ case ID_SHOW_PREV_PROTO:
+ {
+ CallService(MS_MYDETAILS_SHOWPREVIOUSPROTOCOL, 0, 0);
+ break;
+ }
+ case ID_CYCLE_THROUGH_PROTOS:
+ {
+ CallService(MS_MYDETAILS_CYCLE_THROUGH_PROTOCOLS, TRUE, 0);
+ break;
+ }
+ case ID_DONT_CYCLE_THROUGH_PROTOS:
+ {
+ CallService(MS_MYDETAILS_CYCLE_THROUGH_PROTOCOLS, FALSE, 0);
+ break;
+ }
+ }
+ }
+
+ data->showing_menu = false;
+
+
+ break;
+ }
+
+ case WM_NCMOUSELEAVE:
+ case WM_MOUSELEAVE:
+ {
+ MyDetailsFrameData *data = (MyDetailsFrameData *)GetWindowLong(hwnd, GWL_USERDATA);
+ data->tracking_exit = false;
+ }
+ case WM_NCMOUSEMOVE:
+ {
+ MyDetailsFrameData *data = (MyDetailsFrameData *)GetWindowLong(hwnd, GWL_USERDATA);
+
+ bool changed = false;
+ for(size_t i = 0; i < data->items.size(); ++i)
+ changed = changed || data->items[i]->setMouseOver(NULL);
+
+ if (changed)
+ InvalidateRect(hwnd, NULL, FALSE);
+
+ break;
+ }
+
+ case WM_MOUSEMOVE:
+ {
+ MyDetailsFrameData *data = (MyDetailsFrameData *)GetWindowLong(hwnd, GWL_USERDATA);
+ Protocol *proto = GetCurrentProtocol();
+ if (proto == NULL)
+ break;
+
+ if (!data->tracking_exit)
+ {
+ TRACKMOUSEEVENT tme;
+ tme.cbSize = sizeof(TRACKMOUSEEVENT);
+ tme.dwFlags = TME_LEAVE;
+ tme.hwndTrack = hwnd;
+ tme.dwHoverTime = HOVER_DEFAULT;
+ TrackMouseEvent(&tme);
+
+ data->tracking_exit = true;
+ }
+
+ POINT p;
+ p.x = LOWORD(lParam);
+ p.y = HIWORD(lParam);
+
+ bool changed = false;
+ for(size_t i = 0; i < data->items.size(); ++i)
+ changed = changed || data->items[i]->setMouseOver(&p);
+
+ if (changed)
+ InvalidateRect(hwnd, NULL, FALSE);
+
+ break;
+ }
+
+ case WM_NOTIFY:
+ {
+ LPNMHDR lpnmhdr = (LPNMHDR) lParam;
+
+ int i = (int) lpnmhdr->code;
+
+ switch (lpnmhdr->code) {
+ case TTN_GETDISPINFO:
+ {
+ MyDetailsFrameData *data = (MyDetailsFrameData *)GetWindowLong(hwnd, GWL_USERDATA);
+
+ LPNMTTDISPINFO lpttd = (LPNMTTDISPINFO) lpnmhdr;
+ SendMessage(lpnmhdr->hwndFrom, TTM_SETMAXTIPWIDTH, 0, 300);
+
+ for(int i = 0; i < data->items.size(); i++)
+ {
+ lpttd->lpszText = (char *) data->items[i]->getToolTipFor(lpnmhdr->hwndFrom);
+ if (lpttd->lpszText != NULL)
+ break;
+ }
+
+ return 0;
+ }
+ }
+
+ break;
+ }
+
+ case WM_DESTROY:
+ {
+ KillTimer(hwnd, ID_FRAME_TIMER);
+
+ MyDetailsFrameData *tmp = (MyDetailsFrameData *)GetWindowLong(hwnd, GWL_USERDATA);
+ if (tmp != NULL) delete tmp;
+
+ break;
+ }
+
+ // Custom Messages //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ case MWM_REFRESH:
+ {
+ KillTimer(hwnd, ID_RECALC_TIMER);
+ SetTimer(hwnd, ID_RECALC_TIMER, RECALC_TIME, NULL);
+ break;
+ }
+
+ case MWM_REFRESH_DATA:
+ {
+ Protocol *proto = GetCurrentProtocol(false);
+ if (proto)
+ {
+ proto->UpdateAll();
+ RedrawFrame();
+ }
+ break;
+ }
+ }
+
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+}
+
+
+int ShowHideFrameFunc(WPARAM wParam, LPARAM lParam)
+{
+ if (ServiceExists(MS_CLIST_FRAMES_ADDFRAME))
+ {
+ CallService(MS_CLIST_FRAMES_SHFRAME, frame_id, 0);
+ }
+ else
+ {
+ if (MyDetailsFrameVisible())
+ {
+ SendMessage(hwnd_container, WM_CLOSE, 0, 0);
+ }
+ else
+ {
+ ShowWindow(hwnd_container, SW_SHOW);
+ DBWriteContactSettingByte(0, MODULE_NAME, SETTING_FRAME_VISIBLE, 1);
+ }
+
+ FixMainMenu();
+ }
+ return 0;
+}
+
+
+int ShowFrameFunc(WPARAM wParam, LPARAM lParam)
+{
+ if (ServiceExists(MS_CLIST_FRAMES_ADDFRAME))
+ {
+ int flags = CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS, MAKEWPARAM(FO_FLAGS, frame_id), 0);
+ if(!(flags & F_VISIBLE))
+ CallService(MS_CLIST_FRAMES_SHFRAME, frame_id, 0);
+ }
+ else
+ {
+ if (!MyDetailsFrameVisible())
+ {
+ ShowWindow(hwnd_container, SW_SHOW);
+ DBWriteContactSettingByte(0, MODULE_NAME, SETTING_FRAME_VISIBLE, 1);
+
+ FixMainMenu();
+ }
+
+ }
+ return 0;
+}
+
+
+int HideFrameFunc(WPARAM wParam, LPARAM lParam)
+{
+ if (ServiceExists(MS_CLIST_FRAMES_ADDFRAME))
+ {
+ int flags = CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS, MAKEWPARAM(FO_FLAGS, frame_id), 0);
+ if (flags & F_VISIBLE)
+ CallService(MS_CLIST_FRAMES_SHFRAME, frame_id, 0);
+ }
+ else
+ {
+ if (MyDetailsFrameVisible())
+ {
+ SendMessage(hwnd_container, WM_CLOSE, 0, 0);
+
+ FixMainMenu();
+ }
+ }
+ return 0;
+}
+
+
+void FixMainMenu()
+{
+ CLISTMENUITEM mi = {0};
+ mi.cbSize = sizeof(CLISTMENUITEM);
+ mi.flags = CMIM_NAME;
+
+ if(MyDetailsFrameVisible())
+ mi.pszName = Translate("Hide My Details");
+ else
+ mi.pszName = Translate("Show My Details");
+
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuShowHideFrame, (LPARAM)&mi);
+}
+
+#include <math.h>
+
+void RedrawFrame()
+{
+ if (frame_id == -1)
+ {
+ InvalidateRect(hwnd_container, NULL, TRUE);
+ }
+ else
+ {
+ CallService(MS_CLIST_FRAMES_UPDATEFRAME, (WPARAM)frame_id, (LPARAM)FU_TBREDRAW | FU_FMREDRAW);
+ }
+}
+
+void UpdateFrameData()
+{
+ if (hwnd_frame != NULL)
+ PostMessage(hwnd_frame, MWM_REFRESH, 0, 0);
+}
+
+// only used when no multiwindow functionality is available
+BOOL MyDetailsFrameVisible()
+{
+ return IsWindowVisible(hwnd_container) ? true : false;
+}
+
+void SetMyDetailsFrameVisible(BOOL visible)
+{
+ if (frame_id == -1 && hwnd_container != 0)
+ {
+ ShowWindow(hwnd_container, visible ? SW_SHOW : SW_HIDE);
+ }
+}
+
+void SetCycleTime()
+{
+ if (hwnd_frame != NULL)
+ SetCycleTime(hwnd_frame);
+}
+
+void SetCycleTime(HWND hwnd)
+{
+ KillTimer(hwnd, ID_FRAME_TIMER);
+
+ if (opts.cycle_through_protocols)
+ SetTimer(hwnd, ID_FRAME_TIMER, opts.seconds_to_show_protocol * 1000, 0);
+}
+
+void SetStatusMessageRefreshTime()
+{
+ if (hwnd_frame != NULL)
+ SetStatusMessageRefreshTime(hwnd_frame);
+}
+
+void SetStatusMessageRefreshTime(HWND hwnd)
+{
+ KillTimer(hwnd, ID_STATUSMESSAGE_TIMER);
+
+ opts.refresh_status_message_timer = DBGetContactSettingWord(NULL, "MyDetails", "RefreshStatusMessageTimer",5);
+ if (opts.refresh_status_message_timer > 0)
+ {
+ SetTimer(hwnd, ID_STATUSMESSAGE_TIMER, opts.refresh_status_message_timer * 1000, NULL);
+ }
+}
+
+int PluginCommand_ShowNextProtocol(WPARAM wParam,LPARAM lParam)
+{
+ if (hwnd_frame == NULL)
+ return -1;
+
+ SetCurrentProtocol(GetCurrentProtocolIndex() + 1);
+
+ SetCycleTime();
+
+ RedrawFrame();
+
+ return 0;
+}
+
+int PluginCommand_ShowPreviousProtocol(WPARAM wParam,LPARAM lParam)
+{
+ if (hwnd_frame == NULL)
+ return -1;
+
+ SetCurrentProtocol(GetCurrentProtocolIndex() - 1);
+
+ SetCycleTime();
+
+ RedrawFrame();
+
+ return 0;
+}
+
+int PluginCommand_ShowProtocol(WPARAM wParam,LPARAM lParam)
+{
+ char * proto = (char *)lParam;
+
+ if (proto == NULL)
+ return -1;
+
+ int proto_num = GetProtocolIndexByName(proto);
+ if (proto_num == -1)
+ return -2;
+
+ if (hwnd_frame == NULL)
+ return -3;
+
+ SetCurrentProtocol(proto_num);
+
+ SetCycleTime();
+
+ RedrawFrame();
+
+ return 0;
+}
+
+int SettingsChangedHook(WPARAM wParam, LPARAM lParam)
+{
+ if (hwnd_frame == NULL)
+ return 0;
+
+ DBCONTACTWRITESETTING *cws = (DBCONTACTWRITESETTING*)lParam;
+
+ if (wParam != NULL)
+ return 0;
+
+ if (strstr(cws->szModule,"Away"))
+ {
+ // Status message changed
+ UpdateFrameData();
+ return 0;
+ }
+
+ Protocol *proto = GetCurrentProtocol(false);
+ if (proto == NULL || strcmp(proto->GetName(), cws->szModule) != 0)
+ return 0;
+
+ if (!strcmp(cws->szSetting,"Status")
+ || !strcmp(cws->szSetting,"StatusMood")
+ || !strcmp(cws->szSetting,"XStatusName")
+ || !strcmp(cws->szSetting,"XStatusMsg")
+ || !strcmp(cws->szSetting,"XStatusId")
+ || ( proto->GetCustomStatus() != 0 && !strcmp(cws->szSetting, proto->GetCustomStatusNameKey()) )
+ || ( proto->GetCustomStatus() != 0 && !strcmp(cws->szSetting, proto->GetCustomStatusMessageKey()) ))
+ {
+ // Status changed
+ UpdateFrameData();
+ }
+ else if(!strcmp(cws->szSetting,"MyHandle")
+ || !strcmp(cws->szSetting,"UIN")
+ || !strcmp(cws->szSetting,"Nick")
+ || !strcmp(cws->szSetting,"FirstName")
+ || !strcmp(cws->szSetting,"e-mail")
+ || !strcmp(cws->szSetting,"LastName")
+ || !strcmp(cws->szSetting,"JID"))
+ {
+ // Name changed
+ UpdateFrameData();
+ }
+ else if (strcmp(cws->szSetting,"ListeningTo") == 0)
+ {
+ UpdateFrameData();
+ }
+ else if (strcmp(cws->szSetting,"LockMainStatus") == 0)
+ {
+ UpdateFrameData();
+ }
+
+ return 0;
+}
+
+int AvatarChangedHook(WPARAM wParam, LPARAM lParam)
+{
+ if (hwnd_frame == NULL)
+ return 0;
+
+ Protocol *proto = GetCurrentProtocol(false);
+ if (proto == NULL || strcmp(proto->GetName(), (const char *) wParam) != 0)
+ return 0;
+
+ UpdateFrameData();
+
+ return 0;
+}
+
+int ProtoAckHook(WPARAM wParam, LPARAM lParam)
+{
+ if (hwnd_frame == NULL)
+ return 0;
+
+ ACKDATA *ack = (ACKDATA*) lParam;
+ if (ack->hContact != NULL)
+ return 0;
+
+ Protocol *proto = GetCurrentProtocol(false);
+ if (proto == NULL || strcmp(proto->GetName(), ack->szModule) != 0)
+ return 0;
+
+ if (ack->type == ACKTYPE_STATUS)
+ {
+ UpdateFrameData();
+ }
+ else if (ack->type == ACKTYPE_AWAYMSG)
+ {
+ UpdateFrameData();
+ }
+ else if (ack->type == ACKTYPE_EMAIL)
+ {
+ UpdateFrameData();
+ }
+
+ return 0;
+}
+
+int ListeningtoEnableStateChangedHook(WPARAM wParam,LPARAM lParam)
+{
+ if (hwnd_frame == NULL)
+ return 0;
+
+ Protocol *proto = GetCurrentProtocol(false);
+ if (proto == NULL || strcmp(proto->GetName(), (const char *) wParam) != 0)
+ return 0;
+
+ UpdateFrameData();
+
+ return 0;
+}
+
+int AccListChanged(WPARAM wParam, LPARAM lParam)
+{
+ SetCurrentProtocol(0);
+
+ RedrawFrame();
+
+ return 0;
+}
diff --git a/plugins/MyDetails/frame.h b/plugins/MyDetails/frame.h
new file mode 100644
index 0000000000..58aa800090
--- /dev/null
+++ b/plugins/MyDetails/frame.h
@@ -0,0 +1,38 @@
+/*
+Copyright (C) 2005 Ricardo Pescuma Domenecci
+
+This is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this file; see the file license.txt. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef __FRAME_H__
+# define __FRAME_H__
+
+
+void InitFrames();
+void DeInitFrames();
+
+void UpdateFrameData();
+void RedrawFrame();
+
+void SetCycleTime();
+
+int PluginCommand_ShowNextProtocol(WPARAM wParam,LPARAM lParam);
+int PluginCommand_ShowPreviousProtocol(WPARAM wParam,LPARAM lParam);
+int PluginCommand_ShowProtocol(WPARAM wParam,LPARAM lParam);
+
+
+#endif // __FRAME_H__ \ No newline at end of file
diff --git a/plugins/MyDetails/mydetails.cpp b/plugins/MyDetails/mydetails.cpp
new file mode 100644
index 0000000000..9351765f6c
--- /dev/null
+++ b/plugins/MyDetails/mydetails.cpp
@@ -0,0 +1,992 @@
+/*
+Copyright (C) 2005 Ricardo Pescuma Domenecci
+
+This is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this file; see the file license.txt. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+*/
+
+
+#include "commons.h"
+#include "mydetails.h"
+
+
+// Prototypes /////////////////////////////////////////////////////////////////////////////////////
+
+
+HINSTANCE hInst;
+PLUGINLINK *pluginLink;
+
+PLUGININFOEX pluginInfo={
+ sizeof(PLUGININFOEX),
+ "My Details",
+ PLUGIN_MAKE_VERSION(0,0,2,6),
+ "Show and allows you to edit your details for all protocols.",
+ "Ricardo Pescuma Domenecci, Drugwash",
+ "",
+ "© 2005-2010 Ricardo Pescuma Domenecci, Drugwash",
+ "http://pescuma.org/miranda/mydetails",
+ 0, //not transient
+ 0, //doesn't replace anything built-in
+ { 0xa82baeb3, 0xa33c, 0x4036, { 0xb8, 0x37, 0x78, 0x3, 0xa5, 0xb6, 0xc2, 0xab } } // {A82BAEB3-A33C-4036-B837-7803A5B6C2AB}
+};
+
+
+struct MM_INTERFACE mmi;
+struct UTF8_INTERFACE utfi;
+struct SKIN_INTERFACE mski;
+
+
+HANDLE hTTB = NULL;
+
+// Hooks
+HANDLE hModulesLoadedHook = NULL;
+HANDLE hPreShutdownHook = NULL;
+HANDLE hColorChangedHook = NULL;
+
+long nickname_dialog_open;
+HWND hwndSetNickname;
+
+long status_msg_dialog_open;
+HWND hwndSetStatusMsg;
+
+SkinDialog *dialog;
+
+
+// Hook called after init
+static int MainInit(WPARAM wparam,LPARAM lparam);
+static int MainUninit(WPARAM wParam, LPARAM lParam);
+
+
+// Services
+static int PluginCommand_SetMyNicknameUI(WPARAM wParam,LPARAM lParam);
+static int PluginCommand_SetMyNickname(WPARAM wParam,LPARAM lParam);
+static int PluginCommand_GetMyNickname(WPARAM wParam,LPARAM lParam);
+static int PluginCommand_SetMyAvatarUI(WPARAM wParam,LPARAM lParam);
+static int PluginCommand_SetMyAvatar(WPARAM wParam,LPARAM lParam);
+static int PluginCommand_GetMyAvatar(WPARAM wParam,LPARAM lParam);
+static int PluginCommand_SetMyStatusMessageUI(WPARAM wParam,LPARAM lParam);
+static int PluginCommand_CicleThroughtProtocols(WPARAM wParam,LPARAM lParam);
+
+
+
+
+// Functions //////////////////////////////////////////////////////////////////////////////////////
+
+
+BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
+{
+ hInst = hinstDLL;
+ return TRUE;
+}
+
+
+extern "C" __declspec(dllexport) PLUGININFO* MirandaPluginInfo(DWORD mirandaVersion)
+{
+ pluginInfo.cbSize = sizeof(PLUGININFO);
+ return (PLUGININFO*) &pluginInfo;
+}
+
+
+extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion)
+{
+ pluginInfo.cbSize = sizeof(PLUGININFOEX);
+ return &pluginInfo;
+}
+
+
+static const MUUID interfaces[] = { MIID_MDETAILS, MIID_LAST };
+extern "C" __declspec(dllexport) const MUUID* MirandaPluginInterfaces(void)
+{
+ return interfaces;
+}
+
+
+int __declspec(dllexport) Load(PLUGINLINK *link)
+{
+ // Copy data
+ pluginLink = link;
+
+ // CHECK_VERSION("My Details")
+
+ mir_getMMI(&mmi);
+ mir_getUTFI(&utfi);
+
+ init_list_interface();
+
+ // Hook event to load messages and show first one
+ hModulesLoadedHook = HookEvent(ME_SYSTEM_MODULESLOADED, MainInit);
+ hPreShutdownHook = HookEvent(ME_SYSTEM_PRESHUTDOWN, MainUninit);
+
+ nickname_dialog_open = 0;
+ status_msg_dialog_open = 0;
+
+ // Options
+ InitOptions();
+
+ // Register services
+ CreateServiceFunction(MS_MYDETAILS_SETMYNICKNAME, PluginCommand_SetMyNickname);
+ CreateServiceFunction(MS_MYDETAILS_SETMYNICKNAMEUI, PluginCommand_SetMyNicknameUI);
+ CreateServiceFunction(MS_MYDETAILS_SETMYAVATAR, PluginCommand_SetMyAvatar);
+ CreateServiceFunction(MS_MYDETAILS_SETMYAVATARUI, PluginCommand_SetMyAvatarUI);
+ CreateServiceFunction(MS_MYDETAILS_GETMYNICKNAME, PluginCommand_GetMyNickname);
+ CreateServiceFunction(MS_MYDETAILS_GETMYAVATAR, PluginCommand_GetMyAvatar);
+ CreateServiceFunction(MS_MYDETAILS_SETMYSTATUSMESSAGEUI, PluginCommand_SetMyStatusMessageUI);
+ CreateServiceFunction(MS_MYDETAILS_SHOWNEXTPROTOCOL, PluginCommand_ShowNextProtocol);
+ CreateServiceFunction(MS_MYDETAILS_SHOWPREVIOUSPROTOCOL, PluginCommand_ShowPreviousProtocol);
+ CreateServiceFunction(MS_MYDETAILS_SHOWPROTOCOL, PluginCommand_ShowProtocol);
+ CreateServiceFunction(MS_MYDETAILS_CYCLE_THROUGH_PROTOCOLS, PluginCommand_CicleThroughtProtocols);
+
+ return 0;
+}
+
+
+int __declspec(dllexport) Unload(void)
+{
+ DestroyServiceFunction(MS_MYDETAILS_SETMYNICKNAME);
+ DestroyServiceFunction(MS_MYDETAILS_SETMYNICKNAMEUI);
+ DestroyServiceFunction(MS_MYDETAILS_SETMYAVATAR);
+ DestroyServiceFunction(MS_MYDETAILS_SETMYAVATARUI);
+ DestroyServiceFunction(MS_MYDETAILS_GETMYNICKNAME);
+ DestroyServiceFunction(MS_MYDETAILS_GETMYAVATAR);
+ DestroyServiceFunction(MS_MYDETAILS_SETMYSTATUSMESSAGEUI);
+ DestroyServiceFunction(MS_MYDETAILS_SHOWNEXTPROTOCOL);
+ DestroyServiceFunction(MS_MYDETAILS_SHOWPREVIOUSPROTOCOL);
+ DestroyServiceFunction(MS_MYDETAILS_SHOWPROTOCOL);
+ DestroyServiceFunction(MS_MYDETAILS_CYCLE_THROUGH_PROTOCOLS);
+
+ if (hModulesLoadedHook) UnhookEvent(hModulesLoadedHook);
+
+ DeInitProtocolData();
+ DeInitOptions();
+
+ return 0;
+}
+
+
+static int Menu_SetMyAvatarUI(WPARAM wParam,LPARAM lParam)
+{
+ return PluginCommand_SetMyAvatarUI(0, 0);
+}
+static int Menu_SetMyNicknameUI(WPARAM wParam,LPARAM lParam)
+{
+ return PluginCommand_SetMyNicknameUI(0, 0);
+}
+static int Menu_SetMyStatusMessageUI(WPARAM wParam,LPARAM lParam)
+{
+ return PluginCommand_SetMyStatusMessageUI(0, 0);
+}
+
+static void SkinChanged(void *param, SKINNED_DIALOG dlg)
+{
+ RedrawFrame();
+}
+
+
+static int ColorChanged(WPARAM wparam, LPARAM lparam)
+{
+ ColourID cid = {0};
+ cid.cbSize = sizeof(ColourID);
+ lstrcpynA(cid.group, "My Details", sizeof(cid.group));
+ lstrcpynA(cid.name, "Background", sizeof(cid.name));
+
+ opts.bkg_color = (COLORREF) CallService(MS_COLOUR_GET, (WPARAM) &cid, 0);
+
+ RedrawFrame();
+
+ return 0;
+}
+
+
+// Hook called after init
+static int MainInit(WPARAM wparam,LPARAM lparam)
+{
+ if ( mir_skins_getInterface(&mski) != 0 )
+ {
+ MessageBox(NULL, _T("MyDetails needs Skins plugin in order to work"), _T("MyDetails"), MB_OK | MB_ICONERROR);
+ return 0;
+ }
+
+ if (CallService(MS_SKIN2_GETICON, 0, (LPARAM) "LISTENING_TO_ICON") == NULL)
+ {
+ SKINICONDESC sid = {0};
+ sid.cbSize = sizeof(SKINICONDESC);
+ sid.ptszSection = "Contact List";
+ sid.ptszDescription = "Listening to";
+ sid.pszName = "LISTENING_TO_ICON";
+ sid.hDefaultIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_LISTENINGTO));
+ CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid);
+ }
+
+ {
+ SKINICONDESC sid = {0};
+ sid.cbSize = sizeof(SKINICONDESC);
+ sid.ptszSection = "My Details";
+ sid.ptszDescription = "Email";
+ sid.pszName = "MYDETAILS_EMAIL";
+ sid.hDefaultIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_EMAIL));
+ CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid);
+ }
+
+ {
+ SKINICONDESC sid = {0};
+ sid.cbSize = sizeof(SKINICONDESC);
+ sid.ptszSection = "My Details";
+ sid.ptszDescription = "Previous protocol";
+ sid.pszName = "MYDETAILS_PREV_PROTOCOL";
+ sid.hDefaultIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_LEFT_ARROW));
+ CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid);
+ }
+
+ {
+ SKINICONDESC sid = {0};
+ sid.cbSize = sizeof(SKINICONDESC);
+ sid.ptszSection = "My Details";
+ sid.ptszDescription = "Next protocol";
+ sid.pszName = "MYDETAILS_NEXT_PROTOCOL";
+ sid.hDefaultIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_RIGHT_ARROW));
+ CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid);
+ }
+
+ {
+ ColourID cid = {0};
+ cid.cbSize = sizeof(ColourID);
+ lstrcpynA(cid.group, "My Details", sizeof(cid.group));
+ lstrcpynA(cid.name, "Background", sizeof(cid.name));
+ lstrcpynA(cid.dbSettingsGroup, MODULE_NAME, sizeof(cid.dbSettingsGroup));
+ lstrcpynA(cid.setting, "BackgroundColor", sizeof(cid.setting));
+ cid.defcolour = GetSysColor(COLOR_BTNFACE);
+
+ CallService(MS_COLOUR_REGISTER, (WPARAM) &cid, 0);
+
+ ColorChanged(0,0);
+
+ hColorChangedHook = HookEvent(ME_COLOUR_RELOAD, ColorChanged);
+ }
+
+ dialog = new SkinDialog("MyDetails", "My Details", MODULE_NAME);
+ if (!dialog->isValid())
+ {
+ MessageBox(NULL, _T("MyDetails could not create dialog. Check if default skin is installed"), _T("MyDetails"), MB_OK | MB_ICONERROR);
+ return 0;
+ }
+
+ dialog->addImageField("avatar", "Avatar");
+ dialog->addTextField("nickname", "Nickname");
+ dialog->addTextField("protocol", "Protocol");
+ dialog->addIconField("email_icon", "Unread Email Count Icon");
+ dialog->addTextField("email", "Unread Email Count");
+ dialog->addIconField("status_icon", "Status Icon");
+ dialog->addTextField("status_name", "Status");
+ dialog->addTextField("status_msg", "Status Message");
+ dialog->addIconField("listening_icon", "Listening To Icon");
+ dialog->addTextField("listening", "Listening To");
+ dialog->addIconField("next_proto", "Next Protocol");
+ dialog->addIconField("prev_proto", "Previous Protocol");
+ dialog->setSkinChangedCallback(SkinChanged, NULL);
+ dialog->finishedConfiguring();
+
+
+ InitProtocolData();
+
+ // Add options to menu
+ CLISTMENUITEM mi;
+
+ if (protocols->CanSetAvatars())
+ {
+ ZeroMemory(&mi,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.flags = 0;
+ mi.popupPosition = 500050000;
+ mi.pszPopupName = Translate("My Details");
+ mi.position = 100001;
+ mi.pszName = Translate("Set My Avatar...");
+ CreateServiceFunction("MENU_" MS_MYDETAILS_SETMYAVATARUI, Menu_SetMyAvatarUI);
+ mi.pszService = "MENU_" MS_MYDETAILS_SETMYAVATARUI;
+
+ CallService(MS_CLIST_ADDMAINMENUITEM,0,(LPARAM)&mi);
+ }
+
+ ZeroMemory(&mi,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.flags = 0;
+ mi.popupPosition = 500050000;
+ mi.pszPopupName = Translate("My Details");
+ mi.position = 100002;
+ mi.pszName = Translate("Set My Nickname...");
+ CreateServiceFunction("MENU_" MS_MYDETAILS_SETMYNICKNAMEUI, Menu_SetMyNicknameUI);
+ mi.pszService = "MENU_" MS_MYDETAILS_SETMYNICKNAMEUI;
+
+ CallService(MS_CLIST_ADDMAINMENUITEM,0,(LPARAM)&mi);
+
+ ZeroMemory(&mi,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.flags = 0;
+ mi.popupPosition = 500050000;
+ mi.pszPopupName = Translate("My Details");
+ mi.position = 100003;
+ mi.pszName = Translate("Set My Status Message...");
+ CreateServiceFunction("MENU_" MS_MYDETAILS_SETMYSTATUSMESSAGEUI, Menu_SetMyStatusMessageUI);
+ mi.pszService = "MENU_" MS_MYDETAILS_SETMYSTATUSMESSAGEUI;
+
+ CallService(MS_CLIST_ADDMAINMENUITEM,0,(LPARAM)&mi);
+
+ // Set protocols to show frame
+ ZeroMemory(&mi,sizeof(mi));
+ mi.cbSize = sizeof(mi);
+ mi.flags = 0;
+ mi.popupPosition = 500050000;
+ mi.pszPopupName = Translate("My Details");
+ mi.position = 200001;
+ mi.pszName = Translate("Show next protocol");
+ mi.pszService = MS_MYDETAILS_SHOWNEXTPROTOCOL;
+
+ CallService(MS_CLIST_ADDMAINMENUITEM,0,(LPARAM)&mi);
+
+ InitFrames();
+
+ // updater plugin support
+ if(ServiceExists(MS_UPDATE_REGISTER))
+ {
+ Update upd = {0};
+ char szCurrentVersion[30];
+
+ upd.cbSize = sizeof(upd);
+ upd.szComponentName = pluginInfo.shortName;
+
+ upd.szUpdateURL = UPDATER_AUTOREGISTER;
+
+ upd.szBetaVersionURL = "http://svn.berlios.de/svnroot/repos/mgoodies/trunk/mydetails/Docs/mydetails_version.txt";
+ upd.szBetaChangelogURL = "http://svn.berlios.de/svnroot/repos/mgoodies/trunk/mydetails/Docs/mydetails_changelog.txt";
+ upd.pbBetaVersionPrefix = (BYTE *)"My Details ";
+ upd.cpbBetaVersionPrefix = strlen((char *)upd.pbBetaVersionPrefix);
+ upd.szBetaUpdateURL = "http://pescuma.googlecode.com/files/mydetails.%VERSION%.zip";
+
+ upd.pbVersion = (BYTE *)CreateVersionStringPlugin((PLUGININFO*) &pluginInfo, szCurrentVersion);
+ upd.cpbVersion = strlen((char *)upd.pbVersion);
+
+ CallService(MS_UPDATE_REGISTER, 0, (LPARAM)&upd);
+ }
+
+ return 0;
+}
+
+static int MainUninit(WPARAM wParam, LPARAM lParam)
+{
+ DeInitFrames();
+
+ delete dialog;
+
+ return 0;
+}
+
+// Set nickname ///////////////////////////////////////////////////////////////////////////////////
+
+#define WMU_SETDATA (WM_USER+1)
+
+static BOOL CALLBACK DlgProcSetNickname(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch ( msg )
+ {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+ SendMessage(GetDlgItem(hwndDlg, IDC_NICKNAME), EM_LIMITTEXT,
+ MS_MYDETAILS_GETMYNICKNAME_BUFFER_SIZE - 1, 0);
+
+ return TRUE;
+ }
+
+ case WMU_SETDATA:
+ {
+ int proto_num = (int)wParam;
+
+ SetWindowLong(hwndDlg, GWL_USERDATA, proto_num);
+
+ if (proto_num == -1)
+ {
+ SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)LoadSkinnedIcon(SKINICON_OTHER_MIRANDA));
+
+ // All protos have the same nick?
+
+ std::vector<Protocol> protos;
+ GetProtocols(&protos);
+
+ int protosSize = protos.size();
+ if (protosSize > 0)
+ {
+ std::string nick = protos[0].GetNick();
+
+ bool foundDefNick = true;
+ for(int i = 1; i < protosSize; i++)
+ {
+ if (stricmp(protos[i].GetNick(), nick.c_str()) != 0)
+ {
+ foundDefNick = false;
+ break;
+ }
+ }
+
+ if (foundDefNick)
+ {
+ if (stricmp(protocols->default_nick, nick.c_str()) != 0)
+ lstrcpy(protocols->default_nick, nick.c_str());
+ }
+ }
+
+ SetDlgItemText(hwndDlg, IDC_NICKNAME, protocols->default_nick);
+ SendDlgItemMessage(hwndDlg, IDC_NICKNAME, EM_LIMITTEXT, MS_MYDETAILS_GETMYNICKNAME_BUFFER_SIZE, 0);
+ }
+ else
+ {
+ Protocol proto = GetProtocolByIndex(proto_num);
+
+ char tmp[128];
+ mir_snprintf(tmp, sizeof(tmp), Translate("Set My Nickname for %s"), proto.GetDescription());
+
+ SendMessage(hwndDlg, WM_SETTEXT, 0, (LPARAM)tmp);
+
+ HICON hIcon = (HICON) proto.Call(PS_LOADICON, PLI_PROTOCOL);
+ if (hIcon != NULL)
+ {
+ SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)hIcon);
+ DestroyIcon(hIcon);
+ }
+
+ SetDlgItemText(hwndDlg, IDC_NICKNAME, proto.GetNick());
+ SendDlgItemMessage(hwndDlg, IDC_NICKNAME, EM_LIMITTEXT,
+ min(MS_MYDETAILS_GETMYNICKNAME_BUFFER_SIZE, proto.GetNickMaxLength()), 0);
+ }
+
+ return TRUE;
+ }
+
+ case WM_COMMAND:
+ switch(wParam)
+ {
+ case IDOK:
+ {
+ char tmp[MS_MYDETAILS_GETMYNICKNAME_BUFFER_SIZE];
+ GetDlgItemText(hwndDlg, IDC_NICKNAME, tmp, sizeof(tmp));
+
+ int proto_num = (int) GetWindowLong(hwndDlg, GWL_USERDATA);
+ if (proto_num == -1)
+ {
+ protocols->SetNicks(tmp);
+ }
+ else
+ {
+ GetProtocolByIndex(proto_num).SetNick(tmp);
+ }
+
+ DestroyWindow(hwndDlg);
+ break;
+ }
+ case IDCANCEL:
+ {
+ DestroyWindow(hwndDlg);
+ break;
+ }
+ }
+ break;
+
+ case WM_CLOSE:
+ DestroyWindow(hwndDlg);
+ break;
+
+ case WM_DESTROY:
+ InterlockedExchange(&nickname_dialog_open, 0);
+ break;
+ }
+
+ return FALSE;
+}
+
+static int PluginCommand_SetMyNicknameUI(WPARAM wParam,LPARAM lParam)
+{
+ char * proto = (char *)lParam;
+ int proto_num = -1;
+
+ if (proto != NULL)
+ {
+ proto_num = GetProtocolIndexByName(proto);
+ if (proto_num == -1)
+ return -1;
+
+ if (!GetProtocolByIndex(proto_num).CanSetNick())
+ return -2;
+ }
+
+ if (!nickname_dialog_open)
+ {
+ InterlockedExchange(&nickname_dialog_open, 1);
+
+ hwndSetNickname = CreateDialog(hInst, MAKEINTRESOURCE( IDD_SETNICKNAME ), NULL, DlgProcSetNickname );
+
+ SendMessage(hwndSetNickname, WMU_SETDATA, proto_num, 0);
+ }
+
+ SetForegroundWindow( hwndSetNickname );
+ SetFocus( hwndSetNickname );
+ ShowWindow( hwndSetNickname, SW_SHOW );
+
+ return 0;
+}
+
+
+static int PluginCommand_SetMyNickname(WPARAM wParam,LPARAM lParam)
+{
+ char * proto = (char *)wParam;
+
+ if (proto != NULL)
+ {
+ Protocol protocol = GetProtocolByName(proto);
+ if (!protocol)
+ return -1;
+
+ if (!protocol.CanSetNick())
+ return -2;
+
+ protocol.SetNick((char *)lParam);
+ }
+ else
+ {
+ protocols->SetNicks((char *)lParam);
+ }
+
+ return 0;
+}
+
+
+static int PluginCommand_GetMyNickname(WPARAM wParam,LPARAM lParam)
+{
+ char * ret = (char *)lParam;
+ char * proto = (char *)wParam;
+
+ if (ret == NULL)
+ return -1;
+
+ if (proto == NULL)
+ {
+ if (protocols->default_nick != NULL)
+ lstrcpyn(ret, protocols->default_nick, MS_MYDETAILS_GETMYNICKNAME_BUFFER_SIZE);
+ else
+ ret[0] = '\0';
+ }
+ else
+ {
+ Protocol protocol = GetProtocolByName(proto);
+ if (!protocol)
+ return -1;
+
+ lstrcpyn(ret, protocol.GetNick(), MS_MYDETAILS_GETMYNICKNAME_BUFFER_SIZE);
+ }
+
+ return 0;
+}
+
+
+// Set avatar /////////////////////////////////////////////////////////////////////////////////////
+
+static int PluginCommand_SetMyAvatarUI(WPARAM wParam,LPARAM lParam)
+{
+ char * proto = (char *)lParam;
+ int proto_num = -1;
+
+ if (proto != NULL)
+ {
+ Protocol protocol = GetProtocolByName(proto);
+ if (!protocol)
+ return -1;
+
+ if (!protocol.CanSetAvatar())
+ return -2;
+
+ protocol.SetAvatar(NULL);
+ }
+ else
+ {
+ protocols->SetAvatars(NULL);
+ }
+
+ return 0;
+}
+
+
+static int PluginCommand_SetMyAvatar(WPARAM wParam,LPARAM lParam)
+{
+ char * proto = (char *)wParam;
+
+ if (proto != NULL)
+ {
+ Protocol protocol = GetProtocolByName(proto);
+ if (!protocol)
+ return -1;
+
+ if (!protocol.CanSetAvatar())
+ return -2;
+
+ protocol.SetAvatar((char *)lParam);
+ }
+ else
+ {
+ protocols->SetAvatars((char *)lParam);
+ }
+
+ return 0;
+}
+
+
+int Status2SkinIcon(int status)
+{
+ switch(status) {
+ case ID_STATUS_AWAY: return SKINICON_STATUS_AWAY;
+ case ID_STATUS_NA: return SKINICON_STATUS_NA;
+ case ID_STATUS_DND: return SKINICON_STATUS_DND;
+ case ID_STATUS_OCCUPIED: return SKINICON_STATUS_OCCUPIED;
+ case ID_STATUS_FREECHAT: return SKINICON_STATUS_FREE4CHAT;
+ case ID_STATUS_ONLINE: return SKINICON_STATUS_ONLINE;
+ case ID_STATUS_OFFLINE: return SKINICON_STATUS_OFFLINE;
+ case ID_STATUS_INVISIBLE: return SKINICON_STATUS_INVISIBLE;
+ case ID_STATUS_ONTHEPHONE: return SKINICON_STATUS_ONTHEPHONE;
+ case ID_STATUS_OUTTOLUNCH: return SKINICON_STATUS_OUTTOLUNCH;
+ case ID_STATUS_IDLE: return SKINICON_STATUS_AWAY;
+ }
+ return SKINICON_STATUS_OFFLINE;
+}
+
+
+
+static int PluginCommand_GetMyAvatar(WPARAM wParam,LPARAM lParam)
+{
+ char * ret = (char *)lParam;
+ char * proto = (char *)wParam;
+
+ if (ret == NULL)
+ return -1;
+
+ if (proto == NULL)
+ {
+ if (protocols->default_avatar_file != NULL)
+ lstrcpyn(ret, protocols->default_avatar_file, MS_MYDETAILS_GETMYAVATAR_BUFFER_SIZE);
+ else
+ ret[0] = '\0';
+ }
+ else
+ {
+ Protocol protocol = GetProtocolByName(proto);
+ if (!protocol)
+ return -1;
+
+ if (!protocol.CanGetAvatar())
+ return -2;
+
+ lstrcpyn(ret, protocol.GetAvatarFile(), MS_MYDETAILS_GETMYAVATAR_BUFFER_SIZE);
+ }
+
+ return 0;
+}
+
+static LRESULT CALLBACK StatusMsgEditSubclassProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg) {
+ case WM_CHAR:
+ {
+ if(wParam == 0x0a && (GetKeyState(VK_CONTROL) & 0x8000) != 0) {
+ PostMessage(GetParent(hwnd), WM_COMMAND, IDOK, 0);
+ return 0;
+ }
+
+ break;
+ }
+ }
+
+ return CallWindowProc((WNDPROC) GetWindowLong(hwnd, GWL_USERDATA), hwnd, msg, wParam, lParam);
+}
+
+struct SetStatusMessageData {
+ int status;
+ int proto_num;
+};
+
+static BOOL CALLBACK DlgProcSetStatusMessage(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch ( msg )
+ {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hwndDlg);
+ SendMessage(GetDlgItem(hwndDlg, IDC_STATUSMESSAGE), EM_LIMITTEXT,
+ MS_MYDETAILS_GETMYSTATUSMESSAGE_BUFFER_SIZE - 1, 0);
+
+ WNDPROC old_proc = (WNDPROC) SetWindowLong(GetDlgItem(hwndDlg, IDC_STATUSMESSAGE),
+ GWL_WNDPROC, (LONG) StatusMsgEditSubclassProc);
+
+ SetWindowLong(GetDlgItem(hwndDlg, IDC_STATUSMESSAGE), GWL_USERDATA, (long) old_proc);
+
+ return TRUE;
+ }
+
+ case WMU_SETDATA:
+ {
+ SetStatusMessageData *data = (SetStatusMessageData *) malloc(sizeof(SetStatusMessageData));
+ data->status = (int)wParam;
+ data->proto_num = (int)lParam;
+
+ SetWindowLong(hwndDlg, GWL_USERDATA, (LONG) data);
+
+ if (data->proto_num >= 0)
+ {
+ Protocol proto = GetProtocolByIndex(data->proto_num);
+
+ HICON hIcon = (HICON) proto.Call(PS_LOADICON, PLI_PROTOCOL);
+ if (hIcon != NULL)
+ {
+ SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)hIcon);
+ DestroyIcon(hIcon);
+ }
+
+ char title[256];
+ mir_snprintf(title, sizeof(title), Translate("Set My Status Message for %s"),
+ proto.GetDescription());
+ SendMessage(hwndDlg, WM_SETTEXT, 0, (LPARAM)title);
+
+ SetDlgItemText(hwndDlg, IDC_STATUSMESSAGE, proto.GetStatusMsg());
+ }
+ else if (data->status != 0)
+ {
+ SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)LoadSkinnedIcon(Status2SkinIcon(data->status)));
+
+ char title[256];
+ mir_snprintf(title, sizeof(title), Translate("Set My Status Message for %s"),
+ CallService(MS_CLIST_GETSTATUSMODEDESCRIPTION, data->status, 0));
+ SendMessage(hwndDlg, WM_SETTEXT, 0, (LPARAM)title);
+
+ SetDlgItemText(hwndDlg, IDC_STATUSMESSAGE, protocols->GetDefaultStatusMsg(data->status));
+ }
+ else
+ {
+ SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)LoadSkinnedIcon(SKINICON_OTHER_MIRANDA));
+
+ SetDlgItemText(hwndDlg, IDC_STATUSMESSAGE, protocols->GetDefaultStatusMsg());
+ }
+
+ return TRUE;
+ }
+ case WM_COMMAND:
+ switch(wParam)
+ {
+ case IDOK:
+ {
+ char tmp[MS_MYDETAILS_GETMYSTATUSMESSAGE_BUFFER_SIZE];
+ GetDlgItemText(hwndDlg, IDC_STATUSMESSAGE, tmp, sizeof(tmp));
+
+ SetStatusMessageData *data = (SetStatusMessageData *) GetWindowLong(hwndDlg, GWL_USERDATA);
+
+ if (data->proto_num >= 0)
+ GetProtocolByIndex(data->proto_num).SetStatusMsg(tmp);
+ else if (data->status == 0)
+ protocols->SetStatusMsgs(tmp);
+ else
+ protocols->SetStatusMsgs(data->status, tmp);
+
+ // To force a refresh
+ UpdateFrameData();
+
+ DestroyWindow(hwndDlg);
+ break;
+ }
+ case IDCANCEL:
+ {
+ DestroyWindow(hwndDlg);
+ break;
+ }
+ }
+ break;
+
+ case WM_CLOSE:
+ DestroyWindow(hwndDlg);
+ break;
+
+ case WM_DESTROY:
+ SetWindowLong(GetDlgItem(hwndDlg, IDC_STATUSMESSAGE), GWL_WNDPROC,
+ GetWindowLong(GetDlgItem(hwndDlg, IDC_STATUSMESSAGE), GWL_USERDATA));
+ free((SetStatusMessageData *) GetWindowLong(hwndDlg, GWL_USERDATA));
+ InterlockedExchange(&status_msg_dialog_open, 0);
+ break;
+ }
+
+ return FALSE;
+}
+
+static int PluginCommand_SetMyStatusMessageUI(WPARAM wParam,LPARAM lParam)
+{
+ int status = (int)wParam;
+ char * proto_name = (char *)lParam;
+ int proto_num = -1;
+ Protocol proto(NULL);
+ TCHAR status_message[256];
+
+ if (status != 0 && (status < ID_STATUS_OFFLINE || status > ID_STATUS_OUTTOLUNCH))
+ return -10;
+
+ if (proto_name != NULL)
+ {
+ proto_num = GetProtocolIndexByName(proto_name);
+ if (proto_num == -1)
+ return -1;
+
+ proto = GetProtocolByIndex(proto_num);
+ if (!proto.CanSetStatusMsg())
+ return -2;
+ }
+
+ if (ServiceExists(MS_NAS_INVOKESTATUSWINDOW))
+ {
+ NAS_ISWINFO iswi;
+
+ ZeroMemory(&iswi, sizeof(iswi));
+
+ iswi.cbSize = sizeof(NAS_ISWINFO);
+
+ if (proto)
+ {
+ // Has to get the unparsed message
+ NAS_PROTOINFO pi;
+
+ ZeroMemory(&pi, sizeof(pi));
+ pi.cbSize = sizeof(NAS_PROTOINFO);
+ pi.szProto = (char *) proto.GetName();
+ pi.status = status;
+ pi.szMsg = NULL;
+
+ if (ServiceExists(MS_NAS_GETSTATE))
+ {
+ if (CallService(MS_NAS_GETSTATE, (WPARAM) &pi, 1) == 0)
+ {
+ if (pi.szMsg == NULL)
+ {
+ pi.szProto = NULL;
+
+ if (CallService(MS_NAS_GETSTATE, (WPARAM) &pi, 1) == 0)
+ {
+ if (pi.szMsg != NULL)
+ {
+ lstrcpyn(status_message, pi.szMsg, MAX_REGS(status_message));
+ mir_free(pi.szMsg);
+ }
+ }
+ }
+ else // if (pi.szMsg != NULL)
+ {
+ lstrcpyn(status_message, pi.szMsg, MAX_REGS(status_message));
+ mir_free(pi.szMsg);
+ }
+ }
+ }
+ // TODO: Remove when removing old NAS services support
+ else
+ {
+ NAS_PROTOINFO *pii = &pi;
+
+ // Old services
+ if (CallService("NewAwaySystem/GetState", (WPARAM) &pii, 1) == 0)
+ {
+ if (pi.szMsg == NULL)
+ {
+ pi.szProto = NULL;
+
+ if (CallService("NewAwaySystem/GetState", (WPARAM) &pii, 1) == 0)
+ {
+ if (pi.szMsg != NULL)
+ {
+ lstrcpyn(status_message, pi.szMsg, MAX_REGS(status_message));
+ mir_free(pi.szMsg);
+ }
+ }
+ }
+ else // if (pi.szMsg != NULL)
+ {
+ lstrcpyn(status_message, pi.szMsg, MAX_REGS(status_message));
+ mir_free(pi.szMsg);
+ }
+ }
+ }
+
+ iswi.szProto = (char *) proto.GetName();
+ iswi.szMsg = status_message;
+ }
+ else
+ {
+ iswi.szMsg = protocols->GetDefaultStatusMsg();
+ }
+
+ iswi.Flags = ISWF_NOCOUNTDOWN;
+
+ CallService(MS_NAS_INVOKESTATUSWINDOW, (WPARAM) &iswi, 0);
+
+ return 0;
+ }
+ else if (ServiceExists(MS_SA_SHOWSTATUSMSGDIALOG))
+ {
+ CallService(MS_SA_SHOWSTATUSMSGDIALOG, 0, (LPARAM) proto_name);
+ return 0;
+ }
+ else if (ServiceExists(MS_SA_CHANGESTATUSMSG))
+ {
+ if (!proto && status == 0)
+ {
+ CallService(MS_SA_CHANGESTATUSMSG, protocols->GetGlobalStatus(), NULL);
+ }
+ else if (status == 0)
+ {
+ CallService(MS_SA_CHANGESTATUSMSG, proto.GetStatus(), (LPARAM) proto_name);
+ }
+ else
+ {
+ CallService(MS_SA_CHANGESTATUSMSG, status, (LPARAM) proto_name);
+ }
+
+ return 0;
+ }
+ else if (!proto || proto.GetStatus() != ID_STATUS_OFFLINE)
+ {
+ if (!status_msg_dialog_open)
+ {
+ InterlockedExchange(&status_msg_dialog_open, 1);
+
+ hwndSetStatusMsg = CreateDialog(hInst, MAKEINTRESOURCE( IDD_SETSTATUSMESSAGE ), NULL, DlgProcSetStatusMessage );
+
+ SendMessage(hwndSetStatusMsg, WMU_SETDATA, status, proto_num);
+ }
+
+ SetForegroundWindow( hwndSetStatusMsg );
+ SetFocus( hwndSetStatusMsg );
+ ShowWindow( hwndSetStatusMsg, SW_SHOW );
+
+ return 0;
+ }
+
+ return -3;
+}
+
+
+static int PluginCommand_CicleThroughtProtocols(WPARAM wParam,LPARAM lParam)
+{
+ DBWriteContactSettingByte(NULL,"MyDetails","CicleThroughtProtocols", (BYTE) wParam);
+
+ LoadOptions();
+
+ return 0;
+} \ No newline at end of file
diff --git a/plugins/MyDetails/mydetails.h b/plugins/MyDetails/mydetails.h
new file mode 100644
index 0000000000..0780f7335e
--- /dev/null
+++ b/plugins/MyDetails/mydetails.h
@@ -0,0 +1,42 @@
+/*
+Copyright (C) 2005 Ricardo Pescuma Domenecci
+
+This is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this file; see the file license.txt. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef __MYDETAILS_H__
+# define __MYDETAILS_H__
+
+
+extern "C"
+{
+
+// Dll init
+BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved);
+
+// Exports:
+__declspec(dllexport) PLUGININFO* MirandaPluginInfo(DWORD mirandaVersion);
+int __declspec(dllexport) Load(PLUGINLINK *link);
+int __declspec(dllexport) Unload(void);
+
+
+}
+
+
+
+
+#endif // __MYDETAILS_H__ \ No newline at end of file
diff --git a/plugins/MyDetails/mydetails.vcproj b/plugins/MyDetails/mydetails.vcproj
new file mode 100644
index 0000000000..db4b4631a3
--- /dev/null
+++ b/plugins/MyDetails/mydetails.vcproj
@@ -0,0 +1,642 @@
+<?xml version="1.0" encoding="windows-1251"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.00"
+ Name="mydetails"
+ ProjectGUID="{A4855451-6447-437C-B024-B36C3C7901EA}"
+ SccProjectName="SAK"
+ SccAuxPath="SAK"
+ SccLocalPath="SAK"
+ SccProvider="SAK">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)/Plugins"
+ IntermediateDirectory="$(SolutionDir)$(ConfigurationName)/Obj/$(ProjectName)"
+ ConfigurationType="2"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ GlobalOptimizations="TRUE"
+ InlineFunctionExpansion="1"
+ FavorSizeOrSpeed="2"
+ AdditionalIncludeDirectories="../../include;sdk"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;MYDETAILS_EXPORTS"
+ StringPooling="TRUE"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="TRUE"
+ UsePrecompiledHeader="3"
+ PrecompiledHeaderThrough="commons.h"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="comctl32.lib odbc32.lib odbccp32.lib"
+ LinkIncremental="1"
+ SuppressStartupBanner="TRUE"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="NDEBUG"
+ MkTypLibCompatible="TRUE"
+ SuppressStartupBanner="TRUE"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Release/mydetails.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)/Plugins"
+ IntermediateDirectory="$(SolutionDir)$(ConfigurationName)/Obj/$(ProjectName)"
+ ConfigurationType="2"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../include;sdk"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;MYDETAILS_EXPORTS"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="2"
+ BufferSecurityCheck="TRUE"
+ UsePrecompiledHeader="3"
+ PrecompiledHeaderThrough="commons.h"
+ BrowseInformation="1"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="4"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="comctl32.lib odbc32.lib odbccp32.lib"
+ LinkIncremental="2"
+ SuppressStartupBanner="TRUE"
+ GenerateDebugInformation="TRUE"
+ GenerateMapFile="TRUE"
+ BaseAddress="0x3EC10000"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="_DEBUG"
+ MkTypLibCompatible="TRUE"
+ SuppressStartupBanner="TRUE"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Debug/mydetails.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="2057"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Debug Unicode|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)/Plugins"
+ IntermediateDirectory="$(SolutionDir)$(ConfigurationName)/Obj/$(ProjectName)"
+ ConfigurationType="2"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../include;sdk"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;MYDETAILS_EXPORTS"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ BufferSecurityCheck="TRUE"
+ UsePrecompiledHeader="3"
+ PrecompiledHeaderThrough="commons.h"
+ BrowseInformation="1"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ DebugInformationFormat="4"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ IgnoreImportLibrary="TRUE"
+ AdditionalDependencies="comctl32.lib odbc32.lib odbccp32.lib"
+ LinkIncremental="2"
+ SuppressStartupBanner="TRUE"
+ GenerateDebugInformation="TRUE"
+ GenerateMapFile="TRUE"
+ BaseAddress="0x3EC10000"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="_DEBUG"
+ MkTypLibCompatible="TRUE"
+ SuppressStartupBanner="TRUE"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Debug/mydetails.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="_DEBUG"
+ Culture="2057"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release Unicode|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)/Plugins"
+ IntermediateDirectory="$(SolutionDir)$(ConfigurationName)/Obj/$(ProjectName)"
+ ConfigurationType="2"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="FALSE"
+ CharacterSet="2"
+ WholeProgramOptimization="FALSE">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="3"
+ GlobalOptimizations="TRUE"
+ InlineFunctionExpansion="1"
+ FavorSizeOrSpeed="2"
+ AdditionalIncludeDirectories="../../include;sdk"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;MYDETAILS_EXPORTS"
+ StringPooling="TRUE"
+ RuntimeLibrary="2"
+ BufferSecurityCheck="TRUE"
+ UsePrecompiledHeader="3"
+ PrecompiledHeaderThrough="commons.h"
+ WarningLevel="3"
+ SuppressStartupBanner="TRUE"
+ CompileAs="0"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLinkerTool"
+ IgnoreImportLibrary="TRUE"
+ AdditionalDependencies="comctl32.lib odbc32.lib odbccp32.lib"
+ GenerateDebugInformation="TRUE"
+ GenerateMapFile="TRUE"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ OptimizeForWindows98="1"
+ TargetMachine="1"/>
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="NDEBUG"
+ MkTypLibCompatible="TRUE"
+ SuppressStartupBanner="TRUE"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Release/mydetails.tlb"
+ HeaderFileName=""/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1033"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCWebDeploymentTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat">
+ <File
+ RelativePath="data.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;MYDETAILS_EXPORTS;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;MYDETAILS_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;MYDETAILS_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;MYDETAILS_EXPORTS;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="frame.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;MYDETAILS_EXPORTS;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;MYDETAILS_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;MYDETAILS_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;MYDETAILS_EXPORTS;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\utils\mir_dblists.c">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ UsePrecompiledHeader="0"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\utils\mir_memory.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;MYDETAILS_EXPORTS;$(NoInherit)"
+ UsePrecompiledHeader="0"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;MYDETAILS_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"
+ UsePrecompiledHeader="0"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;MYDETAILS_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"
+ UsePrecompiledHeader="0"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;MYDETAILS_EXPORTS;$(NoInherit)"
+ UsePrecompiledHeader="0"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\utils\mir_options.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;MYDETAILS_EXPORTS;$(NoInherit)"
+ UsePrecompiledHeader="0"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;MYDETAILS_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"
+ UsePrecompiledHeader="0"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;MYDETAILS_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"
+ UsePrecompiledHeader="0"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;MYDETAILS_EXPORTS;$(NoInherit)"
+ UsePrecompiledHeader="0"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\utils\mir_smileys.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;MYDETAILS_EXPORTS;$(NoInherit)"
+ UsePrecompiledHeader="0"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;MYDETAILS_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"
+ UsePrecompiledHeader="0"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;MYDETAILS_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"
+ UsePrecompiledHeader="0"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;MYDETAILS_EXPORTS;$(NoInherit)"
+ UsePrecompiledHeader="0"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="mydetails.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;MYDETAILS_EXPORTS;$(NoInherit)"
+ UsePrecompiledHeader="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;MYDETAILS_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"
+ UsePrecompiledHeader="1"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;MYDETAILS_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"
+ UsePrecompiledHeader="1"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;MYDETAILS_EXPORTS;$(NoInherit)"
+ UsePrecompiledHeader="1"/>
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="options.cpp">
+ <FileConfiguration
+ Name="Release|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;MYDETAILS_EXPORTS;$(NoInherit)"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;MYDETAILS_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Debug Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_MBCS;_USRDLL;MYDETAILS_EXPORTS;$(NoInherit)"
+ BasicRuntimeChecks="3"
+ BrowseInformation="1"/>
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release Unicode|Win32">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL;MYDETAILS_EXPORTS;$(NoInherit)"/>
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe">
+ <File
+ RelativePath="resource.rc">
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl">
+ <File
+ RelativePath="commons.h">
+ </File>
+ <File
+ RelativePath="data.h">
+ </File>
+ <File
+ RelativePath="frame.h">
+ </File>
+ <File
+ RelativePath="m_mydetails.h">
+ </File>
+ <File
+ RelativePath="m_simpleaway.h">
+ </File>
+ <File
+ RelativePath="..\utils\mir_dblists.h">
+ </File>
+ <File
+ RelativePath="..\utils\mir_memory.h">
+ </File>
+ <File
+ RelativePath="..\utils\mir_options.h">
+ </File>
+ <File
+ RelativePath="..\utils\mir_smileys.h">
+ </File>
+ <File
+ RelativePath="mydetails.h">
+ </File>
+ <File
+ RelativePath="options.h">
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
+
diff --git a/plugins/MyDetails/options.cpp b/plugins/MyDetails/options.cpp
new file mode 100644
index 0000000000..c5c298c798
--- /dev/null
+++ b/plugins/MyDetails/options.cpp
@@ -0,0 +1,189 @@
+/*
+Copyright (C) 2005 Ricardo Pescuma Domenecci
+
+This is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this file; see the file license.txt. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+*/
+
+
+#include "commons.h"
+#include "options.h"
+
+
+
+// Prototypes /////////////////////////////////////////////////////////////////////////////////////
+
+Options opts;
+
+
+static BOOL CALLBACK DlgProcOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+
+
+// Functions //////////////////////////////////////////////////////////////////////////////////////
+
+
+
+static OptPageControl pageControls[] = {
+ { &opts.draw_text_rtl, CONTROL_CHECKBOX, IDC_TEXT_RTL, "TextRTL", (BYTE) 0 },
+ { &opts.cycle_through_protocols, CONTROL_CHECKBOX, IDC_CYCLE_THROUGH_PROTOS, "CicleThroughtProtocols", (BYTE) 1 },
+ { &opts.seconds_to_show_protocol, CONTROL_SPIN, IDC_CYCLE_TIME, "CicleTime", (WORD) 5, IDC_CYCLE_TIME_SPIN, (WORD) 1, (WORD) 255 },
+ { &opts.replace_smileys, CONTROL_CHECKBOX, IDC_REPLACE_SMILEYS, "ReplaceSmileys", (BYTE) 1 },
+ { &opts.resize_smileys, CONTROL_CHECKBOX, IDC_RESIZE_SMILEYS, "ResizeSmileys", (BYTE) 0 },
+ { &opts.use_contact_list_smileys, CONTROL_CHECKBOX, IDC_USE_CONTACT_LIST_SMILEYS, "UseContactListSmileys", (BYTE) 0 },
+ { &opts.global_on_avatar, CONTROL_CHECKBOX, IDC_GLOBAL_ON_AVATAR, "GlobalOnAvatar", (BYTE) 0 },
+ { &opts.global_on_nickname, CONTROL_CHECKBOX, IDC_GLOBAL_ON_NICKNAME, "GlobalOnNickname", (BYTE) 0 },
+ { &opts.global_on_status, CONTROL_CHECKBOX, IDC_GLOBAL_ON_STATUS, "GlobalOnStatus", (BYTE) 0 },
+ { &opts.global_on_status_message, CONTROL_CHECKBOX, IDC_GLOBAL_ON_STATUS_MESSAGE, "GlobalOnStatusMessage", (BYTE) 0 },
+ { &opts.draw_avatar_border, CONTROL_CHECKBOX, IDC_AVATAR_DRAW_BORDER, "AvatarDrawBorders", (BYTE) 0 },
+ { &opts.draw_avatar_border_color, CONTROL_COLOR, IDC_AVATAR_BORDER_COLOR, "AvatarBorderColor", (DWORD) RGB(0,0,0) },
+ { &opts.draw_avatar_round_corner, CONTROL_CHECKBOX, IDC_AVATAR_ROUND_CORNERS, "AvatarRoundCorners", (BYTE) 1 },
+ { &opts.draw_avatar_use_custom_corner_size, CONTROL_CHECKBOX, IDC_AVATAR_CUSTOM_CORNER_SIZE_CHECK, "AvatarUseCustomCornerSize", (BYTE) 0 },
+ { &opts.draw_avatar_custom_corner_size, CONTROL_SPIN, IDC_AVATAR_CUSTOM_CORNER_SIZE, "AvatarCustomCornerSize", (WORD) 4, IDC_AVATAR_CUSTOM_CORNER_SIZE_SPIN, (WORD) 1, (WORD) 255 },
+ { &opts.resize_frame, CONTROL_CHECKBOX, IDC_RESIZE_FRAME, "ResizeFrame", (BYTE) 0 },
+};
+
+
+// Initializations needed by options
+void LoadOptions()
+{
+ if (GetSystemMetrics(SM_MIDEASTENABLED))
+ pageControls[0].dwDefValue = TRUE;
+
+ LoadOpts(pageControls, MAX_REGS(pageControls), MODULE_NAME);
+
+ // This is created here to assert that this key always exists
+ opts.refresh_status_message_timer = DBGetContactSettingWord(NULL,"MyDetails","RefreshStatusMessageTimer",12);
+ DBWriteContactSettingWord(NULL,"MyDetails","RefreshStatusMessageTimer", opts.refresh_status_message_timer);
+
+ SetCycleTime();
+ RedrawFrame();
+}
+
+
+int InitOptionsCallback(WPARAM wParam,LPARAM lParam)
+{
+ OPTIONSDIALOGPAGE odp;
+
+ ZeroMemory(&odp,sizeof(odp));
+ odp.cbSize=sizeof(odp);
+ odp.position=-200000000;
+ odp.hInstance=hInst;
+ odp.pfnDlgProc=DlgProcOpts;
+ odp.pszTemplate=MAKEINTRESOURCE(IDD_OPTS);
+ odp.pszGroup=Translate("Customize");
+ odp.pszTitle=Translate("My Details");
+ odp.flags=ODPF_BOLDGROUPS;
+ CallService(MS_OPT_ADDPAGE,wParam,(LPARAM)&odp);
+
+ return 0;
+}
+
+
+void InitOptions()
+{
+ LoadOptions();
+
+ HookEvent(ME_OPT_INITIALISE, InitOptionsCallback);
+}
+
+// Deinitializations needed by options
+void DeInitOptions()
+{
+}
+
+
+static BOOL CALLBACK DlgProcOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ BOOL ret = SaveOptsDlgProc(pageControls, MAX_REGS(pageControls), MODULE_NAME, hwndDlg, msg, wParam, lParam);
+
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ if(!IsDlgButtonChecked(hwndDlg,IDC_AVATAR_DRAW_BORDER))
+ {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_BORDER_COLOR_L),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_BORDER_COLOR),FALSE);
+ }
+ if(!IsDlgButtonChecked(hwndDlg,IDC_AVATAR_ROUND_CORNERS))
+ {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_CUSTOM_CORNER_SIZE_CHECK),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_CUSTOM_CORNER_SIZE),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_CUSTOM_CORNER_SIZE_SPIN),FALSE);
+ }
+ if(!IsDlgButtonChecked(hwndDlg,IDC_SHOW_PROTO_NAME))
+ {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOW_CYCLE_PROTO_BUTTON),FALSE);
+ }
+ if (!ServiceExists(MS_SMILEYADD_BATCHPARSE))
+ {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_REPLACE_SMILEYS),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_USE_CONTACT_LIST_SMILEYS),FALSE);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_RESIZE_SMILEYS),FALSE);
+ }
+ if (!ServiceExists(MS_CLIST_FRAMES_SETFRAMEOPTIONS))
+ {
+ EnableWindow(GetDlgItem(hwndDlg,IDC_RESIZE_FRAME),FALSE);
+ }
+
+ break;
+ }
+ case WM_COMMAND:
+ {
+ if (LOWORD(wParam)==IDC_AVATAR_DRAW_BORDER)
+ {
+ BOOL enabled = IsDlgButtonChecked(hwndDlg,IDC_AVATAR_DRAW_BORDER);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_BORDER_COLOR_L),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_BORDER_COLOR),enabled);
+ }
+ else if (LOWORD(wParam)==IDC_AVATAR_ROUND_CORNERS)
+ {
+ BOOL enabled = IsDlgButtonChecked(hwndDlg,IDC_AVATAR_ROUND_CORNERS);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_CUSTOM_CORNER_SIZE_CHECK),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_CUSTOM_CORNER_SIZE),enabled);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_AVATAR_CUSTOM_CORNER_SIZE_SPIN),enabled);
+ }
+ else if (LOWORD(wParam)==IDC_SHOW_PROTO_NAME)
+ {
+ BOOL enabled = IsDlgButtonChecked(hwndDlg,IDC_SHOW_PROTO_NAME);
+ EnableWindow(GetDlgItem(hwndDlg,IDC_SHOW_CYCLE_PROTO_BUTTON),enabled);
+ }
+
+ break;
+ }
+ case WM_NOTIFY:
+ {
+ switch (((LPNMHDR)lParam)->idFrom)
+ {
+ case 0:
+ {
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case PSN_APPLY:
+ {
+ LoadOptions();
+
+ return TRUE;
+ }
+ }
+ break;
+ }
+ }
+ break;
+ }
+ }
+
+ return ret;
+}
diff --git a/plugins/MyDetails/options.h b/plugins/MyDetails/options.h
new file mode 100644
index 0000000000..71d5f474c1
--- /dev/null
+++ b/plugins/MyDetails/options.h
@@ -0,0 +1,83 @@
+/*
+Copyright (C) 2005 Ricardo Pescuma Domenecci
+
+This is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this file; see the file license.txt. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef __OPTIONS_H__
+# define __OPTIONS_H__
+
+
+#define TOP 0
+#define LEFT 1
+#define BOTTOM 2
+#define RIGHT 3
+
+struct Options
+{
+ bool cycle_through_protocols;
+ int seconds_to_show_protocol;
+ bool replace_smileys;
+ bool resize_smileys;
+ bool use_contact_list_smileys;
+
+ bool draw_text_rtl;
+// bool draw_text_align_right;
+
+// bool draw_show_protocol_name;
+// bool show_protocol_cycle_button;
+
+ bool global_on_avatar;
+ bool global_on_nickname;
+ bool global_on_status;
+ bool global_on_status_message;
+
+// bool draw_avatar_custom_size;
+// bool draw_avatar_allow_to_grow;
+// int draw_avatar_custom_size_pixels;
+ bool draw_avatar_border;
+ COLORREF draw_avatar_border_color;
+ bool draw_avatar_round_corner;
+ bool draw_avatar_use_custom_corner_size;
+ int draw_avatar_custom_corner_size;
+
+ COLORREF bkg_color;
+// int borders[4];
+
+// bool use_avatar_space_to_draw_text;
+
+ bool resize_frame;
+
+ int refresh_status_message_timer;
+};
+
+extern Options opts;
+
+
+// Initializations needed by options
+void InitOptions();
+
+// Deinitializations needed by options
+void DeInitOptions();
+
+
+// Loads the options from DB
+// It don't need to be called, except in some rare cases
+void LoadOptions();
+
+
+#endif // __OPTIONS_H__
diff --git a/plugins/MyDetails/res/leftarrow.ico b/plugins/MyDetails/res/leftarrow.ico
new file mode 100644
index 0000000000..4953e83bb5
--- /dev/null
+++ b/plugins/MyDetails/res/leftarrow.ico
Binary files differ
diff --git a/plugins/MyDetails/res/listening_to.ico b/plugins/MyDetails/res/listening_to.ico
new file mode 100644
index 0000000000..d359ec1a11
--- /dev/null
+++ b/plugins/MyDetails/res/listening_to.ico
Binary files differ
diff --git a/plugins/MyDetails/res/mail.ico b/plugins/MyDetails/res/mail.ico
new file mode 100644
index 0000000000..ba0e7d35de
--- /dev/null
+++ b/plugins/MyDetails/res/mail.ico
Binary files differ
diff --git a/plugins/MyDetails/res/rightarrow.ico b/plugins/MyDetails/res/rightarrow.ico
new file mode 100644
index 0000000000..2705830a79
--- /dev/null
+++ b/plugins/MyDetails/res/rightarrow.ico
Binary files differ
diff --git a/plugins/MyDetails/resource.h b/plugins/MyDetails/resource.h
new file mode 100644
index 0000000000..9bc277ea60
--- /dev/null
+++ b/plugins/MyDetails/resource.h
@@ -0,0 +1,72 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by resource.rc
+//
+#define IDD_SETNICKNAME 101
+#define IDD_OPTS 102
+#define IDD_SETSTATUSMESSAGE 103
+#define IDR_MENU1 104
+#define IDI_LISTENINGTO 105
+#define IDI_RIGHT_ARROW 106
+#define IDI_LEFT_ARROW 107
+#define IDI_EMAIL 111
+#define IDC_NICKNAME 1000
+#define IDC_SHOW_PROTO_NAME 1001
+#define IDC_CYCLE_THROUGH_PROTOS 1002
+#define IDC_TEXT_RTL 1003
+#define IDC_TEXT_ALIGN_RIGHT 1004
+#define IDC_REPLACE_SMILEYS 1005
+#define IDC_RESIZE_SMILEYS 1006
+#define IDC_RESIZE_FRAME 1007
+#define IDC_RESIZE_SMILEYS2 1008
+#define IDC_USE_CONTACT_LIST_SMILEYS 1008
+#define IDC_STATUSMESSAGE 1009
+#define IDC_GLOBAL_ON_NICKNAME 1009
+#define IDC_AVATAR_ALLOW_TO_GROW 1010
+#define IDC_GLOBAL_ON_STATUS_MESSAGE 1011
+#define IDC_GLOBAL_ON_STATUS 1012
+#define IDC_GLOBAL_ON_AVATAR 1013
+#define IDC_SHOW_CYCLE_PROTO_BUTTON 1014
+#define IDC_AVATAR_CUSTOM_CORNER_SIZE 1622
+#define IDC_AVATAR_CUSTOM_CORNER_SIZE_SPIN 1623
+#define IDC_BORDER_TOP 1624
+#define IDC_BORDER_TOP_SPIN 1625
+#define IDC_BORDER_LEFT 1626
+#define IDC_BORDER_LEFT_SPIN 1627
+#define IDC_BORDER_BOTTOM 1628
+#define IDC_BORDER_BOTTOM_SPIN 1629
+#define IDC_BORDER_RIGHT 1630
+#define IDC_BORDER_RIGHT_SPIN 1631
+#define IDC_CYCLE_TIME 1632
+#define IDC_CYCLE_TIME_SPIN 1633
+#define IDC_AVATAR_CUSTOM_SIZE 1634
+#define IDC_AVATAR_CUSTOM_SIZE_SPIN 1635
+#define IDC_AVATAR_CUSTOM_CORNER_SIZE_CHECK 1761
+#define IDC_AVATAR_DRAW_BORDER 1764
+#define IDC_AVATAR_CUSTOM_SIZE_CHK 1765
+#define IDC_AVATAR_ROUND_CORNERS 1800
+#define IDC_AVATAR_USE_FREE_SPACE 1801
+#define IDC_AVATAR_BORDER_COLOR_L 1839
+#define IDC_AVATAR_BORDER_COLOR 1840
+#define IDC_AVATAR_BKG_COLOR_L 1841
+#define IDC_AVATAR_BKG_COLOR 1842
+#define ID_CYCLE_THROUGH_PROTOS 40004
+#define ID_DONT_CYCLE_THROUGH_PROTOS 40005
+#define ID_SHOW_NEXT_PROTO 40006
+#define ID_SHOW_PREV_PROTO 40007
+#define ID_NICKPOPUP_SETMYNICKNAME 40008
+#define ID_STATUSMESSAGEPOPUP_SETMYSTATUSMESSAGE 40009
+#define ID_AVATARPOPUP_SETMYAVATAR 40010
+#define ID_LISTENINGTOPOPUP_SENDLISTENINGTO 40011
+#define ID_CONTEXTPOPUP_ENABLELISTENINGTO 40012
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 112
+#define _APS_NEXT_COMMAND_VALUE 40013
+#define _APS_NEXT_CONTROL_VALUE 1011
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/plugins/MyDetails/resource.rc b/plugins/MyDetails/resource.rc
new file mode 100644
index 0000000000..5706422e8e
--- /dev/null
+++ b/plugins/MyDetails/resource.rc
@@ -0,0 +1,326 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+#include "../../include/statusmodes.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Neutral resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU)
+#ifdef _WIN32
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_LISTENINGTO ICON DISCARDABLE "res\\listening_to.ico"
+IDI_RIGHT_ARROW ICON DISCARDABLE "res\\rightarrow.ico"
+IDI_LEFT_ARROW ICON DISCARDABLE "res\\leftarrow.ico"
+IDI_EMAIL ICON DISCARDABLE "res\\mail.ico"
+#endif // Neutral resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifndef _MAC
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 0,0,1,11
+ PRODUCTVERSION 0,0,1,11
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x40004L
+ FILETYPE 0x2L
+ FILESUBTYPE 0x0L
+BEGIN
+ BLOCK "StringFileInfo"
+ BEGIN
+ BLOCK "080004b0"
+ BEGIN
+ VALUE "Comments", "\0"
+ VALUE "CompanyName", " \0"
+ VALUE "FileDescription", "MyDetails Miranda Plugin\0"
+ VALUE "FileVersion", "0, 0, 1, 11\0"
+ VALUE "InternalName", "mydetails\0"
+ VALUE "LegalCopyright", "Copyright © 2005-2008 Ricardo Pescuma Domenecci, Drugwash\0"
+ VALUE "LegalTrademarks", "\0"
+ VALUE "OriginalFilename", "mydetails.dll\0"
+ VALUE "PrivateBuild", "\0"
+ VALUE "ProductName", "\0"
+ VALUE "ProductVersion", "0, 0, 1, 11\0"
+ VALUE "SpecialBuild", "\0"
+ END
+ END
+ BLOCK "VarFileInfo"
+ BEGIN
+ VALUE "Translation", 0x800, 1200
+ END
+END
+
+#endif // !_MAC
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_SETNICKNAME DIALOG DISCARDABLE 0, 0, 283, 65
+STYLE DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION |
+ WS_SYSMENU
+CAPTION "Set My Nickname"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ RTEXT "Nickname:",IDC_STATIC,7,8,51,12
+ EDITTEXT IDC_NICKNAME,67,7,209,31,ES_MULTILINE | ES_AUTOVSCROLL |
+ WS_VSCROLL
+ DEFPUSHBUTTON "OK",IDOK,87,44,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,146,44,50,14
+END
+
+IDD_OPTS DIALOGEX 0, 0, 316, 246
+STYLE DS_FIXEDSYS | WS_CHILD | WS_VISIBLE
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg"
+BEGIN
+ GROUPBOX " General ",IDC_STATIC,7,7,302,70
+ CONTROL "Cycle through protocols every:",
+ IDC_CYCLE_THROUGH_PROTOS,"Button",BS_AUTOCHECKBOX |
+ WS_TABSTOP,13,18,114,14
+ EDITTEXT IDC_CYCLE_TIME,129,18,35,12,ES_NUMBER
+ CONTROL "",IDC_CYCLE_TIME_SPIN,"msctls_updown32",UDS_SETBUDDYINT |
+ UDS_ALIGNRIGHT | UDS_ARROWKEYS | UDS_NOTHOUSANDS |
+ UDS_HOTTRACK,156,18,11,12
+ LTEXT "seconds",IDC_STATIC,171,21,32,11
+ CONTROL "Global on avatar",IDC_GLOBAL_ON_AVATAR,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,207,18,96,14
+ CONTROL "RTL",IDC_TEXT_RTL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
+ 13,32,85,14
+ CONTROL "Global on nickname",IDC_GLOBAL_ON_NICKNAME,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,207,32,96,14
+ CONTROL "Auto-resize frame",IDC_RESIZE_FRAME,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,13,46,85,14
+ CONTROL "Use contact list smileys",IDC_USE_CONTACT_LIST_SMILEYS,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,105,46,96,14
+ CONTROL "Global on status",IDC_GLOBAL_ON_STATUS,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,207,46,96,14
+ CONTROL "Replace Smileys",IDC_REPLACE_SMILEYS,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,13,60,85,14
+ CONTROL "Resize Smileys",IDC_RESIZE_SMILEYS,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,105,60,96,14
+ CONTROL "Global on status message",IDC_GLOBAL_ON_STATUS_MESSAGE,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,207,61,96,14
+ GROUPBOX " Avatar ",IDC_STATIC,7,80,302,59
+ CONTROL "Draw border on avatar",IDC_AVATAR_DRAW_BORDER,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,16,95,103,9
+ LTEXT "Border Color:",IDC_AVATAR_BORDER_COLOR_L,123,95,53,10
+ CONTROL "",IDC_AVATAR_BORDER_COLOR,"ColourPicker",WS_TABSTOP,180,
+ 92,17,13
+ CONTROL "Round corners of avatars",IDC_AVATAR_ROUND_CORNERS,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,109,280,8
+ CONTROL "Custom corner size:",
+ IDC_AVATAR_CUSTOM_CORNER_SIZE_CHECK,"Button",
+ BS_AUTOCHECKBOX | WS_TABSTOP,27,122,93,11
+ EDITTEXT IDC_AVATAR_CUSTOM_CORNER_SIZE,127,121,35,12,ES_NUMBER
+ CONTROL "",IDC_AVATAR_CUSTOM_CORNER_SIZE_SPIN,"msctls_updown32",
+ UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_ARROWKEYS |
+ UDS_NOTHOUSANDS | UDS_HOTTRACK,165,121,11,12
+ LTEXT "pixels",IDC_STATIC,179,124,41,11
+END
+
+IDD_SETSTATUSMESSAGE DIALOG DISCARDABLE 0, 0, 283, 68
+STYLE DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION |
+ WS_SYSMENU
+CAPTION "Set My Status Message for All Status"
+FONT 8, "MS Shell Dlg"
+BEGIN
+ RTEXT "Status Message:",IDC_STATIC,7,8,69,12
+ EDITTEXT IDC_STATUSMESSAGE,81,7,195,35,ES_MULTILINE |
+ ES_AUTOVSCROLL | ES_WANTRETURN | WS_VSCROLL
+ DEFPUSHBUTTON "OK",IDOK,87,47,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,146,47,50,14
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO DISCARDABLE
+BEGIN
+ IDD_SETNICKNAME, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 276
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 58
+ END
+
+ IDD_OPTS, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 309
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 238
+ END
+
+ IDD_SETSTATUSMESSAGE, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 276
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 61
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+#endif // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////
+// Portuguese (Brazil) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_PTB)
+#ifdef _WIN32
+LANGUAGE LANG_PORTUGUESE, SUBLANG_PORTUGUESE_BRAZILIAN
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "#include ""../../include/statusmodes.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Menu
+//
+
+IDR_MENU1 MENU DISCARDABLE
+BEGIN
+ POPUP "Status popup"
+ BEGIN
+ MENUITEM "&Offline", ID_STATUS_OFFLINE
+ MENUITEM "On&line", ID_STATUS_ONLINE
+ MENUITEM "&Away", ID_STATUS_AWAY
+ MENUITEM "&NA", ID_STATUS_NA
+ MENUITEM "Occ&upied", ID_STATUS_OCCUPIED
+ MENUITEM "&DND", ID_STATUS_DND
+ MENUITEM "&Free for chat", ID_STATUS_FREECHAT
+ MENUITEM "&Invisible", ID_STATUS_INVISIBLE
+ MENUITEM "On the &Phone", ID_STATUS_ONTHEPHONE
+ MENUITEM "Out to &Lunch", ID_STATUS_OUTTOLUNCH
+ END
+ POPUP "Context popup"
+ BEGIN
+ MENUITEM SEPARATOR
+ MENUITEM "Set My Avatar...", ID_AVATARPOPUP_SETMYAVATAR
+ MENUITEM "Set My Nickname...", ID_NICKPOPUP_SETMYNICKNAME
+ MENUITEM "Set My Status Message...", ID_STATUSMESSAGEPOPUP_SETMYSTATUSMESSAGE
+
+ MENUITEM "Enable Listening To", ID_CONTEXTPOPUP_ENABLELISTENINGTO
+
+ MENUITEM SEPARATOR
+ MENUITEM "Show next protocol", ID_SHOW_NEXT_PROTO
+ MENUITEM "Show previous protocol", ID_SHOW_PREV_PROTO
+ MENUITEM SEPARATOR
+ MENUITEM "Cycle through protocols", ID_CYCLE_THROUGH_PROTOS
+ MENUITEM "Don't cycle through protocols",
+ ID_DONT_CYCLE_THROUGH_PROTOS
+ END
+ POPUP "Nick popup"
+ BEGIN
+ MENUITEM SEPARATOR
+ MENUITEM "Set My Nickname...", ID_NICKPOPUP_SETMYNICKNAME
+ END
+ POPUP "Status message popup"
+ BEGIN
+ MENUITEM SEPARATOR
+ MENUITEM "Set My Status Message...", ID_STATUSMESSAGEPOPUP_SETMYSTATUSMESSAGE
+
+ END
+ POPUP "Avatar popup"
+ BEGIN
+ MENUITEM SEPARATOR
+ MENUITEM "Set My Avatar...", ID_AVATARPOPUP_SETMYAVATAR
+ END
+ POPUP "ListeningTo popup"
+ BEGIN
+ MENUITEM SEPARATOR
+ MENUITEM "Enable Listening To", ID_LISTENINGTOPOPUP_SENDLISTENINGTO
+
+ END
+END
+
+#endif // Portuguese (Brazil) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/plugins/Skins/Docs/langpack_skins.txt b/plugins/Skins/Docs/langpack_skins.txt
new file mode 100644
index 0000000000..1819d74fce
--- /dev/null
+++ b/plugins/Skins/Docs/langpack_skins.txt
@@ -0,0 +1,2 @@
+; Skins
+; Author: Pescuma
diff --git a/plugins/Skins/Docs/skins_changelog.txt b/plugins/Skins/Docs/skins_changelog.txt
new file mode 100644
index 0000000000..fcaa8da44c
--- /dev/null
+++ b/plugins/Skins/Docs/skins_changelog.txt
@@ -0,0 +1,25 @@
+Skins
+
+Changelog:
+
+. 0.0.0.5
+ + Allow changing skins
+ * Updated v8
+ * Updated updater to use googlecode
+
+. 0.0.0.4
+ * Fixed font service iteration
+ * Fixed naming of skin options
+
+. 0.0.0.3
+ * Better handling of small sizes
+
+. 0.0.0.2
+ * Fix for float numbers
+ + Added valign (not used yet)
+ + Added dialog info (allow clients to set script variables starting with info)
+ + The zip will contain also the pdbs (at least until it is more stable)
+ * Fix for ASCII strings
+
+. 0.0.0.1
+ + Initial version \ No newline at end of file
diff --git a/plugins/Skins/Docs/skins_readme.txt b/plugins/Skins/Docs/skins_readme.txt
new file mode 100644
index 0000000000..fd06309ad1
--- /dev/null
+++ b/plugins/Skins/Docs/skins_readme.txt
@@ -0,0 +1,31 @@
+Skins plugin
+----------------
+
+CAUTION: THIS IS AN ALPHA STAGE PLUGIN. IT CAN DO VERY BAD THINGS. USE AT YOUR OWN RISK.
+
+This is a service plugin to allow using different skins. It uses javascript as the language the skins are written, thus allowing a lot of flexibility.
+
+Keep in mind that this is an initial version of the plugin. It is intended to grow a loot (its to do list is bigger than its features list :P ). Currently it allows only calculating the position of elements.
+
+It works based in the consept of a skin beeing a group of small skins (one for each client). The skins are inside the dir <Miranda>\Skins\<Skin name> , and inside that folder, each client skin has the name <Client>.msk
+
+Inside the zip there is also a version of MyDetails using this plugin.
+
+Many thanks to the v8 team for the javascript engine implementation.
+
+This needs Miranda 0.8 to work.
+
+To report bugs/make suggestions, go to the forum thread: http://forums.miranda-im.org/showthread.php?p=172392
+
+
+TODO:
+ - Allow changing skin without restart
+ - Add support for handling skin packs
+ - Add support for emoticons in text fields
+ - Add code to draw elements on screen
+ - Add service to create a new frame only based on the fields
+ - Allow setting variables by the users of the plugin
+
+
+KNOWN PROBLEMS:
+ - It seems to have a memory leak (last time I debugged it, it was inside v8 - maybe I just don't understant its garbage collector?)
diff --git a/plugins/Skins/Docs/skins_version.txt b/plugins/Skins/Docs/skins_version.txt
new file mode 100644
index 0000000000..92fad2b10f
--- /dev/null
+++ b/plugins/Skins/Docs/skins_version.txt
@@ -0,0 +1 @@
+Skins 0.0.0.5 \ No newline at end of file
diff --git a/plugins/Skins/MirandaField.h b/plugins/Skins/MirandaField.h
new file mode 100644
index 0000000000..d89901c77d
--- /dev/null
+++ b/plugins/Skins/MirandaField.h
@@ -0,0 +1,14 @@
+#ifndef __MIRANDA_FIELD_H__
+# define __MIRANDA_FIELD_H__
+
+
+class MirandaField
+{
+public:
+ virtual void configure() = 0;
+};
+
+
+
+
+#endif // __MIRANDA_FIELD_H__
diff --git a/plugins/Skins/MirandaFont.cpp b/plugins/Skins/MirandaFont.cpp
new file mode 100644
index 0000000000..51b0f34f9b
--- /dev/null
+++ b/plugins/Skins/MirandaFont.cpp
@@ -0,0 +1,87 @@
+#include "MirandaFont.h"
+
+MirandaFont::MirandaFont(Field *aField, const char *description)
+ : field(aField), hFont(NULL)
+{
+ ZeroMemory(&fid, sizeof(fid));
+ lstrcpyn(fid.name, CharToTchar(description), sizeof(fid.name));
+}
+
+MirandaFont::~MirandaFont()
+{
+ releaseFont();
+}
+
+void MirandaFont::registerFont(FontState *font)
+{
+ if (fid.cbSize != 0)
+ return;
+
+ MirandaSkinnedDialog * dlg = (MirandaSkinnedDialog *) field->getDialog();
+
+ HDC hdc = GetDC(NULL);
+
+ fid.cbSize = sizeof(fid);
+ lstrcpyn(fid.group, CharToTchar(dlg->getDescription()), sizeof(fid.group));
+ strncpy(fid.dbSettingsGroup, dlg->getModule(), sizeof(fid.dbSettingsGroup));
+
+ char tmp[sizeof(fid.prefix)];
+ mir_snprintf(tmp, sizeof(tmp), "%s%s%sFont", TcharToChar(dlg->getSkinName()), dlg->getName(), field->getName());
+ strncpy(fid.prefix, tmp, sizeof(fid.prefix));
+
+ fid.deffontsettings.colour = font->getColor();
+ fid.deffontsettings.size = -MulDiv(font->getSize(), GetDeviceCaps(hdc, LOGPIXELSY), 72);
+ fid.deffontsettings.style = (font->isBold() ? DBFONTF_BOLD : 0)
+ | (font->isItalic() ? DBFONTF_ITALIC : 0)
+ | (font->isUnderline() ? DBFONTF_UNDERLINE : 0)
+ | (font->isStrikeOut() ? DBFONTF_STRIKEOUT : 0);
+ fid.deffontsettings.charset = DEFAULT_CHARSET;
+ lstrcpyn(fid.deffontsettings.szFace, font->getFace(), sizeof(fid.deffontsettings.szFace));
+ fid.order = dlg->getIndexOf(field);
+ fid.flags = FIDF_DEFAULTVALID | FIDF_ALLOWEFFECTS;
+
+ CallService(MS_FONT_REGISTERT, (WPARAM)&fid, 0);
+
+ ReleaseDC(NULL, hdc);
+
+ HookEventObj(ME_FONT_RELOAD, staticReloadFont, this);
+
+ reloadFont();
+}
+
+void MirandaFont::reloadFont()
+{
+ releaseFont();
+
+ LOGFONT log_font;
+ COLORREF color = (COLORREF) CallService(MS_FONT_GETT, (WPARAM) &fid, (LPARAM) &log_font);
+ hFont = CreateFontIndirect(&log_font);
+
+ switch(field->getType())
+ {
+ case SIMPLE_TEXT:
+ ((TextField *) field)->setFontColor(color);
+ ((TextField *) field)->setFont(hFont);
+ break;
+ case CONTROL_LABEL:
+ case CONTROL_BUTTON:
+ case CONTROL_EDIT:
+ ((ControlField *) field)->setFont(hFont);
+ break;
+ }
+}
+
+int MirandaFont::staticReloadFont(void *obj, WPARAM wParam, LPARAM lParam)
+{
+ ((MirandaFont *) obj)->reloadFont();
+ return 0;
+}
+
+void MirandaFont::releaseFont()
+{
+ if (hFont != NULL)
+ {
+ DeleteObject(hFont);
+ hFont = NULL;
+ }
+} \ No newline at end of file
diff --git a/plugins/Skins/MirandaFont.h b/plugins/Skins/MirandaFont.h
new file mode 100644
index 0000000000..da9a40a06e
--- /dev/null
+++ b/plugins/Skins/MirandaFont.h
@@ -0,0 +1,28 @@
+#ifndef __MIRANDA_FONT_H__
+# define __MIRANDA_FONT_H__
+
+#include "commons.h"
+
+
+class MirandaFont
+{
+public:
+ MirandaFont(Field *field, const char *description);
+ ~MirandaFont();
+
+ void registerFont(FontState *font);
+ void reloadFont();
+
+private:
+ FontIDT fid;
+ HFONT hFont;
+ Field *field;
+
+ void releaseFont();
+
+ static int staticReloadFont(void *obj, WPARAM wParam, LPARAM lParam);
+};
+
+
+
+#endif // __MIRANDA_FONT_H__
diff --git a/plugins/Skins/MirandaIconField.cpp b/plugins/Skins/MirandaIconField.cpp
new file mode 100644
index 0000000000..7861e11091
--- /dev/null
+++ b/plugins/Skins/MirandaIconField.cpp
@@ -0,0 +1,19 @@
+#include "MirandaIconField.h"
+
+MirandaIconField::MirandaIconField(MirandaSkinnedDialog *dlg, const char *name, const char *description)
+ : IconField(dlg, name)
+{
+}
+
+MirandaIconField::~MirandaIconField()
+{
+}
+
+MirandaSkinnedDialog * MirandaIconField::getDialog() const
+{
+ return (MirandaSkinnedDialog *) IconField::getDialog();
+}
+
+void MirandaIconField::configure()
+{
+} \ No newline at end of file
diff --git a/plugins/Skins/MirandaIconField.h b/plugins/Skins/MirandaIconField.h
new file mode 100644
index 0000000000..0f6f15af9e
--- /dev/null
+++ b/plugins/Skins/MirandaIconField.h
@@ -0,0 +1,21 @@
+#ifndef __MIRANDA_ICON_FIELD_H__
+# define __MIRANDA_ICON_FIELD_H__
+
+#include "commons.h"
+#include "MirandaField.h"
+
+
+class MirandaIconField : public IconField, public MirandaField
+{
+public:
+ MirandaIconField(MirandaSkinnedDialog *dlg, const char *name, const char *description);
+ virtual ~MirandaIconField();
+
+ virtual MirandaSkinnedDialog * getDialog() const;
+
+ virtual void configure();
+};
+
+
+
+#endif // __MIRANDA_ICON_FIELD_H__
diff --git a/plugins/Skins/MirandaImageField.cpp b/plugins/Skins/MirandaImageField.cpp
new file mode 100644
index 0000000000..2c9efe11f2
--- /dev/null
+++ b/plugins/Skins/MirandaImageField.cpp
@@ -0,0 +1,19 @@
+#include "MirandaImageField.h"
+
+MirandaImageField::MirandaImageField(MirandaSkinnedDialog *dlg, const char *name, const char *description)
+ : ImageField(dlg, name)
+{
+}
+
+MirandaImageField::~MirandaImageField()
+{
+}
+
+MirandaSkinnedDialog * MirandaImageField::getDialog() const
+{
+ return (MirandaSkinnedDialog *) ImageField::getDialog();
+}
+
+void MirandaImageField::configure()
+{
+} \ No newline at end of file
diff --git a/plugins/Skins/MirandaImageField.h b/plugins/Skins/MirandaImageField.h
new file mode 100644
index 0000000000..70cd1ce873
--- /dev/null
+++ b/plugins/Skins/MirandaImageField.h
@@ -0,0 +1,21 @@
+#ifndef __MIRANDA_IMAGE_FIELD_H__
+# define __MIRANDA_IMAGE_FIELD_H__
+
+#include "commons.h"
+#include "MirandaField.h"
+
+
+class MirandaImageField : public ImageField, public MirandaField
+{
+public:
+ MirandaImageField(MirandaSkinnedDialog *dlg, const char *name, const char *description);
+ virtual ~MirandaImageField();
+
+ virtual MirandaSkinnedDialog * getDialog() const;
+
+ virtual void configure();
+};
+
+
+#endif // __MIRANDA_IMAGE_FIELD_H__
+
diff --git a/plugins/Skins/MirandaSkinnedDialog.cpp b/plugins/Skins/MirandaSkinnedDialog.cpp
new file mode 100644
index 0000000000..97bf236a5a
--- /dev/null
+++ b/plugins/Skins/MirandaSkinnedDialog.cpp
@@ -0,0 +1,252 @@
+#include "commons.h"
+#include "MirandaSkinnedDialog.h"
+
+#define SETTING_NAME_SIZE 256
+
+
+MirandaSkinnedDialog::MirandaSkinnedDialog(const char *name, const char *aDescription, const char *aModule)
+ : SkinnedDialog(name), description(aDescription), module(aModule),
+ skinChangedCallback(NULL), skinChangedCallbackParam(NULL)
+{
+ getSettting("Skin", _T(DEFAULT_SKIN_NAME), skinName, true);
+}
+
+MirandaSkinnedDialog::~MirandaSkinnedDialog()
+{
+}
+
+const char * MirandaSkinnedDialog::getDescription() const
+{
+ return description.c_str();
+}
+
+const char * MirandaSkinnedDialog::getModule() const
+{
+ return module.c_str();
+}
+
+const TCHAR * MirandaSkinnedDialog::getSkinName() const
+{
+ return skinName.c_str();
+}
+
+void MirandaSkinnedDialog::setSkinName(const TCHAR *name)
+{
+ if (skinName == name)
+ return;
+
+ skinName = name;
+ setSettting("Skin", skinName.c_str(), true);
+ updateFilename();
+}
+
+bool MirandaSkinnedDialog::finishedConfiguring()
+{
+ updateFilename();
+
+ if (getDefaultState() == NULL || getOpts() == NULL)
+ return false;
+
+ return true;
+}
+
+void MirandaSkinnedDialog::updateFilename()
+{
+ std::tstring filename;
+ getSkinnedDialogFilename(filename, getSkinName(), getName());
+ setFilename(filename.c_str());
+}
+
+void MirandaSkinnedDialog::loadFromDB(SkinOption *opt)
+{
+ switch(opt->getType())
+ {
+ case CHECKBOX:
+ {
+ opt->setValueCheckbox(getSettting(opt->getName(), opt->getValueCheckbox()));
+ break;
+ }
+ case NUMBER:
+ {
+ opt->setValueNumber(getSettting(opt->getName(), opt->getValueNumber()));
+ break;
+ }
+ case TEXT:
+ {
+ std::tstring tmp;
+ getSettting(opt->getName(), opt->getValueText(), tmp);
+ opt->setValueText(tmp.c_str());
+ break;
+ }
+ }
+}
+
+void MirandaSkinnedDialog::storeToDB(const SkinOptions *opts)
+{
+ for (unsigned int i = 0; i < opts->getNumOptions(); i++)
+ storeToDB(opts->getOption(i));
+
+ fireOnSkinChanged();
+}
+
+void MirandaSkinnedDialog::storeToDB(const SkinOption *opt)
+{
+ switch(opt->getType())
+ {
+ case CHECKBOX:
+ {
+ setSettting(opt->getName(), opt->getValueCheckbox());
+ break;
+ }
+ case NUMBER:
+ {
+ setSettting(opt->getName(), opt->getValueNumber());
+ break;
+ }
+ case TEXT:
+ {
+ setSettting(opt->getName(), opt->getValueText());
+ break;
+ }
+ }
+}
+
+bool MirandaSkinnedDialog::getSettting(const char *name, bool defVal, bool global)
+{
+ char setting[SETTING_NAME_SIZE];
+ getSettingName(setting, name, global);
+
+ return DBGetContactSettingByte(NULL, getModule(), setting, defVal ? 1 : 0) != 0;
+}
+
+void MirandaSkinnedDialog::setSettting(const char *name, bool val, bool global)
+{
+ char setting[SETTING_NAME_SIZE];
+ getSettingName(setting, name, global);
+
+ DBWriteContactSettingByte(NULL, getModule(), setting, val ? 1 : 0);
+}
+
+int MirandaSkinnedDialog::getSettting(const char *name, int defVal, bool global)
+{
+ char setting[SETTING_NAME_SIZE];
+ getSettingName(setting, name, global);
+
+ return DBGetContactSettingDword(NULL, getModule(), setting, defVal);
+}
+
+void MirandaSkinnedDialog::setSettting(const char *name, int val, bool global)
+{
+ char setting[SETTING_NAME_SIZE];
+ getSettingName(setting, name, global);
+
+ DBWriteContactSettingDword(NULL, getModule(), setting, val);
+}
+
+void MirandaSkinnedDialog::getSettting(const char *name, const WCHAR *defVal, std::wstring &ret, bool global)
+{
+ char setting[SETTING_NAME_SIZE];
+ getSettingName(setting, name, global);
+
+ DBVARIANT dbv = {0};
+ if (DBGetContactSettingWString(NULL, getModule(), setting, &dbv))
+ {
+ ret = defVal;
+ return;
+ }
+
+ ret = dbv.pwszVal;
+ DBFreeVariant(&dbv);
+}
+
+void MirandaSkinnedDialog::setSettting(const char *name, const WCHAR *val, bool global)
+{
+ char setting[SETTING_NAME_SIZE];
+ getSettingName(setting, name, global);
+
+ DBWriteContactSettingWString(NULL, getModule(), setting, val);
+}
+
+void MirandaSkinnedDialog::getSettting(const char *name, const char *defVal, std::string &ret, bool global)
+{
+ char setting[SETTING_NAME_SIZE];
+ getSettingName(setting, name, global);
+
+ DBVARIANT dbv = {0};
+ if (DBGetContactSettingString(NULL, getModule(), setting, &dbv))
+ {
+ ret = defVal;
+ return;
+ }
+
+ ret = dbv.pszVal;
+ DBFreeVariant(&dbv);
+}
+
+void MirandaSkinnedDialog::setSettting(const char *name, const char *val, bool global)
+{
+ char setting[SETTING_NAME_SIZE];
+ getSettingName(setting, name, global);
+
+ DBWriteContactSettingString(NULL, getModule(), setting, val);
+}
+
+void MirandaSkinnedDialog::getSettingName(char *setting, const char * name, bool global)
+{
+ if (global)
+ mir_snprintf(setting, SETTING_NAME_SIZE, "%s%s", getName(), name);
+ else
+ mir_snprintf(setting, SETTING_NAME_SIZE, "%s%s%s", TcharToChar(getSkinName()), getName(), name);
+}
+
+void MirandaSkinnedDialog::setOnSkinChangedCallback(MirandaSkinnedCallback cb, void *param)
+{
+ skinChangedCallback = cb;
+ skinChangedCallbackParam = param;
+}
+
+void MirandaSkinnedDialog::fireOnSkinChanged()
+{
+ if (skinChangedCallback != NULL)
+ skinChangedCallback(skinChangedCallbackParam, this);
+}
+
+int MirandaSkinnedDialog::compile()
+{
+ int ret = SkinnedDialog::compile();
+
+ if (ret == 2)
+ {
+ SkinOptions * opts = getOpts();
+ _ASSERT(opts != NULL);
+
+ for(unsigned int i = 0; i < opts->getNumOptions(); ++i)
+ {
+ SkinOption *opt = opts->getOption(i);
+ loadFromDB(opt);
+ opt->setOnChangeCallback(&staticOnOptionChange, this);
+ }
+
+ for(unsigned int i = 0; i < getFieldCount(); ++i)
+ {
+ MirandaField *field = dynamic_cast<MirandaField *>(getField(i));
+ field->configure();
+ }
+
+ fireOnSkinChanged();
+ }
+
+ return ret;
+}
+
+void MirandaSkinnedDialog::onOptionChange(const SkinOption *opt)
+{
+ storeToDB(opt);
+}
+
+void MirandaSkinnedDialog::staticOnOptionChange(void *param, const SkinOption *opt)
+{
+ _ASSERT(param != NULL);
+
+ ((MirandaSkinnedDialog *) param)->onOptionChange(opt);
+}
diff --git a/plugins/Skins/MirandaSkinnedDialog.h b/plugins/Skins/MirandaSkinnedDialog.h
new file mode 100644
index 0000000000..d556b9a495
--- /dev/null
+++ b/plugins/Skins/MirandaSkinnedDialog.h
@@ -0,0 +1,64 @@
+#ifndef __MIRANDA_SKINNED_DIALOG_H__
+# define __MIRANDA_SKINNED_DIALOG_H__
+
+#include "SkinLib\SkinnedDialog.h"
+
+class SkinOption;
+class MirandaSkinnedDialog;
+
+typedef void (*MirandaSkinnedCallback)(void *param, const MirandaSkinnedDialog *dlg);
+
+
+class MirandaSkinnedDialog : public SkinnedDialog
+{
+public:
+ MirandaSkinnedDialog(const char *name, const char *description, const char *module);
+ virtual ~MirandaSkinnedDialog();
+
+ virtual const char * getDescription() const;
+ virtual const char * getModule() const;
+
+ virtual const TCHAR * getSkinName() const;
+ virtual void setSkinName(const TCHAR *name);
+
+ virtual bool finishedConfiguring();
+
+ virtual void storeToDB(const SkinOptions *opts);
+
+ virtual void setOnSkinChangedCallback(MirandaSkinnedCallback cb, void *param);
+
+protected:
+ virtual int compile();
+
+private:
+ std::string description;
+ std::string module;
+ std::tstring skinName;
+ MirandaSkinnedCallback skinChangedCallback;
+ void *skinChangedCallbackParam;
+
+ void updateFilename();
+
+ void loadFromDB(SkinOption *opt);
+ void storeToDB(const SkinOption *opt);
+
+ bool getSettting(const char *name, bool defVal, bool global = false);
+ void setSettting(const char *name, bool val, bool global = false);
+ int getSettting(const char *name, int defVal, bool global = false);
+ void setSettting(const char *name, int val, bool global = false);
+ void getSettting(const char *name, const WCHAR *defVal, std::wstring &ret, bool global = false);
+ void setSettting(const char *name, const WCHAR *val, bool global = false);
+ void getSettting(const char *name, const char *defVal, std::string &ret, bool global = false);
+ void setSettting(const char *name, const char *val, bool global = false);
+
+ inline void getSettingName(char *setting, const char * name, bool global);
+
+ void fireOnSkinChanged();
+
+ void onOptionChange(const SkinOption *opt);
+
+ static void staticOnOptionChange(void *param, const SkinOption *opt);
+};
+
+
+#endif // __MIRANDA_SKINNED_DIALOG_H__
diff --git a/plugins/Skins/MirandaTextField.cpp b/plugins/Skins/MirandaTextField.cpp
new file mode 100644
index 0000000000..4a3591a322
--- /dev/null
+++ b/plugins/Skins/MirandaTextField.cpp
@@ -0,0 +1,27 @@
+#include "MirandaTextField.h"
+#include "MirandaFont.h"
+
+
+MirandaTextField::MirandaTextField(MirandaSkinnedDialog *dlg, const char *name, const char *aDescription)
+ : TextField(dlg, name)
+{
+ font = new MirandaFont(this, aDescription);
+}
+
+MirandaTextField::~MirandaTextField()
+{
+ delete font;
+}
+
+MirandaSkinnedDialog * MirandaTextField::getDialog() const
+{
+ return (MirandaSkinnedDialog *) TextField::getDialog();
+}
+
+void MirandaTextField::configure()
+{
+ TextFieldState *field = (TextFieldState *) getDialog()->getDefaultState()->getField(getName());
+ _ASSERT(field != NULL);
+
+ font->registerFont(field->getFont());
+}
diff --git a/plugins/Skins/MirandaTextField.h b/plugins/Skins/MirandaTextField.h
new file mode 100644
index 0000000000..36b7ea7292
--- /dev/null
+++ b/plugins/Skins/MirandaTextField.h
@@ -0,0 +1,27 @@
+#ifndef __MIRANDA_TEXT_FIELD_H__
+# define __MIRANDA_TEXT_FIELD_H__
+
+#include "commons.h"
+#include "MirandaField.h"
+
+class MirandaFont;
+
+
+class MirandaTextField : public TextField, public MirandaField
+{
+public:
+ MirandaTextField(MirandaSkinnedDialog *dlg, const char *name, const char *description);
+ virtual ~MirandaTextField();
+
+ virtual MirandaSkinnedDialog * getDialog() const;
+
+ virtual void configure();
+
+private:
+ MirandaFont *font;
+
+};
+
+
+
+#endif // __MIRANDA_TEXT_FIELD_H__
diff --git a/plugins/Skins/SkinLib/BorderState.cpp b/plugins/Skins/SkinLib/BorderState.cpp
new file mode 100644
index 0000000000..83dcdbcf11
--- /dev/null
+++ b/plugins/Skins/SkinLib/BorderState.cpp
@@ -0,0 +1,61 @@
+#include "globals.h"
+#include <windows.h>
+#include "BorderState.h"
+
+BorderState::BorderState(int aLeft, int aRight, int aTop, int aBottom)
+ : left(aLeft), right(aRight), top(aTop), bottom(aBottom)
+{
+}
+
+BorderState::~BorderState()
+{
+}
+
+int BorderState::getLeft() const
+{
+ return left;
+}
+
+void BorderState::setLeft(int left)
+{
+ this->left = max(0, left);
+}
+
+int BorderState::getRight() const
+{
+ return right;
+}
+
+void BorderState::setRight(int right)
+{
+ this->right = max(0, right);
+}
+
+int BorderState::getTop() const
+{
+ return top;
+}
+
+void BorderState::setTop(int top)
+{
+ this->top = max(0, top);
+}
+
+int BorderState::getBottom() const
+{
+ return bottom;
+}
+
+void BorderState::setBottom(int bottom)
+{
+ this->bottom = max(0, bottom);
+}
+
+void BorderState::setAll(int border)
+{
+ border = max(0, border);
+ left = border;
+ right = border;
+ top = border;
+ bottom = border;
+}
diff --git a/plugins/Skins/SkinLib/BorderState.h b/plugins/Skins/SkinLib/BorderState.h
new file mode 100644
index 0000000000..2cac3c1aa5
--- /dev/null
+++ b/plugins/Skins/SkinLib/BorderState.h
@@ -0,0 +1,28 @@
+#pragma once
+
+class BorderState
+{
+public:
+ BorderState(int left, int right, int top, int bottom);
+ ~BorderState();
+
+ int getLeft() const;
+ void setLeft(int left);
+
+ int getRight() const;
+ void setRight(int right);
+
+ int getTop() const;
+ void setTop(int top);
+
+ int getBottom() const;
+ void setBottom(int bottom);
+
+ void setAll(int border);
+
+private:
+ int left;
+ int right;
+ int top;
+ int bottom;
+};
diff --git a/plugins/Skins/SkinLib/BorderState_v8_wrapper.cpp b/plugins/Skins/SkinLib/BorderState_v8_wrapper.cpp
new file mode 100644
index 0000000000..71cc057419
--- /dev/null
+++ b/plugins/Skins/SkinLib/BorderState_v8_wrapper.cpp
@@ -0,0 +1,160 @@
+#include "globals.h"
+#include "BorderState_v8_wrapper.h"
+#include <v8.h>
+#include "BorderState.h"
+
+using namespace v8;
+
+
+#ifdef UNICODE
+# define V8_TCHAR uint16_t
+#else
+# define V8_TCHAR char
+#endif
+
+
+static Handle<Value> Get_BorderState_left(Local<String> property, const AccessorInfo &info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return scope.Close( Undefined() );
+
+ BorderState *tmp = (BorderState *) wrap->Value();
+ if (tmp == NULL)
+ return scope.Close( Undefined() );
+
+ return scope.Close( Int32::New(tmp->getLeft()) );
+}
+
+static void Set_BorderState_left(Local<String> property, Local<Value> value, const AccessorInfo& info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return;
+
+ BorderState *tmp = (BorderState *) wrap->Value();
+ if (tmp == NULL)
+ return;
+
+ if (!value.IsEmpty() && value->IsNumber())
+ tmp->setLeft(value->Int32Value());
+}
+
+
+static Handle<Value> Get_BorderState_right(Local<String> property, const AccessorInfo &info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return scope.Close( Undefined() );
+
+ BorderState *tmp = (BorderState *) wrap->Value();
+ if (tmp == NULL)
+ return scope.Close( Undefined() );
+
+ return scope.Close( Int32::New(tmp->getRight()) );
+}
+
+static void Set_BorderState_right(Local<String> property, Local<Value> value, const AccessorInfo& info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return;
+
+ BorderState *tmp = (BorderState *) wrap->Value();
+ if (tmp == NULL)
+ return;
+
+ if (!value.IsEmpty() && value->IsNumber())
+ tmp->setRight(value->Int32Value());
+}
+
+
+static Handle<Value> Get_BorderState_top(Local<String> property, const AccessorInfo &info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return scope.Close( Undefined() );
+
+ BorderState *tmp = (BorderState *) wrap->Value();
+ if (tmp == NULL)
+ return scope.Close( Undefined() );
+
+ return scope.Close( Int32::New(tmp->getTop()) );
+}
+
+static void Set_BorderState_top(Local<String> property, Local<Value> value, const AccessorInfo& info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return;
+
+ BorderState *tmp = (BorderState *) wrap->Value();
+ if (tmp == NULL)
+ return;
+
+ if (!value.IsEmpty() && value->IsNumber())
+ tmp->setTop(value->Int32Value());
+}
+
+
+static Handle<Value> Get_BorderState_bottom(Local<String> property, const AccessorInfo &info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return scope.Close( Undefined() );
+
+ BorderState *tmp = (BorderState *) wrap->Value();
+ if (tmp == NULL)
+ return scope.Close( Undefined() );
+
+ return scope.Close( Int32::New(tmp->getBottom()) );
+}
+
+static void Set_BorderState_bottom(Local<String> property, Local<Value> value, const AccessorInfo& info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return;
+
+ BorderState *tmp = (BorderState *) wrap->Value();
+ if (tmp == NULL)
+ return;
+
+ if (!value.IsEmpty() && value->IsNumber())
+ tmp->setBottom(value->Int32Value());
+}
+
+
+void AddBorderStateAcessors(Handle<ObjectTemplate> &templ)
+{
+ HandleScope scope;
+
+ templ->SetAccessor(String::New("left"), Get_BorderState_left, Set_BorderState_left);
+ templ->SetAccessor(String::New("right"), Get_BorderState_right, Set_BorderState_right);
+ templ->SetAccessor(String::New("top"), Get_BorderState_top, Set_BorderState_top);
+ templ->SetAccessor(String::New("bottom"), Get_BorderState_bottom, Set_BorderState_bottom);
+}
diff --git a/plugins/Skins/SkinLib/BorderState_v8_wrapper.h b/plugins/Skins/SkinLib/BorderState_v8_wrapper.h
new file mode 100644
index 0000000000..70af9e41dc
--- /dev/null
+++ b/plugins/Skins/SkinLib/BorderState_v8_wrapper.h
@@ -0,0 +1,10 @@
+#ifndef __BORDER_STATE_V8_WRAPPER_H__
+# define __BORDER_STATE_V8_WRAPPER_H__
+
+#include <v8.h>
+
+void AddBorderStateAcessors(v8::Handle<v8::ObjectTemplate> &templ);
+
+
+
+#endif // __BORDER_STATE_V8_WRAPPER_H__
diff --git a/plugins/Skins/SkinLib/ButtonField.cpp b/plugins/Skins/SkinLib/ButtonField.cpp
new file mode 100644
index 0000000000..e6c82ba5e3
--- /dev/null
+++ b/plugins/Skins/SkinLib/ButtonField.cpp
@@ -0,0 +1,22 @@
+#include "globals.h"
+#include "ButtonField.h"
+#include "ButtonFieldState.h"
+
+
+ButtonField::ButtonField(Dialog *dlg, const char *name, HWND hwnd) : ControlField(dlg, name, hwnd)
+{
+}
+
+ButtonField::~ButtonField()
+{
+}
+
+FieldType ButtonField::getType() const
+{
+ return CONTROL_BUTTON;
+}
+
+FieldState * ButtonField::createState(DialogState *dialogState)
+{
+ return new ButtonFieldState(dialogState, this);
+} \ No newline at end of file
diff --git a/plugins/Skins/SkinLib/ButtonField.h b/plugins/Skins/SkinLib/ButtonField.h
new file mode 100644
index 0000000000..0d7a1555ca
--- /dev/null
+++ b/plugins/Skins/SkinLib/ButtonField.h
@@ -0,0 +1,19 @@
+#ifndef __BUTTON_FIELD_H__
+# define __BUTTON_FIELD_H__
+
+#include "ControlField.h"
+
+class ButtonField : public ControlField
+{
+public:
+ ButtonField(Dialog *dlg, const char *name, HWND hwnd);
+ virtual ~ButtonField();
+
+ virtual FieldType getType() const;
+
+ virtual FieldState * createState(DialogState *dialogState);
+};
+
+
+
+#endif // __BUTTON_FIELD_H__
diff --git a/plugins/Skins/SkinLib/ButtonFieldState.cpp b/plugins/Skins/SkinLib/ButtonFieldState.cpp
new file mode 100644
index 0000000000..986484b20b
--- /dev/null
+++ b/plugins/Skins/SkinLib/ButtonFieldState.cpp
@@ -0,0 +1,30 @@
+#include "globals.h"
+#include "ButtonFieldState.h"
+
+ButtonFieldState::ButtonFieldState(DialogState *dialog, ControlField *field)
+ : ControlFieldState(dialog, field)
+{
+}
+
+ButtonFieldState::~ButtonFieldState()
+{
+}
+
+Size ButtonFieldState::getPreferedSize() const
+{
+ Size ret = getTextPreferedSize(DT_SINGLELINE);
+
+ int border = getField()->getBorderSize();
+ ret.x += 2 * border;
+ ret.y += 2 * border;
+
+ ret.x += 12;
+ ret.y += 10;
+
+ return ret;
+}
+
+bool ButtonFieldState::isEmpty() const
+{
+ return false;
+} \ No newline at end of file
diff --git a/plugins/Skins/SkinLib/ButtonFieldState.h b/plugins/Skins/SkinLib/ButtonFieldState.h
new file mode 100644
index 0000000000..12b701035a
--- /dev/null
+++ b/plugins/Skins/SkinLib/ButtonFieldState.h
@@ -0,0 +1,23 @@
+#ifndef __BUTTON_FIELD_STATE_H__
+# define __BUTTON_FIELD_STATE_H__
+
+#include "ControlFieldState.h"
+
+
+class ButtonFieldState : public ControlFieldState
+{
+public:
+ virtual ~ButtonFieldState();
+
+ virtual Size getPreferedSize() const;
+
+ virtual bool isEmpty() const;
+
+private:
+ ButtonFieldState(DialogState *dialog, ControlField *field);
+
+ friend class ButtonField;
+};
+
+
+#endif // __BUTTON_FIELD_STATE_H__
diff --git a/plugins/Skins/SkinLib/ButtonFieldState_v8_wrapper.cpp b/plugins/Skins/SkinLib/ButtonFieldState_v8_wrapper.cpp
new file mode 100644
index 0000000000..c5916b284c
--- /dev/null
+++ b/plugins/Skins/SkinLib/ButtonFieldState_v8_wrapper.cpp
@@ -0,0 +1,20 @@
+#include "globals.h"
+#include "ButtonFieldState_v8_wrapper.h"
+#include <v8.h>
+#include "ButtonFieldState.h"
+
+using namespace v8;
+
+
+#ifdef UNICODE
+# define V8_TCHAR uint16_t
+#else
+# define V8_TCHAR char
+#endif
+
+
+void AddButtonFieldStateAcessors(Handle<ObjectTemplate> &templ)
+{
+ HandleScope scope;
+
+}
diff --git a/plugins/Skins/SkinLib/ButtonFieldState_v8_wrapper.h b/plugins/Skins/SkinLib/ButtonFieldState_v8_wrapper.h
new file mode 100644
index 0000000000..c69fdc5c87
--- /dev/null
+++ b/plugins/Skins/SkinLib/ButtonFieldState_v8_wrapper.h
@@ -0,0 +1,10 @@
+#ifndef __BUTTON_FIELD_STATE_V8_WRAPPER_H__
+# define __BUTTON_FIELD_STATE_V8_WRAPPER_H__
+
+#include <v8.h>
+
+void AddButtonFieldStateAcessors(v8::Handle<v8::ObjectTemplate> &templ);
+
+
+
+#endif // __BUTTON_FIELD_STATE_V8_WRAPPER_H__
diff --git a/plugins/Skins/SkinLib/ControlField.cpp b/plugins/Skins/SkinLib/ControlField.cpp
new file mode 100644
index 0000000000..dd9d7026d9
--- /dev/null
+++ b/plugins/Skins/SkinLib/ControlField.cpp
@@ -0,0 +1,123 @@
+#include "globals.h"
+#include "ControlField.h"
+#include "ControlFieldState.h"
+
+
+ControlField::ControlField(Dialog *dlg, const char *name, HWND aHwnd)
+ : Field(dlg, name), hwnd(aHwnd), textSet(false), hFont(NULL)
+{
+}
+
+
+ControlField::~ControlField()
+{
+}
+
+
+HWND ControlField::getHWND()
+{
+ return hwnd;
+}
+
+
+
+void ControlField::setText(const TCHAR *text)
+{
+ if (text == NULL)
+ {
+ if (!textSet)
+ return;
+
+ textSet = false;
+ this->text.clear();
+ fireOnChange();
+ }
+ else
+ {
+ textSet = true;
+ if (this->text == text)
+ return;
+
+ this->text = text;
+ // SetWindowText(hwnd, text);
+ fireOnChange();
+ }
+}
+
+
+const TCHAR * ControlField::getText()
+{
+ if (textSet)
+ return text.c_str();
+
+ // Control text is the default value
+ int length = GetWindowTextLength(hwnd);
+ if (length <= 0)
+ {
+ text = _T("");
+ }
+ else
+ {
+ TCHAR *tmp = new TCHAR[length+1];
+
+ if (GetWindowText(hwnd, tmp, length+1) == 0)
+ tmp[0] = 0;
+
+ text = tmp;
+
+ delete[] tmp;
+ }
+
+ return text.c_str();
+}
+
+
+void ControlField::setFont(HFONT hFont)
+{
+ if (this->hFont == hFont)
+ return;
+
+ this->hFont = hFont;
+// SendMessage(hwnd, WM_SETFONT, (WPARAM) hFont, FALSE);
+ fireOnChange();
+}
+
+
+HFONT ControlField::getFont() const
+{
+ if (hFont != NULL)
+ return hFont;
+
+ // Control font is the default value
+ return (HFONT) SendMessage(hwnd, WM_GETFONT, 0, 0);
+}
+
+
+COLORREF ControlField::getFontColor() const
+{
+ return GetSysColor(COLOR_WINDOWTEXT);
+}
+
+
+int ControlField::getBorderSize() const
+{
+ int exstyle = GetWindowLong(hwnd, GWL_EXSTYLE);
+ if (exstyle & WS_EX_CLIENTEDGE)
+ return GetSystemMetrics(SM_CXEDGE);
+ if (exstyle & WS_EX_STATICEDGE)
+ return GetSystemMetrics(SM_CXBORDER);
+
+ int style = GetWindowLong(hwnd, GWL_STYLE);
+ if (style & WS_BORDER)
+ return GetSystemMetrics(SM_CXBORDER);
+
+ return 0;
+}
+
+bool ControlField::isScrollVisible(bool horizontal) const
+{
+ SCROLLBARINFO sbi = {0};
+ sbi.cbSize = sizeof(SCROLLBARINFO);
+ GetScrollBarInfo(hwnd, horizontal ? OBJID_HSCROLL : OBJID_VSCROLL, &sbi);
+ return (sbi.rgstate[0] & STATE_SYSTEM_INVISIBLE) == 0;
+}
diff --git a/plugins/Skins/SkinLib/ControlField.h b/plugins/Skins/SkinLib/ControlField.h
new file mode 100644
index 0000000000..014ee04b9b
--- /dev/null
+++ b/plugins/Skins/SkinLib/ControlField.h
@@ -0,0 +1,37 @@
+#ifndef __LABEL_CONTROL_FIELD_H__
+# define __LABEL_CONTROL_FIELD_H__
+
+#include "Field.h"
+
+class ControlField : public Field
+{
+public:
+ ControlField(Dialog *dlg, const char *name, HWND hwnd);
+ virtual ~ControlField();
+
+ virtual HWND getHWND();
+
+ virtual void setText(const TCHAR *text);
+ virtual const TCHAR * getText();
+
+ virtual void setFont(HFONT hFont);
+ virtual HFONT getFont() const;
+
+ virtual COLORREF getFontColor() const;
+
+ virtual int getBorderSize() const;
+
+ virtual bool isScrollVisible(bool horizontal) const;
+
+private:
+ HWND hwnd;
+
+ bool textSet;
+ std::tstring text;
+
+ HFONT hFont;
+};
+
+
+
+#endif // __LABEL_CONTROL_FIELD_H__
diff --git a/plugins/Skins/SkinLib/ControlFieldState.cpp b/plugins/Skins/SkinLib/ControlFieldState.cpp
new file mode 100644
index 0000000000..37c412058a
--- /dev/null
+++ b/plugins/Skins/SkinLib/ControlFieldState.cpp
@@ -0,0 +1,86 @@
+#include "globals.h"
+#include "ControlFieldState.h"
+
+
+ControlFieldState::ControlFieldState(DialogState *dialog, ControlField *field)
+ : FieldState(dialog, field), textSet(false), font(field->getFont(), field->getFontColor())
+{
+}
+
+
+ControlFieldState::~ControlFieldState()
+{
+}
+
+
+ControlField * ControlFieldState::getField() const
+{
+ return (ControlField *) FieldState::getField();
+}
+
+
+Size ControlFieldState::getTextPreferedSize(unsigned int format) const
+{
+ HDC hdc = CreateCompatibleDC(NULL);
+
+ HFONT newFont = getFont()->getHFONT();
+ HFONT oldFont = (HFONT) SelectObject(hdc, newFont);
+
+ int width = 0;
+ int height = 0;
+
+ const TCHAR *text = getText();
+ int len = lstrlen(text);
+ if (len <= 0)
+ {
+ TEXTMETRIC tm = {0};
+ GetTextMetrics(hdc, &tm);
+ height = tm.tmHeight;
+ }
+ else
+ {
+ RECT rc = {0};
+ if ((format & DT_SINGLELINE) == 0 && size.x >= 0)
+ {
+ format |= DT_WORDBREAK;
+ rc.right = size.x;
+ }
+ DrawText(hdc, text, len, &rc, DT_CALCRECT | format);
+ width = rc.right - rc.left;
+ height = rc.bottom - rc.top;
+ }
+
+ SelectObject(hdc, oldFont);
+
+ DeleteDC(hdc);
+
+ return Size(width, height);
+}
+
+
+const TCHAR * ControlFieldState::getText() const
+{
+ if (textSet)
+ return text.c_str();
+
+ return getField()->getText();
+}
+
+
+void ControlFieldState::setText(const TCHAR *text)
+{
+ this->text = text;
+ textSet = true;
+}
+
+
+FontState * ControlFieldState::getFont()
+{
+ return &font;
+}
+
+
+const FontState * ControlFieldState::getFont() const
+{
+ return &font;
+} \ No newline at end of file
diff --git a/plugins/Skins/SkinLib/ControlFieldState.h b/plugins/Skins/SkinLib/ControlFieldState.h
new file mode 100644
index 0000000000..85186c304a
--- /dev/null
+++ b/plugins/Skins/SkinLib/ControlFieldState.h
@@ -0,0 +1,39 @@
+#ifndef __LABEL_CONTROL_FIELD_STATE_H__
+# define __LABEL_CONTROL_FIELD_STATE_H__
+
+#include "ControlField.h"
+#include "FieldState.h"
+#include "FontState.h"
+
+
+class ControlFieldState : public FieldState
+{
+public:
+ virtual ~ControlFieldState();
+
+ virtual ControlField * getField() const;
+
+ virtual Size getPreferedSize() const = 0;
+
+ virtual const TCHAR * getText() const;
+ virtual void setText(const TCHAR *text);
+
+ virtual FontState * getFont();
+ virtual const FontState * getFont() const;
+
+protected:
+ ControlFieldState(DialogState *dialog, ControlField *field);
+
+ virtual Size getTextPreferedSize(unsigned int format) const;
+
+private:
+ FontState font;
+
+ bool textSet;
+ std::tstring text;
+
+ friend class ControlField;
+};
+
+
+#endif // __LABEL_CONTROL_FIELD_STATE_H__ \ No newline at end of file
diff --git a/plugins/Skins/SkinLib/ControlFieldState_v8_wrapper.cpp b/plugins/Skins/SkinLib/ControlFieldState_v8_wrapper.cpp
new file mode 100644
index 0000000000..70d3e06a45
--- /dev/null
+++ b/plugins/Skins/SkinLib/ControlFieldState_v8_wrapper.cpp
@@ -0,0 +1,59 @@
+#include "globals.h"
+#include "ControlFieldState_v8_wrapper.h"
+#include <v8.h>
+#include "ControlFieldState.h"
+#include <utf8_helpers.h>
+
+using namespace v8;
+
+
+#ifdef UNICODE
+# define V8_TCHAR uint16_t
+#else
+# define V8_TCHAR char
+#endif
+
+
+static Handle<Value> Get_ControlFieldState_text(Local<String> property, const AccessorInfo &info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return scope.Close( Undefined() );
+
+ ControlFieldState *tmp = (ControlFieldState *) wrap->Value();
+ if (tmp == NULL)
+ return scope.Close( Undefined() );
+
+ return scope.Close( String::New((const V8_TCHAR *) tmp->getText()) );
+}
+
+static void Set_ControlFieldState_text(Local<String> property, Local<Value> value, const AccessorInfo& info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return;
+
+ ControlFieldState *tmp = (ControlFieldState *) wrap->Value();
+ if (tmp == NULL)
+ return;
+
+ if (!value.IsEmpty() && value->IsString())
+ {
+ String::Utf8Value utf8_value(value);
+ tmp->setText(Utf8ToTchar(*utf8_value));
+ }
+}
+
+
+void AddControlFieldStateAcessors(Handle<ObjectTemplate> &templ)
+{
+ HandleScope scope;
+
+ templ->SetAccessor(String::New("text"), Get_ControlFieldState_text, Set_ControlFieldState_text);
+}
diff --git a/plugins/Skins/SkinLib/ControlFieldState_v8_wrapper.h b/plugins/Skins/SkinLib/ControlFieldState_v8_wrapper.h
new file mode 100644
index 0000000000..c86964ce30
--- /dev/null
+++ b/plugins/Skins/SkinLib/ControlFieldState_v8_wrapper.h
@@ -0,0 +1,10 @@
+#ifndef __CONTROL_FIELD_STATE_V8_WRAPPER_H__
+# define __CONTROL_FIELD_STATE_V8_WRAPPER_H__
+
+#include <v8.h>
+
+void AddControlFieldStateAcessors(v8::Handle<v8::ObjectTemplate> &templ);
+
+
+
+#endif // __CONTROL_FIELD_STATE_V8_WRAPPER_H__
diff --git a/plugins/Skins/SkinLib/Dialog.cpp b/plugins/Skins/SkinLib/Dialog.cpp
new file mode 100644
index 0000000000..edc8437817
--- /dev/null
+++ b/plugins/Skins/SkinLib/Dialog.cpp
@@ -0,0 +1,100 @@
+#include "globals.h"
+#include "Dialog.h"
+#include "DialogState.h"
+
+
+Dialog::Dialog(const char *aName) : name(aName)
+{
+}
+
+
+Dialog::~Dialog()
+{
+ for(unsigned int i = 0; i < fields.size(); i++)
+ delete fields[i];
+
+ fields.clear();
+}
+
+
+const char * Dialog::getName() const
+{
+ return name.c_str();
+}
+
+
+bool Dialog::addField(Field *field)
+{
+ if (getField(field->getName()) != NULL)
+ return false;
+
+ fields.push_back(field);
+ return true;
+}
+
+
+Field * Dialog::getField(const char *name) const
+{
+ if (name == NULL || name[0] == 0)
+ return NULL;
+
+ for(unsigned int i = 0; i < fields.size(); i++)
+ {
+ Field *field = fields[i];
+ if (strcmp(name, field->getName()) == 0)
+ return field;
+ }
+
+ return NULL;
+}
+
+Field * Dialog::getField(unsigned int pos) const
+{
+ if (pos >= fields.size())
+ return NULL;
+ return fields[pos];
+}
+
+int Dialog::getIndexOf(Field *field) const
+{
+ for(unsigned int i = 0; i < fields.size(); i++)
+ {
+ Field *f = fields[i];
+ if (field == f)
+ return i;
+ }
+
+ return -1;
+}
+
+unsigned int Dialog::getFieldCount() const
+{
+ return fields.size();
+}
+
+DialogInfo * Dialog::getInfo()
+{
+ return &info;
+}
+
+const Size & Dialog::getSize() const
+{
+ return size;
+}
+
+
+void Dialog::setSize(const Size &size)
+{
+ this->size = size;
+}
+
+
+DialogState * Dialog::createState()
+{
+ DialogState *ret = new DialogState(this);
+
+ for(unsigned int i = 0; i < fields.size(); i++)
+ ret->fields.push_back(fields[i]->createState(ret));
+
+ return ret;
+}
diff --git a/plugins/Skins/SkinLib/Dialog.h b/plugins/Skins/SkinLib/Dialog.h
new file mode 100644
index 0000000000..0e85b8e340
--- /dev/null
+++ b/plugins/Skins/SkinLib/Dialog.h
@@ -0,0 +1,41 @@
+#ifndef __DIALOG_H__
+# define __DIALOG_H__
+
+#include <vector>
+#include "Field.h"
+#include "DialogInfo.h"
+
+class DialogState;
+
+
+/// It is responsible for freeing the Fields
+class Dialog
+{
+public:
+ Dialog(const char *name);
+ virtual ~Dialog();
+
+ virtual const char * getName() const;
+
+ virtual bool addField(Field *field);
+ virtual Field * getField(const char *name) const;
+ virtual Field * getField(unsigned int pos) const;
+ virtual int getIndexOf(Field *field) const;
+ virtual unsigned int getFieldCount() const;
+
+ virtual DialogInfo * getInfo();
+
+ virtual const Size & getSize() const;
+ virtual void setSize(const Size &size);
+
+ virtual DialogState * createState();
+
+private:
+ const std::string name;
+ std::vector<Field *> fields;
+ DialogInfo info;
+ Size size;
+};
+
+
+#endif // __DIALOG_H__
diff --git a/plugins/Skins/SkinLib/DialogInfo.cpp b/plugins/Skins/SkinLib/DialogInfo.cpp
new file mode 100644
index 0000000000..fd29a37392
--- /dev/null
+++ b/plugins/Skins/SkinLib/DialogInfo.cpp
@@ -0,0 +1,190 @@
+#include "globals.h"
+#include "DialogInfo.h"
+#include "tstring.h"
+
+class DialogInfoValue
+{
+public:
+ DialogInfoValue(const char *aName) : name(aName), type(UNKNOWN) {}
+
+ const char * getName() { return name.c_str(); }
+
+ void set(const TCHAR *value) { valueString = value; type = TYPE_STRING; }
+ void set(int value) { valueInt = value; type = TYPE_INT; }
+ void set(double value) { valueDouble = value; type = TYPE_DOUBLE; }
+ void set(bool value) { valueBool = value; type = TYPE_BOOL; }
+
+ DialogInfoType getType() { return type; }
+
+ const TCHAR * getAsString() { return valueString.c_str(); }
+ int getAsInt() { return valueInt; }
+ double getAsDouble() { return valueDouble; }
+ bool getAsBool() { return valueBool; }
+
+private:
+ std::string name;
+
+ DialogInfoType type;
+
+ std::tstring valueString;
+ int valueInt;
+ double valueDouble;
+ bool valueBool;
+};
+
+DialogInfo::DialogInfo()
+{
+}
+
+DialogInfo::~DialogInfo()
+{
+ for(size_t i = 0; i < values.size(); ++i)
+ delete values[i];
+}
+
+
+void DialogInfo::set(const char *name, const TCHAR *value)
+{
+ bool isVar;
+ DialogInfoValue * val = findValue(name, true, &isVar);
+
+ if (isVar)
+ return;
+
+ val->set(value);
+}
+
+void DialogInfo::set(const char *name, int value)
+{
+ bool isVar;
+ DialogInfoValue * val = findValue(name, true, &isVar);
+
+ if (isVar)
+ return;
+
+ val->set(value);
+}
+
+void DialogInfo::set(const char *name, double value)
+{
+ bool isVar;
+ DialogInfoValue * val = findValue(name, true, &isVar);
+
+ if (isVar)
+ return;
+
+ val->set(value);
+}
+
+void DialogInfo::set(const char *name, bool value)
+{
+ bool isVar;
+ DialogInfoValue * val = findValue(name, true, &isVar);
+
+ if (isVar)
+ return;
+
+ val->set(value);
+}
+
+void DialogInfo::remove(const char *name)
+{
+ size_t len = strlen(name);
+
+ for(std::vector<DialogInfoValue *>::iterator it = values.begin(); it != values.end(); )
+ {
+ DialogInfoValue *val = *it;
+
+ if (stricmp(name, val->getName()) == 0)
+ it = values.erase(it);
+
+ else if (strnicmp(name, val->getName(), len) == 0 && val->getName()[len] == '.')
+ it = values.erase(it);
+
+ else
+ it++;
+ }
+}
+
+DialogInfoType DialogInfo::getType(const char *name)
+{
+ bool isVar;
+ DialogInfoValue * val = findValue(name, false, &isVar);
+
+ if (isVar)
+ return TYPE_VARIABLE;
+
+ else if (val == NULL)
+ return UNKNOWN;
+
+ else
+ return val->getType();
+}
+
+
+const TCHAR * DialogInfo::getAsString(const char *name)
+{
+ DialogInfoValue * val = findValue(name);
+ if (val == NULL)
+ return NULL;
+
+ return val->getAsString();
+}
+
+int DialogInfo::getAsInt(const char *name)
+{
+ DialogInfoValue * val = findValue(name);
+ if (val == NULL)
+ return 0;
+
+ return val->getAsInt();
+}
+
+double DialogInfo::getAsDouble(const char *name)
+{
+ DialogInfoValue * val = findValue(name);
+ if (val == NULL)
+ return 0;
+
+ return val->getAsDouble();
+}
+
+bool DialogInfo::getAsBool(const char *name)
+{
+ DialogInfoValue * val = findValue(name);
+ if (val == NULL)
+ return false;
+
+ return val->getAsBool();
+}
+
+DialogInfoValue * DialogInfo::findValue(const char *name, bool create, bool *isVar)
+{
+ size_t len = strlen(name);
+
+ if (isVar != NULL) *isVar = false;
+
+ for(size_t i = 0; i < values.size(); ++i)
+ {
+ DialogInfoValue *val = values[i];
+
+ if (stricmp(name, val->getName()) == 0)
+ {
+ return val;
+ }
+ else if (strnicmp(name, val->getName(), len) == 0 && val->getName()[len] == '.')
+ {
+ if (isVar != NULL) *isVar = true;
+ return val;
+ }
+ }
+
+ if (create)
+ {
+ DialogInfoValue *ret = new DialogInfoValue(name);
+ values.push_back(ret);
+ return ret;
+ }
+
+ return NULL;
+}
diff --git a/plugins/Skins/SkinLib/DialogInfo.h b/plugins/Skins/SkinLib/DialogInfo.h
new file mode 100644
index 0000000000..02f07310d7
--- /dev/null
+++ b/plugins/Skins/SkinLib/DialogInfo.h
@@ -0,0 +1,50 @@
+#ifndef __DIALOG_INFO_H__
+# define __DIALOG_INFO_H__
+
+#include <windows.h>
+#include <vector>
+
+
+enum DialogInfoType
+{
+ UNKNOWN = 0,
+ TYPE_VARIABLE,
+ TYPE_INT,
+ TYPE_DOUBLE,
+ TYPE_BOOL,
+ TYPE_STRING
+};
+
+
+class DialogInfoValue;
+
+class DialogInfo
+{
+public:
+ DialogInfo();
+ ~DialogInfo();
+
+ void set(const char *name, const TCHAR *value);
+ void set(const char *name, int value);
+ void set(const char *name, double value);
+ void set(const char *name, bool value);
+
+ void remove(const char *name);
+
+ DialogInfoType getType(const char *name);
+
+ const TCHAR * getAsString(const char *name);
+ int getAsInt(const char *name);
+ double getAsDouble(const char *name);
+ bool getAsBool(const char *name);
+
+private:
+ std::vector<DialogInfoValue *> values;
+
+ DialogInfoValue * findValue(const char *name, bool create = false, bool *isVar = NULL);
+
+};
+
+
+
+#endif // __DIALOG_INFO_H__ \ No newline at end of file
diff --git a/plugins/Skins/SkinLib/DialogState.cpp b/plugins/Skins/SkinLib/DialogState.cpp
new file mode 100644
index 0000000000..e1e7654930
--- /dev/null
+++ b/plugins/Skins/SkinLib/DialogState.cpp
@@ -0,0 +1,132 @@
+#include "globals.h"
+#include "DialogState.h"
+
+
+DialogState::DialogState(Dialog *aDialog) : dialog(aDialog), size(-1,-1), borders(0,0,0,0)
+{
+}
+
+DialogState::~DialogState()
+{
+ for(unsigned int i = 0; i < fields.size(); i++)
+ delete fields[i];
+
+ fields.clear();
+}
+
+Dialog * DialogState::getDialog() const
+{
+ return dialog;
+}
+
+FieldState * DialogState::getField(const char *name) const
+{
+ if (name == NULL || name[0] == 0)
+ return NULL;
+
+ for(unsigned int i = 0; i < fields.size(); i++)
+ {
+ FieldState *field = fields[i];
+ if (strcmp(name, field->getField()->getName()) == 0)
+ return field;
+ }
+
+ return NULL;
+}
+
+int DialogState::getX() const
+{
+ return 0;
+}
+
+int DialogState::getY() const
+{
+ return 0;
+}
+
+int DialogState::getLeft() const
+{
+ return getX();
+}
+
+int DialogState::getTop() const
+{
+ return getY();
+}
+
+int DialogState::getRight() const
+{
+ return getX() + getWidth();
+}
+
+int DialogState::getBottom() const
+{
+ return getY() + getHeight();
+}
+
+int DialogState::getWidth() const
+{
+ if (size.x >= 0)
+ return size.x - getHorizontalBorders();
+
+ return dialog->getSize().x - getHorizontalBorders();
+}
+
+void DialogState::setWidth(int width)
+{
+ size.x = max(0, width) + getHorizontalBorders();
+}
+
+int DialogState::getHeight() const
+{
+ if (size.y >= 0)
+ return size.y - getVerticalBorders();
+
+ return dialog->getSize().y - getVerticalBorders();
+}
+
+void DialogState::setHeight(int height)
+{
+ size.y = max(0, height) + getVerticalBorders();
+}
+
+BorderState * DialogState::getBorders()
+{
+ return &borders;
+}
+
+const BorderState * DialogState::getBorders() const
+{
+ return &borders;
+}
+
+int DialogState::getHorizontalBorders() const
+{
+ return borders.getLeft() + borders.getRight();
+}
+
+int DialogState::getVerticalBorders() const
+{
+ return borders.getTop() + borders.getBottom();
+}
+
+RECT DialogState::getInsideRect() const
+{
+ RECT ret;
+ ret.left = borders.getLeft();
+ ret.right = ret.left + getWidth();
+ ret.top = borders.getTop();
+ ret.bottom = ret.top + getHeight();
+ return ret;
+}
+
+RECT DialogState::getRect() const
+{
+ RECT ret;
+ ret.left = 0;
+ ret.right = borders.getLeft() + getWidth() + borders.getRight();
+ ret.top = 0;
+ ret.bottom = borders.getTop() + getHeight() + borders.getBottom();
+ return ret;
+}
+
diff --git a/plugins/Skins/SkinLib/DialogState.h b/plugins/Skins/SkinLib/DialogState.h
new file mode 100644
index 0000000000..e27fc929da
--- /dev/null
+++ b/plugins/Skins/SkinLib/DialogState.h
@@ -0,0 +1,59 @@
+#ifndef __DIALOG_STATE_H__
+# define __DIALOG_STATE_H__
+
+#include "Dialog.h"
+#include "FieldState.h"
+#include "BorderState.h"
+
+
+/// This have to be deleted before the owning dialog
+/// It is responsible for freeing the FieldStates
+class DialogState
+{
+public:
+ ~DialogState();
+
+ Dialog * getDialog() const;
+
+ std::vector<FieldState *> fields;
+ FieldState * getField(const char *name) const;
+
+ // Used inside script
+
+ virtual int getX() const;
+ virtual int getY() const;
+ virtual int getLeft() const;
+ virtual int getTop() const;
+ virtual int getRight() const;
+ virtual int getBottom() const;
+
+ int getWidth() const;
+ void setWidth(int width);
+
+ int getHeight() const;
+ void setHeight(int height);
+
+ BorderState * getBorders();
+ const BorderState * getBorders() const;
+
+ // Results
+
+ RECT getInsideRect() const;
+ RECT getRect() const;
+
+private:
+ DialogState(Dialog *dialog);
+
+ Dialog *dialog;
+
+ Size size;
+ BorderState borders;
+
+ int getHorizontalBorders() const;
+ int getVerticalBorders() const;
+
+ friend class Dialog;
+};
+
+
+#endif // __DIALOG_STATE_H__ \ No newline at end of file
diff --git a/plugins/Skins/SkinLib/DialogState_v8_wrapper.cpp b/plugins/Skins/SkinLib/DialogState_v8_wrapper.cpp
new file mode 100644
index 0000000000..5739414d69
--- /dev/null
+++ b/plugins/Skins/SkinLib/DialogState_v8_wrapper.cpp
@@ -0,0 +1,233 @@
+#include "globals.h"
+#include "DialogState_v8_wrapper.h"
+#include <v8.h>
+#include "DialogState.h"
+
+using namespace v8;
+
+
+#ifdef UNICODE
+# define V8_TCHAR uint16_t
+#else
+# define V8_TCHAR char
+#endif
+
+
+static Handle<Value> Get_DialogState_width(Local<String> property, const AccessorInfo &info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return scope.Close( Undefined() );
+
+ DialogState *tmp = (DialogState *) wrap->Value();
+ if (tmp == NULL)
+ return scope.Close( Undefined() );
+
+ return scope.Close( Int32::New(tmp->getWidth()) );
+}
+
+static void Set_DialogState_width(Local<String> property, Local<Value> value, const AccessorInfo& info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return;
+
+ DialogState *tmp = (DialogState *) wrap->Value();
+ if (tmp == NULL)
+ return;
+
+ if (!value.IsEmpty() && value->IsNumber())
+ tmp->setWidth(value->Int32Value());
+}
+
+
+static Handle<Value> Get_DialogState_height(Local<String> property, const AccessorInfo &info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return scope.Close( Undefined() );
+
+ DialogState *tmp = (DialogState *) wrap->Value();
+ if (tmp == NULL)
+ return scope.Close( Undefined() );
+
+ return scope.Close( Int32::New(tmp->getHeight()) );
+}
+
+static void Set_DialogState_height(Local<String> property, Local<Value> value, const AccessorInfo& info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return;
+
+ DialogState *tmp = (DialogState *) wrap->Value();
+ if (tmp == NULL)
+ return;
+
+ if (!value.IsEmpty() && value->IsNumber())
+ tmp->setHeight(value->Int32Value());
+}
+
+
+static Handle<Value> Get_DialogState_x(Local<String> property, const AccessorInfo &info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return scope.Close( Undefined() );
+
+ DialogState *tmp = (DialogState *) wrap->Value();
+ if (tmp == NULL)
+ return scope.Close( Undefined() );
+
+ return scope.Close( Int32::New(tmp->getX()) );
+}
+
+
+static Handle<Value> Get_DialogState_y(Local<String> property, const AccessorInfo &info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return scope.Close( Undefined() );
+
+ DialogState *tmp = (DialogState *) wrap->Value();
+ if (tmp == NULL)
+ return scope.Close( Undefined() );
+
+ return scope.Close( Int32::New(tmp->getY()) );
+}
+
+
+static Handle<Value> Get_DialogState_left(Local<String> property, const AccessorInfo &info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return scope.Close( Undefined() );
+
+ DialogState *tmp = (DialogState *) wrap->Value();
+ if (tmp == NULL)
+ return scope.Close( Undefined() );
+
+ return scope.Close( Int32::New(tmp->getLeft()) );
+}
+
+
+static Handle<Value> Get_DialogState_top(Local<String> property, const AccessorInfo &info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return scope.Close( Undefined() );
+
+ DialogState *tmp = (DialogState *) wrap->Value();
+ if (tmp == NULL)
+ return scope.Close( Undefined() );
+
+ return scope.Close( Int32::New(tmp->getTop()) );
+}
+
+
+static Handle<Value> Get_DialogState_right(Local<String> property, const AccessorInfo &info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return scope.Close( Undefined() );
+
+ DialogState *tmp = (DialogState *) wrap->Value();
+ if (tmp == NULL)
+ return scope.Close( Undefined() );
+
+ return scope.Close( Int32::New(tmp->getRight()) );
+}
+
+
+static Handle<Value> Get_DialogState_bottom(Local<String> property, const AccessorInfo &info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return scope.Close( Undefined() );
+
+ DialogState *tmp = (DialogState *) wrap->Value();
+ if (tmp == NULL)
+ return scope.Close( Undefined() );
+
+ return scope.Close( Int32::New(tmp->getBottom()) );
+}
+
+
+static Handle<Value> Get_DialogState_borders(Local<String> property, const AccessorInfo &info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return scope.Close( Undefined() );
+
+ DialogState *tmp = (DialogState *) wrap->Value();
+ if (tmp == NULL)
+ return scope.Close( Undefined() );
+
+ return scope.Close( self->Get(String::New("bordersRaw")) );
+}
+
+static void Set_DialogState_borders(Local<String> property, Local<Value> value, const AccessorInfo& info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return;
+
+ DialogState *tmp = (DialogState *) wrap->Value();
+ if (tmp == NULL)
+ return;
+
+ if (!value.IsEmpty() && value->IsInt32())
+ tmp->getBorders()->setAll(value->Int32Value());
+}
+
+
+void AddDialogStateAcessors(Handle<ObjectTemplate> &templ)
+{
+ HandleScope scope;
+
+ templ->SetAccessor(String::New("width"), Get_DialogState_width, Set_DialogState_width);
+ templ->SetAccessor(String::New("height"), Get_DialogState_height, Set_DialogState_height);
+ templ->SetAccessor(String::New("x"), Get_DialogState_x, NULL, Handle<Value>(), DEFAULT, ReadOnly);
+ templ->SetAccessor(String::New("y"), Get_DialogState_y, NULL, Handle<Value>(), DEFAULT, ReadOnly);
+ templ->SetAccessor(String::New("left"), Get_DialogState_left, NULL, Handle<Value>(), DEFAULT, ReadOnly);
+ templ->SetAccessor(String::New("top"), Get_DialogState_top, NULL, Handle<Value>(), DEFAULT, ReadOnly);
+ templ->SetAccessor(String::New("right"), Get_DialogState_right, NULL, Handle<Value>(), DEFAULT, ReadOnly);
+ templ->SetAccessor(String::New("bottom"), Get_DialogState_bottom, NULL, Handle<Value>(), DEFAULT, ReadOnly);
+ templ->SetAccessor(String::New("borders"), Get_DialogState_borders, Set_DialogState_borders);
+}
diff --git a/plugins/Skins/SkinLib/DialogState_v8_wrapper.h b/plugins/Skins/SkinLib/DialogState_v8_wrapper.h
new file mode 100644
index 0000000000..709ef2d738
--- /dev/null
+++ b/plugins/Skins/SkinLib/DialogState_v8_wrapper.h
@@ -0,0 +1,10 @@
+#ifndef __DIALOG_STATE_V8_WRAPPER_H__
+# define __DIALOG_STATE_V8_WRAPPER_H__
+
+#include <v8.h>
+
+void AddDialogStateAcessors(v8::Handle<v8::ObjectTemplate> &templ);
+
+
+
+#endif // __DIALOG_STATE_V8_WRAPPER_H__
diff --git a/plugins/Skins/SkinLib/EditField.cpp b/plugins/Skins/SkinLib/EditField.cpp
new file mode 100644
index 0000000000..8eb0d5050f
--- /dev/null
+++ b/plugins/Skins/SkinLib/EditField.cpp
@@ -0,0 +1,23 @@
+#include "globals.h"
+#include "EditField.h"
+#include "EditFieldState.h"
+
+
+EditField::EditField(Dialog *dlg, const char *name, HWND hwnd)
+ : ControlField(dlg, name, hwnd)
+{
+}
+
+EditField::~EditField()
+{
+}
+
+FieldType EditField::getType() const
+{
+ return CONTROL_EDIT;
+}
+
+FieldState * EditField::createState(DialogState *dialogState)
+{
+ return new EditFieldState(dialogState, this);
+} \ No newline at end of file
diff --git a/plugins/Skins/SkinLib/EditField.h b/plugins/Skins/SkinLib/EditField.h
new file mode 100644
index 0000000000..f69f23576c
--- /dev/null
+++ b/plugins/Skins/SkinLib/EditField.h
@@ -0,0 +1,19 @@
+#ifndef __EDIT_FIELD_H__
+# define __EDIT_FIELD_H__
+
+#include "ControlField.h"
+
+
+class EditField : public ControlField
+{
+public:
+ EditField(Dialog *dlg, const char *name, HWND hwnd);
+ virtual ~EditField();
+
+ virtual FieldType getType() const;
+
+ virtual FieldState * createState(DialogState *dialogState);
+};
+
+
+#endif // __EDIT_FIELD_H__
diff --git a/plugins/Skins/SkinLib/EditFieldState.cpp b/plugins/Skins/SkinLib/EditFieldState.cpp
new file mode 100644
index 0000000000..e634be7b55
--- /dev/null
+++ b/plugins/Skins/SkinLib/EditFieldState.cpp
@@ -0,0 +1,58 @@
+#include "globals.h"
+#include "EditFieldState.h"
+
+
+EditFieldState::EditFieldState(DialogState *dialog, EditField *field)
+ : ControlFieldState(dialog, field)
+{
+}
+
+EditFieldState::~EditFieldState()
+{
+}
+
+Size EditFieldState::getPreferedSize() const
+{
+ ControlField *field = getField();
+ HWND hwnd = field->getHWND();
+
+ int style = GetWindowLong(hwnd, GWL_STYLE);
+ int exstyle = GetWindowLong(hwnd, GWL_EXSTYLE);
+
+ int format = DT_NOPREFIX | DT_EDITCONTROL;
+ if (!(style & ES_MULTILINE))
+ format |= DT_SINGLELINE;
+ Size ret = getTextPreferedSize(format);
+
+ RECT rc = {0};
+ SetRect(&rc, 0, 0, ret.x, ret.y);
+ AdjustWindowRectEx(&rc, style, false, exstyle);
+
+ bool hasHorScroll = field->isScrollVisible(true);
+ if (hasHorScroll)
+ rc.bottom += GetSystemMetrics(SM_CYHSCROLL);
+ if (field->isScrollVisible(false))
+ rc.right += GetSystemMetrics(SM_CXVSCROLL);
+
+ int margins = SendMessage(hwnd, EM_GETMARGINS, 0, 0);
+ rc.left -= LOWORD(margins);
+ rc.right += HIWORD(margins);
+ if (hasHorScroll || (style & ES_AUTOHSCROLL))
+ rc.right++;
+
+ ret.x = rc.right - rc.left;
+ ret.y = rc.bottom - rc.top;
+
+ if ((exstyle & WS_EX_CLIENTEDGE) || (exstyle & WS_EX_STATICEDGE) || (style & WS_BORDER))
+ {
+ ret.x += 3;
+ ret.y += 3;
+ }
+
+ return ret;
+}
+
+bool EditFieldState::isEmpty() const
+{
+ return false;
+} \ No newline at end of file
diff --git a/plugins/Skins/SkinLib/EditFieldState.h b/plugins/Skins/SkinLib/EditFieldState.h
new file mode 100644
index 0000000000..c2372d553d
--- /dev/null
+++ b/plugins/Skins/SkinLib/EditFieldState.h
@@ -0,0 +1,24 @@
+#ifndef __EDIT_FIELD_STATE_H__
+# define __EDIT_FIELD_STATE_H__
+
+#include "ControlFieldState.h"
+#include "EditField.h"
+
+
+class EditFieldState : public ControlFieldState
+{
+public:
+ virtual ~EditFieldState();
+
+ virtual Size getPreferedSize() const;
+
+ virtual bool isEmpty() const;
+
+private:
+ EditFieldState(DialogState *dialog, EditField *field);
+
+ friend class EditField;
+};
+
+
+#endif // __EDIT_FIELD_STATE_H__
diff --git a/plugins/Skins/SkinLib/EditFieldState_v8_wrapper.cpp b/plugins/Skins/SkinLib/EditFieldState_v8_wrapper.cpp
new file mode 100644
index 0000000000..86522b87e3
--- /dev/null
+++ b/plugins/Skins/SkinLib/EditFieldState_v8_wrapper.cpp
@@ -0,0 +1,20 @@
+#include "globals.h"
+#include "EditFieldState_v8_wrapper.h"
+#include <v8.h>
+#include "EditFieldState.h"
+
+using namespace v8;
+
+
+#ifdef UNICODE
+# define V8_TCHAR uint16_t
+#else
+# define V8_TCHAR char
+#endif
+
+
+void AddEditFieldStateAcessors(Handle<ObjectTemplate> &templ)
+{
+ HandleScope scope;
+
+}
diff --git a/plugins/Skins/SkinLib/EditFieldState_v8_wrapper.h b/plugins/Skins/SkinLib/EditFieldState_v8_wrapper.h
new file mode 100644
index 0000000000..a58972549f
--- /dev/null
+++ b/plugins/Skins/SkinLib/EditFieldState_v8_wrapper.h
@@ -0,0 +1,10 @@
+#ifndef __EDIT_FIELD_STATE_V8_WRAPPER_H__
+# define __EDIT_FIELD_STATE_V8_WRAPPER_H__
+
+#include <v8.h>
+
+void AddEditFieldStateAcessors(v8::Handle<v8::ObjectTemplate> &templ);
+
+
+
+#endif // __EDIT_FIELD_STATE_V8_WRAPPER_H__
diff --git a/plugins/Skins/SkinLib/Field.cpp b/plugins/Skins/SkinLib/Field.cpp
new file mode 100644
index 0000000000..24b823bde6
--- /dev/null
+++ b/plugins/Skins/SkinLib/Field.cpp
@@ -0,0 +1,56 @@
+#include "globals.h"
+#include "Field.h"
+#include "FieldState.h"
+
+
+Field::Field(Dialog *aDlg, const char *aName)
+ : dlg(aDlg), name(aName), onChangeCallback(NULL), onChangeCallbackParam(NULL), enabled(true)
+{
+}
+
+Field::~Field()
+{
+}
+
+Dialog * Field::getDialog() const
+{
+ return dlg;
+}
+
+const char * Field::getName() const
+{
+ return name.c_str();
+}
+
+bool Field::isEnabled() const
+{
+ return enabled;
+}
+
+void Field::setEnabled(bool enabled)
+{
+ this->enabled = enabled;
+ fireOnChange();
+}
+
+const TCHAR * Field::getToolTip() const
+{
+ return tooltip.c_str();
+}
+
+void Field::setToolTip(const TCHAR *tooltip)
+{
+ this->tooltip = tooltip;
+}
+
+void Field::setOnChangeCallback(FieldCallback cb, void *param /*= NULL*/)
+{
+ onChangeCallback = cb;
+ onChangeCallbackParam = param;
+}
+
+void Field::fireOnChange() const
+{
+ if (onChangeCallback != NULL)
+ onChangeCallback(onChangeCallbackParam, this);
+}
diff --git a/plugins/Skins/SkinLib/Field.h b/plugins/Skins/SkinLib/Field.h
new file mode 100644
index 0000000000..4cf7faaa51
--- /dev/null
+++ b/plugins/Skins/SkinLib/Field.h
@@ -0,0 +1,66 @@
+#ifndef __FIELD_H__
+# define __FIELD_H__
+
+#include <windows.h>
+#include <tchar.h>
+#include "tstring.h"
+#include "Size.h"
+#include "Position.h"
+
+
+enum FieldType
+{
+ SIMPLE_TEXT = 1,
+ SIMPLE_IMAGE,
+ SIMPLE_ICON,
+ CONTROL_LABEL,
+ CONTROL_BUTTON,
+ CONTROL_EDIT,
+ USER_DEFINED = 0x100
+};
+
+class Dialog;
+class DialogState;
+class Field;
+class FieldState;
+
+typedef void (*FieldCallback)(void *param, const Field *field);
+
+
+class Field
+{
+public:
+ Field(Dialog *dlg, const char *name);
+ virtual ~Field();
+
+ virtual Dialog * getDialog() const;
+ virtual const char * getName() const;
+ virtual FieldType getType() const = 0;
+
+ virtual bool isEnabled() const;
+ virtual void setEnabled(bool enabled);
+
+ virtual const TCHAR * getToolTip() const;
+ virtual void setToolTip(const TCHAR *tooltip);
+
+ virtual FieldState * createState(DialogState *dialogState) = 0;
+
+ virtual void setOnChangeCallback(FieldCallback cb, void *param = NULL);
+
+protected:
+ void fireOnChange() const;
+
+private:
+ Dialog *dlg;
+ const std::string name;
+ bool enabled;
+ std::tstring tooltip;
+
+ FieldCallback onChangeCallback;
+ void *onChangeCallbackParam;
+};
+
+
+
+
+#endif // __FIELD_H__ \ No newline at end of file
diff --git a/plugins/Skins/SkinLib/FieldState.cpp b/plugins/Skins/SkinLib/FieldState.cpp
new file mode 100644
index 0000000000..68510051da
--- /dev/null
+++ b/plugins/Skins/SkinLib/FieldState.cpp
@@ -0,0 +1,303 @@
+#include "globals.h"
+#include "FieldState.h"
+#include "DialogState.h"
+#include "BorderState.h"
+
+#define START 1<<0
+#define LEN 1<<1
+#define END 1<<2
+#define USING_MASK 0xFF
+#define LAST_SHIFT 8
+#define SET(_FIELD_, _ITEM_) _FIELD_ = (((_FIELD_ | _ITEM_) & USING_MASK) | (_ITEM_ << LAST_SHIFT))
+#define LAST_SET(_FIELD_) (_FIELD_ >> LAST_SHIFT)
+
+
+FieldState::FieldState(DialogState *aDialog, Field *aField)
+ : field(aField), dialog(aDialog), size(-1, -1), pos(0, 0),
+ usingX(0), usingY(0), visible(aField->isEnabled()), borders(0,0,0,0),
+ tooltipSet(false), halign(HORIZONTAL_ALIGN_LEFT), valign(VERTICAL_ALIGN_TOP)
+{
+}
+
+FieldState::~FieldState()
+{
+}
+
+Field * FieldState::getField() const
+{
+ return field;
+}
+
+DialogState * FieldState::getDialog() const
+{
+ return dialog;
+}
+
+int FieldState::getX() const
+{
+ return pos.x;
+}
+
+void FieldState::setX(int x)
+{
+ if (usingX & END)
+ {
+ int diff = x - getX();
+ size.x = max(0, getWidth() - getHorizontalBorders() - diff);
+ }
+
+ pos.x = x;
+
+ SET(usingX, START);
+}
+
+int FieldState::getY() const
+{
+ return pos.y;
+}
+
+void FieldState::setY(int y)
+{
+ if (usingY & END)
+ {
+ int diff = y - getY();
+ size.y = max(0, getHeight() - getVerticalBorders() - diff);
+ }
+
+ pos.y = y;
+
+ SET(usingY, START);
+}
+
+int FieldState::getWidth() const
+{
+ if (size.x >= 0)
+ return size.x + getHorizontalBorders();
+
+ return getPreferedSize().x + getHorizontalBorders();
+}
+
+void FieldState::setWidth(int width)
+{
+ width = max(0, width - getHorizontalBorders()) + getHorizontalBorders();
+
+ if (LAST_SET(usingX) == END)
+ {
+ int diff = width - getWidth();
+ pos.x = getX() - diff;
+ }
+
+ size.x = width - getHorizontalBorders();
+
+ usingX |= LEN;
+}
+
+int FieldState::getHeight() const
+{
+ if (size.y >= 0)
+ return size.y + getVerticalBorders();
+
+ return getPreferedSize().y + getVerticalBorders();
+}
+
+void FieldState::setHeight(int height)
+{
+ height = max(0, height - getVerticalBorders()) + getVerticalBorders();
+
+ if (LAST_SET(usingY) == END)
+ {
+ int diff = height - getHeight();
+ pos.y = getY() - diff;
+ }
+
+ size.y = height - getVerticalBorders();
+
+ usingY |= LEN;
+}
+
+bool FieldState::isVisible() const
+{
+ if (!visible)
+ return false;
+
+ RECT rc = getRect();
+ if (rc.right <= rc.left || rc.bottom <= rc.top)
+ return false;
+
+ return true;
+}
+
+void FieldState::setVisible(bool visible)
+{
+ this->visible = visible;
+}
+
+bool FieldState::isEnabled() const
+{
+ return field->isEnabled();
+}
+
+int FieldState::getLeft() const
+{
+ return getX();
+}
+
+void FieldState::setLeft(int left)
+{
+ setX(left);
+}
+
+int FieldState::getTop() const
+{
+ return getY();
+}
+
+void FieldState::setTop(int top)
+{
+ setY(top);
+}
+
+int FieldState::getRight() const
+{
+ return getX() + getWidth();
+}
+
+void FieldState::setRight(int right)
+{
+ if (usingX & START)
+ {
+ size.x = max(0, right - getX());
+ }
+ else
+ {
+ pos.x = right - getWidth();
+ }
+
+ SET(usingX, END);
+}
+
+int FieldState::getBottom() const
+{
+ return getY() + getHeight();
+}
+
+void FieldState::setBottom(int botom)
+{
+ if (usingY & START)
+ {
+ size.y = max(0, botom - getY());
+ }
+ else
+ {
+ pos.y = botom - getHeight();
+ }
+
+ SET(usingY, END);
+}
+
+const TCHAR * FieldState::getToolTip() const
+{
+ if (tooltipSet)
+ return tooltip.c_str();
+ else
+ return field->getToolTip();
+}
+
+void FieldState::setToolTip(const TCHAR *tooltip)
+{
+ this->tooltip = tooltip;
+ tooltipSet = true;
+}
+
+BorderState * FieldState::getBorders()
+{
+ return &borders;
+}
+
+const BorderState * FieldState::getBorders() const
+{
+ return &borders;
+}
+
+int FieldState::getHorizontalBorders() const
+{
+ return borders.getLeft() + borders.getRight();
+}
+
+int FieldState::getVerticalBorders() const
+{
+ return borders.getTop() + borders.getBottom();
+}
+
+static inline int beetween(int val, int minVal, int maxVal)
+{
+ return max(minVal, min(maxVal, val));
+}
+
+static inline void intersection(RECT &main, const RECT &other)
+{
+ main.left = beetween(main.left, other.left, other.right);
+ main.right = beetween(main.right, other.left, other.right);
+ main.top = beetween(main.top, other.top, other.bottom);
+ main.bottom = beetween(main.bottom, other.top, other.bottom);
+}
+
+RECT FieldState::getRect(bool raw) const
+{
+ RECT ret = {0};
+
+ if (!visible)
+ return ret;
+
+ RECT inside = dialog->getInsideRect();
+
+ ret.left = getLeft() + inside.left;
+ ret.right = getRight() + inside.left;
+ ret.top = getTop() + inside.top;
+ ret.bottom = getBottom() + inside.top;
+
+ if (!raw)
+ intersection(ret, inside);
+
+ return ret;
+}
+
+RECT FieldState::getInsideRect(bool raw) const
+{
+ RECT ret = {0};
+
+ if (!visible)
+ return ret;
+
+ RECT inside = dialog->getInsideRect();
+
+ ret.left = getLeft() + borders.getLeft() + inside.left;
+ ret.right = getRight() - borders.getRight() + inside.left;
+ ret.top = getTop() + borders.getTop() + inside.top;
+ ret.bottom = getBottom() - borders.getBottom() + inside.top;
+
+ if (!raw)
+ intersection(ret, inside);
+
+ return ret;
+}
+
+HORIZONTAL_ALIGN FieldState::getHAlign() const
+{
+ return halign;
+}
+
+void FieldState::setHAlign(HORIZONTAL_ALIGN halign)
+{
+ this->halign = halign;
+}
+
+VERTICAL_ALIGN FieldState::getVAlign() const
+{
+ return valign;
+}
+
+void FieldState::setVAlign(VERTICAL_ALIGN valign)
+{
+ this->valign = valign;
+}
diff --git a/plugins/Skins/SkinLib/FieldState.h b/plugins/Skins/SkinLib/FieldState.h
new file mode 100644
index 0000000000..d7c552105f
--- /dev/null
+++ b/plugins/Skins/SkinLib/FieldState.h
@@ -0,0 +1,108 @@
+#ifndef __FIELD_STATE_H__
+# define __FIELD_STATE_H__
+
+#include "Field.h"
+#include "BorderState.h"
+
+class DialogState;
+
+enum HORIZONTAL_ALIGN
+{
+ HORIZONTAL_ALIGN_LEFT = 1,
+ HORIZONTAL_ALIGN_CENTER,
+ HORIZONTAL_ALIGN_RIGHT
+};
+
+enum VERTICAL_ALIGN
+{
+ VERTICAL_ALIGN_TOP = 1,
+ VERTICAL_ALIGN_CENTER,
+ VERTICAL_ALIGN_BOTTOM
+};
+
+
+class FieldState
+{
+public:
+ virtual ~FieldState();
+
+ virtual Field * getField() const;
+ virtual DialogState * getDialog() const;
+
+ virtual Size getPreferedSize() const = 0;
+
+ // Used inside script
+
+ virtual int getX() const;
+ virtual void setX(int x);
+
+ virtual int getY() const;
+ virtual void setY(int y);
+
+ virtual int getWidth() const;
+ virtual void setWidth(int width);
+
+ virtual int getHeight() const;
+ virtual void setHeight(int height);
+
+ virtual int getLeft() const;
+ virtual void setLeft(int left);
+
+ virtual int getTop() const;
+ virtual void setTop(int top);
+
+ virtual int getRight() const;
+ virtual void setRight(int right);
+
+ virtual int getBottom() const;
+ virtual void setBottom(int bottom);
+
+ virtual bool isVisible() const;
+ virtual void setVisible(bool visible);
+
+ virtual bool isEnabled() const;
+
+ virtual const TCHAR * getToolTip() const;
+ virtual void setToolTip(const TCHAR *tooltip);
+
+ virtual BorderState * getBorders();
+ virtual const BorderState * getBorders() const;
+
+ virtual HORIZONTAL_ALIGN getHAlign() const;
+ virtual void setHAlign(HORIZONTAL_ALIGN halign);
+
+ virtual VERTICAL_ALIGN getVAlign() const;
+ virtual void setVAlign(VERTICAL_ALIGN valign);
+
+ virtual bool isEmpty() const = 0;
+
+ // Results
+
+ virtual RECT getInsideRect(bool raw = false) const;
+ virtual RECT getRect(bool raw = false) const;
+
+protected:
+ FieldState(DialogState *dialog, Field *field);
+
+ Field *field;
+ DialogState *dialog;
+
+ Size size;
+ Position pos;
+ int usingX;
+ int usingY;
+ bool visible;
+ BorderState borders;
+ bool tooltipSet;
+ std::tstring tooltip;
+ HORIZONTAL_ALIGN halign;
+ VERTICAL_ALIGN valign;
+
+ int getHorizontalBorders() const;
+ int getVerticalBorders() const;
+
+ friend class Field;
+};
+
+
+#endif // __FIELD_STATE_H__
diff --git a/plugins/Skins/SkinLib/FieldState.rec b/plugins/Skins/SkinLib/FieldState.rec
new file mode 100644
index 0000000000..7b9ffd890d
--- /dev/null
+++ b/plugins/Skins/SkinLib/FieldState.rec
@@ -0,0 +1,89 @@
+struct DialogState
+{
+ Int32 width;
+ Int32 height;
+ const Int32 x;
+ const Int32 y;
+ const Int32 left;
+ const Int32 top;
+ const Int32 right;
+ const Int32 bottom;
+ BorderState borders [setter: if (!value.IsEmpty() && value->IsInt32())\n\ttmp->getBorders()->setAll(value->Int32Value()); ];
+};
+
+struct FieldState
+{
+ Int32 x;
+ Int32 y;
+ Int32 width;
+ Int32 height;
+ Int32 left;
+ Int32 top;
+ Int32 right;
+ Int32 bottom;
+ Boolean visible;
+ const Boolean enabled;
+ Char toolTip[128];
+ Int32 hAlign | HORIZONTAL_ALIGN_LEFT "LEFT" | HORIZONTAL_ALIGN_CENTER "CENTER" | HORIZONTAL_ALIGN_RIGHT "RIGHT";
+ Int32 vAlign | VERTICAL_ALIGN_TOP "TOP" | VERTICAL_ALIGN_CENTER "CENTER" | VERTICAL_ALIGN_BOTTOM "BOTTOM";
+ BorderState borders [setter: if (!value.IsEmpty() && value->IsInt32())\n\ttmp->getBorders()->setAll(value->Int32Value()); ];
+};
+
+struct ControlFieldState : FieldState
+{
+ Char text[1024];
+ FontState font;
+};
+
+struct LabelFieldState : ControlFieldState
+{
+};
+
+struct ButtonFieldState : ControlFieldState
+{
+};
+
+struct EditFieldState : ControlFieldState
+{
+};
+
+struct IconFieldState : FieldState
+{
+};
+
+struct ImageFieldState : FieldState
+{
+};
+
+struct TextFieldState : FieldState
+{
+ Char text[1024];
+ FontState font;
+};
+
+struct FontState
+{
+ Char face[32];
+ Int32 size;
+ Boolean italic;
+ Boolean bold;
+ Boolean underline;
+ Boolean strikeOut;
+ Int32 color;
+};
+
+struct BorderState
+{
+ Int32 left;
+ Int32 right;
+ Int32 top;
+ Int32 bottom;
+};
+
+struct SkinOption
+{
+ Char description[128];
+ Int32 min;
+ Int32 max;
+ Int32 type | CHECKBOX | NUMBER | TEXT;
+};
diff --git a/plugins/Skins/SkinLib/FieldState_v8_wrapper.cpp b/plugins/Skins/SkinLib/FieldState_v8_wrapper.cpp
new file mode 100644
index 0000000000..937ad69a58
--- /dev/null
+++ b/plugins/Skins/SkinLib/FieldState_v8_wrapper.cpp
@@ -0,0 +1,539 @@
+#include "globals.h"
+#include "FieldState_v8_wrapper.h"
+#include <v8.h>
+#include "FieldState.h"
+#include <utf8_helpers.h>
+
+using namespace v8;
+
+
+#ifdef UNICODE
+# define V8_TCHAR uint16_t
+#else
+# define V8_TCHAR char
+#endif
+
+
+static Handle<Value> Get_FieldState_x(Local<String> property, const AccessorInfo &info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return scope.Close( Undefined() );
+
+ FieldState *tmp = (FieldState *) wrap->Value();
+ if (tmp == NULL)
+ return scope.Close( Undefined() );
+
+ return scope.Close( Int32::New(tmp->getX()) );
+}
+
+static void Set_FieldState_x(Local<String> property, Local<Value> value, const AccessorInfo& info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return;
+
+ FieldState *tmp = (FieldState *) wrap->Value();
+ if (tmp == NULL)
+ return;
+
+ if (!value.IsEmpty() && value->IsNumber())
+ tmp->setX(value->Int32Value());
+}
+
+
+static Handle<Value> Get_FieldState_y(Local<String> property, const AccessorInfo &info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return scope.Close( Undefined() );
+
+ FieldState *tmp = (FieldState *) wrap->Value();
+ if (tmp == NULL)
+ return scope.Close( Undefined() );
+
+ return scope.Close( Int32::New(tmp->getY()) );
+}
+
+static void Set_FieldState_y(Local<String> property, Local<Value> value, const AccessorInfo& info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return;
+
+ FieldState *tmp = (FieldState *) wrap->Value();
+ if (tmp == NULL)
+ return;
+
+ if (!value.IsEmpty() && value->IsNumber())
+ tmp->setY(value->Int32Value());
+}
+
+
+static Handle<Value> Get_FieldState_width(Local<String> property, const AccessorInfo &info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return scope.Close( Undefined() );
+
+ FieldState *tmp = (FieldState *) wrap->Value();
+ if (tmp == NULL)
+ return scope.Close( Undefined() );
+
+ return scope.Close( Int32::New(tmp->getWidth()) );
+}
+
+static void Set_FieldState_width(Local<String> property, Local<Value> value, const AccessorInfo& info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return;
+
+ FieldState *tmp = (FieldState *) wrap->Value();
+ if (tmp == NULL)
+ return;
+
+ if (!value.IsEmpty() && value->IsNumber())
+ tmp->setWidth(value->Int32Value());
+}
+
+
+static Handle<Value> Get_FieldState_height(Local<String> property, const AccessorInfo &info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return scope.Close( Undefined() );
+
+ FieldState *tmp = (FieldState *) wrap->Value();
+ if (tmp == NULL)
+ return scope.Close( Undefined() );
+
+ return scope.Close( Int32::New(tmp->getHeight()) );
+}
+
+static void Set_FieldState_height(Local<String> property, Local<Value> value, const AccessorInfo& info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return;
+
+ FieldState *tmp = (FieldState *) wrap->Value();
+ if (tmp == NULL)
+ return;
+
+ if (!value.IsEmpty() && value->IsNumber())
+ tmp->setHeight(value->Int32Value());
+}
+
+
+static Handle<Value> Get_FieldState_left(Local<String> property, const AccessorInfo &info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return scope.Close( Undefined() );
+
+ FieldState *tmp = (FieldState *) wrap->Value();
+ if (tmp == NULL)
+ return scope.Close( Undefined() );
+
+ return scope.Close( Int32::New(tmp->getLeft()) );
+}
+
+static void Set_FieldState_left(Local<String> property, Local<Value> value, const AccessorInfo& info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return;
+
+ FieldState *tmp = (FieldState *) wrap->Value();
+ if (tmp == NULL)
+ return;
+
+ if (!value.IsEmpty() && value->IsNumber())
+ tmp->setLeft(value->Int32Value());
+}
+
+
+static Handle<Value> Get_FieldState_top(Local<String> property, const AccessorInfo &info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return scope.Close( Undefined() );
+
+ FieldState *tmp = (FieldState *) wrap->Value();
+ if (tmp == NULL)
+ return scope.Close( Undefined() );
+
+ return scope.Close( Int32::New(tmp->getTop()) );
+}
+
+static void Set_FieldState_top(Local<String> property, Local<Value> value, const AccessorInfo& info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return;
+
+ FieldState *tmp = (FieldState *) wrap->Value();
+ if (tmp == NULL)
+ return;
+
+ if (!value.IsEmpty() && value->IsNumber())
+ tmp->setTop(value->Int32Value());
+}
+
+
+static Handle<Value> Get_FieldState_right(Local<String> property, const AccessorInfo &info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return scope.Close( Undefined() );
+
+ FieldState *tmp = (FieldState *) wrap->Value();
+ if (tmp == NULL)
+ return scope.Close( Undefined() );
+
+ return scope.Close( Int32::New(tmp->getRight()) );
+}
+
+static void Set_FieldState_right(Local<String> property, Local<Value> value, const AccessorInfo& info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return;
+
+ FieldState *tmp = (FieldState *) wrap->Value();
+ if (tmp == NULL)
+ return;
+
+ if (!value.IsEmpty() && value->IsNumber())
+ tmp->setRight(value->Int32Value());
+}
+
+
+static Handle<Value> Get_FieldState_bottom(Local<String> property, const AccessorInfo &info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return scope.Close( Undefined() );
+
+ FieldState *tmp = (FieldState *) wrap->Value();
+ if (tmp == NULL)
+ return scope.Close( Undefined() );
+
+ return scope.Close( Int32::New(tmp->getBottom()) );
+}
+
+static void Set_FieldState_bottom(Local<String> property, Local<Value> value, const AccessorInfo& info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return;
+
+ FieldState *tmp = (FieldState *) wrap->Value();
+ if (tmp == NULL)
+ return;
+
+ if (!value.IsEmpty() && value->IsNumber())
+ tmp->setBottom(value->Int32Value());
+}
+
+
+static Handle<Value> Get_FieldState_visible(Local<String> property, const AccessorInfo &info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return scope.Close( Undefined() );
+
+ FieldState *tmp = (FieldState *) wrap->Value();
+ if (tmp == NULL)
+ return scope.Close( Undefined() );
+
+ return scope.Close( Boolean::New(tmp->isVisible()) );
+}
+
+static void Set_FieldState_visible(Local<String> property, Local<Value> value, const AccessorInfo& info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return;
+
+ FieldState *tmp = (FieldState *) wrap->Value();
+ if (tmp == NULL)
+ return;
+
+ if (!value.IsEmpty() && value->IsBoolean())
+ tmp->setVisible(value->BooleanValue());
+}
+
+
+static Handle<Value> Get_FieldState_enabled(Local<String> property, const AccessorInfo &info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return scope.Close( Undefined() );
+
+ FieldState *tmp = (FieldState *) wrap->Value();
+ if (tmp == NULL)
+ return scope.Close( Undefined() );
+
+ return scope.Close( Boolean::New(tmp->isEnabled()) );
+}
+
+
+static Handle<Value> Get_FieldState_toolTip(Local<String> property, const AccessorInfo &info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return scope.Close( Undefined() );
+
+ FieldState *tmp = (FieldState *) wrap->Value();
+ if (tmp == NULL)
+ return scope.Close( Undefined() );
+
+ return scope.Close( String::New((const V8_TCHAR *) tmp->getToolTip()) );
+}
+
+static void Set_FieldState_toolTip(Local<String> property, Local<Value> value, const AccessorInfo& info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return;
+
+ FieldState *tmp = (FieldState *) wrap->Value();
+ if (tmp == NULL)
+ return;
+
+ if (!value.IsEmpty() && value->IsString())
+ {
+ String::Utf8Value utf8_value(value);
+ tmp->setToolTip(Utf8ToTchar(*utf8_value));
+ }
+}
+
+
+static Handle<Value> Get_FieldState_hAlign(Local<String> property, const AccessorInfo &info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return scope.Close( Undefined() );
+
+ FieldState *tmp = (FieldState *) wrap->Value();
+ if (tmp == NULL)
+ return scope.Close( Undefined() );
+
+ switch(tmp->getHAlign())
+ {
+ case HORIZONTAL_ALIGN_LEFT: return scope.Close( String::New((const V8_TCHAR *) _T("LEFT")) );
+ case HORIZONTAL_ALIGN_CENTER: return scope.Close( String::New((const V8_TCHAR *) _T("CENTER")) );
+ case HORIZONTAL_ALIGN_RIGHT: return scope.Close( String::New((const V8_TCHAR *) _T("RIGHT")) );
+ }
+ return scope.Close( Undefined() );
+}
+
+static void Set_FieldState_hAlign(Local<String> property, Local<Value> value, const AccessorInfo& info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return;
+
+ FieldState *tmp = (FieldState *) wrap->Value();
+ if (tmp == NULL)
+ return;
+
+ if (!value.IsEmpty() && value->IsString())
+ {
+ String::Utf8Value utf8_value(value);
+ Utf8ToTchar tval(*utf8_value);
+ if ( lstrcmpi(_T("HORIZONTAL_ALIGN_LEFT"), tval) == 0 )
+ tmp->setHAlign(HORIZONTAL_ALIGN_LEFT);
+ else if ( lstrcmpi(_T("LEFT"), tval) == 0 )
+ tmp->setHAlign(HORIZONTAL_ALIGN_LEFT);
+ else if ( lstrcmpi(_T("HORIZONTAL_ALIGN_CENTER"), tval) == 0 )
+ tmp->setHAlign(HORIZONTAL_ALIGN_CENTER);
+ else if ( lstrcmpi(_T("CENTER"), tval) == 0 )
+ tmp->setHAlign(HORIZONTAL_ALIGN_CENTER);
+ else if ( lstrcmpi(_T("HORIZONTAL_ALIGN_RIGHT"), tval) == 0 )
+ tmp->setHAlign(HORIZONTAL_ALIGN_RIGHT);
+ else if ( lstrcmpi(_T("RIGHT"), tval) == 0 )
+ tmp->setHAlign(HORIZONTAL_ALIGN_RIGHT);
+ }
+}
+
+
+static Handle<Value> Get_FieldState_vAlign(Local<String> property, const AccessorInfo &info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return scope.Close( Undefined() );
+
+ FieldState *tmp = (FieldState *) wrap->Value();
+ if (tmp == NULL)
+ return scope.Close( Undefined() );
+
+ switch(tmp->getVAlign())
+ {
+ case VERTICAL_ALIGN_TOP: return scope.Close( String::New((const V8_TCHAR *) _T("TOP")) );
+ case VERTICAL_ALIGN_CENTER: return scope.Close( String::New((const V8_TCHAR *) _T("CENTER")) );
+ case VERTICAL_ALIGN_BOTTOM: return scope.Close( String::New((const V8_TCHAR *) _T("BOTTOM")) );
+ }
+ return scope.Close( Undefined() );
+}
+
+static void Set_FieldState_vAlign(Local<String> property, Local<Value> value, const AccessorInfo& info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return;
+
+ FieldState *tmp = (FieldState *) wrap->Value();
+ if (tmp == NULL)
+ return;
+
+ if (!value.IsEmpty() && value->IsString())
+ {
+ String::Utf8Value utf8_value(value);
+ Utf8ToTchar tval(*utf8_value);
+ if ( lstrcmpi(_T("VERTICAL_ALIGN_TOP"), tval) == 0 )
+ tmp->setVAlign(VERTICAL_ALIGN_TOP);
+ else if ( lstrcmpi(_T("TOP"), tval) == 0 )
+ tmp->setVAlign(VERTICAL_ALIGN_TOP);
+ else if ( lstrcmpi(_T("VERTICAL_ALIGN_CENTER"), tval) == 0 )
+ tmp->setVAlign(VERTICAL_ALIGN_CENTER);
+ else if ( lstrcmpi(_T("CENTER"), tval) == 0 )
+ tmp->setVAlign(VERTICAL_ALIGN_CENTER);
+ else if ( lstrcmpi(_T("VERTICAL_ALIGN_BOTTOM"), tval) == 0 )
+ tmp->setVAlign(VERTICAL_ALIGN_BOTTOM);
+ else if ( lstrcmpi(_T("BOTTOM"), tval) == 0 )
+ tmp->setVAlign(VERTICAL_ALIGN_BOTTOM);
+ }
+}
+
+
+static Handle<Value> Get_FieldState_borders(Local<String> property, const AccessorInfo &info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return scope.Close( Undefined() );
+
+ FieldState *tmp = (FieldState *) wrap->Value();
+ if (tmp == NULL)
+ return scope.Close( Undefined() );
+
+ return scope.Close( self->Get(String::New("bordersRaw")) );
+}
+
+static void Set_FieldState_borders(Local<String> property, Local<Value> value, const AccessorInfo& info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return;
+
+ FieldState *tmp = (FieldState *) wrap->Value();
+ if (tmp == NULL)
+ return;
+
+ if (!value.IsEmpty() && value->IsInt32())
+ tmp->getBorders()->setAll(value->Int32Value());
+}
+
+
+void AddFieldStateAcessors(Handle<ObjectTemplate> &templ)
+{
+ HandleScope scope;
+
+ templ->SetAccessor(String::New("x"), Get_FieldState_x, Set_FieldState_x);
+ templ->SetAccessor(String::New("y"), Get_FieldState_y, Set_FieldState_y);
+ templ->SetAccessor(String::New("width"), Get_FieldState_width, Set_FieldState_width);
+ templ->SetAccessor(String::New("height"), Get_FieldState_height, Set_FieldState_height);
+ templ->SetAccessor(String::New("left"), Get_FieldState_left, Set_FieldState_left);
+ templ->SetAccessor(String::New("top"), Get_FieldState_top, Set_FieldState_top);
+ templ->SetAccessor(String::New("right"), Get_FieldState_right, Set_FieldState_right);
+ templ->SetAccessor(String::New("bottom"), Get_FieldState_bottom, Set_FieldState_bottom);
+ templ->SetAccessor(String::New("visible"), Get_FieldState_visible, Set_FieldState_visible);
+ templ->SetAccessor(String::New("enabled"), Get_FieldState_enabled, NULL, Handle<Value>(), DEFAULT, ReadOnly);
+ templ->SetAccessor(String::New("toolTip"), Get_FieldState_toolTip, Set_FieldState_toolTip);
+ templ->SetAccessor(String::New("hAlign"), Get_FieldState_hAlign, Set_FieldState_hAlign);
+ templ->SetAccessor(String::New("vAlign"), Get_FieldState_vAlign, Set_FieldState_vAlign);
+ templ->SetAccessor(String::New("borders"), Get_FieldState_borders, Set_FieldState_borders);
+}
diff --git a/plugins/Skins/SkinLib/FieldState_v8_wrapper.h b/plugins/Skins/SkinLib/FieldState_v8_wrapper.h
new file mode 100644
index 0000000000..10c2a854b4
--- /dev/null
+++ b/plugins/Skins/SkinLib/FieldState_v8_wrapper.h
@@ -0,0 +1,10 @@
+#ifndef __FIELD_STATE_V8_WRAPPER_H__
+# define __FIELD_STATE_V8_WRAPPER_H__
+
+#include <v8.h>
+
+void AddFieldStateAcessors(v8::Handle<v8::ObjectTemplate> &templ);
+
+
+
+#endif // __FIELD_STATE_V8_WRAPPER_H__
diff --git a/plugins/Skins/SkinLib/FontState.cpp b/plugins/Skins/SkinLib/FontState.cpp
new file mode 100644
index 0000000000..da9b4153d5
--- /dev/null
+++ b/plugins/Skins/SkinLib/FontState.cpp
@@ -0,0 +1,186 @@
+#include "globals.h"
+#include "FontState.h"
+
+
+FontState::FontState(HFONT hFont, COLORREF aColor) : hFont(NULL), externalFont(false), color(aColor)
+{
+ setHFONT(hFont);
+}
+
+FontState::~FontState()
+{
+ releaseHFONT();
+}
+
+void FontState::rebuildHFONT()
+{
+ releaseHFONT();
+ buildHFONT();
+}
+
+void FontState::buildAttribs()
+{
+ LOGFONT lf = {0};
+ if (hFont == NULL || GetObject(hFont, sizeof(lf), &lf) == 0)
+ {
+ face = _T("Tahoma");
+ size = 9;
+ italic = false;
+ bold = false;
+ underline = false;
+ strikeout = false;
+
+ rebuildHFONT();
+
+ return;
+ }
+
+ face = lf.lfFaceName;
+ italic = (lf.lfItalic != 0);
+ bold = (lf.lfWeight > FW_NORMAL);
+ underline = (lf.lfUnderline != 0);
+ strikeout = (lf.lfStrikeOut != 0);
+
+ HDC hdc = GetDC(NULL);
+ size = -MulDiv(lf.lfHeight, 72, GetDeviceCaps(hdc, LOGPIXELSY));
+ ReleaseDC(NULL, hdc);
+}
+
+void FontState::buildHFONT()
+{
+ if (hFont != NULL)
+ return;
+
+ LOGFONT lf;
+
+ _tcscpy(lf.lfFaceName, getFace());
+
+ lf.lfWidth = lf.lfEscapement = lf.lfOrientation = 0;
+ lf.lfWeight = isBold() ? FW_BOLD : FW_NORMAL;
+ lf.lfItalic = isItalic() ? 1 : 0;
+ lf.lfUnderline = isUnderline() ? 1 : 0;
+ lf.lfStrikeOut = isStrikeOut() ? 1 : 0;
+ lf.lfCharSet = DEFAULT_CHARSET;
+ lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
+ lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
+ lf.lfQuality = DEFAULT_QUALITY;
+ lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
+
+ HDC hdc = GetDC(NULL);
+ lf.lfHeight = -MulDiv(getSize(), GetDeviceCaps(hdc, LOGPIXELSY), 72);
+ ReleaseDC(NULL, hdc);
+
+ hFont = CreateFontIndirect(&lf);
+ externalFont = false;
+}
+
+void FontState::releaseHFONT()
+{
+ if (hFont == NULL)
+ return;
+
+ if (!externalFont)
+ DeleteObject(hFont);
+
+ hFont = NULL;
+}
+
+
+HFONT FontState::getHFONT() const
+{
+ return hFont;
+}
+
+
+HFONT FontState::createHFONT() const
+{
+ LOGFONT lf;
+ if (hFont == NULL || GetObject(hFont, sizeof(lf), &lf) == 0)
+ return NULL;
+ else
+ return CreateFontIndirect(&lf);
+}
+
+void FontState::setHFONT(HFONT hFont)
+{
+ releaseHFONT();
+ this->hFont = hFont;
+ externalFont = true;
+ buildAttribs();
+}
+
+const TCHAR * FontState::getFace() const
+{
+ return face.c_str();
+}
+
+void FontState::setFace(const TCHAR * face)
+{
+ this->face = face;
+ rebuildHFONT();
+}
+
+int FontState::getSize() const
+{
+ return size;
+}
+
+void FontState::setSize(int size)
+{
+ this->size = size;
+ rebuildHFONT();
+}
+
+COLORREF FontState::getColor() const
+{
+ return color;
+}
+
+void FontState::setColor(COLORREF color)
+{
+ this->color = color;
+}
+
+bool FontState::isItalic() const
+{
+ return italic;
+}
+
+void FontState::setItalic(bool italic)
+{
+ this->italic = italic;
+ rebuildHFONT();
+}
+
+bool FontState::isBold() const
+{
+ return bold;
+}
+
+void FontState::setBold(bool bold)
+{
+ this->bold = bold;
+ rebuildHFONT();
+}
+
+bool FontState::isUnderline() const
+{
+ return underline;
+}
+
+void FontState::setUnderline(bool underline)
+{
+ this->underline = underline;
+ rebuildHFONT();
+}
+
+bool FontState::isStrikeOut() const
+{
+ return strikeout;
+}
+
+void FontState::setStrikeOut(bool strikeout)
+{
+ this->strikeout = strikeout;
+ rebuildHFONT();
+}
diff --git a/plugins/Skins/SkinLib/FontState.h b/plugins/Skins/SkinLib/FontState.h
new file mode 100644
index 0000000000..de32bcdfb3
--- /dev/null
+++ b/plugins/Skins/SkinLib/FontState.h
@@ -0,0 +1,57 @@
+#ifndef __FONT_STATE_H__
+# define __FONT_STATE_H__
+
+#include "Field.h"
+
+
+class FontState
+{
+public:
+ FontState(HFONT hFont, COLORREF aColor);
+ ~FontState();
+
+ HFONT getHFONT() const;
+ void setHFONT(HFONT hFont);
+ HFONT createHFONT() const; /// Return a copy of the internal HFONT. The caller must free it
+
+ const TCHAR * getFace() const;
+ void setFace(const TCHAR * face);
+
+ int getSize() const;
+ void setSize(int size);
+
+ COLORREF getColor() const;
+ void setColor(COLORREF color);
+
+ bool isItalic() const;
+ void setItalic(bool italic);
+
+ bool isBold() const;
+ void setBold(bool bold);
+
+ bool isUnderline() const;
+ void setUnderline(bool underline);
+
+ bool isStrikeOut() const;
+ void setStrikeOut(bool strikeout);
+
+private:
+ COLORREF color;
+ HFONT hFont;
+ bool externalFont;
+ std::tstring face;
+ int size;
+ bool italic;
+ bool bold;
+ bool underline;
+ bool strikeout;
+
+ void rebuildHFONT();
+ void buildHFONT();
+ void releaseHFONT();
+ void buildAttribs();
+};
+
+
+
+#endif // __FONT_STATE_H__
diff --git a/plugins/Skins/SkinLib/FontState_v8_wrapper.cpp b/plugins/Skins/SkinLib/FontState_v8_wrapper.cpp
new file mode 100644
index 0000000000..5226736b24
--- /dev/null
+++ b/plugins/Skins/SkinLib/FontState_v8_wrapper.cpp
@@ -0,0 +1,269 @@
+#include "globals.h"
+#include "FontState_v8_wrapper.h"
+#include <v8.h>
+#include "FontState.h"
+#include <utf8_helpers.h>
+
+using namespace v8;
+
+
+#ifdef UNICODE
+# define V8_TCHAR uint16_t
+#else
+# define V8_TCHAR char
+#endif
+
+
+static Handle<Value> Get_FontState_face(Local<String> property, const AccessorInfo &info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return scope.Close( Undefined() );
+
+ FontState *tmp = (FontState *) wrap->Value();
+ if (tmp == NULL)
+ return scope.Close( Undefined() );
+
+ return scope.Close( String::New((const V8_TCHAR *) tmp->getFace()) );
+}
+
+static void Set_FontState_face(Local<String> property, Local<Value> value, const AccessorInfo& info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return;
+
+ FontState *tmp = (FontState *) wrap->Value();
+ if (tmp == NULL)
+ return;
+
+ if (!value.IsEmpty() && value->IsString())
+ {
+ String::Utf8Value utf8_value(value);
+ tmp->setFace(Utf8ToTchar(*utf8_value));
+ }
+}
+
+
+static Handle<Value> Get_FontState_size(Local<String> property, const AccessorInfo &info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return scope.Close( Undefined() );
+
+ FontState *tmp = (FontState *) wrap->Value();
+ if (tmp == NULL)
+ return scope.Close( Undefined() );
+
+ return scope.Close( Int32::New(tmp->getSize()) );
+}
+
+static void Set_FontState_size(Local<String> property, Local<Value> value, const AccessorInfo& info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return;
+
+ FontState *tmp = (FontState *) wrap->Value();
+ if (tmp == NULL)
+ return;
+
+ if (!value.IsEmpty() && value->IsNumber())
+ tmp->setSize(value->Int32Value());
+}
+
+
+static Handle<Value> Get_FontState_italic(Local<String> property, const AccessorInfo &info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return scope.Close( Undefined() );
+
+ FontState *tmp = (FontState *) wrap->Value();
+ if (tmp == NULL)
+ return scope.Close( Undefined() );
+
+ return scope.Close( Boolean::New(tmp->isItalic()) );
+}
+
+static void Set_FontState_italic(Local<String> property, Local<Value> value, const AccessorInfo& info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return;
+
+ FontState *tmp = (FontState *) wrap->Value();
+ if (tmp == NULL)
+ return;
+
+ if (!value.IsEmpty() && value->IsBoolean())
+ tmp->setItalic(value->BooleanValue());
+}
+
+
+static Handle<Value> Get_FontState_bold(Local<String> property, const AccessorInfo &info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return scope.Close( Undefined() );
+
+ FontState *tmp = (FontState *) wrap->Value();
+ if (tmp == NULL)
+ return scope.Close( Undefined() );
+
+ return scope.Close( Boolean::New(tmp->isBold()) );
+}
+
+static void Set_FontState_bold(Local<String> property, Local<Value> value, const AccessorInfo& info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return;
+
+ FontState *tmp = (FontState *) wrap->Value();
+ if (tmp == NULL)
+ return;
+
+ if (!value.IsEmpty() && value->IsBoolean())
+ tmp->setBold(value->BooleanValue());
+}
+
+
+static Handle<Value> Get_FontState_underline(Local<String> property, const AccessorInfo &info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return scope.Close( Undefined() );
+
+ FontState *tmp = (FontState *) wrap->Value();
+ if (tmp == NULL)
+ return scope.Close( Undefined() );
+
+ return scope.Close( Boolean::New(tmp->isUnderline()) );
+}
+
+static void Set_FontState_underline(Local<String> property, Local<Value> value, const AccessorInfo& info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return;
+
+ FontState *tmp = (FontState *) wrap->Value();
+ if (tmp == NULL)
+ return;
+
+ if (!value.IsEmpty() && value->IsBoolean())
+ tmp->setUnderline(value->BooleanValue());
+}
+
+
+static Handle<Value> Get_FontState_strikeOut(Local<String> property, const AccessorInfo &info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return scope.Close( Undefined() );
+
+ FontState *tmp = (FontState *) wrap->Value();
+ if (tmp == NULL)
+ return scope.Close( Undefined() );
+
+ return scope.Close( Boolean::New(tmp->isStrikeOut()) );
+}
+
+static void Set_FontState_strikeOut(Local<String> property, Local<Value> value, const AccessorInfo& info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return;
+
+ FontState *tmp = (FontState *) wrap->Value();
+ if (tmp == NULL)
+ return;
+
+ if (!value.IsEmpty() && value->IsBoolean())
+ tmp->setStrikeOut(value->BooleanValue());
+}
+
+
+static Handle<Value> Get_FontState_color(Local<String> property, const AccessorInfo &info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return scope.Close( Undefined() );
+
+ FontState *tmp = (FontState *) wrap->Value();
+ if (tmp == NULL)
+ return scope.Close( Undefined() );
+
+ return scope.Close( Int32::New(tmp->getColor()) );
+}
+
+static void Set_FontState_color(Local<String> property, Local<Value> value, const AccessorInfo& info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return;
+
+ FontState *tmp = (FontState *) wrap->Value();
+ if (tmp == NULL)
+ return;
+
+ if (!value.IsEmpty() && value->IsNumber())
+ tmp->setColor(value->Int32Value());
+}
+
+
+void AddFontStateAcessors(Handle<ObjectTemplate> &templ)
+{
+ HandleScope scope;
+
+ templ->SetAccessor(String::New("face"), Get_FontState_face, Set_FontState_face);
+ templ->SetAccessor(String::New("size"), Get_FontState_size, Set_FontState_size);
+ templ->SetAccessor(String::New("italic"), Get_FontState_italic, Set_FontState_italic);
+ templ->SetAccessor(String::New("bold"), Get_FontState_bold, Set_FontState_bold);
+ templ->SetAccessor(String::New("underline"), Get_FontState_underline, Set_FontState_underline);
+ templ->SetAccessor(String::New("strikeOut"), Get_FontState_strikeOut, Set_FontState_strikeOut);
+ templ->SetAccessor(String::New("color"), Get_FontState_color, Set_FontState_color);
+}
diff --git a/plugins/Skins/SkinLib/FontState_v8_wrapper.h b/plugins/Skins/SkinLib/FontState_v8_wrapper.h
new file mode 100644
index 0000000000..4b0483ffd9
--- /dev/null
+++ b/plugins/Skins/SkinLib/FontState_v8_wrapper.h
@@ -0,0 +1,10 @@
+#ifndef __FONT_STATE_V8_WRAPPER_H__
+# define __FONT_STATE_V8_WRAPPER_H__
+
+#include <v8.h>
+
+void AddFontStateAcessors(v8::Handle<v8::ObjectTemplate> &templ);
+
+
+
+#endif // __FONT_STATE_V8_WRAPPER_H__
diff --git a/plugins/Skins/SkinLib/IconField.cpp b/plugins/Skins/SkinLib/IconField.cpp
new file mode 100644
index 0000000000..4cf1aaf532
--- /dev/null
+++ b/plugins/Skins/SkinLib/IconField.cpp
@@ -0,0 +1,38 @@
+#include "globals.h"
+#include "IconField.h"
+#include "IconFieldState.h"
+
+
+IconField::IconField(Dialog *dlg, const char *name)
+ : Field(dlg, name), hIcon(NULL)
+{
+
+}
+
+IconField::~IconField()
+{
+}
+
+FieldType IconField::getType() const
+{
+ return SIMPLE_ICON;
+}
+
+HICON IconField::getIcon() const
+{
+ return hIcon;
+}
+
+void IconField::setIcon(HICON hIcon)
+{
+ if (this->hIcon == hIcon)
+ return;
+
+ this->hIcon = hIcon;
+ fireOnChange();
+}
+
+FieldState * IconField::createState(DialogState *dialogState)
+{
+ return new IconFieldState(dialogState, this);
+} \ No newline at end of file
diff --git a/plugins/Skins/SkinLib/IconField.h b/plugins/Skins/SkinLib/IconField.h
new file mode 100644
index 0000000000..984b36b984
--- /dev/null
+++ b/plugins/Skins/SkinLib/IconField.h
@@ -0,0 +1,27 @@
+#ifndef __ICON_FIELD_H__
+# define __ICON_FIELD_H__
+
+#include "Field.h"
+
+
+class IconField : public Field
+{
+public:
+ IconField(Dialog *dlg, const char *name);
+ virtual ~IconField();
+
+ virtual FieldType getType() const;
+
+ virtual HICON getIcon() const;
+ virtual void setIcon(HICON hIcon);
+
+ virtual FieldState * createState(DialogState *dialogState);
+
+private:
+ HICON hIcon;
+
+};
+
+
+
+#endif // __ICON_FIELD_H__ \ No newline at end of file
diff --git a/plugins/Skins/SkinLib/IconFieldState.cpp b/plugins/Skins/SkinLib/IconFieldState.cpp
new file mode 100644
index 0000000000..fad1d67084
--- /dev/null
+++ b/plugins/Skins/SkinLib/IconFieldState.cpp
@@ -0,0 +1,37 @@
+#include "globals.h"
+#include "IconFieldState.h"
+
+#define ICON_SIZE 16
+
+
+IconFieldState::IconFieldState(DialogState *dialog, IconField *field)
+ : FieldState(dialog, field)
+{
+}
+
+IconFieldState::~IconFieldState()
+{
+}
+
+IconField * IconFieldState::getField() const
+{
+ return (IconField *) FieldState::getField();
+}
+
+Size IconFieldState::getPreferedSize() const
+{
+ if (getIcon() == NULL)
+ return Size(0, 0);
+
+ return Size(ICON_SIZE, ICON_SIZE);
+}
+
+HICON IconFieldState::getIcon() const
+{
+ return getField()->getIcon();
+}
+
+bool IconFieldState::isEmpty() const
+{
+ return getIcon() == NULL;
+} \ No newline at end of file
diff --git a/plugins/Skins/SkinLib/IconFieldState.h b/plugins/Skins/SkinLib/IconFieldState.h
new file mode 100644
index 0000000000..b69e3fe01f
--- /dev/null
+++ b/plugins/Skins/SkinLib/IconFieldState.h
@@ -0,0 +1,28 @@
+#ifndef __ICON_FIELD_STATE_H__
+# define __ICON_FIELD_STATE_H__
+
+#include "IconField.h"
+#include "FieldState.h"
+
+
+class IconFieldState : public FieldState
+{
+public:
+ virtual ~IconFieldState();
+
+ virtual IconField * getField() const;
+
+ virtual Size getPreferedSize() const;
+
+ virtual HICON getIcon() const;
+
+ virtual bool isEmpty() const;
+
+private:
+ IconFieldState(DialogState *dialog, IconField *field);
+
+ friend class IconField;
+};
+
+
+#endif // __ICON_FIELD_STATE_H__ \ No newline at end of file
diff --git a/plugins/Skins/SkinLib/IconFieldState_v8_wrapper.cpp b/plugins/Skins/SkinLib/IconFieldState_v8_wrapper.cpp
new file mode 100644
index 0000000000..a955653652
--- /dev/null
+++ b/plugins/Skins/SkinLib/IconFieldState_v8_wrapper.cpp
@@ -0,0 +1,20 @@
+#include "globals.h"
+#include "IconFieldState_v8_wrapper.h"
+#include <v8.h>
+#include "IconFieldState.h"
+
+using namespace v8;
+
+
+#ifdef UNICODE
+# define V8_TCHAR uint16_t
+#else
+# define V8_TCHAR char
+#endif
+
+
+void AddIconFieldStateAcessors(Handle<ObjectTemplate> &templ)
+{
+ HandleScope scope;
+
+}
diff --git a/plugins/Skins/SkinLib/IconFieldState_v8_wrapper.h b/plugins/Skins/SkinLib/IconFieldState_v8_wrapper.h
new file mode 100644
index 0000000000..7b63f801bc
--- /dev/null
+++ b/plugins/Skins/SkinLib/IconFieldState_v8_wrapper.h
@@ -0,0 +1,10 @@
+#ifndef __ICON_FIELD_STATE_V8_WRAPPER_H__
+# define __ICON_FIELD_STATE_V8_WRAPPER_H__
+
+#include <v8.h>
+
+void AddIconFieldStateAcessors(v8::Handle<v8::ObjectTemplate> &templ);
+
+
+
+#endif // __ICON_FIELD_STATE_V8_WRAPPER_H__
diff --git a/plugins/Skins/SkinLib/ImageField.cpp b/plugins/Skins/SkinLib/ImageField.cpp
new file mode 100644
index 0000000000..c65cf99a0f
--- /dev/null
+++ b/plugins/Skins/SkinLib/ImageField.cpp
@@ -0,0 +1,38 @@
+#include "globals.h"
+#include "ImageField.h"
+#include "ImageFieldState.h"
+
+
+ImageField::ImageField(Dialog *dlg, const char *name)
+ : Field(dlg, name), hBmp(NULL)
+{
+
+}
+
+ImageField::~ImageField()
+{
+}
+
+FieldType ImageField::getType() const
+{
+ return SIMPLE_IMAGE;
+}
+
+HBITMAP ImageField::getImage() const
+{
+ return hBmp;
+}
+
+void ImageField::setImage(HBITMAP hBmp)
+{
+ if (this->hBmp == hBmp)
+ return;
+
+ this->hBmp = hBmp;
+ fireOnChange();
+}
+
+FieldState * ImageField::createState(DialogState *dialogState)
+{
+ return new ImageFieldState(dialogState, this);
+} \ No newline at end of file
diff --git a/plugins/Skins/SkinLib/ImageField.h b/plugins/Skins/SkinLib/ImageField.h
new file mode 100644
index 0000000000..e2f08665ca
--- /dev/null
+++ b/plugins/Skins/SkinLib/ImageField.h
@@ -0,0 +1,26 @@
+#ifndef __IMAGE_FIELD_H__
+# define __IMAGE_FIELD_H__
+
+#include "Field.h"
+
+class ImageField : public Field
+{
+public:
+ ImageField(Dialog *dlg, const char *name);
+ virtual ~ImageField();
+
+ virtual FieldType getType() const;
+
+ virtual HBITMAP getImage() const;
+ virtual void setImage(HBITMAP hBmp);
+
+ virtual FieldState * createState(DialogState *dialogState);
+
+private:
+ HBITMAP hBmp;
+
+};
+
+
+
+#endif // __IMAGE_FIELD_H__ \ No newline at end of file
diff --git a/plugins/Skins/SkinLib/ImageFieldState.cpp b/plugins/Skins/SkinLib/ImageFieldState.cpp
new file mode 100644
index 0000000000..f74d77e0f3
--- /dev/null
+++ b/plugins/Skins/SkinLib/ImageFieldState.cpp
@@ -0,0 +1,37 @@
+#include "globals.h"
+#include "ImageFieldState.h"
+
+
+ImageFieldState::ImageFieldState(DialogState *dialog, ImageField *field)
+ : FieldState(dialog, field)
+{
+}
+
+ImageFieldState::~ImageFieldState()
+{
+}
+
+ImageField * ImageFieldState::getField() const
+{
+ return (ImageField *) FieldState::getField();
+}
+
+Size ImageFieldState::getPreferedSize() const
+{
+ HBITMAP hBmp = getImage();
+ BITMAP bmp;
+ if (hBmp == NULL || GetObject(hBmp, sizeof(bmp), &bmp) == 0)
+ return Size(0, 0);
+
+ return Size(bmp.bmWidth, bmp.bmHeight);
+}
+
+HBITMAP ImageFieldState::getImage() const
+{
+ return getField()->getImage();
+}
+
+bool ImageFieldState::isEmpty() const
+{
+ return getImage() == NULL;
+} \ No newline at end of file
diff --git a/plugins/Skins/SkinLib/ImageFieldState.h b/plugins/Skins/SkinLib/ImageFieldState.h
new file mode 100644
index 0000000000..493c4db16d
--- /dev/null
+++ b/plugins/Skins/SkinLib/ImageFieldState.h
@@ -0,0 +1,28 @@
+#ifndef __IMAGE_FIELD_STATE_H__
+# define __IMAGE_FIELD_STATE_H__
+
+#include "ImageField.h"
+#include "FieldState.h"
+
+
+class ImageFieldState : public FieldState
+{
+public:
+ virtual ~ImageFieldState();
+
+ virtual ImageField * getField() const;
+
+ virtual Size getPreferedSize() const;
+
+ virtual HBITMAP getImage() const;
+
+ virtual bool isEmpty() const;
+
+private:
+ ImageFieldState(DialogState *dialog, ImageField *field);
+
+ friend class ImageField;
+};
+
+
+#endif // __IMAGE_FIELD_STATE_H__ \ No newline at end of file
diff --git a/plugins/Skins/SkinLib/ImageFieldState_v8_wrapper.cpp b/plugins/Skins/SkinLib/ImageFieldState_v8_wrapper.cpp
new file mode 100644
index 0000000000..1e4a9b6a54
--- /dev/null
+++ b/plugins/Skins/SkinLib/ImageFieldState_v8_wrapper.cpp
@@ -0,0 +1,20 @@
+#include "globals.h"
+#include "ImageFieldState_v8_wrapper.h"
+#include <v8.h>
+#include "ImageFieldState.h"
+
+using namespace v8;
+
+
+#ifdef UNICODE
+# define V8_TCHAR uint16_t
+#else
+# define V8_TCHAR char
+#endif
+
+
+void AddImageFieldStateAcessors(Handle<ObjectTemplate> &templ)
+{
+ HandleScope scope;
+
+}
diff --git a/plugins/Skins/SkinLib/ImageFieldState_v8_wrapper.h b/plugins/Skins/SkinLib/ImageFieldState_v8_wrapper.h
new file mode 100644
index 0000000000..ea5f343e03
--- /dev/null
+++ b/plugins/Skins/SkinLib/ImageFieldState_v8_wrapper.h
@@ -0,0 +1,10 @@
+#ifndef __IMAGE_FIELD_STATE_V8_WRAPPER_H__
+# define __IMAGE_FIELD_STATE_V8_WRAPPER_H__
+
+#include <v8.h>
+
+void AddImageFieldStateAcessors(v8::Handle<v8::ObjectTemplate> &templ);
+
+
+
+#endif // __IMAGE_FIELD_STATE_V8_WRAPPER_H__
diff --git a/plugins/Skins/SkinLib/LabelField.cpp b/plugins/Skins/SkinLib/LabelField.cpp
new file mode 100644
index 0000000000..154ae2fce5
--- /dev/null
+++ b/plugins/Skins/SkinLib/LabelField.cpp
@@ -0,0 +1,23 @@
+#include "globals.h"
+#include "LabelField.h"
+#include "LabelFieldState.h"
+
+
+LabelField::LabelField(Dialog *dlg, const char *name, HWND hwnd)
+ : ControlField(dlg, name, hwnd)
+{
+}
+
+LabelField::~LabelField()
+{
+}
+
+FieldType LabelField::getType() const
+{
+ return CONTROL_LABEL;
+}
+
+FieldState * LabelField::createState(DialogState *dialogState)
+{
+ return new LabelFieldState(dialogState, this);
+} \ No newline at end of file
diff --git a/plugins/Skins/SkinLib/LabelField.h b/plugins/Skins/SkinLib/LabelField.h
new file mode 100644
index 0000000000..8c4cb04a03
--- /dev/null
+++ b/plugins/Skins/SkinLib/LabelField.h
@@ -0,0 +1,20 @@
+#ifndef __LABEL_FIELD_H__
+# define __LABEL_FIELD_H__
+
+#include "ControlField.h"
+
+
+class LabelField : public ControlField
+{
+public:
+ LabelField(Dialog *dlg, const char *name, HWND hwnd);
+ virtual ~LabelField();
+
+ virtual FieldType getType() const;
+
+ virtual FieldState * createState(DialogState *dialogState);
+};
+
+
+
+#endif // __LABEL_FIELD_H__
diff --git a/plugins/Skins/SkinLib/LabelFieldState.cpp b/plugins/Skins/SkinLib/LabelFieldState.cpp
new file mode 100644
index 0000000000..364611fbf7
--- /dev/null
+++ b/plugins/Skins/SkinLib/LabelFieldState.cpp
@@ -0,0 +1,35 @@
+#include "globals.h"
+#include "LabelFieldState.h"
+
+
+LabelFieldState::LabelFieldState(DialogState *dialog, LabelField *field)
+ : ControlFieldState(dialog, field)
+{
+}
+
+LabelFieldState::~LabelFieldState()
+{
+}
+
+Size LabelFieldState::getPreferedSize() const
+{
+ int style = GetWindowLong(getField()->getHWND(), GWL_STYLE);
+
+ int format = DT_EXPANDTABS | DT_EDITCONTROL;
+ if ((style & SS_LEFTNOWORDWRAP) || (style & SS_SIMPLE))
+ format |= DT_SINGLELINE;
+ if (style & SS_NOPREFIX)
+ format |= DT_NOPREFIX;
+ Size ret = getTextPreferedSize(format);
+
+ int border = getField()->getBorderSize();
+ ret.x += 2 * border;
+ ret.y += 2 * border;
+
+ return ret;
+}
+
+bool LabelFieldState::isEmpty() const
+{
+ return lstrlen(getText()) <= 0;
+} \ No newline at end of file
diff --git a/plugins/Skins/SkinLib/LabelFieldState.h b/plugins/Skins/SkinLib/LabelFieldState.h
new file mode 100644
index 0000000000..dbbb3b04d3
--- /dev/null
+++ b/plugins/Skins/SkinLib/LabelFieldState.h
@@ -0,0 +1,25 @@
+#ifndef __LABEL_FIELD_STATE_H__
+# define __LABEL_FIELD_STATE_H__
+
+#include "ControlFieldState.h"
+#include "LabelField.h"
+
+
+class LabelFieldState : public ControlFieldState
+{
+public:
+ virtual ~LabelFieldState();
+
+ virtual Size getPreferedSize() const;
+
+ virtual bool isEmpty() const;
+
+private:
+ LabelFieldState(DialogState *dialog, LabelField *field);
+
+ friend class LabelField;
+};
+
+
+
+#endif // __LABEL_FIELD_STATE_H__
diff --git a/plugins/Skins/SkinLib/LabelFieldState_v8_wrapper.cpp b/plugins/Skins/SkinLib/LabelFieldState_v8_wrapper.cpp
new file mode 100644
index 0000000000..9105a7d878
--- /dev/null
+++ b/plugins/Skins/SkinLib/LabelFieldState_v8_wrapper.cpp
@@ -0,0 +1,20 @@
+#include "globals.h"
+#include "LabelFieldState_v8_wrapper.h"
+#include <v8.h>
+#include "LabelFieldState.h"
+
+using namespace v8;
+
+
+#ifdef UNICODE
+# define V8_TCHAR uint16_t
+#else
+# define V8_TCHAR char
+#endif
+
+
+void AddLabelFieldStateAcessors(Handle<ObjectTemplate> &templ)
+{
+ HandleScope scope;
+
+}
diff --git a/plugins/Skins/SkinLib/LabelFieldState_v8_wrapper.h b/plugins/Skins/SkinLib/LabelFieldState_v8_wrapper.h
new file mode 100644
index 0000000000..7d40de5bc2
--- /dev/null
+++ b/plugins/Skins/SkinLib/LabelFieldState_v8_wrapper.h
@@ -0,0 +1,10 @@
+#ifndef __LABEL_FIELD_STATE_V8_WRAPPER_H__
+# define __LABEL_FIELD_STATE_V8_WRAPPER_H__
+
+#include <v8.h>
+
+void AddLabelFieldStateAcessors(v8::Handle<v8::ObjectTemplate> &templ);
+
+
+
+#endif // __LABEL_FIELD_STATE_V8_WRAPPER_H__
diff --git a/plugins/Skins/SkinLib/Position.cpp b/plugins/Skins/SkinLib/Position.cpp
new file mode 100644
index 0000000000..6c68881fce
--- /dev/null
+++ b/plugins/Skins/SkinLib/Position.cpp
@@ -0,0 +1,9 @@
+#include "Position.h"
+
+Position::Position() : x(0), y(0)
+{
+}
+
+Position::Position(int aX, int aY) : x(aX), y(aY)
+{
+} \ No newline at end of file
diff --git a/plugins/Skins/SkinLib/Position.h b/plugins/Skins/SkinLib/Position.h
new file mode 100644
index 0000000000..ed43a1ece3
--- /dev/null
+++ b/plugins/Skins/SkinLib/Position.h
@@ -0,0 +1,16 @@
+#ifndef __POSITION_H__
+# define __POSITION_H__
+
+
+struct Position
+{
+ int x;
+ int y;
+
+ Position();
+ Position(int x, int y);
+};
+
+
+
+#endif // __POSITION_H__
diff --git a/plugins/Skins/SkinLib/Size.cpp b/plugins/Skins/SkinLib/Size.cpp
new file mode 100644
index 0000000000..9c2eef5d5d
--- /dev/null
+++ b/plugins/Skins/SkinLib/Size.cpp
@@ -0,0 +1,84 @@
+#include "globals.h"
+#include "Size.h"
+
+Size::Size() : x(0), y(0)
+{
+}
+
+Size::Size(int aX, int aY) : x(aX), y(aY)
+{
+
+}
+
+int Size::resizeTo(int newX, int newY)
+{
+ if (newX < 0 && newY < 0)
+ return -1;
+
+ if (newY < 0)
+ {
+ if (x < 0 || y < 0)
+ return -2;
+
+ y = (int) (y * (newX / (float) x));
+ x = newX;
+ }
+ else if (newX < 0)
+ {
+ if (x < 0 || y < 0)
+ return -2;
+
+ x = (int) (x * (newY / (float) y));
+ y = newY;
+ }
+ else
+ {
+ x = newX;
+ y = newY;
+ }
+ return 0;
+}
+
+int Size::fitInside(int maxSize)
+{
+ if (x < 0 || y < 0)
+ return -2;
+ if (x <= maxSize && y <= maxSize)
+ return 0;
+
+ if (x >= y)
+ {
+ y = (int) (y * (maxSize / (float) x));
+ x = maxSize;
+ }
+ else
+ {
+ x = (int) (x * (maxSize / (float) y));
+ y = maxSize;
+ }
+ return 0;
+}
+
+int Size::scaleTo(int size)
+{
+ if (x < 0 || y < 0)
+ return -2;
+
+ if (x >= y)
+ {
+ y = (int) (y * (size / (float) x));
+ x = size;
+ }
+ else
+ {
+ x = (int) (x * (size / (float) y));
+ y = size;
+ }
+
+ return 0;
+}
+
+bool Size::operator==(const Size &other) const
+{
+ return x == other.x && y == other.y;
+} \ No newline at end of file
diff --git a/plugins/Skins/SkinLib/Size.h b/plugins/Skins/SkinLib/Size.h
new file mode 100644
index 0000000000..8c0a297aee
--- /dev/null
+++ b/plugins/Skins/SkinLib/Size.h
@@ -0,0 +1,27 @@
+#ifndef __SIZE_H__
+# define __SIZE_H__
+
+
+struct Size
+{
+ int x;
+ int y;
+
+ Size();
+ Size(int aX, int aY);
+
+ /// @return 0 on success
+ int resizeTo(int x, int y);
+
+ /// @return 0 on success
+ int fitInside(int maxSize);
+
+ /// @return 0 on success
+ int scaleTo(int size);
+
+ bool operator==(const Size &other) const;
+};
+
+
+
+#endif // __SIZE_H__
diff --git a/plugins/Skins/SkinLib/SkinOption.h b/plugins/Skins/SkinLib/SkinOption.h
new file mode 100644
index 0000000000..7812303327
--- /dev/null
+++ b/plugins/Skins/SkinLib/SkinOption.h
@@ -0,0 +1 @@
+#include "SkinOptions.h" \ No newline at end of file
diff --git a/plugins/Skins/SkinLib/SkinOption_v8_wrapper.cpp b/plugins/Skins/SkinLib/SkinOption_v8_wrapper.cpp
new file mode 100644
index 0000000000..11a401ad2e
--- /dev/null
+++ b/plugins/Skins/SkinLib/SkinOption_v8_wrapper.cpp
@@ -0,0 +1,179 @@
+#include "globals.h"
+#include "SkinOption_v8_wrapper.h"
+#include <v8.h>
+#include "SkinOption.h"
+#include <utf8_helpers.h>
+
+using namespace v8;
+
+
+#ifdef UNICODE
+# define V8_TCHAR uint16_t
+#else
+# define V8_TCHAR char
+#endif
+
+
+static Handle<Value> Get_SkinOption_description(Local<String> property, const AccessorInfo &info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return scope.Close( Undefined() );
+
+ SkinOption *tmp = (SkinOption *) wrap->Value();
+ if (tmp == NULL)
+ return scope.Close( Undefined() );
+
+ return scope.Close( String::New((const V8_TCHAR *) tmp->getDescription()) );
+}
+
+static void Set_SkinOption_description(Local<String> property, Local<Value> value, const AccessorInfo& info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return;
+
+ SkinOption *tmp = (SkinOption *) wrap->Value();
+ if (tmp == NULL)
+ return;
+
+ if (!value.IsEmpty() && value->IsString())
+ {
+ String::Utf8Value utf8_value(value);
+ tmp->setDescription(Utf8ToTchar(*utf8_value));
+ }
+}
+
+
+static Handle<Value> Get_SkinOption_min(Local<String> property, const AccessorInfo &info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return scope.Close( Undefined() );
+
+ SkinOption *tmp = (SkinOption *) wrap->Value();
+ if (tmp == NULL)
+ return scope.Close( Undefined() );
+
+ return scope.Close( Int32::New(tmp->getMin()) );
+}
+
+static void Set_SkinOption_min(Local<String> property, Local<Value> value, const AccessorInfo& info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return;
+
+ SkinOption *tmp = (SkinOption *) wrap->Value();
+ if (tmp == NULL)
+ return;
+
+ if (!value.IsEmpty() && value->IsNumber())
+ tmp->setMin(value->Int32Value());
+}
+
+
+static Handle<Value> Get_SkinOption_max(Local<String> property, const AccessorInfo &info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return scope.Close( Undefined() );
+
+ SkinOption *tmp = (SkinOption *) wrap->Value();
+ if (tmp == NULL)
+ return scope.Close( Undefined() );
+
+ return scope.Close( Int32::New(tmp->getMax()) );
+}
+
+static void Set_SkinOption_max(Local<String> property, Local<Value> value, const AccessorInfo& info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return;
+
+ SkinOption *tmp = (SkinOption *) wrap->Value();
+ if (tmp == NULL)
+ return;
+
+ if (!value.IsEmpty() && value->IsNumber())
+ tmp->setMax(value->Int32Value());
+}
+
+
+static Handle<Value> Get_SkinOption_type(Local<String> property, const AccessorInfo &info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return scope.Close( Undefined() );
+
+ SkinOption *tmp = (SkinOption *) wrap->Value();
+ if (tmp == NULL)
+ return scope.Close( Undefined() );
+
+ switch(tmp->getType())
+ {
+ case CHECKBOX: return scope.Close( String::New((const V8_TCHAR *) _T("CHECKBOX")) );
+ case NUMBER: return scope.Close( String::New((const V8_TCHAR *) _T("NUMBER")) );
+ case TEXT: return scope.Close( String::New((const V8_TCHAR *) _T("TEXT")) );
+ }
+ return scope.Close( Undefined() );
+}
+
+static void Set_SkinOption_type(Local<String> property, Local<Value> value, const AccessorInfo& info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return;
+
+ SkinOption *tmp = (SkinOption *) wrap->Value();
+ if (tmp == NULL)
+ return;
+
+ if (!value.IsEmpty() && value->IsString())
+ {
+ String::Utf8Value utf8_value(value);
+ Utf8ToTchar tval(*utf8_value);
+ if ( lstrcmpi(_T("CHECKBOX"), tval) == 0 )
+ tmp->setType(CHECKBOX);
+ else if ( lstrcmpi(_T("NUMBER"), tval) == 0 )
+ tmp->setType(NUMBER);
+ else if ( lstrcmpi(_T("TEXT"), tval) == 0 )
+ tmp->setType(TEXT);
+ }
+}
+
+
+void AddSkinOptionAcessors(Handle<ObjectTemplate> &templ)
+{
+ HandleScope scope;
+
+ templ->SetAccessor(String::New("description"), Get_SkinOption_description, Set_SkinOption_description);
+ templ->SetAccessor(String::New("min"), Get_SkinOption_min, Set_SkinOption_min);
+ templ->SetAccessor(String::New("max"), Get_SkinOption_max, Set_SkinOption_max);
+ templ->SetAccessor(String::New("type"), Get_SkinOption_type, Set_SkinOption_type);
+}
diff --git a/plugins/Skins/SkinLib/SkinOption_v8_wrapper.h b/plugins/Skins/SkinLib/SkinOption_v8_wrapper.h
new file mode 100644
index 0000000000..6aa05c2122
--- /dev/null
+++ b/plugins/Skins/SkinLib/SkinOption_v8_wrapper.h
@@ -0,0 +1,10 @@
+#ifndef __SKIN_OPTION_V8_WRAPPER_H__
+# define __SKIN_OPTION_V8_WRAPPER_H__
+
+#include <v8.h>
+
+void AddSkinOptionAcessors(v8::Handle<v8::ObjectTemplate> &templ);
+
+
+
+#endif // __SKIN_OPTION_V8_WRAPPER_H__
diff --git a/plugins/Skins/SkinLib/SkinOptions.cpp b/plugins/Skins/SkinLib/SkinOptions.cpp
new file mode 100644
index 0000000000..51fb96cbdb
--- /dev/null
+++ b/plugins/Skins/SkinLib/SkinOptions.cpp
@@ -0,0 +1,216 @@
+#include "globals.h"
+#include "SkinOptions.h"
+#include <utf8_helpers.h>
+
+
+SkinOption::SkinOption(const char *aName)
+ : name(aName), type(CHECKBOX), valueCheckbox(false), valueNumber(0),
+ onChangeCallback(NULL), onChangeCallbackParam(NULL),
+ minValue(MININT), maxValue(MAXINT)
+{
+ description = Utf8ToTchar(aName);
+}
+
+SkinOption::~SkinOption()
+{
+}
+
+const char * SkinOption::getName() const
+{
+ return name.c_str();
+}
+
+SkinOptionType SkinOption::getType() const
+{
+ return type;
+}
+
+void SkinOption::setType(SkinOptionType type)
+{
+ if (this->type == type)
+ return;
+
+ this->type = type;
+ fireOnChange();
+}
+
+const TCHAR * SkinOption::getDescription() const
+{
+ return description.c_str();
+}
+
+void SkinOption::setDescription(const TCHAR * description)
+{
+ if (this->description == description)
+ return;
+
+ this->description = description;
+ fireOnChange();
+}
+
+int SkinOption::getMax() const
+{
+ return maxValue;
+}
+
+void SkinOption::setMax(int max)
+{
+ this->maxValue = max;
+ setValueNumber(valueNumber);
+}
+
+int SkinOption::getMin() const
+{
+ return minValue;
+}
+
+void SkinOption::setMin(int min)
+{
+ this->minValue = min;
+ setValueNumber(valueNumber);
+}
+
+bool SkinOption::getValueCheckbox() const
+{
+ return valueCheckbox;
+}
+
+void SkinOption::setValueCheckbox(bool value)
+{
+ if (valueCheckbox == value)
+ return;
+
+ valueCheckbox = value;
+ fireOnChange();
+}
+
+int SkinOption::getValueNumber() const
+{
+ return max(minValue, min(maxValue, valueNumber));
+}
+
+void SkinOption::setValueNumber(int value)
+{
+ value = max(minValue, min(maxValue, value));
+
+ if (value == valueNumber)
+ return;
+
+ valueNumber = value;
+ fireOnChange();
+}
+
+const TCHAR * SkinOption::getValueText() const
+{
+ return valueText.c_str();
+}
+
+void SkinOption::setValueText(const TCHAR * value)
+{
+ if (valueText == value)
+ return;
+
+ valueText = value;
+ fireOnChange();
+}
+
+void SkinOption::setOnChangeCallback(SkinOptionCallback cb, void *param /*= NULL*/)
+{
+ onChangeCallback = cb;
+ onChangeCallbackParam = param;
+}
+
+void SkinOption::fireOnChange()
+{
+ if (onChangeCallback != NULL)
+ onChangeCallback(onChangeCallbackParam, this);
+}
+
+
+
+SkinOptions::SkinOptions()
+ : onAddRemoveCallback(NULL), onAddRemoveCallbackParam(NULL),
+ onChangeCallback(NULL), onChangeCallbackParam(NULL)
+{
+}
+
+SkinOptions::~SkinOptions()
+{
+ for(unsigned int i = 0; i < options.size(); i++)
+ delete options[i];
+ options.clear();
+}
+
+bool SkinOptions::addOption(SkinOption *opt)
+{
+ _ASSERT(opt != NULL);
+ _ASSERT(opt->getName() != NULL);
+
+ if (getOption(opt->getName()) != NULL)
+ return false;
+
+ opt->setOnChangeCallback(onChangeCallback, onChangeCallbackParam);
+ options.push_back(opt);
+
+ fireOnAddRemove(opt);
+ return true;
+}
+
+SkinOption * SkinOptions::getOption(const char *name) const
+{
+ _ASSERT(name != NULL);
+
+ for(unsigned int i = 0; i < options.size(); i++)
+ {
+ SkinOption *opt = options[i];
+ if (strcmp(opt->getName(), name) == 0)
+ return opt;
+ }
+ return NULL;
+}
+
+SkinOption * SkinOptions::getOption(unsigned int pos) const
+{
+ if (pos >= options.size())
+ return NULL;
+ return options[pos];
+}
+
+unsigned int SkinOptions::getNumOptions() const
+{
+ return options.size();
+}
+
+void SkinOptions::clearOptions()
+{
+ if (options.size() <= 0)
+ return;
+
+ for(unsigned int i = 0; i < options.size(); i++)
+ {
+ fireOnAddRemove(options[i]);
+ delete options[i];
+ }
+ options.clear();
+}
+
+void SkinOptions::setOnOptionAddRemoveCallback(SkinOptionCallback cb, void *param /*= NULL*/)
+{
+ onAddRemoveCallback = cb;
+ onAddRemoveCallbackParam = param;
+}
+
+void SkinOptions::setOnOptionChangeCallback(SkinOptionCallback cb, void *param /*= NULL*/)
+{
+ onChangeCallback = cb;
+ onChangeCallbackParam = param;
+
+ for(unsigned int i = 0; i < options.size(); i++)
+ options[i]->setOnChangeCallback(cb, param);
+}
+
+void SkinOptions::fireOnAddRemove(SkinOption *opt)
+{
+ if (onAddRemoveCallback != NULL)
+ onAddRemoveCallback(onAddRemoveCallbackParam, opt);
+}
diff --git a/plugins/Skins/SkinLib/SkinOptions.h b/plugins/Skins/SkinLib/SkinOptions.h
new file mode 100644
index 0000000000..41d238a5a1
--- /dev/null
+++ b/plugins/Skins/SkinLib/SkinOptions.h
@@ -0,0 +1,98 @@
+#ifndef __SKINNED_DIALOG_OPTIONS_H__
+# define __SKINNED_DIALOG_OPTIONS_H__
+
+#include <windows.h>
+#include "tstring.h"
+#include <vector>
+
+
+enum SkinOptionType
+{
+ CHECKBOX,
+ NUMBER,
+ TEXT
+};
+
+class SkinOption;
+
+typedef void (*SkinOptionCallback)(void *param, const SkinOption *opt);
+
+
+class SkinOption
+{
+public:
+ SkinOption(const char *name);
+ ~SkinOption();
+
+ const char * getName() const;
+
+ SkinOptionType getType() const;
+ void setType(SkinOptionType type);
+
+ const TCHAR * getDescription() const;
+ void setDescription(const TCHAR * description);
+
+ int getMax() const;
+ void setMax(int max);
+
+ int getMin() const;
+ void setMin(int min);
+
+ bool getValueCheckbox() const;
+ void setValueCheckbox(bool value);
+
+ int getValueNumber() const;
+ void setValueNumber(int value);
+
+ const TCHAR * getValueText() const;
+ void setValueText(const TCHAR * value);
+
+ void setOnChangeCallback(SkinOptionCallback cb, void *param = NULL);
+
+private:
+ std::string name;
+ SkinOptionType type;
+ std::tstring description;
+ bool valueCheckbox;
+ int valueNumber;
+ int minValue;
+ int maxValue;
+ std::tstring valueText;
+
+ SkinOptionCallback onChangeCallback;
+ void * onChangeCallbackParam;
+
+ void fireOnChange();
+};
+
+
+class SkinOptions
+{
+public:
+ SkinOptions();
+ ~SkinOptions();
+
+ bool addOption(SkinOption *opt);
+ SkinOption * getOption(const char *name) const;
+ SkinOption * getOption(unsigned int pos) const;
+ unsigned int getNumOptions() const;
+ void clearOptions();
+
+ void setOnOptionAddRemoveCallback(SkinOptionCallback cb, void *param = NULL);
+ void setOnOptionChangeCallback(SkinOptionCallback cb, void *param = NULL);
+
+private:
+ std::vector<SkinOption *> options;
+
+ SkinOptionCallback onAddRemoveCallback;
+ void * onAddRemoveCallbackParam;
+
+ SkinOptionCallback onChangeCallback;
+ void * onChangeCallbackParam;
+
+ void fireOnAddRemove(SkinOption *opt);
+};
+
+
+
+#endif // __SKINNED_DIALOG_OPTIONS_H__
diff --git a/plugins/Skins/SkinLib/SkinnedDialog.cpp b/plugins/Skins/SkinLib/SkinnedDialog.cpp
new file mode 100644
index 0000000000..917193ad94
--- /dev/null
+++ b/plugins/Skins/SkinLib/SkinnedDialog.cpp
@@ -0,0 +1,235 @@
+#include "globals.h"
+#include "SkinnedDialog.h"
+
+#include <sys/stat.h>
+#include "V8Script.h"
+#include <utf8_helpers.h>
+#include "SkinOptions.h"
+
+
+SkinnedDialog::SkinnedDialog(const char *name)
+ : Dialog(name), fileChangedTime(0),
+ script(NULL), state(NULL), opts(NULL), defaultState(NULL),
+ errorCallback(NULL), errorCallbackParam(NULL),
+ traceCallback(NULL), traceCallbackParam(NULL)
+{
+ V8Script::initializeEngine();
+}
+
+SkinnedDialog::~SkinnedDialog()
+{
+ releaseState();
+ releaseCompiledScript();
+}
+
+const TCHAR * SkinnedDialog::getFilename() const
+{
+ return filename.c_str();
+}
+
+void SkinnedDialog::setFilename(const TCHAR *filename)
+{
+ if (this->filename == filename)
+ return;
+
+ this->filename = filename;
+ releaseState();
+ releaseCompiledScript();
+}
+
+bool SkinnedDialog::addField(Field *field)
+{
+ if (Dialog::addField(field))
+ {
+ releaseCompiledScript();
+ releaseState();
+ field->setOnChangeCallback(SkinnedDialog::staticOnFieldChange, this);
+ return true;
+ }
+ else
+ return false;
+}
+
+void SkinnedDialog::setSize(const Size &size)
+{
+ if (getSize() == size)
+ return;
+
+ Dialog::setSize(size);
+ releaseState();
+}
+
+int SkinnedDialog::compile()
+{
+ if (!fileChanged())
+ return 1;
+
+ releaseCompiledScript();
+
+ struct _stat st = {0};
+ if (_tstat(filename.c_str(), &st) != 0)
+ return 0;
+
+ std::tstring text;
+ readFile(text);
+ if (text.size() <= 0)
+ return 0;
+
+ script = new V8Script();
+ script->setExceptionCallback(errorCallback, errorCallbackParam);
+
+ if (!script->compile(text.c_str(), this))
+ {
+ releaseCompiledScript();
+ return 0;
+ }
+
+ std::pair<SkinOptions *,DialogState *> pair = script->configure(this);
+ opts = pair.first;
+ defaultState = pair.second;
+ if (opts == NULL)
+ {
+ releaseCompiledScript();
+ return 0;
+ }
+
+ fileChangedTime = st.st_mtime;
+
+ return 2;
+}
+
+DialogState * SkinnedDialog::getState()
+{
+ if (state != NULL && !fileChanged())
+ return state;
+
+ releaseState();
+
+ if (filename.size() <= 0)
+ return NULL;
+
+ if (!compile())
+ return NULL;
+
+ state = Dialog::createState();
+ if (!script->run(state, opts, getInfo()))
+ {
+ releaseState();
+ return NULL;
+ }
+
+ return state;
+}
+
+void SkinnedDialog::releaseCompiledScript()
+{
+ delete script;
+ script = NULL;
+ fileChangedTime = 0;
+
+ delete opts;
+ opts = NULL;
+
+ delete defaultState;
+ defaultState = NULL;
+}
+
+void SkinnedDialog::releaseState()
+{
+ delete state;
+ state = NULL;
+}
+
+bool SkinnedDialog::fileChanged()
+{
+ if (filename.size() <= 0)
+ return false;
+
+ struct _stat st = {0};
+ if (_tstat(filename.c_str(), &st) != 0)
+ return false;
+
+ return st.st_mtime > fileChangedTime;
+}
+
+void SkinnedDialog::readFile(std::tstring &ret)
+{
+ FILE* file = _tfopen(filename.c_str(), _T("rb"));
+ if (file == NULL)
+ return;
+
+ fseek(file, 0, SEEK_END);
+ int size = ftell(file);
+ rewind(file);
+
+ char* chars = new char[size + 1];
+ chars[size] = '\0';
+ for (int i = 0; i < size;)
+ {
+ int read = fread(&chars[i], 1, size - i, file);
+ i += read;
+ }
+ fclose(file);
+
+ ret = Utf8ToTchar(chars);
+
+ delete[] chars;
+}
+
+void SkinnedDialog::onFieldChange(const Field *field)
+{
+ releaseState();
+}
+
+
+void SkinnedDialog::staticOnFieldChange(void *param, const Field *field)
+{
+ _ASSERT(param != NULL);
+ _ASSERT(field != NULL);
+
+ SkinnedDialog *skdlg = (SkinnedDialog *) param;
+ skdlg->onFieldChange(field);
+}
+
+void SkinnedDialog::setErrorCallback(MessageCallback cb, void *param /*= NULL*/)
+{
+ errorCallback = cb;
+ errorCallbackParam = param;
+}
+
+void SkinnedDialog::setTraceCallback(MessageCallback cb, void *param /*= NULL*/)
+{
+ traceCallback = cb;
+ traceCallbackParam = param;
+}
+
+void SkinnedDialog::trace(TCHAR *msg, ...)
+{
+ if (traceCallback == NULL)
+ return;
+
+ TCHAR buff[1024];
+ memset(buff, 0, sizeof(buff));
+
+ va_list args;
+ va_start(args, msg);
+
+ _vsntprintf(buff, MAX_REGS(buff) - 1, msg, args);
+ buff[MAX_REGS(buff) - 1] = 0;
+
+ va_end(args);
+
+ traceCallback(traceCallbackParam, buff);
+}
+
+SkinOptions * SkinnedDialog::getOpts()
+{
+ compile();
+ return opts;
+}
+
+DialogState * SkinnedDialog::getDefaultState()
+{
+ compile();
+ return defaultState;
+} \ No newline at end of file
diff --git a/plugins/Skins/SkinLib/SkinnedDialog.h b/plugins/Skins/SkinLib/SkinnedDialog.h
new file mode 100644
index 0000000000..1387082f44
--- /dev/null
+++ b/plugins/Skins/SkinLib/SkinnedDialog.h
@@ -0,0 +1,89 @@
+#ifndef __SKINNED_DIALOG_H__
+# define __SKINNED_DIALOG_H__
+
+#include <windows.h>
+#include <tchar.h>
+#include "tstring.h"
+
+#include "Dialog.h"
+#include "ButtonField.h"
+#include "EditField.h"
+#include "IconField.h"
+#include "ImageField.h"
+#include "LabelField.h"
+#include "TextField.h"
+
+#include "DialogState.h"
+#include "BorderState.h"
+#include "ButtonFieldState.h"
+#include "EditFieldState.h"
+#include "FontState.h"
+#include "IconFieldState.h"
+#include "ImageFieldState.h"
+#include "LabelFieldState.h"
+#include "TextFieldState.h"
+
+#include "SkinOptions.h"
+
+class V8Script;
+
+
+typedef void (*MessageCallback)(void *param, const TCHAR *err);
+
+
+
+class SkinnedDialog : public Dialog
+{
+public:
+ SkinnedDialog(const char *name);
+ virtual ~SkinnedDialog();
+
+ virtual const TCHAR * getFilename() const;
+ virtual void setFilename(const TCHAR *filename);
+
+ virtual bool addField(Field *field);
+
+ virtual void setSize(const Size &size);
+
+ /// Return the cached state. Do not free the result.
+ /// Each call to this method can potentially create the state, so don't cache it.
+ virtual DialogState * getState();
+
+ virtual void setErrorCallback(MessageCallback cb, void *param = NULL);
+ virtual void setTraceCallback(MessageCallback cb, void *param = NULL);
+
+ virtual SkinOptions * getOpts();
+ virtual DialogState * getDefaultState();
+
+protected:
+ virtual bool fileChanged();
+ virtual int compile(); /// @return 0 error, 1 no change, 2 compiled
+
+ virtual void trace(TCHAR *msg, ...);
+
+ virtual void onFieldChange(const Field *field);
+
+private:
+ std::tstring filename;
+ __time64_t fileChangedTime;
+ V8Script *script;
+ DialogState *state;
+ SkinOptions *opts;
+ DialogState *defaultState;
+
+ MessageCallback errorCallback;
+ void *errorCallbackParam;
+ MessageCallback traceCallback;
+ void *traceCallbackParam;
+
+ void releaseCompiledScript();
+ void releaseState();
+ void readFile(std::tstring &ret);
+
+ static void staticOnFieldChange(void *param, const Field *field);
+};
+
+
+
+
+#endif // __SKINNED_DIALOG_H__
diff --git a/plugins/Skins/SkinLib/TextField.cpp b/plugins/Skins/SkinLib/TextField.cpp
new file mode 100644
index 0000000000..d3841b98fd
--- /dev/null
+++ b/plugins/Skins/SkinLib/TextField.cpp
@@ -0,0 +1,78 @@
+#include "globals.h"
+#include "TextField.h"
+#include "TextFieldState.h"
+
+
+TextField::TextField(Dialog *dlg, const char *name)
+ : Field(dlg, name), hFont(NULL), fontColor(RGB(0,0,0))
+{
+}
+
+
+TextField::~TextField()
+{
+}
+
+
+FieldType TextField::getType() const
+{
+ return SIMPLE_TEXT;
+}
+
+
+void TextField::setText(const TCHAR *text)
+{
+ if (this->text == text)
+ return;
+
+ this->text = text;
+ fireOnChange();
+}
+
+
+const TCHAR * TextField::getText() const
+{
+ return text.c_str();
+}
+
+
+void TextField::setFont(HFONT hFont)
+{
+ if (this->hFont == hFont)
+ return;
+
+ this->hFont = hFont;
+ fireOnChange();
+}
+
+
+HFONT TextField::getFont() const
+{
+ if (hFont != NULL)
+ return hFont;
+
+ // The default is the GUI font
+ return (HFONT) GetStockObject(DEFAULT_GUI_FONT);
+}
+
+
+COLORREF TextField::getFontColor() const
+{
+ return fontColor;
+}
+
+
+void TextField::setFontColor(COLORREF color)
+{
+ if (fontColor == color)
+ return;
+
+ fontColor = color;
+ fireOnChange();
+}
+
+
+FieldState * TextField::createState(DialogState *dialogState)
+{
+ return new TextFieldState(dialogState, this);
+}
diff --git a/plugins/Skins/SkinLib/TextField.h b/plugins/Skins/SkinLib/TextField.h
new file mode 100644
index 0000000000..8d2291f876
--- /dev/null
+++ b/plugins/Skins/SkinLib/TextField.h
@@ -0,0 +1,35 @@
+#ifndef __TEXT_FIELD_H__
+# define __TEXT_FIELD_H__
+
+#include "Field.h"
+
+
+class TextField : public Field
+{
+public:
+ TextField(Dialog *dlg, const char *name);
+ virtual ~TextField();
+
+ virtual FieldType getType() const;
+
+ virtual const TCHAR * getText() const;
+ virtual void setText(const TCHAR *text);
+
+ virtual HFONT getFont() const;
+ virtual void setFont(HFONT hFont);
+
+ virtual COLORREF getFontColor() const;
+ virtual void setFontColor(COLORREF color);
+
+ virtual FieldState * createState(DialogState *dialogState);
+
+private:
+ std::tstring text;
+ HFONT hFont;
+ COLORREF fontColor;
+
+};
+
+
+
+#endif // __TEXT_FIELD_H__
diff --git a/plugins/Skins/SkinLib/TextFieldState.cpp b/plugins/Skins/SkinLib/TextFieldState.cpp
new file mode 100644
index 0000000000..8e295d01ee
--- /dev/null
+++ b/plugins/Skins/SkinLib/TextFieldState.cpp
@@ -0,0 +1,65 @@
+#include "globals.h"
+#include "TextFieldState.h"
+
+
+TextFieldState::TextFieldState(DialogState *dialog, TextField *field)
+ : FieldState(dialog, field), font(field->getFont(), field->getFontColor()), textSet(false)
+{
+}
+
+TextFieldState::~TextFieldState()
+{
+}
+
+TextField * TextFieldState::getField() const
+{
+ return (TextField *) FieldState::getField();
+}
+
+
+Size TextFieldState::getPreferedSize() const
+{
+ HDC hdc = CreateCompatibleDC(NULL);
+
+ HFONT newFont = getFont()->getHFONT();
+ HFONT oldFont = (HFONT) SelectObject(hdc, newFont);
+
+ RECT rc = {0};
+ const TCHAR *text = getText();
+ DrawText(hdc, text, -1, &rc, DT_CALCRECT | DT_NOPREFIX | DT_EXPANDTABS | DT_SINGLELINE);
+
+ SelectObject(hdc, oldFont);
+
+ DeleteDC(hdc);
+
+ return Size(rc.right - rc.left, rc.bottom - rc.top);
+}
+
+const TCHAR * TextFieldState::getText() const
+{
+ if (textSet)
+ return text.c_str();
+
+ return getField()->getText();
+}
+
+void TextFieldState::setText(const TCHAR *text)
+{
+ this->text = text;
+ textSet = true;
+}
+
+FontState * TextFieldState::getFont()
+{
+ return &font;
+}
+
+const FontState * TextFieldState::getFont() const
+{
+ return &font;
+}
+
+bool TextFieldState::isEmpty() const
+{
+ return lstrlen(getText()) <= 0;
+}
diff --git a/plugins/Skins/SkinLib/TextFieldState.h b/plugins/Skins/SkinLib/TextFieldState.h
new file mode 100644
index 0000000000..9779cfa569
--- /dev/null
+++ b/plugins/Skins/SkinLib/TextFieldState.h
@@ -0,0 +1,38 @@
+#ifndef __TEXT_FIELD_STATE_H__
+# define __TEXT_FIELD_STATE_H__
+
+#include "TextField.h"
+#include "FieldState.h"
+#include "FontState.h"
+
+
+class TextFieldState : public FieldState
+{
+public:
+ virtual ~TextFieldState();
+
+ virtual TextField * getField() const;
+
+ virtual Size getPreferedSize() const;
+
+ virtual const TCHAR * getText() const;
+ virtual void setText(const TCHAR *text);
+
+ virtual FontState * getFont();
+ virtual const FontState * getFont() const;
+
+ virtual bool isEmpty() const;
+
+private:
+ TextFieldState(DialogState *dialog, TextField *field);
+
+ FontState font;
+ BOOL textSet;
+ std::tstring text;
+
+
+ friend class TextField;
+};
+
+
+#endif // __TEXT_FIELD_STATE_H__ \ No newline at end of file
diff --git a/plugins/Skins/SkinLib/TextFieldState_v8_wrapper.cpp b/plugins/Skins/SkinLib/TextFieldState_v8_wrapper.cpp
new file mode 100644
index 0000000000..cf11fdb01f
--- /dev/null
+++ b/plugins/Skins/SkinLib/TextFieldState_v8_wrapper.cpp
@@ -0,0 +1,59 @@
+#include "globals.h"
+#include "TextFieldState_v8_wrapper.h"
+#include <v8.h>
+#include "TextFieldState.h"
+#include <utf8_helpers.h>
+
+using namespace v8;
+
+
+#ifdef UNICODE
+# define V8_TCHAR uint16_t
+#else
+# define V8_TCHAR char
+#endif
+
+
+static Handle<Value> Get_TextFieldState_text(Local<String> property, const AccessorInfo &info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return scope.Close( Undefined() );
+
+ TextFieldState *tmp = (TextFieldState *) wrap->Value();
+ if (tmp == NULL)
+ return scope.Close( Undefined() );
+
+ return scope.Close( String::New((const V8_TCHAR *) tmp->getText()) );
+}
+
+static void Set_TextFieldState_text(Local<String> property, Local<Value> value, const AccessorInfo& info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return;
+
+ TextFieldState *tmp = (TextFieldState *) wrap->Value();
+ if (tmp == NULL)
+ return;
+
+ if (!value.IsEmpty() && value->IsString())
+ {
+ String::Utf8Value utf8_value(value);
+ tmp->setText(Utf8ToTchar(*utf8_value));
+ }
+}
+
+
+void AddTextFieldStateAcessors(Handle<ObjectTemplate> &templ)
+{
+ HandleScope scope;
+
+ templ->SetAccessor(String::New("text"), Get_TextFieldState_text, Set_TextFieldState_text);
+}
diff --git a/plugins/Skins/SkinLib/TextFieldState_v8_wrapper.h b/plugins/Skins/SkinLib/TextFieldState_v8_wrapper.h
new file mode 100644
index 0000000000..c5d9e48a80
--- /dev/null
+++ b/plugins/Skins/SkinLib/TextFieldState_v8_wrapper.h
@@ -0,0 +1,10 @@
+#ifndef __TEXT_FIELD_STATE_V8_WRAPPER_H__
+# define __TEXT_FIELD_STATE_V8_WRAPPER_H__
+
+#include <v8.h>
+
+void AddTextFieldStateAcessors(v8::Handle<v8::ObjectTemplate> &templ);
+
+
+
+#endif // __TEXT_FIELD_STATE_V8_WRAPPER_H__
diff --git a/plugins/Skins/SkinLib/V8Script.cpp b/plugins/Skins/SkinLib/V8Script.cpp
new file mode 100644
index 0000000000..c7619187a5
--- /dev/null
+++ b/plugins/Skins/SkinLib/V8Script.cpp
@@ -0,0 +1,236 @@
+#include "globals.h"
+#include "V8Script.h"
+#include "V8Wrappers.h"
+
+#include <utf8_helpers.h>
+
+using namespace v8;
+
+#ifdef UNICODE
+# define V8_TCHAR uint16_t
+#else
+# define V8_TCHAR char
+#endif
+
+
+V8Wrappers *wrappers = NULL;
+
+
+void V8Script::initializeEngine()
+{
+ if (wrappers != NULL)
+ return;
+
+ wrappers = new V8Wrappers();
+}
+
+
+V8Script::V8Script() : exceptionCallback(NULL), exceptionCallbackParam(NULL)
+{
+}
+
+V8Script::~V8Script()
+{
+ dispose();
+}
+
+bool V8Script::compile(const TCHAR *source, Dialog *dlg)
+{
+ dispose();
+
+ HandleScope handle_scope;
+
+ context = Context::New(NULL, wrappers->getGlobalTemplate());
+
+ Context::Scope context_scope(context);
+
+ context->Global()->Set(String::New("window"), wrappers->newDialogState(), ReadOnly);
+ context->Global()->Set(String::New("opts"), wrappers->newOptions(), ReadOnly);
+ context->Global()->Set(String::New("info"), wrappers->newDialogInfo(), ReadOnly);
+ for(unsigned int i = 0; i < dlg->getFieldCount(); i++)
+ {
+ Field *field = dlg->getField(i);
+ context->Global()->Set(String::New(field->getName()), wrappers->newState(field->getType()), ReadOnly);
+ }
+
+ TryCatch try_catch;
+ Local<Script> script = Script::Compile(String::New((const V8_TCHAR *) source), String::New(dlg->getName()));
+ if (script.IsEmpty())
+ {
+ reportException(&try_catch);
+ dispose();
+ return false;
+ }
+
+ // Run once to get the functions
+ Handle<Value> result = script->Run();
+ if (script.IsEmpty())
+ {
+ reportException(&try_catch);
+ dispose();
+ return false;
+ }
+
+ Handle<Value> configureFunction = context->Global()->Get(String::New("configure"));
+ if (!configureFunction.IsEmpty() && !configureFunction->IsFunction())
+ configureFunction.Clear();
+
+ Handle<Value> drawFunction = context->Global()->Get(String::New("draw"));
+ if (drawFunction.IsEmpty() || !drawFunction->IsFunction())
+ {
+ dispose();
+ return false;
+ }
+
+ this->configureFunction = Persistent<Function>::New(Handle<Function>::Cast(configureFunction));
+ this->drawFunction = Persistent<Function>::New(Handle<Function>::Cast(drawFunction));
+
+ return true;
+}
+
+void V8Script::dispose()
+{
+ context.Dispose();
+ configureFunction.Dispose();
+ drawFunction.Dispose();
+
+ context.Clear();
+ configureFunction.Clear();
+ drawFunction.Clear();
+}
+
+bool V8Script::isValid()
+{
+ return !context.IsEmpty() && !drawFunction.IsEmpty();
+}
+
+static Handle<Object> get(Handle<Object> obj, const char *field)
+{
+ HandleScope scope;
+
+ Local<Value> v = obj->Get(String::New(field));
+ _ASSERT(!v.IsEmpty());
+ _ASSERT(!v->IsUndefined());
+ _ASSERT(v->IsObject());
+
+ return scope.Close( Handle<Object>::Cast(v) );
+}
+
+void V8Script::fillWrappers(DialogState *state, SkinOptions *opts, DialogInfo *info, bool configure)
+{
+ Local<Object> global = context->Global();
+ wrappers->fillOptions(get(global, "opts"), opts, configure);
+ wrappers->fillDialogState(get(global, "window"), state);
+ wrappers->fillDialogInfo(get(global, "info"), info);
+ for(unsigned int i = 0; i < state->fields.size(); i++)
+ {
+ FieldState *field = state->fields[i];
+ wrappers->fillState(get(global, field->getField()->getName()), field);
+ }
+}
+
+std::pair<SkinOptions *,DialogState *> V8Script::configure(Dialog *dlg)
+{
+ if (!isValid())
+ return std::pair<SkinOptions *,DialogState *>(NULL, NULL);
+
+ SkinOptions *opts = new SkinOptions();
+ DialogState *state = dlg->createState();
+
+ if (!configureFunction.IsEmpty())
+ {
+ HandleScope handle_scope;
+
+ Context::Scope context_scope(context);
+
+ fillWrappers(state, opts, dlg->getInfo(), true);
+
+ TryCatch try_catch;
+ Handle<Value> result = configureFunction->Call(context->Global(), 0, NULL);
+ if (result.IsEmpty())
+ {
+ reportException(&try_catch);
+ delete opts;
+ delete state;
+ return std::pair<SkinOptions *,DialogState *>(NULL, NULL);;
+ }
+ }
+
+ return std::pair<SkinOptions *,DialogState *>(opts, state);
+}
+
+bool V8Script::run(DialogState * state, SkinOptions *opts, DialogInfo *info)
+{
+ if (!isValid())
+ return false;
+
+ HandleScope handle_scope;
+
+ Context::Scope context_scope(context);
+
+ fillWrappers(state, opts, info, false);
+
+ TryCatch try_catch;
+ Handle<Value> result = drawFunction->Call(context->Global(), 0, NULL);
+ if (result.IsEmpty())
+ {
+ reportException(&try_catch);
+ return false;
+ }
+
+ return true;
+}
+
+void V8Script::setExceptionCallback(ExceptionCallback cb, void *param)
+{
+ exceptionCallback = cb;
+ exceptionCallbackParam = param;
+}
+
+void V8Script::reportException(v8::TryCatch *try_catch)
+{
+ std::string err;
+ char tmp[1024];
+
+ HandleScope handle_scope;
+ String::Utf8Value exception(try_catch->Exception());
+ Handle<Message> message = try_catch->Message();
+ if (message.IsEmpty())
+ {
+ // V8 didn't provide any extra information about this error; just
+ // print the exception.
+ _snprintf(tmp, 1024, "%s\n", *exception);
+ err += tmp;
+ }
+ else
+ {
+ // Print (filename):(line number): (message).
+ String::Utf8Value filename(message->GetScriptResourceName());
+ int linenum = message->GetLineNumber();
+ _snprintf(tmp, 1024, "%s:%i: %s\n", *filename, linenum, *exception);
+ err += tmp;
+
+ // Print line of source code.
+ String::Utf8Value sourceline(message->GetSourceLine());
+ _snprintf(tmp, 1024, "%s\n", *sourceline);
+ err += tmp;
+
+ // Print wavy underline (GetUnderline is deprecated).
+ int start = message->GetStartColumn();
+ for (int i = 0; i < start; i++) {
+ err += " ";
+ }
+ int end = message->GetEndColumn();
+ for (int i = start; i < end; i++) {
+ err += "^";
+ }
+ err += "\n";
+ }
+
+ Utf8ToTchar tcharErr(err.c_str());
+
+ OutputDebugString(tcharErr);
+
+ if (exceptionCallback != NULL)
+ exceptionCallback(exceptionCallbackParam, tcharErr);
+}
diff --git a/plugins/Skins/SkinLib/V8Script.h b/plugins/Skins/SkinLib/V8Script.h
new file mode 100644
index 0000000000..b7e1f3f2a6
--- /dev/null
+++ b/plugins/Skins/SkinLib/V8Script.h
@@ -0,0 +1,46 @@
+#ifndef __V8_SCRIPT_H__
+# define __V8_SCRIPT_H__
+
+#include <v8.h>
+#include <utility>
+#include "V8Wrappers.h"
+
+
+typedef void (*ExceptionCallback)(void *param, const TCHAR *err);
+
+
+class V8Script
+{
+public:
+ static void initializeEngine();
+
+
+ V8Script();
+ ~V8Script();
+
+ bool compile(const TCHAR *source, Dialog *dlg);
+ void dispose();
+
+ bool isValid();
+
+ std::pair<SkinOptions *,DialogState *> configure(Dialog *dlg);
+
+ bool run(DialogState * state, SkinOptions *opts, DialogInfo *info);
+
+ void setExceptionCallback(ExceptionCallback cb, void *param = NULL);
+
+private:
+ v8::Persistent<v8::Context> context;
+ v8::Persistent<v8::Function> configureFunction;
+ v8::Persistent<v8::Function> drawFunction;
+
+ ExceptionCallback exceptionCallback;
+ void *exceptionCallbackParam;
+
+ void reportException(v8::TryCatch *try_catch);
+ void fillWrappers(DialogState *state, SkinOptions *opts, DialogInfo *info, bool configure);
+};
+
+
+
+#endif // __V8_SCRIPT_H__
diff --git a/plugins/Skins/SkinLib/V8Templates.cpp b/plugins/Skins/SkinLib/V8Templates.cpp
new file mode 100644
index 0000000000..4900e13772
--- /dev/null
+++ b/plugins/Skins/SkinLib/V8Templates.cpp
@@ -0,0 +1,475 @@
+#include "globals.h"
+#include <v8.h>
+#include "V8Templates.h"
+#include "DialogState_v8_wrapper.h"
+#include "FieldState_v8_wrapper.h"
+#include "ControlFieldState_v8_wrapper.h"
+#include "TextFieldState_v8_wrapper.h"
+#include "FontState_v8_wrapper.h"
+#include "BorderState_v8_wrapper.h"
+#include "SkinOption_v8_wrapper.h"
+
+using namespace v8;
+
+
+V8Templates::V8Templates()
+{
+}
+
+V8Templates::~V8Templates()
+{
+ dialogStateTemplate.Dispose();
+ fieldStateTemplate.Dispose();
+ controlFieldStateTemplate.Dispose();
+ textFieldStateTemplate.Dispose();
+ fontStateTemplate.Dispose();
+ borderStateTemplate.Dispose();
+ skinOptionTemplate.Dispose();
+}
+
+
+Handle<ObjectTemplate> V8Templates::getGlobalTemplate()
+{
+ HandleScope scope;
+
+ if (!globalTemplate.IsEmpty())
+ return globalTemplate;
+
+ Handle<ObjectTemplate> templ = ObjectTemplate::New();
+ templ->Set(String::New("HORIZONTAL_ALIGN_LEFT"), String::New("HORIZONTAL_ALIGN_LEFT"));
+ templ->Set(String::New("LEFT"), String::New("HORIZONTAL_ALIGN_LEFT"));
+ templ->Set(String::New("HORIZONTAL_ALIGN_CENTER"), String::New("HORIZONTAL_ALIGN_CENTER"));
+ templ->Set(String::New("CENTER"), String::New("HORIZONTAL_ALIGN_CENTER"));
+ templ->Set(String::New("HORIZONTAL_ALIGN_RIGHT"), String::New("HORIZONTAL_ALIGN_RIGHT"));
+ templ->Set(String::New("RIGHT"), String::New("HORIZONTAL_ALIGN_RIGHT"));
+ templ->Set(String::New("VERTICAL_ALIGN_TOP"), String::New("VERTICAL_ALIGN_TOP"));
+ templ->Set(String::New("TOP"), String::New("VERTICAL_ALIGN_TOP"));
+ templ->Set(String::New("VERTICAL_ALIGN_CENTER"), String::New("VERTICAL_ALIGN_CENTER"));
+ templ->Set(String::New("CENTER"), String::New("VERTICAL_ALIGN_CENTER"));
+ templ->Set(String::New("VERTICAL_ALIGN_BOTTOM"), String::New("VERTICAL_ALIGN_BOTTOM"));
+ templ->Set(String::New("BOTTOM"), String::New("VERTICAL_ALIGN_BOTTOM"));
+ templ->Set(String::New("CHECKBOX"), String::New("CHECKBOX"));
+ templ->Set(String::New("NUMBER"), String::New("NUMBER"));
+ templ->Set(String::New("TEXT"), String::New("TEXT"));
+ addGlobalTemplateFields(templ);
+
+ globalTemplate = Persistent<ObjectTemplate>::New(templ);
+
+ return globalTemplate;
+}
+
+
+void V8Templates::addGlobalTemplateFields(Handle<ObjectTemplate> &templ)
+{
+}
+
+
+int V8Templates::numOfDialogStateInternalFields()
+{
+ return 1;
+}
+
+Handle<ObjectTemplate> V8Templates::getDialogStateTemplate()
+{
+ HandleScope scope;
+
+ if (!dialogStateTemplate.IsEmpty())
+ return dialogStateTemplate;
+
+ Handle<ObjectTemplate> templ = ObjectTemplate::New();
+ templ->SetInternalFieldCount(numOfDialogStateInternalFields());
+ AddDialogStateAcessors(templ);
+ addDialogStateTemplateFields(templ);
+
+ dialogStateTemplate = Persistent<ObjectTemplate>::New(templ);
+
+ return dialogStateTemplate;
+}
+
+void V8Templates::addDialogStateTemplateFields(Handle<ObjectTemplate> &templ)
+{
+}
+
+Handle<Object> V8Templates::newDialogState()
+{
+ HandleScope scope;
+
+ Handle<Object> obj = getDialogStateTemplate()->NewInstance();
+ obj->Set(String::New("bordersRaw"), newBorderState(), ReadOnly);
+
+ return scope.Close(obj);
+}
+
+void V8Templates::fillDialogState(Handle<Object> v8Obj, DialogState *obj)
+{
+ HandleScope scope;
+
+ _ASSERT(!v8Obj.IsEmpty());
+
+ v8Obj->SetInternalField(0, External::New(obj));
+ fillBorderState(Handle<Object>::Cast(v8Obj->Get(String::New("bordersRaw"))), obj->getBorders());
+}
+
+
+int V8Templates::numOfFieldStateInternalFields()
+{
+ return 1;
+}
+
+Handle<ObjectTemplate> V8Templates::getFieldStateTemplate()
+{
+ HandleScope scope;
+
+ if (!fieldStateTemplate.IsEmpty())
+ return fieldStateTemplate;
+
+ Handle<ObjectTemplate> templ = ObjectTemplate::New();
+ templ->SetInternalFieldCount(numOfFieldStateInternalFields());
+ AddFieldStateAcessors(templ);
+ addFieldStateTemplateFields(templ);
+
+ fieldStateTemplate = Persistent<ObjectTemplate>::New(templ);
+
+ return fieldStateTemplate;
+}
+
+void V8Templates::addFieldStateTemplateFields(Handle<ObjectTemplate> &templ)
+{
+}
+
+Handle<Object> V8Templates::newFieldState()
+{
+ HandleScope scope;
+
+ Handle<Object> obj = getFieldStateTemplate()->NewInstance();
+ obj->Set(String::New("bordersRaw"), newBorderState(), ReadOnly);
+
+ return scope.Close(obj);
+}
+
+void V8Templates::fillFieldState(Handle<Object> v8Obj, FieldState *obj)
+{
+ HandleScope scope;
+
+ _ASSERT(!v8Obj.IsEmpty());
+
+ v8Obj->SetInternalField(0, External::New(obj));
+ fillBorderState(Handle<Object>::Cast(v8Obj->Get(String::New("bordersRaw"))), obj->getBorders());
+}
+
+
+int V8Templates::numOfControlFieldStateInternalFields()
+{
+ return 1;
+}
+
+Handle<ObjectTemplate> V8Templates::getControlFieldStateTemplate()
+{
+ HandleScope scope;
+
+ if (!controlFieldStateTemplate.IsEmpty())
+ return controlFieldStateTemplate;
+
+ Handle<ObjectTemplate> templ = ObjectTemplate::New();
+ templ->SetInternalFieldCount(numOfControlFieldStateInternalFields());
+ AddFieldStateAcessors(templ);
+ AddControlFieldStateAcessors(templ);
+ addControlFieldStateTemplateFields(templ);
+
+ controlFieldStateTemplate = Persistent<ObjectTemplate>::New(templ);
+
+ return controlFieldStateTemplate;
+}
+
+void V8Templates::addControlFieldStateTemplateFields(Handle<ObjectTemplate> &templ)
+{
+}
+
+Handle<Object> V8Templates::newControlFieldState()
+{
+ HandleScope scope;
+
+ Handle<Object> obj = getControlFieldStateTemplate()->NewInstance();
+ obj->Set(String::New("bordersRaw"), newBorderState(), ReadOnly);
+ obj->Set(String::New("font"), newFontState(), ReadOnly);
+
+ return scope.Close(obj);
+}
+
+void V8Templates::fillControlFieldState(Handle<Object> v8Obj, ControlFieldState *obj)
+{
+ HandleScope scope;
+
+ _ASSERT(!v8Obj.IsEmpty());
+
+ v8Obj->SetInternalField(0, External::New(obj));
+ fillBorderState(Handle<Object>::Cast(v8Obj->Get(String::New("bordersRaw"))), obj->getBorders());
+ fillFontState(Handle<Object>::Cast(v8Obj->Get(String::New("font"))), obj->getFont());
+}
+
+
+Handle<ObjectTemplate> V8Templates::getLabelFieldStateTemplate()
+{
+ return getControlFieldStateTemplate();
+}
+
+Handle<Object> V8Templates::newLabelFieldState()
+{
+ return newControlFieldState();
+}
+
+void V8Templates::fillLabelFieldState(Handle<Object> v8Obj, LabelFieldState *obj)
+{
+ fillControlFieldState(v8Obj, obj);
+}
+
+
+Handle<ObjectTemplate> V8Templates::getButtonFieldStateTemplate()
+{
+ return getControlFieldStateTemplate();
+}
+
+Handle<Object> V8Templates::newButtonFieldState()
+{
+ return newControlFieldState();
+}
+
+void V8Templates::fillButtonFieldState(Handle<Object> v8Obj, ButtonFieldState *obj)
+{
+ fillControlFieldState(v8Obj, obj);
+}
+
+
+Handle<ObjectTemplate> V8Templates::getEditFieldStateTemplate()
+{
+ return getControlFieldStateTemplate();
+}
+
+Handle<Object> V8Templates::newEditFieldState()
+{
+ return newControlFieldState();
+}
+
+void V8Templates::fillEditFieldState(Handle<Object> v8Obj, EditFieldState *obj)
+{
+ fillControlFieldState(v8Obj, obj);
+}
+
+
+Handle<ObjectTemplate> V8Templates::getIconFieldStateTemplate()
+{
+ return getFieldStateTemplate();
+}
+
+Handle<Object> V8Templates::newIconFieldState()
+{
+ return newFieldState();
+}
+
+void V8Templates::fillIconFieldState(Handle<Object> v8Obj, IconFieldState *obj)
+{
+ fillFieldState(v8Obj, obj);
+}
+
+
+Handle<ObjectTemplate> V8Templates::getImageFieldStateTemplate()
+{
+ return getFieldStateTemplate();
+}
+
+Handle<Object> V8Templates::newImageFieldState()
+{
+ return newFieldState();
+}
+
+void V8Templates::fillImageFieldState(Handle<Object> v8Obj, ImageFieldState *obj)
+{
+ fillFieldState(v8Obj, obj);
+}
+
+
+int V8Templates::numOfTextFieldStateInternalFields()
+{
+ return 1;
+}
+
+Handle<ObjectTemplate> V8Templates::getTextFieldStateTemplate()
+{
+ HandleScope scope;
+
+ if (!textFieldStateTemplate.IsEmpty())
+ return textFieldStateTemplate;
+
+ Handle<ObjectTemplate> templ = ObjectTemplate::New();
+ templ->SetInternalFieldCount(numOfTextFieldStateInternalFields());
+ AddFieldStateAcessors(templ);
+ AddTextFieldStateAcessors(templ);
+ addTextFieldStateTemplateFields(templ);
+
+ textFieldStateTemplate = Persistent<ObjectTemplate>::New(templ);
+
+ return textFieldStateTemplate;
+}
+
+void V8Templates::addTextFieldStateTemplateFields(Handle<ObjectTemplate> &templ)
+{
+}
+
+Handle<Object> V8Templates::newTextFieldState()
+{
+ HandleScope scope;
+
+ Handle<Object> obj = getTextFieldStateTemplate()->NewInstance();
+ obj->Set(String::New("bordersRaw"), newBorderState(), ReadOnly);
+ obj->Set(String::New("font"), newFontState(), ReadOnly);
+
+ return scope.Close(obj);
+}
+
+void V8Templates::fillTextFieldState(Handle<Object> v8Obj, TextFieldState *obj)
+{
+ HandleScope scope;
+
+ _ASSERT(!v8Obj.IsEmpty());
+
+ v8Obj->SetInternalField(0, External::New(obj));
+ fillBorderState(Handle<Object>::Cast(v8Obj->Get(String::New("bordersRaw"))), obj->getBorders());
+ fillFontState(Handle<Object>::Cast(v8Obj->Get(String::New("font"))), obj->getFont());
+}
+
+
+int V8Templates::numOfFontStateInternalFields()
+{
+ return 1;
+}
+
+Handle<ObjectTemplate> V8Templates::getFontStateTemplate()
+{
+ HandleScope scope;
+
+ if (!fontStateTemplate.IsEmpty())
+ return fontStateTemplate;
+
+ Handle<ObjectTemplate> templ = ObjectTemplate::New();
+ templ->SetInternalFieldCount(numOfFontStateInternalFields());
+ AddFontStateAcessors(templ);
+ addFontStateTemplateFields(templ);
+
+ fontStateTemplate = Persistent<ObjectTemplate>::New(templ);
+
+ return fontStateTemplate;
+}
+
+void V8Templates::addFontStateTemplateFields(Handle<ObjectTemplate> &templ)
+{
+}
+
+Handle<Object> V8Templates::newFontState()
+{
+ HandleScope scope;
+
+ Handle<Object> obj = getFontStateTemplate()->NewInstance();
+
+ return scope.Close(obj);
+}
+
+void V8Templates::fillFontState(Handle<Object> v8Obj, FontState *obj)
+{
+ HandleScope scope;
+
+ _ASSERT(!v8Obj.IsEmpty());
+
+ v8Obj->SetInternalField(0, External::New(obj));
+}
+
+
+int V8Templates::numOfBorderStateInternalFields()
+{
+ return 1;
+}
+
+Handle<ObjectTemplate> V8Templates::getBorderStateTemplate()
+{
+ HandleScope scope;
+
+ if (!borderStateTemplate.IsEmpty())
+ return borderStateTemplate;
+
+ Handle<ObjectTemplate> templ = ObjectTemplate::New();
+ templ->SetInternalFieldCount(numOfBorderStateInternalFields());
+ AddBorderStateAcessors(templ);
+ addBorderStateTemplateFields(templ);
+
+ borderStateTemplate = Persistent<ObjectTemplate>::New(templ);
+
+ return borderStateTemplate;
+}
+
+void V8Templates::addBorderStateTemplateFields(Handle<ObjectTemplate> &templ)
+{
+}
+
+Handle<Object> V8Templates::newBorderState()
+{
+ HandleScope scope;
+
+ Handle<Object> obj = getBorderStateTemplate()->NewInstance();
+
+ return scope.Close(obj);
+}
+
+void V8Templates::fillBorderState(Handle<Object> v8Obj, BorderState *obj)
+{
+ HandleScope scope;
+
+ _ASSERT(!v8Obj.IsEmpty());
+
+ v8Obj->SetInternalField(0, External::New(obj));
+}
+
+
+int V8Templates::numOfSkinOptionInternalFields()
+{
+ return 1;
+}
+
+Handle<ObjectTemplate> V8Templates::getSkinOptionTemplate()
+{
+ HandleScope scope;
+
+ if (!skinOptionTemplate.IsEmpty())
+ return skinOptionTemplate;
+
+ Handle<ObjectTemplate> templ = ObjectTemplate::New();
+ templ->SetInternalFieldCount(numOfSkinOptionInternalFields());
+ AddSkinOptionAcessors(templ);
+ addSkinOptionTemplateFields(templ);
+
+ skinOptionTemplate = Persistent<ObjectTemplate>::New(templ);
+
+ return skinOptionTemplate;
+}
+
+void V8Templates::addSkinOptionTemplateFields(Handle<ObjectTemplate> &templ)
+{
+}
+
+Handle<Object> V8Templates::newSkinOption()
+{
+ HandleScope scope;
+
+ Handle<Object> obj = getSkinOptionTemplate()->NewInstance();
+
+ return scope.Close(obj);
+}
+
+void V8Templates::fillSkinOption(Handle<Object> v8Obj, SkinOption *obj)
+{
+ HandleScope scope;
+
+ _ASSERT(!v8Obj.IsEmpty());
+
+ v8Obj->SetInternalField(0, External::New(obj));
+}
+
+
diff --git a/plugins/Skins/SkinLib/V8Templates.h b/plugins/Skins/SkinLib/V8Templates.h
new file mode 100644
index 0000000000..38590fe844
--- /dev/null
+++ b/plugins/Skins/SkinLib/V8Templates.h
@@ -0,0 +1,114 @@
+#ifndef __V8_TEMPLATES_H__
+# define __V8_TEMPLATES_H__
+
+#include <v8.h>
+#include "DialogState.h"
+#include "FieldState.h"
+#include "ControlFieldState.h"
+#include "LabelFieldState.h"
+#include "ButtonFieldState.h"
+#include "EditFieldState.h"
+#include "IconFieldState.h"
+#include "ImageFieldState.h"
+#include "TextFieldState.h"
+#include "FontState.h"
+#include "BorderState.h"
+#include "SkinOption.h"
+
+
+class V8Templates
+{
+public:
+ V8Templates();
+ virtual ~V8Templates();
+
+ virtual v8::Handle<v8::ObjectTemplate> getGlobalTemplate();
+
+ virtual v8::Handle<v8::ObjectTemplate> getDialogStateTemplate();
+ virtual v8::Handle<v8::Object> newDialogState();
+ virtual void fillDialogState(v8::Handle<v8::Object> v8Obj, DialogState *obj);
+
+ virtual v8::Handle<v8::ObjectTemplate> getFieldStateTemplate();
+ virtual v8::Handle<v8::Object> newFieldState();
+ virtual void fillFieldState(v8::Handle<v8::Object> v8Obj, FieldState *obj);
+
+ virtual v8::Handle<v8::ObjectTemplate> getControlFieldStateTemplate();
+ virtual v8::Handle<v8::Object> newControlFieldState();
+ virtual void fillControlFieldState(v8::Handle<v8::Object> v8Obj, ControlFieldState *obj);
+
+ virtual v8::Handle<v8::ObjectTemplate> getLabelFieldStateTemplate();
+ virtual v8::Handle<v8::Object> newLabelFieldState();
+ virtual void fillLabelFieldState(v8::Handle<v8::Object> v8Obj, LabelFieldState *obj);
+
+ virtual v8::Handle<v8::ObjectTemplate> getButtonFieldStateTemplate();
+ virtual v8::Handle<v8::Object> newButtonFieldState();
+ virtual void fillButtonFieldState(v8::Handle<v8::Object> v8Obj, ButtonFieldState *obj);
+
+ virtual v8::Handle<v8::ObjectTemplate> getEditFieldStateTemplate();
+ virtual v8::Handle<v8::Object> newEditFieldState();
+ virtual void fillEditFieldState(v8::Handle<v8::Object> v8Obj, EditFieldState *obj);
+
+ virtual v8::Handle<v8::ObjectTemplate> getIconFieldStateTemplate();
+ virtual v8::Handle<v8::Object> newIconFieldState();
+ virtual void fillIconFieldState(v8::Handle<v8::Object> v8Obj, IconFieldState *obj);
+
+ virtual v8::Handle<v8::ObjectTemplate> getImageFieldStateTemplate();
+ virtual v8::Handle<v8::Object> newImageFieldState();
+ virtual void fillImageFieldState(v8::Handle<v8::Object> v8Obj, ImageFieldState *obj);
+
+ virtual v8::Handle<v8::ObjectTemplate> getTextFieldStateTemplate();
+ virtual v8::Handle<v8::Object> newTextFieldState();
+ virtual void fillTextFieldState(v8::Handle<v8::Object> v8Obj, TextFieldState *obj);
+
+ virtual v8::Handle<v8::ObjectTemplate> getFontStateTemplate();
+ virtual v8::Handle<v8::Object> newFontState();
+ virtual void fillFontState(v8::Handle<v8::Object> v8Obj, FontState *obj);
+
+ virtual v8::Handle<v8::ObjectTemplate> getBorderStateTemplate();
+ virtual v8::Handle<v8::Object> newBorderState();
+ virtual void fillBorderState(v8::Handle<v8::Object> v8Obj, BorderState *obj);
+
+ virtual v8::Handle<v8::ObjectTemplate> getSkinOptionTemplate();
+ virtual v8::Handle<v8::Object> newSkinOption();
+ virtual void fillSkinOption(v8::Handle<v8::Object> v8Obj, SkinOption *obj);
+
+
+private:
+ v8::Persistent<v8::ObjectTemplate> globalTemplate;
+ v8::Persistent<v8::ObjectTemplate> dialogStateTemplate;
+ v8::Persistent<v8::ObjectTemplate> fieldStateTemplate;
+ v8::Persistent<v8::ObjectTemplate> controlFieldStateTemplate;
+ v8::Persistent<v8::ObjectTemplate> textFieldStateTemplate;
+ v8::Persistent<v8::ObjectTemplate> fontStateTemplate;
+ v8::Persistent<v8::ObjectTemplate> borderStateTemplate;
+ v8::Persistent<v8::ObjectTemplate> skinOptionTemplate;
+
+protected:
+ virtual void addGlobalTemplateFields(v8::Handle<v8::ObjectTemplate> &templ);
+
+ virtual int numOfDialogStateInternalFields();
+ virtual void addDialogStateTemplateFields(v8::Handle<v8::ObjectTemplate> &templ);
+
+ virtual int numOfFieldStateInternalFields();
+ virtual void addFieldStateTemplateFields(v8::Handle<v8::ObjectTemplate> &templ);
+
+ virtual int numOfControlFieldStateInternalFields();
+ virtual void addControlFieldStateTemplateFields(v8::Handle<v8::ObjectTemplate> &templ);
+
+ virtual int numOfTextFieldStateInternalFields();
+ virtual void addTextFieldStateTemplateFields(v8::Handle<v8::ObjectTemplate> &templ);
+
+ virtual int numOfFontStateInternalFields();
+ virtual void addFontStateTemplateFields(v8::Handle<v8::ObjectTemplate> &templ);
+
+ virtual int numOfBorderStateInternalFields();
+ virtual void addBorderStateTemplateFields(v8::Handle<v8::ObjectTemplate> &templ);
+
+ virtual int numOfSkinOptionInternalFields();
+ virtual void addSkinOptionTemplateFields(v8::Handle<v8::ObjectTemplate> &templ);
+
+};
+
+
+
+#endif // __V8_TEMPLATES_H__
diff --git a/plugins/Skins/SkinLib/V8Wrappers.cpp b/plugins/Skins/SkinLib/V8Wrappers.cpp
new file mode 100644
index 0000000000..9384e3c8ad
--- /dev/null
+++ b/plugins/Skins/SkinLib/V8Wrappers.cpp
@@ -0,0 +1,385 @@
+#include "globals.h"
+#include "V8Wrappers.h"
+
+#include <utf8_helpers.h>
+
+
+using namespace v8;
+
+
+#ifdef UNICODE
+# define V8_TCHAR uint16_t
+#else
+# define V8_TCHAR char
+#endif
+
+
+
+static Handle<Value> IsEmptyCallback(const Arguments& args)
+{
+ HandleScope scope;
+
+ if (args.Length() < 1)
+ return scope.Close( Undefined() );
+
+ for(int i = 0; i < args.Length(); i++)
+ {
+ Local<Value> arg = args[0];
+
+ if (arg.IsEmpty() || arg->IsNull() || arg->IsUndefined())
+ {
+ return scope.Close( Boolean::New(true) );
+ }
+ else if (arg->IsObject())
+ {
+ Local<Object> self = Local<Object>::Cast(arg);
+ if (self->InternalFieldCount() < 1)
+ continue;
+
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ FieldState *field = (FieldState *) wrap->Value();
+ if (field == NULL)
+ continue;
+
+ if (field->isEmpty())
+ return scope.Close( Boolean::New(true) );
+ }
+ else if (arg->IsString())
+ {
+ Local<String> str = Local<String>::Cast(arg);
+ if (str->Length() <= 0)
+ return scope.Close( Boolean::New(true) );
+ }
+ }
+
+ return scope.Close( Boolean::New(false) );
+}
+
+static Handle<Value> RGBCallback(const Arguments& args)
+{
+ HandleScope scope;
+
+ if (args.Length() != 3)
+ return scope.Close( Undefined() );
+
+ COLORREF color = RGB(args[0]->Int32Value(), args[1]->Int32Value(), args[2]->Int32Value());
+ return scope.Close( Int32::New(color) );
+}
+
+static Handle<Value> AlertCallback(const Arguments& args)
+{
+ HandleScope scope;
+
+ if (args.Length() < 1)
+ return scope.Close( Boolean::New(false) );
+
+ Local<Value> arg = args[0];
+ String::Utf8Value utf8_value(arg->ToDetailString());
+
+ char *tmp = *utf8_value;
+// TODO MessageBox(NULL, Utf8ToTchar(*utf8_value), _T("Skin alert"), MB_OK);
+
+ return scope.Close( Boolean::New(true) );
+}
+
+void V8Wrappers::addGlobalTemplateFields(Handle<ObjectTemplate> &templ)
+{
+ HandleScope scope;
+
+ templ->Set(String::New("IsEmpty"), FunctionTemplate::New(&IsEmptyCallback));
+ templ->Set(String::New("RGB"), FunctionTemplate::New(&RGBCallback));
+ templ->Set(String::New("alert"), FunctionTemplate::New(&AlertCallback));
+}
+
+
+Handle<Object> V8Wrappers::newState(FieldType type)
+{
+ switch(type)
+ {
+ case SIMPLE_TEXT:
+ return newTextFieldState();
+ case SIMPLE_IMAGE:
+ return newImageFieldState();
+ case SIMPLE_ICON:
+ return newIconFieldState();
+ case CONTROL_LABEL:
+ return newLabelFieldState();
+ case CONTROL_BUTTON:
+ return newButtonFieldState();
+ case CONTROL_EDIT:
+ return newEditFieldState();
+ }
+ throw "Unknown type";
+}
+
+void V8Wrappers::fillState(Handle<Object> obj, FieldState *state)
+{
+ switch(state->getField()->getType())
+ {
+ case SIMPLE_TEXT:
+ fillTextFieldState(obj, (TextFieldState *) state);
+ break;
+ case SIMPLE_IMAGE:
+ fillImageFieldState(obj, (ImageFieldState *) state);
+ break;
+ case SIMPLE_ICON:
+ fillIconFieldState(obj, (IconFieldState *) state);
+ break;
+ case CONTROL_LABEL:
+ fillLabelFieldState(obj, (LabelFieldState *) state);
+ break;
+ case CONTROL_BUTTON:
+ fillButtonFieldState(obj, (ButtonFieldState *) state);
+ break;
+ case CONTROL_EDIT:
+ fillEditFieldState(obj, (EditFieldState *) state);
+ break;
+ default:
+ throw "Unknown type";
+ }
+}
+
+static Handle<Value> Get_SkinOption_value(SkinOption *opt)
+{
+ HandleScope scope;
+
+ if (opt == NULL)
+ return scope.Close( Undefined() );
+
+ switch (opt->getType())
+ {
+ case CHECKBOX: return scope.Close( Boolean::New(opt->getValueCheckbox()) );
+ case NUMBER: return scope.Close( Int32::New(opt->getValueNumber()) );
+ case TEXT: return scope.Close( String::New((const V8_TCHAR *) opt->getValueText()) );
+ }
+
+ return scope.Close( Undefined() );
+}
+
+static Handle<Value> Get_Options_Fields(Local<String> aName, const AccessorInfo &info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return scope.Close( Undefined() );
+
+ SkinOptions *opts = (SkinOptions *) wrap->Value();
+ if (opts == NULL)
+ return scope.Close( Undefined() );
+
+ String::AsciiValue name(aName);
+ if (name.length() <= 0)
+ return scope.Close( Undefined() );
+
+ bool configure = self->GetInternalField(1)->BooleanValue();
+ if (configure)
+ {
+ SkinOption * opt = opts->getOption(*name);
+
+ if (opt == NULL)
+ {
+ opt = new SkinOption(*name);
+ opts->addOption(opt);
+ }
+
+ wrap = Local<External>::Cast(info.Data());
+ if (wrap.IsEmpty())
+ return scope.Close( Undefined() );
+
+ V8Wrappers *wrappers = (V8Wrappers *) wrap->Value();
+ if (wrappers == NULL)
+ return scope.Close( Undefined() );
+
+ Handle<Object> ret = wrappers->newSkinOption();
+ wrappers->fillSkinOption(ret, opt);
+ return scope.Close( ret );
+ }
+ else
+ {
+ SkinOption * opt = opts->getOption(*name);
+ return scope.Close( Get_SkinOption_value(opt) );
+ }
+}
+
+Handle<ObjectTemplate> V8Wrappers::getOptionsTemplate()
+{
+ HandleScope scope;
+
+ if (!optionsTemplate.IsEmpty())
+ return optionsTemplate;
+
+ Handle<ObjectTemplate> templ = ObjectTemplate::New();
+ templ->SetInternalFieldCount(2);
+ templ->SetNamedPropertyHandler(&Get_Options_Fields, 0, 0, 0, 0, External::New(this));
+
+ optionsTemplate = Persistent<ObjectTemplate>::New(templ);
+
+ return optionsTemplate;
+}
+
+Handle<Object> V8Wrappers::newOptions()
+{
+ HandleScope scope;
+
+ Handle<Object> obj = getOptionsTemplate()->NewInstance();
+
+ return scope.Close(obj);
+}
+
+void V8Wrappers::fillOptions(Handle<Object> v8Obj, SkinOptions *obj, bool configure)
+{
+ HandleScope scope;
+
+ _ASSERT(!v8Obj.IsEmpty());
+
+ v8Obj->SetInternalField(0, External::New(obj));
+ v8Obj->SetInternalField(1, Boolean::New(configure));
+}
+
+
+static Handle<Value> Get_SkinOption_value(Local<String> property, const AccessorInfo &info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return scope.Close( Undefined() );
+
+ return scope.Close( Get_SkinOption_value((SkinOption *) wrap->Value()) );
+}
+
+static void Set_SkinOption_value(Local<String> property, Local<Value> value, const AccessorInfo& info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return;
+
+ SkinOption *opt = (SkinOption *) wrap->Value();
+ if (opt == NULL)
+ return;
+
+ switch (opt->getType())
+ {
+ case CHECKBOX:
+ if (!value.IsEmpty() && value->IsBoolean())
+ opt->setValueCheckbox(value->BooleanValue());
+ break;
+ case NUMBER:
+ if (!value.IsEmpty() && value->IsNumber())
+ opt->setValueNumber(value->Int32Value());
+ break;
+ case TEXT:
+ if (!value.IsEmpty() && value->IsString())
+ opt->setValueText(Utf8ToTchar(*String::Utf8Value(value)));
+ break;
+ }
+}
+
+void V8Wrappers::addSkinOptionTemplateFields(Handle<ObjectTemplate> &templ)
+{
+ HandleScope scope;
+
+ templ->SetAccessor(String::New("value"), Get_SkinOption_value, Set_SkinOption_value);
+}
+
+
+static Handle<Value> Get_DialogInfo_Fields(Local<String> aName, const AccessorInfo &info)
+{
+ HandleScope scope;
+
+ Local<Object> self = info.Holder();
+ Local<External> wrap = Local<External>::Cast(self->GetInternalField(0));
+ if (wrap.IsEmpty())
+ return scope.Close( Undefined() );
+
+ DialogInfo *dialogInfo = (DialogInfo *) wrap->Value();
+ if (dialogInfo == NULL)
+ return scope.Close( Undefined() );
+
+ String::AsciiValue name(aName);
+ if (name.length() <= 0)
+ return scope.Close( Undefined() );
+
+ wrap = Local<External>::Cast(info.Data());
+ if (wrap.IsEmpty())
+ return scope.Close( Undefined() );
+
+ V8Wrappers *wrappers = (V8Wrappers *) wrap->Value();
+ if (wrappers == NULL)
+ return scope.Close( Undefined() );
+
+ Local<String> aPrefix = Local<String>::Cast(self->GetInternalField(1));
+ if (aPrefix.IsEmpty())
+ return scope.Close( Undefined() );
+
+ String::AsciiValue prefix(aPrefix);
+
+ std::string var;
+ var += *prefix;
+ var += *name;
+
+ switch(dialogInfo->getType(var.c_str()))
+ {
+ case TYPE_VARIABLE:
+ {
+ var += '.';
+
+ Handle<Object> ret = wrappers->newDialogInfo();
+ wrappers->fillDialogInfo(ret, dialogInfo, var.c_str());
+ return scope.Close( ret );
+ }
+ case TYPE_INT:
+ return scope.Close( Int32::New(dialogInfo->getAsInt(var.c_str())) );
+ case TYPE_DOUBLE:
+ return scope.Close( Number::New(dialogInfo->getAsDouble(var.c_str())) );
+ case TYPE_BOOL:
+ return scope.Close( Boolean::New(dialogInfo->getAsBool(var.c_str())) );
+ case TYPE_STRING:
+ return scope.Close( String::New((const V8_TCHAR *) dialogInfo->getAsString(var.c_str())) );
+ case UNKNOWN:
+ default:
+ return scope.Close( Undefined() );
+ }
+}
+
+Handle<ObjectTemplate> V8Wrappers::getDialogInfoTemplate()
+{
+ HandleScope scope;
+
+ if (!dialogInfoTemplate.IsEmpty())
+ return dialogInfoTemplate;
+
+ Handle<ObjectTemplate> templ = ObjectTemplate::New();
+ templ->SetInternalFieldCount(2);
+ templ->SetNamedPropertyHandler(&Get_DialogInfo_Fields, 0, 0, 0, 0, External::New(this));
+
+ dialogInfoTemplate = Persistent<ObjectTemplate>::New(templ);
+
+ return dialogInfoTemplate;
+}
+
+Handle<Object> V8Wrappers::newDialogInfo()
+{
+ HandleScope scope;
+
+ Handle<Object> obj = getDialogInfoTemplate()->NewInstance();
+
+ return scope.Close(obj);
+}
+
+void V8Wrappers::fillDialogInfo(Handle<Object> v8Obj, DialogInfo *obj, const char *prefix)
+{
+ HandleScope scope;
+
+ _ASSERT(!v8Obj.IsEmpty());
+
+ v8Obj->SetInternalField(0, External::New(obj));
+
+ v8Obj->SetInternalField(1, String::New(prefix != NULL ? prefix : ""));
+}
diff --git a/plugins/Skins/SkinLib/V8Wrappers.h b/plugins/Skins/SkinLib/V8Wrappers.h
new file mode 100644
index 0000000000..b2c5eb2b92
--- /dev/null
+++ b/plugins/Skins/SkinLib/V8Wrappers.h
@@ -0,0 +1,35 @@
+#ifndef __V8_WRAPPERS_H__
+# define __V8_WRAPPERS_H__
+
+#include "V8Templates.h"
+#include "SkinOptions.h"
+
+
+class V8Wrappers : public V8Templates
+{
+public:
+ virtual v8::Handle<v8::Object> newState(FieldType type);
+ virtual void fillState(v8::Handle<v8::Object> obj, FieldState *state);
+
+ virtual v8::Handle<v8::ObjectTemplate> getOptionsTemplate();
+ virtual v8::Handle<v8::Object> newOptions();
+ virtual void fillOptions(v8::Handle<v8::Object> v8Obj, SkinOptions *obj, bool configure);
+
+ virtual v8::Handle<v8::ObjectTemplate> getDialogInfoTemplate();
+ virtual v8::Handle<v8::Object> newDialogInfo();
+ virtual void fillDialogInfo(v8::Handle<v8::Object> v8Obj, DialogInfo *obj, const char *prefix = NULL);
+
+private:
+ v8::Persistent<v8::ObjectTemplate> optionsTemplate;
+ v8::Persistent<v8::ObjectTemplate> dialogInfoTemplate;
+
+protected:
+ virtual void addGlobalTemplateFields(v8::Handle<v8::ObjectTemplate> &templ);
+
+ virtual void addSkinOptionTemplateFields(v8::Handle<v8::ObjectTemplate> &templ);
+
+};
+
+
+
+#endif // __V8_WRAPPERS_H__
diff --git a/plugins/Skins/SkinLib/globals.h b/plugins/Skins/SkinLib/globals.h
new file mode 100644
index 0000000000..18d6ffdcfc
--- /dev/null
+++ b/plugins/Skins/SkinLib/globals.h
@@ -0,0 +1,20 @@
+#ifndef __GLOBALS_H__
+# define __GLOBALS_H__
+
+#ifdef DEBUG
+#define _CRTDBG_MAP_ALLOC
+#include <stdlib.h>
+#include <crtdbg.h>
+#endif
+
+#include <windows.h>
+#include <newpluginapi.h>
+#include <m_system.h>
+#include <m_utils.h>
+#include <utf8_helpers.h>
+
+
+#define MAX_REGS(_X_) ( sizeof(_X_) / sizeof(_X_[0]) )
+
+
+#endif // __GLOBALS_H__ \ No newline at end of file
diff --git a/plugins/Skins/SkinLib/scope.h b/plugins/Skins/SkinLib/scope.h
new file mode 100644
index 0000000000..2fad797b88
--- /dev/null
+++ b/plugins/Skins/SkinLib/scope.h
@@ -0,0 +1,37 @@
+#ifndef __PTR_H__
+# define __PTR_H__
+
+
+template<class T>
+class scope
+{
+public:
+ scope() : p(NULL) {}
+ scope(T t) : p(t) {}
+ ~scope() { release(); }
+
+ void release()
+ {
+ if (p != NULL)
+ delete p;
+ p = NULL;
+ }
+
+ T operator=(T t) { release(); p = t; return t; }
+ T operator->() const { return p; }
+ operator T() const { return p; }
+
+ T detach()
+ {
+ T ret = p;
+ p = NULL;
+ return ret;
+ }
+
+private:
+ T p;
+};
+
+
+
+#endif // __PTR_H__
diff --git a/plugins/Skins/SkinLib/tstring.h b/plugins/Skins/SkinLib/tstring.h
new file mode 100644
index 0000000000..e6017176c5
--- /dev/null
+++ b/plugins/Skins/SkinLib/tstring.h
@@ -0,0 +1,13 @@
+#ifndef __TSTRING_H__
+# define __TSTRING_H__
+
+#include <tchar.h>
+#include <string>
+
+
+namespace std {
+ typedef basic_string<TCHAR, char_traits<TCHAR>, allocator<TCHAR>> tstring;
+}
+
+
+#endif // __TSTRING_H__
diff --git a/plugins/Skins/commons.h b/plugins/Skins/commons.h
new file mode 100644
index 0000000000..b31dbbebd2
--- /dev/null
+++ b/plugins/Skins/commons.h
@@ -0,0 +1,119 @@
+/*
+Copyright (C) 2008 Ricardo Pescuma Domenecci
+
+This is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this file; see the file license.txt. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef __COMMONS_H__
+# define __COMMONS_H__
+
+
+#define OEMRESOURCE
+#define _WIN32_WINNT 0x0400
+#include <windows.h>
+#include <tchar.h>
+#include <stdio.h>
+#include <time.h>
+#include <commctrl.h>
+
+
+// Disable "...truncated to '255' characters in the debug information" warnings
+#pragma warning(disable: 4786)
+
+#include <vector>
+#include <string>
+using namespace std;
+
+
+// Miranda headers
+#define MIRANDA_VER 0x0800
+#include <win2k.h>
+#include <newpluginapi.h>
+#include <m_system.h>
+#include <m_system_cpp.h>
+#include <m_protocols.h>
+#include <m_protosvc.h>
+#include <m_clist.h>
+#include <m_contacts.h>
+#include <m_langpack.h>
+#include <m_database.h>
+#include <m_options.h>
+#include <m_utils.h>
+#include <m_updater.h>
+#include <m_metacontacts.h>
+#include <m_popup.h>
+#include <m_history.h>
+#include <m_message.h>
+#include <m_folders.h>
+#include <m_icolib.h>
+#include <m_imgsrvc.h>
+#include <m_netlib.h>
+#include <m_fontservice.h>
+
+#include <mir_memory.h>
+#include <mir_options.h>
+#include <mir_icons.h>
+#include <mir_buffer.h>
+#include <utf8_helpers.h>
+
+#include "resource.h"
+#include "m_skins.h"
+#include "m_skins_cpp.h"
+#include "options.h"
+#include "MirandaSkinnedDialog.h"
+#include "MirandaField.h"
+#include "MirandaTextField.h"
+#include "MirandaIconField.h"
+#include "MirandaImageField.h"
+
+
+#define MODULE_NAME "Skins"
+
+#define DEFAULT_SKIN_NAME "Default"
+#define SKIN_EXTENSION "msk"
+
+
+// Global Variables
+extern HINSTANCE hInst;
+extern PLUGINLINK *pluginLink;
+extern FI_INTERFACE *fei;
+extern HANDLE hChangedEvent;
+
+#define MAX_REGS(_A_) ( sizeof(_A_) / sizeof(_A_[0]) )
+#define MIR_FREE(_X_) if (_X_ != NULL) { mir_free(_X_); _X_ = NULL; }
+
+
+extern TCHAR skinsFolder[1024];
+
+extern std::vector<MirandaSkinnedDialog *> dlgs;
+
+void getSkinnedDialogFilename(std::tstring &ret, const TCHAR *skin, const char *dialogName);
+void getAvaiableSkins(std::vector<std::tstring> &skins, MirandaSkinnedDialog *dlg = NULL);
+
+
+// See if a protocol service exists
+static __inline int ProtoServiceExists(const char *szModule,const char *szService)
+{
+ char str[MAXMODULELABELLENGTH];
+ strcpy(str,szModule);
+ strcat(str,szService);
+ return ServiceExists(str);
+}
+
+
+
+#endif // __COMMONS_H__
diff --git a/plugins/Skins/libs/v8-debug.h b/plugins/Skins/libs/v8-debug.h
new file mode 100644
index 0000000000..7da4f98a05
--- /dev/null
+++ b/plugins/Skins/libs/v8-debug.h
@@ -0,0 +1,384 @@
+// Copyright 2008 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_V8_DEBUG_H_
+#define V8_V8_DEBUG_H_
+
+#include "v8.h"
+
+#ifdef _WIN32
+typedef int int32_t;
+typedef unsigned int uint32_t;
+typedef unsigned short uint16_t; // NOLINT
+typedef long long int64_t; // NOLINT
+
+// Setup for Windows DLL export/import. See v8.h in this directory for
+// information on how to build/use V8 as a DLL.
+#if defined(BUILDING_V8_SHARED) && defined(USING_V8_SHARED)
+#error both BUILDING_V8_SHARED and USING_V8_SHARED are set - please check the\
+ build configuration to ensure that at most one of these is set
+#endif
+
+#ifdef BUILDING_V8_SHARED
+#define EXPORT __declspec(dllexport)
+#elif USING_V8_SHARED
+#define EXPORT __declspec(dllimport)
+#else
+#define EXPORT
+#endif
+
+#else // _WIN32
+
+// Setup for Linux shared library export. See v8.h in this directory for
+// information on how to build/use V8 as shared library.
+#if defined(__GNUC__) && (__GNUC__ >= 4) && defined(V8_SHARED)
+#define EXPORT __attribute__ ((visibility("default")))
+#else // defined(__GNUC__) && (__GNUC__ >= 4)
+#define EXPORT
+#endif // defined(__GNUC__) && (__GNUC__ >= 4)
+
+#endif // _WIN32
+
+
+/**
+ * Debugger support for the V8 JavaScript engine.
+ */
+namespace v8 {
+
+// Debug events which can occur in the V8 JavaScript engine.
+enum DebugEvent {
+ Break = 1,
+ Exception = 2,
+ NewFunction = 3,
+ BeforeCompile = 4,
+ AfterCompile = 5,
+ ScriptCollected = 6,
+ BreakForCommand = 7
+};
+
+
+class EXPORT Debug {
+ public:
+ /**
+ * A client object passed to the v8 debugger whose ownership will be taken by
+ * it. v8 is always responsible for deleting the object.
+ */
+ class ClientData {
+ public:
+ virtual ~ClientData() {}
+ };
+
+
+ /**
+ * A message object passed to the debug message handler.
+ */
+ class Message {
+ public:
+ /**
+ * Check type of message.
+ */
+ virtual bool IsEvent() const = 0;
+ virtual bool IsResponse() const = 0;
+ virtual DebugEvent GetEvent() const = 0;
+
+ /**
+ * Indicate whether this is a response to a continue command which will
+ * start the VM running after this is processed.
+ */
+ virtual bool WillStartRunning() const = 0;
+
+ /**
+ * Access to execution state and event data. Don't store these cross
+ * callbacks as their content becomes invalid. These objects are from the
+ * debugger event that started the debug message loop.
+ */
+ virtual Handle<Object> GetExecutionState() const = 0;
+ virtual Handle<Object> GetEventData() const = 0;
+
+ /**
+ * Get the debugger protocol JSON.
+ */
+ virtual Handle<String> GetJSON() const = 0;
+
+ /**
+ * Get the context active when the debug event happened. Note this is not
+ * the current active context as the JavaScript part of the debugger is
+ * running in it's own context which is entered at this point.
+ */
+ virtual Handle<Context> GetEventContext() const = 0;
+
+ /**
+ * Client data passed with the corresponding request if any. This is the
+ * client_data data value passed into Debug::SendCommand along with the
+ * request that led to the message or NULL if the message is an event. The
+ * debugger takes ownership of the data and will delete it even if there is
+ * no message handler.
+ */
+ virtual ClientData* GetClientData() const = 0;
+
+ virtual ~Message() {}
+ };
+
+
+ /**
+ * An event details object passed to the debug event listener.
+ */
+ class EventDetails {
+ public:
+ /**
+ * Event type.
+ */
+ virtual DebugEvent GetEvent() const = 0;
+
+ /**
+ * Access to execution state and event data of the debug event. Don't store
+ * these cross callbacks as their content becomes invalid.
+ */
+ virtual Handle<Object> GetExecutionState() const = 0;
+ virtual Handle<Object> GetEventData() const = 0;
+
+ /**
+ * Get the context active when the debug event happened. Note this is not
+ * the current active context as the JavaScript part of the debugger is
+ * running in it's own context which is entered at this point.
+ */
+ virtual Handle<Context> GetEventContext() const = 0;
+
+ /**
+ * Client data passed with the corresponding callbak whet it was registered.
+ */
+ virtual Handle<Value> GetCallbackData() const = 0;
+
+ /**
+ * Client data passed to DebugBreakForCommand function. The
+ * debugger takes ownership of the data and will delete it even if
+ * there is no message handler.
+ */
+ virtual ClientData* GetClientData() const = 0;
+
+ virtual ~EventDetails() {}
+ };
+
+
+ /**
+ * Debug event callback function.
+ *
+ * \param event the type of the debug event that triggered the callback
+ * (enum DebugEvent)
+ * \param exec_state execution state (JavaScript object)
+ * \param event_data event specific data (JavaScript object)
+ * \param data value passed by the user to SetDebugEventListener
+ */
+ typedef void (*EventCallback)(DebugEvent event,
+ Handle<Object> exec_state,
+ Handle<Object> event_data,
+ Handle<Value> data);
+
+ /**
+ * Debug event callback function.
+ *
+ * \param event_details object providing information about the debug event
+ *
+ * A EventCallback2 does not take possession of the event data,
+ * and must not rely on the data persisting after the handler returns.
+ */
+ typedef void (*EventCallback2)(const EventDetails& event_details);
+
+ /**
+ * Debug message callback function.
+ *
+ * \param message the debug message handler message object
+ * \param length length of the message
+ * \param client_data the data value passed when registering the message handler
+
+ * A MessageHandler does not take possession of the message string,
+ * and must not rely on the data persisting after the handler returns.
+ *
+ * This message handler is deprecated. Use MessageHandler2 instead.
+ */
+ typedef void (*MessageHandler)(const uint16_t* message, int length,
+ ClientData* client_data);
+
+ /**
+ * Debug message callback function.
+ *
+ * \param message the debug message handler message object
+
+ * A MessageHandler does not take possession of the message data,
+ * and must not rely on the data persisting after the handler returns.
+ */
+ typedef void (*MessageHandler2)(const Message& message);
+
+ /**
+ * Debug host dispatch callback function.
+ */
+ typedef void (*HostDispatchHandler)();
+
+ /**
+ * Callback function for the host to ensure debug messages are processed.
+ */
+ typedef void (*DebugMessageDispatchHandler)();
+
+ // Set a C debug event listener.
+ static bool SetDebugEventListener(EventCallback that,
+ Handle<Value> data = Handle<Value>());
+ static bool SetDebugEventListener2(EventCallback2 that,
+ Handle<Value> data = Handle<Value>());
+
+ // Set a JavaScript debug event listener.
+ static bool SetDebugEventListener(v8::Handle<v8::Object> that,
+ Handle<Value> data = Handle<Value>());
+
+ // Schedule a debugger break to happen when JavaScript code is run.
+ static void DebugBreak();
+
+ // Remove scheduled debugger break if it has not happened yet.
+ static void CancelDebugBreak();
+
+ // Break execution of JavaScript (this method can be invoked from a
+ // non-VM thread) for further client command execution on a VM
+ // thread. Client data is then passed in EventDetails to
+ // EventCallback at the moment when the VM actually stops.
+ static void DebugBreakForCommand(ClientData* data = NULL);
+
+ // Message based interface. The message protocol is JSON. NOTE the message
+ // handler thread is not supported any more parameter must be false.
+ static void SetMessageHandler(MessageHandler handler,
+ bool message_handler_thread = false);
+ static void SetMessageHandler2(MessageHandler2 handler);
+ static void SendCommand(const uint16_t* command, int length,
+ ClientData* client_data = NULL);
+
+ // Dispatch interface.
+ static void SetHostDispatchHandler(HostDispatchHandler handler,
+ int period = 100);
+
+ /**
+ * Register a callback function to be called when a debug message has been
+ * received and is ready to be processed. For the debug messages to be
+ * processed V8 needs to be entered, and in certain embedding scenarios this
+ * callback can be used to make sure V8 is entered for the debug message to
+ * be processed. Note that debug messages will only be processed if there is
+ * a V8 break. This can happen automatically by using the option
+ * --debugger-auto-break.
+ * \param provide_locker requires that V8 acquires v8::Locker for you before
+ * calling handler
+ */
+ static void SetDebugMessageDispatchHandler(
+ DebugMessageDispatchHandler handler, bool provide_locker = false);
+
+ /**
+ * Run a JavaScript function in the debugger.
+ * \param fun the function to call
+ * \param data passed as second argument to the function
+ * With this call the debugger is entered and the function specified is called
+ * with the execution state as the first argument. This makes it possible to
+ * get access to information otherwise not available during normal JavaScript
+ * execution e.g. details on stack frames. Receiver of the function call will
+ * be the debugger context global object, however this is a subject to change.
+ * The following example show a JavaScript function which when passed to
+ * v8::Debug::Call will return the current line of JavaScript execution.
+ *
+ * \code
+ * function frame_source_line(exec_state) {
+ * return exec_state.frame(0).sourceLine();
+ * }
+ * \endcode
+ */
+ static Local<Value> Call(v8::Handle<v8::Function> fun,
+ Handle<Value> data = Handle<Value>());
+
+ /**
+ * Returns a mirror object for the given object.
+ */
+ static Local<Value> GetMirror(v8::Handle<v8::Value> obj);
+
+ /**
+ * Enable the V8 builtin debug agent. The debugger agent will listen on the
+ * supplied TCP/IP port for remote debugger connection.
+ * \param name the name of the embedding application
+ * \param port the TCP/IP port to listen on
+ * \param wait_for_connection whether V8 should pause on a first statement
+ * allowing remote debugger to connect before anything interesting happened
+ */
+ static bool EnableAgent(const char* name, int port,
+ bool wait_for_connection = false);
+
+ /**
+ * Makes V8 process all pending debug messages.
+ *
+ * From V8 point of view all debug messages come asynchronously (e.g. from
+ * remote debugger) but they all must be handled synchronously: V8 cannot
+ * do 2 things at one time so normal script execution must be interrupted
+ * for a while.
+ *
+ * Generally when message arrives V8 may be in one of 3 states:
+ * 1. V8 is running script; V8 will automatically interrupt and process all
+ * pending messages (however auto_break flag should be enabled);
+ * 2. V8 is suspended on debug breakpoint; in this state V8 is dedicated
+ * to reading and processing debug messages;
+ * 3. V8 is not running at all or has called some long-working C++ function;
+ * by default it means that processing of all debug message will be deferred
+ * until V8 gets control again; however, embedding application may improve
+ * this by manually calling this method.
+ *
+ * It makes sense to call this method whenever a new debug message arrived and
+ * V8 is not already running. Method v8::Debug::SetDebugMessageDispatchHandler
+ * should help with the former condition.
+ *
+ * Technically this method in many senses is equivalent to executing empty
+ * script:
+ * 1. It does nothing except for processing all pending debug messages.
+ * 2. It should be invoked with the same precautions and from the same context
+ * as V8 script would be invoked from, because:
+ * a. with "evaluate" command it can do whatever normal script can do,
+ * including all native calls;
+ * b. no other thread should call V8 while this method is running
+ * (v8::Locker may be used here).
+ *
+ * "Evaluate" debug command behavior currently is not specified in scope
+ * of this method.
+ */
+ static void ProcessDebugMessages();
+
+ /**
+ * Debugger is running in it's own context which is entered while debugger
+ * messages are being dispatched. This is an explicit getter for this
+ * debugger context. Note that the content of the debugger context is subject
+ * to change.
+ */
+ static Local<Context> GetDebugContext();
+};
+
+
+} // namespace v8
+
+
+#undef EXPORT
+
+
+#endif // V8_V8_DEBUG_H_
diff --git a/plugins/Skins/libs/v8.h b/plugins/Skins/libs/v8.h
new file mode 100644
index 0000000000..9c9edf7292
--- /dev/null
+++ b/plugins/Skins/libs/v8.h
@@ -0,0 +1,3686 @@
+// Copyright 2007-2009 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following
+// disclaimer in the documentation and/or other materials provided
+// with the distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived
+// from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+/** \mainpage V8 API Reference Guide
+ *
+ * V8 is Google's open source JavaScript engine.
+ *
+ * This set of documents provides reference material generated from the
+ * V8 header file, include/v8.h.
+ *
+ * For other documentation see http://code.google.com/apis/v8/
+ */
+
+#ifndef V8_H_
+#define V8_H_
+
+#include <stdio.h>
+
+#ifdef _WIN32
+// When compiling on MinGW stdint.h is available.
+#ifdef __MINGW32__
+#include <stdint.h>
+#else // __MINGW32__
+typedef signed char int8_t;
+typedef unsigned char uint8_t;
+typedef short int16_t; // NOLINT
+typedef unsigned short uint16_t; // NOLINT
+typedef int int32_t;
+typedef unsigned int uint32_t;
+typedef __int64 int64_t;
+typedef unsigned __int64 uint64_t;
+// intptr_t and friends are defined in crtdefs.h through stdio.h.
+#endif // __MINGW32__
+
+// Setup for Windows DLL export/import. When building the V8 DLL the
+// BUILDING_V8_SHARED needs to be defined. When building a program which uses
+// the V8 DLL USING_V8_SHARED needs to be defined. When either building the V8
+// static library or building a program which uses the V8 static library neither
+// BUILDING_V8_SHARED nor USING_V8_SHARED should be defined.
+#if defined(BUILDING_V8_SHARED) && defined(USING_V8_SHARED)
+#error both BUILDING_V8_SHARED and USING_V8_SHARED are set - please check the\
+ build configuration to ensure that at most one of these is set
+#endif
+
+#ifdef BUILDING_V8_SHARED
+#define V8EXPORT __declspec(dllexport)
+#elif USING_V8_SHARED
+#define V8EXPORT __declspec(dllimport)
+#else
+#define V8EXPORT
+#endif // BUILDING_V8_SHARED
+
+#else // _WIN32
+
+#include <stdint.h>
+
+// Setup for Linux shared library export. There is no need to distinguish
+// between building or using the V8 shared library, but we should not
+// export symbols when we are building a static library.
+#if defined(__GNUC__) && (__GNUC__ >= 4) && defined(V8_SHARED)
+#define V8EXPORT __attribute__ ((visibility("default")))
+#else // defined(__GNUC__) && (__GNUC__ >= 4)
+#define V8EXPORT
+#endif // defined(__GNUC__) && (__GNUC__ >= 4)
+
+#endif // _WIN32
+
+/**
+ * The v8 JavaScript engine.
+ */
+namespace v8 {
+
+class Context;
+class String;
+class Value;
+class Utils;
+class Number;
+class Object;
+class Array;
+class Int32;
+class Uint32;
+class External;
+class Primitive;
+class Boolean;
+class Integer;
+class Function;
+class Date;
+class ImplementationUtilities;
+class Signature;
+template <class T> class Handle;
+template <class T> class Local;
+template <class T> class Persistent;
+class FunctionTemplate;
+class ObjectTemplate;
+class Data;
+class AccessorInfo;
+class StackTrace;
+class StackFrame;
+
+namespace internal {
+
+class Arguments;
+class Object;
+class Heap;
+class Top;
+
+}
+
+
+// --- W e a k H a n d l e s
+
+
+/**
+ * A weak reference callback function.
+ *
+ * This callback should either explicitly invoke Dispose on |object| if
+ * V8 wrapper is not needed anymore, or 'revive' it by invocation of MakeWeak.
+ *
+ * \param object the weak global object to be reclaimed by the garbage collector
+ * \param parameter the value passed in when making the weak global object
+ */
+typedef void (*WeakReferenceCallback)(Persistent<Value> object,
+ void* parameter);
+
+
+// --- H a n d l e s ---
+
+#define TYPE_CHECK(T, S) \
+ while (false) { \
+ *(static_cast<T* volatile*>(0)) = static_cast<S*>(0); \
+ }
+
+/**
+ * An object reference managed by the v8 garbage collector.
+ *
+ * All objects returned from v8 have to be tracked by the garbage
+ * collector so that it knows that the objects are still alive. Also,
+ * because the garbage collector may move objects, it is unsafe to
+ * point directly to an object. Instead, all objects are stored in
+ * handles which are known by the garbage collector and updated
+ * whenever an object moves. Handles should always be passed by value
+ * (except in cases like out-parameters) and they should never be
+ * allocated on the heap.
+ *
+ * There are two types of handles: local and persistent handles.
+ * Local handles are light-weight and transient and typically used in
+ * local operations. They are managed by HandleScopes. Persistent
+ * handles can be used when storing objects across several independent
+ * operations and have to be explicitly deallocated when they're no
+ * longer used.
+ *
+ * It is safe to extract the object stored in the handle by
+ * dereferencing the handle (for instance, to extract the Object* from
+ * an Handle<Object>); the value will still be governed by a handle
+ * behind the scenes and the same rules apply to these values as to
+ * their handles.
+ */
+template <class T> class Handle {
+ public:
+
+ /**
+ * Creates an empty handle.
+ */
+ inline Handle();
+
+ /**
+ * Creates a new handle for the specified value.
+ */
+ inline explicit Handle(T* val) : val_(val) { }
+
+ /**
+ * Creates a handle for the contents of the specified handle. This
+ * constructor allows you to pass handles as arguments by value and
+ * to assign between handles. However, if you try to assign between
+ * incompatible handles, for instance from a Handle<String> to a
+ * Handle<Number> it will cause a compiletime error. Assigning
+ * between compatible handles, for instance assigning a
+ * Handle<String> to a variable declared as Handle<Value>, is legal
+ * because String is a subclass of Value.
+ */
+ template <class S> inline Handle(Handle<S> that)
+ : val_(reinterpret_cast<T*>(*that)) {
+ /**
+ * This check fails when trying to convert between incompatible
+ * handles. For example, converting from a Handle<String> to a
+ * Handle<Number>.
+ */
+ TYPE_CHECK(T, S);
+ }
+
+ /**
+ * Returns true if the handle is empty.
+ */
+ inline bool IsEmpty() const { return val_ == 0; }
+
+ inline T* operator->() const { return val_; }
+
+ inline T* operator*() const { return val_; }
+
+ /**
+ * Sets the handle to be empty. IsEmpty() will then return true.
+ */
+ inline void Clear() { this->val_ = 0; }
+
+ /**
+ * Checks whether two handles are the same.
+ * Returns true if both are empty, or if the objects
+ * to which they refer are identical.
+ * The handles' references are not checked.
+ */
+ template <class S> inline bool operator==(Handle<S> that) const {
+ internal::Object** a = reinterpret_cast<internal::Object**>(**this);
+ internal::Object** b = reinterpret_cast<internal::Object**>(*that);
+ if (a == 0) return b == 0;
+ if (b == 0) return false;
+ return *a == *b;
+ }
+
+ /**
+ * Checks whether two handles are different.
+ * Returns true if only one of the handles is empty, or if
+ * the objects to which they refer are different.
+ * The handles' references are not checked.
+ */
+ template <class S> inline bool operator!=(Handle<S> that) const {
+ return !operator==(that);
+ }
+
+ template <class S> static inline Handle<T> Cast(Handle<S> that) {
+#ifdef V8_ENABLE_CHECKS
+ // If we're going to perform the type check then we have to check
+ // that the handle isn't empty before doing the checked cast.
+ if (that.IsEmpty()) return Handle<T>();
+#endif
+ return Handle<T>(T::Cast(*that));
+ }
+
+ template <class S> inline Handle<S> As() {
+ return Handle<S>::Cast(*this);
+ }
+
+ private:
+ T* val_;
+};
+
+
+/**
+ * A light-weight stack-allocated object handle. All operations
+ * that return objects from within v8 return them in local handles. They
+ * are created within HandleScopes, and all local handles allocated within a
+ * handle scope are destroyed when the handle scope is destroyed. Hence it
+ * is not necessary to explicitly deallocate local handles.
+ */
+template <class T> class Local : public Handle<T> {
+ public:
+ inline Local();
+ template <class S> inline Local(Local<S> that)
+ : Handle<T>(reinterpret_cast<T*>(*that)) {
+ /**
+ * This check fails when trying to convert between incompatible
+ * handles. For example, converting from a Handle<String> to a
+ * Handle<Number>.
+ */
+ TYPE_CHECK(T, S);
+ }
+ template <class S> inline Local(S* that) : Handle<T>(that) { }
+ template <class S> static inline Local<T> Cast(Local<S> that) {
+#ifdef V8_ENABLE_CHECKS
+ // If we're going to perform the type check then we have to check
+ // that the handle isn't empty before doing the checked cast.
+ if (that.IsEmpty()) return Local<T>();
+#endif
+ return Local<T>(T::Cast(*that));
+ }
+
+ template <class S> inline Local<S> As() {
+ return Local<S>::Cast(*this);
+ }
+
+ /** Create a local handle for the content of another handle.
+ * The referee is kept alive by the local handle even when
+ * the original handle is destroyed/disposed.
+ */
+ inline static Local<T> New(Handle<T> that);
+};
+
+
+/**
+ * An object reference that is independent of any handle scope. Where
+ * a Local handle only lives as long as the HandleScope in which it was
+ * allocated, a Persistent handle remains valid until it is explicitly
+ * disposed.
+ *
+ * A persistent handle contains a reference to a storage cell within
+ * the v8 engine which holds an object value and which is updated by
+ * the garbage collector whenever the object is moved. A new storage
+ * cell can be created using Persistent::New and existing handles can
+ * be disposed using Persistent::Dispose. Since persistent handles
+ * are passed by value you may have many persistent handle objects
+ * that point to the same storage cell. For instance, if you pass a
+ * persistent handle as an argument to a function you will not get two
+ * different storage cells but rather two references to the same
+ * storage cell.
+ */
+template <class T> class Persistent : public Handle<T> {
+ public:
+
+ /**
+ * Creates an empty persistent handle that doesn't point to any
+ * storage cell.
+ */
+ inline Persistent();
+
+ /**
+ * Creates a persistent handle for the same storage cell as the
+ * specified handle. This constructor allows you to pass persistent
+ * handles as arguments by value and to assign between persistent
+ * handles. However, attempting to assign between incompatible
+ * persistent handles, for instance from a Persistent<String> to a
+ * Persistent<Number> will cause a compiletime error. Assigning
+ * between compatible persistent handles, for instance assigning a
+ * Persistent<String> to a variable declared as Persistent<Value>,
+ * is allowed as String is a subclass of Value.
+ */
+ template <class S> inline Persistent(Persistent<S> that)
+ : Handle<T>(reinterpret_cast<T*>(*that)) {
+ /**
+ * This check fails when trying to convert between incompatible
+ * handles. For example, converting from a Handle<String> to a
+ * Handle<Number>.
+ */
+ TYPE_CHECK(T, S);
+ }
+
+ template <class S> inline Persistent(S* that) : Handle<T>(that) { }
+
+ /**
+ * "Casts" a plain handle which is known to be a persistent handle
+ * to a persistent handle.
+ */
+ template <class S> explicit inline Persistent(Handle<S> that)
+ : Handle<T>(*that) { }
+
+ template <class S> static inline Persistent<T> Cast(Persistent<S> that) {
+#ifdef V8_ENABLE_CHECKS
+ // If we're going to perform the type check then we have to check
+ // that the handle isn't empty before doing the checked cast.
+ if (that.IsEmpty()) return Persistent<T>();
+#endif
+ return Persistent<T>(T::Cast(*that));
+ }
+
+ template <class S> inline Persistent<S> As() {
+ return Persistent<S>::Cast(*this);
+ }
+
+ /**
+ * Creates a new persistent handle for an existing local or
+ * persistent handle.
+ */
+ inline static Persistent<T> New(Handle<T> that);
+
+ /**
+ * Releases the storage cell referenced by this persistent handle.
+ * Does not remove the reference to the cell from any handles.
+ * This handle's reference, and any any other references to the storage
+ * cell remain and IsEmpty will still return false.
+ */
+ inline void Dispose();
+
+ /**
+ * Make the reference to this object weak. When only weak handles
+ * refer to the object, the garbage collector will perform a
+ * callback to the given V8::WeakReferenceCallback function, passing
+ * it the object reference and the given parameters.
+ */
+ inline void MakeWeak(void* parameters, WeakReferenceCallback callback);
+
+ /** Clears the weak reference to this object.*/
+ inline void ClearWeak();
+
+ /**
+ *Checks if the handle holds the only reference to an object.
+ */
+ inline bool IsNearDeath() const;
+
+ /**
+ * Returns true if the handle's reference is weak.
+ */
+ inline bool IsWeak() const;
+
+ private:
+ friend class ImplementationUtilities;
+ friend class ObjectTemplate;
+};
+
+
+ /**
+ * A stack-allocated class that governs a number of local handles.
+ * After a handle scope has been created, all local handles will be
+ * allocated within that handle scope until either the handle scope is
+ * deleted or another handle scope is created. If there is already a
+ * handle scope and a new one is created, all allocations will take
+ * place in the new handle scope until it is deleted. After that,
+ * new handles will again be allocated in the original handle scope.
+ *
+ * After the handle scope of a local handle has been deleted the
+ * garbage collector will no longer track the object stored in the
+ * handle and may deallocate it. The behavior of accessing a handle
+ * for which the handle scope has been deleted is undefined.
+ */
+class V8EXPORT HandleScope {
+ public:
+ HandleScope();
+
+ ~HandleScope();
+
+ /**
+ * Closes the handle scope and returns the value as a handle in the
+ * previous scope, which is the new current scope after the call.
+ */
+ template <class T> Local<T> Close(Handle<T> value);
+
+ /**
+ * Counts the number of allocated handles.
+ */
+ static int NumberOfHandles();
+
+ /**
+ * Creates a new handle with the given value.
+ */
+ static internal::Object** CreateHandle(internal::Object* value);
+
+ private:
+ // Make it impossible to create heap-allocated or illegal handle
+ // scopes by disallowing certain operations.
+ HandleScope(const HandleScope&);
+ void operator=(const HandleScope&);
+ void* operator new(size_t size);
+ void operator delete(void*, size_t);
+
+ // This Data class is accessible internally as HandleScopeData through a
+ // typedef in the ImplementationUtilities class.
+ class V8EXPORT Data {
+ public:
+ int extensions;
+ internal::Object** next;
+ internal::Object** limit;
+ inline void Initialize() {
+ extensions = -1;
+ next = limit = NULL;
+ }
+ };
+
+ Data previous_;
+
+ // Allow for the active closing of HandleScopes which allows to pass a handle
+ // from the HandleScope being closed to the next top most HandleScope.
+ bool is_closed_;
+ internal::Object** RawClose(internal::Object** value);
+
+ friend class ImplementationUtilities;
+};
+
+
+// --- S p e c i a l o b j e c t s ---
+
+
+/**
+ * The superclass of values and API object templates.
+ */
+class V8EXPORT Data {
+ private:
+ Data();
+};
+
+
+/**
+ * Pre-compilation data that can be associated with a script. This
+ * data can be calculated for a script in advance of actually
+ * compiling it, and can be stored between compilations. When script
+ * data is given to the compile method compilation will be faster.
+ */
+class V8EXPORT ScriptData { // NOLINT
+ public:
+ virtual ~ScriptData() { }
+
+ /**
+ * Pre-compiles the specified script (context-independent).
+ *
+ * \param input Pointer to UTF-8 script source code.
+ * \param length Length of UTF-8 script source code.
+ */
+ static ScriptData* PreCompile(const char* input, int length);
+
+ /**
+ * Pre-compiles the specified script (context-independent).
+ *
+ * NOTE: Pre-compilation using this method cannot happen on another thread
+ * without using Lockers.
+ *
+ * \param source Script source code.
+ */
+ static ScriptData* PreCompile(Handle<String> source);
+
+ /**
+ * Load previous pre-compilation data.
+ *
+ * \param data Pointer to data returned by a call to Data() of a previous
+ * ScriptData. Ownership is not transferred.
+ * \param length Length of data.
+ */
+ static ScriptData* New(const char* data, int length);
+
+ /**
+ * Returns the length of Data().
+ */
+ virtual int Length() = 0;
+
+ /**
+ * Returns a serialized representation of this ScriptData that can later be
+ * passed to New(). NOTE: Serialized data is platform-dependent.
+ */
+ virtual const char* Data() = 0;
+
+ /**
+ * Returns true if the source code could not be parsed.
+ */
+ virtual bool HasError() = 0;
+};
+
+
+/**
+ * The origin, within a file, of a script.
+ */
+class ScriptOrigin {
+ public:
+ inline ScriptOrigin(
+ Handle<Value> resource_name,
+ Handle<Integer> resource_line_offset = Handle<Integer>(),
+ Handle<Integer> resource_column_offset = Handle<Integer>())
+ : resource_name_(resource_name),
+ resource_line_offset_(resource_line_offset),
+ resource_column_offset_(resource_column_offset) { }
+ inline Handle<Value> ResourceName() const;
+ inline Handle<Integer> ResourceLineOffset() const;
+ inline Handle<Integer> ResourceColumnOffset() const;
+ private:
+ Handle<Value> resource_name_;
+ Handle<Integer> resource_line_offset_;
+ Handle<Integer> resource_column_offset_;
+};
+
+
+/**
+ * A compiled JavaScript script.
+ */
+class V8EXPORT Script {
+ public:
+
+ /**
+ * Compiles the specified script (context-independent).
+ *
+ * \param source Script source code.
+ * \param origin Script origin, owned by caller, no references are kept
+ * when New() returns
+ * \param pre_data Pre-parsing data, as obtained by ScriptData::PreCompile()
+ * using pre_data speeds compilation if it's done multiple times.
+ * Owned by caller, no references are kept when New() returns.
+ * \param script_data Arbitrary data associated with script. Using
+ * this has same effect as calling SetData(), but allows data to be
+ * available to compile event handlers.
+ * \return Compiled script object (context independent; when run it
+ * will use the currently entered context).
+ */
+ static Local<Script> New(Handle<String> source,
+ ScriptOrigin* origin = NULL,
+ ScriptData* pre_data = NULL,
+ Handle<String> script_data = Handle<String>());
+
+ /**
+ * Compiles the specified script using the specified file name
+ * object (typically a string) as the script's origin.
+ *
+ * \param source Script source code.
+ * \param file_name file name object (typically a string) to be used
+ * as the script's origin.
+ * \return Compiled script object (context independent; when run it
+ * will use the currently entered context).
+ */
+ static Local<Script> New(Handle<String> source,
+ Handle<Value> file_name);
+
+ /**
+ * Compiles the specified script (bound to current context).
+ *
+ * \param source Script source code.
+ * \param origin Script origin, owned by caller, no references are kept
+ * when Compile() returns
+ * \param pre_data Pre-parsing data, as obtained by ScriptData::PreCompile()
+ * using pre_data speeds compilation if it's done multiple times.
+ * Owned by caller, no references are kept when Compile() returns.
+ * \param script_data Arbitrary data associated with script. Using
+ * this has same effect as calling SetData(), but makes data available
+ * earlier (i.e. to compile event handlers).
+ * \return Compiled script object, bound to the context that was active
+ * when this function was called. When run it will always use this
+ * context.
+ */
+ static Local<Script> Compile(Handle<String> source,
+ ScriptOrigin* origin = NULL,
+ ScriptData* pre_data = NULL,
+ Handle<String> script_data = Handle<String>());
+
+ /**
+ * Compiles the specified script using the specified file name
+ * object (typically a string) as the script's origin.
+ *
+ * \param source Script source code.
+ * \param file_name File name to use as script's origin
+ * \param script_data Arbitrary data associated with script. Using
+ * this has same effect as calling SetData(), but makes data available
+ * earlier (i.e. to compile event handlers).
+ * \return Compiled script object, bound to the context that was active
+ * when this function was called. When run it will always use this
+ * context.
+ */
+ static Local<Script> Compile(Handle<String> source,
+ Handle<Value> file_name,
+ Handle<String> script_data = Handle<String>());
+
+ /**
+ * Runs the script returning the resulting value. If the script is
+ * context independent (created using ::New) it will be run in the
+ * currently entered context. If it is context specific (created
+ * using ::Compile) it will be run in the context in which it was
+ * compiled.
+ */
+ Local<Value> Run();
+
+ /**
+ * Returns the script id value.
+ */
+ Local<Value> Id();
+
+ /**
+ * Associate an additional data object with the script. This is mainly used
+ * with the debugger as this data object is only available through the
+ * debugger API.
+ */
+ void SetData(Handle<String> data);
+};
+
+
+/**
+ * An error message.
+ */
+class V8EXPORT Message {
+ public:
+ Local<String> Get() const;
+ Local<String> GetSourceLine() const;
+
+ /**
+ * Returns the resource name for the script from where the function causing
+ * the error originates.
+ */
+ Handle<Value> GetScriptResourceName() const;
+
+ /**
+ * Returns the resource data for the script from where the function causing
+ * the error originates.
+ */
+ Handle<Value> GetScriptData() const;
+
+ /**
+ * Exception stack trace. By default stack traces are not captured for
+ * uncaught exceptions. SetCaptureStackTraceForUncaughtExceptions allows
+ * to change this option.
+ */
+ Handle<StackTrace> GetStackTrace() const;
+
+ /**
+ * Returns the number, 1-based, of the line where the error occurred.
+ */
+ int GetLineNumber() const;
+
+ /**
+ * Returns the index within the script of the first character where
+ * the error occurred.
+ */
+ int GetStartPosition() const;
+
+ /**
+ * Returns the index within the script of the last character where
+ * the error occurred.
+ */
+ int GetEndPosition() const;
+
+ /**
+ * Returns the index within the line of the first character where
+ * the error occurred.
+ */
+ int GetStartColumn() const;
+
+ /**
+ * Returns the index within the line of the last character where
+ * the error occurred.
+ */
+ int GetEndColumn() const;
+
+ // TODO(1245381): Print to a string instead of on a FILE.
+ static void PrintCurrentStackTrace(FILE* out);
+
+ static const int kNoLineNumberInfo = 0;
+ static const int kNoColumnInfo = 0;
+};
+
+
+/**
+ * Representation of a JavaScript stack trace. The information collected is a
+ * snapshot of the execution stack and the information remains valid after
+ * execution continues.
+ */
+class V8EXPORT StackTrace {
+ public:
+ /**
+ * Flags that determine what information is placed captured for each
+ * StackFrame when grabbing the current stack trace.
+ */
+ enum StackTraceOptions {
+ kLineNumber = 1,
+ kColumnOffset = 1 << 1 | kLineNumber,
+ kScriptName = 1 << 2,
+ kFunctionName = 1 << 3,
+ kIsEval = 1 << 4,
+ kIsConstructor = 1 << 5,
+ kOverview = kLineNumber | kColumnOffset | kScriptName | kFunctionName,
+ kDetailed = kOverview | kIsEval | kIsConstructor
+ };
+
+ /**
+ * Returns a StackFrame at a particular index.
+ */
+ Local<StackFrame> GetFrame(uint32_t index) const;
+
+ /**
+ * Returns the number of StackFrames.
+ */
+ int GetFrameCount() const;
+
+ /**
+ * Returns StackTrace as a v8::Array that contains StackFrame objects.
+ */
+ Local<Array> AsArray();
+
+ /**
+ * Grab a snapshot of the the current JavaScript execution stack.
+ *
+ * \param frame_limit The maximum number of stack frames we want to capture.
+ * \param options Enumerates the set of things we will capture for each
+ * StackFrame.
+ */
+ static Local<StackTrace> CurrentStackTrace(
+ int frame_limit,
+ StackTraceOptions options = kOverview);
+};
+
+
+/**
+ * A single JavaScript stack frame.
+ */
+class V8EXPORT StackFrame {
+ public:
+ /**
+ * Returns the number, 1-based, of the line for the associate function call.
+ * This method will return Message::kNoLineNumberInfo if it is unable to
+ * retrieve the line number, or if kLineNumber was not passed as an option
+ * when capturing the StackTrace.
+ */
+ int GetLineNumber() const;
+
+ /**
+ * Returns the 1-based column offset on the line for the associated function
+ * call.
+ * This method will return Message::kNoColumnInfo if it is unable to retrieve
+ * the column number, or if kColumnOffset was not passed as an option when
+ * capturing the StackTrace.
+ */
+ int GetColumn() const;
+
+ /**
+ * Returns the name of the resource that contains the script for the
+ * function for this StackFrame.
+ */
+ Local<String> GetScriptName() const;
+
+ /**
+ * Returns the name of the function associated with this stack frame.
+ */
+ Local<String> GetFunctionName() const;
+
+ /**
+ * Returns whether or not the associated function is compiled via a call to
+ * eval().
+ */
+ bool IsEval() const;
+
+ /**
+ * Returns whther or not the associated function is called as a
+ * constructor via "new".
+ */
+ bool IsConstructor() const;
+};
+
+
+// --- V a l u e ---
+
+
+/**
+ * The superclass of all JavaScript values and objects.
+ */
+class Value : public Data {
+ public:
+
+ /**
+ * Returns true if this value is the undefined value. See ECMA-262
+ * 4.3.10.
+ */
+ V8EXPORT bool IsUndefined() const;
+
+ /**
+ * Returns true if this value is the null value. See ECMA-262
+ * 4.3.11.
+ */
+ V8EXPORT bool IsNull() const;
+
+ /**
+ * Returns true if this value is true.
+ */
+ V8EXPORT bool IsTrue() const;
+
+ /**
+ * Returns true if this value is false.
+ */
+ V8EXPORT bool IsFalse() const;
+
+ /**
+ * Returns true if this value is an instance of the String type.
+ * See ECMA-262 8.4.
+ */
+ inline bool IsString() const;
+
+ /**
+ * Returns true if this value is a function.
+ */
+ V8EXPORT bool IsFunction() const;
+
+ /**
+ * Returns true if this value is an array.
+ */
+ V8EXPORT bool IsArray() const;
+
+ /**
+ * Returns true if this value is an object.
+ */
+ V8EXPORT bool IsObject() const;
+
+ /**
+ * Returns true if this value is boolean.
+ */
+ V8EXPORT bool IsBoolean() const;
+
+ /**
+ * Returns true if this value is a number.
+ */
+ V8EXPORT bool IsNumber() const;
+
+ /**
+ * Returns true if this value is external.
+ */
+ V8EXPORT bool IsExternal() const;
+
+ /**
+ * Returns true if this value is a 32-bit signed integer.
+ */
+ V8EXPORT bool IsInt32() const;
+
+ /**
+ * Returns true if this value is a 32-bit unsigned integer.
+ */
+ V8EXPORT bool IsUint32() const;
+
+ /**
+ * Returns true if this value is a Date.
+ */
+ V8EXPORT bool IsDate() const;
+
+ /**
+ * Returns true if this value is a RegExp.
+ */
+ V8EXPORT bool IsRegExp() const;
+
+ V8EXPORT Local<Boolean> ToBoolean() const;
+ V8EXPORT Local<Number> ToNumber() const;
+ V8EXPORT Local<String> ToString() const;
+ V8EXPORT Local<String> ToDetailString() const;
+ V8EXPORT Local<Object> ToObject() const;
+ V8EXPORT Local<Integer> ToInteger() const;
+ V8EXPORT Local<Uint32> ToUint32() const;
+ V8EXPORT Local<Int32> ToInt32() const;
+
+ /**
+ * Attempts to convert a string to an array index.
+ * Returns an empty handle if the conversion fails.
+ */
+ V8EXPORT Local<Uint32> ToArrayIndex() const;
+
+ V8EXPORT bool BooleanValue() const;
+ V8EXPORT double NumberValue() const;
+ V8EXPORT int64_t IntegerValue() const;
+ V8EXPORT uint32_t Uint32Value() const;
+ V8EXPORT int32_t Int32Value() const;
+
+ /** JS == */
+ V8EXPORT bool Equals(Handle<Value> that) const;
+ V8EXPORT bool StrictEquals(Handle<Value> that) const;
+
+ private:
+ inline bool QuickIsString() const;
+ V8EXPORT bool FullIsString() const;
+};
+
+
+/**
+ * The superclass of primitive values. See ECMA-262 4.3.2.
+ */
+class Primitive : public Value { };
+
+
+/**
+ * A primitive boolean value (ECMA-262, 4.3.14). Either the true
+ * or false value.
+ */
+class Boolean : public Primitive {
+ public:
+ V8EXPORT bool Value() const;
+ static inline Handle<Boolean> New(bool value);
+};
+
+
+/**
+ * A JavaScript string value (ECMA-262, 4.3.17).
+ */
+class String : public Primitive {
+ public:
+
+ /**
+ * Returns the number of characters in this string.
+ */
+ V8EXPORT int Length() const;
+
+ /**
+ * Returns the number of bytes in the UTF-8 encoded
+ * representation of this string.
+ */
+ V8EXPORT int Utf8Length() const;
+
+ /**
+ * Write the contents of the string to an external buffer.
+ * If no arguments are given, expects the buffer to be large
+ * enough to hold the entire string and NULL terminator. Copies
+ * the contents of the string and the NULL terminator into the
+ * buffer.
+ *
+ * Copies up to length characters into the output buffer.
+ * Only null-terminates if there is enough space in the buffer.
+ *
+ * \param buffer The buffer into which the string will be copied.
+ * \param start The starting position within the string at which
+ * copying begins.
+ * \param length The number of bytes to copy from the string.
+ * \param nchars_ref The number of characters written, can be NULL.
+ * \param hints Various hints that might affect performance of this or
+ * subsequent operations.
+ * \return The number of bytes copied to the buffer
+ * excluding the NULL terminator.
+ */
+ enum WriteHints {
+ NO_HINTS = 0,
+ HINT_MANY_WRITES_EXPECTED = 1
+ };
+
+ V8EXPORT int Write(uint16_t* buffer,
+ int start = 0,
+ int length = -1,
+ WriteHints hints = NO_HINTS) const; // UTF-16
+ V8EXPORT int WriteAscii(char* buffer,
+ int start = 0,
+ int length = -1,
+ WriteHints hints = NO_HINTS) const; // ASCII
+ V8EXPORT int WriteUtf8(char* buffer,
+ int length = -1,
+ int* nchars_ref = NULL,
+ WriteHints hints = NO_HINTS) const; // UTF-8
+
+ /**
+ * A zero length string.
+ */
+ V8EXPORT static v8::Local<v8::String> Empty();
+
+ /**
+ * Returns true if the string is external
+ */
+ V8EXPORT bool IsExternal() const;
+
+ /**
+ * Returns true if the string is both external and ascii
+ */
+ V8EXPORT bool IsExternalAscii() const;
+
+ class V8EXPORT ExternalStringResourceBase {
+ public:
+ virtual ~ExternalStringResourceBase() {}
+
+ protected:
+ ExternalStringResourceBase() {}
+
+ /**
+ * Internally V8 will call this Dispose method when the external string
+ * resource is no longer needed. The default implementation will use the
+ * delete operator. This method can be overridden in subclasses to
+ * control how allocated external string resources are disposed.
+ */
+ virtual void Dispose() { delete this; }
+
+ private:
+ // Disallow copying and assigning.
+ ExternalStringResourceBase(const ExternalStringResourceBase&);
+ void operator=(const ExternalStringResourceBase&);
+
+ friend class v8::internal::Heap;
+ };
+
+ /**
+ * An ExternalStringResource is a wrapper around a two-byte string
+ * buffer that resides outside V8's heap. Implement an
+ * ExternalStringResource to manage the life cycle of the underlying
+ * buffer. Note that the string data must be immutable.
+ */
+ class V8EXPORT ExternalStringResource
+ : public ExternalStringResourceBase {
+ public:
+ /**
+ * Override the destructor to manage the life cycle of the underlying
+ * buffer.
+ */
+ virtual ~ExternalStringResource() {}
+
+ /**
+ * The string data from the underlying buffer.
+ */
+ virtual const uint16_t* data() const = 0;
+
+ /**
+ * The length of the string. That is, the number of two-byte characters.
+ */
+ virtual size_t length() const = 0;
+
+ protected:
+ ExternalStringResource() {}
+ };
+
+ /**
+ * An ExternalAsciiStringResource is a wrapper around an ascii
+ * string buffer that resides outside V8's heap. Implement an
+ * ExternalAsciiStringResource to manage the life cycle of the
+ * underlying buffer. Note that the string data must be immutable
+ * and that the data must be strict 7-bit ASCII, not Latin1 or
+ * UTF-8, which would require special treatment internally in the
+ * engine and, in the case of UTF-8, do not allow efficient indexing.
+ * Use String::New or convert to 16 bit data for non-ASCII.
+ */
+
+ class V8EXPORT ExternalAsciiStringResource
+ : public ExternalStringResourceBase {
+ public:
+ /**
+ * Override the destructor to manage the life cycle of the underlying
+ * buffer.
+ */
+ virtual ~ExternalAsciiStringResource() {}
+ /** The string data from the underlying buffer.*/
+ virtual const char* data() const = 0;
+ /** The number of ascii characters in the string.*/
+ virtual size_t length() const = 0;
+ protected:
+ ExternalAsciiStringResource() {}
+ };
+
+ /**
+ * Get the ExternalStringResource for an external string. Returns
+ * NULL if IsExternal() doesn't return true.
+ */
+ inline ExternalStringResource* GetExternalStringResource() const;
+
+ /**
+ * Get the ExternalAsciiStringResource for an external ascii string.
+ * Returns NULL if IsExternalAscii() doesn't return true.
+ */
+ V8EXPORT ExternalAsciiStringResource* GetExternalAsciiStringResource() const;
+
+ static inline String* Cast(v8::Value* obj);
+
+ /**
+ * Allocates a new string from either utf-8 encoded or ascii data.
+ * The second parameter 'length' gives the buffer length.
+ * If the data is utf-8 encoded, the caller must
+ * be careful to supply the length parameter.
+ * If it is not given, the function calls
+ * 'strlen' to determine the buffer length, it might be
+ * wrong if 'data' contains a null character.
+ */
+ V8EXPORT static Local<String> New(const char* data, int length = -1);
+
+ /** Allocates a new string from utf16 data.*/
+ V8EXPORT static Local<String> New(const uint16_t* data, int length = -1);
+
+ /** Creates a symbol. Returns one if it exists already.*/
+ V8EXPORT static Local<String> NewSymbol(const char* data, int length = -1);
+
+ /**
+ * Creates a new string by concatenating the left and the right strings
+ * passed in as parameters.
+ */
+ V8EXPORT static Local<String> Concat(Handle<String> left,
+ Handle<String>right);
+
+ /**
+ * Creates a new external string using the data defined in the given
+ * resource. When the external string is no longer live on V8's heap the
+ * resource will be disposed by calling its Dispose method. The caller of
+ * this function should not otherwise delete or modify the resource. Neither
+ * should the underlying buffer be deallocated or modified except through the
+ * destructor of the external string resource.
+ */
+ V8EXPORT static Local<String> NewExternal(ExternalStringResource* resource);
+
+ /**
+ * Associate an external string resource with this string by transforming it
+ * in place so that existing references to this string in the JavaScript heap
+ * will use the external string resource. The external string resource's
+ * character contents needs to be equivalent to this string.
+ * Returns true if the string has been changed to be an external string.
+ * The string is not modified if the operation fails. See NewExternal for
+ * information on the lifetime of the resource.
+ */
+ V8EXPORT bool MakeExternal(ExternalStringResource* resource);
+
+ /**
+ * Creates a new external string using the ascii data defined in the given
+ * resource. When the external string is no longer live on V8's heap the
+ * resource will be disposed by calling its Dispose method. The caller of
+ * this function should not otherwise delete or modify the resource. Neither
+ * should the underlying buffer be deallocated or modified except through the
+ * destructor of the external string resource.
+ */
+ V8EXPORT static Local<String> NewExternal(
+ ExternalAsciiStringResource* resource);
+
+ /**
+ * Associate an external string resource with this string by transforming it
+ * in place so that existing references to this string in the JavaScript heap
+ * will use the external string resource. The external string resource's
+ * character contents needs to be equivalent to this string.
+ * Returns true if the string has been changed to be an external string.
+ * The string is not modified if the operation fails. See NewExternal for
+ * information on the lifetime of the resource.
+ */
+ V8EXPORT bool MakeExternal(ExternalAsciiStringResource* resource);
+
+ /**
+ * Returns true if this string can be made external.
+ */
+ V8EXPORT bool CanMakeExternal();
+
+ /** Creates an undetectable string from the supplied ascii or utf-8 data.*/
+ V8EXPORT static Local<String> NewUndetectable(const char* data,
+ int length = -1);
+
+ /** Creates an undetectable string from the supplied utf-16 data.*/
+ V8EXPORT static Local<String> NewUndetectable(const uint16_t* data,
+ int length = -1);
+
+ /**
+ * Converts an object to a utf8-encoded character array. Useful if
+ * you want to print the object. If conversion to a string fails
+ * (eg. due to an exception in the toString() method of the object)
+ * then the length() method returns 0 and the * operator returns
+ * NULL.
+ */
+ class V8EXPORT Utf8Value {
+ public:
+ explicit Utf8Value(Handle<v8::Value> obj);
+ ~Utf8Value();
+ char* operator*() { return str_; }
+ const char* operator*() const { return str_; }
+ int length() const { return length_; }
+ private:
+ char* str_;
+ int length_;
+
+ // Disallow copying and assigning.
+ Utf8Value(const Utf8Value&);
+ void operator=(const Utf8Value&);
+ };
+
+ /**
+ * Converts an object to an ascii string.
+ * Useful if you want to print the object.
+ * If conversion to a string fails (eg. due to an exception in the toString()
+ * method of the object) then the length() method returns 0 and the * operator
+ * returns NULL.
+ */
+ class V8EXPORT AsciiValue {
+ public:
+ explicit AsciiValue(Handle<v8::Value> obj);
+ ~AsciiValue();
+ char* operator*() { return str_; }
+ const char* operator*() const { return str_; }
+ int length() const { return length_; }
+ private:
+ char* str_;
+ int length_;
+
+ // Disallow copying and assigning.
+ AsciiValue(const AsciiValue&);
+ void operator=(const AsciiValue&);
+ };
+
+ /**
+ * Converts an object to a two-byte string.
+ * If conversion to a string fails (eg. due to an exception in the toString()
+ * method of the object) then the length() method returns 0 and the * operator
+ * returns NULL.
+ */
+ class V8EXPORT Value {
+ public:
+ explicit Value(Handle<v8::Value> obj);
+ ~Value();
+ uint16_t* operator*() { return str_; }
+ const uint16_t* operator*() const { return str_; }
+ int length() const { return length_; }
+ private:
+ uint16_t* str_;
+ int length_;
+
+ // Disallow copying and assigning.
+ Value(const Value&);
+ void operator=(const Value&);
+ };
+
+ private:
+ V8EXPORT void VerifyExternalStringResource(ExternalStringResource* val) const;
+ V8EXPORT static void CheckCast(v8::Value* obj);
+};
+
+
+/**
+ * A JavaScript number value (ECMA-262, 4.3.20)
+ */
+class Number : public Primitive {
+ public:
+ V8EXPORT double Value() const;
+ V8EXPORT static Local<Number> New(double value);
+ static inline Number* Cast(v8::Value* obj);
+ private:
+ V8EXPORT Number();
+ static void CheckCast(v8::Value* obj);
+};
+
+
+/**
+ * A JavaScript value representing a signed integer.
+ */
+class Integer : public Number {
+ public:
+ V8EXPORT static Local<Integer> New(int32_t value);
+ V8EXPORT static Local<Integer> NewFromUnsigned(uint32_t value);
+ V8EXPORT int64_t Value() const;
+ static inline Integer* Cast(v8::Value* obj);
+ private:
+ V8EXPORT Integer();
+ V8EXPORT static void CheckCast(v8::Value* obj);
+};
+
+
+/**
+ * A JavaScript value representing a 32-bit signed integer.
+ */
+class Int32 : public Integer {
+ public:
+ V8EXPORT int32_t Value() const;
+ private:
+ V8EXPORT Int32();
+};
+
+
+/**
+ * A JavaScript value representing a 32-bit unsigned integer.
+ */
+class Uint32 : public Integer {
+ public:
+ V8EXPORT uint32_t Value() const;
+ private:
+ V8EXPORT Uint32();
+};
+
+
+/**
+ * An instance of the built-in Date constructor (ECMA-262, 15.9).
+ */
+class Date : public Value {
+ public:
+ V8EXPORT static Local<Value> New(double time);
+
+ /**
+ * A specialization of Value::NumberValue that is more efficient
+ * because we know the structure of this object.
+ */
+ V8EXPORT double NumberValue() const;
+
+ static inline Date* Cast(v8::Value* obj);
+ private:
+ V8EXPORT static void CheckCast(v8::Value* obj);
+};
+
+
+enum PropertyAttribute {
+ None = 0,
+ ReadOnly = 1 << 0,
+ DontEnum = 1 << 1,
+ DontDelete = 1 << 2
+};
+
+enum ExternalArrayType {
+ kExternalByteArray = 1,
+ kExternalUnsignedByteArray,
+ kExternalShortArray,
+ kExternalUnsignedShortArray,
+ kExternalIntArray,
+ kExternalUnsignedIntArray,
+ kExternalFloatArray
+};
+
+/**
+ * Accessor[Getter|Setter] are used as callback functions when
+ * setting|getting a particular property. See Object and ObjectTemplate's
+ * method SetAccessor.
+ */
+typedef Handle<Value> (*AccessorGetter)(Local<String> property,
+ const AccessorInfo& info);
+
+
+typedef void (*AccessorSetter)(Local<String> property,
+ Local<Value> value,
+ const AccessorInfo& info);
+
+
+/**
+ * Access control specifications.
+ *
+ * Some accessors should be accessible across contexts. These
+ * accessors have an explicit access control parameter which specifies
+ * the kind of cross-context access that should be allowed.
+ *
+ * Additionally, for security, accessors can prohibit overwriting by
+ * accessors defined in JavaScript. For objects that have such
+ * accessors either locally or in their prototype chain it is not
+ * possible to overwrite the accessor by using __defineGetter__ or
+ * __defineSetter__ from JavaScript code.
+ */
+enum AccessControl {
+ DEFAULT = 0,
+ ALL_CAN_READ = 1,
+ ALL_CAN_WRITE = 1 << 1,
+ PROHIBITS_OVERWRITING = 1 << 2
+};
+
+
+/**
+ * A JavaScript object (ECMA-262, 4.3.3)
+ */
+class Object : public Value {
+ public:
+ V8EXPORT bool Set(Handle<Value> key,
+ Handle<Value> value,
+ PropertyAttribute attribs = None);
+
+ V8EXPORT bool Set(uint32_t index,
+ Handle<Value> value);
+
+ // Sets a local property on this object bypassing interceptors and
+ // overriding accessors or read-only properties.
+ //
+ // Note that if the object has an interceptor the property will be set
+ // locally, but since the interceptor takes precedence the local property
+ // will only be returned if the interceptor doesn't return a value.
+ //
+ // Note also that this only works for named properties.
+ V8EXPORT bool ForceSet(Handle<Value> key,
+ Handle<Value> value,
+ PropertyAttribute attribs = None);
+
+ V8EXPORT Local<Value> Get(Handle<Value> key);
+
+ V8EXPORT Local<Value> Get(uint32_t index);
+
+ // TODO(1245389): Replace the type-specific versions of these
+ // functions with generic ones that accept a Handle<Value> key.
+ V8EXPORT bool Has(Handle<String> key);
+
+ V8EXPORT bool Delete(Handle<String> key);
+
+ // Delete a property on this object bypassing interceptors and
+ // ignoring dont-delete attributes.
+ V8EXPORT bool ForceDelete(Handle<Value> key);
+
+ V8EXPORT bool Has(uint32_t index);
+
+ V8EXPORT bool Delete(uint32_t index);
+
+ V8EXPORT bool SetAccessor(Handle<String> name,
+ AccessorGetter getter,
+ AccessorSetter setter = 0,
+ Handle<Value> data = Handle<Value>(),
+ AccessControl settings = DEFAULT,
+ PropertyAttribute attribute = None);
+
+ /**
+ * Returns an array containing the names of the enumerable properties
+ * of this object, including properties from prototype objects. The
+ * array returned by this method contains the same values as would
+ * be enumerated by a for-in statement over this object.
+ */
+ V8EXPORT Local<Array> GetPropertyNames();
+
+ /**
+ * Get the prototype object. This does not skip objects marked to
+ * be skipped by __proto__ and it does not consult the security
+ * handler.
+ */
+ V8EXPORT Local<Value> GetPrototype();
+
+ /**
+ * Set the prototype object. This does not skip objects marked to
+ * be skipped by __proto__ and it does not consult the security
+ * handler.
+ */
+ V8EXPORT bool SetPrototype(Handle<Value> prototype);
+
+ /**
+ * Finds an instance of the given function template in the prototype
+ * chain.
+ */
+ V8EXPORT Local<Object> FindInstanceInPrototypeChain(
+ Handle<FunctionTemplate> tmpl);
+
+ /**
+ * Call builtin Object.prototype.toString on this object.
+ * This is different from Value::ToString() that may call
+ * user-defined toString function. This one does not.
+ */
+ V8EXPORT Local<String> ObjectProtoToString();
+
+ /** Gets the number of internal fields for this Object. */
+ V8EXPORT int InternalFieldCount();
+ /** Gets the value in an internal field. */
+ inline Local<Value> GetInternalField(int index);
+ /** Sets the value in an internal field. */
+ V8EXPORT void SetInternalField(int index, Handle<Value> value);
+
+ /** Gets a native pointer from an internal field. */
+ inline void* GetPointerFromInternalField(int index);
+
+ /** Sets a native pointer in an internal field. */
+ V8EXPORT void SetPointerInInternalField(int index, void* value);
+
+ // Testers for local properties.
+ V8EXPORT bool HasRealNamedProperty(Handle<String> key);
+ V8EXPORT bool HasRealIndexedProperty(uint32_t index);
+ V8EXPORT bool HasRealNamedCallbackProperty(Handle<String> key);
+
+ /**
+ * If result.IsEmpty() no real property was located in the prototype chain.
+ * This means interceptors in the prototype chain are not called.
+ */
+ V8EXPORT Local<Value> GetRealNamedPropertyInPrototypeChain(
+ Handle<String> key);
+
+ /**
+ * If result.IsEmpty() no real property was located on the object or
+ * in the prototype chain.
+ * This means interceptors in the prototype chain are not called.
+ */
+ V8EXPORT Local<Value> GetRealNamedProperty(Handle<String> key);
+
+ /** Tests for a named lookup interceptor.*/
+ V8EXPORT bool HasNamedLookupInterceptor();
+
+ /** Tests for an index lookup interceptor.*/
+ V8EXPORT bool HasIndexedLookupInterceptor();
+
+ /**
+ * Turns on access check on the object if the object is an instance of
+ * a template that has access check callbacks. If an object has no
+ * access check info, the object cannot be accessed by anyone.
+ */
+ V8EXPORT void TurnOnAccessCheck();
+
+ /**
+ * Returns the identity hash for this object. The current implemenation uses
+ * a hidden property on the object to store the identity hash.
+ *
+ * The return value will never be 0. Also, it is not guaranteed to be
+ * unique.
+ */
+ V8EXPORT int GetIdentityHash();
+
+ /**
+ * Access hidden properties on JavaScript objects. These properties are
+ * hidden from the executing JavaScript and only accessible through the V8
+ * C++ API. Hidden properties introduced by V8 internally (for example the
+ * identity hash) are prefixed with "v8::".
+ */
+ V8EXPORT bool SetHiddenValue(Handle<String> key, Handle<Value> value);
+ V8EXPORT Local<Value> GetHiddenValue(Handle<String> key);
+ V8EXPORT bool DeleteHiddenValue(Handle<String> key);
+
+ /**
+ * Returns true if this is an instance of an api function (one
+ * created from a function created from a function template) and has
+ * been modified since it was created. Note that this method is
+ * conservative and may return true for objects that haven't actually
+ * been modified.
+ */
+ V8EXPORT bool IsDirty();
+
+ /**
+ * Clone this object with a fast but shallow copy. Values will point
+ * to the same values as the original object.
+ */
+ V8EXPORT Local<Object> Clone();
+
+ /**
+ * Set the backing store of the indexed properties to be managed by the
+ * embedding layer. Access to the indexed properties will follow the rules
+ * spelled out in CanvasPixelArray.
+ * Note: The embedding program still owns the data and needs to ensure that
+ * the backing store is preserved while V8 has a reference.
+ */
+ V8EXPORT void SetIndexedPropertiesToPixelData(uint8_t* data, int length);
+ bool HasIndexedPropertiesInPixelData();
+ uint8_t* GetIndexedPropertiesPixelData();
+ int GetIndexedPropertiesPixelDataLength();
+
+ /**
+ * Set the backing store of the indexed properties to be managed by the
+ * embedding layer. Access to the indexed properties will follow the rules
+ * spelled out for the CanvasArray subtypes in the WebGL specification.
+ * Note: The embedding program still owns the data and needs to ensure that
+ * the backing store is preserved while V8 has a reference.
+ */
+ V8EXPORT void SetIndexedPropertiesToExternalArrayData(
+ void* data,
+ ExternalArrayType array_type,
+ int number_of_elements);
+ bool HasIndexedPropertiesInExternalArrayData();
+ void* GetIndexedPropertiesExternalArrayData();
+ ExternalArrayType GetIndexedPropertiesExternalArrayDataType();
+ int GetIndexedPropertiesExternalArrayDataLength();
+
+ V8EXPORT static Local<Object> New();
+ static inline Object* Cast(Value* obj);
+ private:
+ V8EXPORT Object();
+ V8EXPORT static void CheckCast(Value* obj);
+ V8EXPORT Local<Value> CheckedGetInternalField(int index);
+ V8EXPORT void* SlowGetPointerFromInternalField(int index);
+
+ /**
+ * If quick access to the internal field is possible this method
+ * returns the value. Otherwise an empty handle is returned.
+ */
+ inline Local<Value> UncheckedGetInternalField(int index);
+};
+
+
+/**
+ * An instance of the built-in array constructor (ECMA-262, 15.4.2).
+ */
+class Array : public Object {
+ public:
+ V8EXPORT uint32_t Length() const;
+
+ /**
+ * Clones an element at index |index|. Returns an empty
+ * handle if cloning fails (for any reason).
+ */
+ V8EXPORT Local<Object> CloneElementAt(uint32_t index);
+
+ V8EXPORT static Local<Array> New(int length = 0);
+ static inline Array* Cast(Value* obj);
+ private:
+ V8EXPORT Array();
+ static void CheckCast(Value* obj);
+};
+
+
+/**
+ * A JavaScript function object (ECMA-262, 15.3).
+ */
+class Function : public Object {
+ public:
+ V8EXPORT Local<Object> NewInstance() const;
+ V8EXPORT Local<Object> NewInstance(int argc, Handle<Value> argv[]) const;
+ V8EXPORT Local<Value> Call(Handle<Object> recv,
+ int argc,
+ Handle<Value> argv[]);
+ V8EXPORT void SetName(Handle<String> name);
+ V8EXPORT Handle<Value> GetName() const;
+
+ /**
+ * Returns zero based line number of function body and
+ * kLineOffsetNotFound if no information available.
+ */
+ V8EXPORT int GetScriptLineNumber() const;
+ V8EXPORT ScriptOrigin GetScriptOrigin() const;
+ static inline Function* Cast(Value* obj);
+ V8EXPORT static const int kLineOffsetNotFound;
+ private:
+ V8EXPORT Function();
+ V8EXPORT static void CheckCast(Value* obj);
+};
+
+
+/**
+ * A JavaScript value that wraps a C++ void*. This type of value is
+ * mainly used to associate C++ data structures with JavaScript
+ * objects.
+ *
+ * The Wrap function V8 will return the most optimal Value object wrapping the
+ * C++ void*. The type of the value is not guaranteed to be an External object
+ * and no assumptions about its type should be made. To access the wrapped
+ * value Unwrap should be used, all other operations on that object will lead
+ * to unpredictable results.
+ */
+class External : public Value {
+ public:
+ V8EXPORT static Local<Value> Wrap(void* data);
+ static inline void* Unwrap(Handle<Value> obj);
+
+ V8EXPORT static Local<External> New(void* value);
+ static inline External* Cast(Value* obj);
+ V8EXPORT void* Value() const;
+ private:
+ V8EXPORT External();
+ V8EXPORT static void CheckCast(v8::Value* obj);
+ static inline void* QuickUnwrap(Handle<v8::Value> obj);
+ V8EXPORT static void* FullUnwrap(Handle<v8::Value> obj);
+};
+
+
+// --- T e m p l a t e s ---
+
+
+/**
+ * The superclass of object and function templates.
+ */
+class V8EXPORT Template : public Data {
+ public:
+ /** Adds a property to each instance created by this template.*/
+ void Set(Handle<String> name, Handle<Data> value,
+ PropertyAttribute attributes = None);
+ inline void Set(const char* name, Handle<Data> value);
+ private:
+ Template();
+
+ friend class ObjectTemplate;
+ friend class FunctionTemplate;
+};
+
+
+/**
+ * The argument information given to function call callbacks. This
+ * class provides access to information about the context of the call,
+ * including the receiver, the number and values of arguments, and
+ * the holder of the function.
+ */
+class Arguments {
+ public:
+ inline int Length() const;
+ inline Local<Value> operator[](int i) const;
+ inline Local<Function> Callee() const;
+ inline Local<Object> This() const;
+ inline Local<Object> Holder() const;
+ inline bool IsConstructCall() const;
+ inline Local<Value> Data() const;
+ private:
+ friend class ImplementationUtilities;
+ inline Arguments(Local<Value> data,
+ Local<Object> holder,
+ Local<Function> callee,
+ bool is_construct_call,
+ void** values, int length);
+ Local<Value> data_;
+ Local<Object> holder_;
+ Local<Function> callee_;
+ bool is_construct_call_;
+ void** values_;
+ int length_;
+};
+
+
+/**
+ * The information passed to an accessor callback about the context
+ * of the property access.
+ */
+class V8EXPORT AccessorInfo {
+ public:
+ inline AccessorInfo(internal::Object** args)
+ : args_(args) { }
+ inline Local<Value> Data() const;
+ inline Local<Object> This() const;
+ inline Local<Object> Holder() const;
+ private:
+ internal::Object** args_;
+};
+
+
+typedef Handle<Value> (*InvocationCallback)(const Arguments& args);
+
+/**
+ * NamedProperty[Getter|Setter] are used as interceptors on object.
+ * See ObjectTemplate::SetNamedPropertyHandler.
+ */
+typedef Handle<Value> (*NamedPropertyGetter)(Local<String> property,
+ const AccessorInfo& info);
+
+
+/**
+ * Returns the value if the setter intercepts the request.
+ * Otherwise, returns an empty handle.
+ */
+typedef Handle<Value> (*NamedPropertySetter)(Local<String> property,
+ Local<Value> value,
+ const AccessorInfo& info);
+
+/**
+ * Returns a non-empty handle if the interceptor intercepts the request.
+ * The result is an integer encoding property attributes (like v8::None,
+ * v8::DontEnum, etc.)
+ */
+typedef Handle<Integer> (*NamedPropertyQuery)(Local<String> property,
+ const AccessorInfo& info);
+
+
+/**
+ * Returns a non-empty handle if the deleter intercepts the request.
+ * The return value is true if the property could be deleted and false
+ * otherwise.
+ */
+typedef Handle<Boolean> (*NamedPropertyDeleter)(Local<String> property,
+ const AccessorInfo& info);
+
+/**
+ * Returns an array containing the names of the properties the named
+ * property getter intercepts.
+ */
+typedef Handle<Array> (*NamedPropertyEnumerator)(const AccessorInfo& info);
+
+
+/**
+ * Returns the value of the property if the getter intercepts the
+ * request. Otherwise, returns an empty handle.
+ */
+typedef Handle<Value> (*IndexedPropertyGetter)(uint32_t index,
+ const AccessorInfo& info);
+
+
+/**
+ * Returns the value if the setter intercepts the request.
+ * Otherwise, returns an empty handle.
+ */
+typedef Handle<Value> (*IndexedPropertySetter)(uint32_t index,
+ Local<Value> value,
+ const AccessorInfo& info);
+
+
+/**
+ * Returns a non-empty handle if the interceptor intercepts the request.
+ * The result is an integer encoding property attributes.
+ */
+typedef Handle<Integer> (*IndexedPropertyQuery)(uint32_t index,
+ const AccessorInfo& info);
+
+/**
+ * Returns a non-empty handle if the deleter intercepts the request.
+ * The return value is true if the property could be deleted and false
+ * otherwise.
+ */
+typedef Handle<Boolean> (*IndexedPropertyDeleter)(uint32_t index,
+ const AccessorInfo& info);
+
+/**
+ * Returns an array containing the indices of the properties the
+ * indexed property getter intercepts.
+ */
+typedef Handle<Array> (*IndexedPropertyEnumerator)(const AccessorInfo& info);
+
+
+/**
+ * Access type specification.
+ */
+enum AccessType {
+ ACCESS_GET,
+ ACCESS_SET,
+ ACCESS_HAS,
+ ACCESS_DELETE,
+ ACCESS_KEYS
+};
+
+
+/**
+ * Returns true if cross-context access should be allowed to the named
+ * property with the given key on the host object.
+ */
+typedef bool (*NamedSecurityCallback)(Local<Object> host,
+ Local<Value> key,
+ AccessType type,
+ Local<Value> data);
+
+
+/**
+ * Returns true if cross-context access should be allowed to the indexed
+ * property with the given index on the host object.
+ */
+typedef bool (*IndexedSecurityCallback)(Local<Object> host,
+ uint32_t index,
+ AccessType type,
+ Local<Value> data);
+
+
+/**
+ * A FunctionTemplate is used to create functions at runtime. There
+ * can only be one function created from a FunctionTemplate in a
+ * context. The lifetime of the created function is equal to the
+ * lifetime of the context. So in case the embedder needs to create
+ * temporary functions that can be collected using Scripts is
+ * preferred.
+ *
+ * A FunctionTemplate can have properties, these properties are added to the
+ * function object when it is created.
+ *
+ * A FunctionTemplate has a corresponding instance template which is
+ * used to create object instances when the function is used as a
+ * constructor. Properties added to the instance template are added to
+ * each object instance.
+ *
+ * A FunctionTemplate can have a prototype template. The prototype template
+ * is used to create the prototype object of the function.
+ *
+ * The following example shows how to use a FunctionTemplate:
+ *
+ * \code
+ * v8::Local<v8::FunctionTemplate> t = v8::FunctionTemplate::New();
+ * t->Set("func_property", v8::Number::New(1));
+ *
+ * v8::Local<v8::Template> proto_t = t->PrototypeTemplate();
+ * proto_t->Set("proto_method", v8::FunctionTemplate::New(InvokeCallback));
+ * proto_t->Set("proto_const", v8::Number::New(2));
+ *
+ * v8::Local<v8::ObjectTemplate> instance_t = t->InstanceTemplate();
+ * instance_t->SetAccessor("instance_accessor", InstanceAccessorCallback);
+ * instance_t->SetNamedPropertyHandler(PropertyHandlerCallback, ...);
+ * instance_t->Set("instance_property", Number::New(3));
+ *
+ * v8::Local<v8::Function> function = t->GetFunction();
+ * v8::Local<v8::Object> instance = function->NewInstance();
+ * \endcode
+ *
+ * Let's use "function" as the JS variable name of the function object
+ * and "instance" for the instance object created above. The function
+ * and the instance will have the following properties:
+ *
+ * \code
+ * func_property in function == true;
+ * function.func_property == 1;
+ *
+ * function.prototype.proto_method() invokes 'InvokeCallback'
+ * function.prototype.proto_const == 2;
+ *
+ * instance instanceof function == true;
+ * instance.instance_accessor calls 'InstanceAccessorCallback'
+ * instance.instance_property == 3;
+ * \endcode
+ *
+ * A FunctionTemplate can inherit from another one by calling the
+ * FunctionTemplate::Inherit method. The following graph illustrates
+ * the semantics of inheritance:
+ *
+ * \code
+ * FunctionTemplate Parent -> Parent() . prototype -> { }
+ * ^ ^
+ * | Inherit(Parent) | .__proto__
+ * | |
+ * FunctionTemplate Child -> Child() . prototype -> { }
+ * \endcode
+ *
+ * A FunctionTemplate 'Child' inherits from 'Parent', the prototype
+ * object of the Child() function has __proto__ pointing to the
+ * Parent() function's prototype object. An instance of the Child
+ * function has all properties on Parent's instance templates.
+ *
+ * Let Parent be the FunctionTemplate initialized in the previous
+ * section and create a Child FunctionTemplate by:
+ *
+ * \code
+ * Local<FunctionTemplate> parent = t;
+ * Local<FunctionTemplate> child = FunctionTemplate::New();
+ * child->Inherit(parent);
+ *
+ * Local<Function> child_function = child->GetFunction();
+ * Local<Object> child_instance = child_function->NewInstance();
+ * \endcode
+ *
+ * The Child function and Child instance will have the following
+ * properties:
+ *
+ * \code
+ * child_func.prototype.__proto__ == function.prototype;
+ * child_instance.instance_accessor calls 'InstanceAccessorCallback'
+ * child_instance.instance_property == 3;
+ * \endcode
+ */
+class V8EXPORT FunctionTemplate : public Template {
+ public:
+ /** Creates a function template.*/
+ static Local<FunctionTemplate> New(
+ InvocationCallback callback = 0,
+ Handle<Value> data = Handle<Value>(),
+ Handle<Signature> signature = Handle<Signature>());
+ /** Returns the unique function instance in the current execution context.*/
+ Local<Function> GetFunction();
+
+ /**
+ * Set the call-handler callback for a FunctionTemplate. This
+ * callback is called whenever the function created from this
+ * FunctionTemplate is called.
+ */
+ void SetCallHandler(InvocationCallback callback,
+ Handle<Value> data = Handle<Value>());
+
+ /** Get the InstanceTemplate. */
+ Local<ObjectTemplate> InstanceTemplate();
+
+ /** Causes the function template to inherit from a parent function template.*/
+ void Inherit(Handle<FunctionTemplate> parent);
+
+ /**
+ * A PrototypeTemplate is the template used to create the prototype object
+ * of the function created by this template.
+ */
+ Local<ObjectTemplate> PrototypeTemplate();
+
+
+ /**
+ * Set the class name of the FunctionTemplate. This is used for
+ * printing objects created with the function created from the
+ * FunctionTemplate as its constructor.
+ */
+ void SetClassName(Handle<String> name);
+
+ /**
+ * Determines whether the __proto__ accessor ignores instances of
+ * the function template. If instances of the function template are
+ * ignored, __proto__ skips all instances and instead returns the
+ * next object in the prototype chain.
+ *
+ * Call with a value of true to make the __proto__ accessor ignore
+ * instances of the function template. Call with a value of false
+ * to make the __proto__ accessor not ignore instances of the
+ * function template. By default, instances of a function template
+ * are not ignored.
+ */
+ void SetHiddenPrototype(bool value);
+
+ /**
+ * Returns true if the given object is an instance of this function
+ * template.
+ */
+ bool HasInstance(Handle<Value> object);
+
+ private:
+ FunctionTemplate();
+ void AddInstancePropertyAccessor(Handle<String> name,
+ AccessorGetter getter,
+ AccessorSetter setter,
+ Handle<Value> data,
+ AccessControl settings,
+ PropertyAttribute attributes);
+ void SetNamedInstancePropertyHandler(NamedPropertyGetter getter,
+ NamedPropertySetter setter,
+ NamedPropertyQuery query,
+ NamedPropertyDeleter remover,
+ NamedPropertyEnumerator enumerator,
+ Handle<Value> data);
+ void SetIndexedInstancePropertyHandler(IndexedPropertyGetter getter,
+ IndexedPropertySetter setter,
+ IndexedPropertyQuery query,
+ IndexedPropertyDeleter remover,
+ IndexedPropertyEnumerator enumerator,
+ Handle<Value> data);
+ void SetInstanceCallAsFunctionHandler(InvocationCallback callback,
+ Handle<Value> data);
+
+ friend class Context;
+ friend class ObjectTemplate;
+};
+
+
+/**
+ * An ObjectTemplate is used to create objects at runtime.
+ *
+ * Properties added to an ObjectTemplate are added to each object
+ * created from the ObjectTemplate.
+ */
+class V8EXPORT ObjectTemplate : public Template {
+ public:
+ /** Creates an ObjectTemplate. */
+ static Local<ObjectTemplate> New();
+
+ /** Creates a new instance of this template.*/
+ Local<Object> NewInstance();
+
+ /**
+ * Sets an accessor on the object template.
+ *
+ * Whenever the property with the given name is accessed on objects
+ * created from this ObjectTemplate the getter and setter callbacks
+ * are called instead of getting and setting the property directly
+ * on the JavaScript object.
+ *
+ * \param name The name of the property for which an accessor is added.
+ * \param getter The callback to invoke when getting the property.
+ * \param setter The callback to invoke when setting the property.
+ * \param data A piece of data that will be passed to the getter and setter
+ * callbacks whenever they are invoked.
+ * \param settings Access control settings for the accessor. This is a bit
+ * field consisting of one of more of
+ * DEFAULT = 0, ALL_CAN_READ = 1, or ALL_CAN_WRITE = 2.
+ * The default is to not allow cross-context access.
+ * ALL_CAN_READ means that all cross-context reads are allowed.
+ * ALL_CAN_WRITE means that all cross-context writes are allowed.
+ * The combination ALL_CAN_READ | ALL_CAN_WRITE can be used to allow all
+ * cross-context access.
+ * \param attribute The attributes of the property for which an accessor
+ * is added.
+ */
+ void SetAccessor(Handle<String> name,
+ AccessorGetter getter,
+ AccessorSetter setter = 0,
+ Handle<Value> data = Handle<Value>(),
+ AccessControl settings = DEFAULT,
+ PropertyAttribute attribute = None);
+
+ /**
+ * Sets a named property handler on the object template.
+ *
+ * Whenever a named property is accessed on objects created from
+ * this object template, the provided callback is invoked instead of
+ * accessing the property directly on the JavaScript object.
+ *
+ * \param getter The callback to invoke when getting a property.
+ * \param setter The callback to invoke when setting a property.
+ * \param query The callback to invoke to check if a property is present,
+ * and if present, get its attributes.
+ * \param deleter The callback to invoke when deleting a property.
+ * \param enumerator The callback to invoke to enumerate all the named
+ * properties of an object.
+ * \param data A piece of data that will be passed to the callbacks
+ * whenever they are invoked.
+ */
+ void SetNamedPropertyHandler(NamedPropertyGetter getter,
+ NamedPropertySetter setter = 0,
+ NamedPropertyQuery query = 0,
+ NamedPropertyDeleter deleter = 0,
+ NamedPropertyEnumerator enumerator = 0,
+ Handle<Value> data = Handle<Value>());
+
+ /**
+ * Sets an indexed property handler on the object template.
+ *
+ * Whenever an indexed property is accessed on objects created from
+ * this object template, the provided callback is invoked instead of
+ * accessing the property directly on the JavaScript object.
+ *
+ * \param getter The callback to invoke when getting a property.
+ * \param setter The callback to invoke when setting a property.
+ * \param query The callback to invoke to check is an object has a property.
+ * \param deleter The callback to invoke when deleting a property.
+ * \param enumerator The callback to invoke to enumerate all the indexed
+ * properties of an object.
+ * \param data A piece of data that will be passed to the callbacks
+ * whenever they are invoked.
+ */
+ void SetIndexedPropertyHandler(IndexedPropertyGetter getter,
+ IndexedPropertySetter setter = 0,
+ IndexedPropertyQuery query = 0,
+ IndexedPropertyDeleter deleter = 0,
+ IndexedPropertyEnumerator enumerator = 0,
+ Handle<Value> data = Handle<Value>());
+
+ /**
+ * Sets the callback to be used when calling instances created from
+ * this template as a function. If no callback is set, instances
+ * behave like normal JavaScript objects that cannot be called as a
+ * function.
+ */
+ void SetCallAsFunctionHandler(InvocationCallback callback,
+ Handle<Value> data = Handle<Value>());
+
+ /**
+ * Mark object instances of the template as undetectable.
+ *
+ * In many ways, undetectable objects behave as though they are not
+ * there. They behave like 'undefined' in conditionals and when
+ * printed. However, properties can be accessed and called as on
+ * normal objects.
+ */
+ void MarkAsUndetectable();
+
+ /**
+ * Sets access check callbacks on the object template.
+ *
+ * When accessing properties on instances of this object template,
+ * the access check callback will be called to determine whether or
+ * not to allow cross-context access to the properties.
+ * The last parameter specifies whether access checks are turned
+ * on by default on instances. If access checks are off by default,
+ * they can be turned on on individual instances by calling
+ * Object::TurnOnAccessCheck().
+ */
+ void SetAccessCheckCallbacks(NamedSecurityCallback named_handler,
+ IndexedSecurityCallback indexed_handler,
+ Handle<Value> data = Handle<Value>(),
+ bool turned_on_by_default = true);
+
+ /**
+ * Gets the number of internal fields for objects generated from
+ * this template.
+ */
+ int InternalFieldCount();
+
+ /**
+ * Sets the number of internal fields for objects generated from
+ * this template.
+ */
+ void SetInternalFieldCount(int value);
+
+ private:
+ ObjectTemplate();
+ static Local<ObjectTemplate> New(Handle<FunctionTemplate> constructor);
+ friend class FunctionTemplate;
+};
+
+
+/**
+ * A Signature specifies which receivers and arguments a function can
+ * legally be called with.
+ */
+class V8EXPORT Signature : public Data {
+ public:
+ static Local<Signature> New(Handle<FunctionTemplate> receiver =
+ Handle<FunctionTemplate>(),
+ int argc = 0,
+ Handle<FunctionTemplate> argv[] = 0);
+ private:
+ Signature();
+};
+
+
+/**
+ * A utility for determining the type of objects based on the template
+ * they were constructed from.
+ */
+class V8EXPORT TypeSwitch : public Data {
+ public:
+ static Local<TypeSwitch> New(Handle<FunctionTemplate> type);
+ static Local<TypeSwitch> New(int argc, Handle<FunctionTemplate> types[]);
+ int match(Handle<Value> value);
+ private:
+ TypeSwitch();
+};
+
+
+// --- E x t e n s i o n s ---
+
+
+/**
+ * Ignore
+ */
+class V8EXPORT Extension { // NOLINT
+ public:
+ Extension(const char* name,
+ const char* source = 0,
+ int dep_count = 0,
+ const char** deps = 0);
+ virtual ~Extension() { }
+ virtual v8::Handle<v8::FunctionTemplate>
+ GetNativeFunction(v8::Handle<v8::String> name) {
+ return v8::Handle<v8::FunctionTemplate>();
+ }
+
+ const char* name() { return name_; }
+ const char* source() { return source_; }
+ int dependency_count() { return dep_count_; }
+ const char** dependencies() { return deps_; }
+ void set_auto_enable(bool value) { auto_enable_ = value; }
+ bool auto_enable() { return auto_enable_; }
+
+ private:
+ const char* name_;
+ const char* source_;
+ int dep_count_;
+ const char** deps_;
+ bool auto_enable_;
+
+ // Disallow copying and assigning.
+ Extension(const Extension&);
+ void operator=(const Extension&);
+};
+
+
+void V8EXPORT RegisterExtension(Extension* extension);
+
+
+/**
+ * Ignore
+ */
+class V8EXPORT DeclareExtension {
+ public:
+ inline DeclareExtension(Extension* extension) {
+ RegisterExtension(extension);
+ }
+};
+
+
+// --- S t a t i c s ---
+
+
+Handle<Primitive> V8EXPORT Undefined();
+Handle<Primitive> V8EXPORT Null();
+Handle<Boolean> V8EXPORT True();
+Handle<Boolean> V8EXPORT False();
+
+
+/**
+ * A set of constraints that specifies the limits of the runtime's memory use.
+ * You must set the heap size before initializing the VM - the size cannot be
+ * adjusted after the VM is initialized.
+ *
+ * If you are using threads then you should hold the V8::Locker lock while
+ * setting the stack limit and you must set a non-default stack limit separately
+ * for each thread.
+ */
+class V8EXPORT ResourceConstraints {
+ public:
+ ResourceConstraints();
+ int max_young_space_size() const { return max_young_space_size_; }
+ void set_max_young_space_size(int value) { max_young_space_size_ = value; }
+ int max_old_space_size() const { return max_old_space_size_; }
+ void set_max_old_space_size(int value) { max_old_space_size_ = value; }
+ uint32_t* stack_limit() const { return stack_limit_; }
+ // Sets an address beyond which the VM's stack may not grow.
+ void set_stack_limit(uint32_t* value) { stack_limit_ = value; }
+ private:
+ int max_young_space_size_;
+ int max_old_space_size_;
+ uint32_t* stack_limit_;
+};
+
+
+bool V8EXPORT SetResourceConstraints(ResourceConstraints* constraints);
+
+
+// --- E x c e p t i o n s ---
+
+
+typedef void (*FatalErrorCallback)(const char* location, const char* message);
+
+
+typedef void (*MessageCallback)(Handle<Message> message, Handle<Value> data);
+
+
+/**
+ * Schedules an exception to be thrown when returning to JavaScript. When an
+ * exception has been scheduled it is illegal to invoke any JavaScript
+ * operation; the caller must return immediately and only after the exception
+ * has been handled does it become legal to invoke JavaScript operations.
+ */
+Handle<Value> V8EXPORT ThrowException(Handle<Value> exception);
+
+/**
+ * Create new error objects by calling the corresponding error object
+ * constructor with the message.
+ */
+class V8EXPORT Exception {
+ public:
+ static Local<Value> RangeError(Handle<String> message);
+ static Local<Value> ReferenceError(Handle<String> message);
+ static Local<Value> SyntaxError(Handle<String> message);
+ static Local<Value> TypeError(Handle<String> message);
+ static Local<Value> Error(Handle<String> message);
+};
+
+
+// --- C o u n t e r s C a l l b a c k s ---
+
+typedef int* (*CounterLookupCallback)(const char* name);
+
+typedef void* (*CreateHistogramCallback)(const char* name,
+ int min,
+ int max,
+ size_t buckets);
+
+typedef void (*AddHistogramSampleCallback)(void* histogram, int sample);
+
+// --- M e m o r y A l l o c a t i o n C a l l b a c k ---
+ enum ObjectSpace {
+ kObjectSpaceNewSpace = 1 << 0,
+ kObjectSpaceOldPointerSpace = 1 << 1,
+ kObjectSpaceOldDataSpace = 1 << 2,
+ kObjectSpaceCodeSpace = 1 << 3,
+ kObjectSpaceMapSpace = 1 << 4,
+ kObjectSpaceLoSpace = 1 << 5,
+
+ kObjectSpaceAll = kObjectSpaceNewSpace | kObjectSpaceOldPointerSpace |
+ kObjectSpaceOldDataSpace | kObjectSpaceCodeSpace | kObjectSpaceMapSpace |
+ kObjectSpaceLoSpace
+ };
+
+ enum AllocationAction {
+ kAllocationActionAllocate = 1 << 0,
+ kAllocationActionFree = 1 << 1,
+ kAllocationActionAll = kAllocationActionAllocate | kAllocationActionFree
+ };
+
+typedef void (*MemoryAllocationCallback)(ObjectSpace space,
+ AllocationAction action,
+ int size);
+
+// --- F a i l e d A c c e s s C h e c k C a l l b a c k ---
+typedef void (*FailedAccessCheckCallback)(Local<Object> target,
+ AccessType type,
+ Local<Value> data);
+
+// --- G a r b a g e C o l l e c t i o n C a l l b a c k s
+
+/**
+ * Applications can register callback functions which will be called
+ * before and after a garbage collection. Allocations are not
+ * allowed in the callback functions, you therefore cannot manipulate
+ * objects (set or delete properties for example) since it is possible
+ * such operations will result in the allocation of objects.
+ */
+enum GCType {
+ kGCTypeScavenge = 1 << 0,
+ kGCTypeMarkSweepCompact = 1 << 1,
+ kGCTypeAll = kGCTypeScavenge | kGCTypeMarkSweepCompact
+};
+
+enum GCCallbackFlags {
+ kNoGCCallbackFlags = 0,
+ kGCCallbackFlagCompacted = 1 << 0
+};
+
+typedef void (*GCPrologueCallback)(GCType type, GCCallbackFlags flags);
+typedef void (*GCEpilogueCallback)(GCType type, GCCallbackFlags flags);
+
+typedef void (*GCCallback)();
+
+
+/**
+ * Profiler modules.
+ *
+ * In V8, profiler consists of several modules: CPU profiler, and different
+ * kinds of heap profiling. Each can be turned on / off independently.
+ * When PROFILER_MODULE_HEAP_SNAPSHOT flag is passed to ResumeProfilerEx,
+ * modules are enabled only temporarily for making a snapshot of the heap.
+ */
+enum ProfilerModules {
+ PROFILER_MODULE_NONE = 0,
+ PROFILER_MODULE_CPU = 1,
+ PROFILER_MODULE_HEAP_STATS = 1 << 1,
+ PROFILER_MODULE_JS_CONSTRUCTORS = 1 << 2,
+ PROFILER_MODULE_HEAP_SNAPSHOT = 1 << 16
+};
+
+
+/**
+ * Collection of V8 heap information.
+ *
+ * Instances of this class can be passed to v8::V8::HeapStatistics to
+ * get heap statistics from V8.
+ */
+class V8EXPORT HeapStatistics {
+ public:
+ HeapStatistics();
+ size_t total_heap_size() { return total_heap_size_; }
+ size_t used_heap_size() { return used_heap_size_; }
+
+ private:
+ void set_total_heap_size(size_t size) { total_heap_size_ = size; }
+ void set_used_heap_size(size_t size) { used_heap_size_ = size; }
+
+ size_t total_heap_size_;
+ size_t used_heap_size_;
+
+ friend class V8;
+};
+
+
+/**
+ * Container class for static utility functions.
+ */
+class V8EXPORT V8 {
+ public:
+ /** Set the callback to invoke in case of fatal errors. */
+ static void SetFatalErrorHandler(FatalErrorCallback that);
+
+ /**
+ * Ignore out-of-memory exceptions.
+ *
+ * V8 running out of memory is treated as a fatal error by default.
+ * This means that the fatal error handler is called and that V8 is
+ * terminated.
+ *
+ * IgnoreOutOfMemoryException can be used to not treat a
+ * out-of-memory situation as a fatal error. This way, the contexts
+ * that did not cause the out of memory problem might be able to
+ * continue execution.
+ */
+ static void IgnoreOutOfMemoryException();
+
+ /**
+ * Check if V8 is dead and therefore unusable. This is the case after
+ * fatal errors such as out-of-memory situations.
+ */
+ static bool IsDead();
+
+ /**
+ * Adds a message listener.
+ *
+ * The same message listener can be added more than once and it that
+ * case it will be called more than once for each message.
+ */
+ static bool AddMessageListener(MessageCallback that,
+ Handle<Value> data = Handle<Value>());
+
+ /**
+ * Remove all message listeners from the specified callback function.
+ */
+ static void RemoveMessageListeners(MessageCallback that);
+
+ /**
+ * Tells V8 to capture current stack trace when uncaught exception occurs
+ * and report it to the message listeners. The option is off by default.
+ */
+ static void SetCaptureStackTraceForUncaughtExceptions(
+ bool capture,
+ int frame_limit = 10,
+ StackTrace::StackTraceOptions options = StackTrace::kOverview);
+
+ /**
+ * Sets V8 flags from a string.
+ */
+ static void SetFlagsFromString(const char* str, int length);
+
+ /**
+ * Sets V8 flags from the command line.
+ */
+ static void SetFlagsFromCommandLine(int* argc,
+ char** argv,
+ bool remove_flags);
+
+ /** Get the version string. */
+ static const char* GetVersion();
+
+ /**
+ * Enables the host application to provide a mechanism for recording
+ * statistics counters.
+ */
+ static void SetCounterFunction(CounterLookupCallback);
+
+ /**
+ * Enables the host application to provide a mechanism for recording
+ * histograms. The CreateHistogram function returns a
+ * histogram which will later be passed to the AddHistogramSample
+ * function.
+ */
+ static void SetCreateHistogramFunction(CreateHistogramCallback);
+ static void SetAddHistogramSampleFunction(AddHistogramSampleCallback);
+
+ /**
+ * Enables the computation of a sliding window of states. The sliding
+ * window information is recorded in statistics counters.
+ */
+ static void EnableSlidingStateWindow();
+
+ /** Callback function for reporting failed access checks.*/
+ static void SetFailedAccessCheckCallbackFunction(FailedAccessCheckCallback);
+
+ /**
+ * Enables the host application to receive a notification before a
+ * garbage collection. Allocations are not allowed in the
+ * callback function, you therefore cannot manipulate objects (set
+ * or delete properties for example) since it is possible such
+ * operations will result in the allocation of objects. It is possible
+ * to specify the GCType filter for your callback. But it is not possible to
+ * register the same callback function two times with different
+ * GCType filters.
+ */
+ static void AddGCPrologueCallback(
+ GCPrologueCallback callback, GCType gc_type_filter = kGCTypeAll);
+
+ /**
+ * This function removes callback which was installed by
+ * AddGCPrologueCallback function.
+ */
+ static void RemoveGCPrologueCallback(GCPrologueCallback callback);
+
+ /**
+ * The function is deprecated. Please use AddGCPrologueCallback instead.
+ * Enables the host application to receive a notification before a
+ * garbage collection. Allocations are not allowed in the
+ * callback function, you therefore cannot manipulate objects (set
+ * or delete properties for example) since it is possible such
+ * operations will result in the allocation of objects.
+ */
+ static void SetGlobalGCPrologueCallback(GCCallback);
+
+ /**
+ * Enables the host application to receive a notification after a
+ * garbage collection. Allocations are not allowed in the
+ * callback function, you therefore cannot manipulate objects (set
+ * or delete properties for example) since it is possible such
+ * operations will result in the allocation of objects. It is possible
+ * to specify the GCType filter for your callback. But it is not possible to
+ * register the same callback function two times with different
+ * GCType filters.
+ */
+ static void AddGCEpilogueCallback(
+ GCEpilogueCallback callback, GCType gc_type_filter = kGCTypeAll);
+
+ /**
+ * This function removes callback which was installed by
+ * AddGCEpilogueCallback function.
+ */
+ static void RemoveGCEpilogueCallback(GCEpilogueCallback callback);
+
+ /**
+ * The function is deprecated. Please use AddGCEpilogueCallback instead.
+ * Enables the host application to receive a notification after a
+ * major garbage collection. Allocations are not allowed in the
+ * callback function, you therefore cannot manipulate objects (set
+ * or delete properties for example) since it is possible such
+ * operations will result in the allocation of objects.
+ */
+ static void SetGlobalGCEpilogueCallback(GCCallback);
+
+ /**
+ * Enables the host application to provide a mechanism to be notified
+ * and perform custom logging when V8 Allocates Executable Memory.
+ */
+ static void AddMemoryAllocationCallback(MemoryAllocationCallback callback,
+ ObjectSpace space,
+ AllocationAction action);
+
+ /**
+ * This function removes callback which was installed by
+ * AddMemoryAllocationCallback function.
+ */
+ static void RemoveMemoryAllocationCallback(MemoryAllocationCallback callback);
+
+ /**
+ * Allows the host application to group objects together. If one
+ * object in the group is alive, all objects in the group are alive.
+ * After each garbage collection, object groups are removed. It is
+ * intended to be used in the before-garbage-collection callback
+ * function, for instance to simulate DOM tree connections among JS
+ * wrapper objects.
+ */
+ static void AddObjectGroup(Persistent<Value>* objects, size_t length);
+
+ /**
+ * Initializes from snapshot if possible. Otherwise, attempts to
+ * initialize from scratch. This function is called implicitly if
+ * you use the API without calling it first.
+ */
+ static bool Initialize();
+
+ /**
+ * Adjusts the amount of registered external memory. Used to give
+ * V8 an indication of the amount of externally allocated memory
+ * that is kept alive by JavaScript objects. V8 uses this to decide
+ * when to perform global garbage collections. Registering
+ * externally allocated memory will trigger global garbage
+ * collections more often than otherwise in an attempt to garbage
+ * collect the JavaScript objects keeping the externally allocated
+ * memory alive.
+ *
+ * \param change_in_bytes the change in externally allocated memory
+ * that is kept alive by JavaScript objects.
+ * \returns the adjusted value.
+ */
+ static int AdjustAmountOfExternalAllocatedMemory(int change_in_bytes);
+
+ /**
+ * Suspends recording of tick samples in the profiler.
+ * When the V8 profiling mode is enabled (usually via command line
+ * switches) this function suspends recording of tick samples.
+ * Profiling ticks are discarded until ResumeProfiler() is called.
+ *
+ * See also the --prof and --prof_auto command line switches to
+ * enable V8 profiling.
+ */
+ static void PauseProfiler();
+
+ /**
+ * Resumes recording of tick samples in the profiler.
+ * See also PauseProfiler().
+ */
+ static void ResumeProfiler();
+
+ /**
+ * Return whether profiler is currently paused.
+ */
+ static bool IsProfilerPaused();
+
+ /**
+ * Resumes specified profiler modules. Can be called several times to
+ * mark the opening of a profiler events block with the given tag.
+ *
+ * "ResumeProfiler" is equivalent to "ResumeProfilerEx(PROFILER_MODULE_CPU)".
+ * See ProfilerModules enum.
+ *
+ * \param flags Flags specifying profiler modules.
+ * \param tag Profile tag.
+ */
+ static void ResumeProfilerEx(int flags, int tag = 0);
+
+ /**
+ * Pauses specified profiler modules. Each call to "PauseProfilerEx" closes
+ * a block of profiler events opened by a call to "ResumeProfilerEx" with the
+ * same tag value. There is no need for blocks to be properly nested.
+ * The profiler is paused when the last opened block is closed.
+ *
+ * "PauseProfiler" is equivalent to "PauseProfilerEx(PROFILER_MODULE_CPU)".
+ * See ProfilerModules enum.
+ *
+ * \param flags Flags specifying profiler modules.
+ * \param tag Profile tag.
+ */
+ static void PauseProfilerEx(int flags, int tag = 0);
+
+ /**
+ * Returns active (resumed) profiler modules.
+ * See ProfilerModules enum.
+ *
+ * \returns active profiler modules.
+ */
+ static int GetActiveProfilerModules();
+
+ /**
+ * If logging is performed into a memory buffer (via --logfile=*), allows to
+ * retrieve previously written messages. This can be used for retrieving
+ * profiler log data in the application. This function is thread-safe.
+ *
+ * Caller provides a destination buffer that must exist during GetLogLines
+ * call. Only whole log lines are copied into the buffer.
+ *
+ * \param from_pos specified a point in a buffer to read from, 0 is the
+ * beginning of a buffer. It is assumed that caller updates its current
+ * position using returned size value from the previous call.
+ * \param dest_buf destination buffer for log data.
+ * \param max_size size of the destination buffer.
+ * \returns actual size of log data copied into buffer.
+ */
+ static int GetLogLines(int from_pos, char* dest_buf, int max_size);
+
+ /**
+ * The minimum allowed size for a log lines buffer. If the size of
+ * the buffer given will not be enough to hold a line of the maximum
+ * length, an attempt to find a log line end in GetLogLines will
+ * fail, and an empty result will be returned.
+ */
+ static const int kMinimumSizeForLogLinesBuffer = 2048;
+
+ /**
+ * Retrieve the V8 thread id of the calling thread.
+ *
+ * The thread id for a thread should only be retrieved after the V8
+ * lock has been acquired with a Locker object with that thread.
+ */
+ static int GetCurrentThreadId();
+
+ /**
+ * Forcefully terminate execution of a JavaScript thread. This can
+ * be used to terminate long-running scripts.
+ *
+ * TerminateExecution should only be called when then V8 lock has
+ * been acquired with a Locker object. Therefore, in order to be
+ * able to terminate long-running threads, preemption must be
+ * enabled to allow the user of TerminateExecution to acquire the
+ * lock.
+ *
+ * The termination is achieved by throwing an exception that is
+ * uncatchable by JavaScript exception handlers. Termination
+ * exceptions act as if they were caught by a C++ TryCatch exception
+ * handlers. If forceful termination is used, any C++ TryCatch
+ * exception handler that catches an exception should check if that
+ * exception is a termination exception and immediately return if
+ * that is the case. Returning immediately in that case will
+ * continue the propagation of the termination exception if needed.
+ *
+ * The thread id passed to TerminateExecution must have been
+ * obtained by calling GetCurrentThreadId on the thread in question.
+ *
+ * \param thread_id The thread id of the thread to terminate.
+ */
+ static void TerminateExecution(int thread_id);
+
+ /**
+ * Forcefully terminate the current thread of JavaScript execution.
+ *
+ * This method can be used by any thread even if that thread has not
+ * acquired the V8 lock with a Locker object.
+ */
+ static void TerminateExecution();
+
+ /**
+ * Is V8 terminating JavaScript execution.
+ *
+ * Returns true if JavaScript execution is currently terminating
+ * because of a call to TerminateExecution. In that case there are
+ * still JavaScript frames on the stack and the termination
+ * exception is still active.
+ */
+ static bool IsExecutionTerminating();
+
+ /**
+ * Releases any resources used by v8 and stops any utility threads
+ * that may be running. Note that disposing v8 is permanent, it
+ * cannot be reinitialized.
+ *
+ * It should generally not be necessary to dispose v8 before exiting
+ * a process, this should happen automatically. It is only necessary
+ * to use if the process needs the resources taken up by v8.
+ */
+ static bool Dispose();
+
+ /**
+ * Get statistics about the heap memory usage.
+ */
+ static void GetHeapStatistics(HeapStatistics* heap_statistics);
+
+ /**
+ * Optional notification that the embedder is idle.
+ * V8 uses the notification to reduce memory footprint.
+ * This call can be used repeatedly if the embedder remains idle.
+ * Returns true if the embedder should stop calling IdleNotification
+ * until real work has been done. This indicates that V8 has done
+ * as much cleanup as it will be able to do.
+ */
+ static bool IdleNotification();
+
+ /**
+ * Optional notification that the system is running low on memory.
+ * V8 uses these notifications to attempt to free memory.
+ */
+ static void LowMemoryNotification();
+
+ /**
+ * Optional notification that a context has been disposed. V8 uses
+ * these notifications to guide the GC heuristic. Returns the number
+ * of context disposals - including this one - since the last time
+ * V8 had a chance to clean up.
+ */
+ static int ContextDisposedNotification();
+
+ private:
+ V8();
+
+ static internal::Object** GlobalizeReference(internal::Object** handle);
+ static void DisposeGlobal(internal::Object** global_handle);
+ static void MakeWeak(internal::Object** global_handle,
+ void* data,
+ WeakReferenceCallback);
+ static void ClearWeak(internal::Object** global_handle);
+ static bool IsGlobalNearDeath(internal::Object** global_handle);
+ static bool IsGlobalWeak(internal::Object** global_handle);
+
+ template <class T> friend class Handle;
+ template <class T> friend class Local;
+ template <class T> friend class Persistent;
+ friend class Context;
+};
+
+
+/**
+ * An external exception handler.
+ */
+class V8EXPORT TryCatch {
+ public:
+
+ /**
+ * Creates a new try/catch block and registers it with v8.
+ */
+ TryCatch();
+
+ /**
+ * Unregisters and deletes this try/catch block.
+ */
+ ~TryCatch();
+
+ /**
+ * Returns true if an exception has been caught by this try/catch block.
+ */
+ bool HasCaught() const;
+
+ /**
+ * For certain types of exceptions, it makes no sense to continue
+ * execution.
+ *
+ * Currently, the only type of exception that can be caught by a
+ * TryCatch handler and for which it does not make sense to continue
+ * is termination exception. Such exceptions are thrown when the
+ * TerminateExecution methods are called to terminate a long-running
+ * script.
+ *
+ * If CanContinue returns false, the correct action is to perform
+ * any C++ cleanup needed and then return.
+ */
+ bool CanContinue() const;
+
+ /**
+ * Throws the exception caught by this TryCatch in a way that avoids
+ * it being caught again by this same TryCatch. As with ThrowException
+ * it is illegal to execute any JavaScript operations after calling
+ * ReThrow; the caller must return immediately to where the exception
+ * is caught.
+ */
+ Handle<Value> ReThrow();
+
+ /**
+ * Returns the exception caught by this try/catch block. If no exception has
+ * been caught an empty handle is returned.
+ *
+ * The returned handle is valid until this TryCatch block has been destroyed.
+ */
+ Local<Value> Exception() const;
+
+ /**
+ * Returns the .stack property of the thrown object. If no .stack
+ * property is present an empty handle is returned.
+ */
+ Local<Value> StackTrace() const;
+
+ /**
+ * Returns the message associated with this exception. If there is
+ * no message associated an empty handle is returned.
+ *
+ * The returned handle is valid until this TryCatch block has been
+ * destroyed.
+ */
+ Local<v8::Message> Message() const;
+
+ /**
+ * Clears any exceptions that may have been caught by this try/catch block.
+ * After this method has been called, HasCaught() will return false.
+ *
+ * It is not necessary to clear a try/catch block before using it again; if
+ * another exception is thrown the previously caught exception will just be
+ * overwritten. However, it is often a good idea since it makes it easier
+ * to determine which operation threw a given exception.
+ */
+ void Reset();
+
+ /**
+ * Set verbosity of the external exception handler.
+ *
+ * By default, exceptions that are caught by an external exception
+ * handler are not reported. Call SetVerbose with true on an
+ * external exception handler to have exceptions caught by the
+ * handler reported as if they were not caught.
+ */
+ void SetVerbose(bool value);
+
+ /**
+ * Set whether or not this TryCatch should capture a Message object
+ * which holds source information about where the exception
+ * occurred. True by default.
+ */
+ void SetCaptureMessage(bool value);
+
+ private:
+ void* next_;
+ void* exception_;
+ void* message_;
+ bool is_verbose_ : 1;
+ bool can_continue_ : 1;
+ bool capture_message_ : 1;
+ bool rethrow_ : 1;
+
+ friend class v8::internal::Top;
+};
+
+
+// --- C o n t e x t ---
+
+
+/**
+ * Ignore
+ */
+class V8EXPORT ExtensionConfiguration {
+ public:
+ ExtensionConfiguration(int name_count, const char* names[])
+ : name_count_(name_count), names_(names) { }
+ private:
+ friend class ImplementationUtilities;
+ int name_count_;
+ const char** names_;
+};
+
+
+/**
+ * A sandboxed execution context with its own set of built-in objects
+ * and functions.
+ */
+class V8EXPORT Context {
+ public:
+ /** Returns the global object of the context. */
+ Local<Object> Global();
+
+ /**
+ * Detaches the global object from its context before
+ * the global object can be reused to create a new context.
+ */
+ void DetachGlobal();
+
+ /**
+ * Reattaches a global object to a context. This can be used to
+ * restore the connection between a global object and a context
+ * after DetachGlobal has been called.
+ *
+ * \param global_object The global object to reattach to the
+ * context. For this to work, the global object must be the global
+ * object that was associated with this context before a call to
+ * DetachGlobal.
+ */
+ void ReattachGlobal(Handle<Object> global_object);
+
+ /** Creates a new context.
+ *
+ * Returns a persistent handle to the newly allocated context. This
+ * persistent handle has to be disposed when the context is no
+ * longer used so the context can be garbage collected.
+ */
+ static Persistent<Context> New(
+ ExtensionConfiguration* extensions = NULL,
+ Handle<ObjectTemplate> global_template = Handle<ObjectTemplate>(),
+ Handle<Value> global_object = Handle<Value>());
+
+ /** Returns the last entered context. */
+ static Local<Context> GetEntered();
+
+ /** Returns the context that is on the top of the stack. */
+ static Local<Context> GetCurrent();
+
+ /**
+ * Returns the context of the calling JavaScript code. That is the
+ * context of the top-most JavaScript frame. If there are no
+ * JavaScript frames an empty handle is returned.
+ */
+ static Local<Context> GetCalling();
+
+ /**
+ * Sets the security token for the context. To access an object in
+ * another context, the security tokens must match.
+ */
+ void SetSecurityToken(Handle<Value> token);
+
+ /** Restores the security token to the default value. */
+ void UseDefaultSecurityToken();
+
+ /** Returns the security token of this context.*/
+ Handle<Value> GetSecurityToken();
+
+ /**
+ * Enter this context. After entering a context, all code compiled
+ * and run is compiled and run in this context. If another context
+ * is already entered, this old context is saved so it can be
+ * restored when the new context is exited.
+ */
+ void Enter();
+
+ /**
+ * Exit this context. Exiting the current context restores the
+ * context that was in place when entering the current context.
+ */
+ void Exit();
+
+ /** Returns true if the context has experienced an out of memory situation. */
+ bool HasOutOfMemoryException();
+
+ /** Returns true if V8 has a current context. */
+ static bool InContext();
+
+ /**
+ * Associate an additional data object with the context. This is mainly used
+ * with the debugger to provide additional information on the context through
+ * the debugger API.
+ */
+ void SetData(Handle<String> data);
+ Local<Value> GetData();
+
+ /**
+ * Stack-allocated class which sets the execution context for all
+ * operations executed within a local scope.
+ */
+ class Scope {
+ public:
+ inline Scope(Handle<Context> context) : context_(context) {
+ context_->Enter();
+ }
+ inline ~Scope() { context_->Exit(); }
+ private:
+ Handle<Context> context_;
+ };
+
+ private:
+ friend class Value;
+ friend class Script;
+ friend class Object;
+ friend class Function;
+};
+
+
+/**
+ * Multiple threads in V8 are allowed, but only one thread at a time
+ * is allowed to use V8. The definition of 'using V8' includes
+ * accessing handles or holding onto object pointers obtained from V8
+ * handles. It is up to the user of V8 to ensure (perhaps with
+ * locking) that this constraint is not violated.
+ *
+ * If you wish to start using V8 in a thread you can do this by constructing
+ * a v8::Locker object. After the code using V8 has completed for the
+ * current thread you can call the destructor. This can be combined
+ * with C++ scope-based construction as follows:
+ *
+ * \code
+ * ...
+ * {
+ * v8::Locker locker;
+ * ...
+ * // Code using V8 goes here.
+ * ...
+ * } // Destructor called here
+ * \endcode
+ *
+ * If you wish to stop using V8 in a thread A you can do this by either
+ * by destroying the v8::Locker object as above or by constructing a
+ * v8::Unlocker object:
+ *
+ * \code
+ * {
+ * v8::Unlocker unlocker;
+ * ...
+ * // Code not using V8 goes here while V8 can run in another thread.
+ * ...
+ * } // Destructor called here.
+ * \endcode
+ *
+ * The Unlocker object is intended for use in a long-running callback
+ * from V8, where you want to release the V8 lock for other threads to
+ * use.
+ *
+ * The v8::Locker is a recursive lock. That is, you can lock more than
+ * once in a given thread. This can be useful if you have code that can
+ * be called either from code that holds the lock or from code that does
+ * not. The Unlocker is not recursive so you can not have several
+ * Unlockers on the stack at once, and you can not use an Unlocker in a
+ * thread that is not inside a Locker's scope.
+ *
+ * An unlocker will unlock several lockers if it has to and reinstate
+ * the correct depth of locking on its destruction. eg.:
+ *
+ * \code
+ * // V8 not locked.
+ * {
+ * v8::Locker locker;
+ * // V8 locked.
+ * {
+ * v8::Locker another_locker;
+ * // V8 still locked (2 levels).
+ * {
+ * v8::Unlocker unlocker;
+ * // V8 not locked.
+ * }
+ * // V8 locked again (2 levels).
+ * }
+ * // V8 still locked (1 level).
+ * }
+ * // V8 Now no longer locked.
+ * \endcode
+ */
+class V8EXPORT Unlocker {
+ public:
+ Unlocker();
+ ~Unlocker();
+};
+
+
+class V8EXPORT Locker {
+ public:
+ Locker();
+ ~Locker();
+
+ /**
+ * Start preemption.
+ *
+ * When preemption is started, a timer is fired every n milli seconds
+ * that will switch between multiple threads that are in contention
+ * for the V8 lock.
+ */
+ static void StartPreemption(int every_n_ms);
+
+ /**
+ * Stop preemption.
+ */
+ static void StopPreemption();
+
+ /**
+ * Returns whether or not the locker is locked by the current thread.
+ */
+ static bool IsLocked();
+
+ /**
+ * Returns whether v8::Locker is being used by this V8 instance.
+ */
+ static bool IsActive() { return active_; }
+
+ private:
+ bool has_lock_;
+ bool top_level_;
+
+ static bool active_;
+
+ // Disallow copying and assigning.
+ Locker(const Locker&);
+ void operator=(const Locker&);
+};
+
+
+/**
+ * An interface for exporting data from V8, using "push" model.
+ */
+class V8EXPORT OutputStream {
+public:
+ enum OutputEncoding {
+ kAscii = 0 // 7-bit ASCII.
+ };
+ enum WriteResult {
+ kContinue = 0,
+ kAbort = 1
+ };
+ virtual ~OutputStream() {}
+ /** Notify about the end of stream. */
+ virtual void EndOfStream() = 0;
+ /** Get preferred output chunk size. Called only once. */
+ virtual int GetChunkSize() { return 1024; }
+ /** Get preferred output encoding. Called only once. */
+ virtual OutputEncoding GetOutputEncoding() { return kAscii; }
+ /**
+ * Writes the next chunk of snapshot data into the stream. Writing
+ * can be stopped by returning kAbort as function result. EndOfStream
+ * will not be called in case writing was aborted.
+ */
+ virtual WriteResult WriteAsciiChunk(char* data, int size) = 0;
+};
+
+
+
+// --- I m p l e m e n t a t i o n ---
+
+
+namespace internal {
+
+
+// Tag information for HeapObject.
+const int kHeapObjectTag = 1;
+const int kHeapObjectTagSize = 2;
+const intptr_t kHeapObjectTagMask = (1 << kHeapObjectTagSize) - 1;
+
+// Tag information for Smi.
+const int kSmiTag = 0;
+const int kSmiTagSize = 1;
+const intptr_t kSmiTagMask = (1 << kSmiTagSize) - 1;
+
+template <size_t ptr_size> struct SmiConstants;
+
+// Smi constants for 32-bit systems.
+template <> struct SmiConstants<4> {
+ static const int kSmiShiftSize = 0;
+ static const int kSmiValueSize = 31;
+ static inline int SmiToInt(internal::Object* value) {
+ int shift_bits = kSmiTagSize + kSmiShiftSize;
+ // Throw away top 32 bits and shift down (requires >> to be sign extending).
+ return static_cast<int>(reinterpret_cast<intptr_t>(value)) >> shift_bits;
+ }
+};
+
+// Smi constants for 64-bit systems.
+template <> struct SmiConstants<8> {
+ static const int kSmiShiftSize = 31;
+ static const int kSmiValueSize = 32;
+ static inline int SmiToInt(internal::Object* value) {
+ int shift_bits = kSmiTagSize + kSmiShiftSize;
+ // Shift down and throw away top 32 bits.
+ return static_cast<int>(reinterpret_cast<intptr_t>(value) >> shift_bits);
+ }
+};
+
+const int kSmiShiftSize = SmiConstants<sizeof(void*)>::kSmiShiftSize;
+const int kSmiValueSize = SmiConstants<sizeof(void*)>::kSmiValueSize;
+
+template <size_t ptr_size> struct InternalConstants;
+
+// Internal constants for 32-bit systems.
+template <> struct InternalConstants<4> {
+ static const int kStringResourceOffset = 3 * sizeof(void*);
+};
+
+// Internal constants for 64-bit systems.
+template <> struct InternalConstants<8> {
+ static const int kStringResourceOffset = 3 * sizeof(void*);
+};
+
+/**
+ * This class exports constants and functionality from within v8 that
+ * is necessary to implement inline functions in the v8 api. Don't
+ * depend on functions and constants defined here.
+ */
+class Internals {
+ public:
+
+ // These values match non-compiler-dependent values defined within
+ // the implementation of v8.
+ static const int kHeapObjectMapOffset = 0;
+ static const int kMapInstanceTypeOffset = sizeof(void*) + sizeof(int);
+ static const int kStringResourceOffset =
+ InternalConstants<sizeof(void*)>::kStringResourceOffset;
+
+ static const int kProxyProxyOffset = sizeof(void*);
+ static const int kJSObjectHeaderSize = 3 * sizeof(void*);
+ static const int kFullStringRepresentationMask = 0x07;
+ static const int kExternalTwoByteRepresentationTag = 0x02;
+
+ static const int kJSObjectType = 0x9f;
+ static const int kFirstNonstringType = 0x80;
+ static const int kProxyType = 0x85;
+
+ static inline bool HasHeapObjectTag(internal::Object* value) {
+ return ((reinterpret_cast<intptr_t>(value) & kHeapObjectTagMask) ==
+ kHeapObjectTag);
+ }
+
+ static inline bool HasSmiTag(internal::Object* value) {
+ return ((reinterpret_cast<intptr_t>(value) & kSmiTagMask) == kSmiTag);
+ }
+
+ static inline int SmiValue(internal::Object* value) {
+ return SmiConstants<sizeof(void*)>::SmiToInt(value);
+ }
+
+ static inline int GetInstanceType(internal::Object* obj) {
+ typedef internal::Object O;
+ O* map = ReadField<O*>(obj, kHeapObjectMapOffset);
+ return ReadField<uint8_t>(map, kMapInstanceTypeOffset);
+ }
+
+ static inline void* GetExternalPointer(internal::Object* obj) {
+ if (HasSmiTag(obj)) {
+ return obj;
+ } else if (GetInstanceType(obj) == kProxyType) {
+ return ReadField<void*>(obj, kProxyProxyOffset);
+ } else {
+ return NULL;
+ }
+ }
+
+ static inline bool IsExternalTwoByteString(int instance_type) {
+ int representation = (instance_type & kFullStringRepresentationMask);
+ return representation == kExternalTwoByteRepresentationTag;
+ }
+
+ template <typename T>
+ static inline T ReadField(Object* ptr, int offset) {
+ uint8_t* addr = reinterpret_cast<uint8_t*>(ptr) + offset - kHeapObjectTag;
+ return *reinterpret_cast<T*>(addr);
+ }
+
+};
+
+}
+
+
+template <class T>
+Handle<T>::Handle() : val_(0) { }
+
+
+template <class T>
+Local<T>::Local() : Handle<T>() { }
+
+
+template <class T>
+Local<T> Local<T>::New(Handle<T> that) {
+ if (that.IsEmpty()) return Local<T>();
+ internal::Object** p = reinterpret_cast<internal::Object**>(*that);
+ return Local<T>(reinterpret_cast<T*>(HandleScope::CreateHandle(*p)));
+}
+
+
+template <class T>
+Persistent<T> Persistent<T>::New(Handle<T> that) {
+ if (that.IsEmpty()) return Persistent<T>();
+ internal::Object** p = reinterpret_cast<internal::Object**>(*that);
+ return Persistent<T>(reinterpret_cast<T*>(V8::GlobalizeReference(p)));
+}
+
+
+template <class T>
+bool Persistent<T>::IsNearDeath() const {
+ if (this->IsEmpty()) return false;
+ return V8::IsGlobalNearDeath(reinterpret_cast<internal::Object**>(**this));
+}
+
+
+template <class T>
+bool Persistent<T>::IsWeak() const {
+ if (this->IsEmpty()) return false;
+ return V8::IsGlobalWeak(reinterpret_cast<internal::Object**>(**this));
+}
+
+
+template <class T>
+void Persistent<T>::Dispose() {
+ if (this->IsEmpty()) return;
+ V8::DisposeGlobal(reinterpret_cast<internal::Object**>(**this));
+}
+
+
+template <class T>
+Persistent<T>::Persistent() : Handle<T>() { }
+
+template <class T>
+void Persistent<T>::MakeWeak(void* parameters, WeakReferenceCallback callback) {
+ V8::MakeWeak(reinterpret_cast<internal::Object**>(**this),
+ parameters,
+ callback);
+}
+
+template <class T>
+void Persistent<T>::ClearWeak() {
+ V8::ClearWeak(reinterpret_cast<internal::Object**>(**this));
+}
+
+
+Arguments::Arguments(v8::Local<v8::Value> data,
+ v8::Local<v8::Object> holder,
+ v8::Local<v8::Function> callee,
+ bool is_construct_call,
+ void** values, int length)
+ : data_(data), holder_(holder), callee_(callee),
+ is_construct_call_(is_construct_call),
+ values_(values), length_(length) { }
+
+
+Local<Value> Arguments::operator[](int i) const {
+ if (i < 0 || length_ <= i) return Local<Value>(*Undefined());
+ return Local<Value>(reinterpret_cast<Value*>(values_ - i));
+}
+
+
+Local<Function> Arguments::Callee() const {
+ return callee_;
+}
+
+
+Local<Object> Arguments::This() const {
+ return Local<Object>(reinterpret_cast<Object*>(values_ + 1));
+}
+
+
+Local<Object> Arguments::Holder() const {
+ return holder_;
+}
+
+
+Local<Value> Arguments::Data() const {
+ return data_;
+}
+
+
+bool Arguments::IsConstructCall() const {
+ return is_construct_call_;
+}
+
+
+int Arguments::Length() const {
+ return length_;
+}
+
+
+template <class T>
+Local<T> HandleScope::Close(Handle<T> value) {
+ internal::Object** before = reinterpret_cast<internal::Object**>(*value);
+ internal::Object** after = RawClose(before);
+ return Local<T>(reinterpret_cast<T*>(after));
+}
+
+Handle<Value> ScriptOrigin::ResourceName() const {
+ return resource_name_;
+}
+
+
+Handle<Integer> ScriptOrigin::ResourceLineOffset() const {
+ return resource_line_offset_;
+}
+
+
+Handle<Integer> ScriptOrigin::ResourceColumnOffset() const {
+ return resource_column_offset_;
+}
+
+
+Handle<Boolean> Boolean::New(bool value) {
+ return value ? True() : False();
+}
+
+
+void Template::Set(const char* name, v8::Handle<Data> value) {
+ Set(v8::String::New(name), value);
+}
+
+
+Local<Value> Object::GetInternalField(int index) {
+#ifndef V8_ENABLE_CHECKS
+ Local<Value> quick_result = UncheckedGetInternalField(index);
+ if (!quick_result.IsEmpty()) return quick_result;
+#endif
+ return CheckedGetInternalField(index);
+}
+
+
+Local<Value> Object::UncheckedGetInternalField(int index) {
+ typedef internal::Object O;
+ typedef internal::Internals I;
+ O* obj = *reinterpret_cast<O**>(this);
+ if (I::GetInstanceType(obj) == I::kJSObjectType) {
+ // If the object is a plain JSObject, which is the common case,
+ // we know where to find the internal fields and can return the
+ // value directly.
+ int offset = I::kJSObjectHeaderSize + (sizeof(void*) * index);
+ O* value = I::ReadField<O*>(obj, offset);
+ O** result = HandleScope::CreateHandle(value);
+ return Local<Value>(reinterpret_cast<Value*>(result));
+ } else {
+ return Local<Value>();
+ }
+}
+
+
+void* External::Unwrap(Handle<v8::Value> obj) {
+#ifdef V8_ENABLE_CHECKS
+ return FullUnwrap(obj);
+#else
+ return QuickUnwrap(obj);
+#endif
+}
+
+
+void* External::QuickUnwrap(Handle<v8::Value> wrapper) {
+ typedef internal::Object O;
+ O* obj = *reinterpret_cast<O**>(const_cast<v8::Value*>(*wrapper));
+ return internal::Internals::GetExternalPointer(obj);
+}
+
+
+void* Object::GetPointerFromInternalField(int index) {
+ typedef internal::Object O;
+ typedef internal::Internals I;
+
+ O* obj = *reinterpret_cast<O**>(this);
+
+ if (I::GetInstanceType(obj) == I::kJSObjectType) {
+ // If the object is a plain JSObject, which is the common case,
+ // we know where to find the internal fields and can return the
+ // value directly.
+ int offset = I::kJSObjectHeaderSize + (sizeof(void*) * index);
+ O* value = I::ReadField<O*>(obj, offset);
+ return I::GetExternalPointer(value);
+ }
+
+ return SlowGetPointerFromInternalField(index);
+}
+
+
+String* String::Cast(v8::Value* value) {
+#ifdef V8_ENABLE_CHECKS
+ CheckCast(value);
+#endif
+ return static_cast<String*>(value);
+}
+
+
+String::ExternalStringResource* String::GetExternalStringResource() const {
+ typedef internal::Object O;
+ typedef internal::Internals I;
+ O* obj = *reinterpret_cast<O**>(const_cast<String*>(this));
+ String::ExternalStringResource* result;
+ if (I::IsExternalTwoByteString(I::GetInstanceType(obj))) {
+ void* value = I::ReadField<void*>(obj, I::kStringResourceOffset);
+ result = reinterpret_cast<String::ExternalStringResource*>(value);
+ } else {
+ result = NULL;
+ }
+#ifdef V8_ENABLE_CHECKS
+ VerifyExternalStringResource(result);
+#endif
+ return result;
+}
+
+
+bool Value::IsString() const {
+#ifdef V8_ENABLE_CHECKS
+ return FullIsString();
+#else
+ return QuickIsString();
+#endif
+}
+
+bool Value::QuickIsString() const {
+ typedef internal::Object O;
+ typedef internal::Internals I;
+ O* obj = *reinterpret_cast<O**>(const_cast<Value*>(this));
+ if (!I::HasHeapObjectTag(obj)) return false;
+ return (I::GetInstanceType(obj) < I::kFirstNonstringType);
+}
+
+
+Number* Number::Cast(v8::Value* value) {
+#ifdef V8_ENABLE_CHECKS
+ CheckCast(value);
+#endif
+ return static_cast<Number*>(value);
+}
+
+
+Integer* Integer::Cast(v8::Value* value) {
+#ifdef V8_ENABLE_CHECKS
+ CheckCast(value);
+#endif
+ return static_cast<Integer*>(value);
+}
+
+
+Date* Date::Cast(v8::Value* value) {
+#ifdef V8_ENABLE_CHECKS
+ CheckCast(value);
+#endif
+ return static_cast<Date*>(value);
+}
+
+
+Object* Object::Cast(v8::Value* value) {
+#ifdef V8_ENABLE_CHECKS
+ CheckCast(value);
+#endif
+ return static_cast<Object*>(value);
+}
+
+
+Array* Array::Cast(v8::Value* value) {
+#ifdef V8_ENABLE_CHECKS
+ CheckCast(value);
+#endif
+ return static_cast<Array*>(value);
+}
+
+
+Function* Function::Cast(v8::Value* value) {
+#ifdef V8_ENABLE_CHECKS
+ CheckCast(value);
+#endif
+ return static_cast<Function*>(value);
+}
+
+
+External* External::Cast(v8::Value* value) {
+#ifdef V8_ENABLE_CHECKS
+ CheckCast(value);
+#endif
+ return static_cast<External*>(value);
+}
+
+
+Local<Value> AccessorInfo::Data() const {
+ return Local<Value>(reinterpret_cast<Value*>(&args_[-2]));
+}
+
+
+Local<Object> AccessorInfo::This() const {
+ return Local<Object>(reinterpret_cast<Object*>(&args_[0]));
+}
+
+
+Local<Object> AccessorInfo::Holder() const {
+ return Local<Object>(reinterpret_cast<Object*>(&args_[-1]));
+}
+
+
+/**
+ * \example shell.cc
+ * A simple shell that takes a list of expressions on the
+ * command-line and executes them.
+ */
+
+
+/**
+ * \example process.cc
+ */
+
+
+} // namespace v8
+
+
+#undef V8EXPORT
+#undef TYPE_CHECK
+
+
+#endif // V8_H_
diff --git a/plugins/Skins/libs/v8.lib b/plugins/Skins/libs/v8.lib
new file mode 100644
index 0000000000..b7a6809edc
--- /dev/null
+++ b/plugins/Skins/libs/v8.lib
Binary files differ
diff --git a/plugins/Skins/libs/v8_g.lib b/plugins/Skins/libs/v8_g.lib
new file mode 100644
index 0000000000..007c42932b
--- /dev/null
+++ b/plugins/Skins/libs/v8_g.lib
Binary files differ
diff --git a/plugins/Skins/options.cpp b/plugins/Skins/options.cpp
new file mode 100644
index 0000000000..086b7cb9eb
--- /dev/null
+++ b/plugins/Skins/options.cpp
@@ -0,0 +1,487 @@
+/*
+Copyright (C) 2008 Ricardo Pescuma Domenecci
+
+This is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this file; see the file license.txt. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+*/
+
+
+#include "commons.h"
+
+#include "options.h"
+
+
+
+// Prototypes /////////////////////////////////////////////////////////////////////////////////////
+
+HANDLE hOptHook = NULL;
+
+Options opts;
+
+
+static BOOL CALLBACK SkinOptDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+
+
+// Functions //////////////////////////////////////////////////////////////////////////////////////
+
+
+int InitOptionsCallback(WPARAM wParam,LPARAM lParam)
+{
+ OPTIONSDIALOGPAGE odp;
+ ZeroMemory(&odp, sizeof(odp));
+ odp.cbSize = sizeof(odp);
+ odp.position = 0;
+ odp.hInstance = hInst;
+ odp.pszGroup = "Skins";
+ odp.pszTab = "Skin";
+ odp.pfnDlgProc = SkinOptDlgProc;
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_SKIN_OPT);
+ odp.flags = ODPF_BOLDGROUPS;
+
+ for(unsigned int i = 0; i < dlgs.size(); i++)
+ {
+ MirandaSkinnedDialog * dlg = dlgs[i];
+ odp.pszTitle = (char *) dlg->getDescription(); // Yeah, yeah, I know...
+ odp.dwInitParam = (LPARAM) dlg;
+ CallService(MS_OPT_ADDPAGE, wParam, (LPARAM)&odp);
+ }
+
+ return 0;
+}
+
+
+void InitOptions()
+{
+ LoadOptions();
+
+ hOptHook = HookEvent(ME_OPT_INITIALISE, InitOptionsCallback);
+}
+
+
+void DeInitOptions()
+{
+ UnhookEvent(hOptHook);
+}
+
+
+void LoadOptions()
+{
+}
+
+static void GetTextMetric(HFONT hFont, TEXTMETRIC *tm)
+{
+ HDC hdc = GetDC(NULL);
+ HFONT hOldFont = (HFONT) SelectObject(hdc, hFont);
+ GetTextMetrics(hdc, tm);
+ SelectObject(hdc, hOldFont);
+ ReleaseDC(NULL, hdc);
+}
+
+
+static BOOL ScreenToClient(HWND hWnd, LPRECT lpRect)
+{
+ BOOL ret;
+
+ POINT pt;
+
+ pt.x = lpRect->left;
+ pt.y = lpRect->top;
+
+ ret = ScreenToClient(hWnd, &pt);
+
+ if (!ret) return ret;
+
+ lpRect->left = pt.x;
+ lpRect->top = pt.y;
+
+
+ pt.x = lpRect->right;
+ pt.y = lpRect->bottom;
+
+ ret = ScreenToClient(hWnd, &pt);
+
+ lpRect->right = pt.x;
+ lpRect->bottom = pt.y;
+
+ return ret;
+}
+
+
+#define V_SPACE 5
+#define H_INITIAL_SPACE 10
+#define MAX_TEXT_SIZE 128
+
+static BOOL CALLBACK SkinOptDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ MirandaSkinnedDialog * dlg = (MirandaSkinnedDialog *) lParam;
+ _ASSERT(dlg != NULL);
+ SetWindowLong(hwndDlg, GWL_USERDATA, (LONG) NULL);
+
+ std::vector<std::tstring> skins;
+ getAvaiableSkins(skins, dlg);
+ for(unsigned int i = 0; i < skins.size(); i++)
+ {
+ std::tstring &sk = skins[i];
+ SendDlgItemMessage(hwndDlg, IDC_SKIN, CB_ADDSTRING, 0, (LONG) skins[i].c_str());
+ }
+ SendDlgItemMessage(hwndDlg, IDC_SKIN, CB_SELECTSTRING, (WPARAM)-1, (LPARAM)dlg->getSkinName());
+
+ HWND skinOptsLabel = GetDlgItem(hwndDlg, IDC_SKIN_OPTS_L);
+
+ SkinOptions *opts = dlg->getOpts();
+ if (opts == NULL)
+ {
+ ShowWindow(skinOptsLabel, SW_HIDE);
+ ShowScrollBar(hwndDlg, SB_VERT, FALSE);
+ }
+ else
+ {
+ HWND skinLabel = GetDlgItem(hwndDlg, IDC_SKIN_L);
+ HWND skinCombo = GetDlgItem(hwndDlg, IDC_SKIN);
+
+ RECT labelRc = {0};
+ GetWindowRect(skinLabel, &labelRc);
+ ScreenToClient(hwndDlg, &labelRc);
+ labelRc.left += H_INITIAL_SPACE;
+
+ RECT valueRc = {0};
+ GetWindowRect(skinCombo, &valueRc);
+ ScreenToClient(hwndDlg, &valueRc);
+
+ RECT lineRc = {0};
+ GetWindowRect(skinOptsLabel, &lineRc);
+ ScreenToClient(hwndDlg, &lineRc);
+
+ HFONT hFont = (HFONT) SendMessage(hwndDlg, WM_GETFONT, 0, 0);
+ TEXTMETRIC font;
+ GetTextMetric(hFont, &font);
+
+ int lineHeight = max(font.tmHeight, 16) + 4;
+ int y = lineRc.bottom + V_SPACE;
+ int id = IDC_SKIN_OPTS_L + 1;
+
+ for (unsigned int i = 0; i < opts->getNumOptions(); i++)
+ {
+ SkinOption *opt = opts->getOption(i);
+
+ switch(opt->getType())
+ {
+ case CHECKBOX:
+ {
+ HWND chk = CreateWindow(_T("BUTTON"), opt->getDescription(),
+ WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_CHECKBOX | BS_AUTOCHECKBOX,
+ labelRc.left, y,
+ lineRc.right - labelRc.left,
+ lineHeight, hwndDlg, (HMENU) id, hInst, NULL);
+ SendMessage(chk, BM_SETCHECK, opt->getValueCheckbox() ? BST_CHECKED : BST_UNCHECKED, 0);
+ SendMessage(chk, WM_SETFONT, (WPARAM) hFont, FALSE);
+
+ break;
+ }
+ case NUMBER:
+ {
+ std::tstring tmp = opt->getDescription();
+ tmp += _T(":");
+ HWND lbl = CreateWindow(_T("STATIC"), tmp.c_str(),
+ WS_CHILD | WS_VISIBLE,
+ labelRc.left, y + (lineHeight - font.tmHeight) / 2,
+ labelRc.right - labelRc.left, font.tmHeight,
+ hwndDlg, (HMENU) id + 2, hInst, NULL);
+ SendMessage(lbl, WM_SETFONT, (WPARAM) hFont, FALSE);
+
+ HWND edit = CreateWindowEx(WS_EX_CLIENTEDGE, _T("EDIT"), _T(""),
+ WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_LEFT | ES_AUTOHSCROLL | ES_NUMBER,
+ valueRc.left, y,
+ (valueRc.right - valueRc.left) / 2, lineHeight,
+ hwndDlg, (HMENU) id, hInst, NULL);
+ SendMessage(edit, WM_SETFONT, (WPARAM) hFont, FALSE);
+ SendMessage(edit, EM_LIMITTEXT, 10, 0);
+
+ HWND spin = CreateWindow(UPDOWN_CLASS, NULL,
+ WS_CHILD | WS_VISIBLE | UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_ARROWKEYS | UDS_NOTHOUSANDS | UDS_HOTTRACK,
+ valueRc.left, y,
+ 1, 1,
+ hwndDlg, (HMENU) (id + 1), hInst, NULL);
+ SendMessage(spin, WM_SETFONT, (WPARAM) hFont, FALSE);
+ SendMessage(spin, UDM_SETBUDDY, (WPARAM) edit, 0);
+ SendMessage(spin, UDM_SETRANGE, 0, MAKELONG(min(0x7fff, opt->getMax()), max(-0x7fff, min(0x7fff, opt->getMin()))));
+ SendMessage(spin, UDM_SETPOS, 0, MAKELONG(opt->getValueNumber(), 0));
+
+ break;
+ }
+ case TEXT:
+ {
+ std::tstring tmp = opt->getDescription();
+ tmp += _T(":");
+ HWND lbl = CreateWindow(_T("STATIC"), tmp.c_str(),
+ WS_CHILD | WS_VISIBLE,
+ labelRc.left, y + (lineHeight - font.tmHeight) / 2,
+ labelRc.right - labelRc.left, font.tmHeight,
+ hwndDlg, (HMENU) id + 1, hInst, NULL);
+ SendMessage(lbl, WM_SETFONT, (WPARAM) hFont, FALSE);
+
+ HWND edit = CreateWindowEx(WS_EX_CLIENTEDGE, _T("EDIT"), _T(""),
+ WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_LEFT | ES_AUTOHSCROLL,
+ valueRc.left, y,
+ lineRc.right - valueRc.left, lineHeight,
+ hwndDlg, (HMENU) id, hInst, NULL);
+ SendMessage(edit, WM_SETFONT, (WPARAM) hFont, FALSE);
+ SendMessage(edit, EM_LIMITTEXT, MAX_TEXT_SIZE, 0);
+
+ SetWindowText(edit, opt->getValueText());
+
+ break;
+ }
+ }
+
+ id += 3;
+ y += lineHeight + V_SPACE;
+ }
+
+ RECT rc = {0};
+ GetClientRect(hwndDlg, &rc);
+ int avaiable = rc.bottom - rc.top;
+ int total = y - V_SPACE;
+ int current = 0;
+
+ SCROLLINFO si;
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
+ si.nMin = 0;
+ si.nMax = total;
+ si.nPage = avaiable;
+ si.nPos = current;
+ SetScrollInfo(hwndDlg, SB_VERT, &si, TRUE);
+ }
+
+ TranslateDialogDefault(hwndDlg);
+
+ SetWindowLong(hwndDlg, GWL_USERDATA, (LONG) dlg);
+
+ break;
+ }
+
+ case WM_VSCROLL:
+ {
+ if (lParam != 0)
+ break;
+
+ SCROLLINFO si = {0};
+ si.cbSize = sizeof(si);
+ si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
+ GetScrollInfo(hwndDlg, SB_VERT, &si);
+
+ int total = si.nMax;
+ int avaiable = si.nPage;
+ int current = si.nPos;
+
+ HFONT hFont = (HFONT) SendMessage(hwndDlg, WM_GETFONT, 0, 0);
+ TEXTMETRIC font;
+ GetTextMetric(hFont, &font);
+ int lineHeight = max(font.tmHeight, 16) + 4;
+
+ int yDelta; // yDelta = new_pos - current_pos
+ int yNewPos; // new position
+
+ switch (LOWORD(wParam))
+ {
+ case SB_PAGEUP:
+ yNewPos = current - avaiable / 2;
+ break;
+ case SB_PAGEDOWN:
+ yNewPos = current + avaiable / 2;
+ break;
+ case SB_LINEUP:
+ yNewPos = current - lineHeight;
+ break;
+ case SB_LINEDOWN:
+ yNewPos = current + lineHeight;
+ break;
+ case SB_THUMBPOSITION:
+ yNewPos = HIWORD(wParam);
+ break;
+ case SB_THUMBTRACK:
+ yNewPos = HIWORD(wParam);
+ break;
+ default:
+ yNewPos = current;
+ }
+
+ yNewPos = min(total - avaiable, max(0, yNewPos));
+
+ if (yNewPos == current)
+ break;
+
+ yDelta = yNewPos - current;
+ current = yNewPos;
+
+ // Scroll the window. (The system repaints most of the
+ // client area when ScrollWindowEx is called; however, it is
+ // necessary to call UpdateWindow in order to repaint the
+ // rectangle of pixels that were invalidated.)
+
+ ScrollWindowEx(hwndDlg, 0, -yDelta, (CONST RECT *) NULL,
+ (CONST RECT *) NULL, (HRGN) NULL, (LPRECT) NULL,
+ /* SW_ERASE | SW_INVALIDATE | */ SW_SCROLLCHILDREN);
+ UpdateWindow(hwndDlg);
+ InvalidateRect(hwndDlg, NULL, TRUE);
+
+ // Reset the scroll bar.
+
+ si.fMask = SIF_POS;
+ si.nPos = current;
+ SetScrollInfo(hwndDlg, SB_VERT, &si, TRUE);
+
+ break;
+ }
+
+ case WM_COMMAND:
+ {
+ MirandaSkinnedDialog * dlg = (MirandaSkinnedDialog *) GetWindowLong(hwndDlg, GWL_USERDATA);
+ if (dlg == NULL)
+ break;
+
+ SkinOptions *opts = dlg->getOpts();
+
+ if (LOWORD(wParam) == IDC_SKIN)
+ {
+ if (HIWORD(wParam) == CBN_SELCHANGE && (HWND)lParam == GetFocus())
+ {
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+
+ // Disable all options
+ if (opts != NULL)
+ {
+ int id = IDC_SKIN_OPTS_L + 1;
+ for (unsigned int i = 0; i < opts->getNumOptions(); i++)
+ {
+ EnableWindow(GetDlgItem(hwndDlg, id), FALSE);
+ EnableWindow(GetDlgItem(hwndDlg, id+1), FALSE);
+ EnableWindow(GetDlgItem(hwndDlg, id+2), FALSE);
+ id += 3;
+ }
+ }
+ }
+ break;
+ }
+
+ if (opts == NULL)
+ break;
+
+ bool changed = false;
+ int id = IDC_SKIN_OPTS_L + 1;
+ for (unsigned int i = 0; i < opts->getNumOptions() && !changed; i++)
+ {
+ SkinOption *opt = opts->getOption(i);
+
+ if (LOWORD(wParam) == id)
+ {
+ switch(opt->getType())
+ {
+ case CHECKBOX:
+ {
+ changed = true;
+ break;
+ }
+ case NUMBER:
+ case TEXT:
+ {
+ // Don't make apply enabled during buddy set
+ if (HIWORD(wParam) == EN_CHANGE && (HWND)lParam == GetFocus())
+ changed = true;
+ break;
+ }
+ }
+ }
+
+ id += 3;
+ }
+
+ if (changed)
+ SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+
+ break;
+ }
+ case WM_NOTIFY:
+ {
+ LPNMHDR lpnmhdr = (LPNMHDR) lParam;
+
+ if (lpnmhdr->idFrom == 0 && lpnmhdr->code == PSN_APPLY)
+ {
+ MirandaSkinnedDialog * dlg = (MirandaSkinnedDialog *) GetWindowLong(hwndDlg, GWL_USERDATA);
+ if (dlg == NULL)
+ break;
+
+ bool changedSkin = false;
+
+ // TODO Correctly handle changing skins
+ int pos = SendDlgItemMessage(hwndDlg, IDC_SKIN, CB_GETCURSEL, 0, 0);
+ if (pos != CB_ERR)
+ {
+ TCHAR tmp[1024];
+ GetWindowText(GetDlgItem(hwndDlg, IDC_SKIN), tmp, MAX_REGS(tmp));
+
+ changedSkin = (lstrcmp(dlg->getSkinName(), tmp) != 0);
+
+ dlg->setSkinName(tmp);
+ }
+
+ SkinOptions *opts = dlg->getOpts();
+ if (opts != NULL && !changedSkin)
+ {
+ int id = IDC_SKIN_OPTS_L + 1;
+ for (unsigned int i = 0; i < opts->getNumOptions(); i++)
+ {
+ SkinOption *opt = opts->getOption(i);
+
+ switch(opt->getType())
+ {
+ case CHECKBOX:
+ {
+ opt->setValueCheckbox(IsDlgButtonChecked(hwndDlg, id) != 0);
+ break;
+ }
+ case NUMBER:
+ {
+ opt->setValueNumber(SendDlgItemMessage(hwndDlg, id + 1, UDM_GETPOS, 0, 0));
+ break;
+ }
+ case TEXT:
+ {
+ TCHAR tmp[MAX_TEXT_SIZE];
+ GetDlgItemText(hwndDlg, id, tmp, MAX_TEXT_SIZE);
+ opt->setValueText(tmp);
+ break;
+ }
+ }
+
+ id += 3;
+ }
+
+ dlg->storeToDB(opts);
+ }
+
+ return TRUE;
+ }
+ break;
+ }
+ }
+
+ return 0;
+}
diff --git a/plugins/Skins/options.h b/plugins/Skins/options.h
new file mode 100644
index 0000000000..7b2616c521
--- /dev/null
+++ b/plugins/Skins/options.h
@@ -0,0 +1,47 @@
+/*
+Copyright (C) 2008 Ricardo Pescuma Domenecci
+
+This is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this file; see the file license.txt. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+*/
+
+
+#ifndef __OPTIONS_H__
+# define __OPTIONS_H__
+
+
+#include <windows.h>
+
+
+struct Options {
+};
+
+extern Options opts;
+
+
+// Initializations needed by options
+void InitOptions();
+
+// Deinitializations needed by options
+void DeInitOptions();
+
+
+// Loads the options from DB
+// It don't need to be called, except in some rare cases
+void LoadOptions();
+
+
+
+#endif // __OPTIONS_H__
diff --git a/plugins/Skins/resource.h b/plugins/Skins/resource.h
new file mode 100644
index 0000000000..d275032aeb
--- /dev/null
+++ b/plugins/Skins/resource.h
@@ -0,0 +1,22 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by resource.rc
+//
+#define IDD_OPTIONS 119
+#define IDD_SKIN_OPT 119
+#define IDC_SKIN 1087
+#define IDC_SKIN_OPTS_L 1088
+#define IDC_SKIN_L -1
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NO_MFC 1
+#define _APS_3D_CONTROLS 1
+#define _APS_NEXT_RESOURCE_VALUE 128
+#define _APS_NEXT_COMMAND_VALUE 40005
+#define _APS_NEXT_CONTROL_VALUE 1089
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/plugins/Skins/resource.rc b/plugins/Skins/resource.rc
new file mode 100644
index 0000000000..23698c2c7f
--- /dev/null
+++ b/plugins/Skins/resource.rc
@@ -0,0 +1,111 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "resource.h"
+#include "winresrc.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// Neutral resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU)
+#ifdef _WIN32
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_SKIN_OPT DIALOGEX 0, 0, 318, 234
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CONTROL | WS_CHILD | WS_VISIBLE | WS_VSCROLL
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ RTEXT "Skin:",IDC_SKIN_L,14,7,63,11
+ COMBOBOX IDC_SKIN,81,5,108,13,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+ LTEXT "Skin options:",IDC_SKIN_OPTS_L,14,26,283,11
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ IDD_SKIN_OPT, DIALOG
+ BEGIN
+ LEFTMARGIN, 1
+ TOPMARGIN, 1
+ BOTTOMMARGIN, 228
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+#endif // Neutral resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+/////////////////////////////////////////////////////////////////////////////
+// English (Canada) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENC)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_CAN
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""resource.h""\r\n"
+ "#include ""winresrc.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+#endif // English (Canada) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/plugins/Skins/skins.cpp b/plugins/Skins/skins.cpp
new file mode 100644
index 0000000000..f8142045df
--- /dev/null
+++ b/plugins/Skins/skins.cpp
@@ -0,0 +1,968 @@
+/*
+Copyright (C) 2008 Ricardo Pescuma Domenecci
+
+This is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public
+License as published by the Free Software Foundation; either
+version 2 of the License, or (at your option) any later version.
+
+This is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with this file; see the file license.txt. If
+not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.
+*/
+
+#include "commons.h"
+
+
+// Prototypes ///////////////////////////////////////////////////////////////////////////
+
+
+PLUGININFOEX pluginInfo={
+ sizeof(PLUGININFOEX),
+#ifdef UNICODE
+ "Skins (Unicode)",
+#else
+ "Skins",
+#endif
+ PLUGIN_MAKE_VERSION(0,0,0,5),
+ "Skins",
+ "Ricardo Pescuma Domenecci",
+ "",
+ "© 2008-2010 Ricardo Pescuma Domenecci",
+ "http://pescuma.org/miranda/skins",
+ UNICODE_AWARE,
+ 0, //doesn't replace anything built-in
+#ifdef UNICODE
+ { 0xde546127, 0x2cdd, 0x48ca, { 0x8a, 0xe5, 0x36, 0x25, 0xe7, 0x24, 0xf2, 0xda } }
+#else
+ { 0x2f630a2a, 0xd8f9, 0x4f81, { 0x8a, 0x4e, 0xce, 0x9a, 0x73, 0x5d, 0xf2, 0xe9 } }
+#endif
+};
+
+
+HINSTANCE hInst;
+PLUGINLINK *pluginLink;
+
+std::vector<HANDLE> hHooks;
+std::vector<HANDLE> hServices;
+HANDLE hNetlibUser = 0;
+
+HANDLE hSkinsFolder = NULL;
+TCHAR skinsFolder[1024];
+
+std::vector<MirandaSkinnedDialog *> dlgs;
+
+LIST_INTERFACE li;
+FI_INTERFACE *fei = NULL;
+struct MM_INTERFACE mmi;
+struct UTF8_INTERFACE utfi;
+
+
+int ModulesLoaded(WPARAM wParam, LPARAM lParam);
+int PreShutdown(WPARAM wParam, LPARAM lParam);
+
+static int Service_GetInterface(WPARAM wParam, LPARAM lParam);
+
+
+// Functions ////////////////////////////////////////////////////////////////////////////
+
+
+extern "C" BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+ hInst = hinstDLL;
+ return TRUE;
+}
+
+
+extern "C" __declspec(dllexport) PLUGININFO* MirandaPluginInfo(DWORD mirandaVersion)
+{
+ pluginInfo.cbSize = sizeof(PLUGININFO);
+ return (PLUGININFO*) &pluginInfo;
+}
+
+
+extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion)
+{
+ pluginInfo.cbSize = sizeof(PLUGININFOEX);
+ return &pluginInfo;
+}
+
+
+static const MUUID interfaces[] = { MIID_SKINS, MIID_LAST };
+extern "C" __declspec(dllexport) const MUUID* MirandaPluginInterfaces(void)
+{
+ return interfaces;
+}
+
+
+extern "C" int __declspec(dllexport) Load(PLUGINLINK *link)
+{
+ pluginLink = link;
+
+ CHECK_VERSION("Skins");
+
+ // TODO Assert results here
+ mir_getMMI(&mmi);
+ mir_getUTFI(&utfi);
+ mir_getLI(&li);
+
+ hHooks.push_back( HookEvent(ME_SYSTEM_MODULESLOADED, ModulesLoaded) );
+ hHooks.push_back( HookEvent(ME_SYSTEM_PRESHUTDOWN, PreShutdown) );
+
+ NETLIBUSER nl_user = {0};
+ nl_user.cbSize = sizeof(nl_user);
+ nl_user.szSettingsModule = MODULE_NAME;
+ nl_user.flags = NUF_NOOPTIONS;
+ nl_user.szDescriptiveName = Translate("Skins");
+ hNetlibUser = (HANDLE)CallService(MS_NETLIB_REGISTERUSER, 0, (LPARAM)&nl_user);
+
+ TCHAR mirandaFolder[1024];
+ GetModuleFileName(GetModuleHandle(NULL), mirandaFolder, MAX_REGS(mirandaFolder));
+ TCHAR *p = _tcsrchr(mirandaFolder, _T('\\'));
+ if (p != NULL)
+ *p = _T('\0');
+
+ // Folders plugin support
+ if (ServiceExists(MS_FOLDERS_REGISTER_PATH))
+ {
+ hSkinsFolder = FoldersRegisterCustomPathT("Skins", "Skins", _T(MIRANDA_PATH) _T("\\Skins"));
+
+ FoldersGetCustomPathT(hSkinsFolder, skinsFolder, MAX_REGS(skinsFolder), _T("."));
+ }
+ else
+ {
+ mir_sntprintf(skinsFolder, MAX_REGS(skinsFolder), _T("%s\\Skins"), mirandaFolder);
+ }
+
+ InitOptions();
+
+ hServices.push_back( CreateServiceFunction(MS_SKINS_GETINTERFACE, Service_GetInterface) );
+
+ return 0;
+}
+
+
+extern "C" int __declspec(dllexport) Unload(void)
+{
+ return 0;
+}
+
+
+// Called when all the modules are loaded
+int ModulesLoaded(WPARAM wParam, LPARAM lParam)
+{
+ // add our modules to the KnownModules list
+ CallService("DBEditorpp/RegisterSingleModule", (WPARAM) MODULE_NAME, 0);
+
+ // updater plugin support
+ if(ServiceExists(MS_UPDATE_REGISTER))
+ {
+ Update upd = {0};
+ char szCurrentVersion[30];
+
+ upd.cbSize = sizeof(upd);
+ upd.szComponentName = pluginInfo.shortName;
+
+ upd.szUpdateURL = UPDATER_AUTOREGISTER;
+
+ upd.szBetaVersionURL = "http://pescuma.googlecode.com/svn/trunk/Miranda/Plugins/skins/Docs/skins_version.txt";
+ upd.szBetaChangelogURL = "http://pescuma.googlecode.com/svn/trunk/Miranda/Plugins/skins/Docs/skins_changelog.txt";
+ upd.pbBetaVersionPrefix = (BYTE *)"Skins ";
+ upd.cpbBetaVersionPrefix = strlen((char *)upd.pbBetaVersionPrefix);
+#ifdef UNICODE
+ upd.szBetaUpdateURL = "http://pescuma.googlecode.com/files/skinsW.%VERSION%.zip";
+#else
+ upd.szBetaUpdateURL = "http://pescuma.googlecode.com/files/skins.%VERSION%.zip";
+#endif
+
+ upd.pbVersion = (BYTE *)CreateVersionStringPlugin((PLUGININFO*) &pluginInfo, szCurrentVersion);
+ upd.cpbVersion = strlen((char *)upd.pbVersion);
+
+ CallService(MS_UPDATE_REGISTER, 0, (LPARAM)&upd);
+ }
+
+ return 0;
+}
+
+
+int PreShutdown(WPARAM wParam, LPARAM lParam)
+{
+ unsigned int i;
+
+ for(i = 0; i < hServices.size(); i++)
+ DestroyServiceFunction(hServices[i]);
+ hServices.clear();
+
+ for(i = 0; i < hHooks.size(); i++)
+ UnhookEvent(hHooks[i]);
+ hHooks.clear();
+
+ DeInitOptions();
+
+ return 0;
+}
+
+
+BOOL FileExists(const char *filename)
+{
+ DWORD attrib = GetFileAttributesA(filename);
+ if (attrib == 0xFFFFFFFF || (attrib & FILE_ATTRIBUTE_DIRECTORY))
+ return FALSE;
+ return TRUE;
+}
+
+#ifdef UNICODE
+BOOL FileExists(const WCHAR *filename)
+{
+ DWORD attrib = GetFileAttributesW(filename);
+ if (attrib == 0xFFFFFFFF || (attrib & FILE_ATTRIBUTE_DIRECTORY))
+ return FALSE;
+ return TRUE;
+}
+#endif
+
+
+BOOL DirExists(const char *filename)
+{
+ DWORD attrib = GetFileAttributesA(filename);
+ if (attrib == 0xFFFFFFFF || !(attrib & FILE_ATTRIBUTE_DIRECTORY))
+ return FALSE;
+ return TRUE;
+}
+
+#ifdef UNICODE
+BOOL DirExists(const WCHAR *filename)
+{
+ DWORD attrib = GetFileAttributesW(filename);
+ if (attrib == 0xFFFFFFFF || !(attrib & FILE_ATTRIBUTE_DIRECTORY))
+ return FALSE;
+ return TRUE;
+}
+#endif
+
+
+BOOL CreatePath(const char *path)
+{
+ char folder[1024];
+ strncpy(folder, path, MAX_REGS(folder));
+ folder[MAX_REGS(folder)-1] = '\0';
+
+ char *p = folder;
+ if (p[0] && p[1] == ':' && p[2] == '\\') p += 3; // skip drive letter
+
+ SetLastError(ERROR_SUCCESS);
+ while(p = strchr(p, '\\'))
+ {
+ *p = '\0';
+ CreateDirectoryA(folder, 0);
+ *p = '\\';
+ p++;
+ }
+ CreateDirectoryA(folder, 0);
+
+ DWORD lerr = GetLastError();
+ return (lerr == ERROR_SUCCESS || lerr == ERROR_ALREADY_EXISTS);
+}
+
+
+void log(const char *fmt, ...)
+{
+ va_list va;
+ char text[1024];
+
+ va_start(va, fmt);
+ mir_vsnprintf(text, sizeof(text), fmt, va);
+ va_end(va);
+
+ CallService(MS_NETLIB_LOG, (WPARAM) NULL, (LPARAM) text);
+}
+
+
+MirandaSkinnedDialog *GetDialog(const char *name)
+{
+ _ASSERT(name != NULL);
+
+ for(unsigned int i = 0; i < dlgs.size(); i++)
+ {
+ MirandaSkinnedDialog *dlg = dlgs[i];
+ if (strcmp(name, dlg->getName()) == 0)
+ return dlg;
+ }
+
+ return NULL;
+}
+
+void getSkinnedDialogFilename(std::tstring &ret, const TCHAR *skin, const char *dialogName)
+{
+ ret = skinsFolder;
+ ret += _T("\\");
+ ret += skin;
+ ret += _T("\\");
+ ret += CharToTchar(dialogName);
+ ret += _T(".");
+ ret += _T(SKIN_EXTENSION);
+}
+
+void getAvaiableSkins(std::vector<std::tstring> &skins, MirandaSkinnedDialog *dlg)
+{
+ TCHAR file[1024];
+ mir_sntprintf(file, MAX_REGS(file), _T("%s\\*"), skinsFolder);
+
+ WIN32_FIND_DATA ffd = {0};
+ HANDLE hFFD = FindFirstFile(file, &ffd);
+ if (hFFD == INVALID_HANDLE_VALUE)
+ return;
+
+ do
+ {
+ if (lstrcmp(ffd.cFileName, _T(".")) == 0 || lstrcmp(ffd.cFileName, _T("..")) == 0)
+ continue;
+
+ mir_sntprintf(file, MAX_REGS(file), _T("%s\\%s"), skinsFolder, ffd.cFileName);
+ if (!DirExists(file))
+ continue;
+
+ if (dlg != NULL)
+ {
+ std::tstring filename;
+ getSkinnedDialogFilename(filename, ffd.cFileName, dlg->getName());
+ if (!FileExists(filename.c_str()))
+ continue;
+ }
+
+ skins.push_back(std::tstring(ffd.cFileName));
+ }
+ while(FindNextFile(hFFD, &ffd));
+
+ FindClose(hFFD);
+}
+
+void OnError(void *param, const TCHAR *err)
+{
+ MirandaSkinnedDialog *dlg = (MirandaSkinnedDialog *) param;
+
+ std::tstring title;
+ title = CharToTchar(dlg->getName());
+ title += _T("- Error executing skin");
+
+ MessageBox(NULL, err, title.c_str(), MB_OK | MB_ICONERROR);
+}
+
+SKINNED_DIALOG Interface_RegisterDialog(const char *name, const char *description, const char *module)
+{
+ if (name == NULL || name[0] == 0 || module == NULL || module[0] == 0)
+ return NULL;
+ if (GetDialog(name) != NULL)
+ return NULL;
+
+ // Check if default skin exists
+ std::tstring filename;
+ filename = skinsFolder;
+ filename += _T("\\");
+ filename += _T(DEFAULT_SKIN_NAME);
+ filename += _T("\\");
+ filename += Utf8ToTchar(name);
+ filename += _T(".");
+ filename += _T(SKIN_EXTENSION);
+
+ if (!FileExists(filename.c_str()))
+ return NULL;
+
+ MirandaSkinnedDialog *dlg = new MirandaSkinnedDialog(name, description, module);
+ dlg->setErrorCallback(OnError, dlg);
+ dlgs.push_back(dlg);
+ return (SKINNED_DIALOG) dlg;
+}
+
+void Interface_DeleteDialog(SKINNED_DIALOG aDlg)
+{
+ if (aDlg == NULL)
+ return;
+
+ MirandaSkinnedDialog * dlg = (MirandaSkinnedDialog *) aDlg;
+ for(std::vector<MirandaSkinnedDialog*>::iterator it = dlgs.begin(); it != dlgs.end(); it++)
+ {
+ if (*it == dlg)
+ {
+ dlgs.erase(it);
+ break;
+ }
+ }
+
+ delete dlg;
+}
+
+void Interface_SetSkinChangedCallback(SKINNED_DIALOG aDlg, SkinOptionsChangedCallback cb, void *param)
+{
+ if (aDlg == NULL)
+ return;
+
+ MirandaSkinnedDialog * dlg = (MirandaSkinnedDialog *) aDlg;
+ dlg->setOnSkinChangedCallback((MirandaSkinnedCallback) cb, param);
+}
+
+void Interface_FinishedConfiguring(SKINNED_DIALOG aDlg)
+{
+ if (aDlg == NULL)
+ return;
+
+ MirandaSkinnedDialog *dlg = (MirandaSkinnedDialog *) aDlg;
+ dlg->finishedConfiguring();
+}
+
+SKINNED_FIELD Interface_AddTextField(SKINNED_DIALOG aDlg, const char *name, const char *description)
+{
+ if (aDlg == NULL || name == NULL || name[0] == 0)
+ return NULL;
+
+ MirandaSkinnedDialog *dlg = (MirandaSkinnedDialog *) aDlg;
+
+ MirandaTextField *field = new MirandaTextField(dlg, name, description);
+ if (!dlg->addField(field))
+ {
+ delete field;
+ return NULL;
+ }
+
+ return (SKINNED_FIELD) field;
+}
+
+SKINNED_FIELD Interface_AddIconField(SKINNED_DIALOG aDlg, const char *name, const char *description)
+{
+ if (aDlg == NULL || name == NULL || name[0] == 0)
+ return NULL;
+
+ MirandaSkinnedDialog *dlg = (MirandaSkinnedDialog *) aDlg;
+
+ MirandaIconField *field = new MirandaIconField(dlg, name, description);
+ if (!dlg->addField(field))
+ {
+ delete field;
+ return NULL;
+ }
+
+ return (SKINNED_FIELD) field;
+}
+
+SKINNED_FIELD Interface_AddImageField(SKINNED_DIALOG aDlg, const char *name, const char *description)
+{
+ if (aDlg == NULL || name == NULL || name[0] == 0)
+ return NULL;
+
+ MirandaSkinnedDialog *dlg = (MirandaSkinnedDialog *) aDlg;
+
+ MirandaImageField *field = new MirandaImageField(dlg, name, description);
+ if (!dlg->addField(field))
+ {
+ delete field;
+ return NULL;
+ }
+
+ return (SKINNED_FIELD) field;
+}
+
+SKINNED_FIELD Interface_GetField(SKINNED_DIALOG aDlg, const char *name)
+{
+ if (aDlg == NULL || name == NULL || name[0] == 0)
+ return NULL;
+
+ MirandaSkinnedDialog *dlg = (MirandaSkinnedDialog *) aDlg;
+
+ return (SKINNED_FIELD) dlg->getField(name);
+}
+
+void Interface_SetDialogSize(SKINNED_DIALOG aDlg, int width, int height)
+{
+ if (aDlg == NULL)
+ return;
+
+ MirandaSkinnedDialog *dlg = (MirandaSkinnedDialog *) aDlg;
+ dlg->setSize(Size(width, height));
+}
+
+void Interface_SetInfoInt(SKINNED_DIALOG aDlg, const char *name, int value)
+{
+ if (aDlg == NULL || name == NULL)
+ return;
+
+ MirandaSkinnedDialog *dlg = (MirandaSkinnedDialog *) aDlg;
+ dlg->getInfo()->set(name, value);
+}
+
+void Interface_SetInfoDouble(SKINNED_DIALOG aDlg, const char *name, double value)
+{
+ if (aDlg == NULL || name == NULL)
+ return;
+
+ MirandaSkinnedDialog *dlg = (MirandaSkinnedDialog *) aDlg;
+ dlg->getInfo()->set(name, value);
+}
+
+void Interface_SetInfoBool(SKINNED_DIALOG aDlg, const char *name, BOOL value)
+{
+ if (aDlg == NULL || name == NULL)
+ return;
+
+ MirandaSkinnedDialog *dlg = (MirandaSkinnedDialog *) aDlg;
+ dlg->getInfo()->set(name, value);
+}
+
+void Interface_SetInfoString(SKINNED_DIALOG aDlg, const char *name, const TCHAR *value)
+{
+ if (aDlg == NULL || name == NULL)
+ return;
+
+ MirandaSkinnedDialog *dlg = (MirandaSkinnedDialog *) aDlg;
+ dlg->getInfo()->set(name, value);
+}
+
+void Interface_RemoveInfo(SKINNED_DIALOG aDlg, const char *name)
+{
+ if (aDlg == NULL || name == NULL)
+ return;
+
+ MirandaSkinnedDialog *dlg = (MirandaSkinnedDialog *) aDlg;
+ dlg->getInfo()->remove(name);
+}
+
+
+void Interface_SetEnabled(SKINNED_FIELD aField, BOOL enabled)
+{
+ if (aField == NULL)
+ return;
+
+ Field *field = (Field *) aField;
+ field->setEnabled(enabled != 0);
+}
+
+void Interface_SetToolTipA(SKINNED_FIELD aField, const char *tooltip)
+{
+ if (aField == NULL)
+ return;
+
+ Field *field = (Field *) aField;
+ field->setToolTip(CharToTchar(tooltip));
+}
+
+void Interface_SetToolTipW(SKINNED_FIELD aField, const WCHAR *tooltip)
+{
+ if (aField == NULL)
+ return;
+
+ Field *field = (Field *) aField;
+ field->setToolTip(WcharToTchar(tooltip));
+}
+
+void Interface_SetTextA(SKINNED_FIELD aField, const char *text)
+{
+ if (aField == NULL)
+ return;
+
+ Field *field = (Field *) aField;
+ switch(field->getType())
+ {
+ case SIMPLE_TEXT:
+ ((TextField *) field)->setText(CharToTchar(text));
+ break;
+ case CONTROL_LABEL:
+ case CONTROL_BUTTON:
+ case CONTROL_EDIT:
+ ((ControlField *) field)->setText(CharToTchar(text));
+ break;
+ }
+}
+
+void Interface_SetTextW(SKINNED_FIELD aField, const WCHAR *text)
+{
+ if (aField == NULL)
+ return;
+
+ Field *field = (Field *) aField;
+ switch(field->getType())
+ {
+ case SIMPLE_TEXT:
+ ((TextField *) field)->setText(WcharToTchar(text));
+ break;
+ case CONTROL_LABEL:
+ case CONTROL_BUTTON:
+ case CONTROL_EDIT:
+ ((ControlField *) field)->setText(WcharToTchar(text));
+ break;
+ }
+}
+
+void Interface_SetIcon(SKINNED_FIELD aField, HICON hIcon)
+{
+ if (aField == NULL)
+ return;
+
+ Field *field = (Field *) aField;
+ switch(field->getType())
+ {
+ case SIMPLE_ICON:
+ ((IconField *) field)->setIcon(hIcon);
+ break;
+ }
+}
+
+void Interface_SetImage(SKINNED_FIELD aField, HBITMAP hBmp)
+{
+ if (aField == NULL)
+ return;
+
+ Field *field = (Field *) aField;
+ switch(field->getType())
+ {
+ case SIMPLE_IMAGE:
+ ((ImageField *) field)->setImage(hBmp);
+ break;
+ }
+}
+
+SKINNED_DIALOG_STATE Interface_Run(SKINNED_DIALOG aDlg)
+{
+ if (aDlg == NULL)
+ return NULL;
+
+ MirandaSkinnedDialog *dlg = (MirandaSkinnedDialog *) aDlg;
+ return (SKINNED_DIALOG_STATE) dlg->getState();
+}
+
+/*
+void Interface_DeleteDialogState(SKINNED_DIALOG_STATE aDlg)
+{
+ if (aDlg == NULL)
+ return;
+
+ DialogState * dlg = (DialogState *) aDlg;
+
+ delete dlg;
+}
+*/
+
+SKINNED_FIELD_STATE Interface_GetFieldState(SKINNED_DIALOG_STATE aDlg, const char *name)
+{
+ if (aDlg == NULL || name == NULL || name[0] == 0)
+ return NULL;
+
+ DialogState *dlg = (DialogState *) aDlg;
+
+ return (SKINNED_FIELD_STATE) dlg->getField(name);
+}
+
+RECT Interface_GetDialogBorders(SKINNED_DIALOG_STATE aDlg)
+{
+ RECT ret = {0};
+
+ if (aDlg == NULL)
+ return ret;
+
+ DialogState *state = (DialogState *) aDlg;
+ BorderState *borders = state->getBorders();
+
+ ret.left = borders->getLeft();
+ ret.top = borders->getTop();
+ ret.right = borders->getRight();
+ ret.bottom = borders->getBottom();
+
+ return ret;
+}
+
+RECT Interface_GetRect(SKINNED_FIELD_STATE field)
+{
+ if (field == NULL)
+ {
+ RECT ret = {0};
+ return ret;
+ }
+
+ FieldState *fieldState = (FieldState *) field;
+
+ return fieldState->getRect();
+}
+
+RECT Interface_GetInsideRect(SKINNED_FIELD_STATE field)
+{
+ if (field == NULL)
+ {
+ RECT ret = {0};
+ return ret;
+ }
+
+ FieldState *fieldState = (FieldState *) field;
+
+ return fieldState->getInsideRect();
+}
+
+RECT Interface_GetRawRect(SKINNED_FIELD_STATE field)
+{
+ if (field == NULL)
+ {
+ RECT ret = {0};
+ return ret;
+ }
+
+ FieldState *fieldState = (FieldState *) field;
+
+ return fieldState->getRect(true);
+}
+
+RECT Interface_GetRawInsideRect(SKINNED_FIELD_STATE field)
+{
+ if (field == NULL)
+ {
+ RECT ret = {0};
+ return ret;
+ }
+
+ FieldState *fieldState = (FieldState *) field;
+
+ return fieldState->getInsideRect(true);
+}
+
+RECT Interface_GetBorders(SKINNED_FIELD_STATE field)
+{
+ RECT ret = {0};
+
+ if (field == NULL)
+ return ret;
+
+ FieldState *fieldState = (FieldState *) field;
+ BorderState *borders = fieldState->getBorders();
+
+ ret.left = borders->getLeft();
+ ret.top = borders->getTop();
+ ret.right = borders->getRight();
+ ret.bottom = borders->getBottom();
+
+ return ret;
+}
+
+BOOL Interface_IsVisible(SKINNED_FIELD_STATE field)
+{
+ if (field == NULL)
+ return FALSE;
+
+ FieldState *fieldState = (FieldState *) field;
+
+ return fieldState->isVisible();
+}
+
+char * Interface_GetToolTipA(SKINNED_FIELD_STATE field)
+{
+ if (field == NULL)
+ return NULL;
+
+ FieldState *fieldState = (FieldState *) field;
+ return TcharToChar(fieldState->getToolTip()).detach();
+}
+
+WCHAR * Interface_GetToolTipW(SKINNED_FIELD_STATE field)
+{
+ if (field == NULL)
+ return NULL;
+
+ FieldState *fieldState = (FieldState *) field;
+ return TcharToWchar(fieldState->getToolTip()).detach();
+}
+
+char * Interface_GetTextA(SKINNED_FIELD_STATE field)
+{
+ if (field == NULL)
+ return NULL;
+
+ FieldState *fieldState = (FieldState *) field;
+
+ switch(fieldState->getField()->getType())
+ {
+ case SIMPLE_TEXT:
+ return TcharToChar(((TextFieldState *) fieldState)->getText()).detach();
+ case CONTROL_LABEL:
+ case CONTROL_BUTTON:
+ case CONTROL_EDIT:
+ return TcharToChar(((ControlFieldState *) field)->getText()).detach();
+ }
+
+ return NULL;
+}
+
+WCHAR * Interface_GetTextW(SKINNED_FIELD_STATE field)
+{
+ if (field == NULL)
+ return NULL;
+
+ FieldState *fieldState = (FieldState *) field;
+
+ switch(fieldState->getField()->getType())
+ {
+ case SIMPLE_TEXT:
+ return TcharToWchar(((TextFieldState *) fieldState)->getText()).detach();
+ case CONTROL_LABEL:
+ case CONTROL_BUTTON:
+ case CONTROL_EDIT:
+ return TcharToWchar(((ControlFieldState *) field)->getText()).detach();
+ }
+
+ return NULL;
+}
+
+HFONT Interface_GetFont(SKINNED_FIELD_STATE field)
+{
+ if (field == NULL)
+ return NULL;
+
+ FieldState *fieldState = (FieldState *) field;
+
+ switch(fieldState->getField()->getType())
+ {
+ case SIMPLE_TEXT:
+ return ((TextFieldState *) fieldState)->getFont()->getHFONT();
+ case CONTROL_LABEL:
+ case CONTROL_BUTTON:
+ case CONTROL_EDIT:
+ return ((ControlFieldState *) fieldState)->getFont()->getHFONT();
+ }
+
+ return NULL;
+}
+
+COLORREF Interface_GetFontColor(SKINNED_FIELD_STATE field)
+{
+ if (field == NULL)
+ return RGB(0,0,0);
+
+ FieldState *fieldState = (FieldState *) field;
+
+ switch(fieldState->getField()->getType())
+ {
+ case SIMPLE_TEXT:
+ return ((TextFieldState *) fieldState)->getFont()->getColor();
+ case CONTROL_LABEL:
+ case CONTROL_BUTTON:
+ case CONTROL_EDIT:
+ return ((ControlFieldState *) fieldState)->getFont()->getColor();
+ }
+
+ return RGB(0,0,0);
+}
+
+int Interface_GetHorizontalAlign(SKINNED_FIELD_STATE field)
+{
+ if (field == NULL)
+ return SKN_HALIGN_LEFT;
+
+ FieldState *fieldState = (FieldState *) field;
+ return fieldState->getHAlign();
+}
+
+int Interface_GetVerticalAlign(SKINNED_FIELD_STATE field)
+{
+ if (field == NULL)
+ return SKN_VALIGN_TOP;
+
+ FieldState *fieldState = (FieldState *) field;
+ return fieldState->getVAlign();
+}
+
+HICON Interface_GetIcon(SKINNED_FIELD_STATE field)
+{
+ if (field == NULL)
+ return NULL;
+
+ FieldState *fieldState = (FieldState *) field;
+
+ switch(fieldState->getField()->getType())
+ {
+ case SIMPLE_ICON:
+ return ((IconFieldState *) fieldState)->getIcon();
+ }
+ return NULL;
+}
+
+HBITMAP Interface_GetImage(SKINNED_FIELD_STATE field)
+{
+ if (field == NULL)
+ return NULL;
+
+ FieldState *fieldState = (FieldState *) field;
+
+ switch(fieldState->getField()->getType())
+ {
+ case SIMPLE_IMAGE:
+ return ((ImageFieldState *) fieldState)->getImage();
+ }
+ return NULL;
+}
+
+
+static int Service_GetInterface(WPARAM wParam, LPARAM lParam)
+{
+ SKIN_INTERFACE *mski = (SKIN_INTERFACE *) lParam;
+ if (mski == NULL)
+ return -1;
+
+ if (mski->cbSize < sizeof(SKIN_INTERFACE))
+ return -2;
+
+ mski->RegisterDialog = &Interface_RegisterDialog;
+ mski->DeleteDialog = &Interface_DeleteDialog;
+ mski->SetSkinChangedCallback = &Interface_SetSkinChangedCallback;
+ mski->FinishedConfiguring = &Interface_FinishedConfiguring;
+
+ mski->AddTextField = &Interface_AddTextField;
+ mski->AddIconField = &Interface_AddIconField;
+ mski->AddImageField = &Interface_AddImageField;
+ mski->GetField = &Interface_GetField;
+ mski->SetDialogSize = &Interface_SetDialogSize;
+
+ mski->SetInfoInt = &Interface_SetInfoInt;
+ mski->SetInfoDouble = &Interface_SetInfoDouble;
+ mski->SetInfoBool = &Interface_SetInfoBool;
+ mski->SetInfoString = &Interface_SetInfoString;
+ mski->RemoveInfo = &Interface_RemoveInfo;
+
+ mski->SetEnabled = &Interface_SetEnabled;
+ mski->SetToolTipA = &Interface_SetToolTipA;
+ mski->SetToolTipW = &Interface_SetToolTipW;
+
+ mski->SetTextA = &Interface_SetTextA;
+ mski->SetTextW = &Interface_SetTextW;
+
+ mski->SetIcon = &Interface_SetIcon;
+
+ mski->SetImage = &Interface_SetImage;
+
+ mski->Run = &Interface_Run;
+
+ mski->GetFieldState = &Interface_GetFieldState;
+ mski->GetDialogBorders = &Interface_GetDialogBorders;
+
+ mski->GetRect = &Interface_GetRect;
+ mski->GetInsideRect = &Interface_GetInsideRect;
+ mski->GetRawRect = &Interface_GetRawRect;
+ mski->GetRawInsideRect = &Interface_GetRawInsideRect;
+
+ mski->GetBorders = &Interface_GetBorders;
+ mski->IsVisible = &Interface_IsVisible;
+ mski->GetToolTipA = &Interface_GetToolTipA;
+ mski->GetToolTipW = &Interface_GetToolTipW;
+ mski->GetHorizontalAlign = &Interface_GetHorizontalAlign;
+ mski->GetVerticalAlign = &Interface_GetVerticalAlign;
+
+ mski->GetTextA = &Interface_GetTextA;
+ mski->GetTextW = &Interface_GetTextW;
+ mski->GetFont = &Interface_GetFont;
+ mski->GetFontColor = &Interface_GetFontColor;
+
+ mski->GetIcon = &Interface_GetIcon;
+
+ mski->GetImage = &Interface_GetImage;
+
+ return 0;
+}
diff --git a/plugins/Skins/skins.vcproj b/plugins/Skins/skins.vcproj
new file mode 100644
index 0000000000..413faa319e
--- /dev/null
+++ b/plugins/Skins/skins.vcproj
@@ -0,0 +1,1066 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9,00"
+ Name="skins"
+ ProjectGUID="{F5F5EA6E-F648-4174-8419-D6CA41DF0A11}"
+ RootNamespace="skins"
+ TargetFrameworkVersion="0"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory=".\Debug"
+ IntermediateDirectory=".\Debug"
+ ConfigurationType="2"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="NDEBUG"
+ MkTypLibCompatible="true"
+ SuppressStartupBanner="true"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Debug/skins.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../include,sdk,libs,../utils"
+ PreprocessorDefinitions="WIN32;W32;_DEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS"
+ RuntimeLibrary="1"
+ PrecompiledHeaderFile=".\Debug/skins.pch"
+ AssemblerListingLocation=".\Debug/"
+ ObjectFile=".\Debug/"
+ ProgramDataBaseFileName=".\Debug/"
+ BrowseInformation="1"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1047"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalOptions="/ALIGN:4096 /filealign:0x200 /ignore:4108 "
+ AdditionalDependencies="v8_g.lib Ws2_32.lib Winmm.lib"
+ OutputFile="..\..\bin\debug\Plugins\skins.dll"
+ LinkIncremental="2"
+ SuppressStartupBanner="true"
+ AdditionalLibraryDirectories="$(ProjectDir)libs\"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile=".\Debug/skins.pdb"
+ BaseAddress="0x3EC20000"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ ImportLibrary=".\Debug/skins.lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ SuppressStartupBanner="true"
+ OutputFile=".\Debug/skins.bsc"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory=".\Release"
+ IntermediateDirectory=".\Release"
+ ConfigurationType="2"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="2"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="NDEBUG"
+ MkTypLibCompatible="true"
+ SuppressStartupBanner="true"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Release/skins.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="0"
+ WholeProgramOptimization="true"
+ AdditionalIncludeDirectories="../../include,sdk,libs,../utils"
+ PreprocessorDefinitions="WIN32;W32;NDEBUG;_WINDOWS;_USRDLL;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS"
+ StringPooling="true"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="true"
+ PrecompiledHeaderFile=".\Release/skins.pch"
+ AssemblerListingLocation=".\Release/"
+ ObjectFile=".\Release/"
+ ProgramDataBaseFileName=".\Release/"
+ BrowseInformation="2"
+ BrowseInformationFile=".\Release/"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1047"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalOptions="/ALIGN:4096 /filealign:0x200 /ignore:4108 "
+ AdditionalDependencies="v8.lib Ws2_32.lib Winmm.lib"
+ OutputFile="..\..\bin\release\Plugins\skins.dll"
+ LinkIncremental="1"
+ SuppressStartupBanner="true"
+ AdditionalLibraryDirectories="$(ProjectDir)libs\"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile=".\Release/skins.pdb"
+ GenerateMapFile="true"
+ MapFileName=".\Release/skins.map"
+ LinkTimeCodeGeneration="1"
+ BaseAddress="0x3EC20000"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ ImportLibrary=".\Release/skins.lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ SuppressStartupBanner="true"
+ OutputFile=".\Release/skins.bsc"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Unicode Debug|Win32"
+ OutputDirectory=".\Unicode_Debug"
+ IntermediateDirectory=".\Unicode_Debug"
+ ConfigurationType="2"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="NDEBUG"
+ MkTypLibCompatible="true"
+ SuppressStartupBanner="true"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Unicode_Debug/skins.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="../../include,sdk,libs,../utils"
+ PreprocessorDefinitions="WIN32;W32;_DEBUG;DEBUG;_WINDOWS;UNICODE;_USRDLL;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ PrecompiledHeaderFile=".\Unicode_Debug/skins.pch"
+ AssemblerListingLocation=""
+ BrowseInformation="1"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalOptions="/ALIGN:4096 /filealign:0x200 /ignore:4108 "
+ AdditionalDependencies="v8_g.lib Ws2_32.lib Winmm.lib"
+ OutputFile="..\..\bin\debug unicode\Plugins\skinsW.dll"
+ LinkIncremental="2"
+ AdditionalLibraryDirectories="$(ProjectDir)libs\"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile=".\Unicode_Debug/skinsW.pdb"
+ SubSystem="2"
+ BaseAddress=""
+ ImportLibrary=".\Unicode_Debug/skinsW.lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Unicode Release|Win32"
+ OutputDirectory=".\Unicode_Release"
+ IntermediateDirectory=".\Unicode_Release"
+ ConfigurationType="2"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC60.vsprops"
+ UseOfMFC="0"
+ ATLMinimizesCRunTimeLibraryUsage="false"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ PreprocessorDefinitions="NDEBUG"
+ MkTypLibCompatible="true"
+ SuppressStartupBanner="true"
+ TargetEnvironment="1"
+ TypeLibraryName=".\Unicode_Release/skins.tlb"
+ HeaderFileName=""
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ InlineFunctionExpansion="0"
+ FavorSizeOrSpeed="1"
+ WholeProgramOptimization="true"
+ AdditionalIncludeDirectories="../../include,sdk,libs,../utils"
+ PreprocessorDefinitions="WIN32;W32;NDEBUG;_WINDOWS;UNICODE;_USRDLL;_CRT_SECURE_NO_WARNINGS;_CRT_NONSTDC_NO_WARNINGS"
+ StringPooling="true"
+ RuntimeLibrary="0"
+ EnableFunctionLevelLinking="true"
+ PrecompiledHeaderFile=".\Unicode_Release/skins.pch"
+ AssemblerListingLocation=".\Unicode_Release/"
+ ObjectFile=".\Unicode_Release/"
+ ProgramDataBaseFileName=".\Unicode_Release/"
+ BrowseInformation="2"
+ BrowseInformationFile=".\Unicode_Release/"
+ WarningLevel="3"
+ SuppressStartupBanner="true"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions="NDEBUG"
+ Culture="1047"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalOptions="/ALIGN:4096 /filealign:0x200 /ignore:4108 "
+ AdditionalDependencies="v8.lib Ws2_32.lib Winmm.lib"
+ OutputFile="..\..\bin\release unicode\Plugins\skinsW.dll"
+ LinkIncremental="1"
+ SuppressStartupBanner="true"
+ AdditionalLibraryDirectories="$(ProjectDir)libs\"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile=".\Unicode_Release/skinsW.pdb"
+ GenerateMapFile="true"
+ MapFileName=".\Unicode_Release/skinsW.map"
+ LinkTimeCodeGeneration="1"
+ BaseAddress="0x3EC20000"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ ImportLibrary=".\Unicode_Release/skinsW.lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ SuppressStartupBanner="true"
+ OutputFile=".\Unicode_Release/skins.bsc"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl"
+ >
+ <File
+ RelativePath="commons.h"
+ >
+ </File>
+ <File
+ RelativePath="m_skins.h"
+ >
+ </File>
+ <File
+ RelativePath=".\m_skins_cpp.h"
+ >
+ </File>
+ <File
+ RelativePath="..\utils\mir_icons.h"
+ >
+ </File>
+ <File
+ RelativePath="..\utils\mir_memory.h"
+ >
+ </File>
+ <File
+ RelativePath="..\utils\mir_options.h"
+ >
+ </File>
+ <File
+ RelativePath="options.h"
+ >
+ </File>
+ <File
+ RelativePath="resource.h"
+ >
+ </File>
+ <Filter
+ Name="SkinLib Header Files"
+ >
+ <File
+ RelativePath=".\SkinLib\globals.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\Position.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\scope.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\Size.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\SkinnedDialog.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\SkinOption.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\SkinOptions.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\tstring.h"
+ >
+ </File>
+ <Filter
+ Name="Fields Header Files"
+ >
+ <File
+ RelativePath=".\SkinLib\ButtonField.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\ControlField.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\Dialog.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\DialogInfo.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\EditField.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\Field.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\IconField.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\ImageField.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\LabelField.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\TextField.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="v8 Header Files"
+ >
+ <File
+ RelativePath=".\SkinLib\BorderState_v8_wrapper.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\ControlFieldState_v8_wrapper.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\DialogState_v8_wrapper.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\FieldState_v8_wrapper.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\FontState_v8_wrapper.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\SkinOption_v8_wrapper.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\TextFieldState_v8_wrapper.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\V8Script.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\V8Templates.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\V8Wrappers.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="States Header Files"
+ >
+ <File
+ RelativePath=".\SkinLib\BorderState.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\ButtonFieldState.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\ControlFieldState.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\DialogState.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\EditFieldState.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\FieldState.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\FontState.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\IconFieldState.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\ImageFieldState.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\LabelFieldState.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\TextFieldState.h"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="Miranda Wrappers Header Files"
+ >
+ <File
+ RelativePath=".\MirandaField.h"
+ >
+ </File>
+ <File
+ RelativePath=".\MirandaFont.h"
+ >
+ </File>
+ <File
+ RelativePath=".\MirandaIconField.h"
+ >
+ </File>
+ <File
+ RelativePath=".\MirandaImageField.h"
+ >
+ </File>
+ <File
+ RelativePath=".\MirandaSkinnedDialog.h"
+ >
+ </File>
+ <File
+ RelativePath=".\MirandaTextField.h"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
+ >
+ <File
+ RelativePath="resource.rc"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Unicode Debug|Win32"
+ >
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Unicode Release|Win32"
+ >
+ <Tool
+ Name="VCResourceCompilerTool"
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+ >
+ <File
+ RelativePath="..\utils\mir_icons.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Unicode Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Unicode Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\utils\mir_options.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Unicode Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Unicode Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="options.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Unicode Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Unicode Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="skins.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Unicode Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Unicode Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions=""
+ />
+ </FileConfiguration>
+ </File>
+ <Filter
+ Name="SkinLib Source Files"
+ >
+ <File
+ RelativePath=".\SkinLib\Position.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\Size.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\SkinnedDialog.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\SkinOptions.cpp"
+ >
+ </File>
+ <Filter
+ Name="Fields Source Files"
+ >
+ <File
+ RelativePath=".\SkinLib\ButtonField.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\ControlField.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\Dialog.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\DialogInfo.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\EditField.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\Field.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\IconField.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\ImageField.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\LabelField.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\TextField.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="v8 Source Files"
+ >
+ <File
+ RelativePath=".\SkinLib\BorderState_v8_wrapper.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\ControlFieldState_v8_wrapper.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\DialogState_v8_wrapper.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\FieldState_v8_wrapper.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\FontState_v8_wrapper.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\SkinOption_v8_wrapper.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\TextFieldState_v8_wrapper.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\V8Script.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\V8Templates.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\V8Wrappers.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="States Source Files"
+ >
+ <File
+ RelativePath=".\SkinLib\BorderState.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\ButtonFieldState.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\ControlFieldState.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\DialogState.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\EditFieldState.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\FieldState.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\FontState.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\IconFieldState.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\ImageFieldState.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\LabelFieldState.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\SkinLib\TextFieldState.cpp"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="Miranda Wrappers Source Files"
+ >
+ <File
+ RelativePath=".\MirandaFont.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\MirandaIconField.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\MirandaImageField.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\MirandaSkinnedDialog.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\MirandaTextField.cpp"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="Docs"
+ >
+ <File
+ RelativePath="Docs\langpack_skins.txt"
+ >
+ </File>
+ <File
+ RelativePath="Docs\skins_changelog.txt"
+ >
+ </File>
+ <File
+ RelativePath="Docs\skins_readme.txt"
+ >
+ </File>
+ <File
+ RelativePath="Docs\skins_version.txt"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>