/*******************************************************\
{                                                       }
{       Microsoft Visual C++ Version 4.X                }
{       Alarm Clock 1.0                                 }
{                                                       }
{       Copyright (C) 1996, CAT Computing Center (R).   }
{                                                       }
\*******************************************************/

#define STRICT
#include <Windows.h>
#include <Windowsx.h>
#include <commctrl.h>
#include <stdio.h>
#include <tchar.h>
#include "Resource.h"
#include "Alarm.h"

///////////////////////////////////////////////////////////////////////////////

#define UM_ALARMICONNOTIFY     (WM_USER + 100)
#define IDM_ALARM  200

#define HEIGHT		100
#define WIDTH		50

#define CCYY		10

static UINT s_uTID;

static LPCTSTR lpszAlarmTime = _T("Alarm Time");
static LPCTSTR lpszAlarmNot = _T("Alarm Notification");
static LPCTSTR lpszClockNot = _T("Clock Notification");
static LPCTSTR lpszActie = _T("Active");
static LPCTSTR lpszSecond = _T("Second");
static LPCTSTR lpszMinute = _T("Minute");
static LPCTSTR lpszHour = _T("Hour");
static LPCTSTR lpszNotification = _T("Notification");
static LPCTSTR lpszConfirmation = _T("Confirmation");
static LPCTSTR lpszInlineMessage = _T("InlineMessage");
static LPCTSTR lpszInlineSound = _T("InlineSound");
static LPCTSTR lpszFileName1 = _T("FileName1");
static LPCTSTR lpszFileName2 = _T("FileName2");
static LPCTSTR lpszMessageText = _T("MessageText");
static LPCTSTR lpszLastPage = _T("LastPage");

static TCHAR g_szTitle[] = _T("CAT");
static TCHAR g_szCaptionText[256];

static BOOL s_fShowAbout = FALSE;

APPDATA g_AppData;
APPOPTION g_AppOption;

///////////////////////////////////////////////////////////////////////////////

void About_OnCommand(HWND hWnd, int id, HWND hWndCtl, UINT codeNotify)
{
	switch(id)
	{
		case IDOK:
		case IDCANCEL:
		{
			KillTimer(hWnd, 1001);
//No good on Win98
//			KillTimer(hWnd, 2002);
			EndDialog(hWnd, id);
			return;
		}
	}
}

static int x = 0;
BOOL About_OnInitDialog(HWND hWnd, HWND hWndFocus, LPARAM lParam)
{
	x = 0;
	SendMessage(hWnd, WM_SETICON, TRUE, (LPARAM)LoadIcon(g_AppData.hInstance, MAKEINTRESOURCE(IDI_ALARM)));    
	SendMessage(hWnd, WM_SETICON, FALSE, (LPARAM)LoadIcon(g_AppData.hInstance, MAKEINTRESOURCE(IDI_ALARM)));    
	LoadString(g_AppData.hInstance, IDS_CAPTION_TEXT, g_szCaptionText, 255);
	SetTimer(hWnd, 1001, 250, NULL);
//No good on Win98
//	SetTimer(hWnd, 2002, 50, NULL);
	return TRUE;
}

BYTE DrawText(HDC hDC, int nX, int nY, LPCTSTR lpzsText, BYTE bDelta = 5, BYTE bColorVal = -1)
{
	LOGFONT LF;
	memset (&LF, 0, sizeof (LOGFONT));
	LF.lfHeight = HEIGHT;
	LF.lfWidth = WIDTH;

	_tcscpy (LF.lfFaceName, _T("Times New Roman"));
	HFONT HFont = CreateFontIndirect (&LF);
	HFONT HOldFont = (HFONT)SelectObject (hDC, HFont);

	SetBkMode (hDC, TRANSPARENT);
	SetTextAlign(hDC, TA_CENTER | VTA_CENTER);

	BeginPath (hDC);
	TextOut (hDC, nX, nY, lpzsText, _tcslen(lpzsText));
	EndPath (hDC);

	SelectClipPath (hDC, RGN_COPY);

	SIZE Size;
	GetTextExtentPoint32 (hDC, g_szTitle, _tcslen(g_szTitle), &Size);

	RECT Rect = {0, 0, nX * 2, 0};

	HBRUSH HGrayBrush;
	for (int i = nY; i <= nY - 2 + Size.cy; i += 2)
	{
		HGrayBrush = CreateSolidBrush(RGB (0, bColorVal, -1));
		bColorVal -= bDelta;

		Rect.top = i;
		Rect.bottom = i + 2;
		FillRect (hDC, &Rect, HGrayBrush);

		DeleteObject (HGrayBrush);
	} 

	SelectObject (hDC, HOldFont);
	DeleteObject (HFont);
	return bColorVal;
}

