Release 940620

Mon Jun 20 14:26:41 1994  Bob Amstadt  (bob@pooh)

	* [objects/bitmap.c]
	Allow negative bitmap sizes.

Sun Jun 19 12:00:04 1994  David Metcalfe <david@prism.demon.co.uk>

        * [controls/edit.c]
        Improved selection display.  Added processing for WM_SETFONT,
        EM_REPLACESEL, EM_LINELENGTH, EM_UNDO, EM_EMPTYUNDOBUFFER,
        EM_GETHANDLE, EM_SETHANDLE messages.  Text buffer now stored on 
        application's local heap.

        * [windows/graphics.c]
        Corrected bug in Rectangle().  XFillRectangle has the same
        width as Rectangle, but XDrawRectangle is one pixel wider
        for the same co-ordinates.

        * [memory/heap.c] [include/heap.h]
        Added HEAP_LocalSize function.

        * [windows/event.c] [windows/keyboard.c]
        Improvements to KeyStateTable and addition of AsyncKeyStateTable.
        Added supporting code to GetKeyState and GetAsyncKeyState and
        merged mouse button states into GetKeyboardState.

        * [loader/resource.c] [include/accel.h]
        Added recognition of SHIFT, CONTROL and ALT keys to
        TranslateAccelerator.

        * [objects/metafile.c] [objects/font.c] [objects/bitblt.c]
        A bit more metafile support.

Sun Jun 19 17:29:00 MET DST 1994  Erik Bos (erik@hacktic.nl)

        * [loader/resource.c]
        SizeofResource() and AllocResource() added, AccessResource() updated.

        * [if1632/kernel.spec]
        FreeLibrary() used for FreeModule().

        * [windows/graphics.c]
        Rectangle(): swap left & right corners when right < left,
        swap top & bottom when botton < top.

Jun 19, 94 martin2@trgcorp.solucorp.qc.ca (Martin Ayotte)

	* [controls/combo.c]
	Fix bug in window style of the associated listbox.

	* [controls/menu.c]
	Skip separators in keyboard navigation by using new internal 
		functions SelectPrevItem() & SelectNextItem(),

	* [misc/profile.c]
	Bug fix in GetPrivateProfileInt(), was limited to 4 digit,
		IntBuf must be alloc to (5+1)=6. char instead of 5.

	* [misc/main.c]
	Put code in functions SetEnvironment() & GetEnvironment().

	* [misc/shell.c]
	Start putting some code in ExtractIcon() function.

	* [misc/mmsystem.c]
	Some code for MMTimer functions & timers list.

	* [miscemu/int31.c]
	Few stubs for DPMI interrupt calls. Nothing work yet.

Mon Jun 20 07:37:43 EDT 1994	John Richardson (jrichard@cs.uml.edu)

	* include/win.h (tagWND):
	Added icon fields icon, hIcon and rectClientSave to 
	the tagWND struct.

	* windows/Imakefile
	Added icon.c to the list of files to compile

	* windows/dce.c (GetDCEx):
	Added some checks for iconic mode and pass icon window as drawable,
	not the real window.

	* windows/defwnd.c (DefWindowProc)
	Added PAINTICON default windows procedure.

	* windows/event.c (EVENT_Expose)
	Added check for iconic window expose. If iconic window is exposed
	send a WM_PAINTICON message

	* windows/icon.c 
	New file.  ICON_Iconify, ICON_findIconFromPoint, ICON_Deiconify.

	* windows/mdi.c (DefMDIChildProc)
	Test for IsIconic during a SC_RESTORE, this doesn't work yet.

	* windows/message.c (hardware_event)
	Looks for icon as well as window now.

	* windows/nonclient.c (NC_HandleSysCommand, NC_DoNCPaintIcon)
	Added iconify/deiconify in NC_HandleSysCommand, new function
	NC_DoNCPaintIcon which paints an icon.

	* windows/painting.c (BeginPaint)
	Made a BeginPaint select the STOCK_BLACK_PEN, STOCK_WHITE_BRUSH,
	and STOCK_SYSTEM_FONT objects since this is (hopefully) default
	windows behavior.

	* windows/win.h (CreateWindowEx)
	Set the default background color of a window to be white.
	Create icon window, turn off MINIMIZE if it is on, since
	I don't know what to do with it as of yet... register
	the icon with the hwnd of its window so we can identify where
	icon messages are coming from.

Mon Jun 20 10:15:59 1994  Miguel de Icaza  (miguel@sphinx)

	* windows/event.c: Added a hack to define XPointer when using
	X11R4. 

	* toolkit/hello.c: Test application for WineLib. To compile you'll
	need: gcc -Iinclude -DWINELIB -g hello.c -c, and to link you'll
	need: gcc hello.o libwine.a -lX11 -L/usr/openwin/lib -lm 

	* toolkit/heap.c: Extended the size of the block size per chunk.

	* misc/stress.c (GetFreeFileHandles): Fixed typo.

	* misc/main.c (main): Changes to allow compilation under SunOS. 

	* loader/library.c: Changed some ifdefs to compile WineLib.
diff --git a/ChangeLog b/ChangeLog
index 001d4ad..0e61684 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,137 @@
 ----------------------------------------------------------------------
+Mon Jun 20 14:26:41 1994  Bob Amstadt  (bob@pooh)
+
+	* [objects/bitmap.c]
+	Allow negative bitmap sizes.
+
+Sun Jun 19 12:00:04 1994  David Metcalfe <david@prism.demon.co.uk>
+
+        * [controls/edit.c]
+        Improved selection display.  Added processing for WM_SETFONT,
+        EM_REPLACESEL, EM_LINELENGTH, EM_UNDO, EM_EMPTYUNDOBUFFER,
+        EM_GETHANDLE, EM_SETHANDLE messages.  Text buffer now stored on 
+        application's local heap.
+
+        * [windows/graphics.c]
+        Corrected bug in Rectangle().  XFillRectangle has the same
+        width as Rectangle, but XDrawRectangle is one pixel wider
+        for the same co-ordinates.
+
+        * [memory/heap.c] [include/heap.h]
+        Added HEAP_LocalSize function.
+
+        * [windows/event.c] [windows/keyboard.c]
+        Improvements to KeyStateTable and addition of AsyncKeyStateTable.
+        Added supporting code to GetKeyState and GetAsyncKeyState and
+        merged mouse button states into GetKeyboardState.
+
+        * [loader/resource.c] [include/accel.h]
+        Added recognition of SHIFT, CONTROL and ALT keys to
+        TranslateAccelerator.
+
+        * [objects/metafile.c] [objects/font.c] [objects/bitblt.c]
+        A bit more metafile support.
+
+Sun Jun 19 17:29:00 MET DST 1994  Erik Bos (erik@hacktic.nl)
+
+        * [loader/resource.c]
+        SizeofResource() and AllocResource() added, AccessResource() updated.
+
+        * [if1632/kernel.spec]
+        FreeLibrary() used for FreeModule().
+
+        * [windows/graphics.c]
+        Rectangle(): swap left & right corners when right < left,
+        swap top & bottom when botton < top.
+
+Jun 19, 94 martin2@trgcorp.solucorp.qc.ca (Martin Ayotte)
+
+	* [controls/combo.c]
+	Fix bug in window style of the associated listbox.
+
+	* [controls/menu.c]
+	Skip separators in keyboard navigation by using new internal 
+		functions SelectPrevItem() & SelectNextItem(),
+
+	* [misc/profile.c]
+	Bug fix in GetPrivateProfileInt(), was limited to 4 digit,
+		IntBuf must be alloc to (5+1)=6. char instead of 5.
+
+	* [misc/main.c]
+	Put code in functions SetEnvironment() & GetEnvironment().
+
+	* [misc/shell.c]
+	Start putting some code in ExtractIcon() function.
+
+	* [misc/mmsystem.c]
+	Some code for MMTimer functions & timers list.
+
+	* [miscemu/int31.c]
+	Few stubs for DPMI interrupt calls. Nothing work yet.
+
+Mon Jun 20 07:37:43 EDT 1994	John Richardson (jrichard@cs.uml.edu)
+
+	* include/win.h (tagWND):
+	Added icon fields icon, hIcon and rectClientSave to 
+	the tagWND struct.
+
+	* windows/Imakefile
+	Added icon.c to the list of files to compile
+
+	* windows/dce.c (GetDCEx):
+	Added some checks for iconic mode and pass icon window as drawable,
+	not the real window.
+
+	* windows/defwnd.c (DefWindowProc)
+	Added PAINTICON default windows procedure.
+
+	* windows/event.c (EVENT_Expose)
+	Added check for iconic window expose. If iconic window is exposed
+	send a WM_PAINTICON message
+
+	* windows/icon.c 
+	New file.  ICON_Iconify, ICON_findIconFromPoint, ICON_Deiconify.
+
+	* windows/mdi.c (DefMDIChildProc)
+	Test for IsIconic during a SC_RESTORE, this doesn't work yet.
+
+	* windows/message.c (hardware_event)
+	Looks for icon as well as window now.
+
+	* windows/nonclient.c (NC_HandleSysCommand, NC_DoNCPaintIcon)
+	Added iconify/deiconify in NC_HandleSysCommand, new function
+	NC_DoNCPaintIcon which paints an icon.
+
+	* windows/painting.c (BeginPaint)
+	Made a BeginPaint select the STOCK_BLACK_PEN, STOCK_WHITE_BRUSH,
+	and STOCK_SYSTEM_FONT objects since this is (hopefully) default
+	windows behavior.
+
+	* windows/win.h (CreateWindowEx)
+	Set the default background color of a window to be white.
+	Create icon window, turn off MINIMIZE if it is on, since
+	I don't know what to do with it as of yet... register
+	the icon with the hwnd of its window so we can identify where
+	icon messages are coming from.
+
+Mon Jun 20 10:15:59 1994  Miguel de Icaza  (miguel@sphinx)
+
+	* windows/event.c: Added a hack to define XPointer when using
+	X11R4. 
+
+	* toolkit/hello.c: Test application for WineLib. To compile you'll
+	need: gcc -Iinclude -DWINELIB -g hello.c -c, and to link you'll
+	need: gcc hello.o libwine.a -lX11 -L/usr/openwin/lib -lm 
+
+	* toolkit/heap.c: Extended the size of the block size per chunk.
+
+	* misc/stress.c (GetFreeFileHandles): Fixed typo.
+
+	* misc/main.c (main): Changes to allow compilation under SunOS. 
+
+	* loader/library.c: Changed some ifdefs to compile WineLib.
+
+----------------------------------------------------------------------
 Tue Jun 14 08:09:14 1994  Bob Amstadt  (bob@pooh)
 
 	* loader/selector.c (GetCurrentPDB): 
@@ -16,7 +149,7 @@
 	* windows/event.c (SetCapture): 
 	Set winHasCursor if mouse capture succeeds.
 
-Jun 6, 94 martin2@trgcorp.solucorp.qc.ca (Martin Ayotte)
+Jun 13, 94 martin2@trgcorp.solucorp.qc.ca (Martin Ayotte)
 
 	* [controls/listbox.c]
 	Fix bug in listbox : InsertString should call AddString if -1.
diff --git a/controls/combo.c b/controls/combo.c
index ef6c3b7..d059176 100644
--- a/controls/combo.c
+++ b/controls/combo.c
@@ -78,9 +78,9 @@
 				0, 0, width - bm.bmHeight, bm.bmHeight, 
 				hwnd, 1, wndPtr->hInstance, 0L);
 		lphc->hWndLBox = CreateWindow("LISTBOX", "", 
-			WS_CHILD | WS_CLIPCHILDREN | WS_BORDER | WS_VSCROLL | LBS_NOTIFY,
-			wndPtr->rectClient.left, wndPtr->rectClient.top + bm.bmHeight, 
-			width, height, wndPtr->hwndParent, 1, 
+			WS_POPUP | WS_BORDER | WS_VSCROLL | LBS_NOTIFY,
+			rect.left, rect.top + bm.bmHeight, 
+			width, height, wndPtr->hwndParent, 0, 
 			wndPtr->hInstance, (LPSTR)MAKELONG(0, hwnd));
 		ShowWindow(lphc->hWndLBox, SW_HIDE);
 #ifdef DEBUG_COMBO
diff --git a/controls/edit.c b/controls/edit.c
index abafcfe..3aff8f8 100644
--- a/controls/edit.c
+++ b/controls/edit.c
@@ -3,7 +3,7 @@
  *
  * Copyright  David W. Metcalfe, 1994
  *
- * Release 1, April 1994
+ * Release 2, June 1994
  */
 
 static char Copyright[] = "Copyright  David W. Metcalfe, 1994";
@@ -11,11 +11,13 @@
 #include <stdlib.h>
 #include <string.h>
 #include <windows.h>
+#include <heap.h>
 #include "win.h"
 #include "class.h"
 #include "user.h"
+#include "scroll.h"
 
-#define DEBUG_EDIT /* */
+/* #define DEBUG_EDIT /* */
 
 #define NOTIFY_PARENT(hWndCntrl, wNotifyCode) \
 	SendMessage(GetParent(hWndCntrl), WM_COMMAND, \
@@ -44,6 +46,7 @@
     int textwidth;           /* width of longest line in pixels */
     RECT fmtrc;              /* rectangle in which to format text */
     int txtht;               /* height of text line in pixels */
+    MDESC **localheap;       /* pointer to application's local heap */
     HANDLE hText;            /* handle to text buffer */
     HANDLE hCharWidths;      /* widths of chars in font */
     HANDLE hTextPtrs;        /* list of line offsets */
@@ -59,6 +62,11 @@
     int SelBegCol;           /* beginning column of selection */
     int SelEndLine;          /* ending line of selection */
     int SelEndCol;           /* ending column of selection */
+    HFONT hFont;             /* handle of current font (if not default) */
+    HANDLE hDeletedText;     /* handle to deleted txet buffer for undo */
+    int DeletedLength;       /* length of deleted text */
+    int DeletedCurrLine;     /* starting line from which text was deleted */
+    int DeletedCurrCol;      /* starting col from which text was deleted */
 } EDITSTATE;
 
 
@@ -69,8 +77,8 @@
 #define EditBufLen(wndPtr) (wndPtr->dwStyle & ES_MULTILINE \
 			    ? EDITLEN : ENTRYLEN)
 #define CurrChar (EDIT_TextLine(hwnd, es->CurrLine) + es->CurrCol)
-#define SelMarked(es) (es->SelBegLine != -1 && es->SelBegCol != -1 && \
-		       es->SelEndLine != -1 && es->SelEndCol != -1)
+#define SelMarked(es) (es->SelBegLine != 0 || es->SelBegCol != 0 || \
+		       es->SelEndLine != 0 || es->SelEndCol != 0)
 
 /* macros to access window styles */
 #define IsAutoVScroll() (wndPtr->dwStyle & ES_AUTOVSCROLL)
@@ -88,6 +96,7 @@
 
 
 LONG EditWndProc(HWND hWnd, WORD uMsg, WORD wParam, LONG lParam);
+long EDIT_NCCreateMsg(HWND hwnd, LONG lParam);
 long EDIT_CreateMsg(HWND hwnd, LONG lParam);
 void EDIT_ClearTextPointers(HWND hwnd);
 void EDIT_BuildTextPointers(HWND hwnd);
@@ -135,11 +144,24 @@
 int EDIT_TextLineNumber(HWND hwnd, char *lp);
 void EDIT_SetAnchor(HWND hwnd, int row, int col);
 void EDIT_ExtendSel(HWND hwnd, int x, int y);
+void EDIT_WriteSel(HWND hwnd, int y, int start, int end);
 void EDIT_StopMarking(HWND hwnd);
 LONG EDIT_GetLineMsg(HWND hwnd, WORD wParam, LONG lParam);
 LONG EDIT_GetSelMsg(HWND hwnd);
+void EDIT_ReplaceSel(HWND hwnd, LONG lParam);
+void EDIT_InsertText(HWND hwnd, char *str, int len);
 LONG EDIT_LineFromCharMsg(HWND hwnd, WORD wParam);
 LONG EDIT_LineIndexMsg(HWND hwnd, WORD wParam);
+LONG EDIT_LineLengthMsg(HWND hwnd, WORD wParam);
+void EDIT_SetFont(HWND hwnd, WORD wParam, LONG lParam);
+void EDIT_SaveDeletedText(HWND hwnd, char *deltext, int len, int line, 
+			  int col);
+void EDIT_ClearDeletedText(HWND hwnd);
+LONG EDIT_UndoMsg(HWND hwnd);
+unsigned int EDIT_TextAlloc(EDITSTATE *es, int bytes);
+void *EDIT_TextAddr(EDITSTATE *es, unsigned int handle);
+unsigned int EDIT_TextReAlloc(EDITSTATE *es, unsigned int handle, int bytes);
+void EDIT_SetHandleMsg(HWND hwnd, WORD wParam);
 void swap(int *a, int *b);
 
 
