From bf37d6655a27cc3ea5af5412c9717596c9d1c30f Mon Sep 17 00:00:00 2001 From: George Hazan Date: Fri, 19 Jun 2015 18:18:13 +0000 Subject: timezone api migrated to mir_core git-svn-id: http://svn.miranda-ng.org/main/trunk@14266 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- src/core/stdfile/src/filerecvdlg.cpp | 2 +- src/core/stdfile/src/main.cpp | 2 - src/core/stdhelp/src/main.cpp | 2 - src/core/stdidle/src/main.cpp | 2 - src/core/stdmsg/src/msgdialog.cpp | 10 +- src/core/stdmsg/src/msglog.cpp | 2 +- src/core/stdmsg/src/srmm.cpp | 3 - src/core/stduihist/src/history.cpp | 2 +- src/core/stduihist/src/main.cpp | 2 - src/core/stdurl/main.cpp | 2 - src/core/stdurl/urldialogs.cpp | 2 +- src/core/stduserinfo/src/main.cpp | 2 - src/core/stduserinfo/src/stdinfo.cpp | 6 +- src/mir_app/src/contacts.cpp | 4 +- src/mir_app/src/mir_app.def | 1 - src/mir_app/src/mir_app64.def | 1 - src/mir_app/src/timeutils.cpp | 103 ------ src/mir_app/src/timezones.cpp | 557 --------------------------------- src/mir_app/src/utils.cpp | 3 - src/mir_core/src/mir_core.def | 16 + src/mir_core/src/mir_core64.def | 16 + src/mir_core/src/miranda.cpp | 14 +- src/mir_core/src/stdafx.h | 2 + src/mir_core/src/timezones.cpp | 587 +++++++++++++++++++++++++++++++++++ 24 files changed, 639 insertions(+), 704 deletions(-) delete mode 100644 src/mir_app/src/timeutils.cpp delete mode 100644 src/mir_app/src/timezones.cpp create mode 100644 src/mir_core/src/timezones.cpp (limited to 'src') diff --git a/src/core/stdfile/src/filerecvdlg.cpp b/src/core/stdfile/src/filerecvdlg.cpp index a092b1449f..16edf1c4a0 100644 --- a/src/core/stdfile/src/filerecvdlg.cpp +++ b/src/core/stdfile/src/filerecvdlg.cpp @@ -254,7 +254,7 @@ INT_PTR CALLBACK DlgProcRecvFile(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM l else DestroyWindow(hwndDlg); TCHAR datetimestr[64]; - tmi.printTimeStamp(NULL, dbei.timestamp, _T("t d"), datetimestr, SIZEOF(datetimestr), 0); + TimeZone_PrintTimeStamp(NULL, dbei.timestamp, _T("t d"), datetimestr, SIZEOF(datetimestr), 0); SetDlgItemText(hwndDlg, IDC_DATE, datetimestr); char* szProto = GetContactProto(dat->hContact); diff --git a/src/core/stdfile/src/main.cpp b/src/core/stdfile/src/main.cpp index cd849b43b6..b49d593f10 100644 --- a/src/core/stdfile/src/main.cpp +++ b/src/core/stdfile/src/main.cpp @@ -24,7 +24,6 @@ with this program; if not, write to the Free Software Foundation, Inc., int LoadSendRecvFileModule(void); CLIST_INTERFACE* pcli; -TIME_API tmi; HINSTANCE hInst; int hLangpack; @@ -60,7 +59,6 @@ extern "C" __declspec(dllexport) const MUUID MirandaInterfaces[] = { MIID_SRFILE extern "C" int __declspec(dllexport) Load(void) { mir_getLP(&pluginInfo); - mir_getTMI(&tmi); mir_getCLI(); if ( IsWinVer7Plus()) diff --git a/src/core/stdhelp/src/main.cpp b/src/core/stdhelp/src/main.cpp index bd42b15c6d..d1a4729250 100644 --- a/src/core/stdhelp/src/main.cpp +++ b/src/core/stdhelp/src/main.cpp @@ -24,7 +24,6 @@ with this program; if not, write to the Free Software Foundation, Inc., int LoadHelpModule(void); CLIST_INTERFACE* pcli; -TIME_API tmi; HINSTANCE hInst; int hLangpack; @@ -58,7 +57,6 @@ extern "C" __declspec(dllexport) const MUUID MirandaInterfaces[] = { MIID_UIHELP extern "C" int __declspec(dllexport) Load(void) { mir_getLP(&pluginInfo); - mir_getTMI(&tmi); mir_getCLI(); LoadHelpModule(); diff --git a/src/core/stdidle/src/main.cpp b/src/core/stdidle/src/main.cpp index 6c06ad4be3..2f21ff9097 100644 --- a/src/core/stdidle/src/main.cpp +++ b/src/core/stdidle/src/main.cpp @@ -25,7 +25,6 @@ int LoadIdleModule(void); void UnloadIdleModule(void); CLIST_INTERFACE* pcli; -TIME_API tmi; HINSTANCE hInst; int hLangpack; @@ -59,7 +58,6 @@ extern "C" __declspec(dllexport) const MUUID MirandaInterfaces[] = { MIID_IDLE, extern "C" int __declspec(dllexport) Load(void) { mir_getLP(&pluginInfo); - mir_getTMI(&tmi); mir_getCLI(); LoadIdleModule(); diff --git a/src/core/stdmsg/src/msgdialog.cpp b/src/core/stdmsg/src/msgdialog.cpp index b3a9bc050a..c4ca134216 100644 --- a/src/core/stdmsg/src/msgdialog.cpp +++ b/src/core/stdmsg/src/msgdialog.cpp @@ -136,7 +136,7 @@ static void ShowTime(SrmmWindowData *dat) TCHAR buf[32]; unsigned i = (g_dat.flags & SMF_SHOWREADCHAR) ? 2 : 1; - tmi.printDateTime(dat->hTimeZone, _T("t"), buf, SIZEOF(buf), 0); + TimeZone_PrintDateTime(dat->hTimeZone, _T("t"), buf, SIZEOF(buf), 0); SendMessage(dat->hwndStatus, SB_SETTEXT, i, (LPARAM)buf); dat->wMinute = st.wMinute; } @@ -618,7 +618,7 @@ INT_PTR CALLBACK DlgProcMessage(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lP dat->hContact = newData->hContact; dat->bIsMeta = db_mc_isMeta(dat->hContact) != 0; - dat->hTimeZone = tmi.createByContact(dat->hContact, 0, TZF_KNOWNONLY); + dat->hTimeZone = TimeZone_CreateByContact(dat->hContact, 0, TZF_KNOWNONLY); dat->wMinute = 61; NotifyLocalWinEvent(dat->hContact, hwndDlg, MSG_WINDOW_EVT_OPENING); @@ -957,8 +957,8 @@ INT_PTR CALLBACK DlgProcMessage(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lP if (dat->lastMessage) { TCHAR date[64], time[64], fmt[128]; - tmi.printTimeStamp(NULL, dat->lastMessage, _T("d"), date, SIZEOF(date), 0); - tmi.printTimeStamp(NULL, dat->lastMessage, _T("t"), time, SIZEOF(time), 0); + TimeZone_PrintTimeStamp(NULL, dat->lastMessage, _T("d"), date, SIZEOF(date), 0); + TimeZone_PrintTimeStamp(NULL, dat->lastMessage, _T("t"), time, SIZEOF(time), 0); mir_sntprintf(fmt, SIZEOF(fmt), TranslateT("Last message received on %s at %s."), date, time); SendMessage(dat->hwndStatus, SB_SETTEXT, 0, (LPARAM)fmt); } @@ -1080,7 +1080,7 @@ INT_PTR CALLBACK DlgProcMessage(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lP break; case DM_NEWTIMEZONE: - dat->hTimeZone = tmi.createByContact(dat->hContact, 0, TZF_KNOWNONLY); + dat->hTimeZone = TimeZone_CreateByContact(dat->hContact, 0, TZF_KNOWNONLY); dat->wMinute = 61; SendMessage(hwndDlg, WM_SIZE, 0, 0); break; diff --git a/src/core/stdmsg/src/msglog.cpp b/src/core/stdmsg/src/msglog.cpp index 22fd62bf67..aa214357fc 100644 --- a/src/core/stdmsg/src/msglog.cpp +++ b/src/core/stdmsg/src/msglog.cpp @@ -293,7 +293,7 @@ static char *CreateRTFFromDbEvent(SrmmWindowData *dat, MCONTACT hContact, MEVENT else szFormat = g_dat.flags & SMF_SHOWDATE ? _T("d t") : _T("t"); - tmi.printTimeStamp(NULL, dbei.timestamp, szFormat, str, SIZEOF(str), 0); + TimeZone_PrintTimeStamp(NULL, dbei.timestamp, szFormat, str, SIZEOF(str), 0); AppendToBuffer(buffer, bufferEnd, bufferAlloced, " %s ", SetToStyle(dbei.flags & DBEF_SENT ? MSGFONTID_MYTIME : MSGFONTID_YOURTIME)); AppendToBufferWithRTF(buffer, bufferEnd, bufferAlloced, str); diff --git a/src/core/stdmsg/src/srmm.cpp b/src/core/stdmsg/src/srmm.cpp index b629c3598f..8136de9f46 100644 --- a/src/core/stdmsg/src/srmm.cpp +++ b/src/core/stdmsg/src/srmm.cpp @@ -28,8 +28,6 @@ CLIST_INTERFACE *pcli; HINSTANCE g_hInst; int hLangpack; -TIME_API tmi; - PLUGININFOEX pluginInfo = { sizeof(PLUGININFOEX), __PLUGIN_NAME, @@ -58,7 +56,6 @@ extern "C" __declspec(dllexport) const MUUID MirandaInterfaces[] = {MIID_SRMM, M extern "C" int __declspec(dllexport) Load(void) { - mir_getTMI(&tmi); mir_getLP(&pluginInfo); mir_getCLI(); diff --git a/src/core/stduihist/src/history.cpp b/src/core/stduihist/src/history.cpp index 0297875807..0748d76e54 100644 --- a/src/core/stduihist/src/history.cpp +++ b/src/core/stduihist/src/history.cpp @@ -164,7 +164,7 @@ static void FillHistoryThread(void* param) TCHAR str[200], eventText[256], strdatetime[64]; GetObjectSummary(&dbei, str, SIZEOF(str)); if (str[0]) { - tmi.printTimeStamp(NULL, dbei.timestamp, _T("d t"), strdatetime, SIZEOF(strdatetime), 0); + TimeZone_PrintTimeStamp(NULL, dbei.timestamp, _T("d t"), strdatetime, SIZEOF(strdatetime), 0); mir_sntprintf(eventText, SIZEOF(eventText), _T("%s: %s"), strdatetime, str); i = SendMessage(hwndList, LB_ADDSTRING, 0, (LPARAM)eventText); SendMessage(hwndList, LB_SETITEMDATA, i, (LPARAM)hDbEvent); diff --git a/src/core/stduihist/src/main.cpp b/src/core/stduihist/src/main.cpp index 76562307c3..dfb8a0d36a 100644 --- a/src/core/stduihist/src/main.cpp +++ b/src/core/stduihist/src/main.cpp @@ -24,7 +24,6 @@ with this program; if not, write to the Free Software Foundation, Inc., int LoadHistoryModule(void); CLIST_INTERFACE* pcli; -TIME_API tmi; HINSTANCE hInst; int hLangpack; @@ -58,7 +57,6 @@ extern "C" __declspec(dllexport) const MUUID MirandaInterfaces[] = { MIID_UIHIST extern "C" int __declspec(dllexport) Load(void) { mir_getLP(&pluginInfo); - mir_getTMI(&tmi); mir_getCLI(); LoadHistoryModule(); diff --git a/src/core/stdurl/main.cpp b/src/core/stdurl/main.cpp index 16caf83712..4351ea95c3 100644 --- a/src/core/stdurl/main.cpp +++ b/src/core/stdurl/main.cpp @@ -24,7 +24,6 @@ with this program; if not, write to the Free Software Foundation, Inc., int LoadSendRecvUrlModule(void); CLIST_INTERFACE* pcli; -TIME_API tmi; HINSTANCE hInst; int hLangpack; @@ -58,7 +57,6 @@ extern "C" __declspec(dllexport) const MUUID MirandaInterfaces[] = { MIID_SRURL, extern "C" int __declspec(dllexport) Load(void) { mir_getLP(&pluginInfo); - mir_getTMI(&tmi); mir_getCLI(); LoadSendRecvUrlModule(); diff --git a/src/core/stdurl/urldialogs.cpp b/src/core/stdurl/urldialogs.cpp index f65bf202b9..157725362b 100644 --- a/src/core/stdurl/urldialogs.cpp +++ b/src/core/stdurl/urldialogs.cpp @@ -114,7 +114,7 @@ INT_PTR CALLBACK DlgProcUrlRecv(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lP SendDlgItemMessage(hwndDlg, IDOK, BUTTONSETARROW, 1, 0); TCHAR str[128]; - tmi.printTimeStamp(NULL, dbei.timestamp, _T("t d"), str, SIZEOF(str), 0); + TimeZone_PrintTimeStamp(NULL, dbei.timestamp, _T("t d"), str, SIZEOF(str), 0); SetDlgItemText(hwndDlg, IDC_DATE, str); } diff --git a/src/core/stduserinfo/src/main.cpp b/src/core/stduserinfo/src/main.cpp index ea49811c26..6289d9b209 100644 --- a/src/core/stduserinfo/src/main.cpp +++ b/src/core/stduserinfo/src/main.cpp @@ -24,7 +24,6 @@ with this program; if not, write to the Free Software Foundation, Inc., int LoadUserInfoModule(void); CLIST_INTERFACE* pcli; -TIME_API tmi; HINSTANCE hInst; int hLangpack; @@ -58,7 +57,6 @@ extern "C" __declspec(dllexport) const MUUID MirandaInterfaces[] = {MIID_UIUSERI extern "C" int __declspec(dllexport) Load(void) { mir_getLP(&pluginInfo); - mir_getTMI(&tmi); mir_getCLI(); LoadUserInfoModule(); diff --git a/src/core/stduserinfo/src/stdinfo.cpp b/src/core/stduserinfo/src/stdinfo.cpp index 197d24440c..3ad3f9432c 100644 --- a/src/core/stduserinfo/src/stdinfo.cpp +++ b/src/core/stduserinfo/src/stdinfo.cpp @@ -241,7 +241,7 @@ static INT_PTR CALLBACK LocationDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, L TranslateDialogDefault(hwndDlg); SetTimer(hwndDlg, 1, 1000, NULL); - tmi.prepareList(lParam, NULL, GetDlgItem(hwndDlg, IDC_TIMEZONESELECT), TZF_PLF_CB); + TimeZone_PrepareList(lParam, NULL, GetDlgItem(hwndDlg, IDC_TIMEZONESELECT), TZF_PLF_CB); SendMessage(hwndDlg, WM_TIMER, 0, 0); break; @@ -250,7 +250,7 @@ static INT_PTR CALLBACK LocationDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, L MCONTACT hContact = (MCONTACT)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); if (hContact != NULL) { TCHAR szTime[80]; - if (tmi.printDateTimeByContact(hContact, _T("s"), szTime, SIZEOF(szTime), TZF_KNOWNONLY)) { + if (printDateTimeByContact(hContact, _T("s"), szTime, SIZEOF(szTime), TZF_KNOWNONLY)) { EnableWindow(GetDlgItem(hwndDlg, IDC_LOCALTIME), FALSE); SetDlgItemText(hwndDlg, IDC_LOCALTIME, TranslateT("")); } @@ -297,7 +297,7 @@ static INT_PTR CALLBACK LocationDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, L MCONTACT hContact = (MCONTACT)GetWindowLongPtr(hwndDlg, GWLP_USERDATA); SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0); - tmi.storeListResults(hContact, NULL, GetDlgItem(hwndDlg, IDC_TIMEZONESELECT), TZF_PLF_CB); + TimeZone_StoreListResult(hContact, NULL, GetDlgItem(hwndDlg, IDC_TIMEZONESELECT), TZF_PLF_CB); } } break; diff --git a/src/mir_app/src/contacts.cpp b/src/mir_app/src/contacts.cpp index 90ee313f47..b20b201228 100644 --- a/src/mir_app/src/contacts.cpp +++ b/src/mir_app/src/contacts.cpp @@ -344,9 +344,9 @@ static INT_PTR GetContactInfo(WPARAM, LPARAM lParam) case CNF_TIMEZONE: { - HANDLE hTz = tmi.createByContact(ci->hContact, 0, TZF_KNOWNONLY); + HANDLE hTz = TimeZone_CreateByContact(ci->hContact, 0, TZF_KNOWNONLY); if (hTz) { - LPTIME_ZONE_INFORMATION tzi = tmi.getTzi(hTz); + LPTIME_ZONE_INFORMATION tzi = TimeZone_GetInfo(hTz); int offset = tzi->Bias + tzi->StandardBias; char str[80]; diff --git a/src/mir_app/src/mir_app.def b/src/mir_app/src/mir_app.def index 4f7d8b0cc0..14e239b8f6 100644 --- a/src/mir_app/src/mir_app.def +++ b/src/mir_app/src/mir_app.def @@ -2,7 +2,6 @@ EXPORTS CallContactService @1 CallProtoService @2 -RecalculateTime @3 Skin_LoadProtoIcon @4 Skin_LoadIcon @5 Button_FreeIcon_IcoLib @6 diff --git a/src/mir_app/src/mir_app64.def b/src/mir_app/src/mir_app64.def index c5fd8c2d4e..26677f922c 100644 --- a/src/mir_app/src/mir_app64.def +++ b/src/mir_app/src/mir_app64.def @@ -2,7 +2,6 @@ EXPORTS CallContactService @1 CallProtoService @2 -RecalculateTime @3 Skin_LoadProtoIcon @4 Skin_LoadIcon @5 Button_FreeIcon_IcoLib @6 diff --git a/src/mir_app/src/timeutils.cpp b/src/mir_app/src/timeutils.cpp deleted file mode 100644 index 57afeff219..0000000000 --- a/src/mir_app/src/timeutils.cpp +++ /dev/null @@ -1,103 +0,0 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (ñ) 2012-15 Miranda NG project (http://miranda-ng.org), -Copyright (c) 2000-12 Miranda IM project, -all portions of this codebase are copyrighted to the people -listed in contributors.txt. - -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. - -implements services to handle location - based timezones, instead of -simple UTC offsets. -*/ - -#include "stdafx.h" - -// KB167296 -void UnixTimeToFileTime(mir_time ts, LPFILETIME pft) -{ - unsigned __int64 ll = UInt32x32To64(ts, 10000000) + 116444736000000000i64; - pft->dwLowDateTime = (DWORD)ll; - pft->dwHighDateTime = ll >> 32; -} - -mir_time FileTimeToUnixTime(LPFILETIME pft) -{ - unsigned __int64 ll = (unsigned __int64)pft->dwHighDateTime << 32 | pft->dwLowDateTime; - ll -= 116444736000000000i64; - return (mir_time)(ll / 10000000); -} - -void FormatTime(const SYSTEMTIME *st, const TCHAR *szFormat, TCHAR *szDest, int cbDest) -{ - if (szDest == NULL || cbDest == 0) return; - - CMString tszTemp; - - for (const TCHAR* pFormat = szFormat; *pFormat; ++pFormat) { - DWORD fmt = 0; - bool date = false, iso = false; - switch (*pFormat) { - case 't': - fmt = TIME_NOSECONDS; - date = false; - break; - - case 's': - fmt = 0; - date = false; - break; - - case 'm': - fmt = TIME_NOMINUTESORSECONDS; - date = false; - break; - - case 'd': - fmt = DATE_SHORTDATE; - date = true; - break; - - case 'D': - fmt = DATE_LONGDATE; - date = true; - break; - - case 'I': - iso = true; - break; - - default: - tszTemp.AppendChar(*pFormat); - continue; - } - - TCHAR dateTimeStr[64]; - if (iso) - tszTemp.AppendFormat(_T("%d-%02d-%02dT%02d:%02d:%02dZ"), st->wYear, st->wMonth, st->wDay, st->wHour, st->wMinute, st->wSecond); - else if (date) { - GetDateFormat(LOCALE_USER_DEFAULT, fmt, st, NULL, dateTimeStr, SIZEOF(dateTimeStr)); - tszTemp.Append(dateTimeStr); - } - else { - GetTimeFormat(LOCALE_USER_DEFAULT, fmt, st, NULL, dateTimeStr, SIZEOF(dateTimeStr)); - tszTemp.Append(dateTimeStr); - } - } - - _tcsncpy_s(szDest, cbDest, tszTemp, _TRUNCATE); -} diff --git a/src/mir_app/src/timezones.cpp b/src/mir_app/src/timezones.cpp deleted file mode 100644 index d95fef6169..0000000000 --- a/src/mir_app/src/timezones.cpp +++ /dev/null @@ -1,557 +0,0 @@ -/* - -Miranda NG: the free IM client for Microsoft* Windows* - -Copyright (ñ) 2012-15 Miranda NG project (http://miranda-ng.org), -Copyright (c) 2000-12 Miranda IM project, -all portions of this codebase are copyrighted to the people -listed in contributors.txt. - -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. - -implements services to handle location - based timezones, instead of -simple UTC offsets. -*/ - -#include "stdafx.h" - -TIME_API tmi; - -typedef DWORD (WINAPI *pfnGetDynamicTimeZoneInformation_t)(DYNAMIC_TIME_ZONE_INFORMATION *pdtzi); -static pfnGetDynamicTimeZoneInformation_t pfnGetDynamicTimeZoneInformation; - -struct REG_TZI_FORMAT -{ - LONG Bias; - LONG StandardBias; - LONG DaylightBias; - SYSTEMTIME StandardDate; - SYSTEMTIME DaylightDate; -}; - -#define MIM_TZ_DISPLAYLEN 128 - -struct MIM_TIMEZONE -{ - unsigned hash; - int offset; - - TCHAR tszName[MIM_TZ_NAMELEN]; // windows name for the time zone - wchar_t szDisplay[MIM_TZ_DISPLAYLEN]; // more descriptive display name (that's what usually appears in dialogs) - // every hour should be sufficient. - TIME_ZONE_INFORMATION tzi; - - static int compareBias(const MIM_TIMEZONE* p1, const MIM_TIMEZONE* p2) - { return p2->tzi.Bias - p1->tzi.Bias; } -}; - -struct TZ_INT_INFO -{ - DWORD timestamp; // last time updated - MIM_TIMEZONE myTZ; // set to my own timezone -}; - -static TZ_INT_INFO myInfo; - -static OBJLIST g_timezones(55, NumericKeySortT); -static LIST g_timezonesBias(55, MIM_TIMEZONE::compareBias); - -void FormatTime(const SYSTEMTIME *st, const TCHAR *szFormat, TCHAR *szDest, int cbDest); -void UnixTimeToFileTime(mir_time ts, LPFILETIME pft); -mir_time FileTimeToUnixTime(LPFILETIME pft); - -#define fnSystemTimeToTzSpecificLocalTime SystemTimeToTzSpecificLocalTime - -static int timeapiGetTimeZoneTime(HANDLE hTZ, SYSTEMTIME *st) -{ - if (st == NULL) return 1; - - MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ; - if (tz == UTC_TIME_HANDLE) - GetSystemTime(st); - else if (tz && tz != &myInfo.myTZ) { - SYSTEMTIME sto; - GetSystemTime(&sto); - return !fnSystemTimeToTzSpecificLocalTime(&tz->tzi, &sto, st); - } - else - GetLocalTime(st); - - return 0; -} - -static LPCTSTR timeapiGetTzName(HANDLE hTZ) -{ - MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ; - if (tz == NULL) - return myInfo.myTZ.tszName; - else if (tz == UTC_TIME_HANDLE) - return _T("UTC"); - - return tz->tszName; -} - -static LPCTSTR timeapiGetTzDescription(LPCTSTR TZname) -{ - for (int i = 0; i < g_timezonesBias.getCount(); i++) { - MIM_TIMEZONE *tz = g_timezonesBias[i]; - - if (!mir_tstrcmp(tz->tszName, TZname)) - return tz->szDisplay; - } - return _T(""); -} - -static void CalcTsOffset(MIM_TIMEZONE *tz) -{ - SYSTEMTIME st, stl; - GetSystemTime(&st); - - FILETIME ft; - SystemTimeToFileTime(&st, &ft); - mir_time ts1 = FileTimeToUnixTime(&ft); - - if (!fnSystemTimeToTzSpecificLocalTime(&tz->tzi, &st, &stl)) - return; - - SystemTimeToFileTime(&stl, &ft); - mir_time ts2 = FileTimeToUnixTime(&ft); - - tz->offset = ts2 - ts1; -} - -static bool IsSameTime(MIM_TIMEZONE *tz) -{ - SYSTEMTIME st, stl; - - if (tz == &myInfo.myTZ) - return true; - - timeapiGetTimeZoneTime(tz, &stl); - timeapiGetTimeZoneTime(NULL, &st); - - return st.wHour == stl.wHour && st.wMinute == stl.wMinute; -} - -static HANDLE timeapiGetInfoByName(LPCTSTR tszName, DWORD dwFlags) -{ - if (tszName == NULL) - return (dwFlags & (TZF_DIFONLY | TZF_KNOWNONLY)) ? NULL : &myInfo.myTZ; - - if (mir_tstrcmp(myInfo.myTZ.tszName, tszName) == 0) - return (dwFlags & TZF_DIFONLY) ? NULL : &myInfo.myTZ; - - MIM_TIMEZONE tzsearch; - tzsearch.hash = mir_hashstrT(tszName); - - MIM_TIMEZONE *tz = g_timezones.find(&tzsearch); - if (tz == NULL) - return (dwFlags & (TZF_DIFONLY | TZF_KNOWNONLY)) ? NULL : &myInfo.myTZ; - - if (dwFlags & TZF_DIFONLY) - return IsSameTime(tz) ? NULL : tz; - - return tz; -} - -static HANDLE timeapiGetInfoByContact(MCONTACT hContact, LPCSTR szModule, DWORD dwFlags) -{ - if (hContact == NULL && szModule == NULL) - return (dwFlags & (TZF_DIFONLY | TZF_KNOWNONLY)) ? NULL : &myInfo.myTZ; - - if (szModule == NULL) szModule = "UserInfo"; - - DBVARIANT dbv; - if (!db_get_ts(hContact, szModule, "TzName", &dbv)) { - HANDLE res = timeapiGetInfoByName(dbv.ptszVal, dwFlags); - db_free(&dbv); - if (res) return res; - } - - signed char timezone = (signed char)db_get_b(hContact, szModule, "Timezone", -1); - if (timezone == -1) { - char *szProto = GetContactProto(hContact); - if (!db_get_ts(hContact, szProto, "TzName", &dbv)) { - HANDLE res = timeapiGetInfoByName(dbv.ptszVal, dwFlags); - db_free(&dbv); - if (res) return res; - } - timezone = (signed char)db_get_b(hContact, szProto, "Timezone", -1); - } - - if (timezone != -1) { - MIM_TIMEZONE tzsearch; - tzsearch.tzi.Bias = timezone * 30; - if (myInfo.myTZ.tzi.Bias == tzsearch.tzi.Bias) { - if (dwFlags & TZF_DIFONLY) return NULL; - return &myInfo.myTZ; - } - - int i = g_timezonesBias.getIndex(&tzsearch); - while (i >= 0 && g_timezonesBias[i]->tzi.Bias == tzsearch.tzi.Bias) --i; - - int delta = LONG_MAX; - for (int j = ++i; j < g_timezonesBias.getCount() && g_timezonesBias[j]->tzi.Bias == tzsearch.tzi.Bias; ++j) { - int delta1 = abs(g_timezonesBias[j]->tzi.DaylightDate.wMonth - myInfo.myTZ.tzi.DaylightDate.wMonth); - if (delta1 <= delta) { - delta = delta1; - i = j; - } - } - - if (i >= 0) { - MIM_TIMEZONE *tz = g_timezonesBias[i]; - return ((dwFlags & TZF_DIFONLY) && IsSameTime(tz)) ? NULL : tz; - } - } - return (dwFlags & (TZF_DIFONLY | TZF_KNOWNONLY)) ? NULL : &myInfo.myTZ; -} - -static void timeapiSetInfoByContact(MCONTACT hContact, LPCSTR szModule, HANDLE hTZ) -{ - if (szModule == NULL) szModule = "UserInfo"; - - MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ; - if (tz) { - db_set_ts(hContact, szModule, "TzName", tz->tszName); - db_set_b(hContact, szModule, "Timezone", (char)((tz->tzi.Bias + tz->tzi.StandardBias) / 30)); - } - else { - db_unset(hContact, szModule, "TzName"); - db_unset(hContact, szModule, "Timezone"); - } -} - -static int timeapiPrintDateTime(HANDLE hTZ, LPCTSTR szFormat, LPTSTR szDest, int cbDest, DWORD dwFlags) -{ - MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ; - if (tz == NULL && (dwFlags & (TZF_DIFONLY | TZF_KNOWNONLY))) - return 1; - - SYSTEMTIME st; - if (timeapiGetTimeZoneTime(tz, &st)) - return 1; - - FormatTime(&st, szFormat, szDest, cbDest); - return 0; -} - -static int timeapiPrintTimeStamp(HANDLE hTZ, mir_time ts, LPCTSTR szFormat, LPTSTR szDest, int cbDest, DWORD dwFlags) -{ - MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ; - if (tz == NULL && (dwFlags & (TZF_DIFONLY | TZF_KNOWNONLY))) - return 1; - - if (tz == NULL) - tz = &myInfo.myTZ; - - FILETIME ft; - if (tz == UTC_TIME_HANDLE) - UnixTimeToFileTime(ts, &ft); - else { - if (tz->offset == INT_MIN) - CalcTsOffset(tz); - - UnixTimeToFileTime(ts + tz->offset, &ft); - } - - SYSTEMTIME st; - FileTimeToSystemTime(&ft, &st); - - FormatTime(&st, szFormat, szDest, cbDest); - return 0; -} - -static LPTIME_ZONE_INFORMATION timeapiGetTzi(HANDLE hTZ) -{ - MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ; - return tz ? &tz->tzi : &myInfo.myTZ.tzi; -} - -static mir_time timeapiTimeStampToTimeZoneTimeStamp(HANDLE hTZ, mir_time ts) -{ - MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ; - if (tz == NULL) - tz = &myInfo.myTZ; - - if (tz == UTC_TIME_HANDLE) - return ts; - - if (tz->offset == INT_MIN) - CalcTsOffset(tz); - - return ts + tz->offset; -} - -struct ListMessages -{ - UINT addStr, getSel, setSel, getData, setData; -}; - -static const ListMessages lbMessages = { LB_ADDSTRING, LB_GETCURSEL, LB_SETCURSEL, LB_GETITEMDATA, LB_SETITEMDATA }; -static const ListMessages cbMessages = { CB_ADDSTRING, CB_GETCURSEL, CB_SETCURSEL, CB_GETITEMDATA, CB_SETITEMDATA }; - -static const ListMessages* GetListMessages(HWND hWnd, DWORD dwFlags) -{ - if (hWnd == NULL) - return NULL; - - if (!(dwFlags & (TZF_PLF_CB | TZF_PLF_LB))) { - TCHAR tszClassName[128]; - GetClassName(hWnd, tszClassName, SIZEOF(tszClassName)); - if (!mir_tstrcmpi(tszClassName, _T("COMBOBOX"))) - dwFlags |= TZF_PLF_CB; - else if (!mir_tstrcmpi(tszClassName, _T("LISTBOX"))) - dwFlags |= TZF_PLF_LB; - } - if (dwFlags & TZF_PLF_CB) - return &cbMessages; - else if (dwFlags & TZF_PLF_LB) - return &lbMessages; - else - return NULL; -} - -/////////////////////////////////////////////////////////////////////////////// - -static int timeapiSelectListItem(MCONTACT hContact, LPCSTR szModule, HWND hWnd, DWORD dwFlags) -{ - const ListMessages *lstMsg = GetListMessages(hWnd, dwFlags); - if (lstMsg == NULL) - return -1; - - if (szModule == NULL) szModule = "UserInfo"; - - int iSelection = 0; - ptrT tszName(db_get_tsa(hContact, szModule, "TzName")); - if (tszName != NULL) { - unsigned hash = mir_hashstrT(tszName); - for (int i = 0; i < g_timezonesBias.getCount(); i++) { - if (hash == g_timezonesBias[i]->hash) { - iSelection = i + 1; - break; - } - } - } - else { - signed char cBias = db_get_b(hContact, szModule, "Timezone", -100); - if (cBias != -100) { - int iBias = cBias * 30; - for (int i = 0; i < g_timezonesBias.getCount(); i++) { - if (iBias == g_timezonesBias[i]->tzi.Bias) { - iSelection = i + 1; - break; - } - } - } - } - - SendMessage(hWnd, lstMsg->setSel, iSelection, 0); - return iSelection; -} - -static int timeapiPrepareList(MCONTACT hContact, LPCSTR szModule, HWND hWnd, DWORD dwFlags) -{ - const ListMessages *lstMsg = GetListMessages(hWnd, dwFlags); - if (lstMsg == NULL) - return 0; - - SendMessage(hWnd, lstMsg->addStr, 0, (LPARAM)TranslateT("")); - - for (int i = 0; i < g_timezonesBias.getCount(); i++) { - MIM_TIMEZONE *tz = g_timezonesBias[i]; - - SendMessage(hWnd, lstMsg->addStr, 0, (LPARAM)tz->szDisplay); - SendMessage(hWnd, lstMsg->setData, i + 1, (LPARAM)tz); - } - - return timeapiSelectListItem(hContact, szModule, hWnd, dwFlags); -} - -static void timeapiStoreListResult(MCONTACT hContact, LPCSTR szModule, HWND hWnd, DWORD dwFlags) -{ - if (szModule == NULL) szModule = "UserInfo"; - - const ListMessages *lstMsg = GetListMessages(hWnd, dwFlags); - if (lstMsg) { - LRESULT offset = SendMessage(hWnd, lstMsg->getSel, 0, 0); - if (offset > 0) { - MIM_TIMEZONE *tz = (MIM_TIMEZONE*)SendMessage(hWnd, lstMsg->getData, offset, 0); - if ((INT_PTR)tz != CB_ERR && tz != NULL) - timeapiSetInfoByContact(hContact, szModule, tz); - } - else timeapiSetInfoByContact(hContact, szModule, NULL); - } -} - -/////////////////////////////////////////////////////////////////////////////// - -static INT_PTR GetTimeApi(WPARAM, LPARAM lParam) -{ - TIME_API* tmi = (TIME_API*)lParam; - if (tmi == NULL) - return FALSE; - - if (tmi->cbSize != sizeof(TIME_API)) - return FALSE; - - tmi->createByName = timeapiGetInfoByName; - tmi->createByContact = timeapiGetInfoByContact; - tmi->storeByContact = timeapiSetInfoByContact; - - tmi->printDateTime = timeapiPrintDateTime; - tmi->printTimeStamp = timeapiPrintTimeStamp; - - tmi->prepareList = timeapiPrepareList; - tmi->selectListItem = timeapiSelectListItem; - tmi->storeListResults = timeapiStoreListResult; - - tmi->getTimeZoneTime = timeapiGetTimeZoneTime; - tmi->timeStampToTimeZoneTimeStamp = timeapiTimeStampToTimeZoneTimeStamp; - tmi->getTzi = timeapiGetTzi; - tmi->getTzName = timeapiGetTzName; - tmi->getTzDescription = timeapiGetTzDescription; - - return TRUE; -} - -static INT_PTR TimestampToLocal(WPARAM wParam, LPARAM) -{ - return timeapiTimeStampToTimeZoneTimeStamp(NULL, (mir_time)wParam); -} - -static INT_PTR TimestampToStringT(WPARAM wParam, LPARAM lParam) -{ - DBTIMETOSTRINGT *tts = (DBTIMETOSTRINGT*)lParam; - if (tts != NULL) - timeapiPrintTimeStamp(NULL, (mir_time)wParam, tts->szFormat, tts->szDest, tts->cbDest, 0); - return 0; -} - -static INT_PTR TimestampToStringA(WPARAM wParam, LPARAM lParam) -{ - DBTIMETOSTRING *tts = (DBTIMETOSTRING*)lParam; - if (tts != NULL) { - TCHAR *szDest = (TCHAR*)alloca(tts->cbDest*sizeof(TCHAR)); - timeapiPrintTimeStamp(NULL, (mir_time)wParam, _A2T(tts->szFormat), szDest, tts->cbDest, 0); - WideCharToMultiByte(CP_ACP, 0, szDest, -1, tts->szDest, tts->cbDest, NULL, NULL); - } - return 0; -} - -void GetLocalizedString(HKEY hSubKey, const TCHAR *szName, wchar_t *szBuf, DWORD cbLen) -{ - DWORD dwLength = cbLen * sizeof(wchar_t); - RegQueryValueEx(hSubKey, szName, NULL, NULL, (unsigned char *)szBuf, &dwLength); - szBuf[min(dwLength / sizeof(TCHAR), cbLen - 1)] = 0; -} - -extern "C" void RecalculateTime(void) -{ - GetTimeZoneInformation(&myInfo.myTZ.tzi); - myInfo.timestamp = time(NULL); - myInfo.myTZ.offset = INT_MIN; - - bool found = false; - DYNAMIC_TIME_ZONE_INFORMATION dtzi; - - if (pfnGetDynamicTimeZoneInformation && pfnGetDynamicTimeZoneInformation(&dtzi) != TIME_ZONE_ID_INVALID) { - TCHAR *myTzKey = mir_u2t(dtzi.TimeZoneKeyName); - _tcsncpy_s(myInfo.myTZ.tszName, myTzKey, _TRUNCATE); - mir_free(myTzKey); - found = true; - } - - for (int i = 0; i < g_timezones.getCount(); i++) { - MIM_TIMEZONE &tz = g_timezones[i]; - if (tz.offset != INT_MIN) - tz.offset = INT_MIN; - - if (!found) { - if (!mir_wstrcmp(tz.tzi.StandardName, myInfo.myTZ.tzi.StandardName) || !mir_wstrcmp(tz.tzi.DaylightName, myInfo.myTZ.tzi.DaylightName)) { - _tcsncpy_s(myInfo.myTZ.tszName, tz.tszName, _TRUNCATE); - found = true; - } - } - } -} - -void InitTimeZones(void) -{ - REG_TZI_FORMAT tzi; - HKEY hKey; - - const TCHAR *tszKey = _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones"); - - /* - * use GetDynamicTimeZoneInformation() on Vista+ - this will return a structure with - * the registry key name, so finding our own time zone later will be MUCH easier for - * localized systems or systems with a MUI pack installed - */ - if (IsWinVerVistaPlus()) - pfnGetDynamicTimeZoneInformation = (pfnGetDynamicTimeZoneInformation_t)GetProcAddress(GetModuleHandle(_T("kernel32")), "GetDynamicTimeZoneInformation"); - - if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, tszKey, 0, KEY_ENUMERATE_SUB_KEYS, &hKey)) { - DWORD dwIndex = 0; - HKEY hSubKey; - TCHAR tszName[MIM_TZ_NAMELEN]; - - DWORD dwSize = SIZEOF(tszName); - while (ERROR_NO_MORE_ITEMS != RegEnumKeyEx(hKey, dwIndex++, tszName, &dwSize, NULL, NULL, 0, NULL)) { - if (ERROR_SUCCESS == RegOpenKeyEx(hKey, tszName, 0, KEY_QUERY_VALUE, &hSubKey)) { - dwSize = sizeof(tszName); - - DWORD dwLength = sizeof(tzi); - if (ERROR_SUCCESS != RegQueryValueEx(hSubKey, _T("TZI"), NULL, NULL, (unsigned char *)&tzi, &dwLength)) - continue; - - MIM_TIMEZONE *tz = new MIM_TIMEZONE; - - tz->tzi.Bias = tzi.Bias; - tz->tzi.StandardDate = tzi.StandardDate; - tz->tzi.StandardBias = tzi.StandardBias; - tz->tzi.DaylightDate = tzi.DaylightDate; - tz->tzi.DaylightBias = tzi.DaylightBias; - - mir_tstrcpy(tz->tszName, tszName); - tz->hash = mir_hashstrT(tszName); - tz->offset = INT_MIN; - - GetLocalizedString(hSubKey, _T("Display"), tz->szDisplay, SIZEOF(tz->szDisplay)); - GetLocalizedString(hSubKey, _T("Std"), tz->tzi.StandardName, SIZEOF(tz->tzi.StandardName)); - GetLocalizedString(hSubKey, _T("Dlt"), tz->tzi.DaylightName, SIZEOF(tz->tzi.DaylightName)); - - g_timezones.insert(tz); - g_timezonesBias.insert(tz); - - RegCloseKey(hSubKey); - } - dwSize = SIZEOF(tszName); - } - RegCloseKey(hKey); - } - - RecalculateTime(); - - CreateServiceFunction(MS_SYSTEM_GET_TMI, GetTimeApi); - - CreateServiceFunction(MS_DB_TIME_TIMESTAMPTOLOCAL, TimestampToLocal); - CreateServiceFunction(MS_DB_TIME_TIMESTAMPTOSTRINGT, TimestampToStringT); - - CreateServiceFunction(MS_DB_TIME_TIMESTAMPTOSTRING, TimestampToStringA); - - tmi.cbSize = sizeof(tmi); - GetTimeApi(0, (LPARAM)&tmi); -} diff --git a/src/mir_app/src/utils.cpp b/src/mir_app/src/utils.cpp index 2b96d5f4cf..cba82ce12d 100644 --- a/src/mir_app/src/utils.cpp +++ b/src/mir_app/src/utils.cpp @@ -34,8 +34,6 @@ int InitHyperlink(void); int InitColourPicker(void); void InitXmlApi(void); -void InitTimeZones(void); - int InitCrypt(void); void UninitCrypt(void); @@ -384,7 +382,6 @@ int LoadUtilsModule(void) InitPathUtils(); InitColourPicker(); InitXmlApi(); - InitTimeZones(); InitCrypt(); return 0; } diff --git a/src/mir_core/src/mir_core.def b/src/mir_core/src/mir_core.def index f693d41233..70ee0c1c1d 100644 --- a/src/mir_core/src/mir_core.def +++ b/src/mir_core/src/mir_core.def @@ -953,3 +953,19 @@ Utils_AssertInsideScreen @1110 Utils_RestoreWindowPosition @1111 Utils_SaveWindowPosition @1112 mir_getLP @1113 +TimeZone_CreateByContact @1114 +TimeZone_CreateByName @1115 +TimeZone_GetDescription @1116 +TimeZone_GetInfo @1117 +TimeZone_GetName @1118 +TimeZone_GetTimeZoneTime @1119 +TimeZone_PrepareList @1120 +TimeZone_PrintDateTime @1121 +TimeZone_PrintTimeStamp @1122 +TimeZone_SelectListItem @1123 +TimeZone_StoreByContact @1124 +TimeZone_StoreListResult @1125 +TimeZone_ToLocal @1126 +TimeZone_ToString @1127 +TimeZone_ToStringW @1128 +TimeZone_UtcToLocal @1129 diff --git a/src/mir_core/src/mir_core64.def b/src/mir_core/src/mir_core64.def index eadbef2572..cc345a6ca8 100644 --- a/src/mir_core/src/mir_core64.def +++ b/src/mir_core/src/mir_core64.def @@ -953,3 +953,19 @@ Utils_AssertInsideScreen @1110 Utils_RestoreWindowPosition @1111 Utils_SaveWindowPosition @1112 mir_getLP @1113 +TimeZone_CreateByContact @1114 +TimeZone_CreateByName @1115 +TimeZone_GetDescription @1116 +TimeZone_GetInfo @1117 +TimeZone_GetName @1118 +TimeZone_GetTimeZoneTime @1119 +TimeZone_PrepareList @1120 +TimeZone_PrintDateTime @1121 +TimeZone_PrintTimeStamp @1122 +TimeZone_SelectListItem @1123 +TimeZone_StoreByContact @1124 +TimeZone_StoreListResult @1125 +TimeZone_ToLocal @1126 +TimeZone_ToString @1127 +TimeZone_ToStringW @1128 +TimeZone_UtcToLocal @1129 diff --git a/src/mir_core/src/miranda.cpp b/src/mir_core/src/miranda.cpp index 53091dc2c9..fa99d1d8db 100644 --- a/src/mir_core/src/miranda.cpp +++ b/src/mir_core/src/miranda.cpp @@ -28,7 +28,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. HWND hAPCWindow = NULL; int InitPathUtils(void); -void (*RecalculateTime)(void); +void RecalculateTime(void); void CheckLogs(); void InitLogs(); @@ -36,6 +36,7 @@ void UninitLogs(); void InitWinver(); void InitMetaContacts(); +void InitTimeZones(); int hLangpack = 0; HINSTANCE hInst = 0; @@ -57,7 +58,7 @@ static LRESULT CALLBACK APCWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lP if (msg == WM_TIMER) CheckLogs(); - if (msg == WM_TIMECHANGE && RecalculateTime) + if (msg == WM_TIMECHANGE) RecalculateTime(); return DefWindowProc(hwnd, msg, wParam, lParam); @@ -73,7 +74,6 @@ static void LoadCoreModule(void) hAPCWindow = CreateWindowEx(0, _T("ComboLBox"), NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL); SetClassLongPtr(hAPCWindow, GCL_STYLE, GetClassLongPtr(hAPCWindow, GCL_STYLE) | CS_DROPSHADOW); DestroyWindow(hAPCWindow); - hAPCWindow = NULL; hAPCWindow = CreateWindowEx(0, _T("STATIC"), NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL); SetWindowLongPtr(hAPCWindow, GWLP_WNDPROC, (LONG_PTR)APCWndProc); @@ -81,16 +81,10 @@ static void LoadCoreModule(void) hStackMutex = CreateMutex(NULL, FALSE, NULL); hThreadQueueEmpty = CreateEvent(NULL, TRUE, TRUE, NULL); - #ifdef _WIN64 - HMODULE mirInst = GetModuleHandleA("miranda64.exe"); - #else - HMODULE mirInst = GetModuleHandleA("miranda32.exe"); - #endif - RecalculateTime = (void (*)()) GetProcAddress(mirInst, "RecalculateTime"); - InitWinver(); InitPathUtils(); InitLogs(); + InitTimeZones(); InitialiseModularEngine(); InitMetaContacts(); } diff --git a/src/mir_core/src/stdafx.h b/src/mir_core/src/stdafx.h index 359230ab17..eb5f1ac352 100644 --- a/src/mir_core/src/stdafx.h +++ b/src/mir_core/src/stdafx.h @@ -57,6 +57,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. #include #include #include +#include +#include #include "miranda.h" diff --git a/src/mir_core/src/timezones.cpp b/src/mir_core/src/timezones.cpp new file mode 100644 index 0000000000..b9510f2a71 --- /dev/null +++ b/src/mir_core/src/timezones.cpp @@ -0,0 +1,587 @@ +/* + +Miranda NG: the free IM client for Microsoft* Windows* + +Copyright (ñ) 2012-15 Miranda NG project (http://miranda-ng.org), +Copyright (c) 2000-12 Miranda IM project, +all portions of this codebase are copyrighted to the people +listed in contributors.txt. + +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. + +implements services to handle location - based timezones, instead of +simple UTC offsets. +*/ + +#include "stdafx.h" + +typedef DWORD (WINAPI *pfnGetDynamicTimeZoneInformation_t)(DYNAMIC_TIME_ZONE_INFORMATION *pdtzi); +static pfnGetDynamicTimeZoneInformation_t pfnGetDynamicTimeZoneInformation; + +struct REG_TZI_FORMAT +{ + LONG Bias; + LONG StandardBias; + LONG DaylightBias; + SYSTEMTIME StandardDate; + SYSTEMTIME DaylightDate; +}; + +#define MIM_TZ_DISPLAYLEN 128 + +struct MIM_TIMEZONE +{ + unsigned hash; + int offset; + + TCHAR tszName[MIM_TZ_NAMELEN]; // windows name for the time zone + wchar_t szDisplay[MIM_TZ_DISPLAYLEN]; // more descriptive display name (that's what usually appears in dialogs) + // every hour should be sufficient. + TIME_ZONE_INFORMATION tzi; + + static int compareBias(const MIM_TIMEZONE* p1, const MIM_TIMEZONE* p2) + { return p2->tzi.Bias - p1->tzi.Bias; + } +}; + +struct TZ_INT_INFO +{ + DWORD timestamp; // last time updated + MIM_TIMEZONE myTZ; // set to my own timezone +}; + +static TZ_INT_INFO myInfo; + +static OBJLIST g_timezones(55, NumericKeySortT); +static LIST g_timezonesBias(55, MIM_TIMEZONE::compareBias); + +// KB167296 +void UnixTimeToFileTime(mir_time ts, LPFILETIME pft) +{ + unsigned __int64 ll = UInt32x32To64(ts, 10000000) + 116444736000000000i64; + pft->dwLowDateTime = (DWORD)ll; + pft->dwHighDateTime = ll >> 32; +} + +mir_time FileTimeToUnixTime(LPFILETIME pft) +{ + unsigned __int64 ll = (unsigned __int64)pft->dwHighDateTime << 32 | pft->dwLowDateTime; + ll -= 116444736000000000i64; + return (mir_time)(ll / 10000000); +} + +void FormatTime(const SYSTEMTIME *st, const TCHAR *szFormat, TCHAR *szDest, size_t cbDest) +{ + if (szDest == NULL || cbDest == 0) return; + + CMString tszTemp; + + for (const TCHAR* pFormat = szFormat; *pFormat; ++pFormat) { + DWORD fmt = 0; + bool date = false, iso = false; + switch (*pFormat) { + case 't': + fmt = TIME_NOSECONDS; + date = false; + break; + + case 's': + fmt = 0; + date = false; + break; + + case 'm': + fmt = TIME_NOMINUTESORSECONDS; + date = false; + break; + + case 'd': + fmt = DATE_SHORTDATE; + date = true; + break; + + case 'D': + fmt = DATE_LONGDATE; + date = true; + break; + + case 'I': + iso = true; + break; + + default: + tszTemp.AppendChar(*pFormat); + continue; + } + + TCHAR dateTimeStr[64]; + if (iso) + tszTemp.AppendFormat(_T("%d-%02d-%02dT%02d:%02d:%02dZ"), st->wYear, st->wMonth, st->wDay, st->wHour, st->wMinute, st->wSecond); + else if (date) { + GetDateFormat(LOCALE_USER_DEFAULT, fmt, st, NULL, dateTimeStr, SIZEOF(dateTimeStr)); + tszTemp.Append(dateTimeStr); + } + else { + GetTimeFormat(LOCALE_USER_DEFAULT, fmt, st, NULL, dateTimeStr, SIZEOF(dateTimeStr)); + tszTemp.Append(dateTimeStr); + } + } + + _tcsncpy_s(szDest, cbDest, tszTemp, _TRUNCATE); +} + +#define fnSystemTimeToTzSpecificLocalTime SystemTimeToTzSpecificLocalTime + +MIR_CORE_DLL(int) TimeZone_GetTimeZoneTime(HANDLE hTZ, SYSTEMTIME *st) +{ + if (st == NULL) return 1; + + MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ; + if (tz == UTC_TIME_HANDLE) + GetSystemTime(st); + else if (tz && tz != &myInfo.myTZ) { + SYSTEMTIME sto; + GetSystemTime(&sto); + return !fnSystemTimeToTzSpecificLocalTime(&tz->tzi, &sto, st); + } + else + GetLocalTime(st); + + return 0; +} + +MIR_CORE_DLL(LPCTSTR) TimeZone_GetName(HANDLE hTZ) +{ + MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ; + if (tz == NULL) + return myInfo.myTZ.tszName; + else if (tz == UTC_TIME_HANDLE) + return _T("UTC"); + + return tz->tszName; +} + +MIR_CORE_DLL(LPCTSTR) TimeZone_GetDescription(LPCTSTR TZname) +{ + for (int i = 0; i < g_timezonesBias.getCount(); i++) { + MIM_TIMEZONE *tz = g_timezonesBias[i]; + + if (!mir_tstrcmp(tz->tszName, TZname)) + return tz->szDisplay; + } + return _T(""); +} + +static void CalcTsOffset(MIM_TIMEZONE *tz) +{ + SYSTEMTIME st, stl; + GetSystemTime(&st); + + FILETIME ft; + SystemTimeToFileTime(&st, &ft); + mir_time ts1 = FileTimeToUnixTime(&ft); + + if (!fnSystemTimeToTzSpecificLocalTime(&tz->tzi, &st, &stl)) + return; + + SystemTimeToFileTime(&stl, &ft); + mir_time ts2 = FileTimeToUnixTime(&ft); + + tz->offset = ts2 - ts1; +} + +static bool IsSameTime(MIM_TIMEZONE *tz) +{ + SYSTEMTIME st, stl; + + if (tz == &myInfo.myTZ) + return true; + + TimeZone_GetTimeZoneTime(tz, &stl); + TimeZone_GetTimeZoneTime(NULL, &st); + + return st.wHour == stl.wHour && st.wMinute == stl.wMinute; +} + +MIR_CORE_DLL(HANDLE) TimeZone_CreateByName(LPCTSTR tszName, DWORD dwFlags) +{ + if (tszName == NULL) + return (dwFlags & (TZF_DIFONLY | TZF_KNOWNONLY)) ? NULL : &myInfo.myTZ; + + if (mir_tstrcmp(myInfo.myTZ.tszName, tszName) == 0) + return (dwFlags & TZF_DIFONLY) ? NULL : &myInfo.myTZ; + + MIM_TIMEZONE tzsearch; + tzsearch.hash = mir_hashstrT(tszName); + + MIM_TIMEZONE *tz = g_timezones.find(&tzsearch); + if (tz == NULL) + return (dwFlags & (TZF_DIFONLY | TZF_KNOWNONLY)) ? NULL : &myInfo.myTZ; + + if (dwFlags & TZF_DIFONLY) + return IsSameTime(tz) ? NULL : tz; + + return tz; +} + +MIR_CORE_DLL(HANDLE) TimeZone_CreateByContact(MCONTACT hContact, LPCSTR szModule, DWORD dwFlags) +{ + if (hContact == NULL && szModule == NULL) + return (dwFlags & (TZF_DIFONLY | TZF_KNOWNONLY)) ? NULL : &myInfo.myTZ; + + if (szModule == NULL) szModule = "UserInfo"; + + DBVARIANT dbv; + if (!db_get_ts(hContact, szModule, "TzName", &dbv)) { + HANDLE res = TimeZone_CreateByName(dbv.ptszVal, dwFlags); + db_free(&dbv); + if (res) return res; + } + + signed char timezone = (signed char)db_get_b(hContact, szModule, "Timezone", -1); + if (timezone == -1) { + char *szProto = GetContactProto(hContact); + if (!db_get_ts(hContact, szProto, "TzName", &dbv)) { + HANDLE res = TimeZone_CreateByName(dbv.ptszVal, dwFlags); + db_free(&dbv); + if (res) return res; + } + timezone = (signed char)db_get_b(hContact, szProto, "Timezone", -1); + } + + if (timezone != -1) { + MIM_TIMEZONE tzsearch; + tzsearch.tzi.Bias = timezone * 30; + if (myInfo.myTZ.tzi.Bias == tzsearch.tzi.Bias) { + if (dwFlags & TZF_DIFONLY) return NULL; + return &myInfo.myTZ; + } + + int i = g_timezonesBias.getIndex(&tzsearch); + while (i >= 0 && g_timezonesBias[i]->tzi.Bias == tzsearch.tzi.Bias) --i; + + int delta = LONG_MAX; + for (int j = ++i; j < g_timezonesBias.getCount() && g_timezonesBias[j]->tzi.Bias == tzsearch.tzi.Bias; ++j) { + int delta1 = abs(g_timezonesBias[j]->tzi.DaylightDate.wMonth - myInfo.myTZ.tzi.DaylightDate.wMonth); + if (delta1 <= delta) { + delta = delta1; + i = j; + } + } + + if (i >= 0) { + MIM_TIMEZONE *tz = g_timezonesBias[i]; + return ((dwFlags & TZF_DIFONLY) && IsSameTime(tz)) ? NULL : tz; + } + } + return (dwFlags & (TZF_DIFONLY | TZF_KNOWNONLY)) ? NULL : &myInfo.myTZ; +} + +MIR_CORE_DLL(void) TimeZone_StoreByContact(MCONTACT hContact, LPCSTR szModule, HANDLE hTZ) +{ + if (szModule == NULL) szModule = "UserInfo"; + + MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ; + if (tz) { + db_set_ts(hContact, szModule, "TzName", tz->tszName); + db_set_b(hContact, szModule, "Timezone", (char)((tz->tzi.Bias + tz->tzi.StandardBias) / 30)); + } + else { + db_unset(hContact, szModule, "TzName"); + db_unset(hContact, szModule, "Timezone"); + } +} + +MIR_CORE_DLL(int) TimeZone_PrintDateTime(HANDLE hTZ, LPCTSTR szFormat, LPTSTR szDest, size_t cbDest, DWORD dwFlags) +{ + MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ; + if (tz == NULL && (dwFlags & (TZF_DIFONLY | TZF_KNOWNONLY))) + return 1; + + SYSTEMTIME st; + if (TimeZone_GetTimeZoneTime(tz, &st)) + return 1; + + FormatTime(&st, szFormat, szDest, cbDest); + return 0; +} + +MIR_CORE_DLL(int) TimeZone_PrintTimeStamp(HANDLE hTZ, mir_time ts, LPCTSTR szFormat, LPTSTR szDest, size_t cbDest, DWORD dwFlags) +{ + MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ; + if (tz == NULL && (dwFlags & (TZF_DIFONLY | TZF_KNOWNONLY))) + return 1; + + if (tz == NULL) + tz = &myInfo.myTZ; + + FILETIME ft; + if (tz == UTC_TIME_HANDLE) + UnixTimeToFileTime(ts, &ft); + else { + if (tz->offset == INT_MIN) + CalcTsOffset(tz); + + UnixTimeToFileTime(ts + tz->offset, &ft); + } + + SYSTEMTIME st; + FileTimeToSystemTime(&ft, &st); + + FormatTime(&st, szFormat, szDest, cbDest); + return 0; +} + +MIR_CORE_DLL(LPTIME_ZONE_INFORMATION) TimeZone_GetInfo(HANDLE hTZ) +{ + MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ; + return tz ? &tz->tzi : &myInfo.myTZ.tzi; +} + +MIR_CORE_DLL(mir_time) TimeZone_UtcToLocal(HANDLE hTZ, mir_time ts) +{ + MIM_TIMEZONE *tz = (MIM_TIMEZONE*)hTZ; + if (tz == NULL) + tz = &myInfo.myTZ; + + if (tz == UTC_TIME_HANDLE) + return ts; + + if (tz->offset == INT_MIN) + CalcTsOffset(tz); + + return ts + tz->offset; +} + +/////////////////////////////////////////////////////////////////////////////// + +struct ListMessages +{ + UINT addStr, getSel, setSel, getData, setData; +}; + +static const ListMessages lbMessages = { LB_ADDSTRING, LB_GETCURSEL, LB_SETCURSEL, LB_GETITEMDATA, LB_SETITEMDATA }; +static const ListMessages cbMessages = { CB_ADDSTRING, CB_GETCURSEL, CB_SETCURSEL, CB_GETITEMDATA, CB_SETITEMDATA }; + +static const ListMessages* GetListMessages(HWND hWnd, DWORD dwFlags) +{ + if (hWnd == NULL) + return NULL; + + if (!(dwFlags & (TZF_PLF_CB | TZF_PLF_LB))) { + TCHAR tszClassName[128]; + GetClassName(hWnd, tszClassName, SIZEOF(tszClassName)); + if (!mir_tstrcmpi(tszClassName, _T("COMBOBOX"))) + dwFlags |= TZF_PLF_CB; + else if (!mir_tstrcmpi(tszClassName, _T("LISTBOX"))) + dwFlags |= TZF_PLF_LB; + } + if (dwFlags & TZF_PLF_CB) + return &cbMessages; + else if (dwFlags & TZF_PLF_LB) + return &lbMessages; + else + return NULL; +} + +/////////////////////////////////////////////////////////////////////////////// + +MIR_CORE_DLL(int) TimeZone_SelectListItem(MCONTACT hContact, LPCSTR szModule, HWND hWnd, DWORD dwFlags) +{ + const ListMessages *lstMsg = GetListMessages(hWnd, dwFlags); + if (lstMsg == NULL) + return -1; + + if (szModule == NULL) szModule = "UserInfo"; + + int iSelection = 0; + ptrT tszName(db_get_tsa(hContact, szModule, "TzName")); + if (tszName != NULL) { + unsigned hash = mir_hashstrT(tszName); + for (int i = 0; i < g_timezonesBias.getCount(); i++) { + if (hash == g_timezonesBias[i]->hash) { + iSelection = i + 1; + break; + } + } + } + else { + signed char cBias = db_get_b(hContact, szModule, "Timezone", -100); + if (cBias != -100) { + int iBias = cBias * 30; + for (int i = 0; i < g_timezonesBias.getCount(); i++) { + if (iBias == g_timezonesBias[i]->tzi.Bias) { + iSelection = i + 1; + break; + } + } + } + } + + SendMessage(hWnd, lstMsg->setSel, iSelection, 0); + return iSelection; +} + +MIR_CORE_DLL(int) TimeZone_PrepareList(MCONTACT hContact, LPCSTR szModule, HWND hWnd, DWORD dwFlags) +{ + const ListMessages *lstMsg = GetListMessages(hWnd, dwFlags); + if (lstMsg == NULL) + return 0; + + SendMessage(hWnd, lstMsg->addStr, 0, (LPARAM)TranslateT("")); + + for (int i = 0; i < g_timezonesBias.getCount(); i++) { + MIM_TIMEZONE *tz = g_timezonesBias[i]; + + SendMessage(hWnd, lstMsg->addStr, 0, (LPARAM)tz->szDisplay); + SendMessage(hWnd, lstMsg->setData, i + 1, (LPARAM)tz); + } + + return TimeZone_SelectListItem(hContact, szModule, hWnd, dwFlags); +} + +MIR_CORE_DLL(void) TimeZone_StoreListResult(MCONTACT hContact, LPCSTR szModule, HWND hWnd, DWORD dwFlags) +{ + if (szModule == NULL) szModule = "UserInfo"; + + const ListMessages *lstMsg = GetListMessages(hWnd, dwFlags); + if (lstMsg) { + LRESULT offset = SendMessage(hWnd, lstMsg->getSel, 0, 0); + if (offset > 0) { + MIM_TIMEZONE *tz = (MIM_TIMEZONE*)SendMessage(hWnd, lstMsg->getData, offset, 0); + if ((INT_PTR)tz != CB_ERR && tz != NULL) + TimeZone_StoreByContact(hContact, szModule, tz); + } + else TimeZone_StoreByContact(hContact, szModule, NULL); + } +} + +/////////////////////////////////////////////////////////////////////////////// + +MIR_CORE_DLL(DWORD) TimeZone_ToLocal(DWORD timeVal) +{ + return TimeZone_UtcToLocal(NULL, (mir_time)timeVal); +} + +MIR_CORE_DLL(char*) TimeZone_ToString(mir_time timeVal, const char *szFormat, char *szDest, size_t cchDest) +{ + TCHAR *szTemp = (TCHAR*)alloca(cchDest*sizeof(TCHAR)); + TimeZone_PrintTimeStamp(NULL, timeVal, _A2T(szFormat), szTemp, cchDest, 0); + WideCharToMultiByte(CP_ACP, 0, szTemp, -1, szDest, (int)cchDest, NULL, NULL); + return szDest; +} + +MIR_CORE_DLL(wchar_t*) TimeZone_ToStringW(mir_time timeVal, const wchar_t *wszFormat, wchar_t *wszDest, size_t cchDest) +{ + TimeZone_PrintTimeStamp(NULL, timeVal, wszFormat, wszDest, cchDest, 0); + return wszDest; +} + +/////////////////////////////////////////////////////////////////////////////// + +void GetLocalizedString(HKEY hSubKey, const TCHAR *szName, wchar_t *szBuf, DWORD cbLen) +{ + DWORD dwLength = cbLen * sizeof(wchar_t); + RegQueryValueEx(hSubKey, szName, NULL, NULL, (unsigned char *)szBuf, &dwLength); + szBuf[min(dwLength / sizeof(TCHAR), cbLen - 1)] = 0; +} + +void RecalculateTime(void) +{ + GetTimeZoneInformation(&myInfo.myTZ.tzi); + myInfo.timestamp = time(NULL); + myInfo.myTZ.offset = INT_MIN; + + bool found = false; + DYNAMIC_TIME_ZONE_INFORMATION dtzi; + + if (pfnGetDynamicTimeZoneInformation && pfnGetDynamicTimeZoneInformation(&dtzi) != TIME_ZONE_ID_INVALID) { + TCHAR *myTzKey = mir_u2t(dtzi.TimeZoneKeyName); + _tcsncpy_s(myInfo.myTZ.tszName, myTzKey, _TRUNCATE); + mir_free(myTzKey); + found = true; + } + + for (int i = 0; i < g_timezones.getCount(); i++) { + MIM_TIMEZONE &tz = g_timezones[i]; + if (tz.offset != INT_MIN) + tz.offset = INT_MIN; + + if (!found) { + if (!mir_wstrcmp(tz.tzi.StandardName, myInfo.myTZ.tzi.StandardName) || !mir_wstrcmp(tz.tzi.DaylightName, myInfo.myTZ.tzi.DaylightName)) { + _tcsncpy_s(myInfo.myTZ.tszName, tz.tszName, _TRUNCATE); + found = true; + } + } + } +} + +void InitTimeZones(void) +{ + REG_TZI_FORMAT tzi; + HKEY hKey; + + const TCHAR *tszKey = _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones"); + + /* + * use GetDynamicTimeZoneInformation() on Vista+ - this will return a structure with + * the registry key name, so finding our own time zone later will be MUCH easier for + * localized systems or systems with a MUI pack installed + */ + if (IsWinVerVistaPlus()) + pfnGetDynamicTimeZoneInformation = (pfnGetDynamicTimeZoneInformation_t)GetProcAddress(GetModuleHandle(_T("kernel32")), "GetDynamicTimeZoneInformation"); + + if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, tszKey, 0, KEY_ENUMERATE_SUB_KEYS, &hKey)) { + DWORD dwIndex = 0; + HKEY hSubKey; + TCHAR tszName[MIM_TZ_NAMELEN]; + + DWORD dwSize = SIZEOF(tszName); + while (ERROR_NO_MORE_ITEMS != RegEnumKeyEx(hKey, dwIndex++, tszName, &dwSize, NULL, NULL, 0, NULL)) { + if (ERROR_SUCCESS == RegOpenKeyEx(hKey, tszName, 0, KEY_QUERY_VALUE, &hSubKey)) { + dwSize = sizeof(tszName); + + DWORD dwLength = sizeof(tzi); + if (ERROR_SUCCESS != RegQueryValueEx(hSubKey, _T("TZI"), NULL, NULL, (unsigned char *)&tzi, &dwLength)) + continue; + + MIM_TIMEZONE *tz = new MIM_TIMEZONE; + + tz->tzi.Bias = tzi.Bias; + tz->tzi.StandardDate = tzi.StandardDate; + tz->tzi.StandardBias = tzi.StandardBias; + tz->tzi.DaylightDate = tzi.DaylightDate; + tz->tzi.DaylightBias = tzi.DaylightBias; + + mir_tstrcpy(tz->tszName, tszName); + tz->hash = mir_hashstrT(tszName); + tz->offset = INT_MIN; + + GetLocalizedString(hSubKey, _T("Display"), tz->szDisplay, SIZEOF(tz->szDisplay)); + GetLocalizedString(hSubKey, _T("Std"), tz->tzi.StandardName, SIZEOF(tz->tzi.StandardName)); + GetLocalizedString(hSubKey, _T("Dlt"), tz->tzi.DaylightName, SIZEOF(tz->tzi.DaylightName)); + + g_timezones.insert(tz); + g_timezonesBias.insert(tz); + + RegCloseKey(hSubKey); + } + dwSize = SIZEOF(tszName); + } + RegCloseKey(hKey); + } + + RecalculateTime(); +} -- cgit v1.2.3