void About_OnPaint(HWND hWnd)
{
	PAINTSTRUCT ps;
	HDC hDC = BeginPaint(hWnd, &ps);

	RECT temp;
	GetClientRect(hWnd, &temp);
    RECT Rect;
	SetRect(&Rect, temp.right / 3, CCYY * 5 + 5, 0, 0);
	MapDialogRect(hWnd, &Rect);
	DrawText(hDC, Rect.left, Rect.top, g_szTitle);

	EndPaint(hWnd, &ps);
}

static BYTE bColorVal = (BYTE)-1;

//No good on Win98
/*
void About_OnNcPaint(HWND hWnd, BOOL bActive)
{
	HDC hDC = GetWindowDC(hWnd);
	RECT Rect, Rect2;
	GetWindowRect(hWnd, &Rect);
	SetRect(&Rect2, (GetSystemMetrics(SM_CXFIXEDFRAME) << 1) + GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYFIXEDFRAME) << 1, 
		(Rect.right - Rect.left) - (GetSystemMetrics(SM_CXFIXEDFRAME) << 1) ,
		GetSystemMetrics(SM_CYCAPTION) + (GetSystemMetrics(SM_CYFIXEDFRAME) << 1));


	SetBkMode(hDC, TRANSPARENT);
	HRGN hRgn = CreateRectRgn(Rect2.left, Rect2.top, Rect2.right - Rect2.left, Rect2.bottom - Rect2.top);
	HRGN oldRgh = (HRGN)SelectObject(hDC, hRgn);
	LOGBRUSH lb;
	lb.lbStyle = BS_SOLID;
	lb.lbColor = GetSysColor(bActive == TRUE ? COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION);
	HBRUSH hBrush = CreateBrushIndirect(&lb);
	FillRgn(hDC, hRgn, hBrush);
	DeleteObject(hBrush);
	ExcludeUpdateRgn(hDC, hWnd);
	SetTextColor(hDC, GetSysColor(COLOR_CAPTIONTEXT));
	TextOut(hDC, Rect2.right - x, (Rect2.bottom - Rect2.top) >> 2, g_szCaptionText, _tcslen(g_szCaptionText));
	x++;
	SIZE Size;
	GetTextExtentPoint32(hDC, g_szCaptionText, _tcslen(g_szCaptionText), &Size);
	if(Rect2.right - x == Rect2.left - Size.cx)
		x = 0;
	SelectObject(hDC, oldRgh);
	DeleteObject(hRgn);
	ReleaseDC(hWnd, hDC);
}
*/

BOOL WINAPI About_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	static BOOL bActive = TRUE;
	switch (uMsg)
	{
		case WM_TIMER:
		{
			if(wParam == 1001)
			{
				HDC hDC = GetDC(hWnd);
				RECT temp, Rect;
				GetClientRect(hWnd, &temp);
				SetRect(&Rect, temp.right / 3, CCYY * 5 + 5, 0, 0);
				MapDialogRect(hWnd, &Rect);
				bColorVal = DrawText(hDC, Rect.left, Rect.top, g_szTitle, 15, bColorVal);
				ReleaseDC(hWnd, hDC);
				break;
			}
		}
//No good on Win98
/*		case WM_NCPAINT:
		{
			About_OnNcPaint(hWnd, bActive);
			break;
		}
		case WM_NCACTIVATE:
		{
			About_OnNcPaint(hWnd, bActive = wParam);
			break;
		}*/
		adgHANDLE_DLGMSG(hWnd, WM_INITDIALOG, About_OnInitDialog);
		adgHANDLE_DLGMSG(hWnd, WM_COMMAND, About_OnCommand);
		adgHANDLE_DLGMSG(hWnd, WM_PAINT, About_OnPaint);
	}
	return FALSE;
}

///////////////////////////////////////////////////////////////////////////////


DWORD GetMonthDay(DWORD wMonth, DWORD wYear)
{
	switch(wMonth)	
	{
		case 1:
		case 3:
		case 5:
		case 7:
		case 8:
		case 10:
		case 12:
		{
			return 31;
		}

		case 2:
		{
			return (wYear % 4) ? 29 : 28;
		}

		case 4:
		case 6:
		case 9:
		case 11:
		{
			return 30;
		}
	}
	return 0;
}

