← Back to team overview

linuxdcpp-team team mailing list archive

[Branch ~dcplusplus-team/dcpp-plugin-sdk-cpp/DevPlugin] Rev 2: init from lp:dcplusplus/plugins/Dev

 

------------------------------------------------------------
revno: 2
committer: poy <poy@xxxxxxxxxx>
branch nick: DevPlugin
timestamp: Thu 2012-11-15 19:52:40 +0100
message:
  init from lp:dcplusplus/plugins/Dev
added:
  src/Dialog.cpp
  src/Dialog.h
modified:
  src/Plugin.cpp
  src/Plugin.h
  src/main.cpp
  src/resource.h
  src/resource.rc
  src/stdafx.h
  src/version.h


--
lp:~dcplusplus-team/dcpp-plugin-sdk-cpp/DevPlugin
https://code.launchpad.net/~dcplusplus-team/dcpp-plugin-sdk-cpp/DevPlugin

Your team Dcplusplus-team is subscribed to branch lp:~dcplusplus-team/dcpp-plugin-sdk-cpp/DevPlugin.
To unsubscribe from this branch go to https://code.launchpad.net/~dcplusplus-team/dcpp-plugin-sdk-cpp/DevPlugin/+edit-subscription
=== added file 'src/Dialog.cpp'
--- src/Dialog.cpp	1970-01-01 00:00:00 +0000
+++ src/Dialog.cpp	2012-11-15 18:52:40 +0000
@@ -0,0 +1,392 @@
+/*
+ * Copyright (C) 2012 Jacek Sieka, arnetheduck on gmail point com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "stdafx.h"
+#include "Dialog.h"
+#include "Plugin.h"
+#include "resource.h"
+
+#include <pluginsdk/Core.h>
+#include <pluginsdk/Util.h>
+
+#include <boost/lexical_cast.hpp>
+
+#include <commctrl.h>
+#include <windowsx.h>
+
+#ifndef LVS_EX_DOUBLEBUFFER
+#define LVS_EX_DOUBLEBUFFER     0x00010000
+#endif
+
+#define noFilter _T("0 - No filtering")
+
+using dcapi::Core;
+using dcapi::Util;
+
+HINSTANCE Dialog::instance;
+Dialog* dlg = nullptr;
+
+Dialog::Dialog() :
+	hwnd(nullptr),
+	messages(1024),
+	counter(0),
+	scroll(true),
+	hubMessages(true),
+	userMessages(true)
+{
+	dlg = this;
+}
+
+Dialog::~Dialog() {
+	close();
+
+	dlg = nullptr;
+}
+
+void Dialog::create() {
+	if(hwnd) {
+		MessageBox(0, Util::toT("The dev plugin hasn't been properly shut down; you better restart " + Core::appName).c_str(),
+			_T("Error creating the dev plugin's dialog"), MB_OK);
+		return;
+	}
+
+	CreateDialog(instance, MAKEINTRESOURCE(IDD_PLUGINDLG), 0, DialogProc);
+
+	if(!hwnd) {
+		TCHAR buf[256];
+		FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0, GetLastError(), 0, buf, 256, 0);
+		MessageBox(0, buf, _T("Error creating the dev plugin's dialog"), MB_OK);
+	}
+}
+
+void Dialog::write(bool hubOrUser, bool sending, string ip, decltype(ConnectionData().port) port, string peer, string message) {
+	Message msg = { hubOrUser, sending, move(ip), port, move(peer), move(message) };
+	messages.push(msg);
+}
+
+void Dialog::close() {
+	if(hwnd) {
+		DestroyWindow(hwnd);
+		hwnd = nullptr;
+	}
+}
+
+INT_PTR CALLBACK Dialog::DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM) {
+	switch(uMsg) {
+	case WM_INITDIALOG:
+		{
+			dlg->hwnd = hwnd;
+			return dlg->init();
+		}
+	case WM_TIMER:
+		{
+			dlg->timer();
+			break;
+		}
+	case WM_COMMAND:
+		{
+			dlg->command(wParam);
+			break;
+		}
+	case WM_CLOSE:
+		{
+			Plugin::dlgClosed();
+			break;
+		}
+	case WM_DESTROY:
+		{
+			dlg->clear();
+			break;
+		}
+	}
+	return FALSE;
+}
+
+BOOL Dialog::init() {
+	auto control = GetDlgItem(hwnd, IDC_MESSAGES);
+
+	ListView_SetExtendedListViewStyle(control, LVS_EX_DOUBLEBUFFER | LVS_EX_HEADERDRAGDROP | LVS_EX_FULLROWSELECT | LVS_EX_LABELTIP);
+
+	RECT rect;
+	GetClientRect(control, &rect);
+
+	LVCOLUMN col = { LVCF_FMT | LVCF_TEXT | LVCF_WIDTH, LVCFMT_LEFT, 50, (LPWSTR)_T("#") };
+	ListView_InsertColumn(control, 0, &col);
+
+	col.pszText = (LPWSTR)_T("Dir");
+	ListView_InsertColumn(control, 1, &col);
+
+	col.cx = 100;
+	col.pszText = (LPWSTR)_T("IP");
+	ListView_InsertColumn(control, 2, &col);
+
+	col.cx = 50;
+	col.pszText = (LPWSTR) _T("Port");
+	ListView_InsertColumn(control, 3, &col);
+
+	col.cx = 200;
+	col.pszText = (LPWSTR)_T("Peer info");
+	ListView_InsertColumn(control, 4, &col);
+
+	col.cx = rect.right - rect.left - 50 - 50 - 100 - 50 - 200 - 30;
+	col.pszText = (LPWSTR)_T("Message");
+	ListView_InsertColumn(control, 5, &col);
+
+	SendMessage(GetDlgItem(hwnd, IDC_SCROLL), BM_SETCHECK, BST_CHECKED, 0);
+	SendMessage(GetDlgItem(hwnd, IDC_HUB_MESSAGES), BM_SETCHECK, BST_CHECKED, 0);
+	SendMessage(GetDlgItem(hwnd, IDC_USER_MESSAGES), BM_SETCHECK, BST_CHECKED, 0);
+
+	initFilter();
+
+	SetTimer(hwnd, 1, 500, 0);
+
+	return TRUE;
+}
+
+void Dialog::timer() {
+	auto control = GetDlgItem(hwnd, IDC_MESSAGES);
+
+	LVITEM lvi = { 0 };
+
+	Message message;
+	while(messages.pop(message)) {
+
+		if(!(message.hubOrUser ? hubMessages : userMessages)) {
+			continue;
+		}
+
+		auto ip = Util::toT(message.ip);
+		if(!filterSel.empty() && ip != filterSel) {
+			continue;
+		}
+
+		if(!regex.empty()) {
+			try {
+				if(!boost::regex_search(message.message, regex)) {
+					continue;
+				}
+			} catch(const std::runtime_error&) {
+				// most likely a stack overflow, ignore...
+				continue;
+			}
+		}
+
+		auto item = new Item;
+		item->index = Util::toT(boost::lexical_cast<string>(counter));
+		item->dir = message.sending ? _T("Out") : _T("In");
+		item->ip = move(ip);
+		item->port = Util::toT(boost::lexical_cast<string>(message.port));
+		item->peer = Util::toT(message.peer);
+		item->message = Util::toT(message.message);
+
+		// first column; include the lParam.
+		lvi.mask = LVIF_PARAM | LVIF_TEXT;
+		lvi.iItem = counter;
+		lvi.iSubItem = 0;
+		lvi.pszText = const_cast<LPTSTR>(item->index.c_str());
+		lvi.lParam = reinterpret_cast<LPARAM>(item);
+		ListView_InsertItem(control, &lvi);
+
+		// no lParam for other columns (ie sub-items).
+		lvi.mask = LVIF_TEXT;
+
+		lvi.iSubItem = 1;
+		lvi.pszText = const_cast<LPTSTR>(item->dir.c_str());
+		ListView_SetItem(control, &lvi);
+
+		lvi.iSubItem = 2;
+		lvi.pszText = const_cast<LPTSTR>(item->ip.c_str());
+		ListView_SetItem(control, &lvi);
+
+		lvi.iSubItem = 3;
+		lvi.pszText = const_cast<LPTSTR>(item->port.c_str());
+		ListView_SetItem(control, &lvi);
+
+		lvi.iSubItem = 4;
+		lvi.pszText = const_cast<LPTSTR>(item->peer.c_str());
+		ListView_SetItem(control, &lvi);
+
+		lvi.iSubItem = 5;
+		lvi.pszText = const_cast<LPTSTR>(item->message.c_str());
+		ListView_SetItem(control, &lvi);
+
+		++counter;
+
+		if(filter.find(item->ip) == filter.end()) {
+			ComboBox_AddString(GetDlgItem(hwnd, IDC_FILTER), filter.insert(item->ip).first->c_str());
+		}
+	}
+
+	if(scroll && lvi.lParam) { // make sure something was added
+		ListView_EnsureVisible(control, lvi.iItem, FALSE);
+	}
+}
+
+void Dialog::command(WPARAM wParam) {
+	switch(LOWORD(wParam)) {
+	case IDOK:
+	case IDCANCEL:
+		{
+			SendMessage(hwnd, WM_CLOSE, 0, 0);
+			break;
+		}
+
+	case IDC_SCROLL:
+		{
+			scroll = SendMessage(GetDlgItem(hwnd, IDC_SCROLL), BM_GETCHECK, 0, 0) == BST_CHECKED;
+			break;
+		}
+
+	case IDC_HUB_MESSAGES:
+		{
+			hubMessages = SendMessage(GetDlgItem(hwnd, IDC_HUB_MESSAGES), BM_GETCHECK, 0, 0) == BST_CHECKED;
+			break;
+		}
+
+	case IDC_USER_MESSAGES:
+		{
+			userMessages = SendMessage(GetDlgItem(hwnd, IDC_USER_MESSAGES), BM_GETCHECK, 0, 0) == BST_CHECKED;
+			break;
+		}
+
+	case IDC_FILTER:
+		{
+			if(HIWORD(wParam) == CBN_SELENDOK) {
+				filterSelChanged();
+			}
+			break;
+		}
+
+	case IDC_REGEX_APPLY:
+		{
+			applyRegex();
+			break;
+		}
+
+	case IDC_COPY:
+		{
+			copy();
+			break;
+		}
+
+	case IDC_CLEAR:
+		{
+			clear();
+			break;
+		}
+	}
+}
+
+void Dialog::initFilter() {
+	auto control = GetDlgItem(hwnd, IDC_FILTER);
+	ComboBox_SetCurSel(control, ComboBox_AddString(control, noFilter));
+}
+
+void Dialog::filterSelChanged() {
+	auto control = GetDlgItem(hwnd, IDC_FILTER);
+
+	auto sel = ComboBox_GetCurSel(control);
+
+	tstring str(ComboBox_GetLBTextLen(control, sel), '\0');
+	ComboBox_GetLBText(control, sel, &str[0]);
+
+	if(str == noFilter) {
+		filterSel.clear();
+	} else {
+		filterSel = move(str);
+	}
+}
+
+void Dialog::applyRegex() {
+	regex = "";
+
+	auto control = GetDlgItem(hwnd, IDC_REGEX);
+
+	auto n = SendMessage(control, WM_GETTEXTLENGTH, 0, 0);
+	if(!n) { return; }
+	tstring str(n + 1, 0);
+	str.resize(SendMessage(control, WM_GETTEXT, static_cast<WPARAM>(n + 1), reinterpret_cast<LPARAM>(&str[0])));
+
+	try {
+		regex.assign(Util::fromT(str));
+	} catch(const std::runtime_error&) {
+		MessageBox(hwnd, _T("Invalid regular expression"), _T("Dev plugin"), MB_OK);
+		return;
+	}
+}
+
+void Dialog::copy() {
+	tstring str;
+
+	auto control = GetDlgItem(hwnd, IDC_MESSAGES);
+	LVITEM lvi = { LVIF_PARAM };
+	int i = -1;
+	while((i = ListView_GetNextItem(control, i, LVNI_SELECTED)) != -1) {
+		lvi.iItem = i;
+		if(ListView_GetItem(control, &lvi)) {
+			auto& item = *reinterpret_cast<Item*>(lvi.lParam);
+			if(!str.empty()) { str += _T("\r\n"); }
+			str += item.index + _T(" [") + item.dir + _T("] ") + item.ip + _T(":") + item.port + _T(" (") + item.peer + _T("): ") + item.message;
+		}
+	}
+
+	// the following has been taken from WinUtil::setClipboard
+
+	if(!::OpenClipboard(hwnd)) {
+		return;
+	}
+
+	EmptyClipboard();
+
+	// Allocate a global memory object for the text.
+	HGLOBAL hglbCopy = GlobalAlloc(GMEM_MOVEABLE, (str.size() + 1) * sizeof(TCHAR));
+	if(hglbCopy == NULL) {
+		CloseClipboard();
+		return;
+	}
+
+	// Lock the handle and copy the text to the buffer.
+	TCHAR* lptstrCopy = (TCHAR*) GlobalLock(hglbCopy);
+	_tcscpy(lptstrCopy, str.c_str());
+	GlobalUnlock(hglbCopy);
+
+	// Place the handle on the clipboard.
+	SetClipboardData(CF_UNICODETEXT, hglbCopy);
+
+	CloseClipboard();
+}
+
+void Dialog::clear() {
+	auto control = GetDlgItem(hwnd, IDC_MESSAGES);
+
+	LVITEM lvi = { LVIF_PARAM };
+	for(decltype(counter) i = 0; i < counter; ++i) {
+		lvi.iItem = i;
+		if(ListView_GetItem(control, &lvi)) {
+			delete reinterpret_cast<Item*>(lvi.lParam);
+		}
+	}
+
+	ListView_DeleteAllItems(control);
+	counter = 0;
+
+	ComboBox_ResetContent(GetDlgItem(hwnd, IDC_FILTER));
+	filter.clear();
+	filterSel.clear();
+	initFilter();
+}

=== added file 'src/Dialog.h'
--- src/Dialog.h	1970-01-01 00:00:00 +0000
+++ src/Dialog.h	2012-11-15 18:52:40 +0000
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2012 Jacek Sieka, arnetheduck on gmail point com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef PLUGINS_DEV_DIALOG_H
+#define PLUGINS_DEV_DIALOG_H
+
+#include <unordered_set>
+
+#include <boost/lockfree/queue.hpp>
+#include <boost/regex.hpp>
+
+using std::move;
+using std::string;
+using std::unordered_set;
+
+class Dialog
+{
+public:
+	Dialog();
+	~Dialog();
+
+	void create();
+	void write(bool hubOrUser, bool sending, string ip, decltype(ConnectionData().port) port, string peer, string message);
+	void close();
+
+	static HINSTANCE instance;
+
+private:
+	static INT_PTR CALLBACK DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM);
+
+	// events called by DialogProc
+	BOOL init();
+	void timer();
+	void command(WPARAM wParam);
+
+	// other helpers
+	void initFilter();
+	void filterSelChanged();
+	void applyRegex();
+	void copy();
+	void clear();
+
+	HWND hwnd;
+
+	// store the messages to be displayed here; process them with a timer.
+	struct Message { bool hubOrUser; bool sending; string ip; decltype(ConnectionData().port) port; string peer; string message; };
+	boost::lockfree::queue<Message> messages;
+
+	uint16_t counter;
+	bool scroll;
+	bool hubMessages;
+	bool userMessages;
+	unordered_set<tstring> filter;
+	tstring filterSel;
+	boost::regex regex;
+
+	// objects associated to each list litem as LPARAMs.
+	struct Item {
+		tstring index;
+		tstring dir;
+		tstring ip;
+		tstring port;
+		tstring peer;
+		tstring message;
+	};
+};
+
+#endif

=== modified file 'src/Plugin.cpp'
--- src/Plugin.cpp	2012-11-15 18:17:16 +0000
+++ src/Plugin.cpp	2012-11-15 18:52:40 +0000
@@ -24,26 +24,34 @@
 #include <pluginsdk/Config.h>
 #include <pluginsdk/Core.h>
 #include <pluginsdk/Hooks.h>
+#include <pluginsdk/Hubs.h>
 #include <pluginsdk/Logger.h>
+#include <pluginsdk/UI.h>
 #include <pluginsdk/Util.h>
 
 /* Plugin SDK helpers are in the "dcapi" namespace; ease their calling. */
 using dcapi::Config;
 using dcapi::Core;
 using dcapi::Hooks;