@@ -154,13 +176,19 @@
 
     switch (uMsg) {
     case EM_CANUNDO:
-	/* cannot process undo message */
-	lResult = 0L;
+	lResult = es->hDeletedText;
 	break;
 	
+    case EM_EMPTYUNDOBUFFER:
+	EDIT_ClearDeletedText(hwnd);
+	break;
+
     case EM_FMTLINES:
-	printf("edit: cannot process EM_FMTLINES message\n");
-	lResult = 0L;
+	printf("edit: EM_FMTLINES message received\n");
+	if (!wParam)
+	    lResult = 1L;
+	else
+	    lResult = 0L;
 	break;
 
     case EM_GETFIRSTVISIBLELINE:
@@ -168,7 +196,7 @@
 	break;
 
     case EM_GETHANDLE:
-	printf("edit: cannot process EM_GETHANDLE message\n");
+	lResult = es->hText;
 	break;
 
     case EM_GETLINE:
@@ -206,7 +234,10 @@
 	break;
 
     case EM_LIMITTEXT:
-	es->MaxTextLen = wParam;
+	if (wParam)
+	    es->MaxTextLen = wParam;
+	else
+	    es->MaxTextLen = 65000;
 	break;
 
     case EM_LINEFROMCHAR:
@@ -221,7 +252,7 @@
 	break;
 
     case EM_LINELENGTH:
-	printf("edit: cannot process EM_LINELENGTH message\n");
+	lResult = EDIT_LineLengthMsg(hwnd, wParam);
 	break;
 
     case EM_LINESCROLL:
@@ -229,11 +260,14 @@
 	break;
 
     case EM_REPLACESEL:
-	printf("edit: cannot process EM_REPLACESEL message\n");
+	HideCaret(hwnd);
+	EDIT_ReplaceSel(hwnd, lParam);
+	SetCaretPos(es->WndCol, es->WndRow * es->txtht);
+	ShowCaret(hwnd);
 	break;
 
     case EM_SETHANDLE:
-	printf("edit: cannot process EM_SETHANDLE message\n");
+	EDIT_SetHandleMsg(hwnd, wParam);
 	break;
 
     case EM_SETMODIFY:
@@ -268,6 +302,13 @@
 	printf("edit: cannot process EM_SETWORDBREAKPROC message\n");
 	break;
 
+    case EM_UNDO:
+	HideCaret(hwnd);
+	lResult = EDIT_UndoMsg(hwnd);
+	SetCaretPos(es->WndCol, es->WndRow * es->txtht);
+	ShowCaret(hwnd);
+	break;
+
     case WM_CHAR:
 	EDIT_CharMsg(hwnd, wParam);
 	break;
@@ -287,7 +328,7 @@
 	break;
 
     case WM_GETTEXT:
-	textPtr = (LPSTR)EDIT_HEAP_ADDR(es->hText);
+	textPtr = EDIT_TextAddr(es, es->hText);
 	if ((int)wParam > (len = strlen(textPtr)))
 	{
 	    strcpy((char *)lParam, textPtr);
@@ -298,7 +339,7 @@
 	break;
 
     case WM_GETTEXTLENGTH:
-	textPtr = (LPSTR)EDIT_HEAP_ADDR(es->hText);
+	textPtr = EDIT_TextAddr(es, es->hText);
 	lResult = (DWORD)strlen(textPtr);
 	break;
 
@@ -340,6 +381,10 @@
 	lResult = 0;
 	break;
 
+    case WM_NCCREATE:
+	lResult = EDIT_NCCreateMsg(hwnd, lParam);
+	break;
+	
     case WM_PAINT:
 	EDIT_PaintMsg(hwnd);
 	break;
@@ -353,6 +398,10 @@
 	break;
 
     case WM_SETFONT:
+	HideCaret(hwnd);
+	EDIT_SetFont(hwnd, wParam, lParam);
+	SetCaretPos(es->WndCol, es->WndRow * es->txtht);
+	ShowCaret(hwnd);
 	break;
 
     case WM_SETTEXT:
@@ -379,19 +428,17 @@
 
 
 /*********************************************************************
- *  WM_CREATE message function
+ *  WM_NCCREATE message function
  */
 
-long EDIT_CreateMsg(HWND hwnd, LONG lParam)
+long EDIT_NCCreateMsg(HWND hwnd, LONG lParam)
 {
-    HDC hdc;
+    CREATESTRUCT *createStruct = (CREATESTRUCT *)lParam;
     WND *wndPtr = WIN_FindWndPtr(hwnd);
     EDITSTATE *es;
-    CLASS *classPtr;
-    short *charWidths;
-    TEXTMETRIC tm;
-    char *text;
     unsigned int *textPtrs;
+    char *text;
+    int len;
 
     /* allocate space for state variable structure */
     (HANDLE)(*(wndPtr->wExtra)) = 
@@ -401,6 +448,61 @@
     textPtrs = (unsigned int *)EDIT_HEAP_ADDR(es->hTextPtrs);
     es->hCharWidths = EDIT_HEAP_ALLOC(256 * sizeof(short));
 
+    /* --- text buffer */
+    es->localheap = &HEAP_LocalFindHeap(createStruct->hInstance)->free_list;
+    es->MaxTextLen = MAXTEXTLEN + 1;
+    if (!(es->hText))
+    {
+	es->textlen = EditBufLen(wndPtr) + 1;
+	es->hText = EDIT_TextAlloc(es, EditBufLen(wndPtr) + 2);
+	text = EDIT_TextAddr(es, es->hText);
+	memset(text, 0, es->textlen + 2);
+	EDIT_ClearTextPointers(hwnd);
+    }
+    else
+    {
+	if (strlen(createStruct->lpszName) < EditBufLen(wndPtr))
+	{
+	    es->hText = EDIT_TextAlloc(es, EditBufLen(wndPtr) + 2);
+	    es->textlen = EditBufLen(wndPtr) + 1;
+	    *(text + es->textlen) = '\0';
+	}
+	else
+	{
+	    es->hText = EDIT_TextAlloc(es, strlen(createStruct->lpszName) + 2);
+	    es->textlen = strlen(createStruct->lpszName) + 1;
+	}
+	text = EDIT_TextAddr(es, es->hText);
+	*(text + es->textlen + 1) = '\0';
+	EDIT_BuildTextPointers(hwnd);
+    }
+
+    if ((createStruct->style & WS_VSCROLL) || 
+	(createStruct->style & WS_HSCROLL)) NC_CreateScrollBars(hwnd);
+
+    /* remove the WS_CAPTION style if it has been set - this is really a  */
+    /* pseudo option made from a combination of WS_BORDER and WS_DLGFRAME */
+    if (wndPtr->dwStyle & WS_BORDER && wndPtr->dwStyle & WS_DLGFRAME)
+	wndPtr->dwStyle ^= WS_DLGFRAME;
+
+    return 1;
+}
+
+
+/*********************************************************************
+ *  WM_CREATE message function
+ */
+
+long EDIT_CreateMsg(HWND hwnd, LONG lParam)
+{
+    HDC hdc;
+    WND *wndPtr = WIN_FindWndPtr(hwnd);
+    EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
+    CLASS *classPtr;
+    short *charWidths;
+    TEXTMETRIC tm;
+    char *text;
+
     /* initialize state variable structure */
     /* --- char width array */
     hdc = GetDC(hwnd);
@@ -408,24 +510,6 @@
     memset(charWidths, 0, 256 * sizeof(short));
     GetCharWidth(hdc, 0, 255, charWidths);
 
-    /* --- text buffer */
-    es->MaxTextLen = MAXTEXTLEN + 1;
-    if (!(wndPtr->hText))
-    {
-	es->textlen = EditBufLen(wndPtr);
-	es->hText = EDIT_HEAP_ALLOC(EditBufLen(wndPtr) + 2);
-	text = (LPSTR)EDIT_HEAP_ADDR(es->hText);
-	memset(text, 0, es->textlen + 2);
-	EDIT_ClearTextPointers(hwnd);
-    }
-    else
-    {
-	es->hText = wndPtr->hText;
-	wndPtr->hText = 0;
-	es->textlen = GetWindowTextLength(hwnd) + 1;
-	EDIT_BuildTextPointers(hwnd);
-    }
-
     /* --- other structure variables */
     GetTextMetrics(hdc, &tm);
     es->txtht = tm.tmHeight + tm.tmExternalLeading;
@@ -435,8 +519,11 @@
     es->WndCol = es->WndRow = 0;
     es->TextChanged = FALSE;
     es->textwidth = 0;
-    es->SelBegLine = es->SelBegCol = -1;
-    es->SelEndLine = es->SelEndCol = -1;
+    es->SelBegLine = es->SelBegCol = 0;
+    es->SelEndLine = es->SelEndCol = 0;
+    es->hFont = 0;
+    es->hDeletedText = 0;
+    es->DeletedLength = 0;
 
     /* allocate space for a line full of blanks to speed up */
     /* line filling */
@@ -494,7 +581,7 @@
     short *charWidths;
 
     es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
-    text = (char *)EDIT_HEAP_ADDR(es->hText);
+    text = EDIT_TextAddr(es, es->hText);
     textPtrs = (unsigned int *)EDIT_HEAP_ADDR(es->hTextPtrs);
     charWidths = (short *)EDIT_HEAP_ADDR(es->hCharWidths);
 
@@ -627,7 +714,7 @@
 {
     WND *wndPtr = WIN_FindWndPtr(hwnd);
     EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
-    char *text = (char *)EDIT_HEAP_ADDR(es->hText);
+    char *text = EDIT_TextAddr(es, es->hText);
     unsigned int *textPtrs = (unsigned int *)EDIT_HEAP_ADDR(es->hTextPtrs);
 
     return (text + *(textPtrs + sel));
@@ -847,6 +934,7 @@
     int diff, num_spaces;
     HRGN hrgnClip;
     COLORREF oldTextColor, oldBkgdColor;
+    HFONT oldfont;
     WND *wndPtr = WIN_FindWndPtr(hwnd);
     EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
     short *charWidths = (short *)EDIT_HEAP_ADDR(es->hCharWidths);
@@ -861,6 +949,9 @@
     hrgnClip = CreateRectRgnIndirect(rc);
     SelectClipRgn(hdc, hrgnClip);
 
+    if (es->hFont)
+	oldfont = (HFONT)SelectObject(hdc, (HANDLE)es->hFont);
+
     SendMessage(GetParent(hwnd), WM_CTLCOLOR, (WORD)hdc,
 		MAKELPARAM(hwnd, CTLCOLOR_EDIT));
 
@@ -891,6 +982,9 @@
 	}
     }
 
+    if (es->hFont)
+	SelectObject(hdc, (HANDLE)oldfont);
+
     EDIT_HEAP_FREE(hStr);
     ReleaseDC(hwnd, hdc);
 }
@@ -988,7 +1082,7 @@
 {
     WND *wndPtr = WIN_FindWndPtr(hwnd);
     EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
-    char *text = (char *)EDIT_HEAP_ADDR(es->hText);
+    char *text = EDIT_TextAddr(es, es->hText);
     char *currchar = CurrChar;
     RECT rc;
     BOOL FullPaint = FALSE;
@@ -1032,10 +1126,10 @@
 	/* but not above maximum size */
 	if (es->textlen > es->MaxTextLen)
 	    es->textlen = es->MaxTextLen;
-	es->hText = EDIT_HEAP_REALLOC(es->hText, es->textlen + 2);
+	es->hText = EDIT_TextReAlloc(es, es->hText, es->textlen + 2);
 	if (!es->hText)
 	    NOTIFY_PARENT(hwnd, EN_ERRSPACE);
-	text = (char *)EDIT_HEAP_ADDR(es->hText);
+	text = EDIT_TextAddr(es, es->hText);
 	text[es->textlen - 1] = '\0';
 	currchar = CurrChar;
     }
@@ -1122,7 +1216,7 @@
 {
     WND *wndPtr = WIN_FindWndPtr(hwnd);
     EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
-    char *text = (char *)EDIT_HEAP_ADDR(es->hText);
+    char *text = EDIT_TextAddr(es, es->hText);
     char *cc = CurrChar + 1;
 
     if (*cc == '\0')
@@ -1210,7 +1304,7 @@
 {
     WND *wndPtr = WIN_FindWndPtr(hwnd);
     EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
-    char *text = (char *)EDIT_HEAP_ADDR(es->hText);
+    char *text = EDIT_TextAddr(es, es->hText);
 
     if (es->CurrCol)
     {
@@ -1238,7 +1332,7 @@
     RECT rc;
     WND *wndPtr = WIN_FindWndPtr(hwnd);
     EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
-    char *text = (char *)EDIT_HEAP_ADDR(es->hText);
+    char *text = EDIT_TextAddr(es, es->hText);
 
     while (*CurrChar && *CurrChar != '\n')
     {
@@ -1988,8 +2082,8 @@
 	len = strlen((char *)lParam);
 	EDIT_ClearText(hwnd);
 	es->textlen = len;
-	es->hText = EDIT_HEAP_REALLOC(es->hText, len + 3);
-	text = EDIT_HEAP_ADDR(es->hText);
+	es->hText = EDIT_TextReAlloc(es, es->hText, len + 3);
+	text = EDIT_TextAddr(es, es->hText);
 	strcpy(text, (char *)lParam);
 /*	text[len] = '\n'; */ /* Removed by Bob Amstadt */
 	text[len + 1] = '\0';
@@ -2018,8 +2112,8 @@
     unsigned int blen = EditBufLen(wndPtr) + 2;
     char *text;
 
-    es->hText = EDIT_HEAP_REALLOC(es->hText, blen);
-    text = EDIT_HEAP_ADDR(es->hText);
+    es->hText = EDIT_TextReAlloc(es, es->hText, blen);
+    text = EDIT_TextAddr(es, es->hText);
     memset(text, 0, blen);
     es->textlen = 0;
     es->wlines = 0;
@@ -2050,17 +2144,19 @@
     EDIT_GetLineCol(hwnd, so, &(es->SelBegLine), &(es->SelBegCol));
     EDIT_GetLineCol(hwnd, eo, &(es->SelEndLine), &(es->SelEndCol));
 
-    es->CurrLine = es->SelEndLine;
-    es->CurrCol = es->SelEndCol;
-    es->WndRow = es->SelEndLine - es->wtop;
-    if (es->WndRow < 0)
+    if (SelMarked(es))
     {
-	es->wtop = es->SelEndLine;
-	es->WndRow = 0;
+	es->CurrLine = es->SelEndLine;
+	es->CurrCol = es->SelEndCol;
+	es->WndRow = es->SelEndLine - es->wtop;
+	if (es->WndRow < 0)
+	{
+	    es->wtop = es->SelEndLine;
+	    es->WndRow = 0;
+	}
+	es->WndCol = EDIT_LineLength(es, EDIT_TextLine(hwnd, es->SelEndLine), 
+				     es->SelEndCol) - es->wleft;
     }
-    es->WndCol = EDIT_LineLength(es, EDIT_TextLine(hwnd, es->SelEndLine), 
-				 es->SelEndCol) - es->wleft;
-
     InvalidateRect(hwnd, NULL, TRUE);
     UpdateWindow(hwnd);
 }
@@ -2078,9 +2174,17 @@
     char *cp, *cp1;
     WND *wndPtr = WIN_FindWndPtr(hwnd);
     EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
-    char *text = (char *)EDIT_HEAP_ADDR(es->hText);
+    char *text = EDIT_TextAddr(es, es->hText);
     unsigned int *textPtrs = (unsigned int *)EDIT_HEAP_ADDR(es->hTextPtrs);
 
+    /* check for (0,0) */
+    if (!off)
+    {
+	*line = 0;
+	*col = 0;
+	return;
+    }
+
     if (off > strlen(text)) off = strlen(text);
     cp1 = text;
     for (lineno = 0; lineno < es->wlines; lineno++)
@@ -2115,13 +2219,14 @@
     int len;
     WND *wndPtr = WIN_FindWndPtr(hwnd);
     EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
-    char *text = (char *)EDIT_HEAP_ADDR(es->hText);
+    char *text = EDIT_TextAddr(es, es->hText);
 
     if (SelMarked(es))
     {
 	bbl = EDIT_TextLine(hwnd, es->SelBegLine) + es->SelBegCol;
 	bel = EDIT_TextLine(hwnd, es->SelEndLine) + es->SelEndCol;
 	len = (int)(bel - bbl);
+	EDIT_SaveDeletedText(hwnd, bbl, len, es->SelBegLine, es->SelBegCol);
 	es->TextChanged = TRUE;
 	strcpy(bbl, bel);
 
@@ -2154,8 +2259,8 @@
     WND *wndPtr = WIN_FindWndPtr(hwnd);
     EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
 
-    es->SelBegLine = es->SelBegCol = -1;
-    es->SelEndLine = es->SelEndCol = -1;
+    es->SelBegLine = es->SelBegCol = 0;
+    es->SelEndLine = es->SelEndCol = 0;
 
     InvalidateRect(hwnd, NULL, TRUE);
     UpdateWindow(hwnd);
@@ -2175,7 +2280,7 @@
     char *cp;
     WND *wndPtr = WIN_FindWndPtr(hwnd);
     EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
-    char *text = (char *)EDIT_HEAP_ADDR(es->hText);
+    char *text = EDIT_TextAddr(es, es->hText);
     unsigned int *textPtrs = (unsigned int *)EDIT_HEAP_ADDR(es->hTextPtrs);
 
     for (lineno = 0; lineno < es->wlines; lineno++)
@@ -2198,14 +2303,20 @@
 
 void EDIT_SetAnchor(HWND hwnd, int row, int col)
 {
+    BOOL sel = FALSE;
     WND *wndPtr = WIN_FindWndPtr(hwnd);
     EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
 
+    if (SelMarked(es))
+	sel = TRUE;
     EDIT_ClearSel(hwnd);
     es->SelBegLine = es->SelEndLine = row;
     es->SelBegCol = es->SelEndCol = col;
-    InvalidateRect(hwnd, NULL, FALSE);
-    UpdateWindow(hwnd);
+    if (sel)
+    {
+	InvalidateRect(hwnd, NULL, FALSE);
+	UpdateWindow(hwnd);
+    }
 }
 
 
@@ -2217,8 +2328,7 @@
 
 void EDIT_ExtendSel(HWND hwnd, int x, int y)
 {
-    int bbl, bel;
-    int ptop, pbot;
+    int bbl, bel, bbc, bec;
     char *cp, *cp1;
     int len;
     BOOL end = FALSE;
@@ -2229,8 +2339,8 @@
     printf("EDIT_ExtendSel: x=%d, y=%d\n", x, y);
 #endif
 
-    ptop = min(es->SelBegLine, es->SelEndLine);
-    pbot = max(es->SelBegLine, es->SelEndLine);
+    bbl = es->SelEndLine;
+    bbc = es->SelEndCol;
     cp = EDIT_TextLine(hwnd, es->wtop + y / es->txtht);
     cp1 = strchr(cp, '\n');
     len = cp1 ? (int)(cp1 - cp) : 0;
@@ -2251,26 +2361,94 @@
     if (es->WndCol > EDIT_LineLength(es, cp, len) - es->wleft || end)
 	es->WndCol = EDIT_LineLength(es, cp, len) - es->wleft;
     es->CurrCol = EDIT_PixelToChar(hwnd, es->CurrLine, &(es->WndCol));
-    es->SelEndCol = es->CurrCol;
+    es->SelEndCol = es->CurrCol - 1;
 
-    bbl = min(es->SelBegLine, es->SelEndLine);
-    bel = max(es->SelBegLine, es->SelEndLine);
-    while (ptop < bbl)
+    bel = es->SelEndLine;
+    bec = es->SelEndCol;
+
+    /* return if no new characters to mark */
+    if (bbl == bel && bbc == bec)
+	return;
+
+    /* put lowest marker first */
+    if (bbl > bel)
     {
-	EDIT_WriteTextLine(hwnd, NULL, ptop);
-	ptop++;
+	swap(&bbl, &bel);
+	swap(&bbc, &bec);
     }
+    if (bbl == bel && bbc > bec)
+	swap(&bbc, &bec);
+
     for (y = bbl; y <= bel; y++)
-	EDIT_WriteTextLine(hwnd, NULL, y);
-    while (pbot > bel)
     {
-	EDIT_WriteTextLine(hwnd, NULL, pbot);
-	--pbot;
+	if (y == bbl && y == bel)
+	    EDIT_WriteSel(hwnd, y, bbc, bec);
+	else if (y == bbl)
+	    EDIT_WriteSel(hwnd, y, bbc, -1);
+	else if (y == bel)
+	    EDIT_WriteSel(hwnd, y, 0, bec);
+	else
+	    EDIT_WriteSel(hwnd, y, 0, -1);
     }
 }
 
 
 /*********************************************************************
+ *  EDIT_WriteSel
+ *
+ *  Display selection by reversing pixels in selected text.
+ *  If end == -1, selection applies to end of line.
+ */
+
+void EDIT_WriteSel(HWND hwnd, int y, int start, int end)
+{
+    RECT rc;
+    int scol, ecol;
+    char *cp, *cp1;
+    HDC hdc;
+    HBRUSH hbrush, holdbrush;
+    int olddm;
+    WND *wndPtr = WIN_FindWndPtr(hwnd);
+    EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
+
+#ifdef DEBUG_EDIT
+    printf("EDIT_WriteSel: y=%d start=%d end=%d\n", y, start, end);
+#endif
+    GetClientRect(hwnd, &rc);
+
+    /* make sure y is within the window */
+    if (y < es->wtop || y > (es->wtop + ClientHeight(wndPtr, es)))
+	return;
+
+    /* get pointer to text */
+    cp = EDIT_TextLine(hwnd, y);
+
+    /* get length of line if end == -1 */
+    if (end == -1)
+    {
+	cp1 = strchr(cp, '\n');
+	end = cp1 ? (int)(cp1 - cp) : 0;
+    }
+
+    scol = EDIT_LineLength(es, cp, start);
+    if (scol > rc.right) return;
+    if (scol < rc.left) scol = rc.left;
+    ecol = EDIT_LineLength(es, cp, end);
+    if (ecol < rc.left) return;
+    if (ecol > rc.right) ecol = rc.right;
+
+    hdc = GetDC(hwnd);
+    hbrush = GetStockObject(BLACK_BRUSH);
+    holdbrush = (HBRUSH)SelectObject(hdc, (HANDLE)hbrush);
+    olddm = SetROP2(hdc, R2_XORPEN);
+    Rectangle(hdc, scol, y * es->txtht, ecol, (y + 1) * es->txtht);
+    SetROP2(hdc, olddm);
+    SelectObject(hdc, (HANDLE)holdbrush);
+    ReleaseDC(hwnd, hdc);
+}
+
+
+/*********************************************************************
  *  EDIT_StopMarking
  *
  *  Stop text marking (selection).
@@ -2332,6 +2510,53 @@
 
 
 /*********************************************************************
+ *  EM_REPLACESEL message function
+ */
+
+void EDIT_ReplaceSel(HWND hwnd, LONG lParam)
+{
+    EDIT_DeleteSel(hwnd);
+    EDIT_InsertText(hwnd, (char *)lParam, strlen((char *)lParam));
+    InvalidateRect(hwnd, NULL, TRUE);
+    UpdateWindow(hwnd);
+}
+
+
+/*********************************************************************
+ *  EDIT_InsertText
+ *
+ *  Insert text at current line and column.
+ */
+
+void EDIT_InsertText(HWND hwnd, char *str, int len)
+{
+    int plen;
+    WND *wndPtr = WIN_FindWndPtr(hwnd);
+    EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
+    char *text = EDIT_TextAddr(es, es->hText);
+    
+    plen = strlen(text) + len;
+    if (plen + 1 > es->textlen)
+    {
+	es->hText = EDIT_TextReAlloc(es, es->hText, es->textlen + len);
+	es->textlen = plen + 1;
+    }
+    memmove(CurrChar + len, CurrChar, strlen(CurrChar) + 1);
+    memcpy(CurrChar, str, len);
+
+    EDIT_BuildTextPointers(hwnd);
+    es->PaintBkgd = TRUE;
+    es->TextChanged = TRUE;
+
+    EDIT_GetLineCol(hwnd, (int)((CurrChar + len) - text), &(es->CurrLine),
+		                                    &(es->CurrCol));
+    es->WndRow = es->CurrLine - es->wtop;
+    es->WndCol = EDIT_LineLength(es, EDIT_TextLine(hwnd, es->CurrLine),
+				 es->CurrCol) - es->wleft;
+}
+
+
+/*********************************************************************
  *  EM_LINEFROMCHAR message function
  */
 
@@ -2368,6 +2593,239 @@
 
 
 /*********************************************************************
+ *  EM_LINELENGTH message function
+ */
+
+LONG EDIT_LineLengthMsg(HWND hwnd, WORD wParam)
+{
+    int row, col, len;
+    int sbl, sbc, sel, sec;
+    WND *wndPtr = WIN_FindWndPtr(hwnd);
+    EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
+    unsigned int *textPtrs = (unsigned int *)EDIT_HEAP_ADDR(es->hTextPtrs);
+
+    if (wParam == (WORD)-1)
+    {
+	if (SelMarked(es))
+	{
+	    sbl = es->SelBegLine;
+	    sbc = es->SelBegCol;
+	    sel = es->SelEndLine;
+	    sec = es->SelEndCol;
+
+	    if (sbl > sel)
+	    {
+		swap(&sbl, &sel);
+		swap(&sbc, &sec);
+	    }
+	    if (sbl == sel && sbc > sec)
+		swap(&sbc, &sec);
+
+	    if (sbc == sel)
+	    {
+		len = *(textPtrs + sbl + 1) - *(textPtrs + sbl) - 1;
+		return len - sec - sbc;
+	    }
+
+	    len = *(textPtrs + sel + 1) - *(textPtrs + sel) - sec - 1;
+	    return len + sbc;
+	}
+	else    /* no selection marked */
+	{
+	    len = *(textPtrs + es->CurrLine + 1) - 
+		  *(textPtrs + es->CurrLine) - 1;
+	    return len;
+	}
+    }
+    else    /* line number specified */
+    {
+	EDIT_GetLineCol(hwnd, wParam, &row, &col);
+	len = *(textPtrs + row + 1) - *(textPtrs + row);
+	return len;
+    }
+}
+
+
+/*********************************************************************
+ *  WM_SETFONT message function
+ */
+
+void EDIT_SetFont(HWND hwnd, WORD wParam, LONG lParam)
+{
+    HDC hdc;
+    TEXTMETRIC tm;
+    HFONT oldfont;
+    WND *wndPtr = WIN_FindWndPtr(hwnd);
+    EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
+    short *charWidths = (short *)EDIT_HEAP_ADDR(es->hCharWidths);
+
+    es->hFont = wParam;
+    hdc = GetDC(hwnd);
+    oldfont = (HFONT)SelectObject(hdc, (HANDLE)es->hFont);
+    GetCharWidth(hdc, 0, 255, charWidths);
+    GetTextMetrics(hdc, &tm);
+    es->txtht = tm.tmHeight + tm.tmExternalLeading;
+    SelectObject(hdc, (HANDLE)oldfont);
+    ReleaseDC(hwnd, hdc);
+
+    es->WndRow = (es->CurrLine - es->wtop) / es->txtht;
+    es->WndCol = EDIT_LineLength(es, EDIT_TextLine(hwnd, es->CurrLine),
+				 es->CurrCol) - es->wleft;
+
+    InvalidateRect(hwnd, NULL, TRUE);
+    es->PaintBkgd = TRUE;
+    if (lParam) UpdateWindow(hwnd);
+}
+
+
+/*********************************************************************
+ *  EDIT_SaveDeletedText
+ *
+ *  Save deleted text in deleted text buffer.
+ */
+
+void EDIT_SaveDeletedText(HWND hwnd, char *deltext, int len,
+			                  int line, int col)
+{
+    char *text;
+    WND *wndPtr = WIN_FindWndPtr(hwnd);
+    EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
+
+    es->hDeletedText = EDIT_HEAP_REALLOC(es->hDeletedText, len);
+    if (!es->hDeletedText) return;
+    text = (char *)EDIT_HEAP_ADDR(es->hDeletedText);
+    memcpy(text, deltext, len);
+    es->DeletedLength = len;
+    es->DeletedCurrLine = line;
+    es->DeletedCurrCol = col;
+}
+
+
+/*********************************************************************
+ *  EDIT_ClearDeletedText
+ *
+ *  Clear deleted text buffer.
+ */
+
+void EDIT_ClearDeletedText(HWND hwnd)
+{
+    WND *wndPtr = WIN_FindWndPtr(hwnd);
+    EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
+
+    EDIT_HEAP_FREE(es->hDeletedText);
+    es->hDeletedText = 0;
+    es->DeletedLength = 0;
+}
+
+
+/*********************************************************************
+ *  EM_UNDO message function
+ */
+
+LONG EDIT_UndoMsg(HWND hwnd)
+{
+    char *text;
+    WND *wndPtr = WIN_FindWndPtr(hwnd);
+    EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
+    
+    if (es->hDeletedText)
+    {
+	text = (char *)EDIT_HEAP_ADDR(es->hDeletedText);
+	es->CurrLine = es->DeletedCurrLine;
+	es->CurrCol = es->DeletedCurrCol;
+	EDIT_InsertText(hwnd, text, es->DeletedLength);
+	EDIT_ClearDeletedText(hwnd);
+
+	es->SelBegLine = es->CurrLine;
+	es->SelBegCol = es->CurrCol;
+	EDIT_GetLineCol(hwnd, (int)((CurrChar + es->DeletedLength) - text), 
+			&(es->CurrLine), &(es->CurrCol));
+	es->WndRow = es->CurrLine - es->wtop;
+	es->WndCol = EDIT_LineLength(es, EDIT_TextLine(hwnd, es->CurrLine),
+				     es->CurrCol) - es->wleft;
+	es->SelEndLine = es->CurrLine;
+	es->SelEndCol = es->CurrCol;
+
+	InvalidateRect(hwnd, NULL, TRUE);
+	UpdateWindow(hwnd);
+	return 1;
+    }
+    else
+	return 0;
+}
+
+
+/*********************************************************************
+ *  EDIT_TextAlloc
+ *
+ *  Allocate the text buffer.
+ */
+
+unsigned int EDIT_TextAlloc(EDITSTATE *es, int bytes)
+{
+    return ((unsigned int)HEAP_Alloc(es->localheap, GMEM_MOVEABLE,
+				     bytes) & 0xffff);
+}
+
+
+/*********************************************************************
+ *  EDIT_TextAddr
+ *
+ *  Return the address of the text buffer.
+ */
+
+void *EDIT_TextAddr(EDITSTATE *es, unsigned int handle)
+{
+    return ((void *)((handle) ? ((handle) | ((unsigned int)(*(es->localheap))
+					    & 0xffff0000)) : 0));
+}
+
+
+/*********************************************************************
+ *  EDIT_TextReAlloc
+ *
+ *  Reallocate the text buffer.
+ */
+
+unsigned int EDIT_TextReAlloc(EDITSTATE *es, unsigned int handle, int bytes)
+{
+    return ((unsigned int)HEAP_ReAlloc(es->localheap, 
+				       EDIT_TextAddr(es, handle),
+				       bytes, GMEM_MOVEABLE) & 0xffff);
+}
+
+
+/*********************************************************************
+ *  EM_SETHANDLE message function
+ */
+
+void EDIT_SetHandleMsg(HWND hwnd, WORD wParam)
+{
+    MDESC *m;
+    WND *wndPtr = WIN_FindWndPtr(hwnd);
+    EDITSTATE *es = (EDITSTATE *)EDIT_HEAP_ADDR((HANDLE)(*(wndPtr->wExtra)));
+
+    if (IsMultiLine())
+    {
+	es->hText = wParam;
+	es->MaxTextLen = HEAP_LocalSize(es->localheap, es->hText);
+	es->wlines = 0;
+	es->wtop = es->wleft = 0;
+	es->CurrLine = es->CurrCol = 0;
+	es->WndRow = es->WndCol = 0;
+	es->TextChanged = FALSE;
+	es->textwidth = 0;
+	es->SelBegLine = es->SelBegCol = 0;
+	es->SelEndLine = es->SelEndCol = 0;
+
+	es->PaintBkgd = TRUE;
+	InvalidateRect(hwnd, NULL, TRUE);
+	UpdateWindow(hwnd);
+    }
+}
+
+
+/*********************************************************************
  *  Utility functions
  */
 
diff --git a/controls/menu.c b/controls/menu.c
index 58a9865..7b05747 100644
--- a/controls/menu.c
+++ b/controls/menu.c
@@ -37,6 +37,8 @@
 void MenuMouseMove(HWND hWnd, LPPOPUPMENU lppop, WORD wParam, int x, int y);
 void StdDrawPopupMenu(HWND hwnd);
 void ResetHiliteFlags(LPPOPUPMENU lppop);
+void SelectPrevItem(LPPOPUPMENU lppop);
+void SelectNextItem(LPPOPUPMENU lppop);
 BOOL ExecFocusedMenuItem(HWND hWnd, LPPOPUPMENU lppop);
 void MenuItemSelect(HWND hWnd, LPPOPUPMENU lppop, WORD wIndex);
 LPMENUITEM MenuFindItem(LPPOPUPMENU lppop, int x, int y, WORD *lpRet);
@@ -60,6 +62,8 @@
 
 /***********************************************************************
  *           PopupMenuWndProc
+				SetWindow
+				SetWindow
  */
 LONG PopupMenuWndProc( HWND hwnd, WORD message, WORD wParam, LONG lParam )
 {    
@@ -90,6 +94,7 @@
 #ifdef DEBUG_MENU
 		printf("PopupMenu End of WM_CREATE !\n");
 #endif
+		ResetHiliteFlags(lppop);
 		return 0;
 	case WM_DESTROY:
 		lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
@@ -132,6 +137,7 @@
 		lppop = PopupMenuGetWindowAndStorage(hwnd, &wndPtr);
 		if (lppop == NULL) break;
 		if (wParam == 0 && lParam == 0L) {
+			ResetHiliteFlags(lppop);
 			HideAllSubPopupMenu(lppop);
 #ifdef DEBUG_MENU
 			printf("PopupMenuWndProc hWnd=%04X WM_SHOWWINDOW -> HIDE!\n", hwnd);
@@ -144,7 +150,7 @@
 		lppop->FocusedItem = (WORD)-1;
 		if (!lppop->BarFlag) {
 			PopupMenuCalcSize(hwnd);
-			ResetHiliteFlags(lppop);
+/*			ResetHiliteFlags(lppop); */
 #ifdef DEBUG_MENU
 			printf("PopupMenuWndProc hWnd=%04X WM_SHOWWINDOW Width=%d Height=%d !\n", 
 									hwnd, lppop->Width, lppop->Height);
@@ -195,17 +201,11 @@
 				break;
 			case VK_UP:
 				if (lppop->BarFlag) break;
-				if (lppop->FocusedItem < 1) break;
-				MenuItemSelect(hwnd, lppop, lppop->FocusedItem - 1);
+				SelectPrevItem(lppop);
 				break;
 			case VK_DOWN:
 				if (lppop->BarFlag) goto ProceedSPACE;
-				if (lppop->FocusedItem == (WORD)-1) {
-					MenuItemSelect(hwnd, lppop, lppop->FocusedItem + 1);
-					break;
-					}
-				if (lppop->FocusedItem >= lppop->nItems - 1) break;
-				MenuItemSelect(hwnd, lppop, lppop->FocusedItem + 1);
+				SelectNextItem(lppop);
 				break;
 			case VK_LEFT:
 				if (lppop->SysFlag != 0) {
@@ -564,6 +564,53 @@
 }
 
 
+void SelectPrevItem(LPPOPUPMENU lppop)
+{
+	int		nIndex;
+	LPMENUITEM lpitem;
+	if (lppop == NULL) return;
+	nIndex = lppop->FocusedItem;
+	if (nIndex < 1) {
+		if (nIndex == -1)
+			nIndex = 0;
+		else
+			nIndex = lppop->nItems - 1;
+		lpitem = GetMenuItemPtr(lppop, nIndex);
+		}
+	else {
+		nIndex--;
+		lpitem = GetMenuItemPtr(lppop, nIndex);
+		}
+	while (lpitem != NULL && lpitem->item_flags & MF_HILITE) {
+		nIndex--;
+		lpitem = GetMenuItemPtr(lppop, nIndex);
+		}
+	MenuItemSelect(lppop->hWnd, lppop, nIndex);
+}
+
+
+void SelectNextItem(LPPOPUPMENU lppop)
+{
+	int		nIndex;
+	LPMENUITEM lpitem;
+	if (lppop == NULL) return;
+	nIndex = lppop->FocusedItem;
+	if ((nIndex == -1) || (nIndex >= lppop->nItems - 1)) {
+		nIndex = 0;
+		lpitem = GetMenuItemPtr(lppop, nIndex);
+		}
+	else {
+		nIndex++;
+		lpitem = GetMenuItemPtr(lppop, nIndex);
+		}
+	while (lpitem != NULL && (lpitem->item_flags & MF_SEPARATOR)) {
+		nIndex++;
+		lpitem = GetMenuItemPtr(lppop, nIndex);
+		}
+	MenuItemSelect(lppop->hWnd, lppop, nIndex);
+}
+
+
 void ResetHiliteFlags(LPPOPUPMENU lppop)
 {
 	LPMENUITEM lpitem;
@@ -2162,7 +2209,8 @@
 	if (GetCapture() == hWnd) ReleaseCapture();
 	if (wndPtr->window != 0) {
 		flags = SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED;
-		if (!IsWindowVisible(hWnd)) flags |= SWP_NOREDRAW;
+/*		if (!IsWindowVisible(hWnd)) flags |= SWP_NOREDRAW; */
+		flags |= SWP_NOREDRAW;
 		if (hMenu == 0) {
 			wndPtr->wIDmenu = hMenu;
 			printf("SetMenu(%04X, %04X) // Menu removed, need NC recalc!\n", hWnd, hMenu);
@@ -2241,7 +2289,7 @@
 			int oldHeight;
 			oldHeight = lppop->Height;
 			hDC = GetWindowDC(hWnd);
-			StdDrawMenuBar(hDC, &lppop->rect, lppop, FALSE);
+			StdDrawMenuBar(hDC, &lppop->rect, lppop, TRUE);
 			ReleaseDC(hWnd, hDC);
 			if (oldHeight != lppop->Height) {
 				printf("DrawMenuBar // menubar changed oldHeight=%d != lppop->Height=%d\n",
@@ -2251,6 +2299,8 @@
 				wndPtr->rectClient.top += lppop->Height;
 				SendMessage(hWnd, WM_NCPAINT, 1, 0L);
 				}
+			else
+				StdDrawMenuBar(hDC, &lppop->rect, lppop, FALSE);
 			}
 		else
 			SendMessage(hWnd, WM_NCPAINT, 1, 0L);
diff --git a/if1632/call.S b/if1632/call.S
index 7210e68..7c42967 100644
--- a/if1632/call.S
+++ b/if1632/call.S
@@ -105,7 +105,7 @@
 	movw	$UDATASEL,%ax
 	movw	%ax,%fs
 	movw	%ax,%gs
-/*	movw	%ds,%ax */
+	movw	%ds,%ax
 
 	/*
 	 * Call entry point
diff --git a/if1632/kernel.spec b/if1632/kernel.spec
index 668b05a..4cba3a6 100644
--- a/if1632/kernel.spec
+++ b/if1632/kernel.spec
@@ -44,7 +44,7 @@
 #41 ENABLEDOS
 #42 DISABLEDOS
 45  pascal LoadModule(ptr ptr) LoadModule(1 2)
-#46 FREEMODULE
+46  pascal FreeModule(word) FreeLibrary(1)
 47  pascal GetModuleHandle(ptr) GetModuleHandle(1)
 48  pascal GetModuleUsage(word) GetModuleUsage(1)
 49  pascal GetModuleFileName(word ptr s_word) GetModuleFileName(1 2 3)
@@ -63,8 +63,8 @@
 62  pascal LockResource(word) LockResource(1)
 63  pascal FreeResource(word) FreeResource(1)
 64  pascal AccessResource(word word) AccessResource(1 2)
-#65 SIZEOFRESOURCE
-#66 ALLOCRESOURCE
+65  pascal SizeofResource(word word) SizeofResource(1 2)
+66  pascal AllocResource(word word long) AllocResource(1 2 3)
 #67 SETRESOURCEHANDLER
 68  pascal InitAtomTable(word) InitAtomTable(1)
 69  pascal FindAtom(ptr) FindAtom(1)
diff --git a/if1632/mmsystem.spec b/if1632/mmsystem.spec
index df33e6d..d599d19 100644
--- a/if1632/mmsystem.spec
+++ b/if1632/mmsystem.spec
@@ -82,6 +82,13 @@
 511    pascal  WAVEINRESET(word) waveInReset(1)
 512    pascal  WAVEINGETPOSITION(word ptr word) waveInGetPosition(1 2 3)
 513    pascal  WAVEINGETID(word ptr) waveInGetID(1 2)
+601    pascal  timeGetSystemTime(ptr word) timeGetSystemTime(1 2)
+602    pascal  timeSetEvent(word word ptr long word) timeSetEvent(1 2 3 4 5)
+603    pascal  timeKillEvent(word) timeKillEvent(1)
+604    pascal  timeGetDevCaps(ptr word) timeGetDevCaps(1 2)
+605    pascal  timeBeginPeriod(word) timeBeginPeriod(1)
+606    pascal  timeEndPeriod(word) timeEndPeriod(1)
+607    pascal  timeGetTime() timeGetTime()
 701    pascal  MCISENDCOMMAND(word word long long) mciSendCommand(1 2 3 4)
 702    pascal  MCISENDSTRING(ptr ptr word word) mciSendString(1 2 3 4)
 703    pascal  MCIGETDEVICEID(ptr) mciSendCommand(1)
diff --git a/include/accel.h b/include/accel.h
index 6ea4084d..59fdbd8 100644
--- a/include/accel.h
+++ b/include/accel.h
@@ -19,4 +19,5 @@
 #define VIRTKEY_ACCEL	0x01
 #define SHIFT_ACCEL	0x04
 #define CONTROL_ACCEL	0x08
+#define ALT_ACCEL       0x10
 #define SYSTEM_ACCEL	0x80
diff --git a/include/heap.h b/include/heap.h
index 7c389f1..7ff97a0 100644
--- a/include/heap.h
+++ b/include/heap.h
@@ -36,6 +36,7 @@
 extern void *HEAP_ReAlloc(MDESC **free_list, void *old_block, 
 			  int new_size, unsigned int flags);
 extern LHEAP *HEAP_LocalFindHeap(unsigned short owner);
+extern unsigned int HEAP_LocalSize(MDESC **free_list, unsigned int handle);
 
 #define HEAP_OWNER	(Segments[Stack16Frame[11] >> 3].owner)
 #define LOCALHEAP()	(&HEAP_LocalFindHeap(HEAP_OWNER)->free_list)
diff --git a/include/metafile.h b/include/metafile.h
index a3cd796..2c56e34 100644
--- a/include/metafile.h
+++ b/include/metafile.h
@@ -41,8 +41,14 @@
 BOOL MF_CreateBrushIndirect(DC *dc, HBRUSH hBrush, LOGBRUSH *logbrush);
 BOOL MF_CreatePatternBrush(DC *dc, HBRUSH hBrush, LOGBRUSH *logbrush);
 BOOL MF_CreatePenIndirect(DC *dc, HPEN hPen, LOGPEN *logpen);
+BOOL MF_CreateFontIndirect(DC *dc, HFONT hFont, LOGFONT *logfont);
 BOOL MF_TextOut(DC *dc, short x, short y, LPSTR str, short count);
 BOOL MF_MetaPoly(DC *dc, short func, LPPOINT pt, short count);
+BOOL MF_BitBlt(DC *dcDest, short xDest, short yDest, short width,
+	       short height, HDC hdcSrc, short xSrc, short ySrc, DWORD rop);
+BOOL MF_StretchBlt(DC *dcDest, short xDest, short yDest, short widthDest,
+		   short heightDest, HDC hdcSrc, short xSrc, short ySrc, 
+		   short widthSrc, short heightSrc, DWORD rop);
 
 #endif   /* METAFILE_H */
 
diff --git a/include/win.h b/include/win.h
index 1928632..1c3fcc8 100644
--- a/include/win.h
+++ b/include/win.h
@@ -49,6 +49,9 @@
     HANDLE       hText;          /* Handle of window text */
     WORD         flags;          /* Misc. flags (see below) */
     Window       window;         /* X window */
+    Window       icon;           /* icon's X window */
+    HICON        hIcon;          /* icon's MS-windows handle */
+    RECT         rectClientSave;       /* where client rect is saved when icon*/
     HMENU		 hSysMenu;		 /* window's copy of System Menu */
     HANDLE       hProp;          /* Handle of Properties List */
     HTASK 		 hTask;          /* Task Handle of the owner */
diff --git a/loader/library.c b/loader/library.c
index 21898e9..8253cb5 100644
--- a/loader/library.c
+++ b/loader/library.c
@@ -6,8 +6,6 @@
 /*
 #define DEBUG_MODULE
 */
-
-#ifndef WINELIB
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -15,9 +13,9 @@
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <unistd.h>
+#include "wine.h"
 #include "prototypes.h"
 #include "windows.h"
-#include "wine.h"
 #include "dlls.h"
 #include "task.h"
 #include "toolhelp.h"
@@ -316,8 +314,6 @@
     return (FARPROC) ret;
 }
 
-#endif /* ifndef WINELIB */
-
 /* internal dlls */
 static void 
 FillModStructBuiltIn(MODULEENTRY *lpModule, struct dll_name_table_entry_s *dll)
@@ -412,3 +408,4 @@
 {
 	return (ModuleFindHandle(lpModule, GetModuleHandle((char*)lpstrName)));
 }
+
diff --git a/loader/main.c b/loader/main.c
index 90ec7e5..8161854 100644
--- a/loader/main.c
+++ b/loader/main.c
@@ -92,6 +92,7 @@
     return w;
 }
 
+#ifndef WINELIB
 /**********************************************************************
  *
  * Load MZ Header
@@ -104,6 +105,7 @@
 	myerror("Unable to read MZ header from file");
     }
 }
+#endif
 
 int IsDLLLoaded(char *name)
 {
@@ -233,7 +235,6 @@
     return 14;
 }
 
-
 #ifndef WINELIB
 /**********************************************************************
  *					main
@@ -395,4 +396,4 @@
     for( ; wpnt != final_wpnt; wpnt = wpnt->next)
 	InitDLL(wpnt);
 }
-#endif
+#endif /* #ifndef WINELIB */
diff --git a/loader/resource.c b/loader/resource.c
index 902242f..7814e66 100644
--- a/loader/resource.c
+++ b/loader/resource.c
@@ -344,7 +344,7 @@
 		    }
 #ifdef DEBUG_RESOURCE
 		printf("FindResource: search type=%X id=%X // type=%X id=%X\n",
-			type_id, resource_id, typeinfo.type_id, type_id2);
+			type_id, resource_id, typeinfo.type_id, nameinfo.id);
 #endif
 		if (nameinfo.id == resource_id) {
 		    memcpy(result_p, &nameinfo, sizeof(nameinfo));
@@ -479,6 +479,60 @@
 
 
 /**********************************************************************
+ *					GetRsrcCount		[internal]
+ */
+int GetRsrcCount(HINSTANCE hInst, int type_id)
+{
+    struct resource_typeinfo_s typeinfo;
+    struct resource_nameinfo_s nameinfo;
+    unsigned short size_shift;
+/*    off_t old_pos, new_pos;
+    unsigned char nbytes; 
+    char name[256]; */
+    int i;
+    off_t rtoff;
+    if (hInst == 0) return 0;
+#ifdef DEBUG_RESOURCE
+    printf("GetRsrcCount hInst=%04X typename=%08X\n", hInst, type_name);
+#endif
+    if (OpenResourceFile(hInst) < 0)	return 0;
+
+    /*
+     * Move to beginning of resource table.
+     */
+    rtoff = (ResourceFileInfo->mz_header->ne_offset +
+	     ResourceFileInfo->ne_header->resource_tab_offset);
+    lseek(ResourceFd, rtoff, SEEK_SET);
+    /*
+     * Read block size.
+     */
+    if (read(ResourceFd, &size_shift, sizeof(size_shift)) != sizeof(size_shift)) {
+		printf("GetRsrcCount // bad block size !\n");
+		return -1;
+		}
+    size_shift = CONV_SHORT (size_shift);
+    for (;;) {
+		if (!load_typeinfo (ResourceFd, &typeinfo))	{
+			printf("GetRsrcCount // bad typeinfo size !\n");
+			return 0;
+			}
+#ifdef DEBUG_RESOURCE
+		printf("GetRsrcCount // typeinfo.type_id=%X count=%d type_id=%X\n",
+				typeinfo.type_id, typeinfo.count, type_id);
+#endif
+		if (typeinfo.type_id == 0) break;
+		if (type_match(type_id, typeinfo.type_id, ResourceFd, rtoff)) {
+			return typeinfo.count;
+			}
+		else {
+			lseek(ResourceFd, (typeinfo.count * sizeof(nameinfo)), SEEK_CUR);
+			}
+		}
+    return 0;
+}
+
+
+/**********************************************************************
  *			LoadIcon [USER.174]
  */
 HICON LoadIcon(HANDLE instance, LPSTR icon_name)
@@ -685,12 +739,26 @@
 #endif
     lpAccelTbl = (LPACCELHEADER)GlobalLock(hAccel);
     for (i = 0; i < lpAccelTbl->wCount; i++) {
-/*	if (lpAccelTbl->tbl[i].type & SHIFT_ACCEL) { */
-/*	if (lpAccelTbl->tbl[i].type & CONTROL_ACCEL) { */
 	if (lpAccelTbl->tbl[i].type & VIRTKEY_ACCEL) {
 	    if (msg->wParam == lpAccelTbl->tbl[i].wEvent &&
 		msg->message == WM_KEYDOWN) {
+		if ((lpAccelTbl->tbl[i].type & SHIFT_ACCEL) &&
+		    !(GetKeyState(VK_SHIFT) & 0xf)) {
+		    GlobalUnlock(hAccel);
+		    return 0;
+		}
+		if ((lpAccelTbl->tbl[i].type & CONTROL_ACCEL) &&
+		    !(GetKeyState(VK_CONTROL) & 0xf)) {
+		    GlobalUnlock(hAccel);
+		    return 0;
+		}
+		if ((lpAccelTbl->tbl[i].type & ALT_ACCEL) &&
+		    !(GetKeyState(VK_MENU) & 0xf)) {
+		    GlobalUnlock(hAccel);
+		    return 0;
+		}
 		SendMessage(hWnd, WM_COMMAND, lpAccelTbl->tbl[i].wIDval, 0x00010000L);
+		GlobalUnlock(hAccel);
 		return 1;
 		}
 	    if (msg->message == WM_KEYUP) return 1;
@@ -699,6 +767,7 @@
 	    if (msg->wParam == lpAccelTbl->tbl[i].wEvent &&
 		msg->message == WM_CHAR) {
 		SendMessage(hWnd, WM_COMMAND, lpAccelTbl->tbl[i].wIDval, 0x00010000L);
+		GlobalUnlock(hAccel);
 		return 1;
 		}
 	    }
@@ -773,6 +842,8 @@
     
     if (r->size_shift == -1)
     {
+        printf("FindResource hInst=%04X typename=%08X resname=%08X not found!\n", 
+		instance, type_name, resource_name);
 	GlobalFree(rh);
 	return 0;
     }
@@ -781,6 +852,36 @@
 }
 
 /**********************************************************************
+ *			AllocResource	[KERNEL.66]
+ */
+HANDLE AllocResource(HANDLE instance, HANDLE hResInfo, DWORD dwSize)
+{
+    RESOURCE *r;
+    int image_size;
+
+    if (instance == 0)
+	return 0;
+    
+    if (OpenResourceFile(instance) < 0)
+	return 0;
+
+    r = (RESOURCE *)GlobalLock(hResInfo);
+    if (r == NULL)
+	return 0;
+    
+    image_size = r->nameinfo.length << r->size_shift;
+
+    if (dwSize == 0)
+	r->rsc_mem = GlobalAlloc(GMEM_MOVEABLE, image_size);
+    else
+	r->rsc_mem = GlobalAlloc(GMEM_MOVEABLE, dwSize);
+
+    GlobalUnlock(hResInfo);
+
+    return r->rsc_mem;
+}
+
+/**********************************************************************
  *				LoadResource	[KERNEL.61]
  */
 HANDLE LoadResource(HANDLE instance, HANDLE hResInfo)
@@ -851,24 +952,62 @@
     
     return hResData;
 }
-
+
 /**********************************************************************
  *				AccessResource	[KERNEL.64]
  */
 int AccessResource(HANDLE instance, HANDLE hResInfo)
 {
-    int	resfile;
-#ifdef DEBUG_RESOURCE
+    int	resfile, image_size;
+    RESOURCE *r;
+
+/* #ifdef DEBUG_RESOURCE */
     printf("AccessResource(%04X, %04X);\n", instance, hResInfo);
-#endif
-/*
-    resfile = OpenResourceFile(instance);
+/* #endif */
+
+    if (instance == 0)
+	return -1;
+    
+    if ((resfile = OpenResourceFile(instance)) < 0)
+	return -1;
+
+    if ((r = (RESOURCE *)GlobalLock(hResInfo)) == NULL)
+	return -1;
+
+    lseek(resfile, ((int) r->nameinfo.offset << r->size_shift), SEEK_SET);
+    GlobalUnlock(hResInfo);
+
     return resfile;
-*/
-    return - 1;
 }
+
+/**********************************************************************
+ *				SizeofResource	[KERNEL.65]
+ */
+WORD SizeofResource(HANDLE instance, HANDLE hResInfo)
+{
+    int	image_size;
+    RESOURCE *r;
 
+/* #ifdef DEBUG_RESOURCE */
+    printf("SizeofResource(%04X, %04X);\n", instance, hResInfo);
+/* #endif */
 
+    if (instance == 0)
+	return 0;
+    
+    if ((r = (RESOURCE *)GlobalLock(hResInfo)) == NULL)
+	return 0;
+    
+    image_size = r->nameinfo.length << r->size_shift;
+
+    GlobalUnlock(hResInfo);
+
+/* #ifdef DEBUG_RESOURCE */
+    printf("SizeofResource return %d\n", image_size);
+/* #endif */
+
+    return image_size;
+}
 
 /**********************************************************************
  *					RSC_LoadResource
diff --git a/memory/heap.c b/memory/heap.c
index 734520a..be39fe0 100644
--- a/memory/heap.c
+++ b/memory/heap.c
@@ -195,13 +195,14 @@
 	    m_free->next->prev = m_free->prev;
 	
 	m->length += sizeof(MDESC) + m_free->length;
+
 #ifdef DEBUG_HEAP
 	printf("HEAP_ReAlloc before GLOBAL_FLAGS_ZEROINIT !\n");
 #endif
 	if (flags & GLOBAL_FLAGS_ZEROINIT)
 	    memset(m_free, '\0', sizeof(MDESC) + m_free->length);
     }
-    
+
     /*
      * Check for shrink block.
      */
@@ -400,6 +401,22 @@
 }
 
 /**********************************************************************
+ *					HEAP_LocalSize
+ */
+unsigned int
+HEAP_LocalSize(MDESC **free_list, unsigned int handle)
+{
+    MDESC *m;
+    
+    m = (MDESC *) (((int) *free_list & 0xffff0000) | 
+		   (handle & 0xffff)) - 1;
+    if (m->next != m || m->prev != m)
+	return 0;
+
+    return m->length;
+}
+
+/**********************************************************************
  *					WIN16_LocalAlloc
  */
 void *
diff --git a/misc/main.c b/misc/main.c
index ae0d5c9..f238568 100644
--- a/misc/main.c
+++ b/misc/main.c
@@ -22,7 +22,16 @@
 
 #define WINE_CLASS    "Wine"    /* Class name for resources */
 
-LPSTR	lpEnvList;
+typedef struct tagENVENTRY {
+	LPSTR				Name;
+	LPSTR				Value;
+	WORD				wSize;
+	struct tagENVENTRY	*Prev;
+	struct tagENVENTRY	*Next;
+	} ENVENTRY;
+typedef ENVENTRY *LPENVENTRY;
+
+LPENVENTRY	lpEnvList = NULL;
 
 Display * XT_display;  /* To be removed */
 
@@ -400,9 +409,10 @@
     MAIN_SaveSetup();
     DOS_InitFS();
     Comm_Init();
+#ifndef WINELIB
     INT21_Init();
-    
-#ifndef sunos
+#endif
+#ifndef sparc
     atexit(called_at_exit);
 #else
     on_exit (called_at_exit, 0);
@@ -442,9 +452,66 @@
  */
 int SetEnvironment(LPSTR lpPortName, LPSTR lpEnviron, WORD nCount)
 {
-	printf("EMPTY STUB ! // SetEnvironnement('%s', '%s', %d) !\n",
-								lpPortName, lpEnviron, nCount);
-	return 0;
+	LPENVENTRY	lpNewEnv;
+	LPENVENTRY	lpEnv = lpEnvList;
+	printf("SetEnvironnement('%s', '%s', %d) !\n", 
+				lpPortName, lpEnviron, nCount);
+	if (lpPortName == NULL) return -1;
+	while (lpEnv != NULL) {
+		if (lpEnv->Name != NULL && strcmp(lpEnv->Name, lpPortName) == 0) {
+			if (nCount == 0 || lpEnviron == NULL) {
+				if (lpEnv->Prev != NULL) lpEnv->Prev->Next = lpEnv->Next;
+				if (lpEnv->Next != NULL) lpEnv->Next->Prev = lpEnv->Prev;
+				free(lpEnv->Value);
+				free(lpEnv->Name);
+				free(lpEnv);
+				printf("SetEnvironnement() // entry deleted !\n");
+				return -1;
+				}
+			free(lpEnv->Value);
+			lpEnv->Value = malloc(nCount);
+			if (lpNewEnv->Value == NULL) {
+				printf("SetEnvironment() // Error allocating entry value !\n");
+				return 0;
+			}
+			memcpy(lpEnv->Value, lpEnviron, nCount);
+			lpEnv->wSize = nCount;
+			printf("SetEnvironnement() // entry modified !\n");
+			return nCount;
+			}
+		if (lpEnv->Next == NULL) break;
+		lpEnv = lpEnv->Next;
+		}
+	if (nCount == 0 || lpEnviron == NULL) return -1;
+	printf("SetEnvironnement() // new entry !\n");
+	lpNewEnv = malloc(sizeof(ENVENTRY));
+	if (lpNewEnv == NULL) {
+		printf("SetEnvironment() // Error allocating new entry !\n");
+		return 0;
+		}
+	if (lpEnvList == NULL) {
+		lpEnvList = lpNewEnv;
+		lpNewEnv->Prev = NULL;
+		}
+	else {
+		lpEnv->Next = lpNewEnv;
+		lpNewEnv->Prev = lpEnv;
+		}
+	lpNewEnv->Next = NULL;
+	lpNewEnv->Name = malloc(strlen(lpPortName) + 1);
+	if (lpNewEnv->Name == NULL) {
+		printf("SetEnvironment() // Error allocating entry name !\n");
+		return 0;
+		}
+	strcpy(lpNewEnv->Name, lpPortName);
+	lpNewEnv->Value = malloc(nCount);
+	if (lpNewEnv->Value == NULL) {
+		printf("SetEnvironment() // Error allocating entry value !\n");
+		return 0;
+		}
+	memcpy(lpNewEnv->Value, lpEnviron, nCount);
+	lpNewEnv->wSize = nCount;
+	return nCount;
 }
 
 /***********************************************************************
@@ -452,8 +519,20 @@
  */
 int GetEnvironment(LPSTR lpPortName, LPSTR lpEnviron, WORD nMaxSiz)
 {
-	printf("EMPTY STUB ! // GetEnvironnement('%s', '%s', %d) !\n",
-								lpPortName, lpEnviron, nMaxSiz);
+	WORD		nCount;
+	LPENVENTRY	lpEnv = lpEnvList;
+	printf("GetEnvironnement('%s', '%s', %d) !\n",
+					lpPortName, lpEnviron, nMaxSiz);
+	while (lpEnv != NULL) {
+		if (lpEnv->Name != NULL && strcmp(lpEnv->Name, lpPortName) == 0) {
+			nCount = min(nMaxSiz, lpEnv->wSize);
+			memcpy(lpEnviron, lpEnv->Value, nCount);
+			printf("GetEnvironnement() // found '%s' !\n", lpEnviron);
+			return nCount;
+			}
+		lpEnv = lpEnv->Next;
+		}
+	printf("GetEnvironnement() // not found !\n");
 	return 0;
 }
 
diff --git a/misc/mmsystem.c b/misc/mmsystem.c
index 6e22c5c..90fc2de 100644
--- a/misc/mmsystem.c
+++ b/misc/mmsystem.c
@@ -12,7 +12,24 @@
 #include "mmsystem.h"
 
 static WORD		mciActiveDev = 0;
+static BOOL		mmTimeStarted = FALSE;
+static MMTIME	mmSysTimeMS;
+static MMTIME	mmSysTimeSMPTE;
 
+typedef struct tagTIMERENTRY {
+	WORD		wDelay;
+	WORD		wResol;
+	FARPROC		lpFunc;
+	DWORD		dwUser;
+	WORD		wFlags;
+	WORD		wTimerID;
+	WORD		wCurTime;
+	struct tagTIMERENTRY	*Next;
+	struct tagTIMERENTRY	*Prev;
+	} TIMERENTRY;
+typedef TIMERENTRY *LPTIMERENTRY;
+
+static LPTIMERENTRY lpTimerList = NULL;
 
 UINT WINAPI midiGetErrorText(UINT uError, LPSTR lpText, UINT uSize);
 UINT WINAPI waveGetErrorText(UINT uError, LPSTR lpText, UINT uSize);
@@ -1451,6 +1468,160 @@
 }
 
 
+/**************************************************************************
+* 				MMSysTimeCallback	[internal]
+*/
+WORD FAR PASCAL MMSysTimeCallback(HWND hWnd, WORD wMsg, int nID, DWORD dwTime)
+{
+	LPTIMERENTRY	lpTimer = lpTimerList;
+	mmSysTimeMS.u.ms += 33;
+	mmSysTimeSMPTE.u.smpte.frame++;
+	while (lpTimer != NULL) {
+		lpTimer->wCurTime--;
+		if (lpTimer->wCurTime == 0) {
+			lpTimer->wCurTime = lpTimer->wDelay;
+			if (lpTimer->lpFunc != NULL) {
+#ifdef WINELIB
+				(*lpTimer->lpFunc)(lpTimer->wTimerID, (WORD)0, 
+						lpTimer->dwUser, (DWORD)0, (DWORD)0);
+#else
+				CallBack16(lpTimer->lpFunc, 5, 
+					0, (int)lpTimer->wTimerID, 0, (int)0, 
+					2, lpTimer->dwUser, 2, 0, 2, 0);
+#endif
+				}
+			if (lpTimer->wFlags & TIME_ONESHOT)
+				timeKillEvent(lpTimer->wTimerID);
+			}
+		lpTimer = lpTimer->Next;
+		}
+}
+
+/**************************************************************************
+* 				StartMMTime			[internal]
+*/
+void StartMMTime()
+{
+	if (!mmTimeStarted) {
+		mmTimeStarted = TRUE;
+		mmSysTimeMS.wType = TIME_MS;
+		mmSysTimeMS.u.ms = 0;
+		mmSysTimeSMPTE.wType = TIME_SMPTE;
+		mmSysTimeSMPTE.u.smpte.hour = 0;
+		mmSysTimeSMPTE.u.smpte.min = 0;
+		mmSysTimeSMPTE.u.smpte.sec = 0;
+		mmSysTimeSMPTE.u.smpte.frame = 0;
+		mmSysTimeSMPTE.u.smpte.fps = 0;
+		mmSysTimeSMPTE.u.smpte.dummy = 0;
+		SetTimer(0, 1, 33, (FARPROC)MMSysTimeCallback);
+		}
+}
+
+/**************************************************************************
+* 				timeGetSystemTime	[MMSYSTEM.601]
+*/
+WORD timeGetSystemTime(LPMMTIME lpTime, WORD wSize)
+{
+	printf("timeGetSystemTime(%08X, %u);\n", lpTime, wSize);
+	if (!mmTimeStarted) StartMMTime();
+	return 0;
+}
+
+/**************************************************************************
+* 				timeSetEvent		[MMSYSTEM.602]
+*/
+WORD timeSetEvent(WORD wDelay, WORD wResol, 
+				LPTIMECALLBACK lpFunc, 
+				DWORD dwUser, WORD wFlags)
+{
+	WORD			wNewID = 0;
+	LPTIMERENTRY	lpNewTimer;
+	LPTIMERENTRY	lpTimer = lpTimerList;
+	printf("timeSetEvent(%u, %u, %08X, %08X, %04X);\n",
+			wDelay, wResol, lpFunc, dwUser, wFlags);
+	if (!mmTimeStarted) StartMMTime();
+	lpNewTimer = malloc(sizeof(TIMERENTRY));
+	if (lpNewTimer == NULL)	return 0;
+	while (lpTimer != NULL) {
+		wNewID = max(wNewID, lpTimer->wTimerID);
+		if (lpTimer->Next == NULL) break;
+		lpTimer = lpTimer->Next;
+		}
+	if (lpTimerList == NULL) {
+		lpTimerList = lpNewTimer;
+		lpNewTimer->Prev == NULL;
+		}
+	else {
+		lpTimer->Next == lpNewTimer;
+		lpNewTimer->Prev == lpTimer;
+		}
+	lpNewTimer->Next == NULL;
+	lpNewTimer->wTimerID = wNewID + 1;
+	lpNewTimer->wCurTime = wDelay;
+	lpNewTimer->wDelay = wDelay;
+	lpNewTimer->wResol = wResol;
+	lpNewTimer->lpFunc = lpFunc;
+	lpNewTimer->dwUser = dwUser;
+	lpNewTimer->wFlags = wFlags;
+	return lpNewTimer->wTimerID;
+}
+
+/**************************************************************************
+* 				timeKillEvent		[MMSYSTEM.603]
+*/
+WORD timeKillEvent(WORD wID)
+{
+	LPTIMERENTRY	lpTimer = lpTimerList;
+	while (lpTimer != NULL) {
+		if (wID == lpTimer->wTimerID) {
+			if (lpTimer->Prev != NULL) lpTimer->Prev->Next = lpTimer->Next;
+			if (lpTimer->Next != NULL) lpTimer->Next->Prev = lpTimer->Prev;
+			free(lpTimer);
+			return TRUE;
+			}
+		lpTimer = lpTimer->Next;
+		}
+	return 0;
+}
+
+/**************************************************************************
+* 				timeGetDevCaps		[MMSYSTEM.604]
+*/
+WORD timeGetDevCaps(LPTIMECAPS lpCaps, WORD wSize)
+{
+	printf("timeGetDevCaps(%08X, %u) !\n", lpCaps, wSize);
+	return 0;
+}
+
+/**************************************************************************
+* 				timeBeginPeriod		[MMSYSTEM.605]
+*/
+WORD timeBeginPeriod(WORD wPeriod)
+{
+	printf("timeBeginPeriod(%u) !\n", wPeriod);
+	if (!mmTimeStarted) StartMMTime();
+	return 0;
+}
+
+/**************************************************************************
+* 				timeEndPeriod		[MMSYSTEM.606]
+*/
+WORD timeEndPeriod(WORD wPeriod)
+{
+	printf("timeEndPeriod(%u) !\n", wPeriod);
+	return 0;
+}
+
+/**************************************************************************
+* 				timeGetTime			[MMSYSTEM.607]
+*/
+DWORD timeGetTime()
+{
+	printf("timeGetTime(); !\n");
+	if (!mmTimeStarted) StartMMTime();
+	return 0;
+}
+
 
 /**************************************************************************
 * 				mmioOpen			[MMSYSTEM.1210]
diff --git a/misc/profile.c b/misc/profile.c
index 29e6508..7bd9488 100644
--- a/misc/profile.c
+++ b/misc/profile.c
@@ -332,13 +332,13 @@
 WORD GetPrivateProfileInt (LPSTR AppName, LPSTR KeyName, short Default,
 			   LPSTR File)
 {
-    static char IntBuf [5];
-    static char buf [5];
+    static char IntBuf [6];
+    static char buf [6];
 
     sprintf (buf, "%d", Default);
     
     /* Check the exact semantic with the SDK */
-    GetPrivateProfileString (AppName, KeyName, buf, IntBuf, 5, File);
+    GetPrivateProfileString (AppName, KeyName, buf, IntBuf, 6, File);
     if (!strcasecmp (IntBuf, "true"))
 	return 1;
     if (!strcasecmp (IntBuf, "yes"))
diff --git a/misc/property.c b/misc/property.c
index 92f57a4..b58d173 100644
--- a/misc/property.c
+++ b/misc/property.c
@@ -3,7 +3,9 @@
  */
 static char Copyright[] = "Copyright Martin Ayotte, 1994";
 
+/*
 #define DEBUG_PROP
+*/
 
 #include <stdlib.h>
 #include <stdio.h>
@@ -13,12 +15,12 @@
 #include "heap.h"
 #include "win.h"
 
-typedef struct {
+typedef struct tagPROPENTRY {
 	LPSTR		PropName;
 	WORD		Atom;
 	HANDLE		hData;
-	void		*lpPrevProp;
-	void		*lpNextProp;
+	struct tagPROPENTRY	*lpPrevProp;
+	struct tagPROPENTRY	*lpNextProp;
 } PROPENTRY;
 typedef PROPENTRY *LPPROPENTRY;
 
@@ -44,7 +46,9 @@
     	}
 	lpProp = (LPPROPENTRY) GlobalLock(wndPtr->hProp);
 	if (lpProp == NULL) {
+#ifdef DEBUG_PROP
 		printf("Property List Empty !\n");
+#endif
 		return 0;
 		}
 	while (TRUE) {
@@ -53,14 +57,14 @@
 			(((DWORD)lpStr & 0xFFFF0000) != 0L && 
 			lpProp->PropName != NULL &&
 			strcmp(lpProp->PropName, lpStr) == 0)) {
+#ifdef DEBUG_PROP
 		   	printf("RemoveProp // Property found ! hData=%04X\n", lpProp->hData);
+#endif
 			hOldData = lpProp->hData;
 			if (lpProp->lpPrevProp != NULL) 
-				((LPPROPENTRY)lpProp->lpPrevProp)->lpNextProp = 
-											lpProp->lpNextProp;
+				lpProp->lpPrevProp->lpNextProp = lpProp->lpNextProp;
 			if (lpProp->lpNextProp != NULL) 
-				((LPPROPENTRY)lpProp->lpNextProp)->lpPrevProp = 
-											lpProp->lpPrevProp;
+				lpProp->lpNextProp->lpPrevProp = lpProp->lpPrevProp;
 			if (lpProp->PropName != NULL) free(lpProp->PropName);
 			GlobalFree(lpProp);
 			GlobalUnlock(wndPtr->hProp);
@@ -70,7 +74,9 @@
 		lpProp = lpProp->lpNextProp;
 		}
 	GlobalUnlock(wndPtr->hProp);
+#ifdef DEBUG_PROP
    	printf("RemoveProp // Property not found !\n");
+#endif
 	return 0;
 }
 
@@ -95,7 +101,9 @@
     	}
 	lpProp = (LPPROPENTRY) GlobalLock(wndPtr->hProp);
 	if (lpProp == NULL) {
+#ifdef DEBUG_PROP
 		printf("Property List Empty !\n");
+#endif
 		return 0;
 		}
 	while (TRUE) {
@@ -104,14 +112,18 @@
 			(((DWORD)lpStr & 0xFFFF0000) != 0L && 
 			lpProp->PropName != NULL &&
 			strcmp(lpProp->PropName, lpStr) == 0)) {
+#ifdef DEBUG_PROP
 		   	printf("GetProp // Property found ! hData=%04X\n", lpProp->hData);
+#endif
 			GlobalUnlock(wndPtr->hProp);
 			return lpProp->hData;
 			}
 		if (lpProp->lpNextProp == NULL) break;
 		lpProp = lpProp->lpNextProp;
 		}
+#ifdef DEBUG_PROP
    	printf("GetProp // Property not found !\n");
+#endif
 	GlobalUnlock(wndPtr->hProp);
 	return 0;
 }
diff --git a/misc/shell.c b/misc/shell.c
index d55368d..0b6e552 100644
--- a/misc/shell.c
+++ b/misc/shell.c
@@ -5,6 +5,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <unistd.h>
+#include "prototypes.h"
 #include "windows.h"
 #include "shell.h"
 
@@ -396,8 +397,23 @@
  */
 HICON ExtractIcon(HINSTANCE hInst, LPCSTR lpszExeFileName, UINT nIconIndex)
 {
-	fprintf(stderr, "ExtractIcon : Empty Stub !!!\n");
-
+	int		count;
+	HICON	hIcon = 0;
+	HINSTANCE hInst2 = hInst;
+	fprintf(stderr, "ExtractIcon(%04X, '%s', %d\n", 
+			hInst, lpszExeFileName, nIconIndex);
+	if (lpszExeFileName != NULL) {
+		hInst2 = LoadLibrary(lpszExeFileName);
+		}
+	if (hInst2 != 0 && nIconIndex == (UINT)-1) {
+		count = GetRsrcCount(hInst2, NE_RSCTYPE_GROUP_ICON);
+		printf("ExtractIcon // '%s' has %d icons !\n", lpszExeFileName, count);
+		return (HICON)count;
+		}
+	if (hInst2 != hInst && hInst2 != 0) {
+		FreeLibrary(hInst2);
+		}
+	return hIcon;
 }
 
 
diff --git a/misc/stress.c b/misc/stress.c
index 2b748b7..e503ef9 100644
--- a/misc/stress.c
+++ b/misc/stress.c
@@ -88,7 +88,7 @@
 #endif
 
 #ifndef OPEN_MAX
-	return _POSIX_OPEN_MAX
+	return _POSIX_OPEN_MAX;
 #else
 	return OPEN_MAX;
 #endif
diff --git a/miscemu/int31.c b/miscemu/int31.c
index eaee326..3d4500c 100644
--- a/miscemu/int31.c
+++ b/miscemu/int31.c
@@ -3,12 +3,92 @@
 #include "msdos.h"
 #include "wine.h"
 
+typedef struct {
+	WORD	accessed    : 1;
+	WORD	read_write  : 1;
+	WORD	conf_exp    : 1;
+	WORD	code        : 1;
+	WORD	xsystem     : 1;
+	WORD	dpl         : 2;
+	WORD	present     : 1;
+	WORD	dummy	    : 8;
+	} ACCESS;
+typedef ACCESS *LPACCESS;
+
+typedef struct {
+	WORD	Limit;
+	WORD	addr_lo;
+	BYTE	addr_hi;
+	ACCESS	access; 
+	WORD	reserved;
+	} DESCRIPTOR;
+typedef DESCRIPTOR *LPDESCRIPTOR;
+
+HANDLE DPMI_GetNewSelector(WORD selcount);
+BOOL DPMI_FreeSelector(HANDLE pmSel);
+BOOL DPMI_SetDescriptor(HANDLE pmSel, LPDESCRIPTOR lpDesc);
+
+/*************************************************************************/
+
 int do_int31(struct sigcontext_struct *context)
 {
-	switch((context->sc_eax >> 8) & 0xff)
+	LPDESCRIPTOR lpDesc;
+	printf("do_int31 // context->sc_eax=%04X\n", context->sc_eax);
+	switch(context->sc_eax)
 	{
+	case 0x0000:
+		context->sc_eax = DPMI_GetNewSelector(context->sc_ecx);
+		break;
+	case 0x0001:
+		context->sc_eax = DPMI_FreeSelector(context->sc_ebx);
+		break;
+	case 0x000C:
+		lpDesc = MAKELONG(context->sc_edi, context->sc_es);
+		context->sc_eax = DPMI_SetDescriptor(context->sc_ebx, lpDesc);
+		break;
 	default:
 		IntBarf(0x31, context);
 	};
 	return 1;
 }
+
+
+/*************************************************************************/
+
+
+HANDLE DPMI_GetNewSelector(WORD selcount)
+{
+	LPSTR	ptr;
+	HANDLE 	pmSel;
+	printf("DPMI_GetNewSelector(%d); !\n", selcount);
+	pmSel = GlobalAlloc(GMEM_FIXED, 4096);
+	ptr = GlobalLock(pmSel);
+	printf("DPMI_GetNewSelector() return %04X !\n", pmSel);
+	return pmSel;
+}
+
+
+BOOL DPMI_FreeSelector(HANDLE pmSel)
+{
+	printf("DPMI_FreeSelector(%04X); !\n", pmSel);
+	GlobalFree(pmSel);
+	return 0;
+}
+
+BOOL DPMI_SetDescriptor(HANDLE pmSel, LPDESCRIPTOR lpDesc)
+{
+	printf("DPMI_SetDescriptor(%04X, %08X); !\n", pmSel, lpDesc);
+	printf("DPMI lpDesc->Limit=%u \n", lpDesc->Limit);
+	printf("DPMI lpDesc->addr_lo=%04X \n", lpDesc->addr_lo);
+	printf("DPMI lpDesc->addr_hi=%02X \n", lpDesc->addr_hi);
+	printf("DPMI lpDesc->access.accessed=%u \n", lpDesc->access.accessed);
+	printf("DPMI lpDesc->access.read_write=%u \n", lpDesc->access.read_write);
+	printf("DPMI lpDesc->access.conf_exp=%u \n", lpDesc->access.conf_exp);
+	printf("DPMI lpDesc->access.code=%u \n", lpDesc->access.code);
+	printf("DPMI lpDesc->access.xsystem=%u \n", lpDesc->access.xsystem);
+	printf("DPMI lpDesc->access.dpl=%u \n", lpDesc->access.dpl);
+	printf("DPMI lpDesc->access.present=%u \n", lpDesc->access.present);
+	printf("DPMI lpDesc->reserved=%04X \n", lpDesc->reserved);
+	return FALSE;
+}
+
diff --git a/objects/bitblt.c b/objects/bitblt.c
index c90b9e2..bb83f99 100644
--- a/objects/bitblt.c
+++ b/objects/bitblt.c
@@ -66,6 +66,7 @@
 {
     int xs1, xs2, ys1, ys2;
     int xd1, xd2, yd1, yd2;
+    DWORD saverop = rop;
     DC *dcDest, *dcSrc;
 
 #ifdef DEBUG_GDI    
@@ -83,10 +84,17 @@
 	return FALSE;
     }
     
-    dcDest = (DC *) GDI_GetObjPtr( hdcDest, DC_MAGIC );
-    if (!dcDest) return FALSE;
     dcSrc = (DC *) GDI_GetObjPtr( hdcSrc, DC_MAGIC );
     if (!dcSrc) return FALSE;
+    dcDest = (DC *) GDI_GetObjPtr( hdcDest, DC_MAGIC );
+    if (!dcDest) 
+    {
+	dcDest = (DC *)GDI_GetObjPtr(hdcDest, METAFILE_DC_MAGIC);
+	if (!dcDest) return FALSE;
+	MF_BitBlt(dcDest, xDest, yDest, width, height,
+		  hdcSrc, xSrc, ySrc, saverop);
+	return TRUE;
+    }
 
     xs1 = dcSrc->w.DCOrgX + XLPTODP( dcSrc, xSrc );
     xs2 = dcSrc->w.DCOrgX + XLPTODP( dcSrc, xSrc + width );
@@ -319,6 +327,7 @@
     int xd1, xd2, yd1, yd2;
     DC *dcDest, *dcSrc;
     XImage *sxi, *dxi;
+    DWORD saverop = rop;
     WORD stretchmode;
 	BOOL	flg;
 
@@ -351,10 +360,17 @@
         return FALSE;
     }
 