/*
BOOL GetIniFile(LPTSTR lpszFileName)
{
    if(!GetModuleFileName(g_AppData.hInstance,lpszFileName,MAX_PATH))
		return FALSE;
    LPTSTR lpszTemp = _tcschr(lpszFileName, _T('.'));
    if(lpszTemp)
      lpszTemp[0] = 0;
    _tcscat(lpszFileName, _T(".ini"));
	return TRUE;
}
*/

BOOL SaveOption(BOOL fSoft = FALSE)
{
	SetRegDWORD(lpszAlarmTime, lpszActie, g_AppOption.AlarmTime.fActive);
	SetRegDWORD(lpszAlarmTime, lpszSecond, g_AppOption.AlarmTime.dwSecond);
	SetRegDWORD(lpszAlarmTime, lpszMinute, g_AppOption.AlarmTime.dwMinute);
	SetRegDWORD(lpszAlarmTime, lpszHour, g_AppOption.AlarmTime.dwHour);
	SetRegDWORD(lpszAlarmNot, lpszNotification, g_AppOption.AlarmSet.uAlarmNot);
	SetRegDWORD(lpszAlarmNot, lpszConfirmation, g_AppOption.AlarmSet.fConfirm);
	SetRegDWORD(lpszAlarmNot, lpszInlineMessage, g_AppOption.AlarmSet.fMessage);
	SetRegDWORD(lpszAlarmNot, lpszInlineSound, g_AppOption.AlarmSet.fMultimedia);

	SetRegString(lpszAlarmNot, lpszFileName1, g_AppOption.AlarmSet.szFileName1);
	SetRegString(lpszAlarmNot, lpszFileName2, g_AppOption.AlarmSet.szFileName2);
	SetRegString(lpszAlarmNot, lpszMessageText, g_AppOption.AlarmSet.szMesText);
	SetRegDWORD(lpszClockNot, lpszNotification, g_AppOption.AlarmSet.uClockNot);
	SetRegString(lpszClockNot, lpszFileName1, g_AppOption.AlarmSet.szFileName3);

	SetRegDWORD(NULL, lpszLastPage, g_AppOption.AlarmSet.uLastPage);
	return TRUE;
}

BOOL InitOption(BOOL fSoft = FALSE)
{
	if(!fSoft)
	{
		g_AppData.fShow = FALSE;
		g_AppOption.AlarmTime.fActive = GetRegDWORD(lpszAlarmTime, lpszActie, 0);
		g_AppOption.AlarmTime.dwSecond = GetRegDWORD(lpszAlarmTime, lpszSecond, 0);
		if(g_AppOption.AlarmTime.dwSecond > 59)
			g_AppOption.AlarmTime.dwSecond = 0;
		g_AppOption.AlarmTime.dwMinute = GetRegDWORD(lpszAlarmTime, lpszMinute, 0);
		if(g_AppOption.AlarmTime.dwMinute > 59)
			g_AppOption.AlarmTime.dwMinute = 0;
		g_AppOption.AlarmTime.dwHour = GetRegDWORD(lpszAlarmTime, lpszHour, 0);
		if(g_AppOption.AlarmTime.dwHour > 23)
			g_AppOption.AlarmTime.dwHour = 0;

		g_AppOption.AlarmSet.uAlarmNot = GetRegDWORD(lpszAlarmNot, lpszNotification, 0);
		g_AppOption.AlarmSet.fConfirm = GetRegDWORD(lpszAlarmNot, lpszConfirmation, 1);
		g_AppOption.AlarmSet.fMessage = GetRegDWORD(lpszAlarmNot, lpszInlineMessage, 0);
		g_AppOption.AlarmSet.fMultimedia = GetRegDWORD(lpszAlarmNot, lpszInlineSound, 0);
		GetRegString(lpszAlarmNot, lpszFileName1, NULL, g_AppOption.AlarmSet.szFileName1, MAX_PATH);
		GetRegString(lpszAlarmNot, lpszFileName2, NULL, g_AppOption.AlarmSet.szFileName2, MAX_PATH);
		GetRegString(lpszAlarmNot, lpszMessageText, NULL, g_AppOption.AlarmSet.szMesText, 255);

		g_AppOption.AlarmSet.uClockNot = GetRegDWORD(lpszClockNot, lpszNotification, 0);
		GetRegString(lpszClockNot, lpszFileName1, NULL, g_AppOption.AlarmSet.szFileName3, MAX_PATH);
		g_AppOption.AlarmSet.uLastPage = GetRegDWORD(NULL, lpszLastPage, 0);
	}
	g_AppOption.uDate = 0;
	g_AppOption.uSet = 0;
	g_AppOption.uCount = 0;
	g_AppOption.uTimer = 0;
	g_AppOption.uAlarm = 0;
	g_AppData.fSet = FALSE;
	g_AppData.fStopSound = FALSE;
	return TRUE;
}

