diff options
Diffstat (limited to 'no_history/dllmain.cpp')
| -rw-r--r-- | no_history/dllmain.cpp | 362 |
1 files changed, 362 insertions, 0 deletions
diff --git a/no_history/dllmain.cpp b/no_history/dllmain.cpp new file mode 100644 index 0000000..6a33ca2 --- /dev/null +++ b/no_history/dllmain.cpp @@ -0,0 +1,362 @@ +/* Replace "dll.h" with the name of your header */
+#include "common.h"
+#include "private.h"
+#include "resource.h"
+#include "icons.h"
+#include "options.h"
+
+#include <time.h>
+
+///////////////////////////////////////////////
+// Common Plugin Stuff
+///////////////////////////////////////////////
+HINSTANCE hInst;
+PLUGINLINK *pluginLink;
+
+HANDLE hEventDbEventAdded, hEventMenuPrebuild, hMenuToggle, hMenuClear, hServiceToggle, hServiceClear, hEventWindow, hEventIconPressed;
+
+CRITICAL_SECTION list_cs;
+
+UINT timer_id;
+
+#define MS_NOHISTORY_TOGGLE MODULE "/ToggleOnOff"
+#define MS_NOHISTORY_CLEAR MODULE "/Clear"
+
+#define DBSETTING_REMOVE "RemoveHistory"
+
+// a list of db events - we'll check them for the 'read' flag periodically and delete them whwen marked as read
+struct EventListNode {
+ HANDLE hContact, hDBEvent;
+ EventListNode *next;
+};
+
+EventListNode *event_list = 0;
+
+// plugin stuff
+PLUGININFO pluginInfo={
+ sizeof(PLUGININFO),
+ MODULE,
+ PLUGIN_MAKE_VERSION(VER_MAJOR, VER_MINOR, VER_RELEASE, VER_BUILD),
+ DESC_STRING,
+ "Scott Ellis",
+ "mail@scottellis.com.au",
+ "© 2005 Scott Ellis",
+ "http://www.scottellis.com.au/",
+ 0, //not transient
+ 0 //doesn't replace anything built-in
+};
+
+extern "C" BOOL APIENTRY DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved) {
+ hInst=hinstDLL;
+ return TRUE;
+}
+
+extern "C" __declspec (dllexport) PLUGININFO* MirandaPluginInfo(DWORD mirandaVersion) {
+ return &pluginInfo;
+}
+
+void RemoveReadEvents() {
+ DBEVENTINFO info = {0};
+ info.cbSize = sizeof(info);
+ bool remove;
+
+ DWORD current_time = (DWORD)time(0);
+ EnterCriticalSection(&list_cs);
+ EventListNode *node = event_list, *prev = 0;
+ while(node) {
+ remove = false;
+ if(!CallService(MS_DB_EVENT_GET, (WPARAM)node->hDBEvent, (LPARAM)&info)) {
+ if((info.flags & DBEF_READ) || (info.flags & DBEF_SENT)) // note: already checked event type when added to list
+ if(current_time - info.timestamp >= event_timeout) remove = true;
+ } else {
+ // could not get event info - maybe someone else deleted it - so remove list node
+ remove = true;
+ }
+
+ if(remove) {
+ if(DBGetContactSettingByte(node->hContact, MODULE, DBSETTING_REMOVE, 0)) // is history disabled for this contact?
+ CallService(MS_DB_EVENT_DELETE, (WPARAM)node->hContact, (LPARAM)node->hDBEvent);
+
+ // remove list node anyway
+ if(event_list == node) event_list = node->next;
+ if(prev) prev->next = node->next;
+
+ free(node);
+
+ if(prev) node = prev->next;
+ else node = event_list;
+ } else {
+ prev = node;
+ node = node->next;
+ }
+ }
+
+ LeaveCriticalSection(&list_cs);
+}
+
+void RemoveAllEvents(HANDLE hContact) {
+ HANDLE hDBEvent = (HANDLE)CallService(MS_DB_EVENT_FINDFIRST, (WPARAM)hContact, 0), hDBEventNext;
+ while(hDBEvent) {
+ hDBEventNext = (HANDLE)CallService(MS_DB_EVENT_FINDNEXT, (WPARAM)hDBEvent, 0);
+ CallService(MS_DB_EVENT_DELETE, (WPARAM)hContact, (LPARAM)hDBEvent);
+ hDBEvent = hDBEventNext;
+ }
+
+}
+
+void CALLBACK TimerProc(HWND hWnd, UINT uMsg, UINT idEvent, DWORD dwTime) {
+ RemoveReadEvents();
+}
+
+
+int OnDatabaseEventAdd(WPARAM wParam, LPARAM lParam) {
+ HANDLE hContact = (HANDLE)wParam, hDBEvent = (HANDLE)lParam;
+
+ // history not disabled for this contact
+ if(DBGetContactSettingByte(hContact, MODULE, DBSETTING_REMOVE, 0) == 0)
+ return 0;
+
+ DBEVENTINFO info = {0};
+ info.cbSize = sizeof(info);
+ if(!CallService(MS_DB_EVENT_GET, (WPARAM)hDBEvent, (LPARAM)&info)) {
+ if(info.eventType == EVENTTYPE_MESSAGE) {
+ EventListNode *node = (EventListNode *)malloc(sizeof(EventListNode));
+ node->hContact = hContact;
+ node->hDBEvent = hDBEvent;
+
+ EnterCriticalSection(&list_cs);
+ node->next = event_list;
+ event_list = node;
+ LeaveCriticalSection(&list_cs);
+
+ // make sure it waits 1 sec before deleting this event
+ timer_id = SetTimer(0, 0, 1000, TimerProc);
+ }
+ }
+
+ return 0;
+}
+
+int ServiceToggle(WPARAM wParam, LPARAM lParam) {
+ HANDLE hContact = (HANDLE)wParam;
+
+ bool remove = (DBGetContactSettingByte(hContact, MODULE, DBSETTING_REMOVE, 0) != 0);
+ remove = !remove;
+ DBWriteContactSettingByte(hContact, MODULE, DBSETTING_REMOVE, (remove ? 1 : 0));
+
+ StatusIconData sid = {0};
+ sid.cbSize = sizeof(sid);
+ sid.szModule = MODULE;
+ sid.dwId = 0;
+ sid.flags = (remove ? MBF_DISABLED : 0);
+ CallService(MS_MSG_MODIFYICON, (WPARAM)hContact, (LPARAM)&sid);
+
+ return 0;
+}
+
+int ServiceClear(WPARAM wParam, LPARAM lParam) {
+ HANDLE hContact = (HANDLE)wParam;
+
+ if(MessageBox(0, TranslateT("This operation will PERMANENTLY REMOVE all history for this contact.\nAre you sure you want to do this?"), TranslateT("Clear History"), MB_YESNO | MB_ICONWARNING) == IDYES) {
+ RemoveAllEvents(hContact);
+ }
+
+ return 0;
+}
+
+int PrebuildContactMenu(WPARAM wParam, LPARAM lParam) {
+ HANDLE hContact = (HANDLE)wParam;
+
+ bool remove = (DBGetContactSettingByte(hContact, MODULE, DBSETTING_REMOVE, 0) != 0);
+ char *proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+ bool chat_room = (proto && DBGetContactSettingByte(hContact, proto, "ChatRoom", 0) != 0);
+
+ CLISTMENUITEM mi = {0};
+ mi.cbSize = sizeof(mi);
+
+ mi.flags = CMIM_FLAGS;
+ if(chat_room) mi.flags |= CMIF_HIDDEN;
+ else {
+ mi.flags |= (CMIM_NAME | CMIM_ICON);
+ mi.pszName = (remove ? Translate("Enable History") : Translate("Disable History"));
+ mi.hIcon = (remove ? hIconKeep : hIconRemove);
+ }
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuToggle, (LPARAM)&mi);
+
+ mi.flags = CMIM_FLAGS;
+ if(chat_room) mi.flags |= CMIF_HIDDEN;
+ else {
+ int event_count = (int)CallService(MS_DB_EVENT_GETCOUNT, (WPARAM)hContact, 0);
+ if(event_count <= 0) mi.flags |= CMIF_HIDDEN;
+ }
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuClear, (LPARAM)&mi);
+
+ return 0;
+}
+
+int WindowEvent(WPARAM wParam, LPARAM lParam) {
+ MessageWindowEventData *mwd = (MessageWindowEventData *)lParam;
+ if(mwd->uType != MSG_WINDOW_EVT_OPEN) return 0;
+ if(!ServiceExists(MS_MSG_MODIFYICON)) return 0;
+
+ HANDLE hContact = mwd->hContact;
+
+ bool remove = (DBGetContactSettingByte(hContact, MODULE, DBSETTING_REMOVE, 0) != 0);
+ char *proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+ bool chat_room = (proto && DBGetContactSettingByte(hContact, proto, "ChatRoom", 0) != 0);
+
+ StatusIconData sid = {0};
+ sid.cbSize = sizeof(sid);
+ sid.szModule = MODULE;
+ sid.dwId = 0;
+ sid.flags = (chat_room ? MBF_HIDDEN : (remove ? MBF_DISABLED : 0));
+ CallService(MS_MSG_MODIFYICON, (WPARAM)hContact, (LPARAM)&sid);
+
+ return 0;
+}
+
+int IconPressed(WPARAM wParam, LPARAM lParam) {
+ HANDLE hContact = (HANDLE)wParam;
+ StatusIconClickData *sicd = (StatusIconClickData *)lParam;
+ if(sicd->cbSize < (int)sizeof(StatusIconClickData))
+ return 0;
+
+ if(sicd->flags & MBCF_RIGHTBUTTON) return 0; // ignore right-clicks
+ if(strcmp(sicd->szModule, MODULE) != 0) return 0; // not our event
+
+ char *proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
+ bool chat_room = (proto && DBGetContactSettingByte(hContact, proto, "ChatRoom", 0) != 0);
+
+ if(!chat_room) ServiceToggle((WPARAM)hContact, 0);
+ return 0;
+}
+
+int ModulesLoaded(WPARAM wParam, LPARAM lParam) {
+ if(ServiceExists(MS_UPDATE_REGISTER)) {
+ // register with updater
+ Update update = {0};
+ char szVersion[16];
+
+ update.cbSize = sizeof(Update);
+
+ update.szComponentName = pluginInfo.shortName;
+ update.pbVersion = (BYTE *)CreateVersionString(pluginInfo.version, szVersion);
+ update.cpbVersion = strlen((char *)update.pbVersion);
+
+ update.szUpdateURL = UPDATER_AUTOREGISTER;
+
+ // these are the three lines that matter - the archive, the page containing the version string, and the text (or data)
+ // before the version that we use to locate it on the page
+ // (note that if the update URL and the version URL point to standard file listing entries, the backend xml
+ // data will be used to check for updates rather than the actual web page - this is not true for beta urls)
+ update.szBetaUpdateURL = "http://www.scottellis.com.au/miranda_plugins/no_history.zip";
+ update.szBetaVersionURL = "http://www.scottellis.com.au/miranda_plugins/ver_no_history.html";
+ update.pbBetaVersionPrefix = (BYTE *)"NoHistory plugin, version ";
+
+ update.cpbBetaVersionPrefix = strlen((char *)update.pbBetaVersionPrefix);
+
+ CallService(MS_UPDATE_REGISTER, 0, (WPARAM)&update);
+ }
+
+ hServiceToggle = (HANDLE)CreateServiceFunction(MS_NOHISTORY_TOGGLE, ServiceToggle);
+ hServiceClear = (HANDLE)CreateServiceFunction(MS_NOHISTORY_CLEAR, ServiceClear);
+
+ InitIcons();
+
+ // create contact menu item
+ CLISTMENUITEM mi = {0};
+ mi.cbSize = sizeof(mi);
+ mi.flags = CMIM_ALL;
+
+ mi.position = -300010;
+ mi.pszName = Translate("Disable History");
+ mi.pszService = MS_NOHISTORY_TOGGLE;
+ mi.hIcon = hIconRemove;
+ hMenuToggle = (HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM)&mi);
+
+ mi.position = -300005;
+ mi.pszName = Translate("Clear History");
+ mi.pszService = MS_NOHISTORY_CLEAR;
+ mi.hIcon = hIconClear;
+ hMenuClear = (HANDLE)CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM)&mi);
+
+ hEventMenuPrebuild = HookEvent(ME_CLIST_PREBUILDCONTACTMENU, PrebuildContactMenu);
+
+ // hooked so we can track events added to the database
+ hEventDbEventAdded = HookEvent(ME_DB_EVENT_ADDED, OnDatabaseEventAdd);
+
+ // add icon to srmm status icons
+ if(ServiceExists(MS_MSG_ADDICON)) {
+ StatusIconData sid = {0};
+ sid.cbSize = sizeof(sid);
+ sid.szModule = MODULE;
+ sid.dwId = 0;
+ sid.hIcon = hIconKeep;
+ sid.hIconDisabled = hIconRemove;
+ sid.flags = 0;
+ sid.szTooltip = Translate("History Enabled");
+ CallService(MS_MSG_ADDICON, 0, (LPARAM)&sid);
+
+ // hook the window events so that we can can change the status of the icon
+ hEventWindow = HookEvent(ME_MSG_WINDOWEVENT, WindowEvent);
+ hEventIconPressed = HookEvent(ME_MSG_ICONPRESSED, IconPressed);
+ }
+
+ timer_id = SetTimer(0, 0, 1000, TimerProc);
+
+ return 0;
+}
+
+HANDLE hModulesLoaded;
+extern "C" __declspec (dllexport) int Load(PLUGINLINK *link) {
+ pluginLink=link;
+
+ InitializeCriticalSection(&list_cs);
+
+ // fix for wrong module name - ugh
+ DBVARIANT dbv;
+ HANDLE hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDFIRST, 0, 0 );
+ while ( hContact != NULL )
+ {
+ if(!DBGetContactSetting(hContact, "NoHostory", DBSETTING_REMOVE, &dbv)) {
+ if(dbv.type == DBVT_BYTE && dbv.bVal != 0)
+ DBWriteContactSettingByte(hContact, MODULE, DBSETTING_REMOVE, 1);
+ DBFreeVariant(&dbv);
+ DBDeleteContactSetting(hContact, "NoHostory", DBSETTING_REMOVE);
+ }
+ hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDNEXT,( WPARAM )hContact, 0 );
+ }
+
+ INITCOMMONCONTROLSEX icex;
+
+ // Ensure that the common control DLL is loaded (for listview)
+ icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
+ icex.dwICC = ICC_LISTVIEW_CLASSES;
+ InitCommonControlsEx(&icex);
+
+ InitOptions();
+ // hook modules loaded
+ hModulesLoaded = HookEvent(ME_SYSTEM_MODULESLOADED, ModulesLoaded);
+ return 0;
+}
+
+extern "C" __declspec (dllexport) int Unload(void) {
+ UnhookEvent(hEventWindow);
+ UnhookEvent(hEventIconPressed);
+
+ UnhookEvent(hModulesLoaded);
+ DeinitOptions();
+
+ KillTimer(0, timer_id);
+ UnhookEvent(hEventDbEventAdded);
+ UnhookEvent(hEventMenuPrebuild);
+ DestroyServiceFunction(hServiceToggle);
+ DestroyServiceFunction(hServiceClear);
+
+ event_timeout = 0;
+ RemoveReadEvents();
+ DeleteCriticalSection(&list_cs);
+
+ DeinitIcons();
+ return 0;
+}
|
