diff options
| author | Rozhuk Ivan <rozhuk.im@gmail.com> | 2014-11-27 19:10:05 +0000 | 
|---|---|---|
| committer | Rozhuk Ivan <rozhuk.im@gmail.com> | 2014-11-27 19:10:05 +0000 | 
| commit | ea9f7e71bf6d6938bd99795ae6ec8e80028d17a5 (patch) | |
| tree | be086e1794bc34ad02afb26615cbb7efafcdec78 /plugins/NotesAndReminders/src | |
| parent | 9c2117c10e0d9eb7eb5b704c0177ee1553d3f198 (diff) | |
NotesReminders: code cleanup
git-svn-id: http://svn.miranda-ng.org/main/trunk@11122 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/NotesAndReminders/src')
| -rw-r--r-- | plugins/NotesAndReminders/src/notes.cpp | 4316 | 
1 files changed, 2156 insertions, 2160 deletions
diff --git a/plugins/NotesAndReminders/src/notes.cpp b/plugins/NotesAndReminders/src/notes.cpp index 847deb95c0..5d634e24f9 100644 --- a/plugins/NotesAndReminders/src/notes.cpp +++ b/plugins/NotesAndReminders/src/notes.cpp @@ -1,2160 +1,2156 @@ -#include "globals.h"
 -
 -#ifndef MONITOR_DEFAULTTONULL
 -#define MONITOR_DEFAULTTONULL       0x00000000
 -#endif
 -
 -
 -// NotesData DB data params
 -#define DATATAG_TEXT		1	// %s
 -#define DATATAG_SCROLLPOS	2	// %u (specifies rich edit controls scroll post as first visible line)
 -#define DATATAG_BGCOL		3	// %x (custom background color)
 -#define DATATAG_FGCOL		4	// %x (custom text/fg colors)
 -#define DATATAG_TITLE		5	// %s (custom note title)
 -#define DATATAG_FONT		6	// %d:%u:%u:%s (custom font)
 -
 -
 -#define MAX_TITLE_LEN	63
 -#define MAX_NOTE_LEN	16384
 -
 -// delay before saving note changes (ms)
 -#define NOTE_CHANGE_COMMIT_DELAY 1000
 -
 -
 -#ifndef WS_EX_NOACTIVATE
 -#define WS_EX_NOACTIVATE 0x08000000
 -#endif
 -#define IDM_REMOVENOTE 40001
 -#define IDM_HIDENOTE 40002
 -#define IDM_TOGGLEONTOP 40003
 -#define IDM_UNDO 40004
 -#define IDM_COPY 40005
 -#define IDM_PASTE 40006
 -#define IDM_CUT 40007
 -#define IDM_CLEAR 40008
 -#define WS_EX_LAYERED 0x00080000
 -#define LWA_ALPHA 0x00000002
 -
 -#define IDC_LISTREMINDERS 1000
 -#define IDC_LISTREMINDERS_HEADER 2000
 -#define IDC_REMINDERDATA 1001
 -#define IDC_ADDNEWREMINDER 1002
 -#define IDC_CLOSE 1003
 -#define WM_RELOAD (WM_USER + 100)
 -
 -#define NOTIFY_LIST() if (ListNotesVisible) PostMessage(LV,WM_RELOAD,0,0)
 -
 -#define PENLINK ENLINK *
 -
 -#define NOTE_WND_CLASS _T("MIM_StickyNote")
 -
 -
 -#define IDM_COLORPRESET_BG 41000
 -#define IDM_COLORPRESET_FG 41100
 -
 -
 -static BOOL ListNotesVisible = FALSE;
 -static HWND LV;
 -
 -
 -struct ColorPreset
 -{
 -	TCHAR *szName;
 -	COLORREF color;
 -};
 -
 -static struct ColorPreset clrPresets[] =
 -{
 -	{LPGENT("Black"), RGB(0,0,0)},
 -	{LPGENT("Maroon"), RGB(128,0,0)},
 -	{LPGENT("Green"), RGB(0,128,0)},
 -	{LPGENT("Olive"), RGB(128,128,0)},
 -	{LPGENT("Navy"), RGB(0,0,128)},
 -	{LPGENT("Purple"), RGB(128,0,128)},
 -	{LPGENT("Teal"), RGB(0,128,128)},
 -	{LPGENT("Gray"), RGB(128,128,128)},
 -	{LPGENT("Silver"), RGB(192,192,192)},
 -	{LPGENT("Red"), RGB(255,0,0)},
 -	{LPGENT("Orange"), RGB(255,155,0)},
 -	{LPGENT("Lime"), RGB(0,255,0)},
 -	{LPGENT("Yellow"), RGB(255,255,0)},
 -	{LPGENT("Blue"), RGB(0,0,255)},
 -	{LPGENT("Fuchsia"), RGB(255,0,255)},
 -	{LPGENT("Aqua"), RGB(0,255,255)},
 -	{LPGENT("White"), RGB(255,255,255)}
 -};
 -
 -
 -TREEELEMENT *g_Stickies = NULL;
 -
 -
 -INT_PTR CALLBACK StickyNoteWndProc(HWND hdlg,UINT message,
 -								  WPARAM wParam,LPARAM lParam);
 -INT_PTR CALLBACK DlgProcViewNotes(HWND Dialog,UINT Message,WPARAM wParam,
 -								  LPARAM lParam);
 -void JustSaveNotes(void);
 -INT_PTR PluginMenuCommandAddNew(WPARAM w,LPARAM l);
 -INT_PTR PluginMenuCommandDeleteAll(WPARAM w,LPARAM l);
 -void GetTriggerTimeString(const ULARGE_INTEGER *When, char *s, UINT strSize, BOOL bUtc);
 -void OnListResize(HWND Dialog);
 -void UpdateGeomFromWnd(HWND Dialog, int *geom, int *colgeom, int nCols);
 -void FileTimeToTzLocalST(const FILETIME *lpUtc, SYSTEMTIME *tmLocal);
 -
 -
 -COLORREF GetCaptionColor(COLORREF bodyClr)
 -{
 -	const DWORD r = ((bodyClr & 0xff) * 4) / 5;
 -	const DWORD g = (((bodyClr & 0xff00) * 4) / 5) & 0xff00;
 -	const DWORD b = (((bodyClr & 0xff0000) * 4) / 5) & 0xff0000;
 -
 -	return (COLORREF)(r|g|b);
 -}
 -
 -
 -static void EnsureUniqueID(STICKYNOTE *TSN)
 -{
 -	TREEELEMENT *TTE;
 -
 -	if (!g_Stickies)
 -		return;
 -
 -try_next:
 -
 -	// check existing notes if id is in use
 -	TTE = g_Stickies;
 -	while (TTE)
 -	{
 -		if (((STICKYNOTE*)TTE->ptrdata)->ID.QuadPart == TSN->ID.QuadPart)
 -		{
 -			// id in use, try new (increases the ID/time stamp by 100 nanosecond steps until an unused time is found,
 -			// allthough it's very unlikely that there will be duplicated id's it's better to make 100% sure)
 -			TSN->ID.QuadPart++;
 -			goto try_next;
 -		}
 -
 -		TTE = (TREEELEMENT*)TTE->next;
 -	}
 -}
 -
 -
 -static void InitNoteTitle(STICKYNOTE *TSN)
 -{
 -	if (g_NoteTitleDate)
 -	{
 -		char TempStr[MAX_PATH];
 -		SYSTEMTIME tm;
 -		LCID lc = GetUserDefaultLCID();
 -
 -		TempStr[0] = 0;
 -
 -		memset(&tm, 0, sizeof(tm));
 -		FileTimeToTzLocalST((FILETIME*)&TSN->ID, &tm);
 -
 -		if ( GetDateFormat(lc, 0, &tm, GetDateFormatStr(), TempStr, MAX_PATH) )
 -		{
 -			// append time if requested
 -			if (g_NoteTitleTime)
 -			{
 -				int n = (int)strlen(TempStr);
 -				TempStr[n++] = ' ';
 -				TempStr[n] = 0;
 -
 -				GetTimeFormat(MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),0), 0, &tm, GetTimeFormatStr(), TempStr+n, MAX_PATH-n);
 -			}
 -
 -			TSN->title = _strdup(TempStr);
 -		}
 -	}
 -
 -	TSN->CustomTitle = FALSE;
 -}
 -
 -
 -static void InitStickyNoteLogFont(STICKYNOTEFONT *pCustomFont, LOGFONT *lf)
 -{
 -	if (!pCustomFont->size)
 -	{
 -		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);
 -	}
 -	else
 -	{
 -		lf->lfHeight = pCustomFont->size;
 -	}
 -
 -	_tcscpy(lf->lfFaceName, pCustomFont->szFace);
 -
 -	lf->lfWidth = lf->lfEscapement = lf->lfOrientation = 0;
 -	lf->lfWeight = pCustomFont->style & DBFONTF_BOLD ? FW_BOLD : FW_NORMAL;
 -	lf->lfItalic = (pCustomFont->style & DBFONTF_ITALIC) != 0;
 -	lf->lfUnderline = (pCustomFont->style & DBFONTF_UNDERLINE) != 0;
 -	lf->lfStrikeOut = (pCustomFont->style & DBFONTF_STRIKEOUT) != 0;
 -	lf->lfCharSet = pCustomFont->charset;
 -	lf->lfOutPrecision = OUT_DEFAULT_PRECIS;
 -	lf->lfClipPrecision = CLIP_DEFAULT_PRECIS;
 -	lf->lfQuality = DEFAULT_QUALITY;
 -	lf->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
 -}
 -
 -static BOOL CreateStickyNoteFont(STICKYNOTEFONT *pCustomFont, LOGFONT *plf)
 -{
 -	LOGFONT lf = {0};
 -
 -	if (!plf)
 -	{
 -		InitStickyNoteLogFont(pCustomFont, &lf);
 -		plf = &lf;
 -	}
 -
 -	if (pCustomFont->hFont)
 -		DeleteObject(pCustomFont->hFont);
 -
 -	pCustomFont->hFont = CreateFontIndirect(plf);
 -
 -	return pCustomFont->hFont != NULL;
 -}
 -
 -
 -STICKYNOTE* NewNoteEx(int Ax,int Ay,int Aw,int Ah,char *Data,ULARGE_INTEGER *ID,BOOL Visible,BOOL OnTop,int scrollV,COLORREF bgClr,COLORREF fgClr,char *Title,STICKYNOTEFONT *pCustomFont,BOOL bLoading)
 -{
 -	STICKYNOTE* TSN;
 -	WNDCLASSEX TWC = {0};
 -	WINDOWPLACEMENT TWP;
 -	DWORD L1,L2;
 -	SYSTEMTIME tm;
 -	char TempStr[MAX_PATH] = {0};
 -	char *TData;
 -
 -	const BOOL bIsStartup = Visible & 0x10000;
 -	Visible &= ~0x10000;
 -
 -	if (Data) TData = Data;	else TData = NULL;
 -
 -	if (!GetClassInfoEx(hmiranda, NOTE_WND_CLASS, &TWC))
 -	{
 -		TWC.style = CS_HREDRAW | CS_VREDRAW | CS_NOCLOSE;
 -		TWC.cbClsExtra = 0;
 -		TWC.cbWndExtra = 0;
 -		TWC.hInstance = hmiranda;
 -		TWC.hIcon = LoadIcon(0,IDI_APPLICATION);
 -		TWC.hCursor = LoadCursor(0,IDC_ARROW);
 -		TWC.hbrBackground = 0;
 -		TWC.lpszMenuName = 0;
 -		TWC.lpszClassName = NOTE_WND_CLASS;
 -		TWC.cbSize = sizeof(WNDCLASSEX);
 -		TWC.lpfnWndProc = (WNDPROC)StickyNoteWndProc;
 -		if (!RegisterClassEx(&TWC)) return NULL;
 -	}
 -
 -	if (!TData || Aw < 0 || Ah < 0)
 -	{
 -		TWP.length = sizeof(WINDOWPLACEMENT);
 -		GetWindowPlacement(GetDesktopWindow(),&TWP);
 -		Aw = g_NoteWidth; Ah = g_NoteHeight;
 -		Ax = ((TWP.rcNormalPosition.right - TWP.rcNormalPosition.left) / 2) - (Aw / 2);
 -		Ay = ((TWP.rcNormalPosition.bottom - TWP.rcNormalPosition.top) / 2) - (Ah / 2);
 -	}
 -
 -	TSN = (STICKYNOTE*)malloc(sizeof(STICKYNOTE));
 -
 -	if (ID)
 -	{
 -		TSN->ID = *ID;
 -	}
 -	else
 -	{
 -		GetSystemTime(&tm);
 -		SYSTEMTIMEtoFILETIME(&tm, (FILETIME*)&TSN->ID);
 -	}
 -
 -	EnsureUniqueID(TSN);
 -
 -	TreeAdd(&g_Stickies,TSN);
 -
 -	if (!TData)
 -	{
 -		TData = _strdup("");
 -		TSN->data = TData;
 -	}
 -	else
 -		TSN->data = TData;
 -
 -	// init note title (time-stamp)
 -	if (Title)
 -	{
 -		TSN->title = Title;
 -		TSN->CustomTitle = TRUE;
 -	}
 -	else
 -	{
 -		TSN->title = NULL;
 -		InitNoteTitle(TSN);
 -	}
 -
 -	TSN->Visible = Visible;
 -	TSN->OnTop = OnTop;
 -
 -	TSN->BgColor = bgClr;
 -	TSN->FgColor = fgClr;
 -
 -	TSN->pCustomFont = pCustomFont;
 -
 -	L1 = WS_EX_TOOLWINDOW;
 -	if (g_Transparency < 255) L1 |= WS_EX_LAYERED;
 -	if (OnTop) L1 |= WS_EX_TOPMOST;
 -
 -	L2 = WS_POPUP | WS_THICKFRAME | WS_CAPTION;
 -
 -	// NOTE: loaded note positions stem from GetWindowPlacement, which normally have a different coord space than
 -	//       CreateWindow/SetWindowPos, BUT since we now use WS_EX_TOOLWINDOW they use the same coord space so
 -	//       we don't have to worry about notes "drifting" between sessions
 -	TSN->SNHwnd = CreateWindowEx(L1, NOTE_WND_CLASS, _T("StickyNote"), L2, Ax,Ay,Aw,Ah, NULL, 0, hmiranda, TSN);
 -
 -	if (g_Transparency < 255)
 -		SetLayeredWindowAttributes(TSN->SNHwnd,0,(BYTE)g_Transparency,LWA_ALPHA);
 -
 -	// ensure that window is not placed off-screen (if previous session had different monitor count or resolution)
 -	// NOTE: SetWindowPlacement should do this, but it's extremly flakey
 -	if (Data)
 -	{
 -		if (!MonitorFromWindow(TSN->SNHwnd, MONITOR_DEFAULTTONULL) )
 -		{
 -			TWP.length = sizeof(WINDOWPLACEMENT);
 -			GetWindowPlacement(GetDesktopWindow(), &TWP);
 -
 -			if (Aw > 500) Aw = 500;
 -			if (Ay < TWP.rcNormalPosition.left+10 || Ax > TWP.rcNormalPosition.right-120)
 -				Ax = ((TWP.rcNormalPosition.right - TWP.rcNormalPosition.left) / 2) - (Aw / 2) + (rand() & 0x3f);
 -			if (Ay < TWP.rcNormalPosition.top+50 || Ay > TWP.rcNormalPosition.bottom-50)
 -				Ay = ((TWP.rcNormalPosition.bottom - TWP.rcNormalPosition.top) / 4) + (rand() & 0x1f);
 -
 -			SetWindowPos(TSN->SNHwnd, NULL, Ax, Ay, Aw, Ah, SWP_NOZORDER|SWP_NOACTIVATE);
 -		}
 -	}
 -
 -	if (Visible)
 -	{
 -		ShowWindow(TSN->SNHwnd, SW_SHOWNA);
 -
 -		// when loading notes (only at startup), place all non-top notes at the bottom so they don't cover other windows
 -		if (Data && !OnTop && bIsStartup)
 -			SetWindowPos(TSN->SNHwnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_ASYNCWINDOWPOS);
 -	}
 -
 -	if (scrollV)
 -	{
 -		SendMessage(TSN->REHwnd, EM_LINESCROLL, 0, scrollV);
 -	}
 -
 -	// make sure that any event triggered by init doesn't cause a meaningless save
 -	KillTimer(TSN->SNHwnd, 1025);
 -
 -	if (!bLoading)
 -	{
 -		NOTIFY_LIST();
 -	}
 -
 -	return TSN;
 -}
 -
 -STICKYNOTE* NewNote(int Ax,int Ay,int Aw,int Ah,char *Data,ULARGE_INTEGER *ID,BOOL Visible,BOOL OnTop,int scrollV)
 -{
 -	return NewNoteEx(Ax,Ay,Aw,Ah,Data,ID,Visible,OnTop,scrollV,0,0,NULL,NULL,FALSE);
 -}
 -
 -void LoadNotes(BOOL bIsStartup)
 -{
 -	int I;
 -	int NotesCount;
 -	WORD Size;
 -	char *Value = NULL, *TVal = NULL;
 -	char ValueName[32];
 -
 -	g_Stickies = NULL;
 -
 -	NotesCount = db_get_dw(0,MODULENAME,"NotesData",0);
 -
 -	for (I = 0; I < NotesCount; I++)
 -	{
 -		char *DelPos;
 -
 -		mir_snprintf(ValueName, SIZEOF(ValueName), "NotesData%d", I);
 -
 -		if (Value)
 -		{
 -			FreeSettingBlob(Size, Value);
 -			Value = NULL;
 -		}
 -
 -		Size = 65535; // does not get used
 -
 -		ReadSettingBlob(0, MODULENAME, ValueName, &Size, (void**)&Value);
 -
 -		if (!Size || !Value)
 -			continue; // the setting could not be read from DB -> skip
 -
 -		if (Value[0] == 'X')
 -		{
 -			// new eXtended/fleXible data format
 -
 -			STICKYNOTE note = {0};
 -			int i, rect[4];
 -			int scrollV = 0;
 -			STICKYNOTEFONT *pCustomFont = NULL;
 -			DWORD flags;
 -
 -			DelPos = strchr(Value+1,0x1B);
 -			if (DelPos)
 -				*DelPos = 0;
 -
 -			// id:x:y:w:h:flags
 -
 -			TVal = strchr(Value+1, ':');
 -			if (!TVal || (DelPos && TVal > DelPos))
 -				continue;
 -			*TVal++ = 0;
 -
 -			note.ID.QuadPart = _strtoui64(Value+1, NULL, 16);
 -
 -			for (i=0; i<4; i++)
 -			{
 -				char *sep = strchr(TVal, ':');
 -				if (!sep || (DelPos && sep > DelPos))
 -					goto skip;
 -				*sep++ = 0;
 -
 -				rect[i] = strtol(TVal, NULL, 10);
 -
 -				TVal = sep;
 -			}
 -
 -			flags = strtoul(TVal, NULL, 16);
 -
 -			if (flags & 1)
 -				note.Visible = TRUE;
 -			if (flags & 2)
 -				note.OnTop = TRUE;
 -
 -			// optional \033 separated params
 -			while (DelPos)
 -			{
 -				char *sep;
 -				UINT tag;
 -
 -				TVal = DelPos + 1;
 -				// find param end and make sure it's null-terminated (if end of data then it's already null-terminated)
 -				DelPos = strchr(TVal, 0x1B);
 -				if (DelPos)
 -					*DelPos = 0;
 -
 -				// tag:<data>
 -
 -				sep = strchr(TVal, ':');
 -				if (!sep || (DelPos && sep > DelPos))
 -					goto skip;
 -
 -				tag = strtoul(TVal, NULL, 10);
 -				TVal = sep + 1;
 -
 -				switch (tag)
 -				{
 -				case DATATAG_TEXT:
 -					note.data = _strdup(TVal);
 -					break;
 -
 -				case DATATAG_SCROLLPOS:
 -					scrollV = (int)strtoul(TVal, NULL, 10);
 -					break;
 -
 -				case DATATAG_BGCOL:
 -					note.BgColor = strtoul(TVal, NULL, 16) | 0xff000000;
 -					break;
 -
 -				case DATATAG_FGCOL:
 -					note.FgColor = strtoul(TVal, NULL, 16) | 0xff000000;
 -					break;
 -
 -				case DATATAG_TITLE:
 -					if (strlen(TVal) > MAX_TITLE_LEN)
 -						TVal[MAX_TITLE_LEN] = 0;
 -					note.title = _strdup(TVal);
 -					note.CustomTitle = TRUE;
 -					break;
 -
 -				case DATATAG_FONT:
 -					{
 -						int fsize;
 -						UINT fstyle, fcharset;
 -
 -						char *TVal2 = TVal;
 -						sep = strchr(TVal2, ':');
 -						if (!sep || (DelPos && sep > DelPos))
 -							goto skip;
 -						*sep++ = 0;
 -						fsize = strtol(TVal2, NULL, 10);
 -						TVal2 = sep;
 -
 -						sep = strchr(TVal2, ':');
 -						if (!sep || (DelPos && sep > DelPos))
 -							goto skip;
 -						*sep++ = 0;
 -						fstyle = strtoul(TVal2, NULL, 10);
 -						TVal2 = sep;
 -
 -						sep = strchr(TVal2, ':');
 -						if (!sep || (DelPos && sep > DelPos))
 -							goto skip;
 -						*sep++ = 0;
 -						fcharset = strtoul(TVal2, NULL, 10);
 -						TVal2 = sep;
 -
 -						if (TVal2 >= DelPos)
 -							goto skip;
 -
 -						pCustomFont = (STICKYNOTEFONT*)malloc(sizeof(STICKYNOTEFONT));
 -						pCustomFont->size = (char)fsize;
 -						pCustomFont->style = (BYTE)fstyle;
 -						pCustomFont->charset = (BYTE)fcharset;
 -						_tcscpy(pCustomFont->szFace, TVal2);
 -						pCustomFont->hFont = NULL;
 -
 -						if ( !CreateStickyNoteFont(pCustomFont, NULL) )
 -						{
 -							free(pCustomFont);
 -							pCustomFont = NULL;
 -						}
 -					}
 -					break;
 -				}
 -			}
 -
 -			if (!note.data)
 -				note.data = _strdup("");
 -
 -			note.Visible = note.Visible && (!bIsStartup || g_ShowNotesAtStart);
 -			if (bIsStartup)
 -				note.Visible |= 0x10000;
 -
 -			NewNoteEx(rect[0],rect[1],rect[2],rect[3],note.data,¬e.ID,note.Visible,note.OnTop,scrollV,note.BgColor,note.FgColor,note.title,pCustomFont,TRUE);
 -		}
 -		else
 -		{
 -			// old format (for DB backward compatibility)
 -
 -			int Tx,Ty,Tw,Th,TV,OT;
 -			BOOL V;
 -			char *Data,*ID;
 -			ULARGE_INTEGER newid;
 -
 -			OT = 1; TV = 1;
 -			Tx = 100; Ty = 100;
 -			Tw = 179; Th = 35;
 -			Data = NULL; ID = NULL;
 -
 -			if (DelPos = strchr(Value,0x1B))
 -			{	// get first delimiter
 -				int	PartLen = DelPos - TVal;
 -
 -				Data = NULL;
 -				ID = NULL;
 -				TVal = Value;
 -				DelPos[0] = 0x0;
 -				Tx = strtol(TVal, NULL, 10);
 -
 -				TVal = DelPos + 1;
 -				DelPos = strchr(TVal, 0x1B);
 -				if (!DelPos) continue; // setting is broken, do not crash
 -				DelPos[0] = 0x0;
 -				Ty = strtol(TVal, NULL, 10);
 -
 -				TVal = DelPos + 1;
 -				DelPos = strchr(TVal, 0x1B);
 -				if (!DelPos) continue; // setting is broken, do not crash
 -				DelPos[0] = 0x0;
 -				Tw = strtol(TVal, NULL, 10);
 -
 -				TVal = DelPos + 1;
 -				DelPos = strchr(TVal, 0x1B);
 -				if (!DelPos) continue; // setting is broken, do not crash
 -				DelPos[0] = 0x0;
 -				Th = strtol(TVal, NULL, 10);
 -
 -				TVal = DelPos + 1;
 -				DelPos = strchr(TVal, 0x1B);
 -				if (!DelPos) continue; // setting is broken, do not crash
 -				DelPos[0] = 0x0;
 -				TV = strtol(TVal, NULL, 10);
 -
 -				TVal = DelPos + 1;
 -				DelPos = strchr(TVal, 0x1B);
 -				if (!DelPos) continue; // setting is broken, do not crash
 -				DelPos[0] = 0x0;
 -				OT = strtol(TVal, NULL, 10);
 -
 -				TVal = DelPos + 1;
 -				DelPos = strchr(TVal, 0x1B);
 -				if (!DelPos) continue; // setting is broken, do not crash
 -				DelPos[0] = 0x0;
 -				Data = _strdup(TVal);
 -
 -				TVal = DelPos + 1;
 -				ID = TVal;
 -
 -				V = (BOOL)TV && (!bIsStartup || g_ShowNotesAtStart);
 -
 -				if (bIsStartup)
 -					V |= 0x10000;
 -
 -				// convert old ID format to new
 -				if ( strchr(ID, '-') )
 -				{
 -					// validate format (otherwise create new)
 -					if (strlen(ID) < 19 || ID[2] != '-' || ID[5] != '-' || ID[10] != ' ' || ID[13] != ':' || ID[16] != ':')
 -					{
 -						ID = NULL;
 -					}
 -					else
 -					{
 -						SYSTEMTIME tm;
 -
 -						ID[2] = ID[5] = ID[10] = ID[13] = ID[16] = 0;
 -
 -						memset(&tm, 0, sizeof(tm));
 -						tm.wDay = (WORD)strtoul(ID, NULL, 10);
 -						tm.wMonth = (WORD)strtoul(ID+3, NULL, 10);
 -						tm.wYear = (WORD)strtoul(ID+6, NULL, 10);
 -						tm.wHour = (WORD)strtoul(ID+11, NULL, 10);
 -						tm.wMinute = (WORD)strtoul(ID+14, NULL, 10);
 -						tm.wSecond = (WORD)strtoul(ID+17, NULL, 10);
 -
 -						SYSTEMTIMEtoFILETIME(&tm, (FILETIME*)&newid);
 -					}
 -				}
 -				else
 -				{
 -					ID = NULL;
 -				}
 -
 -				NewNoteEx(Tx,Ty,Tw,Th,Data,ID?&newid:NULL,V,(BOOL)OT,0,0,0,NULL,NULL,TRUE);
 -			}
 -		}
 -skip:;
 -	}
 -
 -	if (Value)
 -		FreeSettingBlob(Size, Value); // we do not leak on bad setting
 -
 -	NOTIFY_LIST();
 -}
 -
 -void CloseNotesList()
 -{
 -	if (ListNotesVisible)
 -	{
 -		DestroyWindow(LV);
 -		ListNotesVisible = FALSE;
 -	}
 -}
 -
 -static void PurgeNotesTree()
 -{
 -	STICKYNOTE *pt;
 -
 -	while (g_Stickies) // empty whole tree
 -	{
 -		pt = (STICKYNOTE*)g_Stickies->ptrdata;
 -		if (pt->SNHwnd) DestroyWindow(pt->SNHwnd);
 -		SAFE_FREE((void**)&pt->title);
 -		SAFE_FREE((void**)&pt->data);
 -		if (pt->pCustomFont)
 -		{
 -			DeleteObject(pt->pCustomFont->hFont);
 -			free(pt->pCustomFont);
 -		}
 -		TreeDelete(&g_Stickies,pt);
 -		SAFE_FREE((void**)&pt);
 -	}
 -	g_Stickies = NULL;
 -}
 -
 -void SaveNotes(void)
 -{
 -	JustSaveNotes();
 -	PurgeNotesTree();
 -}
 -
 -void PurgeNotes(void)
 -{
 -	int NotesCount, I;
 -	char ValueName[16];
 -
 -	NotesCount = db_get_dw(0,MODULENAME,"NotesData",0);
 -	for(I = 0; I < NotesCount; I++)
 -	{
 -		mir_snprintf(ValueName, SIZEOF(ValueName), "NotesData%d", I);
 -		db_unset(0,MODULENAME,ValueName);
 -	}
 -}
 -
 -void OnDeleteNote(HWND hdlg, STICKYNOTE *SN)
 -{
 -	if (MessageBox(hdlg, TranslateT("Are you sure you want to delete this note?"), TranslateT(SECTIONNAME), MB_OKCANCEL) == IDOK)
 -	{
 -		if (SN->SNHwnd)
 -			DestroyWindow(SN->SNHwnd);
 -		TreeDelete(&g_Stickies,SN);
 -		SAFE_FREE((void**)&SN->data);
 -		if (SN->pCustomFont)
 -		{
 -			DeleteObject(SN->pCustomFont->hFont);
 -			free(SN->pCustomFont);
 -		}
 -		SAFE_FREE((void**)&SN);
 -		JustSaveNotes();
 -		NOTIFY_LIST();
 -	}
 -}
 -
 -void DeleteNotes(void)
 -{
 -	PurgeNotes();
 -	db_set_dw(0, MODULENAME, "NotesData", 0);
 -	PurgeNotesTree();
 -	NOTIFY_LIST();
 -}
 -
 -void ShowHideNotes(void)
 -{
 -	BOOL Visible;
 -
 -	if (!g_Stickies)
 -		return;
 -
 -	// if some notes are hidden but others visible then first make all visible
 -	// only toggle vis state if all are hidden or all are visible
 -
 -	UINT nHideCount  = 0, nVisCount = 0;
 -	TREEELEMENT *TTE = g_Stickies;
 -	while (TTE)
 -	{
 -		if (((STICKYNOTE*)TTE->ptrdata)->Visible)
 -			nVisCount++;
 -		else
 -			nHideCount++;
 -
 -		TTE = (TREEELEMENT*)TTE->next;
 -	}
 -
 -	if (!nVisCount)
 -		Visible = TRUE;
 -	else if (!nHideCount)
 -		Visible = FALSE;
 -	else
 -		Visible = TRUE;
 -
 -	int bShow = Visible ? SW_SHOWNA : SW_HIDE;
 -
 -	TTE = g_Stickies;
 -	while (TTE)
 -	{
 -		STICKYNOTE *SN = (STICKYNOTE*)TTE->ptrdata;
 -
 -		if ((!Visible) != (!SN->Visible))
 -		{
 -			ShowWindow(SN->SNHwnd, bShow);
 -			SN->Visible = Visible;
 -		}
 -
 -		TTE = (TREEELEMENT*)TTE->next;
 -	}
 -
 -	JustSaveNotes();
 -}
 -
 -void BringAllNotesToFront(STICKYNOTE *pActive)
 -{
 -	TREEELEMENT *TTE;
 -
 -	if (!g_Stickies)
 -		return;
 -
 -	// NOTE: for some reason there are issues when bringing to top through hotkey while another app (like Explorer)
 -	//       is active, it refuses to move notes to top like it should with HWND_TOP. as a workaround still doesn't
 -	//       work 100% of the time, but at least more often, we first move not to top-most then for non-always-on-top
 -	//       notes we demote them back as a non top-most window
 -
 -	TTE = g_Stickies;
 -	while (TTE)
 -	{
 -		STICKYNOTE *SN = (STICKYNOTE*)TTE->ptrdata;
 -
 -		if (SN->Visible && pActive != SN)
 -		{
 -			SetWindowPos(SN->SNHwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
 -			if (!SN->OnTop)
 -				SetWindowPos(SN->SNHwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
 -		}
 -
 -		TTE = (TREEELEMENT*)TTE->next;
 -	}
 -
 -	if (pActive)
 -	{
 -		SetWindowPos(pActive->SNHwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
 -		if (!pActive->OnTop)
 -			SetWindowPos(pActive->SNHwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
 -	}
 -}
 -
 -static void JustSaveNotesEx(STICKYNOTE *pModified)
 -{
 -	// pModified optionally points to the modified note that invoked the JustSaveNotesEx call
 -
 -	TREEELEMENT *TTE;
 -	int I, NotesCount = TreeGetCount(g_Stickies);
 -	int n, l;
 -	char ValueName[32];
 -	WINDOWPLACEMENT wp;
 -	int TX,TY,TW,TH;
 -	DWORD flags;
 -	int SzT;
 -	int scrollV;
 -	char *tData, *Value;
 -
 -	const int OldNotesCount = db_get_dw(0, MODULENAME, "NotesData", 0);
 -
 -	db_set_dw(0, MODULENAME, "NotesData", NotesCount);
 -
 -	for (TTE = g_Stickies, I = 0; TTE; TTE = (TREEELEMENT*)TTE->next, I++)
 -	{
 -		STICKYNOTE *pNote = (STICKYNOTE*)TTE->ptrdata;
 -		BOOL bDeleteTData = TRUE;
 -		scrollV = 0;
 -		tData = NULL;
 -
 -		// window pos and size
 -		wp.length = sizeof(WINDOWPLACEMENT);
 -		GetWindowPlacement(pNote->SNHwnd, &wp);
 -		TX = wp.rcNormalPosition.left;
 -		TY = wp.rcNormalPosition.top;
 -		TW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
 -		TH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
 -
 -		// set flags
 -		flags = 0;
 -		if (pNote->Visible) flags |= 1;
 -		if (pNote->OnTop) flags |= 2;
 -
 -		// get note text
 -		SzT = SendMessage(pNote->REHwnd, WM_GETTEXTLENGTH, 0, 0);
 -		if (SzT) // TODO: change to support unicode and rtf, use EM_STREAMOUT
 -		{
 -			if (SzT > MAX_NOTE_LEN) SzT = MAX_NOTE_LEN; // we want to be far below the 64k limit
 -			tData = (char*)malloc(SzT+1);
 -			if (tData)
 -				SendMessage(pNote->REHwnd, WM_GETTEXT, SzT+1, (LPARAM)tData);
 -		}
 -
 -		if (pNote == pModified)
 -		{
 -			// update the data of the modified note
 -			if (pNote->data)
 -				free(pNote->data);
 -			pNote->data = tData ? tData : _strdup("");
 -			bDeleteTData = FALSE;
 -		}
 -
 -		if (!tData)
 -			// empty note
 -			SzT = 0;
 -		else
 -			// get current scroll position
 -			scrollV = SendMessage(pNote->REHwnd, EM_GETFIRSTVISIBLELINE, 0, 0);
 -
 -		//
 -
 -		Value = (char*)malloc(SzT + 512);
 -		if (!Value) {
 -			if (bDeleteTData)
 -				SAFE_FREE((void**)&tData);
 -			continue;
 -		}
 -
 -		n = 0;
 -
 -		// data header
 -		l = sprintf(Value, "X%I64x:%d:%d:%d:%d:%x", pNote->ID.QuadPart, TX, TY, TW, TH, flags); //!!!!!!!!!!!!
 -		if (l > 0) n += l;
 -
 -		// scroll pos
 -		if (scrollV > 0)
 -		{
 -			l = sprintf(Value+n, "\033""%u:%u", DATATAG_SCROLLPOS, (UINT)scrollV); //!!!!!!!!!!
 -			if (l > 0) n += l;
 -		}
 -
 -		// custom bg color
 -		if (pNote->BgColor)
 -		{
 -			l = sprintf(Value+n, "\033""%u:%x", DATATAG_BGCOL, (UINT)(pNote->BgColor&0xffffff)); //!!!!!!!!!!!!!
 -			if (l > 0) n += l;
 -		}
 -
 -		// custom fg color
 -		if (pNote->FgColor)
 -		{
 -			l = sprintf(Value+n, "\033""%u:%x", DATATAG_FGCOL, (UINT)(pNote->FgColor&0xffffff)); //!!!!!!!!!!!!!
 -			if (l > 0) n += l;
 -		}
 -
 -		if (pNote->pCustomFont)
 -		{
 -			l = sprintf(Value+n, "\033""%u:%d:%u:%u:%s", DATATAG_FONT,
 -				(int)pNote->pCustomFont->size, (UINT)pNote->pCustomFont->style, (UINT)pNote->pCustomFont->charset,
 -				pNote->pCustomFont->szFace); //!!!!!!!!!!!!!!!
 -			if (l > 0) n += l;
 -		}
 -
 -		// custom title
 -		if (pNote->CustomTitle && pNote->title)
 -		{
 -			l = sprintf(Value+n, "\033""%u:%s", DATATAG_TITLE, pNote->title); //!!!!!!!!!!!!!
 -			if (l > 0) n += l;
 -		}
 -
 -		// note text (ALWAYS PUT THIS PARAM LAST)
 -		if (tData)
 -		{
 -			l = sprintf(Value+n, "\033""%u:%s", DATATAG_TEXT, tData); //!!!!!!!!!!!!
 -			if (l > 0) n += l;
 -		}
 -
 -		// clamp data size to WORD (including null terminator)
 -		if (n >= 0xffff)
 -		{
 -			// huston, we have a problem, strip some reminder text
 -			n = 0xfffe;
 -			Value[0xffff] = 0;
 -		}
 -
 -		mir_snprintf(ValueName, SIZEOF(ValueName), "NotesData%d", NotesCount - I - 1); // we do not reverse notes in DB
 -
 -		db_set_blob(0, MODULENAME, ValueName, Value, n+1);
 -
 -		SAFE_FREE((void**)&Value);
 -		if (bDeleteTData)
 -			SAFE_FREE((void**)&tData);
 -
 -		// make no save is queued for the note
 -		if (pNote->SNHwnd)
 -			KillTimer(pNote->SNHwnd, 1025);
 -	}
 -
 -	// delete any left over DB note entries
 -	for(; I < OldNotesCount; I++)
 -	{
 -		mir_snprintf(ValueName, SIZEOF(ValueName), "NotesData%d", I);
 -		db_unset(0,MODULENAME,ValueName);
 -	}
 -
 -	NOTIFY_LIST();
 -}
 -
 -__inline void JustSaveNotes(void)
 -{
 -	JustSaveNotesEx(NULL);
 -}
 -
 -
 -/////////////////////////////////////////////////////////////////////
 -// Note Window
 -
 -static int FindMenuItem(HMENU h, LPTSTR lpszName)
 -{
 -	UINT i;
 -	TCHAR s[128];
 -
 -	int n = GetMenuItemCount(h);
 -
 -	if (n <= 0)
 -	{
 -		return -1;
 -	}
 -
 -	// searches for a menu item based on name (used to avoid hardcoding item indices for sub-menus)
 -	for (i=0; i<(UINT)n; i++)
 -	{
 -		if ( GetMenuString(h, i, s, 128, MF_BYPOSITION) )
 -		{
 -			if ( !_tcscmp(s, lpszName) )
 -			{
 -				return (int)i;
 -			}
 -		}
 -	}
 -
 -	return -1;
 -}
 -
 -static BOOL DoContextMenu(HWND AhWnd,WPARAM wParam,LPARAM lParam)
 -{
 -	int n, i;
 -	STICKYNOTE *SN = (STICKYNOTE*)GetProp(AhWnd, _T("ctrldata"));
 -
 -	HMENU hMenuLoad, FhMenu, hSub;
 -	hMenuLoad = LoadMenu(hinstance, _T("MNU_NOTEPOPUP"));
 -	FhMenu = GetSubMenu(hMenuLoad,0);
 -
 -	if (SN->OnTop)
 -		CheckMenuItem(FhMenu, IDM_TOGGLEONTOP, MF_CHECKED|MF_BYCOMMAND);
 -
 -	EnableMenuItem(FhMenu, ID_CONTEXTMENUNOTEPOPUP_PASTETITLE, MF_BYCOMMAND | (IsClipboardFormatAvailable(CF_TEXT) ? MF_ENABLED : MF_GRAYED));
 -
 -	if (!SN->CustomTitle)
 -		EnableMenuItem(FhMenu, ID_CONTEXTMENUNOTEPOPUP_RESETTITLE, MF_BYCOMMAND | MF_GRAYED);
 -
 -	// NOTE: names used for FindMenuItem would need to include & chars if such shortcuts are added to the menus
 -
 -	n = FindMenuItem(FhMenu, _T("Appearance"));
 -	if (n >= 0 && (hSub = GetSubMenu(FhMenu, n)))
 -	{
 -		HMENU hBg = GetSubMenu(hSub, FindMenuItem(hSub, _T("Background Color")));
 -		HMENU hFg = GetSubMenu(hSub, FindMenuItem(hSub, _T("Text Color")));
 -
 -		for (i=0; i<SIZEOF(clrPresets); i++)
 -			InsertMenu(hBg, i, MF_BYPOSITION|MF_OWNERDRAW, IDM_COLORPRESET_BG+i, TranslateTS(clrPresets[i].szName));
 -
 -		for (i=0; i<SIZEOF(clrPresets); i++)
 -			InsertMenu(hFg, i, MF_BYPOSITION|MF_OWNERDRAW, IDM_COLORPRESET_FG+i, TranslateTS(clrPresets[i].szName));
 -	}
 -
 -    CallService(MS_LANGPACK_TRANSLATEMENU,(DWORD)FhMenu,0);
 -	TrackPopupMenu(FhMenu,TPM_LEFTALIGN | TPM_RIGHTBUTTON,LOWORD(lParam),HIWORD(lParam),0,AhWnd,0);
 -	DestroyMenu(hMenuLoad);
 -
 -	return TRUE;
 -}
 -
 -static void MeasureColorPresetMenuItem(HWND hdlg, LPMEASUREITEMSTRUCT lpMeasureItem, struct ColorPreset *clrPresets)
 -{
 -	HDC hdc = GetDC(hdlg);
 -	LPTSTR lpsz = TranslateTS(clrPresets->szName);
 -	SIZE sz;
 -	GetTextExtentPoint32(hdc, lpsz, (int)_tcslen(lpsz), &sz);
 -	ReleaseDC(hdlg, hdc);
 -
 -	lpMeasureItem->itemWidth = 50 + sz.cx;
 -	lpMeasureItem->itemHeight = (sz.cy+2)>18 ? sz.cy+2 : 18;
 -}
 -
 -static void PaintColorPresetMenuItem(LPDRAWITEMSTRUCT lpDrawItem, struct ColorPreset *clrPresets)
 -{
 -	UINT n = lpDrawItem->itemID - IDM_COLORPRESET_BG;
 -	RECT rect;
 -	rect.left = lpDrawItem->rcItem.left + 50;
 -	rect.top = lpDrawItem->rcItem.top;
 -	rect.right = lpDrawItem->rcItem.right;
 -	rect.bottom = lpDrawItem->rcItem.bottom;
 -
 -	if (lpDrawItem->itemState & ODS_SELECTED)
 -	{
 -		SetDCBrushColor(lpDrawItem->hDC, GetSysColor(COLOR_MENUHILIGHT));
 -		FillRect(lpDrawItem->hDC, &lpDrawItem->rcItem, (HBRUSH)GetStockObject(DC_BRUSH));
 -
 -		SetTextColor(lpDrawItem->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
 -	}
 -	else
 -	{
 -		SetDCBrushColor(lpDrawItem->hDC, GetSysColor(COLOR_MENU));
 -		FillRect(lpDrawItem->hDC, &lpDrawItem->rcItem, (HBRUSH)GetStockObject(DC_BRUSH));
 -
 -		SetTextColor(lpDrawItem->hDC, GetSysColor(COLOR_MENUTEXT));
 -	}
 -
 -	SetBkMode(lpDrawItem->hDC, TRANSPARENT);
 -	DrawText(lpDrawItem->hDC,clrPresets->szName,-1,&rect,DT_LEFT | DT_SINGLELINE | DT_END_ELLIPSIS | DT_VCENTER);
 -
 -	{
 -		int h = lpDrawItem->rcItem.bottom - lpDrawItem->rcItem.top;
 -		rect.left = lpDrawItem->rcItem.left + 5;
 -		rect.top = lpDrawItem->rcItem.top + ((h-14)>>1);
 -		rect.right = rect.left + 40;
 -		rect.bottom = rect.top + 14;
 -
 -		FrameRect(lpDrawItem->hDC, &rect, (HBRUSH)GetStockObject(BLACK_BRUSH));
 -		rect.left++; rect.top++;
 -		rect.right--; rect.bottom--;
 -		SetDCBrushColor(lpDrawItem->hDC, clrPresets->color);
 -		FillRect(lpDrawItem->hDC, &rect, (HBRUSH)GetStockObject(DC_BRUSH));
 -	}
 -}
 -
 -static BOOL GetClipboardText_Title(char *pOut, int size)
 -{
 -	BOOL bResult = FALSE;
 -
 -	if ( OpenClipboard(NULL) )
 -	{
 -		HANDLE hData = GetClipboardData(CF_TEXT);
 -		LPCSTR buffer;
 -
 -		if (hData && (buffer = (LPCSTR)GlobalLock(hData)))
 -		{
 -			// trim initial white spaces
 -			while (*buffer && isspace(*buffer))
 -				buffer++;
 -
 -			if (buffer)
 -			{
 -				char *p;
 -
 -				int n = (int)strlen(buffer);
 -				if (n >= size)
 -					n = size-1;
 -				memcpy(pOut, buffer, n);
 -				pOut[n] = 0;
 -
 -				// end string on line break and convert tabs to spaces
 -				p = pOut;
 -				while (*p)
 -				{
 -					if (*p == '\r' || *p == '\n')
 -					{
 -						*p = 0;
 -						n = (int)strlen(pOut);
 -						break;
 -					}
 -					else if (*p == '\t')
 -					{
 -						*p = ' ';
 -					}
 -					p++;
 -				}
 -
 -				// trim trailing white spaces
 -				while  (n && isspace(pOut[n-1]))
 -					pOut[--n] = 0;
 -
 -				if (n)
 -					bResult = TRUE;
 -			}
 -
 -			GlobalUnlock(hData);
 -		}
 -
 -		CloseClipboard();
 -	}
 -
 -	return bResult;
 -}
 -
 -static void SetNoteTextControl(STICKYNOTE *SN)
 -{
 -    CHARFORMAT CF = {0};
 -	CF.cbSize = sizeof(CHARFORMAT);
 -	CF.dwMask = CFM_COLOR;
 -	CF.crTextColor = SN->FgColor ? (SN->FgColor&0xffffff) : BodyFontColor;
 -	SendMessage(SN->REHwnd, EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&CF);
 -
 -	if (SN->data) // TODO: use EM_STREAMIN
 -		SendMessage(SN->REHwnd, WM_SETTEXT, 0, (LPARAM)(SN->data));
 -}
 -
 -
 -static UINT_PTR CALLBACK CFHookProc(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam)
 -{
 -	if (msg == WM_INITDIALOG)
 -	{
 -		// hide color selector
 -		ShowWindow(GetDlgItem(hdlg,0x443), SW_HIDE);
 -		ShowWindow(GetDlgItem(hdlg,0x473), SW_HIDE);
 -		TranslateDialogDefault(hdlg);
 -	}
 -
 -	return 0;
 -}
 -
 -
 -INT_PTR CALLBACK StickyNoteWndProc(HWND hdlg,UINT message,WPARAM wParam,LPARAM lParam)
 -{
 -	switch (message)
 -	{
 -	case WM_CLOSE:
 -		return TRUE;
 -
 -	case WM_SIZE:
 -		{
 -			RECT SZ;
 -
 -			GetClientRect(hdlg,&SZ);
 -			HWND H = GetDlgItem(hdlg,1);
 -			MoveWindow(H, 0, 0, SZ.right,SZ.bottom, TRUE);
 -
 -			KillTimer(hdlg, 1025);
 -			SetTimer(hdlg, 1025, NOTE_CHANGE_COMMIT_DELAY, 0);
 -
 -			return TRUE;
 -		}
 -    case WM_TIMER:
 -		if (wParam == 1025)
 -		{
 -			STICKYNOTE *SN = (STICKYNOTE*)GetProp(hdlg,_T("ctrldata"));
 -
 -			KillTimer(hdlg, 1025);
 -			JustSaveNotesEx(SN);
 -		}
 -		break;
 -    case WM_MOVE:
 -		{
 -			KillTimer(hdlg, 1025);
 -			SetTimer(hdlg, 1025, NOTE_CHANGE_COMMIT_DELAY, 0);
 -			return TRUE;
 -		}
 -    case WM_CREATE:
 -		{
 -			STICKYNOTE *SN = (STICKYNOTE*)GetProp(hdlg,_T("ctrldata"));
 -
 -			CREATESTRUCT *CS = (CREATESTRUCT *)lParam;
 -			HWND H;
 -			DWORD mystyle;
 -
 -			SN = (STICKYNOTE*)CS->lpCreateParams;
 -			SetProp(hdlg,_T("ctrldata"),(HANDLE)SN);
 -			BringWindowToTop(hdlg);
 -			mystyle = WS_CHILD | WS_VISIBLE | ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL | ES_WANTRETURN;
 -			if (g_ShowScrollbar) mystyle |= WS_VSCROLL;
 -			H = CreateWindow(RICHEDIT_CLASS, 0, mystyle, 0, 0, CS->cx-3-3, CS->cy-3-(3+14), hdlg, (HMENU)1, hmiranda, 0);
 -			SN->REHwnd = H;
 -			SendMessage(H, EM_SETTEXTMODE, TM_PLAINTEXT, 0);
 -			SendMessage(H, EM_LIMITTEXT, MAX_NOTE_LEN, 0);
 -			SendMessage(H, WM_SETFONT, (WPARAM)(SN->pCustomFont ? SN->pCustomFont->hFont : hBodyFont), 1);
 -			SendMessage(H, EM_SETEVENTMASK, 0, ENM_CHANGE | ENM_LINK);
 -			SendMessage(H, EM_SETBKGNDCOLOR, 0, SN->BgColor ? (SN->BgColor&0xffffff) : BodyColor);
 -			SendMessage(H, EM_AUTOURLDETECT, 1, 0);
 -			SetNoteTextControl(SN);
 -			return TRUE;
 -		}
 -	case WM_GETMINMAXINFO:
 -		{
 -			MINMAXINFO *mm = (MINMAXINFO*)lParam;
 -			// min width accomodates frame, buttons and some extra space for sanity
 -			mm->ptMinTrackSize.x = 48+3+3+8 + 40;
 -			// min height allows collapsing entire client area, only leaving frame and caption
 -			mm->ptMinTrackSize.y = 3+3+14;
 -		}
 -		return 0;
 -	case WM_ERASEBKGND:
 -		// no BG needed as edit control takes up entire client area
 -		return TRUE;
 -	case WM_NCPAINT:
 -		// make window borders have the same color as caption
 -		{
 -			STICKYNOTE *SN = (STICKYNOTE*)GetProp(hdlg,"ctrldata");
 -
 -			HBRUSH hBkBrush;
 -			RECT rect, wr, r;
 -			//HDC hdc = GetDCEx(hdlg, (HRGN)wParam, DCX_WINDOW|DCX_INTERSECTRGN);
 -			HDC hdc = GetWindowDC(hdlg);
 -
 -			GetWindowRect(hdlg, &wr);
 -			if (wParam && wParam != 1)
 -			{
 -				SelectClipRgn(hdc, (HRGN)wParam);
 -				OffsetClipRgn(hdc, -wr.left, -wr.top);
 -			}
 -
 -			rect = wr;
 -			OffsetRect(&rect, -wr.left, -wr.top);
 -
 -			hBkBrush = (HBRUSH)GetStockObject(DC_BRUSH);
 -			SetDCBrushColor(hdc, GetCaptionColor((SN && SN->BgColor) ? SN->BgColor : BodyColor));
 -
 -			// draw all frame sides separately to avoid filling client area (which flickers)
 -			{
 -			// top
 -			r.left = rect.left; r.right = rect.right;
 -			r.top = rect.top; r.bottom = r.top + 3+14;
 -			FillRect(hdc, &r, hBkBrush);
 -			// bottom
 -			r.top = rect.bottom - 3; r.bottom = rect.bottom;
 -			FillRect(hdc, &r, hBkBrush);
 -			// left
 -			r.left = rect.left; r.right = r.left + 3;
 -			r.top = rect.top + 3+14; r.bottom = rect.bottom - 3;
 -			FillRect(hdc, &r, hBkBrush);
 -			// right
 -			r.left = rect.right - 3; r.right = rect.right;
 -			FillRect(hdc, &r, hBkBrush);
 -			}
 -
 -			// paint title bar contents (time stamp and buttons)
 -
 -			if (SN && SN->title)
 -			{
 -				RECT R;
 -				SelectObject(hdc,hCaptionFont);
 -				R.top = 3+1; R.bottom = 3+11; R.left = 3+2; R.right = rect.right-3-1;
 -				if (g_ShowNoteButtons)
 -					R.right -= 48;
 -
 -				SetTextColor(hdc,SN->FgColor ? (SN->FgColor&0xffffff) : CaptionFontColor);
 -				SetBkMode(hdc, TRANSPARENT);
 -				DrawText(hdc,SN->title,-1,&R,DT_LEFT | DT_SINGLELINE | DT_END_ELLIPSIS | DT_VCENTER);
 -			}
 -
 -			if (g_ShowNoteButtons)
 -			{
 -				HICON hcIcon;
 -				if (SN->OnTop)
 -					hcIcon = Skin_GetIconByHandle(iconList[4].hIcolib);
 -				else
 -					hcIcon = Skin_GetIconByHandle(iconList[7].hIcolib);
 -				DrawIcon(hdc, wr.right - wr.left - 16, 0 + 3, hcIcon);
 -				Skin_ReleaseIcon(hcIcon);
 -
 -				hcIcon = Skin_GetIconByHandle(iconList[9].hIcolib);
 -				DrawIcon(hdc, wr.right - wr.left - 32, 1 + 3, hcIcon);
 -				Skin_ReleaseIcon(hcIcon);
 -
 -				hcIcon = Skin_GetIconByHandle(iconList[8].hIcolib);
 -				DrawIcon(hdc, wr.right - wr.left - 48, 1 + 3, hcIcon);
 -				Skin_ReleaseIcon(hcIcon);
 -			}
 -
 -			if (wParam && wParam != 1)
 -			{
 -				SelectClipRgn(hdc, NULL);
 -			}
 -
 -			ReleaseDC(hdlg, hdc);
 -			return TRUE;
 -		}
 -	case WM_NCCALCSIZE:
 -		{
 -			RECT *pRect = wParam ? &((NCCALCSIZE_PARAMS*)lParam)->rgrc[0] : (RECT*)lParam;
 -			pRect->bottom -= 3;
 -			pRect->right -= 3;
 -			pRect->left += 3;
 -			pRect->top += 3+14;
 -			return WVR_REDRAW;
 -		}
 -	case WM_NCACTIVATE:
 -		// update window (so that parts that potentially became visible through activation get redrawn immediately)
 -		RedrawWindow(hdlg, NULL, NULL, RDW_UPDATENOW);
 -		return TRUE;
 -    case WM_NOTIFY:
 -        if (LOWORD(wParam) == 1)
 -		{
 -		    char *Buff;
 -			PENLINK PEnLnk = (PENLINK)lParam;
 -
 -			if (PEnLnk->msg == WM_LBUTTONDOWN)
 -			{
 -				SendDlgItemMessage(hdlg,1,EM_EXSETSEL,0,(LPARAM)&(PEnLnk->chrg));
 -				Buff = (char*)malloc(PEnLnk->chrg.cpMax - PEnLnk->chrg.cpMin + 1);
 -				SendDlgItemMessage(hdlg,1,EM_GETSELTEXT,0,(LPARAM)Buff);
 -				if ((GetAsyncKeyState(VK_CONTROL) >> 15) != 0)
 -					ShellExecute(hdlg, _T("open"), _T("iexplore"), Buff, _T("") ,SW_SHOWNORMAL);
 -				else if (g_lpszAltBrowser && *g_lpszAltBrowser)
 -					ShellExecute(hdlg,_T("open"), g_lpszAltBrowser, Buff, _T("") ,SW_SHOWNORMAL);
 -				else
 -					ShellExecute(hdlg, _T("open"), Buff, _T(""), _T(""), SW_SHOWNORMAL);
 -				SAFE_FREE((void**)&Buff);
 -				return TRUE;
 -			}
 -			return FALSE;
 -        }
 -		break;
 -	case WM_NCHITTEST:
 -		{
 -		int r = DefWindowProc(hdlg,message,wParam,lParam);
 -		// filter out potential hits on windows default title bar buttons
 -		switch (r)
 -		{
 -		case HTSYSMENU:
 -		case HTCLOSE:
 -		case HTMINBUTTON:
 -		case HTMAXBUTTON:
 -			return HTCAPTION;
 -		}
 -		return r;
 -		}
 -	case WM_NCLBUTTONDOWN:
 -		if (wParam == HTCAPTION && g_ShowNoteButtons)
 -		{
 -			long X,Y;
 -			RECT rect;
 -			int Tw;
 -
 -			GetWindowRect(hdlg, &rect);
 -			Tw = rect.right - rect.left;
 -
 -			X = LOWORD(lParam) - rect.left;
 -			Y = HIWORD(lParam) - rect.top;
 -
 -			if (X > Tw - 16)
 -			{
 -				SendMessage(hdlg,WM_COMMAND,IDM_TOGGLEONTOP,0);
 -				return TRUE;
 -			}
 -			else if (X > Tw - 31 && X < Tw - 16)
 -			{
 -				SendMessage(hdlg,WM_COMMAND,IDM_REMOVENOTE,0);
 -				return TRUE;
 -			}
 -			else if (X > Tw - 48 && X < Tw - 32)
 -			{
 -				SendMessage(hdlg,WM_COMMAND,IDM_HIDENOTE,0);
 -				return TRUE;
 -			}
 -		}
 -		return DefWindowProc(hdlg,message,wParam,lParam);
 -	case WM_MEASUREITEM:
 -		{
 -			LPMEASUREITEMSTRUCT lpMeasureItem = (LPMEASUREITEMSTRUCT)lParam;
 -
 -			if (lpMeasureItem->CtlType != ODT_MENU)
 -				break;
 -
 -			if (lpMeasureItem->itemID >= IDM_COLORPRESET_BG && lpMeasureItem->itemID <= IDM_COLORPRESET_BG+SIZEOF(clrPresets))
 -			{
 -				MeasureColorPresetMenuItem(hdlg, lpMeasureItem, clrPresets + (lpMeasureItem->itemID - IDM_COLORPRESET_BG));
 -				return TRUE;
 -			}
 -			else if (lpMeasureItem->itemID >= IDM_COLORPRESET_FG && lpMeasureItem->itemID <= IDM_COLORPRESET_FG+SIZEOF(clrPresets))
 -			{
 -				MeasureColorPresetMenuItem(hdlg, lpMeasureItem, clrPresets + (lpMeasureItem->itemID - IDM_COLORPRESET_FG));
 -				return TRUE;
 -			}
 -		}
 -		break;
 -	case WM_DRAWITEM:
 -		if (!wParam)
 -		{
 -			LPDRAWITEMSTRUCT lpDrawItem = (LPDRAWITEMSTRUCT)lParam;
 -
 -			if (lpDrawItem->CtlType != ODT_MENU)
 -				break;
 -
 -			if (lpDrawItem->itemID >= IDM_COLORPRESET_BG && lpDrawItem->itemID <= IDM_COLORPRESET_BG+SIZEOF(clrPresets))
 -			{
 -				PaintColorPresetMenuItem(lpDrawItem, clrPresets + (lpDrawItem->itemID - IDM_COLORPRESET_BG));
 -				return TRUE;
 -			}
 -			else if (lpDrawItem->itemID >= IDM_COLORPRESET_FG && lpDrawItem->itemID <= IDM_COLORPRESET_FG+SIZEOF(clrPresets))
 -			{
 -				PaintColorPresetMenuItem(lpDrawItem, clrPresets + (lpDrawItem->itemID - IDM_COLORPRESET_FG));
 -				return TRUE;
 -			}
 -		}
 -		break;
 -	case WM_COMMAND:
 -		{
 -			STICKYNOTE *SN = (STICKYNOTE*)GetProp(hdlg, _T("ctrldata"));
 -
 -			HWND H;
 -			UINT id;
 -
 -			switch ( HIWORD(wParam) )
 -			{
 -			case EN_CHANGE:
 -			case EN_VSCROLL:
 -			case EN_HSCROLL:
 -				{
 -					KillTimer(hdlg,1025);
 -					SetTimer(hdlg, 1025, NOTE_CHANGE_COMMIT_DELAY, 0);
 -				}
 -				break;
 -			}
 -
 -			id = (UINT) LOWORD(wParam);
 -
 -			H = SN->REHwnd;
 -
 -			if (id >= IDM_COLORPRESET_BG && id <= IDM_COLORPRESET_BG+SIZEOF(clrPresets))
 -			{
 -				SN->BgColor = clrPresets[id-IDM_COLORPRESET_BG].color | 0xff000000;
 -				SendMessage(H, EM_SETBKGNDCOLOR, 0, (LPARAM)(SN->BgColor&0xffffff));
 -				RedrawWindow(SN->SNHwnd, NULL, NULL, RDW_INVALIDATE|RDW_FRAME|RDW_UPDATENOW);
 -				JustSaveNotes();
 -				return FALSE;
 -			}
 -			else if (id >= IDM_COLORPRESET_FG && id <= IDM_COLORPRESET_FG+SIZEOF(clrPresets))
 -			{
 -				CHARFORMAT CF = {0};
 -				SN->FgColor = clrPresets[id-IDM_COLORPRESET_FG].color | 0xff000000;
 -				CF.cbSize = sizeof(CHARFORMAT);
 -				CF.dwMask = CFM_COLOR;
 -				CF.crTextColor = SN->FgColor & 0xffffff;
 -				SendMessage(H, EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&CF);
 -				RedrawWindow(SN->SNHwnd, NULL, NULL, RDW_INVALIDATE|RDW_FRAME|RDW_UPDATENOW);
 -				JustSaveNotes();
 -				return FALSE;
 -			}
 -
 -			switch (id)
 -			{
 -			case ID_CONTEXTMENUNOTEPOPUP_NEWNOTE:
 -				{
 -					PluginMenuCommandAddNew(0,0);
 -				}
 -				break;
 -			case ID_APPEARANCE_CUSTOMBG:
 -				{
 -					COLORREF custclr[16] = {0};
 -					CHOOSECOLOR cc = {0};
 -					COLORREF orgclr = SN->BgColor ? (COLORREF)(SN->BgColor&0xffffff) : (COLORREF)(BodyColor&0xffffff);
 -					cc.lStructSize = sizeof(cc);
 -					cc.hwndOwner = SN->SNHwnd;
 -					cc.rgbResult = orgclr;
 -					cc.Flags = CC_ANYCOLOR | CC_FULLOPEN | CC_RGBINIT | CC_SOLIDCOLOR;
 -					cc.lpCustColors = custclr;
 -
 -					if (ChooseColor(&cc) && cc.rgbResult != orgclr)
 -					{
 -						SN->BgColor = cc.rgbResult | 0xff000000;
 -						SendMessage(H, EM_SETBKGNDCOLOR, 0, (LPARAM)(SN->BgColor&0xffffff));
 -						RedrawWindow(SN->SNHwnd, NULL, NULL, RDW_INVALIDATE|RDW_FRAME|RDW_UPDATENOW);
 -						JustSaveNotes();
 -					}
 -				}
 -				break;
 -			case ID_APPEARANCE_CUSTOMTEXT:
 -				{
 -					COLORREF custclr[16] = {0};
 -					CHOOSECOLOR cc = {0};
 -					COLORREF orgclr = SN->FgColor ? (COLORREF)(SN->FgColor&0xffffff) : (COLORREF)(BodyFontColor&0xffffff);
 -					cc.lStructSize = sizeof(cc);
 -					cc.hwndOwner = SN->SNHwnd;
 -					cc.rgbResult = orgclr;
 -					cc.Flags = CC_ANYCOLOR | CC_FULLOPEN | CC_RGBINIT | CC_SOLIDCOLOR;
 -					cc.lpCustColors = custclr;
 -
 -					if (ChooseColor(&cc) && cc.rgbResult != orgclr)
 -					{
 -						CHARFORMAT CF = {0};
 -						SN->FgColor = cc.rgbResult | 0xff000000;
 -						CF.cbSize = sizeof(CHARFORMAT);
 -						CF.dwMask = CFM_COLOR;
 -						CF.crTextColor = SN->FgColor & 0xffffff;
 -						SendMessage(H, EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&CF);
 -						RedrawWindow(SN->SNHwnd, NULL, NULL, RDW_INVALIDATE|RDW_FRAME|RDW_UPDATENOW);
 -						JustSaveNotes();
 -					}
 -				}
 -				break;
 -			case ID_APPEARANCE_CUSTOMFONT:
 -				{
 -					CHOOSEFONT cf = {0};
 -					LOGFONT lf = {0};
 -
 -					if (SN->pCustomFont)
 -						InitStickyNoteLogFont(SN->pCustomFont, &lf);
 -					else
 -						LoadNRFont(NR_FONTID_BODY, &lf, NULL);
 -
 -					cf.lStructSize = sizeof(cf);
 -					cf.hwndOwner = SN->SNHwnd;
 -					cf.lpLogFont = &lf;
 -					cf.Flags = CF_EFFECTS | CF_FORCEFONTEXIST | CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS | CF_ENABLEHOOK;
 -					cf.lpfnHook = CFHookProc;
 -
 -					if ( ChooseFont(&cf) )
 -					{
 -						if (!SN->pCustomFont)
 -						{
 -							SN->pCustomFont = (STICKYNOTEFONT*)malloc(sizeof(STICKYNOTEFONT));
 -							SN->pCustomFont->hFont = NULL;
 -						}
 -
 -						SN->pCustomFont->size = (char)lf.lfHeight;
 -						SN->pCustomFont->style = (lf.lfWeight >= FW_BOLD ? DBFONTF_BOLD : 0) | (lf.lfItalic ? DBFONTF_ITALIC : 0) | (lf.lfUnderline ? DBFONTF_UNDERLINE : 0) | (lf.lfStrikeOut ? DBFONTF_STRIKEOUT : 0);
 -						SN->pCustomFont->charset = lf.lfCharSet;
 -						_tcscpy(SN->pCustomFont->szFace, lf.lfFaceName);
 -
 -						if ( !CreateStickyNoteFont(SN->pCustomFont, &lf) )
 -						{
 -							// failed
 -							free(SN->pCustomFont);
 -							SN->pCustomFont = NULL;
 -						}
 -
 -						// clear text first to force a reformatting w.r.t scrollbar
 -						SendMessage(H, WM_SETTEXT, 0, (LPARAM)"");
 -						SendMessage(H, WM_SETFONT, (WPARAM)(SN->pCustomFont ? SN->pCustomFont->hFont : hBodyFont), FALSE);
 -						SetNoteTextControl(SN);
 -						RedrawWindow(SN->SNHwnd, NULL, NULL, RDW_INVALIDATE|RDW_FRAME|RDW_UPDATENOW);
 -						JustSaveNotes();
 -					}
 -				}
 -				break;
 -			case ID_BACKGROUNDCOLOR_RESET:
 -				{
 -					SN->BgColor = 0;
 -					SendMessage(H, EM_SETBKGNDCOLOR, 0, (LPARAM)BodyColor);
 -					RedrawWindow(SN->SNHwnd, NULL, NULL, RDW_INVALIDATE|RDW_FRAME|RDW_UPDATENOW);
 -					JustSaveNotes();
 -				}
 -				break;
 -			case ID_TEXTCOLOR_RESET:
 -				{
 -					CHARFORMAT CF = {0};
 -					SN->FgColor = 0;
 -					CF.cbSize = sizeof(CHARFORMAT);
 -					CF.dwMask = CFM_COLOR;
 -					CF.crTextColor = BodyFontColor;
 -					SendMessage(H, EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&CF);
 -					RedrawWindow(SN->SNHwnd, NULL, NULL, RDW_INVALIDATE|RDW_FRAME|RDW_UPDATENOW);
 -					JustSaveNotes();
 -				}
 -				break;
 -			case ID_FONT_RESET:
 -				{
 -					if (SN->pCustomFont)
 -					{
 -						DeleteObject(SN->pCustomFont->hFont);
 -						free(SN->pCustomFont);
 -						SN->pCustomFont = NULL;
 -
 -						// clear text first to force a reformatting w.r.t scrollbar
 -						SendMessage(H, WM_SETTEXT, 0, (LPARAM)"");
 -						SendMessage(H, WM_SETFONT, (WPARAM)hBodyFont, FALSE);
 -						SetNoteTextControl(SN);
 -						RedrawWindow(SN->SNHwnd, NULL, NULL, RDW_INVALIDATE|RDW_FRAME|RDW_UPDATENOW);
 -						JustSaveNotes();
 -					}
 -				}
 -				break;
 -			case ID_CONTEXTMENUNOTEPOPUP_PASTETITLE:
 -				{
 -					char s[MAX_TITLE_LEN+1];
 -					if ( GetClipboardText_Title(s, sizeof(s)) )
 -					{
 -						if (SN->title)
 -							free(SN->title);
 -						SN->title = _strdup(s);
 -						SN->CustomTitle = TRUE;
 -						RedrawWindow(SN->SNHwnd, NULL, NULL, RDW_INVALIDATE|RDW_FRAME|RDW_UPDATENOW);
 -						JustSaveNotes();
 -					}
 -				}
 -				break;
 -			case ID_CONTEXTMENUNOTEPOPUP_RESETTITLE:
 -				if (SN->CustomTitle)
 -				{
 -					if (SN->title)
 -					{
 -						free(SN->title);
 -						SN->title = NULL;
 -					}
 -					InitNoteTitle(SN);
 -					RedrawWindow(SN->SNHwnd, NULL, NULL, RDW_INVALIDATE|RDW_FRAME|RDW_UPDATENOW);
 -					JustSaveNotes();
 -				}
 -				break;
 -			case IDM_REMOVENOTE:
 -				OnDeleteNote(hdlg, SN);
 -				break;
 -			case IDM_HIDENOTE:
 -				{
 -					SN->Visible = FALSE;
 -					ShowWindow(hdlg,SW_HIDE);
 -					JustSaveNotes();
 -				}
 -				break;
 -			case IDM_COPY: SendMessage(H,WM_COPY,0,0); break;
 -			case IDM_PASTE: SendMessage(H,WM_PASTE,0,0); break;
 -			case IDM_CUT: SendMessage(H,WM_CUT,0,0); break;
 -			case IDM_CLEAR: SendMessage(H,WM_CLEAR,0,0); break;
 -			case IDM_UNDO: SendMessage(H,WM_UNDO,0,0); break;
 -			case IDM_TOGGLEONTOP:
 -				{
 -					SN->OnTop = !SN->OnTop;
 -					SetWindowPos(hdlg, SN->OnTop ? HWND_TOPMOST : HWND_NOTOPMOST, 0,0,0,0, SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOSIZE);
 -					RedrawWindow(hdlg, NULL, NULL, RDW_FRAME|RDW_INVALIDATE|RDW_UPDATENOW);
 -					JustSaveNotes();
 -				}
 -				break;
 -			case ID_CONTEXTMENUNOTEPOPUP_VIEWNOTES:
 -				ListNotes();
 -				break;
 -			case ID_CONTEXTMENUNOTEPOPUP_BRINGALLTOTOP:
 -				BringAllNotesToFront(SN);
 -				break;
 -			}
 -			return TRUE;
 -		}
 -	case WM_NCDESTROY:
 -		{
 -			RemoveProp(hdlg, _T("ctrldata"));
 -		}
 -		break;
 -    case WM_CONTEXTMENU:
 -		if (DoContextMenu(hdlg,wParam,lParam)) return FALSE;
 -
 -	default:
 -		return DefWindowProc(hdlg,message,wParam,lParam);
 -	}
 -	return FALSE;
 -}
 -
 -
 -/////////////////////////////////////////////////////////////////////
 -// Notes List Dialog (uses same dialog template as reminder list)
 -
 -void ListNotes(void)
 -{
 -	if (!ListNotesVisible)
 -	{
 -		CreateDialog(hinstance, MAKEINTRESOURCE(IDD_LISTREMINDERS), 0, DlgProcViewNotes);
 -		ListNotesVisible = TRUE;
 -	}
 -	else
 -	{
 -		BringWindowToTop(LV);
 -	}
 -}
 -
 -static void EditNote(STICKYNOTE *SN)
 -{
 -	if (!SN)
 -		return;
 -
 -	if (!SN->Visible)
 -	{
 -		SN->Visible = TRUE;
 -		JustSaveNotes();
 -	}
 -
 -	SetWindowPos(SN->SNHwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
 -	if (!SN->OnTop)
 -		SetWindowPos(SN->SNHwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
 -
 -	SetFocus(SN->REHwnd);
 -}
 -
 -char* GetPreviewString(const char *lpsz)
 -{
 -	int l;
 -	char *p;
 -	const int MaxLen = 80;
 -	static char s[80+8];
 -
 -	if (!lpsz)
 -		return "";
 -
 -	// trim leading spaces
 -	while ( iswspace(*lpsz) )
 -		lpsz++;
 -
 -	l = (int)strlen(lpsz);
 -
 -	if (!l)
 -		return "";
 -
 -	if (l <= MaxLen)
 -	{
 -		strcpy(s, lpsz);
 -	}
 -	else
 -	{
 -		memcpy(s, lpsz, MaxLen);
 -		s[MaxLen] = '.';
 -		s[MaxLen+1] = '.';
 -		s[MaxLen+2] = '.';
 -		s[MaxLen+3] = 0;
 -	}
 -
 -	if (!s)
 -		return NULL;
 -
 -	// convert line breaks and tabs to spaces
 -
 -	p = s;
 -
 -	while (*p)
 -	{
 -		if ( iswspace(*p) )
 -			*p = ' ';
 -		p++;
 -	}
 -
 -	return s;
 -}
 -
 -static void InitListView(HWND AHLV)
 -{
 -	LV_ITEM lvTIt;
 -	int I;
 -    char *S;
 -	char S1[128];
 -	STICKYNOTE *pNote;
 -	TREEELEMENT *TTE;
 -
 -	char *V = Translate("Visible");
 -	char *T = Translate("Top");
 -
 -	ListView_SetHoverTime(AHLV,700);
 -	ListView_SetExtendedListViewStyle(AHLV,LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_TRACKSELECT);
 -	ListView_DeleteAllItems(AHLV);
 -
 -	I = 0;
 -	TTE = g_Stickies;
 -	while (TTE)
 -	{
 -		pNote = (STICKYNOTE*)TTE->ptrdata;
 -
 -		lvTIt.mask = LVIF_TEXT;
 -
 -		if (!pNote->CustomTitle || !pNote->title)
 -			GetTriggerTimeString(&pNote->ID, S1, sizeof(S1), TRUE);
 -
 -		lvTIt.iItem = I;
 -		lvTIt.iSubItem = 0;
 -		lvTIt.pszText = (pNote->CustomTitle && pNote->title) ? pNote->title : S1;
 -		lvTIt.cchTextMax = (int)strlen(S1);
 -		ListView_InsertItem(AHLV,&lvTIt);
 -
 -		if (pNote->Visible)
 -		{
 -			lvTIt.iItem = I;
 -			lvTIt.iSubItem = 1;
 -			lvTIt.pszText = V;
 -			lvTIt.cchTextMax = (int)strlen(lvTIt.pszText);
 -			ListView_SetItem(AHLV,&lvTIt);
 -		}
 -
 -		if (pNote->OnTop)
 -		{
 -			lvTIt.iItem = I;
 -			lvTIt.iSubItem = 2;
 -			lvTIt.pszText = T;
 -			lvTIt.cchTextMax = (int)strlen(lvTIt.pszText);
 -			ListView_SetItem(AHLV,&lvTIt);
 -		}
 -
 -		S = GetPreviewString(pNote->data);
 -		lvTIt.iItem = I;
 -		lvTIt.iSubItem = 3;
 -		lvTIt.pszText = S;
 -		lvTIt.cchTextMax = (int)strlen(S);
 -		ListView_SetItem(AHLV,&lvTIt);
 -
 -		I++;
 -		TTE = (TREEELEMENT*)TTE->next;
 -	}
 -
 -	ListView_SetItemState(AHLV,0,LVIS_SELECTED,LVIS_SELECTED);
 -}
 -
 -static BOOL DoListContextMenu(HWND AhWnd,WPARAM wParam,LPARAM lParam,STICKYNOTE *pNote)
 -{
 -	HWND hwndListView;
 -    HMENU hMenuLoad,FhMenu;
 -	MENUITEMINFO mii;
 -
 -	hwndListView = (HWND)wParam;
 -	if (hwndListView != GetDlgItem(AhWnd,IDC_LISTREMINDERS)) return FALSE;
 -	hMenuLoad = LoadMenu(hinstance,"MNU_NOTELISTPOPUP");
 -	FhMenu = GetSubMenu(hMenuLoad,0);
 -
 -	mii.cbSize = sizeof(mii);
 -	mii.fMask = MIIM_STATE;
 -	mii.fState = MFS_DEFAULT;
 -	if (!pNote)
 -		mii.fState |= MFS_GRAYED;
 -	SetMenuItemInfo(FhMenu, ID_CONTEXTMENUNOTELISTVIEW_EDITNOTE, FALSE, &mii);
 -
 -	if (!pNote)
 -	{
 -		EnableMenuItem(FhMenu, IDM_REMOVENOTE, MF_GRAYED|MF_BYCOMMAND);
 -		EnableMenuItem(FhMenu, ID_CONTEXTMENUNOTELISTVIEW_TOGGLEVISIBILITY, MF_GRAYED|MF_BYCOMMAND);
 -		EnableMenuItem(FhMenu, IDM_TOGGLEONTOP, MF_GRAYED|MF_BYCOMMAND);
 -	}
 -	else
 -	{
 -		if (pNote->Visible)
 -			CheckMenuItem(FhMenu, ID_CONTEXTMENUNOTELISTVIEW_TOGGLEVISIBILITY, MF_CHECKED|MF_BYCOMMAND);
 -		if (pNote->OnTop)
 -			CheckMenuItem(FhMenu, IDM_TOGGLEONTOP, MF_CHECKED|MF_BYCOMMAND);
 -	}
 -
 -    CallService(MS_LANGPACK_TRANSLATEMENU,(DWORD)FhMenu,0);
 -	TrackPopupMenu(FhMenu,TPM_LEFTALIGN | TPM_RIGHTBUTTON,LOWORD(lParam),HIWORD(lParam),0,AhWnd,0);
 -	DestroyMenu(hMenuLoad);
 -
 -	return TRUE;
 -}
 -
 -
 -INT_PTR CALLBACK DlgProcViewNotes(HWND Dialog,UINT Message,WPARAM wParam,LPARAM lParam)
 -{
 -    LV_COLUMN lvCol;
 -    NMLISTVIEW *NM;
 -    TCHAR *S;
 -    int I;
 -
 -	switch (Message)
 -	{
 -	case WM_SIZE:
 -		{
 -			OnListResize(Dialog);
 -			UpdateGeomFromWnd(Dialog, g_notesListGeom, NULL, 0);
 -			break;
 -		}
 -	case WM_MOVE:
 -		UpdateGeomFromWnd(Dialog, g_notesListGeom, NULL, 0);
 -		break;
 -	case WM_GETMINMAXINFO:
 -		{
 -			MINMAXINFO *mm = (MINMAXINFO*)lParam;
 -			mm->ptMinTrackSize.x = 394;
 -			mm->ptMinTrackSize.y = 300;
 -		}
 -		return 0;
 -	case WM_RELOAD:
 -		{
 -			SetDlgItemText(Dialog,IDC_REMINDERDATA,"");
 -			InitListView(GetDlgItem(Dialog,IDC_LISTREMINDERS));
 -			return TRUE;
 -		}
 -	case WM_CONTEXTMENU:
 -		{
 -			HWND H;
 -			STICKYNOTE *pNote = NULL;
 -
 -			H = GetDlgItem(Dialog,IDC_LISTREMINDERS);
 -			if ( ListView_GetSelectedCount(H) )
 -			{
 -				I = ListView_GetSelectionMark(H);
 -				if (I != -1)
 -				{
 -					pNote = (STICKYNOTE*)TreeGetAt(g_Stickies, I);
 -				}
 -			}
 -
 -			if (DoListContextMenu(Dialog, wParam, lParam, pNote))
 -				return TRUE;
 -		}
 -		break;
 -	case WM_INITDIALOG:
 -		{
 -			HWND H;
 -
 -			HICON hIcon = Skin_GetIconByHandle(iconList[13].hIcolib, ICON_SMALL);
 -			SendMessage(Dialog, WM_SETICON, (WPARAM)ICON_SMALL, (LPARAM)hIcon);
 -			hIcon = Skin_GetIconByHandle(iconList[13].hIcolib, ICON_BIG);
 -			SendMessage(Dialog, WM_SETICON, (WPARAM)ICON_BIG, (LPARAM)hIcon);
 -
 -			SetWindowText(Dialog, LPGENT("Notes"));
 -
 -			TranslateDialogDefault(Dialog);
 -
 -			SetDlgItemText(Dialog,IDC_REMINDERDATA, _T(""));
 -
 -			H = GetDlgItem(Dialog,IDC_LISTREMINDERS);
 -			lvCol.mask = LVCF_TEXT | LVCF_WIDTH;
 -
 -			S = TranslateT("Note text");
 -			lvCol.pszText = S;
 -			lvCol.cchTextMax = (int)_tcslen(S);
 -			lvCol.cx = g_notesListColGeom[3];
 -			ListView_InsertColumn(H,0,&lvCol);
 -			lvCol.mask = LVCF_TEXT | LVCF_WIDTH;
 -
 -			S = TranslateT("Top");
 -			lvCol.pszText = S;
 -			lvCol.cchTextMax = (int)_tcslen(S);
 -			lvCol.cx = g_notesListColGeom[2];
 -			ListView_InsertColumn(H,0,&lvCol);
 -			lvCol.mask = LVCF_TEXT | LVCF_WIDTH;
 -
 -			S = TranslateT("Visible");
 -			lvCol.pszText = S;
 -			lvCol.cchTextMax = (int)strlen(S);
 -			lvCol.cx = g_notesListColGeom[1];
 -			ListView_InsertColumn(H,0,&lvCol);
 -			lvCol.mask = LVCF_TEXT | LVCF_WIDTH;
 -
 -			S = TranslateT("Date/Title");
 -			lvCol.pszText = S;
 -			lvCol.cchTextMax = (int)_tcslen(S);
 -			lvCol.cx = g_notesListColGeom[0];
 -			ListView_InsertColumn(H,0,&lvCol);
 -
 -			InitListView(H);
 -			SetWindowLongPtr(GetDlgItem(H, 0), GWL_ID, IDC_LISTREMINDERS_HEADER);
 -			LV = Dialog;
 -
 -			if (g_notesListGeom[1] && g_notesListGeom[2])
 -			{
 -				WINDOWPLACEMENT wp;
 -				wp.length = sizeof(WINDOWPLACEMENT);
 -				GetWindowPlacement(Dialog, &wp);
 -				wp.rcNormalPosition.left = g_notesListGeom[0];
 -				wp.rcNormalPosition.top = g_notesListGeom[1];
 -				wp.rcNormalPosition.right = g_notesListGeom[2] + g_notesListGeom[0];
 -				wp.rcNormalPosition.bottom = g_notesListGeom[3] + g_notesListGeom[1];
 -				SetWindowPlacement(Dialog, &wp);
 -			}
 -			return TRUE;
 -		}
 -	case WM_CLOSE:
 -		DestroyWindow(Dialog);
 -		ListNotesVisible = FALSE;
 -		return TRUE;
 -
 -	case WM_DESTROY:
 -		ListNotesVisible = FALSE;
 -		Skin_ReleaseIcon((HICON)SendMessage(Dialog, WM_SETICON, ICON_BIG, 0));
 -		Skin_ReleaseIcon((HICON)SendMessage(Dialog, WM_SETICON, ICON_SMALL, 0));
 -		return TRUE;
 -
 -	case WM_NOTIFY:
 -		{
 -			if (wParam == IDC_LISTREMINDERS)
 -			{
 -				NM = (NMLISTVIEW *)lParam;
 -				switch (NM->hdr.code)
 -				{
 -				case LVN_ITEMCHANGED:
 -					{
 -						S = ((STICKYNOTE*)TreeGetAt(g_Stickies,NM->iItem))->data;
 -					    SetDlgItemText(Dialog,IDC_REMINDERDATA,S);
 -					}
 -					break;
 -				case NM_DBLCLK:
 -					{
 -						HWND H;
 -
 -						H = GetDlgItem(Dialog,IDC_LISTREMINDERS);
 -						if ( ListView_GetSelectedCount(H) )
 -						{
 -							I = ListView_GetSelectionMark(H);
 -							if (I != -1)
 -							{
 -								EditNote((STICKYNOTE *)TreeGetAt(g_Stickies, I));
 -							}
 -						}
 -					}
 -					break;
 -				}
 -			}
 -			else if (wParam == IDC_LISTREMINDERS_HEADER)
 -			{
 -				NMHEADER *NM = (NMHEADER*)lParam;
 -				switch (NM->hdr.code)
 -				{
 -				case HDN_ENDTRACK:
 -					UpdateGeomFromWnd(Dialog, NULL, g_notesListColGeom, SIZEOF(g_notesListColGeom));
 -					break;
 -				}
 -			}
 -		}
 -		break;
 -	case WM_COMMAND:
 -		{
 -			switch(LOWORD(wParam))
 -			{
 -			case ID_CONTEXTMENUNOTELISTVIEW_EDITNOTE:
 -				{
 -					HWND H;
 -
 -					H = GetDlgItem(Dialog,IDC_LISTREMINDERS);
 -					if ( ListView_GetSelectedCount(H) )
 -					{
 -						I = ListView_GetSelectionMark(H);
 -						if (I != -1)
 -						{
 -							EditNote((STICKYNOTE*)TreeGetAt(g_Stickies, I));
 -						}
 -					}
 -				}
 -				return TRUE;
 -			case ID_CONTEXTMENUNOTELISTVIEW_TOGGLEVISIBILITY:
 -				{
 -					HWND H;
 -
 -					H = GetDlgItem(Dialog,IDC_LISTREMINDERS);
 -					if ( ListView_GetSelectedCount(H) )
 -					{
 -						I = ListView_GetSelectionMark(H);
 -						if (I != -1)
 -						{
 -							STICKYNOTE *SN = (STICKYNOTE*)TreeGetAt(g_Stickies, I);
 -							SN->Visible = !SN->Visible;
 -							ShowWindow(SN->SNHwnd,SN->Visible?SW_SHOWNA:SW_HIDE);
 -							JustSaveNotes();
 -						}
 -					}
 -				}
 -				return TRUE;
 -			case IDM_TOGGLEONTOP:
 -				{
 -					HWND H;
 -
 -					H = GetDlgItem(Dialog,IDC_LISTREMINDERS);
 -					if ( ListView_GetSelectedCount(H) )
 -					{
 -						I = ListView_GetSelectionMark(H);
 -						if (I != -1)
 -						{
 -							STICKYNOTE *SN = (STICKYNOTE*)TreeGetAt(g_Stickies,I);
 -							SN->OnTop = !SN->OnTop;
 -							SetWindowPos(SN->SNHwnd, SN->OnTop ? HWND_TOPMOST : HWND_NOTOPMOST, 0,0,0,0, SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOSIZE);
 -							RedrawWindow(SN->SNHwnd, NULL, NULL, RDW_FRAME|RDW_INVALIDATE|RDW_UPDATENOW);
 -							JustSaveNotes();
 -						}
 -					}
 -				}
 -				return TRUE;
 -			case IDC_CLOSE:
 -				{
 -					DestroyWindow(Dialog);
 -					ListNotesVisible = FALSE;
 -					return TRUE;
 -				}
 -			case ID_CONTEXTMENUNOTEPOPUP_NEWNOTE:
 -			case IDC_ADDNEWREMINDER:
 -				{
 -					PluginMenuCommandAddNew(0,0);
 -					return TRUE;
 -				}
 -			case ID_CONTEXTMENUNOTELISTVIEW_DELETEALLNOTES:
 -				{
 -					PluginMenuCommandDeleteAll(0,0);
 -					return TRUE;
 -				}
 -			case IDM_REMOVENOTE:
 -				{
 -					HWND H;
 -
 -					H = GetDlgItem(Dialog,IDC_LISTREMINDERS);
 -					if ( ListView_GetSelectedCount(H) )
 -					{
 -						I = ListView_GetSelectionMark(H);
 -						if (I != -1)
 -						{
 -							OnDeleteNote(Dialog, (STICKYNOTE*)TreeGetAt(g_Stickies, I));
 -						}
 -					}
 -				}
 -				return TRUE;
 -			case ID_CONTEXTMENUNOTELISTVIEW_SHOW:
 -				{
 -					ShowHideNotes();
 -					return TRUE;
 -				}
 -			case ID_CONTEXTMENUNOTEPOPUP_BRINGALLTOTOP:
 -				{
 -					BringAllNotesToFront(NULL);
 -					return TRUE;
 -				}
 -			}
 -		}
 -	}
 -	return FALSE;
 -}
 +#include "globals.h" + +#ifndef MONITOR_DEFAULTTONULL +#define MONITOR_DEFAULTTONULL       0x00000000 +#endif + + +// NotesData DB data params +#define DATATAG_TEXT		1	// %s +#define DATATAG_SCROLLPOS	2	// %u (specifies rich edit controls scroll post as first visible line) +#define DATATAG_BGCOL		3	// %x (custom background color) +#define DATATAG_FGCOL		4	// %x (custom text/fg colors) +#define DATATAG_TITLE		5	// %s (custom note title) +#define DATATAG_FONT		6	// %d:%u:%u:%s (custom font) + + +#define MAX_TITLE_LEN	63 +#define MAX_NOTE_LEN	16384 + +// delay before saving note changes (ms) +#define NOTE_CHANGE_COMMIT_DELAY 1000 + + +#ifndef WS_EX_NOACTIVATE +#define WS_EX_NOACTIVATE 0x08000000 +#endif +#define IDM_REMOVENOTE 40001 +#define IDM_HIDENOTE 40002 +#define IDM_TOGGLEONTOP 40003 +#define IDM_UNDO 40004 +#define IDM_COPY 40005 +#define IDM_PASTE 40006 +#define IDM_CUT 40007 +#define IDM_CLEAR 40008 +#define WS_EX_LAYERED 0x00080000 +#define LWA_ALPHA 0x00000002 + +#define IDC_LISTREMINDERS 1000 +#define IDC_LISTREMINDERS_HEADER 2000 +#define IDC_REMINDERDATA 1001 +#define IDC_ADDNEWREMINDER 1002 +#define IDC_CLOSE 1003 +#define WM_RELOAD (WM_USER + 100) + +#define NOTIFY_LIST() if (ListNotesVisible) PostMessage(LV,WM_RELOAD,0,0) + +#define PENLINK ENLINK * + +#define NOTE_WND_CLASS _T("MIM_StickyNote") + + +#define IDM_COLORPRESET_BG 41000 +#define IDM_COLORPRESET_FG 41100 + + +static BOOL ListNotesVisible = FALSE; +static HWND LV; + + +struct ColorPreset +{ +	TCHAR *szName; +	COLORREF color; +}; + +static struct ColorPreset clrPresets[] = +{ +	{LPGENT("Black"), RGB(0,0,0)}, +	{LPGENT("Maroon"), RGB(128,0,0)}, +	{LPGENT("Green"), RGB(0,128,0)}, +	{LPGENT("Olive"), RGB(128,128,0)}, +	{LPGENT("Navy"), RGB(0,0,128)}, +	{LPGENT("Purple"), RGB(128,0,128)}, +	{LPGENT("Teal"), RGB(0,128,128)}, +	{LPGENT("Gray"), RGB(128,128,128)}, +	{LPGENT("Silver"), RGB(192,192,192)}, +	{LPGENT("Red"), RGB(255,0,0)}, +	{LPGENT("Orange"), RGB(255,155,0)}, +	{LPGENT("Lime"), RGB(0,255,0)}, +	{LPGENT("Yellow"), RGB(255,255,0)}, +	{LPGENT("Blue"), RGB(0,0,255)}, +	{LPGENT("Fuchsia"), RGB(255,0,255)}, +	{LPGENT("Aqua"), RGB(0,255,255)}, +	{LPGENT("White"), RGB(255,255,255)} +}; + + +TREEELEMENT *g_Stickies = NULL; + + +INT_PTR CALLBACK StickyNoteWndProc(HWND hdlg,UINT message, +								  WPARAM wParam,LPARAM lParam); +INT_PTR CALLBACK DlgProcViewNotes(HWND Dialog,UINT Message,WPARAM wParam, +								  LPARAM lParam); +void JustSaveNotes(void); +INT_PTR PluginMenuCommandAddNew(WPARAM w,LPARAM l); +INT_PTR PluginMenuCommandDeleteAll(WPARAM w,LPARAM l); +void GetTriggerTimeString(const ULARGE_INTEGER *When, char *s, UINT strSize, BOOL bUtc); +void OnListResize(HWND Dialog); +void UpdateGeomFromWnd(HWND Dialog, int *geom, int *colgeom, int nCols); +void FileTimeToTzLocalST(const FILETIME *lpUtc, SYSTEMTIME *tmLocal); + + +COLORREF GetCaptionColor(COLORREF bodyClr) +{ +	const DWORD r = ((bodyClr & 0xff) * 4) / 5; +	const DWORD g = (((bodyClr & 0xff00) * 4) / 5) & 0xff00; +	const DWORD b = (((bodyClr & 0xff0000) * 4) / 5) & 0xff0000; + +	return (COLORREF)(r|g|b); +} + + +static void EnsureUniqueID(STICKYNOTE *TSN) +{ +	TREEELEMENT *TTE; + +	if (!g_Stickies) +		return; + +try_next: + +	// check existing notes if id is in use +	TTE = g_Stickies; +	while (TTE) +	{ +		if (((STICKYNOTE*)TTE->ptrdata)->ID.QuadPart == TSN->ID.QuadPart) +		{ +			// id in use, try new (increases the ID/time stamp by 100 nanosecond steps until an unused time is found, +			// allthough it's very unlikely that there will be duplicated id's it's better to make 100% sure) +			TSN->ID.QuadPart++; +			goto try_next; +		} + +		TTE = (TREEELEMENT*)TTE->next; +	} +} + + +static void InitNoteTitle(STICKYNOTE *TSN) +{ +	if (g_NoteTitleDate) +	{ +		char TempStr[MAX_PATH]; +		SYSTEMTIME tm; +		LCID lc = GetUserDefaultLCID(); + +		TempStr[0] = 0; + +		memset(&tm, 0, sizeof(tm)); +		FileTimeToTzLocalST((FILETIME*)&TSN->ID, &tm); + +		if ( GetDateFormat(lc, 0, &tm, GetDateFormatStr(), TempStr, MAX_PATH) ) +		{ +			// append time if requested +			if (g_NoteTitleTime) +			{ +				int n = (int)strlen(TempStr); +				TempStr[n++] = ' '; +				TempStr[n] = 0; + +				GetTimeFormat(MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_ENGLISH_US),0), 0, &tm, GetTimeFormatStr(), TempStr+n, MAX_PATH-n); +			} + +			TSN->title = _strdup(TempStr); +		} +	} + +	TSN->CustomTitle = FALSE; +} + + +static void InitStickyNoteLogFont(STICKYNOTEFONT *pCustomFont, LOGFONT *lf) +{ +	if (!pCustomFont->size) +	{ +		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); +	} +	else +	{ +		lf->lfHeight = pCustomFont->size; +	} + +	_tcscpy(lf->lfFaceName, pCustomFont->szFace); + +	lf->lfWidth = lf->lfEscapement = lf->lfOrientation = 0; +	lf->lfWeight = pCustomFont->style & DBFONTF_BOLD ? FW_BOLD : FW_NORMAL; +	lf->lfItalic = (pCustomFont->style & DBFONTF_ITALIC) != 0; +	lf->lfUnderline = (pCustomFont->style & DBFONTF_UNDERLINE) != 0; +	lf->lfStrikeOut = (pCustomFont->style & DBFONTF_STRIKEOUT) != 0; +	lf->lfCharSet = pCustomFont->charset; +	lf->lfOutPrecision = OUT_DEFAULT_PRECIS; +	lf->lfClipPrecision = CLIP_DEFAULT_PRECIS; +	lf->lfQuality = DEFAULT_QUALITY; +	lf->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE; +} + +static BOOL CreateStickyNoteFont(STICKYNOTEFONT *pCustomFont, LOGFONT *plf) +{ +	LOGFONT lf = {0}; + +	if (!plf) +	{ +		InitStickyNoteLogFont(pCustomFont, &lf); +		plf = &lf; +	} + +	if (pCustomFont->hFont) +		DeleteObject(pCustomFont->hFont); + +	pCustomFont->hFont = CreateFontIndirect(plf); + +	return pCustomFont->hFont != NULL; +} + + +STICKYNOTE* NewNoteEx(int Ax,int Ay,int Aw,int Ah,char *Data,ULARGE_INTEGER *ID,BOOL Visible,BOOL OnTop,int scrollV,COLORREF bgClr,COLORREF fgClr,char *Title,STICKYNOTEFONT *pCustomFont,BOOL bLoading) +{ +	STICKYNOTE* TSN; +	WNDCLASSEX TWC = {0}; +	WINDOWPLACEMENT TWP; +	DWORD L1,L2; +	SYSTEMTIME tm; +	char TempStr[MAX_PATH] = {0}; +	char *TData; + +	const BOOL bIsStartup = Visible & 0x10000; +	Visible &= ~0x10000; + +	if (Data) TData = Data;	else TData = NULL; + +	if (!GetClassInfoEx(hmiranda, NOTE_WND_CLASS, &TWC)) +	{ +		TWC.style = CS_HREDRAW | CS_VREDRAW | CS_NOCLOSE; +		TWC.cbClsExtra = 0; +		TWC.cbWndExtra = 0; +		TWC.hInstance = hmiranda; +		TWC.hIcon = LoadIcon(0,IDI_APPLICATION); +		TWC.hCursor = LoadCursor(0,IDC_ARROW); +		TWC.hbrBackground = 0; +		TWC.lpszMenuName = 0; +		TWC.lpszClassName = NOTE_WND_CLASS; +		TWC.cbSize = sizeof(WNDCLASSEX); +		TWC.lpfnWndProc = (WNDPROC)StickyNoteWndProc; +		if (!RegisterClassEx(&TWC)) return NULL; +	} + +	if (!TData || Aw < 0 || Ah < 0) +	{ +		TWP.length = sizeof(WINDOWPLACEMENT); +		GetWindowPlacement(GetDesktopWindow(),&TWP); +		Aw = g_NoteWidth; Ah = g_NoteHeight; +		Ax = ((TWP.rcNormalPosition.right - TWP.rcNormalPosition.left) / 2) - (Aw / 2); +		Ay = ((TWP.rcNormalPosition.bottom - TWP.rcNormalPosition.top) / 2) - (Ah / 2); +	} + +	TSN = (STICKYNOTE*)malloc(sizeof(STICKYNOTE)); + +	if (ID) +	{ +		TSN->ID = *ID; +	} +	else +	{ +		GetSystemTime(&tm); +		SYSTEMTIMEtoFILETIME(&tm, (FILETIME*)&TSN->ID); +	} + +	EnsureUniqueID(TSN); + +	TreeAdd(&g_Stickies,TSN); + +	if (!TData) +	{ +		TData = _strdup(""); +		TSN->data = TData; +	} +	else +		TSN->data = TData; + +	// init note title (time-stamp) +	if (Title) +	{ +		TSN->title = Title; +		TSN->CustomTitle = TRUE; +	} +	else +	{ +		TSN->title = NULL; +		InitNoteTitle(TSN); +	} + +	TSN->Visible = Visible; +	TSN->OnTop = OnTop; + +	TSN->BgColor = bgClr; +	TSN->FgColor = fgClr; + +	TSN->pCustomFont = pCustomFont; + +	L1 = WS_EX_TOOLWINDOW; +	if (g_Transparency < 255) L1 |= WS_EX_LAYERED; +	if (OnTop) L1 |= WS_EX_TOPMOST; + +	L2 = WS_POPUP | WS_THICKFRAME | WS_CAPTION; + +	// NOTE: loaded note positions stem from GetWindowPlacement, which normally have a different coord space than +	//       CreateWindow/SetWindowPos, BUT since we now use WS_EX_TOOLWINDOW they use the same coord space so +	//       we don't have to worry about notes "drifting" between sessions +	TSN->SNHwnd = CreateWindowEx(L1, NOTE_WND_CLASS, _T("StickyNote"), L2, Ax,Ay,Aw,Ah, NULL, 0, hmiranda, TSN); + +	if (g_Transparency < 255) +		SetLayeredWindowAttributes(TSN->SNHwnd,0,(BYTE)g_Transparency,LWA_ALPHA); + +	// ensure that window is not placed off-screen (if previous session had different monitor count or resolution) +	// NOTE: SetWindowPlacement should do this, but it's extremly flakey +	if (Data) +	{ +		if (!MonitorFromWindow(TSN->SNHwnd, MONITOR_DEFAULTTONULL) ) +		{ +			TWP.length = sizeof(WINDOWPLACEMENT); +			GetWindowPlacement(GetDesktopWindow(), &TWP); + +			if (Aw > 500) Aw = 500; +			if (Ay < TWP.rcNormalPosition.left+10 || Ax > TWP.rcNormalPosition.right-120) +				Ax = ((TWP.rcNormalPosition.right - TWP.rcNormalPosition.left) / 2) - (Aw / 2) + (rand() & 0x3f); +			if (Ay < TWP.rcNormalPosition.top+50 || Ay > TWP.rcNormalPosition.bottom-50) +				Ay = ((TWP.rcNormalPosition.bottom - TWP.rcNormalPosition.top) / 4) + (rand() & 0x1f); + +			SetWindowPos(TSN->SNHwnd, NULL, Ax, Ay, Aw, Ah, SWP_NOZORDER|SWP_NOACTIVATE); +		} +	} + +	if (Visible) +	{ +		ShowWindow(TSN->SNHwnd, SW_SHOWNA); + +		// when loading notes (only at startup), place all non-top notes at the bottom so they don't cover other windows +		if (Data && !OnTop && bIsStartup) +			SetWindowPos(TSN->SNHwnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE|SWP_NOACTIVATE|SWP_ASYNCWINDOWPOS); +	} + +	if (scrollV) +	{ +		SendMessage(TSN->REHwnd, EM_LINESCROLL, 0, scrollV); +	} + +	// make sure that any event triggered by init doesn't cause a meaningless save +	KillTimer(TSN->SNHwnd, 1025); + +	if (!bLoading) +	{ +		NOTIFY_LIST(); +	} + +	return TSN; +} + +STICKYNOTE* NewNote(int Ax,int Ay,int Aw,int Ah,char *Data,ULARGE_INTEGER *ID,BOOL Visible,BOOL OnTop,int scrollV) +{ +	return NewNoteEx(Ax,Ay,Aw,Ah,Data,ID,Visible,OnTop,scrollV,0,0,NULL,NULL,FALSE); +} + +void LoadNotes(BOOL bIsStartup) +{ +	int I; +	int NotesCount; +	WORD Size; +	char *Value = NULL, *TVal = NULL; +	char ValueName[32]; + +	g_Stickies = NULL; + +	NotesCount = db_get_dw(0,MODULENAME,"NotesData",0); + +	for (I = 0; I < NotesCount; I++) +	{ +		char *DelPos; + +		mir_snprintf(ValueName, SIZEOF(ValueName), "NotesData%d", I); + +		if (Value) +		{ +			FreeSettingBlob(Size, Value); +			Value = NULL; +		} + +		Size = 65535; // does not get used + +		ReadSettingBlob(0, MODULENAME, ValueName, &Size, (void**)&Value); + +		if (!Size || !Value) +			continue; // the setting could not be read from DB -> skip + +		if (Value[0] == 'X') +		{ +			// new eXtended/fleXible data format + +			STICKYNOTE note = {0}; +			int i, rect[4]; +			int scrollV = 0; +			STICKYNOTEFONT *pCustomFont = NULL; +			DWORD flags; + +			DelPos = strchr(Value+1,0x1B); +			if (DelPos) +				*DelPos = 0; + +			// id:x:y:w:h:flags + +			TVal = strchr(Value+1, ':'); +			if (!TVal || (DelPos && TVal > DelPos)) +				continue; +			*TVal++ = 0; + +			note.ID.QuadPart = _strtoui64(Value+1, NULL, 16); + +			for (i=0; i<4; i++) +			{ +				char *sep = strchr(TVal, ':'); +				if (!sep || (DelPos && sep > DelPos)) +					goto skip; +				*sep++ = 0; + +				rect[i] = strtol(TVal, NULL, 10); + +				TVal = sep; +			} + +			flags = strtoul(TVal, NULL, 16); + +			if (flags & 1) +				note.Visible = TRUE; +			if (flags & 2) +				note.OnTop = TRUE; + +			// optional \033 separated params +			while (DelPos) +			{ +				char *sep; +				UINT tag; + +				TVal = DelPos + 1; +				// find param end and make sure it's null-terminated (if end of data then it's already null-terminated) +				DelPos = strchr(TVal, 0x1B); +				if (DelPos) +					*DelPos = 0; + +				// tag:<data> + +				sep = strchr(TVal, ':'); +				if (!sep || (DelPos && sep > DelPos)) +					goto skip; + +				tag = strtoul(TVal, NULL, 10); +				TVal = sep + 1; + +				switch (tag) +				{ +				case DATATAG_TEXT: +					note.data = _strdup(TVal); +					break; + +				case DATATAG_SCROLLPOS: +					scrollV = (int)strtoul(TVal, NULL, 10); +					break; + +				case DATATAG_BGCOL: +					note.BgColor = strtoul(TVal, NULL, 16) | 0xff000000; +					break; + +				case DATATAG_FGCOL: +					note.FgColor = strtoul(TVal, NULL, 16) | 0xff000000; +					break; + +				case DATATAG_TITLE: +					if (strlen(TVal) > MAX_TITLE_LEN) +						TVal[MAX_TITLE_LEN] = 0; +					note.title = _strdup(TVal); +					note.CustomTitle = TRUE; +					break; + +				case DATATAG_FONT: +					{ +						int fsize; +						UINT fstyle, fcharset; + +						char *TVal2 = TVal; +						sep = strchr(TVal2, ':'); +						if (!sep || (DelPos && sep > DelPos)) +							goto skip; +						*sep++ = 0; +						fsize = strtol(TVal2, NULL, 10); +						TVal2 = sep; + +						sep = strchr(TVal2, ':'); +						if (!sep || (DelPos && sep > DelPos)) +							goto skip; +						*sep++ = 0; +						fstyle = strtoul(TVal2, NULL, 10); +						TVal2 = sep; + +						sep = strchr(TVal2, ':'); +						if (!sep || (DelPos && sep > DelPos)) +							goto skip; +						*sep++ = 0; +						fcharset = strtoul(TVal2, NULL, 10); +						TVal2 = sep; + +						if (TVal2 >= DelPos) +							goto skip; + +						pCustomFont = (STICKYNOTEFONT*)malloc(sizeof(STICKYNOTEFONT)); +						pCustomFont->size = (char)fsize; +						pCustomFont->style = (BYTE)fstyle; +						pCustomFont->charset = (BYTE)fcharset; +						_tcscpy(pCustomFont->szFace, TVal2); +						pCustomFont->hFont = NULL; + +						if ( !CreateStickyNoteFont(pCustomFont, NULL) ) +						{ +							free(pCustomFont); +							pCustomFont = NULL; +						} +					} +					break; +				} +			} + +			if (!note.data) +				note.data = _strdup(""); + +			note.Visible = note.Visible && (!bIsStartup || g_ShowNotesAtStart); +			if (bIsStartup) +				note.Visible |= 0x10000; + +			NewNoteEx(rect[0],rect[1],rect[2],rect[3],note.data,¬e.ID,note.Visible,note.OnTop,scrollV,note.BgColor,note.FgColor,note.title,pCustomFont,TRUE); +		} +		else +		{ +			// old format (for DB backward compatibility) + +			int Tx,Ty,Tw,Th,TV,OT; +			BOOL V; +			char *Data,*ID; +			ULARGE_INTEGER newid; + +			OT = 1; TV = 1; +			Tx = 100; Ty = 100; +			Tw = 179; Th = 35; +			Data = NULL; ID = NULL; + +			if (DelPos = strchr(Value,0x1B)) +			{	// get first delimiter +				int	PartLen = DelPos - TVal; + +				Data = NULL; +				ID = NULL; +				TVal = Value; +				DelPos[0] = 0x0; +				Tx = strtol(TVal, NULL, 10); + +				TVal = DelPos + 1; +				DelPos = strchr(TVal, 0x1B); +				if (!DelPos) continue; // setting is broken, do not crash +				DelPos[0] = 0x0; +				Ty = strtol(TVal, NULL, 10); + +				TVal = DelPos + 1; +				DelPos = strchr(TVal, 0x1B); +				if (!DelPos) continue; // setting is broken, do not crash +				DelPos[0] = 0x0; +				Tw = strtol(TVal, NULL, 10); + +				TVal = DelPos + 1; +				DelPos = strchr(TVal, 0x1B); +				if (!DelPos) continue; // setting is broken, do not crash +				DelPos[0] = 0x0; +				Th = strtol(TVal, NULL, 10); + +				TVal = DelPos + 1; +				DelPos = strchr(TVal, 0x1B); +				if (!DelPos) continue; // setting is broken, do not crash +				DelPos[0] = 0x0; +				TV = strtol(TVal, NULL, 10); + +				TVal = DelPos + 1; +				DelPos = strchr(TVal, 0x1B); +				if (!DelPos) continue; // setting is broken, do not crash +				DelPos[0] = 0x0; +				OT = strtol(TVal, NULL, 10); + +				TVal = DelPos + 1; +				DelPos = strchr(TVal, 0x1B); +				if (!DelPos) continue; // setting is broken, do not crash +				DelPos[0] = 0x0; +				Data = _strdup(TVal); + +				TVal = DelPos + 1; +				ID = TVal; + +				V = (BOOL)TV && (!bIsStartup || g_ShowNotesAtStart); + +				if (bIsStartup) +					V |= 0x10000; + +				// convert old ID format to new +				if ( strchr(ID, '-') ) +				{ +					// validate format (otherwise create new) +					if (strlen(ID) < 19 || ID[2] != '-' || ID[5] != '-' || ID[10] != ' ' || ID[13] != ':' || ID[16] != ':') +					{ +						ID = NULL; +					} +					else +					{ +						SYSTEMTIME tm; + +						ID[2] = ID[5] = ID[10] = ID[13] = ID[16] = 0; + +						memset(&tm, 0, sizeof(tm)); +						tm.wDay = (WORD)strtoul(ID, NULL, 10); +						tm.wMonth = (WORD)strtoul(ID+3, NULL, 10); +						tm.wYear = (WORD)strtoul(ID+6, NULL, 10); +						tm.wHour = (WORD)strtoul(ID+11, NULL, 10); +						tm.wMinute = (WORD)strtoul(ID+14, NULL, 10); +						tm.wSecond = (WORD)strtoul(ID+17, NULL, 10); + +						SYSTEMTIMEtoFILETIME(&tm, (FILETIME*)&newid); +					} +				} +				else +				{ +					ID = NULL; +				} + +				NewNoteEx(Tx,Ty,Tw,Th,Data,ID?&newid:NULL,V,(BOOL)OT,0,0,0,NULL,NULL,TRUE); +			} +		} +skip:; +	} + +	if (Value) +		FreeSettingBlob(Size, Value); // we do not leak on bad setting + +	NOTIFY_LIST(); +} + +void CloseNotesList() +{ +	if (ListNotesVisible) +	{ +		DestroyWindow(LV); +		ListNotesVisible = FALSE; +	} +} + +static void PurgeNotesTree() +{ +	STICKYNOTE *pt; + +	while (g_Stickies) // empty whole tree +	{ +		pt = (STICKYNOTE*)g_Stickies->ptrdata; +		if (pt->SNHwnd) DestroyWindow(pt->SNHwnd); +		SAFE_FREE((void**)&pt->title); +		SAFE_FREE((void**)&pt->data); +		if (pt->pCustomFont) +		{ +			DeleteObject(pt->pCustomFont->hFont); +			free(pt->pCustomFont); +		} +		TreeDelete(&g_Stickies,pt); +		SAFE_FREE((void**)&pt); +	} +	g_Stickies = NULL; +} + +void SaveNotes(void) +{ +	JustSaveNotes(); +	PurgeNotesTree(); +} + +void PurgeNotes(void) +{ +	int NotesCount, I; +	char ValueName[16]; + +	NotesCount = db_get_dw(0,MODULENAME,"NotesData",0); +	for(I = 0; I < NotesCount; I++) +	{ +		mir_snprintf(ValueName, SIZEOF(ValueName), "NotesData%d", I); +		db_unset(0,MODULENAME,ValueName); +	} +} + +void OnDeleteNote(HWND hdlg, STICKYNOTE *SN) +{ +	if (MessageBox(hdlg, TranslateT("Are you sure you want to delete this note?"), TranslateT(SECTIONNAME), MB_OKCANCEL) == IDOK) +	{ +		if (SN->SNHwnd) +			DestroyWindow(SN->SNHwnd); +		TreeDelete(&g_Stickies,SN); +		SAFE_FREE((void**)&SN->data); +		if (SN->pCustomFont) +		{ +			DeleteObject(SN->pCustomFont->hFont); +			free(SN->pCustomFont); +		} +		SAFE_FREE((void**)&SN); +		JustSaveNotes(); +		NOTIFY_LIST(); +	} +} + +void DeleteNotes(void) +{ +	PurgeNotes(); +	db_set_dw(0, MODULENAME, "NotesData", 0); +	PurgeNotesTree(); +	NOTIFY_LIST(); +} + +void ShowHideNotes(void) +{ +	BOOL Visible; + +	if (!g_Stickies) +		return; + +	// if some notes are hidden but others visible then first make all visible +	// only toggle vis state if all are hidden or all are visible + +	UINT nHideCount  = 0, nVisCount = 0; +	TREEELEMENT *TTE = g_Stickies; +	while (TTE) +	{ +		if (((STICKYNOTE*)TTE->ptrdata)->Visible) +			nVisCount++; +		else +			nHideCount++; + +		TTE = (TREEELEMENT*)TTE->next; +	} + +	if (!nVisCount) +		Visible = TRUE; +	else if (!nHideCount) +		Visible = FALSE; +	else +		Visible = TRUE; + +	int bShow = Visible ? SW_SHOWNA : SW_HIDE; + +	TTE = g_Stickies; +	while (TTE) +	{ +		STICKYNOTE *SN = (STICKYNOTE*)TTE->ptrdata; + +		if ((!Visible) != (!SN->Visible)) +		{ +			ShowWindow(SN->SNHwnd, bShow); +			SN->Visible = Visible; +		} + +		TTE = (TREEELEMENT*)TTE->next; +	} + +	JustSaveNotes(); +} + +void BringAllNotesToFront(STICKYNOTE *pActive) +{ +	TREEELEMENT *TTE; + +	if (!g_Stickies) +		return; + +	// NOTE: for some reason there are issues when bringing to top through hotkey while another app (like Explorer) +	//       is active, it refuses to move notes to top like it should with HWND_TOP. as a workaround still doesn't +	//       work 100% of the time, but at least more often, we first move not to top-most then for non-always-on-top +	//       notes we demote them back as a non top-most window + +	TTE = g_Stickies; +	while (TTE) +	{ +		STICKYNOTE *SN = (STICKYNOTE*)TTE->ptrdata; + +		if (SN->Visible && pActive != SN) +		{ +			SetWindowPos(SN->SNHwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); +			if (!SN->OnTop) +				SetWindowPos(SN->SNHwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); +		} + +		TTE = (TREEELEMENT*)TTE->next; +	} + +	if (pActive) +	{ +		SetWindowPos(pActive->SNHwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); +		if (!pActive->OnTop) +			SetWindowPos(pActive->SNHwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); +	} +} + +static void JustSaveNotesEx(STICKYNOTE *pModified) +{ +	// pModified optionally points to the modified note that invoked the JustSaveNotesEx call + +	TREEELEMENT *TTE; +	int I, NotesCount = TreeGetCount(g_Stickies); +	int n, l; +	char ValueName[32]; +	WINDOWPLACEMENT wp; +	int TX,TY,TW,TH; +	DWORD flags; +	int SzT; +	int scrollV; +	char *tData, *Value; + +	const int OldNotesCount = db_get_dw(0, MODULENAME, "NotesData", 0); + +	db_set_dw(0, MODULENAME, "NotesData", NotesCount); + +	for (TTE = g_Stickies, I = 0; TTE; TTE = (TREEELEMENT*)TTE->next, I++) +	{ +		STICKYNOTE *pNote = (STICKYNOTE*)TTE->ptrdata; +		BOOL bDeleteTData = TRUE; +		scrollV = 0; +		tData = NULL; + +		// window pos and size +		wp.length = sizeof(WINDOWPLACEMENT); +		GetWindowPlacement(pNote->SNHwnd, &wp); +		TX = wp.rcNormalPosition.left; +		TY = wp.rcNormalPosition.top; +		TW = wp.rcNormalPosition.right - wp.rcNormalPosition.left; +		TH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top; + +		// set flags +		flags = 0; +		if (pNote->Visible) flags |= 1; +		if (pNote->OnTop) flags |= 2; + +		// get note text +		SzT = SendMessage(pNote->REHwnd, WM_GETTEXTLENGTH, 0, 0); +		if (SzT) // TODO: change to support unicode and rtf, use EM_STREAMOUT +		{ +			if (SzT > MAX_NOTE_LEN) SzT = MAX_NOTE_LEN; // we want to be far below the 64k limit +			tData = (char*)malloc(SzT+1); +			if (tData) +				SendMessage(pNote->REHwnd, WM_GETTEXT, SzT+1, (LPARAM)tData); +		} + +		if (pNote == pModified) +		{ +			// update the data of the modified note +			if (pNote->data) +				free(pNote->data); +			pNote->data = tData ? tData : _strdup(""); +			bDeleteTData = FALSE; +		} + +		if (!tData) +			// empty note +			SzT = 0; +		else +			// get current scroll position +			scrollV = SendMessage(pNote->REHwnd, EM_GETFIRSTVISIBLELINE, 0, 0); + +		// + +		Value = (char*)malloc(SzT + 512); +		if (!Value) { +			if (bDeleteTData) +				SAFE_FREE((void**)&tData); +			continue; +		} + +		n = 0; + +		// data header +		l = sprintf(Value, "X%I64x:%d:%d:%d:%d:%x", pNote->ID.QuadPart, TX, TY, TW, TH, flags); //!!!!!!!!!!!! +		if (l > 0) n += l; + +		// scroll pos +		if (scrollV > 0) +		{ +			l = sprintf(Value+n, "\033""%u:%u", DATATAG_SCROLLPOS, (UINT)scrollV); //!!!!!!!!!! +			if (l > 0) n += l; +		} + +		// custom bg color +		if (pNote->BgColor) +		{ +			l = sprintf(Value+n, "\033""%u:%x", DATATAG_BGCOL, (UINT)(pNote->BgColor&0xffffff)); //!!!!!!!!!!!!! +			if (l > 0) n += l; +		} + +		// custom fg color +		if (pNote->FgColor) +		{ +			l = sprintf(Value+n, "\033""%u:%x", DATATAG_FGCOL, (UINT)(pNote->FgColor&0xffffff)); //!!!!!!!!!!!!! +			if (l > 0) n += l; +		} + +		if (pNote->pCustomFont) +		{ +			l = sprintf(Value+n, "\033""%u:%d:%u:%u:%s", DATATAG_FONT, +				(int)pNote->pCustomFont->size, (UINT)pNote->pCustomFont->style, (UINT)pNote->pCustomFont->charset, +				pNote->pCustomFont->szFace); //!!!!!!!!!!!!!!! +			if (l > 0) n += l; +		} + +		// custom title +		if (pNote->CustomTitle && pNote->title) +		{ +			l = sprintf(Value+n, "\033""%u:%s", DATATAG_TITLE, pNote->title); //!!!!!!!!!!!!! +			if (l > 0) n += l; +		} + +		// note text (ALWAYS PUT THIS PARAM LAST) +		if (tData) +		{ +			l = sprintf(Value+n, "\033""%u:%s", DATATAG_TEXT, tData); //!!!!!!!!!!!! +			if (l > 0) n += l; +		} + +		// clamp data size to WORD (including null terminator) +		if (n >= 0xffff) +		{ +			// huston, we have a problem, strip some reminder text +			n = 0xfffe; +			Value[0xffff] = 0; +		} + +		mir_snprintf(ValueName, SIZEOF(ValueName), "NotesData%d", NotesCount - I - 1); // we do not reverse notes in DB + +		db_set_blob(0, MODULENAME, ValueName, Value, n+1); + +		SAFE_FREE((void**)&Value); +		if (bDeleteTData) +			SAFE_FREE((void**)&tData); + +		// make no save is queued for the note +		if (pNote->SNHwnd) +			KillTimer(pNote->SNHwnd, 1025); +	} + +	// delete any left over DB note entries +	for(; I < OldNotesCount; I++) +	{ +		mir_snprintf(ValueName, SIZEOF(ValueName), "NotesData%d", I); +		db_unset(0,MODULENAME,ValueName); +	} + +	NOTIFY_LIST(); +} + +__inline void JustSaveNotes(void) +{ +	JustSaveNotesEx(NULL); +} + + +///////////////////////////////////////////////////////////////////// +// Note Window + +static int FindMenuItem(HMENU h, LPTSTR lpszName) +{ +	UINT i; +	TCHAR s[128]; + +	int n = GetMenuItemCount(h); + +	if (n <= 0) +	{ +		return -1; +	} + +	// searches for a menu item based on name (used to avoid hardcoding item indices for sub-menus) +	for (i=0; i<(UINT)n; i++) +	{ +		if ( GetMenuString(h, i, s, 128, MF_BYPOSITION) ) +		{ +			if ( !_tcscmp(s, lpszName) ) +			{ +				return (int)i; +			} +		} +	} + +	return -1; +} + +static BOOL DoContextMenu(HWND AhWnd,WPARAM wParam,LPARAM lParam) +{ +	int n, i; +	STICKYNOTE *SN = (STICKYNOTE*)GetProp(AhWnd, _T("ctrldata")); + +	HMENU hMenuLoad, FhMenu, hSub; +	hMenuLoad = LoadMenu(hinstance, _T("MNU_NOTEPOPUP")); +	FhMenu = GetSubMenu(hMenuLoad,0); + +	if (SN->OnTop) +		CheckMenuItem(FhMenu, IDM_TOGGLEONTOP, MF_CHECKED|MF_BYCOMMAND); + +	EnableMenuItem(FhMenu, ID_CONTEXTMENUNOTEPOPUP_PASTETITLE, MF_BYCOMMAND | (IsClipboardFormatAvailable(CF_TEXT) ? MF_ENABLED : MF_GRAYED)); + +	if (!SN->CustomTitle) +		EnableMenuItem(FhMenu, ID_CONTEXTMENUNOTEPOPUP_RESETTITLE, MF_BYCOMMAND | MF_GRAYED); + +	// NOTE: names used for FindMenuItem would need to include & chars if such shortcuts are added to the menus + +	n = FindMenuItem(FhMenu, _T("Appearance")); +	if (n >= 0 && (hSub = GetSubMenu(FhMenu, n))) +	{ +		HMENU hBg = GetSubMenu(hSub, FindMenuItem(hSub, _T("Background Color"))); +		HMENU hFg = GetSubMenu(hSub, FindMenuItem(hSub, _T("Text Color"))); + +		for (i=0; i<SIZEOF(clrPresets); i++) +			InsertMenu(hBg, i, MF_BYPOSITION|MF_OWNERDRAW, IDM_COLORPRESET_BG+i, TranslateTS(clrPresets[i].szName)); + +		for (i=0; i<SIZEOF(clrPresets); i++) +			InsertMenu(hFg, i, MF_BYPOSITION|MF_OWNERDRAW, IDM_COLORPRESET_FG+i, TranslateTS(clrPresets[i].szName)); +	} + +    CallService(MS_LANGPACK_TRANSLATEMENU,(DWORD)FhMenu,0); +	TrackPopupMenu(FhMenu,TPM_LEFTALIGN | TPM_RIGHTBUTTON,LOWORD(lParam),HIWORD(lParam),0,AhWnd,0); +	DestroyMenu(hMenuLoad); + +	return TRUE; +} + +static void MeasureColorPresetMenuItem(HWND hdlg, LPMEASUREITEMSTRUCT lpMeasureItem, struct ColorPreset *clrPresets) +{ +	HDC hdc = GetDC(hdlg); +	LPTSTR lpsz = TranslateTS(clrPresets->szName); +	SIZE sz; +	GetTextExtentPoint32(hdc, lpsz, (int)_tcslen(lpsz), &sz); +	ReleaseDC(hdlg, hdc); + +	lpMeasureItem->itemWidth = 50 + sz.cx; +	lpMeasureItem->itemHeight = (sz.cy+2)>18 ? sz.cy+2 : 18; +} + +static void PaintColorPresetMenuItem(LPDRAWITEMSTRUCT lpDrawItem, struct ColorPreset *clrPresets) +{ +	UINT n = lpDrawItem->itemID - IDM_COLORPRESET_BG; +	RECT rect; +	rect.left = lpDrawItem->rcItem.left + 50; +	rect.top = lpDrawItem->rcItem.top; +	rect.right = lpDrawItem->rcItem.right; +	rect.bottom = lpDrawItem->rcItem.bottom; + +	if (lpDrawItem->itemState & ODS_SELECTED) +	{ +		SetDCBrushColor(lpDrawItem->hDC, GetSysColor(COLOR_MENUHILIGHT)); +		FillRect(lpDrawItem->hDC, &lpDrawItem->rcItem, (HBRUSH)GetStockObject(DC_BRUSH)); + +		SetTextColor(lpDrawItem->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT)); +	} +	else +	{ +		SetDCBrushColor(lpDrawItem->hDC, GetSysColor(COLOR_MENU)); +		FillRect(lpDrawItem->hDC, &lpDrawItem->rcItem, (HBRUSH)GetStockObject(DC_BRUSH)); + +		SetTextColor(lpDrawItem->hDC, GetSysColor(COLOR_MENUTEXT)); +	} + +	SetBkMode(lpDrawItem->hDC, TRANSPARENT); +	DrawText(lpDrawItem->hDC,clrPresets->szName,-1,&rect,DT_LEFT | DT_SINGLELINE | DT_END_ELLIPSIS | DT_VCENTER); + +	{ +		int h = lpDrawItem->rcItem.bottom - lpDrawItem->rcItem.top; +		rect.left = lpDrawItem->rcItem.left + 5; +		rect.top = lpDrawItem->rcItem.top + ((h-14)>>1); +		rect.right = rect.left + 40; +		rect.bottom = rect.top + 14; + +		FrameRect(lpDrawItem->hDC, &rect, (HBRUSH)GetStockObject(BLACK_BRUSH)); +		rect.left++; rect.top++; +		rect.right--; rect.bottom--; +		SetDCBrushColor(lpDrawItem->hDC, clrPresets->color); +		FillRect(lpDrawItem->hDC, &rect, (HBRUSH)GetStockObject(DC_BRUSH)); +	} +} + +static BOOL GetClipboardText_Title(char *pOut, int size) +{ +	BOOL bResult = FALSE; + +	if ( OpenClipboard(NULL) ) +	{ +		HANDLE hData = GetClipboardData(CF_TEXT); +		LPCSTR buffer; + +		if (hData && (buffer = (LPCSTR)GlobalLock(hData))) +		{ +			// trim initial white spaces +			while (*buffer && isspace(*buffer)) +				buffer++; + +			char *p; +			int n = strlen(buffer); +			if (n >= size) +				n = size-1; +			memcpy(pOut, buffer, n); +			pOut[n] = 0; + +			// end string on line break and convert tabs to spaces +			p = pOut; +			while (*p) +			{ +				if (*p == '\r' || *p == '\n') +				{ +					*p = 0; +					n = strlen(pOut); +					break; +				} +				else if (*p == '\t') +				{ +					*p = ' '; +				} +				p++; +			} + +			// trim trailing white spaces +			while  (n && isspace(pOut[n-1])) +				pOut[--n] = 0; + +			if (n) +				bResult = TRUE; + +			GlobalUnlock(hData); +		} + +		CloseClipboard(); +	} + +	return bResult; +} + +static void SetNoteTextControl(STICKYNOTE *SN) +{ +    CHARFORMAT CF = {0}; +	CF.cbSize = sizeof(CHARFORMAT); +	CF.dwMask = CFM_COLOR; +	CF.crTextColor = SN->FgColor ? (SN->FgColor&0xffffff) : BodyFontColor; +	SendMessage(SN->REHwnd, EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&CF); + +	if (SN->data) // TODO: use EM_STREAMIN +		SendMessage(SN->REHwnd, WM_SETTEXT, 0, (LPARAM)(SN->data)); +} + + +static UINT_PTR CALLBACK CFHookProc(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam) +{ +	if (msg == WM_INITDIALOG) +	{ +		// hide color selector +		ShowWindow(GetDlgItem(hdlg,0x443), SW_HIDE); +		ShowWindow(GetDlgItem(hdlg,0x473), SW_HIDE); +		TranslateDialogDefault(hdlg); +	} + +	return 0; +} + + +INT_PTR CALLBACK StickyNoteWndProc(HWND hdlg,UINT message,WPARAM wParam,LPARAM lParam) +{ +	switch (message) +	{ +	case WM_CLOSE: +		return TRUE; + +	case WM_SIZE: +		{ +			RECT SZ; + +			GetClientRect(hdlg,&SZ); +			HWND H = GetDlgItem(hdlg,1); +			MoveWindow(H, 0, 0, SZ.right,SZ.bottom, TRUE); + +			KillTimer(hdlg, 1025); +			SetTimer(hdlg, 1025, NOTE_CHANGE_COMMIT_DELAY, 0); + +			return TRUE; +		} +    case WM_TIMER: +		if (wParam == 1025) +		{ +			STICKYNOTE *SN = (STICKYNOTE*)GetProp(hdlg,_T("ctrldata")); + +			KillTimer(hdlg, 1025); +			JustSaveNotesEx(SN); +		} +		break; +    case WM_MOVE: +		{ +			KillTimer(hdlg, 1025); +			SetTimer(hdlg, 1025, NOTE_CHANGE_COMMIT_DELAY, 0); +			return TRUE; +		} +    case WM_CREATE: +		{ +			STICKYNOTE *SN = (STICKYNOTE*)GetProp(hdlg,_T("ctrldata")); + +			CREATESTRUCT *CS = (CREATESTRUCT *)lParam; +			HWND H; +			DWORD mystyle; + +			SN = (STICKYNOTE*)CS->lpCreateParams; +			SetProp(hdlg,_T("ctrldata"),(HANDLE)SN); +			BringWindowToTop(hdlg); +			mystyle = WS_CHILD | WS_VISIBLE | ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL | ES_WANTRETURN; +			if (g_ShowScrollbar) mystyle |= WS_VSCROLL; +			H = CreateWindow(RICHEDIT_CLASS, 0, mystyle, 0, 0, CS->cx-3-3, CS->cy-3-(3+14), hdlg, (HMENU)1, hmiranda, 0); +			SN->REHwnd = H; +			SendMessage(H, EM_SETTEXTMODE, TM_PLAINTEXT, 0); +			SendMessage(H, EM_LIMITTEXT, MAX_NOTE_LEN, 0); +			SendMessage(H, WM_SETFONT, (WPARAM)(SN->pCustomFont ? SN->pCustomFont->hFont : hBodyFont), 1); +			SendMessage(H, EM_SETEVENTMASK, 0, ENM_CHANGE | ENM_LINK); +			SendMessage(H, EM_SETBKGNDCOLOR, 0, SN->BgColor ? (SN->BgColor&0xffffff) : BodyColor); +			SendMessage(H, EM_AUTOURLDETECT, 1, 0); +			SetNoteTextControl(SN); +			return TRUE; +		} +	case WM_GETMINMAXINFO: +		{ +			MINMAXINFO *mm = (MINMAXINFO*)lParam; +			// min width accomodates frame, buttons and some extra space for sanity +			mm->ptMinTrackSize.x = 48+3+3+8 + 40; +			// min height allows collapsing entire client area, only leaving frame and caption +			mm->ptMinTrackSize.y = 3+3+14; +		} +		return 0; +	case WM_ERASEBKGND: +		// no BG needed as edit control takes up entire client area +		return TRUE; +	case WM_NCPAINT: +		// make window borders have the same color as caption +		{ +			STICKYNOTE *SN = (STICKYNOTE*)GetProp(hdlg,"ctrldata"); + +			HBRUSH hBkBrush; +			RECT rect, wr, r; +			//HDC hdc = GetDCEx(hdlg, (HRGN)wParam, DCX_WINDOW|DCX_INTERSECTRGN); +			HDC hdc = GetWindowDC(hdlg); + +			GetWindowRect(hdlg, &wr); +			if (wParam && wParam != 1) +			{ +				SelectClipRgn(hdc, (HRGN)wParam); +				OffsetClipRgn(hdc, -wr.left, -wr.top); +			} + +			rect = wr; +			OffsetRect(&rect, -wr.left, -wr.top); + +			hBkBrush = (HBRUSH)GetStockObject(DC_BRUSH); +			SetDCBrushColor(hdc, GetCaptionColor((SN && SN->BgColor) ? SN->BgColor : BodyColor)); + +			// draw all frame sides separately to avoid filling client area (which flickers) +			{ +			// top +			r.left = rect.left; r.right = rect.right; +			r.top = rect.top; r.bottom = r.top + 3+14; +			FillRect(hdc, &r, hBkBrush); +			// bottom +			r.top = rect.bottom - 3; r.bottom = rect.bottom; +			FillRect(hdc, &r, hBkBrush); +			// left +			r.left = rect.left; r.right = r.left + 3; +			r.top = rect.top + 3+14; r.bottom = rect.bottom - 3; +			FillRect(hdc, &r, hBkBrush); +			// right +			r.left = rect.right - 3; r.right = rect.right; +			FillRect(hdc, &r, hBkBrush); +			} + +			// paint title bar contents (time stamp and buttons) + +			if (SN && SN->title) +			{ +				RECT R; +				SelectObject(hdc,hCaptionFont); +				R.top = 3+1; R.bottom = 3+11; R.left = 3+2; R.right = rect.right-3-1; +				if (g_ShowNoteButtons) +					R.right -= 48; + +				SetTextColor(hdc,SN->FgColor ? (SN->FgColor&0xffffff) : CaptionFontColor); +				SetBkMode(hdc, TRANSPARENT); +				DrawText(hdc,SN->title,-1,&R,DT_LEFT | DT_SINGLELINE | DT_END_ELLIPSIS | DT_VCENTER); +			} + +			if (g_ShowNoteButtons) +			{ +				HICON hcIcon; +				if (SN->OnTop) +					hcIcon = Skin_GetIconByHandle(iconList[4].hIcolib); +				else +					hcIcon = Skin_GetIconByHandle(iconList[7].hIcolib); +				DrawIcon(hdc, wr.right - wr.left - 16, 0 + 3, hcIcon); +				Skin_ReleaseIcon(hcIcon); + +				hcIcon = Skin_GetIconByHandle(iconList[9].hIcolib); +				DrawIcon(hdc, wr.right - wr.left - 32, 1 + 3, hcIcon); +				Skin_ReleaseIcon(hcIcon); + +				hcIcon = Skin_GetIconByHandle(iconList[8].hIcolib); +				DrawIcon(hdc, wr.right - wr.left - 48, 1 + 3, hcIcon); +				Skin_ReleaseIcon(hcIcon); +			} + +			if (wParam && wParam != 1) +			{ +				SelectClipRgn(hdc, NULL); +			} + +			ReleaseDC(hdlg, hdc); +			return TRUE; +		} +	case WM_NCCALCSIZE: +		{ +			RECT *pRect = wParam ? &((NCCALCSIZE_PARAMS*)lParam)->rgrc[0] : (RECT*)lParam; +			pRect->bottom -= 3; +			pRect->right -= 3; +			pRect->left += 3; +			pRect->top += 3+14; +			return WVR_REDRAW; +		} +	case WM_NCACTIVATE: +		// update window (so that parts that potentially became visible through activation get redrawn immediately) +		RedrawWindow(hdlg, NULL, NULL, RDW_UPDATENOW); +		return TRUE; +    case WM_NOTIFY: +        if (LOWORD(wParam) == 1) +		{ +		    char *Buff; +			PENLINK PEnLnk = (PENLINK)lParam; + +			if (PEnLnk->msg == WM_LBUTTONDOWN) +			{ +				SendDlgItemMessage(hdlg,1,EM_EXSETSEL,0,(LPARAM)&(PEnLnk->chrg)); +				Buff = (char*)malloc(PEnLnk->chrg.cpMax - PEnLnk->chrg.cpMin + 1); +				SendDlgItemMessage(hdlg,1,EM_GETSELTEXT,0,(LPARAM)Buff); +				if ((GetAsyncKeyState(VK_CONTROL) >> 15) != 0) +					ShellExecute(hdlg, _T("open"), _T("iexplore"), Buff, _T("") ,SW_SHOWNORMAL); +				else if (g_lpszAltBrowser && *g_lpszAltBrowser) +					ShellExecute(hdlg,_T("open"), g_lpszAltBrowser, Buff, _T("") ,SW_SHOWNORMAL); +				else +					ShellExecute(hdlg, _T("open"), Buff, _T(""), _T(""), SW_SHOWNORMAL); +				SAFE_FREE((void**)&Buff); +				return TRUE; +			} +			return FALSE; +        } +		break; +	case WM_NCHITTEST: +		{ +		int r = DefWindowProc(hdlg,message,wParam,lParam); +		// filter out potential hits on windows default title bar buttons +		switch (r) +		{ +		case HTSYSMENU: +		case HTCLOSE: +		case HTMINBUTTON: +		case HTMAXBUTTON: +			return HTCAPTION; +		} +		return r; +		} +	case WM_NCLBUTTONDOWN: +		if (wParam == HTCAPTION && g_ShowNoteButtons) +		{ +			long X,Y; +			RECT rect; +			int Tw; + +			GetWindowRect(hdlg, &rect); +			Tw = rect.right - rect.left; + +			X = LOWORD(lParam) - rect.left; +			Y = HIWORD(lParam) - rect.top; + +			if (X > Tw - 16) +			{ +				SendMessage(hdlg,WM_COMMAND,IDM_TOGGLEONTOP,0); +				return TRUE; +			} +			else if (X > Tw - 31 && X < Tw - 16) +			{ +				SendMessage(hdlg,WM_COMMAND,IDM_REMOVENOTE,0); +				return TRUE; +			} +			else if (X > Tw - 48 && X < Tw - 32) +			{ +				SendMessage(hdlg,WM_COMMAND,IDM_HIDENOTE,0); +				return TRUE; +			} +		} +		return DefWindowProc(hdlg,message,wParam,lParam); +	case WM_MEASUREITEM: +		{ +			LPMEASUREITEMSTRUCT lpMeasureItem = (LPMEASUREITEMSTRUCT)lParam; + +			if (lpMeasureItem->CtlType != ODT_MENU) +				break; + +			if (lpMeasureItem->itemID >= IDM_COLORPRESET_BG && lpMeasureItem->itemID <= IDM_COLORPRESET_BG+SIZEOF(clrPresets)) +			{ +				MeasureColorPresetMenuItem(hdlg, lpMeasureItem, clrPresets + (lpMeasureItem->itemID - IDM_COLORPRESET_BG)); +				return TRUE; +			} +			else if (lpMeasureItem->itemID >= IDM_COLORPRESET_FG && lpMeasureItem->itemID <= IDM_COLORPRESET_FG+SIZEOF(clrPresets)) +			{ +				MeasureColorPresetMenuItem(hdlg, lpMeasureItem, clrPresets + (lpMeasureItem->itemID - IDM_COLORPRESET_FG)); +				return TRUE; +			} +		} +		break; +	case WM_DRAWITEM: +		if (!wParam) +		{ +			LPDRAWITEMSTRUCT lpDrawItem = (LPDRAWITEMSTRUCT)lParam; + +			if (lpDrawItem->CtlType != ODT_MENU) +				break; + +			if (lpDrawItem->itemID >= IDM_COLORPRESET_BG && lpDrawItem->itemID <= IDM_COLORPRESET_BG+SIZEOF(clrPresets)) +			{ +				PaintColorPresetMenuItem(lpDrawItem, clrPresets + (lpDrawItem->itemID - IDM_COLORPRESET_BG)); +				return TRUE; +			} +			else if (lpDrawItem->itemID >= IDM_COLORPRESET_FG && lpDrawItem->itemID <= IDM_COLORPRESET_FG+SIZEOF(clrPresets)) +			{ +				PaintColorPresetMenuItem(lpDrawItem, clrPresets + (lpDrawItem->itemID - IDM_COLORPRESET_FG)); +				return TRUE; +			} +		} +		break; +	case WM_COMMAND: +		{ +			STICKYNOTE *SN = (STICKYNOTE*)GetProp(hdlg, _T("ctrldata")); + +			HWND H; +			UINT id; + +			switch ( HIWORD(wParam) ) +			{ +			case EN_CHANGE: +			case EN_VSCROLL: +			case EN_HSCROLL: +				{ +					KillTimer(hdlg,1025); +					SetTimer(hdlg, 1025, NOTE_CHANGE_COMMIT_DELAY, 0); +				} +				break; +			} + +			id = (UINT) LOWORD(wParam); + +			H = SN->REHwnd; + +			if (id >= IDM_COLORPRESET_BG && id <= IDM_COLORPRESET_BG+SIZEOF(clrPresets)) +			{ +				SN->BgColor = clrPresets[id-IDM_COLORPRESET_BG].color | 0xff000000; +				SendMessage(H, EM_SETBKGNDCOLOR, 0, (LPARAM)(SN->BgColor&0xffffff)); +				RedrawWindow(SN->SNHwnd, NULL, NULL, RDW_INVALIDATE|RDW_FRAME|RDW_UPDATENOW); +				JustSaveNotes(); +				return FALSE; +			} +			else if (id >= IDM_COLORPRESET_FG && id <= IDM_COLORPRESET_FG+SIZEOF(clrPresets)) +			{ +				CHARFORMAT CF = {0}; +				SN->FgColor = clrPresets[id-IDM_COLORPRESET_FG].color | 0xff000000; +				CF.cbSize = sizeof(CHARFORMAT); +				CF.dwMask = CFM_COLOR; +				CF.crTextColor = SN->FgColor & 0xffffff; +				SendMessage(H, EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&CF); +				RedrawWindow(SN->SNHwnd, NULL, NULL, RDW_INVALIDATE|RDW_FRAME|RDW_UPDATENOW); +				JustSaveNotes(); +				return FALSE; +			} + +			switch (id) +			{ +			case ID_CONTEXTMENUNOTEPOPUP_NEWNOTE: +				{ +					PluginMenuCommandAddNew(0,0); +				} +				break; +			case ID_APPEARANCE_CUSTOMBG: +				{ +					COLORREF custclr[16] = {0}; +					CHOOSECOLOR cc = {0}; +					COLORREF orgclr = SN->BgColor ? (COLORREF)(SN->BgColor&0xffffff) : (COLORREF)(BodyColor&0xffffff); +					cc.lStructSize = sizeof(cc); +					cc.hwndOwner = SN->SNHwnd; +					cc.rgbResult = orgclr; +					cc.Flags = CC_ANYCOLOR | CC_FULLOPEN | CC_RGBINIT | CC_SOLIDCOLOR; +					cc.lpCustColors = custclr; + +					if (ChooseColor(&cc) && cc.rgbResult != orgclr) +					{ +						SN->BgColor = cc.rgbResult | 0xff000000; +						SendMessage(H, EM_SETBKGNDCOLOR, 0, (LPARAM)(SN->BgColor&0xffffff)); +						RedrawWindow(SN->SNHwnd, NULL, NULL, RDW_INVALIDATE|RDW_FRAME|RDW_UPDATENOW); +						JustSaveNotes(); +					} +				} +				break; +			case ID_APPEARANCE_CUSTOMTEXT: +				{ +					COLORREF custclr[16] = {0}; +					CHOOSECOLOR cc = {0}; +					COLORREF orgclr = SN->FgColor ? (COLORREF)(SN->FgColor&0xffffff) : (COLORREF)(BodyFontColor&0xffffff); +					cc.lStructSize = sizeof(cc); +					cc.hwndOwner = SN->SNHwnd; +					cc.rgbResult = orgclr; +					cc.Flags = CC_ANYCOLOR | CC_FULLOPEN | CC_RGBINIT | CC_SOLIDCOLOR; +					cc.lpCustColors = custclr; + +					if (ChooseColor(&cc) && cc.rgbResult != orgclr) +					{ +						CHARFORMAT CF = {0}; +						SN->FgColor = cc.rgbResult | 0xff000000; +						CF.cbSize = sizeof(CHARFORMAT); +						CF.dwMask = CFM_COLOR; +						CF.crTextColor = SN->FgColor & 0xffffff; +						SendMessage(H, EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&CF); +						RedrawWindow(SN->SNHwnd, NULL, NULL, RDW_INVALIDATE|RDW_FRAME|RDW_UPDATENOW); +						JustSaveNotes(); +					} +				} +				break; +			case ID_APPEARANCE_CUSTOMFONT: +				{ +					CHOOSEFONT cf = {0}; +					LOGFONT lf = {0}; + +					if (SN->pCustomFont) +						InitStickyNoteLogFont(SN->pCustomFont, &lf); +					else +						LoadNRFont(NR_FONTID_BODY, &lf, NULL); + +					cf.lStructSize = sizeof(cf); +					cf.hwndOwner = SN->SNHwnd; +					cf.lpLogFont = &lf; +					cf.Flags = CF_EFFECTS | CF_FORCEFONTEXIST | CF_INITTOLOGFONTSTRUCT | CF_SCREENFONTS | CF_ENABLEHOOK; +					cf.lpfnHook = CFHookProc; + +					if ( ChooseFont(&cf) ) +					{ +						if (!SN->pCustomFont) +						{ +							SN->pCustomFont = (STICKYNOTEFONT*)malloc(sizeof(STICKYNOTEFONT)); +							SN->pCustomFont->hFont = NULL; +						} + +						SN->pCustomFont->size = (char)lf.lfHeight; +						SN->pCustomFont->style = (lf.lfWeight >= FW_BOLD ? DBFONTF_BOLD : 0) | (lf.lfItalic ? DBFONTF_ITALIC : 0) | (lf.lfUnderline ? DBFONTF_UNDERLINE : 0) | (lf.lfStrikeOut ? DBFONTF_STRIKEOUT : 0); +						SN->pCustomFont->charset = lf.lfCharSet; +						_tcscpy(SN->pCustomFont->szFace, lf.lfFaceName); + +						if ( !CreateStickyNoteFont(SN->pCustomFont, &lf) ) +						{ +							// failed +							free(SN->pCustomFont); +							SN->pCustomFont = NULL; +						} + +						// clear text first to force a reformatting w.r.t scrollbar +						SendMessage(H, WM_SETTEXT, 0, (LPARAM)""); +						SendMessage(H, WM_SETFONT, (WPARAM)(SN->pCustomFont ? SN->pCustomFont->hFont : hBodyFont), FALSE); +						SetNoteTextControl(SN); +						RedrawWindow(SN->SNHwnd, NULL, NULL, RDW_INVALIDATE|RDW_FRAME|RDW_UPDATENOW); +						JustSaveNotes(); +					} +				} +				break; +			case ID_BACKGROUNDCOLOR_RESET: +				{ +					SN->BgColor = 0; +					SendMessage(H, EM_SETBKGNDCOLOR, 0, (LPARAM)BodyColor); +					RedrawWindow(SN->SNHwnd, NULL, NULL, RDW_INVALIDATE|RDW_FRAME|RDW_UPDATENOW); +					JustSaveNotes(); +				} +				break; +			case ID_TEXTCOLOR_RESET: +				{ +					CHARFORMAT CF = {0}; +					SN->FgColor = 0; +					CF.cbSize = sizeof(CHARFORMAT); +					CF.dwMask = CFM_COLOR; +					CF.crTextColor = BodyFontColor; +					SendMessage(H, EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&CF); +					RedrawWindow(SN->SNHwnd, NULL, NULL, RDW_INVALIDATE|RDW_FRAME|RDW_UPDATENOW); +					JustSaveNotes(); +				} +				break; +			case ID_FONT_RESET: +				{ +					if (SN->pCustomFont) +					{ +						DeleteObject(SN->pCustomFont->hFont); +						free(SN->pCustomFont); +						SN->pCustomFont = NULL; + +						// clear text first to force a reformatting w.r.t scrollbar +						SendMessage(H, WM_SETTEXT, 0, (LPARAM)""); +						SendMessage(H, WM_SETFONT, (WPARAM)hBodyFont, FALSE); +						SetNoteTextControl(SN); +						RedrawWindow(SN->SNHwnd, NULL, NULL, RDW_INVALIDATE|RDW_FRAME|RDW_UPDATENOW); +						JustSaveNotes(); +					} +				} +				break; +			case ID_CONTEXTMENUNOTEPOPUP_PASTETITLE: +				{ +					char s[MAX_TITLE_LEN+1]; +					if ( GetClipboardText_Title(s, sizeof(s)) ) +					{ +						if (SN->title) +							free(SN->title); +						SN->title = _strdup(s); +						SN->CustomTitle = TRUE; +						RedrawWindow(SN->SNHwnd, NULL, NULL, RDW_INVALIDATE|RDW_FRAME|RDW_UPDATENOW); +						JustSaveNotes(); +					} +				} +				break; +			case ID_CONTEXTMENUNOTEPOPUP_RESETTITLE: +				if (SN->CustomTitle) +				{ +					if (SN->title) +					{ +						free(SN->title); +						SN->title = NULL; +					} +					InitNoteTitle(SN); +					RedrawWindow(SN->SNHwnd, NULL, NULL, RDW_INVALIDATE|RDW_FRAME|RDW_UPDATENOW); +					JustSaveNotes(); +				} +				break; +			case IDM_REMOVENOTE: +				OnDeleteNote(hdlg, SN); +				break; +			case IDM_HIDENOTE: +				{ +					SN->Visible = FALSE; +					ShowWindow(hdlg,SW_HIDE); +					JustSaveNotes(); +				} +				break; +			case IDM_COPY: SendMessage(H,WM_COPY,0,0); break; +			case IDM_PASTE: SendMessage(H,WM_PASTE,0,0); break; +			case IDM_CUT: SendMessage(H,WM_CUT,0,0); break; +			case IDM_CLEAR: SendMessage(H,WM_CLEAR,0,0); break; +			case IDM_UNDO: SendMessage(H,WM_UNDO,0,0); break; +			case IDM_TOGGLEONTOP: +				{ +					SN->OnTop = !SN->OnTop; +					SetWindowPos(hdlg, SN->OnTop ? HWND_TOPMOST : HWND_NOTOPMOST, 0,0,0,0, SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOSIZE); +					RedrawWindow(hdlg, NULL, NULL, RDW_FRAME|RDW_INVALIDATE|RDW_UPDATENOW); +					JustSaveNotes(); +				} +				break; +			case ID_CONTEXTMENUNOTEPOPUP_VIEWNOTES: +				ListNotes(); +				break; +			case ID_CONTEXTMENUNOTEPOPUP_BRINGALLTOTOP: +				BringAllNotesToFront(SN); +				break; +			} +			return TRUE; +		} +	case WM_NCDESTROY: +		{ +			RemoveProp(hdlg, _T("ctrldata")); +		} +		break; +    case WM_CONTEXTMENU: +		if (DoContextMenu(hdlg,wParam,lParam)) return FALSE; + +	default: +		return DefWindowProc(hdlg,message,wParam,lParam); +	} +	return FALSE; +} + + +///////////////////////////////////////////////////////////////////// +// Notes List Dialog (uses same dialog template as reminder list) + +void ListNotes(void) +{ +	if (!ListNotesVisible) +	{ +		CreateDialog(hinstance, MAKEINTRESOURCE(IDD_LISTREMINDERS), 0, DlgProcViewNotes); +		ListNotesVisible = TRUE; +	} +	else +	{ +		BringWindowToTop(LV); +	} +} + +static void EditNote(STICKYNOTE *SN) +{ +	if (!SN) +		return; + +	if (!SN->Visible) +	{ +		SN->Visible = TRUE; +		JustSaveNotes(); +	} + +	SetWindowPos(SN->SNHwnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); +	if (!SN->OnTop) +		SetWindowPos(SN->SNHwnd, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE); + +	SetFocus(SN->REHwnd); +} + +char* GetPreviewString(const char *lpsz) +{ +	int l; +	char *p; +	const int MaxLen = 80; +	static char s[80+8]; + +	if (!lpsz) +		return ""; + +	// trim leading spaces +	while ( iswspace(*lpsz) ) +		lpsz++; + +	l = (int)strlen(lpsz); + +	if (!l) +		return ""; + +	if (l <= MaxLen) +	{ +		strcpy(s, lpsz); +	} +	else +	{ +		memcpy(s, lpsz, MaxLen); +		s[MaxLen] = '.'; +		s[MaxLen+1] = '.'; +		s[MaxLen+2] = '.'; +		s[MaxLen+3] = 0; +	} + +	if (!s) +		return NULL; + +	// convert line breaks and tabs to spaces + +	p = s; + +	while (*p) +	{ +		if ( iswspace(*p) ) +			*p = ' '; +		p++; +	} + +	return s; +} + +static void InitListView(HWND AHLV) +{ +	LV_ITEM lvTIt; +	int I; +    char *S; +	char S1[128]; +	STICKYNOTE *pNote; +	TREEELEMENT *TTE; + +	char *V = Translate("Visible"); +	char *T = Translate("Top"); + +	ListView_SetHoverTime(AHLV,700); +	ListView_SetExtendedListViewStyle(AHLV,LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES | LVS_EX_TRACKSELECT); +	ListView_DeleteAllItems(AHLV); + +	I = 0; +	TTE = g_Stickies; +	while (TTE) +	{ +		pNote = (STICKYNOTE*)TTE->ptrdata; + +		lvTIt.mask = LVIF_TEXT; + +		if (!pNote->CustomTitle || !pNote->title) +			GetTriggerTimeString(&pNote->ID, S1, sizeof(S1), TRUE); + +		lvTIt.iItem = I; +		lvTIt.iSubItem = 0; +		lvTIt.pszText = (pNote->CustomTitle && pNote->title) ? pNote->title : S1; +		lvTIt.cchTextMax = (int)strlen(S1); +		ListView_InsertItem(AHLV,&lvTIt); + +		if (pNote->Visible) +		{ +			lvTIt.iItem = I; +			lvTIt.iSubItem = 1; +			lvTIt.pszText = V; +			lvTIt.cchTextMax = (int)strlen(lvTIt.pszText); +			ListView_SetItem(AHLV,&lvTIt); +		} + +		if (pNote->OnTop) +		{ +			lvTIt.iItem = I; +			lvTIt.iSubItem = 2; +			lvTIt.pszText = T; +			lvTIt.cchTextMax = (int)strlen(lvTIt.pszText); +			ListView_SetItem(AHLV,&lvTIt); +		} + +		S = GetPreviewString(pNote->data); +		lvTIt.iItem = I; +		lvTIt.iSubItem = 3; +		lvTIt.pszText = S; +		lvTIt.cchTextMax = (int)strlen(S); +		ListView_SetItem(AHLV,&lvTIt); + +		I++; +		TTE = (TREEELEMENT*)TTE->next; +	} + +	ListView_SetItemState(AHLV,0,LVIS_SELECTED,LVIS_SELECTED); +} + +static BOOL DoListContextMenu(HWND AhWnd,WPARAM wParam,LPARAM lParam,STICKYNOTE *pNote) +{ +	HWND hwndListView; +    HMENU hMenuLoad,FhMenu; +	MENUITEMINFO mii; + +	hwndListView = (HWND)wParam; +	if (hwndListView != GetDlgItem(AhWnd,IDC_LISTREMINDERS)) return FALSE; +	hMenuLoad = LoadMenu(hinstance,"MNU_NOTELISTPOPUP"); +	FhMenu = GetSubMenu(hMenuLoad,0); + +	mii.cbSize = sizeof(mii); +	mii.fMask = MIIM_STATE; +	mii.fState = MFS_DEFAULT; +	if (!pNote) +		mii.fState |= MFS_GRAYED; +	SetMenuItemInfo(FhMenu, ID_CONTEXTMENUNOTELISTVIEW_EDITNOTE, FALSE, &mii); + +	if (!pNote) +	{ +		EnableMenuItem(FhMenu, IDM_REMOVENOTE, MF_GRAYED|MF_BYCOMMAND); +		EnableMenuItem(FhMenu, ID_CONTEXTMENUNOTELISTVIEW_TOGGLEVISIBILITY, MF_GRAYED|MF_BYCOMMAND); +		EnableMenuItem(FhMenu, IDM_TOGGLEONTOP, MF_GRAYED|MF_BYCOMMAND); +	} +	else +	{ +		if (pNote->Visible) +			CheckMenuItem(FhMenu, ID_CONTEXTMENUNOTELISTVIEW_TOGGLEVISIBILITY, MF_CHECKED|MF_BYCOMMAND); +		if (pNote->OnTop) +			CheckMenuItem(FhMenu, IDM_TOGGLEONTOP, MF_CHECKED|MF_BYCOMMAND); +	} + +    CallService(MS_LANGPACK_TRANSLATEMENU,(DWORD)FhMenu,0); +	TrackPopupMenu(FhMenu,TPM_LEFTALIGN | TPM_RIGHTBUTTON,LOWORD(lParam),HIWORD(lParam),0,AhWnd,0); +	DestroyMenu(hMenuLoad); + +	return TRUE; +} + + +INT_PTR CALLBACK DlgProcViewNotes(HWND Dialog,UINT Message,WPARAM wParam,LPARAM lParam) +{ +    LV_COLUMN lvCol; +    NMLISTVIEW *NM; +    TCHAR *S; +    int I; + +	switch (Message) +	{ +	case WM_SIZE: +		{ +			OnListResize(Dialog); +			UpdateGeomFromWnd(Dialog, g_notesListGeom, NULL, 0); +			break; +		} +	case WM_MOVE: +		UpdateGeomFromWnd(Dialog, g_notesListGeom, NULL, 0); +		break; +	case WM_GETMINMAXINFO: +		{ +			MINMAXINFO *mm = (MINMAXINFO*)lParam; +			mm->ptMinTrackSize.x = 394; +			mm->ptMinTrackSize.y = 300; +		} +		return 0; +	case WM_RELOAD: +		{ +			SetDlgItemText(Dialog,IDC_REMINDERDATA,""); +			InitListView(GetDlgItem(Dialog,IDC_LISTREMINDERS)); +			return TRUE; +		} +	case WM_CONTEXTMENU: +		{ +			HWND H; +			STICKYNOTE *pNote = NULL; + +			H = GetDlgItem(Dialog,IDC_LISTREMINDERS); +			if ( ListView_GetSelectedCount(H) ) +			{ +				I = ListView_GetSelectionMark(H); +				if (I != -1) +				{ +					pNote = (STICKYNOTE*)TreeGetAt(g_Stickies, I); +				} +			} + +			if (DoListContextMenu(Dialog, wParam, lParam, pNote)) +				return TRUE; +		} +		break; +	case WM_INITDIALOG: +		{ +			HWND H; + +			HICON hIcon = Skin_GetIconByHandle(iconList[13].hIcolib, ICON_SMALL); +			SendMessage(Dialog, WM_SETICON, (WPARAM)ICON_SMALL, (LPARAM)hIcon); +			hIcon = Skin_GetIconByHandle(iconList[13].hIcolib, ICON_BIG); +			SendMessage(Dialog, WM_SETICON, (WPARAM)ICON_BIG, (LPARAM)hIcon); + +			SetWindowText(Dialog, LPGENT("Notes")); + +			TranslateDialogDefault(Dialog); + +			SetDlgItemText(Dialog,IDC_REMINDERDATA, _T("")); + +			H = GetDlgItem(Dialog,IDC_LISTREMINDERS); +			lvCol.mask = LVCF_TEXT | LVCF_WIDTH; + +			S = TranslateT("Note text"); +			lvCol.pszText = S; +			lvCol.cchTextMax = (int)_tcslen(S); +			lvCol.cx = g_notesListColGeom[3]; +			ListView_InsertColumn(H,0,&lvCol); +			lvCol.mask = LVCF_TEXT | LVCF_WIDTH; + +			S = TranslateT("Top"); +			lvCol.pszText = S; +			lvCol.cchTextMax = (int)_tcslen(S); +			lvCol.cx = g_notesListColGeom[2]; +			ListView_InsertColumn(H,0,&lvCol); +			lvCol.mask = LVCF_TEXT | LVCF_WIDTH; + +			S = TranslateT("Visible"); +			lvCol.pszText = S; +			lvCol.cchTextMax = (int)strlen(S); +			lvCol.cx = g_notesListColGeom[1]; +			ListView_InsertColumn(H,0,&lvCol); +			lvCol.mask = LVCF_TEXT | LVCF_WIDTH; + +			S = TranslateT("Date/Title"); +			lvCol.pszText = S; +			lvCol.cchTextMax = (int)_tcslen(S); +			lvCol.cx = g_notesListColGeom[0]; +			ListView_InsertColumn(H,0,&lvCol); + +			InitListView(H); +			SetWindowLongPtr(GetDlgItem(H, 0), GWL_ID, IDC_LISTREMINDERS_HEADER); +			LV = Dialog; + +			if (g_notesListGeom[1] && g_notesListGeom[2]) +			{ +				WINDOWPLACEMENT wp; +				wp.length = sizeof(WINDOWPLACEMENT); +				GetWindowPlacement(Dialog, &wp); +				wp.rcNormalPosition.left = g_notesListGeom[0]; +				wp.rcNormalPosition.top = g_notesListGeom[1]; +				wp.rcNormalPosition.right = g_notesListGeom[2] + g_notesListGeom[0]; +				wp.rcNormalPosition.bottom = g_notesListGeom[3] + g_notesListGeom[1]; +				SetWindowPlacement(Dialog, &wp); +			} +			return TRUE; +		} +	case WM_CLOSE: +		DestroyWindow(Dialog); +		ListNotesVisible = FALSE; +		return TRUE; + +	case WM_DESTROY: +		ListNotesVisible = FALSE; +		Skin_ReleaseIcon((HICON)SendMessage(Dialog, WM_SETICON, ICON_BIG, 0)); +		Skin_ReleaseIcon((HICON)SendMessage(Dialog, WM_SETICON, ICON_SMALL, 0)); +		return TRUE; + +	case WM_NOTIFY: +		{ +			if (wParam == IDC_LISTREMINDERS) +			{ +				NM = (NMLISTVIEW *)lParam; +				switch (NM->hdr.code) +				{ +				case LVN_ITEMCHANGED: +					{ +						S = ((STICKYNOTE*)TreeGetAt(g_Stickies,NM->iItem))->data; +					    SetDlgItemText(Dialog,IDC_REMINDERDATA,S); +					} +					break; +				case NM_DBLCLK: +					{ +						HWND H; + +						H = GetDlgItem(Dialog,IDC_LISTREMINDERS); +						if ( ListView_GetSelectedCount(H) ) +						{ +							I = ListView_GetSelectionMark(H); +							if (I != -1) +							{ +								EditNote((STICKYNOTE *)TreeGetAt(g_Stickies, I)); +							} +						} +					} +					break; +				} +			} +			else if (wParam == IDC_LISTREMINDERS_HEADER) +			{ +				NMHEADER *NM = (NMHEADER*)lParam; +				switch (NM->hdr.code) +				{ +				case HDN_ENDTRACK: +					UpdateGeomFromWnd(Dialog, NULL, g_notesListColGeom, SIZEOF(g_notesListColGeom)); +					break; +				} +			} +		} +		break; +	case WM_COMMAND: +		{ +			switch(LOWORD(wParam)) +			{ +			case ID_CONTEXTMENUNOTELISTVIEW_EDITNOTE: +				{ +					HWND H; + +					H = GetDlgItem(Dialog,IDC_LISTREMINDERS); +					if ( ListView_GetSelectedCount(H) ) +					{ +						I = ListView_GetSelectionMark(H); +						if (I != -1) +						{ +							EditNote((STICKYNOTE*)TreeGetAt(g_Stickies, I)); +						} +					} +				} +				return TRUE; +			case ID_CONTEXTMENUNOTELISTVIEW_TOGGLEVISIBILITY: +				{ +					HWND H; + +					H = GetDlgItem(Dialog,IDC_LISTREMINDERS); +					if ( ListView_GetSelectedCount(H) ) +					{ +						I = ListView_GetSelectionMark(H); +						if (I != -1) +						{ +							STICKYNOTE *SN = (STICKYNOTE*)TreeGetAt(g_Stickies, I); +							SN->Visible = !SN->Visible; +							ShowWindow(SN->SNHwnd,SN->Visible?SW_SHOWNA:SW_HIDE); +							JustSaveNotes(); +						} +					} +				} +				return TRUE; +			case IDM_TOGGLEONTOP: +				{ +					HWND H; + +					H = GetDlgItem(Dialog,IDC_LISTREMINDERS); +					if ( ListView_GetSelectedCount(H) ) +					{ +						I = ListView_GetSelectionMark(H); +						if (I != -1) +						{ +							STICKYNOTE *SN = (STICKYNOTE*)TreeGetAt(g_Stickies,I); +							SN->OnTop = !SN->OnTop; +							SetWindowPos(SN->SNHwnd, SN->OnTop ? HWND_TOPMOST : HWND_NOTOPMOST, 0,0,0,0, SWP_SHOWWINDOW|SWP_NOMOVE|SWP_NOSIZE); +							RedrawWindow(SN->SNHwnd, NULL, NULL, RDW_FRAME|RDW_INVALIDATE|RDW_UPDATENOW); +							JustSaveNotes(); +						} +					} +				} +				return TRUE; +			case IDC_CLOSE: +				{ +					DestroyWindow(Dialog); +					ListNotesVisible = FALSE; +					return TRUE; +				} +			case ID_CONTEXTMENUNOTEPOPUP_NEWNOTE: +			case IDC_ADDNEWREMINDER: +				{ +					PluginMenuCommandAddNew(0,0); +					return TRUE; +				} +			case ID_CONTEXTMENUNOTELISTVIEW_DELETEALLNOTES: +				{ +					PluginMenuCommandDeleteAll(0,0); +					return TRUE; +				} +			case IDM_REMOVENOTE: +				{ +					HWND H; + +					H = GetDlgItem(Dialog,IDC_LISTREMINDERS); +					if ( ListView_GetSelectedCount(H) ) +					{ +						I = ListView_GetSelectionMark(H); +						if (I != -1) +						{ +							OnDeleteNote(Dialog, (STICKYNOTE*)TreeGetAt(g_Stickies, I)); +						} +					} +				} +				return TRUE; +			case ID_CONTEXTMENUNOTELISTVIEW_SHOW: +				{ +					ShowHideNotes(); +					return TRUE; +				} +			case ID_CONTEXTMENUNOTEPOPUP_BRINGALLTOTOP: +				{ +					BringAllNotesToFront(NULL); +					return TRUE; +				} +			} +		} +	} +	return FALSE; +}  | 