BOOL Alarm_OnInitDialog(HWND hWnd, HWND hWndFocus, LPARAM lParam)
{
	if(IsWindow(g_AppData.hMainWnd))
		return TRUE;

	HMENU hSMenu = GetSystemMenu(hWnd, FALSE);
	if(!hSMenu)
		return EndDialog(hWnd, IDCANCEL);

	TCHAR szMes[256];
	AppendMenu(hSMenu,MF_SEPARATOR,0,0);
	LoadString(g_AppData.hInstance, IDS_TOPMOST, szMes, 256);
	AppendMenu(hSMenu,MF_STRING,ID_TOPMOST,szMes);

	LoadString(g_AppData.hInstance, IDS_ABOUT, szMes, 256);
	AppendMenu(hSMenu,MF_STRING,ID_ABOUT,szMes);

	InitCommonControls();
	if(!InitWatch((g_AppData.hWatchWnd = GetDlgItem(hWnd, IDC_WATCH))))
		return EndDialog(hWnd, IDCANCEL);
	if(!InitToolBar(GetDlgItem(hWnd, IDC_TOOLBAR)))
		return EndDialog(hWnd, IDCANCEL);
	s_uTID = SetTimer(hWnd, 115, 1000, TimerProc);
	InitOption();

	NOTIFYICONDATA nid;
	nid.cbSize = sizeof(nid);
	nid.hWnd = hWnd;        
	nid.uID = IDI_ALARM;   
	nid.uFlags = NIF_MESSAGE | NIF_ICON | NIF_TIP;
	nid.uCallbackMessage = UM_ALARMICONNOTIFY;
	nid.hIcon = LoadIcon(GetWindowInstance(hWnd), MAKEINTRESOURCE(IDI_ALARM));
	_tcsncpy(nid.szTip, g_AppData.szAppName, sizeof(nid.szTip) / sizeof(nid.szTip[0]));
	if(!Shell_NotifyIcon(NIM_ADD, &nid))
		return EndDialog(hWnd, IDCANCEL);

	SendMessage(hWnd, WM_SETICON, (WPARAM) TRUE, (LPARAM) nid.hIcon);
	return TRUE;
}

void Alarm_OnDestroy(HWND hWnd)
{
	if(!IsWindow(hWnd))
		return;
	KillTimer(hWnd, s_uTID);
	SaveOption();
	FreeWatch(GetDlgItem(hWnd,IDC_WATCH));
	FreeToolBar(GetDlgItem(hWnd,IDC_TOOLBAR));
	NOTIFYICONDATA nid;
	nid.cbSize = sizeof(nid);
	nid.hWnd = hWnd;
	nid.uID = IDI_ALARM;
	Shell_NotifyIcon(NIM_DELETE, &nid);
}

void ExitAlarm()
{
	try
	{
		Alarm_OnDestroy(g_AppData.hMainWnd);
		CloseDBSettings();
	}
	catch(...)
	{
	}
	exit(-1);
}

