--- ../src/mwin/winuser.c	2010-03-12 07:40:24.000000000 +0100
+++ mwin/winuser.c	2010-04-23 18:24:38.000000000 +0200
@@ -13,6 +13,8 @@
  *  2003/09/24  Gabriele Brugnoni       WA_ACTIVE with WA_INACTIVE is sent before changing
  *                                      the pointer focus variable.
  *  2003/09/24  Gabriele Brugnoni       Implemented WM_SYSCHAR for ALT-Key
+ *  2010/04/23	Ludwig Ertl				Fixed KillTimer to work in TimerProc for current timer
+ *  									Implemented SetProp/GetProp/RemoveProp
  */
 #include "windows.h"
 #include "wintern.h"
@@ -47,10 +49,20 @@
 	UINT	uTimeout;	/* timeout value, in msecs*/
 	DWORD	dwClockExpires;	/* GetTickCount timer expiration value*/
 	TIMERPROC lpTimerFunc;	/* callback function*/
+	BOOL   bRemove;		/* Remove timer entry on next run */
 	struct timer *next;
 };
 static struct timer *timerList = NULL;	/* global timer list*/
 
+/* property */
+struct mwprop
+{
+	MWLIST link;
+	ATOM Atom;
+	HANDLE hData;
+};
+
+
 static void MwOffsetChildren(HWND hwnd, int offx, int offy);
 static void MwRemoveWndFromTimers(HWND hwnd);
 
@@ -524,6 +536,16 @@
 			p = p->next;
 	}
 
+	/*
+	 * Remove all properties from this window.
+	 */
+	for(p=hwnd->props.head; p; ) {
+		struct mwprop *pProp = GdItemAddr(p, struct mwprop, link);
+		p = p->next;
+		GdListRemove (&hwnd->props, &pProp->link);
+		GdItemFree (pProp);
+	}
+
 	/* FIXME: destroy hdc's relating to window?*/
 
 	if (wp == capturewp) {
@@ -1144,6 +1166,102 @@
 	return oldval;
 }
 