+using dcapi::Hubs;
 using dcapi::Logger;
+using dcapi::UI;
 using dcapi::Util;
 
 Plugin::Plugin() {
 }
 
 Plugin::~Plugin() {
-	Hooks::clear();
+	clearHooks();
+
+	if(UI::handle()) {
+		UI::removeCommand(commandName);
+	}
 }
 
+Plugin* instance;
+
 Bool DCAPI Plugin::main(PluginState state, DCCorePtr core, dcptr_t) {
-	static Plugin* instance;
-
 	switch(state) {
 	case ON_INSTALL:
 	case ON_LOAD:
@@ -67,19 +75,106 @@
 	}
 }
 
+void Plugin::dlgClosed() {
+	instance->close();
+}
+
+void Plugin::addHooks() {
+	Hooks::Network::onHubDataIn([this](HubDataPtr hHub, char* message, bool&) { return onHubDataIn(hHub, message); });
+	Hooks::Network::onHubDataOut([this](HubDataPtr hHub, char* message, bool&) { return onHubDataOut(hHub, message); });
+	Hooks::Network::onClientDataIn([this](ConnectionDataPtr hConn, char* message, bool&) { return onClientDataIn(hConn, message); });
+	Hooks::Network::onClientDataOut([this](ConnectionDataPtr hConn, char* message, bool&) { return onClientDataOut(hConn, message); });
+	Hooks::UI::onChatCommand([this](HubDataPtr hHub, CommandDataPtr cmd, bool&) { return onChatCommand(hHub, cmd); });
+}
+
+void Plugin::clearHooks() {
+	Hooks::clear();
+}
+
+void Plugin::start() {
+	dialog.create();
+	addHooks();
+	Config::setConfig("Enabled", true);
+	refreshSwitchCommand();
+}
+
+void Plugin::close() {
+	Config::setConfig("Enabled", false);
+	clearHooks();
+	dialog.close();
+	refreshSwitchCommand();
+}
+
+void Plugin::refreshSwitchCommand() {
+	UI::removeCommand(commandName);
+	commandName = Hooks::empty() ? PLUGIN_NAME ": enable" : PLUGIN_NAME ": disable";
+	UI::addCommand(commandName, [this] { onSwitched(); });
+}
+
 bool Plugin::onLoad(DCCorePtr core, bool install) {
 	/* Initialization phase. Initiate additional interfaces that you may have included from the
 	plugin SDK. */
 	Core::init(core);
-	if(!Config::init(PLUGIN_GUID) || !Hooks::init() || !Logger::init() || !Util::init()) {
+	if(!Config::init(PLUGIN_GUID) || !Hooks::init() || !Hubs::init() || !Logger::init() || !UI::init() || !Util::init()) {
 		return false;
 	}
 
 	if(install) {
 		// This only executes when the plugin has been installed for the first time.
+		Config::setConfig("Enabled", true);
+
+		Logger::log("The dev plugin has been installed; check the plugins menu and the /raw chat command.");
 	}
 
 	// Start the plugin logic here; add hooks with functions from the Hooks interface.
+	if(Config::getBoolConfig("Enabled")) {
+		start();
+	} else {
+		refreshSwitchCommand();
+	}
 
 	return true;
 }
+
+void Plugin::onSwitched() {
+	if(Hooks::empty()) {
+		start();
+	} else {
+		close();
+	}
+}
+
+bool Plugin::onHubDataIn(HubDataPtr hHub, char* message) {
+	dialog.write(true, false, hHub->ip, hHub->port, "Hub " + string(hHub->url), message);
+	return false;
+}
+
+bool Plugin::onHubDataOut(HubDataPtr hHub, char* message) {
+	dialog.write(true, true, hHub->ip, hHub->port, "Hub " + string(hHub->url), message);
+	return false;
+}
+
+bool Plugin::onClientDataIn(ConnectionDataPtr hConn, char* message) {
+	dialog.write(false, false, hConn->ip, hConn->port, "User" /** @todo get user's nick */, message);
+	return false;
+}
+
+bool Plugin::onClientDataOut(ConnectionDataPtr hConn, char* message) {
+	dialog.write(false, true, hConn->ip, hConn->port, "User" /** @todo get user's nick */, message);
+	return false;
+}
+
+bool Plugin::onChatCommand(HubDataPtr hub, CommandDataPtr cmd) {
+	if(stricmp(cmd->command, "help") == 0) {
+		Hubs::handle()->local_message(hub, "/raw <message>", MSG_SYSTEM);
+
+	} else if(stricmp(cmd->command, "raw") == 0) {
+		if(strlen(cmd->params) == 0) {
+			Hubs::handle()->local_message(hub, "Specify a message to send", MSG_SYSTEM);
+		} else {
+			Hubs::handle()->send_protocol_cmd(hub, cmd->params);
+		}
+	}
+
+	return false;
+}

=== modified file 'src/Plugin.h'
--- src/Plugin.h	2012-11-15 18:17:16 +0000
+++ src/Plugin.h	2012-11-15 18:52:40 +0000
@@ -19,6 +19,8 @@
 #ifndef PLUGIN_PLUGIN_H
 #define PLUGIN_PLUGIN_H
 
+#include "Dialog.h"
+
 using std::string;
 
 class Plugin
@@ -26,11 +28,31 @@
 public:
 	static Bool DCAPI main(PluginState state, DCCorePtr core, dcptr_t);
 
+	static void dlgClosed();
+
 private:
 	Plugin();
 	~Plugin();
 
+	void addHooks();
+	void clearHooks();
+
+	void start();
+	void close();
+
+	void refreshSwitchCommand();
+
 	bool onLoad(DCCorePtr core, bool install);
+	void onSwitched();
+	bool onHubDataIn(HubDataPtr hHub, char* message);
+	bool onHubDataOut(HubDataPtr hHub, char* message);
+	bool onClientDataIn(ConnectionDataPtr hConn, char* message);
+	bool onClientDataOut(ConnectionDataPtr hConn, char* message);
+	bool onChatCommand(HubDataPtr hub, CommandDataPtr cmd);
+
+	Dialog dialog;
+
+	string commandName;
 };
 
 #endif