void Alarm_OnIconNotify(HWND hWnd, UINT uID, UINT uMsg)
{
	UINT uMenuID = 0;
	if(uMsg == WM_RBUTTONUP)
	{
		HMENU hmenuMain = LoadMenu(GetWindowInstance(hWnd), 
			MAKEINTRESOURCE(IDR_ALARM));

		HMENU hmenuContext = GetSubMenu(hmenuMain, 0);

		SetForegroundWindow(hWnd);	

		POINT pt;
		GetCursorPos(&pt);
		SetMenuDefaultItem(hmenuContext,0,TRUE);
		uMenuID = TrackPopupMenu(hmenuContext, 
			TPM_BOTTOMALIGN | TPM_LEFTBUTTON | TPM_RIGHTBUTTON | TPM_RETURNCMD,
			pt.x, pt.y, 0, hWnd, NULL);

		DestroyMenu(hmenuContext);
		DestroyMenu(hmenuMain);

		PostMessage(hWnd, WM_NULL, 0, 0);	

		switch (uMenuID)
		{
			case 0:
			{
				return;
			}

			case ID_EXIT:
			{
				PostQuitMessage(1);
				return;
			}

			case ID_SETTING:
			{
				ShowSettingsDlg(g_AppData.hInstance, hWnd);
				SaveOption();
				return;
			}

			case ID_ABOUT:
			{
				if(!s_fShowAbout)
				{
					s_fShowAbout = TRUE;
					DialogBox(g_AppData.hInstance, MAKEINTRESOURCE(IDD_ABOUT), hWnd, About_WndProc);
					s_fShowAbout = FALSE;
				}
				return;
			}

			case ID_ALARM:
			{
				break;
			}
		}
	}
	
	if(uMsg == WM_LBUTTONDBLCLK || uMenuID == ID_ALARM)
	{
		InitOption(TRUE);
		RECT rc;
		GetWindowRect(hWnd, &rc);
		SetWindowPos(hWnd, NULL, 
			(GetSystemMetrics(SM_CXSCREEN) - (rc.right - rc.left)) / 2,
			(GetSystemMetrics(SM_CYSCREEN) - (rc.bottom - rc.top)) / 2,
			0, 0, SWP_NOZORDER | SWP_NOSIZE);

		if (!IsWindowVisible(hWnd))
		{
			HWND hTemp = FindWindow(_T("Shell_TrayWnd"), NULL);
			if (hTemp)
			{
				HWND hSysTray = FindWindowEx(hTemp, NULL, _T("TrayNotifyWnd"), NULL);
				if (hSysTray)
				{
					RECT rcSysTray;
					GetWindowRect(hSysTray, &rcSysTray);
					GetWindowRect(hWnd, &rc);
					RECT rcFrom = {rcSysTray.left, rcSysTray.top, rcSysTray.left + 50, rcSysTray.top + GetSystemMetrics(SM_CYCAPTION)}, 
						rcTo = {rc.left, rc.top, rc.right, rc.top + GetSystemMetrics(SM_CYCAPTION)};
					DrawAnimatedRects(hWnd, IDANI_CAPTION, &rcFrom, &rcTo);
				}
			}
		}
		g_AppData.fShow = TRUE;
		ShowWindow(hWnd, SW_RESTORE);
		SetForegroundWindow(hWnd);	
	}
}

void Alarm_OnPaint(HWND hWnd)
{
	PAINTSTRUCT ps;
	HDC hDC = BeginPaint(hWnd, &ps);

	RECT temp;
	GetClientRect(hWnd, &temp);
    RECT Rect;
	SetRect(&Rect, temp.right / 3, CCYY, 0, 0);
	MapDialogRect(hWnd, &Rect);
	DrawText(hDC, Rect.left, Rect.top, g_szTitle);

	EndPaint(hWnd, &ps);
}


void OnALTM(HWND hWnd)
{
	if((g_AppOption.uSet && (g_AppOption.uSet <= 6)))
	{
		g_AppOption.uSet = 7;
		OnSet(g_AppData.hMainWnd);
		return;
	}
	else if(g_AppOption.uAlarm)
	{
		g_AppOption.uAlarm = 0;
	}
	else if(g_AppOption.uDate)
	{
		g_AppOption.uDate = 0;
	}
	else
	{
		switch(g_AppOption.uTimer)
		{
			case 0:
			{
				g_AppData.OffsetTime.wHour = 0;
				g_AppData.OffsetTime.wMinute = 0;
				g_AppData.OffsetTime.wSecond = 0;
				g_AppData.OffsetTime.wDayOfWeek = 0xffff;
				g_AppOption.uTimer = 1;
				break;
			}

			case 1:
			{
				g_AppOption.uTimer = 2;
				if(s_uTID != 333)
					s_uTID = KillTimer(hWnd, s_uTID);
				s_uTID = SetTimer(hWnd,333, 100, TimerProc);
				break;
			}

			case 2:
			{
				g_AppOption.uTimer = 3;
				break;
			}

			case 3:
			{
				g_AppOption.uTimer = 2;
				break;
			}

			case 0xffffffff:
			{
				g_AppOption.uTimer = 0;
				if(s_uTID == 333)
					s_uTID = KillTimer(hWnd, s_uTID);
				s_uTID = SetTimer(hWnd,115, 1000,TimerProc);
				break;
			}
		}
	}
	InvalidateRect(g_AppData.hWatchWnd, NULL, FALSE);
	UpdateWindow(g_AppData.hWatchWnd);
}

