From f04d64869f3b1de54fb343f28f955584780001b8 Mon Sep 17 00:00:00 2001 From: mataes2007 Date: Sat, 26 Nov 2011 15:41:10 +0000 Subject: Project folders rename part 3 git-svn-id: http://miranda-plugins.googlecode.com/svn/trunk@215 e753b5eb-9565-29b2-b5c5-2cc6f99dfbcb --- UserInfoEx/classMAnnivDate.cpp | 836 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 836 insertions(+) create mode 100644 UserInfoEx/classMAnnivDate.cpp (limited to 'UserInfoEx/classMAnnivDate.cpp') diff --git a/UserInfoEx/classMAnnivDate.cpp b/UserInfoEx/classMAnnivDate.cpp new file mode 100644 index 0000000..31eeee7 --- /dev/null +++ b/UserInfoEx/classMAnnivDate.cpp @@ -0,0 +1,836 @@ +/* +UserinfoEx plugin for Miranda IM + +Copyright: + 2006-2010 DeathAxe, Yasnovidyashii, Merlin, K. Romanov, Kreol + +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. + +=============================================================================== + +File name : $HeadURL: https://userinfoex.googlecode.com/svn/trunk/classMAnnivDate.cpp $ +Revision : $Revision: 187 $ +Last change on : $Date: 2010-09-08 16:05:54 +0400 (Ср, 08 сен 2010) $ +Last change by : $Author: ing.u.horn $ + +=============================================================================== +*/ + +/** + * System Includes: + **/ +#include "commonheaders.h" +#include "svc_Reminder.h" + +/** + * name: MAnnivDate + * class: MAnnivDate + * desc: default constructor + * param: none + * return: nothing + **/ +MAnnivDate::MAnnivDate() +{ + Clear(); +} + +/** + * name: MAnnivDate + * class: MAnnivDate + * desc: constructor, which duplicates an existing anniversary date + * param: mda - anniversary date to copy + * return: nothing + **/ +MAnnivDate::MAnnivDate(MAnnivDate &mda) +{ + SetDate(mda); +} + +/** + * name: Clear + * class: MAnnivDate + * desc: set all attributes to default value + * param: none + * return: nothing + **/ +VOID MAnnivDate::Clear() +{ + ZeroDate(); + _wID = ANID_NONE; + _strDesc.clear(); + _strModule.clear(); + _wFlags = MADF_NONE; + _bRemind = BST_INDETERMINATE; + _wDaysEarlier = (WORD)-1; +} + +/** + * name: Set + * class: MAnnivDate + * desc: set new date + * param: none + * return: nothing + **/ +VOID MAnnivDate::SetDate(SYSTEMTIME &st) +{ + ZeroDate(); + Year(st.wYear); + Month(st.wMonth); + Day(st.wDay); +} + +/** + * name: Set + * class: MAnnivDate + * desc: duplicates the given anniversary date class + * param: none + * return: nothing + **/ +VOID MAnnivDate::SetDate(MAnnivDate &mda) +{ + SetDate(mda.SystemTime()); + _wID = mda.Id(); + _strDesc = mda.Description(); + _strModule = mda.Module(); + _wFlags = mda.Flags(); + _bRemind = mda.RemindOption(); + _wDaysEarlier = mda.RemindOffset(); +} + +/** + * name: IsValid + * class: MAnnivDate + * desc: compare the current date with the given one in st + * param: st - SYSTEMTIME to compare with + * return: number of days the st differs from the class value + **/ +__inline BOOLEAN MAnnivDate::IsValid() const +{ + return ( + Year() > 1600 && + Month() > 0 && Month() < 13 && + Day() > 0 && Day() <= DaysInMonth(Month()) + ); +} + +/** + * name: CompareDays + * class: MAnnivDate + * desc: compare the current date with the given one in st + * param: mt - MTime to compare with + * return: number of days the mt differs from the class value + **/ +INT MAnnivDate::CompareDays(MTime mt) const +{ + mt.Year(Year()); + return DayOfYear() - mt.DayOfYear(); +} + +/** + * name: Compare + * class: MAnnivDate + * desc: compare the current date with the given one in st + * param: st - SYSTEMTIME to compare with + * return: number of days the st differs from the class value + **/ +BOOLEAN MAnnivDate::IsEqual(const SYSTEMTIME &st) const +{ + return ( + Day() == st.wDay && + Month() == st.wMonth && + Year() == st.wYear + ); +} + +/** + * name: DateStamp + * class: MAnnivDate + * desc: return the current date encoded as an DWORD + * param: nothing + * return: DWORD encoded date + **/ +DWORD MAnnivDate::DateStamp() const +{ + DWORD dwStamp; + + if (!IsValid()) return 0; + + dwStamp = (Day() << 24) & 0xFF000000; + dwStamp |= (Month() << 16) & 0x00FF0000; + dwStamp |= Year() & 0x0000FFFF; + return dwStamp; +} + +/** + * name: DateStamp + * class: MAnnivDate + * desc: set the date according to a datestamp + * param: dwStamp - the dword encoded date + * return: nothing + **/ +VOID MAnnivDate::DateStamp(const DWORD dwStamp) +{ + Day((const WORD)((dwStamp & 0xFF000000) >> 24)); + Month((const WORD)((dwStamp & 0x00FF0000) >> 16)); + Year((const WORD)(dwStamp & 0x0000FFFF)); +} + +/** + * name: Age + * class: MAnnivDate + * desc: calculates the age according to the date of the class and current date + * param: pNow - optional pointer to a MTime class to specify a certain time to use for age calculation + * return: number of years the anniversary differs from now + **/ +INT MAnnivDate::Age(MTime *pNow) +{ + INT age = 0; + MTime now; + + if (!IsValid()) return -1; + + if (pNow) now = *pNow; + else now.GetLocalTime(); + + age = now.Year() - Year(); + if (age > 1 && CompareDays(now) > 0) + age--; + return age; +} + +/** + * name: Zodiac + * class: MAnnivDate + * desc: returns the zodiac icon and text for the date + * param: none + * return: structure, holding zodiac information + **/ +MZodiac MAnnivDate::Zodiac() +{ + static const struct TZodiac { + const WORD startDays; + const WORD endDays; + LPCTSTR szZodiac; + LPCSTR szZodiacIcon; + } zodiac[] = { + { 80, 110, LPGENT("Aries") , ICO_ZOD_ARIES }, // Widder + { 111, 140, LPGENT("Taurus") , ICO_ZOD_TAURUS }, // Stier + { 141, 172, LPGENT("Gemini") , ICO_ZOD_GEMINI }, // Zwillinge + { 173, 203, LPGENT("Cancer") , ICO_ZOD_CANCER }, // Krebs + { 204, 235, LPGENT("Leo") , ICO_ZOD_LEO }, // Lwe + { 236, 266, LPGENT("Virgo") , ICO_ZOD_VIRGO }, // Jungfrau + { 267, 296, LPGENT("Libra") , ICO_ZOD_LIBRA }, // Waage + { 297, 326, LPGENT("Scorpio") , ICO_ZOD_SCORPIO }, // Scorpion + { 327, 355, LPGENT("Sagittarius") , ICO_ZOD_SAGITTARIUS }, // Schtze + { 356, 364, LPGENT("Capricorn") , ICO_ZOD_CAPRICORN }, // Steinbock + { 1, 19, LPGENT("Capricorn") , ICO_ZOD_CAPRICORN }, // Steinbock + { 20, 49, LPGENT("Aquarius") , ICO_ZOD_AQUARIUS }, // Wassermann + { 50, 79, LPGENT("Pisces") , ICO_ZOD_PISCES }, // Fische + //{ 0, 0, LPGENT("Unknown") , ICO_ZOD_UNKNOWN }, // not found + { 0, 0, NULL , "" } // end of array + }; + const WORD wDays = DayOfYear(); + BYTE i; + MZodiac mZodiac; + + for (i = 0; i < 13 && (wDays < zodiac[i].startDays || wDays > zodiac[i].endDays); i++); + + mZodiac.hIcon = IcoLib_GetIcon(zodiac[i].szZodiacIcon); + mZodiac.pszName = zodiac[i].szZodiac; + return mZodiac; +} + +/*********************************************************************************************************** + * reading and writing options + ***********************************************************************************************************/ + +/** + * name: DBGetReminderOpts + * class: MAnnivDate + * desc: read reminder options for previously read date from database + * param: hContact - handle to a contact to read the date from + * return: 0 on success, 1 otherwise + **/ +INT MAnnivDate::DBGetReminderOpts(HANDLE hContact) +{ + if (!hContact || hContact == INVALID_HANDLE_VALUE) + return 1; + if (_wID == ANID_BIRTHDAY) { + _bRemind = DB::Setting::GetByte(hContact, USERINFO, SET_REMIND_BIRTHDAY_ENABLED, BST_INDETERMINATE); + _wDaysEarlier = DB::Setting::GetWord(hContact, USERINFO, SET_REMIND_BIRTHDAY_OFFSET, (WORD)-1); + } + else if (_wID <= ANID_LAST) { + CHAR pszSetting[MAXSETTING]; + + // read reminder option + mir_snprintf(pszSetting, MAXSETTING, "Anniv%dReminder", _wID); + _bRemind = DB::Setting::GetByte(hContact, Module(), pszSetting, BST_INDETERMINATE); + // read offset + mir_snprintf(pszSetting, MAXSETTING, "Anniv%dOffset", _wID); + _wDaysEarlier = DB::Setting::GetWord(hContact, Module(), pszSetting, (WORD)-1); + } + else { + _bRemind = BST_INDETERMINATE; + _wDaysEarlier = (WORD)-1; + } + return 0; +} + +/** + * name: DBWriteReminderOpts + * class: MAnnivDate + * desc: write reminder options for date to database + * param: hContact - handle to a contact to read the date from + * return: 0 on success, 1 otherwise + **/ +INT MAnnivDate::DBWriteReminderOpts(HANDLE hContact) +{ + if (!hContact || hContact == INVALID_HANDLE_VALUE) + return 1; + if (_wID == ANID_BIRTHDAY) { + if (_bRemind == BST_INDETERMINATE) DB::Setting::Delete(hContact, USERINFO, SET_REMIND_BIRTHDAY_ENABLED); + else DB::Setting::WriteByte(hContact, USERINFO, SET_REMIND_BIRTHDAY_ENABLED, _bRemind); + + if (_wDaysEarlier == (WORD)-1) DB::Setting::Delete(hContact, USERINFO, SET_REMIND_BIRTHDAY_OFFSET); + else DB::Setting::WriteWord(hContact, USERINFO, SET_REMIND_BIRTHDAY_OFFSET, _wDaysEarlier); + } + else if (_wID <= ANID_LAST) { + CHAR pszSetting[MAXSETTING]; + // read reminder option + mir_snprintf(pszSetting, MAXSETTING, "Anniv%dReminder", _wID); + if (_bRemind == BST_INDETERMINATE) DB::Setting::Delete(hContact, USERINFO, pszSetting); + else DB::Setting::WriteByte(hContact, USERINFO, pszSetting, _bRemind); + + // read offset + mir_snprintf(pszSetting, MAXSETTING, "Anniv%dOffset", _wID); + if (_wDaysEarlier == (WORD)-1) DB::Setting::Delete(hContact, USERINFO, pszSetting); + else DB::Setting::WriteWord(hContact, USERINFO, pszSetting, _wDaysEarlier); + } + return 0; +} + +/*********************************************************************************************************** + * reading, writing and deleting general date + ***********************************************************************************************************/ + +/** + * name: DBGetDate + * class: MAnnivDate + * desc: read a certain date from database + * param: hContact - handle to a contact to read the date from + * pszModule - module holding the date + * szDay - setting of the day to read + * szMonth - setting of the month to read + * szYear - setting of the year to read + * return: 0 on success, 1 otherwise + **/ +INT MAnnivDate::DBGetDate(HANDLE hContact, LPCSTR pszModule, LPCSTR szDay, LPCSTR szMonth, LPCSTR szYear) +{ + WORD wtmp; + + ZeroDate(); + + wtmp = DB::Setting::GetWord(hContact, pszModule, szYear, 0); + if (wtmp < 1601) return 1; + Year(wtmp); + + wtmp = DB::Setting::GetWord(hContact, pszModule, szMonth, 0); + if (wtmp > 0 && wtmp < 13) { + Month(wtmp); + + wtmp = DB::Setting::GetWord(hContact, pszModule, szDay, 0); + if (wtmp > 0 && wtmp <= DaysInMonth(Month())) { + Day(wtmp); + // date was correctly read from db + _strModule = pszModule; + return 0; + } + } + ZeroDate(); + return 1; +} + +/** + * name: DBWriteDate + * class: MAnnivDate + * desc: write a certain date from database + * param: hContact - handle to a contact to read the date from + * pszModule - module holding the date + * szDay - setting of the day to read + * szMonth - setting of the month to read + * szYear - setting of the year to read + * return: 0 on success, 1 otherwise + **/ +INT MAnnivDate::DBWriteDate(HANDLE hContact, LPCSTR pszModule, LPCSTR szDay, LPCSTR szMonth, LPCSTR szYear) +{ + return ( + DB::Setting::WriteByte(hContact, pszModule, szDay, (BYTE)Day()) || + DB::Setting::WriteByte(hContact, pszModule, szMonth, (BYTE)Month()) || + DB::Setting::WriteWord(hContact, pszModule, szYear, Year()) +); +} + +/** + * name: DBDeleteDate + * class: MAnnivDate + * desc: delete a certain date from database + * param: hContact - handle to a contact to read the date from + * pszModule - module holding the date + * szDay - setting of the day to read + * szMonth - setting of the month to read + * szYear - setting of the year to read + * return: 0 on success, 1 otherwise + **/ +INT MAnnivDate::DBDeleteDate(HANDLE hContact, LPCSTR pszModule, LPCSTR szDay, LPCSTR szMonth, LPCSTR szYear) const +{ + INT ret; + + ret = DB::Setting::Delete(hContact, pszModule, szDay); + ret &= DB::Setting::Delete(hContact, pszModule, szMonth); + ret &= DB::Setting::Delete(hContact, pszModule, szYear); + return ret; +} + +/*********************************************************************************************************** + * reading, writing and deleting general datestamp + ***********************************************************************************************************/ + +/** + * name: DBGetDateStamp + * class: MAnnivDate + * desc: Read a datestamp from database. A datestamp is an DWORD of the form . + * param: hContact - handle to a contact to read the datestamp from + * pszModule - module to read the datestamp from + * pszSetting - key used to identify the datestamp + * return: 0 on success, 1 otherwise + **/ +INT MAnnivDate::DBGetDateStamp(HANDLE hContact, LPCSTR pszModule, LPCSTR pszSetting) +{ + DBVARIANT dbv; + + if (DB::Setting::GetAsIs(hContact, pszModule, pszSetting, &dbv)) + return 1; + if (dbv.type != DBVT_DWORD) { + DB::Variant::Free(&dbv); + return 1; + } + DateStamp(dbv.dVal); + return IsValid() == 0; +} + +/** + * name: DBWriteDateStamp + * class: MAnnivDate + * desc: Write a datestamp to database. A datestamp is an DWORD of the form . + * param: hContact - handle to a contact to write the datestamp to + * pszModule - module to write the datestamp to + * pszSetting - key used to save the datestamp + * return: 0 on success, 1 otherwise + **/ +INT MAnnivDate::DBWriteDateStamp(HANDLE hContact, LPCSTR pszModule, LPCSTR pszSetting) +{ + DWORD dwStamp = DateStamp(); + + if (hContact == INVALID_HANDLE_VALUE || + pszModule == 0 || *pszModule == 0 || + pszSetting == 0 || *pszSetting == 0 || + dwStamp == 0) + { + return 1; + } + return DB::Setting::WriteDWord(hContact, pszModule, pszSetting, dwStamp); +} + +/*********************************************************************************************************** + * reading, writing and deleting birthday + ***********************************************************************************************************/ + +/** + * name: DBGetBirthDate + * class: MAnnivDate + * desc: try to read birthday date from all known modules + * param: hContact - handle to a contact to read the date from + * pszProto - basic protocol module + * return: 0 on success, 1 otherwise + **/ +INT MAnnivDate::DBGetBirthDate(HANDLE hContact, LPSTR pszProto) +{ + Clear(); + + // try to get birthday from any custom module + if ( !DBGetDate(hContact, USERINFO, SET_CONTACT_BIRTHDAY, SET_CONTACT_BIRTHMONTH, SET_CONTACT_BIRTHYEAR) || + !DBGetDate(hContact, MOD_MBIRTHDAY, SET_CONTACT_BIRTHDAY, SET_CONTACT_BIRTHMONTH, SET_CONTACT_BIRTHYEAR) || + !DBGetDate(hContact, SET_CONTACT_BIRTHDAY, SET_CONTACT_BIRTHDAY, SET_CONTACT_BIRTHMONTH, SET_CONTACT_BIRTHYEAR) || + !DBGetDate(hContact, USERINFO, SET_CONTACT_DOBD, SET_CONTACT_DOBM, SET_CONTACT_DOBY)) + { + SetFlags(MADF_HASCUSTOM); + } + // if pszProto is set to NULL, this will be scaned only incase the birthday date has not been found yet + else if (pszProto || (pszProto = DB::Contact::Proto(hContact)) != NULL) + { + // try to get birthday from basic protocol + if (!DBGetDate(hContact, pszProto, SET_CONTACT_BIRTHDAY, SET_CONTACT_BIRTHMONTH, SET_CONTACT_BIRTHYEAR)) + { + SetFlags(MADF_HASPROTO); + } + // try to get birthday date from metacontact's subcontact + else if (DB::Module::IsMetaAndScan(pszProto)) + { + const INT def = DB::MetaContact::SubDefNum(hContact); + HANDLE hSubContact; + + // try to get setting from the default subcontact first + if (def > -1 && def < INT_MAX) + { + hSubContact = DB::MetaContact::Sub(hContact, def); + if (hSubContact != NULL && !DBGetBirthDate(hSubContact, NULL)) + { + RemoveFlags(MADF_HASCUSTOM); + SetFlags(MADF_HASMETA); + } + } + + // scan all subcontacts for the setting + if (_wFlags == 0) + { + const INT cnt = DB::MetaContact::SubCount(hContact); + + if (cnt < INT_MAX) + { + INT i; + for (i = 0; i < cnt; i++) + { + if (i != def) + { + hSubContact = DB::MetaContact::Sub(hContact, i); + if (hSubContact != NULL && !DBGetBirthDate(hSubContact, NULL)) + { + RemoveFlags(MADF_HASCUSTOM); + SetFlags(MADF_HASMETA); + break; + } } } } } } + } + + if (_wFlags != 0) + { + _wID = ANID_BIRTHDAY; + _strDesc = TranslateT("Birthday"); + return 0; + } + return 1; +} + +/** + * name: DBMoveBirthDate + * class: MAnnivDate + * desc: keep the database clean + * param: hContact - handle to a contact to read the date from + * bOld - byte RemindBirthModule src + * bNew - byte RemindBirthModule dest + * return: 0 on success, 1 otherwise + **/ +// +INT MAnnivDate::DBMoveBirthDate(HANDLE hContact, BYTE bOld, BYTE bNew) { + Clear(); + switch(bOld) { + case 0: //MOD_MBIRTHDAY + if(!DBGetDate(hContact, MOD_MBIRTHDAY, SET_CONTACT_BIRTHDAY, SET_CONTACT_BIRTHMONTH, SET_CONTACT_BIRTHYEAR)) { + if(DBWriteDate(hContact, USERINFO, SET_CONTACT_BIRTHDAY, SET_CONTACT_BIRTHMONTH, SET_CONTACT_BIRTHYEAR)) + return 1; + DBDeleteDate(hContact, MOD_MBIRTHDAY, SET_CONTACT_BIRTHDAY, SET_CONTACT_BIRTHMONTH, SET_CONTACT_BIRTHYEAR); + DB::Setting::Delete(hContact, MOD_MBIRTHDAY, "BirthMode"); + } + break; + case 1: //USERINFO + if(!DBGetDate(hContact, USERINFO, SET_CONTACT_BIRTHDAY, SET_CONTACT_BIRTHMONTH, SET_CONTACT_BIRTHYEAR)) { + if(DBWriteDate(hContact, MOD_MBIRTHDAY, SET_CONTACT_BIRTHDAY, SET_CONTACT_BIRTHMONTH, SET_CONTACT_BIRTHYEAR)) + return 1; + DB::Setting::WriteByte(hContact, MOD_MBIRTHDAY, "BirthMode", 2); + DBDeleteDate(hContact, USERINFO, SET_CONTACT_BIRTHDAY, SET_CONTACT_BIRTHMONTH, SET_CONTACT_BIRTHYEAR); + } + break; + default: + return 1; + break; + } + return 0; +} + +/** + * name: DBWriteBirthDate + * class: MAnnivDate + * desc: write birthday date to desired module + * param: hContact - handle to a contact to read the date from + * pszProto - basic protocol module + * return: 0 on success, 1 otherwise + **/ +INT MAnnivDate::DBWriteBirthDate(HANDLE hContact) +{ + INT rc = 0; + LPCSTR pszModule = SvcReminderGetMyBirthdayModule(); + + rc = DBWriteDate(hContact, pszModule, SET_CONTACT_BIRTHDAY, SET_CONTACT_BIRTHMONTH, SET_CONTACT_BIRTHYEAR); + if (!rc) + { + if (!mir_strcmp(pszModule, MOD_MBIRTHDAY)) + { + DB::Setting::WriteByte(hContact, MOD_MBIRTHDAY, "BirthMode", 2); + } + + if ( + // only delete values from current contact's custom modules + !(_wFlags & (MADF_HASPROTO|MADF_HASMETA)) && + // check whether user wants this feature + DB::Setting::GetByte(SET_REMIND_SECUREBIRTHDAY, TRUE) && + !myGlobals.UseDbxTree) + { + // keep the database clean + + if (mir_strcmp(pszModule, MOD_MBIRTHDAY)!= 0) + { + DBDeleteDate(hContact, MOD_MBIRTHDAY, SET_CONTACT_BIRTHDAY, SET_CONTACT_BIRTHMONTH, SET_CONTACT_BIRTHYEAR); + DB::Setting::Delete(hContact, MOD_MBIRTHDAY, "BirthMode"); + } + else if (mir_strcmp(pszModule, USERINFO) !=0) + { + DBDeleteDate(hContact, USERINFO, SET_CONTACT_BIRTHDAY, SET_CONTACT_BIRTHMONTH, SET_CONTACT_BIRTHYEAR); + } + DBDeleteDate(hContact, SET_CONTACT_BIRTHDAY, SET_CONTACT_BIRTHDAY, SET_CONTACT_BIRTHMONTH, SET_CONTACT_BIRTHYEAR); + DBDeleteDate(hContact, USERINFO, SET_CONTACT_DOBD, SET_CONTACT_DOBM, SET_CONTACT_DOBY); + } + + rc = DB::Setting::WriteWord(hContact, USERINFO, SET_CONTACT_AGE, Age()); + } + return rc; +} + +/** + * name: DBDeleteBirthDate + * class: MAnnivDate + * desc: delete birthday date from desired module + * param: hContact - handle to a contact to read the date from + * pszProto - basic protocol module + * return: 0 on success, 1 otherwise + **/ +INT MAnnivDate::DBDeleteBirthDate(HANDLE hContact) +{ + return DBDeleteDate(hContact, Module(), SET_CONTACT_BIRTHDAY, SET_CONTACT_BIRTHMONTH, SET_CONTACT_BIRTHYEAR); +} + +/*********************************************************************************************************** + * reading, writing and deleting anniversary + ***********************************************************************************************************/ + +/** + * name: DBGetAnniversaryDate + * class: MAnnivDate + * desc: try to read anniversary date from userinfo module + * param: hContact - handle to a contact to read the date from + * pszProto - basic protocol module + * return: 0 on success, 1 otherwise + **/ +INT MAnnivDate::DBGetAnniversaryDate(HANDLE hContact, WORD iIndex) +{ + CHAR szStamp[MAXSETTING]; + DBVARIANT dbv; + INT rc; + + Clear(); + + // read date and convert older versions + mir_snprintf(szStamp, SIZEOF(szStamp), "Anniv%dDate", iIndex); + rc = DBGetDateStamp(hContact, USERINFO, szStamp); + if (!rc) + { + _strModule = USERINFO; + _wFlags |= MADF_HASCUSTOM; + _wID = iIndex; + + // read description + mir_snprintf(szStamp, SIZEOF(szStamp), "Anniv%dDesc", iIndex); + if (!DB::Setting::GetTString(hContact, USERINFO, szStamp, &dbv)) + { + _strDesc = dbv.ptszVal; + DB::Variant::Free(&dbv); + } + } + return rc; +} + +/** + * name: DBWriteAnniversaryDate + * class: MAnnivDate + * desc: write birthday date to desired module + * param: hContact - handle to a contact to read the date from + * pszProto - basic protocol module + * return: 0 on success, 1 otherwise + **/ +INT MAnnivDate::DBWriteAnniversaryDate(HANDLE hContact, WORD wIndex) +{ + INT ret = 0; + + // date can only be written to db as anniversary if it is not marked as birthday + if (wIndex <= ANID_LAST && _wID != ANID_BIRTHDAY) + { + CHAR pszSetting[MAXSETTING]; + + _wID = wIndex; + + mir_snprintf(pszSetting, SIZEOF(pszSetting), "Anniv%dDate", wIndex); + if (!DBWriteDateStamp(hContact, USERINFO, pszSetting)) + { + // write description + mir_snprintf(pszSetting, SIZEOF(pszSetting), "Anniv%dDesc", wIndex); + DB::Setting::WriteTString(hContact, USERINFO, pszSetting, (LPTSTR)Description()); + return 0; + } + // delete date if written incompletely + DB::Setting::Delete(hContact, USERINFO, pszSetting); + } + return 1; +} + +/*********************************************************************************************************** + * automatic backup service + ***********************************************************************************************************/ + +static WORD AskUser(HANDLE hContact, MAnnivDate *pOldCustomDate, MAnnivDate *pNewProtoDate) +{ + MSGBOX MB; + TCHAR szMsg[MAXDATASIZE]; + TCHAR szDate[MAX_PATH]; + TCHAR szoldDate[MAX_PATH]; + + pOldCustomDate->DateFormat(szoldDate, SIZEOF(szoldDate)); + pNewProtoDate->DateFormat(szDate, SIZEOF(szDate)); + + mir_sntprintf(szMsg, SIZEOF(szMsg), + TranslateT("%s provides a new birthday via protocol.\nIt is %s. The old one was %s.\n\nDo you want to use this as the new birthday for this contact?"), + DB::Contact::DisplayName(hContact), szDate, szoldDate + ); + + MB.cbSize = sizeof(MSGBOX); + MB.hParent = NULL; + MB.hiLogo = IcoLib_GetIcon(ICO_DLG_ANNIVERSARY); + MB.hiMsg = NULL; + MB.uType = MB_YESALLNO|MB_ICON_QUESTION|MB_INFOBAR|MB_NOPOPUP; + MB.ptszTitle = LPGENT("Update custom birthday"); + MB.ptszInfoText = LPGENT("Keeps your custom birthday up to date."); + MB.ptszMsg = szMsg; + return MsgBoxService(NULL, (LPARAM)&MB); +} + +/** + * name: BackupBirthday + * class: MAnnivDate + * desc: tries to read birthday date from protocol and compares it with the classes date + * param: hContact - handle to a contact to read the date from + * pszProto - basic protocol module + * return: 0 if backup was done, 1 otherwise + **/ +INT MAnnivDate::BackupBirthday(HANDLE hContact, LPSTR pszProto, const BOOLEAN bDontIgnoreAnything, PWORD lastAnswer) +{ + if (hContact) + { + // This birthday is a protocol based or metasubcontact's anniversary and no custom information exist, + // so directly back it up under all circumstances! + if ((_wFlags & MADF_HASPROTO) || (_wFlags & MADF_HASMETA)) + { + DBWriteDateStamp(hContact, USERINFO, SET_REMIND_BIRTHDAY_IGNORED); + DBWriteBirthDate(hContact); + } + // A custom birthday was set by user before and is not to be ignored + else if ((_wFlags & MADF_HASCUSTOM) && (bDontIgnoreAnything || !lastAnswer || (*lastAnswer != IDNONE))) + { + if (!pszProto) + { + pszProto = DB::Contact::Proto(hContact); + } + if (pszProto) + { + BOOLEAN bIsMeta = DB::Module::IsMeta(pszProto); + BOOLEAN bIsMetaSub = !bIsMeta && DB::MetaContact::IsSub(hContact); + BOOLEAN bWantBackup = FALSE; + MAnnivDate mdbNewProto; + MAnnivDate mdbIgnore; + HANDLE hSubContact; + + const INT nSubContactCount = (bIsMeta) ? DB::MetaContact::SubCount(hContact) : 0; + + bWantBackup = !mdbNewProto.DBGetDate(hContact, pszProto, SET_CONTACT_BIRTHDAY, SET_CONTACT_BIRTHMONTH, SET_CONTACT_BIRTHYEAR) + && !IsEqual(mdbNewProto.SystemTime()) + && (bDontIgnoreAnything || (DB::Setting::GetDWord(hContact, USERINFO, SET_REMIND_BIRTHDAY_IGNORED, 0) != mdbNewProto.DateStamp())) + && !bIsMetaSub; + + // allow backup only, if the custom setting differs from all meta subcontacts' protocol based settings, too. + for (INT i = 0; (i < nSubContactCount) && bWantBackup && bIsMeta; i++) + { + hSubContact = DB::MetaContact::Sub(hContact, i); + if (hSubContact && !mdbIgnore.DBGetDate(hSubContact, pszProto, SET_CONTACT_BIRTHDAY, SET_CONTACT_BIRTHMONTH, SET_CONTACT_BIRTHYEAR)) + { + bWantBackup = bWantBackup + && !IsEqual(mdbIgnore.SystemTime()) + && (bDontIgnoreAnything || (DB::Setting::GetDWord(hSubContact, USERINFO, SET_REMIND_BIRTHDAY_IGNORED, 0) != mdbIgnore.DateStamp())); + } + } + if (bWantBackup) + { + if (!lastAnswer || *lastAnswer != IDALL) + { + WORD rc = AskUser(hContact, this, &mdbNewProto); + if (lastAnswer) + { + *lastAnswer = rc; + } + if (IDYES != rc && IDALL != rc) + { + // special handling for metasubcontacts required?! + mdbNewProto.DBWriteDateStamp(hContact, USERINFO, SET_REMIND_BIRTHDAY_IGNORED); + bWantBackup = FALSE; + } + } + if (bWantBackup) + { + Set(mdbNewProto); + DBWriteDateStamp(hContact, USERINFO, SET_REMIND_BIRTHDAY_IGNORED); + DBWriteBirthDate(hContact); + + // update metasubcontacts + for (INT i = 0; i < nSubContactCount; i++) + { + hSubContact = DB::MetaContact::Sub(hContact, i); + if (hSubContact != NULL) + { + if (!mdbIgnore.DBGetDate(hSubContact, DB::Contact::Proto(hSubContact), SET_CONTACT_BIRTHDAY, SET_CONTACT_BIRTHMONTH, SET_CONTACT_BIRTHYEAR)) + { + mdbIgnore.DBWriteDateStamp(hSubContact, USERINFO, SET_REMIND_BIRTHDAY_IGNORED); + } + DBWriteBirthDate(hSubContact); + } + } + return 0; + } + } + } + } + /* + else if (mir_stricmp(Module(), SvcReminderGetMyBirthdayModule())) + { + DBWriteBirthDate(hContact); + } + */ + } + return 1; +} \ No newline at end of file -- cgit v1.2.3