-    dcDest = (DC *) GDI_GetObjPtr( hdcDest, DC_MAGIC );
-    if (!dcDest) return FALSE;
     dcSrc = (DC *) GDI_GetObjPtr( hdcSrc, DC_MAGIC );
     if (!dcSrc) return FALSE;
+    dcDest = (DC *) GDI_GetObjPtr( hdcDest, DC_MAGIC );
+    if (!dcDest) 
+    {
+	dcDest = (DC *)GDI_GetObjPtr(hdcDest, METAFILE_DC_MAGIC);
+	if (!dcDest) return FALSE;
+	MF_StretchBlt(dcDest, xDest, yDest, widthDest, heightDest,
+		  hdcSrc, xSrc, ySrc, widthSrc, heightSrc, saverop);
+	return TRUE;
+    }
 
     xs1 = dcSrc->w.DCOrgX + XLPTODP( dcSrc, xSrc );
     xs2 = dcSrc->w.DCOrgX + XLPTODP( dcSrc, xSrc + widthSrc );
diff --git a/objects/bitmap.c b/objects/bitmap.c
index 6e8c1b0..b068a2a 100644
--- a/objects/bitmap.c
+++ b/objects/bitmap.c
@@ -115,6 +115,13 @@
     if (bmp->bmPlanes != 1) return 0;
     if ((bmp->bmBitsPixel != 1) && (bmp->bmBitsPixel != screenDepth)) return 0;
 