=== modified file 'src/main.cpp'
--- src/main.cpp	2012-11-15 18:17:16 +0000
+++ src/main.cpp	2012-11-15 18:52:40 +0000
@@ -17,6 +17,7 @@
  */
 
 #include "stdafx.h"
+#include "Dialog.h"
 #include "Plugin.h"
 #include "version.h"
 
@@ -36,7 +37,8 @@
 }
 
 #ifdef _WIN32
-BOOL APIENTRY DllMain(HINSTANCE /*hinstDLL*/, DWORD /*fdwReason*/, LPVOID /*lpvReserved*/) {
+BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD /*fdwReason*/, LPVOID /*lpvReserved*/) {
+	Dialog::instance = hinstDLL;
 	return TRUE;
 }
 #endif

=== modified file 'src/resource.h'
--- src/resource.h	2012-11-15 18:17:16 +0000
+++ src/resource.h	2012-11-15 18:52:40 +0000
@@ -3,6 +3,16 @@
 // Used by resource.rc
 //
 #define VERSION_INFO                    1
+#define IDD_PLUGINDLG                   101
+#define IDC_MESSAGES                    1001
+#define IDC_COPY                        1002
+#define IDC_CLEAR                       1003
+#define IDC_SCROLL                      1004
+#define IDC_HUB_MESSAGES                1005
+#define IDC_USER_MESSAGES               1006
+#define IDC_FILTER                      1007
+#define IDC_REGEX                       1008
+#define IDC_REGEX_APPLY                 1009
 
 // Next default values for new objects
 // 