void OnAlarm(HWND hWnd)
{
	if(g_AppOption.uSet && (g_AppOption.uSet <= 6))
	{
		g_AppOption.uCount = 20;
		g_AppData.fSet = TRUE;

		if(g_AppOption.uAlarm)
			GetAlarmTime(g_AppData.OffsetTime);
		else
			GetLocalTime(&g_AppData.OffsetTime);

		switch(g_AppOption.uSet)
		{
			case 1:
			{
				if(g_AppData.OffsetTime.wSecond == 0)
					g_AppData.OffsetTime.wSecond = 59;
				else
					g_AppData.OffsetTime.wSecond--;
				break;
			}

			case 2:
			{
				if(g_AppData.OffsetTime.wMinute == 0)
					g_AppData.OffsetTime.wMinute = 59;
				else
					g_AppData.OffsetTime.wMinute--;
				break;
			}

			case 3:
			{
				if(g_AppData.OffsetTime.wHour == 0)
					g_AppData.OffsetTime.wHour = 23;
				else
					g_AppData.OffsetTime.wHour--;
				break;
			}

			case 4:
			{
				if(g_AppOption.uAlarm)
					g_AppOption.AlarmTime.fActive ^= TRUE;
				else
					g_AppData.OffsetTime.wYear--;
				break;
			}

			case 5:
			{
				if(g_AppData.OffsetTime.wMonth == 1)
					g_AppData.OffsetTime.wMonth = 12;
				else
					g_AppData.OffsetTime.wMonth--;
				break;
			}

			case 6:
			{
				if(g_AppData.OffsetTime.wDay == 1)
					g_AppData.OffsetTime.wDay = (WORD)GetMonthDay(g_AppData.OffsetTime.wMonth,g_AppData.OffsetTime.wYear);
				else
					g_AppData.OffsetTime.wDay--;
				break;
			}

		}
		if(g_AppOption.uAlarm)
			SetAlarmTime(g_AppData.OffsetTime);
		else
			SetLocalTime(&g_AppData.OffsetTime);
	}
	else if(g_AppOption.uTimer == 1)
	{
		g_AppOption.uTimer = 0xffffffff;
		OnALTM(hWnd);
	}
	else if(g_AppOption.uTimer == 2)
	{
		g_AppOption.uTimer = 3;
	}
	else if(g_AppOption.uTimer == 3)
	{
		g_AppOption.uTimer = 0;
		OnALTM(hWnd);
	}
	else
	{
		if(g_AppOption.uAlarm)
			g_AppOption.uAlarm = 0;
		else
		{
			g_AppOption.uAlarm = 5;
			GetAlarmTime(g_AppData.OffsetTime);
		}
		InvalidateRect(g_AppData.hWatchWnd, NULL, FALSE);
		UpdateWindow(g_AppData.hWatchWnd);
	}
}

void OnDate(HWND hWnd)
{
	if(g_AppOption.uSet && (g_AppOption.uSet <= 6))
	{
		g_AppOption.uCount = 20;
		g_AppData.fSet = TRUE;

		if(g_AppOption.uAlarm)
			GetAlarmTime(g_AppData.OffsetTime);
		else
			GetLocalTime(&g_AppData.OffsetTime);

		switch(g_AppOption.uSet)
		{
			case 1:
			{
				if(g_AppData.OffsetTime.wSecond == 59)
					g_AppData.OffsetTime.wSecond = 0;
				else
					g_AppData.OffsetTime.wSecond++;
				break;
			}

			case 2:
			{
				if(g_AppData.OffsetTime.wMinute == 59)
					g_AppData.OffsetTime.wMinute = 0;
				else
					g_AppData.OffsetTime.wMinute++;
				break;
			}

			case 3:
			{
				if(g_AppData.OffsetTime.wHour == 23)
					g_AppData.OffsetTime.wHour = 0;
				else
					g_AppData.OffsetTime.wHour++;
				break;
			}

			case 4:
			{
				if(g_AppOption.uAlarm)
					g_AppOption.AlarmTime.fActive ^= TRUE;
				else
					g_AppData.OffsetTime.wYear++;
				break;
			}

			case 5:
			{
				if(g_AppData.OffsetTime.wMonth == 12)
					g_AppData.OffsetTime.wMonth = 1;
				else
					g_AppData.OffsetTime.wMonth++;
				break;
			}

			case 6:
			{
				if(g_AppData.OffsetTime.wDay == GetMonthDay(g_AppData.OffsetTime.wMonth,g_AppData.OffsetTime.wYear))
					g_AppData.OffsetTime.wDay = 1;
				else
					g_AppData.OffsetTime.wDay++;
				break;
			}
		}
		if(g_AppOption.uAlarm)
			SetAlarmTime(g_AppData.OffsetTime);
		else
			SetLocalTime(&g_AppData.OffsetTime);
	}
	else if(g_AppOption.uTimer == 1 || g_AppOption.uTimer == 3)
	{
		g_AppOption.uTimer = 0xffffffff;
		OnALTM(hWnd);
	}
	else if(g_AppOption.uTimer == 2)
	{
		g_AppOption.uTimer = 3;
	}
	else
	{
		g_AppOption.uAlarm = 0;
		
		if(g_AppOption.uDate)
			g_AppOption.uDate = 0;
		else
			g_AppOption.uDate = 5;
		InvalidateRect(g_AppData.hWatchWnd, NULL, FALSE);
		UpdateWindow(g_AppData.hWatchWnd);
	}
}