+    if (bmp->bmHeight < 0)
+	bmp->bmHeight = -bmp->bmHeight;
+    
+    if (bmp->bmWidth < 0)
+	bmp->bmWidth = -bmp->bmWidth;
+    
+
       /* Create the BITMAPOBJ */
     hbitmap = GDI_AllocObject( sizeof(BITMAPOBJ), BITMAP_MAGIC );
     if (!hbitmap) return 0;
diff --git a/objects/font.c b/objects/font.c
index fba3ab2..63a5543 100644
--- a/objects/font.c
+++ b/objects/font.c
@@ -195,6 +195,9 @@
 	font = (FONTOBJ *) GDI_HEAP_ADDR( hnewfont );
     }
 
+    if (dc->header.wMagic == METAFILE_DC_MAGIC)
+	return MF_CreateFontIndirect(dc, hfont, &(font->logfont));
+
     if ((hfont >= FIRST_STOCK_FONT) && (hfont <= LAST_STOCK_FONT))
 	stockPtr = &stockFonts[hfont - FIRST_STOCK_FONT];
     else 
diff --git a/objects/metafile.c b/objects/metafile.c
index 5ff49ed..544e6e4 100644
--- a/objects/metafile.c
+++ b/objects/metafile.c
@@ -431,6 +431,11 @@
 		     CreatePenIndirect((LOGPEN *)(&(mr->rdParam))));
 	break;
 