@@ -10,7 +20,7 @@
 #ifndef APSTUDIO_READONLY_SYMBOLS
 #define _APS_NEXT_RESOURCE_VALUE        102
 #define _APS_NEXT_COMMAND_VALUE         40001
-#define _APS_NEXT_CONTROL_VALUE         1002
+#define _APS_NEXT_CONTROL_VALUE         1010
 #define _APS_NEXT_SYMED_VALUE           101
 #endif
 #endif

=== modified file 'src/resource.rc'
--- src/resource.rc	2012-11-15 18:17:16 +0000
+++ src/resource.rc	2012-11-15 18:52:40 +0000
@@ -67,13 +67,13 @@
     BEGIN
         BLOCK "080004b0"
         BEGIN
-            VALUE "Comments", "..."
-            VALUE "FileDescription", "..."
+            VALUE "Comments", "http://dcplusplus.sourceforge.net";
+            VALUE "FileDescription", "Dev plugin for DC++"
             VALUE "FileVersion", "1, 0, 0, 0"
-            VALUE "InternalName", "..."
-            VALUE "LegalCopyright", "..."
-            VALUE "OriginalFilename", "..."
-            VALUE "ProductName", "..."
+            VALUE "InternalName", "DevPlugin"
+            VALUE "LegalCopyright", "Copyright (C) 2012 Jacek Sieka"
+            VALUE "OriginalFilename", "DevPlugin.dll"
+            VALUE "ProductName", "Dev plugin for DC++"
             VALUE "ProductVersion", "1, 0, 0, 0"
         END
     END
