summaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'plugins')
-rw-r--r--plugins/Alarms/alarm_win.cpp430
-rw-r--r--plugins/Alarms/alarm_win.h22
-rw-r--r--plugins/Alarms/alarmlist.cpp782
-rw-r--r--plugins/Alarms/alarmlist.h148
-rw-r--r--plugins/Alarms/alarms.cpp339
-rw-r--r--plugins/Alarms/alarms.h11
-rw-r--r--plugins/Alarms/alarms_10.sln23
-rw-r--r--plugins/Alarms/alarms_10.vcxproj217
-rw-r--r--plugins/Alarms/alarms_10.vcxproj.filters121
-rw-r--r--plugins/Alarms/clock.icobin0 -> 8038 bytes
-rw-r--r--plugins/Alarms/common.h75
-rw-r--r--plugins/Alarms/frame.cpp679
-rw-r--r--plugins/Alarms/frame.h20
-rw-r--r--plugins/Alarms/glyph.c537
-rw-r--r--plugins/Alarms/glyph.h21
-rw-r--r--plugins/Alarms/green.icobin0 -> 2550 bytes
-rw-r--r--plugins/Alarms/icons.cpp91
-rw-r--r--plugins/Alarms/icons.h12
-rw-r--r--plugins/Alarms/iconttbdown.icobin0 -> 894 bytes
-rw-r--r--plugins/Alarms/iconttbup.icobin0 -> 894 bytes
-rw-r--r--plugins/Alarms/init.c185
-rw-r--r--plugins/Alarms/main.h0
-rw-r--r--plugins/Alarms/options.cpp1238
-rw-r--r--plugins/Alarms/options.h41
-rw-r--r--plugins/Alarms/resource.h91
-rw-r--r--plugins/Alarms/resource.rc244
-rw-r--r--plugins/Alarms/time_utils.cpp25
-rw-r--r--plugins/Alarms/time_utils.h7
-rw-r--r--plugins/Alarms/timewindow.cpp420
-rw-r--r--plugins/Alarms/timewindow.h14
-rw-r--r--plugins/Alarms/trigger.cpp106
-rw-r--r--plugins/Alarms/trigger.h11
-rw-r--r--plugins/Alarms/yellow.icobin0 -> 2550 bytes
33 files changed, 5910 insertions, 0 deletions
diff --git a/plugins/Alarms/alarm_win.cpp b/plugins/Alarms/alarm_win.cpp
new file mode 100644
index 0000000000..250dcdaf31
--- /dev/null
+++ b/plugins/Alarms/alarm_win.cpp
@@ -0,0 +1,430 @@
+#include "common.h"
+#include "alarm_win.h"
+
+#define ID_TIMER_SOUND 10101
+#define SOUND_REPEAT_PERIOD 5000 // milliseconds
+#define SPEACH_REPEAT_PERIOD 15000 // milliseconds
+HANDLE hAlarmWindowList = 0;
+
+HMODULE hUserDll;
+BOOL (WINAPI *MySetLayeredWindowAttributes)(HWND,COLORREF,BYTE,DWORD) = 0;
+BOOL (WINAPI *MyAnimateWindow)(HWND hWnd,DWORD dwTime,DWORD dwFlags) = 0;
+
+FontID title_font_id, window_font_id;
+ColourID bk_colour_id;
+HFONT hTitleFont = 0, hWindowFont = 0;
+COLORREF title_font_colour, window_font_colour;
+HBRUSH hBackgroundBrush = 0;
+
+#define WMU_SETFONTS (WM_USER + 61)
+#define WMU_REFRESH (WM_USER + 62)
+#define WMU_ADDSNOOZER (WM_USER + 63)
+
+int win_num = 0;
+typedef struct WindowData_tag {
+ ALARM *alarm;
+ POINT p;
+ bool moving;
+ int win_num;
+} WindowData;
+
+void SetAlarmWinOptions() {
+ WindowList_Broadcast(hAlarmWindowList, WMU_SETOPT, IDC_SNOOZE, 0);
+}
+
+bool TransparencyEnabled() {
+ return MySetLayeredWindowAttributes != 0;
+}
+
+BOOL CALLBACK DlgProcAlarm(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) {
+
+ switch ( msg ) {
+ case WM_INITDIALOG:
+ {
+ TranslateDialogDefault( hwndDlg );
+ Utils_RestoreWindowPositionNoSize(hwndDlg, 0, MODULE, "Notify");
+ SetFocus(GetDlgItem(hwndDlg, IDC_SNOOZE));
+
+ WindowData *wd = new WindowData;
+ wd->moving = false;
+ wd->alarm = 0;
+ wd->win_num = win_num++;
+
+ if(wd->win_num > 0) {
+ RECT r;
+ GetWindowRect(hwndDlg, &r);
+ r.top += 20;
+ r.left += 20;
+
+ SetWindowPos(hwndDlg, 0, r.left, r.top, 0, 0, SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
+ Utils_SaveWindowPosition(hwndDlg, 0, MODULE, "Notify");
+ }
+
+ SetWindowLong(hwndDlg, GWL_USERDATA, (LONG)wd);
+
+ // options
+ SendMessage(hwndDlg, WMU_SETOPT, 0, 0);
+
+ // fonts
+ SendMessage(hwndDlg, WMU_SETFONTS, 0, 0);
+
+ }
+ return FALSE;
+ case WMU_REFRESH:
+ InvalidateRect(hwndDlg, 0, TRUE);
+ return TRUE;
+ case WM_CTLCOLORSTATIC:
+ {
+ HDC hdc = (HDC)wParam;
+ HWND hwndCtrl = (HWND)lParam;
+
+ if(hBackgroundBrush) {
+ if(hTitleFont && GetDlgItem(hwndDlg, IDC_TITLE) == hwndCtrl)
+ SetTextColor(hdc, title_font_colour);
+ else if(hWindowFont)
+ SetTextColor(hdc, window_font_colour);
+
+ SetBkMode(hdc, TRANSPARENT);
+ return (BOOL)hBackgroundBrush;
+ }
+ }
+ break;
+ case WM_CTLCOLORDLG:
+ if(hBackgroundBrush)
+ return (BOOL)hBackgroundBrush;
+ break;
+ case WMU_SETFONTS:
+ // fonts
+ if(hWindowFont)
+ SendMessage(hwndDlg, WM_SETFONT, (WPARAM)hWindowFont, (LPARAM)TRUE);
+ if(hTitleFont)
+ SendDlgItemMessage(hwndDlg, IDC_TITLE, WM_SETFONT, (WPARAM)hTitleFont, (LPARAM)TRUE);
+
+ if(hBackgroundBrush) {
+ SetClassLong(hwndDlg, GCL_HBRBACKGROUND, (LONG)hBackgroundBrush);
+ InvalidateRect(hwndDlg, 0, TRUE);
+ }
+
+ return TRUE;
+ case WMU_SETOPT:
+ {
+ Options *opt;
+ if(lParam) opt = (Options *)lParam;
+ else opt = &options;
+
+ // round corners
+ if(opt->aw_roundcorners) {
+ HRGN hRgn1;
+ RECT r;
+ int v,h;
+ int w=10;
+ GetWindowRect(hwndDlg,&r);
+ h=(r.right-r.left)>(w*2)?w:(r.right-r.left);
+ v=(r.bottom-r.top)>(w*2)?w:(r.bottom-r.top);
+ h=(h<v)?h:v;
+ hRgn1=CreateRoundRectRgn(0,0,(r.right-r.left+1),(r.bottom-r.top+1),h,h);
+ SetWindowRgn(hwndDlg,hRgn1,1);
+ } else {
+ HRGN hRgn1;
+ RECT r;
+ int v,h;
+ int w=10;
+ GetWindowRect(hwndDlg,&r);
+ h=(r.right-r.left)>(w*2)?w:(r.right-r.left);
+ v=(r.bottom-r.top)>(w*2)?w:(r.bottom-r.top);
+ h=(h<v)?h:v;
+ hRgn1=CreateRectRgn(0,0,(r.right-r.left+1),(r.bottom-r.top+1));
+ SetWindowRgn(hwndDlg,hRgn1,1);
+ }
+ // transparency
+
+#ifdef WS_EX_LAYERED
+ SetWindowLong(hwndDlg, GWL_EXSTYLE, GetWindowLong(hwndDlg, GWL_EXSTYLE) | WS_EX_LAYERED);
+#endif
+#ifdef LWA_ALPHA
+ if(MySetLayeredWindowAttributes)
+ MySetLayeredWindowAttributes(hwndDlg, RGB(0,0,0), (int)((100 - opt->aw_trans) / 100.0 * 255), LWA_ALPHA);
+#endif
+ }
+ return TRUE;
+ case WMU_SETALARM:
+ {
+ ALARM *data = (ALARM *)lParam;
+ SetWindowText(hwndDlg, data->szTitle);
+ HWND hw = GetDlgItem(hwndDlg, IDC_TITLE);
+ SetWindowText(hw, data->szTitle);
+
+ SetDlgItemText(hwndDlg, IDC_ED_DESC, data->szDesc);
+ ((WindowData *)GetWindowLong(hwndDlg, GWL_USERDATA))->alarm = data;
+
+ if(data->action & AAF_SOUND && options.loop_sound) {
+ if(data->sound_num <= 3)
+ SetTimer(hwndDlg, ID_TIMER_SOUND, SOUND_REPEAT_PERIOD, 0);
+ else if(data->sound_num == 4)
+ SetTimer(hwndDlg, ID_TIMER_SOUND, SPEACH_REPEAT_PERIOD, 0);
+ }
+
+ hw = GetDlgItem(hwndDlg, IDC_SNOOZE);
+ EnableWindow(hw, !(data->flags & ALF_NOSNOOZE));
+ ShowWindow(hw, (data->flags & ALF_NOSNOOZE) ? SW_HIDE : SW_SHOWNA);
+ }
+ return TRUE;
+ case WMU_FAKEALARM:
+ {
+ SetWindowText(hwndDlg, Translate("Example Alarm"));
+ HWND hw = GetDlgItem(hwndDlg, IDC_TITLE);
+ SetWindowText(hw, Translate("Example Alarm"));
+ SetDlgItemText(hwndDlg, IDC_ED_DESC, Translate("Some example text. Example, example, example."));
+ }
+ return TRUE;
+ case WM_TIMER:
+ {
+ if(wParam == ID_TIMER_SOUND) {
+ WindowData *dw = (WindowData *)GetWindowLong(hwndDlg, GWL_USERDATA);
+ if(dw) {
+ ALARM *data = dw->alarm;
+ if(data && data->action & AAF_SOUND) {
+ if(data->sound_num <= 3) {
+ char buff[128];
+ sprintf(buff, "Triggered%d", data->sound_num);
+ SkinPlaySound(buff);
+ } else if(data->sound_num == 4) {
+ if (data->szTitle != NULL && data->szTitle[0] != '\0') {
+ if (ServiceExists("Speak/Say")) {
+ CallService("Speak/Say", 0, (LPARAM)data->szTitle);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return TRUE;
+ case WM_MOVE:
+ {
+ //WindowData *wd = (WindowData *)GetWindowLong(hwndDlg, GWL_USERDATA);
+ Utils_SaveWindowPosition(hwndDlg, 0, MODULE, "Notify");
+ }
+ break;
+
+ case WMU_ADDSNOOZER:
+ {
+ WindowData *wd = (WindowData *)GetWindowLong(hwndDlg, GWL_USERDATA);
+ if(wd) {
+ ALARM *data = wd->alarm;
+
+ if(data) {
+ // add snooze minutes to current time
+ FILETIME ft;
+ GetLocalTime(&data->time);
+ SystemTimeToFileTime(&data->time, &ft);
+ ULARGE_INTEGER uli;
+ uli.LowPart = ft.dwLowDateTime;
+ uli.HighPart = ft.dwHighDateTime;
+
+ // there are 10000000 100-nanosecond blocks in a second...
+ uli.QuadPart += mult.QuadPart * (int)(wParam);
+
+ ft.dwHighDateTime = uli.HighPart;
+ ft.dwLowDateTime = uli.LowPart;
+
+ FileTimeToSystemTime(&ft, &data->time);
+
+ data->occurrence = OC_ONCE;
+ data->snoozer = true;
+ data->flags = data->flags & ~ALF_NOSTARTUP;
+
+ data->id = next_alarm_id++;
+
+ append_to_list(data);
+ }
+ }
+
+ }
+ return TRUE;
+ case WM_COMMAND:
+ if ( HIWORD( wParam ) == BN_CLICKED ) {
+ switch( LOWORD( wParam )) {
+ case IDCANCEL: // no button - esc pressed
+ case IDOK: // space?
+ case IDC_SNOOZE:
+ SendMessage(hwndDlg, WMU_ADDSNOOZER, (WPARAM)options.snooze_minutes, 0);
+ //drop through
+ case IDC_DISMISS:
+ {
+ WindowData *window_data = (WindowData *)GetWindowLong(hwndDlg, GWL_USERDATA);
+ KillTimer(hwndDlg, ID_TIMER_SOUND);
+ if(window_data) {
+ if(window_data->alarm) {
+ free_alarm_data(window_data->alarm);
+ delete window_data->alarm;
+ }
+ delete window_data;
+ }
+ SetWindowLong(hwndDlg, GWL_USERDATA, 0);
+
+ win_num--;
+ //EndDialog(hwndDlg, IDOK); // not modal!
+ WindowList_Remove(hAlarmWindowList, hwndDlg);
+ DestroyWindow(hwndDlg);
+ }
+ break;
+ case IDC_SNOOZELIST:
+ {
+ POINT pt, pt_rel;
+ GetCursorPos(&pt);
+ pt_rel = pt;
+ ScreenToClient(hwndDlg,&pt_rel);
+
+ HMENU hMenu = CreatePopupMenu();
+ MENUITEMINFO mmi = {0};
+ mmi.cbSize = sizeof(mmi);
+ mmi.fMask = MIIM_ID | MIIM_STRING;
+
+#define AddItem(x) \
+ mmi.wID++; \
+ mmi.dwTypeData = Translate(x); \
+ mmi.cch = strlen(mmi.dwTypeData); \
+ InsertMenuItem(hMenu, mmi.wID, FALSE, &mmi);
+
+ AddItem("5 mins");
+ AddItem("15 mins");
+ AddItem("30 mins");
+ AddItem("1 hour");
+ AddItem("1 day");
+ AddItem("1 week");
+
+ TPMPARAMS tpmp = {0};
+ tpmp.cbSize = sizeof(tpmp);
+ LRESULT ret = (LRESULT)TrackPopupMenuEx(hMenu, TPM_RETURNCMD, pt.x, pt.y, hwndDlg, &tpmp);
+ switch(ret) {
+ case 0: DestroyMenu(hMenu); return 0; // dismis menu
+ case 1: SendMessage(hwndDlg, WMU_ADDSNOOZER, (WPARAM)5, 0); break;
+ case 2: SendMessage(hwndDlg, WMU_ADDSNOOZER, (WPARAM)15, 0); break;
+ case 3: SendMessage(hwndDlg, WMU_ADDSNOOZER, (WPARAM)30, 0); break;
+ case 4: SendMessage(hwndDlg, WMU_ADDSNOOZER, (WPARAM)60, 0); break;
+ case 5: SendMessage(hwndDlg, WMU_ADDSNOOZER, (WPARAM)(60 * 24), 0); break;
+ case 6: SendMessage(hwndDlg, WMU_ADDSNOOZER, (WPARAM)(60 * 24 * 7), 0); break;
+ }
+
+ DestroyMenu(hMenu);
+
+ SendMessage(hwndDlg, WM_COMMAND, IDC_DISMISS, 0);
+ }
+ break;
+ }
+ }
+ return TRUE;
+
+ case WM_MOUSEMOVE:
+ if(wParam & MK_LBUTTON) {
+ SetCapture(hwndDlg);
+
+ POINT newp;
+ newp.x = (short)LOWORD(lParam);
+ newp.y = (short)HIWORD(lParam);
+
+ ClientToScreen(hwndDlg, &newp);
+
+ WindowData *window_data = (WindowData *)GetWindowLong(hwndDlg, GWL_USERDATA);
+ if(!window_data->moving) {
+ window_data->moving = true;
+ } else {
+ RECT r;
+ GetWindowRect(hwndDlg, &r);
+
+ SetWindowPos(hwndDlg, 0, r.left + (newp.x - window_data->p.x), r.top + (newp.y - window_data->p.y), 0, 0, SWP_NOSIZE | SWP_NOZORDER);
+ }
+ window_data->p.x = newp.x;
+ window_data->p.y = newp.y;
+ } else {
+ ReleaseCapture();
+ WindowData *window_data = (WindowData *)GetWindowLong(hwndDlg, GWL_USERDATA);
+ window_data->moving = false;
+ }
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+int ReloadFonts(WPARAM wParam, LPARAM lParam) {
+ LOGFONT log_font;
+ title_font_colour = CallService(MS_FONT_GET, (WPARAM)&title_font_id, (LPARAM)&log_font);
+ DeleteObject(hTitleFont);
+ hTitleFont = CreateFontIndirect(&log_font);
+
+ window_font_colour = CallService(MS_FONT_GET, (WPARAM)&window_font_id, (LPARAM)&log_font);
+ DeleteObject(hWindowFont);
+ hWindowFont = CreateFontIndirect(&log_font);
+
+ COLORREF bkCol = CallService(MS_COLOUR_GET, (WPARAM)&bk_colour_id, 0);
+ DeleteObject(hBackgroundBrush);
+ hBackgroundBrush = CreateSolidBrush(bkCol);
+
+ WindowList_Broadcast(hAlarmWindowList, WMU_REFRESH, 0, 0);
+ return 0;
+}
+
+int AlarmWinModulesLoaded(WPARAM wParam, LPARAM lParam) {
+ if(ServiceExists(MS_FONT_REGISTER)) {
+ title_font_id.cbSize = sizeof(FontID);
+ strcpy(title_font_id.group, Translate("Alarms"));
+ strcpy(title_font_id.name, Translate("Title"));
+ strcpy(title_font_id.dbSettingsGroup, MODULE);
+ strcpy(title_font_id.prefix, "FontTitle");
+ title_font_id.flags = 0;
+ title_font_id.order = 0;
+
+ CallService(MS_FONT_REGISTER, (WPARAM)&title_font_id, 0);
+
+ window_font_id.cbSize = sizeof(FontID);
+ strcpy(window_font_id.group, Translate("Alarms"));
+ strcpy(window_font_id.name, Translate("Window"));
+ strcpy(window_font_id.dbSettingsGroup, MODULE);
+ strcpy(window_font_id.prefix, "FontWindow");
+ window_font_id.flags = 0;
+ window_font_id.order = 1;
+
+ CallService(MS_FONT_REGISTER, (WPARAM)&window_font_id, 0);
+
+ bk_colour_id.cbSize = sizeof(ColourID);
+ strcpy(bk_colour_id.dbSettingsGroup, MODULE);
+ strcpy(bk_colour_id.group, Translate("Alarms"));
+ strcpy(bk_colour_id.name, Translate("Background"));
+ strcpy(bk_colour_id.setting, "BkColour");
+ bk_colour_id.defcolour = GetSysColor(COLOR_3DFACE);
+ bk_colour_id.flags = 0;
+ bk_colour_id.order = 0;
+
+ CallService(MS_COLOUR_REGISTER, (WPARAM)&bk_colour_id, 0);
+
+ ReloadFonts(0, 0);
+ HookEvent(ME_FONT_RELOAD, ReloadFonts);
+ }
+ return 0;
+}
+
+void InitAlarmWin() {
+ hUserDll = LoadLibrary("user32.dll");
+ if (hUserDll) {
+ MySetLayeredWindowAttributes = (BOOL (WINAPI *)(HWND,COLORREF,BYTE,DWORD))GetProcAddress(hUserDll, "SetLayeredWindowAttributes");
+ //MyAnimateWindow=(BOOL (WINAPI*)(HWND,DWORD,DWORD))GetProcAddress(hUserDll,"AnimateWindow");
+ }
+
+ hAlarmWindowList = (HANDLE)CallService(MS_UTILS_ALLOCWINDOWLIST, 0, 0);
+
+ HookEvent(ME_SYSTEM_MODULESLOADED, AlarmWinModulesLoaded);
+}
+
+void DeinitAlarmWin() {
+
+ WindowList_Broadcast(hAlarmWindowList, WM_COMMAND, IDC_SNOOZE, 0);
+
+ FreeLibrary(hUserDll);
+
+ if(hBackgroundBrush) DeleteObject(hBackgroundBrush);
+ if(hTitleFont) DeleteObject(hTitleFont);
+ if(hWindowFont) DeleteObject(hWindowFont);
+}
+
diff --git a/plugins/Alarms/alarm_win.h b/plugins/Alarms/alarm_win.h
new file mode 100644
index 0000000000..da3517a353
--- /dev/null
+++ b/plugins/Alarms/alarm_win.h
@@ -0,0 +1,22 @@
+#ifndef _ALARM_WIN_INC
+#define _ALARM_WIN_INC
+
+#include "options.h"
+#include "alarmlist.h"
+
+BOOL CALLBACK DlgProcAlarm(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
+
+#define WMU_SETALARM (WM_USER + 0x100)
+#define WMU_FAKEALARM (WM_USER + 0x101)
+
+#define WMU_SETOPT (WM_USER + 60)
+
+extern HANDLE hAlarmWindowList;
+
+void SetAlarmWinOptions();
+bool TransparencyEnabled();
+
+void InitAlarmWin();
+void DeinitAlarmWin();
+
+#endif
diff --git a/plugins/Alarms/alarmlist.cpp b/plugins/Alarms/alarmlist.cpp
new file mode 100644
index 0000000000..57171fc9c0
--- /dev/null
+++ b/plugins/Alarms/alarmlist.cpp
@@ -0,0 +1,782 @@
+#include "common.h"
+#include "alarmlist.h"
+
+AlarmList alarms;
+CRITICAL_SECTION alarm_cs;
+
+unsigned short next_alarm_id = 1; // 0 is used for invalid id
+
+DWORD timer_id;
+#define TIMER_PERIOD 5000 // milliseconds delay between alarm checks
+
+static SYSTEMTIME last_check, last_saved_check;
+
+HANDLE hAlarmTriggeredEvent, hAddAlarmService;
+
+bool startup = true;
+
+bool is_idle = false;
+
+void free_alarm_data(ALARM *alarm) {
+ if(alarm->szTitle) {free(alarm->szTitle); alarm->szTitle = 0;}
+ if(alarm->szDesc) {free(alarm->szDesc); alarm->szDesc = 0;}
+ if(alarm->szCommand) {free(alarm->szCommand); alarm->szCommand = 0;}
+ if(alarm->szCommandParams) {free(alarm->szCommandParams); alarm->szCommandParams = 0;}
+}
+
+void copy_alarm_data(ALARM *dest, ALARM *src) {
+ dest->action = src->action;
+ dest->flags = src->flags;
+ dest->id = src->id;
+ dest->occurrence = src->occurrence;
+ dest->snoozer = src->snoozer;
+ dest->sound_num = src->sound_num;
+ dest->time = src->time;
+ dest->trigger_id = src->trigger_id;
+
+ free_alarm_data(dest);
+ dest->szTitle = _strdup(src->szTitle);
+ dest->szDesc = _strdup(src->szDesc);
+ dest->szCommand = _strdup(src->szCommand);
+ dest->szCommandParams = _strdup(src->szCommandParams);
+}
+
+void GetPluginTime(SYSTEMTIME *t) {
+ EnterCriticalSection(&alarm_cs);
+ *t = last_check;
+ LeaveCriticalSection(&alarm_cs);
+}
+
+int MinutesInFuture(SYSTEMTIME time, Occurrence occ) {
+ if(!UpdateAlarm(time, occ)) return 0;
+
+ SYSTEMTIME now;
+ GetPluginTime(&now);
+
+ FILETIME ft_now, ft_then;
+ SystemTimeToFileTime(&now, &ft_now);
+ SystemTimeToFileTime(&time, &ft_then);
+
+ ULARGE_INTEGER uli_now, uli_then, diff;
+ uli_now.HighPart = ft_now.dwHighDateTime;
+ uli_now.LowPart = ft_now.dwLowDateTime;
+ uli_then.HighPart = ft_then.dwHighDateTime;
+ uli_then.LowPart = ft_then.dwLowDateTime;
+
+ diff.QuadPart = uli_then.QuadPart - uli_now.QuadPart;
+ bool inc = false;
+ if(diff.QuadPart % mult.QuadPart >= mult.QuadPart / 2)
+ inc = true;
+ return (int)(diff.QuadPart / mult.QuadPart + (inc ? 1 : 0));
+}
+
+void TimeForMinutesInFuture(int mins, SYSTEMTIME *time) {
+ SYSTEMTIME now;
+ FILETIME ft_now;
+ GetPluginTime(&now);
+ SystemTimeToFileTime(&now, &ft_now);
+
+ ULARGE_INTEGER uli_now;
+ uli_now.HighPart = ft_now.dwHighDateTime;
+ uli_now.LowPart = ft_now.dwLowDateTime;
+
+ uli_now.QuadPart += mult.QuadPart * (ULONGLONG)mins;
+ ft_now.dwHighDateTime = uli_now.HighPart;
+ ft_now.dwLowDateTime = uli_now.LowPart;
+
+ FileTimeToSystemTime(&ft_now, time);
+}
+
+
+// update an alarm so that the systemtime reflects the next time the alarm will go off, based on the last_check time
+bool UpdateAlarm(SYSTEMTIME &time, Occurrence occ) {
+
+ FILETIME ft_now, ft_then;
+ ULARGE_INTEGER uli_then;
+
+ switch(occ) {
+ case OC_DAILY:
+ case OC_WEEKDAYS:
+ case OC_WEEKLY:
+ time.wDay = last_check.wDay;
+ case OC_MONTHLY:
+ time.wMonth = last_check.wMonth;
+ case OC_YEARLY:
+ time.wYear = last_check.wYear;
+ case OC_ONCE:
+ break; // all fields valid
+ };
+
+ SystemTimeToFileTime(&last_check, &ft_now); // consider 'now' to be last check time
+ SystemTimeToFileTime(&time, &ft_then);
+
+ switch(occ) {
+ case OC_ONCE:
+ if(CompareFileTime(&ft_then, &ft_now) < 0)
+ return false;
+ break;
+ case OC_YEARLY:
+ while(CompareFileTime(&ft_then, &ft_now) < 0) {
+ time.wYear++;
+ SystemTimeToFileTime(&time, &ft_then);
+ }
+ break;
+ case OC_MONTHLY:
+ while(CompareFileTime(&ft_then, &ft_now) < 0) {
+ if(time.wMonth == 12) {
+ time.wMonth = 1;
+ time.wYear++;
+ } else
+ time.wMonth++;
+ SystemTimeToFileTime(&time, &ft_then);
+ }
+ break;
+ case OC_WEEKLY:
+ {
+ SYSTEMTIME temp;
+ uli_then.HighPart = ft_then.dwHighDateTime;
+ uli_then.LowPart = ft_then.dwLowDateTime;
+ FileTimeToSystemTime(&ft_then, &temp);
+ do {
+ if(temp.wDayOfWeek != time.wDayOfWeek || CompareFileTime(&ft_then, &ft_now) < 0) {
+ uli_then.QuadPart += mult.QuadPart * (ULONGLONG)24 * (ULONGLONG)60;
+ ft_then.dwHighDateTime = uli_then.HighPart;
+ ft_then.dwLowDateTime = uli_then.LowPart;
+ FileTimeToSystemTime(&ft_then, &temp);
+ }
+ } while(temp.wDayOfWeek != time.wDayOfWeek || CompareFileTime(&ft_then, &ft_now) < 0);
+ }
+ break;
+ case OC_WEEKDAYS:
+ {
+ SYSTEMTIME temp;
+ uli_then.HighPart = ft_then.dwHighDateTime;
+ uli_then.LowPart = ft_then.dwLowDateTime;
+ do {
+ FileTimeToSystemTime(&ft_then, &temp);
+ if(temp.wDayOfWeek == 0 || temp.wDayOfWeek == 6 || CompareFileTime(&ft_then, &ft_now) < 0) {
+ uli_then.QuadPart += mult.QuadPart * (ULONGLONG)24 * (ULONGLONG)60;
+ ft_then.dwHighDateTime = uli_then.HighPart;
+ ft_then.dwLowDateTime = uli_then.LowPart;
+ }
+ } while(temp.wDayOfWeek == 0 || temp.wDayOfWeek == 6 || CompareFileTime(&ft_then, &ft_now) < 0);
+ }
+ break;
+ case OC_DAILY:
+ uli_then.HighPart = ft_then.dwHighDateTime;
+ uli_then.LowPart = ft_then.dwLowDateTime;
+ while(CompareFileTime(&ft_then, &ft_now) < 0) {
+ uli_then.QuadPart += mult.QuadPart * (ULONGLONG)24 * (ULONGLONG)60;
+ ft_then.dwHighDateTime = uli_then.HighPart;
+ ft_then.dwLowDateTime = uli_then.LowPart;
+ }
+ break;
+ }
+
+ FileTimeToSystemTime(&ft_then, &time);
+ return true;
+}
+
+void LoadAlarms() {
+ int num_alarms = DBGetContactSettingWord(0, MODULE, "Count", 0);
+ char buff[256];
+ DBVARIANT dbv;
+ ALARM alarm;
+ SYSTEMTIME now;
+ GetLocalTime(&now);
+
+ EnterCriticalSection(&alarm_cs);
+ alarms.clear();
+
+ for(int i = 0; i < num_alarms; i++) {
+ memset(&alarm, 0, sizeof(ALARM));
+
+ sprintf(buff, "Title%d", i);
+ if(!DBGetContactSetting(0, MODULE, buff, &dbv)) {
+ if(dbv.pszVal && strlen(dbv.pszVal))
+ alarm.szTitle = _strdup(dbv.pszVal);
+ DBFreeVariant(&dbv);
+ }
+ sprintf(buff, "Desc%d", i);
+ if(!DBGetContactSetting(0, MODULE, buff, &dbv)) {
+ if(dbv.pszVal && strlen(dbv.pszVal))
+ alarm.szDesc = _strdup(dbv.pszVal);
+ DBFreeVariant(&dbv);
+ }
+ sprintf(buff, "Occ%d", i);
+ alarm.occurrence = (Occurrence)DBGetContactSettingWord(0, MODULE, buff, 0);
+
+ sprintf(buff, "STHour%d", i);
+ alarm.time.wHour = DBGetContactSettingWord(0, MODULE, buff, 0);
+ sprintf(buff, "STMinute%d", i);
+ alarm.time.wMinute = DBGetContactSettingWord(0, MODULE, buff, 0);
+ sprintf(buff, "STSecond%d", i);
+ alarm.time.wSecond = DBGetContactSettingWord(0, MODULE, buff, 0);
+
+ switch(alarm.occurrence) {
+
+ case OC_ONCE:
+ sprintf(buff, "STYear%d", i);
+ alarm.time.wYear = DBGetContactSettingWord(0, MODULE, buff, 0);
+ sprintf(buff, "STMonth%d", i);
+ alarm.time.wMonth = DBGetContactSettingWord(0, MODULE, buff, 0);
+ sprintf(buff, "STDay%d", i);
+ alarm.time.wDay = DBGetContactSettingWord(0, MODULE, buff, 0);
+ break;
+ case OC_WEEKLY:
+ sprintf(buff, "STDayOfWeek%d", i);
+ alarm.time.wDayOfWeek = DBGetContactSettingWord(0, MODULE, buff, 0);
+ break;
+ case OC_WEEKDAYS:
+ break;
+ case OC_DAILY:
+ break;
+ case OC_MONTHLY:
+ sprintf(buff, "STDay%d", i);
+ alarm.time.wDay = DBGetContactSettingWord(0, MODULE, buff, 0);
+ break;
+ case OC_YEARLY:
+ sprintf(buff, "STMonth%d", i);
+ alarm.time.wMonth = DBGetContactSettingWord(0, MODULE, buff, 0);
+ sprintf(buff, "STDay%d", i);
+ alarm.time.wDay = DBGetContactSettingWord(0, MODULE, buff, 0);
+ break;
+ }
+
+ sprintf(buff, "TriggerID%d", i);
+ alarm.trigger_id = DBGetContactSettingDword(0, MODULE, buff, 0);
+
+ if(UpdateAlarm(alarm.time, alarm.occurrence)) {
+ sprintf(buff, "ActionFlags%d", i);
+ alarm.action = (unsigned short)DBGetContactSettingDword(0, MODULE, buff, AAF_POPUP | AAF_SOUND);
+ if(alarm.action & AAF_COMMAND) {
+ sprintf(buff, "ActionCommand%d", i);
+ if(!DBGetContactSetting(0, MODULE, buff, &dbv)) {
+ if(dbv.pszVal && strlen(dbv.pszVal))
+ alarm.szCommand = _strdup(dbv.pszVal);
+ DBFreeVariant(&dbv);
+ sprintf(buff, "ActionParams%d", i);
+ if(!DBGetContactSetting(0, MODULE, buff, &dbv)) {
+ if(dbv.pszVal && strlen(dbv.pszVal))
+ alarm.szCommandParams = _strdup(dbv.pszVal);
+ DBFreeVariant(&dbv);
+ }
+ }
+ }
+
+ sprintf(buff, "SoundNum%d", i);
+ alarm.sound_num = (int)DBGetContactSettingByte(0, MODULE, buff, 1);
+
+ sprintf(buff, "Snoozer%d", i);
+ alarm.snoozer = DBGetContactSettingByte(0, MODULE, buff, 0) == 1;
+
+ sprintf(buff, "Hidden%d", i);
+ alarm.flags |= (DBGetContactSettingByte(0, MODULE, buff, 0) == 1 ? ALF_HIDDEN : 0);
+
+ sprintf(buff, "Suspended%d", i);
+ alarm.flags |= (DBGetContactSettingByte(0, MODULE, buff, 0) == 1 ? ALF_SUSPENDED : 0);
+
+ sprintf(buff, "NoStartup%d", i);
+ alarm.flags |= (DBGetContactSettingByte(0, MODULE, buff, 0) == 1 ? ALF_NOSTARTUP : 0);
+
+ sprintf(buff, "Flags%d", i);
+ alarm.flags = DBGetContactSettingDword(0, MODULE, buff, alarm.flags);
+
+ alarm.id = next_alarm_id++;
+ alarms.push_back(&alarm);
+
+ } else { // else ignore it - it's an expired one-off alarm (but clean up triggers)
+ if(alarm.trigger_id != 0 && ServiceExists(MS_TRIGGER_REPORTEVENT)) {
+ REPORTINFO ri = {0};
+ ri.cbSize = sizeof(ri);
+ ri.triggerID = alarm.trigger_id;
+ ri.flags = TRG_CLEANUP;
+ CallService(MS_TRIGGER_REPORTEVENT, 0, (LPARAM)&ri);
+ }
+ }
+ free_alarm_data(&alarm);
+ }
+ LeaveCriticalSection(&alarm_cs);
+}
+
+void SaveAlarms() {
+ int index = 0;
+ char buff[256];
+
+ EnterCriticalSection(&alarm_cs);
+
+ ALARM *i;
+ for(alarms.reset(); i = alarms.current(); alarms.next(), index++) {
+ sprintf(buff, "Title%d", index);
+ DBWriteContactSettingString(0, MODULE, buff, i->szTitle);
+ sprintf(buff, "Desc%d", index);
+ DBWriteContactSettingString(0, MODULE, buff, i->szDesc);
+ sprintf(buff, "Occ%d", index);
+ DBWriteContactSettingWord(0, MODULE, buff, i->occurrence);
+
+ sprintf(buff, "STHour%d", index);
+ DBWriteContactSettingWord(0, MODULE, buff, i->time.wHour);
+ sprintf(buff, "STMinute%d", index);
+ DBWriteContactSettingWord(0, MODULE, buff, i->time.wMinute);
+ sprintf(buff, "STSecond%d", index);
+ DBWriteContactSettingWord(0, MODULE, buff, i->time.wSecond);
+
+ switch(i->occurrence) {
+ case OC_DAILY:
+ break;
+ case OC_WEEKDAYS:
+ break;
+ case OC_WEEKLY:
+ sprintf(buff, "STDayOfWeek%d", index);
+ DBWriteContactSettingWord(0, MODULE, buff, i->time.wDayOfWeek);
+ break;
+
+ case OC_ONCE:
+ sprintf(buff, "STYear%d", index);
+ DBWriteContactSettingWord(0, MODULE, buff, i->time.wYear);
+ case OC_YEARLY:
+ sprintf(buff, "STMonth%d", index);
+ DBWriteContactSettingWord(0, MODULE, buff, i->time.wMonth);
+ case OC_MONTHLY:
+ sprintf(buff, "STDay%d", index);
+ DBWriteContactSettingWord(0, MODULE, buff, i->time.wDay);
+ break;
+ }
+ sprintf(buff, "ActionFlags%d", index);
+ DBWriteContactSettingDword(0, MODULE, buff, i->action);
+ if(i->action & AAF_COMMAND) {
+ if(strlen(i->szCommand)) {
+ sprintf(buff, "ActionCommand%d", index);
+ DBWriteContactSettingString(0, MODULE, buff, i->szCommand);
+ if(strlen(i->szCommandParams)) {
+ sprintf(buff, "ActionParams%d", index);
+ DBWriteContactSettingString(0, MODULE, buff, i->szCommandParams);
+ }
+ }
+ }
+
+ sprintf(buff, "SoundNum%d", index);
+ DBWriteContactSettingByte(0, MODULE, buff, i->sound_num);
+
+ sprintf(buff, "Snoozer%d", index);
+ DBWriteContactSettingByte(0, MODULE, buff, i->snoozer ? 1 : 0);
+
+ sprintf(buff, "Flags%d", index);
+ DBWriteContactSettingDword(0, MODULE, buff, i->flags);
+
+ sprintf(buff, "TriggerID%d", index);
+ DBWriteContactSettingDword(0, MODULE, buff, i->trigger_id);
+ }
+ DBWriteContactSettingWord(0, MODULE, "Count", index);
+
+ LeaveCriticalSection(&alarm_cs);
+}
+
+void copy_list(AlarmList &copy) {
+ copy.clear();
+ ALARM *i;
+ EnterCriticalSection(&alarm_cs);
+ for(alarms.reset(); i = alarms.current(); alarms.next()) {
+ copy.push_back(i);
+ }
+ LeaveCriticalSection(&alarm_cs);
+}
+
+void copy_list(AlarmList &copy, SYSTEMTIME &start, SYSTEMTIME &end) {
+ copy.clear();
+ ALARM *i;
+ EnterCriticalSection(&alarm_cs);
+ for(alarms.reset(); i = alarms.current(); alarms.next()) {
+ if(IsBetween(i->time, start, end))
+ copy.push_back(i);
+ }
+ LeaveCriticalSection(&alarm_cs);
+}
+
+void set_list(AlarmList &copy) {
+ EnterCriticalSection(&alarm_cs);
+ alarms.clear();
+ ALARM *i;
+ for(copy.reset(); i = copy.current(); copy.next()) {
+ alarms.push_back(i);
+ }
+ LeaveCriticalSection(&alarm_cs);
+
+ SaveAlarms();
+}
+
+void append_to_list(ALARM *alarm) {
+ EnterCriticalSection(&alarm_cs);
+ if(!alarm->id)
+ alarm->id = next_alarm_id++;
+ alarms.push_back(alarm);
+ LeaveCriticalSection(&alarm_cs);
+
+ SaveAlarms();
+}
+
+void alter_alarm_list(ALARM *alarm) {
+ bool found = false;
+ EnterCriticalSection(&alarm_cs);
+ if(alarm->id != 0) {
+ ALARM *i;
+ for(alarms.reset(); i = alarms.current(); alarms.next()) {
+ if(i->id == alarm->id) {
+ copy_alarm_data(i, alarm);
+ found = true;
+ break;
+ }
+ }
+ }
+ if(!found) {
+ if(!alarm->id)
+ alarm->id = next_alarm_id++;
+ alarms.push_back(alarm);
+ }
+
+ LeaveCriticalSection(&alarm_cs);
+
+ SaveAlarms();
+}
+
+void remove(unsigned short alarm_id) {
+ EnterCriticalSection(&alarm_cs);
+ ALARM *i;
+ for(alarms.reset(); i = alarms.current(); alarms.next()) {
+ if(i->id == alarm_id) {
+ if(i->trigger_id != 0 && ServiceExists(MS_TRIGGER_REPORTEVENT)) {
+ REPORTINFO ri = {0};
+ ri.cbSize = sizeof(ri);
+ ri.triggerID = i->trigger_id;
+ ri.flags = TRG_CLEANUP;
+ CallService(MS_TRIGGER_REPORTEVENT, 0, (LPARAM)&ri);
+ }
+ alarms.erase();
+ break;
+ }
+ }
+ LeaveCriticalSection(&alarm_cs);
+
+ SaveAlarms();
+}
+
+void suspend(unsigned short alarm_id) {
+ EnterCriticalSection(&alarm_cs);
+ ALARM *i;
+ for(alarms.reset(); i = alarms.current(); alarms.next()) {
+ if(i->id == alarm_id && i->occurrence != OC_ONCE) {
+ i->flags |= ALF_SUSPENDED;
+ break;
+ }
+ }
+ LeaveCriticalSection(&alarm_cs);
+
+ SaveAlarms();
+}
+
+static int CALLBACK PopupAlarmDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ switch(message) {
+ case WM_COMMAND: // snooze
+ if (HIWORD(wParam) == STN_CLICKED) { //It was a click on the Popup.
+ ALARM *mpd = NULL;
+ mpd = (ALARM *)CallService(MS_POPUP_GETPLUGINDATA, (WPARAM)hWnd,(LPARAM)mpd);
+
+ if(mpd->flags & ALF_NOSNOOZE)
+ return TRUE;
+
+ // add snooze minutes to current time
+ FILETIME ft;
+ GetLocalTime(&mpd->time);
+ SystemTimeToFileTime(&mpd->time, &ft);
+ ULARGE_INTEGER uli;
+ uli.LowPart = ft.dwLowDateTime;
+ uli.HighPart = ft.dwHighDateTime;
+
+ uli.QuadPart += mult.QuadPart * options.snooze_minutes;
+
+ ft.dwHighDateTime = uli.HighPart;
+ ft.dwLowDateTime = uli.LowPart;
+
+ FileTimeToSystemTime(&ft, &mpd->time);
+
+ mpd->occurrence = OC_ONCE;
+ mpd->snoozer = true;
+ mpd->flags = mpd->flags & ~(ALF_NOSTARTUP);
+
+ mpd->id = next_alarm_id++;
+
+ append_to_list(mpd);
+ }
+
+ PUDeletePopUp(hWnd);
+ return TRUE;
+ case WM_CONTEXTMENU:
+ PUDeletePopUp(hWnd);
+ return TRUE;
+ case UM_FREEPLUGINDATA:
+ {
+ ALARM *mpd = NULL;
+ mpd = (ALARM *)CallService(MS_POPUP_GETPLUGINDATA, (WPARAM)hWnd,(LPARAM)mpd);
+ if (mpd > 0) {
+ free_alarm_data(mpd);
+ delete mpd;
+ }
+ return TRUE;
+ }
+ default:
+ break;
+ }
+ return DefWindowProc(hWnd, message, wParam, lParam);
+}
+
+void ShowPopup(ALARM *alarm) {
+ if(ServiceExists(MS_POPUP_ADDPOPUP)) {
+ ALARM *data = new ALARM;
+ memset(data, 0, sizeof(ALARM));
+ copy_alarm_data(data, alarm);
+
+ POPUPDATAEX ppd;
+
+ ZeroMemory(&ppd, sizeof(ppd));
+ ppd.lchContact = 0;
+ ppd.lchIcon = hIconMenuSet;
+
+ lstrcpy(ppd.lpzContactName, data->szTitle);
+ lstrcpy(ppd.lpzText, data->szDesc);
+ ppd.colorBack = 0;
+ ppd.colorText = 0;
+ ppd.PluginWindowProc = (WNDPROC)PopupAlarmDlgProc;
+ ppd.PluginData = data;
+ ppd.iSeconds = -1;
+
+ //Now that every field has been filled, we want to see the popup.
+ CallService(MS_POPUP_ADDPOPUPEX, (WPARAM)&ppd, 0);
+ }
+}
+
+void DoAlarm(ALARM *alarm) {
+ ALARMINFO alarminfo;
+ alarminfo.szTitle = alarm->szTitle;
+ alarminfo.szDesc = alarm->szDesc;
+ alarminfo.szCommand = alarm->szCommand;
+ alarminfo.szCommandParams = alarm->szCommandParams;
+ alarminfo.occurrence = alarm->occurrence;
+ alarminfo.snoozer = alarm->snoozer;
+ alarminfo.time = alarm->time;
+ alarminfo.flags = alarm->flags;
+ alarminfo.action = alarm->action;
+ alarminfo.sound_num = alarm->sound_num;
+
+ if(!NotifyEventHooks(hAlarmTriggeredEvent, 0, (LPARAM)&alarminfo)) {
+
+ if(alarm->action & AAF_SOUND) {
+ if(alarm->sound_num > 0 && alarm->sound_num <= 3) {
+ char buff[128];
+ sprintf(buff, "Triggered%d", alarm->sound_num);
+ SkinPlaySound(buff);
+ } else if(alarm->sound_num == 4) {
+ if (alarm->szTitle != NULL && alarm->szTitle[0] != '\0') {
+ if (ServiceExists("Speak/Say")) {
+ CallService("Speak/Say", 0, (LPARAM)alarm->szTitle);
+ }
+ }
+ }
+ }
+ if(alarm->action & AAF_POPUP) {
+ if(options.use_popup_module && ServiceExists(MS_POPUP_ADDPOPUP))
+ ShowPopup(alarm);
+ else {
+ HWND hwndDlg = CreateDialog(hInst, MAKEINTRESOURCE(IDD_ALARM), GetDesktopWindow(), DlgProcAlarm);
+ WindowList_Add(hAlarmWindowList, hwndDlg, 0);
+
+ ALARM *data = new ALARM;
+ memset(data, 0, sizeof(ALARM));
+ copy_alarm_data(data, alarm);
+ SendMessage(hwndDlg, WMU_SETALARM, 0, (LPARAM)data);
+ if(is_idle || !options.aw_dontstealfocus)
+ ShowWindow(hwndDlg, SW_SHOW);
+ else
+ ShowWindow(hwndDlg, SW_SHOWNOACTIVATE);
+ SetWindowPos(hwndDlg, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
+ }
+ }
+
+ if(alarm->trigger_id != 0 && ServiceExists(MS_TRIGGER_REPORTEVENT)) {
+ REPORTINFO ri = {0};
+ ri.cbSize = sizeof(ri);
+ ri.triggerID = alarm->trigger_id;
+ ri.flags = TRG_PERFORM;
+ if(alarm->occurrence == OC_ONCE)
+ ri.flags |= TRG_CLEANUP;
+ CallService(MS_TRIGGER_REPORTEVENT, 0, (LPARAM)&ri);
+ }
+
+ if(alarm->action & AAF_COMMAND) {
+ ShellExecute(0, 0, alarm->szCommand, alarm->szCommandParams, 0, SW_NORMAL);
+ }
+
+ if(alarm->action & AAF_SYSTRAY)
+ {
+ CLISTEVENT cle = {0};
+ cle.cbSize = sizeof(cle);
+ cle.hContact = 0;
+ cle.hIcon = hIconSystray;
+ cle.pszTooltip = alarm->szTitle;
+ cle.flags = CLEF_ONLYAFEW;
+ CallService(MS_CLIST_ADDEVENT, 0, (LPARAM)&cle);
+ }
+ }
+}
+
+void WriteLastCheckTime() {
+ // save last-check time
+ DBCONTACTWRITESETTING dbcws;
+ dbcws.szModule = MODULE;
+ dbcws.szSetting = "LastCheck";
+ dbcws.value.type = DBVT_BLOB;
+ dbcws.value.cpbVal = sizeof(SYSTEMTIME);
+ dbcws.value.pbVal = (BYTE *)&last_check;
+ CallService(MS_DB_CONTACT_WRITESETTING, 0, (LPARAM)&dbcws);
+
+ last_saved_check = last_check;
+}
+
+void CheckAlarms() {
+ SYSTEMTIME time;
+ GetLocalTime(&time);
+
+ // put triggered alarms in another list - so we don't keep the critical section locked for longer than necessary
+ AlarmList triggered_list, remove_list;
+
+ EnterCriticalSection(&alarm_cs);
+ ALARM *i;
+ for(alarms.reset(); i = alarms.current(); alarms.next()) {
+ if(!UpdateAlarm(i->time, i->occurrence)) {
+ // somehow an expired one-off alarm is in our list
+ remove_list.push_back(i);
+ continue;
+ }
+
+ switch(i->occurrence) {
+ case OC_ONCE:
+ if(IsBetween(i->time, last_check, time)) {
+ if(!startup || !(i->flags & ALF_NOSTARTUP)) triggered_list.push_back(i);
+ // erase and fix iterator - alarm has now been triggered and has therefore expired
+ remove_list.push_back(i);
+ }
+ break;
+ default:
+ if(IsBetween(i->time, last_check, time)) {
+ if(i->flags & ALF_SUSPENDED)
+ i->flags = i->flags & ~ALF_SUSPENDED;
+ else
+ if(!startup || !(i->flags & ALF_NOSTARTUP)) triggered_list.push_back(i);
+ }
+ break;
+ }
+ }
+
+ last_check = time;
+ WriteLastCheckTime();
+
+ startup = false;
+ LeaveCriticalSection(&alarm_cs);
+
+ for(triggered_list.reset(); i = triggered_list.current(); triggered_list.next())
+ DoAlarm(i);
+ for(remove_list.reset(); i = remove_list.current(); remove_list.next())
+ remove(i->id);
+
+
+}
+
+VOID CALLBACK TimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) {
+ CheckAlarms();
+}
+
+
+int AddAlarmService(WPARAM wParam, LPARAM lParam) {
+ ALARMINFO *alarm_info = (ALARMINFO *)lParam;
+ ALARM alarm = {0};
+ alarm.action = alarm_info->action;
+ alarm.flags = alarm_info->flags;
+ alarm.id = next_alarm_id++;
+ alarm.occurrence = alarm_info->occurrence;
+ alarm.snoozer = alarm_info->snoozer;
+ alarm.sound_num = alarm_info->sound_num;
+ alarm.szCommand = _strdup(alarm_info->szCommand);
+ alarm.szCommandParams = _strdup(alarm_info->szCommandParams);
+ alarm.szDesc = _strdup(alarm_info->szDesc);
+ alarm.szTitle = _strdup(alarm_info->szTitle);
+ alarm.time = alarm_info->time;
+
+ append_to_list(&alarm);
+ return 0;
+}
+
+int IdleChanged(WPARAM wParam, LPARAM lParam) {
+ is_idle = (lParam & IDF_ISIDLE);
+
+ return 0;
+}
+
+void InitList() {
+ InitializeCriticalSection(&alarm_cs);
+
+ SkinAddNewSoundEx("Triggered1", Translate("Alarms"), Translate("Alert 1"));
+ SkinAddNewSoundEx("Triggered2", Translate("Alarms"), Translate("Alert 2"));
+ SkinAddNewSoundEx("Triggered3", Translate("Alarms"), Translate("Alert 3"));
+
+ // load last checked time
+ DBCONTACTGETSETTING dbcgs;
+ DBVARIANT dbv;
+ dbcgs.szModule = MODULE;
+ dbcgs.szSetting = "LastCheck";
+ dbcgs.pValue = &dbv;
+ dbv.type = DBVT_BLOB;
+ dbv.cpbVal = sizeof(SYSTEMTIME);
+
+ if(!CallService(MS_DB_CONTACT_GETSETTING, 0, (LPARAM)&dbcgs)) {
+ memcpy(&last_check, dbv.pbVal, sizeof(SYSTEMTIME));
+ DBFreeVariant(&dbv);
+ } else {
+ GetLocalTime(&last_check);
+ }
+
+ last_saved_check = last_check;
+
+ LoadAlarms();
+
+ hAlarmTriggeredEvent = CreateHookableEvent(ME_ALARMS_TRIGGERED);
+ hAddAlarmService = CreateServiceFunction(MS_ALARMS_ADDALARM, AddAlarmService);
+
+ InitAlarmWin();
+
+ timer_id = SetTimer(0, 0, TIMER_PERIOD, TimerProc);
+
+ HookEvent(ME_IDLE_CHANGED, IdleChanged);
+}
+
+
+void DeinitList() {
+
+ DeinitAlarmWin();
+
+ // i don't think this should be necessary, but...
+ EnterCriticalSection(&alarm_cs);
+ KillTimer(0, timer_id);
+ LeaveCriticalSection(&alarm_cs);
+
+ DestroyHookableEvent(hAlarmTriggeredEvent);
+ DestroyServiceFunction(hAddAlarmService);
+
+ SaveAlarms(); // we may have erased some 'cause they were once-offs that were triggered
+
+ //WriteLastCheckTime(); // moved to the CheckAlarms function - for virt db and general crash problems
+
+ // delete this after save alarms above
+ DeleteCriticalSection(&alarm_cs);
+
+}
+
diff --git a/plugins/Alarms/alarmlist.h b/plugins/Alarms/alarmlist.h
new file mode 100644
index 0000000000..8fdc4b3ac1
--- /dev/null
+++ b/plugins/Alarms/alarmlist.h
@@ -0,0 +1,148 @@
+#ifndef _ALARMLIST_INC
+#define _ALARMLIST_INC
+
+#include "options.h"
+#include "time_utils.h"
+#include "alarm_win.h"
+
+#include "m_alarms.h"
+
+void free_alarm_data(ALARM *alarm);
+
+void copy_alarm_data(ALARM *dest, ALARM *src);
+
+int MinutesInFuture(SYSTEMTIME time, Occurrence occ);
+void TimeForMinutesInFuture(int mins, SYSTEMTIME *time);
+
+static bool operator<(const ALARM &a1, const ALARM &a2) {
+ return MinutesInFuture(a1.time, a1.occurrence) < MinutesInFuture(a2.time, a2.occurrence); // less-than inverted 'cause we want ascending order
+}
+
+class AlarmList {
+public:
+ AlarmList(): head(0), tail(0), count(0) {}
+
+ virtual ~AlarmList() {clear();}
+
+ void sort() {
+ if(count < 2) return;
+
+ Node *c1 = head, *c2;
+ // bubble sort...hey, i'm lazy :)
+ while(c1) {
+ c2 = c1->next;
+ while(c2) {
+ if(c2->alarm < c1->alarm) {
+ swap (c1, c2);
+ }
+ c2 = c2->next;
+ }
+ c1 = c1->next;
+ }
+ }
+
+ void clear() {
+ Node *current;
+ while(head) {
+ current = head;
+ head = head->next;
+ free_alarm_data(&current->alarm);
+ delete current;
+ }
+ count = 0;
+ tail = 0;
+ reset();
+ }
+
+ int size() {return count;}
+
+ ALARM &at(int index) {
+ int i = 0;
+ Node *current = head;
+ while(i < index && i < count && current) {
+ current = current->next;
+ i++;
+ }
+ return current->alarm;
+ }
+
+ void reset() {it_current = head;}
+ ALARM *current() {return (it_current ? &it_current->alarm : 0);}
+ void next() {it_current = it_current->next;}
+ void erase() {
+ if(it_current) {
+ if(it_current->next) it_current->next->prev = it_current->prev;
+ if(it_current->prev) it_current->prev->next = it_current->next;
+
+ if(tail == it_current) tail = tail->prev;
+ if(head == it_current) head = head->next;
+
+ free_alarm_data(&it_current->alarm);
+ delete it_current;
+ count--;
+ reset();
+ }
+ }
+
+ // copies the alarm into the list
+ void push_back(ALARM *alarm) {
+ Node *nn = new Node;
+ memset(&nn->alarm, 0, sizeof(ALARM));
+ copy_alarm_data(&nn->alarm, alarm);
+
+ nn->prev = tail;
+ if(tail) tail->next = nn;
+ tail = nn;
+
+ if(!head) head = tail;
+ count++;
+ }
+
+protected:
+ class Node {
+ public:
+ Node(): next(0), prev(0) {}
+ ALARM alarm;
+ Node *next, *prev;
+ };
+
+ Node *head, *tail, *it_current;
+ int count;
+
+ void swap(Node *n1, Node *n2) {
+ ALARM temp = n1->alarm;
+ n1->alarm = n2->alarm;
+ n2->alarm = temp;
+ }
+};
+
+//extern AlarmList alarms;
+
+void LoadAlarms();
+void SaveAlarms();
+
+void InitList();
+void DeinitList();
+
+void copy_list(AlarmList &copy);
+void copy_list(AlarmList &copy, SYSTEMTIME &start, SYSTEMTIME &end);
+
+void set_list(AlarmList &copy);
+
+void append_to_list(ALARM *alarm);
+void alter_alarm_list(ALARM *alarm);
+void remove(unsigned short alarm_id);
+
+void suspend(unsigned short alarm_id);
+
+void GetPluginTime(SYSTEMTIME *t);
+
+// increase 'time' to next occurrence
+bool UpdateAlarm(SYSTEMTIME &time, Occurrence occ);
+
+
+const ULARGE_INTEGER mult = { 600000000, 0}; // number of 100 microsecond blocks in a minute
+
+extern unsigned short next_alarm_id;
+
+#endif
diff --git a/plugins/Alarms/alarms.cpp b/plugins/Alarms/alarms.cpp
new file mode 100644
index 0000000000..d95979ef74
--- /dev/null
+++ b/plugins/Alarms/alarms.cpp
@@ -0,0 +1,339 @@
+/*
+Miranda plugin template, originally by Richard Hughes
+http://miranda-icq.sourceforge.net/
+
+This file is placed in the public domain. Anybody is free to use or
+modify it as they wish with no restriction.
+There is no warranty.
+*/
+
+#include "common.h"
+#include "alarms.h"
+
+struct MM_INTERFACE mmi;
+
+#define SERVICENAME "mp"
+#define COMMANDPREFIX "/" SERVICENAME
+
+#define WMP_PAUSE 32808
+#define WMP_NEXT 0x497B
+
+char szGamePrefix[] = COMMANDPREFIX;
+
+HINSTANCE hInst;
+PLUGINLINK *pluginLink;
+int hLangpack;
+
+HANDLE hTopToolbarButton;
+
+typedef LRESULT (CALLBACK *WNDPROC)(HWND, UINT, WPARAM, LPARAM);
+
+//bool right_window = false;
+WNDPROC old_clist_wndproc;
+
+PLUGININFOEX pluginInfo={
+ sizeof(PLUGININFOEX),
+ "Alarms",
+ PLUGIN_MAKE_VERSION(0,4,0,5),
+ "Set once-off, daily, weekly and weekday alarms.",
+ "Scott Ellis",
+ "mail@scottellis.com.au",
+ "© 2005 Scott Ellis",
+ "http://www.scottellis.com.au",
+ 0, //not transient
+ 0, //doesn't replace anything built-in
+ { 0x4dd7762b, 0xd612, 0x4f84, { 0xaa, 0x86, 0x6, 0x8f, 0x17, 0x85, 0x9b, 0x6d } } // {4DD7762B-D612-4f84-AA86-068F17859B6D}
+};
+
+extern "C" BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
+{
+ hInst=hinstDLL;
+ return TRUE;
+}
+
+extern "C" __declspec(dllexport) PLUGININFOEX* MirandaPluginInfoEx(DWORD mirandaVersion)
+{
+ return &pluginInfo;
+}
+
+extern "C" __declspec(dllexport) PLUGININFO* MirandaPluginInfo(DWORD mirandaVersion)
+{
+ pluginInfo.cbSize = sizeof(PLUGININFO);
+ return (PLUGININFO*)&pluginInfo;
+}
+
+static const MUUID interfaces[] = {MIID_ALARMS, MIID_LAST};
+extern "C" __declspec(dllexport) const MUUID* MirandaPluginInterfaces(void)
+{
+ return interfaces;
+}
+
+
+
+static int CALLBACK PopupDlgProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ switch(message) {
+ case WM_COMMAND:
+ if (HIWORD(wParam) == STN_CLICKED) { //It was a click on the Popup.
+ PUDeletePopUp(hWnd);
+ return TRUE;
+ }
+ break;
+ case UM_FREEPLUGINDATA: {
+ //MY_PLUGIN_DATA * mpd = NULL;
+ //mpd = (MY_PLUGIN_DATA*)CallService(MS_POPUP_GETPLUGINDATA, (WPARAM)hWnd,(LPARAM)mpd);
+ //if (mdp > 0) free(mpd);
+ return TRUE; //TRUE or FALSE is the same, it gets ignored.
+ }
+ default:
+ break;
+ }
+ return DefWindowProc(hWnd, message, wParam, lParam);
+}
+
+void ShowPopup(HANDLE hContact, const char *msg) {
+ if(ServiceExists(MS_POPUP_ADDPOPUP)) {
+ POPUPDATAEX ppd;
+ char *lpzContactName;
+
+ ZeroMemory(&ppd, sizeof(ppd)); //This is always a good thing to do.
+ ppd.lchContact = hContact; //Be sure to use a GOOD handle, since this will not be checked.
+ ppd.lchIcon = LoadSkinnedIcon(SKINICON_EVENT_MESSAGE);
+
+ lpzContactName = (char *)CallService(MS_CLIST_GETCONTACTDISPLAYNAME,(WPARAM)hContact,0);
+
+ lstrcpy(ppd.lpzContactName, lpzContactName);
+ lstrcpy(ppd.lpzText, msg);
+ ppd.colorBack = GetSysColor(COLOR_BTNFACE);;
+ ppd.colorText = RGB(0,0,0);
+ ppd.PluginWindowProc = (WNDPROC)PopupDlgProc;
+ ppd.PluginData = 0;
+ ppd.iSeconds = 3;
+
+ //Now that every field has been filled, we want to see the popup.
+ CallService(MS_POPUP_ADDPOPUPEX, (WPARAM)&ppd, 0);
+ }
+}
+
+static int PluginSendMessage(WPARAM wParam,LPARAM lParam) {
+ CCSDATA css;
+ css.hContact = (HANDLE)wParam;
+ css.szProtoService = PSS_MESSAGE;
+ css.wParam = 0;
+ css.lParam = lParam;
+
+ CallService(MS_PROTO_CALLCONTACTSERVICE, 0, (LPARAM)&css);
+ return 0;
+}
+
+static int PluginMessageReceived(WPARAM wParam,LPARAM lParam)
+{
+ CCSDATA *pccsd = (CCSDATA *)lParam;
+ PROTORECVEVENT *ppre = ( PROTORECVEVENT * )pccsd->lParam;
+ char *savedMsg;
+ HWND hWnd;
+ char response[256];
+
+ char msg[1024], buff[1024];
+
+ if(strncmp(ppre->szMessage, szGamePrefix, strlen(szGamePrefix)))
+ return CallService( MS_PROTO_CHAINRECV, wParam, lParam );
+
+ strcpy(msg, ppre->szMessage + strlen(szGamePrefix));
+
+ savedMsg = ppre->szMessage;
+
+ if(!strcmp(msg, " ffw")) {
+ sprintf(buff, "Fast forward!");
+
+ hWnd = FindWindow(0, "Windows Media Player");
+ PostMessage(hWnd, WM_COMMAND, WMP_NEXT, 0);
+ } else {
+ sprintf(buff, "Unknown command issued: \"%s\"", msg);
+ }
+
+ /*
+ ppre->szMessage = (char *)Translate(buff);
+ retval = CallService( MS_PROTO_CHAINRECV, wParam, lParam );
+ ppre->szMessage = savedMsg;
+ */
+
+ ShowPopup(pccsd->hContact, buff);
+
+ strcpy(response, buff);
+ PluginSendMessage((WPARAM)pccsd->hContact, (LPARAM)response);
+
+ return 0;
+}
+
+HBITMAP LoadBmpFromIcon(int IdRes)
+{
+ HBITMAP hBmp, hoBmp;
+ HDC hdc, hdcMem;
+ HBRUSH hBkgBrush;
+ HICON hIcon;
+
+ hIcon = LoadIcon(hInst,MAKEINTRESOURCE(IdRes));
+
+ RECT rc;
+ BITMAPINFOHEADER bih = {0};
+ int widthBytes;
+
+ hBkgBrush = CreateSolidBrush(GetSysColor(COLOR_3DFACE));
+ bih.biSize = sizeof(bih);
+ bih.biBitCount = 24;
+ bih.biPlanes = 1;
+ bih.biCompression = BI_RGB;
+ bih.biHeight = 16;
+ bih.biWidth = 20;
+ widthBytes = ((bih.biWidth*bih.biBitCount + 31) >> 5) * 4;
+ rc.top = rc.left = 0;
+ rc.right = bih.biWidth;
+ rc.bottom = bih.biHeight;
+ hdc = GetDC(NULL);
+ hBmp = CreateCompatibleBitmap(hdc, bih.biWidth, bih.biHeight);
+ hdcMem = CreateCompatibleDC(hdc);
+ hoBmp = (HBITMAP)SelectObject(hdcMem, hBmp);
+ FillRect(hdcMem, &rc, hBkgBrush);
+ DrawIconEx(hdcMem, 2, 0, hIcon, 16, 16, 0, NULL, DI_NORMAL);
+
+
+ SelectObject(hdcMem, hoBmp);
+ DeleteDC(hdcMem);
+ ReleaseDC(NULL, hdc);
+ DeleteObject(hBkgBrush);
+
+ DeleteObject(hIcon);
+
+ return hBmp;
+}
+
+static int InitTopToolbarButton(WPARAM wParam, LPARAM lParam) {
+ TTBButton ttb = {0};
+
+ ttb.cbSize = sizeof(ttb);
+ ttb.hbBitmapUp = LoadBmpFromIcon(IDI_TBUP); //LoadBitmap(hInst, MAKEINTRESOURCE(IDB_CLOCK));
+ ttb.hbBitmapDown = LoadBmpFromIcon(IDI_TBDN); //LoadBitmap(hInst, MAKEINTRESOURCE(IDB_CLOCK));
+ ttb.pszServiceDown = MODULE "/NewAlarm";
+ ttb.dwFlags = TTBBF_VISIBLE;// | TTBBF_DRAWBORDER;
+ ttb.name = Translate("Set Alarm");
+
+ hTopToolbarButton = (HANDLE)CallService(MS_TTB_ADDBUTTON, (WPARAM)&ttb, 0);
+ CallService(MS_TTB_SETBUTTONSTATE, (WPARAM)hTopToolbarButton, (LPARAM)TTBST_RELEASED);
+
+ return 0;
+}
+
+static int MainInit(WPARAM wparam,LPARAM lparam) {
+ if(ServiceExists(MS_UPDATE_REGISTER)) {
+ // register with updater
+ Update update = {0};
+ char szVersion[16];
+
+ update.cbSize = sizeof(Update);
+
+ update.szComponentName = pluginInfo.shortName;
+ update.pbVersion = (BYTE *)CreateVersionString(pluginInfo.version, szVersion);
+ update.cpbVersion = strlen((char *)update.pbVersion);
+
+ update.szUpdateURL = UPDATER_AUTOREGISTER;
+
+ // these are the three lines that matter - the archive, the page containing the version string, and the text (or data)
+ // before the version that we use to locate it on the page
+ // (note that if the update URL and the version URL point to standard file listing entries, the backend xml
+ // data will be used to check for updates rather than the actual web page - this is not true for beta urls)
+ update.szBetaUpdateURL = "http://www.scottellis.com.au/miranda_plugins/alarms.zip";
+ update.szBetaVersionURL = "http://www.scottellis.com.au/miranda_plugins/ver_alarms.html";
+ update.pbBetaVersionPrefix = (BYTE *)" version ";
+
+ update.cpbBetaVersionPrefix = strlen((char *)update.pbBetaVersionPrefix);
+
+ CallService(MS_UPDATE_REGISTER, 0, (WPARAM)&update);
+ }
+
+ /*
+ PROTOCOLDESCRIPTOR pd;
+ HANDLE hContact;
+
+ memset( &pd, 0, sizeof( PROTOCOLDESCRIPTOR ));
+ pd.cbSize = sizeof( PROTOCOLDESCRIPTOR );
+ pd.szName = SERVICENAME;
+ //pd.type = PROTOTYPE_ENCRYPTION - 9;
+ pd.type = PROTOTYPE_FILTER;
+ CallService( MS_PROTO_REGISTERMODULE, 0, ( LPARAM ) &pd );
+
+ CreateServiceFunction( SERVICENAME PSR_MESSAGE, PluginMessageReceived );
+
+ hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDFIRST, 0, 0 );
+
+ while( hContact )
+ {
+ if( !CallService( MS_PROTO_ISPROTOONCONTACT, ( WPARAM )hContact, ( LPARAM )SERVICENAME ))
+ CallService( MS_PROTO_ADDTOCONTACT, ( WPARAM )hContact, ( LPARAM )SERVICENAME );
+
+ hContact = ( HANDLE )CallService( MS_DB_CONTACT_FINDNEXT, ( WPARAM )hContact, 0 );
+ }
+ */
+
+ // initialize icons
+ InitIcons();
+
+ // Hotkey
+ /*
+ SKINHOTKEYDESCEX hk;
+ hk.cbSize = sizeof(hk);
+ hk.pszName = Translate("Set Alarm");
+ hk.pszDescription = Translate("Set a new alarm");
+ hk.pszSection = Translate("Alarms");
+ hk.pszService = MODULE "/NewAlarm";
+ hk.DefHotKey = (WORD)'A' + HOTKEYF_ALT * 256;
+ CallService(MS_SKIN_ADDHOTKEY, 0, (LPARAM)&hk);
+ */
+
+ // TopToolbar support
+ HookEvent(ME_TTB_MODULELOADED, InitTopToolbarButton);
+
+ InitFrames();
+
+ // TriggerPlugin support
+ LoadTriggerSupport();
+
+ return 0;
+}
+
+static int MainDeInit(WPARAM wParam, LPARAM lParam) {
+ DeinitFrames();
+ DeinitList();
+ DeinitIcons();
+ return 0;
+}
+
+extern "C" int __declspec(dllexport) Load(PLUGINLINK *link)
+{
+ pluginLink = link;
+
+ mir_getLP(&pluginInfo);
+ mir_getMMI(&mmi);
+
+ // ensure datetime picker is loaded
+ INITCOMMONCONTROLSEX ccx;
+ ccx.dwSize = sizeof(ccx);
+ ccx.dwICC = ICC_DATE_CLASSES;
+ InitCommonControlsEx(&ccx);
+
+ HookEvent(ME_SYSTEM_MODULESLOADED,MainInit);
+ HookEvent(ME_SYSTEM_PRESHUTDOWN, MainDeInit);
+
+ LoadOptions();
+ InitList();
+
+ HookEvent(ME_OPT_INITIALISE, OptInit );
+
+ return 0;
+}
+
+extern "C" int __declspec(dllexport) Unload(void)
+{
+ return 0;
+}
+
diff --git a/plugins/Alarms/alarms.h b/plugins/Alarms/alarms.h
new file mode 100644
index 0000000000..94b171d867
--- /dev/null
+++ b/plugins/Alarms/alarms.h
@@ -0,0 +1,11 @@
+#ifndef _TESTPLUG_INC
+#define _TESTPLUG_INC
+
+//#include "win.h"
+#include "alarmlist.h"
+#include "options.h"
+#include "frame.h"
+#include "trigger.h"
+
+
+#endif
diff --git a/plugins/Alarms/alarms_10.sln b/plugins/Alarms/alarms_10.sln
new file mode 100644
index 0000000000..ca2b18a15c
--- /dev/null
+++ b/plugins/Alarms/alarms_10.sln
@@ -0,0 +1,23 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "alarms", "alarms_10.vcxproj", "{5F09C93B-463A-4BF5-A85E-6E4E916AA8F8}"
+EndProject
+Global
+ GlobalSection(DPCodeReviewSolutionGUID) = preSolution
+ DPCodeReviewSolutionGUID = {00000000-0000-0000-0000-000000000000}
+ EndGlobalSection
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {5F09C93B-463A-4BF5-A85E-6E4E916AA8F8}.Debug|Win32.ActiveCfg = Debug|Win32
+ {5F09C93B-463A-4BF5-A85E-6E4E916AA8F8}.Debug|Win32.Build.0 = Debug|Win32
+ {5F09C93B-463A-4BF5-A85E-6E4E916AA8F8}.Release|Win32.ActiveCfg = Release|Win32
+ {5F09C93B-463A-4BF5-A85E-6E4E916AA8F8}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/plugins/Alarms/alarms_10.vcxproj b/plugins/Alarms/alarms_10.vcxproj
new file mode 100644
index 0000000000..8750c9afb0
--- /dev/null
+++ b/plugins/Alarms/alarms_10.vcxproj
@@ -0,0 +1,217 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectName>alarms</ProjectName>
+ <ProjectGuid>{5F09C93B-463A-4BF5-A85E-6E4E916AA8F8}</ProjectGuid>
+ <RootNamespace>alarms</RootNamespace>
+ <Keyword>MFCProj</Keyword>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>Dynamic</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <UseOfMfc>Dynamic</UseOfMfc>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC60.props" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.40219.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">.\Release\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\Debug\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">.\Debug\</IntDir>
+ <LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
+ <CodeAnalysisRuleSet Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">AllRules.ruleset</CodeAnalysisRuleSet>
+ <CodeAnalysisRules Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
+ <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Midl>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TargetEnvironment>Win32</TargetEnvironment>
+ <TypeLibraryName>.\Release/alarms.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>MinSpace</Optimization>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;ALARMS_EXPORTS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <PrecompiledHeaderFile>common.h</PrecompiledHeaderFile>
+ <AssemblerListingLocation>.\Release/</AssemblerListingLocation>
+ <ObjectFileName>.\Release/</ObjectFileName>
+ <ProgramDataBaseFileName>.\Release/</ProgramDataBaseFileName>
+ <WarningLevel>Level3</WarningLevel>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>gdi32.lib;user32.lib;opengl32.lib;glu32.lib;comctl32.lib;shell32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <ProgramDatabaseFile>.\Release/alarms.pdb</ProgramDatabaseFile>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ </Link>
+ <Bscmake>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <OutputFile>.\Release/alarms.bsc</OutputFile>
+ </Bscmake>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Midl>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MkTypLibCompatible>true</MkTypLibCompatible>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <TargetEnvironment>Win32</TargetEnvironment>
+ <TypeLibraryName>.\Debug/alarms.tlb</TypeLibraryName>
+ <HeaderFileName>
+ </HeaderFileName>
+ </Midl>
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>../../include;../ExternalAPI%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;ALARMS_EXPORTS;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>true</MinimalRebuild>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <PrecompiledHeader>Use</PrecompiledHeader>
+ <PrecompiledHeaderFile>common.h</PrecompiledHeaderFile>
+ <AssemblerListingLocation>.\Debug/</AssemblerListingLocation>
+ <ObjectFileName>.\Debug/</ObjectFileName>
+ <ProgramDataBaseFileName>.\Debug/</ProgramDataBaseFileName>
+ <WarningLevel>Level3</WarningLevel>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ <DisableSpecificWarnings>4996;%(DisableSpecificWarnings)</DisableSpecificWarnings>
+ </ClCompile>
+ <ResourceCompile>
+ <PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
+ <Link>
+ <AdditionalDependencies>gdi32.lib;user32.lib;opengl32.lib;glu32.lib;comctl32.lib;shell32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <ProgramDatabaseFile>.\Debug/alarms.pdb</ProgramDatabaseFile>
+ <RandomizedBaseAddress>false</RandomizedBaseAddress>
+ <DataExecutionPrevention>
+ </DataExecutionPrevention>
+ <ImportLibrary>$(IntDir)$(TargetName).lib</ImportLibrary>
+ <TargetMachine>MachineX86</TargetMachine>
+ </Link>
+ <Bscmake>
+ <SuppressStartupBanner>true</SuppressStartupBanner>
+ <OutputFile>.\Debug/alarms.bsc</OutputFile>
+ </Bscmake>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="alarm_win.cpp">
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <ClCompile Include="alarmlist.cpp">
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <Optimization Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">MinSpace</Optimization>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <ClCompile Include="alarms.cpp">
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
+ </ClCompile>
+ <ClCompile Include="frame.cpp">
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <ClCompile Include="icons.cpp">
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <ClCompile Include="options.cpp">
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <ClCompile Include="time_utils.cpp">
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <ClCompile Include="trigger.cpp">
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="alarm_win.h" />
+ <ClInclude Include="alarmlist.h" />
+ <ClInclude Include="alarms.h" />
+ <ClInclude Include="common.h" />
+ <ClInclude Include="frame.h" />
+ <ClInclude Include="icons.h" />
+ <ClInclude Include="m_alarms.h" />
+ <ClInclude Include="options.h" />
+ <ClInclude Include="resource.h" />
+ <ClInclude Include="time_utils.h" />
+ <ClInclude Include="trigger.h" />
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="bitmap1.bmp" />
+ <None Include="clock.ico" />
+ <None Include="clockdow.bmp" />
+ <None Include="flat_16x12.bmp" />
+ <None Include="green.ico" />
+ <None Include="ico00001.ico" />
+ <None Include="icon1.ico" />
+ <None Include="icon2.ico" />
+ <None Include="icon3.ico" />
+ <None Include="iconttbdown.ico" />
+ <None Include="iconttbup.ico" />
+ <None Include="yellow.ico" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="resource.rc">
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ResourceCompile>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/plugins/Alarms/alarms_10.vcxproj.filters b/plugins/Alarms/alarms_10.vcxproj.filters
new file mode 100644
index 0000000000..d6a3dd0e63
--- /dev/null
+++ b/plugins/Alarms/alarms_10.vcxproj.filters
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{7e24b5e6-2653-4143-a42b-d3486d5c416f}</UniqueIdentifier>
+ <Extensions>cpp;c;cxx;rc;def;r;odl;idl;hpj;bat</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{596c44cc-f8d3-4837-8fb4-49d4aa913452}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{9c926bbb-252f-489c-8433-2db02ad00ba7}</UniqueIdentifier>
+ <Extensions>ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="alarm_win.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="alarmlist.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="alarms.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="frame.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="icons.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="options.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="time_utils.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="trigger.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="alarm_win.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="alarmlist.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="alarms.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="common.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="frame.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="icons.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="m_alarms.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="options.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="resource.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="time_utils.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="trigger.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="bitmap1.bmp">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="clock.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="clockdow.bmp">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="flat_16x12.bmp">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="green.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="ico00001.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="icon1.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="icon2.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="icon3.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="iconttbdown.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="iconttbup.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ <None Include="yellow.ico">
+ <Filter>Resource Files</Filter>
+ </None>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="resource.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/plugins/Alarms/clock.ico b/plugins/Alarms/clock.ico
new file mode 100644
index 0000000000..300ca7c052
--- /dev/null
+++ b/plugins/Alarms/clock.ico
Binary files differ
diff --git a/plugins/Alarms/common.h b/plugins/Alarms/common.h
new file mode 100644
index 0000000000..0186d87228
--- /dev/null
+++ b/plugins/Alarms/common.h
@@ -0,0 +1,75 @@
+#ifndef _COMMON_INC
+#define _COMMON_INC
+
+
+#define _WIN32_WINNT 0x0500
+#define _WIN32_IE 0x0400
+
+#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+#define VC_EXTRALEAN
+
+#include <windows.h>
+#include <shellapi.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <commctrl.h>
+
+#include "resource.h"
+
+#include <newpluginapi.h>
+#include <m_system.h>
+#include <m_database.h>
+#include <m_options.h>
+#include <m_skin.h>
+#include <m_contacts.h>
+#include <m_protomod.h>
+#include <m_protosvc.h>
+#include <m_langpack.h>
+#include <m_popup.h>
+#include <m_utils.h>
+#include <m_idle.h>
+
+#include <m_clist.h>
+#include <m_clui.h>
+#include <m_clc.h>
+
+#include <m_cluiframes.h>
+#include <m_genmenu.h>
+
+#include <m_toptoolbar.h>
+#include <m_trigger.h>
+
+#include <m_fontservice.h>
+#include <m_updater.h>
+
+#include <m_alarms.h>
+
+#include <m_icolib.h>
+
+#define MODULE "Alarm"
+
+extern HINSTANCE hInst;
+extern PLUGINLINK *pluginLink;
+
+extern HANDLE hTopToolbarButton;
+
+typedef struct ALARM_tag {
+ unsigned short id;
+ char *szTitle;
+ char *szDesc;
+ Occurrence occurrence;
+ BOOL snoozer;
+ SYSTEMTIME time;
+ unsigned short action;
+ char *szCommand;
+ char *szCommandParams;
+ BYTE sound_num;
+ int flags;
+ DWORD trigger_id;
+} ALARM;
+
+#ifndef MIID_ALARMS
+#define MIID_ALARMS {0x60ebaad1, 0x8d95, 0x4966, { 0x8b, 0xe3, 0xb1, 0xed, 0xaf, 0xa2, 0x11, 0xab}}
+#endif
+
+#endif
diff --git a/plugins/Alarms/frame.cpp b/plugins/Alarms/frame.cpp
new file mode 100644
index 0000000000..6999d10b0c
--- /dev/null
+++ b/plugins/Alarms/frame.cpp
@@ -0,0 +1,679 @@
+#include "common.h"
+#include "frame.h"
+
+HWND hwnd_plugin = 0;
+HWND hwnd_frame = 0;
+HWND hwnd_list = 0;
+
+int frame_id = -1;
+
+FontID font_id;
+ColourID framebk_colour_id;
+HFONT hFont = 0;
+COLORREF fontColour, framebk;
+HBRUSH bk_brush = 0;
+
+AlarmList alarm_list;
+CRITICAL_SECTION list_cs;
+
+HANDLE hMenuShowReminders = 0;
+
+#define ID_FRAME_UPDATE_TIMER 1011
+#define ID_FRAME_SHOWHIDE_TIMER 1012
+
+#define WMU_FILL_LIST (WM_USER + 10)
+#define WMU_SIZE_LIST (WM_USER + 11)
+#define WMU_INITIALIZE (WM_USER + 12)
+
+void FixMainMenu();
+
+int height_client_to_frame(int client_height, LONG style, LONG ex_style) {
+ RECT tr;
+ tr.top = tr.right = tr.left = 0;
+ tr.bottom = client_height;
+ if(AdjustWindowRectEx(&tr, style, FALSE, ex_style))
+ return tr.bottom - tr.top;
+ return 0;
+}
+
+LRESULT CALLBACK FrameContainerWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
+ switch(msg) {
+ case WM_CREATE:
+ return TRUE;
+ case WM_SHOWWINDOW:
+ if((BOOL)wParam) {
+ DBWriteContactSettingByte(0, MODULE, "ReminderFrameVisible", 1);
+ Utils_RestoreWindowPosition(hwnd, 0, MODULE, "reminders_window");
+ PostMessage(hwnd, WM_SIZE, 0, 0);
+ } else {
+ DBWriteContactSettingByte(0, MODULE, "ReminderFrameVisible", 0);
+ Utils_SaveWindowPosition(hwnd, 0, MODULE, "reminders_window");
+ }
+ break;
+ case WM_SIZE:
+ {
+ HWND child = (HWND)GetWindowLong(hwnd, GWL_USERDATA);
+ RECT r;
+ GetClientRect(hwnd, &r);
+
+ SetWindowPos(child, 0, r.left, r.top, r.right - r.left, r.bottom - r.top, SWP_NOZORDER | SWP_NOACTIVATE);
+ InvalidateRect(child, 0, TRUE);
+ InvalidateRect(hwnd, 0, TRUE);
+ }
+ break;
+
+ case WM_CLOSE:
+ Utils_SaveWindowPosition(hwnd, 0, MODULE, "reminders_window");
+ ShowWindow(hwnd, SW_HIDE);
+ FixMainMenu();
+ return TRUE;
+ }
+
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+}
+
+bool FrameIsFloating() {
+ if(frame_id == -1)
+ return true; // no frames, always floating
+
+ return (CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS, MAKEWPARAM(FO_FLOATING, frame_id), 0) != 0);
+}
+
+ALARM context_menu_alarm = {0};
+
+LRESULT CALLBACK FrameWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
+ MEASUREITEMSTRUCT *mis;
+ DRAWITEMSTRUCT *dis;
+ SIZE textSize;
+ SIZE timeSize;
+
+ switch(msg) {
+
+ case WM_CREATE:
+ {
+ hwnd_list = CreateWindow("LISTBOX", "",
+ (WS_VISIBLE | WS_CHILD | LBS_NOINTEGRALHEIGHT | LBS_STANDARD | LBS_NOTIFY | LBS_OWNERDRAWFIXED) & ~LBS_SORT
+ & ~WS_BORDER, 0, 0, 0, 0, hwnd, NULL, hInst,0);
+ }
+ return FALSE;
+ case WMU_INITIALIZE:
+ PostMessage(hwnd, WMU_FILL_LIST, 0, 0);
+ SetTimer(hwnd, ID_FRAME_UPDATE_TIMER, 5000, 0);
+ SetTimer(hwnd, ID_FRAME_SHOWHIDE_TIMER, 200, 0);
+ return TRUE;
+
+ case WM_MEASUREITEM:
+ mis = (MEASUREITEMSTRUCT *)lParam;
+ mis->itemHeight = options.row_height;
+ return TRUE;
+
+ case WM_DRAWITEM:
+ dis = (DRAWITEMSTRUCT *)lParam;
+ if(dis->itemID != (DWORD)-1) {
+ ALARM alarm = {0};
+ EnterCriticalSection(&list_cs);
+ ALARM &list_alarm = alarm_list.at(dis->itemData);
+ copy_alarm_data(&alarm, &list_alarm);
+ LeaveCriticalSection(&list_cs);
+
+ RECT r;
+ GetClientRect(hwnd, &r);
+
+ int min = MinutesInFuture(alarm.time, alarm.occurrence);
+
+ FillRect(dis->hDC, &dis->rcItem, bk_brush);
+
+ dis->rcItem.left += options.indent;
+
+ SetBkMode(dis->hDC, TRANSPARENT);
+ SetTextColor(dis->hDC, fontColour);
+
+ HICON hIcon = (min <= 5 ? hIconList2 : hIconList1);
+ //DrawIconEx(dis->hDC,dis->rcItem.left,(dis->rcItem.top + dis->rcItem.bottom -GetSystemMetrics(SM_CYSMICON))>>1,hIcon,GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),0,NULL,DI_NORMAL);
+ DrawIconEx(dis->hDC,dis->rcItem.left,(dis->rcItem.top + dis->rcItem.bottom - 16)>>1,hIcon,0, 0, 0, NULL, DI_NORMAL);
+
+ GetTextExtentPoint32(dis->hDC,alarm.szTitle,lstrlen(alarm.szTitle),&textSize);
+
+ char buff[100];
+ if(min >= 60) {
+ mir_snprintf(buff, 100, Translate("%dh %dm"), min / 60, min % 60);
+ } else {
+ mir_snprintf(buff, 100, Translate("%dm"), min);
+ }
+
+ GetTextExtentPoint32(dis->hDC,buff,lstrlen(buff),&timeSize);
+
+ if(textSize.cx > (dis->rcItem.right - dis->rcItem.left) - (GetSystemMetrics(SM_CXSMICON) + 4) - timeSize.cx - 2 - 4) {
+ // need elipsis
+ char titlebuff[512];
+ int len = lstrlen(alarm.szTitle);
+ if(len > 511) len = 511;
+ while(len > 0 && textSize.cx > (dis->rcItem.right - dis->rcItem.left) - (GetSystemMetrics(SM_CXSMICON) + 4) - timeSize.cx - 2 - 4) {
+ len--;
+ strncpy(titlebuff, alarm.szTitle, len);
+ titlebuff[len] = 0;
+ strcat(titlebuff, "...");
+ GetTextExtentPoint32(dis->hDC,titlebuff,lstrlen(titlebuff),&textSize);
+ }
+ TextOut(dis->hDC,dis->rcItem.left + 16 + 4,(dis->rcItem.top + dis->rcItem.bottom - textSize.cy)>>1,titlebuff,lstrlen(titlebuff));
+ TextOut(dis->hDC,dis->rcItem.right - timeSize.cx - 2,(dis->rcItem.top + dis->rcItem.bottom - timeSize.cy)>>1, buff,lstrlen(buff));
+ } else {
+ TextOut(dis->hDC,dis->rcItem.left + 16 + 4,(dis->rcItem.top + dis->rcItem.bottom - textSize.cy)>>1,alarm.szTitle,lstrlen(alarm.szTitle));
+ TextOut(dis->hDC,dis->rcItem.right - timeSize.cx - 2,(dis->rcItem.top + dis->rcItem.bottom - timeSize.cy)>>1, buff,lstrlen(buff));
+ }
+
+ SetBkMode(dis->hDC, OPAQUE);
+
+ free_alarm_data(&alarm);
+ } else {
+ FillRect(dis->hDC, &dis->rcItem, bk_brush);
+ }
+ return TRUE;
+
+ case WM_CTLCOLORLISTBOX:
+ break;
+ case WM_ERASEBKGND:
+ {
+ HDC hdc = (HDC)wParam;
+ RECT r;
+ GetClientRect(hwnd, &r);
+ FillRect(hdc, &r, bk_brush);
+ }
+ return TRUE;
+
+ case WM_PRINTCLIENT:
+ {
+ /*
+ HDC hdc = (HDC)wParam;
+ RECT r;
+ GetClientRect(hwnd, &r);
+ */
+ }
+ return TRUE;
+
+ case WM_PAINT:
+ {
+ RECT r;
+ if(GetUpdateRect(hwnd, &r, FALSE)) {
+ PAINTSTRUCT ps;
+ HDC hdc = BeginPaint(hwnd, &ps);
+ SendMessage(hwnd, WM_PRINTCLIENT, (WPARAM)hdc, (LPARAM)(PRF_CLIENT | PRF_CHILDREN));
+ EndPaint(hwnd, &ps);
+ }
+ }
+ return TRUE;
+
+ case WM_SHOWWINDOW:
+ if((BOOL)wParam) PostMessage(hwnd, WMU_SIZE_LIST, 0, 0);
+ break;
+
+ case WM_SIZE:
+ if(IsWindowVisible(hwnd)) {
+ SendMessage(hwnd, WMU_SIZE_LIST, 0, 0);
+
+ if(frame_id != -1) {
+ //CallService(MS_CLIST_FRAMES_UPDATEFRAME, (WPARAM)frame_id, (LPARAM)(FU_TBREDRAW | FU_FMREDRAW));
+ CallService(MS_CLIST_FRAMES_UPDATEFRAME, (WPARAM)frame_id, (LPARAM)FU_TBREDRAW);
+ }
+ InvalidateRect(hwnd, 0, TRUE);
+ }
+ break;
+
+ case WMU_SIZE_LIST:
+ {
+ if(SendMessage(hwnd_list, LB_GETITEMHEIGHT, 0, 0) != options.row_height)
+ SendMessage(hwnd_list, LB_SETITEMHEIGHT, 0, options.row_height);
+
+ int itemheight = SendMessage(hwnd_list, LB_GETITEMHEIGHT, 0, 0),
+ count = SendMessage(hwnd_list, LB_GETCOUNT, 0, 0);
+
+ if(options.auto_size_vert && IsWindowVisible(hwnd)) {
+ if(FrameIsFloating()) {
+
+#define CLUIFrameTitleBarClassName "CLUIFrameTitleBar"
+
+ int height = height_client_to_frame(itemheight * count, GetWindowLong(GetParent(hwnd), GWL_STYLE), GetWindowLong(GetParent(hwnd), GWL_EXSTYLE));
+ HWND titleBarHwnd = FindWindowEx(GetParent(hwnd), 0, CLUIFrameTitleBarClassName, 0);
+ if(titleBarHwnd) {
+ RECT tbr;
+ GetWindowRect(titleBarHwnd, &tbr);
+ height += (tbr.bottom - tbr.top);
+ }
+ RECT rp_window;
+ GetWindowRect(GetParent(hwnd), &rp_window);
+ SetWindowPos(GetParent(hwnd), 0, 0, 0, rp_window.right - rp_window.left, height, SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
+
+ /*
+ RECT rp_client, rp_window, r_window;
+ GetClientRect(GetParent(hwnd), &rp_client);
+ GetWindowRect(GetParent(hwnd), &rp_window);
+ GetWindowRect(hwnd, &r_window);
+ int diff = (rp_window.bottom - rp_window.top) - (rp_client.bottom - rp_client.top);
+ if(ServiceExists(MS_CLIST_FRAMES_ADDFRAME))
+ diff += rp_window.top - r_window.top;
+ SetWindowPos(GetParent(hwnd), 0, 0, 0, rp_window.right - rp_window.left, count * itemheight + diff, SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
+ */
+ } else if(ServiceExists(MS_CLIST_FRAMES_ADDFRAME) && frame_id != -1) {
+ int flags = CallService(MS_CLIST_FRAMES_GETFRAMEOPTIONS, MAKEWPARAM(FO_FLAGS, frame_id), 0);
+ CallService(MS_CLIST_FRAMES_SETFRAMEOPTIONS, MAKEWPARAM(FO_HEIGHT, frame_id), (LPARAM)(count * itemheight));
+ CallService(MS_CLIST_FRAMES_UPDATEFRAME, (WPARAM)frame_id, (LPARAM)(FU_TBREDRAW | FU_FMREDRAW | FU_FMPOS));
+ }
+ }
+
+ RECT r, r2;
+ GetClientRect(hwnd, &r);
+ GetClientRect(hwnd_list, &r2);
+ int width, height, winheight;
+
+ width = r.right - r.left;
+ winheight = r.bottom - r.top;
+
+ height = min(count * itemheight, winheight - (winheight % itemheight));
+ if(r2.right - r2.left != width || (r.bottom - r.top > 0 && r2.bottom - r2.top != height)) {
+ SetWindowPos(hwnd_list, 0, 0, 0, width, height, SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
+ InvalidateRect(hwnd_list, 0, FALSE);
+ }
+
+ if(options.auto_showhide) {
+ if(ServiceExists(MS_CLIST_FRAMES_SHFRAME) && frame_id != -1) {
+ if(IsWindowVisible(hwnd) && count == 0) {
+ CallService(MS_CLIST_FRAMES_SHFRAME, (WPARAM)frame_id, 0);
+ } else if(!IsWindowVisible(hwnd) && count > 0) {
+ // we have reminders - show if not linked to clist or if clist is visible
+ if((!options.hide_with_clist && FrameIsFloating()) || IsWindowVisible((HWND)CallService(MS_CLUI_GETHWND, 0, 0))) {
+ CallService(MS_CLIST_FRAMES_SHFRAME, (WPARAM)frame_id, 0);
+ CallService(MS_CLIST_FRAMES_UPDATEFRAME, (WPARAM)frame_id, (LPARAM)(FU_FMREDRAW | FU_FMPOS));
+ }
+ }
+ } else {
+ if(IsWindowVisible(hwnd) && count == 0)
+ SetReminderFrameVisible(false);
+ else if(!IsWindowVisible(hwnd) && count > 0)
+ // we have reminders - show if not linked to clist or if clist is visible
+ if(!options.hide_with_clist || IsWindowVisible((HWND)CallService(MS_CLUI_GETHWND, 0, 0)))
+ SetReminderFrameVisible(true);
+ }
+ }
+
+ }
+ return TRUE;
+ case WMU_FILL_LIST:
+ {
+ // calculate the period to display alarms for
+ SYSTEMTIME t1, t2;
+ GetLocalTime(&t1);
+ TimeForMinutesInFuture(60 * options.reminder_period, &t2);
+
+ int sel = SendMessage(hwnd_list, LB_GETCURSEL, 0, 0),
+ top = SendMessage(hwnd_list, LB_GETTOPINDEX, 0, 0);
+
+ SendMessage(hwnd_list, WM_SETREDRAW, (WPARAM)FALSE, 0);
+
+ EnterCriticalSection(&list_cs);
+ SendMessage(hwnd_list, LB_RESETCONTENT, 0, 0);
+ copy_list(alarm_list, t1, t2);
+ alarm_list.sort();
+ int index = 0;
+ ALARM *i;
+ for(alarm_list.reset(); i = alarm_list.current(); alarm_list.next(), index++) {
+ if(i->flags & (ALF_HIDDEN | ALF_SUSPENDED | ALF_NOREMINDER))
+ continue;
+ SendMessage(hwnd_list, LB_ADDSTRING, 0, (LPARAM)index);
+ }
+ LeaveCriticalSection(&list_cs);
+
+ SendMessage(hwnd, WMU_SIZE_LIST, 0, 0);
+ SendMessage(hwnd_list, WM_SETREDRAW, (WPARAM)TRUE, 0);
+
+ if(sel != LB_ERR && sel < index) SendMessage(hwnd_list, LB_SETCURSEL, (WPARAM)sel, 0);
+ if(top != LB_ERR && top < index) SendMessage(hwnd_list, LB_SETTOPINDEX, (WPARAM)top, 0);
+
+ }
+ return TRUE;
+
+ case WM_TIMER:
+ if(wParam == ID_FRAME_UPDATE_TIMER)
+ SendMessage(hwnd, WMU_FILL_LIST, 0, 0);
+ else if(wParam == ID_FRAME_SHOWHIDE_TIMER && options.hide_with_clist) { // link show/hide with clist
+ // hide if we're visible and clist isn't (possible only when floating if frames are present)
+ if(!IsWindowVisible((HWND)CallService(MS_CLUI_GETHWND, 0, 0)) && IsWindowVisible(hwnd)) {
+ if(ServiceExists(MS_CLIST_FRAMES_SHFRAME))
+ CallService(MS_CLIST_FRAMES_SHFRAME, (WPARAM)frame_id, 0);
+ else
+ SetReminderFrameVisible(false);
+ }
+ // we're not visible but clist is - show depending on hide_with_clist and auto_showhide options
+ if(!IsWindowVisible(hwnd) && IsWindowVisible((HWND)CallService(MS_CLUI_GETHWND, 0, 0))) {
+ // if not auto show/hide, show (reminders or not) if we're not visible and the clist is
+ // otherwise, show only if there are reminders
+ int count = SendMessage(hwnd_list, LB_GETCOUNT, 0, 0);
+ if(!options.auto_showhide || count > 0) {
+ if(ServiceExists(MS_CLIST_FRAMES_SHFRAME))
+ CallService(MS_CLIST_FRAMES_SHFRAME, (WPARAM)frame_id, 0);
+ else
+ SetReminderFrameVisible(true);
+ }
+ }
+ }
+ return TRUE;
+
+ case WM_CONTEXTMENU:
+ {
+ /*
+ */
+ POINT pt;
+ GetCursorPos(&pt);
+ ScreenToClient(hwnd_list, &pt);
+
+ EnterCriticalSection(&list_cs);
+ DWORD item = SendMessage(hwnd_list, LB_ITEMFROMPOINT, 0, MAKELPARAM(pt.x, pt.y));
+
+ HMENU menu = LoadMenu(hInst, MAKEINTRESOURCE(IDR_MENU1)), submenu = GetSubMenu(menu, 0);
+ CallService(MS_LANGPACK_TRANSLATEMENU,(WPARAM)submenu,0);
+
+ if(HIWORD(item) == 0) {
+ int sel = LOWORD(item);
+ if(sel >= 0) {
+ // one-off alarms can't be suspended
+ int index = SendMessage(hwnd_list, LB_GETITEMDATA, (WPARAM)sel, 0);
+ ALARM &list_alarm = alarm_list.at(index);
+ copy_alarm_data(&context_menu_alarm, &list_alarm);
+ if(context_menu_alarm.occurrence == OC_ONCE)
+ EnableMenuItem(submenu, ID_REMINDERFRAMECONTEXT_SUSPEND, MF_BYCOMMAND | MF_GRAYED);
+
+ }
+ } else {
+ EnableMenuItem(submenu, ID_REMINDERFRAMECONTEXT_SUSPEND, MF_BYCOMMAND | MF_GRAYED);
+ EnableMenuItem(submenu, ID_REMINDERFRAMECONTEXT_EDIT, MF_BYCOMMAND | MF_GRAYED);
+ EnableMenuItem(submenu, ID_REMINDERFRAMECONTEXT_DELETE, MF_BYCOMMAND | MF_GRAYED);
+ }
+ LeaveCriticalSection(&list_cs);
+
+ //ClientToScreen(hwnd_list, &pt);
+ GetCursorPos(&pt);
+
+ BOOL ret = TrackPopupMenu(submenu, TPM_TOPALIGN|TPM_LEFTALIGN|TPM_RIGHTBUTTON|TPM_RETURNCMD, pt.x, pt.y, 0, hwnd, NULL);
+ DestroyMenu(menu);
+ if(ret) PostMessage(hwnd, WM_COMMAND, ret, 0);
+ }
+ return TRUE;
+
+ case WM_COMMAND:
+ switch(LOWORD(wParam)) {
+ case ID_REMINDERFRAMECONTEXT_OPTIONS:
+ {
+ OPENOPTIONSDIALOG oop;
+ oop.cbSize = sizeof(oop);
+ oop.pszGroup = Translate("Events");
+ oop.pszPage = Translate("Alarms");
+ oop.pszTab = 0;
+ CallService(MS_OPT_OPENOPTIONS, 0, (LPARAM)&oop);
+ }
+ break;
+ case ID_REMINDERFRAMECONTEXT_SUSPEND:
+ if(context_menu_alarm.occurrence != OC_ONCE) {
+ suspend(context_menu_alarm.id);
+ PostMessage(hwnd, WMU_FILL_LIST, 0, 0);
+ if(hwndOptionsDialog) {
+ // refresh options list
+ PostMessage(hwndOptionsDialog, WMU_INITOPTLIST, 0, 0);
+ }
+ }
+ break;
+ case ID_REMINDERFRAMECONTEXT_EDIT:
+ EditNonModal(context_menu_alarm);
+ break;
+ case ID_REMINDERFRAMECONTEXT_DELETE:
+ remove(context_menu_alarm.id);
+ PostMessage(hwnd, WMU_FILL_LIST, 0, 0);
+ if(hwndOptionsDialog) {
+ // refresh options list
+ PostMessage(hwndOptionsDialog, WMU_INITOPTLIST, 0, 0);
+ }
+ break;
+
+ case ID_REMINDERFRAMECONTEXT_NEWALARM:
+ NewAlarmMenuFunc(0, 0);
+ break;
+ }
+ return TRUE;
+
+ case WM_DESTROY:
+ KillTimer(hwnd, ID_FRAME_UPDATE_TIMER);
+ KillTimer(hwnd, ID_FRAME_SHOWHIDE_TIMER);
+ free_alarm_data(&context_menu_alarm);
+ break;
+ }
+
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+}
+
+int ReloadFont(WPARAM wParam, LPARAM lParam) {
+ DeleteObject(hFont);
+
+ LOGFONT log_font;
+ fontColour = CallService(MS_FONT_GET, (WPARAM)&font_id, (LPARAM)&log_font);
+ hFont = CreateFontIndirect(&log_font);
+ SendMessage(hwnd_list, WM_SETFONT, (WPARAM)hFont, (LPARAM)TRUE);
+
+ DeleteObject(bk_brush);
+ bk_brush = CreateSolidBrush(DBGetContactSettingDword(0, "Alarm", "clFrameBack", GetSysColor(COLOR_3DFACE)));
+ RefreshReminderFrame();
+
+ return 0;
+}
+
+void FixMainMenu() {
+ CLISTMENUITEM mi = {0};
+ mi.cbSize = sizeof(CLISTMENUITEM);
+ if(!ServiceExists(MS_CLIST_FRAMES_ADDFRAME)) {
+ if(options.hide_with_clist || options.auto_showhide) {
+ mi.flags = CMIM_FLAGS | CMIF_GRAYED;
+ } else {
+ mi.flags = CMIM_NAME | CMIM_FLAGS;
+
+ if(ReminderFrameVisible())
+ mi.pszName = Translate("Hide Reminders");
+ else
+ mi.pszName = Translate("Show Reminders");
+ }
+ }
+ CallService(MS_CLIST_MODIFYMENUITEM, (WPARAM)hMenuShowReminders, (LPARAM)&mi);
+}
+
+/////////////////////////
+// only used when no multiwindow functionality is available
+bool ReminderFrameVisible() {
+ return IsWindowVisible(hwnd_frame) ? true : false;
+}
+
+void SetReminderFrameVisible(bool visible) {
+ if(frame_id == -1 && hwnd_frame != 0)
+ ShowWindow(hwnd_frame, visible ? SW_SHOW : SW_HIDE);
+}
+
+int ShowHideMenuFunc(WPARAM wParam, LPARAM lParam) {
+ if(ReminderFrameVisible())
+ SendMessage(hwnd_frame, WM_CLOSE, 0, 0);
+ else {
+ ShowWindow(hwnd_frame, SW_SHOW);
+ }
+ FixMainMenu();
+ return 0;
+}
+//////////////////////////////
+
+int CreateFrame()
+{
+ WNDCLASS wndclass;
+ wndclass.style = 0;
+ wndclass.lpfnWndProc = FrameWindowProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = 0;
+ wndclass.hInstance = hInst;
+ wndclass.hIcon = NULL;
+ wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
+ wndclass.hbrBackground = 0; //(HBRUSH)(COLOR_3DFACE+1);
+ wndclass.lpszMenuName = NULL;
+ wndclass.lpszClassName = "AlarmsFrame";
+ RegisterClass(&wndclass);
+
+ if(ServiceExists(MS_CLIST_FRAMES_ADDFRAME)) {
+
+ hwnd_plugin = CreateWindow("AlarmsFrame",Translate("Alarms"),
+ WS_CHILD | WS_CLIPCHILDREN,
+ 0,0,10,10, (HWND)CallService(MS_CLUI_GETHWND, 0, 0), NULL,hInst,NULL);
+
+ CLISTFrame Frame = {0};
+
+ Frame.cbSize=sizeof(CLISTFrame);
+ Frame.name = Frame.TBname = Translate("Alarms");
+ Frame.hWnd=hwnd_plugin;
+ Frame.align=alBottom;
+ Frame.Flags=F_VISIBLE|F_SHOWTB|F_SHOWTBTIP;
+ Frame.height=30;
+
+ frame_id=CallService(MS_CLIST_FRAMES_ADDFRAME,(WPARAM)&Frame,0);
+ } else {
+ wndclass.style = 0;//CS_HREDRAW | CS_VREDRAW;
+ wndclass.lpfnWndProc = FrameContainerWindowProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = 0;
+ wndclass.hInstance = hInst;
+ wndclass.hIcon = NULL;
+ wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
+ wndclass.hbrBackground = 0; //(HBRUSH)(COLOR_3DFACE+1);
+ wndclass.lpszMenuName = NULL;
+ wndclass.lpszClassName = "AlarmsFrameContainer";
+ RegisterClass(&wndclass);
+
+ hwnd_frame = CreateWindowEx(WS_EX_TOOLWINDOW, "AlarmsFrameContainer",Translate("Alarms"),
+ (WS_POPUPWINDOW | WS_THICKFRAME | WS_CAPTION | WS_SYSMENU | WS_CLIPCHILDREN) & ~WS_VISIBLE,
+ 0,0,200,100, (HWND)CallService(MS_CLUI_GETHWND, 0, 0), NULL,hInst,NULL);
+ //0,0,200,100, GetDesktopWindow(), NULL,hInst,NULL);
+
+ hwnd_plugin = CreateWindow("AlarmsFrame",Translate("Alarms"),
+ WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE,
+ 0,0,10,10, hwnd_frame, NULL,hInst,NULL);
+
+ SetWindowLong(hwnd_frame, GWL_USERDATA, (LONG)hwnd_plugin);
+
+ ///////////////////////
+ // create menu item
+ CreateServiceFunction(MODULE "/ShowHideReminders", ShowHideMenuFunc);
+
+ CLISTMENUITEM menu = {0};
+
+ menu.cbSize=sizeof(menu);
+ menu.flags = CMIM_ALL;
+
+ menu.hIcon=hIconMenuShowHide;
+ menu.pszName = Translate("Show Reminders");
+ menu.pszService= MODULE "/ShowHideReminders";
+ menu.pszPopupName = Translate("Alarms");
+ menu.position = 500010000;
+ hMenuShowReminders = (HANDLE)CallService(MS_CLIST_ADDMAINMENUITEM, 0, (LPARAM)&menu);
+ /////////////////////
+
+ if(!options.auto_showhide) {
+ if(options.hide_with_clist) {
+ if(IsWindowVisible((HWND)CallService(MS_CLUI_GETHWND, 0, 0))) {
+ ShowWindow(hwnd_frame, SW_SHOW);
+ RefreshReminderFrame();
+ } else {
+ ShowWindow(hwnd_frame, SW_HIDE);
+ }
+ } else {
+ if(DBGetContactSettingByte(0, MODULE, "ReminderFrameVisible", 1) == 1) {
+ ShowWindow(hwnd_frame, SW_SHOW);
+ RefreshReminderFrame();
+ } else {
+ ShowWindow(hwnd_frame, SW_HIDE);
+ }
+ }
+ }
+
+ FixMainMenu();
+ }
+
+ SendMessage(hwnd_plugin, WMU_INITIALIZE, 0, 0);
+
+ if(ServiceExists(MS_FONT_REGISTER)) {
+ font_id.cbSize = sizeof(FontID);
+ strncpy(font_id.group, Translate("Frames"), sizeof(font_id.group));
+ strncpy(font_id.name, Translate("Alarm Reminders"), sizeof(font_id.name));
+ strncpy(font_id.dbSettingsGroup, MODULE, sizeof(font_id.dbSettingsGroup));
+ strncpy(font_id.prefix, "Font", sizeof(font_id.prefix));
+ font_id.order = 0;
+ CallService(MS_FONT_REGISTER, (WPARAM)&font_id, 0);
+
+ framebk_colour_id.cbSize = sizeof(ColourID);
+ strcpy(framebk_colour_id.dbSettingsGroup, MODULE);
+ strcpy(framebk_colour_id.group, Translate("Frames"));
+ strcpy(framebk_colour_id.name, Translate("Alarm Reminders"));
+ strcpy(framebk_colour_id.setting, "clFrameBack");
+ framebk_colour_id.defcolour = GetSysColor(COLOR_3DFACE);
+ framebk_colour_id.flags = 0;
+ framebk_colour_id.order = 0;
+ CallService(MS_COLOUR_REGISTER, (WPARAM)&framebk_colour_id, 0);
+
+ LOGFONT log_font;
+ fontColour = CallService(MS_FONT_GET, (WPARAM)&font_id, (LPARAM)&log_font);
+ hFont = CreateFontIndirect(&log_font);
+ SendMessage(hwnd_list, WM_SETFONT, (WPARAM)hFont, (LPARAM)TRUE);
+
+ HookEvent(ME_FONT_RELOAD, ReloadFont);
+
+ } else {
+ LOGFONT lf;
+ SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(LOGFONT), &lf, FALSE);
+ lf.lfHeight = 10;
+
+ HDC hdc = GetDC(0);
+ lf.lfHeight = -MulDiv(lf.lfHeight,GetDeviceCaps(hdc, LOGPIXELSY), 72);
+ ReleaseDC(0, hdc);
+
+ hFont = CreateFontIndirect(&lf);
+
+ //fontColour = GetSysColor(COLOR_WINDOWTEXT);
+ // match clist 'normal contact' colour if no font service
+ fontColour = (COLORREF)DBGetContactSettingDword(0, "CLC", "Font0Col", GetSysColor(COLOR_WINDOWTEXT));
+ }
+
+ // create the brush used for the background in the absence of clist_modern skinning features - match clist
+ bk_brush = CreateSolidBrush(DBGetContactSettingDword(0, "Alarm", "clFrameBack", GetSysColor(COLOR_3DFACE)));
+
+ SendMessage(hwnd_list, WM_SETFONT, (WPARAM)hFont, (LPARAM)TRUE);
+
+ return 0;
+}
+
+void RefreshReminderFrame() {
+ SendMessage(hwnd_plugin, WMU_FILL_LIST, 0, 0);
+
+ if(frame_id == -1) {
+ InvalidateRect(hwnd_frame, 0, TRUE);
+ } else
+ InvalidateRect(hwnd_plugin, 0, TRUE);
+
+}
+
+void InitFrames()
+{
+ InitializeCriticalSection(&list_cs);
+ CreateFrame();
+}
+
+void DeinitFrames()
+{
+ if(ServiceExists(MS_CLIST_FRAMES_REMOVEFRAME)) {
+ CallService(MS_CLIST_FRAMES_REMOVEFRAME, (WPARAM)frame_id, 0);
+ }
+ DestroyWindow(hwnd_plugin);
+ if(hwnd_frame) DestroyWindow(hwnd_frame);
+
+ DeleteObject(bk_brush);
+
+ DeleteCriticalSection(&list_cs);
+}
+
diff --git a/plugins/Alarms/frame.h b/plugins/Alarms/frame.h
new file mode 100644
index 0000000000..9333c31b7d
--- /dev/null
+++ b/plugins/Alarms/frame.h
@@ -0,0 +1,20 @@
+#ifndef _FRAME_INC
+#define _FRAME_INC
+
+#include "alarmlist.h"
+#include "icons.h"
+#include "options.h"
+
+void RefreshReminderFrame();
+
+void InitFrames();
+void DeinitFrames();
+
+// update 'show/hide reminder frame' menu item
+void FixMainMenu();
+
+// used when no multiwindow functionality avaiable
+bool ReminderFrameVisible();
+void SetReminderFrameVisible(bool visible);
+
+#endif
diff --git a/plugins/Alarms/glyph.c b/plugins/Alarms/glyph.c
new file mode 100644
index 0000000000..b7e4a3e5ff
--- /dev/null
+++ b/plugins/Alarms/glyph.c
@@ -0,0 +1,537 @@
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+#include <GL/gl.h>
+#include <assert.h>
+
+static const unsigned char g20[] = {
+ 0xff, 0xff
+};
+static const unsigned char g21[] = {
+ 0x60, 0x80, 0x62, 0x82, 0xff, 0x64, 0x84, 0x6e,
+ 0x8e, 0xff, 0xff
+};
+static const unsigned char g22[] = {
+ 0x6a, 0x6e, 0x4c, 0x4e, 0xff, 0x8a, 0xac, 0x8e,
+ 0xae, 0xff, 0xff
+};
+static const unsigned char g23[] = {
+ 0x42, 0x62, 0x44, 0x64, 0x46, 0x66, 0x48, 0x68,
+ 0x4a, 0x6a, 0x4c, 0x6c, 0xff, 0x82, 0xa2, 0x84,
+ 0xa4, 0x86, 0xa6, 0x88, 0xa8, 0x8a, 0xaa, 0x8c,
+ 0xac, 0xff, 0x24, 0x44, 0x26, 0x46, 0xff, 0x64,
+ 0x84, 0x66, 0x86, 0xff, 0xa4, 0xc4, 0xa6, 0xc6,
+ 0xff, 0x28, 0x48, 0x2a, 0x4a, 0xff, 0x68, 0x88,
+ 0x6a, 0x8a, 0xff, 0xa8, 0xc8, 0xaa, 0xca, 0xff,
+ 0xff
+};
+static const unsigned char g24[] = {
+ 0x46, 0x48, 0x26, 0x38, 0x08, 0x29, 0x0a, 0x3a,
+ 0x2c, 0x4a, 0x4c, 0xff, 0xa8, 0xa6, 0xc8, 0xb6,
+ 0xe6, 0xc5, 0xe4, 0xb4, 0xc2, 0xa4, 0xa2, 0xff,
+ 0x25, 0x04, 0x34, 0x22, 0x44, 0x42, 0xff, 0xc9,
+ 0xea, 0xba, 0xcc, 0xaa, 0xac, 0xff, 0x40, 0x60,
+ 0x42, 0x62, 0x44, 0x64, 0x46, 0x66, 0x48, 0x68,
+ 0x4a, 0x6a, 0x4c, 0x6c, 0x4e, 0x6e, 0xff, 0x80,
+ 0xa0, 0x82, 0xa2, 0x84, 0xa4, 0x86, 0xa6, 0x88,
+ 0xa8, 0x8a, 0xaa, 0x8c, 0xac, 0x8e, 0xae, 0xff,
+ 0x62, 0x82, 0x64, 0x84, 0xff, 0x66, 0x86, 0x68,
+ 0x88, 0xff, 0x6a, 0x8a, 0x6c, 0x8c, 0xff, 0xff
+};
+static const unsigned char g25[] = {
+ 0x00, 0x20, 0x02, 0xec, 0xce, 0xee, 0xff, 0xa0,
+ 0xb2, 0x82, 0xa3, 0x84, 0xb4, 0xa6, 0xc6, 0xff,
+ 0xc6, 0xb4, 0xe4, 0xc3, 0xe2, 0xb2, 0xc0, 0xa0,
+ 0xff, 0x28, 0x3a, 0x0a, 0x2b, 0x0c, 0x3c, 0x2e,
+ 0x4e, 0xff, 0x4e, 0x3c, 0x6c, 0x4b, 0x6a, 0x3a,
+ 0x48, 0x28, 0xff, 0xff
+};
+static const unsigned char g26[] = {
+ 0xa0, 0xe0, 0x91, 0xb3, 0x73, 0x95, 0x55, 0x77,
+ 0x37, 0x59, 0x28, 0x4a, 0x2c, 0x4b, 0x4e, 0x5c,
+ 0x6e, 0x6b, 0x8c, 0x6a, 0x88, 0x59, 0x77, 0xff,
+ 0x91, 0x73, 0x80, 0x62, 0x20, 0x42, 0x02, 0x33,
+ 0x04, 0x55, 0x37, 0xff, 0x95, 0xb3, 0xa6, 0xc4,
+ 0xff, 0xff
+};
+static const unsigned char g27[] = {
+ 0x6a, 0x8c, 0x6e, 0x8e, 0xff, 0xff
+};
+static const unsigned char g28[] = {
+ 0x80, 0xa0, 0x62, 0x82, 0x6c, 0x8c, 0x8e, 0xae,
+ 0xff, 0xff
+};
+static const unsigned char g29[] = {
+ 0x40, 0x60, 0x62, 0x82, 0x6c, 0x8c, 0x4e, 0x6e,
+ 0xff, 0xff
+};
+static const unsigned char g2A[] = {
+ 0x77, 0xa8, 0x8a, 0xb9, 0x9b, 0xff, 0x77, 0x8a,
+ 0x6a, 0x8c, 0x6c, 0xff, 0x77, 0x6a, 0x48, 0x5b,
+ 0x39, 0xff, 0x77, 0x48, 0x46, 0x28, 0x26, 0xff,
+ 0x77, 0x46, 0x64, 0x35, 0x53, 0xff, 0x77, 0x64,
+ 0x84, 0x62, 0x82, 0xff, 0x77, 0x84, 0xa6, 0x93,
+ 0xb5, 0xff, 0x77, 0xa6, 0xa8, 0xc6, 0xc8, 0xff,
+ 0xff
+};
+static const unsigned char g2B[] = {
+ 0x62, 0x82, 0x66, 0x86, 0x88, 0xc6, 0xc8, 0xff,
+ 0x8c, 0x6c, 0x88, 0x68, 0x66, 0x28, 0x26, 0xff,
+ 0xff
+};
+static const unsigned char g2C[] = {
+ 0x84, 0x64, 0x82, 0x60, 0xff, 0xff
+};
+static const unsigned char g2D[] = {
+ 0x28, 0x26, 0xc8, 0xc6, 0xff, 0xff
+};
+static const unsigned char g2E[] = {
+ 0x60, 0x80, 0x62, 0x82, 0xff, 0xff
+};
+static const unsigned char g2F[] = {
+ 0x00, 0x20, 0x02, 0xec, 0xce, 0xee, 0xff, 0xff
+};
+static const unsigned char g30[] = {
+ 0x24, 0x42, 0xac, 0xca, 0xff, 0xb2, 0xc0, 0xc3,
+ 0xe2, 0xca, 0xec, 0xac, 0xce, 0x3c, 0x2e, 0x2b,
+ 0x0c, 0x24, 0x02, 0x42, 0x20, 0xb2, 0xc0, 0xff,
+ 0xff
+};
+static const unsigned char g31[] = {
+ 0x80, 0xff, 0x4c, 0x4a, 0x6e, 0x6a, 0x8e, 0x60,
+ 0x80, 0xff, 0xff
+};
+static const unsigned char g32[] = {
+ 0x0c, 0x2b, 0x2e, 0x3c, 0xce, 0xbc, 0xec, 0xcb,
+ 0xe8, 0xc9, 0xc6, 0xb8, 0x36, 0x28, 0x25, 0x06,
+ 0x22, 0x00, 0xe2, 0xe0, 0xff, 0xff
+};
+static const unsigned char g33[] = {
+ 0x0c, 0x2b, 0x2e, 0x3c, 0xce, 0xbc, 0xec, 0xcb,
+ 0xe8, 0xc9, 0xd7, 0xb8, 0xb6, 0x68, 0x66, 0xff,
+ 0xd7, 0xb6, 0xe6, 0xc5, 0xe2, 0xc3, 0xc0, 0xb2,
+ 0x20, 0x32, 0x02, 0x23, 0xff, 0xff
+};
+static const unsigned char g34[] = {
+ 0xc6, 0xc8, 0x06, 0x28, 0x0c, 0x2c, 0xff, 0xc0,
+ 0xe0, 0xc6, 0xe7, 0xc8, 0xee, 0xce, 0xff, 0xff
+};
+static const unsigned char g35[] = {
+ 0xec, 0xee, 0x2c, 0x0e, 0x29, 0x08, 0x38, 0x26,
+ 0xc8, 0xb6, 0xe6, 0xc5, 0xe2, 0xc3, 0xc0, 0xb2,
+ 0x20, 0x32, 0x02, 0x23, 0xff, 0xff
+};
+static const unsigned char g36[] = {
+ 0xcb, 0xec, 0xbc, 0xce, 0x3c, 0x2e, 0x2b, 0x0c,
+ 0x28, 0x07, 0x26, 0x02, 0x23, 0x20, 0x32, 0xc0,
+ 0xb2, 0xe2, 0xc3, 0xe6, 0xc5, 0xc8, 0xb6, 0x28,
+ 0x26, 0xff, 0xff
+};
+static const unsigned char g37[] = {
+ 0x0e, 0x0c, 0xee, 0xbc, 0xec, 0x67, 0x86, 0x60,
+ 0x80, 0xff, 0xff
+};
+static const unsigned char g38[] = {
+ 0x36, 0x17, 0x25, 0x06, 0x23, 0x02, 0x32, 0x20,
+ 0xb2, 0xc0, 0xc3, 0xe2, 0xc5, 0xe6, 0xb6, 0xd7,
+ 0xb8, 0xe8, 0xc9, 0xec, 0xcb, 0xce, 0xbc, 0x2e,
+ 0x3c, 0x0c, 0x2b, 0x08, 0x29, 0x17, 0x38, 0x36,
+ 0xb8, 0xb6, 0xff, 0xff
+};
+static const unsigned char g39[] = {
+ 0x23, 0x02, 0x32, 0x20, 0xb2, 0xc0, 0xc3, 0xe2,
+ 0xc6, 0xe7, 0xc8, 0xec, 0xcb, 0xce, 0xbc, 0x2e,
+ 0x3c, 0x0c, 0x2b, 0x08, 0x29, 0x26, 0x38, 0xc6,
+ 0xc8, 0xff, 0xff
+};
+static const unsigned char g3A[] = {
+ 0x60, 0x80, 0x62, 0x82, 0xff, 0x66, 0x86, 0x68,
+ 0x88, 0xff, 0xff
+};
+static const unsigned char g3B[] = {
+ 0x84, 0x64, 0x82, 0x60, 0xff, 0x66, 0x86, 0x68,
+ 0x88, 0xff, 0xff
+};
+static const unsigned char g3C[] = {
+ 0xbc, 0x8c, 0x67, 0x37, 0xb2, 0x82, 0xff, 0xff
+};
+static const unsigned char g3D[] = {
+ 0x24, 0x26, 0xc4, 0xc6, 0xff, 0x28, 0x2a, 0xc8,
+ 0xca, 0xff, 0xff
+};
+static const unsigned char g3E[] = {
+ 0x32, 0x62, 0x87, 0xb7, 0x3c, 0x6c, 0xff, 0xff
+};
+static const unsigned char g3F[] = {
+ 0x60, 0x80, 0x62, 0x82, 0xff, 0x64, 0x84, 0x65,
+ 0xea, 0xcb, 0xec, 0xbc, 0xce, 0x3c, 0x2e, 0x2b,
+ 0x0c, 0xff, 0xff
+};
+static const unsigned char g40[] = {
+ 0xe2, 0xc3, 0xc0, 0xb2, 0x20, 0x32, 0x02, 0x23,
+ 0x0c, 0x2b, 0x2e, 0x3c, 0xce, 0xbc, 0xec, 0xcb,
+ 0xe6, 0xc7, 0xc4, 0xb6, 0xa4, 0xa6, 0x84, 0x86,
+ 0x64, 0x76, 0x46, 0x67, 0x48, 0x78, 0x6a, 0x88,
+ 0xaa, 0x86, 0xa6, 0xff, 0xff
+};
+static const unsigned char g41[] = {
+ 0x00, 0x20, 0x08, 0x26, 0x38, 0xc6, 0xb8, 0xff,
+ 0xc0, 0xe0, 0xc6, 0xe8, 0xb8, 0x8e, 0x7c, 0x6e,
+ 0x38, 0x08, 0xff, 0xff
+};
+static const unsigned char g42[] = {
+ 0xb8, 0xd7, 0xc9, 0xe8, 0xcb, 0xec, 0xbc, 0xce,
+ 0x2c, 0x0e, 0x28, 0x07, 0x26, 0x00, 0x22, 0xc0,
+ 0xb2, 0xe2, 0xc3, 0xe6, 0xc5, 0xd7, 0xb6, 0xb8,
+ 0x26, 0x28, 0xff, 0xff
+};
+static const unsigned char g43[] = {
+ 0xcb, 0xec, 0xbc, 0xce, 0x3c, 0x2e, 0x2b, 0x0c,
+ 0x23, 0x02, 0x32, 0x20, 0xb2, 0xc0, 0xc3, 0xe2,
+ 0xff, 0xff
+};
+static const unsigned char g44[] = {
+ 0x22, 0x00, 0xb2, 0xc0, 0xc3, 0xe2, 0xcb, 0xec,
+ 0xbc, 0xce, 0x2c, 0x0e, 0x22, 0x00, 0xff, 0xff
+};
+static const unsigned char g45[] = {
+ 0xe0, 0xe2, 0x00, 0x22, 0x06, 0x26, 0x08, 0x28,
+ 0x0e, 0x2c, 0xee, 0xec, 0xff, 0x28, 0x26, 0x88,
+ 0x86, 0xff, 0xff
+};
+static const unsigned char g46[] = {
+ 0x00, 0x20, 0x06, 0x26, 0x08, 0x28, 0x0e, 0x2c,
+ 0xee, 0xec, 0xff, 0x28, 0x26, 0x88, 0x86, 0xff,
+ 0xff
+};
+static const unsigned char g47[] = {
+ 0xcb, 0xec, 0xbc, 0xce, 0x3c, 0x2e, 0x2b, 0x0c,
+ 0x23, 0x02, 0x32, 0x20, 0xb2, 0xc0, 0xc3, 0xe2,
+ 0xc6, 0xe8, 0x86, 0x88, 0xff, 0xff
+};
+static const unsigned char g48[] = {
+ 0x2e, 0x0e, 0x28, 0x07, 0x26, 0x00, 0x20, 0xff,
+ 0xc0, 0xe0, 0xc6, 0xe7, 0xc8, 0xee, 0xce, 0xff,
+ 0x28, 0x26, 0xc8, 0xc6, 0xff, 0xff
+};
+static const unsigned char g49[] = {
+ 0x42, 0x40, 0x62, 0x60, 0x82, 0x80, 0xa2, 0xa0,
+ 0xff, 0x4e, 0x4c, 0x6e, 0x6c, 0x8e, 0x8c, 0xae,
+ 0xac, 0xff, 0x62, 0x82, 0x6c, 0x8c, 0xff, 0xff
+};
+static const unsigned char g4A[] = {
+ 0x23, 0x02, 0x32, 0x20, 0xb2, 0xc0, 0xc3, 0xe2,
+ 0xce, 0xee, 0xff, 0xff
+};
+static const unsigned char g4B[] = {
+ 0x2e, 0x0e, 0x28, 0x07, 0x26, 0x00, 0x20, 0xff,
+ 0x28, 0x26, 0x68, 0x66, 0x97, 0xc0, 0xe2, 0xe0,
+ 0xff, 0x68, 0x97, 0xce, 0xec, 0xee, 0xff, 0xff
+};
+static const unsigned char g4C[] = {
+ 0xe0, 0xe2, 0x00, 0x22, 0x0e, 0x2e, 0xff, 0xff
+};
+static const unsigned char g4D[] = {
+ 0x00, 0x20, 0x0e, 0x2b, 0x2e, 0x67, 0x79, 0x87,
+ 0xce, 0xcb, 0xee, 0xc0, 0xe0, 0xff, 0xff
+};
+static const unsigned char g4E[] = {
+ 0x00, 0x20, 0x0e, 0x2b, 0x2e, 0xc0, 0xc3, 0xe0,
+ 0xce, 0xee, 0xff, 0xff
+};
+static const unsigned char g4F[] = {
+ 0x23, 0x02, 0x32, 0x20, 0xb2, 0xc0, 0xc3, 0xe2,
+ 0xcb, 0xec, 0xbc, 0xce, 0x3c, 0x2e, 0x2b, 0x0c,
+ 0x23, 0x02, 0xff, 0xff
+};
+static const unsigned char g50[] = {
+ 0x00, 0x20, 0x06, 0x26, 0x08, 0x28, 0x0c, 0x2c,
+ 0x0e, 0xbc, 0xce, 0xcb, 0xec, 0xc9, 0xe8, 0xb8,
+ 0xc6, 0x28, 0x26, 0xff, 0xff
+};
+static const unsigned char g51[] = {
+ 0xc0, 0xe2, 0xc4, 0xec, 0xcb, 0xce, 0xbc, 0x2e,
+ 0x3c, 0x0c, 0x2b, 0x02, 0x23, 0x20, 0x32, 0xc0,
+ 0xa2, 0xc4, 0x84, 0xa6, 0xff, 0xff
+};
+static const unsigned char g52[] = {
+ 0xc0, 0xe0, 0xc5, 0xe6, 0xb6, 0xd7, 0xb8, 0xe8,
+ 0xc9, 0xec, 0xcb, 0xce, 0xbc, 0x0e, 0x2c, 0x08,
+ 0x28, 0x06, 0x26, 0x00, 0x20, 0xff, 0x28, 0x26,
+ 0xb8, 0xb6, 0xff, 0xff
+};
+static const unsigned char g53[] = {
+ 0x23, 0x02, 0x32, 0x20, 0xb2, 0xc0, 0xc3, 0xe2,
+ 0xc5, 0xe6, 0xb6, 0xc8, 0x26, 0x38, 0x08, 0x29,
+ 0x0c, 0x2b, 0x2e, 0x3c, 0xce, 0xbc, 0xec, 0xcb,
+ 0xff, 0xff
+};
+static const unsigned char g54[] = {
+ 0x0e, 0x0c, 0x6e, 0x6c, 0x8e, 0x8c, 0xee, 0xec,
+ 0xff, 0x60, 0x80, 0x6c, 0x8c, 0xff, 0xff
+};
+static const unsigned char g55[] = {
+ 0x2e, 0x0e, 0x23, 0x02, 0x32, 0x20, 0xb2, 0xc0,
+ 0xc3, 0xe2, 0xce, 0xee, 0xff, 0xff
+};
+static const unsigned char g56[] = {
+ 0x2e, 0x0e, 0x27, 0x06, 0x72, 0x60, 0xff, 0x60,
+ 0x80, 0x72, 0xe6, 0xc7, 0xee, 0xce, 0xff, 0xff
+};
+static const unsigned char g57[] = {
+ 0xee, 0xce, 0xe0, 0xc3, 0xc0, 0x87, 0x75, 0x67,
+ 0x20, 0x23, 0x00, 0x2e, 0x0e, 0xff, 0xff
+};
+static const unsigned char g58[] = {
+ 0x00, 0x20, 0x02, 0x75, 0x57, 0x97, 0x79, 0xec,
+ 0xce, 0xee, 0xff, 0xe0, 0xe2, 0xc0, 0x97, 0x75,
+ 0xff, 0x0e, 0x0c, 0x2e, 0x57, 0x79, 0xff, 0xff
+};
+static const unsigned char g59[] = {
+ 0x0e, 0x0c, 0x2e, 0x66, 0x79, 0x86, 0xce, 0xec,
+ 0xee, 0xff, 0x60, 0x80, 0x66, 0x86, 0xff, 0xff
+};
+static const unsigned char g5A[] = {
+ 0x0e, 0x0c, 0xee, 0xbc, 0xec, 0x02, 0x32, 0x00,
+ 0xe2, 0xe0, 0xff, 0xff
+};
+static const unsigned char g5B[] = {
+ 0xa0, 0xa2, 0x60, 0x82, 0x6e, 0x8c, 0xae, 0xac,
+ 0xff, 0xff
+};
+static const unsigned char g5C[] = {
+ 0xe0, 0xe2, 0xc0, 0x2e, 0x0c, 0x0e, 0xff, 0xff
+};
+static const unsigned char g5D[] = {
+ 0x4e, 0x4c, 0x8e, 0x6c, 0x80, 0x62, 0x40, 0x42,
+ 0xff, 0xff
+};
+static const unsigned char g5E[] = {
+ 0x3a, 0x6a, 0x7e, 0x7b, 0xba, 0x8a, 0xff, 0xff
+};
+static const unsigned char g5F[] = {
+ 0x02, 0x00, 0xe2, 0xe0, 0xff, 0xff
+};
+static const unsigned char g60[] = {
+ 0x8a, 0x8e, 0x6c, 0x6e, 0xff, 0xff
+};
+static const unsigned char g61[] = {
+ 0x08, 0x27, 0x2a, 0x38, 0xca, 0xb8, 0xe8, 0xc7,
+ 0xe6, 0xc6, 0xe4, 0xc4, 0xe0, 0xc2, 0x20, 0x32,
+ 0x02, 0x23, 0x04, 0x34, 0x26, 0xc4, 0xc6, 0xff,
+ 0xff
+};
+static const unsigned char g62[] = {
+ 0x2e, 0x0e, 0x2a, 0x09, 0x28, 0x00, 0x22, 0xc0,
+ 0xb2, 0xe2, 0xc3, 0xe8, 0xc7, 0xca, 0xb8, 0x2a,
+ 0x28, 0xff, 0xff
+};
+static const unsigned char g63[] = {
+ 0xc7, 0xe8, 0xb8, 0xca, 0x38, 0x2a, 0x27, 0x08,
+ 0x23, 0x02, 0x32, 0x20, 0xb2, 0xc0, 0xc3, 0xe2,
+ 0xff, 0xff
+};
+static const unsigned char g64[] = {
+ 0xc8, 0xca, 0x38, 0x2a, 0x27, 0x08, 0x23, 0x02,
+ 0x32, 0x20, 0xc2, 0xe0, 0xc8, 0xe9, 0xca, 0xee,
+ 0xce, 0xff, 0xff
+};
+static const unsigned char g65[] = {
+ 0xe2, 0xc3, 0xc0, 0xb2, 0x20, 0x32, 0x02, 0x23,
+ 0x04, 0x24, 0x06, 0x26, 0x08, 0x27, 0x2a, 0x38,
+ 0xca, 0xb8, 0xe8, 0xc7, 0xe4, 0xc6, 0x24, 0x26,
+ 0xff, 0xff
+};
+static const unsigned char g66[] = {
+ 0x4a, 0x48, 0x6a, 0x68, 0x8a, 0x88, 0xaa, 0xa8,
+ 0xff, 0x60, 0x80, 0x68, 0x88, 0xff, 0x6a, 0x8a,
+ 0x6c, 0x8b, 0x8e, 0x9c, 0xae, 0xac, 0xff, 0xff
+};
+static const unsigned char g67[] = {
+ 0x23, 0x02, 0x32, 0x20, 0xb2, 0xc0, 0xc3, 0xe2,
+ 0xc4, 0xe6, 0xc6, 0xea, 0xc8, 0x2a, 0x38, 0x08,
+ 0x27, 0x06, 0x36, 0x24, 0xc6, 0xc4, 0xff, 0xff
+};
+static const unsigned char g68[] = {
+ 0x00, 0x20, 0x08, 0x28, 0x0a, 0x2a, 0x0e, 0x2e,
+ 0xff, 0x2a, 0x28, 0xca, 0xb8, 0xe8, 0xc7, 0xe0,
+ 0xc0, 0xff, 0xff
+};
+static const unsigned char g69[] = {
+ 0x60, 0x80, 0x6a, 0x8a, 0xff, 0x6c, 0x8c, 0x6e,
+ 0x8e, 0xff, 0xff
+};
+static const unsigned char g6A[] = {
+ 0x23, 0x02, 0x32, 0x20, 0xb2, 0xc0, 0xc3, 0xe2,
+ 0xca, 0xea, 0xff, 0xcc, 0xec, 0xce, 0xee, 0xff,
+ 0xff
+};
+static const unsigned char g6B[] = {
+ 0x00, 0x20, 0x04, 0x24, 0x06, 0x26, 0x0e, 0x2e,
+ 0xff, 0x26, 0x24, 0x86, 0x84, 0xb5, 0xc0, 0xe2,
+ 0xe0, 0xff, 0x86, 0xb5, 0xca, 0xe8, 0xea, 0xff,
+ 0xff
+};
+static const unsigned char g6C[] = {
+ 0x60, 0x80, 0x6e, 0x8e, 0xff, 0xff
+};
+static const unsigned char g6D[] = {
+ 0x00, 0x20, 0x0a, 0x28, 0x6a, 0x68, 0xff, 0x60,
+ 0x80, 0x68, 0x88, 0x6a, 0xb8, 0xca, 0xc7, 0xe8,
+ 0xc0, 0xe0, 0xff, 0xff
+};
+static const unsigned char g6E[] = {
+ 0x00, 0x20, 0x0a, 0x28, 0xca, 0xb8, 0xe8, 0xc7,
+ 0xe0, 0xc0, 0xff, 0xff
+};
+static const unsigned char g6F[] = {
+ 0x23, 0x02, 0x32, 0x20, 0xb2, 0xc0, 0xc3, 0xe2,
+ 0xc7, 0xe8, 0xb8, 0xca, 0x38, 0x2a, 0x27, 0x08,
+ 0x23, 0x02, 0xff, 0xff
+};
+static const unsigned char g70[] = {
+ 0x00, 0x20, 0x04, 0x24, 0x06, 0x26, 0x0a, 0x28,
+ 0xca, 0xb8, 0xe8, 0xc7, 0xe6, 0xb6, 0xc4, 0x26,
+ 0x24, 0xff, 0xff
+};
+static const unsigned char g71[] = {
+ 0xc0, 0xe0, 0xc4, 0xe5, 0xc6, 0xea, 0xc8, 0x2a,
+ 0x38, 0x08, 0x27, 0x06, 0x36, 0x24, 0xc6, 0xc4,
+ 0xff, 0xff
+};
+static const unsigned char g72[] = {
+ 0x00, 0x20, 0x0a, 0x28, 0xca, 0xb8, 0xe8, 0xc7,
+ 0xff, 0xff
+};
+static const unsigned char g73[] = {
+ 0xc3, 0xe4, 0xb4, 0xc6, 0x24, 0x36, 0x06, 0x27,
+ 0x08, 0x38, 0x2a, 0xb8, 0xca, 0xc7, 0xe8, 0xff,
+ 0x23, 0x02, 0x32, 0x20, 0xb2, 0xc0, 0xc3, 0xe2,
+ 0xe4, 0xff, 0xff
+};
+static const unsigned char g74[] = {
+ 0x4a, 0x48, 0x6a, 0x68, 0xff, 0x8a, 0x88, 0xaa,
+ 0xa8, 0xff, 0xa0, 0xa2, 0x80, 0x92, 0x62, 0x83,
+ 0x68, 0x88, 0x6a, 0x8a, 0x6c, 0x8c, 0xff, 0xff
+};
+static const unsigned char g75[] = {
+ 0x2a, 0x0a, 0x23, 0x02, 0x32, 0x20, 0xc2, 0xe0,
+ 0xca, 0xea, 0xff, 0xff
+};
+static const unsigned char g76[] = {
+ 0xea, 0xca, 0xe6, 0xc7, 0x80, 0x72, 0x60, 0x27,
+ 0x06, 0x2a, 0x0a, 0xff, 0xff
+};
+static const unsigned char g77[] = {
+ 0x2a, 0x0a, 0x22, 0x00, 0x52, 0x60, 0x63, 0x71,
+ 0x83, 0x80, 0x92, 0xc0, 0xb2, 0xe2, 0xc3, 0xea,
+ 0xca, 0xff, 0x8a, 0x6a, 0x83, 0x63, 0xff, 0xff
+};
+static const unsigned char g78[] = {
+ 0x00, 0x20, 0x02, 0x74, 0x45, 0x76, 0x08, 0x2a,
+ 0x0a, 0xff, 0xea, 0xca, 0xe8, 0x76, 0xa5, 0x74,
+ 0xe2, 0xc0, 0xe0, 0xff, 0xff
+};
+static const unsigned char g79[] = {
+ 0x23, 0x02, 0x32, 0x20, 0xb2, 0xc0, 0xc3, 0xe2,
+ 0xc4, 0xe5, 0xc6, 0xea, 0xca, 0xff, 0x2a, 0x0a,
+ 0x27, 0x06, 0x36, 0x24, 0xc6, 0xc4, 0xff, 0xff
+};
+static const unsigned char g7A[] = {
+ 0x0a, 0x08, 0xea, 0xa8, 0xe8, 0x02, 0x42, 0x00,
+ 0xe2, 0xe0, 0xff, 0xff
+};
+static const unsigned char g7B[] = {
+ 0x80, 0xa0, 0x62, 0x82, 0x66, 0x86, 0x57, 0x77,
+ 0x68, 0x88, 0x6c, 0x8c, 0x8e, 0xae, 0xff, 0xff
+};
+static const unsigned char g7C[] = {
+ 0x60, 0x80, 0x6f, 0x8f, 0xff, 0xff
+};
+static const unsigned char g7D[] = {
+ 0x6e, 0x4e, 0x8c, 0x6c, 0x88, 0x68, 0x97, 0x77,
+ 0x86, 0x66, 0x82, 0x62, 0x60, 0x40, 0xff, 0xff
+};
+static const unsigned char g7E[] = {
+ 0xbc, 0xbe, 0x9a, 0x9c, 0x5c, 0x5e, 0x3a, 0x3c,
+ 0xff, 0xff
+};
+static const unsigned char g7F[] = {
+ 0x44, 0x22, 0xa4, 0xc2, 0xaa, 0xcc, 0x4a, 0x2c,
+ 0x44, 0x22, 0xff, 0xff
+};
+
+static const unsigned char *glyph[] = {
+ g7F, g7F, g7F, g7F, g7F, g7F, g7F, g7F,
+ g7F, g7F, g7F, g7F, g7F, g7F, g7F, g7F,
+ g7F, g7F, g7F, g7F, g7F, g7F, g7F, g7F,
+ g7F, g7F, g7F, g7F, g7F, g7F, g7F, g7F,
+ g20, g21, g22, g23, g24, g25, g26, g27,
+ g28, g29, g2A, g2B, g2C, g2D, g2E, g2F,
+ g30, g31, g32, g33, g34, g35, g36, g37,
+ g38, g39, g3A, g3B, g3C, g3D, g3E, g3F,
+ g40, g41, g42, g43, g44, g45, g46, g47,
+ g48, g49, g4A, g4B, g4C, g4D, g4E, g4F,
+ g50, g51, g52, g53, g54, g55, g56, g57,
+ g58, g59, g5A, g5B, g5C, g5D, g5E, g5F,
+ g60, g61, g62, g63, g64, g65, g66, g67,
+ g68, g69, g6A, g6B, g6C, g6D, g6E, g6F,
+ g70, g71, g72, g73, g74, g75, g76, g77,
+ g78, g79, g7A, g7B, g7C, g7D, g7E, g7F,
+};
+
+void draw_glyph(int c)
+{
+ int i = 0;
+
+ assert(0 <= c && c < 128);
+
+ while (glyph[c][i] != 0xff)
+ {
+ glBegin(GL_TRIANGLE_STRIP);
+ {
+ while (glyph[c][i] != 0xff)
+ {
+ glVertex2f((glyph[c][i] / 16) / 16.0f,
+ (glyph[c][i] % 16) / 16.0f);
+ i++;
+ }
+ }
+ glEnd();
+
+ i++;
+ }
+
+ glTranslatef(1.0f, 0.0f, 0.0f);
+}
+
+double text_width = 8;
+double text_height = 12;
+
+void draw_string(const char *s) {
+ int index = 0;
+
+ glPushMatrix();
+ glScaled(text_width, text_height, 0);
+ glRotated(180, 1, 0, 0); // flip - ortho screen coords have y inverted
+
+ while(s[index] != '\0') {
+ draw_glyph((int)s[index]);
+ index++;
+ }
+
+ glPopMatrix();
+}
+
+void draw_string_centered(const char *s) {
+ glPushMatrix();
+ glTranslated(strlen(s) / 2.0 * -text_width, text_height / 2, 0);
+ draw_string(s);
+ glPopMatrix();
+}
+
+void set_text_size(const double ttext_width, const double ttext_height) {
+ text_width = ttext_width;
+ text_height = ttext_height;
+}
diff --git a/plugins/Alarms/glyph.h b/plugins/Alarms/glyph.h
new file mode 100644
index 0000000000..86e2247608
--- /dev/null
+++ b/plugins/Alarms/glyph.h
@@ -0,0 +1,21 @@
+#ifndef GLYPH_H
+#define GLYPH_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern double text_width;
+extern double text_height;
+
+void draw_glyph(int);
+void draw_string(const char *s);
+void draw_string_centered(const char *s);
+
+void set_text_size(const double ttext_width, const double ttext_height);
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif
diff --git a/plugins/Alarms/green.ico b/plugins/Alarms/green.ico
new file mode 100644
index 0000000000..82ce348616
--- /dev/null
+++ b/plugins/Alarms/green.ico
Binary files differ
diff --git a/plugins/Alarms/icons.cpp b/plugins/Alarms/icons.cpp
new file mode 100644
index 0000000000..ecc7f5539c
--- /dev/null
+++ b/plugins/Alarms/icons.cpp
@@ -0,0 +1,91 @@
+#include "common.h"
+#include "icons.h"
+
+HANDLE hIcoLibIconsChanged;
+
+HICON hIconMenuSet, hIconList1, hIconList2, hIconMenuShowHide, hIconSystray;
+
+int ReloadIcons(WPARAM wParam, LPARAM lParam) {
+ hIconMenuSet = (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)"alarms_menu_set");
+ hIconList1 = (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)"alarms_list1");
+ hIconList2 = (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)"alarms_list2");
+ if(!ServiceExists(MS_CLIST_FRAMES_ADDFRAME))
+ hIconMenuShowHide = (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)"alarms_menu_showhide");
+
+ RefreshReminderFrame();
+ return 0;
+}
+
+void InitIcons() {
+ if(ServiceExists(MS_SKIN2_ADDICON)) {
+ SKINICONDESC sid = {0};
+
+ sid.cbSize = sizeof(SKINICONDESC);
+ sid.pszSection = Translate("Alarms");
+
+ sid.pszDescription = Translate("Menu: Set Alarm");
+ sid.pszName = "alarms_menu_set";
+ sid.pszDefaultFile = "alarms.dll";
+ sid.iDefaultIndex = 0;
+ sid.hDefaultIcon = (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_MAINMENU), IMAGE_ICON, 16, 16, 0);
+ CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid);
+
+ sid.pszDescription = Translate("Reminder: Soon");
+ sid.pszName = "alarms_list1";
+ sid.pszDefaultFile = "alarms.dll";
+ sid.iDefaultIndex = 1;
+ sid.hDefaultIcon = (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_LIST1), IMAGE_ICON, 16, 16, 0);//LR_LOADTRANSPARENT | LR_LOADMAP3DCOLORS );
+ CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid);
+
+ sid.pszDescription = Translate("Reminder: Very Soon");
+ sid.pszName = "alarms_list2";
+ sid.pszDefaultFile = "alarms.dll";
+ sid.iDefaultIndex = 2;
+ sid.hDefaultIcon = (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_LIST2), IMAGE_ICON, 16, 16, 0);//LR_LOADTRANSPARENT | LR_LOADMAP3DCOLORS );
+ CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid);
+
+ sid.pszDescription = Translate("Alarm: System Tray");
+ sid.pszName = "alarms_systray";
+ sid.pszDefaultFile = "alarms.dll";
+ sid.iDefaultIndex = 3;
+ sid.hDefaultIcon = (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_MAINMENU), IMAGE_ICON, 16, 16, 0);//LR_LOADTRANSPARENT | LR_LOADMAP3DCOLORS );
+ CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid);
+
+ if(!ServiceExists(MS_CLIST_FRAMES_ADDFRAME)) {
+ sid.pszDescription = Translate("Menu: Show/Hide Reminders");
+ sid.pszName = "alarms_menu_showhide";
+ sid.pszDefaultFile = "alarms.dll";
+ sid.iDefaultIndex = 4;
+ sid.hDefaultIcon = (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_MAINMENU), IMAGE_ICON, 16, 16, 0);
+ CallService(MS_SKIN2_ADDICON, 0, (LPARAM)&sid);
+
+ hIconMenuShowHide = (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)"alarms_menu_showhide");
+ }
+
+ hIconMenuSet = (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)"alarms_menu_set");
+ hIconList1 = (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)"alarms_list1");
+ hIconList2 = (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)"alarms_list2");
+ hIconSystray = (HICON)CallService(MS_SKIN2_GETICON, 0, (LPARAM)"alarms_systray");
+
+ hIcoLibIconsChanged = HookEvent(ME_SKIN2_ICONSCHANGED, ReloadIcons);
+ } else {
+ hIconMenuSet = (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_MAINMENU), IMAGE_ICON, 16, 16, 0);//LR_LOADTRANSPARENT | LR_LOADMAP3DCOLORS );
+ hIconList1 = (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_LIST1), IMAGE_ICON, 16, 16, 0);//LR_LOADTRANSPARENT | LR_LOADMAP3DCOLORS );
+ hIconList2 = (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_LIST2), IMAGE_ICON, 16, 16, 0);//LR_LOADTRANSPARENT | LR_LOADMAP3DCOLORS );
+ hIconSystray = (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_MAINMENU), IMAGE_ICON, 16, 16, 0);//LR_LOADTRANSPARENT | LR_LOADMAP3DCOLORS );
+ if(!ServiceExists(MS_CLIST_FRAMES_ADDFRAME))
+ hIconMenuShowHide = (HICON)LoadImage(hInst, MAKEINTRESOURCE(IDI_MAINMENU), IMAGE_ICON, 16, 16, 0);//LR_LOADTRANSPARENT | LR_LOADMAP3DCOLORS );
+ }
+}
+
+
+void DeinitIcons() {
+ if(!ServiceExists(MS_SKIN2_ADDICON)) {
+ DestroyIcon(hIconMenuSet);
+ DestroyIcon(hIconList1);
+ DestroyIcon(hIconList2);
+ DestroyIcon(hIconSystray);
+ if(!ServiceExists(MS_CLIST_FRAMES_ADDFRAME))
+ DestroyIcon(hIconMenuShowHide);
+ }
+}
diff --git a/plugins/Alarms/icons.h b/plugins/Alarms/icons.h
new file mode 100644
index 0000000000..89226dd5d4
--- /dev/null
+++ b/plugins/Alarms/icons.h
@@ -0,0 +1,12 @@
+#ifndef _ICONS_INC
+#define _ICONS_INC
+
+#include "frame.h"
+
+extern HICON hIconMenuSet, hIconList1, hIconList2, hIconMenuShowHide, hIconSystray;
+
+void InitIcons();
+void DeinitIcons();
+
+#endif
+
diff --git a/plugins/Alarms/iconttbdown.ico b/plugins/Alarms/iconttbdown.ico
new file mode 100644
index 0000000000..bcee978747
--- /dev/null
+++ b/plugins/Alarms/iconttbdown.ico
Binary files differ
diff --git a/plugins/Alarms/iconttbup.ico b/plugins/Alarms/iconttbup.ico
new file mode 100644
index 0000000000..4269d0ca8a
--- /dev/null
+++ b/plugins/Alarms/iconttbup.ico
Binary files differ
diff --git a/plugins/Alarms/init.c b/plugins/Alarms/init.c
new file mode 100644
index 0000000000..ffac6c06bb
--- /dev/null
+++ b/plugins/Alarms/init.c
@@ -0,0 +1,185 @@
+/*
+
+Miranda IM: the free IM client for Microsoft* Windows*
+
+Copyright 2000-2003 Miranda ICQ/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.
+*/
+
+#include "commonheaders.h"
+#include "database.h"
+#include <m_plugins.h>
+
+struct MM_INTERFACE memoryManagerInterface;
+extern char szDbPath[MAX_PATH];
+
+HINSTANCE g_hInst=NULL;
+PLUGINLINK *pluginLink;
+
+static int getCapability( int flag )
+{
+ return 0;
+}
+
+// returns 0 if the profile is created, EMKPRF*
+static int makeDatabase(char * profile, int * error)
+{
+ HANDLE hFile=CreateFile(profile, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
+ if ( hFile != INVALID_HANDLE_VALUE ) {
+ CreateDbHeaders(hFile);
+ CloseHandle(hFile);
+ return 0;
+ }
+ if ( error != NULL ) *error=EMKPRF_CREATEFAILED;
+ return 1;
+}
+
+// returns 0 if the given profile has a valid header
+static int grokHeader( char * profile, int * error )
+{
+ int rc=1;
+ int chk=0;
+ struct DBHeader hdr;
+ HANDLE hFile = INVALID_HANDLE_VALUE;
+ DWORD dummy=0;
+
+ hFile = CreateFile(profile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
+ if ( hFile == INVALID_HANDLE_VALUE ) {
+ if ( error != NULL ) *error=EGROKPRF_CANTREAD;
+ return 1;
+ }
+ // read the header, which can fail (for various reasons)
+ if ( !ReadFile(hFile, &hdr, sizeof(struct DBHeader), &dummy, NULL) ) {
+ if ( error != NULL) *error=EGROKPRF_CANTREAD;
+ CloseHandle(hFile);
+ return 1;
+ }
+ chk=CheckDbHeaders(&hdr);
+ if ( chk == 0 ) {
+ // all the internal tests passed, hurrah
+ rc=0;
+ if ( error != NULL ) *error=0;
+ } else {
+ // didn't pass at all, or some did.
+ switch ( chk ) {
+ case 1:
+ {
+ // "Miranda ICQ DB" wasn't present
+ if ( error != NULL ) *error = EGROKPRF_UNKHEADER;
+ break;
+ }
+ case 2:
+ {
+ // header was present, but version information newer
+ if ( error != NULL ) *error= EGROKPRF_VERNEWER;
+ break;
+ }
+ case 3:
+ {
+ // header/version OK, internal data missing
+ if ( error != NULL ) *error=EGROKPRF_DAMAGED;
+ break;
+ }
+ } // switch
+ } //if
+ CloseHandle(hFile);
+ return rc;
+}
+
+// returns 0 if all the APIs are injected otherwise, 1
+static int LoadDatabase( char * profile, void * plink )
+{
+ PLUGINLINK *link = plink;
+#ifdef _DEBUG
+ _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
+#endif
+ // don't need thread notifications
+ strncpy(szDbPath, profile, sizeof(szDbPath));
+ // this is like Load()'s pluginLink
+ pluginLink=link;
+ // set the memory manager
+ memoryManagerInterface.cbSize=sizeof(struct MM_INTERFACE);
+ CallService(MS_SYSTEM_GET_MMI,0,(LPARAM)&memoryManagerInterface);
+
+ // inject all APIs and hooks into the core
+ return LoadDatabaseModule();
+}
+
+static int UnloadDatabase(int wasLoaded)
+{
+ if ( !wasLoaded) return 0;
+ UnloadDatabaseModule();
+ return 0;
+}
+
+static int getFriendlyName( char * buf, size_t cch, int shortName )
+{
+ strncpy(buf,shortName ? "Miranda database" : "Miranda database support",cch);
+ return 0;
+}
+
+
+static DATABASELINK dblink = {
+ sizeof(DATABASELINK),
+ getCapability,
+ getFriendlyName,
+ makeDatabase,
+ grokHeader,
+ LoadDatabase,
+ UnloadDatabase,
+};
+
+BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD dwReason, LPVOID reserved)
+{
+ g_hInst=hInstDLL;
+ return TRUE;
+}
+
+__declspec(dllexport) DATABASELINK* DatabasePluginInfo(void * reserved)
+{
+ return &dblink;
+}
+
+static PLUGININFO pluginInfo = {
+ sizeof(PLUGININFO),
+ "Miranda database - with AutoBackups",
+ PLUGIN_MAKE_VERSION(0,5,2,1),
+ "Provides Miranda database support: global settings, contacts, history, settings per contact.",
+ "Miranda-IM project",
+ "mail@scottellis.com.au",
+ "Copyright 2000-2005 Miranda-IM project",
+ "http://www.scottellis.com.au",
+ 0,
+ DEFMOD_DB
+};
+
+__declspec(dllexport) PLUGININFO * MirandaPluginInfo(DWORD mirandaVersion)
+{
+ if ( mirandaVersion < PLUGIN_MAKE_VERSION(0,4,0,0) ) return NULL;
+ return &pluginInfo;
+}
+
+int __declspec(dllexport) Load(PLUGINLINK * link)
+{
+ return 1;
+}
+
+int __declspec(dllexport) Unload(void)
+{
+ return 0;
+}
diff --git a/plugins/Alarms/main.h b/plugins/Alarms/main.h
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/plugins/Alarms/main.h
diff --git a/plugins/Alarms/options.cpp b/plugins/Alarms/options.cpp
new file mode 100644
index 0000000000..feeec4f55a
--- /dev/null
+++ b/plugins/Alarms/options.cpp
@@ -0,0 +1,1238 @@
+#include "common.h"
+#include "options.h"
+
+Options options;
+
+#define WMU_OPTSETALARM (WM_USER + 10)
+#define WMU_UPDATETIME (WM_USER + 11)
+#define WMU_SETTIME (WM_USER + 12)
+#define WMU_MYDESTROY (WM_USER + 13)
+
+// defined in header
+//#define WMU_INITOPTLIST (WM_USER + 20)
+
+typedef struct AddEditParam_tag {
+ ALARM *alarm_ptr;
+ BOOL edit;
+ BOOL self_add;
+} AddEditParam;
+
+HANDLE hMainMenuItem = 0, hGroupMenuItem;
+
+// store options dialog window handle statically so it can be refreshed by non-modal add alarm dialog
+HWND hwndOptionsDialog = 0;
+
+static BOOL CALLBACK DlgProcAddEdit(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) {
+
+ switch ( msg ) {
+ case WM_INITDIALOG: {
+ TranslateDialogDefault( hwndDlg );
+
+ SendDlgItemMessage(hwndDlg, IDC_DAY, CB_INSERTSTRING, 0, (LPARAM)Translate("Sunday"));
+ SendDlgItemMessage(hwndDlg, IDC_DAY, CB_INSERTSTRING, 1, (LPARAM)Translate("Monday"));
+ SendDlgItemMessage(hwndDlg, IDC_DAY, CB_INSERTSTRING, 2, (LPARAM)Translate("Tuesday"));
+ SendDlgItemMessage(hwndDlg, IDC_DAY, CB_INSERTSTRING, 3, (LPARAM)Translate("Wednesday"));
+ SendDlgItemMessage(hwndDlg, IDC_DAY, CB_INSERTSTRING, 4, (LPARAM)Translate("Thursday"));
+ SendDlgItemMessage(hwndDlg, IDC_DAY, CB_INSERTSTRING, 5, (LPARAM)Translate("Friday"));
+ SendDlgItemMessage(hwndDlg, IDC_DAY, CB_INSERTSTRING, 6, (LPARAM)Translate("Saturday"));
+ SendDlgItemMessage(hwndDlg, IDC_DAY, CB_SETCURSEL, 0, 0);
+
+ char buff[10];
+ for(int i = 1; i <= 31; i++) {
+ SendDlgItemMessage(hwndDlg, IDC_DAYNUM, CB_INSERTSTRING, (WPARAM)-1, (LPARAM)itoa(i, buff, 10));
+ }
+ SendDlgItemMessage(hwndDlg, IDC_DAYNUM, CB_SETCURSEL, 0, 0);
+
+ {
+ HWND hw = GetDlgItem(hwndDlg, IDOK);
+ EnableWindow(hw, FALSE);
+ }
+
+ if (!ServiceExists("Speak/Say")) {
+ EnableWindow(GetDlgItem(hwndDlg, IDC_RAD_SPK), FALSE);
+ }
+
+ AddEditParam *param = (AddEditParam *)lParam;
+ SendMessage(hwndDlg, WMU_OPTSETALARM, (WPARAM)param->edit, (LPARAM)param->alarm_ptr);
+
+ // use invisible checkbox to store 'self_add' setting - naughty hack
+ CheckDlgButton(hwndDlg, IDC_CHK_INVIS, param->self_add);
+
+ delete param;
+
+ Utils_RestoreWindowPositionNoSize(hwndDlg, 0, MODULE, "AddEdit");
+
+ if(GetDlgCtrlID((HWND)wParam) != IDC_TITLE) {
+ SetFocus(GetDlgItem(hwndDlg, IDC_TITLE));
+ return FALSE;
+ }
+ return TRUE;
+ }
+ case WMU_OPTSETALARM: {
+ BOOL edit = (BOOL)wParam;
+ ALARM *add_edit_alarm = (ALARM *)lParam;
+ SetWindowLong(hwndDlg, GWL_USERDATA, (LONG)add_edit_alarm);
+
+ if(edit) {
+ SetDlgItemText(hwndDlg, IDC_TITLE, add_edit_alarm->szTitle);
+ SetDlgItemText(hwndDlg, IDC_DESC, add_edit_alarm->szDesc);
+ switch(add_edit_alarm->occurrence) {
+ case OC_DAILY: {
+ CheckDlgButton(hwndDlg, IDC_RAD_DAILY, TRUE);
+ HWND hw = GetDlgItem(hwndDlg, IDC_BTN_CAL);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_DATE);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_DAY);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_DAYNUM);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_CHK_SUSPEND);
+ EnableWindow(hw, TRUE);
+ }
+ break;
+ case OC_WEEKDAYS: {
+ CheckDlgButton(hwndDlg, IDC_RAD_WEEKDAYS, TRUE);
+ HWND hw = GetDlgItem(hwndDlg, IDC_BTN_CAL);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_DATE);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_DAY);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_DAYNUM);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_RELMIN);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_CHK_SUSPEND);
+ EnableWindow(hw, TRUE);
+ }
+ break;
+ case OC_ONCE: {
+ CheckDlgButton(hwndDlg, IDC_RAD_ONCE, TRUE);
+ HWND hw = GetDlgItem(hwndDlg, IDC_DAY);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_DAYNUM);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_CHK_SUSPEND);
+ EnableWindow(hw, FALSE);
+ }
+ break;
+ case OC_WEEKLY: {
+ CheckDlgButton(hwndDlg, IDC_RAD_WEEKLY, TRUE);
+ HWND hw = GetDlgItem(hwndDlg, IDC_BTN_CAL);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_DATE);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_DAYNUM);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_RELMIN);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_CHK_SUSPEND);
+ EnableWindow(hw, TRUE);
+ }
+ break;
+ case OC_MONTHLY: {
+ CheckDlgButton(hwndDlg, IDC_RAD_MONTHLY, TRUE);
+ HWND hw = GetDlgItem(hwndDlg, IDC_BTN_CAL);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_DATE);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_DAY);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_RELMIN);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_CHK_SUSPEND);
+ EnableWindow(hw, TRUE);
+ }
+ break;
+ case OC_YEARLY: {
+ CheckDlgButton(hwndDlg, IDC_RAD_YEARLY, TRUE);
+ HWND hw = GetDlgItem(hwndDlg, IDC_DAY);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_DAYNUM);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_CHK_SUSPEND);
+ EnableWindow(hw, TRUE);
+ }
+ break;
+ }
+
+ CheckDlgButton(hwndDlg, IDC_CHK_SUSPEND, (add_edit_alarm->flags & ALF_SUSPENDED) ? TRUE : FALSE);
+ CheckDlgButton(hwndDlg, IDC_CHK_NOSTARTUP, (add_edit_alarm->flags & ALF_NOSTARTUP) ? TRUE : FALSE);
+ CheckDlgButton(hwndDlg, IDC_CHK_NOREMINDER, (add_edit_alarm->flags & ALF_NOREMINDER) ? TRUE : FALSE);
+
+ SendDlgItemMessage(hwndDlg, IDC_DAY, CB_SETCURSEL, add_edit_alarm->time.wDayOfWeek, 0);
+ SendDlgItemMessage(hwndDlg, IDC_TIME, DTM_SETSYSTEMTIME, (WPARAM)GDT_VALID, (LPARAM)&add_edit_alarm->time);
+ SendDlgItemMessage(hwndDlg, IDC_DATE, DTM_SETSYSTEMTIME, (WPARAM)GDT_VALID, (LPARAM)&add_edit_alarm->time);
+ SendDlgItemMessage(hwndDlg, IDC_DAYNUM, CB_SETCURSEL, add_edit_alarm->time.wDay - 1, 0);
+ SetDlgItemInt(hwndDlg, IDC_RELMIN, MinutesInFuture(add_edit_alarm->time, add_edit_alarm->occurrence), FALSE);
+
+ if(add_edit_alarm->action & AAF_SOUND) {
+ CheckDlgButton(hwndDlg, IDC_CHK_ASOUND, TRUE);
+ switch(add_edit_alarm->sound_num) {
+ case 1:
+ CheckDlgButton(hwndDlg, IDC_RAD_SND1, TRUE);
+ break;
+ case 2:
+ CheckDlgButton(hwndDlg, IDC_RAD_SND2, TRUE);
+ break;
+ case 3:
+ CheckDlgButton(hwndDlg, IDC_RAD_SND3, TRUE);
+ break;
+ case 4:
+ if (!ServiceExists("Speak/Say")) {
+ add_edit_alarm->sound_num = 1;
+ CheckDlgButton(hwndDlg, IDC_RAD_SND1, TRUE);
+ } else
+ CheckDlgButton(hwndDlg, IDC_RAD_SPK, TRUE);
+
+ break;
+ };
+ } else {
+ HWND hw = GetDlgItem(hwndDlg, IDC_RAD_SND1);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_RAD_SND2);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_RAD_SND3);
+ EnableWindow(hw, FALSE);
+ }
+ if(add_edit_alarm->action & AAF_POPUP) CheckDlgButton(hwndDlg, IDC_CHK_APOPUP, TRUE);
+ if(add_edit_alarm->action & AAF_COMMAND) {
+ CheckDlgButton(hwndDlg, IDC_CHK_ACOMMAND, TRUE);
+ SetDlgItemText(hwndDlg, IDC_ED_COMMAND, add_edit_alarm->szCommand);
+ SetDlgItemText(hwndDlg, IDC_ED_PARAMS, add_edit_alarm->szCommandParams);
+ } else {
+ HWND hw = GetDlgItem(hwndDlg, IDC_ED_COMMAND);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_ED_PARAMS);
+ EnableWindow(hw, FALSE);
+ }
+
+ } else {
+ SYSTEMTIME now;
+ GetPluginTime(&now);
+
+ // set time to 10 mins in future to help prevent 'alarm in past' error
+ TimeForMinutesInFuture(10, &now);
+
+ CheckDlgButton(hwndDlg, IDC_RAD_ONCE, TRUE);
+ HWND hw = GetDlgItem(hwndDlg, IDC_DAY);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_DAYNUM);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_CHK_SUSPEND);
+ EnableWindow(hw, FALSE);
+ SendDlgItemMessage(hwndDlg, IDC_DAY, CB_SETCURSEL, now.wDayOfWeek, 0);
+ SendDlgItemMessage(hwndDlg, IDC_TIME, DTM_SETSYSTEMTIME, (WPARAM)GDT_VALID, (LPARAM)&now);
+ SendDlgItemMessage(hwndDlg, IDC_DATE, DTM_SETSYSTEMTIME, (WPARAM)GDT_VALID, (LPARAM)&now);
+ SendDlgItemMessage(hwndDlg, IDC_DAYNUM, CB_SETCURSEL, now.wDay - 1, 0);
+ SetDlgItemInt(hwndDlg, IDC_RELMIN, MinutesInFuture(now, OC_ONCE), FALSE);
+
+ CheckDlgButton(hwndDlg, IDC_CHK_ASOUND, TRUE);
+ CheckDlgButton(hwndDlg, IDC_RAD_SND1, TRUE);
+ CheckDlgButton(hwndDlg, IDC_CHK_APOPUP, TRUE);
+
+ hw = GetDlgItem(hwndDlg, IDC_ED_COMMAND);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_ED_PARAMS);
+ EnableWindow(hw, FALSE);
+ }
+ return TRUE;
+ }
+
+ case WMU_UPDATETIME: {
+ ALARM *add_edit_alarm = (ALARM *)GetWindowLong(hwndDlg, GWL_USERDATA);
+
+ if(IsDlgButtonChecked(hwndDlg, IDC_RAD_ONCE))
+ add_edit_alarm->occurrence = OC_ONCE;
+ else if(IsDlgButtonChecked(hwndDlg, IDC_RAD_DAILY))
+ add_edit_alarm->occurrence = OC_DAILY;
+ else if(IsDlgButtonChecked(hwndDlg, IDC_RAD_WEEKDAYS))
+ add_edit_alarm->occurrence = OC_WEEKDAYS;
+ else if(IsDlgButtonChecked(hwndDlg, IDC_RAD_WEEKLY))
+ add_edit_alarm->occurrence = OC_WEEKLY;
+ else if(IsDlgButtonChecked(hwndDlg, IDC_RAD_MONTHLY))
+ add_edit_alarm->occurrence = OC_MONTHLY;
+ else if(IsDlgButtonChecked(hwndDlg, IDC_RAD_YEARLY)) {
+ add_edit_alarm->occurrence = OC_YEARLY;
+
+ // set date range to 1 year (now to 1 year in future)
+ SYSTEMTIME r[2];
+ GetPluginTime(&r[0]);
+ TimeForMinutesInFuture(365 * 24 * 60, &r[1]);
+ SendDlgItemMessage(hwndDlg, IDC_DATE, DTM_SETRANGE, (WPARAM)(GDTR_MIN | GDTR_MAX), (LPARAM)r);
+ }
+
+ if(add_edit_alarm->occurrence == OC_ONCE || add_edit_alarm->occurrence == OC_YEARLY) {
+ SendDlgItemMessage(hwndDlg, IDC_DATE, DTM_GETSYSTEMTIME, 0, (LPARAM)&add_edit_alarm->time);
+ }
+
+ if(add_edit_alarm->occurrence == OC_WEEKLY) {
+ add_edit_alarm->time.wDayOfWeek = (unsigned short)SendDlgItemMessage(hwndDlg, IDC_DAY, CB_GETCURSEL, 0, 0);
+ }
+ if(add_edit_alarm->occurrence == OC_MONTHLY) {
+ add_edit_alarm->time.wDay = (WORD)SendDlgItemMessage(hwndDlg, IDC_DAYNUM, CB_GETCURSEL, 0, 0) + 1;
+ }
+
+ SYSTEMTIME temp_time;
+ SendDlgItemMessage(hwndDlg, IDC_TIME, DTM_GETSYSTEMTIME, 0, (LPARAM)&temp_time);
+ add_edit_alarm->time.wHour = temp_time.wHour;
+ add_edit_alarm->time.wMinute = temp_time.wMinute;
+ add_edit_alarm->time.wSecond = temp_time.wSecond;
+
+ UpdateAlarm(add_edit_alarm->time, add_edit_alarm->occurrence);
+
+ return TRUE;
+ }
+
+ case WMU_SETTIME: {
+ ALARM *add_edit_alarm = (ALARM *)GetWindowLong(hwndDlg, GWL_USERDATA);
+
+ SYSTEMTIME temp_time;
+ SendDlgItemMessage(hwndDlg, IDC_DATE, MCM_GETCURSEL, 0, (LPARAM)&temp_time);
+ if(memcmp(&temp_time, &add_edit_alarm->time, sizeof(SYSTEMTIME)) != 0)
+ SendDlgItemMessage(hwndDlg, IDC_DATE, MCM_SETCURSEL, 0, (LPARAM)&add_edit_alarm->time);
+
+ SendDlgItemMessage(hwndDlg, IDC_DAY, CB_SETCURSEL, add_edit_alarm->time.wDayOfWeek, 0);
+ SendDlgItemMessage(hwndDlg, IDC_TIME, DTM_SETSYSTEMTIME, (WPARAM)GDT_VALID, (LPARAM)&add_edit_alarm->time);
+ SendDlgItemMessage(hwndDlg, IDC_DAYNUM, CB_SETCURSEL, add_edit_alarm->time.wDay - 1, 0);
+ SetDlgItemInt(hwndDlg, IDC_RELMIN, MinutesInFuture(add_edit_alarm->time, add_edit_alarm->occurrence), FALSE);
+
+ return TRUE;
+ }
+ case WM_NOTIFY: {
+ ALARM *add_edit_alarm = (ALARM *)GetWindowLong(hwndDlg, GWL_USERDATA);
+
+ if ( ((LPNMHDR)lParam)->code == DTN_DATETIMECHANGE) {
+ switch( ((LPNMHDR)lParam)->idFrom ) {
+ case IDC_TIME:
+ {
+ HWND hw = GetDlgItem(hwndDlg, IDOK);
+ EnableWindow(hw, TRUE);
+
+ SendMessage(hwndDlg, WMU_UPDATETIME, 0, 0);
+ SendMessage(hwndDlg, WMU_SETTIME, 0, 0);
+ }
+ break;
+
+ case IDC_DATE:
+ {
+ HWND hw = GetDlgItem(hwndDlg, IDOK);
+ EnableWindow(hw, TRUE);
+
+ SendMessage(hwndDlg, WMU_UPDATETIME, 0, 0);
+ SendMessage(hwndDlg, WMU_SETTIME, 0, 0);
+ }
+ break;
+ }
+ return TRUE;
+ }
+ }
+ break;
+
+ case WM_COMMAND: {
+ ALARM *add_edit_alarm = (ALARM *)GetWindowLong(hwndDlg, GWL_USERDATA);
+
+ if ( HIWORD(wParam) == CBN_SELCHANGE ) {
+ switch( LOWORD(wParam) ) {
+ case IDC_DAY:
+ case IDC_DAYNUM: {
+ HWND hw = GetDlgItem(hwndDlg, IDOK);
+ EnableWindow(hw, TRUE);
+
+ SendMessage(hwndDlg, WMU_UPDATETIME, 0, 0);
+ SendMessage(hwndDlg, WMU_SETTIME, 0, 0);
+ }
+ break;
+ }
+ return TRUE;
+ }
+ if ( HIWORD( wParam ) == EN_CHANGE && ( HWND )lParam == GetFocus()) {
+ switch( LOWORD( wParam )) {
+ case IDC_RELMIN: {
+ BOOL translated;
+ int mins;
+ mins = GetDlgItemInt(hwndDlg, IDC_RELMIN, &translated, FALSE);
+ SYSTEMTIME newtime;
+ TimeForMinutesInFuture(mins, &newtime);
+
+ SendDlgItemMessage(hwndDlg, IDC_TIME, DTM_SETSYSTEMTIME, (WPARAM)GDT_VALID, (LPARAM)&newtime);
+ SendDlgItemMessage(hwndDlg, IDC_DATE, DTM_SETSYSTEMTIME, (WPARAM)GDT_VALID, (LPARAM)&newtime);
+ SendDlgItemMessage(hwndDlg, IDC_DAY, CB_SETCURSEL, newtime.wDayOfWeek, 0);
+ SendDlgItemMessage(hwndDlg, IDC_DAYNUM, CB_SETCURSEL, newtime.wDay - 1, 0);
+
+ add_edit_alarm->time = newtime;
+
+ SendMessage(hwndDlg, WMU_UPDATETIME, 0, 0);
+ }
+ // drop through
+ case IDC_TITLE:
+ case IDC_DESC:
+ case IDC_ED_COMMAND:
+ case IDC_ED_PARAMS: {
+ HWND hw = GetDlgItem(hwndDlg, IDOK);
+ EnableWindow(hw, TRUE);
+ }
+ break;
+ }
+ return TRUE;
+ }
+ if ( HIWORD( wParam ) == BN_CLICKED ) {
+ switch( LOWORD( wParam )) {
+ case IDC_RAD_ONCE: {
+ HWND hw = GetDlgItem(hwndDlg, IDC_DAY);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_BTN_CAL);
+ EnableWindow(hw, TRUE);
+ hw = GetDlgItem(hwndDlg, IDC_DATE);
+ EnableWindow(hw, TRUE);
+ hw = GetDlgItem(hwndDlg, IDOK);
+ EnableWindow(hw, TRUE);
+ hw = GetDlgItem(hwndDlg, IDC_DAYNUM);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_RELMIN);
+ EnableWindow(hw, TRUE);
+ hw = GetDlgItem(hwndDlg, IDC_CHK_SUSPEND);
+ EnableWindow(hw, FALSE);
+ SendMessage(hwndDlg, WMU_UPDATETIME, 0, 0);
+ SendMessage(hwndDlg, WMU_SETTIME, 0, 0);
+ }
+ break;
+ case IDC_RAD_DAILY: {
+ HWND hw = GetDlgItem(hwndDlg, IDC_BTN_CAL);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_DAY);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_DATE);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDOK);
+ EnableWindow(hw, TRUE);
+ hw = GetDlgItem(hwndDlg, IDC_DAYNUM);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_RELMIN);
+ EnableWindow(hw, TRUE);
+ hw = GetDlgItem(hwndDlg, IDC_CHK_SUSPEND);
+ EnableWindow(hw, TRUE);
+ SendMessage(hwndDlg, WMU_UPDATETIME, 0, 0);
+ SendMessage(hwndDlg, WMU_SETTIME, 0, 0);
+ }
+ break;
+ case IDC_RAD_WEEKLY: {
+ HWND hw = GetDlgItem(hwndDlg, IDC_BTN_CAL);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_DATE);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_DAY);
+ EnableWindow(hw, TRUE);
+ hw = GetDlgItem(hwndDlg, IDOK);
+ EnableWindow(hw, TRUE);
+ hw = GetDlgItem(hwndDlg, IDC_DAYNUM);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_RELMIN);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_CHK_SUSPEND);
+ EnableWindow(hw, TRUE);
+ SendMessage(hwndDlg, WMU_UPDATETIME, 0, 0);
+ SendMessage(hwndDlg, WMU_SETTIME, 0, 0);
+ }
+ break;
+ case IDC_RAD_WEEKDAYS: {
+ HWND hw = GetDlgItem(hwndDlg, IDC_BTN_CAL);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_DATE);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_DAY);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDOK);
+ EnableWindow(hw, TRUE);
+ hw = GetDlgItem(hwndDlg, IDC_DAYNUM);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_RELMIN);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_CHK_SUSPEND);
+ EnableWindow(hw, TRUE);
+ SendMessage(hwndDlg, WMU_UPDATETIME, 0, 0);
+ SendMessage(hwndDlg, WMU_SETTIME, 0, 0);
+ }
+ break;
+ case IDC_RAD_MONTHLY: {
+ HWND hw = GetDlgItem(hwndDlg, IDC_BTN_CAL);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_DATE);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_DAY);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDOK);
+ EnableWindow(hw, TRUE);
+ hw = GetDlgItem(hwndDlg, IDC_DAYNUM);
+ EnableWindow(hw, TRUE);
+ hw = GetDlgItem(hwndDlg, IDC_RELMIN);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_CHK_SUSPEND);
+ EnableWindow(hw, TRUE);
+ SendMessage(hwndDlg, WMU_UPDATETIME, 0, 0);
+ SendMessage(hwndDlg, WMU_SETTIME, 0, 0);
+ }
+ break;
+ case IDC_RAD_YEARLY: {
+ HWND hw = GetDlgItem(hwndDlg, IDC_DAY);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_BTN_CAL);
+ EnableWindow(hw, TRUE);
+ hw = GetDlgItem(hwndDlg, IDC_DATE);
+ EnableWindow(hw, TRUE);
+ hw = GetDlgItem(hwndDlg, IDOK);
+ EnableWindow(hw, TRUE);
+ hw = GetDlgItem(hwndDlg, IDC_DAYNUM);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_RELMIN);
+ EnableWindow(hw, TRUE);
+ hw = GetDlgItem(hwndDlg, IDC_CHK_SUSPEND);
+ EnableWindow(hw, TRUE);
+ SendMessage(hwndDlg, WMU_UPDATETIME, 0, 0);
+ SendMessage(hwndDlg, WMU_SETTIME, 0, 0);
+ }
+ break;
+ case IDC_CHK_ACOMMAND: {
+ if(IsDlgButtonChecked(hwndDlg, IDC_CHK_ACOMMAND)) {
+ HWND hw = GetDlgItem(hwndDlg, IDC_ED_COMMAND);
+ EnableWindow(hw, TRUE);
+ hw = GetDlgItem(hwndDlg, IDC_ED_PARAMS);
+ EnableWindow(hw, TRUE);
+ } else {
+ HWND hw = GetDlgItem(hwndDlg, IDC_ED_COMMAND);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_ED_PARAMS);
+ EnableWindow(hw, FALSE);
+ }
+ }
+ // drop through
+ case IDC_CHK_ASOUND: {
+ if(IsDlgButtonChecked(hwndDlg, IDC_CHK_ASOUND)) {
+ HWND hw = GetDlgItem(hwndDlg, IDC_RAD_SND1);
+ EnableWindow(hw, TRUE);
+ hw = GetDlgItem(hwndDlg, IDC_RAD_SND2);
+ EnableWindow(hw, TRUE);
+ hw = GetDlgItem(hwndDlg, IDC_RAD_SND3);
+ EnableWindow(hw, TRUE);
+ hw = GetDlgItem(hwndDlg, IDC_RAD_SPK);
+ EnableWindow(hw, TRUE);
+ } else {
+ HWND hw = GetDlgItem(hwndDlg, IDC_RAD_SND1);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_RAD_SND2);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_RAD_SND3);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_RAD_SPK);
+ EnableWindow(hw, FALSE);
+ }
+
+ }
+ // drop though
+ case IDC_RAD_SND1:
+ case IDC_RAD_SND2:
+ case IDC_RAD_SND3:
+ case IDC_RAD_SPK:
+ case IDC_CHK_SUSPEND:
+ case IDC_CHK_NOSTARTUP:
+ case IDC_CHK_NOREMINDER:
+ case IDC_CHK_APOPUP: {
+ HWND hw = GetDlgItem(hwndDlg, IDOK);
+ EnableWindow(hw, TRUE);
+ }
+ break;
+ case IDOK: {
+
+ char buff[MAX_PATH];
+ GetDlgItemText(hwndDlg, IDC_TITLE, buff, MAX_PATH);
+ if(add_edit_alarm->szTitle) free(add_edit_alarm->szTitle);
+ add_edit_alarm->szTitle = _strdup(buff);
+
+ GetDlgItemText(hwndDlg, IDC_DESC, buff, MAX_PATH);
+ if(add_edit_alarm->szDesc) free(add_edit_alarm->szDesc);
+ add_edit_alarm->szDesc = _strdup(buff);
+
+ if(add_edit_alarm->szTitle == 0 || strlen(add_edit_alarm->szTitle) == 0) {
+ MessageBox(hwndDlg, Translate("Please enter a title for this alarm."), Translate("Error"), MB_OK | MB_ICONERROR);
+ return TRUE;
+ }
+
+ SendMessage(hwndDlg, WMU_UPDATETIME, 0, 0);
+
+ if(!UpdateAlarm(add_edit_alarm->time, add_edit_alarm->occurrence)) {
+ MessageBox(hwndDlg, Translate("The alarm time you have selected is in the past."), Translate("Error"), MB_OK | MB_ICONERROR);
+ return TRUE;
+ }
+
+ add_edit_alarm->action = (IsDlgButtonChecked(hwndDlg, IDC_CHK_ASOUND) ? AAF_SOUND : 0);
+ add_edit_alarm->action |= (IsDlgButtonChecked(hwndDlg, IDC_CHK_APOPUP) ? AAF_POPUP : 0);
+ add_edit_alarm->action |= (IsDlgButtonChecked(hwndDlg, IDC_CHK_ACOMMAND) ? AAF_COMMAND : 0);
+
+ add_edit_alarm->flags = add_edit_alarm->flags & ~(ALF_SUSPENDED | ALF_NOSTARTUP | ALF_NOREMINDER);
+ if(add_edit_alarm->occurrence != OC_ONCE) {
+ add_edit_alarm->flags |= IsDlgButtonChecked(hwndDlg, IDC_CHK_SUSPEND) ? ALF_SUSPENDED : 0;
+ }
+ add_edit_alarm->flags |= IsDlgButtonChecked(hwndDlg, IDC_CHK_NOSTARTUP) ? ALF_NOSTARTUP : 0;
+ add_edit_alarm->flags |= IsDlgButtonChecked(hwndDlg, IDC_CHK_NOREMINDER) ? ALF_NOREMINDER: 0;
+
+ if(add_edit_alarm->action & AAF_COMMAND) {
+ GetDlgItemText(hwndDlg, IDC_ED_COMMAND, buff, MAX_PATH);
+ if(add_edit_alarm->szCommand) free(add_edit_alarm->szCommand);
+ add_edit_alarm->szCommand = _strdup(buff);
+ GetDlgItemText(hwndDlg, IDC_ED_PARAMS, buff, MAX_PATH);
+ if(add_edit_alarm->szCommandParams) free(add_edit_alarm->szCommandParams);
+ add_edit_alarm->szCommandParams = _strdup(buff);
+ }
+
+ if(add_edit_alarm->action & AAF_SOUND) {
+ if(IsDlgButtonChecked(hwndDlg, IDC_RAD_SND1))
+ add_edit_alarm->sound_num = 1;
+ else if(IsDlgButtonChecked(hwndDlg, IDC_RAD_SND2))
+ add_edit_alarm->sound_num = 2;
+ else if(IsDlgButtonChecked(hwndDlg, IDC_RAD_SND3))
+ add_edit_alarm->sound_num = 3;
+ else if(IsDlgButtonChecked(hwndDlg, IDC_RAD_SPK))
+ add_edit_alarm->sound_num = 4;
+ } else
+ add_edit_alarm->sound_num = 0;
+
+
+ Utils_SaveWindowPosition(hwndDlg, 0, MODULE, "AddEdit");
+
+ // self-add (setting stored in invisible checkbox - see comments in WM_INITDIALOG
+ if(IsDlgButtonChecked(hwndDlg, IDC_CHK_INVIS)) {
+ alter_alarm_list(add_edit_alarm);
+ RefreshReminderFrame();
+ if(hwndOptionsDialog) {
+ // refresh options list
+ PostMessage(hwndOptionsDialog, WMU_INITOPTLIST, 0, 0);
+ }
+ }
+
+ // self-add (setting stored in invisible checkbox - see comments in WM_INITDIALOG
+ if(IsDlgButtonChecked(hwndDlg, IDC_CHK_INVIS)) {
+ free_alarm_data(add_edit_alarm);
+ delete add_edit_alarm;
+ }
+
+ // inform options dialog of change
+
+ // deal with modal and non-modal modes
+ PostMessage(hwndDlg, WMU_MYDESTROY, 0, 0);
+ EndDialog(hwndDlg, IDOK);
+ }
+ break;
+ case IDCANCEL: {
+
+ // self-add (setting stored in invisible checkbox - see comments in WM_INITDIALOG
+ if(IsDlgButtonChecked(hwndDlg, IDC_CHK_INVIS)) {
+ ALARM *add_edit_alarm = (ALARM *)GetWindowLong(hwndDlg, GWL_USERDATA);
+ free_alarm_data(add_edit_alarm);
+ delete add_edit_alarm;
+ }
+
+ Utils_SaveWindowPosition(hwndDlg, 0, MODULE, "AddEdit");
+
+ // deal with modal and non-modal modes
+ PostMessage(hwndDlg, WMU_MYDESTROY, 0, 0);
+ EndDialog(hwndDlg, IDCANCEL);
+ }
+ break;
+
+ default:
+ return TRUE;
+ }
+ }
+ break;
+ }
+ case WMU_MYDESTROY:
+ DestroyWindow(hwndDlg);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+BOOL Edit(HWND hwnd, ALARM &alarm, bool modal) {
+ AddEditParam *param = new AddEditParam;
+ param->alarm_ptr = &alarm;
+ param->edit = TRUE;
+
+ if(modal) {
+ param->self_add = FALSE;
+ if(DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_DIALOG2), hwnd, DlgProcAddEdit, (LPARAM)param) == IDOK) {
+ return TRUE;
+ }
+ } else {
+ param->self_add = TRUE;
+ HWND hwndDlg = CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_DIALOG2), hwnd, DlgProcAddEdit, (LPARAM)param);
+
+ //SetActiveWindow(hwndDlg);
+ //SetWindowPos(hwndDlg,
+ SetForegroundWindow(hwndDlg);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL New(HWND hwnd, ALARM &alarm, bool modal) {
+ AddEditParam *param = new AddEditParam;
+ param->alarm_ptr = &alarm;
+ param->edit = FALSE;
+
+ if(modal) {
+ param->self_add = FALSE;
+ if(DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_DIALOG2), hwnd, DlgProcAddEdit, (LPARAM)param) == IDOK) {
+ return TRUE;
+ }
+ } else {
+ param->self_add = TRUE;
+ HWND hwndDlg = CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_DIALOG2), hwnd, DlgProcAddEdit, (LPARAM)param);
+
+ //SetActiveWindow(hwndDlg);
+ //SetWindowPos(hwndDlg,
+ SetForegroundWindow(hwndDlg);
+ if(ServiceExists(MS_TTB_SETBUTTONSTATE)) {
+ Sleep(100);
+ CallService(MS_TTB_SETBUTTONSTATE, (WPARAM)hTopToolbarButton, (LPARAM)TTBST_RELEASED);
+ }
+
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void AddMenuItem() {
+ if(hMainMenuItem) return;
+
+ CLISTMENUITEM menu = {0};
+
+ menu.cbSize=sizeof(menu);
+ menu.flags = CMIM_ALL;
+ menu.hIcon=hIconMenuSet;
+
+ menu.pszName = Translate("Set Alarm");
+ menu.pszService= MODULE "/NewAlarm";
+ menu.position = 500010000;
+ if(!ServiceExists(MS_CLIST_FRAMES_ADDFRAME))
+ menu.pszPopupName = Translate("Alarms");
+ if (ServiceExists(MS_CLIST_ADDGROUPMENUITEM)) {
+ GroupMenuParam gmp = {0};
+ hGroupMenuItem = (HANDLE)CallService(MS_CLIST_ADDGROUPMENUITEM,(WPARAM)&gmp,(LPARAM)&menu);
+ }
+ hMainMenuItem = (HANDLE)CallService(MS_CLIST_ADDMAINMENUITEM,0,(LPARAM)&menu);
+ /////////////////////
+}
+
+/*
+void RemoveMenuItem() {
+ if(!hMainMenuItem) return;
+
+ CallService(MS_CLIST_REMOVEMAINMENUITEM, (WPARAM)hMainMenuItem, 0);
+ if(ServiceExists(MS_CLIST_REMOVEGROUPMENUITEM)) {
+ CallService(MS_CLIST_REMOVEGROUPMENUITEM, (WPARAM)hGroupMenuItem, 0);
+ }
+ hMainMenuItem = 0;
+
+}
+*/
+
+int OptionsModulesLoaded(WPARAM wParam, LPARAM lParam) {
+ ///////////////////////
+ // create menu item
+ CreateServiceFunction(MODULE "/NewAlarm", NewAlarmMenuFunc);
+
+ AddMenuItem();
+
+ return 0;
+}
+
+AlarmList temp_list, added_list, modified_list; // we need to keep track of added and modified alarms, since if the non-modal dialog
+ // refreshes the list before changes are applied, we loose them
+
+class ShortList {
+public:
+ class Node {
+ public:
+ Node(): next(0) {}
+ unsigned short value;
+ Node *next;
+ };
+
+
+ ShortList(): head(0) {}
+ virtual ~ShortList() {clear();}
+
+ void clear() {
+ Node *current;
+ while(head) {
+ current = head;
+ head = head->next;
+ delete current;
+ }
+ }
+
+ void push_back(unsigned short s) {Node *n = new Node; n->value = s; n->next = head; head = n;}
+
+ Node *get_head() {return head;}
+
+protected:
+
+ Node *head;
+};
+
+ShortList deleted_list; // same with deleted items
+
+Options temp_options;
+static BOOL CALLBACK DlgProcOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) {
+
+ switch ( msg ) {
+ case WM_INITDIALOG: {
+ hwndOptionsDialog = hwndDlg;
+ added_list.clear();
+ modified_list.clear();
+ deleted_list.clear();
+
+ TranslateDialogDefault( hwndDlg );
+
+ temp_options = options;
+
+ PostMessage(hwndDlg, WMU_INITOPTLIST, 0, 0);
+ return TRUE;
+ }
+ case WMU_INITOPTLIST: {
+ copy_list(temp_list);
+ // add added alarms, in case this is a list refresh from non-modal add alarm dialog
+ ALARM *i, *j;
+ for(added_list.reset(); i = added_list.current(); added_list.next()) {
+ temp_list.push_back(i);
+ }
+ // modify modified alarms, in case this is a list refresh from non-modal add alarm dialog
+ for(temp_list.reset(); i = temp_list.current(); temp_list.next()) {
+ for(modified_list.reset(); j = modified_list.current(); modified_list.next()) {
+ if(i->id == j->id) {
+ copy_alarm_data(i, j);
+ }
+ }
+ }
+ // remove deleted alarms, in case this is a list refresh from non-modal add alarm dialog
+
+ ShortList::Node *k = deleted_list.get_head();
+ while(k) {
+ for(temp_list.reset(); i = temp_list.current(); temp_list.next()) {
+ if(i->id == k->value) {
+ temp_list.erase();
+ break;
+ }
+ }
+ k = k->next;
+ }
+
+ SendDlgItemMessage(hwndDlg, IDC_ALIST, LB_RESETCONTENT, 0, 0);
+
+ if(temp_list.size() > 0) {
+ int pos = -1;
+ ALARM *i;
+ for(temp_list.reset(); i = temp_list.current(); temp_list.next()) {
+ if(!(i->flags & ALF_HIDDEN)) {
+ pos = SendDlgItemMessage(hwndDlg, IDC_ALIST, LB_ADDSTRING, 0, (LPARAM)i->szTitle);
+ SendDlgItemMessage(hwndDlg, IDC_ALIST, LB_SETITEMDATA, pos, (LPARAM)i->id);
+ }
+ }
+ SendDlgItemMessage(hwndDlg, IDC_ALIST, LB_SETCURSEL, pos, 0);
+ HWND hw;
+ hw = GetDlgItem(hwndDlg, IDC_EDIT);
+ EnableWindow(hw, TRUE);
+ hw = GetDlgItem(hwndDlg, IDC_DEL);
+ EnableWindow(hw, TRUE);
+ } else {
+ HWND hw;
+ hw = GetDlgItem(hwndDlg, IDC_EDIT);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_DEL);
+ EnableWindow(hw, FALSE);
+ }
+
+ if(ServiceExists(MS_POPUP_ADDPOPUP)) {
+ CheckDlgButton(hwndDlg, IDC_CHK_POPUPS, temp_options.use_popup_module ? TRUE : FALSE);
+ if(options.use_popup_module) {
+ HWND hw = GetDlgItem(hwndDlg, IDC_CHK_LOOPSOUND);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_CHK_AWROUND);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_CHK_AWNOACTIVATE);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_SPIN_TRANS);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_ED_TRANS);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_BTN_PREVIEW);
+ EnableWindow(hw, FALSE);
+ } else {
+ CheckDlgButton(hwndDlg, IDC_CHK_LOOPSOUND, temp_options.loop_sound ? TRUE : FALSE);
+ HWND hw = GetDlgItem(hwndDlg, IDC_CHK_LOOPSOUND);
+ EnableWindow(hw, TRUE);
+ hw = GetDlgItem(hwndDlg, IDC_CHK_AWROUND);
+ EnableWindow(hw, TRUE);
+ hw = GetDlgItem(hwndDlg, IDC_CHK_AWNOACTIVATE);
+ EnableWindow(hw, TRUE);
+ hw = GetDlgItem(hwndDlg, IDC_SPIN_TRANS);
+ EnableWindow(hw, TRUE);
+ hw = GetDlgItem(hwndDlg, IDC_ED_TRANS);
+ EnableWindow(hw, TRUE);
+ hw = GetDlgItem(hwndDlg, IDC_BTN_PREVIEW);
+ EnableWindow(hw, TRUE);
+ }
+ } else {
+ HWND hw = GetDlgItem(hwndDlg, IDC_CHK_POPUPS);
+ EnableWindow(hw, FALSE);
+ CheckDlgButton(hwndDlg, IDC_CHK_LOOPSOUND, temp_options.loop_sound ? TRUE : FALSE);
+
+ hw = GetDlgItem(hwndDlg, IDC_CHK_LOOPSOUND);
+ EnableWindow(hw, TRUE);
+ hw = GetDlgItem(hwndDlg, IDC_CHK_AWROUND);
+ EnableWindow(hw, TRUE);
+ hw = GetDlgItem(hwndDlg, IDC_CHK_AWNOACTIVATE);
+ EnableWindow(hw, TRUE);
+ hw = GetDlgItem(hwndDlg, IDC_SPIN_TRANS);
+ EnableWindow(hw, TRUE);
+ hw = GetDlgItem(hwndDlg, IDC_ED_TRANS);
+ EnableWindow(hw, TRUE);
+ hw = GetDlgItem(hwndDlg, IDC_BTN_PREVIEW);
+ EnableWindow(hw, TRUE);
+ }
+
+ SendMessage(GetDlgItem(hwndDlg, IDC_SPIN_SNOOZE), UDM_SETRANGE, 0, (LPARAM)MAKELONG(360, 0));
+ SendMessage(GetDlgItem(hwndDlg, IDC_SPIN_SNOOZE), UDM_SETPOS, 0, temp_options.snooze_minutes);
+
+ SendMessage(GetDlgItem(hwndDlg, IDC_SPIN_ROWHEIGHT), UDM_SETRANGE, 0, (LPARAM)MAKELONG(100, 5));
+ SendMessage(GetDlgItem(hwndDlg, IDC_SPIN_ROWHEIGHT), UDM_SETPOS, 0, temp_options.row_height);
+
+ SendMessage(GetDlgItem(hwndDlg, IDC_SPIN_INDENT), UDM_SETRANGE, 0, (LPARAM)MAKELONG(100, 0));
+ SendMessage(GetDlgItem(hwndDlg, IDC_SPIN_INDENT), UDM_SETPOS, 0, temp_options.indent);
+
+ SendMessage(GetDlgItem(hwndDlg, IDC_SPIN_TRANS), UDM_SETRANGE, 0, (LPARAM)MAKELONG(100, 0));
+ SendMessage(GetDlgItem(hwndDlg, IDC_SPIN_TRANS), UDM_SETPOS, 0, temp_options.aw_trans);
+ if(!TransparencyEnabled()) {
+ HWND hw = GetDlgItem(hwndDlg, IDC_SPIN_TRANS);
+ EnableWindow(hw, FALSE);
+ hw = GetDlgItem(hwndDlg, IDC_ED_TRANS);
+ EnableWindow(hw, FALSE);
+ }
+
+ CheckDlgButton(hwndDlg, IDC_SHOWHIDE, temp_options.auto_showhide ? TRUE : FALSE);
+ CheckDlgButton(hwndDlg, IDC_SHOWHIDE2, temp_options.hide_with_clist ? TRUE : FALSE);
+ CheckDlgButton(hwndDlg, IDC_AUTOSIZEVERT, temp_options.auto_size_vert ? TRUE : FALSE);
+
+ CheckDlgButton(hwndDlg, IDC_CHK_AWROUND, temp_options.aw_roundcorners ? TRUE : FALSE);
+ CheckDlgButton(hwndDlg, IDC_CHK_AWNOACTIVATE, temp_options.aw_dontstealfocus ? TRUE : FALSE);
+
+ SendMessage(GetDlgItem(hwndDlg, IDC_SPIN_PERIOD), UDM_SETRANGE, 0, (LPARAM)MAKELONG(72, 1));
+ SendMessage(GetDlgItem(hwndDlg, IDC_SPIN_PERIOD), UDM_SETPOS, 0, temp_options.reminder_period);
+
+ SendMessage( GetParent( hwndDlg ), PSM_UNCHANGED, 0, 0 );
+ return TRUE;
+ }
+ case WM_COMMAND:
+ if ( HIWORD( wParam ) == EN_CHANGE && ( HWND )lParam == GetFocus()) {
+ SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 );
+ }
+ if ( HIWORD( wParam ) == BN_CLICKED ) {
+ switch( LOWORD( wParam )) {
+ case IDC_BTN_PREVIEW:
+ {
+ HWND hwndDlgPrev = CreateDialog(hInst, MAKEINTRESOURCE(IDD_ALARM), GetDesktopWindow(), DlgProcAlarm);
+ WindowList_Add(hAlarmWindowList, hwndDlgPrev, 0);
+ SendMessage(hwndDlgPrev, WMU_FAKEALARM, 0, 0);
+ SendMessage(hwndDlgPrev, WMU_SETOPT, 0, (LPARAM)&temp_options);
+ ShowWindow(hwndDlgPrev, SW_SHOW);
+ SetWindowPos(hwndDlgPrev, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
+ }
+ break;
+ case IDC_SHOWHIDE:
+ temp_options.auto_showhide = IsDlgButtonChecked(hwndDlg, IDC_SHOWHIDE) ? true : false;
+ SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 );
+ break;
+ case IDC_SHOWHIDE2:
+ temp_options.hide_with_clist = IsDlgButtonChecked(hwndDlg, IDC_SHOWHIDE2) ? true : false;
+ SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 );
+ break;
+ case IDC_AUTOSIZEVERT:
+ temp_options.auto_size_vert = IsDlgButtonChecked(hwndDlg, IDC_AUTOSIZEVERT) ? true : false;
+ SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 );
+ break;
+ case IDC_NEW: {
+ ALARM new_alarm = {0};
+ GetPluginTime(&new_alarm.time);
+ new_alarm.id = next_alarm_id++;
+ if(New(hwndDlg, new_alarm, true)) {
+ new_alarm.id = next_alarm_id++;
+ temp_list.push_back(&new_alarm);
+ added_list.push_back(&new_alarm);
+ int pos = SendDlgItemMessage(hwndDlg, IDC_ALIST, LB_ADDSTRING, (WPARAM)-1, (LPARAM)new_alarm.szTitle);
+ SendDlgItemMessage(hwndDlg, IDC_ALIST, LB_SETITEMDATA, pos, new_alarm.id);
+ SendDlgItemMessage(hwndDlg, IDC_ALIST, LB_SETCURSEL, pos, 0);
+ HWND hw;
+ hw = GetDlgItem(hwndDlg, IDC_EDIT);
+ EnableWindow(hw, TRUE);
+ hw = GetDlgItem(hwndDlg, IDC_DEL);
+ EnableWindow(hw, TRUE);
+ SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 );
+
+ free_alarm_data(&new_alarm);
+ }
+ }
+ break;
+ case IDC_EDIT: {
+ int sel = SendDlgItemMessage(hwndDlg, IDC_ALIST, LB_GETCURSEL, 0, 0);
+ if(sel != -1) {
+ unsigned short id = (unsigned short)SendDlgItemMessage(hwndDlg, IDC_ALIST, LB_GETITEMDATA, sel, 0);
+ ALARM *i;
+ for(temp_list.reset(); i = temp_list.current(); temp_list.next()) {
+ if(i->id == id) {
+ ALARM a = {0};
+ copy_alarm_data(&a, i);
+ if(Edit(hwndDlg, a, true)) {
+ modified_list.push_back(&a);
+ SendMessage(hwndDlg, WMU_INITOPTLIST, 0, 0);
+ SendDlgItemMessage(hwndDlg, IDC_ALIST, LB_SETCURSEL, sel, 0);
+ SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 );
+ }
+ free_alarm_data(&a);
+ break;
+ }
+ }
+ }
+ }
+ break;
+ case IDC_DEL: {
+ int sel = SendDlgItemMessage(hwndDlg, IDC_ALIST, LB_GETCURSEL, 0, 0);
+ if(sel != -1) {
+ unsigned short id = (unsigned short)SendDlgItemMessage(hwndDlg, IDC_ALIST, LB_GETITEMDATA, sel, 0);
+
+ ALARM *i;
+ for(temp_list.reset(); i = temp_list.current(); temp_list.next()) {
+ if(i->id == id) {
+ deleted_list.push_back(i->id);
+ //temp_list.erase();
+ break;
+ }
+ }
+
+ SendMessage(hwndDlg, WMU_INITOPTLIST, 0, 0);
+
+ //HWND hw;
+ //hw = GetDlgItem(hwndDlg, IDC_EDIT);
+ //EnableWindow(hw, FALSE);
+ //hw = GetDlgItem(hwndDlg, IDC_DEL);
+ //EnableWindow(hw, FALSE);
+
+ SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 );
+ }
+ }
+ break;
+ case IDC_CHK_POPUPS: {
+ BOOL chk = IsDlgButtonChecked(hwndDlg, IDC_CHK_POPUPS);
+ if(chk) CheckDlgButton(hwndDlg, IDC_CHK_LOOPSOUND, FALSE);
+ else CheckDlgButton(hwndDlg, IDC_CHK_LOOPSOUND, temp_options.loop_sound);
+
+ HWND hw = GetDlgItem(hwndDlg, IDC_CHK_LOOPSOUND);
+ EnableWindow(hw, !chk);
+ hw = GetDlgItem(hwndDlg, IDC_CHK_AWROUND);
+ EnableWindow(hw, !chk);
+ hw = GetDlgItem(hwndDlg, IDC_CHK_AWNOACTIVATE);
+ EnableWindow(hw, !chk);
+ hw = GetDlgItem(hwndDlg, IDC_SPIN_TRANS);
+ EnableWindow(hw, !chk);
+ hw = GetDlgItem(hwndDlg, IDC_ED_TRANS);
+ EnableWindow(hw, !chk);
+ hw = GetDlgItem(hwndDlg, IDC_BTN_PREVIEW);
+ EnableWindow(hw, !chk);
+
+ temp_options.use_popup_module = IsDlgButtonChecked(hwndDlg, IDC_CHK_POPUPS) ? true : false;
+ SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 );
+ }
+ break;
+ case IDC_CHK_LOOPSOUND: {
+ temp_options.loop_sound = IsDlgButtonChecked(hwndDlg, IDC_CHK_LOOPSOUND) ? true : false;
+ SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 );
+ }
+ break;
+ case IDC_CHK_AWROUND: {
+ temp_options.aw_roundcorners = IsDlgButtonChecked(hwndDlg, IDC_CHK_AWROUND) ? true : false;
+ SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 );
+ }
+ break;
+ case IDC_CHK_AWNOACTIVATE: {
+ temp_options.aw_dontstealfocus = IsDlgButtonChecked(hwndDlg, IDC_CHK_AWNOACTIVATE) ? true : false;
+ SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 );
+ }
+ break;
+ }
+ return TRUE;
+ }
+ if (HIWORD( wParam ) == LBN_SELCHANGE) {
+ HWND hw;
+ hw = GetDlgItem(hwndDlg, IDC_EDIT);
+ EnableWindow(hw, TRUE);
+ hw = GetDlgItem(hwndDlg, IDC_DEL);
+ EnableWindow(hw, TRUE);
+
+ //SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
+ return TRUE;
+ }
+ if (HIWORD( wParam ) == LBN_DBLCLK) {
+ int sel = SendDlgItemMessage(hwndDlg, IDC_ALIST, LB_GETCURSEL, 0, 0);
+ if(sel != -1) {
+ unsigned short id = (unsigned short)SendDlgItemMessage(hwndDlg, IDC_ALIST, LB_GETITEMDATA, sel, 0);
+ ALARM *i;
+ for(temp_list.reset(); i = temp_list.current(); temp_list.next()) {
+ if(i->id == id) {
+ ALARM a = {0};
+ copy_alarm_data(&a, i);
+ if(Edit(hwndDlg, a, true)) {
+ modified_list.push_back(&a);
+ SendMessage(hwndDlg, WMU_INITOPTLIST, 0, 0);
+ SendDlgItemMessage(hwndDlg, IDC_ALIST, LB_SETCURSEL, sel, 0);
+ SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 );
+ }
+ free_alarm_data(&a);
+ break;
+ }
+ }
+ }
+ }
+ break;
+
+ case WM_NOTIFY:
+ if(((LPNMHDR)lParam)->code == UDN_DELTAPOS ) {
+ BOOL translated;
+ int trans = GetDlgItemInt(hwndDlg, IDC_ED_TRANS, &translated, FALSE);
+ if(translated) temp_options.aw_trans = trans;
+ SendMessage( GetParent( hwndDlg ), PSM_CHANGED, 0, 0 );
+ return TRUE;
+ }
+ if ((int)((LPNMHDR)lParam)->code == PSN_APPLY ) {
+ set_list(temp_list);
+ SaveAlarms();
+
+ BOOL translated;
+ int snooze_mins = GetDlgItemInt(hwndDlg, IDC_ED_SNOOZE, &translated, FALSE);
+ if(translated) temp_options.snooze_minutes = snooze_mins;
+ int row_height = GetDlgItemInt(hwndDlg, IDC_ED_ROWHEIGHT, &translated, FALSE);
+ if(translated) temp_options.row_height = row_height;
+ int indent = GetDlgItemInt(hwndDlg, IDC_ED_INDENT, &translated, FALSE);
+ if(translated) temp_options.indent = indent;
+ int trans = GetDlgItemInt(hwndDlg, IDC_ED_TRANS, &translated, FALSE);
+ if(translated) temp_options.aw_trans = trans;
+
+ temp_options.use_popup_module = IsDlgButtonChecked(hwndDlg, IDC_CHK_POPUPS) ? true : false;
+ temp_options.auto_showhide = IsDlgButtonChecked(hwndDlg, IDC_SHOWHIDE) ? true : false;
+ temp_options.hide_with_clist = IsDlgButtonChecked(hwndDlg, IDC_SHOWHIDE2) ? true : false;
+ temp_options.auto_size_vert = IsDlgButtonChecked(hwndDlg, IDC_AUTOSIZEVERT) ? true : false;
+ temp_options.aw_roundcorners = IsDlgButtonChecked(hwndDlg, IDC_CHK_AWROUND) ? true : false;
+ temp_options.aw_dontstealfocus = IsDlgButtonChecked(hwndDlg, IDC_CHK_AWNOACTIVATE) ? true : false;
+
+ int reminder_period = GetDlgItemInt(hwndDlg, IDC_ED_PERIOD, &translated, FALSE);
+ if(translated) temp_options.reminder_period = reminder_period;
+
+ if(!ServiceExists(MS_POPUP_ADDPOPUP) || !options.use_popup_module)
+ temp_options.loop_sound = IsDlgButtonChecked(hwndDlg, IDC_CHK_LOOPSOUND) ? true : false;
+
+ options = temp_options;
+ SaveOptions();
+ FixMainMenu();
+ RefreshReminderFrame();
+ SetAlarmWinOptions();
+
+ added_list.clear();
+ modified_list.clear();
+ deleted_list.clear();
+ return TRUE;
+ }
+
+ break;
+ case WM_DESTROY:
+ hwndOptionsDialog = 0;
+ added_list.clear();
+ modified_list.clear();
+ deleted_list.clear();
+ break;
+ }
+
+ return FALSE;
+}
+
+
+int OptInit(WPARAM wParam,LPARAM lParam)
+{
+ OPTIONSDIALOGPAGE odp = { 0 };
+// in the 0.6.0.0 m_options.h header, OPTIONSDIALOGPAGE includes tab stuff, and is larger - older versions of miranda won't accept it
+#define OPTIONPAGE_OLD_SIZE2 60
+ //odp.cbSize = sizeof(odp);
+ odp.cbSize = OPTIONPAGE_OLD_SIZE2;
+ odp.position = -790000000;
+ odp.hInstance = hInst;
+ odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT1);
+ odp.pszTitle = Translate("Alarms");
+ odp.pszGroup = Translate("Events");
+ odp.flags = ODPF_BOLDGROUPS;
+ odp.nIDBottomSimpleControl = 0;
+ odp.pfnDlgProc = DlgProcOpts;
+ CallService( MS_OPT_ADDPAGE, wParam,( LPARAM )&odp );
+
+ return 0;
+}
+
+void LoadOptions() {
+ options.use_popup_module = (DBGetContactSettingByte(0, MODULE, "UsePopupModule", 0) == 1);
+ options.snooze_minutes = (int)DBGetContactSettingDword(0, MODULE, "SnoozeMinutes", 10);
+ options.row_height = (int)DBGetContactSettingDword(0, MODULE, "RowHeight", 20);
+ options.indent = (int)DBGetContactSettingDword(0, MODULE, "Indent", 5);
+ options.aw_trans = (int)DBGetContactSettingByte(0, MODULE, "Transparency", 0);
+ options.aw_roundcorners = (DBGetContactSettingByte(0, MODULE, "RoundCorners", 1) == 1);
+ options.aw_dontstealfocus = (DBGetContactSettingByte(0, MODULE, "DontStealFocus", 1) == 1);
+ options.auto_showhide = (DBGetContactSettingByte(0, MODULE, "AutoShowHide", 0) == 1);
+ options.hide_with_clist = (DBGetContactSettingByte(0, MODULE, "HideWithClist", 0) == 1);
+ options.loop_sound = (DBGetContactSettingByte(0, MODULE, "LoopSound", 1) == 1);
+ options.auto_size_vert = (DBGetContactSettingByte(0, MODULE, "AutoSize", 0) == 1);
+ options.reminder_period = (int)DBGetContactSettingDword(0, MODULE, "ReminderPeriod", 8);
+
+ HookEvent(ME_SYSTEM_MODULESLOADED, OptionsModulesLoaded);
+}
+
+void SaveOptions() {
+ DBWriteContactSettingByte(0, MODULE, "UsePopupModule", options.use_popup_module ? 1 : 0);
+ DBWriteContactSettingDword(0, MODULE, "SnoozeMinutes", options.snooze_minutes);
+ DBWriteContactSettingDword(0, MODULE, "RowHeight", options.row_height);
+ DBWriteContactSettingDword(0, MODULE, "Indent", options.indent);
+ DBWriteContactSettingByte(0, MODULE, "Transparency", options.aw_trans);
+ DBWriteContactSettingByte(0, MODULE, "RoundCorners", options.aw_roundcorners ? 1 : 0);
+ DBWriteContactSettingByte(0, MODULE, "DontStealFocus", options.aw_dontstealfocus ? 1 : 0);
+ DBWriteContactSettingByte(0, MODULE, "AutoShowHide", options.auto_showhide ? 1 : 0);
+ DBWriteContactSettingByte(0, MODULE, "HideWithClist", options.hide_with_clist ? 1 : 0);
+ DBWriteContactSettingByte(0, MODULE, "LoopSound", options.loop_sound ? 1 : 0);
+ DBWriteContactSettingByte(0, MODULE, "AutoSize", options.auto_size_vert ? 1 : 0);
+ DBWriteContactSettingDword(0, MODULE, "ReminderPeriod", options.reminder_period);
+}
+
+int NewAlarmMenuFunc(WPARAM wParam, LPARAM lParam) {
+ ALARM *new_alarm = new ALARM;
+ memset(new_alarm, 0, sizeof(ALARM));
+ new_alarm->id = next_alarm_id++;
+ GetPluginTime(&new_alarm->time);
+
+ //New((HWND)CallService(MS_CLUI_GETHWND, 0, 0), *new_alarm, false);
+ New(GetDesktopWindow(), *new_alarm, false);
+
+ return 0;
+}
+
+void EditNonModal(ALARM &alarm) {
+ ALARM *new_alarm = new ALARM;
+ memset(new_alarm, 0, sizeof(ALARM));
+ copy_alarm_data(new_alarm, &alarm);
+
+ Edit(GetDesktopWindow(), *new_alarm, false);
+}
diff --git a/plugins/Alarms/options.h b/plugins/Alarms/options.h
new file mode 100644
index 0000000000..be2686f505
--- /dev/null
+++ b/plugins/Alarms/options.h
@@ -0,0 +1,41 @@
+#ifndef _OPTIONS_INC
+#define _OPTIONS_INC
+
+#include <commctrl.h>
+#include "m_alarms.h"
+#include "alarmlist.h"
+#include "icons.h"
+#include "frame.h"
+#include "alarm_win.h"
+
+typedef struct Options_tag {
+ bool use_popup_module;
+ int snooze_minutes;
+ int row_height;
+ int indent;
+ int aw_trans;
+ bool aw_roundcorners;
+ bool aw_dontstealfocus;
+ bool auto_showhide;
+ bool hide_with_clist;
+ bool loop_sound;
+ bool auto_size_vert;
+ int reminder_period;
+} Options;
+
+extern Options options;
+
+int OptInit(WPARAM wParam,LPARAM lParam);
+
+void LoadOptions();
+void SaveOptions();
+
+int NewAlarmMenuFunc(WPARAM wParam, LPARAM lParam);
+void EditNonModal(ALARM &alarm);
+
+// provide access the options window, for refresh (== 0 when not displayed)
+extern HWND hwndOptionsDialog;
+#define WMU_INITOPTLIST (WM_USER + 20)
+
+
+#endif
diff --git a/plugins/Alarms/resource.h b/plugins/Alarms/resource.h
new file mode 100644
index 0000000000..bff9b1a19c
--- /dev/null
+++ b/plugins/Alarms/resource.h
@@ -0,0 +1,91 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by resource.rc
+//
+#define IDD_DIALOG1 101
+#define IDD_OPT1 102
+#define IDD_DIALOG2 103
+#define IDI_MAINMENU 105
+#define IDD_ALARM 106
+#define IDI_ICON1 109
+#define IDB_CLOCKDOWN 112
+#define IDB_CLOCKUP 113
+#define IDI_LIST2 114
+#define IDI_LIST1 115
+#define IDR_MENU1 116
+#define IDI_TBUP 123
+#define IDI_TBDN 124
+#define IDD_OPTTRIGGER 125
+#define IDC_ALIST 1006
+#define IDC_TIME 1007
+#define IDC_TITLE 1010
+#define IDC_DESC 1011
+#define IDC_RAD_ONCE 1012
+#define IDC_RAD_WEEKLY 1013
+#define IDC_RAD_DAILY 1014
+#define IDC_RAD_WEEKDAYS 1015
+#define IDC_RAD_MONTHLY 1016
+#define IDC_DAY 1017
+#define IDC_DAYNUM 1018
+#define IDC_RAD_YEARLY 1019
+#define IDC_NEW 1020
+#define IDC_DEL 1021
+#define IDC_EDIT 1022
+#define IDC_CHK_POPUPS 1023
+#define IDC_ED_SNOOZE 1024
+#define IDC_SPIN1 1025
+#define IDC_SPIN_SNOOZE 1025
+#define IDC_SNOOZE 1026
+#define IDC_CHK_ASOUND 1028
+#define IDC_CHK_ACOMMAND 1029
+#define IDC_ED_COMMAND 1030
+#define IDC_ED_PARAMS 1031
+#define IDC_CHK_INVIS 1032
+#define IDC_SNOOZELIST 1033
+#define IDC_RAD_SND1 1034
+#define IDC_RAD_SND2 1035
+#define IDC_RAD_SND3 1036
+#define IDC_RAD_SPK 1037
+#define IDC_RELMIN 1038
+#define IDC_ED_ROWHEIGHT 1039
+#define IDC_SPIN_ROWHEIGHT 1040
+#define IDC_ED_INDENT 1041
+#define IDC_SPIN_INDENT 1042
+#define IDC_SHOWHIDE 1043
+#define IDC_ED_PERIOD 1044
+#define IDC_SPIN_PERIOD 1045
+#define IDC_DISMISS 1045
+#define IDC_SHOWHIDE2 1046
+#define IDC_AUTOSIZEVERT 1047
+#define IDC_ED_TRANS 1048
+#define IDC_SPIN_TRANS 1049
+#define IDC_CHK_AWROUND 1050
+#define IDC_CHK_AWNOACTIVATE 1051
+#define IDC_BTN_PREVIEW 1052
+#define IDC_LST_TRIGLIST 1053
+#define IDC_BTN_CAL 1055
+#define IDC_CHK_APOPUP 1060
+#define IDC_SNOOZE2 1061
+#define IDC_CHK_SUSPEND 1062
+#define IDC_CHK_NOSTARTUP 1063
+#define IDC_CHK_NOREMINDER 1064
+#define IDC_CHK_LOOPSOUND 1065
+#define IDC_ED_DESC 1066
+#define IDC_DATE 1071
+#define ID_REMINDERFRAMECONTEXT_SUSPEND 40003
+#define ID_REMINDERFRAMECONTEXT_EDIT 40004
+#define ID_REMINDERFRAMECONTEXT_DELETE 40005
+#define ID_REMINDERFRAMECONTEXT_OPTIONS 40006
+#define ID_REMINDERFRAMECONTEXT_NEWALARM 40007
+#define IDC_STATIC -1
+
+// Next default values for new objects
+//
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE 127
+#define _APS_NEXT_COMMAND_VALUE 40008
+#define _APS_NEXT_CONTROL_VALUE 1072
+#define _APS_NEXT_SYMED_VALUE 101
+#endif
+#endif
diff --git a/plugins/Alarms/resource.rc b/plugins/Alarms/resource.rc
new file mode 100644
index 0000000000..4ebce37ec5
--- /dev/null
+++ b/plugins/Alarms/resource.rc
@@ -0,0 +1,244 @@
+// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (Australia) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENA)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_AUS
+#pragma code_page(1252)
+#endif //_WIN32
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Dialog
+//
+
+IDD_OPT1 DIALOGEX 0, 0, 286, 222
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CENTER | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ LISTBOX IDC_ALIST,15,20,164,69,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
+ PUSHBUTTON "New",IDC_NEW,18,97,50,14
+ PUSHBUTTON "Delete",IDC_DEL,126,97,50,14
+ PUSHBUTTON "Edit",IDC_EDIT,72,97,50,14
+ GROUPBOX "Alarms",IDC_STATIC,7,7,180,159
+ CONTROL "Use popup plugin",IDC_CHK_POPUPS,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,61,118,119,10
+ RTEXT "Default snooze:",IDC_STATIC,9,147,75,8
+ EDITTEXT IDC_ED_SNOOZE,88,144,40,14,ES_AUTOHSCROLL
+ CONTROL "Spin1",IDC_SPIN_SNOOZE,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS | UDS_NOTHOUSANDS,129,144,11,14
+ LTEXT "minutes",IDC_STATIC,144,147,37,8
+ LTEXT "Row Height:",IDC_STATIC,199,22,73,8
+ EDITTEXT IDC_ED_ROWHEIGHT,205,32,40,14,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER
+ CONTROL "Spin2",IDC_SPIN_ROWHEIGHT,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,245,32,12,14
+ LTEXT "Indent:",IDC_STATIC,199,53,73,8
+ EDITTEXT IDC_ED_INDENT,205,63,40,14,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER
+ CONTROL "Spin2",IDC_SPIN_INDENT,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,245,63,12,14
+ GROUPBOX "Reminder Frame",IDC_STATIC,191,7,88,159
+ CONTROL "Auto hide/show",IDC_SHOWHIDE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,197,88,78,10
+ CONTROL "Loop sound",IDC_CHK_LOOPSOUND,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,61,130,119,10
+ LTEXT "Period (hours):",IDC_STATIC,198,131,73,8
+ EDITTEXT IDC_ED_PERIOD,205,143,40,14,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER
+ CONTROL "Spin2",IDC_SPIN_PERIOD,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,245,143,12,14
+ CONTROL "Hide/show with clist",IDC_SHOWHIDE2,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,197,101,78,10
+ CONTROL "Auto size vertically",IDC_AUTOSIZEVERT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,197,114,78,10
+ LTEXT "Transparency (%):",IDC_STATIC,27,180,73,8
+ EDITTEXT IDC_ED_TRANS,33,192,40,14,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER
+ CONTROL "Spin2",IDC_SPIN_TRANS,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNRIGHT | UDS_AUTOBUDDY | UDS_ARROWKEYS,73,192,11,14
+ GROUPBOX "Alert Window",IDC_STATIC,7,166,272,49
+ CONTROL "Round corners",IDC_CHK_AWROUND,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,101,181,109,10
+ CONTROL "Don't steal focus unless idle",IDC_CHK_AWNOACTIVATE,
+ "Button",BS_AUTOCHECKBOX | WS_TABSTOP,101,196,109,10
+ PUSHBUTTON "Preview",IDC_BTN_PREVIEW,215,185,42,16
+END
+
+IDD_DIALOG2 DIALOGEX 0, 0, 381, 234
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
+CAPTION "Alarm"
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ DEFPUSHBUTTON "OK",IDOK,138,213,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,194,213,50,14
+ EDITTEXT IDC_TITLE,8,13,151,14,ES_AUTOHSCROLL
+ LTEXT "Title:",IDC_STATIC,8,3,104,8
+ EDITTEXT IDC_DESC,7,40,152,57,ES_MULTILINE | ES_AUTOVSCROLL | ES_WANTRETURN
+ LTEXT "Description:",IDC_STATIC,8,30,96,8
+ GROUPBOX "Actions",IDC_STATIC,7,100,367,88
+ CONTROL "Popup window",IDC_CHK_APOPUP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,110,119,10
+ CONTROL "Sound:",IDC_CHK_ASOUND,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,120,84,10
+ CONTROL "Run command:",IDC_CHK_ACOMMAND,"Button",BS_AUTOCHECKBOX | BS_LEFT | WS_TABSTOP,16,131,119,10
+ LTEXT "Parameters:",IDC_STATIC,16,159,119,8
+ EDITTEXT IDC_ED_COMMAND,16,143,351,14,ES_AUTOHSCROLL
+ EDITTEXT IDC_ED_PARAMS,16,169,351,14,ES_AUTOHSCROLL
+ CONTROL "Alert 1",IDC_RAD_SND1,"Button",BS_AUTORADIOBUTTON | WS_GROUP,105,120,61,10
+ CONTROL "Alert 2",IDC_RAD_SND2,"Button",BS_AUTORADIOBUTTON,171,120,61,10
+ CONTROL "Alert 3",IDC_RAD_SND3,"Button",BS_AUTORADIOBUTTON,237,120,61,10
+ CONTROL "Speak",IDC_RAD_SPK,"Button",BS_AUTORADIOBUTTON,303,120,61,10
+ CONTROL "DateTimePicker1",IDC_TIME,"SysDateTimePick32",DTS_RIGHTALIGN | DTS_UPDOWN | WS_TABSTOP | 0x8,174,19,55,13
+ GROUPBOX "Occurrence",IDC_STATIC,305,9,69,88
+ CONTROL "Once",IDC_RAD_ONCE,"Button",BS_AUTORADIOBUTTON | WS_GROUP,311,19,58,10
+ CONTROL "Weekly",IDC_RAD_WEEKLY,"Button",BS_AUTORADIOBUTTON,311,45,58,10
+ CONTROL "Daily",IDC_RAD_DAILY,"Button",BS_AUTORADIOBUTTON,311,32,58,10
+ CONTROL "Weekdays",IDC_RAD_WEEKDAYS,"Button",BS_AUTORADIOBUTTON,311,58,58,10
+ CONTROL "Monthly",IDC_RAD_MONTHLY,"Button",BS_AUTORADIOBUTTON,311,71,58,10
+ CONTROL "Yearly",IDC_RAD_YEARLY,"Button",BS_AUTORADIOBUTTON,311,84,58,10
+ COMBOBOX IDC_DAY,231,36,64,61,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ CONTROL "i'm hiding",IDC_CHK_INVIS,"Button",BS_AUTOCHECKBOX | NOT WS_VISIBLE | WS_TABSTOP,113,28,45,10
+ COMBOBOX IDC_DAYNUM,174,36,48,61,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
+ GROUPBOX "Date and Time",IDC_STATIC,167,9,134,88
+ EDITTEXT IDC_RELMIN,238,19,57,13,ES_RIGHT | ES_AUTOHSCROLL | ES_NUMBER
+ CONTROL "Disable next occurence",IDC_CHK_SUSPEND,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,192,128,10
+ CONTROL "Don't trigger on startup",IDC_CHK_NOSTARTUP,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,147,192,110,10
+ CONTROL "No reminder",IDC_CHK_NOREMINDER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,263,192,110,10
+ CONTROL "",IDC_DATE,"SysDateTimePick32",DTS_RIGHTALIGN | WS_TABSTOP,185,65,100,15
+END
+
+IDD_ALARM DIALOGEX 0, 0, 185, 82
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_3DLOOK | WS_POPUP
+EXSTYLE WS_EX_TOOLWINDOW
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ PUSHBUTTON "Dismiss",IDC_DISMISS,116,64,63,14
+ DEFPUSHBUTTON "Snooze",IDC_SNOOZE,4,58,88,21
+ LTEXT "Static",IDC_ED_DESC,6,22,173,31,SS_NOPREFIX | NOT WS_GROUP
+ LTEXT "Static",IDC_TITLE,6,4,173,13
+ DEFPUSHBUTTON "...",IDC_SNOOZELIST,92,58,20,21
+END
+
+IDD_OPTTRIGGER DIALOGEX 0, 0, 263, 184
+STYLE DS_SETFONT | DS_FIXEDSYS | DS_CENTER | WS_CHILD
+EXSTYLE WS_EX_CONTROLPARENT
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ LISTBOX IDC_LST_TRIGLIST,28,26,207,127,LBS_SORT | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
+ GROUPBOX "Alarms",IDC_STATIC,7,7,249,170
+END
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// DESIGNINFO
+//
+
+#ifdef APSTUDIO_INVOKED
+GUIDELINES DESIGNINFO
+BEGIN
+ IDD_OPT1, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 279
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 215
+ END
+
+ IDD_DIALOG2, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 374
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 227
+ END
+
+ IDD_ALARM, DIALOG
+ BEGIN
+ RIGHTMARGIN, 182
+ BOTTOMMARGIN, 81
+ END
+
+ IDD_OPTTRIGGER, DIALOG
+ BEGIN
+ LEFTMARGIN, 7
+ RIGHTMARGIN, 256
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 177
+ END
+END
+#endif // APSTUDIO_INVOKED
+
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
+2 TEXTINCLUDE
+BEGIN
+ "#include ""afxres.h""\r\n"
+ "\0"
+END
+
+3 TEXTINCLUDE
+BEGIN
+ "\r\n"
+ "\0"
+END
+
+#endif // APSTUDIO_INVOKED
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Icon
+//
+
+// Icon with lowest ID value placed first to ensure application icon
+// remains consistent on all systems.
+IDI_MAINMENU ICON "clock.ico"
+IDI_LIST1 ICON "green.ico"
+IDI_LIST2 ICON "yellow.ico"
+IDI_TBUP ICON "iconttbup.ico"
+IDI_TBDN ICON "iconttbdown.ico"
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// Menu
+//
+
+IDR_MENU1 MENU
+BEGIN
+ POPUP "Reminder Frame Context"
+ BEGIN
+ MENUITEM "&Suspend", ID_REMINDERFRAMECONTEXT_SUSPEND
+ MENUITEM "&Edit...", ID_REMINDERFRAMECONTEXT_EDIT
+ MENUITEM SEPARATOR
+ MENUITEM "&Delete", ID_REMINDERFRAMECONTEXT_DELETE
+ MENUITEM SEPARATOR
+ MENUITEM "&Options...", ID_REMINDERFRAMECONTEXT_OPTIONS
+ MENUITEM "&New Alarm...", ID_REMINDERFRAMECONTEXT_NEWALARM
+ END
+END
+
+#endif // English (Australia) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif // not APSTUDIO_INVOKED
+
diff --git a/plugins/Alarms/time_utils.cpp b/plugins/Alarms/time_utils.cpp
new file mode 100644
index 0000000000..69f45612f8
--- /dev/null
+++ b/plugins/Alarms/time_utils.cpp
@@ -0,0 +1,25 @@
+#include "common.h"
+#include "time_utils.h"
+
+SYSTEMTIME last_check;
+
+bool IsBetween(SYSTEMTIME &time, SYSTEMTIME &start, SYSTEMTIME &end) {
+
+ FILETIME ft_time, ft_start, ft_end;
+
+ SystemTimeToFileTime(&time, &ft_time);
+ SystemTimeToFileTime(&start, &ft_start);
+ SystemTimeToFileTime(&end, &ft_end);
+
+ return (CompareFileTime(&ft_time, &ft_start) > 0 && CompareFileTime(&ft_time, &ft_end) <= 0);
+}
+
+bool IsBefore(SYSTEMTIME &time, SYSTEMTIME &start) {
+ FILETIME ft_time, ft_start;
+
+ SystemTimeToFileTime(&time, &ft_time);
+ SystemTimeToFileTime(&start, &ft_start);
+
+ return (CompareFileTime(&ft_time, &ft_start) < 0);
+}
+
diff --git a/plugins/Alarms/time_utils.h b/plugins/Alarms/time_utils.h
new file mode 100644
index 0000000000..9bae092b63
--- /dev/null
+++ b/plugins/Alarms/time_utils.h
@@ -0,0 +1,7 @@
+#ifndef _TIME_UTILS_INC
+#define _TIME_UTILS_INC
+
+bool IsBefore(SYSTEMTIME &time, SYSTEMTIME &start);
+bool IsBetween(SYSTEMTIME &time, SYSTEMTIME &start, SYSTEMTIME &end);
+
+#endif
diff --git a/plugins/Alarms/timewindow.cpp b/plugins/Alarms/timewindow.cpp
new file mode 100644
index 0000000000..fe98dd2ae3
--- /dev/null
+++ b/plugins/Alarms/timewindow.cpp
@@ -0,0 +1,420 @@
+#include "timewindow.h"
+
+HDC hdc;
+HGLRC hglrc;
+
+HWND pluginwind = 0;
+int FrameId = 0;
+
+// Select the pixel format for a given device context
+BOOL SetDCPixelFormat(HDC hDC) {
+ int nPixelFormat;
+
+ static PIXELFORMATDESCRIPTOR pfd = {
+ sizeof(PIXELFORMATDESCRIPTOR), // Size of this structure
+ 1, // Version of this structure
+
+ PFD_DRAW_TO_WINDOW | // Draw to window (not bitmap)
+
+ PFD_SUPPORT_OPENGL | // Support OpenGL calls
+ PFD_DOUBLEBUFFER, // Double-buffered mode
+ PFD_TYPE_RGBA, // RGBA Color mode
+ 24, // Want 24bit color
+ 0,0,0,0,0,0, // Not used to select mode
+ 0,0, // Not used to select mode
+ 0,0,0,0,0, // Not used to select mode
+ 32, // Size of depth buffer
+ 0, // Not used to select mode
+ 0, // Not used to select mode
+ PFD_MAIN_PLANE, // Draw in main plane
+ 0, // Not used to select mode
+ 0,0,0
+ }; // Not used to select mode
+
+ // Choose a pixel format that best matches that described in pfd
+ if((nPixelFormat = ChoosePixelFormat(hDC, &pfd)) == 0) {
+ MessageBox(0, "ChoosePixelFormat failed", "Error", MB_OK);
+ return FALSE;
+ }
+
+ // Set the pixel format for the device context
+ if(SetPixelFormat(hDC, nPixelFormat, &pfd) == FALSE) {
+ MessageBox(0, "SetPixelFormat failed", "Error", MB_OK);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+int InitGL() {
+ // enable depth testing
+ glEnable(GL_DEPTH_TEST);
+
+ glClearColor(0, 0, 0, 0);
+
+ glEnable(GL_SCISSOR_TEST);
+
+ // back face culling
+ //glEnable(GL_CULL_FACE);
+
+ //glEnable(GL_LIGHTING);
+
+ glShadeModel(GL_SMOOTH);
+ //glShadeModel(GL_FLAT);
+
+ glEnable(GL_SCISSOR_TEST);
+ glClearColor(0.4151, 0.4151, 0.4151, 1);
+
+ return 0;
+}
+
+int SizeGL(int width, int height) {
+ if(width == 0 || height == 0) return 0;
+
+ GLfloat n_range = 0.5, x_range, y_range;
+
+ glViewport(0, 0, width, height);
+ glScissor(0, 0, width, height);
+
+ // prevent divide by zero
+ if(width == 0) width = 1;
+ if(height == 0) height = 1;
+
+ // Establish clipping volume (left, right, bottom, top, near, far)
+ if (width <= height) {
+ x_range = n_range;
+ y_range = n_range*height/width;
+ } else {
+ x_range = n_range*width/height;
+ y_range = n_range;
+ }
+
+ // Reset projection matrix stack
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+
+ glFrustum(-x_range, x_range, y_range, -y_range, n_range, 50 /*n_range * 100*/);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+
+ return 0;
+}
+
+void drawSmallMinute() {
+
+ GLfloat size = 0.08f;
+
+ glBegin(GL_POLYGON);
+ glColor3f(1, 1, 1);
+ glVertex3f(-size, -0.5*size, 0);
+ glVertex3f(-size, 0.5*size, 0);
+ glVertex3f(size, 0.5*size, 0);
+ glVertex3f(size, -0.5*size, 0);
+ glEnd();
+}
+
+void drawLargeMinute() {
+
+ GLfloat size = 0.08f;
+
+ glBegin(GL_POLYGON);
+ glColor3f(1, 1, 1);
+ glVertex3f(-size, -1.25*size, 0);
+ glVertex3f(-size, 1.25*size, 0);
+ glVertex3f(size, 1.25*size, 0);
+ glVertex3f(size, -1.25*size, 0);
+ glEnd();
+}
+
+void drawHourHand() {
+
+ glBegin(GL_POLYGON);
+ glColor3f(0.7f, 0.7f, 0.85f);
+ glVertex3f(0, 0, 0);
+ glVertex3f(-0.1f, 0.8f*1.5f, 0);
+ glVertex3f(0, 1.5f, 0);
+ glVertex3f(0.1f, 0.8f*1.5f, 0);
+ glEnd();
+}
+
+void drawMinuteHand() {
+
+ glBegin(GL_POLYGON);
+ glColor3f(0.7f, 0.85f, 0.7f);
+ glVertex3f(0, 0, 0);
+ glVertex3f(-0.15f, 0.8f*2.1f, 0);
+ glVertex3f(0, 2.1f, 0);
+ glVertex3f(0.15f, 0.8f*2.1f, 0);
+ glEnd();
+}
+
+void drawSecondsHand() {
+
+ glBegin(GL_POLYGON);
+ glColor3f(0.85f, 0.7f, 0.7f);
+ glVertex3f(-0.02f, 0, 0);
+ glVertex3f(-0.02f, 2.1f, 0);
+ glVertex3f(0.02f, 2.1f, 0);
+ glVertex3f(0.02f, 0, 0);
+ glEnd();
+}
+
+int RenderGL(HWND hwnd, HDC hdc) {
+
+ SYSTEMTIME ctime;
+ //GLfloat rot;
+ //int i;
+ char buf[512];
+
+ GetLocalTime(&ctime);
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+
+
+ glLoadIdentity();
+ glTranslated(0, 0, -30);
+
+ //gluLookAt(0, 0, 10, 0, 0, 0, 0, 1, 0);
+ glPushMatrix();
+
+/*
+ for (i=0;i<60;i++) {
+ glPushMatrix();
+ rot = (GLfloat)i/60*360;
+ glRotatef(-rot, 0, 0, 1.0);
+ glTranslatef(0, 2.2f, 0);
+ if (i%5!=0) drawSmallMinute();
+ else drawLargeMinute();
+ glPopMatrix();
+ }
+
+ glPopMatrix();
+
+ glPushMatrix();
+ rot = (GLfloat)(ctime.wSecond)/60*360;
+ glRotatef(-rot, 0, 0, 1.0);
+ drawSecondsHand();
+ glPopMatrix();
+
+ glPushMatrix();
+ rot = (GLfloat)(ctime.wMinute)/60*360 + (GLfloat)(ctime.wSecond)/300*360/12;
+ glRotatef(-rot, 0, 0, 1.0);
+ drawMinuteHand();
+ glPopMatrix();
+
+ glPushMatrix();
+ rot = (GLfloat)(ctime.wHour%12)/12*360 + (GLfloat)(ctime.wMinute)/60*360/12;
+ glRotatef(-rot, 0, 0, 1.0);
+ drawHourHand();
+
+ */
+ GetLocalTime(&ctime);
+ GetTimeFormat(LOCALE_USER_DEFAULT, 0, &ctime, 0, buf, 512);
+ draw_string_centered(buf);
+
+ glPopMatrix();
+
+ SwapBuffers(hdc);
+
+ return 0;
+}
+
+LRESULT CALLBACK FrameContainerWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
+ switch(msg) {
+ case WM_SIZE:
+ {
+ HWND child = (HWND)GetWindowLong(hwnd, GWL_USERDATA);
+ RECT r;
+ GetClientRect(hwnd, &r);
+
+ //SetWindowPos(Frames[framepos].hWnd,HWND_TOP,0,DEFAULT_TITLEBAR_HEIGHT,width,height-DEFAULT_TITLEBAR_HEIGHT,SWP_SHOWWINDOW);
+ SetWindowPos(child, HWND_TOP, r.left, r.top, r.right - r.left, r.bottom - r.top, SWP_SHOWWINDOW);
+ }
+ break;
+ case WM_CLOSE:
+ return 0;
+ }
+
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+}
+
+LRESULT CALLBACK FrameWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
+ PAINTSTRUCT ps;
+ RECT r;
+ //HDC hdc;
+
+ switch(msg) {
+
+ case WM_CREATE:
+ hdc = GetDC(hwnd);
+
+ if(SetDCPixelFormat(hdc) == FALSE) {
+ return FALSE;
+ }
+
+ hglrc = wglCreateContext(hdc);
+
+ wglMakeCurrent(hdc, hglrc);
+
+ GetClientRect(hwnd, &r);
+
+ InitGL();
+ SizeGL(r.right - r.left, r.bottom - r.top);
+ wglMakeCurrent(hdc, NULL);
+
+ SetTimer(hwnd, 1011, 20, 0);
+
+ return 0;
+
+ case WM_ERASEBKGND:
+ //RenderGL(hwnd, hdc);
+ return TRUE;
+
+ case WM_PAINT:
+ //ps.fErase = FALSE;
+ if(BeginPaint(hwnd, &ps)) {
+ glScissor(ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right - ps.rcPaint.left, ps.rcPaint.bottom - ps.rcPaint.left);
+
+ wglMakeCurrent(hdc, hglrc);
+
+ RenderGL(hwnd, hdc);
+
+ wglMakeCurrent(hdc, NULL);
+
+ EndPaint(hwnd, &ps);
+ }
+ //wglMakeCurrent(NULL, NULL);
+ return 0;
+
+ case WM_MOVE:
+ case WM_SIZE:
+ if(hdc) {
+ wglMakeCurrent(hdc, hglrc);
+
+ //SizeGL(LOWORD(lParam), HIWORD(lParam));
+
+ GetClientRect(hwnd, &r);
+ SizeGL(r.right - r.left, r.bottom - r.top);
+
+ wglMakeCurrent(hdc, NULL);
+ //RenderGL(hwnd, hdc);
+
+ InvalidateRect(hwnd, 0, FALSE);
+ }
+
+ //return DefWindowProc(hwnd, msg, wParam, lParam);
+ return TRUE;
+
+ case WM_DESTROY:
+ KillTimer(hwnd, 1011);
+ hdc = GetDC(hwnd);
+ wglMakeCurrent(hdc,NULL);
+ wglDeleteContext(hglrc);
+ ReleaseDC(hwnd, hdc);
+
+ //DestroyWindow(hwnd);
+ //return TRUE;
+ break;
+
+ case WM_TIMER:
+ //RenderGL(hwnd, hdc);
+ InvalidateRect(hwnd, 0, FALSE);
+ return 0;
+
+ };
+
+ return DefWindowProc(hwnd, msg, wParam, lParam);
+}
+
+int CreateFrame(HWND parent)
+{
+ WNDCLASS wndclass;
+ wndclass.style = 0; //CS_PARENTDC | CS_HREDRAW | CS_VREDRAW;
+ wndclass.lpfnWndProc = FrameWindowProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = 0;
+ wndclass.hInstance = hInst;
+ wndclass.hIcon = NULL;
+ wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
+ wndclass.hbrBackground = 0; //(HBRUSH)(COLOR_3DFACE+1);
+ wndclass.lpszMenuName = NULL;
+ wndclass.lpszClassName = "TestFrame";
+ RegisterClass(&wndclass);
+
+ //HWND pluginwind = CreateWindow("TestFrame",Translate("Test"),
+ // WS_BORDER | WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN,
+ // 0,0,0,0, parent, NULL,hInst,NULL);
+
+ if(ServiceExists(MS_CLIST_FRAMES_ADDFRAME)) {
+
+ pluginwind = CreateWindow("TestFrame",Translate("Test"),
+ (WS_CHILD | WS_CLIPCHILDREN) & ~CS_VREDRAW & ~CS_HREDRAW,
+ 0,0,100,100, parent, NULL,hInst,NULL);
+
+ CLISTFrame Frame;
+
+ memset(&Frame,0,sizeof(Frame));
+ Frame.name=(char *)malloc(255);
+ memset(Frame.name,0,255);
+
+ strcpy(Frame.name,"TestFrame");
+
+ Frame.cbSize=sizeof(CLISTFrame);
+ Frame.hWnd=pluginwind;
+ Frame.align=alBottom;
+ Frame.Flags=F_VISIBLE|F_SHOWTB|F_SHOWTBTIP;
+ Frame.height=30;
+
+ FrameId=CallService(MS_CLIST_FRAMES_ADDFRAME,(WPARAM)&Frame,0);
+
+ } else {
+ wndclass.style = 0;//CS_HREDRAW | CS_VREDRAW;
+ wndclass.lpfnWndProc = FrameContainerWindowProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = 0;
+ wndclass.hInstance = hInst;
+ wndclass.hIcon = NULL;
+ wndclass.hCursor = LoadCursor (NULL, IDC_ARROW);
+ wndclass.hbrBackground = 0; //(HBRUSH)(COLOR_3DFACE+1);
+ wndclass.lpszMenuName = NULL;
+ wndclass.lpszClassName = "TestFrameContainer";
+ RegisterClass(&wndclass);
+
+ //pluginwind = CreateWindow(WS_EX_TOOLWINDOW, "TestFrame",Translate("Test"),
+ // WS_POPUPWINDOW | WS_THICKFRAME | WS_VISIBLE | WS_CAPTION | WS_SYSMENU,
+ // 0,0,100,100, parent, NULL,hInst,NULL);
+
+ //ShowWindow(pluginwind, SW_SHOW);
+ //UpdateWindow(pluginwind);
+
+ HWND framewind = CreateWindowEx(WS_EX_TOOLWINDOW, "TestFrameContainer",Translate("Test"),
+ WS_POPUPWINDOW | WS_THICKFRAME | WS_VISIBLE | WS_CAPTION,
+ 0,0,100,100, parent, NULL,hInst,NULL);
+
+ pluginwind = CreateWindow("TestFrame",Translate("Test"),
+ WS_CHILD | WS_CLIPCHILDREN | WS_VISIBLE,
+ 0,0,100,100, framewind, NULL,hInst,NULL);
+
+ SetWindowLong(framewind, GWL_USERDATA, (LONG)pluginwind);
+
+ ShowWindow(framewind, SW_SHOW);
+ UpdateWindow(framewind);
+ }
+
+ return 0;
+}
+
+void InitFrame()
+{
+ CreateFrame((HWND)CallService(MS_CLUI_GETHWND, 0, 0));
+}
+
+void DeinitFrame()
+{
+ if(ServiceExists(MS_CLIST_FRAMES_REMOVEFRAME)) {
+ CallService(MS_CLIST_FRAMES_REMOVEFRAME, (WPARAM)FrameId, 0);
+ }
+ DestroyWindow(pluginwind);
+}
diff --git a/plugins/Alarms/timewindow.h b/plugins/Alarms/timewindow.h
new file mode 100644
index 0000000000..12f7672b6e
--- /dev/null
+++ b/plugins/Alarms/timewindow.h
@@ -0,0 +1,14 @@
+#ifndef _TIMEWINDOW_INC
+#define _TIMEWINDOW_INC
+
+#include "common.h"
+
+#include <gl/gl.h>
+#include <gl/glu.h>
+#include "glyph.h"
+
+
+void InitFrame();
+void DeinitFrame();
+
+#endif
diff --git a/plugins/Alarms/trigger.cpp b/plugins/Alarms/trigger.cpp
new file mode 100644
index 0000000000..78878cd72a
--- /dev/null
+++ b/plugins/Alarms/trigger.cpp
@@ -0,0 +1,106 @@
+#include "common.h"
+#include "trigger.h"
+
+AlarmList alist;
+//SPECIFICTRIGGERINFO sti;
+TRIGGERDATA td;
+
+unsigned short last_selected_id = 0;
+
+static BOOL CALLBACK DlgProcTriggerOptions(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) {
+ switch(msg) {
+ case WM_INITDIALOG:
+ TranslateDialogDefault(hwndDlg);
+
+ {
+ copy_list(alist);
+ ALARM *i;
+ for(alist.reset(); i = alist.current(); alist.next()) {
+ int pos = SendDlgItemMessage(hwndDlg, IDC_LST_TRIGLIST, LB_ADDSTRING, (WPARAM)-1, (LPARAM)i->szTitle);
+ SendDlgItemMessage(hwndDlg, IDC_LST_TRIGLIST, LB_SETITEMDATA, (WPARAM)pos, (LPARAM)i->id);
+ if(i->trigger_id == (unsigned int)lParam)
+ SendDlgItemMessage(hwndDlg, IDC_LST_TRIGLIST, LB_SETCURSEL, (WPARAM)pos, 0);
+ }
+ }
+ return FALSE;
+
+ case WM_COMMAND:
+ if (HIWORD( wParam ) == LBN_SELCHANGE) {
+ int pos = SendDlgItemMessage(hwndDlg, IDC_LST_TRIGLIST, LB_GETCURSEL, 0, 0);
+ if(pos != LB_ERR) {
+ last_selected_id = (unsigned short)SendDlgItemMessage(hwndDlg, IDC_LST_TRIGLIST, LB_GETITEMDATA, pos, 0);
+ }
+ return TRUE;
+ }
+ break;
+ case TM_GETTRIGGERINFO:
+ {
+ //memset(&sti, sizeof(sti), 0);
+ memset(&td, sizeof(td), 0);
+
+ ALARM *i;
+ for(alist.reset(); i = alist.current(); alist.next()) {
+ if(i->trigger_id == wParam) {
+ //sti.cbSize = sizeof(sti);
+ //sti.triggerID = wParam;
+ //sti.pszSummary = i->szTitle;
+ //sti.td = &td;
+
+ td.cbSize = sizeof(td);
+ td.dFlags = DF_TEXT;
+ td.szText = i->szDesc;
+ //*(SPECIFICTRIGGERINFO **)lParam = &sti;
+ break;
+ }
+ }
+ }
+ return TRUE;
+ case TM_ADDTRIGGER:
+ {
+ ALARM *i;
+ for(alist.reset(); i = alist.current(); alist.next()) {
+ if(i->id == last_selected_id) {
+ i->trigger_id = wParam;
+ alter_alarm_list(i);
+ break;
+ }
+ }
+ }
+ return TRUE;
+ case TM_DELTRIGGER:
+ {
+ ALARM *i;
+ for(alist.reset(); i = alist.current(); alist.next()) {
+ if(i->trigger_id == wParam) {
+ i->trigger_id = 0;
+ alter_alarm_list(i);
+ break;
+ }
+ }
+ }
+ return TRUE;
+
+ case WM_DESTROY:
+ // it seems this is called before the TM_ADDTRIGGER messsage is passed to us....tsk,tsk :P
+ //alist.clear();
+ break;
+
+ }
+ return FALSE;
+}
+
+int LoadTriggerSupport() {
+ if(ServiceExists(MS_TRIGGER_REGISTERTRIGGER)) {
+ TRIGGERREGISTER treg = {0};
+
+ treg.cbSize = sizeof(treg);
+ treg.pszName = Translate("Alarms");
+ treg.hInstance = hInst;
+ treg.pfnDlgProc = DlgProcTriggerOptions;
+ treg.pszTemplate = MAKEINTRESOURCE(IDD_OPTTRIGGER);
+
+ CallService(MS_TRIGGER_REGISTERTRIGGER, 0, (LPARAM)&treg);
+ }
+
+ return 0;
+}
diff --git a/plugins/Alarms/trigger.h b/plugins/Alarms/trigger.h
new file mode 100644
index 0000000000..3b326e78a4
--- /dev/null
+++ b/plugins/Alarms/trigger.h
@@ -0,0 +1,11 @@
+#ifndef _TRIGGER_INC
+#define _TRIGGER_INC
+
+#include "alarmlist.h"
+
+
+int LoadTriggerSupport();
+
+
+#endif
+
diff --git a/plugins/Alarms/yellow.ico b/plugins/Alarms/yellow.ico
new file mode 100644
index 0000000000..94f62a201d
--- /dev/null
+++ b/plugins/Alarms/yellow.ico
Binary files differ