+    case META_CREATEFONTINDIRECT:
+	MF_AddHandle(ht, nHandles, 
+		     CreateFontIndirect((LOGFONT *)(&(mr->rdParam))));
+	break;
+
     case META_CREATEBRUSHINDIRECT:
 	MF_AddHandle(ht, nHandles, 
 		     CreateBrushIndirect((LOGBRUSH *)(&(mr->rdParam))));
@@ -799,6 +804,41 @@
 
 
 /******************************************************************
+ *         MF_CreateFontIndirect
+ */
+BOOL MF_CreateFontIndirect(DC *dc, HFONT hFont, LOGFONT *logfont)
+{
+    int index;
+    BOOL rc;
+    char buffer[sizeof(METARECORD) - 2 + sizeof(LOGFONT)];
+    METARECORD *mr = (METARECORD *)&buffer;
+    METAFILE *mf;
+    METAHEADER *mh;
+
+    mr->rdSize = (sizeof(METARECORD) + sizeof(LOGFONT) - 2) / 2;
+    mr->rdFunction = META_CREATEFONTINDIRECT;
+    memcpy(&(mr->rdParam), logfont, sizeof(LOGFONT));
+    if (!MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2))
+	return FALSE;
+
+    mr->rdSize = sizeof(METARECORD) / 2;
+    mr->rdFunction = META_SELECTOBJECT;
+    if ((index = MF_AddHandleInternal(hFont)) == -1)
+	return FALSE;
+
+    mf = (METAFILE *)GlobalLock(dc->w.hMetaFile);
+    mh = (METAHEADER *)GlobalLock(mf->hMetaHdr);
+    *(mr->rdParam) = index;
+    if (index >= mh->mtNoObjects)
+	mh->mtNoObjects++;
+    rc = MF_WriteRecord(dc->w.hMetaFile, mr, mr->rdSize * 2);
+    GlobalUnlock(mf->hMetaHdr);
+    GlobalUnlock(dc->w.hMetaFile);
+    return rc;
+}
+
+
+/******************************************************************
  *         MF_TextOut
  */
 BOOL MF_TextOut(DC *dc, short x, short y, LPSTR str, short count)