+/* -------------- begin STATIC atom functions --------------
+ *
+ * FIXME:
+ * MicroWindows currently doesn't have functions for handling the Atom
+ * table.
+ *
+ * Therefore we are just implementing a stupid function that calculates
+ * a "unique" value from a string and returns this as an "atom" so that
+ * out property methods can work as expected.
+ *
+ * TODO: Replace them by correct Atom handling functions.
+ */
+static
+ATOM WINAPI
+GlobalFindAtom(LPCSTR lpString)
+{
+	char *p;
+	ATOM atom = 0;
+
+	for (p = lpString; *p; p++)
+		atom=((atom+*p)%0xFFFF);
+}
+
+static
+ATOM WINAPI
+GlobalAddAtom(LPCSTR lpString)
+{
+	return GlobalFindAtom (lpString);
+}
+
+/* -------------- end STATIC atom functions -------------- */
+
+BOOL WINAPI
+SetProp(HWND hWnd, LPCSTR lpString, HANDLE hData)
+{
+	int i;
+	struct mwprop *pProp;
+
+	if (!(pProp = GdItemNew(struct mwprop))) return FALSE;
+	if (HIWORD(lpString))
+		pProp->Atom = GlobalAddAtom(lpString);
+	else
+		pProp->Atom = LOWORD((DWORD)lpString);
+	pProp->hData = hData;
+
+	GdListAdd (&hWnd->props, &pProp->link);
+	return TRUE;
+}
+
+HANDLE WINAPI
+GetProp(HWND hWnd, LPCSTR lpString)
+{
+	ATOM Atom;
+	PMWLIST p;
+	struct mwprop *pProp;
+
+	if (HIWORD(lpString))
+		Atom = GlobalFindAtom(lpString);
+	else
+		Atom = LOWORD((DWORD)lpString);
+
+	for(p=hWnd->props.head; p; p=p->next)
+	{
+		pProp = GdItemAddr(p, struct mwprop, link);
+		if (pProp->Atom == Atom) return pProp->hData;
+	}
+	return NULL;
+}
+
+HANDLE WINAPI
+RemoveProp(HWND hWnd, LPCSTR lpString)
+{
+	ATOM Atom;
+	PMWLIST p;
+	struct mwprop *pProp;
+	HANDLE hRet;
+
+	if (HIWORD(lpString))
+		Atom = GlobalFindAtom(lpString);
+	else
+		Atom = LOWORD((DWORD)lpString);
+
+	for(p=hWnd->props.head; p; p=p->next)
+	{
+		pProp = GdItemAddr(p, struct mwprop, link);
+		if (pProp->Atom == Atom)
+		{
+			hRet = pProp->hData;
+			GdListRemove (&hWnd->props, &pProp->link);
+			GdItemFree (pProp);
+			return hRet;
+		}
+	}
+	return NULL;
+}
+
 DWORD WINAPI
 GetClassLong(HWND hwnd, int nIndex)
 {
@@ -1428,6 +1546,7 @@
 	tm->dwClockExpires = GetTickCount() + uTimeout;
 	tm->lpTimerFunc = lpTimerFunc;
 	tm->next = timerList;
+	tm->bRemove = FALSE;
 	timerList = tm;
 
 	return tm->idTimer;
@@ -1436,21 +1555,15 @@
 BOOL WINAPI
 KillTimer(HWND hwnd, UINT idTimer)
 {
-	struct timer *tm = timerList;
-	struct timer *ltm = NULL;
+	struct timer *tm;
 
-	while ( tm != NULL ) {
-		if( (tm->hwnd == hwnd) && (tm->idTimer == idTimer) ) {
-			if( ltm != NULL )
-				ltm->next = tm->next;
-			else
-				timerList = tm->next;
-			
-			free ( tm );
-			return TRUE;
-		}
-		ltm = tm;
-		tm = tm->next;
+	// cspert: Just mark it for removal, actual
+	// removal will be done in MwHandleTimers, otherwise killing a
+	// timer in a TimerProc will end up with memory errors
+	for (tm=timerList; tm != NULL; tm = tm->next)
+	{
+		if( (tm->hwnd == hwnd) && (tm->idTimer == idTimer) )
+			return tm->bRemove = TRUE;
 	}
 	return FALSE;
 }
@@ -1488,19 +1601,36 @@
 {
 	DWORD	dwTime = 0;	/* should be system time in UTC*/
 	struct timer *tm = timerList;
+	struct timer *ltm = NULL;
 
 	while ( tm != NULL ) {
-		if( GetTickCount() >= tm->dwClockExpires ) {
-			/* call timer function or post timer message*/
-			if( tm->lpTimerFunc )
-				tm->lpTimerFunc ( tm->hwnd, WM_TIMER, tm->idTimer, dwTime );
-			else
-				PostMessage ( tm->hwnd, WM_TIMER, tm->idTimer, 0 );
+		if ( !tm->bRemove )
+		{
+			if( GetTickCount() >= tm->dwClockExpires ) {
+				/* call timer function or post timer message*/
+				if( tm->lpTimerFunc )
+					tm->lpTimerFunc ( tm->hwnd, WM_TIMER, tm->idTimer, dwTime );
+				else
+					PostMessage ( tm->hwnd, WM_TIMER, tm->idTimer, 0 );
 
-			/* reset timer*/
-			tm->dwClockExpires = GetTickCount() + tm->uTimeout;
+				/* reset timer*/
+				tm->dwClockExpires = GetTickCount() + tm->uTimeout;
+			}
+		}
+		if ( tm->bRemove )
+		{
+			if( ltm != NULL )
+				ltm->next = tm->next;
+			else
+				timerList = tm->next;
+			free ( tm );
+			tm = ltm?ltm->next:timerList;
+		}
+		else
+		{
+			ltm = tm;
+			tm = tm->next;
 		}
-		tm = tm->next;
 	}
 }
 