@@ -83,6 +83,52 @@
     END
 END
 
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_PLUGINDLG DIALOGEX 0, 0, 723, 479
+STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Dev plugin"
+FONT 8, "MS Shell Dlg", 400, 0, 0x1
+BEGIN
+    DEFPUSHBUTTON   "Close",IDOK,666,458,50,14
+    PUSHBUTTON      "Cancel",IDCANCEL,615,458,50,14,NOT WS_VISIBLE | WS_DISABLED
+    CONTROL         "",IDC_MESSAGES,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | WS_BORDER | WS_VSCROLL | WS_HSCROLL | WS_TABSTOP,7,7,709,418
+    PUSHBUTTON      "Copy selected messages",IDC_COPY,7,458,129,14
+    PUSHBUTTON      "Clear the list",IDC_CLEAR,260,458,88,14
+    CONTROL         "Auto-scroll",IDC_SCROLL,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,168,462,50,10
+    CONTROL         "Add hub messages",IDC_HUB_MESSAGES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,439,76,10
+    CONTROL         "Add user messages",IDC_USER_MESSAGES,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,95,439,78,10
+    COMBOBOX        IDC_FILTER,187,437,140,30,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
+    EDITTEXT        IDC_REGEX,351,435,206,14,ES_AUTOHSCROLL
+    PUSHBUTTON      "Apply the regex",IDC_REGEX_APPLY,565,435,81,14
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+    IDD_PLUGINDLG, DIALOG
+    BEGIN
+        LEFTMARGIN, 7
+        RIGHTMARGIN, 716
+        TOPMARGIN, 7
+        BOTTOMMARGIN, 472
+        HORZGUIDE, 435
+        HORZGUIDE, 449
+        HORZGUIDE, 458
+    END
+END
+#endif    // APSTUDIO_INVOKED
+
 #endif    // English (United States) resources
 /////////////////////////////////////////////////////////////////////////////
 