@@ -850,3 +890,24 @@
     GlobalFree(hmr);
     return rc;
 }
+
+
+/******************************************************************
+ *         MF_BitBlt
+ */
+BOOL MF_BitBlt(DC *dcDest, short xDest, short yDest, short width,
+	       short height, HDC hdcSrc, short xSrc, short ySrc, DWORD rop)
+{
+    printf("MF_BitBlt: not implemented yet\n");
+}
+
+
+/******************************************************************
+ *         MF_StretchBlt
+ */
+BOOL MF_StretchBlt(DC *dcDest, short xDest, short yDest, short widthDest,
+		   short heightDest, HDC hdcSrc, short xSrc, short ySrc, 
+		   short widthSrc, short heightSrc, DWORD rop)
+{
+    printf("MF_StretchBlt: not implemented yet\n");
+}
diff --git a/toolkit/heap.c b/toolkit/heap.c
index 9307156..002257f 100644
--- a/toolkit/heap.c
+++ b/toolkit/heap.c
@@ -12,7 +12,7 @@
 #include "windows.h"
 
 /* Controls the blocks per handle table */
-#define MAXBLOCKS 512
+#define MAXBLOCKS 1024
 
 static char Copyright [] = "Copyright (C) 1994 Miguel de Icaza";
 
@@ -186,6 +186,16 @@
 	return LocalReAlloc (hMem, new_size, flags);
 }
 
