summaryrefslogtreecommitdiff
path: root/plugins/WhenWasIt/src
diff options
context:
space:
mode:
authorKirill Volinsky <mataes2007@gmail.com>2012-08-08 18:35:25 +0000
committerKirill Volinsky <mataes2007@gmail.com>2012-08-08 18:35:25 +0000
commit21f160111c9ff42bc3a40e50125cceea094e1d6d (patch)
tree7303d169928482a859dc6eb81f0b4843307d775a /plugins/WhenWasIt/src
parent6bccad35352a239573705d6c61235bcdb2b44426 (diff)
WhenWasIt changed folder structure
git-svn-id: http://svn.miranda-ng.org/main/trunk@1406 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/WhenWasIt/src')
-rw-r--r--plugins/WhenWasIt/src/WhenWasIt.cpp131
-rw-r--r--plugins/WhenWasIt/src/birthdays.cpp170
-rw-r--r--plugins/WhenWasIt/src/birthdays.h68
-rw-r--r--plugins/WhenWasIt/src/commonheaders.h104
-rw-r--r--plugins/WhenWasIt/src/date_utils.cpp283
-rw-r--r--plugins/WhenWasIt/src/date_utils.h51
-rw-r--r--plugins/WhenWasIt/src/dlg_handlers.cpp1292
-rw-r--r--plugins/WhenWasIt/src/dlg_handlers.h45
-rw-r--r--plugins/WhenWasIt/src/events.cpp38
-rw-r--r--plugins/WhenWasIt/src/events.h31
-rw-r--r--plugins/WhenWasIt/src/hooked_events.cpp396
-rw-r--r--plugins/WhenWasIt/src/hooked_events.h49
-rw-r--r--plugins/WhenWasIt/src/icons.cpp216
-rw-r--r--plugins/WhenWasIt/src/icons.h50
-rw-r--r--plugins/WhenWasIt/src/notifiers.cpp343
-rw-r--r--plugins/WhenWasIt/src/notifiers.h60
-rw-r--r--plugins/WhenWasIt/src/resource.h79
-rw-r--r--plugins/WhenWasIt/src/services.cpp422
-rw-r--r--plugins/WhenWasIt/src/services.h58
-rw-r--r--plugins/WhenWasIt/src/utils.cpp393
-rw-r--r--plugins/WhenWasIt/src/utils.h54
-rw-r--r--plugins/WhenWasIt/src/version.h45
22 files changed, 4378 insertions, 0 deletions
diff --git a/plugins/WhenWasIt/src/WhenWasIt.cpp b/plugins/WhenWasIt/src/WhenWasIt.cpp
new file mode 100644
index 0000000000..de77127c7e
--- /dev/null
+++ b/plugins/WhenWasIt/src/WhenWasIt.cpp
@@ -0,0 +1,131 @@
+/*
+WhenWasIt (birthday reminder) plugin for Miranda IM
+
+Copyright © 2006 Cristian Libotean
+
+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 "commonheaders.h"
+
+char ModuleName[] = "WhenWasIt";
+HINSTANCE hInstance;
+HWND hBirthdaysDlg = NULL;
+HWND hUpcomingDlg = NULL;
+extern HANDLE hAddBirthdayWndsList = NULL;
+int hLangpack;
+
+CommonData commonData = {0};
+
+
+
+PLUGININFOEX pluginInfo = {
+ sizeof(PLUGININFOEX),
+ __PLUGIN_DISPLAY_NAME,
+ VERSION,
+ __DESC,
+ __AUTHOR,
+ __AUTHOREMAIL,
+ __COPYRIGHT,
+ __AUTHORWEB,
+ UNICODE_AWARE,
+ {0x2ff96c84, 0xb0b5, 0x470e, {0xbb, 0xf9, 0x90, 0x7b, 0x9f, 0x3f, 0x5d, 0x2f}} //{2ff96c84-b0b5-470e-bbf9-907b9f3f5d2f}
+};
+
+extern "C" __declspec(dllexport) PLUGININFOEX *MirandaPluginInfoEx(DWORD mirandaVersion)
+{
+// Log("%s", "Entering function " __FUNCTION__);
+// Log("%s", "Leaving function " __FUNCTION__);
+ return &pluginInfo;
+}
+
+extern "C" __declspec(dllexport) const MUUID MirandaInterfaces[] = {MIID_BIRTHDAYNOTIFY, MIID_LAST};
+
+#include <commctrl.h>
+
+extern "C" int __declspec(dllexport) Load(void)
+{
+ Log("%s", "Entering function " __FUNCTION__);
+
+ mir_getLP(&pluginInfo);
+
+ INITCOMMONCONTROLSEX icex;
+
+ icex.dwSize = sizeof(icex);
+ icex.dwICC = ICC_DATE_CLASSES;
+
+ InitCommonControlsEx(&icex);
+
+ Log("%s", "Initialising miranda memory functions");
+
+ LoadIcons();
+ //hBirthdaysDlg = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_BIRTHDAYS), NULL, DlgProcBirthdays);
+ Log("%s", "Creating service functions ...");
+ InitServices();
+
+ //Log("%s", "Creating events ...");
+ //CreateEvents();
+
+ Log("%s", "Hooking events ...");
+ HookEvents();
+
+ hAddBirthdayWndsList = (HANDLE) CallService(MS_UTILS_ALLOCWINDOWLIST, 0, 0);
+
+ Log("%s", "Leaving function " __FUNCTION__);
+
+ return 0;
+}
+
+extern "C" int __declspec(dllexport) Unload()
+{
+ Log("%s", "Entering function " __FUNCTION__);
+
+ if (hBirthdaysDlg)
+ {
+ SendMessage(hBirthdaysDlg, WM_CLOSE, 0, 0);
+ }
+
+ if (hUpcomingDlg)
+ {
+ SendMessage(hUpcomingDlg, WM_CLOSE, 0, 0);
+ }
+
+ WindowList_Broadcast(hAddBirthdayWndsList, WM_CLOSE, 0, 0);
+
+ Log("%s", "Killing timers ...");
+ KillTimers();
+
+ Log("%s", "Unhooking events ...");
+ UnhookEvents();
+
+ Log("%s", "Destroying service functions ...");
+ DestroyServices();
+
+
+ Log("%s", "Leaving function " __FUNCTION__);
+
+ return 0;
+}
+
+bool WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
+{
+ hInstance = hinstDLL;
+ if (fdwReason == DLL_PROCESS_ATTACH)
+ {
+ DisableThreadLibraryCalls(hinstDLL);
+ }
+
+ return TRUE;
+}
diff --git a/plugins/WhenWasIt/src/birthdays.cpp b/plugins/WhenWasIt/src/birthdays.cpp
new file mode 100644
index 0000000000..baed614aad
--- /dev/null
+++ b/plugins/WhenWasIt/src/birthdays.cpp
@@ -0,0 +1,170 @@
+/*
+WhenWasIt (birthday reminder) plugin for Miranda IM
+
+Copyright © 2006 Cristian Libotean
+
+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 "commonheaders.h"
+#include "birthdays.h"
+
+CBirthdays &birthdays = CBirthdays();
+
+CBirthdays::CBirthdays(int initialSize)
+{
+ int count = 0;
+ int size = 0;
+ birthdays = NULL;
+ advancedIcon = CLIST_ICON;
+
+ Realloc(initialSize);
+}
+
+CBirthdays::~CBirthdays()
+{
+ Destroy();
+}
+
+void CBirthdays::Destroy()
+{
+ if (birthdays)
+ {
+ Clear();
+ free(birthdays);
+ birthdays = NULL;
+ }
+}
+
+void CBirthdays::Clear()
+{
+ int i;
+ for (i = 0; i < Count(); i++)
+ {
+ ClearItem(i);
+ }
+ count = 0;
+}
+
+void CBirthdays::ClearItem(int index)
+{
+ free(birthdays[index]);
+ birthdays[index] = NULL;
+}
+
+int CBirthdays::Count() const
+{
+ return count;
+}
+
+int CBirthdays::Size() const
+{
+ return size;
+}
+
+void CBirthdays::EnsureCapacity()
+{
+ if (count >= size)
+ {
+ Realloc(size / 2);
+ }
+}
+
+void CBirthdays::Realloc(int increaseCapacity)
+{
+ size += increaseCapacity;
+ birthdays = (PBirthdayContact *) realloc(birthdays, size * sizeof(PBirthdayContact));
+}
+
+int CBirthdays::Add(HANDLE hContact, HANDLE hClistIcon)
+{
+ if (!Contains(hContact))
+ {
+ EnsureCapacity();
+ TBirthdayContact *item = (TBirthdayContact *) malloc(sizeof(TBirthdayContact));
+ item->hContact = hContact;
+ item->hClistIcon = hClistIcon;
+ birthdays[count++] = item;
+ return 0;
+ }
+ return -1;
+}
+
+int CBirthdays::Remove(int index)
+{
+ if ((index >= 0) && (index < count))
+ {
+ int i;
+ for (i = index + 1; i < count; i++)
+ {
+ birthdays[i - 1] = birthdays[i];
+ }
+ ClearItem(count--);
+ return 0;
+ }
+ return -1;
+}
+
+int CBirthdays::Remove(HANDLE hContact)
+{
+ int index = Index(hContact);
+ return Remove(index);
+}
+
+int CBirthdays::Contains(HANDLE hContact) const
+{
+ int i;
+ for (i = 0; i < count; i++)
+ {
+ if (birthdays[i]->hContact == hContact)
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+int CBirthdays::Index(HANDLE hContact) const
+{
+ int i;
+ for (i = 0; i < count; i++)
+ {
+ if (birthdays[i]->hContact == hContact)
+ {
+ return i;
+ }
+ }
+ return -1;
+}
+
+void CBirthdays::SetAdvancedIconIndex(int advIcon)
+{
+ advancedIcon = advIcon;
+}
+
+int CBirthdays::GetAdvancedIconIndex() const
+{
+ return advancedIcon;
+}
+
+HANDLE CBirthdays::GetClistIcon(HANDLE hContact) const
+{
+ int index = Index(hContact);
+ if ((index >= 0) && (index < count))
+ {
+ return birthdays[index]->hClistIcon;
+ }
+ return (HANDLE) -1;
+} \ No newline at end of file
diff --git a/plugins/WhenWasIt/src/birthdays.h b/plugins/WhenWasIt/src/birthdays.h
new file mode 100644
index 0000000000..c54042800c
--- /dev/null
+++ b/plugins/WhenWasIt/src/birthdays.h
@@ -0,0 +1,68 @@
+/*
+WhenWasIt (birthday reminder) plugin for Miranda IM
+
+Copyright © 2006 Cristian Libotean
+
+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 M_WWI_BIRTHDAYS_H
+#define M_WWI_BIRTHDAYS_H
+
+struct TBirthdayContact{
+ HANDLE hContact;
+ HANDLE hClistIcon;
+};
+
+typedef TBirthdayContact *PBirthdayContact;
+
+class CBirthdays
+{
+ protected:
+ int count;
+ int size;
+ PBirthdayContact *birthdays;
+ int advancedIcon;
+
+ void Realloc(int increaseCapacity);
+ void EnsureCapacity();
+
+ void ClearItem(int index);
+
+ public:
+ CBirthdays(int initialSize = 10);
+ ~CBirthdays();
+
+ int Add(HANDLE hContact, HANDLE hClistIcon);
+ int Remove(int index);
+ int Remove(HANDLE hContact);
+ void Clear();
+ void Destroy();
+
+ int Index(HANDLE hContact) const;
+ int Contains(HANDLE hContact) const;
+
+ void SetAdvancedIconIndex(int advIcon);
+ int GetAdvancedIconIndex() const;
+
+ HANDLE GetClistIcon(HANDLE hContact) const;
+
+ int Count() const;
+ int Size() const;
+};
+
+extern CBirthdays &birthdays;
+
+#endif //M_WWI_BIRTHDAYS_H
diff --git a/plugins/WhenWasIt/src/commonheaders.h b/plugins/WhenWasIt/src/commonheaders.h
new file mode 100644
index 0000000000..a231fafba8
--- /dev/null
+++ b/plugins/WhenWasIt/src/commonheaders.h
@@ -0,0 +1,104 @@
+/*
+WhenWasIt (birthday reminder) plugin for Miranda IM
+
+Copyright © 2006-2011 Cristian Libotean
+
+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 M_WWI_COMMONHEADERS_H
+#define M_WWI_COMMONHEADERS_H
+
+#define _CRT_SECURE_NO_WARNINGS
+#define _CRT_NON_CONFORMING_SWPRINTFS
+
+#define MIRANDA_VER 0x0A00
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <windows.h>
+#include <time.h>
+#include <math.h>
+
+#include "resource.h"
+#include "version.h"
+
+#include "utils.h"
+#include "date_utils.h"
+#include "services.h"
+//#include "events.h"
+#include "hooked_events.h"
+#include "icons.h"
+#include "notifiers.h"
+//#include "birthdays.h"
+#include "win2k.h"
+#include "newpluginapi.h"
+#include "m_database.h"
+#include "m_system.h"
+#include "m_skin.h"
+#include "m_options.h"
+#include "m_clist.h"
+#include "m_langpack.h"
+#include "m_history.h"
+#include "m_contacts.h"
+#include "m_popup.h"
+//#include "m_popupw.h"
+#include "m_fontservice.h"
+#include "m_utils.h"
+#include "m_icolib.h"
+#include "m_cluiframes.h"
+#include "m_clui.h"
+#include "m_protosvc.h"
+#include "m_hotkeys.h"
+#include "m_toptoolbar.h"
+#include "m_metacontacts.h"
+#include "m_message.h"
+#include "m_extraicons.h"
+
+extern char ModuleName[];
+extern HINSTANCE hInstance;
+extern HWND hBirthdaysDlg;
+extern HWND hUpcomingDlg;
+extern HANDLE hAddBirthdayWndsList;
+
+struct CommonData{
+ DWORD foreground;
+ DWORD background;
+ int checkInterval;
+ int daysInAdvance;
+ int popupTimeout;
+ int popupTimeoutToday;
+ int clistIcon;
+ int bUsePopups;
+ int bUseClistIcon;
+ int bUseDialog;
+ int bIgnoreSubcontacts;
+ int cShowAgeMode;
+ int bNoBirthdaysPopup;
+ int cSoundNearDays;
+ int cDefaultModule;
+ int lPopupClick;
+ int rPopupClick;
+ int bOncePerDay;
+ int cDlgTimeout;
+ int notifyFor;
+ int daysAfter;
+ int bOpenInBackground;
+};
+
+extern CommonData commonData;
+
+#endif //M_WWI_COMMONHEADERS_H \ No newline at end of file
diff --git a/plugins/WhenWasIt/src/date_utils.cpp b/plugins/WhenWasIt/src/date_utils.cpp
new file mode 100644
index 0000000000..e9da2253e0
--- /dev/null
+++ b/plugins/WhenWasIt/src/date_utils.cpp
@@ -0,0 +1,283 @@
+/*
+WhenWasIt (birthday reminder) plugin for Miranda IM
+
+Copyright © 2006 Cristian Libotean
+
+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 "commonheaders.h"
+#include "date_utils.h"
+
+time_t Today()
+{
+ time_t now = time(NULL);
+ struct tm* date = localtime(&now);
+ date->tm_hour = date->tm_min = date->tm_sec = 0;
+ return mktime(date);
+}
+
+int IsDOBValid(int year, int month, int day)
+{
+ return ((year != 0) && (month != 0) && (day != 0));
+}
+
+int GetContactDOB(HANDLE hContact, int &year, int &month, int &day)
+{
+ int res = DOB_USERINFO;
+
+ //TCHAR *contact = GetContactName(hContact, NULL);
+ year = DBGetContactSettingWord(hContact, "UserInfo", "DOBy", 0);
+ month = DBGetContactSettingByte(hContact, "UserInfo", "DOBm", 0);
+ day = DBGetContactSettingByte(hContact, "UserInfo", "DOBd", 0);
+
+ if (!IsDOBValid(year, month, day))
+ {
+ res = DOB_MBIRTHDAY;
+ year = DBGetContactSettingWord(hContact, "mBirthday", "BirthYear", 0);
+ month = DBGetContactSettingByte(hContact, "mBirthday", "BirthMonth", 0);
+ day = DBGetContactSettingByte(hContact, "mBirthday", "BirthDay", 0);
+ }
+
+ if (!IsDOBValid(year, month, day))
+ {
+ res = DOB_PROTOCOL;
+ char protocol[512];
+ GetContactProtocol(hContact, protocol, sizeof(protocol));
+ year = DBGetContactSettingWord(hContact, protocol, "BirthYear", 0);
+ month = DBGetContactSettingByte(hContact, protocol, "BirthMonth", 0);
+ day = DBGetContactSettingByte(hContact, protocol, "BirthDay", 0);
+ }
+
+ if (!IsDOBValid(year, month, day))
+ {
+ res = DOB_BIRTHDAYREMINDER;
+ year = DBGetContactSettingWord(hContact, "BirthDay", "BirthYear", 0);
+ month = DBGetContactSettingByte(hContact, "BirthDay", "BirthMonth", 0);
+ day = DBGetContactSettingByte(hContact, "BirthDay", "BirthDay", 0);
+ }
+
+ if (!IsDOBValid(year, month, day))
+ {
+ res = DOB_MICQBIRTHDAY;
+ year = DBGetContactSettingDword(hContact, "micqBirthday", "BirthYear", 0);
+ month = DBGetContactSettingDword(hContact, "micqBirthday", "BirthMonth", 0);
+ day = DBGetContactSettingDword(hContact, "micqBirthday", "BirthDay", 0);
+ }
+
+ if (!IsDOBValid(year, month, day))
+ {
+ res = DOB_UNKNOWN;
+ }
+ //free(contact);
+ return res;
+}
+
+int GetContactAge(HANDLE hContact)
+{
+ int year, month, day;
+ time_t tNow;
+ time(&tNow);
+ struct tm *now = localtime(&tNow);
+ GetContactDOB(hContact, year, month, day);
+ return (now->tm_year + 1900) - year;
+}
+
+char GetContactGender(HANDLE hContact)
+{
+ char gender = DBGetContactSettingByte(hContact, "UserInfo", "Gender", 'U');
+ if (gender == 'U')
+ {
+ char protocol[512];
+ GetContactProtocol(hContact, protocol, sizeof(protocol));
+
+ gender = DBGetContactSettingByte(hContact, protocol, "Gender", 'U');
+ }
+ return gender;
+}
+
+int IsLeapYear(int year)
+{
+ int yes = ((year % 400 == 0) || ((year % 4 == 0) && (year % 100 != 0)));
+ return yes;
+}
+
+unsigned int GetDaysDifference(time_t time1, time_t time2)
+{
+ errno = 0;
+ double diff = difftime(time1, time2);
+ if (errno == 0)
+ {
+ diff = diff / (60 * 60 * 24);
+ int days = (int) floor(diff);
+ if (days < 0)
+ {
+ struct tm *date = gmtime(&time1);
+ int leap = 0;
+ if ((date->tm_mon > 2) && (IsLeapYear(date->tm_year))) //if month > feb and it's a leap year
+ {
+ leap = 1;
+ }
+ days = 365 + days + leap;
+ }
+ return days;
+ }
+ return 0x7fffffff;
+}
+
+int GetDaysDifferenceAfter(time_t time1, time_t time2)
+{
+ errno = 0;
+ double diff = difftime(time1, time2);
+ if (errno == 0)
+ {
+ diff = diff / (60 * 60 * 24);
+ int days = (int) floor(diff);
+ if (days > 0)
+ {
+ return -1;
+ }
+
+ return -days;
+ }
+
+ return -1;
+}
+
+unsigned int DaysToBirthday(time_t now, int ctYear, int ctMonth, int ctDay)
+{
+ if (IsDOBValid(ctYear, ctMonth, ctDay))
+ {
+ struct tm ct = {0};
+ struct tm *tmp = gmtime(&now);
+ ct.tm_year = tmp->tm_year;
+ ct.tm_mon = ctMonth - 1;
+ ct.tm_mday = ctDay;
+ time_t ctBirthday = mktime(&ct);
+ return GetDaysDifference(ctBirthday, now);
+ }
+ return -1;
+}
+
+int DaysAfterBirthday(time_t now, int ctYear, int ctMonth, int ctDay)
+{
+ if (IsDOBValid(ctYear, ctMonth, ctDay))
+ {
+ struct tm ct = {0};
+ struct tm *tmp = gmtime(&now);
+ ct.tm_year = tmp->tm_year;
+ ct.tm_mon = ctMonth - 1;
+ ct.tm_mday = ctDay;
+ time_t ctBirthday = mktime(&ct);
+
+ return GetDaysDifferenceAfter(ctBirthday, now);
+ }
+
+ return -1;
+}
+
+
+void FillProtocol(char *&sYear, char *&sMonth, char *&sDay)
+{
+ sYear = "BirthYear";
+ sMonth = "BirthMonth";
+ sDay = "BirthDay";
+}
+
+void FillmBirthday(char *&module, char *&sYear, char *&sMonth, char *&sDay)
+{
+ module = "mBirthday";
+ sYear = "BirthYear";
+ sMonth = "BirthMonth";
+ sDay = "BirthDay";
+}
+
+void FillStandard(char *&module, char *&sYear, char *&sMonth, char *&sDay)
+{
+ module = "UserInfo";
+ sYear = "DOBy";
+ sMonth = "DOBm";
+ sDay = "DOBd";
+}
+
+int SaveBirthday(HANDLE hContact, int year, int month, int day, int mode)
+{
+ char *sModule, *sdModule, *sd2Module; //s* = keep, sd* = delete, sd2* = delete
+ char *sYear, *sdYear, *sd2Year;
+ char *sMonth, *sdMonth, *sd2Month;
+ char *sDay, *sdDay, *sd2Day;
+ char protocol[256];
+ GetContactProtocol(hContact, protocol, sizeof(protocol));
+
+ switch (mode)
+ {
+ case SAVE_MODE_MBIRTHDAY:
+ {
+ FillmBirthday(sModule, sYear, sMonth, sDay);
+ FillStandard(sdModule, sdYear, sdMonth, sdDay);
+ sd2Module = protocol;
+ FillProtocol(sd2Year, sd2Month, sd2Day);
+
+ break;
+ }
+
+ case SAVE_MODE_PROTOCOL:
+ {
+ sModule = protocol;
+ FillProtocol(sYear, sMonth, sDay);
+
+ FillmBirthday(sd2Module, sd2Year, sd2Month, sd2Day);
+ FillStandard(sdModule, sdYear, sdMonth, sdDay);
+
+ break;
+ }
+
+ case SAVE_MODE_STANDARD:
+ default:
+ {
+ FillStandard(sModule, sYear, sMonth, sDay);
+ FillmBirthday(sdModule, sdYear, sdMonth, sdDay);
+ sd2Module = protocol;
+ FillProtocol(sd2Year, sd2Month, sd2Day);
+ break;
+ }
+ }
+
+ if (mode == SAVE_MODE_DELETEALL)
+ {
+ DBDeleteContactSetting(hContact, sModule, sYear);
+ DBDeleteContactSetting(hContact, sModule, sMonth);
+ DBDeleteContactSetting(hContact, sModule, sDay);
+ }
+ else{
+ DBWriteContactSettingWord(hContact, sModule, sYear, year);
+ DBWriteContactSettingByte(hContact, sModule, sMonth, month);
+ DBWriteContactSettingByte(hContact, sModule, sDay, day);
+ }
+
+ DBDeleteContactSetting(hContact, sdModule, sdYear);
+ DBDeleteContactSetting(hContact, sdModule, sdMonth);
+ DBDeleteContactSetting(hContact, sdModule, sdDay);
+
+ DBDeleteContactSetting(hContact, sd2Module, sd2Year);
+ DBDeleteContactSetting(hContact, sd2Module, sd2Month);
+ DBDeleteContactSetting(hContact, sd2Module, sd2Day);
+
+ DBDeleteContactSetting(hContact, "BirthDay", "BirthYear");
+ DBDeleteContactSetting(hContact, "BirthDay", "BirthMonth");
+ DBDeleteContactSetting(hContact, "BirthDay", "BirthDay");
+
+ return 0;
+} \ No newline at end of file
diff --git a/plugins/WhenWasIt/src/date_utils.h b/plugins/WhenWasIt/src/date_utils.h
new file mode 100644
index 0000000000..45db98fad7
--- /dev/null
+++ b/plugins/WhenWasIt/src/date_utils.h
@@ -0,0 +1,51 @@
+/*
+WhenWasIt (birthday reminder) plugin for Miranda IM
+
+Copyright © 2006 Cristian Libotean
+
+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 H_WWI_DATE_UTILS_H
+#define H_WWI_DATE_UTILS_H
+
+#include "errno.h"
+
+#define SAVE_MODE_STANDARD 0
+#define SAVE_MODE_PROTOCOL 1
+#define SAVE_MODE_MBIRTHDAY 2
+
+#define DOB_UNKNOWN 100
+#define DOB_USERINFO 101
+#define DOB_MBIRTHDAY 102
+#define DOB_PROTOCOL 103
+#define DOB_BIRTHDAYREMINDER 104
+#define DOB_MICQBIRTHDAY 105
+
+#define SAVE_MODE_DELETEALL 100
+
+time_t Today();
+int IsLeapYear(int year);
+int IsDOBValid(int year, int month, int day);
+
+unsigned int DaysToBirthday(time_t now, int ctYear, int ctMonth, int ctDay);
+int DaysAfterBirthday(time_t now, int ctYear, int ctMonth, int ctDay);
+int GetContactAge(HANDLE hContact);
+int GetContactDOB(HANDLE hContact, int &year, int &month, int &day);
+char GetContactGender(HANDLE hContact);
+
+int SaveBirthday(HANDLE hContact, int year, int month, int day, int mode);
+
+#endif //H_WWI_DATE_UTILS_H \ No newline at end of file
diff --git a/plugins/WhenWasIt/src/dlg_handlers.cpp b/plugins/WhenWasIt/src/dlg_handlers.cpp
new file mode 100644
index 0000000000..37160995e2
--- /dev/null
+++ b/plugins/WhenWasIt/src/dlg_handlers.cpp
@@ -0,0 +1,1292 @@
+/*
+WhenWasIt (birthday reminder) plugin for Miranda IM
+
+Copyright © 2006 Cristian Libotean
+
+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 "commonheaders.h"
+#include "dlg_handlers.h"
+
+#define COLOR_USERINFO RGB(138, 190, 160)
+#define COLOR_MBIRTHDAY RGB(222, 222, 88)
+#define COLOR_BIRTHDAYREMINDER RGB(200, 120, 240)
+#define COLOR_PROTOCOL RGB(255, 153, 153)
+#define COLOR_MICQBIRTHDAY RGB(88, 88, 240)
+
+#define UPCOMING_TIMER_ID 1002
+
+static WNDPROC OldBirthdaysListProc = NULL;
+
+const TCHAR *szAdvancedIcons[] = {_T("RES0"), _T("Email"), _T("Web"), _T("SMS"), _T("Advanced 1"), _T("Advanced 2"), _T("Advanced 3"), _T("Client"), _T("Advanced 4"), _T("Protocol"), _T("RES2/VisMode")};
+const int cAdvancedIcons = sizeof(szAdvancedIcons) / sizeof(szAdvancedIcons[0]); //don't forget to modify icons.cpp
+
+const TCHAR *szShowAgeMode[] = {_T("Upcoming age"), _T("Current age")};
+const int cShowAgeMode = sizeof(szShowAgeMode) / sizeof(szShowAgeMode[0]);
+
+const TCHAR *szSaveModule[] = {_T("UserInfo module"), _T("Protocol module"), _T("mBirthday module")};
+const int cSaveModule = sizeof(szSaveModule) / sizeof(szSaveModule[0]);
+
+const TCHAR *szPopupClick[] = {_T("Nothing"), _T("Dismiss"), _T("Message window")};
+const int cPopupClick = sizeof(szPopupClick) / sizeof(szPopupClick[0]);
+
+const TCHAR *szNotifyFor[] = {_T("All contacts"), _T("All contacts except hidden ones"), _T("All contacts except ignored ones"), _T("All contacts except hidden and ignored ones")};
+const int cNotifyFor = sizeof(szNotifyFor) / sizeof(szNotifyFor[0]);
+
+#define MIN_BIRTHDAYS_WIDTH 200
+#define MIN_BIRTHDAYS_HEIGHT 200
+
+#include "commctrl.h"
+void CreateToolTip(HWND target, TCHAR* tooltip, LPARAM width)
+{
+ HWND hwndToolTip;
+
+ hwndToolTip = CreateWindow(TOOLTIPS_CLASS, NULL,
+ WS_POPUP | TTS_NOPREFIX | TTS_ALWAYSTIP,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ target,
+ NULL,
+ NULL,
+ NULL);
+ if (hwndToolTip)
+ {
+ TOOLINFO ti = {0};
+ ti.cbSize = sizeof(ti);
+ ti.uFlags = TTF_TRANSPARENT | TTF_SUBCLASS;
+ ti.hwnd = target;
+ ti.uId = 0;
+ ti.hinst = NULL;
+ ti.lpszText = tooltip;
+ GetClientRect(target, &ti.rect);
+ SendMessage(hwndToolTip, TTM_ADDTOOL, 0, (LPARAM) &ti );
+ SendMessage(hwndToolTip, TTM_SETMAXTIPWIDTH, 0, width);
+ SendMessage(hwndToolTip, TTM_SETDELAYTIME, TTDT_AUTOPOP, 20000);
+ }
+}
+
+int EnablePopupsGroup(HWND hWnd, int enable)
+{
+ EnableWindow(GetDlgItem(hWnd, IDC_POPUPS_STATIC), enable);
+ EnableWindow(GetDlgItem(hWnd, IDC_POPUP_TIMEOUT), enable);
+ EnableWindow(GetDlgItem(hWnd, IDC_FOREGROUND), enable);
+ EnableWindow(GetDlgItem(hWnd, IDC_BACKGROUND), enable);
+ EnableWindow(GetDlgItem(hWnd, IDC_NOBIRTHDAYS_POPUP), enable);
+ EnableWindow(GetDlgItem(hWnd, IDC_IGNORE_SUBCONTACTS), (ServiceExists(MS_MC_GETMETACONTACT)) ? enable : FALSE);
+ EnableWindow(GetDlgItem(hWnd, IDC_PREVIEW), enable);
+ EnableWindow(GetDlgItem(hWnd, IDC_LEFT_CLICK), enable);
+ EnableWindow(GetDlgItem(hWnd, IDC_RIGHT_CLICK), enable);
+
+ return enable;
+}
+
+int EnableClistGroup(HWND hWnd, int enable)
+{
+ EnableWindow(GetDlgItem(hWnd, IDC_CLIST_STATIC), enable);
+ EnableWindow(GetDlgItem(hWnd, IDC_ADVANCED_ICON), enable);
+ return enable;
+}
+
+int EnableDialogGroup(HWND hWnd, int enable)
+{
+ EnableWindow(GetDlgItem(hWnd, IDC_DLG_TIMEOUT), enable);
+ EnableWindow(GetDlgItem(hWnd, IDC_OPENINBACKGROUND), enable);
+
+ return enable;
+}
+
+int AddInfoToComboBoxes(HWND hWnd)
+{
+ int i;
+ TCHAR *buffer;
+ for (i = 0; i < cAdvancedIcons; i++)
+ {
+ buffer = TranslateTS(szAdvancedIcons[i]);
+ SendMessage(GetDlgItem(hWnd, IDC_ADVANCED_ICON), CB_ADDSTRING, 0, (LPARAM) buffer);
+ }
+
+ for (i = 0; i < cShowAgeMode; i++)
+ {
+ SendMessage(GetDlgItem(hWnd, IDC_AGE_COMBOBOX), CB_ADDSTRING, 0, (LPARAM) TranslateTS(szShowAgeMode[i]));
+ }
+
+ for (i = 0; i < cSaveModule; i++)
+ {
+ SendMessage(GetDlgItem(hWnd, IDC_DEFAULT_MODULE), CB_ADDSTRING, 0, (LPARAM) TranslateTS(szSaveModule[i]));
+ }
+
+ for (i = 0; i < cPopupClick; i++)
+ {
+ SendMessage(GetDlgItem(hWnd, IDC_LEFT_CLICK), CB_ADDSTRING, 0, (LPARAM) TranslateTS(szPopupClick[i]));
+ SendMessage(GetDlgItem(hWnd, IDC_RIGHT_CLICK), CB_ADDSTRING, 0, (LPARAM) TranslateTS(szPopupClick[i]));
+ }
+
+ for (i = 0; i < cNotifyFor; i++)
+ {
+ SendMessage(GetDlgItem(hWnd, IDC_NOTIFYFOR), CB_ADDSTRING, 0, (LPARAM) TranslateTS(szNotifyFor[i]));
+ }
+
+ return i;
+}
+
+SIZE GetControlTextSize(HWND hCtrl)
+{
+ HDC hDC = GetDC(hCtrl);
+ HFONT font = (HFONT) SendMessage(hCtrl, WM_GETFONT, 0, 0);
+ HFONT oldFont = (HFONT) SelectObject(hDC, font);
+ const size_t maxSize = 2048;
+ TCHAR buffer[maxSize];
+ SIZE size;
+ GetWindowText(hCtrl, buffer, maxSize);
+ GetTextExtentPoint32(hDC, buffer, (int) _tcslen(buffer), &size);
+ SelectObject(hDC, oldFont);
+ ReleaseDC(hCtrl, hDC);
+ return size;
+}
+
+int EnlargeControl(HWND hCtrl, HWND hGroup, SIZE oldSize)
+{
+ SIZE size = GetControlTextSize(hCtrl);
+ int offset = 0;
+ RECT rect;
+ GetWindowRect(hCtrl, &rect);
+ offset = (rect.right - rect.left) - oldSize.cx;
+ SetWindowPos(hCtrl, HWND_TOP, 0, 0, size.cx + offset, oldSize.cy, SWP_NOMOVE);
+ SetWindowPos(hCtrl, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
+ //RedrawWindow(hCtrl, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_ERASENOW);
+
+ return 0;
+}
+
+TCHAR *strtrim(TCHAR *str)
+{
+ size_t i = 0;
+ size_t len = _tcslen(str);
+ while ((i < len) && (str[i] == _T(' '))) { i++; }
+ if (i)
+ {
+ memmove(str, str + i, len - i + 1);
+ len -= i;
+ }
+
+ while ((len > 0) && (str[--len] == _T(' '))) { str[len] = 0; }
+
+ return str;
+}
+
+INT_PTR CALLBACK DlgProcOptions(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ static int bInitializing = 0;
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ bInitializing = 1;
+
+ SIZE oldPopupsSize = GetControlTextSize(GetDlgItem(hWnd, IDC_USE_POPUPS));
+ SIZE oldClistIconSize = GetControlTextSize(GetDlgItem(hWnd, IDC_USE_CLISTICON));
+ SIZE oldDialogSize = GetControlTextSize(GetDlgItem(hWnd, IDC_USE_DIALOG));
+
+ TranslateDialogDefault(hWnd);
+
+ EnlargeControl(GetDlgItem(hWnd, IDC_USE_POPUPS), GetDlgItem(hWnd, IDC_POPUPS_STATIC), oldPopupsSize);
+ EnlargeControl(GetDlgItem(hWnd, IDC_USE_CLISTICON), GetDlgItem(hWnd, IDC_CLIST_STATIC), oldClistIconSize);
+ EnlargeControl(GetDlgItem(hWnd, IDC_USE_DIALOG), GetDlgItem(hWnd, IDC_DIALOG_STATIC), oldDialogSize);
+
+ AddInfoToComboBoxes(hWnd);
+
+ SendMessage(GetDlgItem(hWnd, IDC_FOREGROUND), CPM_SETDEFAULTCOLOUR, 0, FOREGROUND_COLOR);
+ SendMessage(GetDlgItem(hWnd, IDC_BACKGROUND), CPM_SETDEFAULTCOLOUR, 0, BACKGROUND_COLOR);
+
+ SendMessage(GetDlgItem(hWnd, IDC_FOREGROUND), CPM_SETCOLOUR, 0, commonData.foreground);
+ SendMessage(GetDlgItem(hWnd, IDC_BACKGROUND), CPM_SETCOLOUR, 0, commonData.background);
+
+ SendMessage(GetDlgItem(hWnd, IDC_ADVANCED_ICON), CB_SETCURSEL, commonData.clistIcon, 0);
+ SendMessage(GetDlgItem(hWnd, IDC_DEFAULT_MODULE), CB_SETCURSEL, commonData.cDefaultModule, 0);
+ SendMessage(GetDlgItem(hWnd, IDC_LEFT_CLICK), CB_SETCURSEL, commonData.lPopupClick, 0);
+ SendMessage(GetDlgItem(hWnd, IDC_RIGHT_CLICK), CB_SETCURSEL, commonData.rPopupClick, 0);
+ SendMessage(GetDlgItem(hWnd, IDC_NOTIFYFOR), CB_SETCURSEL, commonData.notifyFor, 0);
+
+ CreateToolTip(GetDlgItem(hWnd, IDC_POPUP_TIMEOUT), TranslateT("Set popup delay when notifying of upcoming birthdays.\nFormat: default delay [ | delay for birthdays occuring today]"), 400);
+
+ TCHAR buffer[1024];
+ _itot(commonData.daysInAdvance, buffer, 10);
+ SetWindowText(GetDlgItem(hWnd, IDC_DAYS_IN_ADVANCE), buffer);
+ _itot(commonData.checkInterval, buffer, 10);
+ SetWindowText(GetDlgItem(hWnd, IDC_CHECK_INTERVAL), buffer);
+ _sntprintf(buffer, 1024, _T("%d|%d"), commonData.popupTimeout, commonData.popupTimeoutToday);
+ SetWindowText(GetDlgItem(hWnd, IDC_POPUP_TIMEOUT), buffer);
+ _itot(commonData.cSoundNearDays, buffer, 10);
+ SetWindowText(GetDlgItem(hWnd, IDC_SOUND_NEAR_DAYS_EDIT), buffer);
+ _itot(commonData.cDlgTimeout, buffer, 10);
+ SetWindowText(GetDlgItem(hWnd, IDC_DLG_TIMEOUT), buffer);
+ _itot(commonData.daysAfter, buffer, 10);
+ SetWindowText(GetDlgItem(hWnd, IDC_DAYS_AFTER), buffer);
+
+ CheckDlgButton(hWnd, IDC_OPENINBACKGROUND, (commonData.bOpenInBackground) ? BST_CHECKED : BST_UNCHECKED);
+
+ CheckDlgButton(hWnd, IDC_NOBIRTHDAYS_POPUP, (commonData.bNoBirthdaysPopup) ? BST_CHECKED : BST_UNCHECKED);
+ //CheckDlgButton(hWnd, IDC_SHOW_CURRENT_AGE, (bShowCurrentAge) ? BST_CHECKED : BST_UNCHECKED);
+ SendMessage(GetDlgItem(hWnd, IDC_AGE_COMBOBOX), CB_SETCURSEL, commonData.cShowAgeMode, 0);
+
+ CheckDlgButton(hWnd, IDC_IGNORE_SUBCONTACTS, (commonData.bIgnoreSubcontacts) ? BST_CHECKED : BST_UNCHECKED);
+
+ CheckDlgButton(hWnd, IDC_ONCE_PER_DAY, (commonData.bOncePerDay) ? BST_CHECKED : BST_UNCHECKED);
+ EnableWindow(GetDlgItem(hWnd, IDC_CHECK_INTERVAL), !commonData.bOncePerDay);
+
+ CheckDlgButton(hWnd, IDC_USE_DIALOG, (commonData.bUseDialog) ? BST_CHECKED : BST_UNCHECKED);
+ EnableDialogGroup(hWnd, commonData.bUseDialog);
+
+ if (ServiceExists(MS_POPUP_ADDPOPUPEX))
+ {
+ CheckDlgButton(hWnd, IDC_USE_POPUPS, commonData.bUsePopups ? BST_CHECKED : BST_UNCHECKED);
+ EnablePopupsGroup(hWnd, commonData.bUsePopups);
+ }
+ else{
+ EnableWindow(GetDlgItem(hWnd, IDC_USE_POPUPS), FALSE);
+ EnablePopupsGroup(hWnd, FALSE);
+ }
+
+ if (ServiceExists(MS_CLIST_EXTRA_SET_ICON) && (!ServiceExists(MS_EXTRAICON_REGISTER)))
+ {
+ CheckDlgButton(hWnd, IDC_USE_CLISTICON, commonData.bUseClistIcon ? BST_CHECKED : BST_UNCHECKED);
+ EnableClistGroup(hWnd, commonData.bUseClistIcon);
+ }
+ else{
+ CheckDlgButton(hWnd, IDC_USE_CLISTICON, BST_CHECKED);
+ EnableWindow(GetDlgItem(hWnd, IDC_USE_CLISTICON), FALSE);
+ EnableClistGroup(hWnd, FALSE);
+ }
+ bInitializing = 0;
+
+ return TRUE;
+ }
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDC_CHECK_INTERVAL:
+ case IDC_POPUP_TIMEOUT:
+ case IDC_DAYS_IN_ADVANCE:
+ case IDC_DLG_TIMEOUT:
+ case IDC_SOUND_NEAR_DAYS_EDIT:
+ case IDC_DAYS_AFTER:
+ {
+ if ((HIWORD(wParam) == EN_CHANGE) && (!bInitializing))// || (HIWORD(wParam) == CBN_SELENDOK))
+ {
+ SendMessage(GetParent(hWnd), PSM_CHANGED, 0, 0);
+ }
+
+ break;
+ }
+
+ case IDC_USE_POPUPS:
+ case IDC_USE_CLISTICON:
+ case IDC_USE_DIALOG:
+ {
+ EnablePopupsGroup(hWnd, IsDlgButtonChecked(hWnd, IDC_USE_POPUPS));
+ EnableClistGroup(hWnd, IsDlgButtonChecked(hWnd, IDC_USE_CLISTICON));
+ EnableDialogGroup(hWnd, IsDlgButtonChecked(hWnd, IDC_USE_DIALOG));
+ RedrawWindow(GetDlgItem(hWnd, IDC_USE_POPUPS), NULL, NULL, RDW_ERASE | RDW_INVALIDATE);
+ RedrawWindow(GetDlgItem(hWnd, IDC_USE_CLISTICON), NULL, NULL, RDW_ERASE | RDW_INVALIDATE);
+ RedrawWindow(GetDlgItem(hWnd, IDC_USE_DIALOG), NULL, NULL, RDW_ERASE | RDW_INVALIDATE);
+ }//fallthrough
+
+ case IDC_FOREGROUND:
+ case IDC_BACKGROUND:
+ case IDC_ADVANCED_ICON:
+ case IDC_IGNORE_SUBCONTACTS:
+ case IDC_AGE_COMBOBOX:
+ case IDC_NOBIRTHDAYS_POPUP:
+ case IDC_DEFAULT_MODULE:
+ case IDC_LEFT_CLICK:
+ case IDC_RIGHT_CLICK:
+ case IDC_ONCE_PER_DAY:
+ case IDC_NOTIFYFOR:
+ {
+ SendMessage(GetParent(hWnd), PSM_CHANGED, 0, 0);
+ EnableWindow(GetDlgItem(hWnd, IDC_CHECK_INTERVAL), !IsDlgButtonChecked(hWnd, IDC_ONCE_PER_DAY));
+
+ break;
+ }
+
+ case IDC_PREVIEW:
+ {
+ HANDLE hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ int dtb, age;
+ dtb = rand() % 11; //0..10
+ age = rand() % 50 + 1; //1..50
+ PopupNotifyBirthday(hContact, dtb, age);
+
+ break;
+ }
+ }
+ break;
+ }
+ case WM_NOTIFY:
+ {
+ switch(((LPNMHDR)lParam)->idFrom)
+ {
+ case 0:
+ {
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case PSN_APPLY:
+ {
+ commonData.foreground = SendMessage(GetDlgItem(hWnd, IDC_FOREGROUND), CPM_GETCOLOUR, 0, 0);
+ commonData.background = SendMessage(GetDlgItem(hWnd, IDC_BACKGROUND), CPM_GETCOLOUR, 0, 0);
+ commonData.popupTimeout = POPUP_TIMEOUT;
+ commonData.popupTimeoutToday = POPUP_TIMEOUT;
+ commonData.clistIcon = SendMessage(GetDlgItem(hWnd, IDC_ADVANCED_ICON), CB_GETCURSEL, 0, 0);
+ int oldClistIcon = DBGetContactSettingByte(NULL, ModuleName, "AdvancedIcon", -1);
+ commonData.bUsePopups = IsDlgButtonChecked(hWnd, IDC_USE_POPUPS);
+ commonData.bUseClistIcon = IsDlgButtonChecked(hWnd, IDC_USE_CLISTICON);
+ commonData.bUseDialog = IsDlgButtonChecked(hWnd, IDC_USE_DIALOG);
+ commonData.bIgnoreSubcontacts = IsDlgButtonChecked(hWnd, IDC_IGNORE_SUBCONTACTS);
+ commonData.bNoBirthdaysPopup = IsDlgButtonChecked(hWnd, IDC_NOBIRTHDAYS_POPUP);
+ commonData.cShowAgeMode = SendMessage(GetDlgItem(hWnd, IDC_AGE_COMBOBOX), CB_GETCURSEL, 0, 0);
+ commonData.cDefaultModule = SendMessage(GetDlgItem(hWnd, IDC_DEFAULT_MODULE), CB_GETCURSEL, 0, 0);
+ commonData.lPopupClick = SendMessage(GetDlgItem(hWnd, IDC_LEFT_CLICK), CB_GETCURSEL, 0, 0);
+ commonData.rPopupClick = SendMessage(GetDlgItem(hWnd, IDC_RIGHT_CLICK), CB_GETCURSEL, 0, 0);
+ commonData.bOncePerDay = IsDlgButtonChecked(hWnd, IDC_ONCE_PER_DAY);
+ commonData.notifyFor = SendMessage(GetDlgItem(hWnd, IDC_NOTIFYFOR), CB_GETCURSEL, 0, 0);
+ commonData.bOpenInBackground = IsDlgButtonChecked(hWnd, IDC_OPENINBACKGROUND);
+
+ const int maxSize = 1024;
+ TCHAR buffer[maxSize];
+
+ GetWindowText(GetDlgItem(hWnd, IDC_DAYS_IN_ADVANCE), buffer, maxSize);
+ TCHAR *stop = NULL;
+ commonData.daysInAdvance = _tcstol(buffer, &stop, 10);
+
+ if (*stop) { commonData.daysInAdvance = DAYS_TO_NOTIFY; }
+
+ GetWindowText(GetDlgItem(hWnd, IDC_DAYS_AFTER), buffer, maxSize);
+ commonData.daysAfter = _tcstol(buffer, &stop, 10);
+
+ if (*stop) { commonData.daysAfter = DAYS_TO_NOTIFY_AFTER; }
+
+ GetWindowText(GetDlgItem(hWnd, IDC_CHECK_INTERVAL), buffer, maxSize);
+ commonData.checkInterval = _ttol(buffer);
+ if (!commonData.checkInterval) { commonData.checkInterval = CHECK_INTERVAL; }
+
+ GetWindowText(GetDlgItem(hWnd, IDC_POPUP_TIMEOUT), buffer, maxSize);
+ TCHAR *pos;
+ pos = _tcschr(buffer, _T('|'));
+ if (pos)
+ {
+ TCHAR tmp[128];
+ *pos = 0;
+ _tcscpy(tmp, buffer);
+ strtrim(tmp);
+ commonData.popupTimeout = _ttol(tmp);
+
+ _tcscpy(tmp, pos + 1);
+ strtrim(tmp);
+ commonData.popupTimeoutToday = _ttol(tmp);
+
+ }
+ else{
+ commonData.popupTimeout = commonData.popupTimeoutToday = _ttol(buffer);
+ }
+
+ GetWindowText(GetDlgItem(hWnd, IDC_SOUND_NEAR_DAYS_EDIT), buffer, maxSize);
+ //cSoundNearDays = _ttol(buffer);
+ commonData.cSoundNearDays = _tcstol(buffer, &stop, 10);
+ if (*stop) { commonData.cSoundNearDays = BIRTHDAY_NEAR_DEFAULT_DAYS; }
+
+ GetWindowText(GetDlgItem(hWnd, IDC_DLG_TIMEOUT), buffer, maxSize);
+ commonData.cDlgTimeout = _tcstol(buffer, &stop, 10);
+ if (*stop) { commonData.cDlgTimeout = POPUP_TIMEOUT; }
+
+ DBWriteContactSettingByte(NULL, ModuleName, "IgnoreSubcontacts", commonData.bIgnoreSubcontacts);
+ DBWriteContactSettingByte(NULL, ModuleName, "UsePopups", commonData.bUsePopups);
+ DBWriteContactSettingByte(NULL, ModuleName, "UseClistIcon", commonData.bUseClistIcon);
+ DBWriteContactSettingByte(NULL, ModuleName, "UseDialog", commonData.bUseDialog);
+ DBWriteContactSettingByte(NULL, ModuleName, "AdvancedIcon", commonData.clistIcon);
+ DBWriteContactSettingWord(NULL, ModuleName, "CheckInterval", commonData.checkInterval);
+ DBWriteContactSettingWord(NULL, ModuleName, "DaysInAdvance", commonData.daysInAdvance);
+ DBWriteContactSettingWord(NULL, ModuleName, "DaysAfter", commonData.daysAfter);
+ DBWriteContactSettingWord(NULL, ModuleName, "PopupTimeout", commonData.popupTimeout);
+ DBWriteContactSettingWord(NULL, ModuleName, "PopupTimeoutToday", commonData.popupTimeoutToday);
+
+ DBWriteContactSettingByte(NULL, ModuleName, "ShowCurrentAge", commonData.cShowAgeMode);
+ DBWriteContactSettingByte(NULL, ModuleName, "NoBirthdaysPopup", commonData.bNoBirthdaysPopup);
+
+ DBWriteContactSettingByte(NULL, ModuleName, "OpenInBackground", commonData.bOpenInBackground);
+
+ DBWriteContactSettingByte(NULL, ModuleName, "SoundNearDays", commonData.cSoundNearDays);
+
+ DBWriteContactSettingByte(NULL, ModuleName, "DefaultModule", commonData.cDefaultModule);
+
+ DBWriteContactSettingByte(NULL, ModuleName, "PopupLeftClick", commonData.lPopupClick);
+ DBWriteContactSettingByte(NULL, ModuleName, "PopupRightClick", commonData.rPopupClick);
+
+ DBWriteContactSettingDword(NULL, ModuleName, "Foreground", commonData.foreground);
+ DBWriteContactSettingDword(NULL, ModuleName, "Background", commonData.background);
+
+ DBWriteContactSettingByte(NULL, ModuleName, "OncePerDay", commonData.bOncePerDay);
+
+ DBWriteContactSettingWord(NULL, ModuleName, "DlgTimeout", commonData.cDlgTimeout);
+
+ DBWriteContactSettingByte(NULL, ModuleName, "NotifyFor", commonData.notifyFor);
+
+ RefreshAllContactListIcons(oldClistIcon);
+
+ UpdateTimers(); //interval might get changed
+ break;
+ }
+ }
+ break;
+ }
+ }
+ break;
+ }
+ }
+ return 0;
+}
+
+
+
+
+
+INT_PTR CALLBACK DlgProcAddBirthday(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hWnd);
+
+ SendMessage(hWnd, WM_SETICON, ICON_BIG, (LPARAM) hiAddBirthdayContact);
+ int i;
+ for (i = 0; i < cSaveModule; i++)
+ {
+ SendMessage(GetDlgItem(hWnd, IDC_COMPATIBILITY), CB_ADDSTRING, 0, (LPARAM) TranslateTS(szSaveModule[i]));
+ }
+ i = commonData.cDefaultModule; //DBGetContactSettingByte(NULL, ModuleName, "DefaultModule", 0);
+ SendMessage(GetDlgItem(hWnd, IDC_COMPATIBILITY), CB_SETCURSEL, i, 0);
+
+ break;
+ }
+
+ case WM_SHOWWINDOW:
+ {
+ int year, month, day;
+ TCHAR *szTooltipText = TranslateT("Please select the module where you want the date of birth to be saved.\r\n\"UserInfo\" is the default location.\r\nUse \"Protocol module\" to make the data visible in User Details.\n\"mBirthday module\" uses the same module as mBirthday plugin.");
+ TCHAR *szCurrentModuleTooltip = NULL;
+ HANDLE hContact = (HANDLE) GetWindowLongPtr(hWnd, GWLP_USERDATA);
+ const int maxSize = 2048;
+ TCHAR buffer[maxSize];
+ char protocol[256];
+ GetContactProtocol(hContact, protocol, sizeof(protocol));
+
+ TCHAR *name = GetContactName(hContact, protocol);
+ _stprintf(buffer, TranslateT("Set birthday for %s:"), name);
+ free(name);
+ SetWindowText(hWnd, buffer);
+ HWND hDate = GetDlgItem(hWnd, IDC_DATE);
+ int loc = GetContactDOB(hContact, year, month, day);
+ if (IsDOBValid(year, month, day))
+ {
+ SYSTEMTIME st = {0};
+ st.wDay = day;
+ st.wMonth = month;
+ st.wYear = year;
+ DateTime_SetSystemtime(hDate, GDT_VALID, &st);
+ }
+ else{
+ DateTime_SetSystemtime(hDate, GDT_NONE, NULL);
+ }
+ switch (loc)
+ {
+ case DOB_MBIRTHDAY:
+ {
+ DateTime_SetMonthCalColor(hDate, MCSC_TITLEBK, COLOR_MBIRTHDAY);
+ szCurrentModuleTooltip = _T("mBirthday");
+
+ break;
+ }
+
+ case DOB_PROTOCOL:
+ {
+ DateTime_SetMonthCalColor(hDate, MCSC_TITLEBK, COLOR_PROTOCOL);
+
+ _stprintf(buffer, TranslateT("%S protocol"), protocol);
+
+
+ szCurrentModuleTooltip = buffer;
+
+ break;
+ }
+
+ case DOB_BIRTHDAYREMINDER:
+ {
+ DateTime_SetMonthCalColor(hDate, MCSC_TITLEBK, COLOR_BIRTHDAYREMINDER);
+ szCurrentModuleTooltip = _T("Birthday Reminder");
+
+ break;
+ }
+
+ case DOB_USERINFO:
+ {
+ DateTime_SetMonthCalColor(hDate, MCSC_TITLEBK, COLOR_USERINFO);
+ szCurrentModuleTooltip = _T("UserInfo");
+
+ break;
+ }
+
+ case DOB_MICQBIRTHDAY:
+ {
+ DateTime_SetMonthCalColor(hDate, MCSC_TITLEBK, COLOR_MICQBIRTHDAY);
+ szCurrentModuleTooltip = _T("mICQBirthday");
+
+ break;
+ }
+
+ default:
+ {
+ szCurrentModuleTooltip = NULL;
+
+ break;
+ }
+ }
+ //CreateToolTip(GetDlgItem(hWnd, IDC_COMPATIBILITY), hWnd, szTooltipText);
+ CreateToolTip(GetDlgItem(hWnd, IDC_COMPATIBILITY), szTooltipText, 500);
+ if (szCurrentModuleTooltip)
+ {
+ CreateToolTip(hDate, szCurrentModuleTooltip, 400);
+ }
+
+ break;
+ }
+
+ case WM_DESTROY:
+ {
+ HANDLE hContact = (HANDLE) GetWindowLongPtr(hWnd, GWLP_USERDATA);
+ OnExtraImageApply((WPARAM) hContact, NULL); //the birthday might be changed, refresh icon.
+ WindowList_Remove(hAddBirthdayWndsList, hWnd);
+
+ break;
+ }
+
+ case WM_CLOSE:
+ {
+ DestroyWindow(hWnd);
+
+ break;
+ }
+
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDOK:
+ {
+ SYSTEMTIME st;
+ HANDLE hContact = (HANDLE) GetWindowLongPtr(hWnd, GWLP_USERDATA);
+ HWND hDate = GetDlgItem(hWnd, IDC_DATE);
+ if (DateTime_GetSystemtime(hDate, &st) == GDT_VALID)
+ {
+ int mode = SendMessage(GetDlgItem(hWnd, IDC_COMPATIBILITY), CB_GETCURSEL, 0, 0); //SAVE modes in date_utils.h are synced
+ SaveBirthday(hContact, st.wYear, st.wMonth, st.wDay, mode);
+ }
+ else{
+ SaveBirthday(hContact, 0, 0, 0, SAVE_MODE_DELETEALL);
+ }
+ if (hBirthdaysDlg != NULL)
+ {
+ SendMessage(hBirthdaysDlg, WWIM_UPDATE_BIRTHDAY, (WPARAM) hContact, NULL);
+ }
+
+ SendMessage(hWnd, WM_CLOSE, 0, 0);
+
+ break;
+ }
+ }
+
+ break;
+ }
+
+ }
+
+ return FALSE;
+}
+
+void AddAnchorWindowToDeferList(HDWP &hdWnds, HWND window, RECT *rParent, WINDOWPOS *wndPos, int anchors)
+{
+ RECT rChild = AnchorCalcPos(window, rParent, wndPos, anchors);
+ hdWnds = DeferWindowPos(hdWnds, window, HWND_NOTOPMOST, rChild.left, rChild.top, rChild.right - rChild.left, rChild.bottom - rChild.top, SWP_NOZORDER);
+}
+
+
+#define NA TranslateT("N/A")
+
+TCHAR *GetBirthdayModule(int module, HANDLE hContact, TCHAR *birthdayModule, int size)
+{
+ switch (module)
+ {
+ case DOB_MBIRTHDAY:
+ {
+ _tcsncpy(birthdayModule, _T("mBirthday"), size);
+
+ break;
+ }
+
+ case DOB_PROTOCOL:
+ {
+ char protocol[512];
+ GetContactProtocol(hContact, protocol, sizeof(protocol));
+
+ _sntprintf(birthdayModule, size, TranslateT("%S protocol"), protocol);
+
+
+ break;
+ }
+
+ case DOB_BIRTHDAYREMINDER:
+ {
+ _tcsncpy(birthdayModule, _T("Birthday Reminder"), size);
+
+ break;
+ }
+
+ case DOB_USERINFO:
+ {
+ _tcsncpy(birthdayModule, _T("UserInfo"), size);
+
+ break;
+ }
+
+ case DOB_MICQBIRTHDAY:
+ {
+ _tcsncpy(birthdayModule, _T("mICQBirthday"), size);
+
+ break;
+ }
+
+ default:
+ {
+ _tcsncpy(birthdayModule, NA, size);
+
+ break;
+ }
+ }
+ return birthdayModule;
+}
+
+static int lastColumn = -1;
+
+struct BirthdaysSortParams{
+ HWND hList;
+ int column;
+};
+
+INT_PTR CALLBACK BirthdaysCompare(LPARAM lParam1, LPARAM lParam2, LPARAM myParam)
+{
+ BirthdaysSortParams params = *(BirthdaysSortParams *) myParam;
+ const int maxSize = 1024;
+ TCHAR text1[maxSize];
+ TCHAR text2[maxSize];
+ long value1, value2;
+ ListView_GetItemText(params.hList, (int) lParam1, params.column, text1, maxSize);
+ ListView_GetItemText(params.hList, (int) lParam2, params.column, text2, maxSize);
+
+ int res = 0;
+
+ if ((params.column == 2) || (params.column == 4))
+ {
+ TCHAR *err1, *err2;
+ value1 = _tcstol(text1, &err1, 10);
+ value2 = _tcstol(text2, &err2, 10);
+
+ if ((err1[0]) || (err2[0]))
+ {
+ res = (err1[0]) ? 1 : -1;
+ }
+ else{
+ if (value1 < value2)
+ {
+ res = -1;
+ }
+ else{
+ if (value1 == value2)
+ {
+ res = 0;
+ }
+ else{
+ res = 1;
+ }
+ }
+ }
+ }
+ else{
+ res = _tcsicmp(text1, text2);
+ }
+ res = (params.column == lastColumn) ? -res : res;
+ return res;
+}
+
+//only updates the birthday part of the list view entry. Won't update the protocol and the contact name (those shouldn't change anyway :))
+int UpdateBirthdayEntry(HWND hList, HANDLE hContact, int entry, int bShowAll, int bShowCurrentAge, int bAdd)
+{
+ const int maxSize = 2048;
+ TCHAR buffer[maxSize];
+
+ int age;
+ int dtb;
+ int year, month, day;
+ TCHAR *name;
+ int module;
+ char protocol[512];
+ LVITEM item = {0};
+
+ int currentYear;
+ int currentMonth;
+ int currentDay;
+
+ int res = entry;
+
+ if (bShowCurrentAge)
+ {
+ time_t now = Today();
+ struct tm *today = gmtime(&now);
+ currentDay = today->tm_mday + 1;
+ currentMonth = today->tm_mon + 1;
+ currentYear = today->tm_year;
+ }
+
+ item.mask = LVIF_TEXT | LVIF_PARAM;
+ item.iItem = entry;
+
+ module = GetContactDOB(hContact, year, month, day);
+ if ((bShowAll) || (IsDOBValid(year, month, day)))
+ {
+ lastColumn = -1; //list isn't sorted anymore
+ dtb = DaysToBirthday(Today(), year, month, day);
+ age = GetContactAge(hContact);
+ if (bShowCurrentAge)
+ {
+ if ((month > currentMonth) || ((month == currentMonth) && (day > currentDay))) //birthday still to come
+ {
+ age--;
+ }
+ }
+
+ item.lParam = (LPARAM) hContact;
+
+ GetContactProtocol(hContact, protocol, sizeof(protocol));
+
+ MultiByteToWideChar(CP_ACP, MB_USEGLYPHCHARS, protocol, -1, buffer, maxSize);
+
+ item.pszText = buffer;
+
+ if (bAdd)
+ {
+ ListView_InsertItem(hList, &item);
+ }
+ else{
+ ListView_SetItemText(hList, entry, 0, buffer);
+ }
+
+ name = GetContactName(hContact, protocol);
+ ListView_SetItemText(hList, entry, 1, name);
+ free(name);
+
+ if ((dtb <= 366) && (dtb >= 0))
+ {
+ _stprintf(buffer, _T("%d"), dtb);
+ }
+ else{
+ _stprintf(buffer, NA);
+ }
+ ListView_SetItemText(hList, entry, 2, buffer);
+ if ((year != 0) && (month != 0) && (day != 0))
+ {
+ _stprintf(buffer, _T("%04d-%02d-%02d"), year, month, day);
+ }
+ else{
+ _stprintf(buffer, NA);
+ }
+ ListView_SetItemText(hList, entry, 3, buffer);
+
+ if (age < 400) //hopefully noone lives longer than this :)
+ {
+ _stprintf(buffer, _T("%d"), age);
+ }
+ else{
+ _stprintf(buffer, NA);
+ }
+ ListView_SetItemText(hList, entry, 4, buffer);
+
+ GetBirthdayModule(module, hContact, buffer, maxSize);
+ ListView_SetItemText(hList, entry, 5, buffer);
+
+ res++;
+ }
+ else{
+ if ((!bShowAll) && (!bAdd))
+ {
+ ListView_DeleteItem(hList, entry);
+ }
+ }
+ return res;
+}
+
+INT_PTR CALLBACK BirthdaysListSubclassProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+ case WM_KEYUP:
+ {
+ if (wParam == VK_ESCAPE)
+ {
+ SendMessage(GetParent(hWnd), WM_CLOSE, 0, 0);
+ }
+ break;
+ }
+ case WM_SYSKEYDOWN:
+ {
+ if (wParam == 'X')
+ {
+ SendMessage(GetParent(hWnd), WM_CLOSE, 0, 0);
+ }
+ break;
+ }
+ case WM_LBUTTONDBLCLK:
+ {
+ int i;
+ int count = ListView_GetItemCount(hWnd);
+ HANDLE hContact;
+ LVITEM item = {0};
+// char buffer[1024];
+// item.pszText = buffer;
+// item.cchTextMax = sizeof(buffer);
+ item.mask = LVIF_PARAM;
+ for (i = 0; i < count; i++)
+ {
+ if (ListView_GetItemState(hWnd, i, LVIS_SELECTED))
+ {//TODO
+ item.iItem = i;
+ ListView_GetItem(hWnd, &item);
+ hContact = (HANDLE) item.lParam;
+ CallService(MS_WWI_ADD_BIRTHDAY, (WPARAM) hContact, 0);
+ }
+ }
+ break;
+ }
+ }
+ return CallWindowProc(OldBirthdaysListProc, hWnd, msg, wParam, lParam);
+}
+
+void SetBirthdaysCount(HWND hWnd)
+{
+ int count = ListView_GetItemCount((GetDlgItem(hWnd, IDC_BIRTHDAYS_LIST)));
+ TCHAR title[512];
+ _stprintf(title, TranslateT("Birthday list (%d)"), count);
+ SetWindowText(hWnd, title);
+}
+
+int LoadBirthdays(HWND hWnd, int bShowAll)
+{
+ HANDLE hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ HWND hList = GetDlgItem(hWnd, IDC_BIRTHDAYS_LIST);
+ //int bShowCurrentAge = DBGetContactSettingByte(NULL, ModuleName, "ShowCurrentAge", 0);
+
+ ListView_DeleteAllItems(hList);
+
+ int count = 0;
+ while (hContact)
+ {
+ count = UpdateBirthdayEntry(hList, hContact, count, bShowAll, commonData.cShowAgeMode, 1);
+
+ hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0);
+ }
+ SetBirthdaysCount(hWnd);
+
+ return 0;
+}
+
+INT_PTR CALLBACK DlgProcBirthdays(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault(hWnd);
+ SendMessage(hWnd, WM_SETICON, ICON_BIG, (LPARAM) hiListMenu);
+ HWND hList = GetDlgItem(hWnd, IDC_BIRTHDAYS_LIST);
+
+ ListView_SetExtendedListViewStyleEx(hList, LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT);
+
+ OldBirthdaysListProc = (WNDPROC) SetWindowLongPtr(hList, GWLP_WNDPROC, (LONG_PTR) BirthdaysListSubclassProc);
+
+ LVCOLUMN col;
+ col.mask = LVCF_TEXT | LVCF_WIDTH;
+ col.pszText = TranslateT("Protocol");
+ col.cx = 80;
+ ListView_InsertColumn(hList, 0, &col);
+ col.pszText = TranslateT("Contact");
+ col.cx = 180;
+ ListView_InsertColumn(hList, 1, &col);
+ col.pszText = TranslateT("DTB");
+ col.cx = 50;
+ ListView_InsertColumn(hList, 2, &col);
+ col.pszText = TranslateT("Birthday");
+ col.cx = 80;
+ ListView_InsertColumn(hList, 3, &col);
+ col.pszText = TranslateT("Age");
+ col.cx = 50;
+ ListView_InsertColumn(hList, 4, &col);
+ col.pszText = TranslateT("Module");
+ col.cx = 110;
+ ListView_InsertColumn(hList, 5, &col);
+
+ LoadBirthdays(hWnd, 0);
+ int column = DBGetContactSettingByte(NULL, ModuleName, "SortColumn", 0);
+
+ BirthdaysSortParams params = {0};
+ params.hList = GetDlgItem(hWnd, IDC_BIRTHDAYS_LIST);
+ params.column = column;
+ ListView_SortItemsEx(params.hList, BirthdaysCompare, (LPARAM) &params);
+
+ Utils_RestoreWindowPosition(hWnd,NULL,ModuleName,"BirthdayList");
+
+ return TRUE;
+ break;
+ }
+
+ case WM_DESTROY:
+ {
+ hBirthdaysDlg = NULL;
+ Utils_SaveWindowPosition(hWnd,NULL,ModuleName,"BirthdayList");
+ lastColumn = -1;
+
+ break;
+ }
+
+ case WM_CLOSE:
+ {
+ DestroyWindow(hWnd);
+
+ break;
+ }
+
+ case WWIM_UPDATE_BIRTHDAY:
+ {//wParam = hContact
+ HWND hList = GetDlgItem(hWnd, IDC_BIRTHDAYS_LIST);
+ HANDLE hContact = (HANDLE) wParam;
+ int i;
+ int count = ListView_GetItemCount(hList);
+ //int bShowCurrentAge = DBGetContactSettingByte(NULL, ModuleName, "ShowCurrentAge", 0);
+ LVITEM item = {0};
+ int found = 0;
+
+ item.mask = LVIF_PARAM;
+ for (i = 0; (i < count) && (!found); i++)
+ {
+ item.iItem = i;
+ ListView_GetItem(hList, &item);
+ if (hContact == (HANDLE) item.lParam)
+ {
+ UpdateBirthdayEntry(hList, hContact, i, IsDlgButtonChecked(hWnd, IDC_SHOW_ALL), commonData.cShowAgeMode, 0);
+ found = 1;
+ }
+ }
+ if (!found)
+ {
+ UpdateBirthdayEntry(hList, hContact, count, IsDlgButtonChecked(hWnd, IDC_SHOW_ALL), commonData.cShowAgeMode, 1);
+ }
+
+ SetBirthdaysCount(hWnd);
+
+ break;
+ }
+
+ case WM_WINDOWPOSCHANGING:
+ {
+ HDWP hdWnds = BeginDeferWindowPos(2);
+ RECT rParent;
+ WINDOWPOS *wndPos = (WINDOWPOS *) lParam;
+ GetWindowRect(hWnd, &rParent);
+
+ if (wndPos->cx < MIN_BIRTHDAYS_WIDTH)
+ {
+ wndPos->cx = MIN_BIRTHDAYS_WIDTH;
+ }
+ if (wndPos->cy < MIN_BIRTHDAYS_HEIGHT)
+ {
+ wndPos->cy = MIN_BIRTHDAYS_HEIGHT;
+ }
+ AddAnchorWindowToDeferList(hdWnds, GetDlgItem(hWnd, IDC_CLOSE), &rParent, wndPos, ANCHOR_RIGHT | ANCHOR_BOTTOM);
+ AddAnchorWindowToDeferList(hdWnds, GetDlgItem(hWnd, IDC_SHOW_ALL), &rParent, wndPos, ANCHOR_LEFT | ANCHOR_BOTTOM);
+ AddAnchorWindowToDeferList(hdWnds, GetDlgItem(hWnd, IDC_BIRTHDAYS_LIST), &rParent, wndPos, ANCHOR_ALL);
+
+ EndDeferWindowPos(hdWnds);
+
+ break;
+ }
+
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDC_CLOSE:
+ {
+ SendMessage(hWnd, WM_CLOSE, 0, 0);
+
+ break;
+ }
+ case IDC_SHOW_ALL:
+ {
+ LoadBirthdays(hWnd, IsDlgButtonChecked(hWnd, IDC_SHOW_ALL));
+
+ break;
+ }
+ }
+ break;
+ }
+
+ case WM_NOTIFY:
+ {
+ switch (((LPNMHDR) lParam)->idFrom)
+ {
+ case IDC_BIRTHDAYS_LIST:
+ {
+ switch (((LPNMHDR)lParam)->code)
+ {
+ case LVN_COLUMNCLICK:
+ {
+ LPNMLISTVIEW lv = (LPNMLISTVIEW) lParam;
+ int column = lv->iSubItem;
+ DBWriteContactSettingByte(NULL, ModuleName, "SortColumn", column);
+ BirthdaysSortParams params = {0};
+ params.hList = GetDlgItem(hWnd, IDC_BIRTHDAYS_LIST);
+ params.column = column;
+ ListView_SortItemsEx(params.hList, BirthdaysCompare, (LPARAM) &params);
+ lastColumn = (params.column == lastColumn) ? -1 : params.column;
+
+ break;
+ }
+ }
+
+ break;
+ }
+ }
+
+ break;
+ }
+ }
+ return 0;
+}
+
+
+INT_PTR CALLBACK UpcomingCompare(LPARAM lParam1, LPARAM lParam2, LPARAM myParam)
+{
+ HWND hList = GetDlgItem(hUpcomingDlg, IDC_UPCOMING_LIST);
+ LVITEM item = {0};
+ item.iItem = (int) lParam1;
+ item.mask = LVIF_PARAM;
+ ListView_GetItem(hList, &item);
+ int dtb1 = item.lParam;
+
+ item.iItem = (int) lParam2;
+ ListView_GetItem(hList, &item);
+ int dtb2 = item.lParam;
+
+ if (dtb1 != dtb2)
+ {
+ return (dtb1 > dtb2) ? 1 : -1;
+ }
+
+ return 0;
+}
+
+INT_PTR CALLBACK DlgProcUpcoming(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ static int timeout;
+ switch (msg)
+ {
+ case WM_INITDIALOG:
+ {
+ timeout = commonData.cDlgTimeout;
+ TranslateDialogDefault(hWnd);
+ SendMessage(hWnd, WM_SETICON, ICON_BIG, (LPARAM) hiListMenu);
+ HWND hList = GetDlgItem(hWnd, IDC_UPCOMING_LIST);
+
+ ListView_SetExtendedListViewStyleEx(hList, LVS_EX_FULLROWSELECT, LVS_EX_FULLROWSELECT);
+
+ LVCOLUMN col;
+ col.mask = LVCF_TEXT | LVCF_WIDTH;
+ col.pszText = TranslateT("Contact");
+ col.cx = 300;
+ ListView_InsertColumn(hList, 0, &col);
+ col.pszText = TranslateT("Age");
+ col.cx = 60;
+ ListView_InsertColumn(hList, 1, &col);
+
+ if (timeout > 0)
+ {
+ SetTimer(hWnd, UPCOMING_TIMER_ID, 1000, NULL);
+ }
+
+ return TRUE;
+ break;
+ }
+
+ case WM_TIMER:
+ {
+ const int MAX_SIZE = 512;
+ TCHAR buffer[MAX_SIZE];
+ _stprintf(buffer, (timeout != 2) ? TranslateT("Closing in %d seconds") : TranslateT("Closing in %d second"), --timeout);
+ SetWindowText(GetDlgItem(hWnd, IDC_CLOSE), buffer);
+
+ if (timeout <= 0)
+ {
+ SendMessage(hWnd, WM_CLOSE, 0, 0);
+ }
+
+ break;
+ }
+
+ case WM_CLOSE:
+ {
+ DestroyWindow(hWnd);
+
+ break;
+ }
+
+ case WM_DESTROY:
+ {
+ hUpcomingDlg = NULL;
+ KillTimer(hWnd, UPCOMING_TIMER_ID);
+
+ break;
+ }
+
+ case WWIM_ADD_UPCOMING_BIRTHDAY:
+ {
+ PUpcomingBirthday data = (PUpcomingBirthday) wParam;
+
+ HWND hList = GetDlgItem(hWnd, IDC_UPCOMING_LIST);
+ LVITEM item = {0};
+ int index = ListView_GetItemCount(hList);
+ item.iItem = index;
+ item.mask = LVIF_PARAM | LVIF_TEXT;
+ //item.lParam = (LPARAM) data->hContact;
+ item.lParam = (LPARAM) data->dtb;
+ item.pszText = data->message;
+ ListView_InsertItem(hList, &item);
+
+ TCHAR buffer[512];
+ mir_sntprintf(buffer, 512, _T("%d"), data->age);
+ ListView_SetItemText(hList, index, 1, buffer);
+
+ ListView_SortItemsEx(hList, UpcomingCompare, NULL);
+
+ break;
+ }
+
+ case WM_COMMAND:
+ {
+ switch (LOWORD(wParam))
+ {
+ case IDC_CLOSE:
+ {
+ SendMessage(hWnd, WM_CLOSE, 0, 0);
+
+ break;
+ }
+ }
+
+ break;
+ }
+ }
+
+ return 0;
+}
+
+DWORD WINAPI OpenMessageWindowThread(void *data)
+{
+ HANDLE hContact = (HANDLE) data;
+ CallServiceSync(MS_MSG_SENDMESSAGE, (WPARAM) hContact, 0);
+ CallServiceSync("SRMsg/LaunchMessageWindow", (WPARAM) hContact, 0);
+
+ return 0;
+}
+
+int HandlePopupClick(HWND hWnd, int action)
+{
+ switch (action)
+ {
+ case 2: //OPEN MESSAGE WINDOW
+ {
+ HANDLE hContact = (HANDLE) PUGetContact(hWnd);
+ if (hContact)
+ {
+ DWORD threadID;
+ HANDLE thread = CreateThread(NULL, NULL, OpenMessageWindowThread, hContact, 0, &threadID);
+ }
+
+ }//fallthrough
+
+ case 1: //DISMISS
+ {
+ PUDeletePopUp(hWnd);
+
+ break;
+ }
+
+ case 0: //NOTHING
+ default:
+ {
+
+ break;
+ }
+
+ }
+
+ return 0;
+}
+
+INT_PTR CALLBACK DlgProcPopup(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
+{
+ switch (msg)
+ {
+ case WM_COMMAND:
+ {
+ switch (HIWORD(wParam))
+ {
+ case STN_CLICKED:
+ {
+ HandlePopupClick(hWnd, commonData.lPopupClick);
+
+ break;
+ }
+ }
+ break;
+ }
+
+ case WM_CONTEXTMENU:
+ {
+ HandlePopupClick(hWnd, commonData.rPopupClick);
+
+ break;
+ }
+ }
+
+ return DefWindowProc(hWnd, msg, wParam, lParam);
+} \ No newline at end of file
diff --git a/plugins/WhenWasIt/src/dlg_handlers.h b/plugins/WhenWasIt/src/dlg_handlers.h
new file mode 100644
index 0000000000..10e1b1ff2b
--- /dev/null
+++ b/plugins/WhenWasIt/src/dlg_handlers.h
@@ -0,0 +1,45 @@
+/*
+WhenWasIt (birthday reminder) plugin for Miranda IM
+
+Copyright © 2006 Cristian Libotean
+
+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 M_WWI_DIALOG_HANDLERS_H
+#define M_WWI_DIALOG_HANDLERS_H
+
+#define FOREGROUND_COLOR RGB(0, 64, 128)
+#define BACKGROUND_COLOR RGB(255, 255, 255)
+
+#define POPUP_TIMEOUT 30
+
+#define CHECK_INTERVAL 12
+
+#define DAYS_TO_NOTIFY 9
+#define DAYS_TO_NOTIFY_AFTER 0
+
+#define CLIST_ICON 4
+
+#define WWIM_UPDATE_BIRTHDAY (WM_USER + 101)
+#define WWIM_ADD_UPCOMING_BIRTHDAY (WM_USER + 102)
+
+INT_PTR CALLBACK DlgProcOptions(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+INT_PTR CALLBACK DlgProcBirthdays(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+INT_PTR CALLBACK DlgProcAddBirthday(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+INT_PTR CALLBACK DlgProcUpcoming(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+INT_PTR CALLBACK DlgProcPopup(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+#endif //M_WWI_DIALOG_HANDLERS_H \ No newline at end of file
diff --git a/plugins/WhenWasIt/src/events.cpp b/plugins/WhenWasIt/src/events.cpp
new file mode 100644
index 0000000000..70dc0ffee4
--- /dev/null
+++ b/plugins/WhenWasIt/src/events.cpp
@@ -0,0 +1,38 @@
+/*
+WhenWasIt (birthday reminder) plugin for Miranda IM
+
+Copyright © 2006 Cristian Libotean
+
+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 "commonheaders.h"
+#include "events.h"
+
+HANDLE heContactSendMessage;
+
+int CreateEvents()
+{
+ heContactSendMessage = CreateHookableEvent(ME_WWI_SENDMESSAGE);
+
+ return 0;
+}
+
+int DestroyEvents()
+{
+ DestroyHookableEvent(heContactSendMessage);
+
+ return 0;
+} \ No newline at end of file
diff --git a/plugins/WhenWasIt/src/events.h b/plugins/WhenWasIt/src/events.h
new file mode 100644
index 0000000000..8d63e59630
--- /dev/null
+++ b/plugins/WhenWasIt/src/events.h
@@ -0,0 +1,31 @@
+/*
+WhenWasIt (birthday reminder) plugin for Miranda IM
+
+Copyright © 2006 Cristian Libotean
+
+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 M_WWI_EVENTS_H
+#define M_WWI_EVENTS_H
+
+#define ME_WWI_SENDMESSAGE "WWI/ContactSendMessage"
+
+extern HANDLE heContactSendMessage;
+
+int CreateEvents();
+int DestroyEvents();
+
+#endif //M_WWI_EVENTS_H \ No newline at end of file
diff --git a/plugins/WhenWasIt/src/hooked_events.cpp b/plugins/WhenWasIt/src/hooked_events.cpp
new file mode 100644
index 0000000000..fda21c0aea
--- /dev/null
+++ b/plugins/WhenWasIt/src/hooked_events.cpp
@@ -0,0 +1,396 @@
+/*
+WhenWasIt (birthday reminder) plugin for Miranda IM
+
+Copyright © 2006-2011 Cristian Libotean
+
+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 "commonheaders.h"
+#include "hooked_events.h"
+
+#define DATE_CHANGE_CHECK_INTERVAL 20
+
+#define EXCLUDE_HIDDEN 1
+#define EXCLUDE_IGNORED 2
+
+#define HOST "http://eblis.tla.ro/projects"
+
+
+#define WHENWASIT_DATA "WhenWasIt%20unicode"
+
+
+#if defined(WIN64) || defined(_WIN64)
+#define WHENWASIT_VERSION_URL HOST "/miranda/WhenWasIt/updater/x64/WhenWasIt.html"
+#define WHENWASIT_UPDATE_URL HOST "/miranda/WhenWasIt/updater/x64/" WHENWASIT_DATA ".zip"
+#else
+#define WHENWASIT_VERSION_URL HOST "/miranda/WhenWasIt/updater/WhenWasIt.html"
+#define WHENWASIT_UPDATE_URL HOST "/miranda/WhenWasIt/updater/" WHENWASIT_DATA ".zip"
+#endif
+#define WHENWASIT_VERSION_PREFIX "WhenWasIt version "
+
+HANDLE hModulesLoaded;
+HANDLE hOptionsInitialize;
+HANDLE hIconsChanged;
+HANDLE hExtraIconListRebuild;
+HANDLE hExtraImageApply;
+HANDLE hContactSettingChanged;
+HANDLE hTopToolBarModuleLoaded;
+//HANDLE hContactSendMessage;
+
+HANDLE hmCheckBirthdays = NULL;
+HANDLE hmBirthdayList = NULL;
+HANDLE hmRefreshDetails = NULL;
+HANDLE hmAddChangeBirthday = NULL;
+HANDLE hmImportBirthdays = NULL;
+HANDLE hmExportBirthdays = NULL;
+
+UINT_PTR hCheckTimer = NULL;
+UINT_PTR hDateChangeTimer = NULL;
+
+int currentDay;
+
+int HookEvents()
+{
+ Log("%s", "Entering function " __FUNCTION__);
+ hModulesLoaded = HookEvent(ME_SYSTEM_MODULESLOADED, OnModulesLoaded);
+ hOptionsInitialize = HookEvent(ME_OPT_INITIALISE, OnOptionsInitialise);
+ Log("%s", "Leaving function " __FUNCTION__);
+
+ return 0;
+}
+
+int UnhookEvents()
+{
+ Log("%s", "Entering function " __FUNCTION__);
+ UnhookEvent(hModulesLoaded);
+ UnhookEvent(hOptionsInitialize);
+ UnhookEvent(hIconsChanged);
+ UnhookEvent(hExtraIconListRebuild);
+ UnhookEvent(hExtraImageApply);
+ UnhookEvent(hContactSettingChanged);
+ UnhookEvent(hTopToolBarModuleLoaded);
+
+ KillTimers();
+
+ Log("%s", "Leaving function " __FUNCTION__);
+
+ return 0;
+}
+
+int OnModulesLoaded(WPARAM wParam, LPARAM lParam)
+{
+ hIconsChanged = HookEvent(ME_SKIN2_ICONSCHANGED, OnIconsChanged);
+ hExtraIconListRebuild = HookEvent(ME_CLIST_EXTRA_LIST_REBUILD, OnExtraIconListRebuild);
+ hExtraImageApply = HookEvent(ME_CLIST_EXTRA_IMAGE_APPLY, OnExtraImageApply);
+ hContactSettingChanged = HookEvent(ME_DB_CONTACT_SETTINGCHANGED, OnContactSettingChanged);
+ hTopToolBarModuleLoaded = HookEvent(ME_TTB_MODULELOADED, OnTopToolBarModuleLoaded);
+
+ SkinAddNewSoundEx(BIRTHDAY_NEAR_SOUND, LPGEN("WhenWasIt"), LPGEN("Birthday near"));
+ SkinAddNewSoundEx(BIRTHDAY_TODAY_SOUND, LPGEN("WhenWasIt"), LPGEN("Birthday today"));
+
+ RebuildAdvIconList();
+
+ UpdateTimers();
+ CLISTMENUITEM cl = {0};
+ cl.cbSize = sizeof(CLISTMENUITEM);
+ cl.hIcon = hiCheckMenu;
+ cl.position = 10000000;
+ cl.pszService = MS_WWI_CHECK_BIRTHDAYS;
+ cl.pszName = "Check for birthdays";
+ cl.pszPopupName = "Birthdays (When Was It)";
+ hmCheckBirthdays = Menu_AddMainMenuItem(&cl);
+
+ cl.pszService = MS_WWI_LIST_SHOW;
+ cl.pszName = "Birthday list";
+ cl.hIcon = hiListMenu;
+ hmBirthdayList = Menu_AddMainMenuItem(&cl);
+
+ cl.pszService = MS_WWI_REFRESH_USERDETAILS;
+ cl.position = 10100000;
+ cl.pszName = "Refresh user details";
+ cl.hIcon = hiRefreshUserDetails;
+ hmRefreshDetails = Menu_AddMainMenuItem(&cl);
+
+ cl.pszService = MS_WWI_IMPORT_BIRTHDAYS;
+ cl.position = 10200000;
+ cl.pszName = "Import birthdays";
+ cl.hIcon = hiImportBirthdays;
+ hmImportBirthdays = Menu_AddMainMenuItem(&cl);
+
+ cl.pszService = MS_WWI_EXPORT_BIRTHDAYS;
+ cl.pszName = "Export birthdays";
+ cl.hIcon = hiExportBirthdays;
+ hmExportBirthdays = Menu_AddMainMenuItem(&cl);
+
+ cl.pszService = MS_WWI_ADD_BIRTHDAY;
+ cl.position = 10000000;
+ cl.hIcon = hiAddBirthdayContact;
+ cl.pszName = "Add/change user &birthday";
+ hmAddChangeBirthday = Menu_AddContactMenuItem(&cl);
+
+ // Register hotkeys
+ HOTKEYDESC hotkey = {0};
+ hotkey.cbSize = sizeof(hotkey);
+ hotkey.pszSection = LPGEN("Birthdays");
+
+ hotkey.pszName = "wwi_birthday_list";
+ hotkey.pszDescription = LPGEN("Birthday list");
+ hotkey.pszService = MS_WWI_LIST_SHOW;
+ Hotkey_Register(&hotkey);
+
+ hotkey.pszName = "wwi_check_birthdays";
+ hotkey.pszDescription = LPGEN("Check for birthdays");
+ hotkey.pszService = MS_WWI_CHECK_BIRTHDAYS;
+ Hotkey_Register(&hotkey);
+
+ return 0;
+}
+
+int OnTopToolBarModuleLoaded(WPARAM wParam, LPARAM lParam)
+{
+ TTBButton ttb = {0};
+ ttb.cbSize = sizeof(ttb);
+ ttb.dwFlags = TTBBF_VISIBLE | TTBBF_SHOWTOOLTIP;
+ ttb.pszService = MS_WWI_CHECK_BIRTHDAYS;
+ ttb.hIconUp = hiCheckMenu;
+ ttb.name = ttb.pszTooltipUp = LPGEN("Check for birthdays");
+ TopToolbar_AddButton(&ttb);
+ return 0;
+}
+
+int OnOptionsInitialise(WPARAM wParam, LPARAM lParam)
+{
+ OPTIONSDIALOGPAGE odp = {0};
+
+ odp.cbSize = sizeof(odp);
+ odp.position = 100000000;
+ odp.hInstance = hInstance;
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_WWI);
+ odp.pszTitle = LPGEN("When Was It");
+ odp.pszGroup = LPGEN("Contact List");
+ odp.groupPosition = 910000000;
+ odp.flags = ODPF_BOLDGROUPS;
+ odp.pfnDlgProc = DlgProcOptions;
+ Options_AddPage(wParam, &odp);
+
+ return 0;
+}
+
+void UpdateMenuItems()
+{
+ CLISTMENUITEM cl = {0};
+ cl.cbSize = sizeof(CLISTMENUITEM);
+ cl.flags = CMIM_ICON;
+ cl.hIcon = hiCheckMenu;
+ int res = CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM) hmCheckBirthdays, (LPARAM) &cl);
+
+ cl.hIcon = hiListMenu;
+ res = CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM) hmBirthdayList, (LPARAM) &cl);
+
+ cl.hIcon = hiRefreshUserDetails;
+ res = CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM) hmRefreshDetails, (LPARAM) &cl);
+
+ cl.hIcon = hiAddBirthdayContact;
+ res = CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM) hmAddChangeBirthday, (LPARAM) &cl);
+
+ cl.hIcon = hiImportBirthdays;
+ res = CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM) hmImportBirthdays, (LPARAM) &cl);
+
+ cl.hIcon = hiExportBirthdays;
+ res = CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM) hmExportBirthdays, (LPARAM) &cl);
+}
+
+int OnIconsChanged(WPARAM wParam, LPARAM lParam)
+{
+ GetIcons();
+ UpdateMenuItems();
+
+ return 0;
+}
+
+int OnContactSettingChanged(WPARAM wParam, LPARAM lParam)
+{
+ DBCONTACTWRITESETTING *dw = (DBCONTACTWRITESETTING *) lParam;
+ //static HANDLE oldContact = NULL;
+ DBVARIANT dv = dw->value;
+ if ((strcmp(dw->szModule, DUMMY_MODULE) == 0) && (strcmp(dw->szSetting, DUMMY_SETTING) == 0))
+ {
+ OnExtraImageApply(wParam, 0);
+ }
+ //oldContact = (HANDLE) wParam;
+
+ return 0;
+}
+
+int OnExtraIconListRebuild(WPARAM wParam, LPARAM lParam)
+{
+ RebuildAdvIconList();
+
+ return 0;
+}
+
+int OnExtraImageApply(WPARAM wParam, LPARAM lParam)
+{
+ HANDLE hContact = (HANDLE) wParam;
+ if ((hContact))
+ {
+ int count = CallService(MS_DB_CONTACT_GETCOUNT, 0, 0);
+ //int daysInAdvance = DBGetContactSettingWord(NULL, ModuleName, "DaysInAdvance", DAYS_TO_NOTIFY);
+ //int popupTimeout = DBGetContactSettingWord(NULL, ModuleName, "PopupTimeout", POPUP_TIMEOUT);
+ //DWORD foreground = DBGetContactSettingDword(NULL, ModuleName, "Foreground", FOREGROUND_COLOR);
+ //DWORD background = DBGetContactSettingDword(NULL, ModuleName, "Background", BACKGROUND_COLOR);
+ //int bUsePopups = DBGetContactSettingByte(NULL, ModuleName, "UsePopups", TRUE);
+ //int bUseClistIcon = DBGetContactSettingByte(NULL, ModuleName, "UseClistIcon", TRUE);
+ //int bUseDialog = DBGetContactSettingByte(NULL, ModuleName, "UseDialog", TRUE);
+ //int clistIcon = DBGetContactSettingByte(NULL, ModuleName, "AdvancedIcon", CLIST_ICON);
+ //int notifyFor = DBGetContactSettingByte(NULL, ModuleName, "NotifyFor", 0);
+ int hidden = DBGetContactSettingByte(hContact, "CList", "Hidden", 0);
+ int ignored = DBGetContactSettingDword(hContact, "Ignore", "Mask1", 0);
+ ignored = ((ignored & 0x3f) != 0) ? 1 : 0;
+ int ok = 1;
+ if (commonData.notifyFor & EXCLUDE_HIDDEN)
+ {
+ ok &= (hidden == 0);
+ }
+ if (commonData.notifyFor & EXCLUDE_IGNORED)
+ {
+ ok &= (ignored == 0);
+ }
+
+ int dtb;
+ int dab;
+ int caps = ServiceExists(MS_CLIST_EXTRA_ADD_ICON); // CallService(MS_CLUI_GETCAPS, 0, 0);
+
+ time_t today = Today();
+
+ if ((ok) && (((dtb = NotifyContactBirthday(hContact, today, commonData.daysInAdvance)) >= 0) || ((dab = NotifyMissedContactBirthday(hContact, today, commonData.daysAfter)) > 0)))
+ {
+ int age = GetContactAge(hContact);
+ DBWriteContactSettingByte(hContact, "UserInfo", "Age", age);
+
+ if ((bShouldCheckBirthdays) && (commonData.bUsePopups))
+ {
+ if (dtb >= 0)
+ {
+ bBirthdayFound = 1; //only set it if we're called from our CheckBirthdays service
+ PopupNotifyBirthday(hContact, dtb, age);
+ }
+ else if (dab > 0)
+ {
+ PopupNotifyMissedBirthday(hContact, dab, age);
+ }
+ }
+
+ if (bShouldCheckBirthdays)
+ {
+ if (dtb >= 0)
+ {
+ SoundNotifyBirthday(dtb);
+ }
+ }
+
+ if ((bShouldCheckBirthdays) && (commonData.bUseDialog))
+ {
+ if (dtb >= 0)
+ {
+ DialogNotifyBirthday(hContact, dtb, age);
+ }
+ else if (dab > 0)
+ {
+ DialogNotifyMissedBirthday(hContact, dab, age);
+ }
+ }
+
+ if ((caps > 0) && (commonData.bUseClistIcon)) //TODO
+ {
+ if (dtb >= 0)
+ {
+ ClistIconNotifyBirthday(hContact, dtb, commonData.clistIcon);
+ }
+ }
+ }
+ else{
+ if (caps > 0) //TODO
+ { //clear the icon
+ ClearClistIcon(hContact, commonData.clistIcon);
+ }
+ }
+ }
+
+ return 0;
+}
+
+int UpdateTimers()
+{
+ if (hCheckTimer)
+ {
+ KillTimer(NULL, hCheckTimer);
+ hCheckTimer = NULL;
+ }
+ long interval;
+ interval = DBGetContactSettingDword(NULL, ModuleName, "Interval", CHECK_INTERVAL);
+ interval *= 1000 * 60 * 60; //go from miliseconds to hours
+ hCheckTimer = SetTimer(NULL, 0, interval, (TIMERPROC) OnCheckTimer);
+ if (!hDateChangeTimer)
+ {
+ hDateChangeTimer = SetTimer(NULL, 0, 1000 * DATE_CHANGE_CHECK_INTERVAL, (TIMERPROC) OnDateChangeTimer);
+ }
+
+ return 0;
+}
+
+int KillTimers()
+{
+ Log("%s", "Entering function " __FUNCTION__);
+ if (hCheckTimer)
+ {
+ KillTimer(NULL, hCheckTimer);
+ hCheckTimer = NULL;
+ }
+ if (hDateChangeTimer)
+ {
+ KillTimer(NULL, hDateChangeTimer);
+ hDateChangeTimer = NULL;
+ }
+ Log("%s", "Leaving function " __FUNCTION__);
+
+ return 0;
+}
+
+VOID CALLBACK OnCheckTimer(HWND hWnd, UINT msg, UINT_PTR idEvent, DWORD dwTime)
+{
+ Log("%s", "Entering function " __FUNCTION__);
+ CheckBirthdaysService(0, 1);
+ Log("%s", "Leaving function " __FUNCTION__);
+}
+
+VOID CALLBACK OnDateChangeTimer(HWND hWnd, UINT msg, UINT_PTR idEvent, DWORD dwTime)
+{
+ SYSTEMTIME now;
+ //Log("%s", "Entering function " __FUNCTION__);
+ GetLocalTime(&now);
+ if (currentDay != now.wDay)
+ {
+ CheckBirthdaysService(0, 1);
+ }
+ //else{
+ // RefreshAllContactListIcons();
+ //}
+ currentDay = now.wDay;
+
+ //Log("%s", "Leaving function " __FUNCTION__);
+}
+
diff --git a/plugins/WhenWasIt/src/hooked_events.h b/plugins/WhenWasIt/src/hooked_events.h
new file mode 100644
index 0000000000..69c75f0531
--- /dev/null
+++ b/plugins/WhenWasIt/src/hooked_events.h
@@ -0,0 +1,49 @@
+/*
+WhenWasIt (birthday reminder) plugin for Miranda IM
+
+Copyright © 2006 Cristian Libotean
+
+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 M_WWI_HOOKED_EVENTS_H
+#define M_WWI_HOOKED_EVENTS_H
+
+#include "dlg_handlers.h"
+
+extern HANDLE hModulesLoaded;
+extern HANDLE hOptionsInitialise;
+
+extern UINT_PTR hCheckTimer;
+extern UINT_PTR hDateChangeTimer;
+
+int HookEvents();
+int UnhookEvents();
+
+int OnModulesLoaded(WPARAM wParam, LPARAM lParam);
+int OnTopToolBarModuleLoaded(WPARAM wParam, LPARAM lParam);
+int OnOptionsInitialise(WPARAM wParam, LPARAM lParam);
+int OnIconsChanged(WPARAM wParam, LPARAM lParam);
+int OnExtraIconListRebuild(WPARAM wParam, LPARAM lParam);
+int OnExtraImageApply(WPARAM wParam, LPARAM lParam);
+int OnContactSettingChanged(WPARAM wParam, LPARAM lParam);
+
+int UpdateTimers();
+int KillTimers();
+
+VOID CALLBACK OnCheckTimer(HWND hWnd, UINT msg, UINT_PTR idEvent, DWORD dwTime);
+VOID CALLBACK OnDateChangeTimer(HWND hWnd, UINT msg, UINT_PTR idEvent, DWORD dwTime);
+
+#endif \ No newline at end of file
diff --git a/plugins/WhenWasIt/src/icons.cpp b/plugins/WhenWasIt/src/icons.cpp
new file mode 100644
index 0000000000..0b24c21442
--- /dev/null
+++ b/plugins/WhenWasIt/src/icons.cpp
@@ -0,0 +1,216 @@
+/*
+WhenWasIt (birthday reminder) plugin for Miranda IM
+
+Copyright © 2006 Cristian Libotean
+
+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 "commonheaders.h"
+#include "icons.h"
+
+//HICON hiDlg = NULL;
+HICON hiMainMenu = NULL;
+HICON hiCheckMenu = NULL;
+HICON hiListMenu = NULL;
+HICON hiAddBirthdayContact = NULL;
+HICON hiRefreshUserDetails = NULL;
+
+HICON hiImportBirthdays = NULL;
+HICON hiExportBirthdays = NULL;
+
+const int cDTB = 10;
+HICON hiDTB[cDTB] = {NULL};
+HICON hiDTBMore = NULL;
+
+HANDLE hClistImages[cDTB + 1];
+
+HANDLE hWWIExtraIcons = (HANDLE) -1;
+
+#define GET_DTB_ICON(index) (hiDTB[index] = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_DTB ## index)))
+
+int LoadIcons()
+{
+ //hiDlgIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_BIRTHDAYS_DLG));
+ hiCheckMenu = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_CHECK));
+ hiListMenu = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_LIST));
+ hiAddBirthdayContact = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ADD));
+ hiRefreshUserDetails = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_REFRESH_USERDETAILS));
+
+ hiImportBirthdays = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_IMPORT_BIRTHDAYS));
+ hiExportBirthdays = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_EXPORT_BIRTHDAYS));
+
+ GET_DTB_ICON(0);
+ GET_DTB_ICON(1);
+ GET_DTB_ICON(2);
+ GET_DTB_ICON(3);
+ GET_DTB_ICON(4);
+ GET_DTB_ICON(5);
+ GET_DTB_ICON(6);
+ GET_DTB_ICON(7);
+ GET_DTB_ICON(8);
+ GET_DTB_ICON(9);
+ hiDTBMore = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_DTBMORE));
+
+ AddIcons();
+ GetIcons();
+
+ if (ServiceExists(MS_EXTRAICON_REGISTER))
+ hWWIExtraIcons = ExtraIcon_Register("WhenWasIt", Translate("WhenWasIt birthday reminder"), "MenuCheck", OnExtraIconListRebuild, OnExtraImageApply);
+
+ return 0;
+}
+
+HANDLE AddIcon(HICON icon, char *name, char *description)
+{
+ SKINICONDESC sid = {0};
+ sid.cbSize = sizeof(sid);
+ sid.pszSection = "WhenWasIt";
+ sid.cx = sid.cy = 16;
+ sid.pszDescription = description;
+ sid.pszName = name;
+ sid.hDefaultIcon = icon;
+ return Skin_AddIcon(&sid);
+}
+
+int AddIcons()
+{
+ AddIcon(hiCheckMenu, "MenuCheck", "Check birthdays menu item");
+ AddIcon(hiListMenu, "MenuList", "List birthdays menu item");
+ AddIcon(hiAddBirthdayContact, "AddBirthday", "Add/change birthday");
+ AddIcon(hiRefreshUserDetails, "RefreshUserDetails", "Refresh user details");
+
+ AddIcon(hiImportBirthdays, "ImportBirthdays", "Import birthdays");
+ AddIcon(hiExportBirthdays, "ExportBirthdays", "Export birthdays");
+
+ int i;
+ char name[1024];
+ char description[1024];
+ AddIcon(hiDTB[0], "DTB0", "Birthday today");
+ AddIcon(hiDTB[1], "DTB1", "1 day to birthday");
+ for (i = 2; i < cDTB; i++) {
+ sprintf(name, "DTB%d", i);
+ sprintf(description, "%d days to birthday", i);
+ AddIcon(hiDTB[i], name, description);
+ }
+ sprintf(description, "More than %d days to birthday", cDTB - 1);
+ AddIcon(hiDTBMore, "DTBMore", description);
+ return 0;
+}
+
+HICON GetIcon(char *name)
+{
+ return (HICON) CallService(MS_SKIN2_GETICON, 0, (LPARAM) name);
+}
+
+void FreeIcon(HICON &icon)
+{
+ DestroyIcon(icon);
+ icon = NULL;
+}
+
+void FreeIcons()
+{
+ static int bFreed = 0;
+ if (!bFreed)
+ {
+// FreeIcon(hiDlg);
+ FreeIcon(hiCheckMenu);
+ FreeIcon(hiListMenu);
+ FreeIcon(hiAddBirthdayContact);
+ FreeIcon(hiRefreshUserDetails);
+
+ FreeIcon(hiImportBirthdays);
+ FreeIcon(hiExportBirthdays);
+
+ int i;
+ for (i = 0; i < cDTB; i++)
+ {
+ FreeIcon(hiDTB[i]);
+ }
+ FreeIcon(hiDTBMore);
+ }
+ bFreed = 1; //only free them once (ours).
+}
+
+int GetIcons()
+{
+ if (ServiceExists(MS_SKIN2_GETICON))
+ {
+ //FreeIcons();
+// hiDlgIcon = Get("Dlg");
+ hiCheckMenu = GetIcon("MenuCheck");
+ hiListMenu = GetIcon("MenuList");
+ hiAddBirthdayContact = GetIcon("AddBirthday");
+ hiRefreshUserDetails = GetIcon("RefreshUserDetails");
+
+ hiImportBirthdays = GetIcon("ImportBirthdays");
+ hiExportBirthdays = GetIcon("ExportBirthdays");
+
+ int i;
+ char buffer[1024];
+ for (i = 0; i < cDTB; i++)
+ {
+ sprintf(buffer, "DTB%d", i);
+ hiDTB[i] = GetIcon(buffer);
+ }
+ hiDTBMore = GetIcon("DTBMore");
+ }
+ return 0;
+}
+
+HICON GetDTBIcon(int dtb)
+{
+ if ((dtb >= cDTB) || (dtb < 0))
+ {
+ return hiDTBMore;
+ }
+ return hiDTB[dtb];
+}
+
+HICON GetDABIcon(int dab)
+{
+ return GetDTBIcon(dab);
+}
+
+HANDLE GetClistIcon(int dtb)
+{
+ if (dtb >= cDTB)
+ {
+ return hClistImages[cDTB];
+ }
+ return hClistImages[dtb];
+}
+
+HANDLE RebuildCListIcon(HICON icon)
+{
+ INT_PTR tmp = CallService(MS_CLIST_EXTRA_ADD_ICON, (WPARAM) icon, 0);
+ if (tmp != CALLSERVICE_NOTFOUND)
+ {
+ return (HANDLE) tmp;
+ }
+ return (HANDLE) -1;
+}
+
+int RebuildAdvIconList()
+{
+ int i;
+ for (i = 0; i < cDTB; i++)
+ {
+ hClistImages[i] = RebuildCListIcon(hiDTB[i]);
+ }
+ hClistImages[cDTB] = RebuildCListIcon(hiDTBMore);
+ return 0;
+}
diff --git a/plugins/WhenWasIt/src/icons.h b/plugins/WhenWasIt/src/icons.h
new file mode 100644
index 0000000000..f9d85ce7a4
--- /dev/null
+++ b/plugins/WhenWasIt/src/icons.h
@@ -0,0 +1,50 @@
+/*
+WhenWasIt (birthday reminder) plugin for Miranda IM
+
+Copyright © 2006 Cristian Libotean
+
+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 M_WWI_ICONS_H
+#define M_WWI_ICONS_H
+
+extern HICON hiMainMenu;
+extern HICON hiCheckMenu;
+extern HICON hiListMenu;
+extern HICON hiAddBirthdayContact;
+extern HICON hiRefreshUserDetails;
+
+extern HICON hiImportBirthdays;
+extern HICON hiExportBirthdays;
+
+extern HICON hiDTB[];
+extern HICON hiDTBMore;
+
+extern HANDLE hClistImages[];
+
+extern HANDLE hWWIExtraIcons;
+
+int LoadIcons();
+int AddIcons();
+int GetIcons();
+
+int RebuildAdvIconList();
+
+HICON GetDTBIcon(int dtb);
+HICON GetDABIcon(int dtb);
+HANDLE GetClistIcon(int dtb);
+
+#endif //M_WWI_ICONS_H \ No newline at end of file
diff --git a/plugins/WhenWasIt/src/notifiers.cpp b/plugins/WhenWasIt/src/notifiers.cpp
new file mode 100644
index 0000000000..102511cfaa
--- /dev/null
+++ b/plugins/WhenWasIt/src/notifiers.cpp
@@ -0,0 +1,343 @@
+/*
+WhenWasIt (birthday reminder) plugin for Miranda IM
+
+Copyright © 2006 Cristian Libotean
+
+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 "commonheaders.h"
+#include "notifiers.h"
+
+void FillPopupData(POPUPDATAT &pd, int dtb)
+{
+ //DWORD foreground = DBGetContactSettingDword(NULL, ModuleName, "Foreground", FOREGROUND_COLOR);
+ //DWORD background = DBGetContactSettingDword(NULL, ModuleName, "Background", BACKGROUND_COLOR);
+ int popupTimeout = (dtb == 0) ? commonData.popupTimeoutToday : commonData.popupTimeout;
+
+ pd.colorBack = commonData.background;
+ pd.colorText = commonData.foreground;
+ pd.iSeconds = popupTimeout;
+}
+
+int PopupNotifyNoBirthdays()
+{
+ POPUPDATAT pd = {0};
+ FillPopupData(pd, -1);
+ pd.lchIcon = GetDTBIcon(-1);
+
+ _tcscpy(pd.lptzContactName, TranslateT("WhenWasIt"));
+ _tcscpy(pd.lptzText, TranslateT("No upcoming birthdays."));
+
+
+ return PUAddPopUpT(&pd);
+}
+
+TCHAR *BuildDTBText(int dtb, TCHAR *name, TCHAR *text, int size)
+{
+ if (dtb > 1)
+ {
+ mir_sntprintf(text, size, TranslateT("%s has birthday in %d days."), name, dtb);
+ }
+ else{
+ if (dtb == 1)
+ {
+ mir_sntprintf(text, size, TranslateT("%s has birthday tomorrow."), name);
+ }
+ else{
+ mir_sntprintf(text, size, TranslateT("%s has birthday today."), name);
+ }
+ }
+
+ return text;
+}
+
+TCHAR *BuildDABText(int dab, TCHAR *name, TCHAR *text, int size)
+{
+ if (dab > 1)
+ {
+ mir_sntprintf(text, size, TranslateT("%s had birthday %d days ago."), name, dab);
+ }
+ else{
+ if (dab == 1)
+ {
+ mir_sntprintf(text, size, TranslateT("%s had birthday yesterday."), name);
+ }
+ else{
+ mir_sntprintf(text, size, TranslateT("%s has birthday today (Should not happen, please report)."), name);
+ }
+ }
+
+ return text;
+}
+
+int PopupNotifyBirthday(HANDLE hContact, int dtb, int age)
+{
+ TCHAR *name = GetContactName(hContact, NULL);
+ const int MAX_SIZE = 1024;
+ TCHAR text[MAX_SIZE];
+ //int bIgnoreSubcontacts = DBGetContactSettingByte(NULL, ModuleName, "IgnoreSubcontacts", FALSE);
+ if (commonData.bIgnoreSubcontacts)
+ {
+ HANDLE hMetacontact = (HANDLE) CallService(MS_MC_GETMETACONTACT, (WPARAM) hContact, 0);
+ if ((hMetacontact) && (hMetacontact != hContact)) //not main metacontact
+ {
+ return 0;
+ }
+ }
+ BuildDTBText(dtb, name, text, MAX_SIZE);
+ int gender = GetContactGender(hContact);
+
+ POPUPDATAT pd = {0};
+ FillPopupData(pd, dtb);
+ pd.lchContact = hContact;
+ pd.PluginWindowProc = (WNDPROC) DlgProcPopup;
+ //pd.PluginData = (void *) hContact;
+ //pd.colorBack = background;
+ //pd.colorText = foreground;
+ //pd.iSeconds = popupTimeout;
+ pd.lchIcon = GetDTBIcon(dtb);
+
+ //strcpy(pd.lpzContactName, text);
+ _stprintf(pd.lptzContactName, TranslateT("Birthday - %s"), name);
+ TCHAR *sex;
+ switch (toupper(gender))
+ {
+ case _T('M'):
+ {
+ sex = TranslateT("He");
+ break;
+ }
+ case _T('F'):
+ {
+ sex = TranslateT("She");
+ break;
+ }
+ default:
+ {
+ sex = TranslateT("He/She");
+ break;
+ }
+ }
+ if (dtb > 0)
+ {
+ _stprintf(pd.lptzText, TranslateT("%s\n%s will be %d years old."), text, sex, age);
+ }
+ else{
+ _stprintf(pd.lptzText, TranslateT("%s\n%s just turned %d."), text, sex, age);
+ }
+
+ PUAddPopUpT(&pd);
+ free(name);
+
+ return 0;
+}
+
+int PopupNotifyMissedBirthday(HANDLE hContact, int dab, int age)
+{
+ TCHAR *name = GetContactName(hContact, NULL);
+ const int MAX_SIZE = 1024;
+ TCHAR text[MAX_SIZE];
+ //int bIgnoreSubcontacts = DBGetContactSettingByte(NULL, ModuleName, "IgnoreSubcontacts", FALSE);
+ if (commonData.bIgnoreSubcontacts)
+ {
+ HANDLE hMetacontact = (HANDLE) CallService(MS_MC_GETMETACONTACT, (WPARAM) hContact, 0);
+ if ((hMetacontact) && (hMetacontact != hContact)) //not main metacontact
+ {
+ return 0;
+ }
+ }
+ BuildDABText(dab, name, text, MAX_SIZE);
+ int gender = GetContactGender(hContact);
+
+ POPUPDATAT pd = {0};
+ FillPopupData(pd, dab);
+ pd.lchContact = hContact;
+ pd.PluginWindowProc = (WNDPROC) DlgProcPopup;
+ //pd.PluginData = (void *) hContact;
+ //pd.colorBack = background;
+ //pd.colorText = foreground;
+ //pd.iSeconds = popupTimeout;
+ pd.lchIcon = GetDABIcon(dab);
+
+ //strcpy(pd.lpzContactName, text);
+ _stprintf(pd.lptzContactName, TranslateT("Birthday - %s"), name);
+ TCHAR *sex;
+ switch (toupper(gender))
+ {
+ case _T('M'):
+ {
+ sex = TranslateT("He");
+ break;
+ }
+ case _T('F'):
+ {
+ sex = TranslateT("She");
+ break;
+ }
+ default:
+ {
+ sex = TranslateT("He/She");
+ break;
+ }
+ }
+ if (dab > 0)
+ {
+ _stprintf(pd.lptzText, TranslateT("%s\n%s just turned %d."), text, sex, age);
+ }
+ else{
+ _stprintf(pd.lptzText, TranslateT("%s\n%s just turned %d."), text, sex, age);
+ }
+
+ PUAddPopUpT(&pd);
+ free(name);
+
+ return 0;
+}
+
+int ClistIconNotifyBirthday(HANDLE hContact, int dtb, int advancedIcon)
+{
+ if (ServiceExists(MS_EXTRAICON_SET_ICON))
+ {
+ ExtraIcon_SetIcon(hWWIExtraIcons, hContact, GetClistIcon(dtb));
+ }
+ else {
+ IconExtraColumn iec = {0};
+ iec.cbSize = sizeof(IconExtraColumn);
+ iec.ColumnType = advancedIcon;
+ iec.hImage = GetClistIcon(dtb);
+ CallService(MS_CLIST_EXTRA_SET_ICON, (WPARAM) hContact, (LPARAM) &iec);
+ }
+
+ return 0;
+}
+
+int DialogNotifyBirthday(HANDLE hContact, int dtb, int age)
+{
+ TCHAR *name = GetContactName(hContact, NULL);
+ const int MAX_SIZE = 1024;
+ TCHAR text[MAX_SIZE];
+
+ BuildDTBText(dtb, name, text, MAX_SIZE);
+ if (!hUpcomingDlg)
+ {
+ hUpcomingDlg = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_UPCOMING), NULL, DlgProcUpcoming);
+ ShowWindow(hUpcomingDlg, commonData.bOpenInBackground ? SW_SHOWNOACTIVATE : SW_SHOW);
+ }
+
+ TUpcomingBirthday data = {0};
+ data.name = name;
+ data.message = text;
+ data.dtb = dtb;
+ data.hContact = hContact;
+ data.age = age;
+
+ SendMessage(hUpcomingDlg, WWIM_ADD_UPCOMING_BIRTHDAY, (WPARAM) &data, NULL);
+
+ free(name);
+
+ return 0;
+}
+
+int DialogNotifyMissedBirthday(HANDLE hContact, int dab, int age)
+{
+ TCHAR *name = GetContactName(hContact, NULL);
+ const int MAX_SIZE = 1024;
+ TCHAR text[MAX_SIZE];
+
+ BuildDABText(dab, name, text, MAX_SIZE);
+ if (!hUpcomingDlg)
+ {
+ hUpcomingDlg = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_UPCOMING), NULL, DlgProcUpcoming);
+ ShowWindow(hUpcomingDlg, commonData.bOpenInBackground ? SW_SHOWNOACTIVATE : SW_SHOW);
+ }
+
+ TUpcomingBirthday data = {0};
+ data.name = name;
+ data.message = text;
+ data.dtb = -dab;
+ data.hContact = hContact;
+ data.age = age;
+
+ SendMessage(hUpcomingDlg, WWIM_ADD_UPCOMING_BIRTHDAY, (WPARAM) &data, NULL);
+
+ free(name);
+
+ return 0;
+}
+
+int SoundNotifyBirthday(int dtb)
+{
+ //int daysToPlay = DBGetContactSettingByte(NULL, ModuleName, "SoundNearDays", BIRTHDAY_NEAR_DEFAULT_DAYS);
+ if (dtb == 0)
+ {
+ SkinPlaySound(BIRTHDAY_TODAY_SOUND);
+ }
+ else{
+ if (dtb <= commonData.cSoundNearDays)
+ {
+ SkinPlaySound(BIRTHDAY_NEAR_SOUND);
+ }
+ }
+
+ return 0;
+}
+
+int ClearClistIcon(HANDLE hContact, int advancedIcon)
+{
+ if (ServiceExists(MS_EXTRAICON_SET_ICON))
+ {
+ return ExtraIcon_SetIcon(hWWIExtraIcons, hContact, (HANDLE) -1);
+ }
+ else {
+ IconExtraColumn iec = {0};
+ iec.cbSize = sizeof(IconExtraColumn);
+ iec.ColumnType = advancedIcon;
+ iec.hImage = (HANDLE) -1;
+
+ return CallService(MS_CLIST_EXTRA_SET_ICON, (WPARAM) hContact, (LPARAM) &iec);
+ }
+}
+
+int RefreshContactListIcons(HANDLE hContact)
+{
+ //if (DBGetContactSettingWord(hContact, DUMMY_MODULE, DUMMY_SETTING, 0) != 0)
+ // {
+ // DBDeleteContactSetting(hContact, DUMMY_MODULE, DUMMY_SETTING);
+ // }
+ // else{
+ // DBWriteContactSettingWord(hContact, DUMMY_MODULE, DUMMY_SETTING, 101);
+ // }
+ OnExtraImageApply((WPARAM) hContact, 0);
+
+ return 0;
+}
+
+//if oldClistIcon != -1 it will remove the old location of the clist extra icon
+//called with oldClistIcon != -1 from dlg_handlers whtn the extra icon slot changes.
+int RefreshAllContactListIcons(int oldClistIcon)
+{
+ HANDLE hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ while (hContact != NULL)
+ {
+ if (oldClistIcon != -1)
+ {
+ ClearClistIcon(hContact, oldClistIcon);
+ }
+ RefreshContactListIcons(hContact); //will change bBirthdayFound if needed
+ hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0);
+ }
+ return 0;
+} \ No newline at end of file
diff --git a/plugins/WhenWasIt/src/notifiers.h b/plugins/WhenWasIt/src/notifiers.h
new file mode 100644
index 0000000000..db43ca55e1
--- /dev/null
+++ b/plugins/WhenWasIt/src/notifiers.h
@@ -0,0 +1,60 @@
+/*
+WhenWasIt (birthday reminder) plugin for Miranda IM
+
+Copyright © 2006 Cristian Libotean
+
+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 M_WWI_NOTIFIERS_H
+#define M_WWI_NOTIFIERS_H
+
+
+#define POPUPDATAT POPUPDATAW
+#define PUAddPopUpT PUAddPopUpW
+
+
+#define BIRTHDAY_TODAY_SOUND "WWIBirthdayToday"
+#define BIRTHDAY_NEAR_SOUND "WWIBirthdayNear"
+
+#define BIRTHDAY_NEAR_DEFAULT_DAYS 3
+
+#define DUMMY_MODULE ModuleName
+#define DUMMY_SETTING "refreshIconsDummyVal"
+
+struct TUpcomingBirthday{
+ HANDLE hContact;
+ TCHAR *name;
+ TCHAR *message;
+ int dtb;
+ int age;
+};
+
+typedef TUpcomingBirthday *PUpcomingBirthday;
+
+int PopupNotifyNoBirthdays();
+int PopupNotifyBirthday(HANDLE hContact, int dtb, int age);
+int PopupNotifyMissedBirthday(HANDLE hContact, int dab, int age);
+int ClistIconNotifyBirthday(HANDLE hContact, int dtb, int advancedIcon);
+int DialogNotifyBirthday(HANDLE hContact, int dtb, int age);
+int DialogNotifyMissedBirthday(HANDLE hContact, int dab, int age);
+int SoundNotifyBirthday(int dtb);
+
+int ClearClistIcon(HANDLE hContact, int advancedIcon);
+
+int RefreshContactListIcons(HANDLE hContact);
+int RefreshAllContactListIcons(int oldClistIcon = -1);
+
+#endif //M_WWI_NOTIFIERS_H \ No newline at end of file
diff --git a/plugins/WhenWasIt/src/resource.h b/plugins/WhenWasIt/src/resource.h
new file mode 100644
index 0000000000..e43831ac79
--- /dev/null
+++ b/plugins/WhenWasIt/src/resource.h
@@ -0,0 +1,79 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by WhenWasIt.rc
+//
+#define IDD_OPT_WWI 101
+#define IDI_BIRTHDAYS 102
+#define IDI_BIRTHDAYS_DLG 102
+#define IDD_BIRTHDAYS 104
+#define IDI_CHECK 106
+#define IDI_LIST 107
+#define IDI_DTB1 108
+#define IDI_DTB9 109
+#define IDI_DTB2 110
+#define IDI_DTB3 111
+#define IDI_DTB4 112
+#define IDI_DTB5 113
+#define IDI_DTB6 114
+#define IDI_DTB7 115
+#define IDI_DTB8 116
+#define IDI_DTB0 117
+#define IDI_DTBMORE 118
+#define IDD_ADD_BIRTHDAY 119
+#define IDI_ADD 121
+#define IDI_REFRESH_USERDETAILS 123
+#define IDI_IMPORT 125
+#define IDI_IMPORT_BIRTHDAYS 125
+#define IDI_EXPORT_BIRTHDAYS 126
+#define IDD_ADD_ANNIVERSARY 127
+#define IDD_UPCOMING 128
+#define IDC_USE_POPUPS 1002
+#define IDC_USE_CLISTICON 1003
+#define IDC_USE_DIALOG 1004
+#define IDC_DAYS_IN_ADVANCE 1005
+#define IDC_ADVANCED_ICON 1008
+#define IDC_CHECK_INTERVAL 1009
+#define IDC_POPUP_TIMEOUT 1010
+#define IDC_POPUPS_STATIC 1011
+#define IDC_CLIST_STATIC 1012
+#define IDC_BACKGROUND 1014
+#define IDC_FOREGROUND 1015
+#define IDC_CLOSE 1015
+#define IDC_BIRTHDAYS_LIST 1016
+#define IDC_SHOW_ALL 1017
+#define IDC_DATE 1020
+#define IDC_MBIRTHDAY_COMPATIBILITY 1021
+#define IDC_IGNORE_SUBCONTACTS 1023
+#define IDC_AGE_COMBOBOX 1025
+#define IDC_NOBIRTHDAYS_POPUP 1026
+#define IDC_COMPATIBILITY 1027
+#define IDC_SOUND_NEAR_DAYS_EDIT 1028
+#define IDC_DEFAULT_MODULE 1029
+#define IDC_PREVIEW 1030
+#define IDC_LEFT_CLICK 1031
+#define IDC_RIGHT_CLICK 1032
+#define IDC_ONCE_PER_DAY 1033
+#define IDC_TITLE 1036
+#define IDC_DESCRIPTION 1037
+#define IDC_DELETE 1038
+#define IDC_SAVE 1039
+#define IDC_ANNIVERSARY 1040
+#define IDC_EDIT1 1042
+#define IDC_DLG_TIMEOUT 1042
+#define IDC_UPCOMING_LIST 1043
+#define IDC_DIALOG_STATIC 1044
+#define IDC_NOTIFYFOR 1045
+#define IDC_DAYS_AFTER 1046
+#define IDC_NOFOCUS 1047
+#define IDC_OPENINBACKGROUND 1047
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 129
+#define _APS_NEXT_COMMAND_VALUE 40001
+#define _APS_NEXT_CONTROL_VALUE 1048
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/plugins/WhenWasIt/src/services.cpp b/plugins/WhenWasIt/src/services.cpp
new file mode 100644
index 0000000000..adc06de7b5
--- /dev/null
+++ b/plugins/WhenWasIt/src/services.cpp
@@ -0,0 +1,422 @@
+/*
+WhenWasIt (birthday reminder) plugin for Miranda IM
+
+Copyright © 2006 Cristian Libotean
+
+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 "commonheaders.h"
+#include "services.h"
+
+#define COMMENT_CHAR '#'
+
+HANDLE hsCheckBirthdays;
+HANDLE hsShowList;
+HANDLE hsAddBirthday;
+HANDLE hsRefreshUserDetails;
+HANDLE hsImportBirthdays;
+HANDLE hsExportBirthdays;
+
+int bShouldCheckBirthdays = 0;
+int bBirthdayFound = 0;
+
+int InitServices()
+{
+ Log("%s", "Entering function " __FUNCTION__);
+
+ commonData.foreground = DBGetContactSettingDword(NULL, ModuleName, "Foreground", FOREGROUND_COLOR);
+ commonData.background = DBGetContactSettingDword(NULL, ModuleName, "Background", BACKGROUND_COLOR);
+ commonData.checkInterval = DBGetContactSettingWord(NULL, ModuleName, "CheckInterval", CHECK_INTERVAL);
+ commonData.daysInAdvance = DBGetContactSettingWord(NULL, ModuleName, "DaysInAdvance", DAYS_TO_NOTIFY);
+ commonData.daysAfter = DBGetContactSettingWord(NULL, ModuleName, "DaysAfter", DAYS_TO_NOTIFY_AFTER);
+ commonData.popupTimeout = DBGetContactSettingWord(NULL, ModuleName, "PopupTimeout", POPUP_TIMEOUT);
+ commonData.popupTimeoutToday = DBGetContactSettingWord(NULL, ModuleName, "PopupTimeoutToday", commonData.popupTimeout);
+ commonData.bUsePopups = DBGetContactSettingByte(NULL, ModuleName, "UsePopups", TRUE);
+ commonData.bUseClistIcon = DBGetContactSettingByte(NULL, ModuleName, "UseClistIcon", TRUE);
+ commonData.bUseDialog = DBGetContactSettingByte(NULL, ModuleName, "UseDialog", TRUE);
+ commonData.clistIcon= DBGetContactSettingByte(NULL, ModuleName, "AdvancedIcon", CLIST_ICON);
+ commonData.bIgnoreSubcontacts = DBGetContactSettingByte(NULL, ModuleName, "IgnoreSubcontacts", FALSE);
+ commonData.cShowAgeMode = DBGetContactSettingByte(NULL, ModuleName, "ShowCurrentAge", FALSE);
+ commonData.bNoBirthdaysPopup = DBGetContactSettingByte(NULL, ModuleName, "NoBirthdaysPopup", FALSE);
+ commonData.bOpenInBackground = DBGetContactSettingByte(NULL, ModuleName, "OpenInBackground", FALSE);
+ commonData.cSoundNearDays = DBGetContactSettingByte(NULL, ModuleName, "SoundNearDays", BIRTHDAY_NEAR_DEFAULT_DAYS);
+ commonData.cDefaultModule = DBGetContactSettingByte(NULL, ModuleName, "DefaultModule", 0);
+ commonData.lPopupClick = DBGetContactSettingByte(NULL, ModuleName, "PopupLeftClick", 2);
+ commonData.rPopupClick = DBGetContactSettingByte(NULL, ModuleName, "PopupRightClick", 1);
+ commonData.bOncePerDay = DBGetContactSettingByte(NULL, ModuleName, "OncePerDay", 0);
+ commonData.cDlgTimeout = DBGetContactSettingWord(NULL, ModuleName, "DlgTimeout", POPUP_TIMEOUT);
+ commonData.notifyFor = DBGetContactSettingByte(NULL, ModuleName, "NotifyFor", 0);
+
+ hsCheckBirthdays = CreateServiceFunction(MS_WWI_CHECK_BIRTHDAYS, CheckBirthdaysService);
+ hsShowList = CreateServiceFunction(MS_WWI_LIST_SHOW, ShowListService);
+ hsAddBirthday = CreateServiceFunction(MS_WWI_ADD_BIRTHDAY, AddBirthdayService);
+ hsRefreshUserDetails = CreateServiceFunction(MS_WWI_REFRESH_USERDETAILS, RefreshUserDetailsService);
+ hsImportBirthdays = CreateServiceFunction(MS_WWI_IMPORT_BIRTHDAYS, ImportBirthdaysService);
+ hsExportBirthdays = CreateServiceFunction(MS_WWI_EXPORT_BIRTHDAYS, ExportBirthdaysService);
+
+ Log("%s", "Leaving function " __FUNCTION__);
+ return 0;
+}
+
+int DestroyServices()
+{
+ Log("%s", "Entering function " __FUNCTION__);
+
+ DestroyServiceFunction(hsCheckBirthdays);
+ DestroyServiceFunction(hsShowList);
+ DestroyServiceFunction(hsAddBirthday);
+ DestroyServiceFunction(hsRefreshUserDetails);
+ DestroyServiceFunction(hsImportBirthdays);
+ DestroyServiceFunction(hsExportBirthdays);
+
+ Log("%s", "Leaving function " __FUNCTION__);
+ return 0;
+}
+
+/*
+returns -1 if notify is not necesarry
+returns daysToBirthday if it should notify
+*/
+int NotifyContactBirthday(HANDLE hContact, time_t now, int daysInAdvance)
+{
+ int year, month, day;
+ GetContactDOB(hContact, year, month, day);
+ int daysToBirthday = DaysToBirthday(now, year, month, day);
+ if (daysInAdvance >= daysToBirthday)
+ {
+ return daysToBirthday;
+ }
+ return -1;
+}
+
+// returns -1 if notify is not necessary
+// returns daysAfterBirthday if it should notify
+int NotifyMissedContactBirthday(HANDLE hContact, time_t now, int daysAfter)
+{
+ if (daysAfter > 0)
+ {
+ int year, month, day;
+ GetContactDOB(hContact, year, month, day);
+ int daysAfterBirthday = DaysAfterBirthday(now, year, month, day);
+ if ((daysAfterBirthday >= 0) && (daysAfter >= daysAfterBirthday))
+ {
+ return daysAfterBirthday;
+ }
+ }
+
+ return -1;
+}
+
+//the timer functions call this service with lParam = 1
+//lParam = 0 - force check, lParam - 1 do not force it.
+INT_PTR CheckBirthdaysService(WPARAM wParam, LPARAM lParam)
+{
+ bBirthdayFound = 0; //no birthdays have been found in the given interval
+ //int bNoBirthdaysPopup = DBGetContactSettingByte(NULL, ModuleName, "NoBirthdaysPopup", FALSE);
+
+ SYSTEMTIME today;
+ GetLocalTime(&today);
+
+ DWORD lastChecked = DBGetContactSettingDword(NULL, ModuleName, "LastChecked", 0); //get last checked date
+ int lcDay = LOBYTE(LOWORD(lastChecked));
+ int lcMonth = HIBYTE(LOWORD(lastChecked));
+ int lcYear = HIWORD(lastChecked);
+
+ int daysAfter = DaysAfterBirthday(Today(), lcYear, lcMonth, lcDay); //get difference between last checked date and today
+ int savedDaysAfter = 0;
+
+ savedDaysAfter = commonData.daysAfter; //save value
+
+ if ((daysAfter > commonData.daysAfter) && (commonData.daysAfter > 0))//check for passed birthdays
+ {
+ commonData.daysAfter = daysAfter; //bigger values of the two
+ }
+
+ if ((lParam) && (commonData.bOncePerDay)) //if force check then we don't take OncePerDay into account
+ {
+ if ((lcDay == today.wDay) && (lcMonth == today.wMonth) && (lcYear == today.wYear))
+ {
+ return 0; //already checked today
+ }
+ }
+
+ bShouldCheckBirthdays = 1;
+ RefreshAllContactListIcons();
+ if ((!bBirthdayFound) && (commonData.bNoBirthdaysPopup))
+ {
+ PopupNotifyNoBirthdays();
+ }
+ bShouldCheckBirthdays = 0;
+
+ commonData.daysAfter = savedDaysAfter; //restore previous value
+
+ if (lParam) //if not forced - i.e. timer check
+ {
+ DBWriteContactSettingDword(NULL, ModuleName, "LastChecked", MAKELONG(MAKEWORD(today.wDay, today.wMonth), today.wYear)); //write the value in DB so we don't check again today
+ }
+
+ return 0;
+}
+
+INT_PTR ShowListService(WPARAM wParam, LPARAM lParam)
+{
+ if (!hBirthdaysDlg)
+ {
+ hBirthdaysDlg = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_BIRTHDAYS), NULL, DlgProcBirthdays);
+ }
+ ShowWindow(hBirthdaysDlg, SW_SHOW);
+ return 0;
+}
+
+INT_PTR AddBirthdayService(WPARAM wParam, LPARAM lParam)
+{
+ HWND hWnd = WindowList_Find(hAddBirthdayWndsList, (HANDLE) wParam);
+ if (!hWnd)
+ {
+ hWnd = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_ADD_BIRTHDAY), NULL, DlgProcAddBirthday);
+ if (hWnd == NULL)
+ {
+ TCHAR buffer[1024];
+ _stprintf(buffer, _T("Error #%d while trying to create add birthday dialog"), GetLastError());
+ MessageBox(0, buffer, _T("Error"), MB_OK);
+ }
+ WindowList_Add(hAddBirthdayWndsList, hWnd, (HANDLE) wParam);
+ SetWindowLongPtr(hWnd, GWLP_USERDATA, wParam);
+ }
+ return ShowWindow(hWnd, SW_SHOW);
+}
+
+void ShowPopupMessage(TCHAR *title, TCHAR *message, HICON icon)
+{
+ POPUPDATAT pd = {0};
+ pd.lchIcon = icon;
+ _tcscpy(pd.lptzContactName, title);
+ _tcscpy(pd.lptzText, message);
+ pd.colorText = commonData.foreground;
+ pd.colorBack = commonData.background;
+
+ PUAddPopUpT(&pd);
+}
+
+DWORD WINAPI RefreshUserDetailsWorkerThread(LPVOID param)
+{
+ //MessageBox(0, "Inside worker thread", "Info", MB_OK);
+ //POPUPDATA pd = {0};
+ //pd.lchIcon = hiRefreshUserDetails;
+ //strcpy(pd.lpzContactName, Translate("WhenWasIt"));
+ //strcpy(pd.lpzText, Translate("Starting to refresh user details"));
+ //PUAddPopUp(&pd);
+ ShowPopupMessage(TranslateT("WhenWasIt"), TranslateT("Starting to refresh user details"), hiRefreshUserDetails);
+ int delay = DBGetContactSettingWord(NULL, ModuleName, "UpdateDelay", REFRESH_DETAILS_DELAY);
+ HANDLE hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ int res;
+ while (hContact != NULL)
+ {
+ res = CallContactService(hContact, PSS_GETINFO, 0, 0);
+ hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0);
+ if (hContact)
+ {
+ Sleep(delay); //sleep for a few seconds between requests
+ }
+ }
+ //strcpy(pd.lpzText, Translate("Done refreshing user details"));
+ //PUAddPopUp(&pd);
+ ShowPopupMessage(TranslateT("WhenWasIt"), TranslateT("Done refreshing user details"), hiRefreshUserDetails);
+ //MessageBox(0, "Leaving worker thread", "Info", MB_OK);
+ return 0;
+}
+
+INT_PTR RefreshUserDetailsService(WPARAM wParam, LPARAM lParam)
+{
+ DWORD threadID;
+ //MessageBox(0, "Before CreateThread()", "Info", MB_OK);
+ HANDLE result = CreateThread(NULL, 0, RefreshUserDetailsWorkerThread, NULL, 0, &threadID);
+ //MessageBox(0, "After CreateThread()", "Info", MB_OK);
+ if (!result)
+ {
+ TCHAR buffer[1024];
+ _stprintf(buffer, _T("Could not create worker thread. Error#%d - threadID %d"), GetLastError(), threadID);
+ MessageBox(0, buffer, _T("Error"), MB_OK | MB_ICONERROR);
+ }
+ if ((result != NULL) && (result != INVALID_HANDLE_VALUE))
+ {
+ CloseHandle(result);
+ }
+
+ return 0;
+}
+
+INT_PTR ImportBirthdaysService(WPARAM wParam, LPARAM lParam)
+{
+ TCHAR fileName[1024] = {0};
+ OPENFILENAME of = {0};
+ of.lStructSize = sizeof(OPENFILENAME);
+ //of.hInstance = hInstance;
+ TCHAR filter[MAX_PATH];
+ mir_sntprintf(filter, SIZEOF(filter), _T("%s (*") _T(BIRTHDAY_EXTENSION) _T(")%c*") _T(BIRTHDAY_EXTENSION) _T("%c"), TranslateT("Birthdays files"), 0, 0);
+ of.lpstrFilter = filter;
+ of.lpstrFile = fileName;
+ of.nMaxFile = 1024;
+ of.lpstrTitle = TranslateT("Please select a file to import birthdays from ...");
+ of.Flags = OFN_FILEMUSTEXIST;
+
+ if (GetOpenFileName(&of))
+ {
+ TCHAR buffer[2048];
+ mir_sntprintf(buffer, SIZEOF(buffer), TranslateT("Importing birthdays from file: %s"), fileName);
+ ShowPopupMessage(TranslateT("WhenWasIt"), buffer, hiImportBirthdays);
+ DoImport(fileName);
+ ShowPopupMessage(TranslateT("WhenWasIt"), TranslateT("Done importing birthdays"), hiImportBirthdays);
+ }
+
+ return 0;
+}
+
+INT_PTR ExportBirthdaysService(WPARAM wParam, LPARAM lParam)
+{
+ TCHAR fileName[1024]= {0};
+ OPENFILENAME of = {0};
+ of.lStructSize = sizeof(OPENFILENAME);
+ //of.hInstance = hInstance;
+ TCHAR filter[MAX_PATH];
+ mir_sntprintf(filter, SIZEOF(filter), _T("%s (*") _T(BIRTHDAY_EXTENSION) _T(")%c*") _T(BIRTHDAY_EXTENSION) _T("%c%s (*.*)%c*.*%c"), TranslateT("Birthdays files"), 0, 0, TranslateT("All Files"), 0, 0);
+ of.lpstrFilter = filter;
+ of.lpstrFile = fileName;
+ of.nMaxFile = 1024;
+ of.lpstrTitle = TranslateT("Please select a file to export birthdays to ...");
+ //of.Flags = OFN_ENABLESIZING | OFN_EXPLORER;
+
+ if (GetSaveFileName(&of))
+ {
+ TCHAR buffer[2048];
+ TCHAR *fn = _tcsrchr(fileName, _T('\\')) + 1;
+ if (!_tcschr(fn, _T('.')))
+ {
+ _tcscat(fileName, _T(BIRTHDAY_EXTENSION));
+ }
+ _stprintf(buffer, TranslateT("Exporting birthdays to file: %s"), fileName);
+ ShowPopupMessage(TranslateT("WhenWasIt"), buffer, hiExportBirthdays);
+ DoExport(fileName);
+ ShowPopupMessage(TranslateT("WhenWasIt"), TranslateT("Done exporting birthdays"), hiExportBirthdays);
+ }
+
+ return 0;
+}
+
+int DoImport(TCHAR *fileName)
+{
+ FILE *fin = _tfopen(fileName, _T("rt"));
+ if (!fin)
+ {
+ MessageBox(0, _T("Could not open file to import birthdays"), _T("Error"), MB_OK | MB_ICONERROR);
+ return 1;
+ }
+
+ HANDLE hContact;
+ int year, month, day;
+ TCHAR *szHandle;
+ TCHAR *szProto;
+ const int maxSize = 4096;
+ TCHAR buffer[maxSize];
+ int tmp, tmp2;
+ int mode = commonData.cDefaultModule; //DBGetContactSettingByte(NULL, ModuleName, "DefaultModule", 0);
+ TCHAR *delAccount, *delProto;
+
+ while (!feof(fin))
+ {
+ _fgetts(buffer, maxSize, fin);
+ if (buffer[0] == _T(COMMENT_CHAR))
+ {
+ continue;
+ }
+
+ delAccount = _tcsstr(buffer, _T(" : "));
+ if (delAccount)
+ {
+ tmp = delAccount[0];
+ delAccount[0] = _T('\0');
+ delProto = _tcsrchr(buffer, _T('@'));
+ if (delProto)
+ {
+ tmp2 = delProto[0];
+ delProto[0] = _T('\0');
+
+ szHandle = buffer;
+ szProto = delProto + 1;
+ hContact = GetContactFromID(szHandle, szProto);
+ if (hContact)
+ {
+ delProto[0] = tmp;
+ delAccount[0] = tmp;
+ _stscanf(delAccount, _T(" : %02d/%02d/%04d"), &day, &month, &year);
+ SaveBirthday(hContact, year, month, day, mode);
+ }
+ else{
+ TCHAR tmp[2048];
+ _stprintf(tmp, TranslateT(NOTFOUND_FORMAT), szHandle, szProto);
+ ShowPopupMessage(TranslateT("Warning"), tmp, hiImportBirthdays);
+ }
+ }
+ }
+ }
+
+ fclose(fin);
+
+ return 0;
+}
+
+int DoExport(TCHAR *fileName)
+{
+ FILE *fout = _tfopen(fileName, _T("wt"));
+ if (!fout)
+ {
+ MessageBox(0, _T("Could not open file to export birthdays"), _T("Error"), MB_OK | MB_ICONERROR);
+ return 1;
+ }
+ _ftprintf(fout, _T("%c%s"), _T(COMMENT_CHAR), _T("Please do not edit this file by hand. Use the export function of WhenWasIt plugin.\n"));
+ _ftprintf(fout, _T("%c%s"), _T(COMMENT_CHAR), _T("Warning! Please do not mix Unicode and Ansi exported birthday files. You should use the same version (Ansi/Unicode) of WhenWasIt that was used to export the info.\n"));
+
+ _ftprintf(fout, _T("%c%s"), _T(COMMENT_CHAR), _T("This file was exported with a Unicode version of WhenWasIt. Please only use a Unicode version of the plugin to import the birthdays.\n"));
+
+ HANDLE hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ int year, month, day;
+ TCHAR *szHandle;
+ char szProto[256];
+
+ while (hContact)
+ {
+ GetContactDOB(hContact, year, month, day);
+ if (IsDOBValid(year, month, day))
+ {
+ szProto[0] = '\0';
+ GetContactProtocol(hContact, szProto, sizeof(szProto));
+ szHandle = GetContactID(hContact, szProto);
+
+ if ((szHandle) && (strlen(szProto) > 0))
+ {
+ _ftprintf(fout, _T(BIRTHDAYS_EXPORT_FORMAT), szHandle, szProto, day, month, year);
+ }
+
+ if (szHandle) free(szHandle);
+ }
+
+ hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0);
+ }
+
+ fclose(fout);
+
+ return 0;
+} \ No newline at end of file
diff --git a/plugins/WhenWasIt/src/services.h b/plugins/WhenWasIt/src/services.h
new file mode 100644
index 0000000000..4348077a54
--- /dev/null
+++ b/plugins/WhenWasIt/src/services.h
@@ -0,0 +1,58 @@
+/*
+WhenWasIt (birthday reminder) plugin for Miranda IM
+
+Copyright © 2006 Cristian Libotean
+
+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 M_WWI_SERVICES_H
+#define M_WWI_SERVICES_H
+
+#define MS_WWI_CHECK_BIRTHDAYS "WhenWasIt/Birthdays/Check"
+#define MS_WWI_LIST_SHOW "WhenWasIt/List/Show"
+#define MS_WWI_ADD_BIRTHDAY "WhenWasIt/Birthdays/Add"
+#define MS_WWI_REFRESH_USERDETAILS "WhenWasIt/Birthdays/RefreshDetails"
+#define MS_WWI_IMPORT_BIRTHDAYS "WhenWasIt/Birthdays/Import"
+#define MS_WWI_EXPORT_BIRTHDAYS "WhenWasIt/Birthdays/Export"
+
+#define REFRESH_DETAILS_DELAY 3000
+
+
+#define BIRTHDAY_EXTENSION ".bdaysW"
+#define BIRTHDAYS_EXPORT_FORMAT "%s@%S : %02d/%02d/%04d\n"
+#define NOTFOUND_FORMAT "Could not find UID '%s [%S]' in current database, skipping"
+
+
+extern int bShouldCheckBirthdays;
+extern int bBirthdayFound;
+
+int InitServices();
+int DestroyServices();
+
+int NotifyContactBirthday(HANDLE hContact, time_t now, int daysInAdvance);
+int NotifyMissedContactBirthday(HANDLE hContact, time_t now, int daysAfter);
+
+int DoExport(TCHAR *fileName);
+int DoImport(TCHAR *fileName);
+
+INT_PTR CheckBirthdaysService(WPARAM wParam, LPARAM lParam);
+INT_PTR ShowListService(WPARAM wParam, LPARAM lParam);
+INT_PTR AddBirthdayService(WPARAM wParam, LPARAM lParam);
+INT_PTR RefreshUserDetailsService(WPARAM wParam, LPARAM lParam);
+INT_PTR ImportBirthdaysService(WPARAM wParam, LPARAM lParam);
+INT_PTR ExportBirthdaysService(WPARAM wParam, LPARAM lParam);
+
+#endif //M_EXCHANGE_SERVICES_H \ No newline at end of file
diff --git a/plugins/WhenWasIt/src/utils.cpp b/plugins/WhenWasIt/src/utils.cpp
new file mode 100644
index 0000000000..6bfbcd326e
--- /dev/null
+++ b/plugins/WhenWasIt/src/utils.cpp
@@ -0,0 +1,393 @@
+/*
+WhenWasIt (birthday reminder) plugin for Miranda IM
+
+Copyright © 2006 Cristian Libotean
+
+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 "commonheaders.h"
+#include "utils.h"
+
+int LogInit()
+{
+#ifdef _DEBUG
+ FILE *fout = fopen(LOG_FILE, "wt");
+ fclose(fout);
+#endif
+ return 0;
+}
+
+int Log(char *format, ...)
+{
+#ifdef _DEBUG
+ char str[4096];
+ va_list vararg;
+ int tBytes;
+ FILE *fout = fopen(LOG_FILE, "at");
+ if (!fout)
+ {
+// MessageBox(0, "can't open file", NULL, MB_OK);
+ return -1;
+ }
+ time_t tNow = time(NULL);
+ struct tm *now = localtime(&tNow);
+ strftime(str, sizeof(str), "%d %b %Y @ %H:%M:%S: ", now);
+ fputs(str, fout);
+ va_start(vararg, format);
+
+ tBytes = _vsnprintf(str, sizeof(str), format, vararg);
+ if (tBytes > 0)
+ {
+ str[tBytes] = 0;
+ }
+
+ va_end(vararg);
+ if (str[strlen(str) - 1] != '\n')
+ {
+ strcat(str, "\n");
+ }
+ fputs(str, fout);
+ fclose(fout);
+#endif
+ return 0;
+}
+
+int Info(char *title, char *format, ...)
+{
+ char str[4096];
+ va_list vararg;
+ int tBytes;
+ va_start(vararg, format);
+ tBytes = _vsnprintf(str, sizeof(str), format, vararg);
+ if (tBytes > 0)
+ {
+ str[tBytes] = 0;
+ }
+ va_end(vararg);
+ return MessageBoxA(0, str, title, MB_OK | MB_ICONINFORMATION);
+}
+
+#define HEX_SIZE 8
+
+char *BinToHex(int size, PBYTE data)
+{
+ char *szresult = NULL;
+ char buffer[32] = {0}; //should be more than enough
+ int maxSize = size * 2 + HEX_SIZE + 1;
+ szresult = (char *) new char[ maxSize ];
+ memset(szresult, 0, maxSize);
+ sprintf(buffer, "%0*X", HEX_SIZE, size);
+ strcpy(szresult, buffer);
+ int i;
+ for (i = 0; i < size; i++)
+ {
+ sprintf(buffer, "%02X", data[i]);
+ strcpy(szresult + (HEX_SIZE + i * 2), buffer);
+ }
+ return szresult;
+}
+
+void HexToBin(char *inData, ULONG &size, LPBYTE &outData)
+{
+ char buffer[32] = {0};
+ strcpy(buffer, "0x");
+ strncpy(buffer + 2, inData, HEX_SIZE);
+ sscanf(buffer, "%x", &size);
+ outData = (unsigned char*)new char[size*2];
+ UINT i;
+ //size = i;
+ char *tmp = inData + HEX_SIZE;
+ buffer[4] = '\0'; //mark the end of the string
+ for (i = 0; i < size; i++)
+ {
+ strncpy(buffer + 2, &tmp[i * 2], 2);
+ sscanf(buffer, "%x", &outData[i]);
+ }
+ i = size;
+}
+
+int GetStringFromDatabase(HANDLE hContact, char *szModule, char *szSettingName, char *szError, char *szResult, size_t size)
+{
+ DBVARIANT dbv = {0};
+ int res = 1;
+ size_t len;
+ dbv.type = DBVT_ASCIIZ;
+ if (DBGetContactSetting(hContact, szModule, szSettingName, &dbv) == 0)
+ {
+ res = 0;
+ size_t tmp = strlen(dbv.pszVal);
+ len = (tmp < size - 1) ? tmp : size - 1;
+ strncpy(szResult, dbv.pszVal, len);
+ szResult[len] = '\0';
+ mir_free(dbv.pszVal);
+ }
+ else{
+ res = 1;
+ if (szError)
+ {
+ size_t tmp = strlen(szError);
+ len = (tmp < size - 1) ? tmp : size - 1;
+ strncpy(szResult, szError, len);
+ szResult[len] = '\0';
+ }
+ else{
+ szResult[0] = '\0';
+ }
+ }
+ return res;
+}
+
+int GetStringFromDatabase(char *szSettingName, char *szError, char *szResult, size_t size)
+{
+ return GetStringFromDatabase(NULL, ModuleName, szSettingName, szError, szResult, size);
+}
+
+
+#pragma warning (disable: 4312)
+TCHAR *GetContactName(HANDLE hContact, char *szProto)
+{
+ CONTACTINFO ctInfo;
+ int ret;
+ char proto[200];
+
+ ZeroMemory((void *) &ctInfo, sizeof(ctInfo));
+ ctInfo.cbSize = sizeof(ctInfo);
+ if (szProto)
+ {
+ ctInfo.szProto = szProto;
+ }
+ else{
+ GetContactProtocol(hContact, proto, sizeof(proto));
+ ctInfo.szProto = proto;
+ }
+ ctInfo.dwFlag = CNF_DISPLAY;
+
+ ctInfo.dwFlag += CNF_UNICODE;
+
+ ctInfo.hContact = hContact;
+ //_debug_message("retrieving contact name for %d", hContact);
+ ret = CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM) &ctInfo);
+ //_debug_message(" contact name %s", ctInfo.pszVal);
+ TCHAR *buffer;
+ if (!ret)
+ {
+ buffer = _tcsdup(ctInfo.pszVal);
+ }
+ mir_free(ctInfo.pszVal);
+ if (ret)
+ {
+ return NULL;
+ }
+
+ return buffer;
+}
+#pragma warning (default: 4312)
+
+#pragma warning (disable: 4312)
+void GetContactProtocol(HANDLE hContact, char *szProto, int size)
+{
+ GetStringFromDatabase(hContact, "Protocol", "p", NULL, szProto, size);
+}
+#pragma warning (default: 4312)
+
+#pragma warning (disable: 4312)
+TCHAR *GetContactID(HANDLE hContact)
+{
+ char protocol[256];
+ GetContactProtocol(hContact, protocol, sizeof(protocol));
+
+ return GetContactID(hContact, protocol);
+}
+
+TCHAR *GetContactID(HANDLE hContact, char *szProto)
+{
+ CONTACTINFO ctInfo;
+ int ret;
+
+ ZeroMemory((void *) &ctInfo, sizeof(ctInfo));
+ ctInfo.cbSize = sizeof(ctInfo);
+ ctInfo.szProto = szProto;
+ ctInfo.dwFlag = CNF_UNIQUEID;
+
+ ctInfo.dwFlag |= CNF_UNICODE;
+
+ ctInfo.hContact = hContact;
+ ret = CallService(MS_CONTACT_GETCONTACTINFO, 0, (LPARAM) &ctInfo);
+ TCHAR *buffer;
+ if (!ret)
+ {
+ TCHAR tmp[16];
+ switch (ctInfo.type)
+ {
+ case CNFT_BYTE:
+ {
+ _stprintf(tmp, _T("%d"), ctInfo.bVal);
+ buffer = _tcsdup(tmp);
+
+ break;
+ }
+
+ case CNFT_WORD:
+ {
+ _stprintf(tmp, _T("%d"), ctInfo.wVal);
+ buffer = _tcsdup(tmp);
+
+ break;
+ }
+
+ case CNFT_DWORD:
+ {
+ _stprintf(tmp, _T("%ld"), ctInfo.dVal);
+ buffer = _tcsdup(tmp);
+
+ break;
+ }
+
+ case CNFT_ASCIIZ:
+ default:
+ {
+ buffer = _tcsdup(ctInfo.pszVal);
+
+ break;
+ }
+ }
+
+
+ }
+ mir_free(ctInfo.pszVal);
+ if (!ret)
+ {
+ return buffer;
+ }
+ else{
+ return NULL;
+ }
+}
+#pragma warning (default: 4312)
+
+#pragma warning (disable: 4312)
+HANDLE GetContactFromID(TCHAR *szID, char *szProto)
+{
+ HANDLE hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
+ TCHAR *szHandle;
+ char cProtocol[256];
+
+ int found = 0;
+ while (hContact)
+ {
+ GetContactProtocol(hContact, cProtocol, sizeof(cProtocol));
+ szHandle = GetContactID(hContact, cProtocol);
+ if ((szHandle) && (_tcsicmp(szHandle, szID) == 0) && (_stricmp(szProto, cProtocol) == 0))
+ {
+ found = 1;
+ }
+ if (szHandle) free(szHandle);
+
+ if (found)
+ {
+ break;
+ }
+ hContact = (HANDLE) CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM) hContact, 0);
+ }
+ return hContact;
+}
+#pragma warning (default: 4312)
+
+#pragma warning (disable: 4312)
+HANDLE GetContactFromID(TCHAR *szID, wchar_t *szProto)
+{
+ char protocol[1024];
+ WideCharToMultiByte(CP_ACP, 0, szProto, -1, protocol, sizeof(protocol), NULL, NULL);
+ return GetContactFromID(szID, protocol);
+}
+#pragma warning (default: 4312)
+
+void ScreenToClient(HWND hWnd, LPRECT rect)
+{
+ POINT pt;
+ int cx = rect->right - rect->left;
+ int cy = rect->bottom - rect->top;
+ pt.x = rect->left;
+ pt.y = rect->top;
+ ScreenToClient(hWnd, &pt);
+ rect->left = pt.x;
+ rect->top = pt.y;
+ rect->right = pt.x + cx;
+ rect->bottom = pt.y + cy;
+}
+
+void AnchorMoveWindow(HWND window, const WINDOWPOS *parentPos, int anchors)
+{
+ RECT rParent;
+ RECT rChild;
+
+ if (parentPos->flags & SWP_NOSIZE)
+ {
+ return;
+ }
+ GetWindowRect(parentPos->hwnd, &rParent);
+ rChild = AnchorCalcPos(window, &rParent, parentPos, anchors);
+ MoveWindow(window, rChild.left, rChild.top, rChild.right - rChild.left, rChild.bottom - rChild.top, FALSE);
+}
+
+RECT AnchorCalcPos(HWND window, const RECT *rParent, const WINDOWPOS *parentPos, int anchors)
+{
+ RECT rChild;
+ RECT rTmp;
+
+ GetWindowRect(window, &rChild);
+ ScreenToClient(parentPos->hwnd, &rChild);
+
+ int cx = rParent->right - rParent->left;
+ int cy = rParent->bottom - rParent->top;
+ if ((cx == parentPos->cx) && (cy == parentPos->cy))
+ {
+ return rChild;
+ }
+ if (parentPos->flags & SWP_NOSIZE)
+ {
+ return rChild;
+ }
+
+ rTmp.left = parentPos->x - rParent->left;
+ rTmp.right = (parentPos->x + parentPos->cx) - rParent->right;
+ rTmp.bottom = (parentPos->y + parentPos->cy) - rParent->bottom;
+ rTmp.top = parentPos->y - rParent->top;
+
+ cx = (rTmp.left) ? -rTmp.left : rTmp.right;
+ cy = (rTmp.top) ? -rTmp.top : rTmp.bottom;
+
+ rChild.right += cx;
+ rChild.bottom += cy;
+ //expanded the window accordingly, now we need to enforce the anchors
+ if ((anchors & ANCHOR_LEFT) && (!(anchors & ANCHOR_RIGHT)))
+ {
+ rChild.right -= cx;
+ }
+ if ((anchors & ANCHOR_TOP) && (!(anchors & ANCHOR_BOTTOM)))
+ {
+ rChild.bottom -= cy;
+ }
+ if ((anchors & ANCHOR_RIGHT) && (!(anchors & ANCHOR_LEFT)))
+ {
+ rChild.left += cx;
+ }
+ if ((anchors & ANCHOR_BOTTOM) && (!(anchors & ANCHOR_TOP)))
+ {
+ rChild.top += cy;
+ }
+ return rChild;
+} \ No newline at end of file
diff --git a/plugins/WhenWasIt/src/utils.h b/plugins/WhenWasIt/src/utils.h
new file mode 100644
index 0000000000..6d76c72d2a
--- /dev/null
+++ b/plugins/WhenWasIt/src/utils.h
@@ -0,0 +1,54 @@
+/*
+WhenWasIt (birthday reminder) plugin for Miranda IM
+
+Copyright © 2006 Cristian Libotean
+
+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 M_WWI_UTILS_H
+#define M_WWI_UTILS_H
+
+#include <stdarg.h>
+
+#define LOG_FILE "wwi.log"
+
+#define ANCHOR_LEFT 0x000001
+#define ANCHOR_RIGHT 0x000002
+#define ANCHOR_TOP 0x000004
+#define ANCHOR_BOTTOM 0x000008
+#define ANCHOR_ALL ANCHOR_LEFT | ANCHOR_RIGHT | ANCHOR_TOP | ANCHOR_BOTTOM
+
+int LogInit();
+int Log(char *format, ...);
+int Info(char *title, char *format, ...);
+
+char *BinToHex(int size, PBYTE data);
+void HexToBin(char *inData, ULONG &size, PBYTE &outData);
+
+void ScreenToClient(HWND hWnd, LPRECT rect);
+void AnchorMoveWindow(HWND window, const WINDOWPOS *parentPos, int anchors);
+RECT AnchorCalcPos(HWND window, const RECT *rParent, const WINDOWPOS *parentPos, int anchors);
+
+int GetStringFromDatabase(char *szSettingName, char *szError, char *szResult, int size);
+
+TCHAR *GetContactName(HANDLE hContact, char *szProto);
+TCHAR *GetContactID(HANDLE hContact);
+TCHAR *GetContactID(HANDLE hContact, char *szProto);
+HANDLE GetContactFromID(TCHAR *szID, char *szProto);
+HANDLE GetContactFromID(TCHAR *szID, wchar_t *szProto);
+void GetContactProtocol(HANDLE hContact, char *szProto, int size);
+
+#endif \ No newline at end of file
diff --git a/plugins/WhenWasIt/src/version.h b/plugins/WhenWasIt/src/version.h
new file mode 100644
index 0000000000..73caab55c5
--- /dev/null
+++ b/plugins/WhenWasIt/src/version.h
@@ -0,0 +1,45 @@
+/*
+WhenWasIt (birthday reminder) plugin for Miranda IM
+
+Copyright © 2006-2011 Cristian Libotean
+
+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 M_WWI_VERSION_H
+#define M_WWI_VERSION_H
+
+#define __MAJOR_VERSION 0
+#define __MINOR_VERSION 3
+#define __RELEASE_NUM 3
+#define __BUILD_NUM 4
+
+#define VERSION PLUGIN_MAKE_VERSION(__MAJOR_VERSION, __MINOR_VERSION, __RELEASE_NUM, __BUILD_NUM)
+
+#define __PLUGINVERSION_STRING __MAJOR_VERSION,__MINOR_VERSION,__RELEASE_NUM,__BUILD_NUM
+#define __PLUGINVERSION_STRING_DOTS __MAJOR_VERSION.__MINOR_VERSION.__RELEASE_NUM.__BUILD_NUM
+#define __STRINGIFY_(x) #x
+#define __STRINGIFY(x) __STRINGIFY_(x)
+#define __VERSION_STRING __STRINGIFY(__PLUGINVERSION_STRING_DOTS)
+
+#define __DESC "Notifies you of upcoming birthdays."
+#define __AUTHOR "Cristian Libotean"
+#define __AUTHOREMAIL "eblis102@yahoo.com"
+#define __COPYRIGHT "© 2006-2011 Cristian Libotean"
+#define __AUTHORWEB "http://miranda-ng.org/"
+#define __PLUGIN_DISPLAY_NAME "Birthday reminder"
+
+
+#endif //M_WWI_VERSION_H