=== modified file 'src/stdafx.h'
--- src/stdafx.h	2012-11-15 18:17:16 +0000
+++ src/stdafx.h	2012-11-15 18:52:40 +0000
@@ -26,6 +26,8 @@
 
 #else
 
+#error The dev plugin only works on Windows
+
 #include <unistd.h>
 
 #endif

=== modified file 'src/version.h'
--- src/version.h	2012-11-15 18:17:16 +0000
+++ src/version.h	2012-11-15 18:52:40 +0000
@@ -18,27 +18,25 @@
 
 /* Information about the plugin - fill this out! Don't forget to edit the resource file as well. */
 
-#error Version information not set! Remove this error once you have filled version.h and the resource file.
-
 #ifndef PLUGIN_VERSION_H
 #define PLUGIN_VERSION_H
 
 /* UUID/GUID for this plugin project */
-#define PLUGIN_GUID "..."
+#define PLUGIN_GUID "{22b95072-afdd-4e36-82b4-c796fb61f41a}"
 
 /* Name of the plugin */
-#define PLUGIN_NAME "..."
+#define PLUGIN_NAME "Dev plugin"
 
 /* Author of the plugin */
-#define PLUGIN_AUTHOR "..."
+#define PLUGIN_AUTHOR "DC++"
 
 /* Short description of the plugin */
-#define PLUGIN_DESC "..."
+#define PLUGIN_DESC "Plugin for developers: network traffic analysis, ability to send custom commands."
 
 /* Version of the plugin (note: not API version) */
 #define PLUGIN_VERSION 1.0
 
 /* Plugin website, set to "N/A" if none */
-#define PLUGIN_WEB "N/A"
+#define PLUGIN_WEB "http://dcplusplus.sourceforge.net/";
 
 #endif