+char *GlobalLinearLock (HANDLE hMem)
+{
+    return GlobalLock (hMem);
+}
+
+HANDLE GlobalLinearUnlock (HANDLE hMem)
+{
+    return GlobalUnlock (hMem);
+}
+
 #ifdef UNIMPLEMENTED
 void *GlobalQuickAlloc(int size)
 {
diff --git a/toolkit/hello.c b/toolkit/hello.c
new file mode 100644
index 0000000..d9d9978
--- /dev/null
+++ b/toolkit/hello.c
@@ -0,0 +1,72 @@
+/* #include "autoconf.h" */
+#include <windows.h>
+
+void Write (HDC dc, int x, int y, char *s)
+{
+    TextOut (dc, x, y, s, strlen (s));
+}
+
+LONG WndProc (HANDLE wnd, UINT msg, WORD w, LONG l)
+{
+    static short xChar, yChar;
+    HDC dc;
+    PAINTSTRUCT ps;
+    TEXTMETRIC tm;
+
+    switch (msg){
+    case WM_CREATE:
+	dc = GetDC (wnd);
+	GetTextMetrics (dc, &tm);
+	xChar = tm.tmAveCharWidth;
+	yChar = tm.tmHeight;
+	ReleaseDC (wnd, dc);
+	break;
+
+    case WM_PAINT:
+	dc = BeginPaint (wnd, &ps);
+	Write (dc, xChar, yChar, "Hola");
+	EndPaint (wnd, &ps);
+	break;
+
+    case WM_DESTROY:
+	PostQuitMessage (0);
+	break;
+
+    default:
+	return DefWindowProc (wnd, msg, w, l);
+    }
+    return 0l;
+}
+
+int PASCAL WinMain (HANDLE inst, HANDLE prev, LPSTR cmdline, int show)
+{
+    HWND     wnd;
+    MSG      msg;
+    WNDCLASS class;
+
+    if (!prev){
+	class.style = CS_HREDRAW | CS_VREDRAW;
+	class.lpfnWndProc = WndProc;
+	class.cbClsExtra = 0;
+	class.cbWndExtra = 0;
+	class.hInstance  = inst;
+	class.hIcon      = LoadIcon (0, IDI_APPLICATION);
+	class.hCursor    = LoadCursor (0, IDC_ARROW);
+	class.hbrBackground = GetStockObject (WHITE_BRUSH);
+	class.lpszMenuName = NULL;
+	class.lpszClassName = "class";
+    }
+    if (!RegisterClass (&class))
+	return FALSE;
+
+    wnd = CreateWindow ("class", "Test app", WS_OVERLAPPEDWINDOW,
+			CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, 0, 
+			0, inst, 0);
+    ShowWindow (wnd, show);
+    UpdateWindow (wnd);
+
+    while (GetMessage (&msg, 0, 0, 0)){
+	TranslateMessage (&msg);
+	DispatchMessage (&msg);
+    }
+}
diff --git a/windows/Imakefile b/windows/Imakefile
index c5720cb..53412bc 100644
--- a/windows/Imakefile
+++ b/windows/Imakefile
@@ -14,6 +14,7 @@
 	focus.c \
 	graphics.c \
 	hook.c \
+	icon.c \
 	keyboard.c \
 	mapping.c \
 	mdi.c \
diff --git a/windows/dce.c b/windows/dce.c
index 3dfe56e..58216b4 100644
--- a/windows/dce.c
+++ b/windows/dce.c
@@ -11,6 +11,7 @@
 #include "win.h"
 #include "gdi.h"
 #include "user.h"
+#include "icon.h"
 
 
 #define NB_DCE    5  /* Number of DCEs created at startup */
@@ -130,6 +131,7 @@
     DCE * dce;
     DC * dc;
     WND * wndPtr;
+    ICONALLOC   *lpico;
     
     if (hwnd)
     {
@@ -181,6 +183,25 @@
 	    dc->w.DCSizeX = wndPtr->rectWindow.right - wndPtr->rectWindow.left;
 	    dc->w.DCSizeY = wndPtr->rectWindow.bottom - wndPtr->rectWindow.top;
 	}
+	else if (IsIconic(hwnd))                /* if we have an icon */
+        {
+            /* more things are hardcoded here than should be,
+             * I assume the icon windows is 100 pixels 1/2 of which is 50
+             * this just sets up the dc so it knows about the size of
+             * the icon area
+             */
+            dc->u.x.drawable = wndPtr->icon;
+            if (wndPtr->hIcon != (HICON)NULL) {
+                lpico = (ICONALLOC *)GlobalLock(wndPtr->hIcon);
+                dc->w.DCSizeX = /* (int)lpico->descriptor.Width */ 100;
+                dc->w.DCSizeY = (int)lpico->descriptor.Height + 20;
+            } else {
+                dc->w.DCOrgX = /* 64 */ 100;            /* assume max size */
+                dc->w.DCOrgY = 64 + 20;
+            }
+            dc->w.DCOrgX  = 0;
+            dc->w.DCOrgY  = 0;
+        }
 	else
 	{
 	    dc->w.DCOrgX  = wndPtr->rectClient.left - wndPtr->rectWindow.left;
@@ -202,7 +223,7 @@
     if ((flags & DCX_INTERSECTRGN) || (flags & DCX_EXCLUDERGN))
     {
 	HRGN hrgn = CreateRectRgn( 0, 0, 0, 0 );
-	if (hrgn)
+	if (hrgn && !IsIconic(hwnd))
 	{
 	    if (CombineRgn( hrgn, InquireVisRgn(hdc), hrgnClip,
 			    (flags & DCX_INTERSECTRGN) ? RGN_AND : RGN_DIFF ))
diff --git a/windows/defwnd.c b/windows/defwnd.c
index 2434840..e91e3a8 100644
--- a/windows/defwnd.c
+++ b/windows/defwnd.c
@@ -38,11 +38,9 @@
     WND *wndPtr = WIN_FindWndPtr( hwnd );
 
     if (wndPtr->hText) USER_HEAP_FREE( wndPtr->hText );
-    wndPtr->hText = USER_HEAP_ALLOC( LMEM_MOVEABLE, strlen(text) + 2 );
+    wndPtr->hText = USER_HEAP_ALLOC( LMEM_MOVEABLE, strlen(text) + 1 );
     textPtr = (LPSTR) USER_HEAP_ADDR( wndPtr->hText );
     strcpy( textPtr, text );
-        /* for use by edit control */
-    *(textPtr + strlen(text) + 1) = '\0';
 }
 
 
@@ -79,6 +77,11 @@
     case WM_NCPAINT:
 	return NC_HandleNCPaint( hwnd, (HRGN)wParam );
 
+    case WM_PAINTICON:
+        printf("going to call NC_HandleNCPaintIcon\n");
+        return NC_HandleNCPaintIcon( hwnd );
+
+
     case WM_NCHITTEST:
 	return NC_HandleNCHitTest( hwnd, MAKEPOINT(lParam) );
 
diff --git a/windows/event.c b/windows/event.c
index b873bef..04358df 100644
--- a/windows/event.c
+++ b/windows/event.c
@@ -23,6 +23,11 @@
 #endif
 #endif
 
+#ifdef sparc
+/* Dirty hack to compile with Sun's OpenWindows */
+typedef char *XPointer;
+#endif
+
 #define NB_BUTTONS      3     /* Windows can handle 3 buttons */
 
 extern int desktopX, desktopY;   /* misc/main.c */
@@ -36,6 +41,7 @@
 BOOL MouseButtonsStates[NB_BUTTONS] = { FALSE, FALSE, FALSE };
 BOOL AsyncMouseButtonsStates[NB_BUTTONS] = { FALSE, FALSE, FALSE };
 BYTE KeyStateTable[256];
+BYTE AsyncKeyStateTable[256];
 static WORD ALTKeyState;
 static HWND captureWnd = 0;
 Window winHasCursor = 0;
@@ -245,6 +251,13 @@
     WND * wndPtr = WIN_FindWndPtr( hwnd );
     if (!wndPtr) return;
 
+    if (IsIconic(hwnd) && wndPtr->hIcon)
+    {
+        SendMessage(hwnd, WM_PAINTICON, 0, 0);
+       return;
+    }  
+
+
       /* Make position relative to client area instead of window */
     rect.left = event->x - (wndPtr->rectClient.left - wndPtr->rectWindow.left);
     rect.top  = event->y - (wndPtr->rectClient.top - wndPtr->rectWindow.top);
@@ -321,7 +334,9 @@
     if (event->type == KeyPress)
     {
 	if (vkey == VK_MENU) ALTKeyState = TRUE;
-	KeyStateTable[vkey] = 1;
+	if (!(KeyStateTable[vkey] & 0x0f))
+	    KeyStateTable[vkey] ^= 0x80;
+	KeyStateTable[vkey] |= 0x01;
 	keylp.lp1.count = 1;
 	keylp.lp1.code = LOBYTE(event->keycode);
 	keylp.lp1.extended = (extended ? 1 : 0);
@@ -330,6 +345,7 @@
 	keylp.lp1.transition = 0;
 #ifdef DEBUG_KEY
 	printf("            wParam=%X, lParam=%lX\n", vkey, keylp.lp2 );
+	printf("            KeyState=%X\n", KeyStateTable[vkey]);
 #endif
 	hardware_event( ALTKeyState ? WM_SYSKEYDOWN : WM_KEYDOWN, 
 		        vkey, keylp.lp2,
@@ -353,7 +369,7 @@
     else
     {
 	if (vkey == VK_MENU) ALTKeyState = FALSE;
-	KeyStateTable[vkey] = 1;
+	KeyStateTable[vkey] &= 0xf0;
 	keylp.lp1.count = 1;
 	keylp.lp1.code = LOBYTE(event->keycode);
 	keylp.lp1.extended = (extended ? 1 : 0);
@@ -362,6 +378,7 @@
 	keylp.lp1.transition = 1;
 #ifdef DEBUG_KEY
 	printf("            wParam=%X, lParam=%lX\n", vkey, keylp.lp2 );
+	printf("            KeyState=%X\n", KeyStateTable[vkey]);
 #endif
 	hardware_event( ((ALTKeyState || vkey == VK_MENU) ? 
 			 WM_SYSKEYUP : WM_KEYUP), 
diff --git a/windows/graphics.c b/windows/graphics.c
index dda491a..0d2392f 100644
--- a/windows/graphics.c
+++ b/windows/graphics.c
@@ -20,6 +20,15 @@
 
 extern int COLOR_ToPhysical( DC *dc, COLORREF color );
 
+static inline swap_int(int *a, int *b)
+{
+	int c;
+	
+	c = *a;
+	*a = *b;
+	*b = c;
+}
+
 /***********************************************************************
  *           LineTo    (GDI.19)
  */
@@ -220,6 +229,12 @@
     right  = XLPTODP( dc, right );
     bottom = YLPTODP( dc, bottom );
     if ((left == right) || (top == bottom)) return FALSE;
+
+    if (right < left)
+    	swap_int(&right, &left);
+
+    if (bottom < top)
+    	swap_int(&bottom, &top);
     
     if (DC_SetupGCForBrush( dc ))
 	XFillArc( display, dc->u.x.drawable, dc->u.x.gc,
@@ -246,16 +261,31 @@
 	MF_MetaParam4(dc, META_RECTANGLE, left, top, right, bottom);
 	return TRUE;
     }
-
     left   = XLPTODP( dc, left );
     top    = YLPTODP( dc, top );
     right  = XLPTODP( dc, right );
     bottom = YLPTODP( dc, bottom );
+
+    if (right < left)
+    	swap_int(&right, &left);
+
+    if (bottom < top)
+    	swap_int(&bottom, &top);
+
+    if ((left == right) || (top == bottom)) {
+	if (DC_SetupGCForPen( dc ))
+	    XDrawLine(display, dc->u.x.drawable, dc->u.x.gc, 
+		  dc->w.DCOrgX + left,
+		  dc->w.DCOrgY + top,
+		  dc->w.DCOrgX + right,
+		  dc->w.DCOrgY + bottom);
+	return TRUE;
+    }
     
     if (DC_SetupGCForBrush( dc ))
 	XFillRectangle( display, dc->u.x.drawable, dc->u.x.gc,
 		        dc->w.DCOrgX + left, dc->w.DCOrgY + top,
-		        right-left-1, bottom-top-1 );
+		        right-left, bottom-top );
     if (DC_SetupGCForPen( dc ))
 	XDrawRectangle( display, dc->u.x.drawable, dc->u.x.gc,
 		        dc->w.DCOrgX + left, dc->w.DCOrgY + top,
diff --git a/windows/icon.c b/windows/icon.c
new file mode 100644
index 0000000..dc9648e
--- /dev/null
+++ b/windows/icon.c
@@ -0,0 +1,175 @@
+
+/*
+ * Iconification functions
+ *
+ * Copyright 1994 John Richardson
+ */
+
+static char Copyright[] = "Copyright  John Richardson, 1994";
+
+#include "win.h"
+#include "class.h"
+#include "message.h"
+#include "sysmetrics.h"
+#include "user.h"
+#include "scroll.h"
+#include "menu.h"
+#include "icon.h"
+
+RECT myrect;
+
+
+ICON_Iconify(HWND hwnd)
+{
+	WND *wndPtr = WIN_FindWndPtr( hwnd );
+	GC testgc;
+	WND *parwPtr;
+	
+#ifdef DEBUG_ICON
+#endif
+	printf("ICON_Iconify %d\n", hwnd);
+
+	parwPtr = WIN_FindWndPtr(wndPtr->hwndParent);
+	if (parwPtr == NULL) {
+		printf("argh, the parent is NULL, what to do?\n");
+		exit(1);
+	}
+	wndPtr->dwStyle |= WS_MINIMIZE; 
+ 	XUnmapWindow(display, wndPtr->window); 
+	if (wndPtr->icon == NULL) {
+		printf("argh, couldn't find icon\n");
+		exit(1);
+	}
+	printf("parent edge values are %d, %d\n",  parwPtr->rectWindow.left,
+				parwPtr->rectWindow.bottom);
+	wndPtr->ptIconPos.x = parwPtr->rectWindow.left + 10;
+	wndPtr->ptIconPos.y = parwPtr->rectWindow.bottom - 80;
+
+#ifdef NOT
+        wndPtr->rectWindow.right = 100;
+        wndPtr->rectWindow.bottom = 32;
+        wndPtr->rectNormal.right = 1000;
+        wndPtr->rectNormal.bottom = 32;
+        wndPtr->rectClient.top= wndPtr->ptIconPos.y;
+	wndPtr->rectClient.left= wndPtr->ptIconPos.x;
+
+        wndPtr->rectClient.right = 100;
+	wndPtr->rectClient.bottom = 64;
+#endif
+	wndPtr->rectClientSave = wndPtr->rectNormal;
+	myrect = wndPtr->rectClient;
+
+	MoveWindow(hwnd, wndPtr->ptIconPos.x, wndPtr->ptIconPos.y,
+			100, 64+20, FALSE);
+
+	XMoveWindow(display, wndPtr->icon, 
+		wndPtr->ptIconPos.x, wndPtr->ptIconPos.y);
+
+	XMapWindow(display, wndPtr->icon);
+
+	SendMessage(hwnd, WM_PAINTICON, 0, 0);
+        printf("done with iconify\n");
+}
+
+
+BOOL ICON_isAtPoint(HWND hwnd, POINT pt)
+{
+       	WND *wndPtr = WIN_FindWndPtr( hwnd );
+	int iconWidth, iconHeight;
+
+/****************
+	if (wndPtr->hwndParent != GetDesktopWindow()) { 
+        	pt.x -= wndPtr->rectClient.left;
+        	pt.y -= wndPtr->rectClient.top;
+	} 
+*****************/
+ 
+	
+	if (wndPtr->hIcon != (HICON)NULL) {
+		ICONALLOC   *lpico;
+      		lpico = (ICONALLOC *)GlobalLock(wndPtr->hIcon);
+      		iconWidth = (int)lpico->descriptor.Width;
+      		iconHeight = (int)lpico->descriptor.Height;
+    	} else {
+      		iconWidth = 64;
+      		iconHeight = 64;
+    	}	
+#define DEBUG_ICON 1
+#ifdef DEBUG_ICON
+        printf("icon x,y is %d,%d\n",
+		wndPtr->ptIconPos.x, wndPtr->ptIconPos.y);
+
+        printf("icon end x,y is %d,%d\n",
+		wndPtr->ptIconPos.x + 100, 
+		wndPtr->ptIconPos.y + iconHeight + 20);
+
+        printf("mouse pt x,y is %d,%d\n", pt.x, pt.y);
+
+	printf("%d\n", IsIconic(hwnd));
+	printf("%d\n", (pt.x >= wndPtr->ptIconPos.x));
+	printf("%d\n", (pt.x < wndPtr->ptIconPos.x + 100));
+	printf("%d\n", (pt.y >= wndPtr->ptIconPos.y));
+	printf("%d\n", (pt.y < wndPtr->ptIconPos.y + iconHeight + 20));
+	printf("%d\n", !(wndPtr->dwStyle & WS_DISABLED));
+	printf("%d\n",  (wndPtr->dwStyle & WS_VISIBLE));
+	printf("%d\n", !(wndPtr->dwExStyle & WS_EX_TRANSPARENT));
+#endif
+	
+        if ( IsIconic(hwnd) &&
+            (pt.x >= wndPtr->ptIconPos.x) &&
+            (pt.x < wndPtr->ptIconPos.x + 100) &&
+            (pt.y >= wndPtr->ptIconPos.y) &&
+            (pt.y < wndPtr->ptIconPos.y + iconHeight + 20) &&
+            !(wndPtr->dwStyle & WS_DISABLED) &&
+            (wndPtr->dwStyle & WS_VISIBLE) &&
+            !(wndPtr->dwExStyle & WS_EX_TRANSPARENT))
+        {
+		printf("got a winner!\n");
+		return 1;
+        } 
+ 
+	return 0;
+	
+}
+
+HWND ICON_findIconFromPoint(POINT pt)
+{
+    	HWND hwnd = GetTopWindow( GetDesktopWindow() );
+    	WND *wndPtr;
+	HWND hwndRet = 0;
+
+    	while (hwnd) {
+
+        	if ( !(wndPtr=WIN_FindWndPtr(hwnd)))  return 0;
+      		if (ICON_isAtPoint(hwnd, pt))  {
+			printf("returning\n");
+			return hwndRet = hwnd;
+		} else {
+			printf("checking child\n");
+      			hwnd = wndPtr->hwndChild;
+		}
+    	}
+	return hwndRet;
+}
+
+
+ICON_Deiconify(HWND hwnd)
+{
+	WND *wndPtr = WIN_FindWndPtr( hwnd );
+
+	printf("deiconifying\n");
+	XUnmapWindow(display, wndPtr->icon); 
+	wndPtr->dwStyle &= ~WS_MINIMIZE;
+/*	wndPtr->rectNormal = myrect;
+*/
+	MoveWindow(hwnd, 
+		wndPtr->rectClientSave.left, 
+		wndPtr->rectClientSave.top,
+		wndPtr->rectClientSave.right - wndPtr->rectClientSave.left, 
+		wndPtr->rectClientSave.bottom - wndPtr->rectClientSave.top, 
+		FALSE);
+
+	XMapWindow(display, wndPtr->window);
+}
+
+
diff --git a/windows/keyboard.c b/windows/keyboard.c
index bdde31e..e8181cb 100644
--- a/windows/keyboard.c
+++ b/windows/keyboard.c
@@ -12,6 +12,7 @@
 extern BOOL MouseButtonsStates[3];
 extern BOOL AsyncMouseButtonsStates[3];
 extern BYTE KeyStateTable[256];
+extern BYTE AsyncKeyStateTable[256];
 
 /**********************************************************************
  *		GetKeyState			[USER.106]
@@ -26,7 +27,7 @@
 		case VK_RBUTTON:
 		    return MouseButtonsStates[2];
 		default:
-		    return 0;
+		    return KeyStateTable[keycode];
 		}
 }
 
@@ -35,25 +36,26 @@
  */
 void GetKeyboardState(BYTE FAR *lpKeyState)
 {
-	if (lpKeyState != NULL) {
-		memcpy(lpKeyState, KeyStateTable, 256);
-		}
+    if (lpKeyState != NULL) {
+	KeyStateTable[VK_LBUTTON] = MouseButtonsStates[0];
+	KeyStateTable[VK_MBUTTON] = MouseButtonsStates[1];
+	KeyStateTable[VK_RBUTTON] = MouseButtonsStates[2];
+	memcpy(lpKeyState, KeyStateTable, 256);
+    }
 }
 
 /**********************************************************************
- *
  *            GetAsyncKeyState        (USER.249)
  *
  *	Determine if a key is or was pressed.  retval has high-order 
  * byte set to 1 if currently pressed, low-order byte 1 if key has
  * been pressed.
  *
- *	This uses the variable AsyncMouseButtonsStates (set in event.c)
- * which have the mouse button number set to true if the mouse had been
- * depressed since the last call to GetAsyncKeyState.
- *
- *   	There should also be some keyboard stuff here... it isn't here
- * yet.
+ *	This uses the variable AsyncMouseButtonsStates and
+ * AsyncKeyStateTable (set in event.c) which have the mouse button
+ * number or key number (whichever is applicable) set to true if the
+ * mouse or key had been depressed since the last call to 
+ * GetAsyncKeyState.
  */
 int GetAsyncKeyState(int nKey)
 {
@@ -71,14 +73,16 @@
 		break;
            case VK_RBUTTON:
                 retval = AsyncMouseButtonsStates[2] |
-                              MouseButtonsStates[2] << 8;
+                              (MouseButtonsStates[2] << 8);
 		break;
            default:
-                retval = 0;
+                retval = AsyncKeyStateTable[nKey] | 
+		              (KeyStateTable[nKey] << 8);
 		break;
         }
 
 	bzero(AsyncMouseButtonsStates, 3);	/* all states to false */
+	bzero(AsyncKeyStateTable, 256);
 
 	return retval;
 }
diff --git a/windows/mdi.c b/windows/mdi.c
index 08f45bb..0835c8a 100644
--- a/windows/mdi.c
+++ b/windows/mdi.c
@@ -296,6 +296,8 @@
     WND    *w      = WIN_FindWndPtr(child);
     LPRECT  lprect = &ci->rectRestore;
 
+    printf("restoring mdi child\n");
+
     child = ci->hwndActiveChild;
     
     w->dwStyle &= ~WS_MAXIMIZE;
@@ -749,6 +751,8 @@
 	    return SendMessage(GetParent(hwnd), WM_MDIMAXIMIZE, hwnd, 0);
 
 	  case SC_RESTORE:
+	    if (IsIconic(hwnd))
+	        ICON_Deiconify(hwnd);
 	    return SendMessage(GetParent(hwnd), WM_MDIRESTORE, hwnd, 0);
 	}
 	break;
diff --git a/windows/message.c b/windows/message.c
index a356f51..dfafcde 100644
--- a/windows/message.c
+++ b/windows/message.c
@@ -387,6 +387,12 @@
       /* Determine the hwnd for this message */
       /* Maybe this should be done in GetMessage() */
 
+    if (msg.hwnd = ICON_findIconFromPoint(msg.pt)) {
+       SendMessage( msg.hwnd, WM_SYSCOMMAND, SC_RESTORE, *(LONG*)&msg.pt );
+       return;
+    }
+
+
     if ((message >= WM_MOUSEFIRST) && (message <= WM_MOUSELAST))
     {
 	  /* Mouse event */
diff --git a/windows/nonclient.c b/windows/nonclient.c
index e31a875..f799826 100644
--- a/windows/nonclient.c
+++ b/windows/nonclient.c
@@ -647,6 +647,47 @@
 }
 
 
+NC_DoNCPaintIcon(HWND hwnd)
+{
+      WND *wndPtr = WIN_FindWndPtr(hwnd);
+      PAINTSTRUCT ps;
+      HDC hdc;
+      int ret;
+      DC *dc;
+      GC testgc;
+      int s;
+      char buffer[256];
+
+      printf("painting icon\n");
+      if (wndPtr == NULL) {
+              printf("argh, can't find an icon to draw\n");
+              return;
+      }
+      hdc = BeginPaint(hwnd, &ps);
+
+      ret = DrawIcon(hdc, 100/2 - 16, 0, wndPtr->hIcon);
+      printf("ret is %d\n", ret);
+
+      if (s=GetWindowText(hwnd, buffer, 256))
+      {
+          /*SetBkColor(hdc, TRANSPARENT); */
+          TextOut(hdc, 0, 32, buffer, s);
+      }
+      EndPaint(hwnd, &ps);
+
+      printf("done painting icon\n");
+      
+}
+
+
+LONG NC_HandleNCPaintIcon( HWND hwnd )
+{
+    NC_DoNCPaintIcon(hwnd);
+    return 0;
+}
+
+
+
 /***********************************************************************
  *           NC_HandleNCPaint
  *
@@ -1183,7 +1224,8 @@
 	break;
 
     case SC_MINIMIZE:
-	ShowWindow( hwnd, SW_MINIMIZE );
+	ICON_Iconify( hwnd );
+	/*ShowWindow( hwnd, SW_MINIMIZE );*/
 	break;
 
     case SC_MAXIMIZE:
@@ -1191,6 +1233,7 @@
 	break;
 
     case SC_RESTORE:
+	ICON_Deiconify(hwnd);
 	ShowWindow( hwnd, SW_RESTORE );
 	break;
 
diff --git a/windows/painting.c b/windows/painting.c
index 36c72e7..65a17ca 100644
--- a/windows/painting.c
+++ b/windows/painting.c
@@ -10,6 +10,7 @@
 
 #include "win.h"
 #include "message.h"
+#include "gdi.h"
 
   /* Last CTLCOLOR id */
 #define CTLCOLOR_MAX   CTLCOLOR_STATIC
@@ -43,6 +44,13 @@
 
     if (!(wndPtr->flags & WIN_ERASE_UPDATERGN)) lps->fErase = TRUE;
     else lps->fErase = !SendMessage( hwnd, WM_ERASEBKGND, lps->hdc, 0 );
+
+    /*
+     * a BeginPaint should return with these objects set by default
+     */
+    SelectObject(lps->hdc, STOCK_BLACK_PEN);
+    SelectObject(lps->hdc, STOCK_WHITE_BRUSH);
+    SelectObject(lps->hdc, STOCK_SYSTEM_FONT);
     
     return lps->hdc;
 }
diff --git a/windows/win.c b/windows/win.c
index 041c227..cc11dd1 100644
--- a/windows/win.c
+++ b/windows/win.c
@@ -17,6 +17,7 @@
 #include "dce.h"
 #include "sysmetrics.h"
 #include "scroll.h"
+#include "icon.h"
 
 extern Colormap COLOR_WinColormap;
 
@@ -244,7 +245,8 @@
     CREATESTRUCT *createStruct;
     HANDLE hcreateStruct;
     int wmcreate;
-    XSetWindowAttributes win_attr;
+    XSetWindowAttributes win_attr, icon_attr;
+    int iconWidth, iconHeight;
 
 #ifdef DEBUG_WIN
     printf( "CreateWindowEx: %04X '%s' '%s' %04X %d,%d %dx%d %04X %04X %04X %08X\n",
@@ -368,6 +370,12 @@
        win_attr.save_under = FALSE;
     else
        win_attr.save_under = TRUE;        
+
+
+    /* set the background of all windows to be white, just like
+     * MS-Windows does (hopefully!)
+     */   
+    win_attr.background_pixel = WhitePixelOfScreen(screen);
     
     wndPtr->window = XCreateWindow( display, parentPtr->window,
 		   x + parentPtr->rectClient.left - parentPtr->rectWindow.left,
@@ -375,9 +383,46 @@
 		   width, height, 0,
 		   CopyFromParent, InputOutput, CopyFromParent,
 		   CWEventMask | CWOverrideRedirect | CWColormap |
-		   CWSaveUnder | CWBackingStore, &win_attr );
+		   CWSaveUnder | CWBackingStore | CWBackPixel, &win_attr );
     XStoreName( display, wndPtr->window, windowName );
 
+
+    /* create icon window */
+
+    icon_attr.override_redirect = rootWindow==DefaultRootWindow(display);
+    icon_attr.background_pixel = WhitePixelOfScreen(screen);
+    icon_attr.event_mask = ExposureMask | KeyPressMask |
+                            ButtonPressMask | ButtonReleaseMask;
+
+    wndPtr->hIcon = classPtr->wc.hIcon;
+    if (wndPtr->hIcon != (HICON)NULL) {
+      ICONALLOC   *lpico;
+      lpico = (ICONALLOC *)GlobalLock(wndPtr->hIcon);
+      printf("icon is %d x %d\n", 
+              (int)lpico->descriptor.Width,
+              (int)lpico->descriptor.Height);
+      iconWidth = (int)lpico->descriptor.Width;
+      iconHeight = (int)lpico->descriptor.Height;
+    } else {
+      printf("icon was NULL\n");
+      iconWidth = 64;
+      iconHeight = 64;
+    }
+
+    wndPtr->icon = XCreateWindow(display, parentPtr->window,
+                    10, 10, 100, iconHeight+20, 
+                    0, CopyFromParent,
+                    InputOutput, CopyFromParent,
+                    CWBorderPixel | CWEventMask | CWOverrideRedirect, 
+                    &icon_attr);
+   
+    if (style & WS_MINIMIZE) 
+    {
+      style &= ~WS_MINIMIZE;
+    }
+ 
+
+
 #ifdef DEBUG_MENU
     printf("CreateWindowEx // menu=%04X instance=%04X classmenu=%08X !\n", 
     	menu, instance, classPtr->wc.lpszMenuName); 
@@ -455,6 +500,7 @@
     else CURSOR_SetWinCursor( hwnd, LoadCursor( 0, IDC_ARROW ));
 
     EVENT_RegisterWindow( wndPtr->window, hwnd );
+    EVENT_RegisterWindow( wndPtr->icon, hwnd );
 
     WIN_SendParentNotify( hwnd, WM_CREATE, MAKELONG( hwnd, wndPtr->wIDmenu ) );