void SwitchTimer(HWND hWnd, UINT &dwID, BOOL fLong)
{
	if(fLong)
	{
		if(dwID == 225)
			KillTimer(hWnd, 225);
		dwID = SetTimer(hWnd, 115, 1000, TimerProc);
		g_AppOption.uSet = 0;
		g_AppOption.uCount = 0;
	}
	else
	{
		if(dwID == 115)
			KillTimer(hWnd, 115);
		dwID = SetTimer(hWnd, 225, 250, TimerProc);
	}
//	InvalidateRect(g_AppData.hWatchWnd, NULL, FALSE);
//	UpdateWindow(g_AppData.hWatchWnd);
}

void OnSet(HWND hWnd)
{
	if(g_AppOption.uTimer)
	{
		g_AppOption.uTimer = 0xffffffff;
		OnALTM(hWnd);
		return;
	}
	if(g_AppOption.uAlarm)
	{
		g_AppOption.uCount = 20;
		g_AppOption.uAlarm = 5;
		g_AppOption.uSet++;
		SwitchTimer(hWnd, s_uTID, g_AppOption.uSet > 4);
	}
	else
	{
		g_AppOption.uCount = 20;
		g_AppOption.uSet++;
		g_AppOption.uDate = 0;
		SwitchTimer(hWnd, s_uTID, g_AppOption.uSet > 6);
	}
}

void Alarm_OnCommand(HWND hWnd, int id, HWND hWndCtl, UINT codeNotify)
{
	switch(id)
	{
		case IDOK:
		case IDCANCEL:
		{
			if (IsWindowVisible(hWnd))
			{
				HWND hTemp = FindWindow(_T("Shell_TrayWnd"), NULL);
				if (hTemp)
				{
					HWND hSysTray = FindWindowEx(hTemp, NULL, _T("TrayNotifyWnd"), NULL);
					if (hSysTray)
					{
						RECT rc, rcSysTray;
						GetWindowRect(hSysTray, &rcSysTray);
						GetWindowRect(hWnd, &rc);
						RECT rcTo = {rcSysTray.left, rcSysTray.top, rcSysTray.left + 50, rcSysTray.top + GetSystemMetrics(SM_CYCAPTION)}, 
							rcFrom = {rc.left, rc.top, rc.right, rc.top + GetSystemMetrics(SM_CYCAPTION)};
						DrawAnimatedRects(hWnd, IDANI_CAPTION, &rcFrom, &rcTo);
					}
				}
			}
			ShowWindow(hWnd, SW_HIDE);
			g_AppData.fShow = FALSE;
			return;
		}

		case ID_SETTING:
		{
			ShowSettingsDlg(g_AppData.hInstance, hWnd);
			SaveOption();
			return;
		}

		case ID_ALTM:
		{
			g_AppData.fStopSound = TRUE;
			OnALTM(hWnd);
			return;
		}

		case ID_ALARM:
		{
			g_AppData.fStopSound = TRUE;
			OnAlarm(hWnd);
			return;
		}

		case ID_DATE:
		{
			g_AppData.fStopSound = TRUE;
			OnDate(hWnd);
			return;
		}

		case ID_SET:
		{
			g_AppData.fStopSound = TRUE;
			OnSet(hWnd);
			return;
		}
	}
}

