From f17646aaa5e410a2e673e0de69358c9d5e09f63b Mon Sep 17 00:00:00 2001 From: Vadim Dashevskiy Date: Mon, 9 Jul 2012 06:47:31 +0000 Subject: Boltun: changed folder structure git-svn-id: http://svn.miranda-ng.org/main/trunk@866 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- plugins/Boltun/src/actionQueue.cpp | 254 +++++++++++++ plugins/Boltun/src/actionQueue.h | 30 ++ plugins/Boltun/src/boltun.cpp | 713 +++++++++++++++++++++++++++++++++++++ plugins/Boltun/src/boltun.h | 74 ++++ plugins/Boltun/src/config.cpp | 159 +++++++++ plugins/Boltun/src/config.h | 157 ++++++++ plugins/Boltun/src/resource.h | 46 +++ 7 files changed, 1433 insertions(+) create mode 100644 plugins/Boltun/src/actionQueue.cpp create mode 100644 plugins/Boltun/src/actionQueue.h create mode 100644 plugins/Boltun/src/boltun.cpp create mode 100644 plugins/Boltun/src/boltun.h create mode 100644 plugins/Boltun/src/config.cpp create mode 100644 plugins/Boltun/src/config.h create mode 100644 plugins/Boltun/src/resource.h (limited to 'plugins/Boltun/src') diff --git a/plugins/Boltun/src/actionQueue.cpp b/plugins/Boltun/src/actionQueue.cpp new file mode 100644 index 0000000000..c464c92f39 --- /dev/null +++ b/plugins/Boltun/src/actionQueue.cpp @@ -0,0 +1,254 @@ +//*********************************************************** +// Copyright 2003-2008 Alexander S. Kiselev, Valentin Pavlyuchenko +// +// This file is part of Boltun. +// +// Boltun 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. +// +// Boltun 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 Boltun. If not, see . +// +//*********************************************************** + +#include "actionQueue.h" +#include "config.h" +#include "boltun.h" +#include "Engine/tstring.h" +#include "Engine/TalkEngine.h" + +#include +#include +#include +#include "Engine/CriticalSection.h" +#ifdef _DEBUG +#include +#endif + +#define MIRANDA_VER 0x0A00 +#include "newpluginapi.h" +#include "m_database.h" +#include "m_system.h" +#include "m_protosvc.h" + +using namespace std; + +extern TalkBot* bot; + +typedef void (*ActionHandler)(HANDLE hContact, const TalkBot::MessageInfo *inf); + +typedef struct _QueueElement { + HANDLE hContact; + const TalkBot::MessageInfo *inf; + ActionHandler Handler; + bool Sticky; + int TimeOffset; + _QueueElement(HANDLE contact, ActionHandler handler, int timeOffset, const TalkBot::MessageInfo *info = NULL, bool sticky = false) + :hContact(contact), Handler(handler), TimeOffset(timeOffset), inf(info), Sticky(sticky) + { + } +} QueueElement; + +static list actionQueue; +static set typingContacts; +UINT_PTR timerID = 0; + +CriticalSection cs; +CriticalSection typingContactsLock; + +void UpdateTimer(); + +VOID CALLBACK TimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) +{ + cs.Enter(); + QueueElement q = actionQueue.front(); + actionQueue.pop_front(); + UpdateTimer(); + cs.Leave(); + q.Handler(q.hContact, q.inf); +} + +void UpdateTimer() +{ + if (timerID) + KillTimer(NULL, timerID); + if (actionQueue.size()) + timerID = SetTimer(NULL, 0, actionQueue.front().TimeOffset, TimerProc); + else + timerID = 0; +} + +static bool NotifyTyping(HANDLE hContact) +{ + int res = DBGetContactSettingByte(hContact, "SRMsg", "SupportTyping", 2); + if (res == 2) + res = DBGetContactSettingByte(NULL, "SRMsg", "DefaultTyping", 1); + return res != 0; +} + +static char *MsgServiceName(HANDLE hContact) +{ + + char szServiceName[100]; + char *szProto = (char *) CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM) hContact, 0); + if (szProto == NULL) + return PSS_MESSAGE; + + mir_snprintf(szServiceName, sizeof(szServiceName), "%s%sW", szProto, PSS_MESSAGE); + if (ServiceExists(szServiceName)) + return PSS_MESSAGE "W"; + + return PSS_MESSAGE; +} + +static void TimerAnswer(HANDLE hContact, const TalkBot::MessageInfo* info) +{ + DBEVENTINFO ldbei; + int size = (int)info->Answer.length() + 1; + int bufsize = size; + char* msg; + + bufsize *= sizeof(TCHAR) + 1; + msg = new char[bufsize]; + //msg[size - 1] = '\0'; + + if (!WideCharToMultiByte(CP_ACP, 0, info->Answer.c_str(), -1, msg, size, + NULL, NULL)) + FillMemory(msg, size - 1, '-'); //In case of fault return "----" in ANSI part + CopyMemory(msg + size, info->Answer.c_str(), size * 2); + + + CallContactService(hContact, MsgServiceName(hContact), PREF_TCHAR, (LPARAM)msg); + + ZeroMemory(&ldbei, sizeof(ldbei)); + ldbei.cbSize = sizeof(ldbei); + //FIXME: Error may happen + ldbei.cbBlob = bufsize; + ldbei.pBlob = (PBYTE)(void*)msg; + ldbei.eventType = EVENTTYPE_MESSAGE; + ldbei.flags = DBEF_SENT; + ldbei.szModule = BOLTUN_NAME; + ldbei.timestamp = (DWORD)time(NULL); + + CallService(MS_DB_EVENT_ADD, (WPARAM)hContact, (LPARAM)&ldbei); + bot->AnswerGiven(hContact, *info); + delete info; + + delete msg; + + typingContactsLock.Enter(); + typingContacts.erase(hContact); + typingContactsLock.Leave(); +} + +static void StartTyping(HANDLE hContact, const TalkBot::MessageInfo*) +{ + CallService(MS_PROTO_SELFISTYPING, (WPARAM)hContact, + (LPARAM)PROTOTYPE_SELFTYPING_ON); + typingContactsLock.Enter(); + typingContacts.insert(hContact); + typingContactsLock.Leave(); +} + +void DoAnswer(HANDLE hContact, const TalkBot::MessageInfo *info, bool sticky = false) +{ + if (info->Answer[0] == _T('\0')) + return; + int waitTime, thinkTime = 0; + int defWaitTime = Config.AnswerPauseTime * 1000; + if (Config.PauseDepends) + waitTime = defWaitTime * (int)info->Answer.length() / 25; + else + waitTime = defWaitTime; + if (Config.PauseRandom) + { + //Let it be up to 4 times longer. + waitTime = waitTime * (rand() % 300) / 100 + waitTime; + } + if (waitTime == 0) + waitTime = 50; //it's essential, because otherwise message will be added later + //then its response, that will cause incorrect ordering of + //messages in the opened history (reopening will + //help, but anyway it's no good) + if (NotifyTyping(hContact) && Config.AnswerThinkTime) + { + thinkTime = Config.AnswerThinkTime * 1000; + if (Config.PauseRandom) + { + //Let it be up to 4 times longer. + thinkTime = thinkTime * (rand() % 300) / 100 + thinkTime; + } + } + cs.Enter(); + //Check if this contact's timer handler is now waiting for a cs. + bool needTimerRearrange = false; + if (!actionQueue.empty() && actionQueue.front().hContact == hContact) + { + needTimerRearrange = true; + KillTimer(NULL, timerID); + cs.Leave(); + cs.Enter(); + } + if (!actionQueue.empty()) + { + list::iterator it = actionQueue.end(); + it--; + while (true) + { + if ((*it).hContact == hContact) + { + if ((*it).Sticky) + break; + list::iterator tmp = it; + if (tmp != actionQueue.begin()) + tmp--; + actionQueue.erase(it); + it = tmp; + if (actionQueue.empty()) + break; + } + if (it == actionQueue.begin()) + break; + it--; + } + } + typingContactsLock.Enter(); + if (typingContacts.find(hContact) != typingContacts.end()) + { + CallService(MS_PROTO_SELFISTYPING, (WPARAM)hContact, (LPARAM)PROTOTYPE_SELFTYPING_OFF); + typingContacts.erase(hContact); + } + typingContactsLock.Leave(); + if (actionQueue.empty()) + needTimerRearrange = true; + if (thinkTime) + actionQueue.push_back(QueueElement(hContact, StartTyping, thinkTime, NULL, sticky)); + actionQueue.push_back(QueueElement(hContact, TimerAnswer, waitTime, info, sticky)); + if (needTimerRearrange) + UpdateTimer(); + cs.Leave(); +} + +void AnswerToContact(HANDLE hContact, const TCHAR* messageToAnswer) +{ + if (Config.TalkWarnContacts && DBGetContactSettingByte(hContact, BOLTUN_KEY, + DB_CONTACT_WARNED, FALSE) == FALSE) + { + DoAnswer(hContact, new TalkBot::MessageInfo((const TCHAR*)Config.WarnText), true); + DBWriteContactSettingByte(hContact, BOLTUN_KEY, DB_CONTACT_WARNED, TRUE); + } + else + DoAnswer(hContact, bot->Reply(hContact, messageToAnswer, false)); +} + +void StartChatting(HANDLE hContact) +{ + DoAnswer(hContact, new TalkBot::MessageInfo(bot->GetInitMessage(hContact)), true); +} diff --git a/plugins/Boltun/src/actionQueue.h b/plugins/Boltun/src/actionQueue.h new file mode 100644 index 0000000000..78f6ce5f9e --- /dev/null +++ b/plugins/Boltun/src/actionQueue.h @@ -0,0 +1,30 @@ +//*********************************************************** +// Copyright © 2003-2008 Alexander S. Kiselev, Valentin Pavlyuchenko +// +// This file is part of Boltun. +// +// Boltun 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. +// +// Boltun 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 Boltun. If not, see . +// +//*********************************************************** + +#ifndef ACTIONQUEUE_H +#define ACTIONQUEUE_H + +#include + +void AnswerToContact(HANDLE hContact, const TCHAR* messageToAnswer); + +void StartChatting(HANDLE hContact); + +#endif /* ACTIONQUEUE_H */ \ No newline at end of file diff --git a/plugins/Boltun/src/boltun.cpp b/plugins/Boltun/src/boltun.cpp new file mode 100644 index 0000000000..52e140d509 --- /dev/null +++ b/plugins/Boltun/src/boltun.cpp @@ -0,0 +1,713 @@ +//*********************************************************** +// Copyright © 2003-2008 Alexander S. Kiselev, Valentin Pavlyuchenko +// +// This file is part of Boltun. +// +// Boltun 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. +// +// Boltun 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 Boltun. If not, see . +// +//*********************************************************** + +#define MIRANDA_VER 0x0A00 + +#include "Engine/TalkEngine.h" + +#include +#include +#include + +#include "newpluginapi.h" +#include "m_clist.h" +#include "m_skin.h" +#include "m_database.h" +#include "m_system.h" +#include "m_protosvc.h" +#include "m_options.h" +#include "m_langpack.h" +#include "resource.h" + +#include "resource.h" + +#include "boltun.h" +#include "config.h" +#include "actionQueue.h" + +//#define DEBUG_LOAD_TIME + +int hLangpack; + +TalkBot* bot = NULL; + + +#define MAX_WARN_TEXT 1024 +#define MAX_MIND_FILE 1024 + +HINSTANCE hInst; +BOOL blInit = FALSE; +UINT pTimer = 0; +TCHAR *path; + +PLUGININFOEX pluginInfo={ + sizeof(PLUGININFOEX), + BOLTUN_NAME, + PLUGIN_MAKE_VERSION(0,0,3,0), + PLUGIN_DESCRIPTION, + "Alexander S. Kiselev, Valentin Pavlyuchenko", + "Valentin.Pavlyuchenko@gmail.com", + "© 2003-2008 Alexander S. Kiselev A.K.A. KAS, Valentin Pavlyuchenko", + "http://miranda-im.org", + UNICODE_AWARE, + // {488C5C84-56DA-434F-96F1-B18900DEF760} + { 0x488c5c84, 0x56da, 0x434f, { 0x96, 0xf1, 0xb1, 0x89, 0x0, 0xde, 0xf7, 0x60 } } +}; + +static HANDLE hEventDbEventAdded; +static HANDLE hEventOptInitialise; +static HANDLE hEventPrebuild; +static HANDLE hMenuItemAutoChat; +static HANDLE hMenuItemNotToChat; +static HANDLE hMenuItemStartChatting; + + +#define MIND_DIALOG_FILTER _T("%s (*.mindw)\1*.mindw\1%s (*.*)\1*.*\1") + + +#ifdef DEBUG_LOAD_TIME +#include +#endif + +void UpdateEngine() +{ + if (bot) + { + bot->SetSilent(Config.EngineStaySilent); + bot->SetLowercase(Config.EngineMakeLowerCase); + bot->SetUnderstandAlways(Config.EngineUnderstandAlways); + } +} + +TCHAR* GetFullName(const TCHAR* filename) +{ + size_t flen = _tcslen(filename); + TCHAR* fullname = const_cast(filename); + if (!_tcschr(filename, _T(':'))) + { + size_t plen = _tcslen(path); + fullname = new TCHAR[plen+flen+1]; + fullname[0] = NULL; + _tcscat(fullname, path); + _tcscat(fullname, filename); + } + return fullname; +} + +static bool LoadMind(const TCHAR* filename, int &line) +{ + TCHAR* fullname = GetFullName(filename); + HCURSOR newCur = LoadCursor(NULL, MAKEINTRESOURCE(IDC_WAIT)); + HCURSOR oldCur = SetCursor(newCur); +#ifdef DEBUG_LOAD_TIME + unsigned __int64 t = __rdtsc(); +#endif + Mind* mind = new Mind(); + line = -1; + try + { + mind->Load(fullname); + } + catch(Mind::CorruptedMind c) + { + line = c.line; + delete mind; + if (fullname != filename) + delete[] fullname; + SetCursor(oldCur); + return false; + } + catch(...) + { + delete mind; + if (fullname != filename) + delete[] fullname; + SetCursor(oldCur); + return false; + } + if (fullname != filename) + delete[] fullname; + +#ifdef DEBUG_LOAD_TIME + t = __rdtsc() - t; + char dest[101]; + sprintf_s(dest, 100, "%I64d ticks\n", t / 3200000); + MessageBoxA(NULL, dest, NULL, 0); + //exit(0); +#endif + SetCursor(oldCur); + HRSRC hRes = FindResource(hInst, MAKEINTRESOURCE(IDR_SMILES), _T("SMILES")); + if (!hRes) + { + delete mind; + return false; + } + DWORD size = SizeofResource(hInst, hRes); + if (!size) + { + delete mind; + return false; + } + HGLOBAL hGlob = LoadResource(hInst, hRes); + if (!hGlob) + { + delete mind; + return false; + } + void *data = LockResource(hGlob); + if (!data) + { + FreeResource(hGlob); + delete mind; + return false; + } + bool res = true; + try + { + mind->LoadSmiles(data, size); + } + catch(...) + { + res = false; + } + UnlockResource(data); + FreeResource(hGlob); + if (!res) + { + delete mind; + return false; + } + if (bot) + delete bot; + bot = new TalkBot(*mind); + delete mind; + UpdateEngine(); + return true; +} + +/*static bool SaveMind(const TCHAR* filename) +{ + if (!bot) + return false; + bot->GetMind().Save(filename); + return true; +}*/ + +static bool BoltunAutoChat(HANDLE hContact) +{ + if (DBGetContactSettingByte(hContact, BOLTUN_KEY, DB_CONTACT_BOLTUN_NOT_TO_CHAT + , FALSE) == TRUE) + return false; + + if (Config.TalkWithEverybody) + return true; + + if (Config.TalkEveryoneWhileAway) + { + int status = CallService(MS_CLIST_GETSTATUSMODE, 0, 0); + if (status == ID_STATUS_AWAY || + status == ID_STATUS_DND || + status == ID_STATUS_NA || + status == ID_STATUS_OCCUPIED || + status == ID_STATUS_ONTHEPHONE || + status == ID_STATUS_OUTTOLUNCH) + return true; + } + + if ((DBGetContactSettingByte(hContact,"CList","NotOnList",0) == 1) && + Config.TalkWithNotInList) + return true; + + if (DBGetContactSettingByte(hContact, BOLTUN_KEY, DB_CONTACT_BOLTUN_AUTO_CHAT, + FALSE) == TRUE) + return true; + + return false; +} + +static int MessageEventAdded(WPARAM wParam, LPARAM lParam) +{ + //DBEVENTINFO ldbei; + HANDLE hContact = (HANDLE)wParam; + if (!BoltunAutoChat(hContact)) + return 0; + + DBEVENTINFO dbei; + ZeroMemory(&dbei, sizeof(dbei)); + dbei.cbSize = sizeof(dbei); + dbei.cbBlob = 0; + + dbei.cbBlob = CallService(MS_DB_EVENT_GETBLOBSIZE, lParam, 0); + if (dbei.cbBlob == -1) + return 0; + + dbei.pBlob = (PBYTE)malloc(dbei.cbBlob); + if (dbei.pBlob == NULL) + return 0; + + CallService(MS_DB_EVENT_GET, lParam, (LPARAM)&dbei); + if (dbei.flags & DBEF_SENT || dbei.flags & DBEF_READ || dbei.eventType != EVENTTYPE_MESSAGE) + return 0; + DBEVENTGETTEXT egt; + egt.codepage = CP_ACP; + egt.datatype = DBVT_TCHAR; + egt.dbei = &dbei; + TCHAR* s = (TCHAR*)(void*)CallService(MS_DB_EVENT_GETTEXT, 0, (LPARAM)&egt); + free(dbei.pBlob); + if (Config.MarkAsRead) + CallService(MS_DB_EVENT_MARKREAD, wParam, lParam); + + AnswerToContact(hContact, s); + mir_free(s); + return 0; +} + +BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved) +{ + hInst = hinstDLL; + return TRUE; +} + +void UpdateEverybodyCheckboxes(HWND hwndDlg) +{ + bool Enable = !IsDlgButtonChecked(hwndDlg, IDC_EVERYBODY) == BST_CHECKED; + HWND wnd; + wnd = GetDlgItem(hwndDlg, IDC_NOTINLIST); + EnableWindow(wnd, Enable); + wnd = GetDlgItem(hwndDlg, IDC_AUTOAWAY); + EnableWindow(wnd, Enable); +} + +static INT_PTR CALLBACK MainDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + BOOL bTranslated = FALSE; + static bool loading = true; + switch (uMsg) + { + case WM_INITDIALOG: + loading = true; + TranslateDialogDefault(hwndDlg); + CheckDlgButton(hwndDlg, IDC_EVERYBODY, Config.TalkWithEverybody ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_NOTINLIST, Config.TalkWithNotInList ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_AUTOAWAY, Config.TalkEveryoneWhileAway ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_WARN, Config.TalkWarnContacts ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_MARKREAD, Config.MarkAsRead ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_PAUSEDEPENDS, Config.PauseDepends ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_PAUSERANDOM, Config.PauseRandom ? BST_CHECKED : BST_UNCHECKED); + SendDlgItemMessage(hwndDlg, IDC_WAITTIME, EM_SETLIMITTEXT, 3, 0); + SetDlgItemInt(hwndDlg, IDC_WAITTIME, Config.AnswerPauseTime, FALSE); + SendDlgItemMessage(hwndDlg, IDC_THINKTIME, EM_SETLIMITTEXT, 3, 0); + SetDlgItemInt(hwndDlg, IDC_THINKTIME, Config.AnswerThinkTime, FALSE); + SendDlgItemMessage(hwndDlg, IDC_WARNTXT, EM_SETLIMITTEXT, MAX_WARN_TEXT, 0); + SetDlgItemText(hwndDlg, IDC_WARNTXT, Config.WarnText); + UpdateEverybodyCheckboxes(hwndDlg); + loading = false; + return TRUE; + case WM_COMMAND: + if (LOWORD(wParam) == IDC_EVERYBODY && HIWORD(wParam) == BN_CLICKED) + UpdateEverybodyCheckboxes(hwndDlg); + if (!loading) + { + bool notify = true; + switch (LOWORD(wParam)) + { + case IDC_WARNTXT: + case IDC_WAITTIME: + case IDC_THINKTIME: + if (HIWORD(wParam) != EN_CHANGE) + notify = false; + break; + } + if (notify) + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + } + break; + case WM_NOTIFY: + { + NMHDR* nmhdr = (NMHDR*)lParam; + switch (nmhdr->code) + { + case PSN_APPLY: + case PSN_KILLACTIVE: + { + Config.TalkWithEverybody = IsDlgButtonChecked(hwndDlg, IDC_EVERYBODY) == BST_CHECKED ? TRUE : FALSE; + Config.TalkWithNotInList = IsDlgButtonChecked(hwndDlg, IDC_NOTINLIST) == BST_CHECKED ? TRUE : FALSE; + Config.TalkEveryoneWhileAway = IsDlgButtonChecked(hwndDlg, IDC_AUTOAWAY) == BST_CHECKED ? TRUE : FALSE; + Config.TalkWarnContacts = IsDlgButtonChecked(hwndDlg, IDC_WARN) == BST_CHECKED ? TRUE : FALSE; + Config.MarkAsRead = IsDlgButtonChecked(hwndDlg, IDC_MARKREAD) == BST_CHECKED ? TRUE : FALSE; + Config.PauseDepends = IsDlgButtonChecked(hwndDlg, IDC_PAUSEDEPENDS) == BST_CHECKED ? TRUE : FALSE; + Config.PauseRandom = IsDlgButtonChecked(hwndDlg, IDC_PAUSERANDOM) == BST_CHECKED ? TRUE : FALSE; + Config.AnswerPauseTime = GetDlgItemInt(hwndDlg, IDC_WAITTIME, &bTranslated, FALSE); + if (!bTranslated) + Config.AnswerPauseTime = 2; + Config.AnswerThinkTime = GetDlgItemInt(hwndDlg, IDC_THINKTIME, &bTranslated, FALSE); + if (!bTranslated) + Config.AnswerThinkTime = 4; + TCHAR c[MAX_WARN_TEXT]; + bTranslated = GetDlgItemText(hwndDlg, IDC_WARNTXT, c, MAX_WARN_TEXT); + if(bTranslated) + Config.WarnText = c; + else + Config.WarnText = TranslateTS(DEFAULT_WARN_TEXT); + } + return TRUE; + } + break; + } + break; + } + return 0; +} + +void UpdateUnderstandAlwaysCheckbox(HWND hwndDlg) +{ + bool Enable = !IsDlgButtonChecked(hwndDlg, IDC_ENGINE_SILENT) == BST_CHECKED; + HWND wnd; + wnd = GetDlgItem(hwndDlg, IDC_ENGINE_UNDERSTAND_ALWAYS); + EnableWindow(wnd, Enable); +} + +static INT_PTR CALLBACK EngineDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + WORD param; + BOOL bTranslated = FALSE; + static bool loading = true; + static int changeCount = 0; + switch (uMsg) + { + case WM_INITDIALOG: + loading = true; + TranslateDialogDefault(hwndDlg); + CheckDlgButton(hwndDlg, IDC_ENGINE_SILENT, Config.EngineStaySilent ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_ENGINE_LOWERCASE, Config.EngineMakeLowerCase ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(hwndDlg, IDC_ENGINE_UNDERSTAND_ALWAYS, Config.EngineUnderstandAlways ? BST_CHECKED : BST_UNCHECKED); + SetDlgItemText(hwndDlg, IDC_MINDFILE, Config.MindFileName); + EnableWindow(GetDlgItem(hwndDlg, IDC_BTNSAVE), blInit); + UpdateUnderstandAlwaysCheckbox(hwndDlg); + loading = false; + return TRUE; + case WM_COMMAND: + param = LOWORD(wParam); + if (param == IDC_ENGINE_SILENT && HIWORD(wParam) == BN_CLICKED) + UpdateUnderstandAlwaysCheckbox(hwndDlg); + OPENFILENAME ofn; + switch(param) + { + case IDC_BTNPATH: + { + const size_t fileNameSize = 5000; + TCHAR *filename = new TCHAR[fileNameSize]; + TCHAR *fullname = GetFullName(Config.MindFileName); + _tcscpy(filename, fullname); + if (fullname != Config.MindFileName) + delete[] fullname; + + ZeroMemory(&ofn, sizeof(ofn)); + ofn.lStructSize = sizeof(OPENFILENAME); + ofn.hwndOwner = GetParent(hwndDlg); + + TCHAR* mind = TranslateTS(MIND_FILE_DESC); + TCHAR* anyfile = TranslateTS(ALL_FILES_DESC); + size_t l = _tcslen(MIND_DIALOG_FILTER) + + _tcslen(mind) + _tcslen(anyfile); + TCHAR *filt = new TCHAR[l]; + wsprintf(filt, MIND_DIALOG_FILTER, mind, anyfile); + for (size_t i = 0; i < l; i++) + if (filt[i] == '\1') + filt[i] = '\0'; + ofn.lpstrFilter = filt; + + ofn.lpstrFile = filename; + ofn.nMaxFile = fileNameSize; + ofn.Flags = OFN_FILEMUSTEXIST; + ofn.lpstrInitialDir = path; + if (!GetOpenFileName(&ofn)) + { + delete filename; + delete[] filt; + break; + } + delete[] filt; + TCHAR* origf = filename; + TCHAR* f = filename; + TCHAR* p = path; + while (*p && *f) + { + TCHAR p1 = (TCHAR)CharLower((TCHAR*)(long)*p++); + TCHAR f1 = (TCHAR)CharLower((TCHAR*)(long)*f++); + if (p1 != f1) + break; + } + if (!*p) + filename = f; + Config.MindFileName = filename; + SetDlgItemText(hwndDlg, IDC_MINDFILE, filename); + delete origf; + } + case IDC_BTNRELOAD: + { + const TCHAR *c = Config.MindFileName; + int line; + bTranslated = blInit = LoadMind(c, line); + if (!bTranslated) + { + TCHAR* message = new TCHAR[5000]; + wsprintf(message, TranslateTS(FAILED_TO_LOAD_BASE), line, c); + MessageBox(NULL, message, TranslateTS(BOLTUN_ERROR), MB_ICONERROR|MB_TASKMODAL|MB_OK); + delete[] message; + } + break; + } + default: + if (!loading) + { + if (param == IDC_MINDFILE/* && HIWORD(wParam) != EN_CHANGE*/) + break; + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + } + } + break; + case WM_NOTIFY: + { + NMHDR* nmhdr = (NMHDR*)lParam; + switch (nmhdr->code) + { + case PSN_APPLY: + case PSN_KILLACTIVE: + { + Config.EngineStaySilent = IsDlgButtonChecked(hwndDlg, IDC_ENGINE_SILENT) == BST_CHECKED ? TRUE : FALSE; + Config.EngineMakeLowerCase = IsDlgButtonChecked(hwndDlg, IDC_ENGINE_LOWERCASE) == BST_CHECKED ? TRUE : FALSE; + Config.EngineUnderstandAlways = IsDlgButtonChecked(hwndDlg, IDC_ENGINE_UNDERSTAND_ALWAYS) == BST_CHECKED ? TRUE : FALSE; + UpdateEngine(); + TCHAR c[MAX_MIND_FILE]; + bTranslated = GetDlgItemText(hwndDlg, IDC_MINDFILE, c, MAX_MIND_FILE); + if (bTranslated) + Config.MindFileName = c; + else + Config.MindFileName = DEFAULT_MIND_FILE; + } + return TRUE; + } + break; + } + break; + } + return 0; +} + +static int MessageOptInit(WPARAM wParam, LPARAM lParam) +{ + OPTIONSDIALOGPAGE odp; + + ZeroMemory(&odp, sizeof(odp)); + odp.cbSize = sizeof(odp); + odp.position = 910000000; + odp.hInstance = hInst; + odp.pszGroup = BOLTUN_GROUP; + odp.pszTitle = BOLTUN_NAME; + odp.pfnDlgProc = MainDlgProc; + odp.pszTemplate = MAKEINTRESOURCEA(IDD_MAIN); + odp.pszTab = TAB_GENERAL; + Options_AddPage(wParam, &odp); + odp.pfnDlgProc = EngineDlgProc; + odp.pszTemplate = MAKEINTRESOURCEA(IDD_ENGINE); + odp.pszTab = TAB_ENGINE; + Options_AddPage(wParam, &odp); + return 0; +} + +static int ContactClick(WPARAM wParam, LPARAM lParam, BOOL clickNotToChat) +{ + HANDLE hContact = (HANDLE)wParam; + + BOOL boltunautochat = DBGetContactSettingByte(hContact, BOLTUN_KEY, DB_CONTACT_BOLTUN_AUTO_CHAT, FALSE); + BOOL boltunnottochat = DBGetContactSettingByte(hContact, BOLTUN_KEY, DB_CONTACT_BOLTUN_NOT_TO_CHAT, FALSE); + + if (clickNotToChat) + { + boltunnottochat = !boltunnottochat; + if(boltunnottochat) + { + boltunautochat = FALSE; + } + } + else + { + boltunautochat = !boltunautochat; + if(boltunautochat) + { + boltunnottochat = FALSE; + } + else + { + DBWriteContactSettingByte(hContact, BOLTUN_KEY, DB_CONTACT_WARNED, FALSE); + } + } + + DBWriteContactSettingByte(hContact, BOLTUN_KEY, DB_CONTACT_BOLTUN_AUTO_CHAT, (BYTE)boltunautochat); + DBWriteContactSettingByte(hContact, BOLTUN_KEY, DB_CONTACT_BOLTUN_NOT_TO_CHAT, (BYTE)boltunnottochat); + + return 0; +} + +static INT_PTR ContactClickAutoChat(WPARAM wParam, LPARAM lParam) +{ + return ContactClick(wParam, lParam, 0); +} + +static INT_PTR ContactClickNotToChat(WPARAM wParam, LPARAM lParam) +{ + return ContactClick(wParam, lParam, 1); +} + +static INT_PTR ContactClickStartChatting(WPARAM wParam, LPARAM lParam) +{ + HANDLE hContact = (HANDLE)wParam; + StartChatting(hContact); + return 0; +} + +static int MessagePrebuild(WPARAM wParam, LPARAM lParam) +{ + CLISTMENUITEM clmi; + HANDLE hContact = (HANDLE)wParam; + + if (!blInit || (DBGetContactSettingByte(hContact,"CList","NotOnList",0) == 1)) + { + ZeroMemory(&clmi, sizeof(clmi)); + clmi.cbSize = sizeof(clmi); + clmi.flags = CMIM_FLAGS | CMIF_GRAYED; + + CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuItemAutoChat, (LPARAM)&clmi); + CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuItemNotToChat, (LPARAM)&clmi); + } + else + { + BOOL boltunautochat = DBGetContactSettingByte(hContact, BOLTUN_KEY, DB_CONTACT_BOLTUN_AUTO_CHAT, FALSE); + BOOL boltunnottochat = DBGetContactSettingByte(hContact, BOLTUN_KEY, DB_CONTACT_BOLTUN_NOT_TO_CHAT, FALSE); + ZeroMemory(&clmi, sizeof(clmi)); + clmi.cbSize = sizeof(clmi); + clmi.flags = CMIM_FLAGS | CMIM_ICON | (boltunautochat ? CMIF_CHECKED : 0); + clmi.hIcon = LoadIcon( GetModuleHandle(NULL), MAKEINTRESOURCE((boltunautochat ? IDI_TICK : IDI_NOTICK))); + CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuItemAutoChat, (LPARAM)&clmi); + + clmi.flags = CMIM_FLAGS | CMIM_ICON | (boltunnottochat ? CMIF_CHECKED : 0); + clmi.hIcon = LoadIcon( GetModuleHandle(NULL), MAKEINTRESOURCE((boltunnottochat ? IDI_TICK : IDI_NOTICK))); + CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuItemNotToChat, (LPARAM)&clmi); + } + return 0; +} + +extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion) +{ + return &pluginInfo; +} + +extern "C" int __declspec(dllexport) Load(void) +{ + mir_getLP(&pluginInfo); + + path = new TCHAR[MAX_PATH]; + int len = GetModuleFileName(hInst, path, MAX_PATH); + if (len > MAX_PATH) + { + delete[] path; + TCHAR *path = new TCHAR[len]; + int len2 = GetModuleFileName(hInst, path, len); + if (len2 != len) + { + delete[] path; + return false; + } + } + *(_tcsrchr(path, _T('\\'))+1) = _T('\0'); + + /*initialize miranda hooks and services on options dialog*/ + hEventOptInitialise = HookEvent(ME_OPT_INITIALISE, MessageOptInit); + /*initialize miranda hooks and services*/ + hEventDbEventAdded = HookEvent(ME_DB_EVENT_ADDED, MessageEventAdded); + hEventPrebuild = HookEvent(ME_CLIST_PREBUILDCONTACTMENU, MessagePrebuild); + + CreateServiceFunction(SERV_CONTACT_AUTO_CHAT, ContactClickAutoChat); + CreateServiceFunction(SERV_CONTACT_NOT_TO_CHAT, ContactClickNotToChat); + CreateServiceFunction(SERV_CONTACT_START_CHATTING, ContactClickStartChatting); + { + CLISTMENUITEM mi; + + ZeroMemory(&mi,sizeof(mi)); + mi.cbSize = sizeof(mi); + mi.position = -50010002; //TODO: check the warning + mi.flags = 0; + mi.hIcon = NULL; + mi.pszContactOwner = NULL; + mi.pszName = BOLTUN_AUTO_CHAT; + mi.pszService = SERV_CONTACT_AUTO_CHAT; + hMenuItemAutoChat = Menu_AddContactMenuItem(&mi); + + mi.position = -50010001; //TODO: check the warning + mi.pszName = BOLTUN_NOT_TO_CHAT; + mi.pszService = SERV_CONTACT_NOT_TO_CHAT; + hMenuItemNotToChat = Menu_AddContactMenuItem(&mi); + + mi.flags = CMIF_NOTOFFLINE; + mi.position = -50010000; //TODO: check the warning + mi.hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_RECVMSG)); + mi.pszName = BOLTUN_START_CHATTING; + mi.pszService = SERV_CONTACT_START_CHATTING; + hMenuItemStartChatting = Menu_AddContactMenuItem(&mi); + } + int line; + blInit = LoadMind(Config.MindFileName, line); + if (!blInit) + { + TCHAR path[2000]; + wsprintf(path, TranslateTS(FAILED_TO_LOAD_BASE), line, (const TCHAR*)Config.MindFileName); + MessageBox(NULL, path, TranslateTS(BOLTUN_ERROR), MB_ICONERROR|MB_TASKMODAL|MB_OK); + } + /*record for Uninstall plugin*/ + DBWriteContactSettingString(NULL, "Uninstall", BOLTUN_NAME, BOLTUN_KEY); + return 0; +} + +extern "C" int __declspec(dllexport) Unload(void) +{ + if (pTimer) + KillTimer(NULL, pTimer); + if(blInit) + { +#if 0 //No need to save, we don't have studying algorithm + if(Config.MindFileName && !SaveMind(Config.MindFileName)) + { +//This causes errors with development core when calling MessageBox. +//It seems that it's now a Boltun problem. +//So in case of saving error we will remain silent +#if 0 + TCHAR path[MAX_PATH]; + wsprintf(path, TranslateTS(FAILED_TO_SAVE_BASE), (const TCHAR*)Config.MindFileName); + TCHAR* err = TranslateTS(BOLTUN_ERROR); + MessageBox(NULL, path, err, MB_ICONERROR|MB_TASKMODAL|MB_OK);*/ +#endif + } +#endif + delete bot; + } + delete[] path; + return 0; +} diff --git a/plugins/Boltun/src/boltun.h b/plugins/Boltun/src/boltun.h new file mode 100644 index 0000000000..914869387c --- /dev/null +++ b/plugins/Boltun/src/boltun.h @@ -0,0 +1,74 @@ +//*********************************************************** +// Copyright © 2003-2008 Alexander S. Kiselev, Valentin Pavlyuchenko +// +// This file is part of Boltun. +// +// Boltun 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. +// +// Boltun 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 Boltun. If not, see . +// +//*********************************************************** + +#ifndef _BOLTUN_H +#define _BOLTUN_H + +//Should use different keys in UNICODE and ANSI builds, because usage of plugin +//with old (another) configs will cause crashes. + +#define BOLTUN_KEY "Boltun" + + +//Service names +#define SERV_CONTACT_AUTO_CHAT "Boltun/ContactAutoChat" +#define SERV_CONTACT_NOT_TO_CHAT "Boltun/ContactNotToChat" +#define SERV_CONTACT_START_CHATTING "Boltun/ContactStartChatting" + +//Database keys +#define DB_CONTACT_BOLTUN_NOT_TO_CHAT "BoltunNotToChat" +#define DB_CONTACT_BOLTUN_AUTO_CHAT "BoltunAutoChat" +#define DB_CONTACT_WARNED "Warned" + +//Plugin group in settings +#define BOLTUN_GROUP "Message sessions" + +//Filename depends on UNICODE +#define DEFAULT_MIND_FILE _T("boltun.mindw") + +//=============================================== +// These are strings for translation: +//=============================================== + +//Plugin name +#define BOLTUN_NAME "Boltun" + +#define PLUGIN_DESCRIPTION "Boltun, the chat bot in the russian language." + +#define MIND_FILE_DESC _T("Mind Files") +#define ALL_FILES_DESC _T("All Files") + +//UI strings +#define BOLTUN_AUTO_CHAT "Boltun/Auto Chat" +#define BOLTUN_NOT_TO_CHAT "Boltun/Not to Chat" +#define BOLTUN_START_CHATTING "Boltun/Start Chatting" + +#define DEFAULT_WARN_TEXT _T("Hello. I'm Boltun! I'll talk to you, while my owner is away. Please write without mistakes!") + +// Error messages +#define BOLTUN_ERROR _T("Boltun Error") +#define FAILED_TO_LOAD_BASE _T("Failed to load base of remarks. Error at line %d of %s. (Or few lines before).") +#define FAILED_TO_SAVE_BASE _T("Failed to save base of remarks to %s") + +//Settings tab names +#define TAB_GENERAL "General Settings" +#define TAB_ENGINE "Engine Settings" + +#endif /*_BOLTUN_H*/ diff --git a/plugins/Boltun/src/config.cpp b/plugins/Boltun/src/config.cpp new file mode 100644 index 0000000000..4a88bf2df3 --- /dev/null +++ b/plugins/Boltun/src/config.cpp @@ -0,0 +1,159 @@ +//*********************************************************** +// Copyright © 2003-2008 Alexander S. Kiselev, Valentin Pavlyuchenko +// +// This file is part of Boltun. +// +// Boltun 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. +// +// Boltun 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 Boltun. If not, see . +// +//*********************************************************** + +#include "config.h" + +#include +#include +#include + +#include "newpluginapi.h" +#include "m_database.h" +#include "m_langpack.h" +#include "boltun.h" + +//Database keys +#define DB_EVERYBODY "Everybody" +#define DB_NOT_IN_LIST "NotInList" +#define DB_AUTOAWAY "AutoAway" +#define DB_WARN "Warn" +#define DB_MARK_READ "MarkRead" +#define DB_WAIT_TIME "WaitTime" +#define DB_THINK_TIME "ThinkTime" +#define DB_PAUSE_DEPENDS "PauseDepends" +#define DB_PAUSE_RANDOM "PauseRandom" +#define DB_WARN_TEXT "WarnText" +#define DB_MIND_FILE_NAME "MindFileName" +#define DB_ENGINE_SILENT "SilentEngine" +#define DB_ENGINE_LOWERCASE "MakeLowerCase" +#define DB_ENGINE_UNDERSTAND_ALWAYS "UnderstandAlways" + +inline TCHAR* GetString(char* key, const TCHAR* def) +{ + DBVARIANT dbv; + TCHAR* val; + if (!DBGetContactSettingTString(NULL, BOLTUN_KEY, key, &dbv)) + { + size_t len = wcslen(dbv.ptszVal) + 1; + val = new TCHAR[len]; + _tcscpy_s(val, len, dbv.ptszVal); + DBFreeVariant(&dbv); + } + else + { + size_t len = wcslen(def) + 1; + val = new TCHAR[len]; + _tcscpy_s(val, len, def); + } + return val; +} + +inline const TCHAR* SetString(char* key, const TCHAR* value) +{ + size_t len = _tcslen(value) + 1; + TCHAR* val = new TCHAR[len]; + _tcscpy_s(val, len, value); + DBWriteContactSettingTString(NULL, BOLTUN_KEY, key, val); + return val; +} + +#define BUILDETTERS(x, str, def) \ + const bool BoltunConfig::Get##x() { \ + return DBGetContactSettingDword(NULL, BOLTUN_KEY, str, def) != 0; } \ + const bool BoltunConfig::Set##x(const bool value) { \ + DBWriteContactSettingDword(NULL, BOLTUN_KEY, str, value); \ + return value; } + +#define BUILDINTETTERS(x, str, def) \ + const int BoltunConfig::Get##x() { \ + return DBGetContactSettingDword(NULL, BOLTUN_KEY, str, def); } \ + const int BoltunConfig::Set##x(const int value) { \ + DBWriteContactSettingDword(NULL, BOLTUN_KEY, str, value); \ + return value; } + +#define BUILDSTRETTERS(x, str, def) \ + const TCHAR* BoltunConfig::Get##x() { \ + return GetString(str, def); } \ + const TCHAR* BoltunConfig::Set##x(const TCHAR* value) { \ + return SetString(str, value); } + +#define BUILDINIT(x) \ + x(&BoltunConfig::Get##x, &BoltunConfig::Set##x) + +BUILDETTERS(TalkWithNotInList, DB_NOT_IN_LIST, false); +BUILDETTERS(TalkWithEverybody, DB_EVERYBODY, false); +BUILDETTERS(TalkWarnContacts, DB_WARN, false); +BUILDETTERS(TalkEveryoneWhileAway, DB_AUTOAWAY, false); +BUILDETTERS(MarkAsRead, DB_MARK_READ, true); +BUILDINTETTERS(AnswerPauseTime, DB_WAIT_TIME, 2); +BUILDINTETTERS(AnswerThinkTime, DB_THINK_TIME, 4); +BUILDETTERS(PauseDepends, DB_PAUSE_DEPENDS, TRUE); +BUILDETTERS(PauseRandom, DB_PAUSE_RANDOM, TRUE); +BUILDSTRETTERS(WarnText, DB_WARN_TEXT, TranslateTS(DEFAULT_WARN_TEXT)); +BUILDSTRETTERS(MindFileName, DB_MIND_FILE_NAME, DEFAULT_MIND_FILE); +BUILDETTERS(EngineStaySilent, DB_ENGINE_SILENT, FALSE); +BUILDETTERS(EngineMakeLowerCase, DB_ENGINE_LOWERCASE, FALSE); +BUILDETTERS(EngineUnderstandAlways, DB_ENGINE_UNDERSTAND_ALWAYS, FALSE); + +BoltunConfig::BoltunConfig() + :BUILDINIT(TalkWithEverybody), + BUILDINIT(TalkWithNotInList), + BUILDINIT(TalkWarnContacts), + BUILDINIT(TalkEveryoneWhileAway), + BUILDINIT(MarkAsRead), + BUILDINIT(AnswerPauseTime), + BUILDINIT(AnswerThinkTime), + BUILDINIT(PauseDepends), + BUILDINIT(PauseRandom), + BUILDINIT(WarnText), + BUILDINIT(MindFileName), + BUILDINIT(EngineStaySilent), + BUILDINIT(EngineMakeLowerCase), + BUILDINIT(EngineUnderstandAlways) +{ + TalkWithEverybody.SetOwner(this); + TalkWithNotInList.SetOwner(this); + TalkWarnContacts.SetOwner(this); + TalkEveryoneWhileAway.SetOwner(this); + MarkAsRead.SetOwner(this); + AnswerPauseTime.SetOwner(this); + AnswerThinkTime.SetOwner(this); + PauseDepends.SetOwner(this); + PauseRandom.SetOwner(this); + WarnText.SetOwner(this); + MindFileName.SetOwner(this); + EngineStaySilent.SetOwner(this); + EngineMakeLowerCase.SetOwner(this); + EngineUnderstandAlways.SetOwner(this); +} + +BoltunConfig::~BoltunConfig() +{ +} + +class _BoltunConfigInit +{ +public: + BoltunConfig cfg; +}; + +_BoltunConfigInit inst; + +BoltunConfig &Config = inst.cfg; \ No newline at end of file diff --git a/plugins/Boltun/src/config.h b/plugins/Boltun/src/config.h new file mode 100644 index 0000000000..c5bb20e700 --- /dev/null +++ b/plugins/Boltun/src/config.h @@ -0,0 +1,157 @@ +//*********************************************************** +// Copyright © 2003-2008 Alexander S. Kiselev, Valentin Pavlyuchenko +// +// This file is part of Boltun. +// +// Boltun 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. +// +// Boltun 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 Boltun. If not, see . +// +//*********************************************************** + +#ifndef _CONFIG_H +#define _CONFIG_H + +#include + +class BoltunConfig; + +template +class Property +{ +public: + typedef const T (__thiscall BaseClass::*Getter)(); + typedef const T (__thiscall BaseClass::*Setter)(const T); +private: + const Getter getter; + const Setter setter; + BaseClass* owner; + bool cacheValid; + T cached; +public: + Property(Getter g, Setter s) + :getter(g), setter(s), cacheValid(false) + { + } + + void SetOwner(BaseClass* o) + { + owner = o; + } + + inline operator const T() + { + if (cacheValid) + return cached; + cached = (owner->*getter)(); + cacheValid = true; + return cached; + } + + inline const T operator= (const T& value) + { + cacheValid = true; + return (owner->*setter)(cached = value); + } +}; + +template +class PtrProperty +{ +public: + typedef const T* (__thiscall BaseClass::*Getter)(); + typedef const T* (__thiscall BaseClass::*Setter)(const T*); +private: + const Getter getter; + const Setter setter; + BaseClass* owner; + bool cacheValid; + const T* cached; +public: + PtrProperty(Getter g, Setter s) + :getter(g), setter(s), cacheValid(false), cached(NULL) + { + } + + ~PtrProperty() + { + delete cached; + } + + void SetOwner(BaseClass* o) + { + owner = o; + } + + inline operator const T*() + { + if (cacheValid) + return cached; + cached = (owner->*getter)(); + cacheValid = true; + return cached; + } + + inline const T* operator= (const T* value) + { + cacheValid = true; + delete cached; + cached = (owner->*setter)(value); + return cached; + } +}; + +class _BoltunConfigInit; + +#define BUILDDEFETTERS(x, typ) \ + const typ Get##x(); \ + const typ Set##x(const typ value); + +class BoltunConfig +{ + BUILDDEFETTERS(TalkWithEverybody, bool); + BUILDDEFETTERS(TalkWithNotInList, bool); + BUILDDEFETTERS(TalkWarnContacts, bool); + BUILDDEFETTERS(TalkEveryoneWhileAway, bool); + BUILDDEFETTERS(MarkAsRead, bool); + BUILDDEFETTERS(AnswerPauseTime, int); + BUILDDEFETTERS(AnswerThinkTime, int); + BUILDDEFETTERS(PauseDepends, bool); + BUILDDEFETTERS(PauseRandom, bool); + BUILDDEFETTERS(WarnText, TCHAR*); + BUILDDEFETTERS(MindFileName, TCHAR*); + BUILDDEFETTERS(EngineStaySilent, bool); + BUILDDEFETTERS(EngineMakeLowerCase, bool); + BUILDDEFETTERS(EngineUnderstandAlways, bool); + BoltunConfig(); + ~BoltunConfig(); + friend class _BoltunConfigInit; +public: + Property TalkWithEverybody; + Property TalkWithNotInList; + Property TalkWarnContacts; + Property TalkEveryoneWhileAway; + Property MarkAsRead; + Property AnswerPauseTime; + Property AnswerThinkTime; + Property PauseDepends; + Property PauseRandom; + PtrProperty WarnText; + PtrProperty MindFileName; + Property EngineStaySilent; + Property EngineMakeLowerCase; + Property EngineUnderstandAlways; +}; + +extern BoltunConfig &Config; + +#endif /* _CONFIG_H */ \ No newline at end of file diff --git a/plugins/Boltun/src/resource.h b/plugins/Boltun/src/resource.h new file mode 100644 index 0000000000..b4fa069c0e --- /dev/null +++ b/plugins/Boltun/src/resource.h @@ -0,0 +1,46 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Boltun.rc +// +#define IDM_HIDE 0x0010 +#define IDD_MAIN 101 +#define IDI_MAINBOLTUN 102 +#define IDD_ENGINE 103 +#define IDR_SMILES 105 +#define IDI_TICK 106 +#define IDI_NOTICK 107 +#define IDI_RECVMSG 108 +#define IDC_EVERYBODY 1000 +#define IDC_NOTINLIST 1001 +#define IDC_AUTOAWAY 1002 +#define IDC_WARN 1003 +#define IDC_MARKREAD 1004 +#define IDC_LWAITTIME 1005 +#define IDC_WAITTIME 1006 +#define IDC_LSEC 1007 +#define IDC_LWARN 1008 +#define IDC_WARNTXT 1009 +#define IDC_PLUGINRM 1010 +#define IDC_TXTREPLICPATH 1011 +#define IDC_MINDFILE 1012 +#define IDC_BTNPATH 1013 +#define IDC_BTNSAVE 1014 +#define IDC_BTNRELOAD 1015 +#define IDC_PAUSEDEPENDS 1016 +#define IDC_PAUSERANDOM 1017 +#define IDC_THINKTIME 1018 +#define IDC_LSEC2 1019 +#define IDC_ENGINE_SILENT 1020 +#define IDC_ENGINE_LOWERCASE 1021 +#define IDC_ENGINE_UNDERSTAND_ALWAYS 1022 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 106 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1023 +#define _APS_NEXT_SYMED_VALUE 102 +#endif +#endif -- cgit v1.2.3