From 3aeb41e399a944450223bbbc160b7d984985d9d8 Mon Sep 17 00:00:00 2001 From: sje Date: Wed, 1 Nov 2006 14:38:13 +0000 Subject: git-svn-id: https://server.scottellis.com.au/svn/mim_plugs@9 4f64403b-2f21-0410-a795-97e2b3489a10 --- no_history/IcoLib.h | 37 ++++ no_history/NoHistory.mdsp | 102 ++++++++++ no_history/NoHistory.rc | 122 ++++++++++++ no_history/NoHistory.sln | 20 ++ no_history/NoHistory.vcproj | 327 ++++++++++++++++++++++++++++++ no_history/common.h | 33 ++++ no_history/dllmain.cpp | 362 ++++++++++++++++++++++++++++++++++ no_history/docs/licence_NoHistory.txt | 6 + no_history/history_clear.ico | Bin 0 -> 2550 bytes no_history/history_disabled.ico | Bin 0 -> 2550 bytes no_history/history_enabled.ico | Bin 0 -> 2550 bytes no_history/icons.cpp | 55 ++++++ no_history/icons.h | 9 + no_history/options.cpp | 270 +++++++++++++++++++++++++ no_history/options.h | 9 + no_history/private.h | 24 +++ no_history/private.rc | 35 ++++ no_history/resource.h | 23 +++ no_history/resource.rc | 2 + 19 files changed, 1436 insertions(+) create mode 100644 no_history/IcoLib.h create mode 100644 no_history/NoHistory.mdsp create mode 100644 no_history/NoHistory.rc create mode 100644 no_history/NoHistory.sln create mode 100644 no_history/NoHistory.vcproj create mode 100644 no_history/common.h create mode 100644 no_history/dllmain.cpp create mode 100644 no_history/docs/licence_NoHistory.txt create mode 100644 no_history/history_clear.ico create mode 100644 no_history/history_disabled.ico create mode 100644 no_history/history_enabled.ico create mode 100644 no_history/icons.cpp create mode 100644 no_history/icons.h create mode 100644 no_history/options.cpp create mode 100644 no_history/options.h create mode 100644 no_history/private.h create mode 100644 no_history/private.rc create mode 100644 no_history/resource.h create mode 100644 no_history/resource.rc diff --git a/no_history/IcoLib.h b/no_history/IcoLib.h new file mode 100644 index 0000000..1817df6 --- /dev/null +++ b/no_history/IcoLib.h @@ -0,0 +1,37 @@ +typedef struct { + int cbSize; + char *pszSection; //section name used to group icons + char *pszDescription; //description for options dialog + char *pszName; //name to refer to icon when playing and in db + //this name is miranda-wide. so use prefixes of your plugin + //e.g: "isee_connect", "clist_delete", etc + char *pszDefaultFile; //default icon file to use + int iDefaultIndex; +} SKINICONDESC; + +typedef struct { + int cbSize; + char *pszSection; + char *pszDescription; + char *pszName; + char *pszDefaultFile; + int iDefaultIndex; + HICON hDefaultIcon; +} SKINICONDESC2; + +// +// Add a icon into options UI +// +// wParam = (WPARAM)0 +// lParam = (LPARAM)(SKINICONDESC*)sid; +// +#define MS_SKIN2_ADDICON "Skin2/Icons/AddIcon" +// +// Retrieve HICON with name specified in lParam +// Returned HICON SHOULDN'T be destroyed, it managed by IcoLib +// +#define MS_SKIN2_GETICON "Skin2/Icons/GetIcon" +// +// Icons change notification +// +#define ME_SKIN2_ICONSCHANGED "Skin2/IconsChanged" diff --git a/no_history/NoHistory.mdsp b/no_history/NoHistory.mdsp new file mode 100644 index 0000000..a81f71e --- /dev/null +++ b/no_history/NoHistory.mdsp @@ -0,0 +1,102 @@ +[Project] +name=NoHistory +type=2 +defaultConfig=0 + + +[Debug] +// compiler +workingDirectory= +arguments= +intermediateFilesDirectory=Debug +outputFilesDirectory=Debug +compilerPreprocessor= +extraCompilerOptions= +compilerIncludeDirectory=..\..\include +noWarning=0 +defaultWarning=0 +allWarning=1 +extraWarning=0 +isoWarning=0 +warningsAsErrors=0 +debugType=1 +debugLevel=2 +exceptionEnabled=1 +runtimeTypeEnabled=1 +optimizeLevel=0 + +// linker +libraryPath= +outputFilename=Debug\NoHistory.dll +libraries=comctl32 +extraLinkerOptions= +ignoreStartupFile=0 +ignoreDefaultLibs=0 +stripExecutableFile=0 + +// archive +extraArchiveOptions= + +//resource +resourcePreprocessor= +resourceIncludeDirectory= +extraResourceOptions= + +[Release] +// compiler +workingDirectory= +arguments= +intermediateFilesDirectory=Release +outputFilesDirectory=Release +compilerPreprocessor= +extraCompilerOptions= +compilerIncludeDirectory=..\..\include +noWarning=0 +defaultWarning=0 +allWarning=1 +extraWarning=0 +isoWarning=0 +warningAsErrors=0 +debugType=0 +debugLevel=1 +exceptionEnabled=1 +runtimeTypeEnabled=1 +optimizeLevel=2 + +// linker +libraryPath= +outputFilename=Release\NoHistory.dll +libraries=comctl32 +extraLinkerOptions= +ignoreStartupFile=0 +ignoreDefaultLibs=0 +stripExecutableFile=1 + +// archive +extraArchiveOptions= + +//resource +resourcePreprocessor= +resourceIncludeDirectory= +extraResourceOptions= + +[Source] +1=dllmain.cpp +2=icons.cpp +3=options.cpp +[Header] +1=common.h +2=private.h +3=resource.h +4=icons.h +5=IcoLib.h +6=options.h +[Resource] +1=resource.rc +[Other] +[History] +options.cpp,8160 +common.h,512 +..\..\protocols\sametime_meanwhile\sametime\sametime.cpp,21244 +private.h,280 +dllmain.cpp,6790 diff --git a/no_history/NoHistory.rc b/no_history/NoHistory.rc new file mode 100644 index 0000000..2753283 --- /dev/null +++ b/no_history/NoHistory.rc @@ -0,0 +1,122 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Neutral (Default) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEUD) +#ifdef _WIN32 +LANGUAGE LANG_NEUTRAL, SUBLANG_DEFAULT +#pragma code_page(1252) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_HKEEP ICON "history_enabled.ico" +IDI_HREMOVE ICON "history_disabled.ico" +IDI_HCLEAR ICON "history_clear.ico" +#endif // Neutral (Default) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// English (Australia) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENA) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_AUS +#pragma code_page(1252) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" +END + +2 TEXTINCLUDE +BEGIN + "#include ""afxres.h""\r\n" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_OPT DIALOGEX 0, 0, 312, 235 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_VISIBLE | WS_SYSMENU +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + CONTROL "Custom1",IDC_LIST,"CListControl",WS_TABSTOP | 0x1d0,7,7,298,177,WS_EX_CLIENTEDGE + ICON IDI_HKEEP,IDC_PIC_KEEP,8,203,12,12 + LTEXT "Keep history for this contact",IDC_STATIC,26,205,279,8,SS_NOPREFIX | SS_CENTERIMAGE + ICON IDI_HREMOVE,IDC_PIC_REMOVE,8,218,12,12 + LTEXT "Disable history for this contact",IDC_STATIC,26,220,279,8,SS_NOPREFIX | SS_CENTERIMAGE +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO +BEGIN + IDD_OPT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 305 + VERTGUIDE, 42 + VERTGUIDE, 49 + TOPMARGIN, 7 + BOTTOMMARGIN, 228 + END +END +#endif // APSTUDIO_INVOKED + +#endif // English (Australia) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/no_history/NoHistory.sln b/no_history/NoHistory.sln new file mode 100644 index 0000000..26bbdb6 --- /dev/null +++ b/no_history/NoHistory.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NoHistory", "NoHistory.vcproj", "{ABF05E2C-C335-4BD1-8C3E-4C63285362CF}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {ABF05E2C-C335-4BD1-8C3E-4C63285362CF}.Debug|Win32.ActiveCfg = Debug|Win32 + {ABF05E2C-C335-4BD1-8C3E-4C63285362CF}.Debug|Win32.Build.0 = Debug|Win32 + {ABF05E2C-C335-4BD1-8C3E-4C63285362CF}.Release|Win32.ActiveCfg = Release|Win32 + {ABF05E2C-C335-4BD1-8C3E-4C63285362CF}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/no_history/NoHistory.vcproj b/no_history/NoHistory.vcproj new file mode 100644 index 0000000..76381eb --- /dev/null +++ b/no_history/NoHistory.vcproj @@ -0,0 +1,327 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/no_history/common.h b/no_history/common.h new file mode 100644 index 0000000..0e8ac88 --- /dev/null +++ b/no_history/common.h @@ -0,0 +1,33 @@ +#ifndef _COMMON_INC +#define _COMMON_INC + +#define _WIN32_WINNT 0x0501 +#define _WIN32_IE 0x0500 + +#include +#include +#include "win2k.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include "IcoLib.h" + +#define MODULE "NoHistory" +#define DBSETTING_REMOVE "RemoveHistory" + +extern HINSTANCE hInst; + +#endif 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 + +/////////////////////////////////////////////// +// 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; +} diff --git a/no_history/docs/licence_NoHistory.txt b/no_history/docs/licence_NoHistory.txt new file mode 100644 index 0000000..a391390 --- /dev/null +++ b/no_history/docs/licence_NoHistory.txt @@ -0,0 +1,6 @@ +The NoHistory plugin for Miranda-IM is Copyright (c) 2006 Scott Ellis (mail@scottellis.com.au) + +http://www.scottellis.com.au + +It is released under the General Public Licence, available here: +http://www.gnu.org/copyleft/gpl.html \ No newline at end of file diff --git a/no_history/history_clear.ico b/no_history/history_clear.ico new file mode 100644 index 0000000..e80e834 Binary files /dev/null and b/no_history/history_clear.ico differ diff --git a/no_history/history_disabled.ico b/no_history/history_disabled.ico new file mode 100644 index 0000000..53565f9 Binary files /dev/null and b/no_history/history_disabled.ico differ diff --git a/no_history/history_enabled.ico b/no_history/history_enabled.ico new file mode 100644 index 0000000..3e30661 Binary files /dev/null and b/no_history/history_enabled.ico differ diff --git a/no_history/icons.cpp b/no_history/icons.cpp new file mode 100644 index 0000000..747b164 --- /dev/null +++ b/no_history/icons.cpp @@ -0,0 +1,55 @@ +#include "common.h" +#include "icons.h" +#include "resource.h" + +HICON hIconRemove, hIconKeep, hIconClear; +HANDLE hIcoLibIconsChanged = 0; + +int ReloadIcons(WPARAM wParam, LPARAM lParam) { + hIconRemove = (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)MODULE "_remove"); + hIconKeep = (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)MODULE "_keep"); + hIconClear = (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)MODULE "_clear"); + + return 0; +} + +void InitIcons() { + if(ServiceExists(MS_SKIN2_ADDICON)) { + SKINICONDESC2 sid = {0}; + sid.cbSize = sizeof(SKINICONDESC2); + + sid.pszSection = MODULE; + +#define AddIcon(x,y,z) \ + sid.pszDescription = Translate(x); \ + sid.pszName = y; \ + sid.pszDefaultFile = MODULE ".dll"; \ + sid.hDefaultIcon = (HICON)LoadImage(hInst, MAKEINTRESOURCE(z), IMAGE_ICON, 0, 0, 0); \ + CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid); \ + sid.iDefaultIndex++; + + AddIcon("Disable", MODULE "_remove", IDI_HREMOVE); + AddIcon("Enable", MODULE "_keep", IDI_HKEEP); + AddIcon("Clear", MODULE "_clear", IDI_HCLEAR); + +#undef AddIcon + + ReloadIcons(0, 0); + + hIcoLibIconsChanged = HookEvent(ME_SKIN2_ICONSCHANGED, ReloadIcons); + } else { + hIconRemove = (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_HREMOVE), IMAGE_ICON, 0, 0, 0);//LR_LOADTRANSPARENT | LR_LOADMAP3DCOLORS ); + hIconKeep = (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_HKEEP), IMAGE_ICON, 0, 0, 0);//LR_LOADTRANSPARENT | LR_LOADMAP3DCOLORS ); + hIconClear = (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_HCLEAR), IMAGE_ICON, 0, 0, 0);//LR_LOADTRANSPARENT | LR_LOADMAP3DCOLORS ); + } + +} + +void DeinitIcons() { + if(hIcoLibIconsChanged) UnhookEvent(hIcoLibIconsChanged); + else { + DestroyIcon(hIconRemove); + DestroyIcon(hIconKeep); + DestroyIcon(hIconClear); + } +} diff --git a/no_history/icons.h b/no_history/icons.h new file mode 100644 index 0000000..88fae4b --- /dev/null +++ b/no_history/icons.h @@ -0,0 +1,9 @@ +#ifndef _ICONS_INC +#define _ICONS_INC + +extern HICON hIconRemove, hIconKeep, hIconClear; + +void InitIcons(); +void DeinitIcons(); + +#endif diff --git a/no_history/options.cpp b/no_history/options.cpp new file mode 100644 index 0000000..6f2733f --- /dev/null +++ b/no_history/options.cpp @@ -0,0 +1,270 @@ +#include "common.h" +#include "options.h" +#include "resource.h" +#include "icons.h" + +DWORD event_timeout; + +static void SetListGroupIcons(HWND hwndList,HANDLE hFirstItem,HANDLE hParentItem,int *groupChildCount) +{ + int typeOfFirst; + int iconOn = 1; + int childCount = 0; + int iImage; + HANDLE hItem,hChildItem; + + typeOfFirst=SendMessage(hwndList,CLM_GETITEMTYPE,(WPARAM)hFirstItem,0); + //check groups + if(typeOfFirst==CLCIT_GROUP) hItem=hFirstItem; + else hItem=(HANDLE)SendMessage(hwndList,CLM_GETNEXTITEM,CLGN_NEXTGROUP,(LPARAM)hFirstItem); + while(hItem) { + hChildItem=(HANDLE)SendMessage(hwndList,CLM_GETNEXTITEM,CLGN_CHILD,(LPARAM)hItem); + if(hChildItem) SetListGroupIcons(hwndList,hChildItem,hItem,&childCount); + if(iconOn && SendMessage(hwndList,CLM_GETEXTRAIMAGE,(WPARAM)hItem,0)==0) iconOn=0; + hItem=(HANDLE)SendMessage(hwndList,CLM_GETNEXTITEM,CLGN_NEXTGROUP,(LPARAM)hItem); + } + //check contacts + if(typeOfFirst==CLCIT_CONTACT) hItem=hFirstItem; + else hItem=(HANDLE)SendMessage(hwndList,CLM_GETNEXTITEM,CLGN_NEXTCONTACT,(LPARAM)hFirstItem); + while(hItem) { + iImage=SendMessage(hwndList,CLM_GETEXTRAIMAGE,(WPARAM)hItem,0); + if(iconOn && iImage==0) iconOn=0; + if(iImage!=0xFF) childCount++; + hItem=(HANDLE)SendMessage(hwndList,CLM_GETNEXTITEM,CLGN_NEXTCONTACT,(LPARAM)hItem); + } + //set icons + SendMessage(hwndList,CLM_SETEXTRAIMAGE,(WPARAM)hParentItem,MAKELPARAM(0,childCount?(iconOn?1:0):0xFF)); + if(groupChildCount) *groupChildCount+=childCount; +} + +static void SetAllChildIcons(HWND hwndList,HANDLE hFirstItem,int iColumn,int iImage) +{ + int typeOfFirst,iOldIcon; + HANDLE hItem,hChildItem; + + typeOfFirst=SendMessage(hwndList,CLM_GETITEMTYPE,(WPARAM)hFirstItem,0); + //check groups + if(typeOfFirst==CLCIT_GROUP) hItem=hFirstItem; + else hItem=(HANDLE)SendMessage(hwndList,CLM_GETNEXTITEM,CLGN_NEXTGROUP,(LPARAM)hFirstItem); + while(hItem) { + hChildItem=(HANDLE)SendMessage(hwndList,CLM_GETNEXTITEM,CLGN_CHILD,(LPARAM)hItem); + if(hChildItem) SetAllChildIcons(hwndList,hChildItem,iColumn,iImage); + hItem=(HANDLE)SendMessage(hwndList,CLM_GETNEXTITEM,CLGN_NEXTGROUP,(LPARAM)hItem); + } + //check contacts + if(typeOfFirst==CLCIT_CONTACT) hItem=hFirstItem; + else hItem=(HANDLE)SendMessage(hwndList,CLM_GETNEXTITEM,CLGN_NEXTCONTACT,(LPARAM)hFirstItem); + while(hItem) { + iOldIcon=SendMessage(hwndList,CLM_GETEXTRAIMAGE,(WPARAM)hItem,iColumn); + if(iOldIcon!=0xFF && iOldIcon!=iImage) SendMessage(hwndList,CLM_SETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(iColumn,iImage)); + hItem=(HANDLE)SendMessage(hwndList,CLM_GETNEXTITEM,CLGN_NEXTCONTACT,(LPARAM)hItem); + } +} + + +static void ResetListOptions(HWND hwndList) +{ + int i; + + SendMessage(hwndList,CLM_SETBKBITMAP,0,(LPARAM)(HBITMAP)NULL); + SendMessage(hwndList,CLM_SETBKCOLOR,GetSysColor(COLOR_WINDOW),0); + SendMessage(hwndList,CLM_SETGREYOUTFLAGS,0,0); + SendMessage(hwndList,CLM_SETLEFTMARGIN,2,0); + SendMessage(hwndList,CLM_SETINDENT,10,0); + for(i=0;i<=FONTID_MAX;i++) + SendMessage(hwndList,CLM_SETTEXTCOLOR,i,GetSysColor(COLOR_WINDOWTEXT)); + SetWindowLong(hwndList,GWL_STYLE,GetWindowLong(hwndList,GWL_STYLE)|CLS_SHOWHIDDEN); +} + +static void SetAllContactIcons(HWND hwndList) +{ + HANDLE hContact,hItem; + bool disabled; + char *proto; + bool chat_room; + + hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0); + do { + proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); + chat_room = (proto && DBGetContactSettingByte(hContact, proto, "ChatRoom", 0) != 0); + + if(!chat_room) { + hItem=(HANDLE)SendMessage(hwndList,CLM_FINDCONTACT,(WPARAM)hContact,0); + if(hItem) { + disabled = (DBGetContactSettingByte(hContact, MODULE, DBSETTING_REMOVE, 0) == 1); + SendMessage(hwndList,CLM_SETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(0,disabled?1:0)); + } + } + } while(hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hContact,0)); +} + + + +static BOOL CALLBACK DlgProcOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) { + static HANDLE hItemAll; + + switch ( msg ) { + case WM_INITDIALOG: + TranslateDialogDefault( hwndDlg ); + { HIMAGELIST hIml; + hIml=ImageList_Create(GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),(IsWinVerXPPlus()?ILC_COLOR32:ILC_COLOR16)|ILC_MASK,2,2); + ImageList_AddIcon(hIml,hIconKeep); + ImageList_AddIcon(hIml,hIconRemove); + SendDlgItemMessage(hwndDlg,IDC_LIST,CLM_SETEXTRAIMAGELIST,0,(LPARAM)hIml); + SendDlgItemMessage(hwndDlg,IDC_PIC_KEEP,STM_SETICON,(WPARAM)hIconKeep,0); + SendDlgItemMessage(hwndDlg,IDC_PIC_REMOVE,STM_SETICON,(WPARAM)hIconRemove,0); + } + + ResetListOptions(GetDlgItem(hwndDlg,IDC_LIST)); + SendDlgItemMessage(hwndDlg,IDC_LIST,CLM_SETEXTRACOLUMNS,1,0); + + { CLCINFOITEM cii={0}; + cii.cbSize=sizeof(cii); + cii.flags=CLCIIF_GROUPFONT; + cii.pszText=TranslateT("** All contacts **"); + hItemAll=(HANDLE)SendDlgItemMessage(hwndDlg,IDC_LIST,CLM_ADDINFOITEM,0,(LPARAM)&cii); + } + + SetAllContactIcons(GetDlgItem(hwndDlg,IDC_LIST)); + SetListGroupIcons(GetDlgItem(hwndDlg,IDC_LIST),(HANDLE)SendDlgItemMessage(hwndDlg,IDC_LIST,CLM_GETNEXTITEM,CLGN_ROOT,0),hItemAll,NULL); + + return FALSE; + case WM_SETFOCUS: + SetFocus(GetDlgItem(hwndDlg,IDC_LIST)); + break; + case WM_COMMAND: + break; + case WM_NOTIFY: + switch(((LPNMHDR)lParam)->idFrom) { + case IDC_LIST: + switch (((LPNMHDR)lParam)->code) + { + case CLN_NEWCONTACT: + case CLN_LISTREBUILT: + SetAllContactIcons(GetDlgItem(hwndDlg,IDC_LIST)); + //fall through + case CLN_CONTACTMOVED: + SetListGroupIcons(GetDlgItem(hwndDlg,IDC_LIST),(HANDLE)SendDlgItemMessage(hwndDlg,IDC_LIST,CLM_GETNEXTITEM,CLGN_ROOT,0),hItemAll,NULL); + break; + case CLN_OPTIONSCHANGED: + ResetListOptions(GetDlgItem(hwndDlg,IDC_LIST)); + break; + case NM_CLICK: + { HANDLE hItem; + NMCLISTCONTROL *nm=(NMCLISTCONTROL*)lParam; + DWORD hitFlags; + int iImage; + int itemType; + + // Make sure we have an extra column + if (nm->iColumn == -1) + break; + + // Find clicked item + hItem = (HANDLE)SendDlgItemMessage(hwndDlg, IDC_LIST, CLM_HITTEST, (WPARAM)&hitFlags, MAKELPARAM(nm->pt.x,nm->pt.y)); + // Nothing was clicked + if (hItem == NULL) break; + // It was not a visbility icon + if (!(hitFlags & CLCHT_ONITEMEXTRA)) break; + + // Get image in clicked column (0=none, 1=visible, 2=invisible) + iImage = SendDlgItemMessage(hwndDlg, IDC_LIST, CLM_GETEXTRAIMAGE, (WPARAM)hItem, MAKELPARAM(nm->iColumn, 0)); + if (iImage == 0) + iImage=nm->iColumn + 1; + else + if (iImage == 1) + iImage = 0; + + // Get item type (contact, group, etc...) + itemType = SendDlgItemMessage(hwndDlg, IDC_LIST, CLM_GETITEMTYPE, (WPARAM)hItem, 0); + + // Update list, making sure that the options are mutually exclusive + if (itemType == CLCIT_CONTACT) { // A contact + SendDlgItemMessage(hwndDlg, IDC_LIST, CLM_SETEXTRAIMAGE, (WPARAM)hItem, MAKELPARAM(nm->iColumn, iImage)); + } + else if (itemType == CLCIT_INFO) { // All Contacts + SetAllChildIcons(GetDlgItem(hwndDlg, IDC_LIST), hItem, nm->iColumn, iImage); + } + else if (itemType == CLCIT_GROUP) { // A group + hItem = (HANDLE)SendDlgItemMessage(hwndDlg, IDC_LIST, CLM_GETNEXTITEM, CLGN_CHILD, (LPARAM)hItem); + if (hItem) { + SetAllChildIcons(GetDlgItem(hwndDlg, IDC_LIST), hItem, nm->iColumn, iImage); + } + } + // Update the all/none icons + SetListGroupIcons(GetDlgItem(hwndDlg, IDC_LIST), (HANDLE)SendDlgItemMessage(hwndDlg, IDC_LIST, CLM_GETNEXTITEM, CLGN_ROOT, 0), hItemAll, NULL); + + // Activate Apply button + SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); + break; + } + } + break; + case 0: + switch (((LPNMHDR)lParam)->code) + { + case PSN_APPLY: + { HANDLE hContact,hItem; + int iImage; + char *proto; + bool chat_room; + + hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDFIRST,0,0); + do { + proto = (char *)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0); + chat_room = (proto && DBGetContactSettingByte(hContact, proto, "ChatRoom", 0) != 0); + + if(!chat_room) { + hItem=(HANDLE)SendDlgItemMessage(hwndDlg,IDC_LIST,CLM_FINDCONTACT,(WPARAM)hContact,0); + if(hItem) { + iImage=SendDlgItemMessage(hwndDlg,IDC_LIST,CLM_GETEXTRAIMAGE,(WPARAM)hItem,MAKELPARAM(0,0)); + DBWriteContactSettingByte(hContact, MODULE, DBSETTING_REMOVE, iImage==1?1:0); + } + } + } while(hContact=(HANDLE)CallService(MS_DB_CONTACT_FINDNEXT,(WPARAM)hContact,0)); + return TRUE; + } + } + break; + } + break; + case WM_DESTROY: + { HIMAGELIST hIml=(HIMAGELIST)SendDlgItemMessage(hwndDlg,IDC_LIST,CLM_GETEXTRAIMAGELIST,0,0); + ImageList_Destroy(hIml); + } + break; + } + + return 0; +} + +int OptInit(WPARAM wParam, LPARAM lParam) { +#define OPTIONPAGE_OLD_SIZE2 60 + + OPTIONSDIALOGPAGE odp = { 0 }; + //odp.cbSize = sizeof(odp); + odp.cbSize = OPTIONPAGE_OLD_SIZE2; + odp.flags = ODPF_BOLDGROUPS; + //odp.flags |= ODPF_UNICODE; + odp.position = -790000000; + odp.hInstance = hInst; + + odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT); + odp.pszTitle = Translate("NoHistory"); + odp.pszGroup = Translate("Services"); + odp.nIDBottomSimpleControl = 0; + odp.pfnDlgProc = DlgProcOpts; + CallService( MS_OPT_ADDPAGE, wParam,( LPARAM )&odp ); + + return 0; +} + +HANDLE hEventOptInit; +void InitOptions() { + hEventOptInit = HookEvent(ME_OPT_INITIALISE, OptInit); + event_timeout = DBGetContactSettingDword(0, MODULE, "EventTimeout", 1); +} + +void DeinitOptions() { + UnhookEvent(hEventOptInit); +} diff --git a/no_history/options.h b/no_history/options.h new file mode 100644 index 0000000..f9825ce --- /dev/null +++ b/no_history/options.h @@ -0,0 +1,9 @@ +#ifndef _OPTIONS_INC +#define _OPTIONS_INC + +extern DWORD event_timeout; + +void InitOptions(); +void DeinitOptions(); + +#endif diff --git a/no_history/private.h b/no_history/private.h new file mode 100644 index 0000000..fc90db5 --- /dev/null +++ b/no_history/private.h @@ -0,0 +1,24 @@ +#ifndef _PRIVATE_H +#define _PRIVATE_H + +/* VERSION DEFINITIONS */ +#define VER_MAJOR 0 +#define VER_MINOR 0 +#define VER_RELEASE 4 +#define VER_BUILD 0 + +#define __STRINGIZE(x) #x +#define VER_STRING __STRINGIZE( VER_MAJOR.VER_MINOR.VER_RELEASE.VER_BUILD ) + +#define DESC_STRING "Prevent miranda from storing any history" +#define COMPANY_NAME "" +#define FILE_VERSION VER_STRING +#define FILE_DESCRIPTION DESC_STRING +#define INTERNAL_NAME "" +#define LEGAL_COPYRIGHT "© Scott Ellis 2005" +#define LEGAL_TRADEMARKS "" +#define ORIGINAL_FILENAME "no_history.dll" +#define PRODUCT_NAME DESC_STRING +#define PRODUCT_VERSION VER_STRING + +#endif /*OTR_PRIVATE_H*/ diff --git a/no_history/private.rc b/no_history/private.rc new file mode 100644 index 0000000..47bca39 --- /dev/null +++ b/no_history/private.rc @@ -0,0 +1,35 @@ +/* THIS FILE WILL BE OVERWRITTEN BY DEV-C++ */ +/* DO NOT EDIT! */ + +#include "private.h" +#include "afxres.h" +// +// TO CHANGE VERSION INFORMATION, EDIT PROJECT OPTIONS... +// +1 VERSIONINFO +FILEVERSION VER_MAJOR,VER_MINOR,VER_RELEASE,VER_BUILD +PRODUCTVERSION VER_MAJOR,VER_MINOR,VER_RELEASE,VER_BUILD +FILETYPE VFT_DLL +{ + BLOCK "StringFileInfo" + { + BLOCK "0C0904E4" + { + VALUE "CompanyName", COMPANY_NAME + VALUE "FileVersion", FILE_VERSION + VALUE "FileDescription", FILE_DESCRIPTION + VALUE "InternalName", INTERNAL_NAME + VALUE "LegalCopyright", LEGAL_COPYRIGHT + VALUE "LegalTrademarks", LEGAL_TRADEMARKS + VALUE "OriginalFilename", ORIGINAL_FILENAME + VALUE "ProductName", PRODUCT_NAME + VALUE "ProductVersion", PRODUCT_VERSION + } + } + BLOCK "VarFileInfo" + { + VALUE "Translation", 0x0C09, 1252 + } +} + + diff --git a/no_history/resource.h b/no_history/resource.h new file mode 100644 index 0000000..2361f87 --- /dev/null +++ b/no_history/resource.h @@ -0,0 +1,23 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by NoHistory.rc +// +#define IDI_HKEEP 100 +#define IDI_HREMOVE 101 +#define IDI_HCLEAR 102 +#define IDD_OPT 103 +#define IDC_LIST 1000 +#define IDC_PIC_KEEP 1001 +#define IDC_PIC_REMOVE 1002 +#define IDC_BUTTON1 1003 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 104 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1004 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/no_history/resource.rc b/no_history/resource.rc new file mode 100644 index 0000000..12fdadc --- /dev/null +++ b/no_history/resource.rc @@ -0,0 +1,2 @@ +#include "NoHistory.rc" +#include "private.rc" -- cgit v1.2.3