BOOL WINAPI Alarm_WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
	switch (uMsg)
	{
		case WM_HOTKEY:
			return HotKeyMonitor(wParam, lParam);
		case UM_ALARMICONNOTIFY:
		{
			Alarm_OnIconNotify(hWnd, (UINT) wParam, (UINT) lParam);
			return TRUE;
		}

		case WM_SYSCOMMAND:
		{
			if(wParam == ID_TOPMOST)
			{
				HMENU hSMenu = GetSystemMenu(hWnd, FALSE);
				if(hSMenu)
				{
					if(GetMenuState(hSMenu, ID_TOPMOST, MF_BYCOMMAND) & MF_CHECKED)
					{
						CheckMenuItem(hSMenu, ID_TOPMOST, MF_BYCOMMAND|MF_UNCHECKED);
						SetWindowPos(g_AppData.hMainWnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW);
					}
					else
					{
						CheckMenuItem(hSMenu, ID_TOPMOST, MF_BYCOMMAND|MF_CHECKED);
						SetWindowPos(g_AppData.hMainWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_SHOWWINDOW);
					}
				}
			}
			else if(wParam == ID_ABOUT)
			{
				if(!s_fShowAbout)
				{
					s_fShowAbout = TRUE;
					DialogBox(g_AppData.hInstance, MAKEINTRESOURCE(IDD_ABOUT), hWnd, About_WndProc);
					s_fShowAbout = FALSE;
				}
			}
			break;
		}

		case WM_SHOWWINDOW:
		{
			if(!wParam)
				SaveOption();
		}
		adgHANDLE_DLGMSG(hWnd, WM_INITDIALOG, Alarm_OnInitDialog);
		adgHANDLE_DLGMSG(hWnd, WM_DESTROY, Alarm_OnDestroy);
		adgHANDLE_DLGMSG(hWnd, WM_COMMAND, Alarm_OnCommand);
		adgHANDLE_DLGMSG(hWnd, WM_PAINT, Alarm_OnPaint);
	}
	return FALSE;
}

///////////////////////////////////////////////////////////////////////////////

// Variables shared across all instances of our application which ensure
// that only one instance of this application  will run at a given time.
#pragma data_seg("Shared")
static LONG g_lInstanceCount = -1;
#pragma data_seg()

#pragma data_seg(".drectve")
static TCHAR szShared[] = _T("-section:Shared,rws");
#pragma data_seg()

void SetGlobalHandlers();
extern HCURSOR g_hCursor;
///////////////////////////////////////////////////////////////////////////////

int WINAPI _tWinMain (HINSTANCE hinstExe, HINSTANCE hinstExePrev, 
					LPTSTR pszCmdLine, int nCmdShow)
{
	SetGlobalHandlers();
	g_AppData.hMainWnd = NULL;
	g_AppData.hInstance = hinstExe;
	LoadString(g_AppData.hInstance, IDS_TITLE, g_AppData.szAppName, 256);
	if(InterlockedIncrement(&g_lInstanceCount) > 0)
	{
		InterlockedDecrement(&g_lInstanceCount);
		TCHAR szMes[256];
		LoadString(g_AppData.hInstance, IDS_MESSAGE, szMes, 256);
		ReportBox(szMes, MB_ICONINFORMATION | MB_OK);

	}
	else
	{
		if(!InitTDEdit(g_AppData.hInstance))
		{
			ShowOSError(IDS_CANNOTINITCATCTL, GetLastError());
			return 0;
		}
		g_AppData.hMainWnd = CreateDialog(g_AppData.hInstance, MAKEINTRESOURCE(IDD_ALARM), NULL, Alarm_WndProc);
		if(!g_AppData.hMainWnd)
			return FALSE;

		if(!OpenDBSettings())
		{
			DestroyWindow(g_AppData.hMainWnd);
			return FALSE;
		}

		g_hCursor = LoadCursor(g_AppData.hInstance, MAKEINTRESOURCE(IDC_POINT));

		MSG msg;
		while(GetMessage(&msg, g_AppData.hMainWnd, 0, 0))
		{
			if(!IsDialogMessage(g_AppData.hMainWnd, &msg))
			{
				TranslateMessage(&msg);
				DispatchMessage(&msg);
			}
		}
		CloseDBSettings();
		DestroyWindow(g_AppData.hMainWnd);
		DestroyCursor(g_hCursor);
	}
	return 0;
}


///////////////////////////////// End of File /////////////////////////////////
